[Mlir-commits] [mlir] [mlir][OpenMP] Avoid privatization barriers in partial-team regions (PR #229413)

Tom Eccles llvmlistbot at llvm.org
Tue Oct 6 08:11:24 PDT 2026


================
@@ -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
----------------
tblah wrote:

This one uses the private clause not firstprivate. But I have updated it to have more anchors. Apologies for the avoidable mistake.

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


More information about the Mlir-commits mailing list