[llvm] [ARM] Fix failure to register-allocate CMP_SWAP_64 pseudo-inst (PR #104039)

via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 14 08:27:21 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-arm

Author: Oliver Stannard (ostannard)

<details>
<summary>Changes</summary>

This test case was failing to compile with a "ran out of registers during register allocation" error at -O0. This was because CMP_SWAP_64 has 3 operands which must be an even-odd register pair, and two other GPR operands. All of the def operands are also early-clobber, so registers can't be shared between uses and defs. Because the function has an over-aligned alloca it needs frame and base pointers, so r6 and r11 are both reserved. That leaves r0/r1, r2/r3, r4/r5 and r8/r9 as the only valid register pairs, and if the two individual GPR operands happen to get allocated to registers in different pairs then only 2 pairs will be available for the three GPRPair operands.

The fix is to allocate the GPRPair operands first, because once they are allocated they can't prevent the GPR operands from being allocated.

Fixes #<!-- -->98222

---

Patch is 203.22 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/104039.diff


6 Files Affected:

- (modified) llvm/lib/CodeGen/RegAllocFast.cpp (+40-1) 
- (modified) llvm/lib/Target/ARM/ARMRegisterInfo.td (+3) 
- (added) llvm/test/CodeGen/ARM/atomic-64bit-fast-regalloc.ll (+82) 
- (modified) llvm/test/CodeGen/ARM/atomic-64bit.ll (+1494-352) 
- (modified) llvm/test/CodeGen/ARM/atomic-ops-v8.ll (+1995-909) 
- (modified) llvm/test/CodeGen/ARM/atomicrmw-uinc-udec-wrap.ll (+29-31) 


``````````diff
diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp
index 62f7ed29c8c819..6feefd87575e05 100644
--- a/llvm/lib/CodeGen/RegAllocFast.cpp
+++ b/llvm/lib/CodeGen/RegAllocFast.cpp
@@ -270,6 +270,8 @@ class RegAllocFastImpl {
   SmallVector<unsigned, 0> UsedInInstr;
 
   SmallVector<unsigned, 8> DefOperandIndexes;
+  SmallVector<unsigned, 8> UseOperandIndexes;
+
   // Register masks attached to the current instruction.
   SmallVector<const uint32_t *> RegMasks;
 
@@ -336,6 +338,7 @@ class RegAllocFastImpl {
                             Register Reg) const;
 
   void findAndSortDefOperandIndexes(const MachineInstr &MI);
+  void findAndSortUseOperandIndexes(const MachineInstr &MI);
 
   void allocateInstruction(MachineInstr &MI);
   void handleDebugValue(MachineInstr &MI);
@@ -1368,6 +1371,40 @@ void RegAllocFastImpl::findAndSortDefOperandIndexes(const MachineInstr &MI) {
   });
 }
 
