[llvm] [ARM] Fix failure to register-allocate CMP_SWAP_64 pseudo-inst (PR #106721)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 30 05:45:43 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.
To fix this, I've merged the two GPR operands into a single GPRPair operand. This means that the instruction now has 4 GPRPair operands, which can always be allocated without relying on luck. This does constrain register allocation a bit more, but this pseudo instruction is only used at -O0, so I don't think that's a problem.
---
Patch is 114.71 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/106721.diff
9 Files Affected:
- (modified) llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp (+6-3)
- (modified) llvm/lib/Target/ARM/ARMISelLowering.cpp (+20-12)
- (modified) llvm/lib/Target/ARM/ARMInstrInfo.td (+15-2)
- (added) llvm/test/CodeGen/ARM/atomic-64bit-fast-regalloc.ll (+96)
- (modified) llvm/test/CodeGen/ARM/atomic-load-store.ll (+54-42)
- (modified) llvm/test/CodeGen/ARM/atomicrmw_exclusive_monitor_ints.ll (+622-490)
- (modified) llvm/test/CodeGen/ARM/cmpxchg-O0.ll (+2-3)
- (modified) llvm/test/CodeGen/ARM/cmpxchg.mir (+7-6)
- (modified) llvm/test/CodeGen/Thumb2/cmpxchg.mir (+7-6)
``````````diff
diff --git a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp
index df10613fcc7c93..25dfacca956bb8 100644
--- a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp
@@ -1942,11 +1942,14 @@ bool ARMExpandPseudo::ExpandCMP_SWAP_64(MachineBasicBlock &MBB,
MachineInstr &MI = *MBBI;
DebugLoc DL = MI.getDebugLoc();
MachineOperand &Dest = MI.getOperand(0);
- Register TempReg = MI.getOperand(1).getReg();
// Duplicating undef operands into 2 instructions does not guarantee the same
// value on both; However undef should be replaced by xzr anyway.
- assert(!MI.getOperand(2).isUndef() && "cannot handle undef");
- Register AddrReg = MI.getOperand(2).getReg();
+ assert(!MI.getOperand(1).isUndef() && "cannot handle undef");
+ Register AddrAndTempReg = MI.getOperand(1).getReg();
+ Register AddrReg = TRI->getSubReg(AddrAndTempReg, ARM::gsub_0);
+ Register TempReg = TRI->getSubReg(AddrAndTempReg, ARM::gsub_1);
+ assert(MI.getOperand(1).getReg() == MI.getOperand(2).getReg() &&
+ "tied operands have different registers");
Register DesiredReg = MI.getOperand(3).getReg();
MachineOperand New = MI.getOperand(4);
New.setIsKill(false);
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index ec6367a803506b..e0e62950b42c19 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -10479,33 +10479,41 @@ static void ReplaceREADCYCLECOUNTER(SDNode *N,
Results.push_back(Cycles32.getValue(1));
}
-static SDValue createGPRPairNode(SelectionDAG &DAG, SDValue V) {
- SDLoc dl(V.getNode());
- auto [VLo, VHi] = DAG.SplitScalar(V, dl, MVT::i32, MVT::i32);
- bool isBigEndian = DAG.getDataLayout().isBigEndian();
- if (isBigEndian)
- std::swap (VLo, VHi);
+static SDValue createGPRPairNode2xi32(SelectionDAG &DAG, SDValue V0, SDValue V1) {
+ SDLoc dl(V0.getNode());
SDValue RegClass =
DAG.getTargetConstant(ARM::GPRPairRegClassID, dl, MVT::i32);
SDValue SubReg0 = DAG.getTargetConstant(ARM::gsub_0, dl, MVT::i32);
SDValue SubReg1 = DAG.getTargetConstant(ARM::gsub_1, dl, MVT::i32);
- const SDValue Ops[] = { RegClass, VLo, SubReg0, VHi, SubReg1 };
+ const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
return SDValue(
DAG.getMachineNode(TargetOpcode::REG_SEQUENCE, dl, MVT::Untyped, Ops), 0);
}
+static SDValue createGPRPairNodei64(SelectionDAG &DAG, SDValue V) {
+ SDLoc dl(V.getNode());
+ auto [VLo, VHi] = DAG.SplitScalar(V, dl, MVT::i32, MVT::i32);
+ bool isBigEndian = DAG.getDataLayout().isBigEndian();
+ if (isBigEndian)
+ std::swap (VLo, VHi);
+ return createGPRPairNode2xi32(DAG, VLo, VHi);
+}
+
static void ReplaceCMP_SWAP_64Results(SDNode *N,
SmallVectorImpl<SDValue> & Results,
SelectionDAG &DAG) {
assert(N->getValueType(0) == MVT::i64 &&
"AtomicCmpSwap on types less than 64 should be legal");
- SDValue Ops[] = {N->getOperand(1),
- createGPRPairNode(DAG, N->getOperand(2)),
- createGPRPairNode(DAG, N->getOperand(3)),
- N->getOperand(0)};
+ SDValue Ops[] = {
+ createGPRPairNode2xi32(DAG, N->getOperand(1),
+ DAG.getUNDEF(MVT::i32)), // pointer, temp
+ createGPRPairNodei64(DAG, N->getOperand(2)), // expected
+ createGPRPairNodei64(DAG, N->getOperand(3)), // new
+ N->getOperand(0), // chain in
+ };
SDNode *CmpSwap = DAG.getMachineNode(
ARM::CMP_SWAP_64, SDLoc(N),
- DAG.getVTList(MVT::Untyped, MVT::i32, MVT::Other), Ops);
+ DAG.getVTList(MVT::Untyped, MVT::Untyped, MVT::Other), Ops);
MachineMemOperand *MemOp = cast<MemSDNode>(N)->getMemOperand();
DAG.setNodeMemRefs(cast<MachineSDNode>(CmpSwap), {MemOp});
diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td
index 26f7d70b43b262..0fc561382084e3 100644
--- a/llvm/lib/Target/ARM/ARMInstrInfo.td
+++ b/llvm/lib/Target/ARM/ARMInstrInfo.td
@@ -6509,8 +6509,21 @@ def CMP_SWAP_32 : PseudoInst<(outs GPR:$Rd, GPR:$temp),
(ins GPR:$addr, GPR:$desired, GPR:$new),
NoItinerary, []>, Sched<[]>;
-def CMP_SWAP_64 : PseudoInst<(outs GPRPair:$Rd, GPR:$temp),
- (ins GPR:$addr, GPRPair:$desired, GPRPair:$new),
+// The addr_temp and addr_temp_out operands are logically a pair of GPR
+// operands:
+// * addr is an input, holding the address to swap.
+// * temp is a earlyclobber output, used internally in the expansion of the
+// pseudo-inst.
+// These are combined into one GPRPair operand to ensure that register
+// allocation always succeeds. In the worst case there are only 4 GPRPair
+// registers available, of which this instruction needs 3 for the other
+// operands. If these operands weren't combined they would also use two GPR
+// registers, which could overlap with two different GPRPairs, causing
+// allocation to fail. With them combined, we need to allocate 4 GPRPairs,
+// which will always succeed.
+let Constraints = "@earlyclobber $Rd,$addr_temp_out = $addr_temp" in
+def CMP_SWAP_64 : PseudoInst<(outs GPRPair:$Rd, GPRPair:$addr_temp_out),
+ (ins GPRPair:$addr_temp, GPRPair:$desired, GPRPair:$new),
NoItinerary, []>, Sched<[]>;
}
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..bcaea3d0258b70
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/atomic-64bit-fast-regalloc.ll
@@ -0,0 +1,96 @@
+; 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 --check-prefix=CHECK --check-prefix=LE
+; RUN: llc < %s -mtriple=armv7eb-none-eabi -O0 | FileCheck %s --check-prefix=CHECK --check-prefix=BE
+
+;; 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 #32
+; CHECK-NEXT: sub sp, sp, #32
+; CHECK-NEXT: bfc sp, #0, #4
+; CHECK-NEXT: mov r6, sp
+; CHECK-NEXT: str r0, [r6, #28] @ 4-byte Spill
+; CHECK-NEXT: b .LBB0_1
+; CHECK-NEXT: .LBB0_1: @ %block1
+; CHECK-NEXT: ldr r0, [r6, #28] @ 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, #20] @ 4-byte Spill
+; CHECK-NEXT: str r0, [r6, #24] @ 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 r2, [r6, #24] @ 4-byte Reload
+; CHECK-NEXT: ldr r0, [r6, #20] @ 4-byte Reload
+; CHECK-NEXT: ldr r8, [r6, #28] @ 4-byte Reload
+; LE-NEXT: str r2, [r6, #16] @ 4-byte Spill
+; LE-NEXT: str r0, [r6, #12] @ 4-byte Spill
+; BE-NEXT: str r2, [r6, #12] @ 4-byte Spill
+; BE-NEXT: str r0, [r6, #16] @ 4-byte Spill
+; CHECK-NEXT: @ implicit-def: $r1
+; CHECK-NEXT: @ implicit-def: $r3
+; CHECK-NEXT: @ kill: def $r8 killed $r8 def $r8_r9
+; CHECK-NEXT: mov r9, r1
+; CHECK-NEXT: @ kill: def $r0 killed $r0 def $r0_r1
+; CHECK-NEXT: mov r1, r2
+; CHECK-NEXT: mov r12, #0
+; CHECK-NEXT: mov r2, r12
+; CHECK-NEXT: mov r3, r12
+; 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, [r8]
+; CHECK-NEXT: cmp r4, r0
+; CHECK-NEXT: cmpeq r5, r1
+; CHECK-NEXT: bne .LBB0_5
+; CHECK-NEXT: @ %bb.4: @ %atomicrmw.start
+; CHECK-NEXT: @ in Loop: Header=BB0_3 Depth=2
+; CHECK-NEXT: strexd r9, r2, r3, [r8]
+; CHECK-NEXT: cmp r9, #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, #12] @ 4-byte Reload
+; LE-NEXT: ldr r1, [r6, #16] @ 4-byte Reload
+; LE-NEXT: mov r0, r5
+; LE-NEXT: eor r3, r0, r1
+; LE-NEXT: mov r1, r4
+; LE-NEXT: eor r2, r1, r2
+; BE-NEXT: ldr r0, [r6, #16] @ 4-byte Reload
+; BE-NEXT: mov r1, r4
+; BE-NEXT: eor r3, r1, r0
+; BE-NEXT: mov r0, r5
+; BE-NEXT: eor r2, r0, r2
+; CHECK-NEXT: orr r2, r2, r3
+; CHECK-NEXT: cmp r2, #0
+; CHECK-NEXT: str r1, [r6, #20] @ 4-byte Spill
+; CHECK-NEXT: str r0, [r6, #24] @ 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-load-store.ll b/llvm/test/CodeGen/ARM/atomic-load-store.ll
index c53fb2f330a792..14e49bf3c9376a 100644
--- a/llvm/test/CodeGen/ARM/atomic-load-store.ll
+++ b/llvm/test/CodeGen/ARM/atomic-load-store.ll
@@ -327,50 +327,56 @@ define void @test_old_store_64bit(ptr %p, i64 %v) {
; ARMOPTNONE-NEXT: push {r4, r5, r7, lr}
; ARMOPTNONE-NEXT: add r7, sp, #8
; ARMOPTNONE-NEXT: push {r8, r10, r11}
-; ARMOPTNONE-NEXT: sub sp, sp, #20
-; ARMOPTNONE-NEXT: str r0, [sp] @ 4-byte Spill
-; ARMOPTNONE-NEXT: str r2, [sp, #4] @ 4-byte Spill
-; ARMOPTNONE-NEXT: str r1, [sp, #8] @ 4-byte Spill
+; ARMOPTNONE-NEXT: sub sp, sp, #24
+; ARMOPTNONE-NEXT: str r0, [sp, #4] @ 4-byte Spill
+; ARMOPTNONE-NEXT: str r2, [sp, #8] @ 4-byte Spill
+; ARMOPTNONE-NEXT: str r1, [sp, #12] @ 4-byte Spill
; ARMOPTNONE-NEXT: dmb ish
; ARMOPTNONE-NEXT: ldr r1, [r0]
; ARMOPTNONE-NEXT: ldr r0, [r0, #4]
-; ARMOPTNONE-NEXT: str r1, [sp, #12] @ 4-byte Spill
-; ARMOPTNONE-NEXT: str r0, [sp, #16] @ 4-byte Spill
+; ARMOPTNONE-NEXT: str r1, [sp, #16] @ 4-byte Spill
+; ARMOPTNONE-NEXT: str r0, [sp, #20] @ 4-byte Spill
; ARMOPTNONE-NEXT: b LBB5_1
; ARMOPTNONE-NEXT: LBB5_1: @ %atomicrmw.start
; ARMOPTNONE-NEXT: @ =>This Loop Header: Depth=1
; ARMOPTNONE-NEXT: @ Child Loop BB5_2 Depth 2
-; ARMOPTNONE-NEXT: ldr r1, [sp, #16] @ 4-byte Reload
-; ARMOPTNONE-NEXT: ldr r2, [sp, #12] @ 4-byte Reload
-; ARMOPTNONE-NEXT: ldr r3, [sp] @ 4-byte Reload
-; ARMOPTNONE-NEXT: ldr r0, [sp, #4] @ 4-byte Reload
-; ARMOPTNONE-NEXT: ldr r10, [sp, #8] @ 4-byte Reload
-; ARMOPTNONE-NEXT: @ kill: def $r10 killed $r10 def $r10_r11
-; ARMOPTNONE-NEXT: mov r11, r0
-; ARMOPTNONE-NEXT: mov r8, r2
+; ARMOPTNONE-NEXT: ldr r3, [sp, #20] @ 4-byte Reload
+; ARMOPTNONE-NEXT: ldr r2, [sp, #16] @ 4-byte Reload
+; ARMOPTNONE-NEXT: ldr r12, [sp, #8] @ 4-byte Reload
+; ARMOPTNONE-NEXT: ldr r0, [sp, #12] @ 4-byte Reload
+; ARMOPTNONE-NEXT: ldr r8, [sp, #4] @ 4-byte Reload
+; ARMOPTNONE-NEXT: str r3, [sp] @ 4-byte Spill
+; ARMOPTNONE-NEXT: @ implicit-def: $r1
+; ARMOPTNONE-NEXT: @ implicit-def: $r9
+; ARMOPTNONE-NEXT: @ kill: def $r8 killed $r8 def $r8_r9
; ARMOPTNONE-NEXT: mov r9, r1
+; ARMOPTNONE-NEXT: @ kill: def $r0 killed $r0 def $r0_r1
+; ARMOPTNONE-NEXT: mov r1, r12
+; ARMOPTNONE-NEXT: mov r10, r2
+; ARMOPTNONE-NEXT: mov r11, r3
; ARMOPTNONE-NEXT: LBB5_2: @ %atomicrmw.start
; ARMOPTNONE-NEXT: @ Parent Loop BB5_1 Depth=1
; ARMOPTNONE-NEXT: @ => This Inner Loop Header: Depth=2
-; ARMOPTNONE-NEXT: ldrexd r4, r5, [r3]
-; ARMOPTNONE-NEXT: cmp r4, r8
-; ARMOPTNONE-NEXT: cmpeq r5, r9
+; ARMOPTNONE-NEXT: ldrexd r4, r5, [r8]
+; ARMOPTNONE-NEXT: cmp r4, r10
+; ARMOPTNONE-NEXT: cmpeq r5, r11
; ARMOPTNONE-NEXT: bne LBB5_4
; ARMOPTNONE-NEXT: @ %bb.3: @ %atomicrmw.start
; ARMOPTNONE-NEXT: @ in Loop: Header=BB5_2 Depth=2
-; ARMOPTNONE-NEXT: strexd r0, r10, r11, [r3]
-; ARMOPTNONE-NEXT: cmp r0, #0
+; ARMOPTNONE-NEXT: strexd r9, r0, r1, [r8]
+; ARMOPTNONE-NEXT: cmp r9, #0
; ARMOPTNONE-NEXT: bne LBB5_2
; ARMOPTNONE-NEXT: LBB5_4: @ %atomicrmw.start
; ARMOPTNONE-NEXT: @ in Loop: Header=BB5_1 Depth=1
+; ARMOPTNONE-NEXT: ldr r1, [sp] @ 4-byte Reload
; ARMOPTNONE-NEXT: mov r0, r5
; ARMOPTNONE-NEXT: eor r3, r0, r1
; ARMOPTNONE-NEXT: mov r1, r4
; ARMOPTNONE-NEXT: eor r2, r1, r2
; ARMOPTNONE-NEXT: orr r2, r2, r3
; ARMOPTNONE-NEXT: cmp r2, #0
-; ARMOPTNONE-NEXT: str r1, [sp, #12] @ 4-byte Spill
-; ARMOPTNONE-NEXT: str r0, [sp, #16] @ 4-byte Spill
+; ARMOPTNONE-NEXT: str r1, [sp, #16] @ 4-byte Spill
+; ARMOPTNONE-NEXT: str r0, [sp, #20] @ 4-byte Spill
; ARMOPTNONE-NEXT: bne LBB5_1
; ARMOPTNONE-NEXT: b LBB5_5
; ARMOPTNONE-NEXT: LBB5_5: @ %atomicrmw.end
@@ -861,52 +867,58 @@ define void @store_atomic_f64__seq_cst(ptr %ptr, double %val1) {
; ARMOPTNONE-NEXT: push {r4, r5, r7, lr}
; ARMOPTNONE-NEXT: add r7, sp, #8
; ARMOPTNONE-NEXT: push {r8, r10, r11}
-; ARMOPTNONE-NEXT: sub sp, sp, #20
-; ARMOPTNONE-NEXT: str r0, [sp] @ 4-byte Spill
+; ARMOPTNONE-NEXT: sub sp, sp, #24
+; ARMOPTNONE-NEXT: str r0, [sp, #4] @ 4-byte Spill
; ARMOPTNONE-NEXT: vmov d16, r1, r2
; ARMOPTNONE-NEXT: vmov r1, r2, d16
-; ARMOPTNONE-NEXT: str r2, [sp, #4] @ 4-byte Spill
-; ARMOPTNONE-NEXT: str r1, [sp, #8] @ 4-byte Spill
+; ARMOPTNONE-NEXT: str r2, [sp, #8] @ 4-byte Spill
+; ARMOPTNONE-NEXT: str r1, [sp, #12] @ 4-byte Spill
; ARMOPTNONE-NEXT: dmb ish
; ARMOPTNONE-NEXT: ldr r1, [r0]
; ARMOPTNONE-NEXT: ldr r0, [r0, #4]
-; ARMOPTNONE-NEXT: str r1, [sp, #12] @ 4-byte Spill
-; ARMOPTNONE-NEXT: str r0, [sp, #16] @ 4-byte Spill
+; ARMOPTNONE-NEXT: str r1, [sp, #16] @ 4-byte Spill
+; ARMOPTNONE-NEXT: str r0, [sp, #20] @ 4-byte Spill
; ARMOPTNONE-NEXT: b LBB13_1
; ARMOPTNONE-NEXT: LBB13_1: @ %atomicrmw.start
; ARMOPTNONE-NEXT: @ =>This Loop Header: Depth=1
; ARMOPTNONE-NEXT: @ Child Loop BB13_2 Depth 2
-; ARMOPTNONE-NEXT: ldr r1, [sp, #16] @ 4-byte Reload
-; ARMOPTNONE-NEXT: ldr r2, [sp, #12] @ 4-byte Reload
-; ARMOPTNONE-NEXT: ldr r3, [sp] @ 4-byte Reload
-; ARMOPTNONE-NEXT: ldr r0, [sp, #4] @ 4-byte Reload
-; ARMOPTNONE-NEXT: ldr r10, [sp, #8] @ 4-byte Reload
-; ARMOPTNONE-NEXT: @ kill: def $r10 killed $r10 def $r10_r11
-; ARMOPTNONE-NEXT: mov r11, r0
-; ARMOPTNONE-NEXT: mov r8, r2
+; ARMOPTNONE-NEXT: ldr r3, [sp, #20] @ 4-byte Reload
+; ARMOPTNONE-NEXT: ldr r2, [sp, #16] @ 4-byte Reload
+; ARMOPTNONE-NEXT: ldr r12, [sp, #8] @ 4-byte Reload
+; ARMOPTNONE-NEXT: ldr r0, [sp, #12] @ 4-byte Reload
+; ARMOPTNONE-NEXT: ldr r8, [sp, #4] @ 4-byte Reload
+; ARMOPTNONE-NEXT: str r3, [sp] @ 4-byte Spill
+; ARMOPTNONE-NEXT: @ implicit-def: $r1
+; ARMOPTNONE-NEXT: @ implicit-def: $r9
+; ARMOPTNONE-NEXT: @ kill: def $r8 killed $r8 def $r8_r9
; ARMOPTNONE-NEXT: mov r9, r1
+; ARMOPTNONE-NEXT: @ kill: def $r0 killed $r0 def $r0_r1
+; ARMOPTNONE-NEXT: mov r1, r12
+; ARMOPTNONE-NEXT: mov r10, r2
+; ARMOPTNONE-NEXT: mov r11, r3
; ARMOPTNONE-NEXT: LBB13_2: @ %atomicrmw.start
; ARMOPTNONE-NEXT: @ Parent Loop BB13_1 Depth=1
; ARMOPTNONE-NEXT: @ => This Inner Loop Header: Depth=2
-; ARMOPTNONE-NEXT: ldrexd r4, r5, [r3]
-; ARMOPTNONE-NEXT: cmp r4, r8
-; ARMOPTNONE-NEXT: cmpeq r5, r9
+; ARMOPTNONE-NEXT: ldrexd r4, r5, [r8]
+; ARMOPTNONE-NEXT: cmp r4, r10
+; ARMOPTNONE-NEXT: cmpeq r5, r11
; ARMOPTNONE-NEXT: bne LBB13_4
; ARMOPTNONE-NEXT: @ %bb.3: @ %atomicrmw.start
; ARMOPTNONE-NEXT: @ in Loop: Header=BB13_2 Depth=2
-; ARMOPTNONE-NEXT: strexd r0, r10, r11, [r3]
-; ARMOPTNONE-NEXT: cmp r0, #0
+; ARMOPTNONE-NEXT: strexd r9, r0, r1, [r8]
+; ARMOPTNONE-NEXT: cmp r9, #0
; ARMOPTNONE-NEXT: bne LBB13_2
; ARMOPTNONE-NEXT: LBB13_4: @ %atomicrmw.start
; ARMOPTNONE-NEXT: @ in Loop: Header=BB13_1 Depth=1
+; ARMOPTNONE-NEXT: ldr r1, [sp] @ 4-byte Reload
; ARMOPTNONE-NEXT: mov r0, r5
; ARMOPTNONE-NEXT: eor r3, r0, r1
; ARMOPTNONE-NEXT: mov r1, r4
; ARMOPTNONE-NEXT: eor r2, r1, r2
; ARMOPTNONE-NEXT: orr r2, r2, r3
; ARMOPTNONE-NEXT: cmp r2, #0
-; ARMOPTNONE-NEXT: str r1, [sp, #12] @ 4-byte Spill
-; ARMOPTNONE-NEXT: str r0, [sp, #16] @ 4-byte Spill
+; ARMOPTNONE-NEXT: str r1, [sp, #16] @ 4-byte Spill
+; ARMOPTNONE-NEXT: str r0, [sp, #20] @ 4-byte Spill
; ARMOPTNONE-NEXT: bne LBB13_1
; ARMOPTNONE-NEXT: b LBB13_5
; ARMOPTNONE-NEXT: LBB13_5: @ %atomicrmw.end
diff --git a/llvm/test/CodeGen/ARM/atomicrmw_exclusive_monitor_ints.ll b/llvm/test/CodeGen/ARM/atomicrmw_exclusive_monitor_ints.ll
index 161692137fc30b..a38ade7cdbf06b 100644
--- a/llvm/test/CodeGen/ARM/atomicrmw_exclusive_monitor_ints.ll
+++ b/llvm/test/CodeGen/ARM/atomicrmw_exclusive_monitor_ints.ll
@@ -6765,8 +6765,8 @@ entry:
define i64 @test_xchg_i64() {
; CHECK-ARM8-LABEL: test_xchg_i64:
; CHECK-ARM8: @ %bb.0: @ %entry
-; CHECK-ARM8-NEXT: .save {r4, r5, r6, r7, r8, r9, r11, lr}
-; CHECK-ARM8-NEXT: push {r4, r5, r6, r7, r8, r9, r11, lr}
+; CHECK-ARM8-NEXT: .save {r4, r5, r6, r7, r8, r9, r10, r11, lr}
+; CHECK-ARM8-NEXT: push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
; CHECK-ARM8-NEXT: .pad #16
; CHECK-ARM8-NEXT: sub sp, sp, #16
; CHECK-ARM8-NEXT: movw r0, :lower16:atomic_i64
@@ -6781,25 +6781,29 @@ define i64 @test_xchg_i64() {
; CHECK-ARM8-NEXT: @ Child Loop BB33_2 Depth 2
; CHECK-ARM8-NEXT: ldr r1, [sp, #12] @ 4-byte Reload
; CHECK-ARM8-NEXT: ldr r2, [sp, #8] @ 4-byte Reload
-; CHECK-ARM8-NEXT: mov r6, r2
-; CHECK-ARM8-NEXT: mov r7, r1
-; CHECK-ARM8-NEXT: movw r3, :lower16:atomic_i64
-; CHECK-ARM8-NEXT: movt r3, :upper16:atomic_i64
+; CHECK-ARM8-NEXT: movw r6, :lower16:atomic_i64
+; CHECK-ARM8-NEXT: movt r6, :upper16:atomic_i64
+; CHECK-ARM8-NEXT: @ implicit-def: $r0
+; CHECK-ARM8-NEXT: @ implicit-def: $r3
+; CHECK-ARM8-NEXT: @ kill: def $r6 killed $r6 def $r6_r7
+; CHECK-ARM8-NEXT: mov r7, r0
+; CHECK-ARM8-NEXT: mov r8, r2
+; CHECK-ARM8-NEXT: mov r9, r1
; CHECK-ARM8-NEXT: mov r0, #0
-; CHECK-ARM8-NEXT: mov r8, #1
-; CHECK-ARM8-NEXT: @ kill: def $r8 killed $r8 def $r8_r9
-; CHECK-ARM8-NEXT: mov r9, r0
+; CHECK-ARM8-NEXT: mov r10, #1
+; CHECK-ARM8-NEXT: @ kill: def $r10 killed $r10 def $r10_r11
+; CHECK-ARM8-NEXT: mov r11, r0
; CHECK-ARM8-NEXT: .LBB33_2: @ %atomicrmw.start
; CHECK-ARM8-NEXT: @ Parent Loop BB33_1 Depth=1
; CHECK-ARM8-NEXT: @ => This Inner Loop Header: Depth=2
-; CHECK-ARM8-NEXT: ldrexd r4, r5, [r3]
-; CHECK-ARM8-NEXT: cmp r4, r6
-; CHECK-ARM8-NEXT: cmpeq r5, r7
+; CHECK-ARM8-NEXT: ldrexd r4, r5, [r6]
+; CHECK-ARM8-NEXT: cmp r4, r8
+; CHECK-ARM8-NEXT: cmpeq r5, r9
; CHECK-ARM8-NEXT: bne .LBB33_4
; CHECK-ARM8-NEXT: @ %bb.3: @ %atomicrmw.start
; CHECK-ARM8-NEXT: @ in Loop: Header=BB33_2 Depth=2
-; CHECK-ARM8-NEXT: strexd r0, r8, r9, [r3]
-; CHECK-ARM8-NEXT: cmp r0, #0
+; CHECK-ARM8-NEXT: strexd r7, r10, r11, [r6]
+; CHECK-ARM8-NEXT: cmp r7, #0
; CHECK-ARM8-NEXT: bne .LBB33_2
; CHECK-ARM8-NEXT: .LBB33_4: @ %atomicrmw.start
; CHECK-ARM8-NEXT: @ in Loop: Header=BB33_1 Depth=1
@@ -6819,12 +6823,12 @@ define i64 @test_xchg_i64() {
; CHECK-ARM8-NEXT: ldr r1, [sp] @ 4-byte Reload
; CHECK-ARM8-NEXT: ldr r0, [sp, #4] @ 4-byte Reload
; CHECK-ARM8-NEXT: add sp, sp, #16
-; CHECK-ARM8-NEXT: pop {r4, r5, r6, r7, r8, r9, r11, pc}
+; CHECK-ARM8-NEXT: pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}
;
; CHECK-ARM6-LABEL: test_xchg_i64:
; CHECK-ARM6: @ %bb.0: @ %entry
-; CHECK-ARM6-NEXT: .save {r4, r5, r6, r7, r8, r9, r11, lr}
-; CHECK-ARM6-NEXT: push {r4, r5, r...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/106721
More information about the llvm-commits
mailing list