• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3#
4# Check folding a G_SHL into a G_BRCOND which has been matched as a TB(N)Z.
5...
6---
7name:            fold_shl
8alignment:       4
9legalized:       true
10regBankSelected: true
11body:             |
12  ; CHECK-LABEL: name: fold_shl
13  ; CHECK: bb.0:
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
19  ; CHECK:   B %bb.0
20  ; CHECK: bb.1:
21  ; CHECK:   RET_ReallyLR
22  bb.0:
23    successors: %bb.0, %bb.1
24    liveins: $x0
25    %copy:gpr(s64) = COPY $x0
26    %bit:gpr(s64) = G_CONSTANT i64 8
27    %zero:gpr(s64) = G_CONSTANT i64 0
28
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
32
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
37    G_BR %bb.0
38  bb.1:
39    RET_ReallyLR
40...
41---
42name:            dont_fold_shl_1
43alignment:       4
44legalized:       true
45regBankSelected: true
46body:             |
47  ; CHECK-LABEL: name: dont_fold_shl_1
48  ; CHECK: bb.0:
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
55  ; CHECK:   B %bb.0
56  ; CHECK: bb.1:
57  ; CHECK:   RET_ReallyLR
58  bb.0:
59    successors: %bb.0, %bb.1
60    liveins: $x0
61    %copy:gpr(s64) = COPY $x0
62    %bit:gpr(s64) = G_CONSTANT i64 8
63    %zero:gpr(s64) = G_CONSTANT i64 0
64
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
68
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
73    G_BR %bb.0
74  bb.1:
75    RET_ReallyLR
76...
77---
78name:            dont_fold_shl_2
79alignment:       4
80legalized:       true
81regBankSelected: true
82body:             |
83  ; CHECK-LABEL: name: dont_fold_shl_2
84  ; CHECK: bb.0:
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
92  ; CHECK:   B %bb.0
93  ; CHECK: bb.1:
94  ; CHECK:   RET_ReallyLR
95  bb.0:
96    successors: %bb.0, %bb.1
97    liveins: $x0
98    %copy:gpr(s64) = COPY $x0
99    %bit:gpr(s64) = G_CONSTANT i64 8
100    %zero:gpr(s64) = G_CONSTANT i64 0
101
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
105
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
110    G_BR %bb.0
111  bb.1:
112    RET_ReallyLR
113
114...
115---
116name:            dont_fold_shl_3
117alignment:       4
118legalized:       true
119regBankSelected: true
120body:             |
121  ; CHECK-LABEL: name: dont_fold_shl_3
122  ; CHECK: bb.0:
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
129  ; CHECK:   B %bb.0
130  ; CHECK: bb.1:
131  ; CHECK:   %second_use:gpr64sp = ORRXri %shl, 8000
132  ; CHECK:   $x0 = COPY %second_use
133  ; CHECK:   RET_ReallyLR implicit $x0
134  bb.0:
135    successors: %bb.0, %bb.1
136    liveins: $x0
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
141
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
148    G_BR %bb.0
149
150  bb.1:
151    %second_use:gpr(s64) = G_OR %shl, %bit
152    $x0 = COPY %second_use
153    RET_ReallyLR implicit $x0
154
155...
156---
157name:            fold_ashr_in_range
158alignment:       4
159legalized:       true
160regBankSelected: true
161body:             |
162  ; CHECK-LABEL: name: fold_ashr_in_range
163  ; CHECK: bb.0:
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
169  ; CHECK:   B %bb.0
170  ; CHECK: bb.1:
171  ; CHECK:   RET_ReallyLR
172  bb.0:
173    successors: %bb.0, %bb.1
174    liveins: $x0
175    %copy:gpr(s64) = COPY $x0
176    %bit:gpr(s64) = G_CONSTANT i64 8
177    %zero:gpr(s64) = G_CONSTANT i64 0
178
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
183
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
188    G_BR %bb.0
189  bb.1:
190    RET_ReallyLR
191
192...
193---
194name:            fold_ashr_msb_1
195alignment:       4
196legalized:       true
197regBankSelected: true
198body:             |
199  ; CHECK-LABEL: name: fold_ashr_msb_1
200  ; CHECK: bb.0:
201  ; CHECK:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
202  ; CHECK:   %copy:gpr32 = COPY $w0
203  ; CHECK:   TBNZW %copy, 31, %bb.1
204  ; CHECK:   B %bb.0
205  ; CHECK: bb.1:
206  ; CHECK:   RET_ReallyLR
207  bb.0:
208    successors: %bb.0, %bb.1
209    liveins: $x0
210    %copy:gpr(s32) = COPY $w0
211    %bit:gpr(s32) = G_CONSTANT i32 8
212    %zero:gpr(s32) = G_CONSTANT i32 0
213
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
217
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
222    G_BR %bb.0
223  bb.1:
224    RET_ReallyLR
225
226...
227---
228name:            fold_ashr_msb_2
229alignment:       4
230legalized:       true
231regBankSelected: true
232body:             |
233  ; CHECK-LABEL: name: fold_ashr_msb_2
234  ; CHECK: bb.0:
235  ; CHECK:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
236  ; CHECK:   %copy:gpr64 = COPY $x0
237  ; CHECK:   TBNZX %copy, 63, %bb.1
238  ; CHECK:   B %bb.0
239  ; CHECK: bb.1:
240  ; CHECK:   RET_ReallyLR
241  bb.0:
242    successors: %bb.0, %bb.1
243    liveins: $x0
244    %copy:gpr(s64) = COPY $x0
245    %bit:gpr(s64) = G_CONSTANT i64 8
246    %zero:gpr(s64) = G_CONSTANT i64 0
247
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
251
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
256    G_BR %bb.0
257  bb.1:
258    RET_ReallyLR
259
260...
261---
262name:            fold_lshr
263alignment:       4
264legalized:       true
265regBankSelected: true
266body:             |
267  ; CHECK-LABEL: name: fold_lshr
268  ; CHECK: bb.0:
269  ; CHECK:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
270  ; CHECK:   %copy:gpr32 = COPY $w0
271  ; CHECK:   TBNZW %copy, 4, %bb.1
272  ; CHECK:   B %bb.0
273  ; CHECK: bb.1:
274  ; CHECK:   RET_ReallyLR
275  bb.0:
276    successors: %bb.0, %bb.1
277    liveins: $x0
278    %copy:gpr(s32) = COPY $w0
279    %bit:gpr(s32) = G_CONSTANT i32 8
280    %zero:gpr(s32) = G_CONSTANT i32 0
281
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
285
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
290    G_BR %bb.0
291  bb.1:
292    RET_ReallyLR
293
294...
295---
296name:            fold_lshr_2
297alignment:       4
298legalized:       true
299regBankSelected: true
300body:             |
301  ; CHECK-LABEL: name: fold_lshr_2
302  ; CHECK: bb.0:
303  ; CHECK:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
304  ; CHECK:   %copy:gpr64 = COPY $x0
305  ; CHECK:   TBNZX %copy, 32, %bb.1
306  ; CHECK:   B %bb.0
307  ; CHECK: bb.1:
308  ; CHECK:   RET_ReallyLR
309  bb.0:
310    successors: %bb.0, %bb.1
311    liveins: $x0
312    %copy:gpr(s64) = COPY $x0
313    %bit:gpr(s64) = G_CONSTANT i64 8
314    %zero:gpr(s64) = G_CONSTANT i64 0
315
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
320
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
325    G_BR %bb.0
326  bb.1:
327    RET_ReallyLR
328
329...
330---
331name:            dont_fold_lshr
332alignment:       4
333legalized:       true
334regBankSelected: true
335body:             |
336  ; CHECK-LABEL: name: dont_fold_lshr
337  ; CHECK: bb.0:
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
343  ; CHECK:   B %bb.0
344  ; CHECK: bb.1:
345  ; CHECK:   RET_ReallyLR
346  bb.0:
347    successors: %bb.0, %bb.1
348    liveins: $x0
349    %copy:gpr(s32) = COPY $w0
350    %bit:gpr(s32) = G_CONSTANT i32 8
351    %zero:gpr(s32) = G_CONSTANT i32 0
352
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
357
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
362    G_BR %bb.0
363  bb.1:
364    RET_ReallyLR
365
366...
367---
368name:            lshr_negative
369alignment:       4
370legalized:       true
371regBankSelected: true
372body:             |
373  ; CHECK-LABEL: name: lshr_negative
374  ; CHECK: bb.0:
375  ; CHECK:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
376  ; CHECK:   %copy:gpr32 = COPY $w0
377  ; CHECK:   TBNZW %copy, 2, %bb.1
378  ; CHECK:   B %bb.0
379  ; CHECK: bb.1:
380  ; CHECK:   RET_ReallyLR
381  bb.0:
382    successors: %bb.0, %bb.1
383    liveins: $x0
384    %copy:gpr(s32) = COPY $w0
385    %bit:gpr(s32) = G_CONSTANT i32 8
386    %zero:gpr(s32) = G_CONSTANT i32 0
387
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
392
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
397    G_BR %bb.0
398  bb.1:
399    RET_ReallyLR
400