Skip to content

Commit b134c62

Browse files
committed
[AArch64] Fix creation of invalid instructions with XZR register
A combination of GlobalISel and MachineCombiner can end up creating `SUB xrz, (MOVI -2105098)` instructions which have not been constant folded. The AArch64MIPeepholeOpt pass will then attempt to create `ADD xzr, 513, lsl 12`, which is not a valid instruction. This adds a bail out of the transform if the register is xzr/wzr. Fixes llvm#60528 Differential Revision: https://reviews.llvm.org/D143475
1 parent 22d9828 commit b134c62

File tree

2 files changed

+109
-7
lines changed

2 files changed

+109
-7
lines changed

llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -323,17 +323,24 @@ bool AArch64MIPeepholeOpt::visitADDSUB(
323323
unsigned PosOpc, unsigned NegOpc, MachineInstr &MI) {
324324
// Try below transformation.
325325
//
326-
// MOVi32imm + ADDWrr ==> ADDWri + ADDWri
327-
// MOVi64imm + ADDXrr ==> ADDXri + ADDXri
326+
// ADDWrr X, MOVi32imm ==> ADDWri + ADDWri
327+
// ADDXrr X, MOVi64imm ==> ADDXri + ADDXri
328328
//
329-
// MOVi32imm + SUBWrr ==> SUBWri + SUBWri
330-
// MOVi64imm + SUBXrr ==> SUBXri + SUBXri
329+
// SUBWrr X, MOVi32imm ==> SUBWri + SUBWri
330+
// SUBXrr X, MOVi64imm ==> SUBXri + SUBXri
331331
//
332332
// The mov pseudo instruction could be expanded to multiple mov instructions
333333
// later. Let's try to split the constant operand of mov instruction into two
334334
// legal add/sub immediates. It makes only two ADD/SUB instructions intead of
335335
// multiple `mov` + `and/sub` instructions.
336336

337+
// We can sometimes have ADDWrr WZR, MULi32imm that have not been constant
338+
// folded. Make sure that we don't generate invalid instructions that use XZR
339+
// in those cases.
340+
if (MI.getOperand(1).getReg() == AArch64::XZR ||
341+
MI.getOperand(1).getReg() == AArch64::WZR)
342+
return false;
343+
337344
return splitTwoPartImm<T>(
338345
MI,
339346
[PosOpc, NegOpc](T Imm, unsigned RegSize, T &Imm0,
@@ -365,6 +372,11 @@ bool AArch64MIPeepholeOpt::visitADDSSUBS(
365372
OpcodePair PosOpcs, OpcodePair NegOpcs, MachineInstr &MI) {
366373
// Try the same transformation as ADDSUB but with additional requirement
367374
// that the condition code usages are only for Equal and Not Equal
375+
376+
if (MI.getOperand(1).getReg() == AArch64::XZR ||
377+
MI.getOperand(1).getReg() == AArch64::WZR)
378+
return false;
379+
368380
return splitTwoPartImm<T>(
369381
MI,
370382
[PosOpcs, NegOpcs, &MI, &TRI = TRI,

llvm/test/CodeGen/AArch64/addsub-24bit-imm.mir

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ body: |
1010
bb.0.entry:
1111
liveins: $w0
1212
; CHECK-LABEL: name: addi
13-
; CHECK: [[COPY:%[0-9]+]]:gpr32common = COPY $w0
13+
; CHECK: liveins: $w0
14+
; CHECK-NEXT: {{ $}}
15+
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32common = COPY $w0
1416
; CHECK-NEXT: [[ADDWri:%[0-9]+]]:gpr32sp = ADDWri [[COPY]], 273, 12
1517
; CHECK-NEXT: [[ADDWri1:%[0-9]+]]:gpr32common = ADDWri [[ADDWri]], 3549, 0
1618
; CHECK-NEXT: [[UBFMWri:%[0-9]+]]:gpr32 = UBFMWri [[ADDWri1]], 28, 31
@@ -29,7 +31,9 @@ body: |
2931
bb.0.entry:
3032
liveins: $x0
3133
; CHECK-LABEL: name: addl
32-
; CHECK: [[COPY:%[0-9]+]]:gpr64common = COPY $x0
34+
; CHECK: liveins: $x0
35+
; CHECK-NEXT: {{ $}}
36+
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64common = COPY $x0
3337
; CHECK-NEXT: [[ADDXri:%[0-9]+]]:gpr64sp = ADDXri [[COPY]], 273, 12
3438
; CHECK-NEXT: [[ADDXri1:%[0-9]+]]:gpr64common = ADDXri [[ADDXri]], 3549, 0
3539
; CHECK-NEXT: [[UBFMXri:%[0-9]+]]:gpr64 = UBFMXri [[ADDXri1]], 28, 31
@@ -49,7 +53,9 @@ body: |
4953
bb.0.entry:
5054
liveins: $x0
5155
; CHECK-LABEL: name: addl_negate
52-
; CHECK: [[COPY:%[0-9]+]]:gpr64common = COPY $x0
56+
; CHECK: liveins: $x0
57+
; CHECK-NEXT: {{ $}}
58+
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64common = COPY $x0
5359
; CHECK-NEXT: [[SUBXri:%[0-9]+]]:gpr64sp = SUBXri [[COPY]], 273, 12
5460
; CHECK-NEXT: [[SUBXri1:%[0-9]+]]:gpr64common = SUBXri [[SUBXri]], 3549, 0
5561
; CHECK-NEXT: [[UBFMXri:%[0-9]+]]:gpr64 = UBFMXri [[SUBXri1]], 28, 31
@@ -61,3 +67,87 @@ body: |
6167
%3:gpr64 = UBFMXri %2, 28, 31
6268
$x0 = COPY %3
6369
RET_ReallyLR implicit $x0
70+
...
71+
---
72+
name: add_xzr
73+
body: |
74+
bb.0.entry:
75+
liveins: $x0
76+
; CHECK-LABEL: name: add_xzr
77+
; CHECK: liveins: $x0
78+
; CHECK-NEXT: {{ $}}
79+
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0
80+
; CHECK-NEXT: [[MOVi64imm:%[0-9]+]]:gpr64 = MOVi64imm -2105098
81+
; CHECK-NEXT: [[ADDXrr:%[0-9]+]]:gpr64common = ADDXrr $xzr, [[MOVi64imm]]
82+
; CHECK-NEXT: [[MADDXrrr:%[0-9]+]]:gpr64 = MADDXrrr [[COPY]], [[COPY]], [[ADDXrr]]
83+
; CHECK-NEXT: $x0 = COPY [[MADDXrrr]]
84+
; CHECK-NEXT: RET_ReallyLR implicit $x0
85+
%0:gpr64 = COPY $x0
86+
%2:gpr64 = MOVi64imm -2105098
87+
%4:gpr64common = ADDXrr $xzr, %2
88+
%3:gpr64 = MADDXrrr %0, %0, %4
89+
$x0 = COPY %3
90+
RET_ReallyLR implicit $x0
91+
...
92+
---
93+
name: sub_xzr
94+
body: |
95+
bb.0.entry:
96+
liveins: $x0
97+
; CHECK-LABEL: name: sub_xzr
98+
; CHECK: liveins: $x0
99+
; CHECK-NEXT: {{ $}}
100+
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0
101+
; CHECK-NEXT: [[MOVi64imm:%[0-9]+]]:gpr64 = MOVi64imm -2105098
102+
; CHECK-NEXT: [[SUBXrr:%[0-9]+]]:gpr64common = SUBXrr $xzr, [[MOVi64imm]]
103+
; CHECK-NEXT: [[MADDXrrr:%[0-9]+]]:gpr64 = MADDXrrr [[COPY]], [[COPY]], [[SUBXrr]]
104+
; CHECK-NEXT: $x0 = COPY [[MADDXrrr]]
105+
; CHECK-NEXT: RET_ReallyLR implicit $x0
106+
%0:gpr64 = COPY $x0
107+
%2:gpr64 = MOVi64imm -2105098
108+
%4:gpr64common = SUBXrr $xzr, %2
109+
%3:gpr64 = MADDXrrr %0, %0, %4
110+
$x0 = COPY %3
111+
RET_ReallyLR implicit $x0
112+
...
113+
---
114+
name: adds_xzr
115+
body: |
116+
bb.0.entry:
117+
liveins: $x0
118+
; CHECK-LABEL: name: adds_xzr
119+
; CHECK: liveins: $x0
120+
; CHECK-NEXT: {{ $}}
121+
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0
122+
; CHECK-NEXT: [[MOVi64imm:%[0-9]+]]:gpr64 = MOVi64imm -2105098
123+
; CHECK-NEXT: [[ADDSXrr:%[0-9]+]]:gpr64common = ADDSXrr $xzr, [[MOVi64imm]], implicit-def $nzcv
124+
; CHECK-NEXT: [[MADDXrrr:%[0-9]+]]:gpr64 = MADDXrrr [[COPY]], [[COPY]], [[ADDSXrr]]
125+
; CHECK-NEXT: $x0 = COPY [[MADDXrrr]]
126+
; CHECK-NEXT: RET_ReallyLR implicit $x0
127+
%0:gpr64 = COPY $x0
128+
%2:gpr64 = MOVi64imm -2105098
129+
%4:gpr64common = ADDSXrr $xzr, %2, implicit-def $nzcv
130+
%3:gpr64 = MADDXrrr %0, %0, %4
131+
$x0 = COPY %3
132+
RET_ReallyLR implicit $x0
133+
...
134+
---
135+
name: subs_xzr
136+
body: |
137+
bb.0.entry:
138+
liveins: $x0
139+
; CHECK-LABEL: name: subs_xzr
140+
; CHECK: liveins: $x0
141+
; CHECK-NEXT: {{ $}}
142+
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0
143+
; CHECK-NEXT: [[MOVi64imm:%[0-9]+]]:gpr64 = MOVi64imm -2105098
144+
; CHECK-NEXT: [[SUBSXrr:%[0-9]+]]:gpr64common = SUBSXrr $xzr, [[MOVi64imm]], implicit-def $nzcv
145+
; CHECK-NEXT: [[MADDXrrr:%[0-9]+]]:gpr64 = MADDXrrr [[COPY]], [[COPY]], [[SUBSXrr]]
146+
; CHECK-NEXT: $x0 = COPY [[MADDXrrr]]
147+
; CHECK-NEXT: RET_ReallyLR implicit $x0
148+
%0:gpr64 = COPY $x0
149+
%2:gpr64 = MOVi64imm -2105098
150+
%4:gpr64common = SUBSXrr $xzr, %2, implicit-def $nzcv
151+
%3:gpr64 = MADDXrrr %0, %0, %4
152+
$x0 = COPY %3
153+
RET_ReallyLR implicit $x0

0 commit comments

Comments
 (0)