[NFC][RemoveDIs] Prefer iterators over inst-pointers in InstCombine
[llvm-project.git] / llvm / test / CodeGen / AArch64 / GlobalISel / opt-fold-shift-tbz-tbnz.mir
blobb32508ed12c60ef580fdca0ffca0e99b46bcb43c
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.
5 ...
6 ---
7 name:            fold_shl
8 alignment:       4
9 legalized:       true
10 regBankSelected: true
11 body:             |
12   ; CHECK-LABEL: name: fold_shl
13   ; CHECK: bb.0:
14   ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
15   ; CHECK-NEXT:   liveins: $x0
16   ; CHECK-NEXT: {{  $}}
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
21   ; CHECK-NEXT:   B %bb.0
22   ; CHECK-NEXT: {{  $}}
23   ; CHECK-NEXT: bb.1:
24   ; CHECK-NEXT:   RET_ReallyLR
25   bb.0:
26     successors: %bb.0, %bb.1
27     liveins: $x0
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
38     G_BRCOND %cmp, %bb.1
39     G_BR %bb.0
40   bb.1:
41     RET_ReallyLR
42 ...
43 ---
44 name:            dont_fold_shl_1
45 alignment:       4
46 legalized:       true
47 regBankSelected: true
48 body:             |
49   ; CHECK-LABEL: name: dont_fold_shl_1
50   ; CHECK: bb.0:
51   ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
52   ; CHECK-NEXT:   liveins: $x0
53   ; CHECK-NEXT: {{  $}}
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
59   ; CHECK-NEXT:   B %bb.0
60   ; CHECK-NEXT: {{  $}}
61   ; CHECK-NEXT: bb.1:
62   ; CHECK-NEXT:   RET_ReallyLR
63   bb.0:
64     successors: %bb.0, %bb.1
65     liveins: $x0
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
76     G_BRCOND %cmp, %bb.1
77     G_BR %bb.0
78   bb.1:
79     RET_ReallyLR
80 ...
81 ---
82 name:            dont_fold_shl_2
83 alignment:       4
84 legalized:       true
85 regBankSelected: true
86 body:             |
87   ; CHECK-LABEL: name: dont_fold_shl_2
88   ; CHECK: bb.0:
89   ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
90   ; CHECK-NEXT:   liveins: $x0
91   ; CHECK-NEXT: {{  $}}
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
98   ; CHECK-NEXT:   B %bb.0
99   ; CHECK-NEXT: {{  $}}
100   ; CHECK-NEXT: bb.1:
101   ; CHECK-NEXT:   RET_ReallyLR
102   bb.0:
103     successors: %bb.0, %bb.1
104     liveins: $x0
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
115     G_BRCOND %cmp, %bb.1
116     G_BR %bb.0
117   bb.1:
118     RET_ReallyLR
122 name:            dont_fold_shl_3
123 alignment:       4
124 legalized:       true
125 regBankSelected: true
126 body:             |
127   ; CHECK-LABEL: name: dont_fold_shl_3
128   ; CHECK: bb.0:
129   ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
130   ; CHECK-NEXT:   liveins: $x0
131   ; CHECK-NEXT: {{  $}}
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
138   ; CHECK-NEXT: {{  $}}
139   ; CHECK-NEXT: bb.1:
140   ; CHECK-NEXT:   %second_use:gpr64sp = ORRXri %shl, 8000
141   ; CHECK-NEXT:   $x0 = COPY %second_use
142   ; CHECK-NEXT:   RET_ReallyLR implicit $x0
143   bb.0:
144     successors: %bb.0, %bb.1
145     liveins: $x0
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
155     G_BRCOND %cmp, %bb.1
156     G_BR %bb.0
158   bb.1:
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
166 alignment:       4
167 legalized:       true
168 regBankSelected: true
169 body:             |
170   ; CHECK-LABEL: name: fold_ashr_in_range
171   ; CHECK: bb.0:
172   ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
173   ; CHECK-NEXT:   liveins: $x0
174   ; CHECK-NEXT: {{  $}}
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
180   ; CHECK-NEXT: {{  $}}
181   ; CHECK-NEXT: bb.1:
182   ; CHECK-NEXT:   RET_ReallyLR
183   bb.0:
184     successors: %bb.0, %bb.1
185     liveins: $x0
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
197     G_BRCOND %cmp, %bb.1
198     G_BR %bb.0
199   bb.1:
200     RET_ReallyLR
204 name:            fold_ashr_msb_1
205 alignment:       4
206 legalized:       true
207 regBankSelected: true
208 body:             |
209   ; CHECK-LABEL: name: fold_ashr_msb_1
210   ; CHECK: bb.0:
211   ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
212   ; CHECK-NEXT:   liveins: $x0
213   ; CHECK-NEXT: {{  $}}
214   ; CHECK-NEXT:   %copy:gpr32 = COPY $w0
215   ; CHECK-NEXT:   TBNZW %copy, 31, %bb.1
216   ; CHECK-NEXT:   B %bb.0
217   ; CHECK-NEXT: {{  $}}
218   ; CHECK-NEXT: bb.1:
219   ; CHECK-NEXT:   RET_ReallyLR
220   bb.0:
221     successors: %bb.0, %bb.1
222     liveins: $x0
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
233     G_BRCOND %cmp, %bb.1
234     G_BR %bb.0
235   bb.1:
236     RET_ReallyLR
240 name:            fold_ashr_msb_2
241 alignment:       4
242 legalized:       true
243 regBankSelected: true
244 body:             |
245   ; CHECK-LABEL: name: fold_ashr_msb_2
246   ; CHECK: bb.0:
247   ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
248   ; CHECK-NEXT:   liveins: $x0
249   ; CHECK-NEXT: {{  $}}
250   ; CHECK-NEXT:   %copy:gpr64 = COPY $x0
251   ; CHECK-NEXT:   TBNZX %copy, 63, %bb.1
252   ; CHECK-NEXT:   B %bb.0
253   ; CHECK-NEXT: {{  $}}
254   ; CHECK-NEXT: bb.1:
255   ; CHECK-NEXT:   RET_ReallyLR
256   bb.0:
257     successors: %bb.0, %bb.1
258     liveins: $x0
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
269     G_BRCOND %cmp, %bb.1
270     G_BR %bb.0
271   bb.1:
272     RET_ReallyLR
276 name:            fold_lshr
277 alignment:       4
278 legalized:       true
279 regBankSelected: true
280 body:             |
281   ; CHECK-LABEL: name: fold_lshr
282   ; CHECK: bb.0:
283   ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
284   ; CHECK-NEXT:   liveins: $x0
285   ; CHECK-NEXT: {{  $}}
286   ; CHECK-NEXT:   %copy:gpr32 = COPY $w0
287   ; CHECK-NEXT:   TBNZW %copy, 4, %bb.1
288   ; CHECK-NEXT:   B %bb.0
289   ; CHECK-NEXT: {{  $}}
290   ; CHECK-NEXT: bb.1:
291   ; CHECK-NEXT:   RET_ReallyLR
292   bb.0:
293     successors: %bb.0, %bb.1
294     liveins: $x0
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
305     G_BRCOND %cmp, %bb.1
306     G_BR %bb.0
307   bb.1:
308     RET_ReallyLR
312 name:            fold_lshr_2
313 alignment:       4
314 legalized:       true
315 regBankSelected: true
316 body:             |
317   ; CHECK-LABEL: name: fold_lshr_2
318   ; CHECK: bb.0:
319   ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
320   ; CHECK-NEXT:   liveins: $x0
321   ; CHECK-NEXT: {{  $}}
322   ; CHECK-NEXT:   %copy:gpr64 = COPY $x0
323   ; CHECK-NEXT:   TBNZX %copy, 32, %bb.1
324   ; CHECK-NEXT:   B %bb.0
325   ; CHECK-NEXT: {{  $}}
326   ; CHECK-NEXT: bb.1:
327   ; CHECK-NEXT:   RET_ReallyLR
328   bb.0:
329     successors: %bb.0, %bb.1
330     liveins: $x0
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
342     G_BRCOND %cmp, %bb.1
343     G_BR %bb.0
344   bb.1:
345     RET_ReallyLR
349 name:            dont_fold_lshr
350 alignment:       4
351 legalized:       true
352 regBankSelected: true
353 body:             |
354   ; CHECK-LABEL: name: dont_fold_lshr
355   ; CHECK: bb.0:
356   ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
357   ; CHECK-NEXT:   liveins: $x0
358   ; CHECK-NEXT: {{  $}}
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
364   ; CHECK-NEXT: {{  $}}
365   ; CHECK-NEXT: bb.1:
366   ; CHECK-NEXT:   RET_ReallyLR
367   bb.0:
368     successors: %bb.0, %bb.1
369     liveins: $x0
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
381     G_BRCOND %cmp, %bb.1
382     G_BR %bb.0
383   bb.1:
384     RET_ReallyLR
388 name:            lshr_negative
389 alignment:       4
390 legalized:       true
391 regBankSelected: true
392 body:             |
393   ; CHECK-LABEL: name: lshr_negative
394   ; CHECK: bb.0:
395   ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
396   ; CHECK-NEXT:   liveins: $x0
397   ; CHECK-NEXT: {{  $}}
398   ; CHECK-NEXT:   %copy:gpr32 = COPY $w0
399   ; CHECK-NEXT:   TBNZW %copy, 2, %bb.1
400   ; CHECK-NEXT:   B %bb.0
401   ; CHECK-NEXT: {{  $}}
402   ; CHECK-NEXT: bb.1:
403   ; CHECK-NEXT:   RET_ReallyLR
404   bb.0:
405     successors: %bb.0, %bb.1
406     liveins: $x0
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
418     G_BRCOND %cmp, %bb.1
419     G_BR %bb.0
420   bb.1:
421     RET_ReallyLR