[Mlir-commits] [mlir] 9aa7434 - [mlir][SCF] Further simplify affine maps during `for-loop-canonicalization`

Matthias Springer llvmlistbot at llvm.org
Mon Feb 7 09:40:27 PST 2022


Author: Matthias Springer
Date: 2022-02-08T02:40:08+09:00
New Revision: 9aa74347d5ad34ecaa990bd19fcffe0c7fbb8256

URL: https://github.com/llvm/llvm-project/commit/9aa74347d5ad34ecaa990bd19fcffe0c7fbb8256
DIFF: https://github.com/llvm/llvm-project/commit/9aa74347d5ad34ecaa990bd19fcffe0c7fbb8256.diff

LOG: [mlir][SCF] Further simplify affine maps during `for-loop-canonicalization`

* Implement `FlatAffineConstraints::getConstantBound(EQ)`.
* Inject a simpler constraint for loops that have at most 1 iteration.
* Taking into account constant EQ bounds of FlatAffineConstraint dims/symbols during canonicalization of the resulting affine map in `canonicalizeMinMaxOp`.

Differential Revision: https://reviews.llvm.org/D119153

Added: 
    

Modified: 
    mlir/include/mlir/Analysis/Presburger/IntegerPolyhedron.h
    mlir/lib/Analysis/Presburger/IntegerPolyhedron.cpp
    mlir/lib/Dialect/SCF/Utils/AffineCanonicalizationUtils.cpp
    mlir/test/Dialect/SCF/for-loop-canonicalization.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Analysis/Presburger/IntegerPolyhedron.h b/mlir/include/mlir/Analysis/Presburger/IntegerPolyhedron.h
