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