[flang-commits] [flang] [flang][OpenMP] Inline the firstprivate array copy instead of calling Assign() (PR #211543)

Spencer Bryngelson via flang-commits flang-commits at lists.llvm.org
Thu Jul 23 08:16:13 PDT 2026


================
@@ -39,6 +40,22 @@ static llvm::cl::opt<bool> inlineAllocatableExprAssignFlag(
                    "hlfir.expr (e.g., from hlfir.elemental)"),
     llvm::cl::init(false));
 
+/// Is \p assign the copy-in of an `omp.private` copy region, writing the
+/// privatized clone? The operation defines its first copy-region block
+/// argument to be the original host variable and the second to be the memory
+/// allocated for the clone, so the two cannot overlap and the copy can be
+/// inlined without an aliasing check.
+static bool isOmpPrivateCopyInAssign(hlfir::AssignOp assign) {
+  mlir::Region *region = assign->getParentRegion();
+  auto privateOp =
+      llvm::dyn_cast_or_null<mlir::omp::PrivateClauseOp>(region->getParentOp());
+  if (!privateOp || region != &privateOp.getCopyRegion())
+    return false;
+  auto blockArg = llvm::dyn_cast<mlir::BlockArgument>(assign.getLhs());
----------------
sbryngelson wrote:

Both points were right and both were reachable: the two new tests below fail against the previous revision.

I dropped the provenance walk rather than extend it. Treating every regionless op as provenance-preserving was the wrong shape of check, and `fir.call` is exactly the counterexample. The predicate now matches only the canonical copy-in that lowering emits:

```mlir
^bb0(%orig, %clone):
  %0 = fir.load %orig          // boxed privatizer only
  hlfir.assign %0 to %clone
```

It requires the assignment to be in the entry block, the LHS to be exactly `entry.getArgument(1)`, and the RHS to be either `entry.getArgument(0)` or a single `fir.load` of it. Anything else keeps the aliasing check, so there is no longer a class of operations to reason about.

Two negative tests, both accepted by the previous revision:

- `@_QFtestEf_firstprivate`: RHS from `fir.call @get_box(%arg0)`. The call may return a descriptor for memory that overlaps the clone, so skipping the check here can be wrong.
- `@_QFtestEg_firstprivate`: LHS is argument 1 of a non-entry block reached by `cf.br`. The previous revision accepted it on the argument number alone.

Both stay as `hlfir.assign`.

check-flang: 4607 passed, 11 expected failures, 0 failures. The one-element `real(8)` case still emits no `_FortranAAssign`.


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


More information about the flang-commits mailing list