[flang-commits] [flang] [FIRToMemRef] Fix fir.convert insertion inside omp.wsloop (PR #197653)

via flang-commits flang-commits at lists.llvm.org
Thu May 14 04:16:50 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-fir-hlfir

Author: Kareem Ergawy (ergawy)

<details>
<summary>Changes</summary>

When replaceFIRMemrefs inserted a fir.convert before an op inside a LoopWrapperInterface region (e.g. omp.simd inside omp.wsloop), it violated the single-nested-op invariant, producing a verifier error. Fix by walking up the LoopWrapperInterface parent chain and inserting before the outermost wrapper instead.

Co-authored-by: Claude Sonnet 4.6 <noreply@<!-- -->anthropic.com>

---
Full diff: https://github.com/llvm/llvm-project/pull/197653.diff


2 Files Affected:

- (modified) flang/lib/Optimizer/Transforms/FIRToMemRef.cpp (+7-1) 
- (added) flang/test/Transforms/FIRToMemRef/omp-wsloop-simd-private.mlir (+33) 


``````````diff
diff --git a/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp b/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
index 5b353a2e3f689..6add098647bb7 100644
--- a/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
+++ b/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
@@ -1153,7 +1153,13 @@ void FIRToMemRef::replaceFIRMemrefs(Value firMemref, Value converted,
   Type ty = firMemref.getType();
 
   for (auto op : worklist) {
-    rewriter.setInsertionPoint(op);
+    // If op is directly inside a LoopWrapperInterface region, inserting before
+    // op would violate the single-nested-op invariant. Walk up the wrapper
+    // chain and insert before the outermost wrapper instead.
+    Operation *insertBefore = op;
+    while (mlir::isa<omp::LoopWrapperInterface>(insertBefore->getParentOp()))
+      insertBefore = insertBefore->getParentOp();
+    rewriter.setInsertionPoint(insertBefore);
     Location loc = op->getLoc();
     Value replaceConvert = fir::ConvertOp::create(rewriter, loc, ty, converted);
     op->replaceUsesOfWith(firMemref, replaceConvert);
diff --git a/flang/test/Transforms/FIRToMemRef/omp-wsloop-simd-private.mlir b/flang/test/Transforms/FIRToMemRef/omp-wsloop-simd-private.mlir
new file mode 100644
index 0000000000000..4f6adf8e05b5f
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/omp-wsloop-simd-private.mlir
@@ -0,0 +1,33 @@
+// RUN: fir-opt %s --fir-to-memref | FileCheck %s
+
+// Verifies that fir-to-memref does not insert any operations in-between
+// LoopWrapperInterface ops which violates the single operation invariant enforced
+// by the interface.
+
+omp.private {type = private} @_QFEa_private_i32 : i32
+
+// CHECK-LABEL: func.func @_QQmain
+// CHECK: [[DECL:%.*]] = fir.declare
+// CHECK: [[CONV1:%.*]] = fir.convert [[DECL]]
+// CHECK: omp.parallel
+// CHECK-NEXT: {{%.*}} = fir.convert [[CONV1]]
+// CHECK-NEXT: omp.wsloop
+
+func.func @_QQmain() {
+  %c0_i32 = arith.constant 0 : i32
+  %c1_i32 = arith.constant 1 : i32
+  %0 = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFEa"}
+  %1 = fir.declare %0 {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> !fir.ref<i32>
+  fir.store %c0_i32 to %1 : !fir.ref<i32>
+  omp.parallel {
+    omp.wsloop {
+      omp.simd private(@_QFEa_private_i32 %1 -> %arg0 : !fir.ref<i32>) {
+        omp.loop_nest (%arg1) : i32 = (%c1_i32) to (%c1_i32) inclusive step (%c1_i32) {
+          omp.yield
+        }
+      } {omp.composite}
+    } {omp.composite}
+    omp.terminator
+  }
+  return
+}

``````````

</details>


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


More information about the flang-commits mailing list