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
