120
|
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
|
121
|
9 # CHECK: %3:sreg_128 = REG_SEQUENCE %0, {{[0-9]+}}, %1, {{[0-9]+}}, undef %2, {{[0-9]+}}
|
120
|
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
|
121
|
13 # CHECK: %4:sreg_64 = COPY %3.sub0_sub1
|
|
14 # CHECK: %5:sreg_64 = COPY undef %3.sub2_sub3
|
120
|
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: sreg_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
|
121
|
45 # CHECK: %0:sreg_128 = REG_SEQUENCE %sgpr0, {{[0-9]+}}, %sgpr0, {{[0-9]+}}
|
|
46 # CHECK: %1:sreg_128 = INSERT_SUBREG %0, %sgpr1, {{[0-9]+}}
|
|
47 # CHECK: %2:sreg_64 = INSERT_SUBREG %0.sub2_sub3, %sgpr42, {{[0-9]+}}
|
120
|
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
|
|
54
|
121
|
55 # CHECK: %3:sreg_32_xm0 = IMPLICIT_DEF
|
|
56 # CHECK: %4:sreg_128 = INSERT_SUBREG %0, undef %3, {{[0-9]+}}
|
120
|
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
|
|
61
|
121
|
62 # CHECK: %5:sreg_64 = EXTRACT_SUBREG %0, {{[0-9]+}}
|
|
63 # CHECK: %6:sreg_32_xm0 = EXTRACT_SUBREG %5, {{[0-9]+}}
|
|
64 # CHECK: %7:sreg_32_xm0 = EXTRACT_SUBREG %5, {{[0-9]+}}
|
120
|
65 # CHECK: S_NOP 0, implicit %5
|
|
66 # CHECK: S_NOP 0, implicit %6
|
|
67 # CHECK: S_NOP 0, implicit undef %7
|
|
68
|
121
|
69 # CHECK: %8:sreg_64 = IMPLICIT_DEF
|
|
70 # CHECK: %9:sreg_32_xm0 = EXTRACT_SUBREG undef %8, {{[0-9]+}}
|
120
|
71 # CHECK: S_NOP 0, implicit undef %9
|
|
72
|
121
|
73 # CHECK: %10:sreg_128 = EXTRACT_SUBREG undef %0, {{[0-9]+}}
|
120
|
74 # CHECK: S_NOP 0, implicit undef %10
|
|
75 name: test1
|
|
76 registers:
|
|
77 - { id: 0, class: sreg_128 }
|
|
78 - { id: 1, class: sreg_128 }
|
|
79 - { id: 2, class: sreg_64 }
|
|
80 - { id: 3, class: sreg_32_xm0 }
|
|
81 - { id: 4, class: sreg_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: sreg_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
|
|
99
|
|
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
|
|
106
|
|
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
|
|
113
|
|
114 %8 = IMPLICIT_DEF
|
|
115 %9 = EXTRACT_SUBREG %8, %subreg.sub1
|
|
116 S_NOP 0, implicit %9
|
|
117
|
|
118 %10 = EXTRACT_SUBREG undef %0, %subreg.sub2_sub3
|
|
119 S_NOP 0, implicit %10
|
|
120 ...
|
|
121 ---
|
|
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
|
121
|
128 # CHECK: %3:sreg_128 = REG_SEQUENCE undef %0, {{[0-9]+}}, %1, {{[0-9]+}}, %2, {{[0-9]+}}
|
120
|
129 # CHECK: S_NOP 0, implicit %3.sub1
|
|
130 # CHECK: S_NOP 0, implicit %3.sub3
|
|
131
|
|
132 # CHECK: S_NOP 0, implicit-def %4
|
|
133 # CHECK: S_NOP 0, implicit-def dead %5
|
121
|
134 # CHECK: %6:sreg_64 = REG_SEQUENCE %4, {{[0-9]+}}, undef %5, {{[0-9]+}}
|
120
|
135 # CHECK: S_NOP 0, implicit %6
|
|
136
|
|
137 # CHECK: S_NOP 0, implicit-def dead %7
|
|
138 # CHECK: S_NOP 0, implicit-def %8
|
121
|
139 # CHECK: %9:sreg_128 = INSERT_SUBREG undef %7, %8, {{[0-9]+}}
|
120
|
140 # CHECK: S_NOP 0, implicit %9.sub2
|
|
141
|
|
142 # CHECK: S_NOP 0, implicit-def %10
|
|
143 # CHECK: S_NOP 0, implicit-def dead %11
|
121
|
144 # CHECK: %12:sreg_128 = INSERT_SUBREG %10, undef %11, {{[0-9]+}}
|
120
|
145 # CHECK: S_NOP 0, implicit %12.sub3
|
|
146
|
|
147 # CHECK: S_NOP 0, implicit-def %13
|
|
148 # CHECK: S_NOP 0, implicit-def dead %14
|
121
|
149 # CHECK: %15:sreg_128 = REG_SEQUENCE %13, {{[0-9]+}}, undef %14, {{[0-9]+}}
|
|
150 # CHECK: %16:sreg_64 = EXTRACT_SUBREG %15, {{[0-9]+}}
|
120
|
151 # CHECK: S_NOP 0, implicit %16.sub1
|
|
152
|
|
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: sreg_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: sreg_128 }
|
|
163 - { id: 8, class: sreg_64 }
|
|
164 - { id: 9, class: sreg_128 }
|
|
165 - { id: 10, class: sreg_128 }
|
|
166 - { id: 11, class: sreg_64 }
|
|
167 - { id: 12, class: sreg_128 }
|
|
168 - { id: 13, class: sreg_64 }
|
|
169 - { id: 14, class: sreg_64 }
|
|
170 - { id: 15, class: sreg_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
|
|
180
|
|
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
|
|
185
|
|
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
|
|
190
|
|
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
|
|
195
|
|
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
|
|
201 ...
|
|
202 ---
|
|
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
|
121
|
208 # CHECK: %1:sreg_64 = COPY %vcc
|
120
|
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
|
|
219
|
|
220 %1 = COPY %vcc
|
|
221 S_NOP 0, implicit %1
|
|
222 ...
|
|
223 ---
|
|
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
|
121
|
228 # CHECK: %1:sreg_64 = IMPLICIT_DEF
|
120
|
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
|
|
239
|
|
240 %1 = IMPLICIT_DEF
|
|
241 S_NOP 0, implicit %1
|
|
242 ...
|
|
243 ---
|
|
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
|
121
|
248 # CHECK: %1:sreg_64 = REG_SEQUENCE undef %0, {{[0-9]+}}, %0, {{[0-9]+}}
|
120
|
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
|
|
260 ...
|
|
261 ---
|
|
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
|
121
|
268 # CHECK: %3:sreg_128 = REG_SEQUENCE %0, {{[0-9]+}}, undef %1, {{[0-9]+}}, undef %2, {{[0-9]+}}
|
120
|
269
|
|
270 # CHECK: bb.1:
|
121
|
271 # CHECK: %4:sreg_128 = PHI %3, %bb.0, %5, %bb.1
|
120
|
272
|
|
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: sreg_128 }
|
|
283 - { id: 4, class: sreg_128 }
|
|
284 - { id: 5, class: sreg_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
|
|
292
|
|
293 bb.1:
|
|
294 %4 = PHI %3, %bb.0, %5, %bb.1
|
|
295
|
|
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
|
|
298
|
|
299 S_CBRANCH_VCCNZ %bb.1, implicit undef %vcc
|
|
300 S_BRANCH %bb.2
|
|
301
|
|
302 bb.2:
|
|
303 S_NOP 0, implicit %4.sub0
|
|
304 S_NOP 0, implicit %4.sub3
|
|
305 ...
|
|
306 ---
|
|
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
|
121
|
318 # CHECK: %4:sreg_128 = REG_SEQUENCE %0, {{[0-9]+}}, %1, {{[0-9]+}}, undef %2, {{[0-9]+}}, %3, {{[0-9]+}}
|
120
|
319
|
|
320 # CHECK: bb.1:
|
121
|
321 # CHECK: %5:sreg_128 = PHI %4, %bb.0, %6, %bb.1
|
120
|
322
|
121
|
323 # CHECK: %6:sreg_128 = REG_SEQUENCE %5.sub1, {{[0-9]+}}, %5.sub3, {{[0-9]+}}, undef %5.sub2, {{[0-9]+}}, %5.sub0, {{[0-9]+}}
|
120
|
324
|
|
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: sreg_128 }
|
|
335 - { id: 5, class: sreg_128 }
|
|
336 - { id: 6, class: sreg_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
|
|
345
|
|
346 bb.1:
|
|
347 %5 = PHI %4, %bb.0, %6, %bb.1
|
|
348
|
|
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
|
|
351
|
|
352 S_CBRANCH_VCCNZ %bb.1, implicit undef %vcc
|
|
353 S_BRANCH %bb.2
|
|
354
|
|
355 bb.2:
|
|
356 S_NOP 0, implicit %6.sub3
|
|
357 ...
|
|
358 ---
|
|
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
|
121
|
364 # CHECK: %1:sreg_128 = REG_SEQUENCE %0, {{[0-9]+}}
|
120
|
365
|
|
366 # CHECK: bb.1:
|
121
|
367 # CHECK: %2:sreg_128 = PHI %1, %bb.0, %3, %bb.1
|
120
|
368
|
121
|
369 # CHECK: %3:sreg_128 = REG_SEQUENCE %2.sub3, {{[0-9]+}}, undef %2.sub1, {{[0-9]+}}, %2.sub0, {{[0-9]+}}, %2.sub2, {{[0-9]+}}
|
120
|
370
|
|
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: sreg_128 }
|
|
381 - { id: 2, class: sreg_128 }
|
|
382 - { id: 3, class: sreg_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
|
|
388
|
|
389 bb.1:
|
|
390 %2 = PHI %1, %bb.0, %3, %bb.1
|
|
391
|
|
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
|
|
394
|
|
395 S_CBRANCH_VCCNZ %bb.1, implicit undef %vcc
|
|
396 S_BRANCH %bb.2
|
|
397
|
|
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
|
|
403 ...
|