[flang-commits] [flang] e949b65 - [flang][OpenMP] Fix alias analysis for omp.private copy region block arguments to help inline hlfir.assign to improve time taken in LTO. (#209539)

via flang-commits flang-commits at lists.llvm.org
Fri Jul 24 11:56:35 PDT 2026


Author: Pranav Bhandarkar
Date: 2026-07-24T13:56:30-05:00
New Revision: e949b654424beda81ab4db154a72b904c8b32245

URL: https://github.com/llvm/llvm-project/commit/e949b654424beda81ab4db154a72b904c8b32245
DIFF: https://github.com/llvm/llvm-project/commit/e949b654424beda81ab4db154a72b904c8b32245.diff

LOG: [flang][OpenMP] Fix alias analysis for omp.private copy region block arguments to help inline hlfir.assign to improve time taken in LTO. (#209539)

## Summary

This PR fixes https://github.com/llvm/llvm-project/issues/200922 - a
compile-time regression affecting firstprivate clauses on simple arrays
in OpenMP target regions.

When `InlineHLFIRAssign` checks whether to inline `hlfir.assign`
operations in `omp.private` copy regions, the alias analysis
conservatively returns `MayAlias` for the copy region block arguments
(`%arg0` mold vs `%arg1` private). This prevents inlining and forces a
fallback to `fir.call @_FortranAAssign`, which:

- Pulls in 89 runtime functions via LTO
- Creates 550K+ abstract attributes in OpenMPOpt
- Causes severe compile-time degradation (60%+ increase in some cases)

**Example:**
```fortran
!$omp target firstprivate(array)
  ! ... use array ...
!$omp end target
```

The firstprivate copy generates an `omp.private` copy region where the
assignment from the original array to the private copy cannot be inlined
due to conservative aliasing assumptions.

## Root Cause and Solution

The FIR alias analysis did not recognize that `omp.private` copy region
block arguments are guaranteed by the OpenMP specification to reference
different memory locations:
- `%arg0` (mold) - the original variable
- `%arg1` (private) - freshly allocated private storage created in the
init region

Since the private copy is allocated fresh, these arguments **cannot
alias**.

So, this PR adds special-case handling in
`flang/lib/Optimizer/Analysis/AliasAnalysis.cpp` to recognize
`omp.private` copy region block arguments and correctly return
`NoAlias`. This allows `InlineHLFIRAssign` to inline the assignment into
an element-wise loop, avoiding the expensive runtime call entirely.

Assisted by: Claude Sonnet

---------

Co-authored-by: Claude Sonnet 4 <noreply at anthropic.com>

Added: 
    flang/test/Analysis/AliasAnalysis/alias-analysis-omp-private-copy-region.mlir
    flang/test/Analysis/AliasAnalysis/alias-analysis-omp-private-pointer.mlir

Modified: 
    flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
    flang/test/Integration/OpenMP/parallel-private-reduction-worstcase.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
index 599add48e4e95..4322e9ebcd0d1 100644
--- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
+++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
@@ -662,6 +662,71 @@ AliasResult AliasAnalysis::alias(Source lhsSrc, Source rhsSrc, mlir::Value lhs,
   if (lhs == rhs || getZeroOffsetViewRoot(lhs) == getZeroOffsetViewRoot(rhs))
     return AliasResult::MustAlias;
 
+  // OpenMP private clause copy region arguments are guaranteed to be disjoint.
+  // The copy region has two arguments: %arg0 (original/mold) and %arg1
+  // (private). By omp.private semantics, %arg1 is initialized with freshly
+  // allocated memory (from the init region), while %arg0 references the
+  // original variable. These cannot alias. This check handles both direct block
+  // argument comparisons and cases where one value is loaded from a block
+  // argument (common pattern: hlfir.assign %loaded to %arg1 where %loaded =
+  // fir.load %arg0).
+  auto getBlockArgOrLoadSource = [](mlir::Value v) -> mlir::BlockArgument {
+    if (auto arg = mlir::dyn_cast<BlockArgument>(v))
+      return arg;
+    // Check if this is a load from a block argument
+    if (auto defOp = v.getDefiningOp()) {
+      if (auto loadOp = mlir::dyn_cast<fir::LoadOp>(defOp)) {
+        return mlir::dyn_cast<BlockArgument>(loadOp.getMemref());
+      }
+    }
+    return {};
+  };
+
+  auto lhsArg = getBlockArgOrLoadSource(lhs);
+  auto rhsArg = getBlockArgOrLoadSource(rhs);
+
+  if (lhsArg && rhsArg &&
+      lhsArg.getParentRegion() == rhsArg.getParentRegion()) {
+    if (auto *parentOp = lhsArg.getParentRegion()->getParentOp()) {
+      if (auto privateOp = mlir::dyn_cast<omp::PrivateClauseOp>(parentOp)) {
+        auto &copyRegion = privateOp.getCopyRegion();
+        if (lhsArg.getParentRegion() == &copyRegion) {
+          // Both trace to block args from the copy region - check if they're
+          // the defined pair
+          auto moldArg = privateOp.getCopyMoldArg();
+          auto privArg = privateOp.getCopyPrivateArg();
+          if ((lhsArg == moldArg && rhsArg == privArg) ||
+              (lhsArg == privArg && rhsArg == moldArg)) {
+            // Check if this is a POINTER type.
+            // For POINTER + FIRSTPRIVATE: the descriptor is copied (private)
+            // but pointer association is preserved, so the DATA they point to
+            // is the same → ALIASING.
+            // For ALLOCATABLE: fresh memory is allocated → NO ALIASING.
+            auto isPointerType = [](mlir::Type ty) -> bool {
+              ty = fir::unwrapRefType(ty);
+              if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(ty))
+                return boxTy.isPointer();
+              return false;
+            };
+
+            if (isPointerType(lhsArg.getType()) ||
+                isPointerType(rhsArg.getType())) {
+              LLVM_DEBUG(llvm::dbgs()
+                         << "  may alias: omp.private POINTER preserves "
+                         << "association (data aliases)\n");
+              return AliasResult::MayAlias;
+            }
+
+            LLVM_DEBUG(llvm::dbgs()
+                       << "  no alias: omp.private copy region arguments "
+                       << "(mold vs private)\n");
+            return AliasResult::NoAlias;
+          }
+        }
+      }
+    }
+  }
+
   bool approximateSource = lhsSrc.approximateSource || rhsSrc.approximateSource;
   LLVM_DEBUG(llvm::dbgs() << "\nAliasAnalysis::alias\n";
              llvm::dbgs() << "  lhs: " << lhs << "\n";

diff  --git a/flang/test/Analysis/AliasAnalysis/alias-analysis-omp-private-copy-region.mlir b/flang/test/Analysis/AliasAnalysis/alias-analysis-omp-private-copy-region.mlir
new file mode 100644
index 0000000000000..23e2cf2441839
--- /dev/null
+++ b/flang/test/Analysis/AliasAnalysis/alias-analysis-omp-private-copy-region.mlir
@@ -0,0 +1,50 @@
+// Test that InlineHLFIRAssign successfully inlines hlfir.assign operations
+// in omp.private copy regions when the fix for omp.private block argument
+// aliasing is present. Without the fix, alias analysis returns MayAlias and
+// InlineHLFIRAssign fails.
+//
+// RUN: fir-opt %s --inline-hlfir-assign --split-input-file | FileCheck %s
+
+// Fortran source (simplified):
+//   program minimal
+//     integer :: arr(8)
+//     arr(1) = 1
+//     !$omp target firstprivate(arr)
+//     arr(1) = 42
+//     !$omp end target
+//   end program
+
+omp.private {type = firstprivate} @arr_privatizer : !fir.box<!fir.array<8xi32>> init {
+^bb0(%arg0: !fir.ref<!fir.box<!fir.array<8xi32>>>, %arg1: !fir.ref<!fir.box<!fir.array<8xi32>>>):
+  %c8 = arith.constant 8 : index
+  %c1 = arith.constant 1 : index
+  %0 = fir.shape %c8 : (index) -> !fir.shape<1>
+  %1 = fir.allocmem !fir.array<8xi32> {bindc_name = ".tmp", uniq_name = ""}
+  %2:2 = hlfir.declare %1(%0) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<8xi32>>, !fir.shape<1>) -> (!fir.heap<!fir.array<8xi32>>, !fir.heap<!fir.array<8xi32>>)
+  %3 = fir.shape_shift %c1, %c8 : (index, index) -> !fir.shapeshift<1>
+  %4 = fir.embox %2#0(%3) : (!fir.heap<!fir.array<8xi32>>, !fir.shapeshift<1>) -> !fir.box<!fir.array<8xi32>>
+  fir.store %4 to %arg1 : !fir.ref<!fir.box<!fir.array<8xi32>>>
+  omp.yield(%arg1 : !fir.ref<!fir.box<!fir.array<8xi32>>>)
+} copy {
+^bb0(%arg0: !fir.ref<!fir.box<!fir.array<8xi32>>>, %arg1: !fir.ref<!fir.box<!fir.array<8xi32>>>):
+  // This hlfir.assign should be inlined into a loop by InlineHLFIRAssign
+  // because alias analysis should return NoAlias for %0 (loaded from %arg0 mold)
+  // vs %arg1 (private copy).
+  %0 = fir.load %arg0 : !fir.ref<!fir.box<!fir.array<8xi32>>>
+  hlfir.assign %0 to %arg1 : !fir.box<!fir.array<8xi32>>, !fir.ref<!fir.box<!fir.array<8xi32>>>
+  omp.yield(%arg1 : !fir.ref<!fir.box<!fir.array<8xi32>>>)
+}
+
+// CHECK-LABEL: omp.private {type = firstprivate} @arr_privatizer
+// CHECK: } copy {
+// CHECK: ^bb0(%[[MOLD:.*]]: !fir.ref<!fir.box<!fir.array<8xi32>>>, %[[PRIV:.*]]: !fir.ref<!fir.box<!fir.array<8xi32>>>):
+// CHECK-NOT: hlfir.assign {{.*}} to {{.*}} : !fir.box<!fir.array<8xi32>>
+// CHECK: fir.do_loop
+// CHECK: hlfir.designate
+// CHECK: hlfir.designate
+// CHECK: hlfir.assign {{.*}} to {{.*}} : i32
+// CHECK: omp.yield
+
+func.func @test_omp_private_copy_inlined() {
+  return
+}

diff  --git a/flang/test/Analysis/AliasAnalysis/alias-analysis-omp-private-pointer.mlir b/flang/test/Analysis/AliasAnalysis/alias-analysis-omp-private-pointer.mlir
new file mode 100644
index 0000000000000..5a3d4f24e3da4
--- /dev/null
+++ b/flang/test/Analysis/AliasAnalysis/alias-analysis-omp-private-pointer.mlir
@@ -0,0 +1,34 @@
+// Test alias analysis for POINTER + FIRSTPRIVATE in omp.private copy region.
+// For POINTER variables, the descriptor is copied but pointer association
+// is preserved. Both the mold descriptor and private descriptor point to
+// the SAME target data, therefore they ALIAS.
+//
+// RUN: fir-opt %s -pass-pipeline='builtin.module(test-fir-alias-analysis)' -split-input-file --mlir-disable-threading 2>&1 | FileCheck %s
+
+// CHECK-LABEL: Testing : <<NULL ATTRIBUTE>>
+// CHECK: mold_data#0 <-> priv_data#0: MayAlias
+
+// This test verifies that alias analysis correctly returns MayAlias for POINTER
+// variables in omp.private copy regions. For POINTER, the descriptor is copied
+// but pointer association is preserved, so both descriptors point to the SAME
+// target data.
+
+omp.private {type = firstprivate} @ptr_privatizer : !fir.box<!fir.ptr<!fir.array<8xi32>>> init {
+^bb0(%arg0: !fir.ref<!fir.box<!fir.ptr<!fir.array<8xi32>>>>, %arg1: !fir.ref<!fir.box<!fir.ptr<!fir.array<8xi32>>>>):
+  %c8 = arith.constant 8 : index
+  %c1 = arith.constant 1 : index
+  %0 = fir.zero_bits !fir.ptr<!fir.array<8xi32>>
+  %1 = fir.shape %c8 : (index) -> !fir.shape<1>
+  %2 = fir.embox %0(%1) : (!fir.ptr<!fir.array<8xi32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<8xi32>>>
+  fir.store %2 to %arg1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<8xi32>>>>
+  omp.yield(%arg1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<8xi32>>>>)
+} copy {
+^bb0(%arg0: !fir.ref<!fir.box<!fir.ptr<!fir.array<8xi32>>>>, %arg1: !fir.ref<!fir.box<!fir.ptr<!fir.array<8xi32>>>>):
+  // For POINTER: the descriptor is copied, but pointer association is preserved.
+  // Load both the mold (%arg0) and private (%arg1) to test alias analysis.
+  // Both descriptors point to THE SAME target data => should ALIAS.
+  %mold_desc = fir.load %arg0 {test.ptr = "mold_data"} : !fir.ref<!fir.box<!fir.ptr<!fir.array<8xi32>>>>
+  fir.store %mold_desc to %arg1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<8xi32>>>>
+  %priv_desc = fir.load %arg1 {test.ptr = "priv_data"} : !fir.ref<!fir.box<!fir.ptr<!fir.array<8xi32>>>>
+  omp.yield(%arg1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<8xi32>>>>)
+}

diff  --git a/flang/test/Integration/OpenMP/parallel-private-reduction-worstcase.f90 b/flang/test/Integration/OpenMP/parallel-private-reduction-worstcase.f90
index 6e6fffe28a082..6d34dc8ec05a7 100644
--- a/flang/test/Integration/OpenMP/parallel-private-reduction-worstcase.f90
+++ b/flang/test/Integration/OpenMP/parallel-private-reduction-worstcase.f90
@@ -83,72 +83,72 @@ subroutine worst_case(a, b, c, d)
 ! CHECK:       omp.private.copy12:                               ; preds = %omp.private.copy
 !                [begin firstprivate copy for first var]
 !                [read the length, is it non-zero?]
-! CHECK:         br i1 %{{.*}}, label %omp.private.copy13, label %omp.private.copy14
+! CHECK:         br i1 %{{.*}}, label %omp.private.copy13, label %omp.private.copy22
 
-! CHECK:       omp.private.copy14:                               ; preds = %omp.private.copy13, %omp.private.copy12
+! CHECK:       omp.private.copy22:                               ; preds = %omp.private.copy21, %omp.private.copy12
 ! CHECK-NEXT:    br label %omp.region.cont11
 
-! CHECK:       omp.region.cont11:                                 ; preds = %omp.private.copy14
+! CHECK:       omp.region.cont11:                                 ; preds = %omp.private.copy22
 ! CHECK-NEXT:    %{{.*}} = phi ptr
-! CHECK-NEXT:    br label %omp.private.copy16
+! CHECK-NEXT:    br label %omp.private.copy24
 
-! CHECK:       omp.private.copy16:                               ; preds = %omp.region.cont11
+! CHECK:       omp.private.copy24:                               ; preds = %omp.region.cont11
 !                [begin firstprivate copy for second var]
 !                [read the length, is it non-zero?]
-! CHECK:         br i1 %{{.*}}, label %omp.private.copy17, label %omp.private.copy18
+! CHECK:         br i1 %{{.*}}, label %omp.private.copy25, label %omp.private.copy34
 
-! CHECK:       omp.private.copy18:                               ; preds = %omp.private.copy17, %omp.private.copy16
-! CHECK-NEXT:    br label %omp.region.cont15
+! CHECK:       omp.private.copy34:                               ; preds = %omp.private.copy33, %omp.private.copy24
+! CHECK-NEXT:    br label %omp.region.cont23
 
-! CHECK:       omp.region.cont15:                                ; preds = %omp.private.copy18
+! CHECK:       omp.region.cont23:                                ; preds = %omp.private.copy34
 ! CHECK-NEXT:    %{{.*}} = phi ptr
 ! CHECK-NEXT:    br label %omp.reduction.init
 
-! CHECK:       omp.reduction.init:                               ; preds = %omp.region.cont15
+! CHECK:       omp.reduction.init:                               ; preds = %omp.region.cont23
 !                [deferred stores for results of reduction alloc regions]
 ! CHECK:         br label %[[VAL_96:.*]]
 
 ! CHECK:       omp.reduction.neutral:                            ; preds = %omp.reduction.init
 !                [start of reduction initialization region]
 !                [null check:]
-! CHECK:         br i1 %{{.*}}, label %omp.reduction.neutral20, label %omp.reduction.neutral21
+! CHECK:         br i1 %{{.*}}, label %omp.reduction.neutral36, label %omp.reduction.neutral37
 
-! CHECK:       omp.reduction.neutral21:                          ; preds = %omp.reduction.neutral
+! CHECK:       omp.reduction.neutral37:                          ; preds = %omp.reduction.neutral
 !                [malloc and assign the default value to the reduction variable]
-! CHECK:         br label %omp.reduction.neutral22
+! CHECK:         br label %omp.reduction.neutral38
 
-! CHECK:       omp.reduction.neutral22:                          ; preds = %omp.reduction.neutral20, %omp.reduction.neutral21
-! CHECK-NEXT:    br label %omp.region.cont19
+! CHECK:       omp.reduction.neutral38:                          ; preds = %omp.reduction.neutral36, %omp.reduction.neutral37
+! CHECK-NEXT:    br label %omp.region.cont35
 
-! CHECK:       omp.region.cont19:                                ; preds = %omp.reduction.neutral22
+! CHECK:       omp.region.cont35:                                ; preds = %omp.reduction.neutral38
 ! CHECK-NEXT:    %{{.*}} = phi ptr
-! CHECK-NEXT:    br label %omp.reduction.neutral24
+! CHECK-NEXT:    br label %omp.reduction.neutral40
 
-! CHECK:       omp.reduction.neutral24:                          ; preds = %omp.region.cont19
+! CHECK:       omp.reduction.neutral40:                          ; preds = %omp.region.cont35
 !                [start of reduction initialization region]
 !                [null check:]
-! CHECK:         br i1 %{{.*}}, label %omp.reduction.neutral25, label %omp.reduction.neutral26
+! CHECK:         br i1 %{{.*}}, label %omp.reduction.neutral41, label %omp.reduction.neutral42
 
-! CHECK:       omp.reduction.neutral26:                          ; preds = %omp.reduction.neutral24
+! CHECK:       omp.reduction.neutral42:                          ; preds = %omp.reduction.neutral40
 !                [malloc and assign the default value to the reduction variable]
-! CHECK:         br label %omp.reduction.neutral27
+! CHECK:         br label %omp.reduction.neutral43
 
-! CHECK:       omp.reduction.neutral27:                          ; preds = %omp.reduction.neutral25, %omp.reduction.neutral26
-! CHECK-NEXT:    br label %omp.region.cont23
+! CHECK:       omp.reduction.neutral43:                          ; preds = %omp.reduction.neutral41, %omp.reduction.neutral42
+! CHECK-NEXT:    br label %omp.region.cont39
 
-! CHECK:       omp.region.cont23:                                ; preds = %omp.reduction.neutral27
+! CHECK:       omp.region.cont39:                                ; preds = %omp.reduction.neutral43
 ! CHECK-NEXT:    %{{.*}} = phi ptr
-! CHECK-NEXT:    br label %omp.par.region29
+! CHECK-NEXT:    br label %omp.par.region45
 
-! CHECK:       omp.par.region29:                                 ; preds = %omp.region.cont23
+! CHECK:       omp.par.region45:                                 ; preds = %omp.region.cont39
 !                [call SUM runtime function]
 !                [if (sum(a) == 1)]
-! CHECK:         br i1 %{{.*}}, label %omp.par.region30, label %omp.par.region31
+! CHECK:         br i1 %{{.*}}, label %omp.par.region46, label %omp.par.region47
 
-! CHECK:       omp.par.region31:                                 ; preds = %omp.par.region29
-! CHECK-NEXT:    br label %omp.region.cont28
+! CHECK:       omp.par.region47:                                 ; preds = %omp.par.region45
+! CHECK-NEXT:    br label %omp.region.cont44
 
-! CHECK:       omp.region.cont28:                                ; preds = %omp.par.region31
+! CHECK:       omp.region.cont44:                                ; preds = %omp.par.region47
 !                [omp parallel region done, call into the runtime to complete reduction]
 ! CHECK:         %[[VAL_233:.*]] = call i32 @__kmpc_reduce(
 ! CHECK:         switch i32 %[[VAL_233]], label %reduce.finalize [
@@ -156,16 +156,16 @@ subroutine worst_case(a, b, c, d)
 ! CHECK-NEXT:      i32 2, label %reduce.switch.atomic
 ! CHECK-NEXT:    ]
 
-! CHECK:       reduce.switch.atomic:                             ; preds = %omp.region.cont28
+! CHECK:       reduce.switch.atomic:                             ; preds = %omp.region.cont44
 ! CHECK-NEXT:    unreachable
 
-! CHECK:       reduce.switch.nonatomic:                          ; preds = %omp.region.cont28
+! CHECK:       reduce.switch.nonatomic:                          ; preds = %omp.region.cont44
 ! CHECK-NEXT:    %[[red_private_value_0:.*]] = load ptr, ptr %{{.*}}, align 8
 ! CHECK-NEXT:    br label %omp.reduction.nonatomic.body
 
 !              [various blocks implementing the reduction]
 
-! CHECK:       omp.region.cont36:                                ; preds =
+! CHECK:       omp.region.cont52:                                ; preds =
 ! CHECK-NEXT:    %{{.*}} = phi ptr
 ! CHECK-NEXT:    call void @__kmpc_end_reduce(
 ! CHECK-NEXT:    br label %reduce.finalize
@@ -182,38 +182,38 @@ subroutine worst_case(a, b, c, d)
 
 ! CHECK:       omp.reduction.cleanup:                            ; preds = %.fini
 !                [null check]
-! CHECK:         br i1 %{{.*}}, label %omp.reduction.cleanup42, label %omp.reduction.cleanup43
+! CHECK:         br i1 %{{.*}}, label %omp.reduction.cleanup58, label %omp.reduction.cleanup59
 
-! CHECK:       omp.reduction.cleanup43:                          ; preds = %omp.reduction.cleanup42, %omp.reduction.cleanup
-! CHECK-NEXT:    br label %omp.region.cont41
+! CHECK:       omp.reduction.cleanup59:                          ; preds = %omp.reduction.cleanup58, %omp.reduction.cleanup
+! CHECK-NEXT:    br label %omp.region.cont57
 
-! CHECK:       omp.region.cont41:                                ; preds = %omp.reduction.cleanup43
+! CHECK:       omp.region.cont57:                                ; preds = %omp.reduction.cleanup59
 ! CHECK-NEXT:    %{{.*}} = load ptr, ptr
-! CHECK-NEXT:    br label %omp.reduction.cleanup45
+! CHECK-NEXT:    br label %omp.reduction.cleanup61
 
-! CHECK:       omp.reduction.cleanup45:                          ; preds = %omp.region.cont41
+! CHECK:       omp.reduction.cleanup61:                          ; preds = %omp.region.cont57
 !                [null check]
-! CHECK:         br i1 %{{.*}}, label %omp.reduction.cleanup46, label %omp.reduction.cleanup47
+! CHECK:         br i1 %{{.*}}, label %omp.reduction.cleanup62, label %omp.reduction.cleanup63
 
-! CHECK:       omp.par.region30:                                 ; preds = %omp.par.region29
+! CHECK:       omp.par.region46:                                 ; preds = %omp.par.region45
 ! CHECK-NEXT:    call void @_FortranAStopStatement
 ! CHECK-NEXT:    unreachable
 
-! CHECK:       omp.reduction.neutral25:                          ; preds = %omp.reduction.neutral24
+! CHECK:       omp.reduction.neutral41:                          ; preds = %omp.reduction.neutral40
 !                [source length was zero: finish initializing array]
-! CHECK:         br label %omp.reduction.neutral27
+! CHECK:         br label %omp.reduction.neutral43
 
-! CHECK:       omp.reduction.neutral20:                          ; preds = %omp.reduction.neutral
+! CHECK:       omp.reduction.neutral36:                          ; preds = %omp.reduction.neutral
 !                [source length was zero: finish initializing array]
-! CHECK:         br label %omp.reduction.neutral22
+! CHECK:         br label %omp.reduction.neutral38
 
-! CHECK:       omp.private.copy17:                               ; preds = %omp.private.copy16
+! CHECK:       omp.private.copy33:                               ; preds = %omp.private.copy32, %omp.private.copy29
 !                [source length was non-zero: call assign runtime]
-! CHECK:         br label %omp.private.copy18
+! CHECK:         br label %omp.private.copy34
 
-! CHECK:       omp.private.copy13:                               ; preds = %omp.private.copy12
+! CHECK:       omp.private.copy21:                               ; preds = %omp.private.copy20, %omp.private.copy17
 !                [source length was non-zero: call assign runtime]
-! CHECK:         br label %omp.private.copy14
+! CHECK:         br label %omp.private.copy22
 
 ! CHECK:       omp.private.init8:                               ; preds = %omp.private.init7
 !                [var extent was non-zero: malloc a private array]
@@ -223,5 +223,5 @@ subroutine worst_case(a, b, c, d)
 !                [var extent was non-zero: malloc a private array]
 ! CHECK:         br label %omp.private.init5
 
-! CHECK:       omp.par.exit.exitStub:                           ; preds = %omp.region.cont51
+! CHECK:       omp.par.exit.exitStub:                           ; preds = %omp.region.cont67
 ! CHECK-NEXT:    ret void


        


More information about the flang-commits mailing list