llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clangir
Author: Erich Keane (erichkeane)
<details>
<summary>Changes</summary>
This was left as an NYI, but appears in self build!
This patch follows the existing solution in that we are doing the branching of
weak vs not-weak at the CIR level. This is necessary because the LLVM
intrinsics (and the CIR operaions) take 'weak' as a constant value.
Unlike classic-codegen, this patch uses an 'if' instead of a 'switch' on the
'weak' value. This is mainly for readability (since it is a switch
over a bool!), but also because our 'switch' doesn't seem to support
'bool', so this would require an additional cast.
As a future direction, we may wish to modify the CIR operations to take 'weak'
and 'failure' value (both are constants in LLVM intrinsics!) as non-constants,
and handle the switch/if statement during lowering. This would give us an
opportunity to optimize the value out without having to collapse the
if/switch/etc, and minimize the size of the CIR. However, as that is a larger
direction, this patch skips that for now.
---
Patch is 21.96 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/198546.diff
2 Files Affected:
- (modified) clang/lib/CIR/CodeGen/CIRGenAtomic.cpp (+33-3)
- (modified) clang/test/CIR/CodeGen/atomic.c (+354)
``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
index 3a02fa0888f82..4e6698e3bbf29 100644
--- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
@@ -523,6 +523,37 @@ static void emitAtomicCmpXchgFailureSet(CIRGenFunction
&cgf, AtomicExpr *e,
});
}
+static void emitAtomicCmpXchgFailureSet(CIRGenFunction &cgf, AtomicExpr *e,
+ Expr *isWeakExpr, Address dest,
+ Address ptr, Address val1, Address
val2,
+ Expr *failureOrderExpr, uint64_t size,
+ cir::MemOrder successOrder,
+ cir::SyncScopeKind scope) {
+ mlir::Value isWeakVal = cgf.emitScalarExpr(isWeakExpr);
+ // The AST seems to be inserting a 'bool' cast (even in C mode) here, so
we'll
+ // just emit it like a scalar.
+ assert(isWeakVal.getType() == cgf.getBuilder().getBoolTy());
+ mlir::Location atomicLoc = cgf.getLoc(e->getSourceRange());
+
+ // Unlike classic compiler, we use an 'if' here instead of a switch, simply
to
+ // make this more readable/logical, plus we don't allow switch over a bool in
+ // CIR.
+ cir::IfOp::create(
+ cgf.getBuilder(), atomicLoc, isWeakVal, /*elseRegion=*/true,
+ [&](mlir::OpBuilder &b, mlir::Location loc) {
+ emitAtomicCmpXchgFailureSet(cgf, e, /*isWeak=*/true, dest, ptr, val1,
+ val2, failureOrderExpr, size, successOrder,
+ scope);
+ cgf.getBuilder().createYield(atomicLoc);
+ },
+ [&](mlir::OpBuilder &b, mlir::Location loc) {
+ emitAtomicCmpXchgFailureSet(cgf, e, /*isWeak=*/false, dest, ptr, val1,
+ val2, failureOrderExpr, size, successOrder,
+ scope);
+ cgf.getBuilder().createYield(atomicLoc);
+ });
+}
+
static void emitAtomicOp(CIRGenFunction &cgf, AtomicExpr *expr, Address dest,
Address ptr, Address val1, Address val2,
Expr *isWeakExpr, Expr *failureOrderExpr, int64_t
size,
@@ -560,9 +591,8 @@ static void emitAtomicOp(CIRGenFunction &cgf, AtomicExpr
*expr, Address dest,
emitAtomicCmpXchgFailureSet(cgf, expr, isWeak, dest, ptr, val1, val2,
failureOrderExpr, size, order, scope);
} else {
- assert(!cir::MissingFeatures::atomicExpr());
- cgf.cgm.errorNYI(expr->getSourceRange(),
- "emitAtomicOp: non-constant isWeak");
+ emitAtomicCmpXchgFailureSet(cgf, expr, isWeakExpr, dest, ptr, val1, val2,
+ failureOrderExpr, size, order, scope);
}
return;
}
diff --git a/clang/test/CIR/CodeGen/atomic.c b/clang/test/CIR/CodeGen/atomic.c
index badc1bf0e2bb1..60a2f2e9c907d 100644
--- a/clang/test/CIR/CodeGen/atomic.c
+++ b/clang/test/CIR/CodeGen/atomic.c
@@ -3008,3 +3008,357 @@ int atomic_fetch_udec(int *ptr, int value) {
// OGCG: %[[RES:.+]] = atomicrmw udec_wrap ptr %{{.+}}, i32 %{{.+}}
seq_cst, align 4
// OGCG-NEXT: store i32 %[[RES]], ptr %{{.+}}, align 4
}
+
+void atomic_cmpxchg_maybe_weak(int *ptr, int *expected, int *desired, int
failure, int weak) {
+ // CIR-LABEL: @atomic_cmpxchg_maybe_weak
+ // LLVM-LABEL: @atomic_cmpxchg_maybe_weak
+ // OGCG-LABEL: @atomic_cmpxchg_maybe_weak
+ // CIR: %[[FAILURE:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["failure",
init]
+ // CIR: %[[WEAK:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["weak", init]
+
+ __atomic_compare_exchange(ptr, expected, desired, weak, __ATOMIC_SEQ_CST,
__ATOMIC_ACQUIRE);
+ // CIR: %[[WEAK_LOAD:.*]] = cir.load{{.*}}%[[WEAK]]
+ // CIR-NEXT: %[[WEAK_CAST:.*]] = cir.cast int_to_bool %[[WEAK_LOAD]]
+ // CIR-NEXT: cir.if %[[WEAK_CAST]] {
+ // CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg weak
success(seq_cst) failure(acquire) syncscope(system) %{{.+}}, %{{.+}}, %{{.+}}
align(4) : (!cir.ptr<!s32i>, !s32i, !s32i) -> (!s32i, !cir.bool)
+ // CIR-NEXT: %[[FAILED:.+]] = cir.not %[[SUCCESS]] : !cir.bool
+ // CIR-NEXT: cir.if %[[FAILED]] {
+ // CIR-NEXT: cir.store align(4) %[[OLD]], %{{.+}} : !s32i,
!cir.ptr<!s32i>
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.store align(1) %[[SUCCESS]], %{{.+}} : !cir.bool,
!cir.ptr<!cir.bool>
+ // CIR-NEXT: } else {
+ // CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg
success(seq_cst) failure(acquire) syncscope(system) %{{.+}}, %{{.+}}, %{{.+}}
align(4) : (!cir.ptr<!s32i>, !s32i, !s32i) -> (!s32i, !cir.bool)
+ // CIR-NEXT: %[[FAILED:.+]] = cir.not %[[SUCCESS]] : !cir.bool
+ // CIR-NEXT: cir.if %[[FAILED]] {
+ // CIR-NEXT: cir.store align(4) %[[OLD]], %{{.+}} : !s32i,
!cir.ptr<!s32i>
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.store align(1) %[[SUCCESS]], %{{.+}} : !cir.bool,
!cir.ptr<!cir.bool>
+ // CIR-NEXT: }
+
+ // LLVM: %[[WEAK_CAST:.*]] = icmp ne i32 %{{.*}}, 0
+ // LLVM-NEXT: br i1 %[[WEAK_CAST]], label %[[WEAK_TRUE:.*]], label
%[[WEAK_FALSE:.*]]
+ //
+ // LLVM: [[WEAK_TRUE]]:
+ // LLVM: %[[RESULT:.+]] = cmpxchg weak ptr %{{.+}}, i32 %{{.+}}, i32
%{{.+}} seq_cst acquire, align 4
+ // LLVM-NEXT: %[[OLD:.+]] = extractvalue { i32, i1 } %[[RESULT]], 0
+ // LLVM-NEXT: %[[SUCCESS:.+]] = extractvalue { i32, i1 } %[[RESULT]], 1
+ // LLVM-NEXT: %[[FAILED:.+]] = xor i1 %[[SUCCESS]], true
+ // LLVM-NEXT: br i1 %[[FAILED]], label %[[LABEL_FAILED:.+]], label
%[[LABEL_CONT:.+]]
+ // LLVM: [[LABEL_FAILED]]:
+ // LLVM-NEXT: store i32 %[[OLD]], ptr %{{.+}}, align 4
+ // LLVM-NEXT: br label %[[LABEL_CONT]]
+ // LLVM: [[LABEL_CONT]]:
+ // LLVM-NEXT: %[[SUCCESS_2:.+]] = zext i1 %[[SUCCESS]] to i8
+ // LLVM-NEXT: store i8 %[[SUCCESS_2]], ptr %{{.+}}, align 1
+ //
+ // LLVM: [[WEAK_FALSE]]:
+ // LLVM: %[[RESULT:.+]] = cmpxchg ptr %{{.+}}, i32 %{{.+}}, i32
%{{.+}} seq_cst acquire, align 4
+ // LLVM-NEXT: %[[OLD:.+]] = extractvalue { i32, i1 } %[[RESULT]], 0
+ // LLVM-NEXT: %[[SUCCESS:.+]] = extractvalue { i32, i1 } %[[RESULT]], 1
+ // LLVM-NEXT: %[[FAILED:.+]] = xor i1 %[[SUCCESS]], true
+ // LLVM-NEXT: br i1 %[[FAILED]], label %[[LABEL_FAILED:.+]], label
%[[LABEL_CONT:.+]]
+ // LLVM: [[LABEL_FAILED]]:
+ // LLVM-NEXT: store i32 %[[OLD]], ptr %{{.+}}, align 4
+ // LLVM-NEXT: br label %[[LABEL_CONT]]
+ // LLVM: [[LABEL_CONT]]:
+ // LLVM-NEXT: %[[SUCCESS_2:.+]] = zext i1 %[[SUCCESS]] to i8
+ // LLVM-NEXT: store i8 %[[SUCCESS_2]], ptr %{{.+}}, align 1
+
+ // OGCG: %[[IS_WEAK:.*]] = icmp ne i32 %{{.*}}, 0
+ // OGCG-NEXT: switch i1 %[[IS_WEAK]], label %[[WEAK_TRUE:.*]] [
+ // OGCG-NEXT: i1 false, label %[[WEAK_FALSE:.*]]
+ // OGCG-NEXT: ]
+ //
+ // OGCG: [[WEAK_FALSE]]:
+ // OGCG: %[[RESULT:.+]] = cmpxchg ptr %{{.+}}, i32 %{{.+}}, i32
%{{.+}} seq_cst acquire, align 4
+ // OGCG-NEXT: %[[OLD:.+]] = extractvalue { i32, i1 } %[[RESULT]], 0
+ // OGCG-NEXT: %[[SUCCESS:.+]] = extractvalue { i32, i1 } %[[RESULT]], 1
+ // OGCG-NEXT: br i1 %[[SUCCESS]], label %{{.*}}, label %{{.*}}
+ //
+ // OGCG: [[WEAK_TRUE]]:
+ // OGCG: %[[RESULT:.+]] = cmpxchg weak ptr %{{.+}}, i32 %{{.+}}, i32
%{{.+}} seq_cst acquire, align 4
+ // OGCG-NEXT: %[[OLD:.+]] = extractvalue { i32, i1 } %[[RESULT]], 0
+ // OGCG-NEXT: %[[SUCCESS:.+]] = extractvalue { i32, i1 } %[[RESULT]], 1
+ // OGCG-NEXT: br i1 %[[SUCCESS]], label %{{.*}}, label %{{.*}}
+ //
+ // Note: The order of the rest of the blocks is pretty awkward in OGCG
+ // in a way that makes this not particularly checkable in any way that
+ // is readable. So we're checking only up to the above.
+
+ __atomic_compare_exchange(ptr, expected, desired, weak, __ATOMIC_SEQ_CST,
failure);
+ // CIR: %[[WEAK_LOAD:.*]] = cir.load{{.*}}%[[WEAK]]
+ // CIR-NEXT: %[[WEAK_CAST:.*]] = cir.cast int_to_bool %[[WEAK_LOAD]]
+ // CIR-NEXT: cir.if %[[WEAK_CAST]] {
+ // CIR: %[[FAIL_LOAD:.*]] = cir.load{{.*}}%[[FAILURE]]
+ // CIR: cir.switch(%[[FAIL_LOAD]] : !s32i) {
+ // CIR-NEXT: cir.case(default, []) {
+ // CIR: cir.atomic.cmpxchg weak success(seq_cst) failure(relaxed)
syncscope(system) %{{.+}}, %{{.+}}, %{{.+}} align(4) : (!cir.ptr<!s32i>, !s32i,
!s32i) -> (!s32i, !cir.bool)
+ // CIR: cir.break
+ // CIR: }
+ // CIR-NEXT: cir.case(anyof, [#cir.int<1> : !s32i, #cir.int<2> : !s32i])
{
+ // CIR: cir.atomic.cmpxchg weak success(seq_cst) failure(acquire)
syncscope(system) %{{.+}}, %{{.+}}, %{{.+}} align(4) : (!cir.ptr<!s32i>, !s32i,
!s32i) -> (!s32i, !cir.bool)
+ // CIR: cir.break
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.case(anyof, [#cir.int<5> : !s32i]) {
+ // CIR: cir.atomic.cmpxchg weak success(seq_cst) failure(seq_cst)
syncscope(system) %{{.+}}, %{{.+}}, %{{.+}} align(4) : (!cir.ptr<!s32i>, !s32i,
!s32i) -> (!s32i, !cir.bool)
+ // CIR: cir.break
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.yield
+ // CIR-NEXT: }
+ // CIR-NEXT: } else {
+ // CIR: %[[FAIL_LOAD:.*]] = cir.load{{.*}}%[[FAILURE]]
+ // CIR: cir.switch(%[[FAIL_LOAD]] : !s32i) {
+ // CIR-NEXT: cir.case(default, []) {
+ // CIR: cir.atomic.cmpxchg success(seq_cst) failure(relaxed)
syncscope(system) %{{.+}}, %{{.+}}, %{{.+}} align(4) : (!cir.ptr<!s32i>, !s32i,
!s32i) -> (!s32i, !cir.bool)
+ // CIR: cir.break
+ // CIR: }
+ // CIR-NEXT: cir.case(anyof, [#cir.int<1> : !s32i, #cir.int<2> : !s32i])
{
+ // CIR: cir.atomic.cmpxchg success(seq_cst) failure(acquire)
syncscope(system) %{{.+}}, %{{.+}}, %{{.+}} align(4) : (!cir.ptr<!s32i>, !s32i,
!s32i) -> (!s32i, !cir.bool)
+ // CIR: cir.break
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.case(anyof, [#cir.int<5> : !s32i]) {
+ // CIR: cir.atomic.cmpxchg success(seq_cst) failure(seq_cst)
syncscope(system) %{{.+}}, %{{.+}}, %{{.+}} align(4) : (!cir.ptr<!s32i>, !s32i,
!s32i) -> (!s32i, !cir.bool)
+ // CIR: cir.break
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.yield
+ // CIR-NEXT: }
+ // CIR-NEXT: }
+
+ // LLVM: %[[WEAK_CAST:.*]] = icmp ne i32 %{{.*}}, 0
+ // LLVM-NEXT: br i1 %[[WEAK_CAST]], label %[[WEAK_TRUE:.*]], label
%[[WEAK_FALSE:.*]]
+ //
+ // LLVM: [[WEAK_TRUE]]:
+ // LLVM: switch i32 %{{.*}}, label %[[DEF:.*]] [
+ // LLVM-NEXT: i32 1, label %[[ACQ:.*]]
+ // LLVM-NEXT: i32 2, label %[[ACQ]]
+ // LLVM-NEXT: i32 5, label %[[SEQ_CST:.*]]
+ // LLVM-NEXT: ]
+ // LLVM: [[DEF]]:
+ // LLVM: cmpxchg weak ptr %{{.+}}, i32 %{{.+}}, i32 %{{.+}} seq_cst
monotonic
+ // LLVM: [[ACQ]]:
+ // LLVM: cmpxchg weak ptr %{{.+}}, i32 %{{.+}}, i32 %{{.+}} seq_cst acquire
+ // LLVM: [[SEQ_CST]]:
+ // LLVM: cmpxchg weak ptr %{{.+}}, i32 %{{.+}}, i32 %{{.+}} seq_cst seq_cst
+ //
+ // LLVM: [[WEAK_FALSE]]:
+ // LLVM: switch i32 %{{.*}}, label %[[DEF:.*]] [
+ // LLVM-NEXT: i32 1, label %[[ACQ:.*]]
+ // LLVM-NEXT: i32 2, label %[[ACQ]]
+ // LLVM-NEXT: i32 5, label %[[SEQ_CST:.*]]
+ // LLVM-NEXT: ]
+ // LLVM: [[DEF]]:
+ // LLVM: cmpxchg ptr %{{.+}}, i32 %{{.+}}, i32 %{{.+}} seq_cst monotonic
+ // LLVM: [[ACQ]]:
+ // LLVM: cmpxchg ptr %{{.+}}, i32 %{{.+}}, i32 %{{.+}} seq_cst acquire
+ // LLVM: [[SEQ_CST]]:
+ // LLVM: cmpxchg ptr %{{.+}}, i32 %{{.+}}, i32 %{{.+}} seq_cst seq_cst
+
+ // OGCG: %[[IS_WEAK:.*]] = icmp ne i32 %{{.*}}, 0
+ // OGCG-NEXT: switch i1 %[[IS_WEAK]], label %[[WEAK_TRUE:.*]] [
+ // OGCG-NEXT: i1 false, label %[[WEAK_FALSE:.*]]
+ // OGCG-NEXT: ]
+ //
+ // OGCG: [[WEAK_FALSE]]:
+ // OGCG: switch i32 %{{.*}}, label %[[STRONG_DEF:.*]] [
+ // OGCG-NEXT: i32 1, label %[[STRONG_ACQ:.*]]
+ // OGCG-NEXT: i32 2, label %[[STRONG_ACQ]]
+ // OGCG-NEXT: i32 5, label %[[STRONG_SEQ_CST:.*]]
+ // OGCG-NEXT: ]
+ //
+ // OGCG: [[WEAK_TRUE]]:
+ // OGCG: switch i32 %{{.*}}, label %[[WEAK_DEF:.*]] [
+ // OGCG-NEXT: i32 1, label %[[WEAK_ACQ:.*]]
+ // OGCG-NEXT: i32 2, label %[[WEAK_ACQ]]
+ // OGCG-NEXT: i32 5, label %[[WEAK_SEQ_CST:.*]]
+ // OGCG-NEXT: ]
+ //
+ // OGCG: [[STRONG_DEF]]:
+ // OGCG: cmpxchg ptr %{{.+}}, i32 %{{.+}}, i32 %{{.+}} seq_cst monotonic
+ // OGCG: [[STRONG_ACQ]]:
+ // OGCG: cmpxchg ptr %{{.+}}, i32 %{{.+}}, i32 %{{.+}} seq_cst acquire
+ // OGCG: [[STRONG_SEQ_CST]]:
+ // OGCG: cmpxchg ptr %{{.+}}, i32 %{{.+}}, i32 %{{.+}} seq_cst seq_cst
+ //
+ // OGCG: [[WEAK_DEF]]:
+ // OGCG: cmpxchg weak ptr %{{.+}}, i32 %{{.+}}, i32 %{{.+}} seq_cst
monotonic
+ // OGCG: [[WEAK_ACQ]]:
+ // OGCG: cmpxchg weak ptr %{{.+}}, i32 %{{.+}}, i32 %{{.+}} seq_cst acquire
+ // OGCG: [[WEAK_SEQ_CST]]:
+ // OGCG: cmpxchg weak ptr %{{.+}}, i32 %{{.+}}, i32 %{{.+}} seq_cst seq_cst
+}
+
+void atomic_cmpxchg_n_maybe_weak(int *ptr, int *expected, int desired, int
failure, int weak) {
+ // CIR-LABEL: @atomic_cmpxchg_n_maybe_weak
+ // LLVM-LABEL: @atomic_cmpxchg_n_maybe_weak
+ // OGCG-LABEL: @atomic_cmpxchg_n_maybe_weak
+ // CIR: %[[FAILURE:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["failure",
init]
+ // CIR: %[[WEAK:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["weak", init]
+
+ __atomic_compare_exchange_n(ptr, expected, desired, weak, __ATOMIC_SEQ_CST,
__ATOMIC_ACQUIRE);
+ // CIR: %[[WEAK_LOAD:.*]] = cir.load{{.*}}%[[WEAK]]
+ // CIR-NEXT: %[[WEAK_CAST:.*]] = cir.cast int_to_bool %[[WEAK_LOAD]]
+ // CIR-NEXT: cir.if %[[WEAK_CAST]] {
+ // CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg weak
success(seq_cst) failure(acquire) syncscope(system) %{{.+}}, %{{.+}}, %{{.+}}
align(4) : (!cir.ptr<!s32i>, !s32i, !s32i) -> (!s32i, !cir.bool)
+ // CIR-NEXT: %[[FAILED:.+]] = cir.not %[[SUCCESS]] : !cir.bool
+ // CIR-NEXT: cir.if %[[FAILED]] {
+ // CIR-NEXT: cir.store align(4) %[[OLD]], %{{.+}} : !s32i,
!cir.ptr<!s32i>
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.store align(1) %[[SUCCESS]], %{{.+}} : !cir.bool,
!cir.ptr<!cir.bool>
+ // CIR-NEXT: } else {
+ // CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg
success(seq_cst) failure(acquire) syncscope(system) %{{.+}}, %{{.+}}, %{{.+}}
align(4) : (!cir.ptr<!s32i>, !s32i, !s32i) -> (!s32i, !cir.bool)
+ // CIR-NEXT: %[[FAILED:.+]] = cir.not %[[SUCCESS]] : !cir.bool
+ // CIR-NEXT: cir.if %[[FAILED]] {
+ // CIR-NEXT: cir.store align(4) %[[OLD]], %{{.+}} : !s32i,
!cir.ptr<!s32i>
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.store align(1) %[[SUCCESS]], %{{.+}} : !cir.bool,
!cir.ptr<!cir.bool>
+ // CIR-NEXT: }
+
+ // LLVM: %[[WEAK_CAST:.*]] = icmp ne i32 %{{.*}}, 0
+ // LLVM-NEXT: br i1 %[[WEAK_CAST]], label %[[WEAK_TRUE:.*]], label
%[[WEAK_FALSE:.*]]
+ //
+ // LLVM: [[WEAK_TRUE]]:
+ // LLVM: %[[RESULT:.+]] = cmpxchg weak ptr %{{.+}}, i32 %{{.+}}, i32
%{{.+}} seq_cst acquire, align 4
+ // LLVM-NEXT: %[[OLD:.+]] = extractvalue { i32, i1 } %[[RESULT]], 0
+ // LLVM-NEXT: %[[SUCCESS:.+]] = extractvalue { i32, i1 } %[[RESULT]], 1
+ // LLVM-NEXT: %[[FAILED:.+]] = xor i1 %[[SUCCESS]], true
+ // LLVM-NEXT: br i1 %[[FAILED]], label %[[LABEL_FAILED:.+]], label
%[[LABEL_CONT:.+]]
+ // LLVM: [[LABEL_FAILED]]:
+ // LLVM-NEXT: store i32 %[[OLD]], ptr %{{.+}}, align 4
+ // LLVM-NEXT: br label %[[LABEL_CONT]]
+ // LLVM: [[LABEL_CONT]]:
+ // LLVM-NEXT: %[[SUCCESS_2:.+]] = zext i1 %[[SUCCESS]] to i8
+ // LLVM-NEXT: store i8 %[[SUCCESS_2]], ptr %{{.+}}, align 1
+ //
+ // LLVM: [[WEAK_FALSE]]:
+ // LLVM: %[[RESULT:.+]] = cmpxchg ptr %{{.+}}, i32 %{{.+}}, i32
%{{.+}} seq_cst acquire, align 4
+ // LLVM-NEXT: %[[OLD:.+]] = extractvalue { i32, i1 } %[[RESULT]], 0
+ // LLVM-NEXT: %[[SUCCESS:.+]] = extractvalue { i32, i1 } %[[RESULT]], 1
+ // LLVM-NEXT: %[[FAILED:.+]] = xor i1 %[[SUCCESS]], true
+ // LLVM-NEXT: br i1 %[[FAILED]], label %[[LABEL_FAILED:.+]], label
%[[LABEL_CONT:.+]]
+ // LLVM: [[LABEL_FAILED]]:
+ // LLVM-NEXT: store i32 %[[OLD]], ptr %{{.+}}, align 4
+ // LLVM-NEXT: br label %[[LABEL_CONT]]
+ // LLVM: [[LABEL_CONT]]:
+ // LLVM-NEXT: %[[SUCCESS_2:.+]] = zext i1 %[[SUCCESS]] to i8
+ // LLVM-NEXT: store i8 %[[SUCCESS_2]], ptr %{{.+}}, align 1
+
+
+ // OGCG: %[[IS_WEAK:.*]] = icmp ne i32 %{{.*}}, 0
+ // OGCG-NEXT: switch i1 %[[IS_WEAK]], label %[[WEAK_TRUE:.*]] [
+ // OGCG-NEXT: i1 false, label %[[WEAK_FALSE:.*]]
+ // OGCG-NEXT: ]
+ //
+ // OGCG: [[WEAK_FALSE]]:
+ // OGCG: %[[RESULT:.+]] = cmpxchg ptr %{{.+}}, i32 %{{.+}}, i32
%{{.+}} seq_cst acquire, align 4
+ // OGCG-NEXT: %[[OLD:.+]] = extractvalue { i32, i1 } %[[RESULT]], 0
+ // OGCG-NEXT: %[[SUCCESS:.+]] = extractvalue { i32, i1 } %[[RESULT]], 1
+ // OGCG-NEXT: br i1 %[[SUCCESS]], label %{{.*}}, label %{{.*}}
+ //
+ // OGCG: [[WEAK_TRUE]]:
+ // OGCG: %[[RESULT:.+]] = cmpxchg weak ptr %{{.+}}, i32 %{{.+}}, i32
%{{.+}} seq_cst acquire, align 4
+ // OGCG-NEXT: %[[OLD:.+]] = extractvalue { i32, i1 } %[[RESULT]], 0
+ // OGCG-NEXT: %[[SUCCESS:.+]] = extractvalue { i32, i1 } %[[RESULT]], 1
+ // OGCG-NEXT: br i1 %[[SUCCESS]], label %{{.*}}, label %{{.*}}
+
+ __atomic_compare_exchange_n(ptr, expected, desired, weak, __ATOMIC_SEQ_CST,
failure);
+ // CIR: %[[WEAK_LOAD:.*]] = cir.load{{.*}}%[[WEAK]]
+ // CIR-NEXT: %[[WEAK_CAST:.*]] = cir.cast int_to_bool %[[WEAK_LOAD]]
+ // CIR-NEXT: cir.if %[[WEAK_CAST]] {
+ // CIR: %[[FAIL_LOAD:.*]] = cir.load{{.*}}%[[FAILURE]]
+ // CIR: cir.switch(%[[FAIL_LOAD]] : !s32i) {
+ // CIR-NEXT: cir.case(default, []) {
+ // CIR: cir.atomic.cmpxchg weak success(seq_cst) failure(relaxed)
syncscope(system) %{{.+}}, %{{.+}}, %{{.+}} align(4) : (!cir.ptr<!s32i>, !s32i,
!s32i) -> (!s32i, !cir.bool)
+ // CIR: cir.break
+ // CIR: }
+ // CIR-NEXT: cir.case(anyof, [#cir.int<1> : !s32i, #cir.int<2> : !s32i])
{
+ // CIR: cir.atomic.cmpxchg weak success(seq_cst) failure(acquire)
syncscope(system) %{{.+}}, %{{.+}}, %{{.+}} align(4) : (!cir.ptr<!s32i>, !s32i,
!s32i) -> (!s32i, !cir.bool)
+ // CIR: cir.break
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.case(anyof, [#cir.int<5> : !s32i]) {
+ // CIR: cir.atomic.cmpxchg weak success(seq_cst) failure(seq_cst)
syncscope(system) %{{.+}}, %{{.+}}, %{{.+}} align(4) : (!cir.ptr<!s32i>, !s32i,
!s32i) -> (!s32i, !cir.bool)
+ // CIR: cir.break
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.yield
+ // CIR-NEXT: }
+ // CIR-NEXT: } else {
+ // CIR: %[[FAIL_LOAD:.*]] = cir.load{{.*}}%[[FAILURE]]
+ // CIR: cir.switch(%[[FAIL_LOAD]] : !s32i) {
+ // CIR-NEXT: cir.case(default, []) {
+ // CIR: cir.atomic.cmpxchg success(seq_cst) failure(relaxed)
syncscope(system) %{{.+}}, %{{.+}}, %{{.+}} align(4) : (!cir.ptr<!s32i>, !s32i,
!s32i) -> (!s32i, !cir.bool)
+ // CIR: cir.break
+ // CIR: }
+ // CIR-NEXT: cir.case(anyof, [#cir.int<1> : !s32i, #cir.int<2> : !s32i])
{
+ // CIR: cir.atomic.cmpxchg success(seq_cst) failure(acquire)
syncscope(system) %{{.+}}, %{{.+}}, %{{.+}} align(4) : (!cir.ptr<!s32i>, !s32i,
!s32i) -> (!s32i, !cir.bool)
+ // CIR: cir.break
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.case(anyof, [#cir.int<5> : !s32i]) {
+ // CIR: cir.atomic.cmpxchg success(seq_cst) failure(seq_cst)
syncscope(system) %{{.+}}, %{{.+}}, %{{.+}} align(4) : (!cir.ptr<!s32i>, !s32i,
!s32i) -> (!s32i, !cir.bool)
+ // CIR: cir.break
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.yield
+ // CIR-NEXT: }
+ // CIR-NEXT: }
+
+ // LLVM: %[[WEAK_CAST:.*]] = icmp ne i32 %{{.*}}, 0
+ // LLVM-NEXT: br i1 %[[WEAK_CAST]], label %[[WEAK_TRUE:.*]], label
%[[WEAK_FALSE:.*]]
+ //
+ // LLVM: [[WEAK_TRUE]]:
+ // LLVM: switch i32 %{{.*}}, label %[[DEF:.*]] [
+ // LLVM-NEXT: i32 1, label %[[ACQ:.*]]
+ // LLVM-NEXT: i32 2, label %[[ACQ]]
+ // LLVM-NEXT: i32 5, label %[[SEQ_CST:.*]]
+ // LLVM-NEXT: ]
+ // LLVM: [[DEF]]:
+ // LLVM: cmpxchg weak ptr %{{.+}}, i32 %{{.+}}, i32 %{{.+}} seq_cst
monotonic
+ // LLVM: [[ACQ]]:
+ // LLVM: cmpxchg weak ptr %{{.+}}, i32 %{{.+}}, i32 %{{.+}} seq_cst acquire
+ // LLVM...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/198546
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits