MLIR  21.0.0git
Utils.h
Go to the documentation of this file.
1 //===- Utils.h - Affine dialect utilities -----------------------*- C++ -*-===//
2 //
3 // Part of the LLVM 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 declares a set of utilities for the affine dialect ops.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef MLIR_DIALECT_AFFINE_UTILS_H
14 #define MLIR_DIALECT_AFFINE_UTILS_H
15 
19 #include "mlir/IR/OpDefinition.h"
20 #include <optional>
21 
22 namespace mlir {
23 class DominanceInfo;
24 class Operation;
25 class PostDominanceInfo;
26 class ImplicitLocOpBuilder;
27 
28 namespace func {
29 class FuncOp;
30 } // namespace func
31 
32 namespace memref {
33 class AllocOp;
34 class AllocaOp;
35 class ReinterpretCastOp;
36 } // namespace memref
37 
38 namespace affine {
39 class AffineForOp;
40 class AffineIfOp;
41 class AffineParallelOp;
42 
44 
45 /// Replaces a parallel affine.for op with a 1-d affine.parallel op. `forOp`'s
46 /// body is taken by the affine.parallel op and the former is erased.
47 /// (mlir::isLoopParallel can be used to detect a parallel affine.for op.) The
48 /// reductions specified in `parallelReductions` are also parallelized.
49 /// Parallelization will fail in the presence of loop iteration arguments that
50 /// are not listed in `parallelReductions`. `resOp` if non-null is set to the
51 /// newly created affine.parallel op.
52 LogicalResult affineParallelize(AffineForOp forOp,
53  ArrayRef<LoopReduction> parallelReductions = {},
54  AffineParallelOp *resOp = nullptr);
55 
56 /// Hoists out affine.if/else to as high as possible, i.e., past all invariant
57 /// affine.fors/parallel's. Returns success if any hoisting happened; folded` is
58 /// set to true if the op was folded or erased. This hoisting could lead to
59 /// significant code expansion in some cases.
60 LogicalResult hoistAffineIfOp(AffineIfOp ifOp, bool *folded = nullptr);
61 
62 /// Holds parameters to perform n-D vectorization on a single loop nest.
63 /// For example, for the following loop nest:
64 ///
65 /// func @vec2d(%in: memref<64x128x512xf32>, %out: memref<64x128x512xf32>) {
66 /// affine.for %i0 = 0 to 64 {
67 /// affine.for %i1 = 0 to 128 {
68 /// affine.for %i2 = 0 to 512 {
69 /// %ld = affine.load %in[%i0, %i1, %i2] : memref<64x128x512xf32>
70 /// affine.store %ld, %out[%i0, %i1, %i2] : memref<64x128x512xf32>
71 /// }
72 /// }
73 /// }
74 /// return
75 /// }
76 ///
77 /// and VectorizationStrategy = 'vectorSizes = {8, 4}', 'loopToVectorDim =
78 /// {{i1->0}, {i2->1}}', SuperVectorizer will generate:
79 ///
80 /// func @vec2d(%arg0: memref<64x128x512xf32>, %arg1: memref<64x128x512xf32>) {
81 /// affine.for %arg2 = 0 to 64 {
82 /// affine.for %arg3 = 0 to 128 step 8 {
83 /// affine.for %arg4 = 0 to 512 step 4 {
84 /// %cst = arith.constant 0.000000e+00 : f32
85 /// %0 = vector.transfer_read %arg0[%arg2, %arg3, %arg4], %cst : ...
86 /// vector.transfer_write %0, %arg1[%arg2, %arg3, %arg4] : ...
87 /// }
88 /// }
89 /// }
90 /// return
91 /// }
92 // TODO: Hoist to a VectorizationStrategy.cpp when appropriate.
94  // Vectorization factors to apply to each target vector dimension.
95  // Each factor will be applied to a different loop.
97  // Maps each AffineForOp vectorization candidate with its vector dimension.
98  // The candidate will be vectorized using the vectorization factor in
99  // 'vectorSizes' for that dimension.
101  // Maps loops that implement vectorizable reductions to the corresponding
102  // reduction descriptors.
104 };
105 
106 /// Replace affine store and load accesses by scalars by forwarding stores to
107 /// loads and eliminate invariant affine loads; consequently, eliminate dead
108 /// allocs.
109 void affineScalarReplace(func::FuncOp f, DominanceInfo &domInfo,
110  PostDominanceInfo &postDomInfo,
111  AliasAnalysis &analysis);
112 
113 /// Vectorizes affine loops in 'loops' using the n-D vectorization factors in
114 /// 'vectorSizes'. By default, each vectorization factor is applied
115 /// inner-to-outer to the loops of each loop nest. 'fastestVaryingPattern' can
116 /// be optionally used to provide a different loop vectorization order.
117 /// If `reductionLoops` is not empty, the given reduction loops may be
118 /// vectorized along the reduction dimension.
119 /// TODO: Vectorizing reductions is supported only for 1-D vectorization.
121  Operation *parentOp,
123  ArrayRef<int64_t> vectorSizes, ArrayRef<int64_t> fastestVaryingPattern,
124  const ReductionLoopMap &reductionLoops = ReductionLoopMap());
125 
126 /// External utility to vectorize affine loops from a single loop nest using an
127 /// n-D vectorization strategy (see doc in VectorizationStrategy definition).
128 /// Loops are provided in a 2D vector container. The first dimension represents
129 /// the nesting level relative to the loops to be vectorized. The second
130 /// dimension contains the loops. This means that:
131 /// a) every loop in 'loops[i]' must have a parent loop in 'loops[i-1]',
132 /// b) a loop in 'loops[i]' may or may not have a child loop in 'loops[i+1]'.
133 ///
134 /// For example, for the following loop nest:
135 ///
136 /// func @vec2d(%in0: memref<64x128x512xf32>, %in1: memref<64x128x128xf32>,
137 /// %out0: memref<64x128x512xf32>,
138 /// %out1: memref<64x128x128xf32>) {
139 /// affine.for %i0 = 0 to 64 {
140 /// affine.for %i1 = 0 to 128 {
141 /// affine.for %i2 = 0 to 512 {
142 /// %ld = affine.load %in0[%i0, %i1, %i2] : memref<64x128x512xf32>
143 /// affine.store %ld, %out0[%i0, %i1, %i2] : memref<64x128x512xf32>
144 /// }
145 /// affine.for %i3 = 0 to 128 {
146 /// %ld = affine.load %in1[%i0, %i1, %i3] : memref<64x128x128xf32>
147 /// affine.store %ld, %out1[%i0, %i1, %i3] : memref<64x128x128xf32>
148 /// }
149 /// }
150 /// }
151 /// return
152 /// }
153 ///
154 /// loops = {{%i0}, {%i2, %i3}}, to vectorize the outermost and the two
155 /// innermost loops;
156 /// loops = {{%i1}, {%i2, %i3}}, to vectorize the middle and the two innermost
157 /// loops;
158 /// loops = {{%i2}}, to vectorize only the first innermost loop;
159 /// loops = {{%i3}}, to vectorize only the second innermost loop;
160 /// loops = {{%i1}}, to vectorize only the middle loop.
161 LogicalResult
163  const VectorizationStrategy &strategy);
164 
165 /// Normalize a affine.parallel op so that lower bounds are 0 and steps are 1.
166 /// As currently implemented, this transformation cannot fail and will return
167 /// early if the op is already in a normalized form.
168 void normalizeAffineParallel(AffineParallelOp op);
169 
170 /// Normalize an affine.for op. An affine.for op is normalized by converting the
171 /// lower bound to zero and loop step to one. The upper bound is set to the trip
172 /// count of the loop. Original loops must have a lower bound with only a single
173 /// result. There is no such restriction on upper bounds. Returns success if the
174 /// loop has been normalized (or is already in the normal form). If
175 /// `promoteSingleIter` is true, the loop is simply promoted if it has a single
176 /// iteration.
177 LogicalResult normalizeAffineFor(AffineForOp op,
178  bool promoteSingleIter = false);
179 
180 /// Traverse `e` and return an AffineExpr where all occurrences of `dim` have
181 /// been replaced by either:
182 /// - `min` if `positivePath` is true when we reach an occurrence of `dim`
183 /// - `max` if `positivePath` is true when we reach an occurrence of `dim`
184 /// `positivePath` is negated each time we hit a multiplicative or divisive
185 /// binary op with a constant negative coefficient.
187  AffineExpr max, bool positivePath = true);
188 
189 /// Replaces all "dereferencing" uses of `oldMemRef` with `newMemRef` while
190 /// optionally remapping the old memref's indices using the supplied affine map,
191 /// `indexRemap`. The new memref could be of a different shape or rank.
192 /// `extraIndices` provides any additional access indices to be added to the
193 /// start.
194 ///
195 /// `indexRemap` remaps indices of the old memref access to a new set of indices
196 /// that are used to index the memref. Additional input operands to indexRemap
197 /// can be optionally provided in `extraOperands`, and they occupy the start
198 /// of its input list. `indexRemap`'s dimensional inputs are expected to
199 /// correspond to memref's indices, and its symbolic inputs if any should be
200 /// provided in `symbolOperands`.
201 ///
202 /// `domOpFilter`, if non-null, restricts the replacement to only those
203 /// operations that are dominated by the former; similarly, `postDomOpFilter`
204 /// restricts replacement to only those operations that are postdominated by it.
205 ///
206 /// 'allowNonDereferencingOps', if set, allows replacement of non-dereferencing
207 /// uses of a memref without any requirement for access index rewrites as long
208 /// as the user operation has the MemRefsNormalizable trait. The default value
209 /// of this flag is false.
210 ///
211 /// 'replaceInDeallocOp', if set, lets DeallocOp, a non-dereferencing user, to
212 /// also be a candidate for replacement. The default value of this flag is
213 /// false.
214 ///
215 /// Returns true on success and false if the replacement is not possible,
216 /// whenever a memref is used as an operand in a non-dereferencing context and
217 /// 'allowNonDereferencingOps' is false, except for dealloc's on the memref
218 /// which are left untouched. See comments at function definition for an
219 /// example.
220 //
221 // Ex: to replace load %A[%i, %j] with load %Abuf[%t mod 2, %ii - %i, %j]:
222 // The SSA value corresponding to '%t mod 2' should be in 'extraIndices', and
223 // index remap will perform (%i, %j) -> (%ii - %i, %j), i.e., indexRemap = (d0,
224 // d1, d2) -> (d0 - d1, d2), and %ii will be the extra operand. Without any
225 // extra operands, note that 'indexRemap' would just be applied to existing
226 // indices (%i, %j).
227 // TODO: allow extraIndices to be added at any position.
228 LogicalResult replaceAllMemRefUsesWith(
229  Value oldMemRef, Value newMemRef, ArrayRef<Value> extraIndices = {},
230  AffineMap indexRemap = AffineMap(), ArrayRef<Value> extraOperands = {},
231  ArrayRef<Value> symbolOperands = {}, Operation *domOpFilter = nullptr,
232  Operation *postDomOpFilter = nullptr, bool allowNonDereferencingOps = false,
233  bool replaceInDeallocOp = false);
234 
235 /// Performs the same replacement as the other version above but only for the
236 /// dereferencing uses of `oldMemRef` in `op`, except in cases where
237 /// 'allowNonDereferencingOps' is set to true where we replace the
238 /// non-dereferencing uses as well.
239 LogicalResult replaceAllMemRefUsesWith(Value oldMemRef, Value newMemRef,
240  Operation *op,
241  ArrayRef<Value> extraIndices = {},
242  AffineMap indexRemap = AffineMap(),
243  ArrayRef<Value> extraOperands = {},
244  ArrayRef<Value> symbolOperands = {},
245  bool allowNonDereferencingOps = false);
246 
247 /// Rewrites the memref defined by alloc or reinterpret_cast op to have an
248 /// identity layout map and updates all its indexing uses. Returns failure if
249 /// any of its uses escape (while leaving the IR in a valid state).
250 template <typename AllocLikeOp>
251 LogicalResult normalizeMemRef(AllocLikeOp op);
252 extern template LogicalResult
253 normalizeMemRef<memref::AllocaOp>(memref::AllocaOp op);
254 extern template LogicalResult
255 normalizeMemRef<memref::AllocOp>(memref::AllocOp op);
256 LogicalResult normalizeMemRef(memref::ReinterpretCastOp op);
257 
258 /// Normalizes `memrefType` so that the affine layout map of the memref is
259 /// transformed to an identity map with a new shape being computed for the
260 /// normalized memref type and returns it. The old memref type is simplify
261 /// returned if the normalization failed.
262 MemRefType normalizeMemRefType(MemRefType memrefType);
263 
264 /// Given an operation, inserts one or more single result affine apply
265 /// operations, results of which are exclusively used by this operation.
266 /// The operands of these newly created affine apply ops are
267 /// guaranteed to be loop iterators or terminal symbols of a function.
268 ///
269 /// Before
270 ///
271 /// affine.for %i = 0 to #map(%N)
272 /// %idx = affine.apply (d0) -> (d0 mod 2) (%i)
273 /// send %A[%idx], ...
274 /// %v = "compute"(%idx, ...)
275 ///
276 /// After
277 ///
278 /// affine.for %i = 0 to #map(%N)
279 /// %idx = affine.apply (d0) -> (d0 mod 2) (%i)
280 /// send %A[%idx], ...
281 /// %idx_ = affine.apply (d0) -> (d0 mod 2) (%i)
282 /// %v = "compute"(%idx_, ...)
283 
284 /// This allows the application of different transformations on send and
285 /// compute (for eg. different shifts/delays)
286 ///
287 /// Fills `sliceOps` with the list of affine.apply operations.
288 /// In the following cases, `sliceOps` remains empty:
289 /// 1. If none of opInst's operands were the result of an affine.apply
290 /// (i.e., there was no affine computation slice to create).
291 /// 2. If all the affine.apply op's supplying operands to this opInst did not
292 /// have any uses other than those in this opInst.
295 
296 /// Emit code that computes the given affine expression using standard
297 /// arithmetic operations applied to the provided dimension and symbol values.
299  ValueRange dimValues, ValueRange symbolValues);
300 
301 /// Create a sequence of operations that implement the `affineMap` applied to
302 /// the given `operands` (as it it were an AffineApplyOp).
303 std::optional<SmallVector<Value, 8>> expandAffineMap(OpBuilder &builder,
304  Location loc,
305  AffineMap affineMap,
306  ValueRange operands);
307 
308 /// Holds the result of (div a, b) and (mod a, b).
309 struct DivModValue {
312 };
313 
314 /// Create IR to calculate (div lhs, rhs) and (mod lhs, rhs).
316 
317 /// Generate the IR to delinearize `linearIndex` given the `basis` and return
318 /// the multi-index. `hasOuterBound` indicates whether `basis` has an entry
319 /// given the size of the first multi-index result - if it is true, the function
320 /// will return `basis.size()` values, otherwise, it will return `basis.size() +
321 /// 1`.
322 FailureOr<SmallVector<Value>> delinearizeIndex(OpBuilder &b, Location loc,
323  Value linearIndex,
324  ArrayRef<Value> basis,
325  bool hasOuterBound = true);
326 
327 FailureOr<SmallVector<Value>> delinearizeIndex(OpBuilder &b, Location loc,
328  Value linearIndex,
330  bool hasOuterBound = true);
331 
332 // Generate IR that extracts the linear index from a multi-index according to
333 // a basis/shape. The basis may contain either `multiIndex.size()` or
334 // `multiIndex.size() - 1` elements.
337  ImplicitLocOpBuilder &builder);
338 
340  ArrayRef<OpFoldResult> multiIndex,
341  ArrayRef<OpFoldResult> basis);
342 
343 /// Ensure that all operations that could be executed after `start`
344 /// (noninclusive) and prior to `memOp` (e.g. on a control flow/op path
345 /// between the operations) do not have the potential memory effect
346 /// `EffectType` on `memOp`. `memOp` is an operation that reads or writes to
347 /// a memref. For example, if `EffectType` is MemoryEffects::Write, this method
348 /// will check if there is no write to the memory between `start` and `memOp`
349 /// that would change the read within `memOp`.
350 template <typename EffectType, typename T>
351 bool hasNoInterveningEffect(Operation *start, T memOp,
353 
355  explicit AffineValueExpr(AffineExpr e) : e(e) {}
357  this->v = v;
358  return *this;
359  }
361  this->v = v;
362  return *this;
363  }
364  operator AffineExpr() const { return e; }
365  operator OpFoldResult() const { return v; }
368 };
369 
370 /// Helper struct to build simple AffineValueExprs with minimal type inference
371 /// support.
373  AffineBuilder(OpBuilder &b, Location loc) : b(b), loc(loc) {}
375  return makeComposedFoldedAffineApply(b, loc, {lhs.e + rhs.e}, {lhs, rhs});
376  }
378  return makeComposedFoldedAffineApply(b, loc, {lhs.e - rhs.e}, {lhs, rhs});
379  }
381  return makeComposedFoldedAffineApply(b, loc, {lhs.e * rhs.e}, {lhs, rhs});
382  }
384  return makeComposedFoldedAffineApply(b, loc, {lhs.e.floorDiv(rhs.e)},
385  {lhs, rhs});
386  }
388  return makeComposedFoldedAffineApply(b, loc, {lhs.e.ceilDiv(rhs.e)},
389  {lhs, rhs});
390  }
393  b, loc, AffineMap::getMultiDimIdentityMap(vals.size(), b.getContext()),
394  vals);
395  }
398  b, loc, AffineMap::getMultiDimIdentityMap(vals.size(), b.getContext()),
399  vals);
400  }
401 
402 private:
403  OpBuilder &b;
404  Location loc;
405 };
406 
407 } // namespace affine
408 } // namespace mlir
409 
410 #endif // MLIR_DIALECT_AFFINE_UTILS_H
static bool mayAlias(Value first, Value second)
Returns true if two values may be referencing aliasing memory.
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
Base type for affine expression.
Definition: AffineExpr.h:68
AffineExpr floorDiv(uint64_t v) const
Definition: AffineExpr.cpp:921
AffineExpr ceilDiv(uint64_t v) const
Definition: AffineExpr.cpp:968
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
Definition: AffineMap.h:46
static AffineMap getMultiDimIdentityMap(unsigned numDims, MLIRContext *context)
Returns an AffineMap with 'numDims' identity result dim exprs.
Definition: AffineMap.cpp:334
This class represents the main alias analysis interface in MLIR.
MLIRContext * getContext() const
Definition: Builders.h:56
A class for computing basic dominance information.
Definition: Dominance.h:140
ImplicitLocOpBuilder maintains a 'current location', allowing use of the create<> method without spec...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:66
This class helps build Operations.
Definition: Builders.h:205
This class represents a single result from folding an operation.
Definition: OpDefinition.h:271
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
A class for computing basic postdominance information.
Definition: Dominance.h:204
This class provides an abstraction over the different types of ranges over Values.
Definition: ValueRange.h:387
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:96
std::optional< SmallVector< Value, 8 > > expandAffineMap(OpBuilder &builder, Location loc, AffineMap affineMap, ValueRange operands)
Create a sequence of operations that implement the affineMap applied to the given operands (as it it ...
Definition: Utils.cpp:229
void affineScalarReplace(func::FuncOp f, DominanceInfo &domInfo, PostDominanceInfo &postDomInfo, AliasAnalysis &analysis)
Replace affine store and load accesses by scalars by forwarding stores to loads and eliminate invaria...
Definition: Utils.cpp:1039
Value expandAffineExpr(OpBuilder &builder, Location loc, AffineExpr expr, ValueRange dimValues, ValueRange symbolValues)
Emit code that computes the given affine expression using standard arithmetic operations applied to t...
Definition: Utils.cpp:219
void normalizeAffineParallel(AffineParallelOp op)
Normalize a affine.parallel op so that lower bounds are 0 and steps are 1.
Definition: Utils.cpp:495
LogicalResult affineParallelize(AffineForOp forOp, ArrayRef< LoopReduction > parallelReductions={}, AffineParallelOp *resOp=nullptr)
Replaces a parallel affine.for op with a 1-d affine.parallel op.
Definition: Utils.cpp:353
OpFoldResult makeComposedFoldedAffineMax(OpBuilder &b, Location loc, AffineMap map, ArrayRef< OpFoldResult > operands)
Constructs an AffineMinOp that computes a maximum across the results of applying map to operands,...
Definition: AffineOps.cpp:1328
void vectorizeAffineLoops(Operation *parentOp, llvm::DenseSet< Operation *, DenseMapInfo< Operation * >> &loops, ArrayRef< int64_t > vectorSizes, ArrayRef< int64_t > fastestVaryingPattern, const ReductionLoopMap &reductionLoops=ReductionLoopMap())
Vectorizes affine loops in 'loops' using the n-D vectorization factors in 'vectorSizes'.
LogicalResult normalizeAffineFor(AffineForOp op, bool promoteSingleIter=false)
Normalize an affine.for op.
Definition: Utils.cpp:559
OpFoldResult makeComposedFoldedAffineMin(OpBuilder &b, Location loc, AffineMap map, ArrayRef< OpFoldResult > operands)
Constructs an AffineMinOp that computes a minimum across the results of applying map to operands,...
Definition: AffineOps.cpp:1321
OpFoldResult makeComposedFoldedAffineApply(OpBuilder &b, Location loc, AffineMap map, ArrayRef< OpFoldResult > operands)
Constructs an AffineApplyOp that applies map to operands after composing the map with the maps of any...
Definition: AffineOps.cpp:1217
MemRefType normalizeMemRefType(MemRefType memrefType)
Normalizes memrefType so that the affine layout map of the memref is transformed to an identity map w...
Definition: Utils.cpp:1876
LogicalResult normalizeMemRef(AllocLikeOp op)
Rewrites the memref defined by alloc or reinterpret_cast op to have an identity layout map and update...
Definition: Utils.cpp:1726
DenseMap< Operation *, SmallVector< LoopReduction, 2 > > ReductionLoopMap
Definition: Utils.h:43
FailureOr< SmallVector< Value > > delinearizeIndex(OpBuilder &b, Location loc, Value linearIndex, ArrayRef< Value > basis, bool hasOuterBound=true)
Generate the IR to delinearize linearIndex given the basis and return the multi-index.
Definition: Utils.cpp:1979
OpFoldResult linearizeIndex(ArrayRef< OpFoldResult > multiIndex, ArrayRef< OpFoldResult > basis, ImplicitLocOpBuilder &builder)
Definition: Utils.cpp:2039
DivModValue getDivMod(OpBuilder &b, Location loc, Value lhs, Value rhs)
Create IR to calculate (div lhs, rhs) and (mod lhs, rhs).
Definition: Utils.cpp:1955
bool hasNoInterveningEffect(Operation *start, T memOp, llvm::function_ref< bool(Value, Value)> mayAlias)
Ensure that all operations that could be executed after start (noninclusive) and prior to memOp (e....
Definition: Utils.cpp:686
void createAffineComputationSlice(Operation *opInst, SmallVectorImpl< AffineApplyOp > *sliceOps)
Given an operation, inserts one or more single result affine apply operations, results of which are e...
Definition: Utils.cpp:1421
LogicalResult hoistAffineIfOp(AffineIfOp ifOp, bool *folded=nullptr)
Hoists out affine.if/else to as high as possible, i.e., past all invariant affine....
Definition: Utils.cpp:415
AffineExpr substWithMin(AffineExpr e, AffineExpr dim, AffineExpr min, AffineExpr max, bool positivePath=true)
Traverse e and return an AffineExpr where all occurrences of dim have been replaced by either:
Definition: Utils.cpp:468
LogicalResult replaceAllMemRefUsesWith(Value oldMemRef, Value newMemRef, ArrayRef< Value > extraIndices={}, AffineMap indexRemap=AffineMap(), ArrayRef< Value > extraOperands={}, ArrayRef< Value > symbolOperands={}, Operation *domOpFilter=nullptr, Operation *postDomOpFilter=nullptr, bool allowNonDereferencingOps=false, bool replaceInDeallocOp=false)
Replaces all "dereferencing" uses of oldMemRef with newMemRef while optionally remapping the old memr...
Definition: Utils.cpp:1305
LogicalResult vectorizeAffineLoopNest(std::vector< SmallVector< AffineForOp, 2 >> &loops, const VectorizationStrategy &strategy)
External utility to vectorize affine loops from a single loop nest using an n-D vectorization strateg...
Include the generated interface declarations.
Helper struct to build simple AffineValueExprs with minimal type inference support.
Definition: Utils.h:372
OpFoldResult add(AffineValueExpr lhs, AffineValueExpr rhs)
Definition: Utils.h:374
OpFoldResult min(ArrayRef< OpFoldResult > vals)
Definition: Utils.h:391
OpFoldResult ceil(AffineValueExpr lhs, AffineValueExpr rhs)
Definition: Utils.h:387
OpFoldResult max(ArrayRef< OpFoldResult > vals)
Definition: Utils.h:396
AffineBuilder(OpBuilder &b, Location loc)
Definition: Utils.h:373
OpFoldResult floor(AffineValueExpr lhs, AffineValueExpr rhs)
Definition: Utils.h:383
OpFoldResult sub(AffineValueExpr lhs, AffineValueExpr rhs)
Definition: Utils.h:377
OpFoldResult mul(AffineValueExpr lhs, AffineValueExpr rhs)
Definition: Utils.h:380
AffineValueExpr(AffineExpr e)
Definition: Utils.h:355
AffineValueExpr bind(Value v)
Definition: Utils.h:356
AffineValueExpr bind(OpFoldResult v)
Definition: Utils.h:360
Holds the result of (div a, b) and (mod a, b).
Definition: Utils.h:309
Holds parameters to perform n-D vectorization on a single loop nest.
Definition: Utils.h:93
SmallVector< int64_t, 8 > vectorSizes
Definition: Utils.h:96
DenseMap< Operation *, unsigned > loopToVectorDim
Definition: Utils.h:100
ReductionLoopMap reductionLoops
Definition: Utils.h:103