My Project
Utils.h
Go to the documentation of this file.
1 //===- Utils.h - General analysis utilities ---------------------*- C++ -*-===//
2 //
3 // Part of the MLIR Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This header file defines prototypes for various transformation utilities for
10 // memref's and non-loop IR structures. These are not passes by themselves but
11 // are used either by passes, optimization sequences, or in turn by other
12 // transformation utilities.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #ifndef MLIR_ANALYSIS_UTILS_H
17 #define MLIR_ANALYSIS_UTILS_H
18 
20 #include "mlir/IR/AffineMap.h"
21 #include "mlir/IR/Block.h"
22 #include "mlir/IR/Location.h"
23 #include "mlir/Support/LLVM.h"
24 #include "llvm/ADT/SmallVector.h"
25 #include <memory>
26 
27 namespace mlir {
28 
29 class AffineForOp;
30 class Block;
31 class FlatAffineConstraints;
32 class Location;
33 struct MemRefAccess;
34 class Operation;
35 class Value;
36 
39 // TODO(bondhugula): handle 'affine.if' ops.
40 void getLoopIVs(Operation &op, SmallVectorImpl<AffineForOp> *loops);
41 
44 unsigned getNestingDepth(Operation &op);
45 
48 void getSequentialLoops(AffineForOp forOp,
49  llvm::SmallDenseSet<Value, 8> *sequentialLoops);
50 
56  // List of sliced loop IVs (ordered from outermost to innermost).
57  // EX: 'ivs[i]' has lower bound 'lbs[i]' and upper bound 'ubs[i]'.
59  // List of lower bound AffineMaps.
61  // List of upper bound AffineMaps.
63  // List of lower bound operands (lbOperands[i] are used by 'lbs[i]').
64  std::vector<SmallVector<Value, 4>> lbOperands;
65  // List of upper bound operands (ubOperands[i] are used by 'ubs[i]').
66  std::vector<SmallVector<Value, 4>> ubOperands;
67  // Slice loop nest insertion point in target loop nest.
69  // Adds to 'cst' with constraints which represent the slice bounds on 'ivs'
70  // in 'this'. Specifically, the values in 'ivs' are added to 'cst' as dim
71  // identifiers and the values in 'lb/ubOperands' are added as symbols.
72  // Constraints are added for all loop IV bounds (dim or symbol), and
73  // constraints are added for slice bounds in 'lbs'/'ubs'.
74  // Returns failure if we cannot add loop bounds because of unsupported cases.
76 
77  // Clears all bounds and operands in slice state.
78  void clearBounds();
79 };
80 
93 //
94 // Backward slice example:
95 //
96 // affine.for %i0 = 0 to 10 {
97 // affine.store %cst, %0[%i0] : memref<100xf32> // 'depSourceAccess'
98 // }
99 // affine.for %i1 = 0 to 10 {
100 // %v = affine.load %0[%i1] : memref<100xf32> // 'depSinkAccess'
101 // }
102 //
103 // // Backward computation slice of loop nest '%i0'.
104 // affine.for %i0 = (d0) -> (d0)(%i1) to (d0) -> (d0 + 1)(%i1) {
105 // affine.store %cst, %0[%i0] : memref<100xf32> // 'depSourceAccess'
106 // }
107 //
108 // Forward slice example:
109 //
110 // affine.for %i0 = 0 to 10 {
111 // affine.store %cst, %0[%i0] : memref<100xf32> // 'depSourceAccess'
112 // }
113 // affine.for %i1 = 0 to 10 {
114 // %v = affine.load %0[%i1] : memref<100xf32> // 'depSinkAccess'
115 // }
116 //
117 // // Forward computation slice of loop nest '%i1'.
118 // affine.for %i1 = (d0) -> (d0)(%i0) to (d0) -> (d0 + 1)(%i0) {
119 // %v = affine.load %0[%i1] : memref<100xf32> // 'depSinkAccess'
120 // }
121 //
122 void getComputationSliceState(Operation *depSourceOp, Operation *depSinkOp,
123  FlatAffineConstraints *dependenceConstraints,
124  unsigned loopDepth, bool isBackwardSlice,
125  ComputationSliceState *sliceState);
126 
138 // TODO(andydavis) Change this API to take 'forOpA'/'forOpB'.
140  ArrayRef<Operation *> opsB, unsigned loopDepth,
141  unsigned numCommonLoops, bool isBackwardSlice,
142  ComputationSliceState *sliceUnion);
143 
150 // Loop depth is a crucial optimization choice that determines where to
151 // materialize the results of the backward slice - presenting a trade-off b/w
152 // storage and redundant computation in several cases.
153 // TODO(andydavis) Support computation slices with common surrounding loops.
154 AffineForOp insertBackwardComputationSlice(Operation *srcOpInst,
155  Operation *dstOpInst,
156  unsigned dstLoopDepth,
157  ComputationSliceState *sliceState);
158 
162 // For example, the memref region for a load operation at loop depth = 1:
163 //
164 // affine.for %i = 0 to 32 {
165 // affine.for %ii = %i to (d0) -> (d0 + 8) (%i) {
166 // affine.load %A[%ii]
167 // }
168 // }
169 //
170 // Region: {memref = %A, write = false, {%i <= m0 <= %i + 7} }
171 // The last field is a 2-d FlatAffineConstraints symbolic in %i.
172 //
173 struct MemRefRegion {
174  explicit MemRefRegion(Location loc) : loc(loc) {}
175 
208  LogicalResult compute(Operation *op, unsigned loopDepth,
209  ComputationSliceState *sliceState = nullptr,
210  bool addMemRefDimBounds = true);
211 
213  const FlatAffineConstraints *getConstraints() const { return &cst; }
214  bool isWrite() const { return write; }
215  void setWrite(bool flag) { write = flag; }
216 
224  Optional<int64_t> getConstantBoundingSizeAndShape(
225  SmallVectorImpl<int64_t> *shape = nullptr,
226  std::vector<SmallVector<int64_t, 4>> *lbs = nullptr,
227  SmallVectorImpl<int64_t> *lbDivisors = nullptr) const;
228 
232  //'cst'.
235  SmallVectorImpl<int64_t> *lb = nullptr,
236  int64_t *lbFloorDivisor = nullptr) const {
237  assert(pos < getRank() && "invalid position");
238  return cst.getConstantBoundOnDimSize(pos, lb);
239  }
240 
242  Optional<int64_t> getRegionSize();
243 
244  // Wrapper around FlatAffineConstraints::unionBoundingBox.
245  LogicalResult unionBoundingBox(const MemRefRegion &other);
246 
248  unsigned getRank() const;
249 
252 
254  bool write;
255 
259 
267  // TODO(bondhugula): Replace this to exploit HyperRectangularSet.
269 };
270 
274 
278 template <typename LoadOrStoreOpPointer>
279 LogicalResult boundCheckLoadOrStoreOp(LoadOrStoreOpPointer loadOrStoreOp,
280  bool emitError = true);
281 
284 
288  int memorySpace = -1);
289 
291 bool isLoopParallel(AffineForOp forOp);
292 
293 } // end namespace mlir
294 
295 #endif // MLIR_ANALYSIS_UTILS_H
Definition: InferTypeOpInterface.cpp:20
Definition: Operation.h:27
SmallVector< Value, 4 > ivs
Definition: Utils.h:58
Optional< int64_t > getMemoryFootprintBytes(AffineForOp forOp, int memorySpace=-1)
Definition: Utils.cpp:953
unsigned getNestingDepth(Operation &op)
Definition: Utils.cpp:864
void getComputationSliceState(Operation *depSourceOp, Operation *depSinkOp, FlatAffineConstraints *dependenceConstraints, unsigned loopDepth, bool isBackwardSlice, ComputationSliceState *sliceState)
Definition: Utils.cpp:680
Definition: LLVM.h:40
void getLoopIVs(Operation &op, SmallVectorImpl< AffineForOp > *loops)
Definition: Utils.cpp:31
Definition: LLVM.h:34
Definition: Location.h:52
void clearBounds()
Definition: Utils.cpp:83
Optional< uint64_t > getMemRefSizeInBytes(MemRefType memRefType)
Definition: Utils.cpp:356
Definition: AffineStructures.h:229
Definition: LogicalResult.h:18
Definition: LLVM.h:37
OpListType::iterator iterator
Definition: Block.h:107
Definition: Utils.h:55
void setWrite(bool flag)
Definition: Utils.h:215
bool isLoopParallel(AffineForOp forOp)
Returns true if `forOp&#39; is a parallel loop.
Definition: Utils.cpp:973
bool write
Read or write.
Definition: Utils.h:254
SmallVector< AffineMap, 4 > lbs
Definition: Utils.h:60
Location loc
Definition: Utils.h:258
const FlatAffineConstraints * getConstraints() const
Definition: Utils.h:213
Block::iterator insertPoint
Definition: Utils.h:68
Definition: StandardTypes.h:390
MemRefRegion(Location loc)
Definition: Utils.h:174
void getSequentialLoops(AffineForOp forOp, llvm::SmallDenseSet< Value, 8 > *sequentialLoops)
Definition: Utils.cpp:963
unsigned getNumCommonSurroundingLoops(Operation &A, Operation &B)
Returns the number of surrounding loops common to both A and B.
Definition: Utils.cpp:894
Definition: Value.h:38
SmallVector< AffineMap, 4 > ubs
Definition: Utils.h:62
Definition: LLVM.h:35
LogicalResult boundCheckLoadOrStoreOp(LoadOrStoreOpPointer loadOrStoreOp, bool emitError=true)
Definition: Utils.cpp:371
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
Definition: Diagnostics.cpp:301
FlatAffineConstraints * getConstraints()
Definition: Utils.h:212
std::vector< SmallVector< Value, 4 > > ubOperands
Definition: Utils.h:66
bool isWrite() const
Definition: Utils.h:214
FlatAffineConstraints cst
Definition: Utils.h:268
LogicalResult computeSliceUnion(ArrayRef< Operation *> opsA, ArrayRef< Operation *> opsB, unsigned loopDepth, unsigned numCommonLoops, bool isBackwardSlice, ComputationSliceState *sliceUnion)
Definition: Utils.cpp:520
AffineForOp insertBackwardComputationSlice(Operation *srcOpInst, Operation *dstOpInst, unsigned dstLoopDepth, ComputationSliceState *sliceState)
Definition: Utils.cpp:777
Value memref
Memref that this region corresponds to.
Definition: Utils.h:251
Definition: Utils.h:173
std::vector< SmallVector< Value, 4 > > lbOperands
Definition: Utils.h:64
LogicalResult getAsConstraints(FlatAffineConstraints *cst)
Definition: Utils.cpp:47
Optional< int64_t > getConstantBoundOnDimSize(unsigned pos, SmallVectorImpl< int64_t > *lb=nullptr, int64_t *lbFloorDivisor=nullptr) const
Definition: Utils.h:234