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