Index: llvm/lib/Target/RISCV/RISCV.td =================================================================== --- llvm/lib/Target/RISCV/RISCV.td +++ llvm/lib/Target/RISCV/RISCV.td @@ -481,6 +481,17 @@ "SiFive 7-Series processors", [TuneNoDefaultUnroll]>; +// Assume that lock-free native-width atomics are available, even if the target +// and operating system combination would not usually provide them. The user +// is responsible for providing any necessary __sync implementations. Code +// built with this feature is not ABI-compatible with code built without this +// feature, if atomic variables are exposed across the ABI boundary. +def FeatureForcedAtomics : SubtargetFeature< + "forced-atomics", "HasForcedAtomics", "true", + "Assume that lock-free native-width atomics are available">; +def HasAtomicLdSt + : Predicate<"Subtarget->hasStdExtA() || Subtarget->hasForcedAtomics()">; + //===----------------------------------------------------------------------===// // Named operands for CSR instructions. //===----------------------------------------------------------------------===// Index: llvm/lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -411,6 +411,8 @@ if (Subtarget.hasStdExtA()) { setMaxAtomicSizeInBitsSupported(Subtarget.getXLen()); setMinCmpXchgSizeInBits(32); + } else if (Subtarget.hasForcedAtomics()) { + setMaxAtomicSizeInBitsSupported(Subtarget.is64Bit() ? 64 : 32); } else { setMaxAtomicSizeInBitsSupported(0); } @@ -928,6 +930,16 @@ } } + if (Subtarget.hasForcedAtomics()) { + // Set atomic rmw/cas operations to expand to force __sync libcalls. + setOperationAction( + {ISD::ATOMIC_CMP_SWAP, ISD::ATOMIC_SWAP, ISD::ATOMIC_LOAD_ADD, + ISD::ATOMIC_LOAD_SUB, ISD::ATOMIC_LOAD_AND, ISD::ATOMIC_LOAD_OR, + ISD::ATOMIC_LOAD_XOR, ISD::ATOMIC_LOAD_NAND, ISD::ATOMIC_LOAD_MIN, + ISD::ATOMIC_LOAD_MAX, ISD::ATOMIC_LOAD_UMIN, ISD::ATOMIC_LOAD_UMAX}, + Subtarget.is64Bit() ? MVT::i64 : MVT::i32, Expand); + } + // Function alignments. const Align FunctionAlignment(Subtarget.hasStdExtC() ? 2 : 4); setMinFunctionAlignment(FunctionAlignment); @@ -12061,6 +12073,10 @@ TargetLowering::AtomicExpansionKind RISCVTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const { + // Don't expand forced atomics, we want to have __sync libcalls instead. + if (Subtarget.hasForcedAtomics()) + return AtomicExpansionKind::None; + // atomicrmw {fadd,fsub} must be expanded to use compare-exchange, as floating // point operations can't be used in an lr/sc sequence without breaking the // forward-progress guarantee. @@ -12170,6 +12186,10 @@ TargetLowering::AtomicExpansionKind RISCVTargetLowering::shouldExpandAtomicCmpXchgInIR( AtomicCmpXchgInst *CI) const { + // Don't expand forced atomics, we want to have __sync libcalls instead. + if (Subtarget.hasForcedAtomics()) + return AtomicExpansionKind::None; + unsigned Size = CI->getCompareOperand()->getType()->getPrimitiveSizeInBits(); if (Size == 8 || Size == 16) return AtomicExpansionKind::MaskedIntrinsic; Index: llvm/lib/Target/RISCV/RISCVInstrInfoA.td =================================================================== --- llvm/lib/Target/RISCV/RISCVInstrInfoA.td +++ llvm/lib/Target/RISCV/RISCVInstrInfoA.td @@ -105,20 +105,25 @@ // Pseudo-instructions and codegen patterns //===----------------------------------------------------------------------===// -let Predicates = [HasStdExtA] in { - -/// Atomic loads and stores - +// Atomic load/store are available under both +a and +force-atomics. // Fences will be inserted for atomic load/stores according to the logic in // RISCVTargetLowering::{emitLeadingFence,emitTrailingFence}. +let Predicates = [HasAtomicLdSt] in { + defm : LdPat; + defm : LdPat; + defm : LdPat; + + defm : AtomicStPat; + defm : AtomicStPat; + defm : AtomicStPat; +} -defm : LdPat; -defm : LdPat; -defm : LdPat; +let Predicates = [HasAtomicLdSt, IsRV64] in { + defm : LdPat; + defm : AtomicStPat; +} -defm : AtomicStPat; -defm : AtomicStPat; -defm : AtomicStPat; +let Predicates = [HasStdExtA] in { /// AMOs @@ -304,13 +309,6 @@ let Predicates = [HasStdExtA, IsRV64] in { -/// 64-bit atomic loads and stores - -// Fences will be inserted for atomic load/stores according to the logic in -// RISCVTargetLowering::{emitLeadingFence,emitTrailingFence}. -defm : LdPat; -defm : AtomicStPat; - defm : AMOPat<"atomic_swap_64", "AMOSWAP_D">; defm : AMOPat<"atomic_load_add_64", "AMOADD_D">; defm : AMOPat<"atomic_load_and_64", "AMOAND_D">; Index: llvm/lib/Target/RISCV/RISCVSubtarget.h =================================================================== --- llvm/lib/Target/RISCV/RISCVSubtarget.h +++ llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -98,6 +98,7 @@ bool EnableSaveRestore = false; bool EnableUnalignedScalarMem = false; bool HasLUIADDIFusion = false; + bool HasForcedAtomics = false; unsigned XLen = 32; unsigned ZvlLen = 0; MVT XLenVT = MVT::i32; @@ -194,6 +195,7 @@ bool enableSaveRestore() const { return EnableSaveRestore; } bool enableUnalignedScalarMem() const { return EnableUnalignedScalarMem; } bool hasLUIADDIFusion() const { return HasLUIADDIFusion; } + bool hasForcedAtomics() const { return HasForcedAtomics; } MVT getXLenVT() const { return XLenVT; } unsigned getXLen() const { return XLen; } unsigned getFLen() const { Index: llvm/test/CodeGen/RISCV/forced-atomics32.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/RISCV/forced-atomics32.ll @@ -0,0 +1,366 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 < %s | FileCheck %s --check-prefixes=CHECK,NO-ATOMIC +; RUN: llc -mtriple=riscv32 -mattr=+forced-atomics < %s | FileCheck %s --check-prefixes=CHECK,ATOMIC + +define i8 @load8(ptr %p) nounwind { +; NO-ATOMIC-LABEL: load8: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; NO-ATOMIC-NEXT: li a1, 5 +; NO-ATOMIC-NEXT: call __atomic_load_1@plt +; NO-ATOMIC-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: load8: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: fence rw, rw +; ATOMIC-NEXT: lb a0, 0(a0) +; ATOMIC-NEXT: fence r, rw +; ATOMIC-NEXT: ret + %v = load atomic i8, ptr %p seq_cst, align 1 + ret i8 %v +} + +define void @store8(ptr %p) nounwind { +; NO-ATOMIC-LABEL: store8: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; NO-ATOMIC-NEXT: li a2, 5 +; NO-ATOMIC-NEXT: li a1, 0 +; NO-ATOMIC-NEXT: call __atomic_store_1@plt +; NO-ATOMIC-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: store8: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: fence rw, w +; ATOMIC-NEXT: sb zero, 0(a0) +; ATOMIC-NEXT: ret + store atomic i8 0, ptr %p seq_cst, align 1 + ret void +} + +define i8 @rmw8(ptr %p) nounwind { +; NO-ATOMIC-LABEL: rmw8: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; NO-ATOMIC-NEXT: li a1, 1 +; NO-ATOMIC-NEXT: li a2, 5 +; NO-ATOMIC-NEXT: call __atomic_fetch_add_1@plt +; NO-ATOMIC-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: rmw8: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: addi sp, sp, -16 +; ATOMIC-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; ATOMIC-NEXT: li a1, 1 +; ATOMIC-NEXT: call __sync_fetch_and_add_1@plt +; ATOMIC-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; ATOMIC-NEXT: addi sp, sp, 16 +; ATOMIC-NEXT: ret + %v = atomicrmw add ptr %p, i8 1 seq_cst, align 1 + ret i8 %v +} + +define i8 @cmpxchg8(ptr %p) nounwind { +; NO-ATOMIC-LABEL: cmpxchg8: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; NO-ATOMIC-NEXT: sb zero, 11(sp) +; NO-ATOMIC-NEXT: addi a1, sp, 11 +; NO-ATOMIC-NEXT: li a2, 1 +; NO-ATOMIC-NEXT: li a3, 5 +; NO-ATOMIC-NEXT: li a4, 5 +; NO-ATOMIC-NEXT: call __atomic_compare_exchange_1@plt +; NO-ATOMIC-NEXT: lb a0, 11(sp) +; NO-ATOMIC-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: cmpxchg8: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: addi sp, sp, -16 +; ATOMIC-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; ATOMIC-NEXT: li a2, 1 +; ATOMIC-NEXT: li a1, 0 +; ATOMIC-NEXT: call __sync_val_compare_and_swap_1@plt +; ATOMIC-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; ATOMIC-NEXT: addi sp, sp, 16 +; ATOMIC-NEXT: ret + %res = cmpxchg ptr %p, i8 0, i8 1 seq_cst seq_cst + %res.0 = extractvalue { i8, i1 } %res, 0 + ret i8 %res.0 +} + +define i16 @load16(ptr %p) nounwind { +; NO-ATOMIC-LABEL: load16: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; NO-ATOMIC-NEXT: li a1, 5 +; NO-ATOMIC-NEXT: call __atomic_load_2@plt +; NO-ATOMIC-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: load16: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: fence rw, rw +; ATOMIC-NEXT: lh a0, 0(a0) +; ATOMIC-NEXT: fence r, rw +; ATOMIC-NEXT: ret + %v = load atomic i16, ptr %p seq_cst, align 2 + ret i16 %v +} + +define void @store16(ptr %p) nounwind { +; NO-ATOMIC-LABEL: store16: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; NO-ATOMIC-NEXT: li a2, 5 +; NO-ATOMIC-NEXT: li a1, 0 +; NO-ATOMIC-NEXT: call __atomic_store_2@plt +; NO-ATOMIC-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: store16: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: fence rw, w +; ATOMIC-NEXT: sh zero, 0(a0) +; ATOMIC-NEXT: ret + store atomic i16 0, ptr %p seq_cst, align 2 + ret void +} + +define i16 @rmw16(ptr %p) nounwind { +; NO-ATOMIC-LABEL: rmw16: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; NO-ATOMIC-NEXT: li a1, 1 +; NO-ATOMIC-NEXT: li a2, 5 +; NO-ATOMIC-NEXT: call __atomic_fetch_add_2@plt +; NO-ATOMIC-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: rmw16: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: addi sp, sp, -16 +; ATOMIC-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; ATOMIC-NEXT: li a1, 1 +; ATOMIC-NEXT: call __sync_fetch_and_add_2@plt +; ATOMIC-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; ATOMIC-NEXT: addi sp, sp, 16 +; ATOMIC-NEXT: ret + %v = atomicrmw add ptr %p, i16 1 seq_cst, align 2 + ret i16 %v +} + +define i16 @cmpxchg16(ptr %p) nounwind { +; NO-ATOMIC-LABEL: cmpxchg16: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; NO-ATOMIC-NEXT: sh zero, 10(sp) +; NO-ATOMIC-NEXT: addi a1, sp, 10 +; NO-ATOMIC-NEXT: li a2, 1 +; NO-ATOMIC-NEXT: li a3, 5 +; NO-ATOMIC-NEXT: li a4, 5 +; NO-ATOMIC-NEXT: call __atomic_compare_exchange_2@plt +; NO-ATOMIC-NEXT: lh a0, 10(sp) +; NO-ATOMIC-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: cmpxchg16: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: addi sp, sp, -16 +; ATOMIC-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; ATOMIC-NEXT: li a2, 1 +; ATOMIC-NEXT: li a1, 0 +; ATOMIC-NEXT: call __sync_val_compare_and_swap_2@plt +; ATOMIC-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; ATOMIC-NEXT: addi sp, sp, 16 +; ATOMIC-NEXT: ret + %res = cmpxchg ptr %p, i16 0, i16 1 seq_cst seq_cst + %res.0 = extractvalue { i16, i1 } %res, 0 + ret i16 %res.0 +} + +define i32 @load32(ptr %p) nounwind { +; NO-ATOMIC-LABEL: load32: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; NO-ATOMIC-NEXT: li a1, 5 +; NO-ATOMIC-NEXT: call __atomic_load_4@plt +; NO-ATOMIC-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: load32: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: fence rw, rw +; ATOMIC-NEXT: lw a0, 0(a0) +; ATOMIC-NEXT: fence r, rw +; ATOMIC-NEXT: ret + %v = load atomic i32, ptr %p seq_cst, align 4 + ret i32 %v +} + +define void @store32(ptr %p) nounwind { +; NO-ATOMIC-LABEL: store32: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; NO-ATOMIC-NEXT: li a2, 5 +; NO-ATOMIC-NEXT: li a1, 0 +; NO-ATOMIC-NEXT: call __atomic_store_4@plt +; NO-ATOMIC-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: store32: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: fence rw, w +; ATOMIC-NEXT: sw zero, 0(a0) +; ATOMIC-NEXT: ret + store atomic i32 0, ptr %p seq_cst, align 4 + ret void +} + +define i32 @rmw32(ptr %p) nounwind { +; NO-ATOMIC-LABEL: rmw32: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; NO-ATOMIC-NEXT: li a1, 1 +; NO-ATOMIC-NEXT: li a2, 5 +; NO-ATOMIC-NEXT: call __atomic_fetch_add_4@plt +; NO-ATOMIC-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: rmw32: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: addi sp, sp, -16 +; ATOMIC-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; ATOMIC-NEXT: li a1, 1 +; ATOMIC-NEXT: call __sync_fetch_and_add_4@plt +; ATOMIC-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; ATOMIC-NEXT: addi sp, sp, 16 +; ATOMIC-NEXT: ret + %v = atomicrmw add ptr %p, i32 1 seq_cst, align 4 + ret i32 %v +} + +define i32 @cmpxchg32(ptr %p) nounwind { +; NO-ATOMIC-LABEL: cmpxchg32: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; NO-ATOMIC-NEXT: sw zero, 8(sp) +; NO-ATOMIC-NEXT: addi a1, sp, 8 +; NO-ATOMIC-NEXT: li a2, 1 +; NO-ATOMIC-NEXT: li a3, 5 +; NO-ATOMIC-NEXT: li a4, 5 +; NO-ATOMIC-NEXT: call __atomic_compare_exchange_4@plt +; NO-ATOMIC-NEXT: lw a0, 8(sp) +; NO-ATOMIC-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: cmpxchg32: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: addi sp, sp, -16 +; ATOMIC-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; ATOMIC-NEXT: li a2, 1 +; ATOMIC-NEXT: li a1, 0 +; ATOMIC-NEXT: call __sync_val_compare_and_swap_4@plt +; ATOMIC-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; ATOMIC-NEXT: addi sp, sp, 16 +; ATOMIC-NEXT: ret + %res = cmpxchg ptr %p, i32 0, i32 1 seq_cst seq_cst + %res.0 = extractvalue { i32, i1 } %res, 0 + ret i32 %res.0 +} + +define i64 @load64(ptr %p) nounwind { +; CHECK-LABEL: load64: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; CHECK-NEXT: li a1, 5 +; CHECK-NEXT: call __atomic_load_8@plt +; CHECK-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %v = load atomic i64, ptr %p seq_cst, align 8 + ret i64 %v +} + +define void @store64(ptr %p) nounwind { +; CHECK-LABEL: store64: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; CHECK-NEXT: li a3, 5 +; CHECK-NEXT: li a1, 0 +; CHECK-NEXT: li a2, 0 +; CHECK-NEXT: call __atomic_store_8@plt +; CHECK-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + store atomic i64 0, ptr %p seq_cst, align 8 + ret void +} + +define i64 @rmw64(ptr %p) nounwind { +; CHECK-LABEL: rmw64: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; CHECK-NEXT: li a1, 1 +; CHECK-NEXT: li a3, 5 +; CHECK-NEXT: li a2, 0 +; CHECK-NEXT: call __atomic_fetch_add_8@plt +; CHECK-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %v = atomicrmw add ptr %p, i64 1 seq_cst, align 8 + ret i64 %v +} + +define i64 @cmpxchg64(ptr %p) nounwind { +; CHECK-LABEL: cmpxchg64: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; CHECK-NEXT: sw zero, 4(sp) +; CHECK-NEXT: sw zero, 0(sp) +; CHECK-NEXT: mv a1, sp +; CHECK-NEXT: li a2, 1 +; CHECK-NEXT: li a4, 5 +; CHECK-NEXT: li a5, 5 +; CHECK-NEXT: li a3, 0 +; CHECK-NEXT: call __atomic_compare_exchange_8@plt +; CHECK-NEXT: lw a1, 4(sp) +; CHECK-NEXT: lw a0, 0(sp) +; CHECK-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %res = cmpxchg ptr %p, i64 0, i64 1 seq_cst seq_cst + %res.0 = extractvalue { i64, i1 } %res, 0 + ret i64 %res.0 +} Index: llvm/test/CodeGen/RISCV/forced-atomics64.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/RISCV/forced-atomics64.ll @@ -0,0 +1,464 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv64 < %s | FileCheck %s --check-prefixes=CHECK,NO-ATOMIC +; RUN: llc -mtriple=riscv64 -mattr=+forced-atomics < %s | FileCheck %s --check-prefixes=CHECK,ATOMIC + +define i8 @load8(ptr %p) nounwind { +; NO-ATOMIC-LABEL: load8: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; NO-ATOMIC-NEXT: li a1, 5 +; NO-ATOMIC-NEXT: call __atomic_load_1@plt +; NO-ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: load8: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: fence rw, rw +; ATOMIC-NEXT: lb a0, 0(a0) +; ATOMIC-NEXT: fence r, rw +; ATOMIC-NEXT: ret + %v = load atomic i8, ptr %p seq_cst, align 1 + ret i8 %v +} + +define void @store8(ptr %p) nounwind { +; NO-ATOMIC-LABEL: store8: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; NO-ATOMIC-NEXT: li a2, 5 +; NO-ATOMIC-NEXT: li a1, 0 +; NO-ATOMIC-NEXT: call __atomic_store_1@plt +; NO-ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: store8: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: fence rw, w +; ATOMIC-NEXT: sb zero, 0(a0) +; ATOMIC-NEXT: ret + store atomic i8 0, ptr %p seq_cst, align 1 + ret void +} + +define i8 @rmw8(ptr %p) nounwind { +; NO-ATOMIC-LABEL: rmw8: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; NO-ATOMIC-NEXT: li a1, 1 +; NO-ATOMIC-NEXT: li a2, 5 +; NO-ATOMIC-NEXT: call __atomic_fetch_add_1@plt +; NO-ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: rmw8: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: addi sp, sp, -16 +; ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; ATOMIC-NEXT: li a1, 1 +; ATOMIC-NEXT: call __sync_fetch_and_add_1@plt +; ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; ATOMIC-NEXT: addi sp, sp, 16 +; ATOMIC-NEXT: ret + %v = atomicrmw add ptr %p, i8 1 seq_cst, align 1 + ret i8 %v +} + +define i8 @cmpxchg8(ptr %p) nounwind { +; NO-ATOMIC-LABEL: cmpxchg8: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; NO-ATOMIC-NEXT: sb zero, 7(sp) +; NO-ATOMIC-NEXT: addi a1, sp, 7 +; NO-ATOMIC-NEXT: li a2, 1 +; NO-ATOMIC-NEXT: li a3, 5 +; NO-ATOMIC-NEXT: li a4, 5 +; NO-ATOMIC-NEXT: call __atomic_compare_exchange_1@plt +; NO-ATOMIC-NEXT: lb a0, 7(sp) +; NO-ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: cmpxchg8: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: addi sp, sp, -16 +; ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; ATOMIC-NEXT: li a2, 1 +; ATOMIC-NEXT: li a1, 0 +; ATOMIC-NEXT: call __sync_val_compare_and_swap_1@plt +; ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; ATOMIC-NEXT: addi sp, sp, 16 +; ATOMIC-NEXT: ret + %res = cmpxchg ptr %p, i8 0, i8 1 seq_cst seq_cst + %res.0 = extractvalue { i8, i1 } %res, 0 + ret i8 %res.0 +} + +define i16 @load16(ptr %p) nounwind { +; NO-ATOMIC-LABEL: load16: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; NO-ATOMIC-NEXT: li a1, 5 +; NO-ATOMIC-NEXT: call __atomic_load_2@plt +; NO-ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: load16: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: fence rw, rw +; ATOMIC-NEXT: lh a0, 0(a0) +; ATOMIC-NEXT: fence r, rw +; ATOMIC-NEXT: ret + %v = load atomic i16, ptr %p seq_cst, align 2 + ret i16 %v +} + +define void @store16(ptr %p) nounwind { +; NO-ATOMIC-LABEL: store16: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; NO-ATOMIC-NEXT: li a2, 5 +; NO-ATOMIC-NEXT: li a1, 0 +; NO-ATOMIC-NEXT: call __atomic_store_2@plt +; NO-ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: store16: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: fence rw, w +; ATOMIC-NEXT: sh zero, 0(a0) +; ATOMIC-NEXT: ret + store atomic i16 0, ptr %p seq_cst, align 2 + ret void +} + +define i16 @rmw16(ptr %p) nounwind { +; NO-ATOMIC-LABEL: rmw16: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; NO-ATOMIC-NEXT: li a1, 1 +; NO-ATOMIC-NEXT: li a2, 5 +; NO-ATOMIC-NEXT: call __atomic_fetch_add_2@plt +; NO-ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: rmw16: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: addi sp, sp, -16 +; ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; ATOMIC-NEXT: li a1, 1 +; ATOMIC-NEXT: call __sync_fetch_and_add_2@plt +; ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; ATOMIC-NEXT: addi sp, sp, 16 +; ATOMIC-NEXT: ret + %v = atomicrmw add ptr %p, i16 1 seq_cst, align 2 + ret i16 %v +} + +define i16 @cmpxchg16(ptr %p) nounwind { +; NO-ATOMIC-LABEL: cmpxchg16: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; NO-ATOMIC-NEXT: sh zero, 6(sp) +; NO-ATOMIC-NEXT: addi a1, sp, 6 +; NO-ATOMIC-NEXT: li a2, 1 +; NO-ATOMIC-NEXT: li a3, 5 +; NO-ATOMIC-NEXT: li a4, 5 +; NO-ATOMIC-NEXT: call __atomic_compare_exchange_2@plt +; NO-ATOMIC-NEXT: lh a0, 6(sp) +; NO-ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: cmpxchg16: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: addi sp, sp, -16 +; ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; ATOMIC-NEXT: li a2, 1 +; ATOMIC-NEXT: li a1, 0 +; ATOMIC-NEXT: call __sync_val_compare_and_swap_2@plt +; ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; ATOMIC-NEXT: addi sp, sp, 16 +; ATOMIC-NEXT: ret + %res = cmpxchg ptr %p, i16 0, i16 1 seq_cst seq_cst + %res.0 = extractvalue { i16, i1 } %res, 0 + ret i16 %res.0 +} + +define i32 @load32(ptr %p) nounwind { +; NO-ATOMIC-LABEL: load32: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; NO-ATOMIC-NEXT: li a1, 5 +; NO-ATOMIC-NEXT: call __atomic_load_4@plt +; NO-ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: load32: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: fence rw, rw +; ATOMIC-NEXT: lw a0, 0(a0) +; ATOMIC-NEXT: fence r, rw +; ATOMIC-NEXT: ret + %v = load atomic i32, ptr %p seq_cst, align 4 + ret i32 %v +} + +define void @store32(ptr %p) nounwind { +; NO-ATOMIC-LABEL: store32: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; NO-ATOMIC-NEXT: li a2, 5 +; NO-ATOMIC-NEXT: li a1, 0 +; NO-ATOMIC-NEXT: call __atomic_store_4@plt +; NO-ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: store32: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: fence rw, w +; ATOMIC-NEXT: sw zero, 0(a0) +; ATOMIC-NEXT: ret + store atomic i32 0, ptr %p seq_cst, align 4 + ret void +} + +define i32 @rmw32(ptr %p) nounwind { +; NO-ATOMIC-LABEL: rmw32: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; NO-ATOMIC-NEXT: li a1, 1 +; NO-ATOMIC-NEXT: li a2, 5 +; NO-ATOMIC-NEXT: call __atomic_fetch_add_4@plt +; NO-ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: rmw32: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: addi sp, sp, -16 +; ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; ATOMIC-NEXT: li a1, 1 +; ATOMIC-NEXT: call __sync_fetch_and_add_4@plt +; ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; ATOMIC-NEXT: addi sp, sp, 16 +; ATOMIC-NEXT: ret + %v = atomicrmw add ptr %p, i32 1 seq_cst, align 4 + ret i32 %v +} + +define i32 @cmpxchg32(ptr %p) nounwind { +; NO-ATOMIC-LABEL: cmpxchg32: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; NO-ATOMIC-NEXT: sw zero, 4(sp) +; NO-ATOMIC-NEXT: addi a1, sp, 4 +; NO-ATOMIC-NEXT: li a2, 1 +; NO-ATOMIC-NEXT: li a3, 5 +; NO-ATOMIC-NEXT: li a4, 5 +; NO-ATOMIC-NEXT: call __atomic_compare_exchange_4@plt +; NO-ATOMIC-NEXT: lw a0, 4(sp) +; NO-ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: cmpxchg32: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: addi sp, sp, -16 +; ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; ATOMIC-NEXT: li a2, 1 +; ATOMIC-NEXT: li a1, 0 +; ATOMIC-NEXT: call __sync_val_compare_and_swap_4@plt +; ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; ATOMIC-NEXT: addi sp, sp, 16 +; ATOMIC-NEXT: ret + %res = cmpxchg ptr %p, i32 0, i32 1 seq_cst seq_cst + %res.0 = extractvalue { i32, i1 } %res, 0 + ret i32 %res.0 +} + +define i64 @load64(ptr %p) nounwind { +; NO-ATOMIC-LABEL: load64: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; NO-ATOMIC-NEXT: li a1, 5 +; NO-ATOMIC-NEXT: call __atomic_load_8@plt +; NO-ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: load64: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: fence rw, rw +; ATOMIC-NEXT: ld a0, 0(a0) +; ATOMIC-NEXT: fence r, rw +; ATOMIC-NEXT: ret + %v = load atomic i64, ptr %p seq_cst, align 8 + ret i64 %v +} + +define void @store64(ptr %p) nounwind { +; NO-ATOMIC-LABEL: store64: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; NO-ATOMIC-NEXT: li a2, 5 +; NO-ATOMIC-NEXT: li a1, 0 +; NO-ATOMIC-NEXT: call __atomic_store_8@plt +; NO-ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: store64: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: fence rw, w +; ATOMIC-NEXT: sd zero, 0(a0) +; ATOMIC-NEXT: ret + store atomic i64 0, ptr %p seq_cst, align 8 + ret void +} + +define i64 @rmw64(ptr %p) nounwind { +; NO-ATOMIC-LABEL: rmw64: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; NO-ATOMIC-NEXT: li a1, 1 +; NO-ATOMIC-NEXT: li a2, 5 +; NO-ATOMIC-NEXT: call __atomic_fetch_add_8@plt +; NO-ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: rmw64: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: addi sp, sp, -16 +; ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; ATOMIC-NEXT: li a1, 1 +; ATOMIC-NEXT: call __sync_fetch_and_add_8@plt +; ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; ATOMIC-NEXT: addi sp, sp, 16 +; ATOMIC-NEXT: ret + %v = atomicrmw add ptr %p, i64 1 seq_cst, align 8 + ret i64 %v +} + +define i64 @cmpxchg64(ptr %p) nounwind { +; NO-ATOMIC-LABEL: cmpxchg64: +; NO-ATOMIC: # %bb.0: +; NO-ATOMIC-NEXT: addi sp, sp, -16 +; NO-ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; NO-ATOMIC-NEXT: sd zero, 0(sp) +; NO-ATOMIC-NEXT: mv a1, sp +; NO-ATOMIC-NEXT: li a2, 1 +; NO-ATOMIC-NEXT: li a3, 5 +; NO-ATOMIC-NEXT: li a4, 5 +; NO-ATOMIC-NEXT: call __atomic_compare_exchange_8@plt +; NO-ATOMIC-NEXT: ld a0, 0(sp) +; NO-ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; NO-ATOMIC-NEXT: addi sp, sp, 16 +; NO-ATOMIC-NEXT: ret +; +; ATOMIC-LABEL: cmpxchg64: +; ATOMIC: # %bb.0: +; ATOMIC-NEXT: addi sp, sp, -16 +; ATOMIC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; ATOMIC-NEXT: li a2, 1 +; ATOMIC-NEXT: li a1, 0 +; ATOMIC-NEXT: call __sync_val_compare_and_swap_8@plt +; ATOMIC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; ATOMIC-NEXT: addi sp, sp, 16 +; ATOMIC-NEXT: ret + %res = cmpxchg ptr %p, i64 0, i64 1 seq_cst seq_cst + %res.0 = extractvalue { i64, i1 } %res, 0 + ret i64 %res.0 +} + +define i128 @load128(ptr %p) nounwind { +; CHECK-LABEL: load128: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: li a1, 5 +; CHECK-NEXT: call __atomic_load_16@plt +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %v = load atomic i128, ptr %p seq_cst, align 16 + ret i128 %v +} + +define void @store128(ptr %p) nounwind { +; CHECK-LABEL: store128: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: li a3, 5 +; CHECK-NEXT: li a1, 0 +; CHECK-NEXT: li a2, 0 +; CHECK-NEXT: call __atomic_store_16@plt +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + store atomic i128 0, ptr %p seq_cst, align 16 + ret void +} + +define i128 @rmw128(ptr %p) nounwind { +; CHECK-LABEL: rmw128: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: li a1, 1 +; CHECK-NEXT: li a3, 5 +; CHECK-NEXT: li a2, 0 +; CHECK-NEXT: call __atomic_fetch_add_16@plt +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %v = atomicrmw add ptr %p, i128 1 seq_cst, align 16 + ret i128 %v +} + +define i128 @cmpxchg128(ptr %p) nounwind { +; CHECK-LABEL: cmpxchg128: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -32 +; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; CHECK-NEXT: sd zero, 8(sp) +; CHECK-NEXT: sd zero, 0(sp) +; CHECK-NEXT: mv a1, sp +; CHECK-NEXT: li a2, 1 +; CHECK-NEXT: li a4, 5 +; CHECK-NEXT: li a5, 5 +; CHECK-NEXT: li a3, 0 +; CHECK-NEXT: call __atomic_compare_exchange_16@plt +; CHECK-NEXT: ld a1, 8(sp) +; CHECK-NEXT: ld a0, 0(sp) +; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 32 +; CHECK-NEXT: ret + %res = cmpxchg ptr %p, i128 0, i128 1 seq_cst seq_cst + %res.0 = extractvalue { i128, i1 } %res, 0 + ret i128 %res.0 +}