-
Notifications
You must be signed in to change notification settings - Fork 13.3k
[mlir][affine] Modify assertion into a user visible diagnostic #136474
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
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
|
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]).