Skip to content

Commit 248e748

Browse files
authored
[mlir][affine] Generalize canonicalization for one-element delinearize (#114871)
There was an existing canonicalization pattern for delinearize_index that would remove `affine.delinearize_index %linear into (%basis)` under some conditions. However, the delinearize_index means that this rewrite is always permissisible.
1 parent 847d507 commit 248e748

File tree

2 files changed

+11
-61
lines changed

2 files changed

+11
-61
lines changed

mlir/lib/Dialect/Affine/IR/AffineOps.cpp

Lines changed: 9 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -4605,74 +4605,22 @@ struct DropUnitExtentBasis
46054605
}
46064606
};
46074607

4608-
/// Drop delinearization pattern related to loops in the following way
4608+
/// Drop delinearization with a single basis element
46094609
///
4610-
/// ```
4611-
/// <loop>(%iv) = (%c0) to (%ub) step (%c1) {
4612-
/// %0 = affine.delinearize_index %iv into (%ub) : index
4613-
/// <some_use>(%0)
4614-
/// }
4615-
/// ```
4616-
///
4617-
/// can be canonicalized to
4618-
///
4619-
/// ```
4620-
/// <loop>(%iv) = (%c0) to (%ub) step (%c1) {
4621-
/// <some_use>(%iv)
4622-
/// }
4623-
/// ```
4624-
struct DropDelinearizeOfSingleLoop
4610+
/// By definition, `delinearize_index %linear into (%basis)` is
4611+
/// `%linear floorDiv 1` (since `1` is the product of the basis elememts,
4612+
/// ignoring the 0th one, and since there is no previous division we need
4613+
/// to use the remainder of). Therefore, a single-element `delinearize`
4614+
/// can be replaced by the underlying linear index.
4615+
struct DropDelinearizeOneBasisElement
46254616
: public OpRewritePattern<affine::AffineDelinearizeIndexOp> {
46264617
using OpRewritePattern::OpRewritePattern;
46274618

46284619
LogicalResult matchAndRewrite(affine::AffineDelinearizeIndexOp delinearizeOp,
46294620
PatternRewriter &rewriter) const override {
46304621
if (delinearizeOp.getStaticBasis().size() != 1)
46314622
return failure();
4632-
auto basis = delinearizeOp.getMixedBasis();
4633-
4634-
// Check that the `linear_index` is an induction variable.
4635-
auto inductionVar = dyn_cast<BlockArgument>(delinearizeOp.getLinearIndex());
4636-
if (!inductionVar)
4637-
return failure();
4638-
4639-
// Check that the parent is a `LoopLikeOpInterface`.
4640-
auto loopLikeOp = dyn_cast<LoopLikeOpInterface>(
4641-
inductionVar.getParentRegion()->getParentOp());
4642-
if (!loopLikeOp)
4643-
return failure();
4644-
4645-
// Check that loop is unit-rank and that the `linear_index` is the induction
4646-
// variable.
4647-
auto inductionVars = loopLikeOp.getLoopInductionVars();
4648-
if (!inductionVars || inductionVars->size() != 1 ||
4649-
inductionVars->front() != inductionVar) {
4650-
return rewriter.notifyMatchFailure(
4651-
delinearizeOp, "`linear_index` is not loop induction variable");
4652-
}
4653-
4654-
// Check that the upper-bound is the basis.
4655-
auto upperBounds = loopLikeOp.getLoopUpperBounds();
4656-
if (!upperBounds || upperBounds->size() != 1 ||
4657-
upperBounds->front() != basis.front()) {
4658-
return rewriter.notifyMatchFailure(delinearizeOp,
4659-
"`basis` is not upper bound");
4660-
}
4661-
4662-
// Check that the lower bound is zero.
4663-
auto lowerBounds = loopLikeOp.getLoopLowerBounds();
4664-
if (!lowerBounds || lowerBounds->size() != 1 ||
4665-
!isZeroIndex(lowerBounds->front())) {
4666-
return rewriter.notifyMatchFailure(delinearizeOp,
4667-
"loop lower bound is not zero");
4668-
}
4669-
4670-
// Check that the step is one.
4671-
auto steps = loopLikeOp.getLoopSteps();
4672-
if (!steps || steps->size() != 1 || !isConstantIntValue(steps->front(), 1))
4673-
return rewriter.notifyMatchFailure(delinearizeOp, "loop step is not one");
4674-
4675-
rewriter.replaceOp(delinearizeOp, inductionVar);
4623+
rewriter.replaceOp(delinearizeOp, delinearizeOp.getLinearIndex());
46764624
return success();
46774625
}
46784626
};
@@ -4681,7 +4629,7 @@ struct DropDelinearizeOfSingleLoop
46814629

46824630
void affine::AffineDelinearizeIndexOp::getCanonicalizationPatterns(
46834631
RewritePatternSet &patterns, MLIRContext *context) {
4684-
patterns.insert<DropDelinearizeOfSingleLoop, DropUnitExtentBasis>(context);
4632+
patterns.insert<DropDelinearizeOneBasisElement, DropUnitExtentBasis>(context);
46854633
}
46864634

46874635
//===----------------------------------------------------------------------===//

mlir/test/Dialect/Affine/canonicalize.mlir

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,6 +1517,7 @@ func.func @drop_single_loop_delinearize(%arg0 : index, %arg1 : index) -> index {
15171517
// -----
15181518

15191519
// CHECK-LABEL: func @delinearize_non_induction_variable
1520+
// CHECK-NOT: affine.delinearize
15201521
func.func @delinearize_non_induction_variable(%arg0: memref<?xi32>, %i : index, %t0 : index, %t1 : index, %t2 : index) -> index {
15211522
%1 = affine.apply affine_map<(d0)[s0, s1, s2] -> (d0 + s0 + s1 * 64 + s2 * 128)>(%i)[%t0, %t1, %t2]
15221523
%2 = affine.delinearize_index %1 into (1024) : index
@@ -1526,6 +1527,7 @@ func.func @delinearize_non_induction_variable(%arg0: memref<?xi32>, %i : index,
15261527
// -----
15271528

15281529
// CHECK-LABEL: func @delinearize_non_loop_like
1530+
// CHECK-NOT: affine.delinearize
15291531
func.func @delinearize_non_loop_like(%arg0: memref<?xi32>, %i : index) -> index {
15301532
%2 = affine.delinearize_index %i into (1024) : index
15311533
return %2 : index

0 commit comments

Comments
 (0)