[Mlir-commits] [mlir] [mlir][OpenMP] Avoid privatization barriers in partial-team regions (PR #229413)
Tom Eccles
llvmlistbot at llvm.org
Tue Oct 6 08:09:42 PDT 2026
https://github.com/tblah updated https://github.com/llvm/llvm-project/pull/229413
>From 97d7f39f32968f350fe82e8c8da0aefe5d042f7e Mon Sep 17 00:00:00 2001
From: Tom Eccles <tom.eccles at arm.com>
Date: Tue, 29 Sep 2026 12:08:55 +0100
Subject: [PATCH 1/3] [mlir][OpenMP] Avoid privatization barriers in
partial-team regions
A compiler-generated privatization barrier under masked, master,
critical, single, or section can wait for team threads that never
reach it.
Check whether the current operation might safely reach a barrier
with its whole team, stopping at the nearest parallel region.
Assisted-by: Codex
---
.../OpenMP/OpenMPToLLVMIRTranslation.cpp | 26 ++-
.../openmp-private-barrier-participation.mlir | 190 ++++++++++++++++++
2 files changed, 202 insertions(+), 14 deletions(-)
create mode 100644 mlir/test/Target/LLVMIR/openmp-private-barrier-participation.mlir
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 3e970ab01dd1b..f9c20c7fa3457 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -2131,30 +2131,28 @@ static llvm::Expected<llvm::BasicBlock *> allocatePrivateVars(
return afterAllocatorAllocations ? afterAllocatorAllocations : afterAllocas;
}
-/// This can't always be determined statically, but when we can, it is good to
-/// avoid generating compiler-added barriers which will deadlock the program.
-static bool opIsInSingleThread(mlir::Operation *op) {
- for (mlir::Operation *parent = op->getParentOp(); parent != nullptr;
+/// A compiler-generated barrier is unsafe when only part of the current team
+/// can reach it. This cannot always be determined statically (e.g. across a
+/// function call), but the enclosing OpenMP constructs can rule it out.
+static bool opMightBeSafeForBarriers(mlir::Operation *op) {
+ for (mlir::Operation *parent = op; parent != nullptr;
parent = parent->getParentOp()) {
- if (mlir::isa<omp::SingleOp, omp::CriticalOp>(parent))
+ // An inner parallel construct creates a new team, even when it is nested
+ // inside a construct that only some threads of the outer team encounter.
+ if (mlir::isa<omp::ParallelOp>(parent))
return true;
- // e.g.
- // omp.single {
- // omp.parallel {
- // op
- // }
- // }
- if (mlir::isa<omp::ParallelOp>(parent))
+ if (mlir::isa<omp::SingleOp, omp::CriticalOp, omp::MaskedOp, omp::MasterOp,
+ omp::SectionOp>(parent))
return false;
}
- return false;
+ return true;
}
static LogicalResult
emitPrivatizationBarrier(mlir::Operation *op, llvm::IRBuilderBase &builder,
LLVM::ModuleTranslation &moduleTranslation) {
- if (opIsInSingleThread(op))
+ if (!opMightBeSafeForBarriers(op))
return success();
llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder();
diff --git a/mlir/test/Target/LLVMIR/openmp-private-barrier-participation.mlir b/mlir/test/Target/LLVMIR/openmp-private-barrier-participation.mlir
new file mode 100644
index 0000000000000..481e58fb260d0
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/openmp-private-barrier-participation.mlir
@@ -0,0 +1,190 @@
+// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+
+// A privatization barrier needs every thread in its team to reach it. These
+// constructs select or serialize threads, even when more than one thread can
+// execute the region over time.
+
+omp.private {type = private} @private_i32 : i32
+omp.private {type = firstprivate} @firstprivate_i32 : i32 copy {
+^bb0(%from: !llvm.ptr, %to: !llvm.ptr):
+ %value = llvm.load %from : !llvm.ptr -> i32
+ llvm.store %value, %to : i32, !llvm.ptr
+ omp.yield(%to : !llvm.ptr)
+}
+
+// CHECK-LABEL: define void @masked_private(
+llvm.func @masked_private(%ptr: !llvm.ptr, %filter: i32) {
+ %lo = llvm.mlir.constant(1 : i32) : i32
+ %hi = llvm.mlir.constant(2 : i32) : i32
+ %step = llvm.mlir.constant(1 : i32) : i32
+ omp.parallel {
+ omp.masked filter(%filter : i32) {
+ omp.taskloop.context private(@private_i32 %ptr -> %arg0 : !llvm.ptr) private_barrier {
+ omp.taskloop.wrapper {
+ omp.loop_nest (%i) : i32 = (%lo) to (%hi) inclusive step (%step) {
+ llvm.store %i, %arg0 : i32, !llvm.ptr
+ omp.yield
+ }
+ }
+ omp.terminator
+ } {omp.combined}
+ omp.terminator
+ }
+ omp.terminator
+ }
+ llvm.return
+}
+// CHECK: omp.private.copy:
+// CHECK-NOT: call void @__kmpc_barrier
+// CHECK: br label %omp.taskloop.wrapper.start
+
+// The old firstprivate path needs the same protection.
+// CHECK-LABEL: define void @masked_firstprivate(
+llvm.func @masked_firstprivate(%ptr: !llvm.ptr, %filter: i32) {
+ %lo = llvm.mlir.constant(1 : i32) : i32
+ %hi = llvm.mlir.constant(2 : i32) : i32
+ %step = llvm.mlir.constant(1 : i32) : i32
+ omp.parallel {
+ omp.masked filter(%filter : i32) {
+ omp.taskloop.context private(@firstprivate_i32 %ptr -> %arg0 : !llvm.ptr) private_barrier {
+ omp.taskloop.wrapper {
+ omp.loop_nest (%i) : i32 = (%lo) to (%hi) inclusive step (%step) {
+ llvm.store %i, %arg0 : i32, !llvm.ptr
+ omp.yield
+ }
+ }
+ omp.terminator
+ } {omp.combined}
+ omp.terminator
+ }
+ omp.terminator
+ }
+ llvm.return
+}
+// CHECK: omp.private.copy{{[0-9]*}}:
+// CHECK-NOT: call void @__kmpc_barrier
+// CHECK: br label %omp.taskloop.wrapper.start
+
+// CHECK-LABEL: define void @master_private(
+llvm.func @master_private(%ptr: !llvm.ptr) {
+ %lo = llvm.mlir.constant(1 : i32) : i32
+ %hi = llvm.mlir.constant(2 : i32) : i32
+ %step = llvm.mlir.constant(1 : i32) : i32
+ omp.parallel {
+ omp.master {
+ omp.taskloop.context private(@private_i32 %ptr -> %arg0 : !llvm.ptr) private_barrier {
+ omp.taskloop.wrapper {
+ omp.loop_nest (%i) : i32 = (%lo) to (%hi) inclusive step (%step) {
+ llvm.store %i, %arg0 : i32, !llvm.ptr
+ omp.yield
+ }
+ }
+ omp.terminator
+ } {omp.combined}
+ omp.terminator
+ }
+ omp.terminator
+ }
+ llvm.return
+}
+// CHECK: omp.private.copy:
+// CHECK-NOT: call void @__kmpc_barrier
+// CHECK: br label %omp.taskloop.wrapper.start
+
+// CHECK-LABEL: define void @critical_private(
+llvm.func @critical_private(%ptr: !llvm.ptr) {
+ %lo = llvm.mlir.constant(1 : i32) : i32
+ %hi = llvm.mlir.constant(2 : i32) : i32
+ %step = llvm.mlir.constant(1 : i32) : i32
+ omp.parallel {
+ omp.critical {
+ omp.taskloop.context private(@private_i32 %ptr -> %arg0 : !llvm.ptr) private_barrier {
+ omp.taskloop.wrapper {
+ omp.loop_nest (%i) : i32 = (%lo) to (%hi) inclusive step (%step) {
+ llvm.store %i, %arg0 : i32, !llvm.ptr
+ omp.yield
+ }
+ }
+ omp.terminator
+ } {omp.combined}
+ omp.terminator
+ }
+ omp.terminator
+ }
+ llvm.return
+}
+// CHECK: omp.private.copy:
+// CHECK-NOT: call void @__kmpc_barrier
+// CHECK: br label %omp.taskloop.wrapper.start
+
+// CHECK-LABEL: define void @single_private(
+llvm.func @single_private(%ptr: !llvm.ptr) {
+ %lo = llvm.mlir.constant(1 : i32) : i32
+ %hi = llvm.mlir.constant(2 : i32) : i32
+ %step = llvm.mlir.constant(1 : i32) : i32
+ omp.parallel {
+ omp.single {
+ omp.taskloop.context private(@private_i32 %ptr -> %arg0 : !llvm.ptr) private_barrier {
+ omp.taskloop.wrapper {
+ omp.loop_nest (%i) : i32 = (%lo) to (%hi) inclusive step (%step) {
+ llvm.store %i, %arg0 : i32, !llvm.ptr
+ omp.yield
+ }
+ }
+ omp.terminator
+ } {omp.combined}
+ omp.terminator
+ }
+ omp.terminator
+ }
+ llvm.return
+}
+// CHECK: omp.private.copy:
+// CHECK-NOT: call void @__kmpc_barrier
+// CHECK: br label %omp.taskloop.wrapper.start
+
+// CHECK-LABEL: define void @section_private(
+llvm.func @section_private(%ptr: !llvm.ptr) {
+ %lo = llvm.mlir.constant(1 : i32) : i32
+ %hi = llvm.mlir.constant(2 : i32) : i32
+ %step = llvm.mlir.constant(1 : i32) : i32
+ omp.parallel {
+ omp.sections {
+ omp.section {
+ omp.taskloop.context private(@private_i32 %ptr -> %arg0 : !llvm.ptr) private_barrier {
+ omp.taskloop.wrapper {
+ omp.loop_nest (%i) : i32 = (%lo) to (%hi) inclusive step (%step) {
+ llvm.store %i, %arg0 : i32, !llvm.ptr
+ omp.yield
+ }
+ }
+ omp.terminator
+ } {omp.combined}
+ omp.terminator
+ }
+ omp.terminator
+ }
+ omp.terminator
+ }
+ llvm.return
+}
+// CHECK: omp.private.copy:
+// CHECK-NOT: call void @__kmpc_barrier
+// CHECK: br label %omp.taskloop.wrapper.start
+
+// A nested parallel region creates a new team whose members all enter its
+// privatization code, even when only one outer-team thread launches it.
+// CHECK-LABEL: define void @nested_parallel_private(
+llvm.func @nested_parallel_private(%ptr: !llvm.ptr, %filter: i32) {
+ omp.parallel {
+ omp.masked filter(%filter : i32) {
+ omp.parallel private(@private_i32 %ptr -> %arg0 : !llvm.ptr) private_barrier {
+ omp.terminator
+ }
+ omp.terminator
+ }
+ omp.terminator
+ }
+ llvm.return
+}
+// CHECK: call void @__kmpc_barrier
>From 73af46b1a0784d53b230a2ff9541aa5397684573 Mon Sep 17 00:00:00 2001
From: Tom Eccles <tom.eccles at arm.com>
Date: Tue, 6 Oct 2026 15:39:05 +0100
Subject: [PATCH 2/3] Fix test nits
Assisted-by: Codex
---
.../Target/LLVMIR/openmp-private-barrier-participation.mlir | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/mlir/test/Target/LLVMIR/openmp-private-barrier-participation.mlir b/mlir/test/Target/LLVMIR/openmp-private-barrier-participation.mlir
index 481e58fb260d0..f107eae33ad53 100644
--- a/mlir/test/Target/LLVMIR/openmp-private-barrier-participation.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-private-barrier-participation.mlir
@@ -38,7 +38,7 @@ llvm.func @masked_private(%ptr: !llvm.ptr, %filter: i32) {
// CHECK-NOT: call void @__kmpc_barrier
// CHECK: br label %omp.taskloop.wrapper.start
-// The old firstprivate path needs the same protection.
+// A firstprivate copy must also avoid a barrier inside a masked region.
// CHECK-LABEL: define void @masked_firstprivate(
llvm.func @masked_firstprivate(%ptr: !llvm.ptr, %filter: i32) {
%lo = llvm.mlir.constant(1 : i32) : i32
@@ -187,4 +187,7 @@ llvm.func @nested_parallel_private(%ptr: !llvm.ptr, %filter: i32) {
}
llvm.return
}
+// CHECK-LABEL: define internal void @nested_parallel_private..omp_par(
+// CHECK: omp.private.init:
+// CHECK-NOT: br{{[[:space:]]}}
// CHECK: call void @__kmpc_barrier
>From 90ce78e9754bf08b0d0a6a1fd38e853aa53933af Mon Sep 17 00:00:00 2001
From: Tom Eccles <tom.eccles at arm.com>
Date: Tue, 6 Oct 2026 15:59:07 +0100
Subject: [PATCH 3/3] Merge privatization barrier tests
Rename the combined file to reflect its broader coverage.
Assisted-by: Codex
---
.../LLVMIR/openmp-private-barrier-single.mlir | 88 -------------------
...ation.mlir => openmp-private-barrier.mlir} | 87 ++++++++++++++++++
2 files changed, 87 insertions(+), 88 deletions(-)
delete mode 100644 mlir/test/Target/LLVMIR/openmp-private-barrier-single.mlir
rename mlir/test/Target/LLVMIR/{openmp-private-barrier-participation.mlir => openmp-private-barrier.mlir} (64%)
diff --git a/mlir/test/Target/LLVMIR/openmp-private-barrier-single.mlir b/mlir/test/Target/LLVMIR/openmp-private-barrier-single.mlir
deleted file mode 100644
index 0c003db0903da..0000000000000
--- a/mlir/test/Target/LLVMIR/openmp-private-barrier-single.mlir
+++ /dev/null
@@ -1,88 +0,0 @@
-// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
-
-// Tests that no privatization barrier is added for operations inside of SINGLE.
-// The specific combination here (wsloop inside of single) may not be valid
-// OpenMP. This combination was chosen so that this patch did not have to wait
-// for taskloop support. If it ever becomes a problem having a wsloop inside
-// of single, this can be updated to use taskloop.
-
-omp.private {type = private} @_QFwsloop_privateEi_private_ref_i32 : i32
-
-llvm.func @foo_free(!llvm.ptr)
-
-omp.private {type = firstprivate} @_QFwsloop_privateEc_firstprivate_ref_c8 : !llvm.array<1 x i8> copy {
-^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
- %0 = llvm.load %arg0 : !llvm.ptr -> !llvm.array<1 x i8>
- llvm.store %0, %arg1 : !llvm.array<1 x i8>, !llvm.ptr
- omp.yield(%arg1 : !llvm.ptr)
-} dealloc {
-^bb0(%arg0: !llvm.ptr):
- llvm.call @foo_free(%arg0) : (!llvm.ptr) -> ()
- omp.yield
-}
-
-// CHECK-LABEL wsloop_private_
-llvm.func @wsloop_private_(%arg0: !llvm.ptr {fir.bindc_name = "y"}) attributes {fir.internal_name = "_QPwsloop_private", frame_pointer = #llvm.framePointerKind<all>, target_cpu = "x86-64"} {
- %0 = llvm.mlir.constant(1 : i64) : i64
- %1 = llvm.alloca %0 x f32 {bindc_name = "x"} : (i64) -> !llvm.ptr
- %3 = llvm.alloca %0 x i32 {bindc_name = "i"} : (i64) -> !llvm.ptr
- %5 = llvm.alloca %0 x !llvm.array<1 x i8> {bindc_name = "c"} : (i64) -> !llvm.ptr
- %6 = llvm.mlir.constant(1 : i32) : i32
- %7 = llvm.mlir.constant(10 : i32) : i32
- %8 = llvm.mlir.constant(0 : i32) : i32
- omp.parallel {
- omp.single {
- omp.wsloop private(@_QFwsloop_privateEc_firstprivate_ref_c8 %5 -> %arg1, @_QFwsloop_privateEi_private_ref_i32 %3 -> %arg2 : !llvm.ptr, !llvm.ptr) private_barrier {
- // CHECK: omp.private.copy:
- // CHECK-NOT: __kmpc_barrier
- // CHECK: br label
- omp.loop_nest (%arg4) : i32 = (%8) to (%7) inclusive step (%6) {
- omp.yield
- }
- }
- omp.terminator
- }
- omp.terminator
- }
- llvm.return
-}
-
-
-// Check for a case where the barrier should be applied. Regression check for
-// infinite loop.
-omp.private {type = private} @_QFsubEi_private_i32 : i32
-omp.private {type = firstprivate} @_QFsubEp_firstprivate_i32 : i32 copy {
-^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
- %0 = llvm.load %arg0 : !llvm.ptr -> i32
- llvm.store %0, %arg1 : i32, !llvm.ptr
- omp.yield(%arg1 : !llvm.ptr)
-}
-
-// CHECK-LABEL: _QPsub
-llvm.func @_QPsub() {
- %0 = llvm.mlir.constant(100 : i32) : i32
- %1 = llvm.mlir.constant(1 : i32) : i32
- %2 = llvm.mlir.constant(1 : i64) : i64
- %3 = llvm.alloca %2 x i32 {bindc_name = "p"} : (i64) -> !llvm.ptr
- %4 = llvm.alloca %2 x i32 {bindc_name = "i"} : (i64) -> !llvm.ptr
- llvm.store %0, %3 : i32, !llvm.ptr
- omp.wsloop private(@_QFsubEp_firstprivate_i32 %3 -> %arg0, @_QFsubEi_private_i32 %4 -> %arg1 : !llvm.ptr, !llvm.ptr) private_barrier {
- // CHECK: omp.private.copy:
- // CHECK: __kmpc_barrier
- // CHECK: br label
- omp.loop_nest (%arg2) : i32 = (%1) to (%1) inclusive step (%1) {
- llvm.store %arg2, %arg1 : i32, !llvm.ptr
- %5 = llvm.add %arg2, %1 : i32
- %6 = llvm.icmp "sgt" %5, %1 : i32
- llvm.cond_br %6, ^bb1, ^bb2
- ^bb1: // pred: ^bb0
- llvm.store %5, %arg1 : i32, !llvm.ptr
- %7 = llvm.load %arg0 : !llvm.ptr -> i32
- llvm.store %7, %3 : i32, !llvm.ptr
- llvm.br ^bb2
- ^bb2: // 2 preds: ^bb0, ^bb1
- omp.yield
- }
- }
- llvm.return
-}
diff --git a/mlir/test/Target/LLVMIR/openmp-private-barrier-participation.mlir b/mlir/test/Target/LLVMIR/openmp-private-barrier.mlir
similarity index 64%
rename from mlir/test/Target/LLVMIR/openmp-private-barrier-participation.mlir
rename to mlir/test/Target/LLVMIR/openmp-private-barrier.mlir
index f107eae33ad53..d51443c856d84 100644
--- a/mlir/test/Target/LLVMIR/openmp-private-barrier-participation.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-private-barrier.mlir
@@ -1,5 +1,92 @@
// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+// Tests that no privatization barrier is added for operations inside of SINGLE.
+// The specific combination here (wsloop inside of single) may not be valid
+// OpenMP. This combination was chosen so that this patch did not have to wait
+// for taskloop support. If it ever becomes a problem having a wsloop inside
+// of single, this can be updated to use taskloop.
+
+omp.private {type = private} @_QFwsloop_privateEi_private_ref_i32 : i32
+
+llvm.func @foo_free(!llvm.ptr)
+
+omp.private {type = firstprivate} @_QFwsloop_privateEc_firstprivate_ref_c8 : !llvm.array<1 x i8> copy {
+^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
+ %0 = llvm.load %arg0 : !llvm.ptr -> !llvm.array<1 x i8>
+ llvm.store %0, %arg1 : !llvm.array<1 x i8>, !llvm.ptr
+ omp.yield(%arg1 : !llvm.ptr)
+} dealloc {
+^bb0(%arg0: !llvm.ptr):
+ llvm.call @foo_free(%arg0) : (!llvm.ptr) -> ()
+ omp.yield
+}
+
+// CHECK-LABEL wsloop_private_
+llvm.func @wsloop_private_(%arg0: !llvm.ptr {fir.bindc_name = "y"}) attributes {fir.internal_name = "_QPwsloop_private", frame_pointer = #llvm.framePointerKind<all>, target_cpu = "x86-64"} {
+ %0 = llvm.mlir.constant(1 : i64) : i64
+ %1 = llvm.alloca %0 x f32 {bindc_name = "x"} : (i64) -> !llvm.ptr
+ %3 = llvm.alloca %0 x i32 {bindc_name = "i"} : (i64) -> !llvm.ptr
+ %5 = llvm.alloca %0 x !llvm.array<1 x i8> {bindc_name = "c"} : (i64) -> !llvm.ptr
+ %6 = llvm.mlir.constant(1 : i32) : i32
+ %7 = llvm.mlir.constant(10 : i32) : i32
+ %8 = llvm.mlir.constant(0 : i32) : i32
+ omp.parallel {
+ omp.single {
+ omp.wsloop private(@_QFwsloop_privateEc_firstprivate_ref_c8 %5 -> %arg1, @_QFwsloop_privateEi_private_ref_i32 %3 -> %arg2 : !llvm.ptr, !llvm.ptr) private_barrier {
+ // CHECK: omp.private.copy:
+ // CHECK-NOT: __kmpc_barrier
+ // CHECK: br label
+ omp.loop_nest (%arg4) : i32 = (%8) to (%7) inclusive step (%6) {
+ omp.yield
+ }
+ }
+ omp.terminator
+ }
+ omp.terminator
+ }
+ llvm.return
+}
+
+
+// Check for a case where the barrier should be applied. Regression check for
+// infinite loop.
+omp.private {type = private} @_QFsubEi_private_i32 : i32
+omp.private {type = firstprivate} @_QFsubEp_firstprivate_i32 : i32 copy {
+^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
+ %0 = llvm.load %arg0 : !llvm.ptr -> i32
+ llvm.store %0, %arg1 : i32, !llvm.ptr
+ omp.yield(%arg1 : !llvm.ptr)
+}
+
+// CHECK-LABEL: _QPsub
+llvm.func @_QPsub() {
+ %0 = llvm.mlir.constant(100 : i32) : i32
+ %1 = llvm.mlir.constant(1 : i32) : i32
+ %2 = llvm.mlir.constant(1 : i64) : i64
+ %3 = llvm.alloca %2 x i32 {bindc_name = "p"} : (i64) -> !llvm.ptr
+ %4 = llvm.alloca %2 x i32 {bindc_name = "i"} : (i64) -> !llvm.ptr
+ llvm.store %0, %3 : i32, !llvm.ptr
+ omp.wsloop private(@_QFsubEp_firstprivate_i32 %3 -> %arg0, @_QFsubEi_private_i32 %4 -> %arg1 : !llvm.ptr, !llvm.ptr) private_barrier {
+ // CHECK: omp.private.copy:
+ // CHECK: __kmpc_barrier
+ // CHECK: br label
+ omp.loop_nest (%arg2) : i32 = (%1) to (%1) inclusive step (%1) {
+ llvm.store %arg2, %arg1 : i32, !llvm.ptr
+ %5 = llvm.add %arg2, %1 : i32
+ %6 = llvm.icmp "sgt" %5, %1 : i32
+ llvm.cond_br %6, ^bb1, ^bb2
+ ^bb1: // pred: ^bb0
+ llvm.store %5, %arg1 : i32, !llvm.ptr
+ %7 = llvm.load %arg0 : !llvm.ptr -> i32
+ llvm.store %7, %3 : i32, !llvm.ptr
+ llvm.br ^bb2
+ ^bb2: // 2 preds: ^bb0, ^bb1
+ omp.yield
+ }
+ }
+ llvm.return
+}
+
// A privatization barrier needs every thread in its team to reach it. These
// constructs select or serialize threads, even when more than one thread can
// execute the region over time.
More information about the Mlir-commits
mailing list