1 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2 # RUN: llc -mtriple aarch64-unknown-unknown -run-pass=instruction-select -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: successors: %bb.0(0x40000000), %bb.1(0x40000000)
15 ; CHECK: %copy:gpr64all = COPY $x0
16 ; CHECK: [[COPY:%[0-9]+]]:gpr32all = COPY %copy.sub_32
17 ; CHECK: [[COPY1:%[0-9]+]]:gpr32 = COPY [[COPY]]
18 ; CHECK: TBNZW [[COPY1]], 2, %bb.1
23 successors: %bb.0, %bb.1
25 %copy:gpr(s64) = COPY $x0
26 %bit:gpr(s64) = G_CONSTANT i64 8
27 %zero:gpr(s64) = G_CONSTANT i64 0
29 ; tbnz (shl x, 1), 3 == tbnz x, 2
30 %fold_cst:gpr(s64) = G_CONSTANT i64 1
31 %fold_me:gpr(s64) = G_SHL %copy, %fold_cst
33 %and:gpr(s64) = G_AND %fold_me, %bit
34 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero
35 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32)
36 G_BRCOND %cmp_trunc(s1), %bb.1
47 ; CHECK-LABEL: name: dont_fold_shl_1
49 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000)
50 ; CHECK: %copy:gpr64 = COPY $x0
51 ; CHECK: %fold_me:gpr64 = UBFMXri %copy, 59, 58
52 ; CHECK: [[COPY:%[0-9]+]]:gpr32all = COPY %fold_me.sub_32
53 ; CHECK: [[COPY1:%[0-9]+]]:gpr32 = COPY [[COPY]]
54 ; CHECK: TBNZW [[COPY1]], 3, %bb.1
59 successors: %bb.0, %bb.1
61 %copy:gpr(s64) = COPY $x0
62 %bit:gpr(s64) = G_CONSTANT i64 8
63 %zero:gpr(s64) = G_CONSTANT i64 0
65 ; 5 > 3, so we cannot do the transformation as above.
66 %fold_cst:gpr(s64) = G_CONSTANT i64 5
67 %fold_me:gpr(s64) = G_SHL %copy, %fold_cst
69 %and:gpr(s64) = G_AND %fold_me, %bit
70 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero
71 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32)
72 G_BRCOND %cmp_trunc(s1), %bb.1
83 ; CHECK-LABEL: name: dont_fold_shl_2
85 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000)
86 ; CHECK: %copy:gpr64 = COPY $x0
87 ; CHECK: %fold_cst:gpr64 = MOVi64imm -5
88 ; CHECK: %fold_me:gpr64 = LSLVXr %copy, %fold_cst
89 ; CHECK: [[COPY:%[0-9]+]]:gpr32all = COPY %fold_me.sub_32
90 ; CHECK: [[COPY1:%[0-9]+]]:gpr32 = COPY [[COPY]]
91 ; CHECK: TBNZW [[COPY1]], 3, %bb.1
96 successors: %bb.0, %bb.1
98 %copy:gpr(s64) = COPY $x0
99 %bit:gpr(s64) = G_CONSTANT i64 8
100 %zero:gpr(s64) = G_CONSTANT i64 0
102 ; Same case as above, except we wrap around.
103 %fold_cst:gpr(s64) = G_CONSTANT i64 -5
104 %fold_me:gpr(s64) = G_SHL %copy, %fold_cst
106 %and:gpr(s64) = G_AND %fold_me, %bit
107 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero
108 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32)
109 G_BRCOND %cmp_trunc(s1), %bb.1
116 name: dont_fold_shl_3
119 regBankSelected: true
121 ; CHECK-LABEL: name: dont_fold_shl_3
123 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000)
124 ; CHECK: %copy:gpr64 = COPY $x0
125 ; CHECK: %shl:gpr64 = UBFMXri %copy, 62, 61
126 ; CHECK: [[COPY:%[0-9]+]]:gpr32all = COPY %shl.sub_32
127 ; CHECK: [[COPY1:%[0-9]+]]:gpr32 = COPY [[COPY]]
128 ; CHECK: TBNZW [[COPY1]], 3, %bb.1
131 ; CHECK: %second_use:gpr64sp = ORRXri %shl, 8000
132 ; CHECK: $x0 = COPY %second_use
133 ; CHECK: RET_ReallyLR implicit $x0
135 successors: %bb.0, %bb.1
137 %copy:gpr(s64) = COPY $x0
138 %bit:gpr(s64) = G_CONSTANT i64 8
139 %zero:gpr(s64) = G_CONSTANT i64 0
140 %fold_cst:gpr(s64) = G_CONSTANT i64 2
142 ; Don't walk past the G_SHL when it's used more than once.
143 %shl:gpr(s64) = G_SHL %copy, %fold_cst
144 %and:gpr(s64) = G_AND %shl, %bit
145 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero
146 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32)
147 G_BRCOND %cmp_trunc(s1), %bb.1
151 %second_use:gpr(s64) = G_OR %shl, %bit
152 $x0 = COPY %second_use
153 RET_ReallyLR implicit $x0
157 name: fold_ashr_in_range
160 regBankSelected: true
162 ; CHECK-LABEL: name: fold_ashr_in_range
164 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000)
165 ; CHECK: %copy:gpr64all = COPY $x0
166 ; CHECK: [[COPY:%[0-9]+]]:gpr32all = COPY %copy.sub_32
167 ; CHECK: [[COPY1:%[0-9]+]]:gpr32 = COPY [[COPY]]
168 ; CHECK: TBNZW [[COPY1]], 4, %bb.1
171 ; CHECK: RET_ReallyLR
173 successors: %bb.0, %bb.1
175 %copy:gpr(s64) = COPY $x0
176 %bit:gpr(s64) = G_CONSTANT i64 8
177 %zero:gpr(s64) = G_CONSTANT i64 0
179 ; tb(n)z (ashr x, c), b == tbz(x, b + c) when b+c <= the size of the type.
180 ; In this case, we should get 1 + 3 = 4 as the bit number.
181 %fold_cst:gpr(s64) = G_CONSTANT i64 1
182 %fold_me:gpr(s64) = G_ASHR %copy, %fold_cst
184 %and:gpr(s64) = G_AND %fold_me, %bit
185 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero
186 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32)
187 G_BRCOND %cmp_trunc(s1), %bb.1
194 name: fold_ashr_msb_1
197 regBankSelected: true
199 ; CHECK-LABEL: name: fold_ashr_msb_1
201 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000)
202 ; CHECK: %copy:gpr32 = COPY $w0
203 ; CHECK: TBNZW %copy, 31, %bb.1
206 ; CHECK: RET_ReallyLR
208 successors: %bb.0, %bb.1
210 %copy:gpr(s32) = COPY $w0
211 %bit:gpr(s32) = G_CONSTANT i32 8
212 %zero:gpr(s32) = G_CONSTANT i32 0
214 ; We should get a TBNZW with a 31 as the bit.
215 %fold_cst:gpr(s32) = G_CONSTANT i32 1234
216 %fold_me:gpr(s32) = G_ASHR %copy, %fold_cst
218 %and:gpr(s32) = G_AND %fold_me, %bit
219 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s32), %zero
220 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32)
221 G_BRCOND %cmp_trunc(s1), %bb.1
228 name: fold_ashr_msb_2
231 regBankSelected: true
233 ; CHECK-LABEL: name: fold_ashr_msb_2
235 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000)
236 ; CHECK: %copy:gpr64 = COPY $x0
237 ; CHECK: TBNZX %copy, 63, %bb.1
240 ; CHECK: RET_ReallyLR
242 successors: %bb.0, %bb.1
244 %copy:gpr(s64) = COPY $x0
245 %bit:gpr(s64) = G_CONSTANT i64 8
246 %zero:gpr(s64) = G_CONSTANT i64 0
248 ; We should get a TBNZX with a 63 as the bit.
249 %fold_cst:gpr(s64) = G_CONSTANT i64 1234
250 %fold_me:gpr(s64) = G_ASHR %copy, %fold_cst
252 %and:gpr(s64) = G_AND %fold_me, %bit
253 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero
254 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32)
255 G_BRCOND %cmp_trunc(s1), %bb.1
265 regBankSelected: true
267 ; CHECK-LABEL: name: fold_lshr
269 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000)
270 ; CHECK: %copy:gpr32 = COPY $w0
271 ; CHECK: TBNZW %copy, 4, %bb.1
274 ; CHECK: RET_ReallyLR
276 successors: %bb.0, %bb.1
278 %copy:gpr(s32) = COPY $w0
279 %bit:gpr(s32) = G_CONSTANT i32 8
280 %zero:gpr(s32) = G_CONSTANT i32 0
282 ; We should get 4 as the test bit.
283 %fold_cst:gpr(s32) = G_CONSTANT i32 1
284 %fold_me:gpr(s32) = G_LSHR %copy, %fold_cst
286 %and:gpr(s32) = G_AND %fold_me, %bit
287 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s32), %zero
288 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32)
289 G_BRCOND %cmp_trunc(s1), %bb.1
299 regBankSelected: true
301 ; CHECK-LABEL: name: fold_lshr_2
303 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000)
304 ; CHECK: %copy:gpr64 = COPY $x0
305 ; CHECK: TBNZX %copy, 32, %bb.1
308 ; CHECK: RET_ReallyLR
310 successors: %bb.0, %bb.1
312 %copy:gpr(s64) = COPY $x0
313 %bit:gpr(s64) = G_CONSTANT i64 8
314 %zero:gpr(s64) = G_CONSTANT i64 0
316 ; We're testing a s64.
317 ; 3 + 29 = 32, which is less than 63, so we can fold.
318 %fold_cst:gpr(s64) = G_CONSTANT i64 29
319 %fold_me:gpr(s64) = G_LSHR %copy, %fold_cst
321 %and:gpr(s64) = G_AND %fold_me, %bit
322 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero
323 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32)
324 G_BRCOND %cmp_trunc(s1), %bb.1
334 regBankSelected: true
336 ; CHECK-LABEL: name: dont_fold_lshr
338 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000)
339 ; CHECK: %copy:gpr32 = COPY $w0
340 ; CHECK: %fold_cst:gpr32 = MOVi32imm 29
341 ; CHECK: %fold_me:gpr32 = LSRVWr %copy, %fold_cst
342 ; CHECK: TBNZW %fold_me, 3, %bb.1
345 ; CHECK: RET_ReallyLR
347 successors: %bb.0, %bb.1
349 %copy:gpr(s32) = COPY $w0
350 %bit:gpr(s32) = G_CONSTANT i32 8
351 %zero:gpr(s32) = G_CONSTANT i32 0
353 ; We're testing a s32.
354 ; 3 + 29 = 32, which is greater than 31, so we don't fold.
355 %fold_cst:gpr(s32) = G_CONSTANT i32 29
356 %fold_me:gpr(s32) = G_LSHR %copy, %fold_cst
358 %and:gpr(s32) = G_AND %fold_me, %bit
359 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s32), %zero
360 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32)
361 G_BRCOND %cmp_trunc(s1), %bb.1
371 regBankSelected: true
373 ; CHECK-LABEL: name: lshr_negative
375 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000)
376 ; CHECK: %copy:gpr32 = COPY $w0
377 ; CHECK: TBNZW %copy, 2, %bb.1
380 ; CHECK: RET_ReallyLR
382 successors: %bb.0, %bb.1
384 %copy:gpr(s32) = COPY $w0
385 %bit:gpr(s32) = G_CONSTANT i32 8
386 %zero:gpr(s32) = G_CONSTANT i32 0
388 ; Constant becomes very large and wraps around. Since it's larger than the
389 ; bit width, that means the LSHR is poison, so we can still fold.
390 %fold_cst:gpr(s32) = G_CONSTANT i32 -1
391 %fold_me:gpr(s32) = G_LSHR %copy, %fold_cst
393 %and:gpr(s32) = G_AND %fold_me, %bit
394 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s32), %zero
395 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32)
396 G_BRCOND %cmp_trunc(s1), %bb.1