[flang-commits] [flang] [flang][Transforms] Add LiftSCFWhileToSCFFor pass (PR #213273)

Kareem Ergawy via flang-commits flang-commits at lists.llvm.org
Mon Aug 3 07:37:06 PDT 2026


================
@@ -0,0 +1,54 @@
+// The IV recurrence's result (%ivNext) has body uses beyond the
+// scf.yield — here a `memref.store`, modelling the `fir.declare_value` ops
+// mem2reg emits after promoting a Fortran scalar variable. The body-clone
+// loop walks the continues block in source order; the IV recurrence is
+// cloned as a regular body op (its operand %iv resolves to ivAsOrig via
+// the IRMapping, and the loop-invariant step passes through unmapped).
+// SSA ordering guarantees the clone is in the new body before any cloned
+// user of its result. Without the mapping, the cloned `memref.store` would
+// hold a dangling reference to the original %ivNext inside the erased
+// scf.while.
+
+// RUN: fir-opt %s --lift-scf-while-to-scf-for 2>/dev/null | FileCheck %s
+
+func.func @iv_next_with_body_use(%lb: i32, %N: i32, %sink: memref<i32>) {
+  %c0 = arith.constant 0 : i32
+  %c1 = arith.constant 1 : i32
+  %poison = arith.constant 0 : i32
+  %r:2 = scf.while (%trip = %N, %iv = %lb) : (i32, i32) -> (i32, i32) {
+    %cmp = arith.cmpi sgt, %trip, %c0 : i32
----------------
ergawy wrote:

This pattern follows what `genFIRIncrementLoopBegin` produces for the trip counter. Also, `arith.compi` canonicalization rewrites comparison in a similar structure: https://github.com/llvm/llvm-project/blob/58862f1adfc9690ddcda8cded008bc0ecda54859/mlir/lib/Dialect/Arith/IR/ArithOps.cpp#L2393 (this does not address your loop invariable being non-zero only the fact that it will be on the RHS).

We can try to handle more general input but not sure that would be worth as a start.

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


More information about the flang-commits mailing list