20#include "llvm/ADT/SmallVector.h"
24#define GEN_PASS_DEF_AFFINELOOPNORMALIZE
25#include "mlir/Dialect/Affine/Transforms/Passes.h.inc"
36static FailureOr<int64_t> computeConstantBound(
AffineMap map,
41 type, var,
nullptr, {
true,
true});
52inferAffineLoopUpperConstantBound(
RewriterBase &
b, AffineForOp forOp,
53 bool promoteSingleIter =
true) {
56 if (!forOp.hasConstantLowerBound() || forOp.getConstantLowerBound() != 0)
58 if (forOp.getStepAsInt() != 1)
60 if (forOp.getUpperBoundMap().getNumResults() > 1)
66 FailureOr<int64_t> upperMin = computeConstantBound(
67 forOp.getUpperBoundMap(), forOp.getUpperBoundOperands(),
69 FailureOr<int64_t> upperMax = computeConstantBound(
70 forOp.getUpperBoundMap(), forOp.getUpperBoundOperands(),
72 if (
failed(upperMin) || *upperMin <= 0)
78 if (
failed(upperMax) || *upperMax > *upperMin) {
79 b.setInsertionPoint(forOp);
80 AffineForOp clonedForOp = cast<AffineForOp>(
b.clone(*forOp));
81 clonedForOp.setConstantUpperBound(*upperMin);
82 forOp.setConstantLowerBound(*upperMin);
83 forOp.getInitsMutable().assign(clonedForOp->getResults());
84 if (promoteSingleIter)
93 forOp.setConstantUpperBound(*upperMin);
94 if (promoteSingleIter)
102struct AffineLoopNormalizePass
103 :
public affine::impl::AffineLoopNormalizeBase<AffineLoopNormalizePass> {
104 explicit AffineLoopNormalizePass(
bool promoteSingleIter,
105 bool useExpensiveMath) {
106 this->promoteSingleIter = promoteSingleIter;
107 this->useExpensiveMath = useExpensiveMath;
110 void runOnOperation()
override {
111 getOperation().walk([&](Operation *op) {
112 if (
auto affineParallel = dyn_cast<AffineParallelOp>(op))
113 normalizeAffineParallel(affineParallel);
114 else if (
auto affineFor = dyn_cast<AffineForOp>(op))
115 (void)normalizeAffineFor(affineFor, promoteSingleIter);
120 if (useExpensiveMath) {
122 SmallVector<AffineForOp> loops;
130 getOperation()->walk([&](AffineForOp forOp) { loops.push_back(forOp); });
131 for (AffineForOp forOp : loops)
132 (void)inferAffineLoopUpperConstantBound(
b, forOp, promoteSingleIter);
139std::unique_ptr<OperationPass<func::FuncOp>>
141 bool useExpensiveMath) {
142 return std::make_unique<AffineLoopNormalizePass>(promoteSingleIter,
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
This class coordinates the application of a rewrite on a set of IR, providing a way for clients to tr...
A variable that can be added to the constraint set as a "column".
static FailureOr< int64_t > computeConstantBound(presburger::BoundType type, const Variable &var, const StopConditionFn &stopCondition=nullptr, ValueBoundsOptions options={})
Compute a constant bound for the given variable.
This class provides an abstraction over the different types of ranges over Values.
LogicalResult promoteIfSingleIteration(AffineForOp forOp)
Promotes the loop body of a AffineForOp to its containing block if the loop was known to have a singl...
std::unique_ptr< OperationPass< func::FuncOp > > createAffineLoopNormalizePass(bool promoteSingleIter=false, bool useExpensiveMath=false)
Apply normalization transformations to affine loop-like ops.
BoundType
The type of bound: equal, lower bound or upper bound.
Include the generated interface declarations.