Index: lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- lib/Target/RISCV/RISCVISelLowering.cpp +++ lib/Target/RISCV/RISCVISelLowering.cpp @@ -142,6 +142,9 @@ setOperationAction(ISD::BlockAddress, XLenVT, Custom); setOperationAction(ISD::ConstantPool, XLenVT, Custom); + // Atomic operations aren't suported in the base RV32I ISA. + setMaxAtomicSizeInBitsSupported(0); + setBooleanContents(ZeroOrOneBooleanContent); // Function alignments (log2). Index: lib/Target/RISCV/RISCVInstrInfo.td =================================================================== --- lib/Target/RISCV/RISCVInstrInfo.td +++ lib/Target/RISCV/RISCVInstrInfo.td @@ -720,6 +720,21 @@ defm : StPat; defm : StPat; +/// Fences + +// Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set +// Manual: Volume I. + +// fence acquire -> fence r, rw +def : Pat<(atomic_fence (i32 4), (imm)), (FENCE 2, 3)>; +// fence release -> fence rw, w +def : Pat<(atomic_fence (i32 5), (imm)), (FENCE 3, 1)>; +// fence acq_rel -> fence rw, rw (a fence.tso instruction has been proposed +// but hasn't been added to the specification yet) +def : Pat<(atomic_fence (i32 6), (imm)), (FENCE 3, 3)>; +// fence seq_cst -> fence rw, rw +def : Pat<(atomic_fence (i32 7), (imm)), (FENCE 3, 3)>; + /// Other pseudo-instructions // Pessimistically assume the stack pointer will be clobbered Index: lib/Target/RISCV/RISCVTargetMachine.cpp =================================================================== --- lib/Target/RISCV/RISCVTargetMachine.cpp +++ lib/Target/RISCV/RISCVTargetMachine.cpp @@ -75,6 +75,7 @@ return getTM(); } + void addIRPasses() override; bool addInstSelector() override; void addPreEmitPass() override; }; @@ -84,6 +85,11 @@ return new RISCVPassConfig(*this, PM); } +void RISCVPassConfig::addIRPasses() { + addPass(createAtomicExpandPass()); + TargetPassConfig::addIRPasses(); +} + bool RISCVPassConfig::addInstSelector() { addPass(createRISCVISelDag(getRISCVTargetMachine())); Index: test/CodeGen/RISCV/atomic-cmpxchg.ll =================================================================== --- /dev/null +++ test/CodeGen/RISCV/atomic-cmpxchg.ll @@ -0,0 +1,720 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV32I %s + +define void @cmpxchg_i8_monotonic_monotonic(i8* %ptr, i8 %cmp, i8 %val) { +; RV32I-LABEL: cmpxchg_i8_monotonic_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sb a1, 11(sp) +; RV32I-NEXT: addi a1, sp, 11 +; RV32I-NEXT: mv a3, zero +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i8* %ptr, i8 %cmp, i8 %val monotonic monotonic + ret void +} + +define void @cmpxchg_i8_acquire_monotonic(i8* %ptr, i8 %cmp, i8 %val) { +; RV32I-LABEL: cmpxchg_i8_acquire_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sb a1, 11(sp) +; RV32I-NEXT: addi a1, sp, 11 +; RV32I-NEXT: addi a3, zero, 2 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i8* %ptr, i8 %cmp, i8 %val acquire monotonic + ret void +} + +define void @cmpxchg_i8_acquire_acquire(i8* %ptr, i8 %cmp, i8 %val) { +; RV32I-LABEL: cmpxchg_i8_acquire_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sb a1, 11(sp) +; RV32I-NEXT: addi a1, sp, 11 +; RV32I-NEXT: addi a3, zero, 2 +; RV32I-NEXT: mv a4, a3 +; RV32I-NEXT: call __atomic_compare_exchange_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i8* %ptr, i8 %cmp, i8 %val acquire acquire + ret void +} + +define void @cmpxchg_i8_release_monotonic(i8* %ptr, i8 %cmp, i8 %val) { +; RV32I-LABEL: cmpxchg_i8_release_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sb a1, 11(sp) +; RV32I-NEXT: addi a1, sp, 11 +; RV32I-NEXT: addi a3, zero, 3 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i8* %ptr, i8 %cmp, i8 %val release monotonic + ret void +} + +define void @cmpxchg_i8_release_acquire(i8* %ptr, i8 %cmp, i8 %val) { +; RV32I-LABEL: cmpxchg_i8_release_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sb a1, 11(sp) +; RV32I-NEXT: addi a1, sp, 11 +; RV32I-NEXT: addi a3, zero, 3 +; RV32I-NEXT: addi a4, zero, 2 +; RV32I-NEXT: call __atomic_compare_exchange_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i8* %ptr, i8 %cmp, i8 %val release acquire + ret void +} + +define void @cmpxchg_i8_acq_rel_monotonic(i8* %ptr, i8 %cmp, i8 %val) { +; RV32I-LABEL: cmpxchg_i8_acq_rel_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sb a1, 11(sp) +; RV32I-NEXT: addi a1, sp, 11 +; RV32I-NEXT: addi a3, zero, 4 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i8* %ptr, i8 %cmp, i8 %val acq_rel monotonic + ret void +} + +define void @cmpxchg_i8_acq_rel_acquire(i8* %ptr, i8 %cmp, i8 %val) { +; RV32I-LABEL: cmpxchg_i8_acq_rel_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sb a1, 11(sp) +; RV32I-NEXT: addi a1, sp, 11 +; RV32I-NEXT: addi a3, zero, 4 +; RV32I-NEXT: addi a4, zero, 2 +; RV32I-NEXT: call __atomic_compare_exchange_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i8* %ptr, i8 %cmp, i8 %val acq_rel acquire + ret void +} + +define void @cmpxchg_i8_seq_cst_monotonic(i8* %ptr, i8 %cmp, i8 %val) { +; RV32I-LABEL: cmpxchg_i8_seq_cst_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sb a1, 11(sp) +; RV32I-NEXT: addi a1, sp, 11 +; RV32I-NEXT: addi a3, zero, 5 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i8* %ptr, i8 %cmp, i8 %val seq_cst monotonic + ret void +} + +define void @cmpxchg_i8_seq_cst_acquire(i8* %ptr, i8 %cmp, i8 %val) { +; RV32I-LABEL: cmpxchg_i8_seq_cst_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sb a1, 11(sp) +; RV32I-NEXT: addi a1, sp, 11 +; RV32I-NEXT: addi a3, zero, 5 +; RV32I-NEXT: addi a4, zero, 2 +; RV32I-NEXT: call __atomic_compare_exchange_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i8* %ptr, i8 %cmp, i8 %val seq_cst acquire + ret void +} + +define void @cmpxchg_i8_seq_cst_seq_cst(i8* %ptr, i8 %cmp, i8 %val) { +; RV32I-LABEL: cmpxchg_i8_seq_cst_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sb a1, 11(sp) +; RV32I-NEXT: addi a1, sp, 11 +; RV32I-NEXT: addi a3, zero, 5 +; RV32I-NEXT: mv a4, a3 +; RV32I-NEXT: call __atomic_compare_exchange_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i8* %ptr, i8 %cmp, i8 %val seq_cst seq_cst + ret void +} + +define void @cmpxchg_i16_monotonic_monotonic(i16* %ptr, i16 %cmp, i16 %val) { +; RV32I-LABEL: cmpxchg_i16_monotonic_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sh a1, 10(sp) +; RV32I-NEXT: addi a1, sp, 10 +; RV32I-NEXT: mv a3, zero +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i16* %ptr, i16 %cmp, i16 %val monotonic monotonic + ret void +} + +define void @cmpxchg_i16_acquire_monotonic(i16* %ptr, i16 %cmp, i16 %val) { +; RV32I-LABEL: cmpxchg_i16_acquire_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sh a1, 10(sp) +; RV32I-NEXT: addi a1, sp, 10 +; RV32I-NEXT: addi a3, zero, 2 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i16* %ptr, i16 %cmp, i16 %val acquire monotonic + ret void +} + +define void @cmpxchg_i16_acquire_acquire(i16* %ptr, i16 %cmp, i16 %val) { +; RV32I-LABEL: cmpxchg_i16_acquire_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sh a1, 10(sp) +; RV32I-NEXT: addi a1, sp, 10 +; RV32I-NEXT: addi a3, zero, 2 +; RV32I-NEXT: mv a4, a3 +; RV32I-NEXT: call __atomic_compare_exchange_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i16* %ptr, i16 %cmp, i16 %val acquire acquire + ret void +} + +define void @cmpxchg_i16_release_monotonic(i16* %ptr, i16 %cmp, i16 %val) { +; RV32I-LABEL: cmpxchg_i16_release_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sh a1, 10(sp) +; RV32I-NEXT: addi a1, sp, 10 +; RV32I-NEXT: addi a3, zero, 3 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i16* %ptr, i16 %cmp, i16 %val release monotonic + ret void +} + +define void @cmpxchg_i16_release_acquire(i16* %ptr, i16 %cmp, i16 %val) { +; RV32I-LABEL: cmpxchg_i16_release_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sh a1, 10(sp) +; RV32I-NEXT: addi a1, sp, 10 +; RV32I-NEXT: addi a3, zero, 3 +; RV32I-NEXT: addi a4, zero, 2 +; RV32I-NEXT: call __atomic_compare_exchange_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i16* %ptr, i16 %cmp, i16 %val release acquire + ret void +} + +define void @cmpxchg_i16_acq_rel_monotonic(i16* %ptr, i16 %cmp, i16 %val) { +; RV32I-LABEL: cmpxchg_i16_acq_rel_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sh a1, 10(sp) +; RV32I-NEXT: addi a1, sp, 10 +; RV32I-NEXT: addi a3, zero, 4 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i16* %ptr, i16 %cmp, i16 %val acq_rel monotonic + ret void +} + +define void @cmpxchg_i16_acq_rel_acquire(i16* %ptr, i16 %cmp, i16 %val) { +; RV32I-LABEL: cmpxchg_i16_acq_rel_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sh a1, 10(sp) +; RV32I-NEXT: addi a1, sp, 10 +; RV32I-NEXT: addi a3, zero, 4 +; RV32I-NEXT: addi a4, zero, 2 +; RV32I-NEXT: call __atomic_compare_exchange_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i16* %ptr, i16 %cmp, i16 %val acq_rel acquire + ret void +} + +define void @cmpxchg_i16_seq_cst_monotonic(i16* %ptr, i16 %cmp, i16 %val) { +; RV32I-LABEL: cmpxchg_i16_seq_cst_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sh a1, 10(sp) +; RV32I-NEXT: addi a1, sp, 10 +; RV32I-NEXT: addi a3, zero, 5 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i16* %ptr, i16 %cmp, i16 %val seq_cst monotonic + ret void +} + +define void @cmpxchg_i16_seq_cst_acquire(i16* %ptr, i16 %cmp, i16 %val) { +; RV32I-LABEL: cmpxchg_i16_seq_cst_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sh a1, 10(sp) +; RV32I-NEXT: addi a1, sp, 10 +; RV32I-NEXT: addi a3, zero, 5 +; RV32I-NEXT: addi a4, zero, 2 +; RV32I-NEXT: call __atomic_compare_exchange_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i16* %ptr, i16 %cmp, i16 %val seq_cst acquire + ret void +} + +define void @cmpxchg_i16_seq_cst_seq_cst(i16* %ptr, i16 %cmp, i16 %val) { +; RV32I-LABEL: cmpxchg_i16_seq_cst_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sh a1, 10(sp) +; RV32I-NEXT: addi a1, sp, 10 +; RV32I-NEXT: addi a3, zero, 5 +; RV32I-NEXT: mv a4, a3 +; RV32I-NEXT: call __atomic_compare_exchange_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i16* %ptr, i16 %cmp, i16 %val seq_cst seq_cst + ret void +} + +define void @cmpxchg_i32_monotonic_monotonic(i32* %ptr, i32 %cmp, i32 %val) { +; RV32I-LABEL: cmpxchg_i32_monotonic_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw a1, 8(sp) +; RV32I-NEXT: addi a1, sp, 8 +; RV32I-NEXT: mv a3, zero +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i32* %ptr, i32 %cmp, i32 %val monotonic monotonic + ret void +} + +define void @cmpxchg_i32_acquire_monotonic(i32* %ptr, i32 %cmp, i32 %val) { +; RV32I-LABEL: cmpxchg_i32_acquire_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw a1, 8(sp) +; RV32I-NEXT: addi a1, sp, 8 +; RV32I-NEXT: addi a3, zero, 2 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i32* %ptr, i32 %cmp, i32 %val acquire monotonic + ret void +} + +define void @cmpxchg_i32_acquire_acquire(i32* %ptr, i32 %cmp, i32 %val) { +; RV32I-LABEL: cmpxchg_i32_acquire_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw a1, 8(sp) +; RV32I-NEXT: addi a1, sp, 8 +; RV32I-NEXT: addi a3, zero, 2 +; RV32I-NEXT: mv a4, a3 +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i32* %ptr, i32 %cmp, i32 %val acquire acquire + ret void +} + +define void @cmpxchg_i32_release_monotonic(i32* %ptr, i32 %cmp, i32 %val) { +; RV32I-LABEL: cmpxchg_i32_release_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw a1, 8(sp) +; RV32I-NEXT: addi a1, sp, 8 +; RV32I-NEXT: addi a3, zero, 3 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i32* %ptr, i32 %cmp, i32 %val release monotonic + ret void +} + +define void @cmpxchg_i32_release_acquire(i32* %ptr, i32 %cmp, i32 %val) { +; RV32I-LABEL: cmpxchg_i32_release_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw a1, 8(sp) +; RV32I-NEXT: addi a1, sp, 8 +; RV32I-NEXT: addi a3, zero, 3 +; RV32I-NEXT: addi a4, zero, 2 +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i32* %ptr, i32 %cmp, i32 %val release acquire + ret void +} + +define void @cmpxchg_i32_acq_rel_monotonic(i32* %ptr, i32 %cmp, i32 %val) { +; RV32I-LABEL: cmpxchg_i32_acq_rel_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw a1, 8(sp) +; RV32I-NEXT: addi a1, sp, 8 +; RV32I-NEXT: addi a3, zero, 4 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i32* %ptr, i32 %cmp, i32 %val acq_rel monotonic + ret void +} + +define void @cmpxchg_i32_acq_rel_acquire(i32* %ptr, i32 %cmp, i32 %val) { +; RV32I-LABEL: cmpxchg_i32_acq_rel_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw a1, 8(sp) +; RV32I-NEXT: addi a1, sp, 8 +; RV32I-NEXT: addi a3, zero, 4 +; RV32I-NEXT: addi a4, zero, 2 +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i32* %ptr, i32 %cmp, i32 %val acq_rel acquire + ret void +} + +define void @cmpxchg_i32_seq_cst_monotonic(i32* %ptr, i32 %cmp, i32 %val) { +; RV32I-LABEL: cmpxchg_i32_seq_cst_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw a1, 8(sp) +; RV32I-NEXT: addi a1, sp, 8 +; RV32I-NEXT: addi a3, zero, 5 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i32* %ptr, i32 %cmp, i32 %val seq_cst monotonic + ret void +} + +define void @cmpxchg_i32_seq_cst_acquire(i32* %ptr, i32 %cmp, i32 %val) { +; RV32I-LABEL: cmpxchg_i32_seq_cst_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw a1, 8(sp) +; RV32I-NEXT: addi a1, sp, 8 +; RV32I-NEXT: addi a3, zero, 5 +; RV32I-NEXT: addi a4, zero, 2 +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i32* %ptr, i32 %cmp, i32 %val seq_cst acquire + ret void +} + +define void @cmpxchg_i32_seq_cst_seq_cst(i32* %ptr, i32 %cmp, i32 %val) { +; RV32I-LABEL: cmpxchg_i32_seq_cst_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw a1, 8(sp) +; RV32I-NEXT: addi a1, sp, 8 +; RV32I-NEXT: addi a3, zero, 5 +; RV32I-NEXT: mv a4, a3 +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i32* %ptr, i32 %cmp, i32 %val seq_cst seq_cst + ret void +} + +define void @cmpxchg_i64_monotonic_monotonic(i64* %ptr, i64 %cmp, i64 %val) { +; RV32I-LABEL: cmpxchg_i64_monotonic_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw a2, 4(sp) +; RV32I-NEXT: sw a1, 0(sp) +; RV32I-NEXT: mv a1, sp +; RV32I-NEXT: mv a2, a3 +; RV32I-NEXT: mv a3, a4 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: mv a5, zero +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i64* %ptr, i64 %cmp, i64 %val monotonic monotonic + ret void +} + +define void @cmpxchg_i64_acquire_monotonic(i64* %ptr, i64 %cmp, i64 %val) { +; RV32I-LABEL: cmpxchg_i64_acquire_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw a2, 4(sp) +; RV32I-NEXT: sw a1, 0(sp) +; RV32I-NEXT: mv a1, sp +; RV32I-NEXT: addi a5, zero, 2 +; RV32I-NEXT: mv a2, a3 +; RV32I-NEXT: mv a3, a4 +; RV32I-NEXT: mv a4, a5 +; RV32I-NEXT: mv a5, zero +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i64* %ptr, i64 %cmp, i64 %val acquire monotonic + ret void +} + +define void @cmpxchg_i64_acquire_acquire(i64* %ptr, i64 %cmp, i64 %val) { +; RV32I-LABEL: cmpxchg_i64_acquire_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw a2, 4(sp) +; RV32I-NEXT: sw a1, 0(sp) +; RV32I-NEXT: mv a1, sp +; RV32I-NEXT: addi a5, zero, 2 +; RV32I-NEXT: mv a2, a3 +; RV32I-NEXT: mv a3, a4 +; RV32I-NEXT: mv a4, a5 +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i64* %ptr, i64 %cmp, i64 %val acquire acquire + ret void +} + +define void @cmpxchg_i64_release_monotonic(i64* %ptr, i64 %cmp, i64 %val) { +; RV32I-LABEL: cmpxchg_i64_release_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw a2, 4(sp) +; RV32I-NEXT: sw a1, 0(sp) +; RV32I-NEXT: mv a1, sp +; RV32I-NEXT: addi a5, zero, 3 +; RV32I-NEXT: mv a2, a3 +; RV32I-NEXT: mv a3, a4 +; RV32I-NEXT: mv a4, a5 +; RV32I-NEXT: mv a5, zero +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i64* %ptr, i64 %cmp, i64 %val release monotonic + ret void +} + +define void @cmpxchg_i64_release_acquire(i64* %ptr, i64 %cmp, i64 %val) { +; RV32I-LABEL: cmpxchg_i64_release_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw a2, 4(sp) +; RV32I-NEXT: sw a1, 0(sp) +; RV32I-NEXT: mv a1, sp +; RV32I-NEXT: addi a6, zero, 3 +; RV32I-NEXT: addi a5, zero, 2 +; RV32I-NEXT: mv a2, a3 +; RV32I-NEXT: mv a3, a4 +; RV32I-NEXT: mv a4, a6 +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i64* %ptr, i64 %cmp, i64 %val release acquire + ret void +} + +define void @cmpxchg_i64_acq_rel_monotonic(i64* %ptr, i64 %cmp, i64 %val) { +; RV32I-LABEL: cmpxchg_i64_acq_rel_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw a2, 4(sp) +; RV32I-NEXT: sw a1, 0(sp) +; RV32I-NEXT: mv a1, sp +; RV32I-NEXT: addi a5, zero, 4 +; RV32I-NEXT: mv a2, a3 +; RV32I-NEXT: mv a3, a4 +; RV32I-NEXT: mv a4, a5 +; RV32I-NEXT: mv a5, zero +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i64* %ptr, i64 %cmp, i64 %val acq_rel monotonic + ret void +} + +define void @cmpxchg_i64_acq_rel_acquire(i64* %ptr, i64 %cmp, i64 %val) { +; RV32I-LABEL: cmpxchg_i64_acq_rel_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw a2, 4(sp) +; RV32I-NEXT: sw a1, 0(sp) +; RV32I-NEXT: mv a1, sp +; RV32I-NEXT: addi a6, zero, 4 +; RV32I-NEXT: addi a5, zero, 2 +; RV32I-NEXT: mv a2, a3 +; RV32I-NEXT: mv a3, a4 +; RV32I-NEXT: mv a4, a6 +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i64* %ptr, i64 %cmp, i64 %val acq_rel acquire + ret void +} + +define void @cmpxchg_i64_seq_cst_monotonic(i64* %ptr, i64 %cmp, i64 %val) { +; RV32I-LABEL: cmpxchg_i64_seq_cst_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw a2, 4(sp) +; RV32I-NEXT: sw a1, 0(sp) +; RV32I-NEXT: mv a1, sp +; RV32I-NEXT: addi a5, zero, 5 +; RV32I-NEXT: mv a2, a3 +; RV32I-NEXT: mv a3, a4 +; RV32I-NEXT: mv a4, a5 +; RV32I-NEXT: mv a5, zero +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i64* %ptr, i64 %cmp, i64 %val seq_cst monotonic + ret void +} + +define void @cmpxchg_i64_seq_cst_acquire(i64* %ptr, i64 %cmp, i64 %val) { +; RV32I-LABEL: cmpxchg_i64_seq_cst_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw a2, 4(sp) +; RV32I-NEXT: sw a1, 0(sp) +; RV32I-NEXT: mv a1, sp +; RV32I-NEXT: addi a6, zero, 5 +; RV32I-NEXT: addi a5, zero, 2 +; RV32I-NEXT: mv a2, a3 +; RV32I-NEXT: mv a3, a4 +; RV32I-NEXT: mv a4, a6 +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i64* %ptr, i64 %cmp, i64 %val seq_cst acquire + ret void +} + +define void @cmpxchg_i64_seq_cst_seq_cst(i64* %ptr, i64 %cmp, i64 %val) { +; RV32I-LABEL: cmpxchg_i64_seq_cst_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw a2, 4(sp) +; RV32I-NEXT: sw a1, 0(sp) +; RV32I-NEXT: mv a1, sp +; RV32I-NEXT: addi a5, zero, 5 +; RV32I-NEXT: mv a2, a3 +; RV32I-NEXT: mv a3, a4 +; RV32I-NEXT: mv a4, a5 +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %res = cmpxchg i64* %ptr, i64 %cmp, i64 %val seq_cst seq_cst + ret void +} Index: test/CodeGen/RISCV/atomic-fence.ll =================================================================== --- /dev/null +++ test/CodeGen/RISCV/atomic-fence.ll @@ -0,0 +1,41 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV32I %s + +define void @fence_acquire() nounwind { +; RV32I-LABEL: fence_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: fence r, rw +; RV32I-NEXT: ret + fence acquire + ret void +} + +define void @fence_release() nounwind { +; RV32I-LABEL: fence_release: +; RV32I: # %bb.0: +; RV32I-NEXT: fence rw, w +; RV32I-NEXT: ret + fence release + ret void +} + +; A fence.tso instruction has been proposed for future inclusion, but for now +; just emit a stronger fence for fence acq_rel. +define void @fence_acq_rel() nounwind { +; RV32I-LABEL: fence_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: fence rw, rw +; RV32I-NEXT: ret + fence acq_rel + ret void +} + +define void @fence_seq_cst() nounwind { +; RV32I-LABEL: fence_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: fence rw, rw +; RV32I-NEXT: ret + fence seq_cst + ret void +} Index: test/CodeGen/RISCV/atomic-load-store.ll =================================================================== --- /dev/null +++ test/CodeGen/RISCV/atomic-load-store.ll @@ -0,0 +1,451 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV32I %s + +define i8 @atomic_load_i8_unordered(i8 *%a) nounwind { +; RV32I-LABEL: atomic_load_i8_unordered: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a1, zero +; RV32I-NEXT: call __atomic_load_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = load atomic i8, i8* %a unordered, align 1 + ret i8 %1 +} + +define i8 @atomic_load_i8_monotonic(i8 *%a) nounwind { +; RV32I-LABEL: atomic_load_i8_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a1, zero +; RV32I-NEXT: call __atomic_load_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = load atomic i8, i8* %a monotonic, align 1 + ret i8 %1 +} + +define i8 @atomic_load_i8_acquire(i8 *%a) nounwind { +; RV32I-LABEL: atomic_load_i8_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a1, zero, 2 +; RV32I-NEXT: call __atomic_load_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = load atomic i8, i8* %a acquire, align 1 + ret i8 %1 +} + +define i8 @atomic_load_i8_seq_cst(i8 *%a) nounwind { +; RV32I-LABEL: atomic_load_i8_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a1, zero, 5 +; RV32I-NEXT: call __atomic_load_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = load atomic i8, i8* %a seq_cst, align 1 + ret i8 %1 +} + +define i16 @atomic_load_i16_unordered(i16 *%a) nounwind { +; RV32I-LABEL: atomic_load_i16_unordered: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a1, zero +; RV32I-NEXT: call __atomic_load_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = load atomic i16, i16* %a unordered, align 2 + ret i16 %1 +} + +define i16 @atomic_load_i16_monotonic(i16 *%a) nounwind { +; RV32I-LABEL: atomic_load_i16_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a1, zero +; RV32I-NEXT: call __atomic_load_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = load atomic i16, i16* %a monotonic, align 2 + ret i16 %1 +} + +define i16 @atomic_load_i16_acquire(i16 *%a) nounwind { +; RV32I-LABEL: atomic_load_i16_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a1, zero, 2 +; RV32I-NEXT: call __atomic_load_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = load atomic i16, i16* %a acquire, align 2 + ret i16 %1 +} + +define i16 @atomic_load_i16_seq_cst(i16 *%a) nounwind { +; RV32I-LABEL: atomic_load_i16_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a1, zero, 5 +; RV32I-NEXT: call __atomic_load_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = load atomic i16, i16* %a seq_cst, align 2 + ret i16 %1 +} + +define i32 @atomic_load_i32_unordered(i32 *%a) nounwind { +; RV32I-LABEL: atomic_load_i32_unordered: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a1, zero +; RV32I-NEXT: call __atomic_load_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = load atomic i32, i32* %a unordered, align 4 + ret i32 %1 +} + +define i32 @atomic_load_i32_monotonic(i32 *%a) nounwind { +; RV32I-LABEL: atomic_load_i32_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a1, zero +; RV32I-NEXT: call __atomic_load_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = load atomic i32, i32* %a monotonic, align 4 + ret i32 %1 +} + +define i32 @atomic_load_i32_acquire(i32 *%a) nounwind { +; RV32I-LABEL: atomic_load_i32_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a1, zero, 2 +; RV32I-NEXT: call __atomic_load_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = load atomic i32, i32* %a acquire, align 4 + ret i32 %1 +} + +define i32 @atomic_load_i32_seq_cst(i32 *%a) nounwind { +; RV32I-LABEL: atomic_load_i32_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a1, zero, 5 +; RV32I-NEXT: call __atomic_load_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = load atomic i32, i32* %a seq_cst, align 4 + ret i32 %1 +} + +define i64 @atomic_load_i64_unordered(i64 *%a) nounwind { +; RV32I-LABEL: atomic_load_i64_unordered: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a1, zero +; RV32I-NEXT: call __atomic_load_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = load atomic i64, i64* %a unordered, align 8 + ret i64 %1 +} + +define i64 @atomic_load_i64_monotonic(i64 *%a) nounwind { +; RV32I-LABEL: atomic_load_i64_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a1, zero +; RV32I-NEXT: call __atomic_load_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = load atomic i64, i64* %a monotonic, align 8 + ret i64 %1 +} + +define i64 @atomic_load_i64_acquire(i64 *%a) nounwind { +; RV32I-LABEL: atomic_load_i64_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a1, zero, 2 +; RV32I-NEXT: call __atomic_load_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = load atomic i64, i64* %a acquire, align 8 + ret i64 %1 +} + +define i64 @atomic_load_i64_seq_cst(i64 *%a) nounwind { +; RV32I-LABEL: atomic_load_i64_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a1, zero, 5 +; RV32I-NEXT: call __atomic_load_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = load atomic i64, i64* %a seq_cst, align 8 + ret i64 %1 +} + +define void @atomic_store_i8_unordered(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomic_store_i8_unordered: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_store_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + store atomic i8 %b, i8* %a unordered, align 1 + ret void +} + +define void @atomic_store_i8_monotonic(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomic_store_i8_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_store_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + store atomic i8 %b, i8* %a monotonic, align 1 + ret void +} + +define void @atomic_store_i8_release(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomic_store_i8_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_store_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + store atomic i8 %b, i8* %a release, align 1 + ret void +} + +define void @atomic_store_i8_seq_cst(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomic_store_i8_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_store_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + store atomic i8 %b, i8* %a seq_cst, align 1 + ret void +} + +define void @atomic_store_i16_unordered(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomic_store_i16_unordered: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_store_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + store atomic i16 %b, i16* %a unordered, align 2 + ret void +} + +define void @atomic_store_i16_monotonic(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomic_store_i16_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_store_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + store atomic i16 %b, i16* %a monotonic, align 2 + ret void +} + +define void @atomic_store_i16_release(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomic_store_i16_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_store_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + store atomic i16 %b, i16* %a release, align 2 + ret void +} + +define void @atomic_store_i16_seq_cst(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomic_store_i16_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_store_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + store atomic i16 %b, i16* %a seq_cst, align 2 + ret void +} + +define void @atomic_store_i32_unordered(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomic_store_i32_unordered: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_store_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + store atomic i32 %b, i32* %a unordered, align 4 + ret void +} + +define void @atomic_store_i32_monotonic(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomic_store_i32_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_store_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + store atomic i32 %b, i32* %a monotonic, align 4 + ret void +} + +define void @atomic_store_i32_release(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomic_store_i32_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_store_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + store atomic i32 %b, i32* %a release, align 4 + ret void +} + +define void @atomic_store_i32_seq_cst(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomic_store_i32_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_store_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + store atomic i32 %b, i32* %a seq_cst, align 4 + ret void +} + +define void @atomic_store_i64_unordered(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomic_store_i64_unordered: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a3, zero +; RV32I-NEXT: call __atomic_store_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + store atomic i64 %b, i64* %a unordered, align 8 + ret void +} + +define void @atomic_store_i64_monotonic(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomic_store_i64_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a3, zero +; RV32I-NEXT: call __atomic_store_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + store atomic i64 %b, i64* %a monotonic, align 8 + ret void +} + +define void @atomic_store_i64_release(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomic_store_i64_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 3 +; RV32I-NEXT: call __atomic_store_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + store atomic i64 %b, i64* %a release, align 8 + ret void +} + +define void @atomic_store_i64_seq_cst(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomic_store_i64_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 5 +; RV32I-NEXT: call __atomic_store_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + store atomic i64 %b, i64* %a seq_cst, align 8 + ret void +} Index: test/CodeGen/RISCV/atomic-rmw.ll =================================================================== --- /dev/null +++ test/CodeGen/RISCV/atomic-rmw.ll @@ -0,0 +1,4139 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV32I %s + +define i8 @atomicrmw_xchg_i8_monotonic(i8* %a, i8 %b) { +; RV32I-LABEL: atomicrmw_xchg_i8_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_exchange_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xchg i8* %a, i8 %b monotonic + ret i8 %1 +} + +define i8 @atomicrmw_xchg_i8_acquire(i8* %a, i8 %b) { +; RV32I-LABEL: atomicrmw_xchg_i8_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_exchange_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xchg i8* %a, i8 %b acquire + ret i8 %1 +} + +define i8 @atomicrmw_xchg_i8_release(i8* %a, i8 %b) { +; RV32I-LABEL: atomicrmw_xchg_i8_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_exchange_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xchg i8* %a, i8 %b release + ret i8 %1 +} + +define i8 @atomicrmw_xchg_i8_acq_rel(i8* %a, i8 %b) { +; RV32I-LABEL: atomicrmw_xchg_i8_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_exchange_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xchg i8* %a, i8 %b acq_rel + ret i8 %1 +} + +define i8 @atomicrmw_xchg_i8_seq_cst(i8* %a, i8 %b) { +; RV32I-LABEL: atomicrmw_xchg_i8_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_exchange_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xchg i8* %a, i8 %b seq_cst + ret i8 %1 +} + +define i8 @atomicrmw_add_i8_monotonic(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomicrmw_add_i8_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_fetch_add_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw add i8* %a, i8 %b monotonic + ret i8 %1 +} + +define i8 @atomicrmw_add_i8_acquire(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomicrmw_add_i8_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_fetch_add_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw add i8* %a, i8 %b acquire + ret i8 %1 +} + +define i8 @atomicrmw_add_i8_release(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomicrmw_add_i8_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_fetch_add_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw add i8* %a, i8 %b release + ret i8 %1 +} + +define i8 @atomicrmw_add_i8_acq_rel(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomicrmw_add_i8_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_fetch_add_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw add i8* %a, i8 %b acq_rel + ret i8 %1 +} + +define i8 @atomicrmw_add_i8_seq_cst(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomicrmw_add_i8_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_fetch_add_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw add i8* %a, i8 %b seq_cst + ret i8 %1 +} + +define i8 @atomicrmw_sub_i8_monotonic(i8* %a, i8 %b) { +; RV32I-LABEL: atomicrmw_sub_i8_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_fetch_sub_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw sub i8* %a, i8 %b monotonic + ret i8 %1 +} + +define i8 @atomicrmw_sub_i8_acquire(i8* %a, i8 %b) { +; RV32I-LABEL: atomicrmw_sub_i8_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_fetch_sub_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw sub i8* %a, i8 %b acquire + ret i8 %1 +} + +define i8 @atomicrmw_sub_i8_release(i8* %a, i8 %b) { +; RV32I-LABEL: atomicrmw_sub_i8_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_fetch_sub_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw sub i8* %a, i8 %b release + ret i8 %1 +} + +define i8 @atomicrmw_sub_i8_acq_rel(i8* %a, i8 %b) { +; RV32I-LABEL: atomicrmw_sub_i8_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_fetch_sub_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw sub i8* %a, i8 %b acq_rel + ret i8 %1 +} + +define i8 @atomicrmw_sub_i8_seq_cst(i8* %a, i8 %b) { +; RV32I-LABEL: atomicrmw_sub_i8_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_fetch_sub_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw sub i8* %a, i8 %b seq_cst + ret i8 %1 +} + +define i8 @atomicrmw_and_i8_monotonic(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomicrmw_and_i8_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_fetch_and_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw and i8* %a, i8 %b monotonic + ret i8 %1 +} + +define i8 @atomicrmw_and_i8_acquire(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomicrmw_and_i8_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_fetch_and_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw and i8* %a, i8 %b acquire + ret i8 %1 +} + +define i8 @atomicrmw_and_i8_release(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomicrmw_and_i8_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_fetch_and_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw and i8* %a, i8 %b release + ret i8 %1 +} + +define i8 @atomicrmw_and_i8_acq_rel(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomicrmw_and_i8_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_fetch_and_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw and i8* %a, i8 %b acq_rel + ret i8 %1 +} + +define i8 @atomicrmw_and_i8_seq_cst(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomicrmw_and_i8_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_fetch_and_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw and i8* %a, i8 %b seq_cst + ret i8 %1 +} + +define i8 @atomicrmw_nand_i8_monotonic(i8* %a, i8 %b) { +; RV32I-LABEL: atomicrmw_nand_i8_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_fetch_nand_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw nand i8* %a, i8 %b monotonic + ret i8 %1 +} + +define i8 @atomicrmw_nand_i8_acquire(i8* %a, i8 %b) { +; RV32I-LABEL: atomicrmw_nand_i8_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_fetch_nand_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw nand i8* %a, i8 %b acquire + ret i8 %1 +} + +define i8 @atomicrmw_nand_i8_release(i8* %a, i8 %b) { +; RV32I-LABEL: atomicrmw_nand_i8_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_fetch_nand_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw nand i8* %a, i8 %b release + ret i8 %1 +} + +define i8 @atomicrmw_nand_i8_acq_rel(i8* %a, i8 %b) { +; RV32I-LABEL: atomicrmw_nand_i8_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_fetch_nand_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw nand i8* %a, i8 %b acq_rel + ret i8 %1 +} + +define i8 @atomicrmw_nand_i8_seq_cst(i8* %a, i8 %b) { +; RV32I-LABEL: atomicrmw_nand_i8_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_fetch_nand_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw nand i8* %a, i8 %b seq_cst + ret i8 %1 +} + +define i8 @atomicrmw_or_i8_monotonic(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomicrmw_or_i8_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_fetch_or_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw or i8* %a, i8 %b monotonic + ret i8 %1 +} + +define i8 @atomicrmw_or_i8_acquire(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomicrmw_or_i8_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_fetch_or_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw or i8* %a, i8 %b acquire + ret i8 %1 +} + +define i8 @atomicrmw_or_i8_release(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomicrmw_or_i8_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_fetch_or_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw or i8* %a, i8 %b release + ret i8 %1 +} + +define i8 @atomicrmw_or_i8_acq_rel(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomicrmw_or_i8_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_fetch_or_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw or i8* %a, i8 %b acq_rel + ret i8 %1 +} + +define i8 @atomicrmw_or_i8_seq_cst(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomicrmw_or_i8_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_fetch_or_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw or i8* %a, i8 %b seq_cst + ret i8 %1 +} + +define i8 @atomicrmw_xor_i8_monotonic(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomicrmw_xor_i8_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_fetch_xor_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xor i8* %a, i8 %b monotonic + ret i8 %1 +} + +define i8 @atomicrmw_xor_i8_acquire(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomicrmw_xor_i8_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_fetch_xor_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xor i8* %a, i8 %b acquire + ret i8 %1 +} + +define i8 @atomicrmw_xor_i8_release(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomicrmw_xor_i8_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_fetch_xor_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xor i8* %a, i8 %b release + ret i8 %1 +} + +define i8 @atomicrmw_xor_i8_acq_rel(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomicrmw_xor_i8_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_fetch_xor_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xor i8* %a, i8 %b acq_rel + ret i8 %1 +} + +define i8 @atomicrmw_xor_i8_seq_cst(i8 *%a, i8 %b) nounwind { +; RV32I-LABEL: atomicrmw_xor_i8_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_fetch_xor_1 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xor i8* %a, i8 %b seq_cst + ret i8 %1 +} + +; Don't test for i8 atomicrmw {min,max,umin,umax} as Clang won't generate it +; and we don't currently intend to support these with RV32A. + +define i16 @atomicrmw_xchg_i16_monotonic(i16* %a, i16 %b) { +; RV32I-LABEL: atomicrmw_xchg_i16_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_exchange_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xchg i16* %a, i16 %b monotonic + ret i16 %1 +} + +define i16 @atomicrmw_xchg_i16_acquire(i16* %a, i16 %b) { +; RV32I-LABEL: atomicrmw_xchg_i16_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_exchange_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xchg i16* %a, i16 %b acquire + ret i16 %1 +} + +define i16 @atomicrmw_xchg_i16_release(i16* %a, i16 %b) { +; RV32I-LABEL: atomicrmw_xchg_i16_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_exchange_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xchg i16* %a, i16 %b release + ret i16 %1 +} + +define i16 @atomicrmw_xchg_i16_acq_rel(i16* %a, i16 %b) { +; RV32I-LABEL: atomicrmw_xchg_i16_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_exchange_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xchg i16* %a, i16 %b acq_rel + ret i16 %1 +} + +define i16 @atomicrmw_xchg_i16_seq_cst(i16* %a, i16 %b) { +; RV32I-LABEL: atomicrmw_xchg_i16_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_exchange_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xchg i16* %a, i16 %b seq_cst + ret i16 %1 +} + +define i16 @atomicrmw_add_i16_monotonic(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomicrmw_add_i16_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_fetch_add_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw add i16* %a, i16 %b monotonic + ret i16 %1 +} + +define i16 @atomicrmw_add_i16_acquire(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomicrmw_add_i16_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_fetch_add_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw add i16* %a, i16 %b acquire + ret i16 %1 +} + +define i16 @atomicrmw_add_i16_release(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomicrmw_add_i16_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_fetch_add_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw add i16* %a, i16 %b release + ret i16 %1 +} + +define i16 @atomicrmw_add_i16_acq_rel(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomicrmw_add_i16_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_fetch_add_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw add i16* %a, i16 %b acq_rel + ret i16 %1 +} + +define i16 @atomicrmw_add_i16_seq_cst(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomicrmw_add_i16_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_fetch_add_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw add i16* %a, i16 %b seq_cst + ret i16 %1 +} + +define i16 @atomicrmw_sub_i16_monotonic(i16* %a, i16 %b) { +; RV32I-LABEL: atomicrmw_sub_i16_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_fetch_sub_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw sub i16* %a, i16 %b monotonic + ret i16 %1 +} + +define i16 @atomicrmw_sub_i16_acquire(i16* %a, i16 %b) { +; RV32I-LABEL: atomicrmw_sub_i16_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_fetch_sub_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw sub i16* %a, i16 %b acquire + ret i16 %1 +} + +define i16 @atomicrmw_sub_i16_release(i16* %a, i16 %b) { +; RV32I-LABEL: atomicrmw_sub_i16_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_fetch_sub_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw sub i16* %a, i16 %b release + ret i16 %1 +} + +define i16 @atomicrmw_sub_i16_acq_rel(i16* %a, i16 %b) { +; RV32I-LABEL: atomicrmw_sub_i16_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_fetch_sub_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw sub i16* %a, i16 %b acq_rel + ret i16 %1 +} + +define i16 @atomicrmw_sub_i16_seq_cst(i16* %a, i16 %b) { +; RV32I-LABEL: atomicrmw_sub_i16_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_fetch_sub_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw sub i16* %a, i16 %b seq_cst + ret i16 %1 +} + +define i16 @atomicrmw_and_i16_monotonic(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomicrmw_and_i16_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_fetch_and_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw and i16* %a, i16 %b monotonic + ret i16 %1 +} + +define i16 @atomicrmw_and_i16_acquire(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomicrmw_and_i16_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_fetch_and_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw and i16* %a, i16 %b acquire + ret i16 %1 +} + +define i16 @atomicrmw_and_i16_release(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomicrmw_and_i16_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_fetch_and_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw and i16* %a, i16 %b release + ret i16 %1 +} + +define i16 @atomicrmw_and_i16_acq_rel(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomicrmw_and_i16_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_fetch_and_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw and i16* %a, i16 %b acq_rel + ret i16 %1 +} + +define i16 @atomicrmw_and_i16_seq_cst(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomicrmw_and_i16_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_fetch_and_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw and i16* %a, i16 %b seq_cst + ret i16 %1 +} + +define i16 @atomicrmw_nand_i16_monotonic(i16* %a, i16 %b) { +; RV32I-LABEL: atomicrmw_nand_i16_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_fetch_nand_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw nand i16* %a, i16 %b monotonic + ret i16 %1 +} + +define i16 @atomicrmw_nand_i16_acquire(i16* %a, i16 %b) { +; RV32I-LABEL: atomicrmw_nand_i16_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_fetch_nand_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw nand i16* %a, i16 %b acquire + ret i16 %1 +} + +define i16 @atomicrmw_nand_i16_release(i16* %a, i16 %b) { +; RV32I-LABEL: atomicrmw_nand_i16_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_fetch_nand_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw nand i16* %a, i16 %b release + ret i16 %1 +} + +define i16 @atomicrmw_nand_i16_acq_rel(i16* %a, i16 %b) { +; RV32I-LABEL: atomicrmw_nand_i16_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_fetch_nand_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw nand i16* %a, i16 %b acq_rel + ret i16 %1 +} + +define i16 @atomicrmw_nand_i16_seq_cst(i16* %a, i16 %b) { +; RV32I-LABEL: atomicrmw_nand_i16_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_fetch_nand_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw nand i16* %a, i16 %b seq_cst + ret i16 %1 +} + +define i16 @atomicrmw_or_i16_monotonic(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomicrmw_or_i16_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_fetch_or_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw or i16* %a, i16 %b monotonic + ret i16 %1 +} + +define i16 @atomicrmw_or_i16_acquire(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomicrmw_or_i16_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_fetch_or_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw or i16* %a, i16 %b acquire + ret i16 %1 +} + +define i16 @atomicrmw_or_i16_release(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomicrmw_or_i16_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_fetch_or_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw or i16* %a, i16 %b release + ret i16 %1 +} + +define i16 @atomicrmw_or_i16_acq_rel(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomicrmw_or_i16_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_fetch_or_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw or i16* %a, i16 %b acq_rel + ret i16 %1 +} + +define i16 @atomicrmw_or_i16_seq_cst(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomicrmw_or_i16_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_fetch_or_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw or i16* %a, i16 %b seq_cst + ret i16 %1 +} + +define i16 @atomicrmw_xor_i16_monotonic(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomicrmw_xor_i16_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_fetch_xor_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xor i16* %a, i16 %b monotonic + ret i16 %1 +} + +define i16 @atomicrmw_xor_i16_acquire(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomicrmw_xor_i16_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_fetch_xor_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xor i16* %a, i16 %b acquire + ret i16 %1 +} + +define i16 @atomicrmw_xor_i16_release(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomicrmw_xor_i16_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_fetch_xor_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xor i16* %a, i16 %b release + ret i16 %1 +} + +define i16 @atomicrmw_xor_i16_acq_rel(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomicrmw_xor_i16_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_fetch_xor_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xor i16* %a, i16 %b acq_rel + ret i16 %1 +} + +define i16 @atomicrmw_xor_i16_seq_cst(i16 *%a, i16 %b) nounwind { +; RV32I-LABEL: atomicrmw_xor_i16_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_fetch_xor_2 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xor i16* %a, i16 %b seq_cst + ret i16 %1 +} + +; Don't test for i16 atomicrmw {min,max,umin,umax} as Clang won't generate it +; and we don't currently intend to support these with RV32A. + +define i32 @atomicrmw_xchg_i32_monotonic(i32* %a, i32 %b) { +; RV32I-LABEL: atomicrmw_xchg_i32_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_exchange_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xchg i32* %a, i32 %b monotonic + ret i32 %1 +} + +define i32 @atomicrmw_xchg_i32_acquire(i32* %a, i32 %b) { +; RV32I-LABEL: atomicrmw_xchg_i32_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_exchange_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xchg i32* %a, i32 %b acquire + ret i32 %1 +} + +define i32 @atomicrmw_xchg_i32_release(i32* %a, i32 %b) { +; RV32I-LABEL: atomicrmw_xchg_i32_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_exchange_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xchg i32* %a, i32 %b release + ret i32 %1 +} + +define i32 @atomicrmw_xchg_i32_acq_rel(i32* %a, i32 %b) { +; RV32I-LABEL: atomicrmw_xchg_i32_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_exchange_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xchg i32* %a, i32 %b acq_rel + ret i32 %1 +} + +define i32 @atomicrmw_xchg_i32_seq_cst(i32* %a, i32 %b) { +; RV32I-LABEL: atomicrmw_xchg_i32_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_exchange_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xchg i32* %a, i32 %b seq_cst + ret i32 %1 +} + +define i32 @atomicrmw_add_i32_monotonic(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_add_i32_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_fetch_add_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw add i32* %a, i32 %b monotonic + ret i32 %1 +} + +define i32 @atomicrmw_add_i32_acquire(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_add_i32_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_fetch_add_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw add i32* %a, i32 %b acquire + ret i32 %1 +} + +define i32 @atomicrmw_add_i32_release(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_add_i32_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_fetch_add_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw add i32* %a, i32 %b release + ret i32 %1 +} + +define i32 @atomicrmw_add_i32_acq_rel(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_add_i32_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_fetch_add_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw add i32* %a, i32 %b acq_rel + ret i32 %1 +} + +define i32 @atomicrmw_add_i32_seq_cst(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_add_i32_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_fetch_add_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw add i32* %a, i32 %b seq_cst + ret i32 %1 +} + +define i32 @atomicrmw_sub_i32_monotonic(i32* %a, i32 %b) { +; RV32I-LABEL: atomicrmw_sub_i32_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_fetch_sub_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw sub i32* %a, i32 %b monotonic + ret i32 %1 +} + +define i32 @atomicrmw_sub_i32_acquire(i32* %a, i32 %b) { +; RV32I-LABEL: atomicrmw_sub_i32_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_fetch_sub_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw sub i32* %a, i32 %b acquire + ret i32 %1 +} + +define i32 @atomicrmw_sub_i32_release(i32* %a, i32 %b) { +; RV32I-LABEL: atomicrmw_sub_i32_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_fetch_sub_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw sub i32* %a, i32 %b release + ret i32 %1 +} + +define i32 @atomicrmw_sub_i32_acq_rel(i32* %a, i32 %b) { +; RV32I-LABEL: atomicrmw_sub_i32_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_fetch_sub_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw sub i32* %a, i32 %b acq_rel + ret i32 %1 +} + +define i32 @atomicrmw_sub_i32_seq_cst(i32* %a, i32 %b) { +; RV32I-LABEL: atomicrmw_sub_i32_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_fetch_sub_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw sub i32* %a, i32 %b seq_cst + ret i32 %1 +} + +define i32 @atomicrmw_and_i32_monotonic(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_and_i32_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_fetch_and_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw and i32* %a, i32 %b monotonic + ret i32 %1 +} + +define i32 @atomicrmw_and_i32_acquire(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_and_i32_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_fetch_and_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw and i32* %a, i32 %b acquire + ret i32 %1 +} + +define i32 @atomicrmw_and_i32_release(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_and_i32_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_fetch_and_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw and i32* %a, i32 %b release + ret i32 %1 +} + +define i32 @atomicrmw_and_i32_acq_rel(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_and_i32_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_fetch_and_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw and i32* %a, i32 %b acq_rel + ret i32 %1 +} + +define i32 @atomicrmw_and_i32_seq_cst(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_and_i32_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_fetch_and_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw and i32* %a, i32 %b seq_cst + ret i32 %1 +} + +define i32 @atomicrmw_nand_i32_monotonic(i32* %a, i32 %b) { +; RV32I-LABEL: atomicrmw_nand_i32_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_fetch_nand_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw nand i32* %a, i32 %b monotonic + ret i32 %1 +} + +define i32 @atomicrmw_nand_i32_acquire(i32* %a, i32 %b) { +; RV32I-LABEL: atomicrmw_nand_i32_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_fetch_nand_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw nand i32* %a, i32 %b acquire + ret i32 %1 +} + +define i32 @atomicrmw_nand_i32_release(i32* %a, i32 %b) { +; RV32I-LABEL: atomicrmw_nand_i32_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_fetch_nand_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw nand i32* %a, i32 %b release + ret i32 %1 +} + +define i32 @atomicrmw_nand_i32_acq_rel(i32* %a, i32 %b) { +; RV32I-LABEL: atomicrmw_nand_i32_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_fetch_nand_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw nand i32* %a, i32 %b acq_rel + ret i32 %1 +} + +define i32 @atomicrmw_nand_i32_seq_cst(i32* %a, i32 %b) { +; RV32I-LABEL: atomicrmw_nand_i32_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_fetch_nand_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw nand i32* %a, i32 %b seq_cst + ret i32 %1 +} + +define i32 @atomicrmw_or_i32_monotonic(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_or_i32_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_fetch_or_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw or i32* %a, i32 %b monotonic + ret i32 %1 +} + +define i32 @atomicrmw_or_i32_acquire(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_or_i32_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_fetch_or_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw or i32* %a, i32 %b acquire + ret i32 %1 +} + +define i32 @atomicrmw_or_i32_release(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_or_i32_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_fetch_or_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw or i32* %a, i32 %b release + ret i32 %1 +} + +define i32 @atomicrmw_or_i32_acq_rel(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_or_i32_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_fetch_or_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw or i32* %a, i32 %b acq_rel + ret i32 %1 +} + +define i32 @atomicrmw_or_i32_seq_cst(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_or_i32_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_fetch_or_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw or i32* %a, i32 %b seq_cst + ret i32 %1 +} + +define i32 @atomicrmw_xor_i32_monotonic(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_xor_i32_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a2, zero +; RV32I-NEXT: call __atomic_fetch_xor_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xor i32* %a, i32 %b monotonic + ret i32 %1 +} + +define i32 @atomicrmw_xor_i32_acquire(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_xor_i32_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 2 +; RV32I-NEXT: call __atomic_fetch_xor_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xor i32* %a, i32 %b acquire + ret i32 %1 +} + +define i32 @atomicrmw_xor_i32_release(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_xor_i32_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 3 +; RV32I-NEXT: call __atomic_fetch_xor_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xor i32* %a, i32 %b release + ret i32 %1 +} + +define i32 @atomicrmw_xor_i32_acq_rel(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_xor_i32_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 4 +; RV32I-NEXT: call __atomic_fetch_xor_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xor i32* %a, i32 %b acq_rel + ret i32 %1 +} + +define i32 @atomicrmw_xor_i32_seq_cst(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_xor_i32_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, zero, 5 +; RV32I-NEXT: call __atomic_fetch_xor_4 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xor i32* %a, i32 %b seq_cst + ret i32 %1 +} + +define i32 @atomicrmw_max_i32_monotonic(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_max_i32_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: mv s1, a1 +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s3, sp, 12 +; RV32I-NEXT: .LBB105_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: sw a2, 12(sp) +; RV32I-NEXT: blt s1, a2, .LBB105_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB105_1 Depth=1 +; RV32I-NEXT: mv a2, s1 +; RV32I-NEXT: .LBB105_3: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB105_1 Depth=1 +; RV32I-NEXT: mv a0, s2 +; RV32I-NEXT: mv a1, s3 +; RV32I-NEXT: mv a3, zero +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw a2, 12(sp) +; RV32I-NEXT: beqz a0, .LBB105_1 +; RV32I-NEXT: # %bb.4: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw max i32* %a, i32 %b monotonic + ret i32 %1 +} + +define i32 @atomicrmw_max_i32_acquire(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_max_i32_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: mv s1, a1 +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s3, sp, 8 +; RV32I-NEXT: addi s4, zero, 2 +; RV32I-NEXT: .LBB106_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: sw a2, 8(sp) +; RV32I-NEXT: blt s1, a2, .LBB106_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB106_1 Depth=1 +; RV32I-NEXT: mv a2, s1 +; RV32I-NEXT: .LBB106_3: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB106_1 Depth=1 +; RV32I-NEXT: mv a0, s2 +; RV32I-NEXT: mv a1, s3 +; RV32I-NEXT: mv a3, s4 +; RV32I-NEXT: mv a4, s4 +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw a2, 8(sp) +; RV32I-NEXT: beqz a0, .LBB106_1 +; RV32I-NEXT: # %bb.4: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw max i32* %a, i32 %b acquire + ret i32 %1 +} + +define i32 @atomicrmw_max_i32_release(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_max_i32_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: mv s1, a1 +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s3, sp, 8 +; RV32I-NEXT: addi s4, zero, 3 +; RV32I-NEXT: .LBB107_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: sw a2, 8(sp) +; RV32I-NEXT: blt s1, a2, .LBB107_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB107_1 Depth=1 +; RV32I-NEXT: mv a2, s1 +; RV32I-NEXT: .LBB107_3: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB107_1 Depth=1 +; RV32I-NEXT: mv a0, s2 +; RV32I-NEXT: mv a1, s3 +; RV32I-NEXT: mv a3, s4 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw a2, 8(sp) +; RV32I-NEXT: beqz a0, .LBB107_1 +; RV32I-NEXT: # %bb.4: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw max i32* %a, i32 %b release + ret i32 %1 +} + +define i32 @atomicrmw_max_i32_acq_rel(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_max_i32_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: sw s5, 8(sp) +; RV32I-NEXT: mv s1, a1 +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s3, sp, 4 +; RV32I-NEXT: addi s4, zero, 4 +; RV32I-NEXT: addi s5, zero, 2 +; RV32I-NEXT: .LBB108_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: sw a2, 4(sp) +; RV32I-NEXT: blt s1, a2, .LBB108_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB108_1 Depth=1 +; RV32I-NEXT: mv a2, s1 +; RV32I-NEXT: .LBB108_3: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB108_1 Depth=1 +; RV32I-NEXT: mv a0, s2 +; RV32I-NEXT: mv a1, s3 +; RV32I-NEXT: mv a3, s4 +; RV32I-NEXT: mv a4, s5 +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw a2, 4(sp) +; RV32I-NEXT: beqz a0, .LBB108_1 +; RV32I-NEXT: # %bb.4: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s5, 8(sp) +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw max i32* %a, i32 %b acq_rel + ret i32 %1 +} + +define i32 @atomicrmw_max_i32_seq_cst(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_max_i32_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: mv s1, a1 +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s3, sp, 8 +; RV32I-NEXT: addi s4, zero, 5 +; RV32I-NEXT: .LBB109_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: sw a2, 8(sp) +; RV32I-NEXT: blt s1, a2, .LBB109_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB109_1 Depth=1 +; RV32I-NEXT: mv a2, s1 +; RV32I-NEXT: .LBB109_3: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB109_1 Depth=1 +; RV32I-NEXT: mv a0, s2 +; RV32I-NEXT: mv a1, s3 +; RV32I-NEXT: mv a3, s4 +; RV32I-NEXT: mv a4, s4 +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw a2, 8(sp) +; RV32I-NEXT: beqz a0, .LBB109_1 +; RV32I-NEXT: # %bb.4: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw max i32* %a, i32 %b seq_cst + ret i32 %1 +} + +define i32 @atomicrmw_min_i32_monotonic(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_min_i32_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: mv s1, a1 +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s3, sp, 12 +; RV32I-NEXT: .LBB110_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: sw a2, 12(sp) +; RV32I-NEXT: bge s1, a2, .LBB110_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB110_1 Depth=1 +; RV32I-NEXT: mv a2, s1 +; RV32I-NEXT: .LBB110_3: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB110_1 Depth=1 +; RV32I-NEXT: mv a0, s2 +; RV32I-NEXT: mv a1, s3 +; RV32I-NEXT: mv a3, zero +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw a2, 12(sp) +; RV32I-NEXT: beqz a0, .LBB110_1 +; RV32I-NEXT: # %bb.4: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw min i32* %a, i32 %b monotonic + ret i32 %1 +} + +define i32 @atomicrmw_min_i32_acquire(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_min_i32_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: mv s1, a1 +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s3, sp, 8 +; RV32I-NEXT: addi s4, zero, 2 +; RV32I-NEXT: .LBB111_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: sw a2, 8(sp) +; RV32I-NEXT: bge s1, a2, .LBB111_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB111_1 Depth=1 +; RV32I-NEXT: mv a2, s1 +; RV32I-NEXT: .LBB111_3: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB111_1 Depth=1 +; RV32I-NEXT: mv a0, s2 +; RV32I-NEXT: mv a1, s3 +; RV32I-NEXT: mv a3, s4 +; RV32I-NEXT: mv a4, s4 +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw a2, 8(sp) +; RV32I-NEXT: beqz a0, .LBB111_1 +; RV32I-NEXT: # %bb.4: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw min i32* %a, i32 %b acquire + ret i32 %1 +} + +define i32 @atomicrmw_min_i32_release(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_min_i32_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: mv s1, a1 +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s3, sp, 8 +; RV32I-NEXT: addi s4, zero, 3 +; RV32I-NEXT: .LBB112_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: sw a2, 8(sp) +; RV32I-NEXT: bge s1, a2, .LBB112_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB112_1 Depth=1 +; RV32I-NEXT: mv a2, s1 +; RV32I-NEXT: .LBB112_3: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB112_1 Depth=1 +; RV32I-NEXT: mv a0, s2 +; RV32I-NEXT: mv a1, s3 +; RV32I-NEXT: mv a3, s4 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw a2, 8(sp) +; RV32I-NEXT: beqz a0, .LBB112_1 +; RV32I-NEXT: # %bb.4: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw min i32* %a, i32 %b release + ret i32 %1 +} + +define i32 @atomicrmw_min_i32_acq_rel(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_min_i32_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: sw s5, 8(sp) +; RV32I-NEXT: mv s1, a1 +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s3, sp, 4 +; RV32I-NEXT: addi s4, zero, 4 +; RV32I-NEXT: addi s5, zero, 2 +; RV32I-NEXT: .LBB113_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: sw a2, 4(sp) +; RV32I-NEXT: bge s1, a2, .LBB113_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB113_1 Depth=1 +; RV32I-NEXT: mv a2, s1 +; RV32I-NEXT: .LBB113_3: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB113_1 Depth=1 +; RV32I-NEXT: mv a0, s2 +; RV32I-NEXT: mv a1, s3 +; RV32I-NEXT: mv a3, s4 +; RV32I-NEXT: mv a4, s5 +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw a2, 4(sp) +; RV32I-NEXT: beqz a0, .LBB113_1 +; RV32I-NEXT: # %bb.4: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s5, 8(sp) +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw min i32* %a, i32 %b acq_rel + ret i32 %1 +} + +define i32 @atomicrmw_min_i32_seq_cst(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_min_i32_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: mv s1, a1 +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s3, sp, 8 +; RV32I-NEXT: addi s4, zero, 5 +; RV32I-NEXT: .LBB114_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: sw a2, 8(sp) +; RV32I-NEXT: bge s1, a2, .LBB114_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB114_1 Depth=1 +; RV32I-NEXT: mv a2, s1 +; RV32I-NEXT: .LBB114_3: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB114_1 Depth=1 +; RV32I-NEXT: mv a0, s2 +; RV32I-NEXT: mv a1, s3 +; RV32I-NEXT: mv a3, s4 +; RV32I-NEXT: mv a4, s4 +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw a2, 8(sp) +; RV32I-NEXT: beqz a0, .LBB114_1 +; RV32I-NEXT: # %bb.4: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw min i32* %a, i32 %b seq_cst + ret i32 %1 +} + +define i32 @atomicrmw_umax_i32_monotonic(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_umax_i32_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: mv s1, a1 +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s3, sp, 12 +; RV32I-NEXT: .LBB115_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: sw a2, 12(sp) +; RV32I-NEXT: bltu s1, a2, .LBB115_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB115_1 Depth=1 +; RV32I-NEXT: mv a2, s1 +; RV32I-NEXT: .LBB115_3: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB115_1 Depth=1 +; RV32I-NEXT: mv a0, s2 +; RV32I-NEXT: mv a1, s3 +; RV32I-NEXT: mv a3, zero +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw a2, 12(sp) +; RV32I-NEXT: beqz a0, .LBB115_1 +; RV32I-NEXT: # %bb.4: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw umax i32* %a, i32 %b monotonic + ret i32 %1 +} + +define i32 @atomicrmw_umax_i32_acquire(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_umax_i32_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: mv s1, a1 +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s3, sp, 8 +; RV32I-NEXT: addi s4, zero, 2 +; RV32I-NEXT: .LBB116_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: sw a2, 8(sp) +; RV32I-NEXT: bltu s1, a2, .LBB116_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB116_1 Depth=1 +; RV32I-NEXT: mv a2, s1 +; RV32I-NEXT: .LBB116_3: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB116_1 Depth=1 +; RV32I-NEXT: mv a0, s2 +; RV32I-NEXT: mv a1, s3 +; RV32I-NEXT: mv a3, s4 +; RV32I-NEXT: mv a4, s4 +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw a2, 8(sp) +; RV32I-NEXT: beqz a0, .LBB116_1 +; RV32I-NEXT: # %bb.4: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw umax i32* %a, i32 %b acquire + ret i32 %1 +} + +define i32 @atomicrmw_umax_i32_release(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_umax_i32_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: mv s1, a1 +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s3, sp, 8 +; RV32I-NEXT: addi s4, zero, 3 +; RV32I-NEXT: .LBB117_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: sw a2, 8(sp) +; RV32I-NEXT: bltu s1, a2, .LBB117_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB117_1 Depth=1 +; RV32I-NEXT: mv a2, s1 +; RV32I-NEXT: .LBB117_3: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB117_1 Depth=1 +; RV32I-NEXT: mv a0, s2 +; RV32I-NEXT: mv a1, s3 +; RV32I-NEXT: mv a3, s4 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw a2, 8(sp) +; RV32I-NEXT: beqz a0, .LBB117_1 +; RV32I-NEXT: # %bb.4: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw umax i32* %a, i32 %b release + ret i32 %1 +} + +define i32 @atomicrmw_umax_i32_acq_rel(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_umax_i32_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: sw s5, 8(sp) +; RV32I-NEXT: mv s1, a1 +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s3, sp, 4 +; RV32I-NEXT: addi s4, zero, 4 +; RV32I-NEXT: addi s5, zero, 2 +; RV32I-NEXT: .LBB118_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: sw a2, 4(sp) +; RV32I-NEXT: bltu s1, a2, .LBB118_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB118_1 Depth=1 +; RV32I-NEXT: mv a2, s1 +; RV32I-NEXT: .LBB118_3: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB118_1 Depth=1 +; RV32I-NEXT: mv a0, s2 +; RV32I-NEXT: mv a1, s3 +; RV32I-NEXT: mv a3, s4 +; RV32I-NEXT: mv a4, s5 +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw a2, 4(sp) +; RV32I-NEXT: beqz a0, .LBB118_1 +; RV32I-NEXT: # %bb.4: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s5, 8(sp) +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw umax i32* %a, i32 %b acq_rel + ret i32 %1 +} + +define i32 @atomicrmw_umax_i32_seq_cst(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_umax_i32_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: mv s1, a1 +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s3, sp, 8 +; RV32I-NEXT: addi s4, zero, 5 +; RV32I-NEXT: .LBB119_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: sw a2, 8(sp) +; RV32I-NEXT: bltu s1, a2, .LBB119_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB119_1 Depth=1 +; RV32I-NEXT: mv a2, s1 +; RV32I-NEXT: .LBB119_3: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB119_1 Depth=1 +; RV32I-NEXT: mv a0, s2 +; RV32I-NEXT: mv a1, s3 +; RV32I-NEXT: mv a3, s4 +; RV32I-NEXT: mv a4, s4 +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw a2, 8(sp) +; RV32I-NEXT: beqz a0, .LBB119_1 +; RV32I-NEXT: # %bb.4: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw umax i32* %a, i32 %b seq_cst + ret i32 %1 +} + +define i32 @atomicrmw_umin_i32_monotonic(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_umin_i32_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: mv s1, a1 +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s3, sp, 12 +; RV32I-NEXT: .LBB120_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: sw a2, 12(sp) +; RV32I-NEXT: bgeu s1, a2, .LBB120_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB120_1 Depth=1 +; RV32I-NEXT: mv a2, s1 +; RV32I-NEXT: .LBB120_3: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB120_1 Depth=1 +; RV32I-NEXT: mv a0, s2 +; RV32I-NEXT: mv a1, s3 +; RV32I-NEXT: mv a3, zero +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw a2, 12(sp) +; RV32I-NEXT: beqz a0, .LBB120_1 +; RV32I-NEXT: # %bb.4: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw umin i32* %a, i32 %b monotonic + ret i32 %1 +} + +define i32 @atomicrmw_umin_i32_acquire(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_umin_i32_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: mv s1, a1 +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s3, sp, 8 +; RV32I-NEXT: addi s4, zero, 2 +; RV32I-NEXT: .LBB121_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: sw a2, 8(sp) +; RV32I-NEXT: bgeu s1, a2, .LBB121_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB121_1 Depth=1 +; RV32I-NEXT: mv a2, s1 +; RV32I-NEXT: .LBB121_3: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB121_1 Depth=1 +; RV32I-NEXT: mv a0, s2 +; RV32I-NEXT: mv a1, s3 +; RV32I-NEXT: mv a3, s4 +; RV32I-NEXT: mv a4, s4 +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw a2, 8(sp) +; RV32I-NEXT: beqz a0, .LBB121_1 +; RV32I-NEXT: # %bb.4: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw umin i32* %a, i32 %b acquire + ret i32 %1 +} + +define i32 @atomicrmw_umin_i32_release(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_umin_i32_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: mv s1, a1 +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s3, sp, 8 +; RV32I-NEXT: addi s4, zero, 3 +; RV32I-NEXT: .LBB122_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: sw a2, 8(sp) +; RV32I-NEXT: bgeu s1, a2, .LBB122_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB122_1 Depth=1 +; RV32I-NEXT: mv a2, s1 +; RV32I-NEXT: .LBB122_3: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB122_1 Depth=1 +; RV32I-NEXT: mv a0, s2 +; RV32I-NEXT: mv a1, s3 +; RV32I-NEXT: mv a3, s4 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw a2, 8(sp) +; RV32I-NEXT: beqz a0, .LBB122_1 +; RV32I-NEXT: # %bb.4: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw umin i32* %a, i32 %b release + ret i32 %1 +} + +define i32 @atomicrmw_umin_i32_acq_rel(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_umin_i32_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: sw s5, 8(sp) +; RV32I-NEXT: mv s1, a1 +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s3, sp, 4 +; RV32I-NEXT: addi s4, zero, 4 +; RV32I-NEXT: addi s5, zero, 2 +; RV32I-NEXT: .LBB123_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: sw a2, 4(sp) +; RV32I-NEXT: bgeu s1, a2, .LBB123_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB123_1 Depth=1 +; RV32I-NEXT: mv a2, s1 +; RV32I-NEXT: .LBB123_3: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB123_1 Depth=1 +; RV32I-NEXT: mv a0, s2 +; RV32I-NEXT: mv a1, s3 +; RV32I-NEXT: mv a3, s4 +; RV32I-NEXT: mv a4, s5 +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw a2, 4(sp) +; RV32I-NEXT: beqz a0, .LBB123_1 +; RV32I-NEXT: # %bb.4: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s5, 8(sp) +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw umin i32* %a, i32 %b acq_rel + ret i32 %1 +} + +define i32 @atomicrmw_umin_i32_seq_cst(i32 *%a, i32 %b) nounwind { +; RV32I-LABEL: atomicrmw_umin_i32_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: mv s1, a1 +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s3, sp, 8 +; RV32I-NEXT: addi s4, zero, 5 +; RV32I-NEXT: .LBB124_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: sw a2, 8(sp) +; RV32I-NEXT: bgeu s1, a2, .LBB124_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB124_1 Depth=1 +; RV32I-NEXT: mv a2, s1 +; RV32I-NEXT: .LBB124_3: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB124_1 Depth=1 +; RV32I-NEXT: mv a0, s2 +; RV32I-NEXT: mv a1, s3 +; RV32I-NEXT: mv a3, s4 +; RV32I-NEXT: mv a4, s4 +; RV32I-NEXT: call __atomic_compare_exchange_4 +; RV32I-NEXT: lw a2, 8(sp) +; RV32I-NEXT: beqz a0, .LBB124_1 +; RV32I-NEXT: # %bb.4: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw umin i32* %a, i32 %b seq_cst + ret i32 %1 +} + +define i64 @atomicrmw_xchg_i64_monotonic(i64* %a, i64 %b) { +; RV32I-LABEL: atomicrmw_xchg_i64_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a3, zero +; RV32I-NEXT: call __atomic_exchange_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xchg i64* %a, i64 %b monotonic + ret i64 %1 +} + +define i64 @atomicrmw_xchg_i64_acquire(i64* %a, i64 %b) { +; RV32I-LABEL: atomicrmw_xchg_i64_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 2 +; RV32I-NEXT: call __atomic_exchange_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xchg i64* %a, i64 %b acquire + ret i64 %1 +} + +define i64 @atomicrmw_xchg_i64_release(i64* %a, i64 %b) { +; RV32I-LABEL: atomicrmw_xchg_i64_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 3 +; RV32I-NEXT: call __atomic_exchange_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xchg i64* %a, i64 %b release + ret i64 %1 +} + +define i64 @atomicrmw_xchg_i64_acq_rel(i64* %a, i64 %b) { +; RV32I-LABEL: atomicrmw_xchg_i64_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 4 +; RV32I-NEXT: call __atomic_exchange_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xchg i64* %a, i64 %b acq_rel + ret i64 %1 +} + +define i64 @atomicrmw_xchg_i64_seq_cst(i64* %a, i64 %b) { +; RV32I-LABEL: atomicrmw_xchg_i64_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 5 +; RV32I-NEXT: call __atomic_exchange_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xchg i64* %a, i64 %b seq_cst + ret i64 %1 +} + +define i64 @atomicrmw_add_i64_monotonic(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_add_i64_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a3, zero +; RV32I-NEXT: call __atomic_fetch_add_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw add i64* %a, i64 %b monotonic + ret i64 %1 +} + +define i64 @atomicrmw_add_i64_acquire(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_add_i64_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 2 +; RV32I-NEXT: call __atomic_fetch_add_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw add i64* %a, i64 %b acquire + ret i64 %1 +} + +define i64 @atomicrmw_add_i64_release(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_add_i64_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 3 +; RV32I-NEXT: call __atomic_fetch_add_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw add i64* %a, i64 %b release + ret i64 %1 +} + +define i64 @atomicrmw_add_i64_acq_rel(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_add_i64_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 4 +; RV32I-NEXT: call __atomic_fetch_add_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw add i64* %a, i64 %b acq_rel + ret i64 %1 +} + +define i64 @atomicrmw_add_i64_seq_cst(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_add_i64_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 5 +; RV32I-NEXT: call __atomic_fetch_add_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw add i64* %a, i64 %b seq_cst + ret i64 %1 +} + +define i64 @atomicrmw_sub_i64_monotonic(i64* %a, i64 %b) { +; RV32I-LABEL: atomicrmw_sub_i64_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a3, zero +; RV32I-NEXT: call __atomic_fetch_sub_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw sub i64* %a, i64 %b monotonic + ret i64 %1 +} + +define i64 @atomicrmw_sub_i64_acquire(i64* %a, i64 %b) { +; RV32I-LABEL: atomicrmw_sub_i64_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 2 +; RV32I-NEXT: call __atomic_fetch_sub_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw sub i64* %a, i64 %b acquire + ret i64 %1 +} + +define i64 @atomicrmw_sub_i64_release(i64* %a, i64 %b) { +; RV32I-LABEL: atomicrmw_sub_i64_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 3 +; RV32I-NEXT: call __atomic_fetch_sub_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw sub i64* %a, i64 %b release + ret i64 %1 +} + +define i64 @atomicrmw_sub_i64_acq_rel(i64* %a, i64 %b) { +; RV32I-LABEL: atomicrmw_sub_i64_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 4 +; RV32I-NEXT: call __atomic_fetch_sub_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw sub i64* %a, i64 %b acq_rel + ret i64 %1 +} + +define i64 @atomicrmw_sub_i64_seq_cst(i64* %a, i64 %b) { +; RV32I-LABEL: atomicrmw_sub_i64_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 5 +; RV32I-NEXT: call __atomic_fetch_sub_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw sub i64* %a, i64 %b seq_cst + ret i64 %1 +} + +define i64 @atomicrmw_and_i64_monotonic(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_and_i64_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a3, zero +; RV32I-NEXT: call __atomic_fetch_and_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw and i64* %a, i64 %b monotonic + ret i64 %1 +} + +define i64 @atomicrmw_and_i64_acquire(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_and_i64_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 2 +; RV32I-NEXT: call __atomic_fetch_and_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw and i64* %a, i64 %b acquire + ret i64 %1 +} + +define i64 @atomicrmw_and_i64_release(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_and_i64_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 3 +; RV32I-NEXT: call __atomic_fetch_and_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw and i64* %a, i64 %b release + ret i64 %1 +} + +define i64 @atomicrmw_and_i64_acq_rel(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_and_i64_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 4 +; RV32I-NEXT: call __atomic_fetch_and_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw and i64* %a, i64 %b acq_rel + ret i64 %1 +} + +define i64 @atomicrmw_and_i64_seq_cst(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_and_i64_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 5 +; RV32I-NEXT: call __atomic_fetch_and_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw and i64* %a, i64 %b seq_cst + ret i64 %1 +} + +define i64 @atomicrmw_nand_i64_monotonic(i64* %a, i64 %b) { +; RV32I-LABEL: atomicrmw_nand_i64_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a3, zero +; RV32I-NEXT: call __atomic_fetch_nand_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw nand i64* %a, i64 %b monotonic + ret i64 %1 +} + +define i64 @atomicrmw_nand_i64_acquire(i64* %a, i64 %b) { +; RV32I-LABEL: atomicrmw_nand_i64_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 2 +; RV32I-NEXT: call __atomic_fetch_nand_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw nand i64* %a, i64 %b acquire + ret i64 %1 +} + +define i64 @atomicrmw_nand_i64_release(i64* %a, i64 %b) { +; RV32I-LABEL: atomicrmw_nand_i64_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 3 +; RV32I-NEXT: call __atomic_fetch_nand_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw nand i64* %a, i64 %b release + ret i64 %1 +} + +define i64 @atomicrmw_nand_i64_acq_rel(i64* %a, i64 %b) { +; RV32I-LABEL: atomicrmw_nand_i64_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 4 +; RV32I-NEXT: call __atomic_fetch_nand_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw nand i64* %a, i64 %b acq_rel + ret i64 %1 +} + +define i64 @atomicrmw_nand_i64_seq_cst(i64* %a, i64 %b) { +; RV32I-LABEL: atomicrmw_nand_i64_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 5 +; RV32I-NEXT: call __atomic_fetch_nand_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw nand i64* %a, i64 %b seq_cst + ret i64 %1 +} + +define i64 @atomicrmw_or_i64_monotonic(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_or_i64_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a3, zero +; RV32I-NEXT: call __atomic_fetch_or_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw or i64* %a, i64 %b monotonic + ret i64 %1 +} + +define i64 @atomicrmw_or_i64_acquire(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_or_i64_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 2 +; RV32I-NEXT: call __atomic_fetch_or_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw or i64* %a, i64 %b acquire + ret i64 %1 +} + +define i64 @atomicrmw_or_i64_release(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_or_i64_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 3 +; RV32I-NEXT: call __atomic_fetch_or_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw or i64* %a, i64 %b release + ret i64 %1 +} + +define i64 @atomicrmw_or_i64_acq_rel(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_or_i64_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 4 +; RV32I-NEXT: call __atomic_fetch_or_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw or i64* %a, i64 %b acq_rel + ret i64 %1 +} + +define i64 @atomicrmw_or_i64_seq_cst(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_or_i64_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 5 +; RV32I-NEXT: call __atomic_fetch_or_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw or i64* %a, i64 %b seq_cst + ret i64 %1 +} + +define i64 @atomicrmw_xor_i64_monotonic(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_xor_i64_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a3, zero +; RV32I-NEXT: call __atomic_fetch_xor_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xor i64* %a, i64 %b monotonic + ret i64 %1 +} + +define i64 @atomicrmw_xor_i64_acquire(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_xor_i64_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 2 +; RV32I-NEXT: call __atomic_fetch_xor_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xor i64* %a, i64 %b acquire + ret i64 %1 +} + +define i64 @atomicrmw_xor_i64_release(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_xor_i64_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 3 +; RV32I-NEXT: call __atomic_fetch_xor_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xor i64* %a, i64 %b release + ret i64 %1 +} + +define i64 @atomicrmw_xor_i64_acq_rel(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_xor_i64_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 4 +; RV32I-NEXT: call __atomic_fetch_xor_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xor i64* %a, i64 %b acq_rel + ret i64 %1 +} + +define i64 @atomicrmw_xor_i64_seq_cst(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_xor_i64_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a3, zero, 5 +; RV32I-NEXT: call __atomic_fetch_xor_8 +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = atomicrmw xor i64* %a, i64 %b seq_cst + ret i64 %1 +} + +define i64 @atomicrmw_max_i64_monotonic(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_max_i64_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: mv s1, a2 +; RV32I-NEXT: mv s2, a1 +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: lw a1, 4(a0) +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: mv s4, sp +; RV32I-NEXT: .LBB160_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: beq a1, s1, .LBB160_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB160_1 Depth=1 +; RV32I-NEXT: slt a0, s1, a1 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB160_4 +; RV32I-NEXT: j .LBB160_5 +; RV32I-NEXT: .LBB160_3: # in Loop: Header=BB160_1 Depth=1 +; RV32I-NEXT: sltu a0, s2, a2 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: bnez a0, .LBB160_5 +; RV32I-NEXT: .LBB160_4: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB160_1 Depth=1 +; RV32I-NEXT: mv a2, s2 +; RV32I-NEXT: .LBB160_5: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB160_1 Depth=1 +; RV32I-NEXT: mv a3, a1 +; RV32I-NEXT: bnez a0, .LBB160_7 +; RV32I-NEXT: # %bb.6: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB160_1 Depth=1 +; RV32I-NEXT: mv a3, s1 +; RV32I-NEXT: .LBB160_7: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB160_1 Depth=1 +; RV32I-NEXT: sw a1, 4(sp) +; RV32I-NEXT: mv a0, s3 +; RV32I-NEXT: mv a1, s4 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: mv a5, zero +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw a1, 4(sp) +; RV32I-NEXT: lw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB160_1 +; RV32I-NEXT: # %bb.8: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw max i64* %a, i64 %b monotonic + ret i64 %1 +} + +define i64 @atomicrmw_max_i64_acquire(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_max_i64_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: sw s5, 8(sp) +; RV32I-NEXT: mv s1, a2 +; RV32I-NEXT: mv s2, a1 +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: lw a1, 4(a0) +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: mv s4, sp +; RV32I-NEXT: addi s5, zero, 2 +; RV32I-NEXT: .LBB161_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: beq a1, s1, .LBB161_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB161_1 Depth=1 +; RV32I-NEXT: slt a0, s1, a1 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB161_4 +; RV32I-NEXT: j .LBB161_5 +; RV32I-NEXT: .LBB161_3: # in Loop: Header=BB161_1 Depth=1 +; RV32I-NEXT: sltu a0, s2, a2 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: bnez a0, .LBB161_5 +; RV32I-NEXT: .LBB161_4: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB161_1 Depth=1 +; RV32I-NEXT: mv a2, s2 +; RV32I-NEXT: .LBB161_5: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB161_1 Depth=1 +; RV32I-NEXT: mv a3, a1 +; RV32I-NEXT: bnez a0, .LBB161_7 +; RV32I-NEXT: # %bb.6: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB161_1 Depth=1 +; RV32I-NEXT: mv a3, s1 +; RV32I-NEXT: .LBB161_7: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB161_1 Depth=1 +; RV32I-NEXT: sw a1, 4(sp) +; RV32I-NEXT: mv a0, s3 +; RV32I-NEXT: mv a1, s4 +; RV32I-NEXT: mv a4, s5 +; RV32I-NEXT: mv a5, s5 +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw a1, 4(sp) +; RV32I-NEXT: lw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB161_1 +; RV32I-NEXT: # %bb.8: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s5, 8(sp) +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw max i64* %a, i64 %b acquire + ret i64 %1 +} + +define i64 @atomicrmw_max_i64_release(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_max_i64_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: sw s5, 8(sp) +; RV32I-NEXT: mv s1, a2 +; RV32I-NEXT: mv s2, a1 +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: lw a1, 4(a0) +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: mv s4, sp +; RV32I-NEXT: addi s5, zero, 3 +; RV32I-NEXT: .LBB162_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: beq a1, s1, .LBB162_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB162_1 Depth=1 +; RV32I-NEXT: slt a0, s1, a1 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB162_4 +; RV32I-NEXT: j .LBB162_5 +; RV32I-NEXT: .LBB162_3: # in Loop: Header=BB162_1 Depth=1 +; RV32I-NEXT: sltu a0, s2, a2 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: bnez a0, .LBB162_5 +; RV32I-NEXT: .LBB162_4: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB162_1 Depth=1 +; RV32I-NEXT: mv a2, s2 +; RV32I-NEXT: .LBB162_5: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB162_1 Depth=1 +; RV32I-NEXT: mv a3, a1 +; RV32I-NEXT: bnez a0, .LBB162_7 +; RV32I-NEXT: # %bb.6: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB162_1 Depth=1 +; RV32I-NEXT: mv a3, s1 +; RV32I-NEXT: .LBB162_7: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB162_1 Depth=1 +; RV32I-NEXT: sw a1, 4(sp) +; RV32I-NEXT: mv a0, s3 +; RV32I-NEXT: mv a1, s4 +; RV32I-NEXT: mv a4, s5 +; RV32I-NEXT: mv a5, zero +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw a1, 4(sp) +; RV32I-NEXT: lw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB162_1 +; RV32I-NEXT: # %bb.8: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s5, 8(sp) +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw max i64* %a, i64 %b release + ret i64 %1 +} + +define i64 @atomicrmw_max_i64_acq_rel(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_max_i64_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -48 +; RV32I-NEXT: sw ra, 44(sp) +; RV32I-NEXT: sw s1, 40(sp) +; RV32I-NEXT: sw s2, 36(sp) +; RV32I-NEXT: sw s3, 32(sp) +; RV32I-NEXT: sw s4, 28(sp) +; RV32I-NEXT: sw s5, 24(sp) +; RV32I-NEXT: sw s6, 20(sp) +; RV32I-NEXT: mv s1, a2 +; RV32I-NEXT: mv s2, a1 +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: lw a1, 4(a0) +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s4, sp, 8 +; RV32I-NEXT: addi s5, zero, 4 +; RV32I-NEXT: addi s6, zero, 2 +; RV32I-NEXT: .LBB163_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: beq a1, s1, .LBB163_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB163_1 Depth=1 +; RV32I-NEXT: slt a0, s1, a1 +; RV32I-NEXT: sw a2, 8(sp) +; RV32I-NEXT: beqz a0, .LBB163_4 +; RV32I-NEXT: j .LBB163_5 +; RV32I-NEXT: .LBB163_3: # in Loop: Header=BB163_1 Depth=1 +; RV32I-NEXT: sltu a0, s2, a2 +; RV32I-NEXT: sw a2, 8(sp) +; RV32I-NEXT: bnez a0, .LBB163_5 +; RV32I-NEXT: .LBB163_4: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB163_1 Depth=1 +; RV32I-NEXT: mv a2, s2 +; RV32I-NEXT: .LBB163_5: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB163_1 Depth=1 +; RV32I-NEXT: mv a3, a1 +; RV32I-NEXT: bnez a0, .LBB163_7 +; RV32I-NEXT: # %bb.6: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB163_1 Depth=1 +; RV32I-NEXT: mv a3, s1 +; RV32I-NEXT: .LBB163_7: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB163_1 Depth=1 +; RV32I-NEXT: sw a1, 12(sp) +; RV32I-NEXT: mv a0, s3 +; RV32I-NEXT: mv a1, s4 +; RV32I-NEXT: mv a4, s5 +; RV32I-NEXT: mv a5, s6 +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw a1, 12(sp) +; RV32I-NEXT: lw a2, 8(sp) +; RV32I-NEXT: beqz a0, .LBB163_1 +; RV32I-NEXT: # %bb.8: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s6, 20(sp) +; RV32I-NEXT: lw s5, 24(sp) +; RV32I-NEXT: lw s4, 28(sp) +; RV32I-NEXT: lw s3, 32(sp) +; RV32I-NEXT: lw s2, 36(sp) +; RV32I-NEXT: lw s1, 40(sp) +; RV32I-NEXT: lw ra, 44(sp) +; RV32I-NEXT: addi sp, sp, 48 +; RV32I-NEXT: ret + %1 = atomicrmw max i64* %a, i64 %b acq_rel + ret i64 %1 +} + +define i64 @atomicrmw_max_i64_seq_cst(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_max_i64_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: sw s5, 8(sp) +; RV32I-NEXT: mv s1, a2 +; RV32I-NEXT: mv s2, a1 +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: lw a1, 4(a0) +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: mv s4, sp +; RV32I-NEXT: addi s5, zero, 5 +; RV32I-NEXT: .LBB164_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: beq a1, s1, .LBB164_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB164_1 Depth=1 +; RV32I-NEXT: slt a0, s1, a1 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB164_4 +; RV32I-NEXT: j .LBB164_5 +; RV32I-NEXT: .LBB164_3: # in Loop: Header=BB164_1 Depth=1 +; RV32I-NEXT: sltu a0, s2, a2 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: bnez a0, .LBB164_5 +; RV32I-NEXT: .LBB164_4: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB164_1 Depth=1 +; RV32I-NEXT: mv a2, s2 +; RV32I-NEXT: .LBB164_5: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB164_1 Depth=1 +; RV32I-NEXT: mv a3, a1 +; RV32I-NEXT: bnez a0, .LBB164_7 +; RV32I-NEXT: # %bb.6: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB164_1 Depth=1 +; RV32I-NEXT: mv a3, s1 +; RV32I-NEXT: .LBB164_7: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB164_1 Depth=1 +; RV32I-NEXT: sw a1, 4(sp) +; RV32I-NEXT: mv a0, s3 +; RV32I-NEXT: mv a1, s4 +; RV32I-NEXT: mv a4, s5 +; RV32I-NEXT: mv a5, s5 +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw a1, 4(sp) +; RV32I-NEXT: lw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB164_1 +; RV32I-NEXT: # %bb.8: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s5, 8(sp) +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw max i64* %a, i64 %b seq_cst + ret i64 %1 +} + +define i64 @atomicrmw_min_i64_monotonic(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_min_i64_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: mv s1, a2 +; RV32I-NEXT: mv s2, a1 +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: lw a1, 4(a0) +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: mv s4, sp +; RV32I-NEXT: .LBB165_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: beq a1, s1, .LBB165_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB165_1 Depth=1 +; RV32I-NEXT: slt a0, s1, a1 +; RV32I-NEXT: j .LBB165_4 +; RV32I-NEXT: .LBB165_3: # in Loop: Header=BB165_1 Depth=1 +; RV32I-NEXT: sltu a0, s2, a2 +; RV32I-NEXT: .LBB165_4: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB165_1 Depth=1 +; RV32I-NEXT: xori a0, a0, 1 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: bnez a0, .LBB165_6 +; RV32I-NEXT: # %bb.5: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB165_1 Depth=1 +; RV32I-NEXT: mv a2, s2 +; RV32I-NEXT: .LBB165_6: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB165_1 Depth=1 +; RV32I-NEXT: mv a3, a1 +; RV32I-NEXT: bnez a0, .LBB165_8 +; RV32I-NEXT: # %bb.7: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB165_1 Depth=1 +; RV32I-NEXT: mv a3, s1 +; RV32I-NEXT: .LBB165_8: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB165_1 Depth=1 +; RV32I-NEXT: sw a1, 4(sp) +; RV32I-NEXT: mv a0, s3 +; RV32I-NEXT: mv a1, s4 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: mv a5, zero +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw a1, 4(sp) +; RV32I-NEXT: lw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB165_1 +; RV32I-NEXT: # %bb.9: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw min i64* %a, i64 %b monotonic + ret i64 %1 +} + +define i64 @atomicrmw_min_i64_acquire(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_min_i64_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: sw s5, 8(sp) +; RV32I-NEXT: mv s1, a2 +; RV32I-NEXT: mv s2, a1 +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: lw a1, 4(a0) +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: mv s4, sp +; RV32I-NEXT: addi s5, zero, 2 +; RV32I-NEXT: .LBB166_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: beq a1, s1, .LBB166_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB166_1 Depth=1 +; RV32I-NEXT: slt a0, s1, a1 +; RV32I-NEXT: j .LBB166_4 +; RV32I-NEXT: .LBB166_3: # in Loop: Header=BB166_1 Depth=1 +; RV32I-NEXT: sltu a0, s2, a2 +; RV32I-NEXT: .LBB166_4: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB166_1 Depth=1 +; RV32I-NEXT: xori a0, a0, 1 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: bnez a0, .LBB166_6 +; RV32I-NEXT: # %bb.5: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB166_1 Depth=1 +; RV32I-NEXT: mv a2, s2 +; RV32I-NEXT: .LBB166_6: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB166_1 Depth=1 +; RV32I-NEXT: mv a3, a1 +; RV32I-NEXT: bnez a0, .LBB166_8 +; RV32I-NEXT: # %bb.7: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB166_1 Depth=1 +; RV32I-NEXT: mv a3, s1 +; RV32I-NEXT: .LBB166_8: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB166_1 Depth=1 +; RV32I-NEXT: sw a1, 4(sp) +; RV32I-NEXT: mv a0, s3 +; RV32I-NEXT: mv a1, s4 +; RV32I-NEXT: mv a4, s5 +; RV32I-NEXT: mv a5, s5 +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw a1, 4(sp) +; RV32I-NEXT: lw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB166_1 +; RV32I-NEXT: # %bb.9: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s5, 8(sp) +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw min i64* %a, i64 %b acquire + ret i64 %1 +} + +define i64 @atomicrmw_min_i64_release(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_min_i64_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: sw s5, 8(sp) +; RV32I-NEXT: mv s1, a2 +; RV32I-NEXT: mv s2, a1 +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: lw a1, 4(a0) +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: mv s4, sp +; RV32I-NEXT: addi s5, zero, 3 +; RV32I-NEXT: .LBB167_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: beq a1, s1, .LBB167_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB167_1 Depth=1 +; RV32I-NEXT: slt a0, s1, a1 +; RV32I-NEXT: j .LBB167_4 +; RV32I-NEXT: .LBB167_3: # in Loop: Header=BB167_1 Depth=1 +; RV32I-NEXT: sltu a0, s2, a2 +; RV32I-NEXT: .LBB167_4: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB167_1 Depth=1 +; RV32I-NEXT: xori a0, a0, 1 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: bnez a0, .LBB167_6 +; RV32I-NEXT: # %bb.5: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB167_1 Depth=1 +; RV32I-NEXT: mv a2, s2 +; RV32I-NEXT: .LBB167_6: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB167_1 Depth=1 +; RV32I-NEXT: mv a3, a1 +; RV32I-NEXT: bnez a0, .LBB167_8 +; RV32I-NEXT: # %bb.7: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB167_1 Depth=1 +; RV32I-NEXT: mv a3, s1 +; RV32I-NEXT: .LBB167_8: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB167_1 Depth=1 +; RV32I-NEXT: sw a1, 4(sp) +; RV32I-NEXT: mv a0, s3 +; RV32I-NEXT: mv a1, s4 +; RV32I-NEXT: mv a4, s5 +; RV32I-NEXT: mv a5, zero +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw a1, 4(sp) +; RV32I-NEXT: lw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB167_1 +; RV32I-NEXT: # %bb.9: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s5, 8(sp) +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw min i64* %a, i64 %b release + ret i64 %1 +} + +define i64 @atomicrmw_min_i64_acq_rel(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_min_i64_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -48 +; RV32I-NEXT: sw ra, 44(sp) +; RV32I-NEXT: sw s1, 40(sp) +; RV32I-NEXT: sw s2, 36(sp) +; RV32I-NEXT: sw s3, 32(sp) +; RV32I-NEXT: sw s4, 28(sp) +; RV32I-NEXT: sw s5, 24(sp) +; RV32I-NEXT: sw s6, 20(sp) +; RV32I-NEXT: mv s1, a2 +; RV32I-NEXT: mv s2, a1 +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: lw a1, 4(a0) +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s4, sp, 8 +; RV32I-NEXT: addi s5, zero, 4 +; RV32I-NEXT: addi s6, zero, 2 +; RV32I-NEXT: .LBB168_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: beq a1, s1, .LBB168_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB168_1 Depth=1 +; RV32I-NEXT: slt a0, s1, a1 +; RV32I-NEXT: j .LBB168_4 +; RV32I-NEXT: .LBB168_3: # in Loop: Header=BB168_1 Depth=1 +; RV32I-NEXT: sltu a0, s2, a2 +; RV32I-NEXT: .LBB168_4: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB168_1 Depth=1 +; RV32I-NEXT: xori a0, a0, 1 +; RV32I-NEXT: sw a2, 8(sp) +; RV32I-NEXT: bnez a0, .LBB168_6 +; RV32I-NEXT: # %bb.5: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB168_1 Depth=1 +; RV32I-NEXT: mv a2, s2 +; RV32I-NEXT: .LBB168_6: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB168_1 Depth=1 +; RV32I-NEXT: mv a3, a1 +; RV32I-NEXT: bnez a0, .LBB168_8 +; RV32I-NEXT: # %bb.7: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB168_1 Depth=1 +; RV32I-NEXT: mv a3, s1 +; RV32I-NEXT: .LBB168_8: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB168_1 Depth=1 +; RV32I-NEXT: sw a1, 12(sp) +; RV32I-NEXT: mv a0, s3 +; RV32I-NEXT: mv a1, s4 +; RV32I-NEXT: mv a4, s5 +; RV32I-NEXT: mv a5, s6 +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw a1, 12(sp) +; RV32I-NEXT: lw a2, 8(sp) +; RV32I-NEXT: beqz a0, .LBB168_1 +; RV32I-NEXT: # %bb.9: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s6, 20(sp) +; RV32I-NEXT: lw s5, 24(sp) +; RV32I-NEXT: lw s4, 28(sp) +; RV32I-NEXT: lw s3, 32(sp) +; RV32I-NEXT: lw s2, 36(sp) +; RV32I-NEXT: lw s1, 40(sp) +; RV32I-NEXT: lw ra, 44(sp) +; RV32I-NEXT: addi sp, sp, 48 +; RV32I-NEXT: ret + %1 = atomicrmw min i64* %a, i64 %b acq_rel + ret i64 %1 +} + +define i64 @atomicrmw_min_i64_seq_cst(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_min_i64_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: sw s5, 8(sp) +; RV32I-NEXT: mv s1, a2 +; RV32I-NEXT: mv s2, a1 +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: lw a1, 4(a0) +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: mv s4, sp +; RV32I-NEXT: addi s5, zero, 5 +; RV32I-NEXT: .LBB169_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: beq a1, s1, .LBB169_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB169_1 Depth=1 +; RV32I-NEXT: slt a0, s1, a1 +; RV32I-NEXT: j .LBB169_4 +; RV32I-NEXT: .LBB169_3: # in Loop: Header=BB169_1 Depth=1 +; RV32I-NEXT: sltu a0, s2, a2 +; RV32I-NEXT: .LBB169_4: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB169_1 Depth=1 +; RV32I-NEXT: xori a0, a0, 1 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: bnez a0, .LBB169_6 +; RV32I-NEXT: # %bb.5: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB169_1 Depth=1 +; RV32I-NEXT: mv a2, s2 +; RV32I-NEXT: .LBB169_6: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB169_1 Depth=1 +; RV32I-NEXT: mv a3, a1 +; RV32I-NEXT: bnez a0, .LBB169_8 +; RV32I-NEXT: # %bb.7: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB169_1 Depth=1 +; RV32I-NEXT: mv a3, s1 +; RV32I-NEXT: .LBB169_8: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB169_1 Depth=1 +; RV32I-NEXT: sw a1, 4(sp) +; RV32I-NEXT: mv a0, s3 +; RV32I-NEXT: mv a1, s4 +; RV32I-NEXT: mv a4, s5 +; RV32I-NEXT: mv a5, s5 +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw a1, 4(sp) +; RV32I-NEXT: lw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB169_1 +; RV32I-NEXT: # %bb.9: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s5, 8(sp) +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw min i64* %a, i64 %b seq_cst + ret i64 %1 +} + +define i64 @atomicrmw_umax_i64_monotonic(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_umax_i64_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: mv s1, a2 +; RV32I-NEXT: mv s2, a1 +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: lw a1, 4(a0) +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: mv s4, sp +; RV32I-NEXT: .LBB170_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: beq a1, s1, .LBB170_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB170_1 Depth=1 +; RV32I-NEXT: sltu a0, s1, a1 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB170_4 +; RV32I-NEXT: j .LBB170_5 +; RV32I-NEXT: .LBB170_3: # in Loop: Header=BB170_1 Depth=1 +; RV32I-NEXT: sltu a0, s2, a2 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: bnez a0, .LBB170_5 +; RV32I-NEXT: .LBB170_4: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB170_1 Depth=1 +; RV32I-NEXT: mv a2, s2 +; RV32I-NEXT: .LBB170_5: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB170_1 Depth=1 +; RV32I-NEXT: mv a3, a1 +; RV32I-NEXT: bnez a0, .LBB170_7 +; RV32I-NEXT: # %bb.6: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB170_1 Depth=1 +; RV32I-NEXT: mv a3, s1 +; RV32I-NEXT: .LBB170_7: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB170_1 Depth=1 +; RV32I-NEXT: sw a1, 4(sp) +; RV32I-NEXT: mv a0, s3 +; RV32I-NEXT: mv a1, s4 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: mv a5, zero +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw a1, 4(sp) +; RV32I-NEXT: lw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB170_1 +; RV32I-NEXT: # %bb.8: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw umax i64* %a, i64 %b monotonic + ret i64 %1 +} + +define i64 @atomicrmw_umax_i64_acquire(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_umax_i64_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: sw s5, 8(sp) +; RV32I-NEXT: mv s1, a2 +; RV32I-NEXT: mv s2, a1 +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: lw a1, 4(a0) +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: mv s4, sp +; RV32I-NEXT: addi s5, zero, 2 +; RV32I-NEXT: .LBB171_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: beq a1, s1, .LBB171_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB171_1 Depth=1 +; RV32I-NEXT: sltu a0, s1, a1 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB171_4 +; RV32I-NEXT: j .LBB171_5 +; RV32I-NEXT: .LBB171_3: # in Loop: Header=BB171_1 Depth=1 +; RV32I-NEXT: sltu a0, s2, a2 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: bnez a0, .LBB171_5 +; RV32I-NEXT: .LBB171_4: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB171_1 Depth=1 +; RV32I-NEXT: mv a2, s2 +; RV32I-NEXT: .LBB171_5: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB171_1 Depth=1 +; RV32I-NEXT: mv a3, a1 +; RV32I-NEXT: bnez a0, .LBB171_7 +; RV32I-NEXT: # %bb.6: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB171_1 Depth=1 +; RV32I-NEXT: mv a3, s1 +; RV32I-NEXT: .LBB171_7: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB171_1 Depth=1 +; RV32I-NEXT: sw a1, 4(sp) +; RV32I-NEXT: mv a0, s3 +; RV32I-NEXT: mv a1, s4 +; RV32I-NEXT: mv a4, s5 +; RV32I-NEXT: mv a5, s5 +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw a1, 4(sp) +; RV32I-NEXT: lw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB171_1 +; RV32I-NEXT: # %bb.8: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s5, 8(sp) +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw umax i64* %a, i64 %b acquire + ret i64 %1 +} + +define i64 @atomicrmw_umax_i64_release(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_umax_i64_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: sw s5, 8(sp) +; RV32I-NEXT: mv s1, a2 +; RV32I-NEXT: mv s2, a1 +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: lw a1, 4(a0) +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: mv s4, sp +; RV32I-NEXT: addi s5, zero, 3 +; RV32I-NEXT: .LBB172_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: beq a1, s1, .LBB172_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB172_1 Depth=1 +; RV32I-NEXT: sltu a0, s1, a1 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB172_4 +; RV32I-NEXT: j .LBB172_5 +; RV32I-NEXT: .LBB172_3: # in Loop: Header=BB172_1 Depth=1 +; RV32I-NEXT: sltu a0, s2, a2 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: bnez a0, .LBB172_5 +; RV32I-NEXT: .LBB172_4: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB172_1 Depth=1 +; RV32I-NEXT: mv a2, s2 +; RV32I-NEXT: .LBB172_5: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB172_1 Depth=1 +; RV32I-NEXT: mv a3, a1 +; RV32I-NEXT: bnez a0, .LBB172_7 +; RV32I-NEXT: # %bb.6: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB172_1 Depth=1 +; RV32I-NEXT: mv a3, s1 +; RV32I-NEXT: .LBB172_7: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB172_1 Depth=1 +; RV32I-NEXT: sw a1, 4(sp) +; RV32I-NEXT: mv a0, s3 +; RV32I-NEXT: mv a1, s4 +; RV32I-NEXT: mv a4, s5 +; RV32I-NEXT: mv a5, zero +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw a1, 4(sp) +; RV32I-NEXT: lw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB172_1 +; RV32I-NEXT: # %bb.8: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s5, 8(sp) +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw umax i64* %a, i64 %b release + ret i64 %1 +} + +define i64 @atomicrmw_umax_i64_acq_rel(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_umax_i64_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -48 +; RV32I-NEXT: sw ra, 44(sp) +; RV32I-NEXT: sw s1, 40(sp) +; RV32I-NEXT: sw s2, 36(sp) +; RV32I-NEXT: sw s3, 32(sp) +; RV32I-NEXT: sw s4, 28(sp) +; RV32I-NEXT: sw s5, 24(sp) +; RV32I-NEXT: sw s6, 20(sp) +; RV32I-NEXT: mv s1, a2 +; RV32I-NEXT: mv s2, a1 +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: lw a1, 4(a0) +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s4, sp, 8 +; RV32I-NEXT: addi s5, zero, 4 +; RV32I-NEXT: addi s6, zero, 2 +; RV32I-NEXT: .LBB173_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: beq a1, s1, .LBB173_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB173_1 Depth=1 +; RV32I-NEXT: sltu a0, s1, a1 +; RV32I-NEXT: sw a2, 8(sp) +; RV32I-NEXT: beqz a0, .LBB173_4 +; RV32I-NEXT: j .LBB173_5 +; RV32I-NEXT: .LBB173_3: # in Loop: Header=BB173_1 Depth=1 +; RV32I-NEXT: sltu a0, s2, a2 +; RV32I-NEXT: sw a2, 8(sp) +; RV32I-NEXT: bnez a0, .LBB173_5 +; RV32I-NEXT: .LBB173_4: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB173_1 Depth=1 +; RV32I-NEXT: mv a2, s2 +; RV32I-NEXT: .LBB173_5: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB173_1 Depth=1 +; RV32I-NEXT: mv a3, a1 +; RV32I-NEXT: bnez a0, .LBB173_7 +; RV32I-NEXT: # %bb.6: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB173_1 Depth=1 +; RV32I-NEXT: mv a3, s1 +; RV32I-NEXT: .LBB173_7: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB173_1 Depth=1 +; RV32I-NEXT: sw a1, 12(sp) +; RV32I-NEXT: mv a0, s3 +; RV32I-NEXT: mv a1, s4 +; RV32I-NEXT: mv a4, s5 +; RV32I-NEXT: mv a5, s6 +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw a1, 12(sp) +; RV32I-NEXT: lw a2, 8(sp) +; RV32I-NEXT: beqz a0, .LBB173_1 +; RV32I-NEXT: # %bb.8: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s6, 20(sp) +; RV32I-NEXT: lw s5, 24(sp) +; RV32I-NEXT: lw s4, 28(sp) +; RV32I-NEXT: lw s3, 32(sp) +; RV32I-NEXT: lw s2, 36(sp) +; RV32I-NEXT: lw s1, 40(sp) +; RV32I-NEXT: lw ra, 44(sp) +; RV32I-NEXT: addi sp, sp, 48 +; RV32I-NEXT: ret + %1 = atomicrmw umax i64* %a, i64 %b acq_rel + ret i64 %1 +} + +define i64 @atomicrmw_umax_i64_seq_cst(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_umax_i64_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: sw s5, 8(sp) +; RV32I-NEXT: mv s1, a2 +; RV32I-NEXT: mv s2, a1 +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: lw a1, 4(a0) +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: mv s4, sp +; RV32I-NEXT: addi s5, zero, 5 +; RV32I-NEXT: .LBB174_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: beq a1, s1, .LBB174_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB174_1 Depth=1 +; RV32I-NEXT: sltu a0, s1, a1 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB174_4 +; RV32I-NEXT: j .LBB174_5 +; RV32I-NEXT: .LBB174_3: # in Loop: Header=BB174_1 Depth=1 +; RV32I-NEXT: sltu a0, s2, a2 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: bnez a0, .LBB174_5 +; RV32I-NEXT: .LBB174_4: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB174_1 Depth=1 +; RV32I-NEXT: mv a2, s2 +; RV32I-NEXT: .LBB174_5: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB174_1 Depth=1 +; RV32I-NEXT: mv a3, a1 +; RV32I-NEXT: bnez a0, .LBB174_7 +; RV32I-NEXT: # %bb.6: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB174_1 Depth=1 +; RV32I-NEXT: mv a3, s1 +; RV32I-NEXT: .LBB174_7: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB174_1 Depth=1 +; RV32I-NEXT: sw a1, 4(sp) +; RV32I-NEXT: mv a0, s3 +; RV32I-NEXT: mv a1, s4 +; RV32I-NEXT: mv a4, s5 +; RV32I-NEXT: mv a5, s5 +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw a1, 4(sp) +; RV32I-NEXT: lw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB174_1 +; RV32I-NEXT: # %bb.8: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s5, 8(sp) +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw umax i64* %a, i64 %b seq_cst + ret i64 %1 +} + +define i64 @atomicrmw_umin_i64_monotonic(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_umin_i64_monotonic: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: mv s1, a2 +; RV32I-NEXT: mv s2, a1 +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: lw a1, 4(a0) +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: mv s4, sp +; RV32I-NEXT: .LBB175_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: beq a1, s1, .LBB175_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB175_1 Depth=1 +; RV32I-NEXT: sltu a0, s1, a1 +; RV32I-NEXT: j .LBB175_4 +; RV32I-NEXT: .LBB175_3: # in Loop: Header=BB175_1 Depth=1 +; RV32I-NEXT: sltu a0, s2, a2 +; RV32I-NEXT: .LBB175_4: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB175_1 Depth=1 +; RV32I-NEXT: xori a0, a0, 1 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: bnez a0, .LBB175_6 +; RV32I-NEXT: # %bb.5: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB175_1 Depth=1 +; RV32I-NEXT: mv a2, s2 +; RV32I-NEXT: .LBB175_6: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB175_1 Depth=1 +; RV32I-NEXT: mv a3, a1 +; RV32I-NEXT: bnez a0, .LBB175_8 +; RV32I-NEXT: # %bb.7: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB175_1 Depth=1 +; RV32I-NEXT: mv a3, s1 +; RV32I-NEXT: .LBB175_8: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB175_1 Depth=1 +; RV32I-NEXT: sw a1, 4(sp) +; RV32I-NEXT: mv a0, s3 +; RV32I-NEXT: mv a1, s4 +; RV32I-NEXT: mv a4, zero +; RV32I-NEXT: mv a5, zero +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw a1, 4(sp) +; RV32I-NEXT: lw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB175_1 +; RV32I-NEXT: # %bb.9: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw umin i64* %a, i64 %b monotonic + ret i64 %1 +} + +define i64 @atomicrmw_umin_i64_acquire(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_umin_i64_acquire: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: sw s5, 8(sp) +; RV32I-NEXT: mv s1, a2 +; RV32I-NEXT: mv s2, a1 +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: lw a1, 4(a0) +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: mv s4, sp +; RV32I-NEXT: addi s5, zero, 2 +; RV32I-NEXT: .LBB176_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: beq a1, s1, .LBB176_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB176_1 Depth=1 +; RV32I-NEXT: sltu a0, s1, a1 +; RV32I-NEXT: j .LBB176_4 +; RV32I-NEXT: .LBB176_3: # in Loop: Header=BB176_1 Depth=1 +; RV32I-NEXT: sltu a0, s2, a2 +; RV32I-NEXT: .LBB176_4: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB176_1 Depth=1 +; RV32I-NEXT: xori a0, a0, 1 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: bnez a0, .LBB176_6 +; RV32I-NEXT: # %bb.5: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB176_1 Depth=1 +; RV32I-NEXT: mv a2, s2 +; RV32I-NEXT: .LBB176_6: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB176_1 Depth=1 +; RV32I-NEXT: mv a3, a1 +; RV32I-NEXT: bnez a0, .LBB176_8 +; RV32I-NEXT: # %bb.7: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB176_1 Depth=1 +; RV32I-NEXT: mv a3, s1 +; RV32I-NEXT: .LBB176_8: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB176_1 Depth=1 +; RV32I-NEXT: sw a1, 4(sp) +; RV32I-NEXT: mv a0, s3 +; RV32I-NEXT: mv a1, s4 +; RV32I-NEXT: mv a4, s5 +; RV32I-NEXT: mv a5, s5 +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw a1, 4(sp) +; RV32I-NEXT: lw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB176_1 +; RV32I-NEXT: # %bb.9: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s5, 8(sp) +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw umin i64* %a, i64 %b acquire + ret i64 %1 +} + +define i64 @atomicrmw_umin_i64_release(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_umin_i64_release: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: sw s5, 8(sp) +; RV32I-NEXT: mv s1, a2 +; RV32I-NEXT: mv s2, a1 +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: lw a1, 4(a0) +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: mv s4, sp +; RV32I-NEXT: addi s5, zero, 3 +; RV32I-NEXT: .LBB177_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: beq a1, s1, .LBB177_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB177_1 Depth=1 +; RV32I-NEXT: sltu a0, s1, a1 +; RV32I-NEXT: j .LBB177_4 +; RV32I-NEXT: .LBB177_3: # in Loop: Header=BB177_1 Depth=1 +; RV32I-NEXT: sltu a0, s2, a2 +; RV32I-NEXT: .LBB177_4: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB177_1 Depth=1 +; RV32I-NEXT: xori a0, a0, 1 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: bnez a0, .LBB177_6 +; RV32I-NEXT: # %bb.5: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB177_1 Depth=1 +; RV32I-NEXT: mv a2, s2 +; RV32I-NEXT: .LBB177_6: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB177_1 Depth=1 +; RV32I-NEXT: mv a3, a1 +; RV32I-NEXT: bnez a0, .LBB177_8 +; RV32I-NEXT: # %bb.7: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB177_1 Depth=1 +; RV32I-NEXT: mv a3, s1 +; RV32I-NEXT: .LBB177_8: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB177_1 Depth=1 +; RV32I-NEXT: sw a1, 4(sp) +; RV32I-NEXT: mv a0, s3 +; RV32I-NEXT: mv a1, s4 +; RV32I-NEXT: mv a4, s5 +; RV32I-NEXT: mv a5, zero +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw a1, 4(sp) +; RV32I-NEXT: lw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB177_1 +; RV32I-NEXT: # %bb.9: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s5, 8(sp) +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw umin i64* %a, i64 %b release + ret i64 %1 +} + +define i64 @atomicrmw_umin_i64_acq_rel(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_umin_i64_acq_rel: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -48 +; RV32I-NEXT: sw ra, 44(sp) +; RV32I-NEXT: sw s1, 40(sp) +; RV32I-NEXT: sw s2, 36(sp) +; RV32I-NEXT: sw s3, 32(sp) +; RV32I-NEXT: sw s4, 28(sp) +; RV32I-NEXT: sw s5, 24(sp) +; RV32I-NEXT: sw s6, 20(sp) +; RV32I-NEXT: mv s1, a2 +; RV32I-NEXT: mv s2, a1 +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: lw a1, 4(a0) +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: addi s4, sp, 8 +; RV32I-NEXT: addi s5, zero, 4 +; RV32I-NEXT: addi s6, zero, 2 +; RV32I-NEXT: .LBB178_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: beq a1, s1, .LBB178_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB178_1 Depth=1 +; RV32I-NEXT: sltu a0, s1, a1 +; RV32I-NEXT: j .LBB178_4 +; RV32I-NEXT: .LBB178_3: # in Loop: Header=BB178_1 Depth=1 +; RV32I-NEXT: sltu a0, s2, a2 +; RV32I-NEXT: .LBB178_4: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB178_1 Depth=1 +; RV32I-NEXT: xori a0, a0, 1 +; RV32I-NEXT: sw a2, 8(sp) +; RV32I-NEXT: bnez a0, .LBB178_6 +; RV32I-NEXT: # %bb.5: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB178_1 Depth=1 +; RV32I-NEXT: mv a2, s2 +; RV32I-NEXT: .LBB178_6: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB178_1 Depth=1 +; RV32I-NEXT: mv a3, a1 +; RV32I-NEXT: bnez a0, .LBB178_8 +; RV32I-NEXT: # %bb.7: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB178_1 Depth=1 +; RV32I-NEXT: mv a3, s1 +; RV32I-NEXT: .LBB178_8: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB178_1 Depth=1 +; RV32I-NEXT: sw a1, 12(sp) +; RV32I-NEXT: mv a0, s3 +; RV32I-NEXT: mv a1, s4 +; RV32I-NEXT: mv a4, s5 +; RV32I-NEXT: mv a5, s6 +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw a1, 12(sp) +; RV32I-NEXT: lw a2, 8(sp) +; RV32I-NEXT: beqz a0, .LBB178_1 +; RV32I-NEXT: # %bb.9: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s6, 20(sp) +; RV32I-NEXT: lw s5, 24(sp) +; RV32I-NEXT: lw s4, 28(sp) +; RV32I-NEXT: lw s3, 32(sp) +; RV32I-NEXT: lw s2, 36(sp) +; RV32I-NEXT: lw s1, 40(sp) +; RV32I-NEXT: lw ra, 44(sp) +; RV32I-NEXT: addi sp, sp, 48 +; RV32I-NEXT: ret + %1 = atomicrmw umin i64* %a, i64 %b acq_rel + ret i64 %1 +} + +define i64 @atomicrmw_umin_i64_seq_cst(i64 *%a, i64 %b) nounwind { +; RV32I-LABEL: atomicrmw_umin_i64_seq_cst: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: sw s5, 8(sp) +; RV32I-NEXT: mv s1, a2 +; RV32I-NEXT: mv s2, a1 +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: lw a1, 4(a0) +; RV32I-NEXT: lw a2, 0(a0) +; RV32I-NEXT: mv s4, sp +; RV32I-NEXT: addi s5, zero, 5 +; RV32I-NEXT: .LBB179_1: # %atomicrmw.start +; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32I-NEXT: beq a1, s1, .LBB179_3 +; RV32I-NEXT: # %bb.2: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB179_1 Depth=1 +; RV32I-NEXT: sltu a0, s1, a1 +; RV32I-NEXT: j .LBB179_4 +; RV32I-NEXT: .LBB179_3: # in Loop: Header=BB179_1 Depth=1 +; RV32I-NEXT: sltu a0, s2, a2 +; RV32I-NEXT: .LBB179_4: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB179_1 Depth=1 +; RV32I-NEXT: xori a0, a0, 1 +; RV32I-NEXT: sw a2, 0(sp) +; RV32I-NEXT: bnez a0, .LBB179_6 +; RV32I-NEXT: # %bb.5: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB179_1 Depth=1 +; RV32I-NEXT: mv a2, s2 +; RV32I-NEXT: .LBB179_6: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB179_1 Depth=1 +; RV32I-NEXT: mv a3, a1 +; RV32I-NEXT: bnez a0, .LBB179_8 +; RV32I-NEXT: # %bb.7: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB179_1 Depth=1 +; RV32I-NEXT: mv a3, s1 +; RV32I-NEXT: .LBB179_8: # %atomicrmw.start +; RV32I-NEXT: # in Loop: Header=BB179_1 Depth=1 +; RV32I-NEXT: sw a1, 4(sp) +; RV32I-NEXT: mv a0, s3 +; RV32I-NEXT: mv a1, s4 +; RV32I-NEXT: mv a4, s5 +; RV32I-NEXT: mv a5, s5 +; RV32I-NEXT: call __atomic_compare_exchange_8 +; RV32I-NEXT: lw a1, 4(sp) +; RV32I-NEXT: lw a2, 0(sp) +; RV32I-NEXT: beqz a0, .LBB179_1 +; RV32I-NEXT: # %bb.9: # %atomicrmw.end +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: lw s5, 8(sp) +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret + %1 = atomicrmw umin i64* %a, i64 %b seq_cst + ret i64 %1 +}