[InstCombine] Signed saturation patterns
[llvm-core.git] / test / CodeGen / AMDGPU / detect-dead-lanes.mir
blob5908fc4b8831297ec5faba3124d766e52551e51d
1 # RUN: llc -march=amdgcn -run-pass detect-dead-lanes -o - %s | FileCheck %s
2 ...
3 ---
4 # Combined use/def transfer check, the basics.
5 # CHECK-LABEL: name: test0
6 # CHECK: S_NOP 0, implicit-def %0
7 # CHECK: S_NOP 0, implicit-def %1
8 # CHECK: S_NOP 0, implicit-def dead %2
9 # CHECK: %3:sgpr_128 = REG_SEQUENCE %0,  %subreg.sub0, %1,  %subreg.sub1, undef %2, %subreg.sub3
10 # CHECK: S_NOP 0, implicit %3.sub0
11 # CHECK: S_NOP 0, implicit %3.sub1
12 # CHECK: S_NOP 0, implicit undef %3.sub2
13 # CHECK: %4:sreg_64 = COPY %3.sub0_sub1
14 # CHECK: %5:sreg_64 = COPY undef %3.sub2_sub3
15 # CHECK: S_NOP 0, implicit %4.sub0
16 # CHECK: S_NOP 0, implicit %4.sub1
17 # CHECK: S_NOP 0, implicit undef %5.sub0
18 name: test0
19 registers:
20   - { id: 0, class: sreg_32_xm0 }
21   - { id: 1, class: sreg_32_xm0 }
22   - { id: 2, class: sreg_32_xm0 }
23   - { id: 3, class: sgpr_128 }
24   - { id: 4, class: sreg_64 }
25   - { id: 5, class: sreg_64 }
26 body: |
27   bb.0:
28     S_NOP 0, implicit-def %0
29     S_NOP 0, implicit-def %1
30     S_NOP 0, implicit-def %2
31     %3 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub3
32     S_NOP 0, implicit %3.sub0
33     S_NOP 0, implicit %3.sub1
34     S_NOP 0, implicit %3.sub2
35     %4 = COPY %3.sub0_sub1
36     %5 = COPY %3.sub2_sub3
37     S_NOP 0, implicit %4.sub0
38     S_NOP 0, implicit %4.sub1
39     S_NOP 0, implicit %5.sub0
40 ...
41 ---
42 # Check defined lanes transfer; Includes checking for some special cases like
43 # undef operands or IMPLICIT_DEF definitions.
44 # CHECK-LABEL: name: test1
45 # CHECK: %0:sgpr_128 = REG_SEQUENCE $sgpr0, %subreg.sub0, $sgpr0, %subreg.sub2
46 # CHECK: %1:sgpr_128 = INSERT_SUBREG %0, $sgpr1,  %subreg.sub3
47 # CHECK: %2:sreg_64 = INSERT_SUBREG %0.sub2_sub3, $sgpr42,  %subreg.sub0
48 # CHECK: S_NOP 0, implicit %1.sub0
49 # CHECK: S_NOP 0, implicit undef %1.sub1
50 # CHECK: S_NOP 0, implicit %1.sub2
51 # CHECK: S_NOP 0, implicit %1.sub3
52 # CHECK: S_NOP 0, implicit %2.sub0
53 # CHECK: S_NOP 0, implicit undef %2.sub1
55 # CHECK: %3:sreg_32_xm0 = IMPLICIT_DEF
56 # CHECK: %4:sgpr_128 = INSERT_SUBREG %0, undef %3, %subreg.sub0
57 # CHECK: S_NOP 0, implicit undef %4.sub0
58 # CHECK: S_NOP 0, implicit undef %4.sub1
59 # CHECK: S_NOP 0, implicit %4.sub2
60 # CHECK: S_NOP 0, implicit undef %4.sub3
62 # CHECK: %5:sreg_64 = EXTRACT_SUBREG %0, %subreg.sub0_sub1
63 # CHECK: %6:sreg_32_xm0 = EXTRACT_SUBREG %5, %subreg.sub0
64 # CHECK: %7:sreg_32_xm0 = EXTRACT_SUBREG %5, %subreg.sub1
65 # CHECK: S_NOP 0, implicit %5
66 # CHECK: S_NOP 0, implicit %6
67 # CHECK: S_NOP 0, implicit undef %7
69 # CHECK: %8:sreg_64 = IMPLICIT_DEF
70 # CHECK: %9:sreg_32_xm0 = EXTRACT_SUBREG undef %8, %subreg.sub1
71 # CHECK: S_NOP 0, implicit undef %9
73 # CHECK: %10:sgpr_128 = EXTRACT_SUBREG undef %0, %subreg.sub2_sub3
74 # CHECK: S_NOP 0, implicit undef %10
75 name: test1
76 registers:
77   - { id: 0, class: sgpr_128 }
78   - { id: 1, class: sgpr_128 }
79   - { id: 2, class: sreg_64 }
80   - { id: 3, class: sreg_32_xm0 }
81   - { id: 4, class: sgpr_128 }
82   - { id: 5, class: sreg_64 }
83   - { id: 6, class: sreg_32_xm0 }
84   - { id: 7, class: sreg_32_xm0 }
85   - { id: 8, class: sreg_64 }
86   - { id: 9, class: sreg_32_xm0 }
87   - { id: 10, class: sgpr_128 }
88 body: |
89   bb.0:
90     %0 = REG_SEQUENCE $sgpr0, %subreg.sub0, $sgpr0, %subreg.sub2
91     %1 = INSERT_SUBREG %0, $sgpr1, %subreg.sub3
92     %2 = INSERT_SUBREG %0.sub2_sub3, $sgpr42, %subreg.sub0
93     S_NOP 0, implicit %1.sub0
94     S_NOP 0, implicit %1.sub1
95     S_NOP 0, implicit %1.sub2
96     S_NOP 0, implicit %1.sub3
97     S_NOP 0, implicit %2.sub0
98     S_NOP 0, implicit %2.sub1
100     %3 = IMPLICIT_DEF
101     %4 = INSERT_SUBREG %0, %3, %subreg.sub0
102     S_NOP 0, implicit %4.sub0
103     S_NOP 0, implicit %4.sub1
104     S_NOP 0, implicit %4.sub2
105     S_NOP 0, implicit %4.sub3
107     %5 = EXTRACT_SUBREG %0, %subreg.sub0_sub1
108     %6 = EXTRACT_SUBREG %5, %subreg.sub0
109     %7 = EXTRACT_SUBREG %5, %subreg.sub1
110     S_NOP 0, implicit %5
111     S_NOP 0, implicit %6
112     S_NOP 0, implicit %7
114     %8 = IMPLICIT_DEF
115     %9 = EXTRACT_SUBREG %8, %subreg.sub1
116     S_NOP 0, implicit %9
118     %10 = EXTRACT_SUBREG undef %0, %subreg.sub2_sub3
119     S_NOP 0, implicit %10
122 # Check used lanes transfer; Includes checking for some special cases like
123 # undef operands.
124 # CHECK-LABEL: name: test2
125 # CHECK: S_NOP 0, implicit-def dead %0
126 # CHECK: S_NOP 0, implicit-def %1
127 # CHECK: S_NOP 0, implicit-def %2
128 # CHECK: %3:sgpr_128 = REG_SEQUENCE undef %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub2_sub3
129 # CHECK: S_NOP 0, implicit %3.sub1
130 # CHECK: S_NOP 0, implicit %3.sub3
132 # CHECK: S_NOP 0, implicit-def %4
133 # CHECK: S_NOP 0, implicit-def dead %5
134 # CHECK: %6:sreg_64 = REG_SEQUENCE %4, %subreg.sub0, undef %5, %subreg.sub1
135 # CHECK: S_NOP 0, implicit %6
137 # CHECK: S_NOP 0, implicit-def dead %7
138 # CHECK: S_NOP 0, implicit-def %8
139 # CHECK: %9:sgpr_128 = INSERT_SUBREG undef %7, %8, %subreg.sub2_sub3
140 # CHECK: S_NOP 0, implicit %9.sub2
142 # CHECK: S_NOP 0, implicit-def %10
143 # CHECK: S_NOP 0, implicit-def dead %11
144 # CHECK: %12:sgpr_128 = INSERT_SUBREG %10, undef %11, %subreg.sub0_sub1
145 # CHECK: S_NOP 0, implicit %12.sub3
147 # CHECK: S_NOP 0, implicit-def %13
148 # CHECK: S_NOP 0, implicit-def dead %14
149 # CHECK: %15:sgpr_128 = REG_SEQUENCE %13, %subreg.sub0_sub1, undef %14, %subreg.sub2_sub3
150 # CHECK: %16:sreg_64 = EXTRACT_SUBREG %15, %subreg.sub0_sub1
151 # CHECK: S_NOP 0, implicit %16.sub1
153 name: test2
154 registers:
155   - { id: 0, class: sreg_32_xm0 }
156   - { id: 1, class: sreg_32_xm0 }
157   - { id: 2, class: sreg_64 }
158   - { id: 3, class: sgpr_128 }
159   - { id: 4, class: sreg_32_xm0 }
160   - { id: 5, class: sreg_32_xm0 }
161   - { id: 6, class: sreg_64 }
162   - { id: 7, class: sgpr_128 }
163   - { id: 8, class: sreg_64 }
164   - { id: 9, class: sgpr_128 }
165   - { id: 10, class: sgpr_128 }
166   - { id: 11, class: sreg_64 }
167   - { id: 12, class: sgpr_128 }
168   - { id: 13, class: sreg_64 }
169   - { id: 14, class: sreg_64 }
170   - { id: 15, class: sgpr_128 }
171   - { id: 16, class: sreg_64 }
172 body: |
173   bb.0:
174     S_NOP 0, implicit-def %0
175     S_NOP 0, implicit-def %1
176     S_NOP 0, implicit-def %2
177     %3 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub2_sub3
178     S_NOP 0, implicit %3.sub1
179     S_NOP 0, implicit %3.sub3
181     S_NOP 0, implicit-def %4
182     S_NOP 0, implicit-def %5
183     %6 = REG_SEQUENCE %4, %subreg.sub0, undef %5, %subreg.sub1
184     S_NOP 0, implicit %6
186     S_NOP 0, implicit-def %7
187     S_NOP 0, implicit-def %8
188     %9 = INSERT_SUBREG %7, %8, %subreg.sub2_sub3
189     S_NOP 0, implicit %9.sub2
191     S_NOP 0, implicit-def %10
192     S_NOP 0, implicit-def %11
193     %12 = INSERT_SUBREG %10, %11, %subreg.sub0_sub1
194     S_NOP 0, implicit %12.sub3
196     S_NOP 0, implicit-def %13
197     S_NOP 0, implicit-def %14
198     %15 = REG_SEQUENCE %13, %subreg.sub0_sub1, %14, %subreg.sub2_sub3
199     %16 = EXTRACT_SUBREG %15, %subreg.sub0_sub1
200     S_NOP 0, implicit %16.sub1
203 # Check that copies to physregs use all lanes, copies from physregs define all
204 # lanes. So we should not get a dead/undef flag here.
205 # CHECK-LABEL: name: test3
206 # CHECK: S_NOP 0, implicit-def %0
207 # CHECK: $vcc = COPY %0
208 # CHECK: %1:sreg_64 = COPY $vcc
209 # CHECK: S_NOP 0, implicit %1
210 name: test3
211 tracksRegLiveness: true
212 registers:
213   - { id: 0, class: sreg_64 }
214   - { id: 1, class: sreg_64 }
215 body: |
216   bb.0:
217     S_NOP 0, implicit-def %0
218     $vcc = COPY %0
220     %1 = COPY $vcc
221     S_NOP 0, implicit %1
224 # Check that implicit-def/kill do not count as def/uses.
225 # CHECK-LABEL: name: test4
226 # CHECK: S_NOP 0, implicit-def dead %0
227 # CHECK: KILL undef %0
228 # CHECK: %1:sreg_64 = IMPLICIT_DEF
229 # CHECK: S_NOP 0, implicit undef %1
230 name: test4
231 tracksRegLiveness: true
232 registers:
233   - { id: 0, class: sreg_64 }
234   - { id: 1, class: sreg_64 }
235 body: |
236   bb.0:
237     S_NOP 0, implicit-def %0
238     KILL %0
240     %1 = IMPLICIT_DEF
241     S_NOP 0, implicit %1
244 # Check that unused inputs are marked as undef, even if the vreg itself is
245 # used.
246 # CHECK-LABEL: name: test5
247 # CHECK: S_NOP 0, implicit-def %0
248 # CHECK: %1:sreg_64 = REG_SEQUENCE undef %0, %subreg.sub0, %0, %subreg.sub1
249 # CHECK: S_NOP 0, implicit %1.sub1
250 name: test5
251 tracksRegLiveness: true
252 registers:
253   - { id: 0, class: sreg_32_xm0 }
254   - { id: 1, class: sreg_64 }
255 body: |
256   bb.0:
257     S_NOP 0, implicit-def %0
258     %1 = REG_SEQUENCE %0, %subreg.sub0, %0, %subreg.sub1
259     S_NOP 0, implicit %1.sub1
262 # Check "optimistic" dataflow fixpoint in phi-loops.
263 # CHECK-LABEL: name: loop0
264 # CHECK: bb.0:
265 # CHECK: S_NOP 0, implicit-def %0
266 # CHECK: S_NOP 0, implicit-def dead %1
267 # CHECK: S_NOP 0, implicit-def dead %2
268 # CHECK: %3:sgpr_128 = REG_SEQUENCE %0,  %subreg.sub0, undef %1,  %subreg.sub1, undef %2,  %subreg.sub2
270 # CHECK: bb.1:
271 # CHECK: %4:sgpr_128 = PHI %3, %bb.0, %5, %bb.1
273 # CHECK: bb.2:
274 # CHECK:   S_NOP 0, implicit %4.sub0
275 # CHECK:   S_NOP 0, implicit undef %4.sub3
276 name: loop0
277 tracksRegLiveness: true
278 registers:
279   - { id: 0, class: sreg_32_xm0 }
280   - { id: 1, class: sreg_32_xm0 }
281   - { id: 2, class: sreg_32_xm0 }
282   - { id: 3, class: sgpr_128 }
283   - { id: 4, class: sgpr_128 }
284   - { id: 5, class: sgpr_128 }
285 body: |
286   bb.0:
287     S_NOP 0, implicit-def %0
288     S_NOP 0, implicit-def %1
289     S_NOP 0, implicit-def %2
290     %3 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub2
291     S_BRANCH %bb.1
293   bb.1:
294     %4 = PHI %3, %bb.0, %5, %bb.1
296     ; let's swiffle some lanes around for fun...
297     %5 = REG_SEQUENCE %4.sub0, %subreg.sub0, %4.sub2, %subreg.sub1, %4.sub1, %subreg.sub2, %4.sub3, %subreg.sub3
299     S_CBRANCH_VCCNZ %bb.1, implicit undef $vcc
300     S_BRANCH %bb.2
302   bb.2:
303     S_NOP 0, implicit %4.sub0
304     S_NOP 0, implicit %4.sub3
307 # Check a loop that needs to be traversed multiple times to reach the fixpoint
308 # for the used lanes. The example reads sub3 lane at the end, however with each
309 # loop iteration we should get 1 more lane marked as we cycles the sublanes
310 # along. Sublanes sub0, sub1 and sub3 are rotate in the loop so only sub2
311 # should be dead.
312 # CHECK-LABEL: name: loop1
313 # CHECK: bb.0:
314 # CHECK: S_NOP 0, implicit-def %0
315 # CHECK: S_NOP 0, implicit-def %1
316 # CHECK: S_NOP 0, implicit-def dead %2
317 # CHECK: S_NOP 0, implicit-def %3
318 # CHECK: %4:sgpr_128 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, undef %2, %subreg.sub2, %3, %subreg.sub3
320 # CHECK: bb.1:
321 # CHECK: %5:sgpr_128 = PHI %4, %bb.0, %6, %bb.1
323 # CHECK: %6:sgpr_128 = REG_SEQUENCE %5.sub1, %subreg.sub0, %5.sub3, %subreg.sub1, undef %5.sub2, %subreg.sub2, %5.sub0, %subreg.sub3
325 # CHECK: bb.2:
326 # CHECK:   S_NOP 0, implicit %6.sub3
327 name: loop1
328 tracksRegLiveness: true
329 registers:
330   - { id: 0, class: sreg_32_xm0 }
331   - { id: 1, class: sreg_32_xm0 }
332   - { id: 2, class: sreg_32_xm0 }
333   - { id: 3, class: sreg_32_xm0 }
334   - { id: 4, class: sgpr_128 }
335   - { id: 5, class: sgpr_128 }
336   - { id: 6, class: sgpr_128 }
337 body: |
338   bb.0:
339     S_NOP 0, implicit-def %0
340     S_NOP 0, implicit-def %1
341     S_NOP 0, implicit-def dead %2
342     S_NOP 0, implicit-def %3
343     %4 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub2, %3, %subreg.sub3
344     S_BRANCH %bb.1
346   bb.1:
347     %5 = PHI %4, %bb.0, %6, %bb.1
349     ; rotate lanes, but skip sub2 lane...
350     %6 = REG_SEQUENCE %5.sub1, %subreg.sub0, %5.sub3, %subreg.sub1, %5.sub2, %subreg.sub2, %5.sub0, %subreg.sub3
352     S_CBRANCH_VCCNZ %bb.1, implicit undef $vcc
353     S_BRANCH %bb.2
355   bb.2:
356     S_NOP 0, implicit %6.sub3
359 # Similar to loop1 test, but check for fixpoint of defined lanes.
360 # Lanes are rotate between sub0, sub2, sub3 so only sub1 should be dead/undef.
361 # CHECK-LABEL: name: loop2
362 # CHECK: bb.0:
363 # CHECK: S_NOP 0, implicit-def %0
364 # CHECK: %1:sgpr_128 = REG_SEQUENCE %0, %subreg.sub0
366 # CHECK: bb.1:
367 # CHECK: %2:sgpr_128 = PHI %1, %bb.0, %3, %bb.1
369 # CHECK: %3:sgpr_128 = REG_SEQUENCE %2.sub3, %subreg.sub0, undef %2.sub1, %subreg.sub1, %2.sub0, %subreg.sub2, %2.sub2, %subreg.sub3
371 # CHECK: bb.2:
372 # CHECK:   S_NOP 0, implicit %2.sub0
373 # CHECK:   S_NOP 0, implicit undef %2.sub1
374 # CHECK:   S_NOP 0, implicit %2.sub2
375 # CHECK:   S_NOP 0, implicit %2.sub3
376 name: loop2
377 tracksRegLiveness: true
378 registers:
379   - { id: 0, class: sreg_32_xm0 }
380   - { id: 1, class: sgpr_128 }
381   - { id: 2, class: sgpr_128 }
382   - { id: 3, class: sgpr_128 }
383 body: |
384   bb.0:
385     S_NOP 0, implicit-def %0
386     %1 = REG_SEQUENCE %0, %subreg.sub0
387     S_BRANCH %bb.1
389   bb.1:
390     %2 = PHI %1, %bb.0, %3, %bb.1
392     ; rotate subreg lanes, skipping sub1
393     %3 = REG_SEQUENCE %2.sub3, %subreg.sub0, %2.sub1, %subreg.sub1, %2.sub0, %subreg.sub2, %2.sub2, %subreg.sub3
395     S_CBRANCH_VCCNZ %bb.1, implicit undef $vcc
396     S_BRANCH %bb.2
398   bb.2:
399     S_NOP 0, implicit %2.sub0
400     S_NOP 0, implicit undef %2.sub1
401     S_NOP 0, implicit %2.sub2
402     S_NOP 0, implicit %2.sub3