[Mlir-commits] [mlir] [mlir][scf] Fix the scf.while result reconstructed by upliftWhileToForLoop (PR #219617)

Alessandro Potenza llvmlistbot at llvm.org
Sun Aug 30 01:04:47 PDT 2026


https://github.com/alepot55 commented:

I built this on `11e915f2b75d` and checked the arithmetic by folding it, which makes the bug show up as three wrong constants. Input shape, with the bounds constant so `canonicalize` collapses the reconstructed expression:

```mlir
func.func @uplift_const() -> index {
  %lb = arith.constant 5 : index
  %ub = arith.constant 5 : index
  %st = arith.constant 1 : index
  %0 = scf.while (%i = %lb) : (index) -> (index) {
    %c = arith.cmpi slt, %i, %ub : index
    scf.condition(%c) %i : index
  } do {
  ^bb0(%i: index):
    "test.test1"(%i) : (index) -> ()
    %n = arith.addi %i, %st : index
    scf.yield %n : index
  }
  return %0 : index
}
```

`mlir-opt -pass-pipeline='builtin.module(func.func(test-scf-uplift-while-to-for,canonicalize))'`:

| lb, ub, step | `scf.while` returns | main | with this PR |
| --- | --- | --- | --- |
| 5, 5, 1 | 5, the loop never runs | 4 | 5 |
| 5, 3, 1 | 5, the loop never runs | 2 | 5 |
| 0, 10, 3 | 12, the first index that fails `slt` | 9 | 12 |

So both halves of the change are load-bearing, and separately: dropping the `- 1` fixes the third row, and the `maxsi` is what fixes the second, where the signed division truncates to `-2` and the old expression walked the result backwards past `lb`. `mlir/test/Dialect/SCF` is green with the patch (45 passed, 1 expectedly failed).

Two remarks, neither blocking.

The description is right that the result is `lb + tripCount * step`, but it is worth saying in the code comment *why* that differs from the last executed index, since the `- 1` presumably looked correct to whoever wrote it: `scf.condition` forwards to the results on the iteration that fails, and that iteration has already incremented. The comment you added says the first half; the second half is the part that was misread.

The clamp is on the trip count rather than on the result. Those differ when `step` is negative, where `(ub - lb + step - 1) / step` is not a ceiling division at all. I could not find a guard in `upliftWhileToForLoop` that rejects a non-positive step, so if one can reach this code the expression was already wrong before your change and stays wrong after it, just differently. Worth a look, and if a negative step really is impossible here an assert or a comment saying so would save the next reader the same trip.

No reviewers are requested on this. @Hardcode84 wrote `UpliftWhileToFor.cpp` in #76108 and is the obvious person to ask.

https://github.com/llvm/llvm-project/pull/219617


More information about the Mlir-commits mailing list