[flang-commits] [flang] [llvm] [mlir] [flang][OpenMP] Adding support for (PR #201823)
via flang-commits
flang-commits at lists.llvm.org
Fri Jun 5 05:20:16 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-openmp
Author: SunilKuravinakop
<details>
<summary>Changes</summary>
Adding support for "!$omp atomic compare weak".
!$omp atomic compare weak
if (var1 == num1) var1 = num2
!$omp end atomic
This handles issue [201812](https://github.com/llvm/llvm-project/issues/201812)
---
Full diff: https://github.com/llvm/llvm-project/pull/201823.diff
9 Files Affected:
- (modified) flang/lib/Lower/OpenMP/Atomic.cpp (+7-3)
- (modified) flang/lib/Parser/openmp-parsers.cpp (+1)
- (modified) flang/test/Lower/OpenMP/atomic-compare.f90 (+21)
- (modified) flang/test/Parser/OpenMP/atomic-unparse.f90 (+16)
- (modified) llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h (+6-6)
- (modified) llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp (+6-3)
- (modified) mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp (+6-3)
- (modified) mlir/test/Dialect/OpenMP/ops.mlir (+36)
- (modified) mlir/test/Target/LLVMIR/openmp-llvm.mlir (+27)
``````````diff
diff --git a/flang/lib/Lower/OpenMP/Atomic.cpp b/flang/lib/Lower/OpenMP/Atomic.cpp
index 9d711b92bb520..21a556159a949 100644
--- a/flang/lib/Lower/OpenMP/Atomic.cpp
+++ b/flang/lib/Lower/OpenMP/Atomic.cpp
@@ -563,12 +563,11 @@ void Fortran::lower::omp::lowerAtomic(
// e : expecteVal
// d : desiredVal
- // Check for compound clauses (fail, capture, weak) that are not yet
+ // Check for compound clauses (fail, capture) that are not yet
// supported with atomic compare.
if (llvm::any_of(clauses, [](const omp::Clause &clause) {
return clause.id == llvm::omp::Clause::OMPC_fail ||
- clause.id == llvm::omp::Clause::OMPC_capture ||
- clause.id == llvm::omp::Clause::OMPC_weak;
+ clause.id == llvm::omp::Clause::OMPC_capture;
})) {
TODO(loc, "Compound clauses of OpenMP ATOMIC COMPARE");
}
@@ -617,6 +616,11 @@ void Fortran::lower::omp::lowerAtomic(
}
mlir::UnitAttr weakAttr = nullptr;
+ if (llvm::any_of(clauses, [](const omp::Clause &clause) {
+ return clause.id == llvm::omp::Clause::OMPC_weak;
+ })) {
+ weakAttr = builder.getUnitAttr();
+ }
mlir::Operation *atomicOp = mlir::omp::AtomicCompareOp::create(
builder, loc, atomAddr, weakAttr, hint,
makeMemOrderAttr(converter, memOrder));
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 33af8c3f37be2..7016c688a572d 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -1663,6 +1663,7 @@ TYPE_PARSER( //
"UNTIED" >> construct<OmpClause>(construct<OmpClause::Untied>()) ||
"UPDATE" >> construct<OmpClause>(construct<OmpClause::Update>(
maybe(Parser<OmpUpdateClause>{}))) ||
+ "WEAK" >> construct<OmpClause>(construct<OmpClause::Weak>()) ||
"WHEN" >> construct<OmpClause>(construct<OmpClause::When>(
parenthesized(Parser<OmpWhenClause>{}))) ||
"WRITE" >> construct<OmpClause>(construct<OmpClause::Write>()) ||
diff --git a/flang/test/Lower/OpenMP/atomic-compare.f90 b/flang/test/Lower/OpenMP/atomic-compare.f90
index 62388d11f491c..ac70edbed4e60 100644
--- a/flang/test/Lower/OpenMP/atomic-compare.f90
+++ b/flang/test/Lower/OpenMP/atomic-compare.f90
@@ -140,3 +140,24 @@ subroutine atomic_compare_float_gt(x, e)
!$omp atomic compare
if (x .gt. e) x = e
end
+
+! CHECK-LABEL: func.func @_QPatomic_compare_int_eq_weak(
+! CHECK-SAME: %[[X:.*]]: !fir.ref<i32> {fir.bindc_name = "x"}
+! CHECK-SAME: %[[E:.*]]: !fir.ref<i32> {fir.bindc_name = "e"}
+! CHECK-SAME: %[[D:.*]]: !fir.ref<i32> {fir.bindc_name = "d"}
+! CHECK: %[[D_DECL:.*]]:2 = hlfir.declare %[[D]] {{.*}}
+! CHECK: %[[E_DECL:.*]]:2 = hlfir.declare %[[E]] {{.*}}
+! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {{.*}}
+! CHECK: %[[EVAL:.*]] = fir.load %[[E_DECL]]#0 : !fir.ref<i32>
+! CHECK: omp.atomic.compare memory_order(relaxed) %[[X_DECL]]#0 : !fir.ref<i32> {
+! CHECK: ^bb0(%[[XVAL:.*]]: i32):
+! CHECK: %[[CMP:.*]] = arith.cmpi eq, %[[XVAL]], %[[EVAL]] : i32
+! CHECK: %[[DVAL:.*]] = fir.load %[[D_DECL]]#0 : !fir.ref<i32>
+! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[DVAL]], %[[XVAL]] : i32
+! CHECK: omp.yield(%[[SEL]] : i32)
+! CHECK: } {{.*}}weak{{.*}}
+subroutine atomic_compare_int_eq_weak(x, e, d)
+ integer :: x, e, d
+ !$omp atomic compare weak
+ if (x .eq. e) x = d
+end
diff --git a/flang/test/Parser/OpenMP/atomic-unparse.f90 b/flang/test/Parser/OpenMP/atomic-unparse.f90
index 9a21d2c6d5486..4f3cf0eac0338 100644
--- a/flang/test/Parser/OpenMP/atomic-unparse.f90
+++ b/flang/test/Parser/OpenMP/atomic-unparse.f90
@@ -179,6 +179,19 @@ program main
i = j
end if
+!$omp atomic compare weak
+ if (i .eq. k) then
+ i = j
+ end if
+!$omp atomic weak compare
+ if (i .eq. k) then
+ i = j
+ end if
+!$omp atomic compare seq_cst weak
+ if (i .eq. k) then
+ i = j
+ end if
+
!ATOMIC
!$omp atomic
i = j
@@ -279,6 +292,9 @@ end program main
!CHECK: !$OMP ATOMIC COMPARE FAIL(RELAXED)
!CHECK: !$OMP ATOMIC FAIL(RELAXED) COMPARE
!CHECK: !$OMP ATOMIC FAIL(RELAXED) COMPARE ACQUIRE
+!CHECK: !$OMP ATOMIC COMPARE WEAK
+!CHECK: !$OMP ATOMIC WEAK COMPARE
+!CHECK: !$OMP ATOMIC COMPARE SEQ_CST WEAK
!ATOMIC
!CHECK: !$OMP ATOMIC
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
index 961b9958319a4..128fb7af7152a 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -4025,16 +4025,16 @@ class OpenMPIRBuilder {
return Old;
}
- LLVM_ABI InsertPointTy
- createAtomicCompare(const LocationDescription &Loc, AtomicOpValue &X,
- AtomicOpValue &V, AtomicOpValue &R, Value *E, Value *D,
- AtomicOrdering AO, omp::OMPAtomicCompareOp Op,
- bool IsXBinopExpr, bool IsPostfixUpdate, bool IsFailOnly);
LLVM_ABI InsertPointTy createAtomicCompare(
const LocationDescription &Loc, AtomicOpValue &X, AtomicOpValue &V,
AtomicOpValue &R, Value *E, Value *D, AtomicOrdering AO,
omp::OMPAtomicCompareOp Op, bool IsXBinopExpr, bool IsPostfixUpdate,
- bool IsFailOnly, AtomicOrdering Failure);
+ bool IsFailOnly, bool IsWeak = false);
+ LLVM_ABI InsertPointTy createAtomicCompare(
+ const LocationDescription &Loc, AtomicOpValue &X, AtomicOpValue &V,
+ AtomicOpValue &R, Value *E, Value *D, AtomicOrdering AO,
+ omp::OMPAtomicCompareOp Op, bool IsXBinopExpr, bool IsPostfixUpdate,
+ bool IsFailOnly, AtomicOrdering Failure, bool IsWeak = false);
/// Create the control flow structure of a canonical OpenMP loop.
///
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index c03497e162c9a..92eb7de0d882f 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -11146,18 +11146,18 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createAtomicCompare(
const LocationDescription &Loc, AtomicOpValue &X, AtomicOpValue &V,
AtomicOpValue &R, Value *E, Value *D, AtomicOrdering AO,
omp::OMPAtomicCompareOp Op, bool IsXBinopExpr, bool IsPostfixUpdate,
- bool IsFailOnly) {
+ bool IsFailOnly, bool IsWeak) {
AtomicOrdering Failure = AtomicCmpXchgInst::getStrongestFailureOrdering(AO);
return createAtomicCompare(Loc, X, V, R, E, D, AO, Op, IsXBinopExpr,
- IsPostfixUpdate, IsFailOnly, Failure);
+ IsPostfixUpdate, IsFailOnly, Failure, IsWeak);
}
OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createAtomicCompare(
const LocationDescription &Loc, AtomicOpValue &X, AtomicOpValue &V,
AtomicOpValue &R, Value *E, Value *D, AtomicOrdering AO,
omp::OMPAtomicCompareOp Op, bool IsXBinopExpr, bool IsPostfixUpdate,
- bool IsFailOnly, AtomicOrdering Failure) {
+ bool IsFailOnly, AtomicOrdering Failure, bool IsWeak) {
if (!updateToLocation(Loc))
return Loc.IP;
@@ -11262,6 +11262,7 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createAtomicCompare(
Builder.SetInsertPoint(ZeroBB);
AtomicCmpXchgInst *ResZero = Builder.CreateAtomicCmpXchg(
X.Var, XCurr, DBCast, MaybeAlign(), AO, Failure);
+ ResZero->setWeak(IsWeak);
Value *OldZero = Builder.CreateExtractValue(ResZero, /*Idxs=*/0);
Value *OkZero = Builder.CreateExtractValue(ResZero, /*Idxs=*/1);
Builder.CreateBr(ExitBB);
@@ -11270,6 +11271,7 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createAtomicCompare(
Builder.SetInsertPoint(NormalBB);
AtomicCmpXchgInst *ResNormal = Builder.CreateAtomicCmpXchg(
X.Var, EBCast, DBCast, MaybeAlign(), AO, Failure);
+ ResNormal->setWeak(IsWeak);
Value *OldNormal = Builder.CreateExtractValue(ResNormal, /*Idxs=*/0);
Value *OkNormal = Builder.CreateExtractValue(ResNormal, /*Idxs=*/1);
Builder.CreateBr(ExitBB);
@@ -11310,6 +11312,7 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createAtomicCompare(
Result =
Builder.CreateAtomicCmpXchg(X.Var, E, D, MaybeAlign(), AO, Failure);
}
+ Result->setWeak(IsWeak);
if (V.Var) {
OldValue = Builder.CreateExtractValue(Result, /*Idxs=*/0);
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 07fa92bdabe50..6f93ad231cfac 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -5141,8 +5141,9 @@ convertOmpAtomicCompare(omp::AtomicCompareOp atomicCompareOp,
llvm::AtomicOrdering failOrdering =
llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(atomicOrdering);
- builder.CreateAtomicCmpXchg(llvmX, eInt, dInt, maxAlign, atomicOrdering,
- failOrdering);
+ auto *cmpXchg = builder.CreateAtomicCmpXchg(llvmX, eInt, dInt, maxAlign,
+ atomicOrdering, failOrdering);
+ cmpXchg->setWeak(atomicCompareOp.getWeak());
// Emit flush after atomic compare if needed (for release, acq_rel,
// seq_cst orderings).
@@ -5224,11 +5225,13 @@ convertOmpAtomicCompare(omp::AtomicCompareOp atomicCompareOp,
false};
llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
+ bool isWeak = atomicCompareOp.getWeak();
+
bool savedHandleFPNegZero = ompBuilder->setHandleFPNegZero(true);
llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
ompBuilder->createAtomicCompare(ompLoc, llvmAtomicX, vOpVal, rOpVal, eVal,
dVal, atomicOrdering, compareOp,
- isXBinopExpr, false, false);
+ isXBinopExpr, false, false, isWeak);
ompBuilder->setHandleFPNegZero(savedHandleFPNegZero);
if (failed(handleError(afterIP, *atomicCompareOp)))
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index cbfa62c575a04..acf6879906e74 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -2011,6 +2011,42 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: memref<i32>, %expr: i32) {
return
}
+// CHECK-LABEL: omp_atomic_compare
+// CHECK-SAME: (%[[X:.*]]: memref<i32>, %[[E:.*]]: i32, %[[D:.*]]: i32)
+func.func @omp_atomic_compare(%x: memref<i32>, %e: i32, %d: i32) {
+ // CHECK: omp.atomic.compare %[[X]] : memref<i32> {
+ // CHECK-NEXT: ^bb0(%[[XVAL:.*]]: i32):
+ // CHECK-NEXT: %[[CMP:.*]] = arith.cmpi eq, %[[XVAL]], %[[E]] : i32
+ // CHECK-NEXT: %[[SEL:.*]] = arith.select %[[CMP]], %[[D]], %[[XVAL]] : i32
+ // CHECK-NEXT: omp.yield(%[[SEL]] : i32)
+ // CHECK-NEXT: }
+ omp.atomic.compare %x : memref<i32> {
+ ^bb0(%xval: i32):
+ %cmp = arith.cmpi eq, %xval, %e : i32
+ %sel = arith.select %cmp, %d, %xval : i32
+ omp.yield(%sel : i32)
+ }
+ // CHECK: omp.atomic.compare %[[X]] : memref<i32> {
+ // CHECK: omp.yield
+ // CHECK-NEXT: } {weak}
+ omp.atomic.compare %x : memref<i32> {
+ ^bb0(%xval: i32):
+ %cmp = arith.cmpi eq, %xval, %e : i32
+ %sel = arith.select %cmp, %d, %xval : i32
+ omp.yield(%sel : i32)
+ } {weak}
+ // CHECK: omp.atomic.compare memory_order(seq_cst) %[[X]] : memref<i32> {
+ // CHECK: omp.yield
+ // CHECK-NEXT: } {weak}
+ omp.atomic.compare memory_order(seq_cst) %x : memref<i32> {
+ ^bb0(%xval: i32):
+ %cmp = arith.cmpi eq, %xval, %e : i32
+ %sel = arith.select %cmp, %d, %xval : i32
+ omp.yield(%sel : i32)
+ } {weak}
+ return
+}
+
// CHECK-LABEL: omp_sectionsop
func.func @omp_sectionsop(%data_var1 : memref<i32>, %data_var2 : memref<i32>,
%data_var3 : memref<i32>, %redn_var : !llvm.ptr) {
diff --git a/mlir/test/Target/LLVMIR/openmp-llvm.mlir b/mlir/test/Target/LLVMIR/openmp-llvm.mlir
index 38f10320bd3ae..1890eaa6a3f0b 100644
--- a/mlir/test/Target/LLVMIR/openmp-llvm.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-llvm.mlir
@@ -2720,6 +2720,33 @@ llvm.func @omp_atomic_compare(
// -----
+// CHECK-LABEL: @omp_atomic_compare_weak
+// CHECK-SAME: (ptr %[[X:.*]], i32 %[[E:.*]], i32 %[[D:.*]])
+llvm.func @omp_atomic_compare_weak(%x : !llvm.ptr, %e : i32, %d : i32) {
+ // Integer equality with weak → cmpxchg weak
+ // CHECK: cmpxchg weak ptr %[[X]], i32 %[[E]], i32 %[[D]] monotonic monotonic
+ omp.atomic.compare %x : !llvm.ptr {
+ ^bb0(%xval : i32):
+ %cmp = llvm.icmp "eq" %xval, %e : i32
+ %sel = llvm.select %cmp, %d, %xval : i1, i32
+ omp.yield(%sel : i32)
+ } {weak}
+
+ // Integer equality with weak + seq_cst → cmpxchg weak + flush
+ // CHECK: cmpxchg weak ptr %[[X]], i32 %[[E]], i32 %[[D]] seq_cst seq_cst
+ // CHECK: call void @__kmpc_flush(ptr @{{.*}})
+ omp.atomic.compare memory_order(seq_cst) %x : !llvm.ptr {
+ ^bb0(%xval : i32):
+ %cmp = llvm.icmp "eq" %xval, %e : i32
+ %sel = llvm.select %cmp, %d, %xval : i1, i32
+ omp.yield(%sel : i32)
+ } {weak}
+
+ llvm.return
+}
+
+// -----
+
// CHECK-LABEL: @omp_atomic_compare_float_neg_zero
// CHECK-SAME: (ptr %[[XF:.*]], float %[[EF:.*]], float %[[DF:.*]])
// Verify NaN guard + ±0.0 handling.
``````````
</details>
https://github.com/llvm/llvm-project/pull/201823
More information about the flang-commits
mailing list