+/// Compute \ref UseOperandIndexes so it contains the indices of "use" operands
+/// that are to be allocated. Those are ordered in a way that high-priority
+/// classes are allocated first.
+void RegAllocFastImpl::findAndSortUseOperandIndexes(const MachineInstr &MI) {
+  UseOperandIndexes.clear();
+
+  for (unsigned I = 0, E = MI.getNumOperands(); I < E; ++I) {
+    const MachineOperand &MO = MI.getOperand(I);
+    if (!MO.isReg())
+      continue;
+    Register Reg = MO.getReg();
+    if (MO.isUse() && Reg.isVirtual() && shouldAllocateRegister(Reg))
+      UseOperandIndexes.push_back(I);
+  }
+
+  llvm::sort(UseOperandIndexes, [&](unsigned I0, unsigned I1) {
+    const MachineOperand &MO0 = MI.getOperand(I0);
+    const MachineOperand &MO1 = MI.getOperand(I1);
+    Register Reg0 = MO0.getReg();
+    Register Reg1 = MO1.getReg();
+    const TargetRegisterClass &RC0 = *MRI->getRegClass(Reg0);
+    const TargetRegisterClass &RC1 = *MRI->getRegClass(Reg1);
+
+    // Allocate register classes with a high allocation priority first.
+    if (RC0.AllocationPriority > RC1.AllocationPriority)
+      return true;
+    if (RC0.AllocationPriority < RC1.AllocationPriority)
+      return false;
+
+    // Tie-break rule: operand index.
+    return I0 < I1;
+  });
+}
+
 // Returns true if MO is tied and the operand it's tied to is not Undef (not
 // Undef is not the same thing as Def).
 static bool isTiedToNotUndef(const MachineOperand &MO) {
@@ -1569,7 +1606,9 @@ void RegAllocFastImpl::allocateInstruction(MachineInstr &MI) {
   bool ReArrangedImplicitMOs = true;
   while (ReArrangedImplicitMOs) {
     ReArrangedImplicitMOs = false;
-    for (MachineOperand &MO : MI.operands()) {
+    findAndSortUseOperandIndexes(MI);
+    for (unsigned OpIdx : UseOperandIndexes) {
+      MachineOperand &MO = MI.getOperand(OpIdx);
       if (!MO.isReg() || !MO.isUse())
         continue;
       Register Reg = MO.getReg();
diff --git a/llvm/lib/Target/ARM/ARMRegisterInfo.td b/llvm/lib/Target/ARM/ARMRegisterInfo.td
index 212f22651f9f94..fc7e591ff44c89 100644
--- a/llvm/lib/Target/ARM/ARMRegisterInfo.td
+++ b/llvm/lib/Target/ARM/ARMRegisterInfo.td
@@ -548,6 +548,9 @@ def Tuples2Rsp   : RegisterTuples<[gsub_0, gsub_1],
 // Register class representing a pair of even-odd GPRs.
 def GPRPair : RegisterClass<"ARM", [untyped], 64, (add Tuples2Rnosp, Tuples2Rsp)> {
   let Size = 64; // 2 x 32 bits, we have no predefined type of that size.
+  // GPRPair must be allocated before GPR so that CMP_SWAP_64 can always be
+  // allocated when both the frame pointer and base pointer are reserved.
+  let AllocationPriority = 1;
 }
 
 // Register class representing a pair of even-odd GPRs, except (R12, SP).
diff --git a/llvm/test/CodeGen/ARM/atomic-64bit-fast-regalloc.ll b/llvm/test/CodeGen/ARM/atomic-64bit-fast-regalloc.ll
new file mode 100644
index 00000000000000..e06064a1bf9f32
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/atomic-64bit-fast-regalloc.ll
@@ -0,0 +1,82 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=armv7-none-eabi -O0 | FileCheck %s
+
+;; Previously, this failed during register allocation because the CMP_SWAP_64
+;; pseudo-instruction has a lot of operands, many of which need to be even-odd
+;; register pairs, and the over-aligned alloca in this function causes both a
+;; frame pointer and a base pointer to be needed.
+
+define void @test(ptr %ptr) {
+; CHECK-LABEL: test:
+; CHECK:       @ %bb.0: @ %entry
+; CHECK-NEXT:    .save {r4, r5, r6, r8, r9, r10, r11, lr}
+; CHECK-NEXT:    push {r4, r5, r6, r8, r9, r10, r11, lr}
+; CHECK-NEXT:    .setfp r11, sp, #24
+; CHECK-NEXT:    add r11, sp, #24
+; CHECK-NEXT:    .pad #16
+; CHECK-NEXT:    sub sp, sp, #16
+; CHECK-NEXT:    bfc sp, #0, #4
+; CHECK-NEXT:    mov r6, sp
+; CHECK-NEXT:    str r0, [r6, #12] @ 4-byte Spill
+; CHECK-NEXT:    b .LBB0_1
+; CHECK-NEXT:  .LBB0_1: @ %block1
+; CHECK-NEXT:    ldr r0, [r6, #12] @ 4-byte Reload
+; CHECK-NEXT:    mov r1, sp
+; CHECK-NEXT:    sub r1, r1, #16
+; CHECK-NEXT:    bic r1, r1, #15
+; CHECK-NEXT:    mov sp, r1
+; CHECK-NEXT:    dmb ish
+; CHECK-NEXT:    ldr r1, [r0]
+; CHECK-NEXT:    ldr r0, [r0, #4]
+; CHECK-NEXT:    str r1, [r6, #4] @ 4-byte Spill
+; CHECK-NEXT:    str r0, [r6, #8] @ 4-byte Spill
+; CHECK-NEXT:    b .LBB0_2
+; CHECK-NEXT:  .LBB0_2: @ %atomicrmw.start
+; CHECK-NEXT:    @ =>This Loop Header: Depth=1
+; CHECK-NEXT:    @ Child Loop BB0_3 Depth 2
+; CHECK-NEXT:    ldr r1, [r6, #8] @ 4-byte Reload
+; CHECK-NEXT:    ldr r8, [r6, #4] @ 4-byte Reload
+; CHECK-NEXT:    ldr r12, [r6, #12] @ 4-byte Reload
+; CHECK-NEXT:    str r8, [r6] @ 4-byte Spill
+; CHECK-NEXT:    @ kill: def $r8 killed $r8 def $r8_r9
+; CHECK-NEXT:    mov r9, r1
+; CHECK-NEXT:    mov r0, #0
+; CHECK-NEXT:    mov r2, r0
+; CHECK-NEXT:    mov r3, r0
+; CHECK-NEXT:  .LBB0_3: @ %atomicrmw.start
+; CHECK-NEXT:    @ Parent Loop BB0_2 Depth=1
+; CHECK-NEXT:    @ => This Inner Loop Header: Depth=2
+; CHECK-NEXT:    ldrexd r4, r5, [r12]
+; CHECK-NEXT:    cmp r4, r8
+; CHECK-NEXT:    cmpeq r5, r9
+; CHECK-NEXT:    bne .LBB0_5
+; CHECK-NEXT:  @ %bb.4: @ %atomicrmw.start
+; CHECK-NEXT:    @ in Loop: Header=BB0_3 Depth=2
+; CHECK-NEXT:    strexd r0, r2, r3, [r12]
+; CHECK-NEXT:    cmp r0, #0
+; CHECK-NEXT:    bne .LBB0_3
+; CHECK-NEXT:  .LBB0_5: @ %atomicrmw.start
+; CHECK-NEXT:    @ in Loop: Header=BB0_2 Depth=1
+; CHECK-NEXT:    ldr r2, [r6] @ 4-byte Reload
+; CHECK-NEXT:    mov r0, r5
+; CHECK-NEXT:    eor r3, r0, r1
+; CHECK-NEXT:    mov r1, r4
+; CHECK-NEXT:    eor r2, r1, r2
+; CHECK-NEXT:    orr r2, r2, r3
+; CHECK-NEXT:    cmp r2, #0
+; CHECK-NEXT:    str r1, [r6, #4] @ 4-byte Spill
+; CHECK-NEXT:    str r0, [r6, #8] @ 4-byte Spill
+; CHECK-NEXT:    bne .LBB0_2
+; CHECK-NEXT:    b .LBB0_6
+; CHECK-NEXT:  .LBB0_6: @ %atomicrmw.end
+; CHECK-NEXT:    dmb ish
+; CHECK-NEXT:    sub sp, r11, #24
+; CHECK-NEXT:    pop {r4, r5, r6, r8, r9, r10, r11, pc}
+entry:
+  br label %block1
+
+block1:
+  %stuff = alloca i8, i64 16, align 16
+  store atomic i64 0, ptr %ptr seq_cst, align 8
+  ret void
+}
diff --git a/llvm/test/CodeGen/ARM/atomic-64bit.ll b/llvm/test/CodeGen/ARM/atomic-64bit.ll
index ab9e1dfd1cfb19..84f1559fee14af 100644
--- a/llvm/test/CodeGen/ARM/atomic-64bit.ll
+++ b/llvm/test/CodeGen/ARM/atomic-64bit.ll
@@ -1,219 +1,722 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
 ; RUN: llc < %s -mtriple=armv7-apple-ios | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-LE
 ; RUN: llc < %s -mtriple=thumbv7-none-linux-gnueabihf | FileCheck %s --check-prefix=CHECK-THUMB --check-prefix=CHECK-THUMB-LE
 ; RUN: llc < %s -mtriple=armebv7 -target-abi apcs | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BE
 ; RUN: llc < %s -mtriple=thumbebv7-none-linux-gnueabihf | FileCheck %s --check-prefix=CHECK-THUMB --check-prefix=CHECK-THUMB-BE
-; RUN: llc < %s -mtriple=armv7m--none-eabi | FileCheck %s --check-prefix=CHECK-M
-; RUN: llc < %s -mtriple=armv8m--none-eabi | FileCheck %s --check-prefix=CHECK-M
+; RUN: llc < %s -mtriple=armv7m--none-eabi | FileCheck %s --check-prefix=CHECK-7M
+; RUN: llc < %s -mtriple=armv8m--none-eabi | FileCheck %s --check-prefix=CHECK-8M
 
 define i64 @test1(ptr %ptr, i64 %val) {
-; CHECK-LABEL: test1:
-; CHECK: dmb {{ish$}}
-; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
-; CHECK-LE: adds [[REG3:(r[0-9]?[02468])]], [[REG1]]
-; CHECK-LE: adc [[REG4:(r[0-9]?[13579])]], [[REG2]]
-; CHECK-BE: adds [[REG4:(r[0-9]?[13579])]], [[REG2]]
-; CHECK-BE: adc [[REG3:(r[0-9]?[02468])]], [[REG1]]
-; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
-; CHECK: cmp
-; CHECK: bne
-; CHECK: dmb {{ish$}}
-
-; CHECK-THUMB-LABEL: test1:
-; CHECK-THUMB: dmb {{ish$}}
-; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
-; CHECK-THUMB-LE: adds.w [[REG3:[a-z0-9]+]], [[REG1]]
-; CHECK-THUMB-LE: adc.w [[REG4:[a-z0-9]+]], [[REG2]]
-; CHECK-THUMB-BE: adds.w [[REG4:[a-z0-9]+]], [[REG2]]
-; CHECK-THUMB-BE: adc.w [[REG3:[a-z0-9]+]], [[REG1]]
-; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
-; CHECK-THUMB: cmp
-; CHECK-THUMB: bne
-; CHECK-THUMB: dmb {{ish$}}
-
-; CHECK-M: __atomic_fetch_add_8
+; CHECK-LE-LABEL: test1:
+; CHECK-LE:       @ %bb.0:
+; CHECK-LE-NEXT:    push {r4, r5, lr}
+; CHECK-LE-NEXT:    mov r9, r1
+; CHECK-LE-NEXT:    mov r12, r0
+; CHECK-LE-NEXT:    dmb ish
+; CHECK-LE-NEXT:  LBB0_1: @ %atomicrmw.start
+; CHECK-LE-NEXT:    @ =>This Inner Loop Header: Depth=1
+; CHECK-LE-NEXT:    ldrexd r0, r1, [r12]
+; CHECK-LE-NEXT:    adds r4, r0, r9
+; CHECK-LE-NEXT:    adc r5, r1, r2
+; CHECK-LE-NEXT:    strexd r3, r4, r5, [r12]
+; CHECK-LE-NEXT:    cmp r3, #0
+; CHECK-LE-NEXT:    bne LBB0_1
+; CHECK-LE-NEXT:  @ %bb.2: @ %atomicrmw.end
+; CHECK-LE-NEXT:    dmb ish
+; CHECK-LE-NEXT:    pop {r4, r5, pc}
+;
+; CHECK-THUMB-LE-LABEL: test1:
+; CHECK-THUMB-LE:       @ %bb.0:
+; CHECK-THUMB-LE-NEXT:    .save {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT:    push {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT:    mov r12, r0
+; CHECK-THUMB-LE-NEXT:    dmb ish
+; CHECK-THUMB-LE-NEXT:  .LBB0_1: @ %atomicrmw.start
+; CHECK-THUMB-LE-NEXT:    @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-LE-NEXT:    ldrexd r0, r1, [r12]
+; CHECK-THUMB-LE-NEXT:    adds.w lr, r0, r2
+; CHECK-THUMB-LE-NEXT:    adc.w r4, r1, r3
+; CHECK-THUMB-LE-NEXT:    strexd r5, lr, r4, [r12]
+; CHECK-THUMB-LE-NEXT:    cmp r5, #0
+; CHECK-THUMB-LE-NEXT:    bne .LBB0_1
+; CHECK-THUMB-LE-NEXT:  @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-LE-NEXT:    dmb ish
+; CHECK-THUMB-LE-NEXT:    pop {r4, r5, r7, pc}
+;
+; CHECK-BE-LABEL: test1:
+; CHECK-BE:       @ %bb.0:
+; CHECK-BE-NEXT:    push {r4, r5, lr}
+; CHECK-BE-NEXT:    mov r12, r1
+; CHECK-BE-NEXT:    mov lr, r0
+; CHECK-BE-NEXT:    dmb ish
+; CHECK-BE-NEXT:  .LBB0_1: @ %atomicrmw.start
+; CHECK-BE-NEXT:    @ =>This Inner Loop Header: Depth=1
+; CHECK-BE-NEXT:    ldrexd r0, r1, [lr]
+; CHECK-BE-NEXT:    adds r5, r1, r2
+; CHECK-BE-NEXT:    adc r4, r0, r12
+; CHECK-BE-NEXT:    strexd r3, r4, r5, [lr]
+; CHECK-BE-NEXT:    cmp r3, #0
+; CHECK-BE-NEXT:    bne .LBB0_1
+; CHECK-BE-NEXT:  @ %bb.2: @ %atomicrmw.end
+; CHECK-BE-NEXT:    dmb ish
+; CHECK-BE-NEXT:    pop {r4, r5, pc}
+;
+; CHECK-THUMB-BE-LABEL: test1:
+; CHECK-THUMB-BE:       @ %bb.0:
+; CHECK-THUMB-BE-NEXT:    .save {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT:    push {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT:    mov r12, r0
+; CHECK-THUMB-BE-NEXT:    dmb ish
+; CHECK-THUMB-BE-NEXT:  .LBB0_1: @ %atomicrmw.start
+; CHECK-THUMB-BE-NEXT:    @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-BE-NEXT:    ldrexd r0, r1, [r12]
+; CHECK-THUMB-BE-NEXT:    adds.w lr, r1, r3
+; CHECK-THUMB-BE-NEXT:    adc.w r4, r0, r2
+; CHECK-THUMB-BE-NEXT:    strexd r5, r4, lr, [r12]
+; CHECK-THUMB-BE-NEXT:    cmp r5, #0
+; CHECK-THUMB-BE-NEXT:    bne .LBB0_1
+; CHECK-THUMB-BE-NEXT:  @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-BE-NEXT:    dmb ish
+; CHECK-THUMB-BE-NEXT:    pop {r4, r5, r7, pc}
+;
+; CHECK-7M-LABEL: test1:
+; CHECK-7M:       @ %bb.0:
+; CHECK-7M-NEXT:    .save {r7, lr}
+; CHECK-7M-NEXT:    push {r7, lr}
+; CHECK-7M-NEXT:    .pad #8
+; CHECK-7M-NEXT:    sub sp, #8
+; CHECK-7M-NEXT:    movs r1, #5
+; CHECK-7M-NEXT:    str r1, [sp]
+; CHECK-7M-NEXT:    bl __atomic_fetch_add_8
+; CHECK-7M-NEXT:    add sp, #8
+; CHECK-7M-NEXT:    pop {r7, pc}
+;
+; CHECK-8M-LABEL: test1:
+; CHECK-8M:       @ %bb.0:
+; CHECK-8M-NEXT:    .save {r11, lr}
+; CHECK-8M-NEXT:    push {r11, lr}
+; CHECK-8M-NEXT:    .pad #8
+; CHECK-8M-NEXT:    sub sp, sp, #8
+; CHECK-8M-NEXT:    mov r1, #5
+; CHECK-8M-NEXT:    str r1, [sp]
+; CHECK-8M-NEXT:    bl __atomic_fetch_add_8
+; CHECK-8M-NEXT:    add sp, sp, #8
+; CHECK-8M-NEXT:    pop {r11, lr}
+; CHECK-8M-NEXT:    mov pc, lr
+
+
 
   %r = atomicrmw add ptr %ptr, i64 %val seq_cst
   ret i64 %r
 }
 
 define i64 @test2(ptr %ptr, i64 %val) {
-; CHECK-LABEL: test2:
-; CHECK: dmb {{ish$}}
-; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
-; CHECK-LE: subs [[REG3:(r[0-9]?[02468])]], [[REG1]]
-; CHECK-LE: sbc [[REG4:(r[0-9]?[13579])]], [[REG2]]
-; CHECK-BE: subs [[REG4:(r[0-9]?[13579])]], [[REG2]]
-; CHECK-BE: sbc [[REG3:(r[0-9]?[02468])]], [[REG1]]
-; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
-; CHECK: cmp
-; CHECK: bne
-; CHECK: dmb {{ish$}}
-
-; CHECK-THUMB-LABEL: test2:
-; CHECK-THUMB: dmb {{ish$}}
-; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
-; CHECK-THUMB-LE: subs.w [[REG3:[a-z0-9]+]], [[REG1]]
-; CHECK-THUMB-LE: sbc.w [[REG4:[a-z0-9]+]], [[REG2]]
-; CHECK-THUMB-BE: subs.w [[REG4:[a-z0-9]+]], [[REG2]]
-; CHECK-THUMB-BE: sbc.w [[REG3:[a-z0-9]+]], [[REG1]]
-; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
-; CHECK-THUMB: cmp
-; CHECK-THUMB: bne
-; CHECK-THUMB: dmb {{ish$}}
-
-; CHECK-M: __atomic_fetch_sub_8
+; CHECK-LE-LABEL: test2:
+; CHECK-LE:       @ %bb.0:
+; CHECK-LE-NEXT:    push {r4, r5, lr}
+; CHECK-LE-NEXT:    mov r9, r1
+; CHECK-LE-NEXT:    mov r12, r0
+; CHECK-LE-NEXT:    dmb ish
+; CHECK-LE-NEXT:  LBB1_1: @ %atomicrmw.start
+; CHECK-LE-NEXT:    @ =>This Inner Loop Header: Depth=1
+; CHECK-LE-NEXT:    ldrexd r0, r1, [r12]
+; CHECK-LE-NEXT:    subs r4, r0, r9
+; CHECK-LE-NEXT:    sbc r5, r1, r2
+; CHECK-LE-NEXT:    strexd r3, r4, r5, [r12]
+; CHECK-LE-NEXT:    cmp r3, #0
+; CHECK-LE-NEXT:    bne LBB1_1
+; CHECK-LE-NEXT:  @ %bb.2: @ %atomicrmw.end
+; CHECK-LE-NEXT:    dmb ish
+; CHECK-LE-NEXT:    pop {r4, r5, pc}
+;
+; CHECK-THUMB-LE-LABEL: test2:
+; CHECK-THUMB-LE:       @ %bb.0:
+; CHECK-THUMB-LE-NEXT:    .save {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT:    push {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT:    mov r12, r0
+; CHECK-THUMB-LE-NEXT:    dmb ish
+; CHECK-THUMB-LE-NEXT:  .LBB1_1: @ %atomicrmw.start
+; CHECK-THUMB-LE-NEXT:    @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-LE-NEXT:    ldrexd r0, r1, [r12]
+; CHECK-THUMB-LE-NEXT:    subs.w lr, r0, r2
+; CHECK-THUMB-LE-NEXT:    sbc.w r4, r1, r3
+; CHECK-THUMB-LE-NEXT:    strexd r5, lr, r4, [r12]
+; CHECK-THUMB-LE-NEXT:    cmp r5, #0
+; CHECK-THUMB-LE-NEXT:    bne .LBB1_1
+; CHECK-THUMB-LE-NEXT:  @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-LE-NEXT:    dmb ish
+; CHECK-THUMB-LE-NEXT:    pop {r4, r5, r7, pc}
+;
+; CHECK-BE-LABEL: test2:
+; CHECK-BE:       @ %bb.0:
+; CHECK-BE-NEXT:    push {r4, r5, lr}
+; CHECK-BE-NEXT:    mov r12, r1
+; CHECK-BE-NEXT:    mov lr, r0
+; CHECK-BE-NEXT:    dmb ish
+; CHECK-BE-NEXT:  .LBB1_1: @ %atomicrmw.start
+; CHECK-BE-NEXT:    @ =>This Inner Loop Header: Depth=1
+; CHECK-BE-NEXT:    ldrexd r0, r1, [lr]
+; CHECK-BE-NEXT:    subs r5, r1, r2
+; CHECK-BE-NEXT:    sbc r4, r0, r12
+; CHECK-BE-NEXT:    strexd r3, r4, r5, [lr]
+; CHECK-BE-NEXT:    cmp r3, #0
+; CHECK-BE-NEXT:    bne .LBB1_1
+; CHECK-BE-NEXT:  @ %bb.2: @ %atomicrmw.end
+; CHECK-BE-NEXT:    dmb ish
+; CHECK-BE-NEXT:    pop {r4, r5, pc}
+;
+; CHECK-THUMB-BE-LABEL: test2:
+; CHECK-THUMB-BE:       @ %bb.0:
+; CHECK-THUMB-BE-NEXT:    .save {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT:    push {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT:    mov r12, r0
+; CHECK-THUMB-BE-NEXT:    dmb ish
+; CHECK-THUMB-BE-NEXT:  .LBB1_1: @ %atomicrmw.start
+; CHECK-THUMB-BE-NEXT:    @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-BE-NEXT:    ldrexd r0, r1, [r12]
+; CHECK-THUMB-BE-NEXT:    subs.w lr, r1, r3
+; CHECK-THUMB-BE-NEXT:    sbc.w r4, r0, r2
+; CHECK-THUMB-BE-NEXT:    strexd r5, r4, lr, [r12]
+; CHECK-THUMB-BE-NEXT:    cmp r5, #0
+; CHECK-THUMB-BE-NEXT:    bne .LBB1_1
+; CHECK-THUMB-BE-NEXT:  @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-BE-NEXT:    dmb ish
+; CHECK-THUMB-BE-NEXT:    pop {r4, r5, r7, pc}
+;
+; CHECK-7M-LABEL: test2:
+; CHECK-7M:       @ %bb.0:
+; CHECK-7M-NEXT:    .save {r7, lr}
+; CHECK-7M-NEXT:    push {r7, lr}
+; CHECK-7M-NEXT:    .pad #8
+; CHECK-7M-NEXT:    sub sp, #8
+; CHECK-7M-NEXT:    movs r1, #5
+; CHECK-7M-NEXT:    str r1, [sp]
+; CHECK-7M-NEXT:    bl __atomic_fetch_sub_8
+; CHECK-7M-NEXT:    add sp, #8
+; CHECK-7M-NEXT:    pop {r7, pc}
+;
+; CHECK-8M-LABEL: test2:
+; CHECK-8M:       @ %bb.0:
+; CHECK-8M-NEXT:    .save {r11, lr}
+; CHECK-8M-NEXT:    push {r11, lr}
+; CHECK-8M-NEXT:    .pad #8
+; CHECK-8M-NEXT:    sub sp, sp, #8
+; CHECK-8M-NEXT:    mov r1, #5
+; CHECK-8M-NEXT:    str r1, [sp]
+; CHECK-8M-NEXT:    bl __atomic_fetch_sub_8
+; CHECK-8M-NEXT:    add sp, sp, #8
+; CHECK-8M-NEXT:    pop {r11, lr}
+; CHECK-8M-NEXT:    mov pc, lr
+
+
 
   %r = atomicrmw sub ptr %ptr, i64 %val seq_cst
   ret i64 %r
 }
 
 define i64 @test3(ptr %ptr, i64 %val) {
-; CHECK-LABEL: test3:
-; CHECK: dmb {{ish$}}
-; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
-; CHECK-LE-DAG: and [[REG3:(r[0-9]?[02468])]], [[REG1]],
-; CHECK-LE-DAG: and [[REG4:(r[0-9]?[13579])]], [[REG2]],
-; CHECK-BE-DAG: and [[REG4:(r[0-9]?[13579])]], [[REG2]],
-; CHECK-BE-DAG: and [[REG3:(r[0-9]?[02468])]], [[REG1]],
-; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
-; CHECK: cmp
-; CHECK: bne
-; CHECK: dmb {{ish$}}
-
+; CHECK-LE-LABEL: test3:
+; CHECK-LE:       @ %bb.0:
+; CHECK-LE-NEXT:    push {r4, r5, lr}
+; CHECK-LE-NEXT:    mov r9, r1
+; CHECK-LE-NEXT:    mov r12, r0
+; CHECK-LE-NEXT:    dmb ish
+; CHECK-LE-NEXT:  LBB2_1: @ %atomicrmw.start
+; CHECK-LE-NEXT:    @ =>This Inner Loop Header: Depth=1
+; CHECK-LE-NEXT:    ldrexd r0, r1, [r12]
+; CHECK-LE-NEXT:    and r4, r0, r9
+; CHECK-LE-NEXT:    and r5, r1, r2
+; CHECK-LE-NEXT:    strexd r3, r4, r5, [r12]
+; CHECK-LE-NEXT:    cmp r3, #0
+; CHECK-LE-NEXT:    bne LBB2_1
+; CHECK-LE-NEXT:  @ %bb.2: @ %atomicrmw.end
+; CHECK-LE-NEXT:    dmb ish
+; CHECK-LE-NEXT:    pop {r4, r5, pc}
+;
 ; CHECK-THUMB-LABEL: test3:
-; CHECK-THUMB: dmb {{ish$}}
-; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
-; CHECK-THUMB-LE-DAG: and.w [[REG3:[a-z0-9]+]], [[REG1]],
-; CHECK-THUMB-LE-DAG: and.w [[REG4:[a-z0-9]+]], [[REG2]],
-; CHECK-THUMB-BE-DAG: and.w [[REG4:[a-z0-9]+]], [[REG2]],
-; CHECK-THUMB-BE-DAG: and.w [[REG3:[a-z0-9]+]], [[REG1]],
-; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
-; CHECK-THUMB: cmp
-; CHECK-THUMB: bne
-; CHECK-THUMB: dmb {{ish$}}
-
-; CHECK-M: _atomic_fetch_and_8
+; CHECK-THUMB:       @ %bb.0:
+; CHECK-THUMB-NEXT:    .save {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT:    push {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT:    mov r12, r0
+; CHECK-THUMB-NEXT:    dmb ish
+; CHECK-THUMB-NEXT:  .LBB2_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT:    @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT:    ldrexd r0, r1, [r12]
+; CHECK-THUMB-NEXT:    and.w lr, r0, r2
+; CHECK-THUMB-NEXT:    and.w r4, r1, r3
+; CHECK-THUMB-NEXT:    strexd r5, lr, r4, [r12]
+; CHECK-THUMB-NEXT:    cmp r5, #0
+; CHECK-THUMB-NEXT:    bne .LBB2_1
+; CHECK-THUMB-NEXT:  @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT:    dmb ish
+; CHECK-THUMB-NEXT:    pop {r4, r5, r7, pc}
+;
+; CHECK-BE-LABEL: test3:
+; CHECK-BE:       @ %bb.0:
+; CHECK-BE-NEXT:    push {r4, r5, lr}
+; CHECK-BE-NEXT:    mov r12, r1
+; CHECK-BE-NEXT:    mov lr, r0
+; CHECK-BE-NEXT:    dmb ish
+; CHECK-BE-NEXT:  .LBB2_1: @ %atomicrmw.start
+; CHECK-BE-NEXT:    @ =>This Inner Loop Header: Depth=1
+; CHECK-BE-NEXT:    ldrexd r0, r1, [lr]
+; CHECK-BE-NEXT:    and r4, r0, r12
+; CHECK-BE-NEXT:    and r5, r1, r2
+; CHECK-BE-NEXT:    strexd r3, r4, r5, [lr]
+; CHECK-BE-NEXT:    cmp r3, #0
+; CHECK-BE-NEXT:    bne .LBB2_1
+; CHECK-BE-NEXT:  @ %bb.2: @ %atomicrmw.end
+; CHECK-BE-NEXT:    dmb ish
+; CHECK-BE-NEXT:    pop {r4, r5, pc}
+;
+; CHECK-7M-LABEL: test3:
+; CHECK-7M:       @ %bb.0:
+; CHECK-7M-NEXT:    .save {r7, lr}
+; CHECK-7M-NEXT:    push {r7, lr}
+; CHECK-7M-NEXT:    .pad #8
+; CHECK-7M-NE...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/104039


More information about the llvm-commits mailing list