Skip to content

Commit b01c71b

Browse files
authored
[MLIR][Affine] Fix crash in loop unswitching/hoistAffineIfOp (#130401)
Fix obvious crash as a result of missing affine.parallel handling. Also, fix bug exposed in a helper method used by hoistAffineIfOp. Fixes: #62323
1 parent a779af3 commit b01c71b

File tree

2 files changed

+36
-8
lines changed

2 files changed

+36
-8
lines changed

mlir/lib/Dialect/Affine/Utils/Utils.cpp

+8-8
Original file line numberDiff line numberDiff line change
@@ -263,16 +263,17 @@ static void promoteIfBlock(AffineIfOp ifOp, bool elseBlock) {
263263
static Operation *getOutermostInvariantForOp(AffineIfOp ifOp) {
264264
// Walk up the parents past all for op that this conditional is invariant on.
265265
auto ifOperands = ifOp.getOperands();
266-
auto *res = ifOp.getOperation();
267-
while (!isa<func::FuncOp>(res->getParentOp())) {
266+
Operation *res = ifOp;
267+
while (!res->getParentOp()->hasTrait<OpTrait::IsIsolatedFromAbove>()) {
268268
auto *parentOp = res->getParentOp();
269269
if (auto forOp = dyn_cast<AffineForOp>(parentOp)) {
270270
if (llvm::is_contained(ifOperands, forOp.getInductionVar()))
271271
break;
272272
} else if (auto parallelOp = dyn_cast<AffineParallelOp>(parentOp)) {
273-
for (auto iv : parallelOp.getIVs())
274-
if (llvm::is_contained(ifOperands, iv))
275-
break;
273+
if (llvm::any_of(parallelOp.getIVs(), [&](Value iv) {
274+
return llvm::is_contained(ifOperands, iv);
275+
}))
276+
break;
276277
} else if (!isa<AffineIfOp>(parentOp)) {
277278
// Won't walk up past anything other than affine.for/if ops.
278279
break;
@@ -438,11 +439,10 @@ LogicalResult mlir::affine::hoistAffineIfOp(AffineIfOp ifOp, bool *folded) {
438439
if (folded)
439440
*folded = false;
440441

441-
// The folding above should have ensured this, but the affine.if's
442-
// canonicalization is missing composition of affine.applys into it.
442+
// The folding above should have ensured this.
443443
assert(llvm::all_of(ifOp.getOperands(),
444444
[](Value v) {
445-
return isTopLevelValue(v) || isAffineForInductionVar(v);
445+
return isTopLevelValue(v) || isAffineInductionVar(v);
446446
}) &&
447447
"operands not composed");
448448

mlir/test/Dialect/Affine/loop-unswitch.mlir

+28
Original file line numberDiff line numberDiff line change
@@ -254,3 +254,31 @@ func.func @multiple_if(%N : index) {
254254
// CHECK-NEXT: return
255255

256256
func.func private @external()
257+
258+
// Check to ensure affine.parallel ops are handled as well.
259+
260+
#set = affine_set<(d0) : (-d0 + 3 >= 0)>
261+
// CHECK-LABEL: affine_parallel
262+
func.func @affine_parallel(%arg0: memref<35xf32>) -> memref<35xf32> {
263+
%0 = llvm.mlir.constant(1.000000e+00 : f32) : f32
264+
%alloc = memref.alloc() {alignment = 64 : i64} : memref<35xf32>
265+
// CHECK: affine.parallel
266+
affine.parallel (%arg1) = (0) to (35) step (32) {
267+
// This can't be hoisted further.
268+
// CHECK-NEXT: affine.if
269+
affine.if #set(%arg1) {
270+
affine.parallel (%arg2) = (%arg1) to (%arg1 + 32) {
271+
%1 = affine.load %arg0[%arg2] : memref<35xf32>
272+
%2 = llvm.fdiv %0, %1 : f32
273+
affine.store %2, %alloc[%arg2] : memref<35xf32>
274+
}
275+
} else {
276+
affine.parallel (%arg2) = (%arg1) to (min(%arg1 + 32, 35)) {
277+
%1 = affine.load %arg0[%arg2] : memref<35xf32>
278+
%2 = llvm.fdiv %0, %1 : f32
279+
affine.store %2, %alloc[%arg2] : memref<35xf32>
280+
}
281+
}
282+
}
283+
return %alloc : memref<35xf32>
284+
}

0 commit comments

Comments
 (0)