Skip to content

Commit b78ceef

Browse files
authored
[mlir][scf] Fix crash in extractFixedOuterLoops with iter_args loops (llvm#184106)
The stripmineSink helper splices loop body operations into a new inner scf.for that has no iter_args. When the target loop carries iter_args, values yielded by the spliced body are moved inside the inner loop, but the outer loop's yield terminator still references those values, creating an SSA invariant violation. In debug builds this triggers the assertion use_empty() && "Cannot destroy a value that still has uses\!" when the outer RewriterBase tries to erase the now-broken operations. Fix: in extractFixedOuterLoops, skip the strip-mining transformation if any of the collected perfectly-nested loops have iter_args. Add a regression test to parametric-tiling.mlir. Fixes llvm#129044 Assisted-by: Claude Code
1 parent 7beba38 commit b78ceef

2 files changed

Lines changed: 28 additions & 0 deletions

File tree

mlir/lib/Dialect/SCF/Utils/Utils.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,6 +1351,15 @@ TileLoops mlir::extractFixedOuterLoops(scf::ForOp rootForOp,
13511351
if (forOps.size() < sizes.size())
13521352
sizes = sizes.take_front(forOps.size());
13531353

1354+
// The strip-mining transformation splices loop bodies into a new inner loop
1355+
// without threading iter_args. If any of the collected loops carries
1356+
// iter_args, the splice would produce invalid IR (yielded values from the
1357+
// inner scope used in the outer terminator). Skip the transformation in
1358+
// that case.
1359+
if (llvm::any_of(forOps,
1360+
[](scf::ForOp op) { return !op.getInitArgs().empty(); }))
1361+
return {};
1362+
13541363
// Compute the tile sizes such that i-th outer loop executes size[i]
13551364
// iterations. Given that the loop current executes
13561365
// numIterations = ceildiv((upperBound - lowerBound), step)

mlir/test/Transforms/parametric-tiling.mlir

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,22 @@ func.func @triangular(%arg0: memref<?x?xf32>) {
127127
}
128128
return
129129
}
130+
131+
// Verify that extractFixedOuterLoops silently skips loops with iter_args
132+
// instead of producing invalid IR (regression test for
133+
// https://github.com/llvm/llvm-project/issues/129044).
134+
135+
// COMMON-LABEL: @loop_with_iter_args
136+
// COMMON: scf.for {{.*}} iter_args({{.*}}) -> (f32)
137+
func.func @loop_with_iter_args(%buffer: memref<1024xf32>, %lb: index,
138+
%ub: index, %step: index) -> f32 {
139+
%initial_sum = arith.constant 0.0 : f32
140+
// This loop has iter_args; strip-mining must not be applied.
141+
%final_sum = scf.for %iv = %lb to %ub step %step
142+
iter_args(%sum_iter = %initial_sum) -> (f32) {
143+
%element = memref.load %buffer[%iv] : memref<1024xf32>
144+
%updated_sum = arith.addf %sum_iter, %element : f32
145+
scf.yield %updated_sum : f32
146+
}
147+
return %final_sum : f32
148+
}

0 commit comments

Comments
 (0)