llvm.org GIT mirror llvm / 7c67a1f
[ARM] Fix CPSR liveness in tMOVCCr_pseudo lowering. The lowering was missing live-ins in certain cases, like a sequence of multiple tMOVCCr_pseudo instructions. This would lead to a verifier failure, and on pre-v6 Thumb CPSR would be incorrectly clobbered. For reasons I don't completely understand, it's hard to get a sequence of multiple tMOVCCr_pseudo instructions; the issue only seems to show up with 64-bit comparisons where the result is zero-extended. I added some extra testcases in case that changes in the future. Probably some optimization opportunities here if anyone is interested. (@test_slt_not is the case that was getting miscompiled.) The code to check the liveness of CPSR was stolen from X86ISelLowering.cpp; maybe it could be refactored into common helper, but I have no idea where to put it. Differential Revision: https://reviews.llvm.org/D54192 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@346355 91177308-0d34-0410-b5e6-96231b3b80d8 Eli Friedman 10 months ago
3 changed file(s) with 290 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
91599159 return ContBB;
91609160 }
91619161
9162 // The CPSR operand of SelectItr might be missing a kill marker
9163 // because there were multiple uses of CPSR, and ISel didn't know
9164 // which to mark. Figure out whether SelectItr should have had a
9165 // kill marker, and set it if it should. Returns the correct kill
9166 // marker value.
9167 static bool checkAndUpdateCPSRKill(MachineBasicBlock::iterator SelectItr,
9168 MachineBasicBlock* BB,
9169 const TargetRegisterInfo* TRI) {
9170 // Scan forward through BB for a use/def of CPSR.
9171 MachineBasicBlock::iterator miI(std::next(SelectItr));
9172 for (MachineBasicBlock::iterator miE = BB->end(); miI != miE; ++miI) {
9173 const MachineInstr& mi = *miI;
9174 if (mi.readsRegister(ARM::CPSR))
9175 return false;
9176 if (mi.definesRegister(ARM::CPSR))
9177 break; // Should have kill-flag - update below.
9178 }
9179
9180 // If we hit the end of the block, check whether CPSR is live into a
9181 // successor.
9182 if (miI == BB->end()) {
9183 for (MachineBasicBlock::succ_iterator sItr = BB->succ_begin(),
9184 sEnd = BB->succ_end();
9185 sItr != sEnd; ++sItr) {
9186 MachineBasicBlock* succ = *sItr;
9187 if (succ->isLiveIn(ARM::CPSR))
9188 return false;
9189 }
9190 }
9191
9192 // We found a def, or hit the end of the basic block and CPSR wasn't live
9193 // out. SelectMI should have a kill flag on CPSR.
9194 SelectItr->addRegisterKilled(ARM::CPSR, TRI);
9195 return true;
9196 }
9197
91629198 MachineBasicBlock *
91639199 ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
91649200 MachineBasicBlock *BB) const {
92579293 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
92589294 F->insert(It, copy0MBB);
92599295 F->insert(It, sinkMBB);
9296
9297 // Check whether CPSR is live past the tMOVCCr_pseudo.
9298 const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo();
9299 if (!MI.killsRegister(ARM::CPSR) &&
9300 !checkAndUpdateCPSRKill(MI, thisMBB, TRI)) {
9301 copy0MBB->addLiveIn(ARM::CPSR);
9302 sinkMBB->addLiveIn(ARM::CPSR);
9303 }
92609304
92619305 // Transfer the remainder of BB and its successor edges to sinkMBB.
92629306 sinkMBB->splice(sinkMBB->begin(), BB,
0 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
1 ; RUN: llc -mtriple=armv7-unknown-linux < %s | FileCheck --check-prefix=CHECK-ARM %s
2 ; RUN: llc -mtriple=thumbv6-unknown-linux < %s | FileCheck --check-prefix=CHECK-THUMB1 %s
3 ; RUN: llc -mtriple=thumbv7-unknown-linux < %s | FileCheck --check-prefix=CHECK-THUMB2 %s
1 ; RUN: llc -mtriple=armv7-unknown-linux < %s -verify-machineinstrs | FileCheck --check-prefix=CHECK-ARM %s
2 ; RUN: llc -mtriple=thumb-eabi < %s -verify-machineinstrs | FileCheck --check-prefix=CHECK-THUMB1-NOMOV %s
3 ; RUN: llc -mtriple=thumbv6-unknown-linux < %s -verify-machineinstrs | FileCheck --check-prefix=CHECK-THUMB1 %s
4 ; RUN: llc -mtriple=thumbv7-unknown-linux < %s -verify-machineinstrs | FileCheck --check-prefix=CHECK-THUMB2 %s
45
56 define i32 @test_slt1(i64 %a, i64 %b) {
67 ; CHECK-ARM-LABEL: test_slt1:
1112 ; CHECK-ARM-NEXT: movwlt r12, #1
1213 ; CHECK-ARM-NEXT: mov r0, r12
1314 ; CHECK-ARM-NEXT: bx lr
15 ;
16 ; CHECK-THUMB1-NOMOV-LABEL: test_slt1:
17 ; CHECK-THUMB1-NOMOV: @ %bb.0: @ %entry
18 ; CHECK-THUMB1-NOMOV-NEXT: subs r0, r0, r2
19 ; CHECK-THUMB1-NOMOV-NEXT: sbcs r1, r3
20 ; CHECK-THUMB1-NOMOV-NEXT: bge .LBB0_2
21 ; CHECK-THUMB1-NOMOV-NEXT: @ %bb.1: @ %bb1
22 ; CHECK-THUMB1-NOMOV-NEXT: movs r0, #1
23 ; CHECK-THUMB1-NOMOV-NEXT: bx lr
24 ; CHECK-THUMB1-NOMOV-NEXT: .LBB0_2: @ %bb2
25 ; CHECK-THUMB1-NOMOV-NEXT: movs r0, #2
26 ; CHECK-THUMB1-NOMOV-NEXT: bx lr
1427 ;
1528 ; CHECK-THUMB1-LABEL: test_slt1:
1629 ; CHECK-THUMB1: @ %bb.0: @ %entry
5568 ; CHECK-ARM-NEXT: .LBB1_2: @ %bb2
5669 ; CHECK-ARM-NEXT: bl g
5770 ; CHECK-ARM-NEXT: pop {r11, pc}
71 ;
72 ; CHECK-THUMB1-NOMOV-LABEL: test_slt2:
73 ; CHECK-THUMB1-NOMOV: @ %bb.0: @ %entry
74 ; CHECK-THUMB1-NOMOV-NEXT: .save {r7, lr}
75 ; CHECK-THUMB1-NOMOV-NEXT: push {r7, lr}
76 ; CHECK-THUMB1-NOMOV-NEXT: subs r0, r0, r2
77 ; CHECK-THUMB1-NOMOV-NEXT: sbcs r1, r3
78 ; CHECK-THUMB1-NOMOV-NEXT: bge .LBB1_2
79 ; CHECK-THUMB1-NOMOV-NEXT: @ %bb.1: @ %bb1
80 ; CHECK-THUMB1-NOMOV-NEXT: bl f
81 ; CHECK-THUMB1-NOMOV-NEXT: b .LBB1_3
82 ; CHECK-THUMB1-NOMOV-NEXT: .LBB1_2: @ %bb2
83 ; CHECK-THUMB1-NOMOV-NEXT: bl g
84 ; CHECK-THUMB1-NOMOV-NEXT: .LBB1_3: @ %bb1
85 ; CHECK-THUMB1-NOMOV-NEXT: pop {r7}
86 ; CHECK-THUMB1-NOMOV-NEXT: pop {r0}
87 ; CHECK-THUMB1-NOMOV-NEXT: bx r0
5888 ;
5989 ; CHECK-THUMB1-LABEL: test_slt2:
6090 ; CHECK-THUMB1: @ %bb.0: @ %entry
94124
95125 declare void @f()
96126 declare void @g()
127
128 define i64 @test_slt_select(i64 %c, i64 %d, i64 %a, i64 %b) {
129 ; CHECK-ARM-LABEL: test_slt_select:
130 ; CHECK-ARM: @ %bb.0: @ %entry
131 ; CHECK-ARM-NEXT: push {r4, r5, r6, r7, r11, lr}
132 ; CHECK-ARM-NEXT: ldr r12, [sp, #32]
133 ; CHECK-ARM-NEXT: mov r6, #0
134 ; CHECK-ARM-NEXT: ldr lr, [sp, #24]
135 ; CHECK-ARM-NEXT: ldr r7, [sp, #36]
136 ; CHECK-ARM-NEXT: ldr r5, [sp, #28]
137 ; CHECK-ARM-NEXT: subs r4, lr, r12
138 ; CHECK-ARM-NEXT: sbcs r7, r5, r7
139 ; CHECK-ARM-NEXT: movwlo r6, #1
140 ; CHECK-ARM-NEXT: cmp r6, #0
141 ; CHECK-ARM-NEXT: moveq r0, r2
142 ; CHECK-ARM-NEXT: moveq r1, r3
143 ; CHECK-ARM-NEXT: pop {r4, r5, r6, r7, r11, pc}
144 ;
145 ; CHECK-THUMB1-NOMOV-LABEL: test_slt_select:
146 ; CHECK-THUMB1-NOMOV: @ %bb.0: @ %entry
147 ; CHECK-THUMB1-NOMOV-NEXT: .save {r4, r5, r6, r7, lr}
148 ; CHECK-THUMB1-NOMOV-NEXT: push {r4, r5, r6, r7, lr}
149 ; CHECK-THUMB1-NOMOV-NEXT: .pad #4
150 ; CHECK-THUMB1-NOMOV-NEXT: sub sp, #4
151 ; CHECK-THUMB1-NOMOV-NEXT: ldr r4, [sp, #36]
152 ; CHECK-THUMB1-NOMOV-NEXT: ldr r5, [sp, #28]
153 ; CHECK-THUMB1-NOMOV-NEXT: ldr r6, [sp, #32]
154 ; CHECK-THUMB1-NOMOV-NEXT: ldr r7, [sp, #24]
155 ; CHECK-THUMB1-NOMOV-NEXT: subs r6, r7, r6
156 ; CHECK-THUMB1-NOMOV-NEXT: sbcs r5, r4
157 ; CHECK-THUMB1-NOMOV-NEXT: blo .LBB2_2
158 ; CHECK-THUMB1-NOMOV-NEXT: @ %bb.1: @ %entry
159 ; CHECK-THUMB1-NOMOV-NEXT: movs r4, #0
160 ; CHECK-THUMB1-NOMOV-NEXT: cmp r4, #0
161 ; CHECK-THUMB1-NOMOV-NEXT: beq .LBB2_3
162 ; CHECK-THUMB1-NOMOV-NEXT: b .LBB2_4
163 ; CHECK-THUMB1-NOMOV-NEXT: .LBB2_2:
164 ; CHECK-THUMB1-NOMOV-NEXT: movs r4, #1
165 ; CHECK-THUMB1-NOMOV-NEXT: cmp r4, #0
166 ; CHECK-THUMB1-NOMOV-NEXT: bne .LBB2_4
167 ; CHECK-THUMB1-NOMOV-NEXT: .LBB2_3: @ %entry
168 ; CHECK-THUMB1-NOMOV-NEXT: movs r0, r2
169 ; CHECK-THUMB1-NOMOV-NEXT: .LBB2_4: @ %entry
170 ; CHECK-THUMB1-NOMOV-NEXT: cmp r4, #0
171 ; CHECK-THUMB1-NOMOV-NEXT: bne .LBB2_6
172 ; CHECK-THUMB1-NOMOV-NEXT: @ %bb.5: @ %entry
173 ; CHECK-THUMB1-NOMOV-NEXT: movs r1, r3
174 ; CHECK-THUMB1-NOMOV-NEXT: .LBB2_6: @ %entry
175 ; CHECK-THUMB1-NOMOV-NEXT: add sp, #4
176 ; CHECK-THUMB1-NOMOV-NEXT: pop {r4, r5, r6, r7}
177 ; CHECK-THUMB1-NOMOV-NEXT: pop {r2}
178 ; CHECK-THUMB1-NOMOV-NEXT: bx r2
179 ;
180 ; CHECK-THUMB1-LABEL: test_slt_select:
181 ; CHECK-THUMB1: @ %bb.0: @ %entry
182 ; CHECK-THUMB1-NEXT: push {r4, r5, r6, r7, lr}
183 ; CHECK-THUMB1-NEXT: sub sp, #4
184 ; CHECK-THUMB1-NEXT: ldr r4, [sp, #36]
185 ; CHECK-THUMB1-NEXT: ldr r5, [sp, #28]
186 ; CHECK-THUMB1-NEXT: ldr r6, [sp, #32]
187 ; CHECK-THUMB1-NEXT: ldr r7, [sp, #24]
188 ; CHECK-THUMB1-NEXT: subs r6, r7, r6
189 ; CHECK-THUMB1-NEXT: sbcs r5, r4
190 ; CHECK-THUMB1-NEXT: blo .LBB2_2
191 ; CHECK-THUMB1-NEXT: @ %bb.1: @ %entry
192 ; CHECK-THUMB1-NEXT: movs r4, #0
193 ; CHECK-THUMB1-NEXT: cmp r4, #0
194 ; CHECK-THUMB1-NEXT: beq .LBB2_3
195 ; CHECK-THUMB1-NEXT: b .LBB2_4
196 ; CHECK-THUMB1-NEXT: .LBB2_2:
197 ; CHECK-THUMB1-NEXT: movs r4, #1
198 ; CHECK-THUMB1-NEXT: cmp r4, #0
199 ; CHECK-THUMB1-NEXT: bne .LBB2_4
200 ; CHECK-THUMB1-NEXT: .LBB2_3: @ %entry
201 ; CHECK-THUMB1-NEXT: mov r0, r2
202 ; CHECK-THUMB1-NEXT: .LBB2_4: @ %entry
203 ; CHECK-THUMB1-NEXT: cmp r4, #0
204 ; CHECK-THUMB1-NEXT: beq .LBB2_6
205 ; CHECK-THUMB1-NEXT: @ %bb.5: @ %entry
206 ; CHECK-THUMB1-NEXT: add sp, #4
207 ; CHECK-THUMB1-NEXT: pop {r4, r5, r6, r7, pc}
208 ; CHECK-THUMB1-NEXT: .LBB2_6: @ %entry
209 ; CHECK-THUMB1-NEXT: mov r1, r3
210 ; CHECK-THUMB1-NEXT: add sp, #4
211 ; CHECK-THUMB1-NEXT: pop {r4, r5, r6, r7, pc}
212 ;
213 ; CHECK-THUMB2-LABEL: test_slt_select:
214 ; CHECK-THUMB2: @ %bb.0: @ %entry
215 ; CHECK-THUMB2-NEXT: push {r4, r5, r6, r7, lr}
216 ; CHECK-THUMB2-NEXT: sub sp, #4
217 ; CHECK-THUMB2-NEXT: ldrd r12, r7, [sp, #32]
218 ; CHECK-THUMB2-NEXT: movs r6, #0
219 ; CHECK-THUMB2-NEXT: ldrd lr, r5, [sp, #24]
220 ; CHECK-THUMB2-NEXT: subs.w r4, lr, r12
221 ; CHECK-THUMB2-NEXT: sbcs.w r7, r5, r7
222 ; CHECK-THUMB2-NEXT: it lo
223 ; CHECK-THUMB2-NEXT: movlo r6, #1
224 ; CHECK-THUMB2-NEXT: cmp r6, #0
225 ; CHECK-THUMB2-NEXT: itt eq
226 ; CHECK-THUMB2-NEXT: moveq r0, r2
227 ; CHECK-THUMB2-NEXT: moveq r1, r3
228 ; CHECK-THUMB2-NEXT: add sp, #4
229 ; CHECK-THUMB2-NEXT: pop {r4, r5, r6, r7, pc}
230 entry:
231 %cmp = icmp ult i64 %a, %b
232 %r1 = select i1 %cmp, i64 %c, i64 %d
233 ret i64 %r1
234 }
235
236 define {i32, i32} @test_slt_not(i32 %c, i32 %d, i64 %a, i64 %b) {
237 ; CHECK-ARM-LABEL: test_slt_not:
238 ; CHECK-ARM: @ %bb.0: @ %entry
239 ; CHECK-ARM-NEXT: ldr r12, [sp]
240 ; CHECK-ARM-NEXT: mov r1, #0
241 ; CHECK-ARM-NEXT: ldr r0, [sp, #4]
242 ; CHECK-ARM-NEXT: subs r2, r2, r12
243 ; CHECK-ARM-NEXT: sbcs r0, r3, r0
244 ; CHECK-ARM-NEXT: mov r0, #0
245 ; CHECK-ARM-NEXT: movwge r1, #1
246 ; CHECK-ARM-NEXT: movwlt r0, #1
247 ; CHECK-ARM-NEXT: bx lr
248 ;
249 ; CHECK-THUMB1-NOMOV-LABEL: test_slt_not:
250 ; CHECK-THUMB1-NOMOV: @ %bb.0: @ %entry
251 ; CHECK-THUMB1-NOMOV-NEXT: .save {r4, r5, r7, lr}
252 ; CHECK-THUMB1-NOMOV-NEXT: push {r4, r5, r7, lr}
253 ; CHECK-THUMB1-NOMOV-NEXT: movs r1, #1
254 ; CHECK-THUMB1-NOMOV-NEXT: movs r4, #0
255 ; CHECK-THUMB1-NOMOV-NEXT: ldr r0, [sp, #20]
256 ; CHECK-THUMB1-NOMOV-NEXT: ldr r5, [sp, #16]
257 ; CHECK-THUMB1-NOMOV-NEXT: subs r2, r2, r5
258 ; CHECK-THUMB1-NOMOV-NEXT: sbcs r3, r0
259 ; CHECK-THUMB1-NOMOV-NEXT: push {r1}
260 ; CHECK-THUMB1-NOMOV-NEXT: pop {r0}
261 ; CHECK-THUMB1-NOMOV-NEXT: blt .LBB3_2
262 ; CHECK-THUMB1-NOMOV-NEXT: @ %bb.1: @ %entry
263 ; CHECK-THUMB1-NOMOV-NEXT: push {r4}
264 ; CHECK-THUMB1-NOMOV-NEXT: pop {r0}
265 ; CHECK-THUMB1-NOMOV-NEXT: .LBB3_2: @ %entry
266 ; CHECK-THUMB1-NOMOV-NEXT: bge .LBB3_4
267 ; CHECK-THUMB1-NOMOV-NEXT: @ %bb.3: @ %entry
268 ; CHECK-THUMB1-NOMOV-NEXT: movs r1, r4
269 ; CHECK-THUMB1-NOMOV-NEXT: .LBB3_4: @ %entry
270 ; CHECK-THUMB1-NOMOV-NEXT: pop {r4, r5, r7}
271 ; CHECK-THUMB1-NOMOV-NEXT: pop {r2}
272 ; CHECK-THUMB1-NOMOV-NEXT: bx r2
273 ;
274 ; CHECK-THUMB1-LABEL: test_slt_not:
275 ; CHECK-THUMB1: @ %bb.0: @ %entry
276 ; CHECK-THUMB1-NEXT: push {r4, r5, r7, lr}
277 ; CHECK-THUMB1-NEXT: movs r1, #1
278 ; CHECK-THUMB1-NEXT: movs r4, #0
279 ; CHECK-THUMB1-NEXT: ldr r0, [sp, #20]
280 ; CHECK-THUMB1-NEXT: ldr r5, [sp, #16]
281 ; CHECK-THUMB1-NEXT: subs r2, r2, r5
282 ; CHECK-THUMB1-NEXT: sbcs r3, r0
283 ; CHECK-THUMB1-NEXT: mov r0, r1
284 ; CHECK-THUMB1-NEXT: bge .LBB3_3
285 ; CHECK-THUMB1-NEXT: @ %bb.1: @ %entry
286 ; CHECK-THUMB1-NEXT: blt .LBB3_4
287 ; CHECK-THUMB1-NEXT: .LBB3_2: @ %entry
288 ; CHECK-THUMB1-NEXT: pop {r4, r5, r7, pc}
289 ; CHECK-THUMB1-NEXT: .LBB3_3: @ %entry
290 ; CHECK-THUMB1-NEXT: mov r0, r4
291 ; CHECK-THUMB1-NEXT: bge .LBB3_2
292 ; CHECK-THUMB1-NEXT: .LBB3_4: @ %entry
293 ; CHECK-THUMB1-NEXT: mov r1, r4
294 ; CHECK-THUMB1-NEXT: pop {r4, r5, r7, pc}
295 ;
296 ; CHECK-THUMB2-LABEL: test_slt_not:
297 ; CHECK-THUMB2: @ %bb.0: @ %entry
298 ; CHECK-THUMB2-NEXT: ldr.w r12, [sp]
299 ; CHECK-THUMB2-NEXT: movs r1, #0
300 ; CHECK-THUMB2-NEXT: ldr r0, [sp, #4]
301 ; CHECK-THUMB2-NEXT: subs.w r2, r2, r12
302 ; CHECK-THUMB2-NEXT: sbcs.w r0, r3, r0
303 ; CHECK-THUMB2-NEXT: mov.w r0, #0
304 ; CHECK-THUMB2-NEXT: ite lt
305 ; CHECK-THUMB2-NEXT: movlt r0, #1
306 ; CHECK-THUMB2-NEXT: movge r1, #1
307 ; CHECK-THUMB2-NEXT: bx lr
308 entry:
309 %cmp = icmp slt i64 %a, %b
310 %not = xor i1 %cmp, true
311 %r1 = zext i1 %cmp to i32
312 %r2 = zext i1 %not to i32
313 %z = insertvalue { i32, i32 } undef, i32 %r1, 0
314 %z2 = insertvalue { i32, i32 } %z, i32 %r2, 1
315 ret { i32, i32 } %z2
316 }
None ; RUN: llc < %s -mtriple=thumb-apple-darwin | FileCheck %s
1 ; RUN: llc < %s -mtriple=thumb-pc-linux-gnueabi | FileCheck -check-prefix=CHECK-EABI %s
0 ; RUN: llc < %s -mtriple=thumb-apple-darwin -verify-machineinstrs | FileCheck %s
1 ; RUN: llc < %s -mtriple=thumb-pc-linux-gnueabi -verify-machineinstrs | FileCheck -check-prefix=CHECK-EABI %s
22
33 define i32 @f1(i32 %a.s) {
44 entry:
7979 ; CHECK-EABI: __aeabi_dcmplt
8080 ; CHECK-EABI: {{bne|beq}}
8181 ; CHECK-EABI: {{bne|beq}}
82
83 define {i32, i32} @f8(i32 %a, i32 %b, i32 %c, i32 %d) {
84 entry:
85 %cmp = icmp slt i32 %a, %b
86 %r1 = select i1 %cmp, i32 %c, i32 %a
87 %r2 = select i1 %cmp, i32 %d, i32 %b
88 %z = insertvalue { i32, i32 } undef, i32 %r1, 0
89 %z2 = insertvalue { i32, i32 } %z, i32 %r2, 1
90 ret { i32, i32 } %z2
91 }
92
93 ; CHECK-LABEL: f8:
94 ; CHECK: cmp r0, r1
95 ; CHECK: blt
96 ; CHECK: movs
97 ; CHECK: cmp r0, r1
98 ; CHECK: blt
99 ; CHECK: movs
100 ; CHECK: movs
101 ; CHECK: movs
102 ; CHECK: bx lr