https://github.com/ayokunle321 updated https://github.com/llvm/llvm-project/pull/186026
>From 9295f50ff60f8160d00bd25d51053a7f1bc01199 Mon Sep 17 00:00:00 2001 From: Ayokunle Amodu <[email protected]> Date: Wed, 11 Mar 2026 20:39:35 -0600 Subject: [PATCH 1/5] add support for binary atomic ops --- clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 17 +- clang/test/CIR/CodeGen/atomic.c | 524 +++++++++++++++++++++++- 2 files changed, 538 insertions(+), 3 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 244979aac917e..d407ebc87aefc 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -116,7 +116,7 @@ static Address checkAtomicAlignment(CIRGenFunction &cgf, const CallExpr *e) { /// and the expression node. static mlir::Value makeBinaryAtomicValue( CIRGenFunction &cgf, cir::AtomicFetchKind kind, const CallExpr *expr, - mlir::Type *originalArgType, mlir::Value *emittedArgValue = nullptr, + mlir::Type *originalArgType = nullptr, mlir::Value *emittedArgValue = nullptr, cir::MemOrder ordering = cir::MemOrder::SequentiallyConsistent) { QualType type = expr->getType(); @@ -169,6 +169,11 @@ static mlir::Value makeBinaryAtomicValue( return rmwi->getResult(0); } +static RValue emitBinaryAtomic(CIRGenFunction &cgf, cir::AtomicFetchKind atomicOpkind, + const CallExpr *e) { + return RValue::get(makeBinaryAtomicValue(cgf, atomicOpkind, e)); +} + template <typename BinOp> static RValue emitBinaryAtomicPost(CIRGenFunction &cgf, cir::AtomicFetchKind atomicOpkind, @@ -1710,42 +1715,50 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, case Builtin::BI__sync_lock_test_and_set: case Builtin::BI__sync_lock_release: case Builtin::BI__sync_swap: + return errorBuiltinNYI(*this, e, builtinID); case Builtin::BI__sync_fetch_and_add_1: case Builtin::BI__sync_fetch_and_add_2: case Builtin::BI__sync_fetch_and_add_4: case Builtin::BI__sync_fetch_and_add_8: case Builtin::BI__sync_fetch_and_add_16: + return emitBinaryAtomic(*this, cir::AtomicFetchKind::Add, e); case Builtin::BI__sync_fetch_and_sub_1: case Builtin::BI__sync_fetch_and_sub_2: case Builtin::BI__sync_fetch_and_sub_4: case Builtin::BI__sync_fetch_and_sub_8: case Builtin::BI__sync_fetch_and_sub_16: + return emitBinaryAtomic(*this, cir::AtomicFetchKind::Sub, e); case Builtin::BI__sync_fetch_and_or_1: case Builtin::BI__sync_fetch_and_or_2: case Builtin::BI__sync_fetch_and_or_4: case Builtin::BI__sync_fetch_and_or_8: case Builtin::BI__sync_fetch_and_or_16: + return emitBinaryAtomic(*this, cir::AtomicFetchKind::Or, e); case Builtin::BI__sync_fetch_and_and_1: case Builtin::BI__sync_fetch_and_and_2: case Builtin::BI__sync_fetch_and_and_4: case Builtin::BI__sync_fetch_and_and_8: case Builtin::BI__sync_fetch_and_and_16: + return emitBinaryAtomic(*this, cir::AtomicFetchKind::And, e); case Builtin::BI__sync_fetch_and_xor_1: case Builtin::BI__sync_fetch_and_xor_2: case Builtin::BI__sync_fetch_and_xor_4: case Builtin::BI__sync_fetch_and_xor_8: case Builtin::BI__sync_fetch_and_xor_16: + return emitBinaryAtomic(*this, cir::AtomicFetchKind::Xor, e); case Builtin::BI__sync_fetch_and_nand_1: case Builtin::BI__sync_fetch_and_nand_2: case Builtin::BI__sync_fetch_and_nand_4: case Builtin::BI__sync_fetch_and_nand_8: case Builtin::BI__sync_fetch_and_nand_16: + return emitBinaryAtomic(*this, cir::AtomicFetchKind::Nand, e); + case Builtin::BI__sync_fetch_and_min: case Builtin::BI__sync_fetch_and_max: case Builtin::BI__sync_fetch_and_umin: case Builtin::BI__sync_fetch_and_umax: return errorBuiltinNYI(*this, e, builtinID); - return getUndefRValue(e->getType()); + case Builtin::BI__sync_add_and_fetch_1: case Builtin::BI__sync_add_and_fetch_2: case Builtin::BI__sync_add_and_fetch_4: diff --git a/clang/test/CIR/CodeGen/atomic.c b/clang/test/CIR/CodeGen/atomic.c index 9bce73f253a11..200ebc549ef2b 100644 --- a/clang/test/CIR/CodeGen/atomic.c +++ b/clang/test/CIR/CodeGen/atomic.c @@ -1416,8 +1416,528 @@ int c11_atomic_fetch_nand(_Atomic(int) *ptr, int value) { // OGCG: %[[RES:.+]] = atomicrmw nand ptr %{{.+}}, i32 %{{.+}} seq_cst, align 4 // OGCG-NEXT: store i32 %[[RES]], ptr %{{.+}}, align 4 } +void inc_int(int* a, int b) { + // CIR-LABEL: @inc_int + // CIR: %[[PTR:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i> + // CIR: %[[VAL:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!s32i>, !s32i + // CIR: %[[RES:.*]] = cir.atomic.fetch add seq_cst syncscope(system) fetch_first %[[PTR]], %[[VAL]] : (!cir.ptr<!s32i>, !s32i) -> !s32i + // CIR: cir.store {{.*}} %[[RES]], {{.*}} : !s32i, !cir.ptr<!s32i> + + // LLVM-LABEL: @inc_int + // LLVM: atomicrmw add ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + + // OGCG-LABEL: @inc_int + // OGCG: atomicrmw add ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + int c = __sync_fetch_and_add(a, b); +} + +void inc_long(long* a, long b) { + // CIR-LABEL: @inc_long + // CIR: cir.atomic.fetch add seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!s64i>, !s64i) -> !s64i + + // LLVM-LABEL: @inc_long + // LLVM: atomicrmw add ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + + // OGCG-LABEL: @inc_long + // OGCG: atomicrmw add ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + long c = __sync_fetch_and_add(a, 2); +} + +void inc_short(short* a, short b) { + // CIR-LABEL: @inc_short + // CIR: cir.atomic.fetch add seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!s16i>, !s16i) -> !s16i + + // LLVM-LABEL: @inc_short + // LLVM: atomicrmw add ptr {{.*}}, i16 {{.*}} seq_cst, align 2 + + // OGCG-LABEL: @inc_short + // OGCG: atomicrmw add ptr {{.*}}, i16 {{.*}} seq_cst, align 2 + short c = __sync_fetch_and_add(a, 2); +} + +void inc_byte(char* a, char b) { + // CIR-LABEL: @inc_byte + // CIR: cir.atomic.fetch add seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!s8i>, !s8i) -> !s8i + + // LLVM-LABEL: @inc_byte + // LLVM: atomicrmw add ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + + // OGCG-LABEL: @inc_byte + // OGCG: atomicrmw add ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + char c = __sync_fetch_and_add(a, b); +} + +void inc_uint(unsigned int* a, int b) { + // CIR-LABEL: @inc_uint + // CIR: cir.atomic.fetch add seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!u32i>, !u32i) -> !u32i + + // LLVM-LABEL: @inc_uint + // LLVM: atomicrmw add ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + + // OGCG-LABEL: @inc_uint + // OGCG: atomicrmw add ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + unsigned int c = __sync_fetch_and_add(a, b); +} + +void inc_ulong(unsigned long* a, long b) { + // CIR-LABEL: @inc_ulong + // CIR: cir.atomic.fetch add seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!u64i>, !u64i) -> !u64i + + // LLVM-LABEL: @inc_ulong + // LLVM: atomicrmw add ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + + // OGCG-LABEL: @inc_ulong + // OGCG: atomicrmw add ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + unsigned long c = __sync_fetch_and_add(a, b); +} + +void inc_uchar(unsigned char* a, char b) { + // CIR-LABEL: @inc_uchar + // CIR: cir.atomic.fetch add seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!u8i>, !u8i) -> !u8i + + // LLVM-LABEL: @inc_uchar + // LLVM: atomicrmw add ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + + // OGCG-LABEL: @inc_uchar + // OGCG: atomicrmw add ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + unsigned char c = __sync_fetch_and_add(a, b); +} + +void sub_int(int* a, int b) { + // CIR-LABEL: @sub_int + // CIR: %[[PTR:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i> + // CIR: %[[VAL:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!s32i>, !s32i + // CIR: %[[RES:.*]] = cir.atomic.fetch sub seq_cst syncscope(system) fetch_first %[[PTR]], %[[VAL]] : (!cir.ptr<!s32i>, !s32i) -> !s32i + // CIR: cir.store {{.*}} %[[RES]], {{.*}} : !s32i, !cir.ptr<!s32i> + + // LLVM-LABEL: @sub_int + // LLVM: atomicrmw sub ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + + // OGCG-LABEL: @sub_int + // OGCG: atomicrmw sub ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + int c = __sync_fetch_and_sub(a, b); +} + +void sub_long(long* a, long b) { + // CIR-LABEL: @sub_long + // CIR: cir.atomic.fetch sub seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!s64i>, !s64i) -> !s64i + + // LLVM-LABEL: @sub_long + // LLVM: atomicrmw sub ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + + // OGCG-LABEL: @sub_long + // OGCG: atomicrmw sub ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + long c = __sync_fetch_and_sub(a, 2); +} + +void sub_short(short* a, short b) { + // CIR-LABEL: @sub_short + // CIR: cir.atomic.fetch sub seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!s16i>, !s16i) -> !s16i + + // LLVM-LABEL: @sub_short + // LLVM: atomicrmw sub ptr {{.*}}, i16 {{.*}} seq_cst, align 2 + + // OGCG-LABEL: @sub_short + // OGCG: atomicrmw sub ptr {{.*}}, i16 {{.*}} seq_cst, align 2 + short c = __sync_fetch_and_sub(a, 2); +} + +void sub_byte(char* a, char b) { + // CIR-LABEL: @sub_byte + // CIR: cir.atomic.fetch sub seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!s8i>, !s8i) -> !s8i + + // LLVM-LABEL: @sub_byte + // LLVM: atomicrmw sub ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + + // OGCG-LABEL: @sub_byte + // OGCG: atomicrmw sub ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + char c = __sync_fetch_and_sub(a, b); +} + +void sub_uint(unsigned int* a, int b) { + // CIR-LABEL: @sub_uint + // CIR: cir.atomic.fetch sub seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!u32i>, !u32i) -> !u32i + + // LLVM-LABEL: @sub_uint + // LLVM: atomicrmw sub ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + + // OGCG-LABEL: @sub_uint + // OGCG: atomicrmw sub ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + unsigned int c = __sync_fetch_and_sub(a, b); +} + +void sub_ulong(unsigned long* a, long b) { + // CIR-LABEL: @sub_ulong + // CIR: cir.atomic.fetch sub seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!u64i>, !u64i) -> !u64i + + // LLVM-LABEL: @sub_ulong + // LLVM: atomicrmw sub ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + + // OGCG-LABEL: @sub_ulong + // OGCG: atomicrmw sub ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + unsigned long c = __sync_fetch_and_sub(a, b); +} + +void sub_uchar(unsigned char* a, char b) { + // CIR-LABEL: @sub_uchar + // CIR: cir.atomic.fetch sub seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!u8i>, !u8i) -> !u8i + + // LLVM-LABEL: @sub_uchar + // LLVM: atomicrmw sub ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + + // OGCG-LABEL: @sub_uchar + // OGCG: atomicrmw sub ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + unsigned char c = __sync_fetch_and_sub(a, b); +} + +void or_int(int* a, int b) { + // CIR-LABEL: or_int + // CIR: %[[PTR:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i> + // CIR: %[[VAL:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!s32i>, !s32i + // CIR: %[[RES:.*]] = cir.atomic.fetch or seq_cst syncscope(system) fetch_first %[[PTR]], %[[VAL]] : (!cir.ptr<!s32i>, !s32i) -> !s32i + // CIR: cir.store {{.*}} %[[RES]], {{.*}} : !s32i, !cir.ptr<!s32i> + + // LLVM-LABEL: or_int + // LLVM: atomicrmw or ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + + // OGCG-LABEL: or_int + // OGCG: atomicrmw or ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + int c = __sync_fetch_and_or(a, b); +} + +void or_long(long* a, long b) { + // CIR-LABEL: @or_long + // CIR: cir.atomic.fetch or seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!s64i>, !s64i) -> !s64i + + // LLVM-LABEL: @or_long + // LLVM: atomicrmw or ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + + // OGCG-LABEL: @or_long + // OGCG: atomicrmw or ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + long c = __sync_fetch_and_or(a, 2); +} + +void or_short(short* a, short b) { + // CIR-LABEL: @or_short + // CIR: cir.atomic.fetch or seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!s16i>, !s16i) -> !s16i + + // LLVM-LABEL: @or_short + // LLVM: atomicrmw or ptr {{.*}}, i16 {{.*}} seq_cst, align 2 + + // OGCG-LABEL: @or_short + // OGCG: atomicrmw or ptr {{.*}}, i16 {{.*}} seq_cst, align 2 + short c = __sync_fetch_and_or(a, 2); +} + +void or_byte(char* a, char b) { + // CIR-LABEL: @or_byte + // CIR: cir.atomic.fetch or seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!s8i>, !s8i) -> !s8i + + // LLVM-LABEL: @or_byte + // LLVM: atomicrmw or ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + + // OGCG-LABEL: @or_byte + // OGCG: atomicrmw or ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + char c = __sync_fetch_and_or(a, b); +} + +void or_uint(unsigned int* a, int b) { + // CIR-LABEL: @or_uint + // CIR: cir.atomic.fetch or seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!u32i>, !u32i) -> !u32i + + // LLVM-LABEL: @or_uint + // LLVM: atomicrmw or ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + + // OGCG-LABEL: @or_uint + // OGCG: atomicrmw or ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + unsigned int c = __sync_fetch_and_or(a, b); +} + +void or_ulong(unsigned long* a, long b) { + // CIR-LABEL: @or_ulong + // CIR: cir.atomic.fetch or seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!u64i>, !u64i) -> !u64i + + // LLVM-LABEL: @or_ulong + // LLVM: atomicrmw or ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + + // OGCG-LABEL: @or_ulong + // OGCG: atomicrmw or ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + unsigned long c = __sync_fetch_and_or(a, b); +} + +void or_uchar(unsigned char* a, char b) { + // CIR-LABEL: @or_uchar + // CIR: cir.atomic.fetch or seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!u8i>, !u8i) -> !u8i + + // LLVM-LABEL: @or_uchar + // LLVM: atomicrmw or ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + + // OGCG-LABEL: @or_uchar + // OGCG: atomicrmw or ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + unsigned char c = __sync_fetch_and_or(a, b); +} + +void xor_int(int* a, int b) { + // CIR-LABEL: xor_int + // CIR: %[[PTR:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i> + // CIR: %[[VAL:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!s32i>, !s32i + // CIR: %[[RES:.*]] = cir.atomic.fetch xor seq_cst syncscope(system) fetch_first %[[PTR]], %[[VAL]] : (!cir.ptr<!s32i>, !s32i) -> !s32i + // CIR: cir.store {{.*}} %[[RES]], {{.*}} : !s32i, !cir.ptr<!s32i> -// CHECK-LABEL: @test_op_and_fetch + // LLVM-LABEL: xor_int + // LLVM: atomicrmw xor ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + + // OGCG-LABEL: xor_int + // OGCG: atomicrmw xor ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + int c = __sync_fetch_and_xor(a, b); +} + +void xor_long(long* a, long b) { + // CIR-LABEL: @xor_long + // CIR: cir.atomic.fetch xor seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!s64i>, !s64i) -> !s64i + + // LLVM-LABEL: @xor_long + // LLVM: atomicrmw xor ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + + // OGCG-LABEL: @xor_long + // OGCG: atomicrmw xor ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + long c = __sync_fetch_and_xor(a, 2); +} + +void xor_short(short* a, short b) { + // CIR-LABEL: @xor_short + // CIR: cir.atomic.fetch xor seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!s16i>, !s16i) -> !s16i + + // LLVM-LABEL: @xor_short + // LLVM: atomicrmw xor ptr {{.*}}, i16 {{.*}} seq_cst, align 2 + + // OGCG-LABEL: @xor_short + // OGCG: atomicrmw xor ptr {{.*}}, i16 {{.*}} seq_cst, align 2 + short c = __sync_fetch_and_xor(a, 2); +} + +void xor_byte(char* a, char b) { + // CIR-LABEL: @xor_byte + // CIR: cir.atomic.fetch xor seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!s8i>, !s8i) -> !s8i + + // LLVM-LABEL: @xor_byte + // LLVM: atomicrmw xor ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + + // OGCG-LABEL: @xor_byte + // OGCG: atomicrmw xor ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + char c = __sync_fetch_and_xor(a, b); +} + +void xor_uint(unsigned int* a, int b) { + // CIR-LABEL: @xor_uint + // CIR: cir.atomic.fetch xor seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!u32i>, !u32i) -> !u32i + + // LLVM-LABEL: @xor_uint + // LLVM: atomicrmw xor ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + + // OGCG-LABEL: @xor_uint + // OGCG: atomicrmw xor ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + unsigned int c = __sync_fetch_and_xor(a, b); +} + +void xor_ulong(unsigned long* a, long b) { + // CIR-LABEL: @xor_ulong + // CIR: cir.atomic.fetch xor seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!u64i>, !u64i) -> !u64i + + // LLVM-LABEL: @xor_ulong + // LLVM: atomicrmw xor ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + + // OGCG-LABEL: @xor_ulong + // OGCG: atomicrmw xor ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + unsigned long c = __sync_fetch_and_xor(a, b); +} + +void xor_uchar(unsigned char* a, char b) { + // CIR-LABEL: @xor_uchar + // CIR: cir.atomic.fetch xor seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!u8i>, !u8i) -> !u8i + + // LLVM-LABEL: @xor_uchar + // LLVM: atomicrmw xor ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + + // OGCG-LABEL: @xor_uchar + // OGCG: atomicrmw xor ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + unsigned char c = __sync_fetch_and_xor(a, b); +} +void and_int(int* a, int b) { + // CIR-LABEL: and_int + // CIR: %[[PTR:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i> + // CIR: %[[VAL:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!s32i>, !s32i + // CIR: %[[RES:.*]] = cir.atomic.fetch and seq_cst syncscope(system) fetch_first %[[PTR]], %[[VAL]] : (!cir.ptr<!s32i>, !s32i) -> !s32i + // CIR: cir.store {{.*}} %[[RES]], {{.*}} : !s32i, !cir.ptr<!s32i> + + // LLVM-LABEL: and_int + // LLVM: atomicrmw and ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + + // OGCG-LABEL: and_int + // OGCG: atomicrmw and ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + int c = __sync_fetch_and_and(a, b); +} + +void and_long(long* a, long b) { + // CIR-LABEL: @and_long + // CIR: cir.atomic.fetch and seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!s64i>, !s64i) -> !s64i + + // LLVM-LABEL: @and_long + // LLVM: atomicrmw and ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + + // OGCG-LABEL: @and_long + // OGCG: atomicrmw and ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + long c = __sync_fetch_and_and(a, 2); +} + +void and_short(short* a, short b) { + // CIR-LABEL: @and_short + // CIR: cir.atomic.fetch and seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!s16i>, !s16i) -> !s16i + + // LLVM-LABEL: @and_short + // LLVM: atomicrmw and ptr {{.*}}, i16 {{.*}} seq_cst, align 2 + + // OGCG-LABEL: @and_short + // OGCG: atomicrmw and ptr {{.*}}, i16 {{.*}} seq_cst, align 2 + short c = __sync_fetch_and_and(a, 2); +} + +void and_byte(char* a, char b) { + // CIR-LABEL: @and_byte + // CIR: cir.atomic.fetch and seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!s8i>, !s8i) -> !s8i + + // LLVM-LABEL: @and_byte + // LLVM: atomicrmw and ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + + // OGCG-LABEL: @and_byte + // OGCG: atomicrmw and ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + char c = __sync_fetch_and_and(a, b); +} + +void and_uint(unsigned int* a, int b) { + // CIR-LABEL: @and_uint + // CIR: cir.atomic.fetch and seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!u32i>, !u32i) -> !u32i + + // LLVM-LABEL: @and_uint + // LLVM: atomicrmw and ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + + // OGCG-LABEL: @and_uint + // OGCG: atomicrmw and ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + unsigned int c = __sync_fetch_and_and(a, b); +} + +void and_ulong(unsigned long* a, long b) { + // CIR-LABEL: @and_ulong + // CIR: cir.atomic.fetch and seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!u64i>, !u64i) -> !u64i + + // LLVM-LABEL: @and_ulong + // LLVM: atomicrmw and ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + + // OGCG-LABEL: @and_ulong + // OGCG: atomicrmw and ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + unsigned long c = __sync_fetch_and_and(a, b); +} + +void and_uchar(unsigned char* a, char b) { + // CIR-LABEL: @and_uchar + // CIR: cir.atomic.fetch and seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!u8i>, !u8i) -> !u8i + + // LLVM-LABEL: @and_uchar + // LLVM: atomicrmw and ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + + // OGCG-LABEL: @and_uchar + // OGCG: atomicrmw and ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + unsigned char c = __sync_fetch_and_and(a, b); +} + +void nand_int(int* a, int b) { + // CIR-LABEL: nand_int + // CIR: %[[PTR:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i> + // CIR: %[[VAL:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!s32i>, !s32i + // CIR: %[[RES:.*]] = cir.atomic.fetch nand seq_cst syncscope(system) fetch_first %[[PTR]], %[[VAL]] : (!cir.ptr<!s32i>, !s32i) -> !s32i + // CIR: cir.store {{.*}} %[[RES]], {{.*}} : !s32i, !cir.ptr<!s32i> + + // LLVM-LABEL: nand_int + // LLVM: atomicrmw nand ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + + // OGCG-LABEL: nand_int + // OGCG: atomicrmw nand ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + int c = __sync_fetch_and_nand(a, b); +} + +void nand_long(long* a, long b) { + // CIR-LABEL: @nand_long + // CIR: cir.atomic.fetch nand seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!s64i>, !s64i) -> !s64i + + // LLVM-LABEL: @nand_long + // LLVM: atomicrmw nand ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + + // OGCG-LABEL: @nand_long + // OGCG: atomicrmw nand ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + long c = __sync_fetch_and_nand(a, 2); +} + +void nand_short(short* a, short b) { + // CIR-LABEL: @nand_short + // CIR: cir.atomic.fetch nand seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!s16i>, !s16i) -> !s16i + + // LLVM-LABEL: @nand_short + // LLVM: atomicrmw nand ptr {{.*}}, i16 {{.*}} seq_cst, align 2 + + // OGCG-LABEL: @nand_short + // OGCG: atomicrmw nand ptr {{.*}}, i16 {{.*}} seq_cst, align 2 + short c = __sync_fetch_and_nand(a, 2); +} + +void nand_byte(char* a, char b) { + // CIR-LABEL: @nand_byte + // CIR: cir.atomic.fetch nand seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!s8i>, !s8i) -> !s8i + + // LLVM-LABEL: @nand_byte + // LLVM: atomicrmw nand ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + + // OGCG-LABEL: @nand_byte + // OGCG: atomicrmw nand ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + char c = __sync_fetch_and_nand(a, b); +} + +void nand_uint(unsigned int* a, int b) { + // CIR-LABEL: @nand_uint + // CIR: cir.atomic.fetch nand seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!u32i>, !u32i) -> !u32i + + // LLVM-LABEL: @nand_uint + // LLVM: atomicrmw nand ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + + // OGCG-LABEL: @nand_uint + // OGCG: atomicrmw nand ptr {{.*}}, i32 {{.*}} seq_cst, align 4 + unsigned int c = __sync_fetch_and_nand(a, b); +} + +void nand_ulong(unsigned long* a, long b) { + // CIR-LABEL: @nand_ulong + // CIR: cir.atomic.fetch nand seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!u64i>, !u64i) -> !u64i + + // LLVM-LABEL: @nand_ulong + // LLVM: atomicrmw nand ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + + // OGCG-LABEL: @nand_ulong + // OGCG: atomicrmw nand ptr {{.*}}, i64 {{.*}} seq_cst, align 8 + unsigned long c = __sync_fetch_and_nand(a, b); +} + +void nand_uchar(unsigned char* a, char b) { + // CIR-LABEL: @nand_uchar + // CIR: cir.atomic.fetch nand seq_cst syncscope(system) fetch_first {{.*}}, {{.*}} : (!cir.ptr<!u8i>, !u8i) -> !u8i + + // LLVM-LABEL: @nand_uchar + // LLVM: atomicrmw nand ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + + // OGCG-LABEL: @nand_uchar + // OGCG: atomicrmw nand ptr {{.*}}, i8 {{.*}} seq_cst, align 1 + unsigned char c = __sync_fetch_and_nand(a, b); +} + +// CIR-LABEL: @test_op_and_fetch // LLVM-LABEL: @test_op_and_fetch void test_op_and_fetch() { int *ptr; @@ -2164,6 +2684,8 @@ void test_op_and_fetch() { ull = __sync_nand_and_fetch(&ull, uc); } + + int atomic_load_dynamic_order(int *ptr, int order) { // CIR-LABEL: atomic_load_dynamic_order // LLVM-LABEL: atomic_load_dynamic_order >From 08492c6f7b33571cd5af1fe7ada64644b2cf140e Mon Sep 17 00:00:00 2001 From: Ayokunle Amodu <[email protected]> Date: Wed, 11 Mar 2026 20:44:27 -0600 Subject: [PATCH 2/5] fix style --- clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index d407ebc87aefc..6c660552844e8 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -116,7 +116,8 @@ static Address checkAtomicAlignment(CIRGenFunction &cgf, const CallExpr *e) { /// and the expression node. static mlir::Value makeBinaryAtomicValue( CIRGenFunction &cgf, cir::AtomicFetchKind kind, const CallExpr *expr, - mlir::Type *originalArgType = nullptr, mlir::Value *emittedArgValue = nullptr, + mlir::Type *originalArgType = nullptr, + mlir::Value *emittedArgValue = nullptr, cir::MemOrder ordering = cir::MemOrder::SequentiallyConsistent) { QualType type = expr->getType(); @@ -169,7 +170,8 @@ static mlir::Value makeBinaryAtomicValue( return rmwi->getResult(0); } -static RValue emitBinaryAtomic(CIRGenFunction &cgf, cir::AtomicFetchKind atomicOpkind, +static RValue emitBinaryAtomic(CIRGenFunction &cgf, + cir::AtomicFetchKind atomicOpkind, const CallExpr *e) { return RValue::get(makeBinaryAtomicValue(cgf, atomicOpkind, e)); } @@ -1752,7 +1754,7 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, case Builtin::BI__sync_fetch_and_nand_8: case Builtin::BI__sync_fetch_and_nand_16: return emitBinaryAtomic(*this, cir::AtomicFetchKind::Nand, e); - + case Builtin::BI__sync_fetch_and_min: case Builtin::BI__sync_fetch_and_max: case Builtin::BI__sync_fetch_and_umin: >From 267af53414a9135afedf24099bb240c056390dd3 Mon Sep 17 00:00:00 2001 From: Ayokunle Amodu <[email protected]> Date: Wed, 11 Mar 2026 20:49:21 -0600 Subject: [PATCH 3/5] add rvalue return back --- clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 6c660552844e8..652f59c739e0f 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -1754,13 +1754,12 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, case Builtin::BI__sync_fetch_and_nand_8: case Builtin::BI__sync_fetch_and_nand_16: return emitBinaryAtomic(*this, cir::AtomicFetchKind::Nand, e); - case Builtin::BI__sync_fetch_and_min: case Builtin::BI__sync_fetch_and_max: case Builtin::BI__sync_fetch_and_umin: case Builtin::BI__sync_fetch_and_umax: return errorBuiltinNYI(*this, e, builtinID); - + return getUndefRValue(e->getType()); case Builtin::BI__sync_add_and_fetch_1: case Builtin::BI__sync_add_and_fetch_2: case Builtin::BI__sync_add_and_fetch_4: >From 7ae0b05ee5718791d50f3f889dd123aeb4283f93 Mon Sep 17 00:00:00 2001 From: Ayokunle Amodu <[email protected]> Date: Thu, 12 Mar 2026 19:04:36 -0600 Subject: [PATCH 4/5] add non-null assert for originalArgType --- clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 652f59c739e0f..621b1bbe20d10 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -160,7 +160,9 @@ static mlir::Value makeBinaryAtomicValue( // memory location and returns the old value. if (emittedArgValue) { *emittedArgValue = val; - *originalArgType = valueType; + assert(originalArgType != nullptr && + "originalArgType must be provided when emittedArgValue is set") + *originalArgType = valueType; } auto rmwi = cir::AtomicFetchOp::create( >From 5d852d8cb100ceb503bc29cfbcee876a2fa51566 Mon Sep 17 00:00:00 2001 From: Ayokunle Amodu <[email protected]> Date: Thu, 12 Mar 2026 19:05:51 -0600 Subject: [PATCH 5/5] add semi colon --- clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 621b1bbe20d10..1a33c3cd446a7 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -161,8 +161,8 @@ static mlir::Value makeBinaryAtomicValue( if (emittedArgValue) { *emittedArgValue = val; assert(originalArgType != nullptr && - "originalArgType must be provided when emittedArgValue is set") - *originalArgType = valueType; + "originalArgType must be provided when emittedArgValue is set"); + *originalArgType = valueType; } auto rmwi = cir::AtomicFetchOp::create( _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
