Skip to content

Commit 2630141

Browse files
davemgreengithub-actions[bot]
authored andcommitted
Automerge: [ARM] Use lo tCMPr opcode when expanding CMP_SWAP (#204567)
We were always generating the tCMPhir even when the registers were both low, which is an unpredictable instruction. Generating tCMPr instead when both the registers are low. Fixes #204519.
2 parents 7b05655 + 6542d6d commit 2630141

2 files changed

Lines changed: 81 additions & 11 deletions

File tree

llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1841,6 +1841,15 @@ void ARMExpandPseudo::CMSERestoreFPRegsV81(
18411841
}
18421842
}
18431843

1844+
static unsigned getCmpOpcode(bool IsThumb, Register LHS, Register RHS) {
1845+
if (!IsThumb)
1846+
return ARM::CMPrr;
1847+
if (ARM::tGPRRegClass.contains(LHS) &&
1848+
ARM::tGPRRegClass.contains(RHS))
1849+
return ARM::tCMPr;
1850+
return ARM::tCMPhir;
1851+
}
1852+
18441853
/// Expand a CMP_SWAP pseudo-inst to an ldrex/strex loop as simply as
18451854
/// possible. This only gets used at -O0 so we don't care about efficiency of
18461855
/// the generated code.
@@ -1901,7 +1910,7 @@ bool ARMExpandPseudo::ExpandCMP_SWAP(MachineBasicBlock &MBB,
19011910
MIB.addImm(0); // a 32-bit Thumb ldrex (only) allows an offset.
19021911
MIB.add(predOps(ARMCC::AL));
19031912

1904-
unsigned CMPrr = IsThumb ? ARM::tCMPhir : ARM::CMPrr;
1913+
unsigned CMPrr = getCmpOpcode(IsThumb, Dest.getReg(), DesiredReg);
19051914
BuildMI(LoadCmpBB, DL, TII->get(CMPrr))
19061915
.addReg(Dest.getReg(), getKillRegState(Dest.isDead()))
19071916
.addReg(DesiredReg)
@@ -2021,16 +2030,18 @@ bool ARMExpandPseudo::ExpandCMP_SWAP_64(MachineBasicBlock &MBB,
20212030
addExclusiveRegPair(MIB, Dest, RegState::Define, IsThumb, TRI);
20222031
MIB.addReg(AddrReg).add(predOps(ARMCC::AL));
20232032

2024-
unsigned CMPrr = IsThumb ? ARM::tCMPhir : ARM::CMPrr;
2025-
BuildMI(LoadCmpBB, DL, TII->get(CMPrr))
2033+
unsigned CMPrrLo = getCmpOpcode(IsThumb, DestLo, DesiredLo);
2034+
BuildMI(LoadCmpBB, DL, TII->get(CMPrrLo))
20262035
.addReg(DestLo, getKillRegState(Dest.isDead()))
20272036
.addReg(DesiredLo)
20282037
.add(predOps(ARMCC::AL));
20292038

2030-
BuildMI(LoadCmpBB, DL, TII->get(CMPrr))
2039+
unsigned CMPrrHi = getCmpOpcode(IsThumb, DestHi, DesiredHi);
2040+
BuildMI(LoadCmpBB, DL, TII->get(CMPrrHi))
20312041
.addReg(DestHi, getKillRegState(Dest.isDead()))
20322042
.addReg(DesiredHi)
2033-
.addImm(ARMCC::EQ).addReg(ARM::CPSR, RegState::Kill);
2043+
.addImm(ARMCC::EQ)
2044+
.addReg(ARM::CPSR, RegState::Kill);
20342045

20352046
unsigned Bcc = IsThumb ? ARM::tBcc : ARM::Bcc;
20362047
BuildMI(LoadCmpBB, DL, TII->get(Bcc))

llvm/test/CodeGen/Thumb2/cmpxchg.mir

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
# RUN: llc -o - %s -mtriple=thumbv7-unknown-linux-gnu -verify-machineinstrs -run-pass=arm-pseudo | FileCheck %s
33
# RUN: llc -o - %s -mtriple=thumbv7eb-unknown-linux-gnu -verify-machineinstrs -run-pass=arm-pseudo | FileCheck %s
44
---
5-
name: func
5+
name: func64
66
tracksRegLiveness: true
77
body: |
88
bb.0:
99
liveins: $r0_r1, $r4_r5, $r3, $lr
10-
; CHECK-LABEL: name: func
10+
; CHECK-LABEL: name: func64
1111
; CHECK: successors: %bb.1(0x80000000)
1212
; CHECK-NEXT: liveins: $r0_r1, $r4_r5, $r3, $lr
1313
; CHECK-NEXT: {{ $}}
@@ -16,8 +16,8 @@ body: |
1616
; CHECK-NEXT: liveins: $r4, $r5, $r2
1717
; CHECK-NEXT: {{ $}}
1818
; CHECK-NEXT: $r0, $r1 = t2LDREXD $r2, 14 /* CC::al */, $noreg
19-
; CHECK-NEXT: tCMPhir killed $r0, $r4, 14 /* CC::al */, $noreg, implicit-def $cpsr
20-
; CHECK-NEXT: tCMPhir killed $r1, $r5, 0 /* CC::eq */, killed $cpsr, implicit-def $cpsr
19+
; CHECK-NEXT: tCMPr killed $r0, $r4, 14 /* CC::al */, $noreg, implicit-def $cpsr
20+
; CHECK-NEXT: tCMPr killed $r1, $r5, 0 /* CC::eq */, killed $cpsr, implicit-def $cpsr
2121
; CHECK-NEXT: tBcc %bb.3, 1 /* CC::ne */, killed $cpsr
2222
; CHECK-NEXT: {{ $}}
2323
; CHECK-NEXT: .2:
@@ -32,12 +32,42 @@ body: |
3232
dead early-clobber renamable $r0_r1, dead early-clobber renamable $r2_r3 = CMP_SWAP_64 killed renamable $r2_r3, killed renamable $r4_r5, renamable $r4_r5 :: (volatile load store monotonic monotonic (s64))
3333
...
3434
---
35-
name: func2
35+
name: func64_hihi
36+
tracksRegLiveness: true
37+
body: |
38+
bb.0:
39+
liveins: $r0_r1, $r8_r9, $r3, $lr
40+
; CHECK-LABEL: name: func64_hihi
41+
; CHECK: successors: %bb.1(0x80000000)
42+
; CHECK-NEXT: liveins: $r0_r1, $r8_r9, $r3, $lr
43+
; CHECK-NEXT: {{ $}}
44+
; CHECK-NEXT: .1:
45+
; CHECK-NEXT: successors: %bb.3(0x40000000), %bb.2(0x40000000)
46+
; CHECK-NEXT: liveins: $r8, $r9, $r2
47+
; CHECK-NEXT: {{ $}}
48+
; CHECK-NEXT: $r0, $r1 = t2LDREXD $r2, 14 /* CC::al */, $noreg
49+
; CHECK-NEXT: tCMPhir killed $r0, $r8, 14 /* CC::al */, $noreg, implicit-def $cpsr
50+
; CHECK-NEXT: tCMPhir killed $r1, $r9, 0 /* CC::eq */, killed $cpsr, implicit-def $cpsr
51+
; CHECK-NEXT: tBcc %bb.3, 1 /* CC::ne */, killed $cpsr
52+
; CHECK-NEXT: {{ $}}
53+
; CHECK-NEXT: .2:
54+
; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.3(0x40000000)
55+
; CHECK-NEXT: liveins: $r8, $r9, $r2
56+
; CHECK-NEXT: {{ $}}
57+
; CHECK-NEXT: early-clobber $r3 = t2STREXD $r8, $r9, $r2, 14 /* CC::al */, $noreg
58+
; CHECK-NEXT: t2CMPri killed $r3, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr
59+
; CHECK-NEXT: tBcc %bb.1, 1 /* CC::ne */, killed $cpsr
60+
; CHECK-NEXT: {{ $}}
61+
; CHECK-NEXT: .3:
62+
dead early-clobber renamable $r0_r1, dead early-clobber renamable $r2_r3 = CMP_SWAP_64 killed renamable $r2_r3, killed renamable $r8_r9, renamable $r8_r9 :: (volatile load store monotonic monotonic (s64))
63+
...
64+
---
65+
name: func2_hi
3666
tracksRegLiveness: true
3767
body: |
3868
bb.0:
3969
liveins: $r1, $r2, $r3, $r12, $lr
40-
; CHECK-LABEL: name: func2
70+
; CHECK-LABEL: name: func2_hi
4171
; CHECK: successors: %bb.1(0x80000000)
4272
; CHECK-NEXT: liveins: $r1, $r2, $r3, $r12, $lr
4373
; CHECK-NEXT: {{ $}}
@@ -60,3 +90,32 @@ body: |
6090
; CHECK-NEXT: .3:
6191
dead early-clobber renamable $r1, dead early-clobber renamable $r2 = tCMP_SWAP_32 killed renamable $r3, killed renamable $r12, killed renamable $lr
6292
...
93+
---
94+
name: func2_lo
95+
tracksRegLiveness: true
96+
body: |
97+
bb.0:
98+
liveins: $r1, $r2, $r3, $r4, $lr
99+
; CHECK-LABEL: name: func2_lo
100+
; CHECK: successors: %bb.1(0x80000000)
101+
; CHECK-NEXT: liveins: $r1, $r2, $r3, $r4, $lr
102+
; CHECK-NEXT: {{ $}}
103+
; CHECK-NEXT: .1:
104+
; CHECK-NEXT: successors: %bb.3(0x40000000), %bb.2(0x40000000)
105+
; CHECK-NEXT: liveins: $lr, $r3, $r4
106+
; CHECK-NEXT: {{ $}}
107+
; CHECK-NEXT: $r1 = t2LDREX $r3, 0, 14 /* CC::al */, $noreg
108+
; CHECK-NEXT: tCMPr killed $r1, $r4, 14 /* CC::al */, $noreg, implicit-def $cpsr
109+
; CHECK-NEXT: tBcc %bb.3, 1 /* CC::ne */, killed $cpsr
110+
; CHECK-NEXT: {{ $}}
111+
; CHECK-NEXT: .2:
112+
; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.3(0x40000000)
113+
; CHECK-NEXT: liveins: $lr, $r3, $r4
114+
; CHECK-NEXT: {{ $}}
115+
; CHECK-NEXT: early-clobber $r2 = t2STREX $lr, $r3, 0, 14 /* CC::al */, $noreg
116+
; CHECK-NEXT: t2CMPri killed $r2, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr
117+
; CHECK-NEXT: tBcc %bb.1, 1 /* CC::ne */, killed $cpsr
118+
; CHECK-NEXT: {{ $}}
119+
; CHECK-NEXT: .3:
120+
dead early-clobber renamable $r1, dead early-clobber renamable $r2 = tCMP_SWAP_32 killed renamable $r3, killed renamable $r4, killed renamable $lr
121+
...

0 commit comments

Comments
 (0)