diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index ff2a6d626bca..298e44cb7435 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -5934,7 +5934,8 @@ def CIR_AtomicFetchKind : CIR_I32EnumAttr< I32EnumAttrCase<"Or", 4, "or">, I32EnumAttrCase<"Nand", 5, "nand">, I32EnumAttrCase<"Max", 6, "max">, - I32EnumAttrCase<"Min", 7, "min"> + I32EnumAttrCase<"Min", 7, "min">, + I32EnumAttrCase<"Xchg", 8, "xchg"> ]>; def CIR_AtomicFetch : CIR_Op<"atomic.fetch", [ diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 192f2233fcd8..964531b7806b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -2120,7 +2120,7 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__sync_lock_test_and_set_4: case Builtin::BI__sync_lock_test_and_set_8: case Builtin::BI__sync_lock_test_and_set_16: - llvm_unreachable("BI__sync_lock_test_and_set_1 like NYI"); + return emitBinaryAtomic(*this, cir::AtomicFetchKind::Xchg, E); case Builtin::BI__sync_lock_release_1: case Builtin::BI__sync_lock_release_2: diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 404e0f52b0f4..05ee049eb21c 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -3602,6 +3602,8 @@ mlir::LLVM::AtomicBinOp CIRToLLVMAtomicFetchLowering::getLLVMAtomicBinOp( return isSignedInt ? mlir::LLVM::AtomicBinOp::min : mlir::LLVM::AtomicBinOp::umin; } + case cir::AtomicFetchKind::Xchg: + return mlir::LLVM::AtomicBinOp::xchg; } llvm_unreachable("Unknown atomic fetch opcode"); } diff --git a/clang/test/CIR/CodeGen/atomic.cpp b/clang/test/CIR/CodeGen/atomic.cpp index d033d2a45e07..dee20e6dd388 100644 --- a/clang/test/CIR/CodeGen/atomic.cpp +++ b/clang/test/CIR/CodeGen/atomic.cpp @@ -1196,3 +1196,78 @@ void clear(void *p, volatile void *vp) { // LLVM: store atomic volatile i8 0, ptr %{{.+}} seq_cst, align 1 } + +// CHECK-LABEL: @_Z17lock_test_and_setPii +// CHECK: cir.atomic.fetch(xchg, {{.*}} : !cir.ptr, {{.*}} : !s32i, seq_cst) fetch_first : !s32i + +// LLVM-LABEL: @_Z17lock_test_and_setPii +// LLVM: atomicrmw xchg ptr {{.*}}, i32 {{.*}} seq_cst, align 4 +void lock_test_and_set(int* a, int b) { + int c = __sync_lock_test_and_set(a, b); +} + + +// CHECK-LABEL: @_Z17lock_test_and_setPll +// CHECK: cir.atomic.fetch(xchg, {{.*}} : !cir.ptr, {{.*}} : !s64i, seq_cst) fetch_first : !s64i + +// LLVM-LABEL: @_Z17lock_test_and_setPll +// LLVM: atomicrmw xchg ptr {{.*}}, i64 {{.*}} seq_cst, align 8 +void lock_test_and_set(long* a, long b) { + long c = __sync_lock_test_and_set(a, b); +} + +// CHECK-LABEL: @_Z17lock_test_and_setPss +// CHECK: cir.atomic.fetch(xchg, {{.*}} : !cir.ptr, {{.*}} : !s16i, seq_cst) fetch_first : !s16i + +// LLVM-LABEL: @_Z17lock_test_and_setPss +// LLVM: atomicrmw xchg ptr {{.*}}, i16 {{.*}} seq_cst, align 2 +void lock_test_and_set(short* a, short b) { + short c = __sync_lock_test_and_set(a, 2); +} + + +// CHECK-LABEL: @_Z17lock_test_and_setPcc +// CHECK: cir.atomic.fetch(xchg, {{.*}} : !cir.ptr, {{.*}} : !s8i, seq_cst) fetch_first : !s8i + +// LLVM-LABEL: @_Z17lock_test_and_setPcc +// LLVM: atomicrmw xchg ptr {{.*}}, i8 {{.*}} seq_cst, align 1 +void lock_test_and_set(char* a, char b) { + char c = __sync_lock_test_and_set(a, b); +} + +// CHECK-LABEL: @_Z17lock_test_and_setPji +// CHECK: cir.atomic.fetch(xchg, {{.*}} : !cir.ptr, {{.*}} : !u32i, seq_cst) fetch_first : !u32i + +// LLVM-LABEL: @_Z17lock_test_and_setPji +// LLVM: atomicrmw xchg ptr {{.*}}, i32 {{.*}} seq_cst, align 4 +void lock_test_and_set(unsigned int* a, int b) { + unsigned int c = __sync_lock_test_and_set(a, b); +} + + +// CHECK-LABEL: @_Z17lock_test_and_setPml +// CHECK: cir.atomic.fetch(xchg, {{.*}} : !cir.ptr, {{.*}} : !u64i, seq_cst) fetch_first : !u64i + +// LLVM-LABEL: @_Z17lock_test_and_setPml +// LLVM: atomicrmw xchg ptr {{.*}}, i64 {{.*}} seq_cst, align 8 +void lock_test_and_set(unsigned long* a, long b) { + unsigned long c = __sync_lock_test_and_set(a, b); +} + +// CHECK-LABEL: @_Z17lock_test_and_setPts +// CHECK: cir.atomic.fetch(xchg, {{.*}} : !cir.ptr, {{.*}} : !u16i, seq_cst) fetch_first : !u16i +// +// LLVM-LABEL: @_Z17lock_test_and_setPts +// LLVM: atomicrmw xchg ptr {{.*}}, i16 {{.*}} seq_cst, align 2 +void lock_test_and_set(unsigned short* a, short b) { + unsigned long long c = __sync_lock_test_and_set(a, b); +} + +// CHECK-LABEL: @_Z17lock_test_and_setPhc +// CHECK: cir.atomic.fetch(xchg, {{.*}} : !cir.ptr, {{.*}} : !u8i, seq_cst) fetch_first : !u8i + +// LLVM-LABEL: @_Z17lock_test_and_setPhc +// LLVM: atomicrmw xchg ptr {{.*}}, i8 {{.*}} seq_cst, align 1 +void lock_test_and_set(unsigned char* a, char b) { + unsigned char c = __sync_lock_test_and_set(a, b); +}