llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Ayokunle Amodu (ayokunle321)

<details>
<summary>Changes</summary>

Adds CIRGen support for `__sync_val_compare_and_swap` and 
`__sync_bool_compare_and_swap` builtins.

---
Full diff: https://github.com/llvm/llvm-project/pull/186529.diff


2 Files Affected:

- (modified) clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp (+33) 
- (modified) clang/test/CIR/CodeGen/atomic.c (+93) 


``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 5d9ddbe5c3f22..77a20e56a5936 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -172,6 +172,37 @@ static mlir::Value makeBinaryAtomicValue(
   return rmwi->getResult(0);
 }
 
+/// Utility to insert an atomic cmpxchg instruction.
+static mlir::Value makeAtomicCmpXchgValue(CIRGenFunction &cgf,
+                                          const CallExpr *expr,
+                                          bool returnBool) {
+  QualType typ = returnBool ? expr->getArg(1)->getType() : expr->getType();
+  Address destAddr = checkAtomicAlignment(cgf, expr);
+  clang::CIRGen::CIRGenBuilderTy &builder = cgf.getBuilder();
+
+  cir::IntType intType =
+      expr->getArg(0)->getType()->getPointeeType()->isUnsignedIntegerType()
+          ? builder.getUIntNTy(cgf.getContext().getTypeSize(typ))
+          : builder.getSIntNTy(cgf.getContext().getTypeSize(typ));
+  mlir::Value cmpVal = cgf.emitScalarExpr(expr->getArg(1));
+  cmpVal = emitToInt(cgf, cmpVal, typ, intType);
+  mlir::Value newVal =
+      emitToInt(cgf, cgf.emitScalarExpr(expr->getArg(2)), typ, intType);
+
+  cir::AtomicCmpXchgOp op = cir::AtomicCmpXchgOp::create(
+      builder, cgf.getLoc(expr->getSourceRange()), cmpVal.getType(),
+      builder.getBoolTy(), destAddr.getPointer(), cmpVal, newVal,
+      cir::MemOrderAttr::get(&cgf.getMLIRContext(),
+                             cir::MemOrder::SequentiallyConsistent),
+      cir::MemOrderAttr::get(&cgf.getMLIRContext(),
+                             cir::MemOrder::SequentiallyConsistent),
+      cir::SyncScopeKindAttr::get(&cgf.getMLIRContext(),
+                                  cir::SyncScopeKind::System),
+      builder.getI64IntegerAttr(destAddr.getAlignment().getAsAlign().value()));
+
+  return returnBool ? op.getResult(1) : op.getResult(0);
+}
+
 static RValue emitBinaryAtomic(CIRGenFunction &cgf,
                                cir::AtomicFetchKind atomicOpkind,
                                const CallExpr *e) {
@@ -1818,11 +1849,13 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl 
&gd, unsigned builtinID,
   case Builtin::BI__sync_val_compare_and_swap_4:
   case Builtin::BI__sync_val_compare_and_swap_8:
   case Builtin::BI__sync_val_compare_and_swap_16:
+    return RValue::get(makeAtomicCmpXchgValue(*this, e, false));
   case Builtin::BI__sync_bool_compare_and_swap_1:
   case Builtin::BI__sync_bool_compare_and_swap_2:
   case Builtin::BI__sync_bool_compare_and_swap_4:
   case Builtin::BI__sync_bool_compare_and_swap_8:
   case Builtin::BI__sync_bool_compare_and_swap_16:
+    return RValue::get(makeAtomicCmpXchgValue(*this, e, true));
   case Builtin::BI__sync_swap_1:
   case Builtin::BI__sync_swap_2:
   case Builtin::BI__sync_swap_4:
diff --git a/clang/test/CIR/CodeGen/atomic.c b/clang/test/CIR/CodeGen/atomic.c
index 200ebc549ef2b..8b0191a49876f 100644
--- a/clang/test/CIR/CodeGen/atomic.c
+++ b/clang/test/CIR/CodeGen/atomic.c
@@ -5,6 +5,8 @@
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value 
-emit-llvm %s -o %t.ll
 // RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
 
+#include <stdbool.h>
+
 void f1(void) {
   _Atomic(int) x = 42;
 }
@@ -2951,3 +2953,94 @@ int atomic_load_and_store_dynamic_order(int *ptr, int 
order) {
   // OGCG:      [[CONTINUE_BLK]]:
   // OGCG-NEXT:   %{{.+}} = load i32, ptr %[[RES_SLOT]], align 4
 }
+
+void cmp_bool_int(int* p, int x, int u) {
+  // CIR-LABEL: @cmp_bool_int
+  // CIR: %[[PTR:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.ptr<!s32i>>, 
!cir.ptr<!s32i>
+  // CIR: %[[CMP:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!s32i>, !s32i
+  // CIR: %[[UPD:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!s32i>, !s32i
+  // CIR: %[[OLD:.*]], %[[RES:.*]] = cir.atomic.cmpxchg success(seq_cst) 
failure(seq_cst) syncscope(system) %[[PTR]], %[[CMP]], %[[UPD]] align(4) : 
(!cir.ptr<!s32i>, !s32i, !s32i) -> (!s32i, !cir.bool)
+  // CIR: cir.store{{.*}} %[[RES]], {{.*}} : !cir.bool, !cir.ptr<!cir.bool>
+
+  // LLVM-LABEL: @cmp_bool_int
+  // LLVM: %[[PTR:.*]] = load ptr
+  // LLVM: %[[CMP:.*]] = load i32
+  // LLVM: %[[UPD:.*]] = load i32
+  // LLVM: %[[RES:.*]] = cmpxchg ptr %[[PTR]], i32 %[[CMP]], i32 %[[UPD]] 
seq_cst seq_cst, align 4
+  // LLVM: %[[TMP:.*]] = extractvalue { i32, i1 } %[[RES]], 1
+  // LLVM: %[[EXT:.*]] = zext i1 %[[TMP]] to i8
+  // LLVM: store i8 %[[EXT]], ptr {{.*}}
+  bool r = __sync_bool_compare_and_swap(p, x, u);
+}
+
+void cmp_bool_long(long* p, long x, long u) {
+  // CIR-LABEL: @cmp_bool_long
+  // CIR: cir.atomic.cmpxchg success(seq_cst) failure(seq_cst) 
syncscope(system) {{.*}}, {{.*}}, {{.*}} align(8) : (!cir.ptr<!s64i>, !s64i, 
!s64i) -> (!s64i, !cir.bool)
+
+  // LLVM-LABEL: @cmp_bool_long
+  // LLVM: cmpxchg ptr {{.*}}, i64 {{.*}}, i64 {{.*}} seq_cst seq_cst, align 8
+  bool r = __sync_bool_compare_and_swap(p, x, u);
+}
+
+void cmp_bool_short(short* p, short x, short u) {
+  // CIR-LABEL: @cmp_bool_short
+  // CIR: cir.atomic.cmpxchg success(seq_cst) failure(seq_cst) 
syncscope(system) {{.*}}, {{.*}}, {{.*}} align(2) : (!cir.ptr<!s16i>, !s16i, 
!s16i) -> (!s16i, !cir.bool)
+
+  // LLVM-LABEL: @cmp_bool_short
+  // LLVM: cmpxchg ptr {{.*}}, i16 {{.*}}, i16 {{.*}} seq_cst seq_cst, align 2
+  bool r = __sync_bool_compare_and_swap(p, x, u);
+}
+
+void cmp_bool_byte(char* p, char x, char u) {
+  // CIR-LABEL: @cmp_bool_byte
+  // CIR: cir.atomic.cmpxchg success(seq_cst) failure(seq_cst) 
syncscope(system) {{.*}}, {{.*}}, {{.*}} align(1) : (!cir.ptr<!s8i>, !s8i, 
!s8i) -> (!s8i, !cir.bool)
+
+  // LLVM-LABEL: @cmp_bool_byte
+  // LLVM: cmpxchg ptr {{.*}}, i8 {{.*}}, i8 {{.*}} seq_cst seq_cst, align 1
+  bool r = __sync_bool_compare_and_swap(p, x, u);
+}
+
+void cmp_val_int(int* p, int x, int u) {
+  // CIR-LABEL: @cmp_val_int
+  // CIR: %[[PTR:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.ptr<!s32i>>, 
!cir.ptr<!s32i>
+  // CIR: %[[CMP:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!s32i>, !s32i
+  // CIR: %[[UPD:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!s32i>, !s32i
+  // CIR: %[[OLD:.*]], %[[RES:.*]] = cir.atomic.cmpxchg success(seq_cst) 
failure(seq_cst) syncscope(system) %[[PTR]], %[[CMP]], %[[UPD]] align(4) : 
(!cir.ptr<!s32i>, !s32i, !s32i) -> (!s32i, !cir.bool)
+  // CIR: cir.store{{.*}} %[[OLD]], {{.*}} : !s32i, !cir.ptr<!s32i>
+
+  // LLVM-LABEL: @cmp_val_int
+  // LLVM: %[[PTR:.*]] = load ptr
+  // LLVM: %[[CMP:.*]] = load i32
+  // LLVM: %[[UPD:.*]] = load i32
+  // LLVM: %[[RES:.*]] = cmpxchg ptr %[[PTR]], i32 %[[CMP]], i32 %[[UPD]] 
seq_cst seq_cst, align 4
+  // LLVM: %[[TMP:.*]] = extractvalue { i32, i1 } %[[RES]], 0
+  // LLVM: store i32 %[[TMP]], ptr {{.*}}
+  int r = __sync_val_compare_and_swap(p, x, u);
+}
+
+void cmp_val_long(long* p, long x, long u) {
+  // CIR-LABEL: @cmp_val_long
+  // CIR: cir.atomic.cmpxchg success(seq_cst) failure(seq_cst) 
syncscope(system) {{.*}}, {{.*}}, {{.*}} align(8) : (!cir.ptr<!s64i>, !s64i, 
!s64i) -> (!s64i, !cir.bool)
+
+  // LLVM-LABEL: @cmp_val_long
+  // LLVM: cmpxchg ptr {{.*}}, i64 {{.*}}, i64 {{.*}} seq_cst seq_cst, align 8
+  long r = __sync_val_compare_and_swap(p, x, u);
+}
+
+void cmp_val_short(short* p, short x, short u) {
+  // CIR-LABEL: @cmp_val_short
+  // CIR: cir.atomic.cmpxchg success(seq_cst) failure(seq_cst) 
syncscope(system) {{.*}}, {{.*}}, {{.*}} align(2) : (!cir.ptr<!s16i>, !s16i, 
!s16i) -> (!s16i, !cir.bool)
+
+  // LLVM-LABEL: @cmp_val_short
+  // LLVM: cmpxchg ptr {{.*}}, i16 {{.*}}, i16 {{.*}} seq_cst seq_cst, align 2
+  short r = __sync_val_compare_and_swap(p, x, u);
+}
+
+void cmp_val_byte(char* p, char x, char u) {
+  // CIR-LABEL: @cmp_val_byte
+  // CIR: cir.atomic.cmpxchg success(seq_cst) failure(seq_cst) 
syncscope(system) {{.*}}, {{.*}}, {{.*}} align(1) : (!cir.ptr<!s8i>, !s8i, 
!s8i) -> (!s8i, !cir.bool)
+
+  // LLVM-LABEL: @cmp_val_byte
+  // LLVM: cmpxchg ptr {{.*}}, i8 {{.*}}, i8 {{.*}} seq_cst seq_cst, align 1
+  char r = __sync_val_compare_and_swap(p, x, u);
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/186529
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to