Register DesiredReg = MI.getOperand(3).getReg();
Register NewReg = MI.getOperand(4).getReg();
+ if (IsThumb) {
+ assert(STI->hasV8MBaselineOps() &&
+ "CMP_SWAP not expected to be custom expanded for Thumb1");
+ assert((UxtOp == 0 || UxtOp == ARM::tUXTB || UxtOp == ARM::tUXTH) &&
+ "ARMv8-M.baseline does not have t2UXTB/t2UXTH");
+ assert(ARM::tGPRRegClass.contains(DesiredReg) &&
+ "DesiredReg used for UXT op must be tGPR");
+ }
+
MachineFunction *MF = MBB.getParent();
auto LoadCmpBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
auto StoreBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
case ARM::VTBX3Pseudo: ExpandVTBL(MBBI, ARM::VTBX3, true); return true;
case ARM::VTBX4Pseudo: ExpandVTBL(MBBI, ARM::VTBX4, true); return true;
+ case ARM::tCMP_SWAP_8:
+ assert(STI->isThumb());
+ return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREXB, ARM::t2STREXB, ARM::tUXTB,
+ NextMBBI);
+ case ARM::tCMP_SWAP_16:
+ assert(STI->isThumb());
+ return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREXH, ARM::t2STREXH, ARM::tUXTH,
+ NextMBBI);
+
case ARM::CMP_SWAP_8:
- if (STI->isThumb())
- return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREXB, ARM::t2STREXB,
- ARM::tUXTB, NextMBBI);
- else
- return ExpandCMP_SWAP(MBB, MBBI, ARM::LDREXB, ARM::STREXB,
- ARM::UXTB, NextMBBI);
+ assert(!STI->isThumb());
+ 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);
- else
- return ExpandCMP_SWAP(MBB, MBBI, ARM::LDREXH, ARM::STREXH,
- ARM::UXTH, NextMBBI);
+ assert(!STI->isThumb());
+ return ExpandCMP_SWAP(MBB, MBBI, ARM::LDREXH, ARM::STREXH, ARM::UXTH,
+ NextMBBI);
case ARM::CMP_SWAP_32:
if (STI->isThumb())
return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREX, ARM::t2STREX, 0,
define i8 @test_xchg_i8() {
; COMMON-LABEL: test_xchg_i8:
; EXPAND32: ldrexb
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexb
; THUMB1: bl __sync_lock_test_and_set_1
entry:
define i8 @test_add_i8() {
; COMMON-LABEL: test_add_i8:
; EXPAND32: ldrexb
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexb
; THUMB1: bl __sync_fetch_and_add_1
entry:
define i8 @test_sub_i8() {
; COMMON-LABEL: test_sub_i8:
; EXPAND32: ldrexb
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexb
; THUMB1: bl __sync_fetch_and_sub_1
entry:
define i8 @test_and_i8() {
; COMMON-LABEL: test_and_i8:
; EXPAND32: ldrexb
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexb
; THUMB1: bl __sync_fetch_and_and_1
entry:
define i8 @test_nand_i8() {
; COMMON-LABEL: test_nand_i8:
; EXPAND32: ldrexb
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexb
; THUMB1: bl __sync_fetch_and_nand_1
entry:
define i8 @test_or_i8() {
; COMMON-LABEL: test_or_i8:
; EXPAND32: ldrexb
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexb
; THUMB1: bl __sync_fetch_and_or_1
entry:
define i8 @test_xor_i8() {
; COMMON-LABEL: test_xor_i8:
; EXPAND32: ldrexb
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexb
; THUMB1: bl __sync_fetch_and_xor_1
entry:
define i8 @test_max_i8() {
; COMMON-LABEL: test_max_i8:
; EXPAND32: ldrexb
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexb
; THUMB1: bl __sync_fetch_and_max_1
entry:
define i8 @test_min_i8() {
; COMMON-LABEL: test_min_i8:
; EXPAND32: ldrexb
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexb
; THUMB1: bl __sync_fetch_and_min_1
entry:
define i8 @test_umax_i8() {
; COMMON-LABEL: test_umax_i8:
; EXPAND32: ldrexb
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexb
; THUMB1: bl __sync_fetch_and_umax_1
entry:
define i8 @test_umin_i8() {
; COMMON-LABEL: test_umin_i8:
; EXPAND32: ldrexb
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexb
; THUMB1: bl __sync_fetch_and_umin_1
entry:
define i16 @test_xchg_i16() {
; COMMON-LABEL: test_xchg_i16:
; EXPAND32: ldrexh
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexh
; THUMB1: bl __sync_lock_test_and_set_2
entry:
define i16 @test_add_i16() {
; COMMON-LABEL: test_add_i16:
; EXPAND32: ldrexh
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexh
; THUMB1: bl __sync_fetch_and_add_2
entry:
define i16 @test_sub_i16() {
; COMMON-LABEL: test_sub_i16:
; EXPAND32: ldrexh
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexh
; THUMB1: bl __sync_fetch_and_sub_2
entry:
define i16 @test_and_i16() {
; COMMON-LABEL: test_and_i16:
; EXPAND32: ldrexh
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexh
; THUMB1: bl __sync_fetch_and_and_2
entry:
define i16 @test_nand_i16() {
; COMMON-LABEL: test_nand_i16:
; EXPAND32: ldrexh
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexh
; THUMB1: bl __sync_fetch_and_nand_2
entry:
define i16 @test_or_i16() {
; COMMON-LABEL: test_or_i16:
; EXPAND32: ldrexh
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexh
; THUMB1: bl __sync_fetch_and_or_2
entry:
define i16 @test_xor_i16() {
; COMMON-LABEL: test_xor_i16:
; EXPAND32: ldrexh
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexh
; THUMB1: bl __sync_fetch_and_xor_2
entry:
define i16 @test_max_i16() {
; COMMON-LABEL: test_max_i16:
; EXPAND32: ldrexh
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexh
; THUMB1: bl __sync_fetch_and_max_2
entry:
define i16 @test_min_i16() {
; COMMON-LABEL: test_min_i16:
; EXPAND32: ldrexh
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexh
; THUMB1: bl __sync_fetch_and_min_2
entry:
define i16 @test_umax_i16() {
; COMMON-LABEL: test_umax_i16:
; EXPAND32: ldrexh
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexh
; THUMB1: bl __sync_fetch_and_umax_2
entry:
define i16 @test_umin_i16() {
; COMMON-LABEL: test_umin_i16:
; EXPAND32: ldrexh
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strexh
; THUMB1: bl __sync_fetch_and_umin_2
entry:
define i32 @test_xchg_i32() {
; COMMON-LABEL: test_xchg_i32:
; EXPAND32: ldrex
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strex
; THUMB1: bl __sync_lock_test_and_set_4
entry:
define i32 @test_add_i32() {
; COMMON-LABEL: test_add_i32:
; EXPAND32: ldrex
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strex
; THUMB1: bl __sync_fetch_and_add_4
entry:
define i32 @test_sub_i32() {
; COMMON-LABEL: test_sub_i32:
; EXPAND32: ldrex
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strex
; THUMB1: bl __sync_fetch_and_sub_4
entry:
define i32 @test_and_i32() {
; COMMON-LABEL: test_and_i32:
; EXPAND32: ldrex
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strex
; THUMB1: bl __sync_fetch_and_and_4
entry:
define i32 @test_nand_i32() {
; COMMON-LABEL: test_nand_i32:
; EXPAND32: ldrex
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strex
; THUMB1: bl __sync_fetch_and_nand_4
entry:
define i32 @test_or_i32() {
; COMMON-LABEL: test_or_i32:
; EXPAND32: ldrex
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strex
; THUMB1: bl __sync_fetch_and_or_4
entry:
define i32 @test_xor_i32() {
; COMMON-LABEL: test_xor_i32:
; EXPAND32: ldrex
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strex
; THUMB1: bl __sync_fetch_and_xor_4
entry:
define i32 @test_max_i32() {
; COMMON-LABEL: test_max_i32:
; EXPAND32: ldrex
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strex
; THUMB1: bl __sync_fetch_and_max_4
entry:
define i32 @test_min_i32() {
; COMMON-LABEL: test_min_i32:
; EXPAND32: ldrex
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strex
; THUMB1: bl __sync_fetch_and_min_4
define i32 @test_umax_i32() {
; COMMON-LABEL: test_umax_i32:
; EXPAND32: ldrex
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strex
; THUMB1: bl __sync_fetch_and_umax_4
entry:
define i32 @test_umin_i32() {
; COMMON-LABEL: test_umin_i32:
; EXPAND32: ldrex
-; EXPAND32: str
+; EXPAND32-NOT: str
; EXPAND32: strex
; THUMB1: bl __sync_fetch_and_umin_4
entry:
define i64 @test_xchg_i64() {
; COMMON-LABEL: test_xchg_i64:
; EXPAND64: ldrexd
-; EXPAND64: str
+; EXPAND64-NOT: str
; EXPAND64: strexd
; THUMB1: bl __sync_lock_test_and_set_8
-; BASELINE64: bl __sync_lock_test_and_set_8
+; BASELINE64: bl __sync_val_compare_and_swap_8
entry:
%0 = atomicrmw xchg i64* @atomic_i64, i64 1 monotonic
ret i64 %0
define i64 @test_add_i64() {
; COMMON-LABEL: test_add_i64:
; EXPAND64: ldrexd
-; EXPAND64: str
+; EXPAND64-NOT: str
; EXPAND64: strexd
; THUMB1: bl __sync_fetch_and_add_8
-; BASELINE64: bl __sync_fetch_and_add_8
+; BASELINE64: bl __sync_val_compare_and_swap_8
entry:
%0 = atomicrmw add i64* @atomic_i64, i64 1 monotonic
ret i64 %0
define i64 @test_sub_i64() {
; COMMON-LABEL: test_sub_i64:
; EXPAND64: ldrexd
-; EXPAND64: str
+; EXPAND64-NOT: str
; EXPAND64: strexd
; THUMB1: bl __sync_fetch_and_sub_8
-; BASELINE64: bl __sync_fetch_and_sub_8
+; BASELINE64: bl __sync_val_compare_and_swap_8
entry:
%0 = atomicrmw sub i64* @atomic_i64, i64 1 monotonic
ret i64 %0
define i64 @test_and_i64() {
; COMMON-LABEL: test_and_i64:
; EXPAND64: ldrexd
-; EXPAND64: str
+; EXPAND64-NOT: str
; EXPAND64: strexd
; THUMB1: bl __sync_fetch_and_and_8
-; BASELINE64: bl __sync_fetch_and_and_8
+; BASELINE64: bl __sync_val_compare_and_swap_8
entry:
%0 = atomicrmw and i64* @atomic_i64, i64 1 monotonic
ret i64 %0
define i64 @test_nand_i64() {
; COMMON-LABEL: test_nand_i64:
; EXPAND64: ldrexd
-; EXPAND64: str
+; EXPAND64-NOT: str
; EXPAND64: strexd
; THUMB1: bl __sync_fetch_and_nand_8
-; BASELINE64: bl __sync_fetch_and_nand_8
+; BASELINE64: bl __sync_val_compare_and_swap_8
entry:
%0 = atomicrmw nand i64* @atomic_i64, i64 1 monotonic
ret i64 %0
define i64 @test_or_i64() {
; COMMON-LABEL: test_or_i64:
; EXPAND64: ldrexd
-; EXPAND64: str
+; EXPAND64-NOT: str
; EXPAND64: strexd
; THUMB1: bl __sync_fetch_and_or_8
-; BASELINE64: bl __sync_fetch_and_or_8
+; BASELINE64: bl __sync_val_compare_and_swap_8
entry:
%0 = atomicrmw or i64* @atomic_i64, i64 1 monotonic
ret i64 %0
define i64 @test_xor_i64() {
; COMMON-LABEL: test_xor_i64:
; EXPAND64: ldrexd
-; EXPAND64: str
+; EXPAND64-NOT: str
; EXPAND64: strexd
; THUMB1: bl __sync_fetch_and_xor_8
-; BASELINE64: bl __sync_fetch_and_xor_8
+; BASELINE64: bl __sync_val_compare_and_swap_8
entry:
%0 = atomicrmw xor i64* @atomic_i64, i64 1 monotonic
ret i64 %0
define i64 @test_max_i64() {
; COMMON-LABEL: test_max_i64:
; EXPAND64: ldrexd
-; EXPAND64: str
+; EXPAND64-NOT: str
; EXPAND64: strexd
; THUMB1: bl __sync_fetch_and_max_8
-; BASELINE64: bl __sync_fetch_and_max_8
+; BASELINE64: bl __sync_val_compare_and_swap_8
entry:
%0 = atomicrmw max i64* @atomic_i64, i64 1 monotonic
ret i64 %0
define i64 @test_min_i64() {
; COMMON-LABEL: test_min_i64:
; EXPAND64: ldrexd
-; EXPAND64: str
+; EXPAND64-NOT: str
; EXPAND64: strexd
; THUMB1: bl __sync_fetch_and_min_8
-; BASELINE64: bl __sync_fetch_and_min_8
+; BASELINE64: bl __sync_val_compare_and_swap_8
entry:
%0 = atomicrmw min i64* @atomic_i64, i64 1 monotonic
ret i64 %0
define i64 @test_umax_i64() {
; COMMON-LABEL: test_umax_i64:
; EXPAND64: ldrexd
-; EXPAND64: str
+; EXPAND64-NOT: str
; EXPAND64: strexd
; THUMB1: bl __sync_fetch_and_umax_8
-; BASELINE64: bl __sync_fetch_and_umax_8
+; BASELINE64: bl __sync_val_compare_and_swap_8
entry:
%0 = atomicrmw umax i64* @atomic_i64, i64 1 monotonic
ret i64 %0
define i64 @test_umin_i64() {
; COMMON-LABEL: test_umin_i64:
; EXPAND64: ldrexd
-; EXPAND64: str
+; EXPAND64-NOT: str
; EXPAND64: strexd
; THUMB1: bl __sync_fetch_and_umin_8
-; BASELINE64: bl __sync_fetch_and_umin_8
+; BASELINE64: bl __sync_val_compare_and_swap_8
entry:
%0 = atomicrmw umin i64* @atomic_i64, i64 1 monotonic
ret i64 %0