MachineBasicBlock::iterator MBBI, unsigned LdrexOp,
unsigned StrexOp, unsigned UxtOp,
MachineBasicBlock::iterator &NextMBBI);
- bool ExpandAtomicOp(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MBBI, const int Size,
- unsigned PseudoOp,
- MachineBasicBlock::iterator &NextMBBI);
bool ExpandCMP_SWAP_64(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
/// ARM's ldrexd/strexd take a consecutive register pair (represented as a
/// single GPRPair register), Thumb's take two separate registers so we need to
/// extract the subregs from the pair.
-static void addExclusiveRegPair(MachineInstrBuilder &MIB, Register Reg,
+static void addExclusiveRegPair(MachineInstrBuilder &MIB, MachineOperand &Reg,
unsigned Flags, bool IsThumb,
const TargetRegisterInfo *TRI) {
if (IsThumb) {
- Register RegLo = TRI->getSubReg(Reg, ARM::gsub_0);
- Register RegHi = TRI->getSubReg(Reg, ARM::gsub_1);
+ Register RegLo = TRI->getSubReg(Reg.getReg(), ARM::gsub_0);
+ Register RegHi = TRI->getSubReg(Reg.getReg(), ARM::gsub_1);
MIB.addReg(RegLo, Flags);
MIB.addReg(RegHi, Flags);
} else
- MIB.addReg(Reg, Flags);
-}
-
-static void
-makeAtomicUpdateInstrs(const unsigned PseudoOp, MachineBasicBlock *LoadStoreBB,
- const DebugLoc &DL, const ARMBaseInstrInfo *TII,
- const Register DestReg, const Register ValReg) {
-
- auto BasicOp = [&](unsigned Opcode) {
- auto MIB = BuildMI(LoadStoreBB, DL, TII->get(Opcode), DestReg)
- .addReg(DestReg, RegState::Kill)
- .addReg(ValReg)
- .add(predOps(ARMCC::AL));
- if (Opcode != ARM::VADDS && Opcode != ARM::VSUBS && Opcode != ARM::VADDD &&
- Opcode != ARM::VSUBD)
- // Floating point operations don't have this.
- // Add 's' bit operand (always reg0 for this)
- MIB.addReg(0);
- };
- auto MinMax = [&](ARMCC::CondCodes Condition) {
- BuildMI(LoadStoreBB, DL, TII->get(ARM::CMPrr), DestReg)
- .addReg(ValReg)
- .add(predOps(ARMCC::AL));
- BuildMI(LoadStoreBB, DL, TII->get(ARM::MOVr), DestReg)
- .addReg(ValReg)
- .add(predOps(Condition))
- .add(condCodeOp()); // 's' bit
- };
-
- switch (PseudoOp) {
- // No operations (swaps)
- case ARM::ATOMIC_SWAP_8:
- case ARM::ATOMIC_SWAP_16:
- case ARM::ATOMIC_SWAP_32:
- case ARM::ATOMIC_SWAP_64:
- llvm_unreachable("Swap should be handled at call site.");
- return;
-
- // Basic binary operation
- case ARM::ATOMIC_LOAD_ADD_8:
- case ARM::ATOMIC_LOAD_ADD_16:
- case ARM::ATOMIC_LOAD_ADD_32:
- case ARM::ATOMIC_LOAD_ADD_64:
- return BasicOp(ARM::ADDrr);
- case ARM::ATOMIC_LOAD_SUB_8:
- case ARM::ATOMIC_LOAD_SUB_16:
- case ARM::ATOMIC_LOAD_SUB_32:
- case ARM::ATOMIC_LOAD_SUB_64:
- return BasicOp(ARM::SUBrr);
- case ARM::ATOMIC_LOAD_AND_8:
- case ARM::ATOMIC_LOAD_AND_16:
- case ARM::ATOMIC_LOAD_AND_32:
- case ARM::ATOMIC_LOAD_AND_64:
- return BasicOp(ARM::ANDrr);
- case ARM::ATOMIC_LOAD_OR_8:
- case ARM::ATOMIC_LOAD_OR_16:
- case ARM::ATOMIC_LOAD_OR_32:
- case ARM::ATOMIC_LOAD_OR_64:
- return BasicOp(ARM::ORRrr);
- case ARM::ATOMIC_LOAD_XOR_8:
- case ARM::ATOMIC_LOAD_XOR_16:
- case ARM::ATOMIC_LOAD_XOR_32:
- case ARM::ATOMIC_LOAD_XOR_64:
- return BasicOp(ARM::EORrr);
- case ARM::ATOMIC_LOAD_FADD_16:
- case ARM::ATOMIC_LOAD_FADD_32:
- return BasicOp(ARM::VADDS);
- case ARM::ATOMIC_LOAD_FADD_64:
- return BasicOp(ARM::VADDD);
- case ARM::ATOMIC_LOAD_FSUB_16:
- case ARM::ATOMIC_LOAD_FSUB_32:
- return BasicOp(ARM::VSUBS);
- case ARM::ATOMIC_LOAD_FSUB_64:
- return BasicOp(ARM::VSUBD);
-
- // Minimum or maximum operations
- case ARM::ATOMIC_LOAD_MAX_8:
- case ARM::ATOMIC_LOAD_MAX_16:
- case ARM::ATOMIC_LOAD_MAX_32:
- case ARM::ATOMIC_LOAD_MAX_64:
- case ARM::ATOMIC_LOAD_UMAX_8:
- case ARM::ATOMIC_LOAD_UMAX_16:
- case ARM::ATOMIC_LOAD_UMAX_32:
- case ARM::ATOMIC_LOAD_UMAX_64:
- return MinMax(ARMCC::LE);
- case ARM::ATOMIC_LOAD_MIN_8:
- case ARM::ATOMIC_LOAD_MIN_16:
- case ARM::ATOMIC_LOAD_MIN_32:
- case ARM::ATOMIC_LOAD_MIN_64:
- case ARM::ATOMIC_LOAD_UMIN_8:
- case ARM::ATOMIC_LOAD_UMIN_16:
- case ARM::ATOMIC_LOAD_UMIN_32:
- case ARM::ATOMIC_LOAD_UMIN_64:
- return MinMax(ARMCC::GE);
-
- // NAND
- case ARM::ATOMIC_LOAD_NAND_8:
- case ARM::ATOMIC_LOAD_NAND_16:
- case ARM::ATOMIC_LOAD_NAND_32:
- case ARM::ATOMIC_LOAD_NAND_64:
- BuildMI(LoadStoreBB, DL, TII->get(ARM::ANDrr), DestReg)
- .addReg(DestReg, RegState::Kill)
- .addReg(ValReg)
- .add(predOps(ARMCC::AL))
- .addReg(0); // 's' bit
- BuildMI(LoadStoreBB, DL, TII->get(ARM::MVNr), DestReg)
- .addReg(DestReg, RegState::Kill)
- .add(predOps(ARMCC::AL))
- .addReg(0); // 's' bit
- return;
- }
-
- llvm_unreachable("unexpected opcode");
-}
-
-bool ARMExpandPseudo::ExpandAtomicOp(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MBBI,
- const int Size, const unsigned PseudoOp,
- MachineBasicBlock::iterator &NextMBBI) {
- assert(!STI->isThumb() && "atomic pseudo-instructions are ARM only");
-
- unsigned LdrexOp;
- unsigned StrexOp;
- switch (Size) {
- case 8:
- LdrexOp = ARM::LDREXB;
- StrexOp = ARM::STREXB;
- break;
- case 16:
- LdrexOp = ARM::LDREXH;
- StrexOp = ARM::STREXH;
- break;
- case 32:
- LdrexOp = ARM::LDREX;
- StrexOp = ARM::STREX;
- break;
- case 64:
- LdrexOp = ARM::LDREXD;
- StrexOp = ARM::STREXD;
- break;
- default:
- llvm_unreachable("Invalid Size");
- }
-
- MachineInstr &MI = *MBBI;
- DebugLoc DL = MI.getDebugLoc();
- MachineOperand &Dest = MI.getOperand(0);
- MachineOperand &Temp = MI.getOperand(1);
- // If Temp is a GPRPair, MiniTempReg is the first of the pair
- Register MiniTempReg =
- ARM::GPRPairRegClass.contains(Temp.getReg())
- ? (Register)TRI->getSubReg(Temp.getReg(), ARM::gsub_0)
- : Temp.getReg();
- assert(ARM::GPRRegClass.contains(MiniTempReg));
- Register AddrReg = MI.getOperand(2).getReg();
- Register ValReg = MI.getOperand(3).getReg();
-
- // TempReg is GPR and is used for load/store operations.
- // DestReg is either GPR or DPR and is used for arithmetic operations.
-
- // LoadStoreBB:
- // TempReg = LoadExclusive [AddrReg]
- // DestReg = mov TempReg
- // if xchg:
- // TempReg = mov ValReg
- // else:
- // DestReg = Operation DestReg, ValReg
- // TempReg = mov DestReg
- // MiniTempReg = StoreExclusive TempReg, [AddrReg]
- // cmp MiniTempReg, #0
- // bne LoadStoreBB
- // b DoneBB
- // DoneBB:
- // bx lr
-
- MachineFunction *MF = MBB.getParent();
- auto *LoadStoreBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
- auto *DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
-
- MF->insert(++MBB.getIterator(), LoadStoreBB);
- MF->insert(++LoadStoreBB->getIterator(), DoneBB);
-
- MachineInstrBuilder MIB;
- // LoadExclusive into temporary general purpose register (pair)
- MIB = BuildMI(LoadStoreBB, DL, TII->get(LdrexOp));
- addExclusiveRegPair(MIB, Temp.getReg(), RegState::Define, STI->isThumb(),
- TRI);
- MIB.addReg(AddrReg);
- MIB.add(predOps(ARMCC::AL));
-
- // Copy Temp into Dest. For floating point operations this is GPR -> DPR.
- TII->copyPhysReg(*LoadStoreBB, LoadStoreBB->end(), DL, Dest.getReg(),
- Temp.getReg(), true /* KillSrc */);
-
- const bool IsXchg =
- PseudoOp == ARM::ATOMIC_SWAP_8 || PseudoOp == ARM::ATOMIC_SWAP_16 ||
- PseudoOp == ARM::ATOMIC_SWAP_32 || PseudoOp == ARM::ATOMIC_SWAP_64;
-
- if (IsXchg) {
- // Copy ValReg into Temp. For floating point operations this is DPR -> GPR.
- TII->copyPhysReg(*LoadStoreBB, LoadStoreBB->end(), DL, Temp.getReg(),
- ValReg, false /* KillSrc */);
- } else {
- // Update the value in Dest with the results of the operation
- makeAtomicUpdateInstrs(PseudoOp, LoadStoreBB, DL, TII, Dest.getReg(),
- ValReg);
-
- // Copy Dest into Temp. For floating point operations this is DPR -> GPR.
- TII->copyPhysReg(*LoadStoreBB, LoadStoreBB->end(), DL, Temp.getReg(),
- Dest.getReg(), false /* KillSrc */);
- }
-
- // StoreExclusive Temp to Addr, store success in Temp (or MiniTempReg)
- MIB = BuildMI(LoadStoreBB, DL, TII->get(StrexOp));
- addExclusiveRegPair(MIB, MiniTempReg, RegState::Define, STI->isThumb(), TRI);
- MIB.addReg(Temp.getReg(), RegState::Kill);
- MIB.addReg(AddrReg);
- MIB.add(predOps(ARMCC::AL));
-
- // Compare to zero
- BuildMI(LoadStoreBB, DL, TII->get(ARM::CMPri))
- .addReg(MiniTempReg, RegState::Kill)
- .addImm(0)
- .add(predOps(ARMCC::AL));
-
- // Branch to LoadStoreBB if failed
- BuildMI(LoadStoreBB, DL, TII->get(ARM::Bcc))
- .addMBB(LoadStoreBB)
- .addImm(ARMCC::NE)
- .addReg(ARM::CPSR, RegState::Kill);
-
- // Branch to DoneBB if success
- BuildMI(LoadStoreBB, DL, TII->get(ARM::B)).addMBB(DoneBB);
-
- LoadStoreBB->addSuccessor(LoadStoreBB);
- LoadStoreBB->addSuccessor(DoneBB);
-
- // Copy remaining instructions in MBB into DoneBB
- DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());
- DoneBB->transferSuccessors(&MBB);
-
- MBB.addSuccessor(LoadStoreBB);
-
- NextMBBI = MBB.end();
- MI.eraseFromParent();
-
- // Recompute livein lists.
- LivePhysRegs LiveRegs;
- computeAndAddLiveIns(LiveRegs, *DoneBB);
- computeAndAddLiveIns(LiveRegs, *LoadStoreBB);
- // Do an extra pass around the loop to get loop carried registers right.
- LoadStoreBB->clearLiveIns();
- computeAndAddLiveIns(LiveRegs, *LoadStoreBB);
-
- return true;
+ MIB.addReg(Reg.getReg(), Flags);
}
/// Expand a 64-bit CMP_SWAP to an ldrexd/strexd loop.
unsigned LDREXD = IsThumb ? ARM::t2LDREXD : ARM::LDREXD;
MachineInstrBuilder MIB;
MIB = BuildMI(LoadCmpBB, DL, TII->get(LDREXD));
- addExclusiveRegPair(MIB, Dest.getReg(), RegState::Define, IsThumb, TRI);
+ addExclusiveRegPair(MIB, Dest, RegState::Define, IsThumb, TRI);
MIB.addReg(AddrReg).add(predOps(ARMCC::AL));
unsigned CMPrr = IsThumb ? ARM::tCMPhir : ARM::CMPrr;
unsigned STREXD = IsThumb ? ARM::t2STREXD : ARM::STREXD;
MIB = BuildMI(StoreBB, DL, TII->get(STREXD), TempReg);
unsigned Flags = getKillRegState(New.isDead());
- addExclusiveRegPair(MIB, New.getReg(), Flags, IsThumb, TRI);
+ addExclusiveRegPair(MIB, New, Flags, IsThumb, TRI);
MIB.addReg(AddrReg).add(predOps(ARMCC::AL));
unsigned CMPri = IsThumb ? ARM::t2CMPri : ARM::CMPri;
case ARM::CMP_SWAP_64:
return ExpandCMP_SWAP_64(MBB, MBBI, NextMBBI);
- case ARM::ATOMIC_LOAD_ADD_8:
- case ARM::ATOMIC_LOAD_AND_8:
- case ARM::ATOMIC_LOAD_MAX_8:
- case ARM::ATOMIC_LOAD_MIN_8:
- case ARM::ATOMIC_LOAD_NAND_8:
- case ARM::ATOMIC_LOAD_OR_8:
- case ARM::ATOMIC_LOAD_SUB_8:
- case ARM::ATOMIC_LOAD_UMAX_8:
- case ARM::ATOMIC_LOAD_UMIN_8:
- case ARM::ATOMIC_LOAD_XOR_8:
- case ARM::ATOMIC_SWAP_8:
- return ExpandAtomicOp(MBB, MBBI, 8, Opcode, NextMBBI);
-
- case ARM::ATOMIC_LOAD_ADD_16:
- case ARM::ATOMIC_LOAD_AND_16:
- case ARM::ATOMIC_LOAD_FADD_16:
- case ARM::ATOMIC_LOAD_FSUB_16:
- case ARM::ATOMIC_LOAD_MAX_16:
- case ARM::ATOMIC_LOAD_MIN_16:
- case ARM::ATOMIC_LOAD_NAND_16:
- case ARM::ATOMIC_LOAD_OR_16:
- case ARM::ATOMIC_LOAD_SUB_16:
- case ARM::ATOMIC_LOAD_UMAX_16:
- case ARM::ATOMIC_LOAD_UMIN_16:
- case ARM::ATOMIC_LOAD_XOR_16:
- case ARM::ATOMIC_SWAP_16:
- return ExpandAtomicOp(MBB, MBBI, 16, Opcode, NextMBBI);
-
- case ARM::ATOMIC_LOAD_ADD_32:
- case ARM::ATOMIC_LOAD_AND_32:
- case ARM::ATOMIC_LOAD_FADD_32:
- case ARM::ATOMIC_LOAD_FSUB_32:
- case ARM::ATOMIC_LOAD_MAX_32:
- case ARM::ATOMIC_LOAD_MIN_32:
- case ARM::ATOMIC_LOAD_NAND_32:
- case ARM::ATOMIC_LOAD_OR_32:
- case ARM::ATOMIC_LOAD_SUB_32:
- case ARM::ATOMIC_LOAD_UMAX_32:
- case ARM::ATOMIC_LOAD_UMIN_32:
- case ARM::ATOMIC_LOAD_XOR_32:
- case ARM::ATOMIC_SWAP_32:
- return ExpandAtomicOp(MBB, MBBI, 32, Opcode, NextMBBI);
-
- case ARM::ATOMIC_LOAD_ADD_64:
- case ARM::ATOMIC_LOAD_AND_64:
- case ARM::ATOMIC_LOAD_FADD_64:
- case ARM::ATOMIC_LOAD_FSUB_64:
- case ARM::ATOMIC_LOAD_MAX_64:
- case ARM::ATOMIC_LOAD_MIN_64:
- case ARM::ATOMIC_LOAD_NAND_64:
- case ARM::ATOMIC_LOAD_OR_64:
- case ARM::ATOMIC_LOAD_SUB_64:
- case ARM::ATOMIC_LOAD_UMAX_64:
- case ARM::ATOMIC_LOAD_UMIN_64:
- case ARM::ATOMIC_LOAD_XOR_64:
- case ARM::ATOMIC_SWAP_64:
- return ExpandAtomicOp(MBB, MBBI, 64, Opcode, NextMBBI);
-
case ARM::tBL_PUSHLR:
case ARM::BL_PUSHLR: {
const bool Thumb = Opcode == ARM::tBL_PUSHLR;
+++ /dev/null
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-
-; Test the instruction sequences produced by atomicrmw instructions. In
-; particular, ensure there are no stores/spills inserted between the exclusive
-; load and stores, which would invalidate the exclusive monitor.
-
-; atomicrmw xchg for floating point types are not implemented yet, so the tests
-; are commented.
-
-; RUN: llc -O0 -o - %s | FileCheck %s --check-prefix=CHECK
-target triple = "armv7-none-eabi"
-
-@atomic_i8 = external global i8
-@atomic_i16 = external global i16
-@atomic_i32 = external global i32
-@atomic_i64 = external global i64
-
-@atomic_half = external global half
-@atomic_float = external global float
-@atomic_double = external global double
-
-define i8 @test_xchg_i8() {
-; CHECK-LABEL: test_xchg_i8:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i8
-; CHECK-NEXT: movt r2, :upper16:atomic_i8
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB0_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexb r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: mov r1, r3
-; CHECK-NEXT: strexb r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB0_1
-; CHECK-NEXT: b .LBB0_2
-; CHECK-NEXT: .LBB0_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw xchg i8* @atomic_i8, i8 1 monotonic
- ret i8 %0
-}
-define i8 @test_add_i8() {
-; CHECK-LABEL: test_add_i8:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i8
-; CHECK-NEXT: movt r2, :upper16:atomic_i8
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB1_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexb r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: add r0, r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strexb r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB1_1
-; CHECK-NEXT: b .LBB1_2
-; CHECK-NEXT: .LBB1_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw add i8* @atomic_i8, i8 1 monotonic
- ret i8 %0
-}
-define i8 @test_sub_i8() {
-; CHECK-LABEL: test_sub_i8:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i8
-; CHECK-NEXT: movt r2, :upper16:atomic_i8
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB2_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexb r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: sub r0, r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strexb r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB2_1
-; CHECK-NEXT: b .LBB2_2
-; CHECK-NEXT: .LBB2_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw sub i8* @atomic_i8, i8 1 monotonic
- ret i8 %0
-}
-define i8 @test_and_i8() {
-; CHECK-LABEL: test_and_i8:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i8
-; CHECK-NEXT: movt r2, :upper16:atomic_i8
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB3_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexb r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: and r0, r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strexb r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB3_1
-; CHECK-NEXT: b .LBB3_2
-; CHECK-NEXT: .LBB3_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw and i8* @atomic_i8, i8 1 monotonic
- ret i8 %0
-}
-define i8 @test_nand_i8() {
-; CHECK-LABEL: test_nand_i8:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i8
-; CHECK-NEXT: movt r2, :upper16:atomic_i8
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB4_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexb r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: and r0, r0, r3
-; CHECK-NEXT: mvn r0, r0
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strexb r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB4_1
-; CHECK-NEXT: b .LBB4_2
-; CHECK-NEXT: .LBB4_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw nand i8* @atomic_i8, i8 1 monotonic
- ret i8 %0
-}
-define i8 @test_or_i8() {
-; CHECK-LABEL: test_or_i8:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i8
-; CHECK-NEXT: movt r2, :upper16:atomic_i8
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB5_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexb r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: orr r0, r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strexb r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB5_1
-; CHECK-NEXT: b .LBB5_2
-; CHECK-NEXT: .LBB5_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw or i8* @atomic_i8, i8 1 monotonic
- ret i8 %0
-}
-define i8 @test_xor_i8() {
-; CHECK-LABEL: test_xor_i8:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i8
-; CHECK-NEXT: movt r2, :upper16:atomic_i8
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB6_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexb r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: eor r0, r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strexb r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB6_1
-; CHECK-NEXT: b .LBB6_2
-; CHECK-NEXT: .LBB6_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw xor i8* @atomic_i8, i8 1 monotonic
- ret i8 %0
-}
-define i8 @test_max_i8() {
-; CHECK-LABEL: test_max_i8:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i8
-; CHECK-NEXT: movt r2, :upper16:atomic_i8
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB7_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexb r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: cmp r0, r3
-; CHECK-NEXT: movle r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strexb r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB7_1
-; CHECK-NEXT: b .LBB7_2
-; CHECK-NEXT: .LBB7_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw max i8* @atomic_i8, i8 1 monotonic
- ret i8 %0
-}
-define i8 @test_min_i8() {
-; CHECK-LABEL: test_min_i8:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i8
-; CHECK-NEXT: movt r2, :upper16:atomic_i8
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB8_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexb r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: cmp r0, r3
-; CHECK-NEXT: movge r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strexb r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB8_1
-; CHECK-NEXT: b .LBB8_2
-; CHECK-NEXT: .LBB8_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw min i8* @atomic_i8, i8 1 monotonic
- ret i8 %0
-}
-define i8 @test_umax_i8() {
-; CHECK-LABEL: test_umax_i8:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i8
-; CHECK-NEXT: movt r2, :upper16:atomic_i8
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB9_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexb r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: cmp r0, r3
-; CHECK-NEXT: movle r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strexb r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB9_1
-; CHECK-NEXT: b .LBB9_2
-; CHECK-NEXT: .LBB9_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw umax i8* @atomic_i8, i8 1 monotonic
- ret i8 %0
-}
-define i8 @test_umin_i8() {
-; CHECK-LABEL: test_umin_i8:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i8
-; CHECK-NEXT: movt r2, :upper16:atomic_i8
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB10_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexb r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: cmp r0, r3
-; CHECK-NEXT: movge r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strexb r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB10_1
-; CHECK-NEXT: b .LBB10_2
-; CHECK-NEXT: .LBB10_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw umin i8* @atomic_i8, i8 1 monotonic
- ret i8 %0
-}
-
-
-define i16 @test_xchg_i16() {
-; CHECK-LABEL: test_xchg_i16:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i16
-; CHECK-NEXT: movt r2, :upper16:atomic_i16
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB11_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexh r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: mov r1, r3
-; CHECK-NEXT: strexh r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB11_1
-; CHECK-NEXT: b .LBB11_2
-; CHECK-NEXT: .LBB11_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw xchg i16* @atomic_i16, i16 1 monotonic
- ret i16 %0
-}
-define i16 @test_add_i16() {
-; CHECK-LABEL: test_add_i16:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i16
-; CHECK-NEXT: movt r2, :upper16:atomic_i16
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB12_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexh r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: add r0, r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strexh r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB12_1
-; CHECK-NEXT: b .LBB12_2
-; CHECK-NEXT: .LBB12_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw add i16* @atomic_i16, i16 1 monotonic
- ret i16 %0
-}
-define i16 @test_sub_i16() {
-; CHECK-LABEL: test_sub_i16:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i16
-; CHECK-NEXT: movt r2, :upper16:atomic_i16
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB13_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexh r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: sub r0, r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strexh r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB13_1
-; CHECK-NEXT: b .LBB13_2
-; CHECK-NEXT: .LBB13_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw sub i16* @atomic_i16, i16 1 monotonic
- ret i16 %0
-}
-define i16 @test_and_i16() {
-; CHECK-LABEL: test_and_i16:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i16
-; CHECK-NEXT: movt r2, :upper16:atomic_i16
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB14_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexh r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: and r0, r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strexh r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB14_1
-; CHECK-NEXT: b .LBB14_2
-; CHECK-NEXT: .LBB14_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw and i16* @atomic_i16, i16 1 monotonic
- ret i16 %0
-}
-define i16 @test_nand_i16() {
-; CHECK-LABEL: test_nand_i16:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i16
-; CHECK-NEXT: movt r2, :upper16:atomic_i16
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB15_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexh r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: and r0, r0, r3
-; CHECK-NEXT: mvn r0, r0
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strexh r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB15_1
-; CHECK-NEXT: b .LBB15_2
-; CHECK-NEXT: .LBB15_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw nand i16* @atomic_i16, i16 1 monotonic
- ret i16 %0
-}
-define i16 @test_or_i16() {
-; CHECK-LABEL: test_or_i16:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i16
-; CHECK-NEXT: movt r2, :upper16:atomic_i16
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB16_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexh r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: orr r0, r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strexh r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB16_1
-; CHECK-NEXT: b .LBB16_2
-; CHECK-NEXT: .LBB16_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw or i16* @atomic_i16, i16 1 monotonic
- ret i16 %0
-}
-define i16 @test_xor_i16() {
-; CHECK-LABEL: test_xor_i16:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i16
-; CHECK-NEXT: movt r2, :upper16:atomic_i16
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB17_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexh r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: eor r0, r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strexh r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB17_1
-; CHECK-NEXT: b .LBB17_2
-; CHECK-NEXT: .LBB17_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw xor i16* @atomic_i16, i16 1 monotonic
- ret i16 %0
-}
-define i16 @test_max_i16() {
-; CHECK-LABEL: test_max_i16:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i16
-; CHECK-NEXT: movt r2, :upper16:atomic_i16
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB18_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexh r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: cmp r0, r3
-; CHECK-NEXT: movle r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strexh r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB18_1
-; CHECK-NEXT: b .LBB18_2
-; CHECK-NEXT: .LBB18_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw max i16* @atomic_i16, i16 1 monotonic
- ret i16 %0
-}
-define i16 @test_min_i16() {
-; CHECK-LABEL: test_min_i16:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i16
-; CHECK-NEXT: movt r2, :upper16:atomic_i16
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB19_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexh r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: cmp r0, r3
-; CHECK-NEXT: movge r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strexh r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB19_1
-; CHECK-NEXT: b .LBB19_2
-; CHECK-NEXT: .LBB19_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw min i16* @atomic_i16, i16 1 monotonic
- ret i16 %0
-}
-define i16 @test_umax_i16() {
-; CHECK-LABEL: test_umax_i16:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i16
-; CHECK-NEXT: movt r2, :upper16:atomic_i16
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB20_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexh r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: cmp r0, r3
-; CHECK-NEXT: movle r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strexh r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB20_1
-; CHECK-NEXT: b .LBB20_2
-; CHECK-NEXT: .LBB20_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw umax i16* @atomic_i16, i16 1 monotonic
- ret i16 %0
-}
-define i16 @test_umin_i16() {
-; CHECK-LABEL: test_umin_i16:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i16
-; CHECK-NEXT: movt r2, :upper16:atomic_i16
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB21_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexh r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: cmp r0, r3
-; CHECK-NEXT: movge r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strexh r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB21_1
-; CHECK-NEXT: b .LBB21_2
-; CHECK-NEXT: .LBB21_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw umin i16* @atomic_i16, i16 1 monotonic
- ret i16 %0
-}
-
-
-define i32 @test_xchg_i32() {
-; CHECK-LABEL: test_xchg_i32:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i32
-; CHECK-NEXT: movt r2, :upper16:atomic_i32
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB22_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrex r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: mov r1, r3
-; CHECK-NEXT: strex r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB22_1
-; CHECK-NEXT: b .LBB22_2
-; CHECK-NEXT: .LBB22_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw xchg i32* @atomic_i32, i32 1 monotonic
- ret i32 %0
-}
-define i32 @test_add_i32() {
-; CHECK-LABEL: test_add_i32:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i32
-; CHECK-NEXT: movt r2, :upper16:atomic_i32
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB23_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrex r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: add r0, r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strex r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB23_1
-; CHECK-NEXT: b .LBB23_2
-; CHECK-NEXT: .LBB23_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw add i32* @atomic_i32, i32 1 monotonic
- ret i32 %0
-}
-define i32 @test_sub_i32() {
-; CHECK-LABEL: test_sub_i32:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i32
-; CHECK-NEXT: movt r2, :upper16:atomic_i32
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB24_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrex r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: sub r0, r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strex r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB24_1
-; CHECK-NEXT: b .LBB24_2
-; CHECK-NEXT: .LBB24_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw sub i32* @atomic_i32, i32 1 monotonic
- ret i32 %0
-}
-define i32 @test_and_i32() {
-; CHECK-LABEL: test_and_i32:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i32
-; CHECK-NEXT: movt r2, :upper16:atomic_i32
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB25_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrex r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: and r0, r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strex r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB25_1
-; CHECK-NEXT: b .LBB25_2
-; CHECK-NEXT: .LBB25_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw and i32* @atomic_i32, i32 1 monotonic
- ret i32 %0
-}
-define i32 @test_nand_i32() {
-; CHECK-LABEL: test_nand_i32:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i32
-; CHECK-NEXT: movt r2, :upper16:atomic_i32
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB26_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrex r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: and r0, r0, r3
-; CHECK-NEXT: mvn r0, r0
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strex r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB26_1
-; CHECK-NEXT: b .LBB26_2
-; CHECK-NEXT: .LBB26_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw nand i32* @atomic_i32, i32 1 monotonic
- ret i32 %0
-}
-define i32 @test_or_i32() {
-; CHECK-LABEL: test_or_i32:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i32
-; CHECK-NEXT: movt r2, :upper16:atomic_i32
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB27_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrex r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: orr r0, r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strex r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB27_1
-; CHECK-NEXT: b .LBB27_2
-; CHECK-NEXT: .LBB27_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw or i32* @atomic_i32, i32 1 monotonic
- ret i32 %0
-}
-define i32 @test_xor_i32() {
-; CHECK-LABEL: test_xor_i32:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i32
-; CHECK-NEXT: movt r2, :upper16:atomic_i32
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB28_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrex r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: eor r0, r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strex r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB28_1
-; CHECK-NEXT: b .LBB28_2
-; CHECK-NEXT: .LBB28_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw xor i32* @atomic_i32, i32 1 monotonic
- ret i32 %0
-}
-define i32 @test_max_i32() {
-; CHECK-LABEL: test_max_i32:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i32
-; CHECK-NEXT: movt r2, :upper16:atomic_i32
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB29_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrex r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: cmp r0, r3
-; CHECK-NEXT: movle r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strex r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB29_1
-; CHECK-NEXT: b .LBB29_2
-; CHECK-NEXT: .LBB29_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw max i32* @atomic_i32, i32 1 monotonic
- ret i32 %0
-}
-define i32 @test_min_i32() {
-; CHECK-LABEL: test_min_i32:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i32
-; CHECK-NEXT: movt r2, :upper16:atomic_i32
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB30_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrex r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: cmp r0, r3
-; CHECK-NEXT: movge r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strex r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB30_1
-; CHECK-NEXT: b .LBB30_2
-; CHECK-NEXT: .LBB30_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw min i32* @atomic_i32, i32 1 monotonic
- ret i32 %0
-}
-define i32 @test_umax_i32() {
-; CHECK-LABEL: test_umax_i32:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i32
-; CHECK-NEXT: movt r2, :upper16:atomic_i32
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB31_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrex r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: cmp r0, r3
-; CHECK-NEXT: movle r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strex r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB31_1
-; CHECK-NEXT: b .LBB31_2
-; CHECK-NEXT: .LBB31_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw umax i32* @atomic_i32, i32 1 monotonic
- ret i32 %0
-}
-define i32 @test_umin_i32() {
-; CHECK-LABEL: test_umin_i32:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_i32
-; CHECK-NEXT: movt r2, :upper16:atomic_i32
-; CHECK-NEXT: mov r3, #1
-; CHECK-NEXT: .LBB32_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrex r1, [r2]
-; CHECK-NEXT: mov r0, r1
-; CHECK-NEXT: cmp r0, r3
-; CHECK-NEXT: movge r0, r3
-; CHECK-NEXT: mov r1, r0
-; CHECK-NEXT: strex r1, r1, [r2]
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: bne .LBB32_1
-; CHECK-NEXT: b .LBB32_2
-; CHECK-NEXT: .LBB32_2: @ %entry
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw umin i32* @atomic_i32, i32 1 monotonic
- ret i32 %0
-}
-
-
-
-define i64 @test_xchg_i64() {
-; CHECK-LABEL: test_xchg_i64:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: push {r11, lr}
-; CHECK-NEXT: movw r0, :lower16:atomic_i64
-; CHECK-NEXT: movt r0, :upper16:atomic_i64
-; CHECK-NEXT: mov r2, #1
-; CHECK-NEXT: mov r3, #0
-; CHECK-NEXT: bl __sync_lock_test_and_set_8
-; CHECK-NEXT: pop {r11, pc}
-entry:
- %0 = atomicrmw xchg i64* @atomic_i64, i64 1 monotonic
- ret i64 %0
-}
-define i64 @test_add_i64() {
-; CHECK-LABEL: test_add_i64:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: push {r11, lr}
-; CHECK-NEXT: movw r0, :lower16:atomic_i64
-; CHECK-NEXT: movt r0, :upper16:atomic_i64
-; CHECK-NEXT: mov r2, #1
-; CHECK-NEXT: mov r3, #0
-; CHECK-NEXT: bl __sync_fetch_and_add_8
-; CHECK-NEXT: pop {r11, pc}
-entry:
- %0 = atomicrmw add i64* @atomic_i64, i64 1 monotonic
- ret i64 %0
-}
-define i64 @test_sub_i64() {
-; CHECK-LABEL: test_sub_i64:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: push {r11, lr}
-; CHECK-NEXT: movw r0, :lower16:atomic_i64
-; CHECK-NEXT: movt r0, :upper16:atomic_i64
-; CHECK-NEXT: mov r2, #1
-; CHECK-NEXT: mov r3, #0
-; CHECK-NEXT: bl __sync_fetch_and_sub_8
-; CHECK-NEXT: pop {r11, pc}
-entry:
- %0 = atomicrmw sub i64* @atomic_i64, i64 1 monotonic
- ret i64 %0
-}
-define i64 @test_and_i64() {
-; CHECK-LABEL: test_and_i64:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: push {r11, lr}
-; CHECK-NEXT: movw r0, :lower16:atomic_i64
-; CHECK-NEXT: movt r0, :upper16:atomic_i64
-; CHECK-NEXT: mov r2, #1
-; CHECK-NEXT: mov r3, #0
-; CHECK-NEXT: bl __sync_fetch_and_and_8
-; CHECK-NEXT: pop {r11, pc}
-entry:
- %0 = atomicrmw and i64* @atomic_i64, i64 1 monotonic
- ret i64 %0
-}
-define i64 @test_nand_i64() {
-; CHECK-LABEL: test_nand_i64:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: push {r11, lr}
-; CHECK-NEXT: movw r0, :lower16:atomic_i64
-; CHECK-NEXT: movt r0, :upper16:atomic_i64
-; CHECK-NEXT: mov r2, #1
-; CHECK-NEXT: mov r3, #0
-; CHECK-NEXT: bl __sync_fetch_and_nand_8
-; CHECK-NEXT: pop {r11, pc}
-entry:
- %0 = atomicrmw nand i64* @atomic_i64, i64 1 monotonic
- ret i64 %0
-}
-define i64 @test_or_i64() {
-; CHECK-LABEL: test_or_i64:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: push {r11, lr}
-; CHECK-NEXT: movw r0, :lower16:atomic_i64
-; CHECK-NEXT: movt r0, :upper16:atomic_i64
-; CHECK-NEXT: mov r2, #1
-; CHECK-NEXT: mov r3, #0
-; CHECK-NEXT: bl __sync_fetch_and_or_8
-; CHECK-NEXT: pop {r11, pc}
-entry:
- %0 = atomicrmw or i64* @atomic_i64, i64 1 monotonic
- ret i64 %0
-}
-define i64 @test_xor_i64() {
-; CHECK-LABEL: test_xor_i64:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: push {r11, lr}
-; CHECK-NEXT: movw r0, :lower16:atomic_i64
-; CHECK-NEXT: movt r0, :upper16:atomic_i64
-; CHECK-NEXT: mov r2, #1
-; CHECK-NEXT: mov r3, #0
-; CHECK-NEXT: bl __sync_fetch_and_xor_8
-; CHECK-NEXT: pop {r11, pc}
-entry:
- %0 = atomicrmw xor i64* @atomic_i64, i64 1 monotonic
- ret i64 %0
-}
-
-
-; ; Test floats
-; define half @test_xchg_half() {
-; entry:
-; %0 = atomicrmw xchg half* @atomic_half, half 1.0 monotonic
-; ret half %0
-; }
-define half @test_fadd_half() {
-; CHECK-LABEL: test_fadd_half:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: push {r11, lr}
-; CHECK-NEXT: movw r1, :lower16:atomic_half
-; CHECK-NEXT: movt r1, :upper16:atomic_half
-; CHECK-NEXT: vmov.f32 s2, #1.000000e+00
-; CHECK-NEXT: .LBB40_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexh r0, [r1]
-; CHECK-NEXT: vmov s0, r0
-; CHECK-NEXT: vadd.f32 s0, s0, s2
-; CHECK-NEXT: vmov r0, s0
-; CHECK-NEXT: strexh r0, r0, [r1]
-; CHECK-NEXT: cmp r0, #0
-; CHECK-NEXT: bne .LBB40_1
-; CHECK-NEXT: b .LBB40_2
-; CHECK-NEXT: .LBB40_2: @ %entry
-; CHECK-NEXT: vmov r0, s0
-; CHECK-NEXT: bl __gnu_f2h_ieee
-; CHECK-NEXT: pop {r11, pc}
-entry:
- %0 = atomicrmw fadd half* @atomic_half, half 1.0 monotonic
- ret half %0
-}
-define half @test_fsub_half() {
-; CHECK-LABEL: test_fsub_half:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: push {r11, lr}
-; CHECK-NEXT: movw r1, :lower16:atomic_half
-; CHECK-NEXT: movt r1, :upper16:atomic_half
-; CHECK-NEXT: vmov.f32 s2, #1.000000e+00
-; CHECK-NEXT: .LBB41_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexh r0, [r1]
-; CHECK-NEXT: vmov s0, r0
-; CHECK-NEXT: vsub.f32 s0, s0, s2
-; CHECK-NEXT: vmov r0, s0
-; CHECK-NEXT: strexh r0, r0, [r1]
-; CHECK-NEXT: cmp r0, #0
-; CHECK-NEXT: bne .LBB41_1
-; CHECK-NEXT: b .LBB41_2
-; CHECK-NEXT: .LBB41_2: @ %entry
-; CHECK-NEXT: vmov r0, s0
-; CHECK-NEXT: bl __gnu_f2h_ieee
-; CHECK-NEXT: pop {r11, pc}
-entry:
- %0 = atomicrmw fsub half* @atomic_half, half 1.0 monotonic
- ret half %0
-}
-; define float @test_xchg_float() {
-; entry:
-; %0 = atomicrmw xchg float* @atomic_float, float 1.0 monotonic
-; ret float %0
-; }
-define float @test_fadd_float() {
-; CHECK-LABEL: test_fadd_float:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r1, :lower16:atomic_float
-; CHECK-NEXT: movt r1, :upper16:atomic_float
-; CHECK-NEXT: vmov.f32 s2, #1.000000e+00
-; CHECK-NEXT: .LBB42_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrex r0, [r1]
-; CHECK-NEXT: vmov s0, r0
-; CHECK-NEXT: vadd.f32 s0, s0, s2
-; CHECK-NEXT: vmov r0, s0
-; CHECK-NEXT: strex r0, r0, [r1]
-; CHECK-NEXT: cmp r0, #0
-; CHECK-NEXT: bne .LBB42_1
-; CHECK-NEXT: b .LBB42_2
-; CHECK-NEXT: .LBB42_2: @ %entry
-; CHECK-NEXT: vmov r0, s0
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw fadd float* @atomic_float, float 1.0 monotonic
- ret float %0
-}
-define float @test_fsub_float() {
-; CHECK-LABEL: test_fsub_float:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r1, :lower16:atomic_float
-; CHECK-NEXT: movt r1, :upper16:atomic_float
-; CHECK-NEXT: vmov.f32 s2, #1.000000e+00
-; CHECK-NEXT: .LBB43_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrex r0, [r1]
-; CHECK-NEXT: vmov s0, r0
-; CHECK-NEXT: vsub.f32 s0, s0, s2
-; CHECK-NEXT: vmov r0, s0
-; CHECK-NEXT: strex r0, r0, [r1]
-; CHECK-NEXT: cmp r0, #0
-; CHECK-NEXT: bne .LBB43_1
-; CHECK-NEXT: b .LBB43_2
-; CHECK-NEXT: .LBB43_2: @ %entry
-; CHECK-NEXT: vmov r0, s0
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw fsub float* @atomic_float, float 1.0 monotonic
- ret float %0
-}
-; define double @test_xchg_double() {
-; entry:
-; %0 = atomicrmw xchg double* @atomic_double, double 1.0 monotonic
-; ret double %0
-; }
-define double @test_fadd_double() {
-; CHECK-LABEL: test_fadd_double:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_double
-; CHECK-NEXT: movt r2, :upper16:atomic_double
-; CHECK-NEXT: vmov.f64 d17, #1.000000e+00
-; CHECK-NEXT: .LBB44_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexd r0, r1, [r2]
-; CHECK-NEXT: vmov d16, r0, r1
-; CHECK-NEXT: vadd.f64 d16, d16, d17
-; CHECK-NEXT: vmov r0, r1, d16
-; CHECK-NEXT: strexd r0, r0, r1, [r2]
-; CHECK-NEXT: cmp r0, #0
-; CHECK-NEXT: bne .LBB44_1
-; CHECK-NEXT: b .LBB44_2
-; CHECK-NEXT: .LBB44_2: @ %entry
-; CHECK-NEXT: vmov r0, r1, d16
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw fadd double* @atomic_double, double 1.0 monotonic
- ret double %0
-}
-define double @test_fsub_double() {
-; CHECK-LABEL: test_fsub_double:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: movw r2, :lower16:atomic_double
-; CHECK-NEXT: movt r2, :upper16:atomic_double
-; CHECK-NEXT: vmov.f64 d17, #1.000000e+00
-; CHECK-NEXT: .LBB45_1: @ %entry
-; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexd r0, r1, [r2]
-; CHECK-NEXT: vmov d16, r0, r1
-; CHECK-NEXT: vsub.f64 d16, d16, d17
-; CHECK-NEXT: vmov r0, r1, d16
-; CHECK-NEXT: strexd r0, r0, r1, [r2]
-; CHECK-NEXT: cmp r0, #0
-; CHECK-NEXT: bne .LBB45_1
-; CHECK-NEXT: b .LBB45_2
-; CHECK-NEXT: .LBB45_2: @ %entry
-; CHECK-NEXT: vmov r0, r1, d16
-; CHECK-NEXT: bx lr
-entry:
- %0 = atomicrmw fsub double* @atomic_double, double 1.0 monotonic
- ret double %0
-}