[mlir][affine] Modify assertion into a user visible diagnostic#136474
[mlir][affine] Modify assertion into a user visible diagnostic#136474
Conversation
|
@llvm/pr-subscribers-mlir-vector @llvm/pr-subscribers-mlir Author: Prakhar Dixit (Prakhar-Dixit) ChangesFixes #122227 Minimal example crashing : The single loop %i contributes two indices (%row and %col) to the 2D memref access. The permutation map expects one index per vectorized loop dimension, but here one loop (%i) maps to two indices (dim=0 and dim=1). The code detects this when trying to assign the second index (dim=1) to the same vector dimension (perm[0]). Full diff: https://github.com/llvm/llvm-project/pull/136474.diff 2 Files Affected:
diff --git a/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp b/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp
index 024e8ccb901de..f15ed4b0d5f84 100644
--- a/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp
+++ b/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp
@@ -141,8 +141,14 @@ static AffineMap makePermutationMap(
unsigned countInvariantIndices = 0;
for (unsigned dim = 0; dim < numIndices; ++dim) {
if (!invariants.count(indices[dim])) {
- assert(perm[kvp.second] == getAffineConstantExpr(0, context) &&
- "permutationMap already has an entry along dim");
+ if (perm[kvp.second] != getAffineConstantExpr(0, context)) {
+ auto loopOp = cast<affine::AffineForOp>(kvp.first);
+ loopOp->emitError(
+ "loop induction variable is used in multiple indices, which is "
+ "unsupported for vectorization. Consider using nested loops "
+ "instead of a single loop with affine.apply.");
+ return AffineMap();
+ }
perm[kvp.second] = getAffineDimExpr(dim, context);
} else {
++countInvariantIndices;
diff --git a/mlir/test/Dialect/Affine/SuperVectorize/vectorize_unsupported.mlir b/mlir/test/Dialect/Affine/SuperVectorize/vectorize_unsupported.mlir
index 6c1a7c48c4cb1..c8c009f02212b 100644
--- a/mlir/test/Dialect/Affine/SuperVectorize/vectorize_unsupported.mlir
+++ b/mlir/test/Dialect/Affine/SuperVectorize/vectorize_unsupported.mlir
@@ -9,3 +9,38 @@ func.func @unparallel_loop_reduction_unsupported(%in: memref<256x512xf32>, %out:
}
return
}
+
+// -----
+
+#map = affine_map<(d0)[s0] -> (d0 mod s0)>
+#map1 = affine_map<(d0)[s0] -> (d0 floordiv s0)>
+
+func.func @single_loop_unrolling_2D_access_pattern(%arg0: index) -> memref<2x2xf32> {
+ %c2 = arith.constant 2 : index
+ %cst = arith.constant 1.0 : f32
+ %alloc = memref.alloc() : memref<2x2xf32>
+
+ affine.for %i = 0 to 4 {
+ %row = affine.apply #map1(%i)[%c2]
+ %col = affine.apply #map(%i)[%c2]
+ affine.store %cst, %alloc[%row, %col] : memref<2x2xf32>
+ }
+
+ return %alloc : memref<2x2xf32>
+ }
+
+// CHECK: #[[$ATTR_0:.+]] = affine_map<(d0)[s0] -> (d0 floordiv s0)>
+// CHECK: #[[$ATTR_1:.+]] = affine_map<(d0)[s0] -> (d0 mod s0)>
+
+// CHECK-LABEL: func.func @single_loop_unrolling_2D_access_pattern(
+// CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: index) -> memref<2x2xf32> {
+// CHECK: %[[VAL_1:.*]] = arith.constant 2 : index
+// CHECK: %[[VAL_2:.*]] = arith.constant 1.000000e+00 : f32
+// CHECK: %[[VAL_3:.*]] = memref.alloc() : memref<2x2xf32>
+// CHECK: affine.for %[[VAL_4:.*]] = 0 to 4 {
+// CHECK: %[[VAL_5:.*]] = affine.apply #[[$ATTR_0]](%[[VAL_4]]){{\[}}%[[VAL_1]]]
+// CHECK: %[[VAL_6:.*]] = affine.apply #[[$ATTR_1]](%[[VAL_4]]){{\[}}%[[VAL_1]]]
+// CHECK: affine.store %[[VAL_2]], %[[VAL_3]]{{\[}}%[[VAL_5]], %[[VAL_6]]] : memref<2x2xf32>
+// CHECK: }
+// CHECK: return %[[VAL_3]] : memref<2x2xf32>
+// CHECK: }
\ No newline at end of file
|
|
@llvm/pr-subscribers-mlir-affine Author: Prakhar Dixit (Prakhar-Dixit) ChangesFixes #122227 Minimal example crashing : The single loop %i contributes two indices (%row and %col) to the 2D memref access. The permutation map expects one index per vectorized loop dimension, but here one loop (%i) maps to two indices (dim=0 and dim=1). The code detects this when trying to assign the second index (dim=1) to the same vector dimension (perm[0]). Full diff: https://github.com/llvm/llvm-project/pull/136474.diff 2 Files Affected:
diff --git a/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp b/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp
index 024e8ccb901de..f15ed4b0d5f84 100644
--- a/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp
+++ b/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp
@@ -141,8 +141,14 @@ static AffineMap makePermutationMap(
unsigned countInvariantIndices = 0;
for (unsigned dim = 0; dim < numIndices; ++dim) {
if (!invariants.count(indices[dim])) {
- assert(perm[kvp.second] == getAffineConstantExpr(0, context) &&
- "permutationMap already has an entry along dim");
+ if (perm[kvp.second] != getAffineConstantExpr(0, context)) {
+ auto loopOp = cast<affine::AffineForOp>(kvp.first);
+ loopOp->emitError(
+ "loop induction variable is used in multiple indices, which is "
+ "unsupported for vectorization. Consider using nested loops "
+ "instead of a single loop with affine.apply.");
+ return AffineMap();
+ }
perm[kvp.second] = getAffineDimExpr(dim, context);
} else {
++countInvariantIndices;
diff --git a/mlir/test/Dialect/Affine/SuperVectorize/vectorize_unsupported.mlir b/mlir/test/Dialect/Affine/SuperVectorize/vectorize_unsupported.mlir
index 6c1a7c48c4cb1..c8c009f02212b 100644
--- a/mlir/test/Dialect/Affine/SuperVectorize/vectorize_unsupported.mlir
+++ b/mlir/test/Dialect/Affine/SuperVectorize/vectorize_unsupported.mlir
@@ -9,3 +9,38 @@ func.func @unparallel_loop_reduction_unsupported(%in: memref<256x512xf32>, %out:
}
return
}
+
+// -----
+
+#map = affine_map<(d0)[s0] -> (d0 mod s0)>
+#map1 = affine_map<(d0)[s0] -> (d0 floordiv s0)>
+
+func.func @single_loop_unrolling_2D_access_pattern(%arg0: index) -> memref<2x2xf32> {
+ %c2 = arith.constant 2 : index
+ %cst = arith.constant 1.0 : f32
+ %alloc = memref.alloc() : memref<2x2xf32>
+
+ affine.for %i = 0 to 4 {
+ %row = affine.apply #map1(%i)[%c2]
+ %col = affine.apply #map(%i)[%c2]
+ affine.store %cst, %alloc[%row, %col] : memref<2x2xf32>
+ }
+
+ return %alloc : memref<2x2xf32>
+ }
+
+// CHECK: #[[$ATTR_0:.+]] = affine_map<(d0)[s0] -> (d0 floordiv s0)>
+// CHECK: #[[$ATTR_1:.+]] = affine_map<(d0)[s0] -> (d0 mod s0)>
+
+// CHECK-LABEL: func.func @single_loop_unrolling_2D_access_pattern(
+// CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: index) -> memref<2x2xf32> {
+// CHECK: %[[VAL_1:.*]] = arith.constant 2 : index
+// CHECK: %[[VAL_2:.*]] = arith.constant 1.000000e+00 : f32
+// CHECK: %[[VAL_3:.*]] = memref.alloc() : memref<2x2xf32>
+// CHECK: affine.for %[[VAL_4:.*]] = 0 to 4 {
+// CHECK: %[[VAL_5:.*]] = affine.apply #[[$ATTR_0]](%[[VAL_4]]){{\[}}%[[VAL_1]]]
+// CHECK: %[[VAL_6:.*]] = affine.apply #[[$ATTR_1]](%[[VAL_4]]){{\[}}%[[VAL_1]]]
+// CHECK: affine.store %[[VAL_2]], %[[VAL_3]]{{\[}}%[[VAL_5]], %[[VAL_6]]] : memref<2x2xf32>
+// CHECK: }
+// CHECK: return %[[VAL_3]] : memref<2x2xf32>
+// CHECK: }
\ No newline at end of file
|
|
Just a gentle reminder! |
…136474) Fixes llvm#122227 The loop’s induction variable (%i) is used to compute two different indices via affine.apply. And the Vectorization Assumption is Violated i.e, Each vectorized loop should contribute at most one non-invariant index. **Minimal example crashing :** ``` #map = affine_map<(d0)[s0] -> (d0 mod s0)> #map1 = affine_map<(d0)[s0] -> (d0 floordiv s0)> func.func @single_loop_unrolling_2D_access_pattern(%arg0: index) -> memref<2x2xf32> { %c2 = arith.constant 2 : index %cst = arith.constant 1.0 : f32 %alloc = memref.alloc() : memref<2x2xf32> affine.for %i = 0 to 4 { %row = affine.apply #map1(%i)[%c2] %col = affine.apply #map(%i)[%c2] affine.store %cst, %alloc[%row, %col] : memref<2x2xf32> } return %alloc : memref<2x2xf32> } ``` The single loop %i contributes two indices (%row and %col) to the 2D memref access. The permutation map expects one index per vectorized loop dimension, but here one loop (%i) maps to two indices (dim=0 and dim=1). The code detects this when trying to assign the second index (dim=1) to the same vector dimension (perm[0]).
…136474) Fixes llvm#122227 The loop’s induction variable (%i) is used to compute two different indices via affine.apply. And the Vectorization Assumption is Violated i.e, Each vectorized loop should contribute at most one non-invariant index. **Minimal example crashing :** ``` #map = affine_map<(d0)[s0] -> (d0 mod s0)> #map1 = affine_map<(d0)[s0] -> (d0 floordiv s0)> func.func @single_loop_unrolling_2D_access_pattern(%arg0: index) -> memref<2x2xf32> { %c2 = arith.constant 2 : index %cst = arith.constant 1.0 : f32 %alloc = memref.alloc() : memref<2x2xf32> affine.for %i = 0 to 4 { %row = affine.apply #map1(%i)[%c2] %col = affine.apply #map(%i)[%c2] affine.store %cst, %alloc[%row, %col] : memref<2x2xf32> } return %alloc : memref<2x2xf32> } ``` The single loop %i contributes two indices (%row and %col) to the 2D memref access. The permutation map expects one index per vectorized loop dimension, but here one loop (%i) maps to two indices (dim=0 and dim=1). The code detects this when trying to assign the second index (dim=1) to the same vector dimension (perm[0]).
Fixes #122227
The loop’s induction variable (%i) is used to compute two different indices via affine.apply.
And the Vectorization Assumption is Violated i.e, Each vectorized loop should contribute at most one non-invariant index.
Minimal example crashing :
The single loop %i contributes two indices (%row and %col) to the 2D memref access.
The permutation map expects one index per vectorized loop dimension, but here one loop (%i) maps to two indices (dim=0 and dim=1).
The code detects this when trying to assign the second index (dim=1) to the same vector dimension (perm[0]).