Canonicalize affine set + operands while adding affine.if op domain
authorUday Bondhugula <uday@polymagelabs.com>
Thu, 5 Jan 2023 23:03:42 +0000 (04:33 +0530)
committerUday Bondhugula <uday@polymagelabs.com>
Thu, 12 Jan 2023 06:09:14 +0000 (11:39 +0530)
Canonicalize affine set + operands in addAffineIfOpDomain. This is to
ensure a unique set of operands for FlatAffineValueConstraints and in
general to provide a simplified set of constraints. For the latter
scenario, this just leads to efficiency improvements as opposed to
functionality. While on this, remove outdated/stale stuff from
AffineStructures.h.

Fixes: https://github.com/llvm/llvm-project/issues/59461

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

mlir/include/mlir/Dialect/Affine/Analysis/AffineStructures.h
mlir/lib/Dialect/Affine/Analysis/AffineStructures.cpp
mlir/test/Transforms/memref-dependence-check.mlir

index cd23e12..e519cbc 100644 (file)
@@ -88,10 +88,7 @@ public:
   explicit FlatAffineValueConstraints(ArrayRef<const AffineValueMap *> avmRef);
 
   /// Creates an affine constraint system from an IntegerSet.
-  explicit FlatAffineValueConstraints(IntegerSet set);
-
-  FlatAffineValueConstraints(ArrayRef<const AffineValueMap *> avmRef,
-                             IntegerSet set);
+  explicit FlatAffineValueConstraints(IntegerSet set, ValueRange operands = {});
 
   // Construct a hyperrectangular constraint set from ValueRanges that represent
   // induction variables, lower and upper bounds. `ivs`, `lbs` and `ubs` are
@@ -139,7 +136,6 @@ public:
   /// 'affine.for' operation are added as trailing variables (either
   /// dimensional or symbolic depending on whether the operand is a valid
   /// symbol).
-  //  TODO: add support for non-unit strides.
   LogicalResult addAffineForOpDomain(AffineForOp forOp);
 
   /// Add constraints (lower and upper bounds) for the specified
@@ -279,7 +275,7 @@ public:
 
   /// Returns true if an variable with the specified Value exists, false
   /// otherwise.
-  bool containsVar(Value mayBeVar) const;
+  bool containsVar(Value val) const;
 
   /// Swap the posA^th variable with the posB^th variable.
   void swapVar(unsigned posA, unsigned posB) override;
index 453f20c..8ed31c5 100644 (file)
@@ -150,15 +150,20 @@ FlatAffineValueConstraints::clone() const {
 }
 
 // Construct from an IntegerSet.
-FlatAffineValueConstraints::FlatAffineValueConstraints(IntegerSet set)
+FlatAffineValueConstraints::FlatAffineValueConstraints(IntegerSet set,
+                                                       ValueRange operands)
     : IntegerPolyhedron(set.getNumInequalities(), set.getNumEqualities(),
                         set.getNumDims() + set.getNumSymbols() + 1,
                         PresburgerSpace::getSetSpace(set.getNumDims(),
                                                      set.getNumSymbols(),
                                                      /*numLocals=*/0)) {
-
-  // Resize values.
-  values.resize(getNumDimAndSymbolVars(), std::nullopt);
+  // Populate values.
+  if (operands.empty()) {
+    values.resize(getNumDimAndSymbolVars(), std::nullopt);
+  } else {
+    assert(set.getNumInputs() == operands.size() && "operand count mismatch");
+    values.assign(operands.begin(), operands.end());
+  }
 
   // Flatten expressions and add them to the constraint system.
   std::vector<SmallVector<int64_t, 8>> flatExprs;
@@ -718,12 +723,14 @@ FlatAffineValueConstraints::addDomainFromSliceMaps(ArrayRef<AffineMap> lbMaps,
 }
 
 void FlatAffineValueConstraints::addAffineIfOpDomain(AffineIfOp ifOp) {
-  // Create the base constraints from the integer set attached to ifOp.
-  FlatAffineValueConstraints cst(ifOp.getIntegerSet());
+  IntegerSet set = ifOp.getIntegerSet();
+  // Canonicalize set and operands to ensure unique values for
+  // FlatAffineValueConstraints below and for early simplification.
+  SmallVector<Value> operands(ifOp.getOperands());
+  canonicalizeSetAndOperands(&set, &operands);
 
-  // Bind vars in the constraints to ifOp operands.
-  SmallVector<Value, 4> operands = ifOp.getOperands();
-  cst.setValues(0, cst.getNumDimAndSymbolVars(), operands);
+  // Create the base constraints from the integer set attached to ifOp.
+  FlatAffineValueConstraints cst(set, operands);
 
   // Merge the constraints from ifOp to the current domain. We need first merge
   // and align the IDs from both constraints, and then append the constraints
index 2e28a4c..d9bf2ff 100644 (file)
@@ -1080,3 +1080,21 @@ func.func @parallel_dependence_check_failure() {
   }
   return
 }
+
+// -----
+
+func.func @affine_if_no_dependence() {
+  %c1 = arith.constant 1 : index
+  %alloc = memref.alloc() : memref<15xi1>
+  %true = arith.constant true
+  affine.store %true, %alloc[%c1] : memref<15xi1>
+  // expected-remark@above {{dependence from 0 to 0 at depth 1 = false}}
+  // expected-remark@above {{dependence from 0 to 1 at depth 1 = false}}
+  // This set is empty.
+  affine.if affine_set<(d0, d1, d2, d3) : ((d0 + 1) mod 8 >= 0, d0 * -8 >= 0)>(%c1, %c1, %c1, %c1){
+    %265 = affine.load %alloc[%c1] : memref<15xi1>
+    // expected-remark@above {{dependence from 1 to 0 at depth 1 = false}}
+    // expected-remark@above {{dependence from 1 to 1 at depth 1 = false}}
+  }
+  return
+}