diff --git a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp --- a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -1579,8 +1579,7 @@ MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(UxtOp), DesiredReg) .addReg(DesiredReg, RegState::Kill); - if (!IsThumb) - MIB.addImm(0); + MIB.addImm(0); // A1/T2 rotate operand MIB.add(predOps(ARMCC::AL)); } @@ -2782,14 +2781,14 @@ case ARM::CMP_SWAP_8: if (STI->isThumb()) return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREXB, ARM::t2STREXB, - ARM::tUXTB, NextMBBI); + ARM::t2UXTB, NextMBBI); else return ExpandCMP_SWAP(MBB, MBBI, ARM::LDREXB, ARM::STREXB, ARM::UXTB, NextMBBI); case ARM::CMP_SWAP_16: if (STI->isThumb()) return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREXH, ARM::t2STREXH, - ARM::tUXTH, NextMBBI); + ARM::t2UXTH, NextMBBI); else return ExpandCMP_SWAP(MBB, MBBI, ARM::LDREXH, ARM::STREXH, ARM::UXTH, NextMBBI); diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -19120,6 +19120,14 @@ if (AI->isFloatingPointOperation()) return AtomicExpansionKind::CmpXChg; + // At -O0, fast-regalloc cannot cope with the live vregs necessary to + // implement atomicrmw without spilling. If the target address is also on the + // stack and close enough to the spill slot, this can lead to a situation + // where the monitor always gets cleared and the atomic operation can never + // succeed. So at -O0 lower this operation to a CAS loop. + if (getTargetMachine().getOptLevel() == CodeGenOpt::None) + return AtomicExpansionKind::CmpXChg; + unsigned Size = AI->getType()->getPrimitiveSizeInBits(); bool hasAtomicRMW = !Subtarget->isThumb() || Subtarget->hasV8MBaselineOps(); return (Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW) diff --git a/llvm/test/CodeGen/ARM/atomicrmw_exclusive_monitor_ints.ll b/llvm/test/CodeGen/ARM/atomicrmw_exclusive_monitor_ints.ll --- a/llvm/test/CodeGen/ARM/atomicrmw_exclusive_monitor_ints.ll +++ b/llvm/test/CodeGen/ARM/atomicrmw_exclusive_monitor_ints.ll @@ -15,7 +15,7 @@ define i8 @test_xchg_i8() { ; CHECK-LABEL: test_xchg_i8: ; ARM: ldrexb -; ARM: str +; ARM-NOT: str ; ARM: strexb ; THUMB1: bl __sync_lock_test_and_set_1 entry: @@ -25,7 +25,7 @@ define i8 @test_add_i8() { ; CHECK-LABEL: test_add_i8: ; ARM: ldrexb -; ARM: str +; ARM-NOT: str ; ARM: strexb ; THUMB1: bl __sync_fetch_and_add_1 entry: @@ -35,7 +35,7 @@ define i8 @test_sub_i8() { ; CHECK-LABEL: test_sub_i8: ; ARM: ldrexb -; ARM: str +; ARM-NOT: str ; ARM: strexb ; THUMB1: bl __sync_fetch_and_sub_1 entry: @@ -45,7 +45,7 @@ define i8 @test_and_i8() { ; CHECK-LABEL: test_and_i8: ; ARM: ldrexb -; ARM: str +; ARM-NOT: str ; ARM: strexb ; THUMB1: bl __sync_fetch_and_and_1 entry: @@ -55,7 +55,7 @@ define i8 @test_nand_i8() { ; CHECK-LABEL: test_nand_i8: ; ARM: ldrexb -; ARM: str +; ARM-NOT: str ; ARM: strexb ; THUMB1: bl __sync_fetch_and_nand_1 entry: @@ -65,7 +65,7 @@ define i8 @test_or_i8() { ; CHECK-LABEL: test_or_i8: ; ARM: ldrexb -; ARM: str +; ARM-NOT: str ; ARM: strexb ; THUMB1: bl __sync_fetch_and_or_1 entry: @@ -75,7 +75,7 @@ define i8 @test_xor_i8() { ; CHECK-LABEL: test_xor_i8: ; ARM: ldrexb -; ARM: str +; ARM-NOT: str ; ARM: strexb ; THUMB1: bl __sync_fetch_and_xor_1 entry: @@ -85,7 +85,7 @@ define i8 @test_max_i8() { ; CHECK-LABEL: test_max_i8: ; ARM: ldrexb -; ARM: str +; ARM-NOT: str ; ARM: strexb ; THUMB1: bl __sync_fetch_and_max_1 entry: @@ -95,7 +95,7 @@ define i8 @test_min_i8() { ; CHECK-LABEL: test_min_i8: ; ARM: ldrexb -; ARM: str +; ARM-NOT: str ; ARM: strexb ; THUMB1: bl __sync_fetch_and_min_1 entry: @@ -105,7 +105,7 @@ define i8 @test_umax_i8() { ; CHECK-LABEL: test_umax_i8: ; ARM: ldrexb -; ARM: str +; ARM-NOT: str ; ARM: strexb ; THUMB1: bl __sync_fetch_and_umax_1 entry: @@ -115,7 +115,7 @@ define i8 @test_umin_i8() { ; CHECK-LABEL: test_umin_i8: ; ARM: ldrexb -; ARM: str +; ARM-NOT: str ; ARM: strexb ; THUMB1: bl __sync_fetch_and_umin_1 entry: @@ -127,7 +127,7 @@ define i16 @test_xchg_i16() { ; CHECK-LABEL: test_xchg_i16: ; ARM: ldrexh -; ARM: str +; ARM-NOT: str ; ARM: strexh ; THUMB1: bl __sync_lock_test_and_set_2 entry: @@ -137,7 +137,7 @@ define i16 @test_add_i16() { ; CHECK-LABEL: test_add_i16: ; ARM: ldrexh -; ARM: str +; ARM-NOT: str ; ARM: strexh ; THUMB1: bl __sync_fetch_and_add_2 entry: @@ -147,7 +147,7 @@ define i16 @test_sub_i16() { ; CHECK-LABEL: test_sub_i16: ; ARM: ldrexh -; ARM: str +; ARM-NOT: str ; ARM: strexh ; THUMB1: bl __sync_fetch_and_sub_2 entry: @@ -157,7 +157,7 @@ define i16 @test_and_i16() { ; CHECK-LABEL: test_and_i16: ; ARM: ldrexh -; ARM: str +; ARM-NOT: str ; ARM: strexh ; THUMB1: bl __sync_fetch_and_and_2 entry: @@ -167,7 +167,7 @@ define i16 @test_nand_i16() { ; CHECK-LABEL: test_nand_i16: ; ARM: ldrexh -; ARM: str +; ARM-NOT: str ; ARM: strexh ; THUMB1: bl __sync_fetch_and_nand_2 entry: @@ -177,7 +177,7 @@ define i16 @test_or_i16() { ; CHECK-LABEL: test_or_i16: ; ARM: ldrexh -; ARM: str +; ARM-NOT: str ; ARM: strexh ; THUMB1: bl __sync_fetch_and_or_2 entry: @@ -187,7 +187,7 @@ define i16 @test_xor_i16() { ; CHECK-LABEL: test_xor_i16: ; ARM: ldrexh -; ARM: str +; ARM-NOT: str ; ARM: strexh ; THUMB1: bl __sync_fetch_and_xor_2 entry: @@ -197,7 +197,7 @@ define i16 @test_max_i16() { ; CHECK-LABEL: test_max_i16: ; ARM: ldrexh -; ARM: str +; ARM-NOT: str ; ARM: strexh ; THUMB1: bl __sync_fetch_and_max_2 entry: @@ -207,7 +207,7 @@ define i16 @test_min_i16() { ; CHECK-LABEL: test_min_i16: ; ARM: ldrexh -; ARM: str +; ARM-NOT: str ; ARM: strexh ; THUMB1: bl __sync_fetch_and_min_2 entry: @@ -217,7 +217,7 @@ define i16 @test_umax_i16() { ; CHECK-LABEL: test_umax_i16: ; ARM: ldrexh -; ARM: str +; ARM-NOT: str ; ARM: strexh ; THUMB1: bl __sync_fetch_and_umax_2 entry: @@ -227,7 +227,7 @@ define i16 @test_umin_i16() { ; CHECK-LABEL: test_umin_i16: ; ARM: ldrexh -; ARM: str +; ARM-NOT: str ; ARM: strexh ; THUMB1: bl __sync_fetch_and_umin_2 entry: @@ -239,7 +239,7 @@ define i32 @test_xchg_i32() { ; CHECK-LABEL: test_xchg_i32: ; ARM: ldrex -; ARM: str +; ARM-NOT: str ; ARM: strex ; THUMB1: bl __sync_lock_test_and_set_4 entry: @@ -249,7 +249,7 @@ define i32 @test_add_i32() { ; CHECK-LABEL: test_add_i32: ; ARM: ldrex -; ARM: str +; ARM-NOT: str ; ARM: strex ; THUMB1: bl __sync_fetch_and_add_4 entry: @@ -259,7 +259,7 @@ define i32 @test_sub_i32() { ; CHECK-LABEL: test_sub_i32: ; ARM: ldrex -; ARM: str +; ARM-NOT: str ; ARM: strex ; THUMB1: bl __sync_fetch_and_sub_4 entry: @@ -269,7 +269,7 @@ define i32 @test_and_i32() { ; CHECK-LABEL: test_and_i32: ; ARM: ldrex -; ARM: str +; ARM-NOT: str ; ARM: strex ; THUMB1: bl __sync_fetch_and_and_4 entry: @@ -279,7 +279,7 @@ define i32 @test_nand_i32() { ; CHECK-LABEL: test_nand_i32: ; ARM: ldrex -; ARM: str +; ARM-NOT: str ; ARM: strex ; THUMB1: bl __sync_fetch_and_nand_4 entry: @@ -289,7 +289,7 @@ define i32 @test_or_i32() { ; CHECK-LABEL: test_or_i32: ; ARM: ldrex -; ARM: str +; ARM-NOT: str ; ARM: strex ; THUMB1: bl __sync_fetch_and_or_4 entry: @@ -299,7 +299,7 @@ define i32 @test_xor_i32() { ; CHECK-LABEL: test_xor_i32: ; ARM: ldrex -; ARM: str +; ARM-NOT: str ; ARM: strex ; THUMB1: bl __sync_fetch_and_xor_4 entry: @@ -309,7 +309,7 @@ define i32 @test_max_i32() { ; CHECK-LABEL: test_max_i32: ; ARM: ldrex -; ARM: str +; ARM-NOT: str ; ARM: strex ; THUMB1: bl __sync_fetch_and_max_4 entry: @@ -319,7 +319,7 @@ define i32 @test_min_i32() { ; CHECK-LABEL: test_min_i32: ; ARM: ldrex -; ARM: str +; ARM-NOT: str ; ARM: strex ; THUMB1: bl __sync_fetch_and_min_4 @@ -330,7 +330,7 @@ define i32 @test_umax_i32() { ; CHECK-LABEL: test_umax_i32: ; ARM: ldrex -; ARM: str +; ARM-NOT: str ; ARM: strex ; THUMB1: bl __sync_fetch_and_umax_4 entry: @@ -340,7 +340,7 @@ define i32 @test_umin_i32() { ; CHECK-LABEL: test_umin_i32: ; ARM: ldrex -; ARM: str +; ARM-NOT: str ; ARM: strex ; THUMB1: bl __sync_fetch_and_umin_4 entry: @@ -351,7 +351,7 @@ define i64 @test_xchg_i64() { ; CHECK-LABEL: test_xchg_i64: ; ARM: ldrexd -; ARM: str +; ARM-NOT: str ; ARM: strexd ; THUMB1: bl __sync_lock_test_and_set_8 entry: @@ -361,7 +361,7 @@ define i64 @test_add_i64() { ; CHECK-LABEL: test_add_i64: ; ARM: ldrexd -; ARM: str +; ARM-NOT: str ; ARM: strexd ; THUMB1: bl __sync_fetch_and_add_8 entry: @@ -371,7 +371,7 @@ define i64 @test_sub_i64() { ; CHECK-LABEL: test_sub_i64: ; ARM: ldrexd -; ARM: str +; ARM-NOT: str ; ARM: strexd ; THUMB1: bl __sync_fetch_and_sub_8 entry: @@ -381,7 +381,7 @@ define i64 @test_and_i64() { ; CHECK-LABEL: test_and_i64: ; ARM: ldrexd -; ARM: str +; ARM-NOT: str ; ARM: strexd ; THUMB1: bl __sync_fetch_and_and_8 entry: @@ -391,7 +391,7 @@ define i64 @test_nand_i64() { ; CHECK-LABEL: test_nand_i64: ; ARM: ldrexd -; ARM: str +; ARM-NOT: str ; ARM: strexd ; THUMB1: bl __sync_fetch_and_nand_8 entry: @@ -401,7 +401,7 @@ define i64 @test_or_i64() { ; CHECK-LABEL: test_or_i64: ; ARM: ldrexd -; ARM: str +; ARM-NOT: str ; ARM: strexd ; THUMB1: bl __sync_fetch_and_or_8 entry: @@ -411,7 +411,7 @@ define i64 @test_xor_i64() { ; CHECK-LABEL: test_xor_i64: ; ARM: ldrexd -; ARM: str +; ARM-NOT: str ; ARM: strexd ; THUMB1: bl __sync_fetch_and_xor_8 entry: @@ -422,7 +422,7 @@ define i64 @test_max_i64() { ; CHECK-LABEL: test_max_i64: ; ARM: ldrexd -; ARM: str +; ARM-NOT: str ; ARM: strexd ; THUMB1: bl __sync_fetch_and_max_8 entry: @@ -432,7 +432,7 @@ define i64 @test_min_i64() { ; CHECK-LABEL: test_min_i64: ; ARM: ldrexd -; ARM: str +; ARM-NOT: str ; ARM: strexd ; THUMB1: bl __sync_fetch_and_min_8 entry: @@ -442,7 +442,7 @@ define i64 @test_umax_i64() { ; CHECK-LABEL: test_umax_i64: ; ARM: ldrexd -; ARM: str +; ARM-NOT: str ; ARM: strexd ; THUMB1: bl __sync_fetch_and_umax_8 entry: @@ -452,7 +452,7 @@ define i64 @test_umin_i64() { ; CHECK-LABEL: test_umin_i64: ; ARM: ldrexd -; ARM: str +; ARM-NOT: str ; ARM: strexd ; THUMB1: bl __sync_fetch_and_umin_8 entry: