1 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2 # RUN: llc -mtriple aarch64-unknown-unknown -run-pass=instruction-select -global-isel-abort=1 -verify-machineinstrs %s -o - | FileCheck %s
4 # Check folding a G_SHL into a G_BRCOND which has been matched as a TB(N)Z.
12 ; CHECK-LABEL: name: fold_shl
14 ; CHECK-NEXT: successors: %bb.0(0x40000000), %bb.1(0x40000000)
15 ; CHECK-NEXT: liveins: $x0
17 ; CHECK-NEXT: %copy:gpr64all = COPY $x0
18 ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32all = COPY %copy.sub_32
19 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32 = COPY [[COPY]]
20 ; CHECK-NEXT: TBNZW [[COPY1]], 2, %bb.1
24 ; CHECK-NEXT: RET_ReallyLR
26 successors: %bb.0, %bb.1
28 %copy:gpr(s64) = COPY $x0
29 %bit:gpr(s64) = G_CONSTANT i64 8
30 %zero:gpr(s64) = G_CONSTANT i64 0
32 ; tbnz (shl x, 1), 3 == tbnz x, 2
33 %fold_cst:gpr(s64) = G_CONSTANT i64 1
34 %fold_me:gpr(s64) = G_SHL %copy, %fold_cst
36 %and:gpr(s64) = G_AND %fold_me, %bit
37 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero
49 ; CHECK-LABEL: name: dont_fold_shl_1
51 ; CHECK-NEXT: successors: %bb.0(0x40000000), %bb.1(0x40000000)
52 ; CHECK-NEXT: liveins: $x0
54 ; CHECK-NEXT: %copy:gpr64 = COPY $x0
55 ; CHECK-NEXT: %fold_me:gpr64 = UBFMXri %copy, 59, 58
56 ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32all = COPY %fold_me.sub_32
57 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32 = COPY [[COPY]]
58 ; CHECK-NEXT: TBNZW [[COPY1]], 3, %bb.1
62 ; CHECK-NEXT: RET_ReallyLR
64 successors: %bb.0, %bb.1
66 %copy:gpr(s64) = COPY $x0
67 %bit:gpr(s64) = G_CONSTANT i64 8
68 %zero:gpr(s64) = G_CONSTANT i64 0
70 ; 5 > 3, so we cannot do the transformation as above.
71 %fold_cst:gpr(s64) = G_CONSTANT i64 5
72 %fold_me:gpr(s64) = G_SHL %copy, %fold_cst
74 %and:gpr(s64) = G_AND %fold_me, %bit
75 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero
87 ; CHECK-LABEL: name: dont_fold_shl_2
89 ; CHECK-NEXT: successors: %bb.0(0x40000000), %bb.1(0x40000000)
90 ; CHECK-NEXT: liveins: $x0
92 ; CHECK-NEXT: %copy:gpr64 = COPY $x0
93 ; CHECK-NEXT: %fold_cst:gpr64 = MOVi64imm -5
94 ; CHECK-NEXT: %fold_me:gpr64 = LSLVXr %copy, %fold_cst
95 ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32all = COPY %fold_me.sub_32
96 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32 = COPY [[COPY]]
97 ; CHECK-NEXT: TBNZW [[COPY1]], 3, %bb.1
101 ; CHECK-NEXT: RET_ReallyLR
103 successors: %bb.0, %bb.1
105 %copy:gpr(s64) = COPY $x0
106 %bit:gpr(s64) = G_CONSTANT i64 8
107 %zero:gpr(s64) = G_CONSTANT i64 0
109 ; Same case as above, except we wrap around.
110 %fold_cst:gpr(s64) = G_CONSTANT i64 -5
111 %fold_me:gpr(s64) = G_SHL %copy, %fold_cst
113 %and:gpr(s64) = G_AND %fold_me, %bit
114 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero
122 name: dont_fold_shl_3
125 regBankSelected: true
127 ; CHECK-LABEL: name: dont_fold_shl_3
129 ; CHECK-NEXT: successors: %bb.0(0x40000000), %bb.1(0x40000000)
130 ; CHECK-NEXT: liveins: $x0
132 ; CHECK-NEXT: %copy:gpr64 = COPY $x0
133 ; CHECK-NEXT: %shl:gpr64 = UBFMXri %copy, 62, 61
134 ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32all = COPY %shl.sub_32
135 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32 = COPY [[COPY]]
136 ; CHECK-NEXT: TBNZW [[COPY1]], 3, %bb.1
137 ; CHECK-NEXT: B %bb.0
140 ; CHECK-NEXT: %second_use:gpr64sp = ORRXri %shl, 8000
141 ; CHECK-NEXT: $x0 = COPY %second_use
142 ; CHECK-NEXT: RET_ReallyLR implicit $x0
144 successors: %bb.0, %bb.1
146 %copy:gpr(s64) = COPY $x0
147 %bit:gpr(s64) = G_CONSTANT i64 8
148 %zero:gpr(s64) = G_CONSTANT i64 0
149 %fold_cst:gpr(s64) = G_CONSTANT i64 2
151 ; Don't walk past the G_SHL when it's used more than once.
152 %shl:gpr(s64) = G_SHL %copy, %fold_cst
153 %and:gpr(s64) = G_AND %shl, %bit
154 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero
159 %second_use:gpr(s64) = G_OR %shl, %bit
160 $x0 = COPY %second_use
161 RET_ReallyLR implicit $x0
165 name: fold_ashr_in_range
168 regBankSelected: true
170 ; CHECK-LABEL: name: fold_ashr_in_range
172 ; CHECK-NEXT: successors: %bb.0(0x40000000), %bb.1(0x40000000)
173 ; CHECK-NEXT: liveins: $x0
175 ; CHECK-NEXT: %copy:gpr64all = COPY $x0
176 ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32all = COPY %copy.sub_32
177 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32 = COPY [[COPY]]
178 ; CHECK-NEXT: TBNZW [[COPY1]], 4, %bb.1
179 ; CHECK-NEXT: B %bb.0
182 ; CHECK-NEXT: RET_ReallyLR
184 successors: %bb.0, %bb.1
186 %copy:gpr(s64) = COPY $x0
187 %bit:gpr(s64) = G_CONSTANT i64 8
188 %zero:gpr(s64) = G_CONSTANT i64 0
190 ; tb(n)z (ashr x, c), b == tbz(x, b + c) when b+c <= the size of the type.
191 ; In this case, we should get 1 + 3 = 4 as the bit number.
192 %fold_cst:gpr(s64) = G_CONSTANT i64 1
193 %fold_me:gpr(s64) = G_ASHR %copy, %fold_cst
195 %and:gpr(s64) = G_AND %fold_me, %bit
196 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero
204 name: fold_ashr_msb_1
207 regBankSelected: true
209 ; CHECK-LABEL: name: fold_ashr_msb_1
211 ; CHECK-NEXT: successors: %bb.0(0x40000000), %bb.1(0x40000000)
212 ; CHECK-NEXT: liveins: $x0
214 ; CHECK-NEXT: %copy:gpr32 = COPY $w0
215 ; CHECK-NEXT: TBNZW %copy, 31, %bb.1
216 ; CHECK-NEXT: B %bb.0
219 ; CHECK-NEXT: RET_ReallyLR
221 successors: %bb.0, %bb.1
223 %copy:gpr(s32) = COPY $w0
224 %bit:gpr(s32) = G_CONSTANT i32 8
225 %zero:gpr(s32) = G_CONSTANT i32 0
227 ; We should get a TBNZW with a 31 as the bit.
228 %fold_cst:gpr(s32) = G_CONSTANT i32 1234
229 %fold_me:gpr(s32) = G_ASHR %copy, %fold_cst
231 %and:gpr(s32) = G_AND %fold_me, %bit
232 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s32), %zero
240 name: fold_ashr_msb_2
243 regBankSelected: true
245 ; CHECK-LABEL: name: fold_ashr_msb_2
247 ; CHECK-NEXT: successors: %bb.0(0x40000000), %bb.1(0x40000000)
248 ; CHECK-NEXT: liveins: $x0
250 ; CHECK-NEXT: %copy:gpr64 = COPY $x0
251 ; CHECK-NEXT: TBNZX %copy, 63, %bb.1
252 ; CHECK-NEXT: B %bb.0
255 ; CHECK-NEXT: RET_ReallyLR
257 successors: %bb.0, %bb.1
259 %copy:gpr(s64) = COPY $x0
260 %bit:gpr(s64) = G_CONSTANT i64 8
261 %zero:gpr(s64) = G_CONSTANT i64 0
263 ; We should get a TBNZX with a 63 as the bit.
264 %fold_cst:gpr(s64) = G_CONSTANT i64 1234
265 %fold_me:gpr(s64) = G_ASHR %copy, %fold_cst
267 %and:gpr(s64) = G_AND %fold_me, %bit
268 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero
279 regBankSelected: true
281 ; CHECK-LABEL: name: fold_lshr
283 ; CHECK-NEXT: successors: %bb.0(0x40000000), %bb.1(0x40000000)
284 ; CHECK-NEXT: liveins: $x0
286 ; CHECK-NEXT: %copy:gpr32 = COPY $w0
287 ; CHECK-NEXT: TBNZW %copy, 4, %bb.1
288 ; CHECK-NEXT: B %bb.0
291 ; CHECK-NEXT: RET_ReallyLR
293 successors: %bb.0, %bb.1
295 %copy:gpr(s32) = COPY $w0
296 %bit:gpr(s32) = G_CONSTANT i32 8
297 %zero:gpr(s32) = G_CONSTANT i32 0
299 ; We should get 4 as the test bit.
300 %fold_cst:gpr(s32) = G_CONSTANT i32 1
301 %fold_me:gpr(s32) = G_LSHR %copy, %fold_cst
303 %and:gpr(s32) = G_AND %fold_me, %bit
304 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s32), %zero
315 regBankSelected: true
317 ; CHECK-LABEL: name: fold_lshr_2
319 ; CHECK-NEXT: successors: %bb.0(0x40000000), %bb.1(0x40000000)
320 ; CHECK-NEXT: liveins: $x0
322 ; CHECK-NEXT: %copy:gpr64 = COPY $x0
323 ; CHECK-NEXT: TBNZX %copy, 32, %bb.1
324 ; CHECK-NEXT: B %bb.0
327 ; CHECK-NEXT: RET_ReallyLR
329 successors: %bb.0, %bb.1
331 %copy:gpr(s64) = COPY $x0
332 %bit:gpr(s64) = G_CONSTANT i64 8
333 %zero:gpr(s64) = G_CONSTANT i64 0
335 ; We're testing a s64.
336 ; 3 + 29 = 32, which is less than 63, so we can fold.
337 %fold_cst:gpr(s64) = G_CONSTANT i64 29
338 %fold_me:gpr(s64) = G_LSHR %copy, %fold_cst
340 %and:gpr(s64) = G_AND %fold_me, %bit
341 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero
352 regBankSelected: true
354 ; CHECK-LABEL: name: dont_fold_lshr
356 ; CHECK-NEXT: successors: %bb.0(0x40000000), %bb.1(0x40000000)
357 ; CHECK-NEXT: liveins: $x0
359 ; CHECK-NEXT: %copy:gpr32 = COPY $w0
360 ; CHECK-NEXT: %fold_cst:gpr32 = MOVi32imm 29
361 ; CHECK-NEXT: %fold_me:gpr32 = LSRVWr %copy, %fold_cst
362 ; CHECK-NEXT: TBNZW %fold_me, 3, %bb.1
363 ; CHECK-NEXT: B %bb.0
366 ; CHECK-NEXT: RET_ReallyLR
368 successors: %bb.0, %bb.1
370 %copy:gpr(s32) = COPY $w0
371 %bit:gpr(s32) = G_CONSTANT i32 8
372 %zero:gpr(s32) = G_CONSTANT i32 0
374 ; We're testing a s32.
375 ; 3 + 29 = 32, which is greater than 31, so we don't fold.
376 %fold_cst:gpr(s32) = G_CONSTANT i32 29
377 %fold_me:gpr(s32) = G_LSHR %copy, %fold_cst
379 %and:gpr(s32) = G_AND %fold_me, %bit
380 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s32), %zero
391 regBankSelected: true
393 ; CHECK-LABEL: name: lshr_negative
395 ; CHECK-NEXT: successors: %bb.0(0x40000000), %bb.1(0x40000000)
396 ; CHECK-NEXT: liveins: $x0
398 ; CHECK-NEXT: %copy:gpr32 = COPY $w0
399 ; CHECK-NEXT: TBNZW %copy, 2, %bb.1
400 ; CHECK-NEXT: B %bb.0
403 ; CHECK-NEXT: RET_ReallyLR
405 successors: %bb.0, %bb.1
407 %copy:gpr(s32) = COPY $w0
408 %bit:gpr(s32) = G_CONSTANT i32 8
409 %zero:gpr(s32) = G_CONSTANT i32 0
411 ; Constant becomes very large and wraps around. Since it's larger than the
412 ; bit width, that means the LSHR is poison, so we can still fold.
413 %fold_cst:gpr(s32) = G_CONSTANT i32 -1
414 %fold_me:gpr(s32) = G_LSHR %copy, %fold_cst
416 %and:gpr(s32) = G_AND %fold_me, %bit
417 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s32), %zero