[flang-commits] [flang] [flang][do concurrent] Use values yielded by `local init` regions (PR #155223)

Kareem Ergawy via flang-commits flang-commits at lists.llvm.org
Mon Aug 25 01:56:28 PDT 2025


https://github.com/ergawy created https://github.com/llvm/llvm-project/pull/155223

Similar to what is done for OpenMP `private` clauses, prefer the value yielded from the init region to the allocated private variable in case the region is operating on arguments by-value (e.g. Fortran character boxes).

This changes provides the same results as https://github.com/llvm/llvm-project/pull/154303 in both the LLVM and Fujitsu test suites (so no regressions).

```
Testing Time: 7216.26s
  Passed            : 88522
  Failed            :   160
  Executable Missing:   408
```


>From d09478a58b114ca4352225896dc38a976ff547ed Mon Sep 17 00:00:00 2001
From: ergawy <kareem.ergawy at amd.com>
Date: Mon, 25 Aug 2025 03:50:27 -0500
Subject: [PATCH] [flang][do concurrent] Use values yielded by `local init`
 regions

Similar to what is done for OpenMP `private` clauses, prefer the value yielded from the init region to the allocated private variable in case the region is operating on arguments by-value (e.g. Fortran character boxes).
---
 .../Transforms/SimplifyFIROperations.cpp      | 23 +++++++--
 .../do-concurrent-localizer-boxchar.fir       | 48 +++++++++++++++++++
 2 files changed, 66 insertions(+), 5 deletions(-)
 create mode 100644 flang/test/Transforms/do-concurrent-localizer-boxchar.fir

diff --git a/flang/lib/Optimizer/Transforms/SimplifyFIROperations.cpp b/flang/lib/Optimizer/Transforms/SimplifyFIROperations.cpp
index c6aec96ceb5ae..181bcb73d2d20 100644
--- a/flang/lib/Optimizer/Transforms/SimplifyFIROperations.cpp
+++ b/flang/lib/Optimizer/Transforms/SimplifyFIROperations.cpp
@@ -210,19 +210,32 @@ class DoConcurrentConversion
           mapper.map(region.getArguments(), regionArgs);
           for (mlir::Operation &op : region.front().without_terminator())
             (void)rewriter.clone(op, mapper);
+
+          auto yield = mlir::cast<fir::YieldOp>(region.front().getTerminator());
+          assert(yield.getResults().size() < 2);
+
+          return yield.getResults().empty()
+                     ? mlir::Value{}
+                     : mapper.lookup(yield.getResults()[0]);
         };
 
-        if (!localizer.getInitRegion().empty())
-          cloneLocalizerRegion(localizer.getInitRegion(), {localVar, localArg},
-                               rewriter.getInsertionPoint());
+        if (!localizer.getInitRegion().empty()) {
+          // Prefer the value yielded from the init region to the allocated
+          // private variable in case the region is operating on arguments
+          // by-value (e.g. Fortran character boxes).
+          localAlloc = cloneLocalizerRegion(localizer.getInitRegion(),
+                                            {localVar, localAlloc},
+                                            rewriter.getInsertionPoint());
+          assert(localAlloc);
+        }
 
         if (localizer.getLocalitySpecifierType() ==
             fir::LocalitySpecifierType::LocalInit)
-          cloneLocalizerRegion(localizer.getCopyRegion(), {localVar, localArg},
+          cloneLocalizerRegion(localizer.getCopyRegion(), {localVar, localAlloc},
                                rewriter.getInsertionPoint());
 
         if (!localizer.getDeallocRegion().empty())
-          cloneLocalizerRegion(localizer.getDeallocRegion(), {localArg},
+          cloneLocalizerRegion(localizer.getDeallocRegion(), {localAlloc},
                                rewriter.getInsertionBlock()->end());
 
         rewriter.replaceAllUsesWith(localArg, localAlloc);
diff --git a/flang/test/Transforms/do-concurrent-localizer-boxchar.fir b/flang/test/Transforms/do-concurrent-localizer-boxchar.fir
new file mode 100644
index 0000000000000..311f51d729d03
--- /dev/null
+++ b/flang/test/Transforms/do-concurrent-localizer-boxchar.fir
@@ -0,0 +1,48 @@
+// Tests that for `boxchar` local values, we use the value yielded by the `init`
+// region rather than the local allocated storage.
+
+// RUN: fir-opt --split-input-file --simplify-fir-operations %s | FileCheck %s
+
+fir.local {type = local} @_QFtestEx_private_boxchar_c8xU : !fir.boxchar<1> init {
+^bb0(%arg0: !fir.boxchar<1>, %arg1: !fir.boxchar<1>):
+  %0:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+  %1 = fir.allocmem !fir.char<1,?>(%0#1 : index) {bindc_name = "", uniq_name = ""}
+  %2 = fir.emboxchar %1, %0#1 : (!fir.heap<!fir.char<1,?>>, index) -> !fir.boxchar<1>
+  fir.yield(%2 : !fir.boxchar<1>)
+} dealloc {
+^bb0(%arg0: !fir.boxchar<1>):
+  %0:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+  %1 = fir.convert %0#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.heap<!fir.char<1,?>>
+  fir.freemem %1 : !fir.heap<!fir.char<1,?>>
+  fir.yield
+}
+func.func @_QPtest(%arg0: !fir.boxchar<1> {fir.bindc_name = "x"}) {
+  %0 = fir.dummy_scope : !fir.dscope
+  %1:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+  %2:2 = hlfir.declare %1#0 typeparams %1#1 dummy_scope %0 {uniq_name = "_QFtestEx"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+  %c1 = arith.constant 1 : index
+  %c10 = arith.constant 10 : index
+  fir.do_concurrent {
+    %5 = fir.alloca i32 {bindc_name = "i"}
+    %6:2 = hlfir.declare %5 {uniq_name = "_QFtestEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+    fir.do_concurrent.loop (%arg1) = (%c1) to (%c10) step (%c1) local(@_QFtestEx_private_boxchar_c8xU %2#0 -> %arg2 : !fir.boxchar<1>) {
+      %7 = fir.convert %arg1 : (index) -> i32
+      fir.store %7 to %6#0 : !fir.ref<i32>
+      %8:2 = fir.unboxchar %arg2 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+    }
+  }
+  return
+}
+
+// CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFtestEx"}
+// CHECK: fir.do_loop %{{.*}} = %{{.*}} unordered {
+// CHECK:   %[[X_UNBOX:.*]]:2 = fir.unboxchar %[[X_DECL:.*]]#0
+
+// Verify that the value yielded by the `init` region is the one used through
+// out the loop region rather than the local allocation.
+// CHECK:   %[[LOCAL_ALLOC:.*]] = fir.allocmem !fir.char<1,?>(%[[X_UNBOX]]#1 : index)
+// CHECK:   %[[LOCAL_BOX:.*]] = fir.emboxchar %[[LOCAL_ALLOC]], %[[X_UNBOX]]#1
+// CHECK:   %[[LOCAL_UNBOX:.*]]:2 = fir.unboxchar %[[LOCAL_BOX]]
+// CHECK:   %[[LOCAL_CVT:.*]] = fir.convert %[[LOCAL_UNBOX]]#0
+// CHECK:   fir.freemem %[[LOCAL_CVT]]
+// CHECK: }



More information about the flang-commits mailing list