Skip to content

Commit 7beba38

Browse files
authored
[MLIR] Fix crash in ValueBoundsConstraintSet for non-entry block args (llvm#185048)
When two vector transfer ops share a non-entry block argument as an index (e.g., in a loop with unstructured control flow), calling `ValueBoundsConstraintSet::areEqual` on those values caused a crash. The first `populateConstraints` call would insert the block argument into the constraint set. The second call found it already mapped and called `getPos`, which hit an assert requiring the value to be either an OpResult or an entry-block argument. Fix with two changes: 1. In `insert()`, suppress adding non-entry block arguments to the worklist. `ValueBoundsOpInterface` cannot derive bounds for such values, so the worklist push was a no-op and triggered the re-entrant `getPos` call. 2. Remove the overly conservative assert in `getPos`. Looking up a previously inserted non-entry block argument is valid; the assert was preventing legitimate use after the value had already been inserted. Fixes llvm#119861 Assisted-by: Claude Code
1 parent 2b6bd31 commit 7beba38

2 files changed

Lines changed: 36 additions & 4 deletions

File tree

mlir/lib/Interfaces/ValueBoundsOpInterface.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,16 @@ int64_t ValueBoundsConstraintSet::insert(Value value,
282282
if (positionToValueDim[i].has_value())
283283
valueDimToPosition[*positionToValueDim[i]] = i;
284284

285-
if (addToWorklist) {
285+
// Do not add block arguments from non-entry blocks to the worklist. The
286+
// ValueBoundsOpInterface cannot derive any bounds for such values (they
287+
// arise from unstructured control flow), so putting them on the worklist
288+
// would be a no-op. More importantly, suppressing the worklist push ensures
289+
// that processWorklist never calls getExpr on such a value a second time,
290+
// which would otherwise cause the same value to be looked up as already
291+
// mapped (triggering an unintended bug path).
292+
if (addToWorklist &&
293+
(!isa<BlockArgument>(value) ||
294+
cast<BlockArgument>(value).getOwner()->isEntryBlock())) {
286295
LDBG() << "Push to worklist: " << value
287296
<< " (dim: " << dim.value_or(kIndexValue) << ")";
288297
worklist.push(pos);
@@ -334,9 +343,6 @@ int64_t ValueBoundsConstraintSet::getPos(Value value,
334343
std::optional<int64_t> dim) const {
335344
#ifndef NDEBUG
336345
assertValidValueDim(value, dim);
337-
assert((isa<OpResult>(value) ||
338-
cast<BlockArgument>(value).getOwner()->isEntryBlock()) &&
339-
"unstructured control flow is not supported");
340346
#endif // NDEBUG
341347
LDBG() << "Getting pos for: " << value
342348
<< " (dim: " << dim.value_or(kIndexValue)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: mlir-opt %s -pass-pipeline='builtin.module(func.func(test-affine-reify-value-bounds))' \
2+
// RUN: -verify-diagnostics -split-input-file
3+
4+
// Note: unstructured control flow (cf dialect) is not yet supported by the
5+
// ValueBoundsOpInterface. Block arguments from non-entry blocks cannot have
6+
// their bounds computed. The tests below verify that the infrastructure does
7+
// not crash on such inputs and fails gracefully instead.
8+
// See: https://github.com/llvm/llvm-project/issues/119861
9+
10+
// Regression test: ValueBoundsConstraintSet must not crash when asked to
11+
// reify a bound for a non-entry block argument produced by unstructured
12+
// control flow.
13+
14+
func.func @no_crash_non_entry_block_arg(%n: index) -> index {
15+
%c0 = arith.constant 0 : index
16+
cf.br ^bb1(%c0 : index)
17+
^bb1(%i: index):
18+
// expected-error@+1 {{'test.reify_bound' op could not reify bound}}
19+
%bound = "test.reify_bound"(%i) {type = "UB"} : (index) -> index
20+
"test.some_use"(%bound) : (index) -> ()
21+
%cond = arith.cmpi slt, %i, %n : index
22+
%next = arith.addi %i, %c0 : index
23+
cf.cond_br %cond, ^bb1(%next : index), ^bb2
24+
^bb2:
25+
return %i : index
26+
}

0 commit comments

Comments
 (0)