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

Reply via email to