index fd2dca6f99b98..4cdccef6db155 100644
--- a/mlir/include/mlir/Analysis/Presburger/IntegerPolyhedron.h
+++ b/mlir/include/mlir/Analysis/Presburger/IntegerPolyhedron.h
@@ -374,7 +374,6 @@ class IntegerPolyhedron {
 
   /// Returns the constant bound for the pos^th identifier if there is one;
   /// None otherwise.
-  // TODO: Support EQ bounds.
   Optional<int64_t> getConstantBound(BoundType type, unsigned pos) const;
 
   /// Removes constraints that are independent of (i.e., do not have a

diff  --git a/mlir/lib/Analysis/Presburger/IntegerPolyhedron.cpp b/mlir/lib/Analysis/Presburger/IntegerPolyhedron.cpp
index 2d65fd9d0fcd1..837830eeff7a0 100644
--- a/mlir/lib/Analysis/Presburger/IntegerPolyhedron.cpp
+++ b/mlir/lib/Analysis/Presburger/IntegerPolyhedron.cpp
@@ -1518,11 +1518,21 @@ IntegerPolyhedron::computeConstantLowerOrUpperBound(unsigned pos) {
 
 Optional<int64_t> IntegerPolyhedron::getConstantBound(BoundType type,
                                                       unsigned pos) const {
-  assert(type != BoundType::EQ && "EQ not implemented");
-  IntegerPolyhedron tmpCst(*this);
   if (type == BoundType::LB)
-    return tmpCst.computeConstantLowerOrUpperBound</*isLower=*/true>(pos);
-  return tmpCst.computeConstantLowerOrUpperBound</*isLower=*/false>(pos);
+    return IntegerPolyhedron(*this)
+        .computeConstantLowerOrUpperBound</*isLower=*/true>(pos);
+  if (type == BoundType::UB)
+    return IntegerPolyhedron(*this)
+        .computeConstantLowerOrUpperBound</*isLower=*/false>(pos);
+
+  assert(type == BoundType::EQ && "expected EQ");
+  Optional<int64_t> lb =
+      IntegerPolyhedron(*this)
+          .computeConstantLowerOrUpperBound</*isLower=*/true>(pos);
+  Optional<int64_t> ub =
+      IntegerPolyhedron(*this)
+          .computeConstantLowerOrUpperBound</*isLower=*/false>(pos);
+  return (lb && ub && *lb == *ub) ? Optional<int64_t>(*ub) : None;
 }
 
 // A simple (naive and conservative) check for hyper-rectangularity.

diff  --git a/mlir/lib/Dialect/SCF/Utils/AffineCanonicalizationUtils.cpp b/mlir/lib/Dialect/SCF/Utils/AffineCanonicalizationUtils.cpp
index 31f0bd534559f..07f7435998015 100644
--- a/mlir/lib/Dialect/SCF/Utils/AffineCanonicalizationUtils.cpp
+++ b/mlir/lib/Dialect/SCF/Utils/AffineCanonicalizationUtils.cpp
@@ -183,6 +183,16 @@ canonicalizeMinMaxOp(RewriterBase &rewriter, Operation *op, AffineMap map,
   AffineMap newMap = alignedBoundMap;
   SmallVector<Value> newOperands;
   unpackOptionalValues(constraints.getMaybeDimAndSymbolValues(), newOperands);
+  // If dims/symbols have known constant values, use those in order to simplify
+  // the affine map further.
+  for (int64_t i = 0, e = constraints.getNumIds(); i < e; ++i) {
+    // Skip unused operands and operands that are already constants.
+    if (!newOperands[i] || getConstantIntValue(newOperands[i]))
+      continue;
+    if (auto bound = constraints.getConstantBound(FlatAffineConstraints::EQ, i))
+      newOperands[i] =
+          rewriter.create<arith::ConstantIndexOp>(op->getLoc(), *bound);
+  }
   mlir::canonicalizeMapAndOperands(&newMap, &newOperands);
   rewriter.setInsertionPoint(op);
   rewriter.replaceOpWithNewOp<AffineApplyOp>(op, newMap, newOperands);
@@ -211,19 +221,29 @@ addLoopRangeConstraints(FlatAffineValueConstraints &constraints, Value iv,
   if (ubInt)
     constraints.addBound(FlatAffineConstraints::EQ, dimUb, *ubInt);
 
-  // iv >= lb (equiv.: iv - lb >= 0)
+  // Lower bound: iv >= lb (equiv.: iv - lb >= 0)
   SmallVector<int64_t> ineqLb(constraints.getNumCols(), 0);
   ineqLb[dimIv] = 1;
   ineqLb[dimLb] = -1;
   constraints.addInequality(ineqLb);
 
-  // iv < lb + step * ((ub - lb - 1) floorDiv step) + 1
-  AffineExpr exprLb = lbInt ? rewriter.getAffineConstantExpr(*lbInt)
-                            : rewriter.getAffineDimExpr(dimLb);
-  AffineExpr exprUb = ubInt ? rewriter.getAffineConstantExpr(*ubInt)
-                            : rewriter.getAffineDimExpr(dimUb);
-  AffineExpr ivUb =
-      exprLb + 1 + (*stepInt * ((exprUb - exprLb - 1).floorDiv(*stepInt)));
+  // Upper bound
+  AffineExpr ivUb;
+  if (lbInt && ubInt && (*lbInt + *stepInt >= *ubInt)) {
+    // The loop has at most one iteration.
+    // iv < lb + 1
+    // TODO: Try to derive this constraint by simplifying the expression in
+    // the else-branch.
+    ivUb = rewriter.getAffineDimExpr(dimLb) + 1;
+  } else {
+    // The loop may have more than one iteration.
+    // iv < lb + step * ((ub - lb - 1) floorDiv step) + 1
+    AffineExpr exprLb = lbInt ? rewriter.getAffineConstantExpr(*lbInt)
+                              : rewriter.getAffineDimExpr(dimLb);
+    AffineExpr exprUb = ubInt ? rewriter.getAffineConstantExpr(*ubInt)
+                              : rewriter.getAffineDimExpr(dimUb);
+    ivUb = exprLb + 1 + (*stepInt * ((exprUb - exprLb - 1).floorDiv(*stepInt)));
+  }
   auto map = AffineMap::get(
       /*dimCount=*/constraints.getNumDimIds(),
       /*symbolCount=*/constraints.getNumSymbolIds(), /*result=*/ivUb);

diff  --git a/mlir/test/Dialect/SCF/for-loop-canonicalization.mlir b/mlir/test/Dialect/SCF/for-loop-canonicalization.mlir
index e26dfa937a528..da66be5ae5cca 100644
--- a/mlir/test/Dialect/SCF/for-loop-canonicalization.mlir
+++ b/mlir/test/Dialect/SCF/for-loop-canonicalization.mlir
@@ -349,3 +349,22 @@ func @tensor_dim_of_loop_result_no_canonicalize(%t : tensor<?x?xf32>,
   %dim = tensor.dim %1, %c0 : tensor<?x?xf32>
   return %dim : index
 }
+
+// -----
+
+// CHECK-LABEL: func @one_trip_scf_for_canonicalize_min
+//       CHECK:   %[[C4:.*]] = arith.constant 4 : i64
+//       CHECK:   scf.for
+//       CHECK:     memref.store %[[C4]], %{{.*}}[] : memref<i64>
+func @one_trip_scf_for_canonicalize_min(%A : memref<i64>) {
+  %c0 = arith.constant 0 : index
+  %c2 = arith.constant 2 : index
+  %c4 = arith.constant 4 : index
+
+  scf.for %i = %c0 to %c4 step %c4 {
+    %1 = affine.min affine_map<(d0, d1)[] -> (4, d1 - d0)> (%i, %c4)
+    %2 = arith.index_cast %1: index to i64
+    memref.store %2, %A[]: memref<i64>
+  }
+  return
+}


        


More information about the Mlir-commits mailing list