2 * Copyright © 2017 Gert Wollny
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 #include <tgsi/tgsi_ureg.h>
25 #include <tgsi/tgsi_info.h>
26 #include <mesa/program/prog_instruction.h>
28 #include <gtest/gtest.h>
33 #include "st_tests_common.h"
42 TEST_F(LifetimeEvaluatorExactTest
, SimpleMoveAdd
)
44 const vector
<FakeCodeline
> code
= {
45 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
46 { TGSI_OPCODE_UADD
, {out0
}, {1,in0
}, {}},
49 run(code
, temp_lt_expect({{-1,-1}, {0,1}}));
52 TEST_F(LifetimeEvaluatorExactTest
, SimpleMoveAddMove
)
54 const vector
<FakeCodeline
> code
= {
55 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
56 { TGSI_OPCODE_UADD
, {2}, {1,in0
}, {}},
57 { TGSI_OPCODE_MOV
, {out0
}, {2}, {}},
60 run(code
, temp_lt_expect({{-1, -1}, {0,1}, {1,2}}));
63 /* Test whether the texoffst are actually visited by the
64 * merge algorithm. Note that it is of no importance
65 * what instruction is actually used, the MockShader class
66 * does not consider the details of the operation, only
67 * the number of arguments is of importance.
69 TEST_F(LifetimeEvaluatorExactTest
, SimpleOpWithTexoffset
)
71 const vector
<FakeCodeline
> code
= {
72 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
73 { TGSI_OPCODE_MOV
, {2}, {in1
}, {}},
74 { TGSI_OPCODE_TEX
, {out0
}, {in0
}, {1,2}},
77 run(code
, temp_lt_expect({{-1, -1}, {0,2}, {1,2}}));
80 /* Simple register access involving a loop
81 * 1: must life up to then end of the loop
82 * 2: only needs to life from write to read
83 * 3: only needs to life from write to read outside the loop
85 TEST_F(LifetimeEvaluatorExactTest
, SimpleMoveInLoop
)
87 const vector
<FakeCodeline
> code
= {
88 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
89 { TGSI_OPCODE_BGNLOOP
},
90 { TGSI_OPCODE_UADD
, {2}, {1,in0
}, {}},
91 { TGSI_OPCODE_UADD
, {3}, {1,2}, {}},
92 { TGSI_OPCODE_UADD
, {3}, {3,in1
}, {}},
93 { TGSI_OPCODE_ENDLOOP
},
94 { TGSI_OPCODE_MOV
, {out0
}, {3}, {}},
97 run (code
, temp_lt_expect({{-1,-1}, {0,5}, {2,3}, {3,6}}));
100 /* In loop if/else value written only in one path, and read later
101 * - value must survive the whole loop.
103 TEST_F(LifetimeEvaluatorExactTest
, MoveInIfInLoop
)
105 const vector
<FakeCodeline
> code
= {
106 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
107 { TGSI_OPCODE_BGNLOOP
},
108 { TGSI_OPCODE_IF
, {}, {in1
}, {}},
109 { TGSI_OPCODE_UADD
, {2}, {1,in0
}, {}},
110 { TGSI_OPCODE_ENDIF
},
111 { TGSI_OPCODE_UADD
, {3}, {1,2}, {}},
112 { TGSI_OPCODE_UADD
, {3}, {3,in1
}, {}},
113 { TGSI_OPCODE_ENDLOOP
},
114 { TGSI_OPCODE_MOV
, {out0
}, {3}, {}},
117 run (code
, temp_lt_expect({{-1,-1}, {0,7}, {1,7}, {5,8}}));
120 /* A non-dominant write within an IF can be ignored (if it is read
123 TEST_F(LifetimeEvaluatorExactTest
, NonDominantWriteinIfInLoop
)
125 const vector
<FakeCodeline
> code
= {
126 { TGSI_OPCODE_BGNLOOP
},
127 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
128 { TGSI_OPCODE_IF
, {}, {in1
}, {}},
129 { TGSI_OPCODE_MOV
, {1}, {in1
}, {}},
130 { TGSI_OPCODE_ENDIF
},
131 { TGSI_OPCODE_UADD
, {2}, {1,in1
}, {}},
132 { TGSI_OPCODE_IF
, {}, {2}, {}},
134 { TGSI_OPCODE_ENDIF
},
135 { TGSI_OPCODE_ENDLOOP
},
136 { TGSI_OPCODE_MOV
, {out0
}, {2}, {}},
139 run (code
, temp_lt_expect({{-1,-1}, {1,5}, {5,10}}));
142 /* In Nested loop if/else value written only in one path, and read later
143 * - value must survive the outer loop.
145 TEST_F(LifetimeEvaluatorExactTest
, MoveInIfInNestedLoop
)
147 const vector
<FakeCodeline
> code
= {
148 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
149 { TGSI_OPCODE_BGNLOOP
},
150 { TGSI_OPCODE_BGNLOOP
},
151 { TGSI_OPCODE_IF
, {}, {in1
}, {} },
152 { TGSI_OPCODE_UADD
, {2}, {1,in0
}, {}},
153 { TGSI_OPCODE_ENDIF
},
154 { TGSI_OPCODE_UADD
, {3}, {1,2}, {}},
155 { TGSI_OPCODE_ENDLOOP
},
156 { TGSI_OPCODE_ENDLOOP
},
157 { TGSI_OPCODE_MOV
, {out0
}, {3}, {}},
160 run (code
, temp_lt_expect({{-1,-1}, {0,8}, {1,8}, {6,9}}));
163 /* In loop if/else value written in both path, and read later
164 * - value must survive from first write to last read in loop
165 * for now we only check that the minimum life time is correct.
167 TEST_F(LifetimeEvaluatorExactTest
, WriteInIfAndElseInLoop
)
169 const vector
<FakeCodeline
> code
= {
170 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
171 { TGSI_OPCODE_BGNLOOP
},
172 { TGSI_OPCODE_IF
, {}, {1}, {}},
173 { TGSI_OPCODE_UADD
, {2}, {1,in0
}, {}},
174 { TGSI_OPCODE_ELSE
},
175 { TGSI_OPCODE_MOV
, {2}, {1}, {}},
176 { TGSI_OPCODE_ENDIF
},
177 { TGSI_OPCODE_UADD
, {3}, {1,2}, {}},
178 { TGSI_OPCODE_UADD
, {3}, {3,in1
}, {}},
179 { TGSI_OPCODE_ENDLOOP
},
180 { TGSI_OPCODE_MOV
, {out0
}, {3}, {}},
183 run (code
, temp_lt_expect({{-1,-1}, {0,9}, {3,7}, {7,10}}));
186 /* Test that read before write in ELSE path is properly tracked:
187 * In loop if/else value written in both path but read in else path
188 * before write and also read later - value must survive the whole loop.
190 TEST_F(LifetimeEvaluatorExactTest
, WriteInIfAndElseReadInElseInLoop
)
192 const vector
<FakeCodeline
> code
= {
193 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
194 { TGSI_OPCODE_BGNLOOP
},
195 { TGSI_OPCODE_IF
, {}, {1}, {}},
196 { TGSI_OPCODE_UADD
, {2}, {1,in0
}, {}},
197 { TGSI_OPCODE_ELSE
},
198 { TGSI_OPCODE_ADD
, {2}, {1,2}, {}},
199 { TGSI_OPCODE_ENDIF
},
200 { TGSI_OPCODE_UADD
, {3}, {1,2}, {}},
201 { TGSI_OPCODE_UADD
, {3}, {3,in1
}, {}},
202 { TGSI_OPCODE_ENDLOOP
},
203 { TGSI_OPCODE_MOV
, {out0
}, {3}, {}},
206 run (code
, temp_lt_expect({{-1,-1}, {0,9}, {1,9}, {7,10}}));
210 /* Test that a write in ELSE path only in loop is properly tracked:
211 * In loop if/else value written in else path and read outside
212 * - value must survive the whole loop.
214 TEST_F(LifetimeEvaluatorExactTest
, WriteInElseReadInLoop
)
216 const vector
<FakeCodeline
> code
= {
217 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
218 { TGSI_OPCODE_BGNLOOP
},
219 { TGSI_OPCODE_IF
, {}, {1}, {}},
220 { TGSI_OPCODE_UADD
, {2}, {1,in0
}, {}},
221 { TGSI_OPCODE_ELSE
},
222 { TGSI_OPCODE_ADD
, {3}, {1,2}, {}},
223 { TGSI_OPCODE_ENDIF
},
224 { TGSI_OPCODE_UADD
, {1}, {3,in1
}, {}},
225 { TGSI_OPCODE_ENDLOOP
},
226 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
229 run (code
, temp_lt_expect({{-1,-1}, {0,9}, {1,8}, {1,8}}));
232 /* Test that tracking a second write in an ELSE path is not attributed
233 * to the IF path: In loop if/else value written in else path twice and
234 * read outside - value must survive the whole loop
236 TEST_F(LifetimeEvaluatorExactTest
, WriteInElseTwiceReadInLoop
)
238 const vector
<FakeCodeline
> code
= {
239 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
240 { TGSI_OPCODE_BGNLOOP
},
241 { TGSI_OPCODE_IF
, {}, {1}, {}},
242 { TGSI_OPCODE_UADD
, {2}, {1,in0
}, {}},
243 { TGSI_OPCODE_ELSE
},
244 { TGSI_OPCODE_ADD
, {3}, {1,2}, {}},
245 { TGSI_OPCODE_ADD
, {3}, {1,3}, {}},
246 { TGSI_OPCODE_ENDIF
},
247 { TGSI_OPCODE_UADD
, {1}, {3,in1
}, {}},
248 { TGSI_OPCODE_ENDLOOP
},
249 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
252 run (code
, temp_lt_expect({{-1,-1}, {0,10}, {1,9}, {1,9}}));
255 /* Test that the IF and ELSE scopes from different IF/ELSE pairs are not
256 * merged: In loop if/else value written in if, and then in different else path
257 * and read outside - value must survive the whole loop
259 TEST_F(LifetimeEvaluatorExactTest
, WriteInOneIfandInAnotherElseInLoop
)
261 const vector
<FakeCodeline
> code
= {
262 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
263 { TGSI_OPCODE_BGNLOOP
},
264 { TGSI_OPCODE_IF
, {}, {1}, {}},
265 { TGSI_OPCODE_UADD
, {2}, {1,in0
}, {}},
266 { TGSI_OPCODE_ENDIF
},
267 { TGSI_OPCODE_IF
, {}, {1}, {}},
268 { TGSI_OPCODE_ELSE
},
269 { TGSI_OPCODE_ADD
, {2}, {1,1}, {}},
270 { TGSI_OPCODE_ENDIF
},
271 { TGSI_OPCODE_UADD
, {1}, {2,in1
}, {}},
272 { TGSI_OPCODE_ENDLOOP
},
273 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
276 run (code
, temp_lt_expect({{-1,-1}, {0,11}, {1,10}}));
279 /* Test that with a new loop the resolution of the IF/ELSE write conditionality
280 * is restarted: In first loop value is written in both if and else, in second
281 * loop value is written only in if - must survive the second loop.
282 * However, the tracking is currently not able to restrict the lifetime
283 * in the first loop, hence the "AtLeast" test.
285 TEST_F(LifetimeEvaluatorAtLeastTest
, UnconditionalInFirstLoopConditionalInSecond
)
287 const vector
<FakeCodeline
> code
= {
288 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
289 { TGSI_OPCODE_BGNLOOP
},
290 { TGSI_OPCODE_IF
, {}, {1}, {}},
291 { TGSI_OPCODE_UADD
, {2}, {1,in0
}, {}},
292 { TGSI_OPCODE_ELSE
},
293 { TGSI_OPCODE_UADD
, {2}, {1,in1
}, {}},
294 { TGSI_OPCODE_ENDIF
},
295 { TGSI_OPCODE_ENDLOOP
},
296 { TGSI_OPCODE_BGNLOOP
},
297 { TGSI_OPCODE_IF
, {}, {1}, {}},
298 { TGSI_OPCODE_ADD
, {2}, {in0
,1}, {}},
299 { TGSI_OPCODE_ENDIF
},
300 { TGSI_OPCODE_UADD
, {1}, {2,in1
}, {}},
301 { TGSI_OPCODE_ENDLOOP
},
302 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
305 run (code
, temp_lt_expect({{-1,-1}, {0,14}, {3,13}}));
308 /* Test that with a new loop the resolution of the IF/ELSE write conditionality
309 * is restarted, and also takes care of write before read in else scope:
310 * In first loop value is written in both if and else, in second loop value is
311 * also written in both, but first read in if - must survive the second loop.
312 * However, the tracking is currently not able to restrict the lifetime
313 * in the first loop, hence the "AtLeast" test.
315 TEST_F(LifetimeEvaluatorAtLeastTest
, UnconditionalInFirstLoopConditionalInSecond2
)
317 const vector
<FakeCodeline
> code
= {
318 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
319 { TGSI_OPCODE_BGNLOOP
},
320 { TGSI_OPCODE_IF
, {}, {1}, {}},
321 { TGSI_OPCODE_UADD
, {2}, {1,in0
}, {}},
322 { TGSI_OPCODE_ELSE
},
323 { TGSI_OPCODE_UADD
, {2}, {1,in1
}, {}},
324 { TGSI_OPCODE_ENDIF
},
325 { TGSI_OPCODE_ENDLOOP
},
326 { TGSI_OPCODE_BGNLOOP
},
327 { TGSI_OPCODE_IF
, {}, {in1
}, {}},
328 { TGSI_OPCODE_ADD
, {2}, {2,1}, {}},
329 { TGSI_OPCODE_ELSE
},
330 { TGSI_OPCODE_MOV
, {2}, {1}, {}},
331 { TGSI_OPCODE_ENDIF
},
332 { TGSI_OPCODE_UADD
, {1}, {2,in1
}, {}},
333 { TGSI_OPCODE_ENDLOOP
},
334 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
337 run (code
, temp_lt_expect({{-1,-1}, {0,16}, {3,15}}));
340 /* In loop if/else read in one path before written in the same loop
341 * - value must survive the whole loop
343 TEST_F(LifetimeEvaluatorExactTest
, ReadInIfInLoopBeforeWrite
)
345 const vector
<FakeCodeline
> code
= {
346 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
347 { TGSI_OPCODE_BGNLOOP
},
348 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
349 { TGSI_OPCODE_UADD
, {2}, {1,3}, {}},
350 { TGSI_OPCODE_ENDIF
},
351 { TGSI_OPCODE_UADD
, {3}, {1,2}, {}},
352 { TGSI_OPCODE_UADD
, {3}, {3,in1
}, {}},
353 { TGSI_OPCODE_ENDLOOP
},
354 { TGSI_OPCODE_MOV
, {out0
}, {3}, {}},
357 run (code
, temp_lt_expect({{-1,-1}, {0,7}, {1,7}, {1,8}}));
360 /* In loop if/else read in one path before written in the same loop
361 * read after the loop, value must survivethe whole loop and
364 TEST_F(LifetimeEvaluatorExactTest
, ReadInLoopInIfBeforeWriteAndLifeToTheEnd
)
366 const vector
<FakeCodeline
> code
= {
367 { TGSI_OPCODE_BGNLOOP
},
368 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
369 { TGSI_OPCODE_MUL
, {1}, {1,in1
}, {}},
370 { TGSI_OPCODE_ENDIF
},
371 { TGSI_OPCODE_UADD
, {1}, {1,in1
}, {}},
372 { TGSI_OPCODE_ENDLOOP
},
373 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
376 run (code
, temp_lt_expect({{-1,-1}, {0,6}}));
379 /* In loop read before written in the same loop read after the loop,
380 * value must survive the whole loop and to the read.
381 * This is kind of undefined behaviour though ...
383 TEST_F(LifetimeEvaluatorExactTest
, ReadInLoopBeforeWriteAndLifeToTheEnd
)
385 const vector
<FakeCodeline
> code
= {
386 { TGSI_OPCODE_BGNLOOP
},
387 { TGSI_OPCODE_MUL
, {1}, {1,in1
}, {}},
388 { TGSI_OPCODE_UADD
, {1}, {1,in1
}, {}},
389 { TGSI_OPCODE_ENDLOOP
},
390 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
393 run (code
, temp_lt_expect({{-1,-1}, {0,4}}));
396 /* Test whether nesting IF/ELSE pairs within a loop is resolved:
397 * Write in all conditional branches if the inner nesting level and
398 * read after the outer IF/ELSE pair is closed. The lifetime doesn't have
399 * to be extended to the full loop.
401 TEST_F(LifetimeEvaluatorExactTest
, NestedIfInLoopAlwaysWriteButNotPropagated
)
403 const vector
<FakeCodeline
> code
= {
404 { TGSI_OPCODE_BGNLOOP
},
405 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
406 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
407 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
409 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
410 { TGSI_OPCODE_ENDIF
},
412 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
413 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
415 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
416 { TGSI_OPCODE_ENDIF
},
417 { TGSI_OPCODE_ENDIF
},
418 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
419 { TGSI_OPCODE_ENDLOOP
},
422 run (code
, temp_lt_expect({{-1,-1}, {3,14}}));
425 /* Test that nested chaining of IF/ELSE scopes is resolved:
426 * Write in each IF branch, and open another IF/ELSE scope pair in the ELSE
427 * branch. At the last nesting level, the temporary is also written in the
428 * ELSE branch, hence the full constrict results in an unconditional write.
430 TEST_F(LifetimeEvaluatorExactTest
, DeeplyNestedIfElseInLoopResolved
)
432 const vector
<FakeCodeline
> code
= {
433 { TGSI_OPCODE_BGNLOOP
},
434 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
435 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
437 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
438 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
440 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
441 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
443 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
444 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
446 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
447 { TGSI_OPCODE_ENDIF
},
448 { TGSI_OPCODE_ENDIF
},
449 { TGSI_OPCODE_ENDIF
},
450 { TGSI_OPCODE_ENDIF
},
451 { TGSI_OPCODE_ADD
, {2}, {1, in1
}, {}},
452 { TGSI_OPCODE_ENDLOOP
},
453 { TGSI_OPCODE_MOV
, {out0
}, {2}, {}},
456 run (code
, temp_lt_expect({{-1,-1}, {2,18}, {18, 20}}));
459 /* The complementary case of the above: Open deeply nested IF/ELSE clauses
460 * and only at the deepest nesting level the temporary is written in the IF
461 * branch, but for all ELSE scopes the value is also written. Like above, when
462 * the full construct has been executed, the temporary has been written
465 TEST_F(LifetimeEvaluatorExactTest
, DeeplyNestedIfElseInLoopResolved2
)
467 const vector
<FakeCodeline
> code
= {
468 { TGSI_OPCODE_BGNLOOP
},
469 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
470 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
471 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
472 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
473 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
475 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
476 { TGSI_OPCODE_ENDIF
},
478 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
479 { TGSI_OPCODE_ENDIF
},
481 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
482 { TGSI_OPCODE_ENDIF
},
484 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
485 { TGSI_OPCODE_ENDIF
},
486 { TGSI_OPCODE_ADD
, {2}, {1, in1
}, {}},
487 { TGSI_OPCODE_ENDLOOP
},
488 { TGSI_OPCODE_MOV
, {out0
}, {2}, {}},
491 run (code
, temp_lt_expect({{-1,-1}, {5,18}, {18, 20}}));
494 /* Test that a write in an IF scope within IF scope where the temporary already
497 TEST_F(LifetimeEvaluatorExactTest
, NestedIfElseInLoopResolvedInOuterScope
)
499 const vector
<FakeCodeline
> code
= {
500 { TGSI_OPCODE_BGNLOOP
},
501 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
502 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
503 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
504 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
505 { TGSI_OPCODE_ENDIF
},
507 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
508 { TGSI_OPCODE_ENDIF
},
509 { TGSI_OPCODE_ADD
, {2}, {1, in1
}, {}},
510 { TGSI_OPCODE_ENDLOOP
},
511 { TGSI_OPCODE_MOV
, {out0
}, {2}, {}},
514 run (code
, temp_lt_expect({{-1,-1}, {2,9}, {9, 11}}));
517 /* Here the read before write in the nested if is of no consequence to the
518 * life time because the variable was already written in the enclosing if-branch.
520 TEST_F(LifetimeEvaluatorExactTest
, NestedIfElseInLoopWithReadResolvedInOuterScope
)
522 const vector
<FakeCodeline
> code
= {
523 { TGSI_OPCODE_BGNLOOP
},
524 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
525 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
526 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
527 { TGSI_OPCODE_ADD
, {1}, {in0
, 1}, {}},
528 { TGSI_OPCODE_ENDIF
},
530 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
531 { TGSI_OPCODE_ENDIF
},
532 { TGSI_OPCODE_ADD
, {2}, {1, in1
}, {}},
533 { TGSI_OPCODE_ENDLOOP
},
534 { TGSI_OPCODE_MOV
, {out0
}, {2}, {}},
537 run (code
, temp_lt_expect({{-1,-1}, {2,9}, {9, 11}}));
540 /* Here the nested if condition is of no consequence to the life time
541 * because the variable was already written in the enclosing else-branch.
543 TEST_F(LifetimeEvaluatorExactTest
, NestedIfElseInLoopResolvedInOuterScope2
)
545 const vector
<FakeCodeline
> code
= {
546 { TGSI_OPCODE_BGNLOOP
},
547 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
548 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
550 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
551 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
552 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
553 { TGSI_OPCODE_ENDIF
},
554 { TGSI_OPCODE_ENDIF
},
555 { TGSI_OPCODE_ADD
, {2}, {1, in1
}, {}},
556 { TGSI_OPCODE_ENDLOOP
},
557 { TGSI_OPCODE_MOV
, {out0
}, {2}, {}},
560 run (code
, temp_lt_expect({{-1,-1}, {2,9}, {9, 11}}));
563 /* Test that tracking of IF/ELSE scopes does not unnessesarily cross loops,
564 * i.e. if the inner IF/ELSE pair is enclosed by a loop which is enclosed
565 * by another IF statement: The resolution of unconditionality of the write
566 * within the loop is not changed by the fact that the loop is enclosed by
569 TEST_F(LifetimeEvaluatorExactTest
, NestedIfInLoopAlwaysWriteParentIfOutsideLoop
)
571 const vector
<FakeCodeline
> code
= {
572 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
573 { TGSI_OPCODE_BGNLOOP
},
574 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
575 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
577 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
578 { TGSI_OPCODE_ENDIF
},
579 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
580 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
582 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
583 { TGSI_OPCODE_ENDIF
},
584 { TGSI_OPCODE_MOV
, {2}, {1}, {}},
585 { TGSI_OPCODE_ENDLOOP
},
587 { TGSI_OPCODE_MOV
, {2}, {in1
}, {}},
588 { TGSI_OPCODE_ENDIF
},
589 { TGSI_OPCODE_MOV
, {out0
}, {2}, {}},
593 run (code
, temp_lt_expect({{-1,-1}, {3,12}, {12, 17}}));
596 /* The value is written in a loop and in a nested IF, but
597 * not in all code paths, hence the value must survive the loop.
599 TEST_F(LifetimeEvaluatorExactTest
, NestedIfInLoopWriteNotAlways
)
601 const vector
<FakeCodeline
> code
= {
602 { TGSI_OPCODE_BGNLOOP
},
603 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
604 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
605 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
607 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
608 { TGSI_OPCODE_ENDIF
},
610 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
611 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
612 { TGSI_OPCODE_ENDIF
},
613 { TGSI_OPCODE_ENDIF
},
614 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
615 { TGSI_OPCODE_ENDLOOP
},
618 run (code
, temp_lt_expect({{-1,-1}, {0,13}}));
621 /* Test that reading in an ELSE branach after writing is ignored:
622 * The value is written in a loop in both branches of if-else but also
623 * read in the else after writing, should have no effect on lifetime.
625 TEST_F(LifetimeEvaluatorExactTest
, IfElseWriteInLoopAlsoReadInElse
)
627 const vector
<FakeCodeline
> code
= {
628 { TGSI_OPCODE_BGNLOOP
},
629 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
630 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
632 { TGSI_OPCODE_MOV
, {1}, {in1
}, {}},
633 { TGSI_OPCODE_MUL
, {1}, {in0
, 1}, {}},
634 { TGSI_OPCODE_ENDIF
},
635 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
636 { TGSI_OPCODE_ENDLOOP
},
639 run (code
, temp_lt_expect({{-1,-1}, {2,7}}));
642 /* Test that a write in an inner IF/ELSE pair is propagated to the outer
643 * ELSE branch: The value is written in a loop in both branches of a nested
644 * IF/ELSE pair, but only within the outer else, hence in summary the write is
645 * conditional within the loop.
647 TEST_F(LifetimeEvaluatorExactTest
, WriteInNestedIfElseOuterElseOnly
)
649 const vector
<FakeCodeline
> code
= {
650 { TGSI_OPCODE_BGNLOOP
},
651 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
653 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
654 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
656 { TGSI_OPCODE_ADD
, {1}, {in1
, in0
}, {}},
657 { TGSI_OPCODE_ENDIF
},
658 { TGSI_OPCODE_ENDIF
},
659 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
660 { TGSI_OPCODE_ENDLOOP
},
663 run (code
, temp_lt_expect({{-1,-1}, {0,10}}));
666 /* Test that reads in an inner ELSE after write within the enclosing IF branch
667 * is of no consequence (i.e. check that the read in the ELSE branch is not
668 * attributed as read before write when the outer ELSE branch is scanned:
669 * Nested if-else in loop. The value is written in the outer if and else and
670 * read in one inner else, should limit lifetime.
672 TEST_F(LifetimeEvaluatorExactTest
, WriteUnconditionallyReadInNestedElse
)
674 const vector
<FakeCodeline
> code
= {
675 { TGSI_OPCODE_BGNLOOP
},
676 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
677 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
678 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
680 { TGSI_OPCODE_MOV
, {out1
}, {1}, {}},
681 { TGSI_OPCODE_ENDIF
},
683 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
684 { TGSI_OPCODE_ENDIF
},
685 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
686 { TGSI_OPCODE_ENDLOOP
},
689 run (code
, temp_lt_expect({{-1,-1}, {2,10}}));
693 /* Nested if-else in loop. The value is written in a loop in both branches
694 * of if-else but also read in the second nested else before writing.
697 TEST_F(LifetimeEvaluatorExactTest
, NestedIfelseReadFirstInInnerElseInLoop
)
699 const vector
<FakeCodeline
> code
= {
700 { TGSI_OPCODE_BGNLOOP
},
701 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
702 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
703 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
705 { TGSI_OPCODE_MOV
, {1}, {in1
}, {}},
706 { TGSI_OPCODE_ENDIF
},
708 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
709 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
711 { TGSI_OPCODE_ADD
, {1}, {in1
, 1}, {}},
712 { TGSI_OPCODE_ENDIF
},
713 { TGSI_OPCODE_ENDIF
},
714 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
715 { TGSI_OPCODE_ENDLOOP
},
718 run (code
, temp_lt_expect({{-1,-1}, {0,15}}));
721 /* Test that read before write is properly tracked for nested IF branches.
722 * The value is written in a loop in both branches of IF/ELSE but also read in
723 * the second nested IF before writing - is conditional.
725 TEST_F(LifetimeEvaluatorExactTest
, NestedIfelseReadFirstInInnerIfInLoop
)
727 const vector
<FakeCodeline
> code
= {
728 { TGSI_OPCODE_BGNLOOP
},
729 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
730 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
731 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
733 { TGSI_OPCODE_MOV
, {1}, {in1
}, {}},
734 { TGSI_OPCODE_ENDIF
},
736 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
737 { TGSI_OPCODE_ADD
, {1}, {in1
, 1}, {}},
739 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
740 { TGSI_OPCODE_ENDIF
},
741 { TGSI_OPCODE_ENDIF
},
742 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
743 { TGSI_OPCODE_ENDLOOP
},
746 run (code
, temp_lt_expect({{-1,-1}, {0,15}}));
749 /* Same as above, but for the secondary ELSE branch:
750 * The value is written in a loop in both branches of IF/ELSE but also read in
751 * the second nested ELSE branch before writing - is conditional.
753 TEST_F(LifetimeEvaluatorExactTest
, WriteInOneElseBranchReadFirstInOtherInLoop
)
755 const vector
<FakeCodeline
> code
= {
756 { TGSI_OPCODE_BGNLOOP
},
757 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
758 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
760 { TGSI_OPCODE_MOV
, {1}, {in1
}, {}},
761 { TGSI_OPCODE_ENDIF
},
762 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
763 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
765 { TGSI_OPCODE_ADD
, {1}, {in1
, 1}, {}},
766 { TGSI_OPCODE_ENDIF
},
767 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
768 { TGSI_OPCODE_ENDLOOP
},
771 run (code
, temp_lt_expect({{-1,-1}, {2,11}}));
774 /* Test that the "write is unconditional" resolution is not overwritten within
775 * a loop: The value is written in a loop in both branches of an IF/ELSE clause,
776 * hence the second IF doesn't make it conditional.
778 TEST_F(LifetimeEvaluatorExactTest
, WriteInIfElseBranchSecondIfInLoop
)
780 const vector
<FakeCodeline
> code
= {
781 { TGSI_OPCODE_BGNLOOP
},
782 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
783 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
785 { TGSI_OPCODE_MOV
, {1}, {in1
}, {}},
786 { TGSI_OPCODE_ENDIF
},
787 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
788 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
789 { TGSI_OPCODE_ENDIF
},
790 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
791 { TGSI_OPCODE_ENDLOOP
},
794 run (code
, temp_lt_expect({{-1,-1}, {2,9}}));
797 /** Regression test for bug #104803,
798 * Read and write in if/else path outside loop and later read in conditional
799 * within a loop. The first write is to be considered the dominant write.
801 TEST_F(LifetimeEvaluatorExactTest
, IfElseWriteInBothOutsideLoopReadInElseInLoop
)
803 const vector
<FakeCodeline
> code
= {
804 { TGSI_OPCODE_IF
, {}, {in0
}, {} },
805 { TGSI_OPCODE_MOV
, {1}, {in0
}, {} },
806 { TGSI_OPCODE_ELSE
, {}, {}, {} },
807 { TGSI_OPCODE_MOV
, {1}, {in1
}, {} },
808 { TGSI_OPCODE_ENDIF
, {}, {}, {} },
809 { TGSI_OPCODE_BGNLOOP
},
810 { TGSI_OPCODE_IF
, {}, {in0
}, {} },
811 { TGSI_OPCODE_MOV
, {2}, {in1
}, {} },
812 { TGSI_OPCODE_ELSE
, {}, {}, {} },
813 { TGSI_OPCODE_MOV
, {2}, {1}, {} },
814 { TGSI_OPCODE_ENDIF
, {}, {}, {} },
815 { TGSI_OPCODE_ENDLOOP
},
816 { TGSI_OPCODE_MOV
, {out0
}, {2}, {}},
819 run (code
, temp_lt_expect({{-1,-1}, {1,11}, {7, 12}}));
822 /* A continue in the loop is not relevant */
823 TEST_F(LifetimeEvaluatorExactTest
, LoopWithWriteAfterContinue
)
825 const vector
<FakeCodeline
> code
= {
826 { TGSI_OPCODE_BGNLOOP
},
827 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
829 { TGSI_OPCODE_ENDIF
},
830 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
831 { TGSI_OPCODE_ENDLOOP
},
832 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
835 run (code
, temp_lt_expect({{-1,-1}, {4,6}}));
838 /* Temporary used to in case must live up to the case
839 * statement where it is used, the switch we only keep
840 * for the actual SWITCH opcode like it is in tgsi_exec.c, the
841 * only current use case.
843 TEST_F(LifetimeEvaluatorExactTest
, UseSwitchCase
)
845 const vector
<FakeCodeline
> code
= {
846 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
847 { TGSI_OPCODE_MOV
, {2}, {in1
}, {}},
848 { TGSI_OPCODE_MOV
, {3}, {in2
}, {}},
849 { TGSI_OPCODE_SWITCH
, {}, {3}, {}},
850 { TGSI_OPCODE_CASE
, {}, {2}, {}},
851 { TGSI_OPCODE_CASE
, {}, {1}, {}},
853 { TGSI_OPCODE_DEFAULT
},
854 { TGSI_OPCODE_ENDSWITCH
},
857 run (code
, temp_lt_expect({{-1,-1}, {0,5}, {1,4}, {2,3}}));
860 /* With two destinations, if one result is thrown away, the
861 * register must be kept past the writing instructions.
863 TEST_F(LifetimeEvaluatorExactTest
, WriteTwoOnlyUseOne
)
865 const vector
<FakeCodeline
> code
= {
866 { TGSI_OPCODE_DFRACEXP
, {1,2}, {in0
}, {}},
867 { TGSI_OPCODE_ADD
, {3}, {2,in0
}, {}},
868 { TGSI_OPCODE_MOV
, {out1
}, {3}, {}},
872 run (code
, temp_lt_expect({{-1,-1}, {0,1}, {0,1}, {1,2}}));
875 /* If a break is in the loop, all variables written after the
876 * break and used outside the loop must be maintained for the
879 TEST_F(LifetimeEvaluatorExactTest
, LoopWithWriteAfterBreak
)
881 const vector
<FakeCodeline
> code
= {
882 { TGSI_OPCODE_BGNLOOP
},
883 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
885 { TGSI_OPCODE_ENDIF
},
886 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
887 { TGSI_OPCODE_ENDLOOP
},
888 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
891 run (code
, temp_lt_expect({{-1,-1}, {0,6}}));
894 /* If a break is in the loop, all variables written after the
895 * break and used outside the loop must be maintained for the
896 * whole loop. The first break in the loop is the defining one.
898 TEST_F(LifetimeEvaluatorExactTest
, LoopWithWriteAfterBreak2Breaks
)
900 const vector
<FakeCodeline
> code
= {
901 { TGSI_OPCODE_BGNLOOP
},
902 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
904 { TGSI_OPCODE_ENDIF
},
905 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
907 { TGSI_OPCODE_ENDLOOP
},
908 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
911 run (code
, temp_lt_expect({{-1,-1}, {0,7}}));
914 /* Loop with a break at the beginning and read/write in the post
915 * break loop scope. The value written and read within the loop
916 * can be limited to [write, read], but the value read outside the
917 * loop must survive the whole loop. This is the typical code for
918 * while and for loops, where the breaking condition is tested at
921 TEST_F(LifetimeEvaluatorExactTest
, LoopWithWriteAndReadAfterBreak
)
923 const vector
<FakeCodeline
> code
= {
924 { TGSI_OPCODE_BGNLOOP
},
925 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
927 { TGSI_OPCODE_ENDIF
},
928 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
929 { TGSI_OPCODE_MOV
, {2}, {1}, {}},
930 { TGSI_OPCODE_ENDLOOP
},
931 { TGSI_OPCODE_MOV
, {out0
}, {2}, {}},
934 run (code
, temp_lt_expect({{-1,-1}, {4,5}, {0,7}}));
937 /* Same as above, just make sure that the life time of the local variable
938 * in the outer loop (3) is not accidently promoted to the whole loop.
940 TEST_F(LifetimeEvaluatorExactTest
, NestedLoopWithWriteAndReadAfterBreak
)
942 const vector
<FakeCodeline
> code
= {
943 { TGSI_OPCODE_BGNLOOP
},
944 { TGSI_OPCODE_IF
, {}, {in1
}, {}},
946 { TGSI_OPCODE_ENDIF
},
947 { TGSI_OPCODE_BGNLOOP
},
948 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
950 { TGSI_OPCODE_ENDIF
},
951 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
952 { TGSI_OPCODE_MOV
, {2}, {1}, {}},
953 { TGSI_OPCODE_ENDLOOP
},
954 { TGSI_OPCODE_ADD
, {3}, {2,in0
}, {}},
955 { TGSI_OPCODE_ADD
, {4}, {3,in2
}, {}},
956 { TGSI_OPCODE_ENDLOOP
},
957 { TGSI_OPCODE_MOV
, {out0
}, {4}, {}},
960 run (code
, temp_lt_expect({{-1,-1}, {8,9}, {0,13}, {11,12}, {0,14}}));
963 /* If a break is in the loop inside a switch case, make sure it is
964 * interpreted as breaking that inner loop, i.e. the variable has to
967 TEST_F(LifetimeEvaluatorExactTest
, LoopWithWriteAfterBreakInSwitchInLoop
)
969 const vector
<FakeCodeline
> code
= {
970 { TGSI_OPCODE_SWITCH
, {}, {in1
}, {}},
971 { TGSI_OPCODE_CASE
, {}, {in1
}, {}},
972 { TGSI_OPCODE_BGNLOOP
},
973 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
975 { TGSI_OPCODE_ENDIF
},
976 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
977 { TGSI_OPCODE_ENDLOOP
},
978 { TGSI_OPCODE_DEFAULT
, {}, {}, {}},
979 { TGSI_OPCODE_ENDSWITCH
, {}, {}, {}},
980 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
983 run (code
, temp_lt_expect({{-1,-1}, {2,10}}));
986 /* Value written conditionally in one loop and read in another loop,
987 * and both of these loops are within yet another loop. Here the value
988 * has to survive the outer loop.
990 TEST_F(LifetimeEvaluatorExactTest
, LoopsWithDifferntScopesConditionalWrite
)
992 const vector
<FakeCodeline
> code
= {
993 { TGSI_OPCODE_BGNLOOP
},
994 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
995 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
996 { TGSI_OPCODE_ENDIF
},
997 { TGSI_OPCODE_ENDLOOP
},
998 { TGSI_OPCODE_BGNLOOP
},
999 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1000 { TGSI_OPCODE_ENDLOOP
},
1003 run (code
, temp_lt_expect({{-1,-1}, {0,7}}));
1006 /* Value written and read in one loop and last read in another loop,
1007 * Here the value has to survive both loops.
1009 TEST_F(LifetimeEvaluatorExactTest
, LoopsWithDifferntScopesFirstReadBeforeWrite
)
1011 const vector
<FakeCodeline
> code
= {
1012 { TGSI_OPCODE_BGNLOOP
},
1013 { TGSI_OPCODE_MUL
, {1}, {1,in0
}, {}},
1014 { TGSI_OPCODE_ENDLOOP
},
1015 { TGSI_OPCODE_BGNLOOP
},
1016 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1017 { TGSI_OPCODE_ENDLOOP
},
1020 run (code
, temp_lt_expect({{-1,-1}, {0,5}}));
1024 /* Value is written in one switch code path within a loop
1025 * must survive the full loop.
1027 TEST_F(LifetimeEvaluatorExactTest
, LoopWithWriteInSwitch
)
1029 const vector
<FakeCodeline
> code
= {
1030 { TGSI_OPCODE_BGNLOOP
},
1031 { TGSI_OPCODE_SWITCH
, {}, {in0
}, {} },
1032 { TGSI_OPCODE_CASE
, {}, {in0
}, {} },
1033 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1034 { TGSI_OPCODE_BRK
},
1035 { TGSI_OPCODE_DEFAULT
},
1036 { TGSI_OPCODE_BRK
},
1037 { TGSI_OPCODE_ENDSWITCH
},
1038 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1039 { TGSI_OPCODE_ENDLOOP
},
1042 run (code
, temp_lt_expect({{-1,-1}, {0,9}}));
1045 /* Value written in one case, and read in other,in loop
1046 * - must survive the loop.
1048 TEST_F(LifetimeEvaluatorExactTest
, LoopWithReadWriteInSwitchDifferentCase
)
1050 const vector
<FakeCodeline
> code
= {
1051 { TGSI_OPCODE_BGNLOOP
},
1052 { TGSI_OPCODE_SWITCH
, {}, {in0
}, {} },
1053 { TGSI_OPCODE_CASE
, {}, {in0
}, {} },
1054 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1055 { TGSI_OPCODE_BRK
},
1056 { TGSI_OPCODE_DEFAULT
},
1057 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1058 { TGSI_OPCODE_BRK
},
1059 { TGSI_OPCODE_ENDSWITCH
},
1060 { TGSI_OPCODE_ENDLOOP
},
1063 run (code
, temp_lt_expect({{-1,-1}, {0,9}}));
1066 /* Value written in one case, and read in other,in loop
1067 * - must survive the loop, even if the write case falls through.
1069 TEST_F(LifetimeEvaluatorExactTest
, LoopWithReadWriteInSwitchDifferentCaseFallThrough
)
1071 const vector
<FakeCodeline
> code
= {
1072 { TGSI_OPCODE_BGNLOOP
},
1073 { TGSI_OPCODE_SWITCH
, {}, {in0
}, {} },
1074 { TGSI_OPCODE_CASE
, {}, {in0
}, {} },
1075 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1076 { TGSI_OPCODE_DEFAULT
},
1077 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1078 { TGSI_OPCODE_BRK
},
1079 { TGSI_OPCODE_ENDSWITCH
},
1080 { TGSI_OPCODE_ENDLOOP
},
1083 run (code
, temp_lt_expect({{-1,-1}, {0,8}}));
1086 /* Here we read and write from an to the same temp in the same instruction,
1087 * but the read is conditional (select operation), hence the lifetime must
1088 * start with the first write.
1090 TEST_F(LifetimeEvaluatorExactTest
, WriteSelectFromSelf
)
1092 const vector
<FakeCodeline
> code
= {
1093 { TGSI_OPCODE_USEQ
, {5}, {in0
,in1
}, {}},
1094 { TGSI_OPCODE_UCMP
, {1}, {5,in1
,1}, {}},
1095 { TGSI_OPCODE_UCMP
, {1}, {5,in1
,1}, {}},
1096 { TGSI_OPCODE_UCMP
, {1}, {5,in1
,1}, {}},
1097 { TGSI_OPCODE_UCMP
, {1}, {5,in1
,1}, {}},
1098 { TGSI_OPCODE_FSLT
, {2}, {1,in1
}, {}},
1099 { TGSI_OPCODE_UIF
, {}, {2}, {}},
1100 { TGSI_OPCODE_MOV
, {3}, {in1
}, {}},
1101 { TGSI_OPCODE_ELSE
},
1102 { TGSI_OPCODE_MOV
, {4}, {in1
}, {}},
1103 { TGSI_OPCODE_MOV
, {4}, {4}, {}},
1104 { TGSI_OPCODE_MOV
, {3}, {4}, {}},
1105 { TGSI_OPCODE_ENDIF
},
1106 { TGSI_OPCODE_MOV
, {out1
}, {3}, {}},
1109 run (code
, temp_lt_expect({{-1,-1}, {1,5}, {5,6}, {7,13}, {9,11}, {0,4}}));
1112 /* This test checks wheter the ENDSWITCH is handled properly if the
1113 * last switch case/default doesn't stop with a BRK.
1115 TEST_F(LifetimeEvaluatorExactTest
, LoopRWInSwitchCaseLastCaseWithoutBreak
)
1117 const vector
<FakeCodeline
> code
= {
1118 { TGSI_OPCODE_BGNLOOP
},
1119 { TGSI_OPCODE_SWITCH
, {}, {in0
}, {} },
1120 { TGSI_OPCODE_CASE
, {}, {in0
}, {} },
1121 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1122 { TGSI_OPCODE_BRK
},
1123 { TGSI_OPCODE_DEFAULT
},
1124 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1125 { TGSI_OPCODE_ENDSWITCH
},
1126 { TGSI_OPCODE_ENDLOOP
},
1129 run (code
, temp_lt_expect({{-1,-1}, {0,8}}));
1132 /* Value read/write in same case, stays there */
1133 TEST_F(LifetimeEvaluatorExactTest
, LoopWithReadWriteInSwitchSameCase
)
1135 const vector
<FakeCodeline
> code
= {
1136 { TGSI_OPCODE_BGNLOOP
},
1137 { TGSI_OPCODE_SWITCH
, {}, {in0
}, {} },
1138 { TGSI_OPCODE_CASE
, {}, {in0
}, {} },
1139 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1140 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1141 { TGSI_OPCODE_BRK
},
1142 { TGSI_OPCODE_DEFAULT
},
1143 { TGSI_OPCODE_BRK
},
1144 { TGSI_OPCODE_ENDSWITCH
},
1145 { TGSI_OPCODE_ENDLOOP
},
1148 run (code
, temp_lt_expect({{-1,-1}, {3,4}}));
1151 /* Value read/write in all cases, should only live from first
1152 * write to last read, but currently the whole loop is used.
1154 TEST_F(LifetimeEvaluatorAtLeastTest
, LoopWithReadWriteInSwitchSameCase
)
1156 const vector
<FakeCodeline
> code
= {
1157 { TGSI_OPCODE_BGNLOOP
},
1158 { TGSI_OPCODE_SWITCH
, {}, {in0
}, {}},
1159 { TGSI_OPCODE_CASE
, {}, {in0
}, {} },
1160 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1161 { TGSI_OPCODE_BRK
},
1162 { TGSI_OPCODE_DEFAULT
},
1163 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1164 { TGSI_OPCODE_BRK
},
1165 { TGSI_OPCODE_ENDSWITCH
},
1166 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1167 { TGSI_OPCODE_ENDLOOP
},
1170 run (code
, temp_lt_expect({{-1,-1}, {3,9}}));
1173 /* First read before first write with nested loops */
1174 TEST_F(LifetimeEvaluatorExactTest
, LoopsWithDifferentScopesCondReadBeforeWrite
)
1176 const vector
<FakeCodeline
> code
= {
1177 { TGSI_OPCODE_BGNLOOP
},
1178 { TGSI_OPCODE_BGNLOOP
},
1179 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
1180 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1181 { TGSI_OPCODE_ENDIF
},
1182 { TGSI_OPCODE_ENDLOOP
},
1183 { TGSI_OPCODE_BGNLOOP
},
1184 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1185 { TGSI_OPCODE_ENDLOOP
},
1186 { TGSI_OPCODE_ENDLOOP
},
1189 run (code
, temp_lt_expect({{-1,-1}, {0,9}}));
1192 /* First read before first write wiredness with nested loops.
1193 * Here the first read of 2 is logically before the first, dominant
1194 * write, therfore, the 2 has to survive both loops.
1196 TEST_F(LifetimeEvaluatorExactTest
, FirstWriteAtferReadInNestedLoop
)
1198 const vector
<FakeCodeline
> code
= {
1199 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1200 { TGSI_OPCODE_BGNLOOP
},
1201 { TGSI_OPCODE_BGNLOOP
},
1202 { TGSI_OPCODE_MUL
, {2}, {2,1}, {}},
1203 { TGSI_OPCODE_MOV
, {3}, {2}, {}},
1204 { TGSI_OPCODE_ENDLOOP
},
1205 { TGSI_OPCODE_ADD
, {1}, {1,in1
}, {}},
1206 { TGSI_OPCODE_ENDLOOP
},
1207 { TGSI_OPCODE_MOV
, {out0
}, {3}, {}},
1210 run (code
, temp_lt_expect({{-1,-1}, {0,7}, {1,7}, {4,8}}));
1214 #define DST(X, W) vector<pair<int,int>>(1, make_pair(X, W))
1215 #define SRC(X, S) vector<pair<int, const char *>>(1, make_pair(X, S))
1216 #define SRC2(X, S, Y, T) vector<pair<int, const char *>>({make_pair(X, S), make_pair(Y, T)})
1218 /* Partial write to components: one component was written unconditionally
1219 * but another conditionally, temporary must survive the whole loop.
1220 * Test series for all components.
1222 TEST_F(LifetimeEvaluatorExactTest
, LoopWithConditionalComponentWrite_X
)
1224 const vector
<FakeCodeline
> code
= {
1225 { TGSI_OPCODE_BGNLOOP
},
1226 { TGSI_OPCODE_MOV
, DST(1, WRITEMASK_Y
), SRC(in1
, "x"), {}, SWZ()},
1227 { TGSI_OPCODE_IF
, {}, SRC(in0
, "xxxx"), {}, SWZ()},
1228 { TGSI_OPCODE_MOV
, DST(1, WRITEMASK_X
), SRC(in1
, "y"), {}, SWZ()},
1229 { TGSI_OPCODE_ENDIF
},
1230 { TGSI_OPCODE_MOV
, DST(2, WRITEMASK_XY
), SRC(1, "xy"), {}, SWZ()},
1231 { TGSI_OPCODE_ENDLOOP
},
1232 { TGSI_OPCODE_MOV
, DST(out0
, WRITEMASK_XYZW
), SRC(2, "xyxy"), {}, SWZ()},
1235 run (code
, temp_lt_expect({{-1,-1}, {0,6}, {5,7}}));
1238 TEST_F(LifetimeEvaluatorExactTest
, LoopWithConditionalComponentWrite_Y
)
1240 const vector
<FakeCodeline
> code
= {
1241 { TGSI_OPCODE_BGNLOOP
},
1242 { TGSI_OPCODE_MOV
, DST(1, WRITEMASK_X
), SRC(in1
, "x"), {}, SWZ()},
1243 { TGSI_OPCODE_IF
, {}, SRC(in0
, "xxxx"), {}, SWZ()},
1244 { TGSI_OPCODE_MOV
, DST(1, WRITEMASK_Y
), SRC(in1
, "y"), {}, SWZ()},
1245 { TGSI_OPCODE_ENDIF
},
1246 { TGSI_OPCODE_MOV
, DST(2, WRITEMASK_XY
), SRC(1, "xy"), {}, SWZ()},
1247 { TGSI_OPCODE_ENDLOOP
},
1248 { TGSI_OPCODE_MOV
, DST(out0
, WRITEMASK_XYZW
), SRC(2, "xyxy"), {}, SWZ()},
1251 run (code
, temp_lt_expect({{-1,-1}, {0,6}, {5,7}}));
1254 TEST_F(LifetimeEvaluatorExactTest
, LoopWithConditionalComponentWrite_Z
)
1256 const vector
<FakeCodeline
> code
= {
1257 { TGSI_OPCODE_BGNLOOP
},
1258 { TGSI_OPCODE_MOV
, DST(1, WRITEMASK_X
), SRC(in1
, "x"), {}, SWZ()},
1259 { TGSI_OPCODE_IF
, {}, SRC(in0
, "xxxx"), {}, SWZ()},
1260 { TGSI_OPCODE_MOV
, DST(1, WRITEMASK_Z
), SRC(in1
, "y"), {}, SWZ()},
1261 { TGSI_OPCODE_ENDIF
},
1262 { TGSI_OPCODE_MOV
, DST(2, WRITEMASK_XY
), SRC(1, "xz"), {}, SWZ()},
1263 { TGSI_OPCODE_ENDLOOP
},
1264 { TGSI_OPCODE_MOV
, DST(out0
, WRITEMASK_XYZW
), SRC(2, "xyxy"), {}, SWZ()},
1267 run (code
, temp_lt_expect({{-1,-1}, {0,6}, {5,7}}));
1270 TEST_F(LifetimeEvaluatorExactTest
, LoopWithConditionalComponentWrite_W
)
1272 const vector
<FakeCodeline
> code
= {
1273 { TGSI_OPCODE_BGNLOOP
},
1274 { TGSI_OPCODE_MOV
, DST(1, WRITEMASK_X
), SRC(in1
, "x"), {}, SWZ()},
1275 { TGSI_OPCODE_IF
, {}, SRC(in0
, "xxxx"), {}, SWZ()},
1276 { TGSI_OPCODE_MOV
, DST(1, WRITEMASK_W
), SRC(in1
, "y"), {}, SWZ()},
1277 { TGSI_OPCODE_ENDIF
},
1278 { TGSI_OPCODE_MOV
, DST(2, WRITEMASK_XY
), SRC(1, "xw"), {}, SWZ()},
1279 { TGSI_OPCODE_ENDLOOP
},
1280 { TGSI_OPCODE_MOV
, DST(out0
, WRITEMASK_XYZW
), SRC(2, "xyxy"), {}, SWZ()},
1283 run (code
, temp_lt_expect({{-1,-1}, {0,6}, {5,7}}));
1286 TEST_F(LifetimeEvaluatorExactTest
, LoopWithConditionalComponentWrite_X_Read_Y_Before
)
1288 const vector
<FakeCodeline
> code
= {
1289 { TGSI_OPCODE_BGNLOOP
},
1290 { TGSI_OPCODE_MOV
, DST(1, WRITEMASK_X
), SRC(in1
, "x"), {}, SWZ()},
1291 { TGSI_OPCODE_IF
, {}, SRC(in0
, "xxxx"), {}, SWZ()},
1292 { TGSI_OPCODE_MOV
, DST(2, WRITEMASK_XYZW
), SRC(1, "yyyy"), {}, SWZ()},
1293 { TGSI_OPCODE_ENDIF
},
1294 { TGSI_OPCODE_MOV
, DST(1, WRITEMASK_YZW
), SRC(2, "yyzw"), {}, SWZ()},
1295 { TGSI_OPCODE_ENDLOOP
},
1296 { TGSI_OPCODE_ADD
, DST(out0
, WRITEMASK_XYZW
),
1297 SRC2(2, "yyzw", 1, "xyxy"), {}, SWZ()},
1300 run (code
, temp_lt_expect({{-1,-1}, {0,7}, {0,7}}));
1303 /* The variable is conditionally read before first written, so
1304 * it has to surive all the loops.
1306 TEST_F(LifetimeEvaluatorExactTest
, FRaWSameInstructionInLoopAndCondition
)
1308 const vector
<FakeCodeline
> code
= {
1309 { TGSI_OPCODE_BGNLOOP
},
1310 { TGSI_OPCODE_BGNLOOP
},
1311 { TGSI_OPCODE_IF
, {}, {in0
}, {} },
1312 { TGSI_OPCODE_ADD
, {1}, {1,in0
}, {}},
1313 { TGSI_OPCODE_ENDIF
},
1314 { TGSI_OPCODE_MOV
, {1}, {in1
}, {}},
1315 { TGSI_OPCODE_ENDLOOP
},
1316 { TGSI_OPCODE_ENDLOOP
},
1320 run (code
, temp_lt_expect({{-1,-1}, {0,7}}));
1323 /* If unconditionally first written and read in the same
1324 * instruction, then the register must be kept for the
1325 * one write, but not more (undefined behaviour)
1327 TEST_F(LifetimeEvaluatorExactTest
, FRaWSameInstruction
)
1329 const vector
<FakeCodeline
> code
= {
1330 { TGSI_OPCODE_ADD
, {1}, {1,in0
}, {}},
1334 run (code
, temp_lt_expect({{-1,-1}, {0,1}}));
1337 /* If unconditionally written and read in the same
1338 * instruction, various times then the register must be
1339 * kept past the last write, but not longer (undefined behaviour)
1341 TEST_F(LifetimeEvaluatorExactTest
, FRaWSameInstructionMoreThenOnce
)
1343 const vector
<FakeCodeline
> code
= {
1344 { TGSI_OPCODE_ADD
, {1}, {1,in0
}, {}},
1345 { TGSI_OPCODE_ADD
, {1}, {1,in0
}, {}},
1346 { TGSI_OPCODE_MOV
, {out0
}, {in0
}, {}},
1350 run (code
, temp_lt_expect({{-1,-1}, {0,2}}));
1353 /* Register is only written. This should not happen,
1354 * but to handle the case we want the register to life
1355 * at least one instruction
1357 TEST_F(LifetimeEvaluatorExactTest
, WriteOnly
)
1359 const vector
<FakeCodeline
> code
= {
1360 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1363 run (code
, temp_lt_expect({{-1,-1}, {0,1}}));
1366 /* Register is read in IF.
1368 TEST_F(LifetimeEvaluatorExactTest
, SimpleReadForIf
)
1370 const vector
<FakeCodeline
> code
= {
1371 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1372 { TGSI_OPCODE_ADD
, {out0
}, {in0
,in1
}, {}},
1373 { TGSI_OPCODE_IF
, {}, {1}, {}},
1374 { TGSI_OPCODE_ENDIF
}
1376 run (code
, temp_lt_expect({{-1,-1}, {0,2}}));
1379 TEST_F(LifetimeEvaluatorExactTest
, WriteTwoReadOne
)
1381 const vector
<FakeCodeline
> code
= {
1382 { TGSI_OPCODE_DFRACEXP
, {1,2}, {in0
}, {}},
1383 { TGSI_OPCODE_ADD
, {3}, {2,in0
}, {}},
1384 { TGSI_OPCODE_MOV
, {out1
}, {3}, {}},
1387 run (code
, temp_lt_expect({{-1,-1}, {0,1}, {0,1}, {1,2}}));
1390 TEST_F(LifetimeEvaluatorExactTest
, ReadOnly
)
1392 const vector
<FakeCodeline
> code
= {
1393 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1396 run (code
, temp_lt_expect({{-1,-1}, {-1,-1}}));
1399 /* Test handling of missing END marker
1401 TEST_F(LifetimeEvaluatorExactTest
, SomeScopesAndNoEndProgramId
)
1403 const vector
<FakeCodeline
> code
= {
1404 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1405 { TGSI_OPCODE_IF
, {}, {1}, {}},
1406 { TGSI_OPCODE_MOV
, {2}, {1}, {}},
1407 { TGSI_OPCODE_ENDIF
},
1408 { TGSI_OPCODE_IF
, {}, {1}, {}},
1409 { TGSI_OPCODE_MOV
, {out0
}, {2}, {}},
1410 { TGSI_OPCODE_ENDIF
},
1412 run (code
, temp_lt_expect({{-1,-1}, {0,4}, {2,5}}));
1415 TEST_F(LifetimeEvaluatorExactTest
, SerialReadWrite
)
1417 const vector
<FakeCodeline
> code
= {
1418 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1419 { TGSI_OPCODE_MOV
, {2}, {1}, {}},
1420 { TGSI_OPCODE_MOV
, {3}, {2}, {}},
1421 { TGSI_OPCODE_MOV
, {out0
}, {3}, {}},
1424 run (code
, temp_lt_expect({{-1,-1}, {0,1}, {1,2}, {2,3}}));
1427 /* Check that two destination registers are used */
1428 TEST_F(LifetimeEvaluatorExactTest
, TwoDestRegisters
)
1430 const vector
<FakeCodeline
> code
= {
1431 { TGSI_OPCODE_DFRACEXP
, {1,2}, {in0
}, {}},
1432 { TGSI_OPCODE_ADD
, {out0
}, {1,2}, {}},
1435 run (code
, temp_lt_expect({{-1,-1}, {0,1}, {0,1}}));
1438 /* Check that writing within a loop in a conditional is propagated
1439 * to the outer loop.
1441 TEST_F(LifetimeEvaluatorExactTest
, WriteInLoopInConditionalReadOutside
)
1443 const vector
<FakeCodeline
> code
= {
1444 { TGSI_OPCODE_BGNLOOP
},
1445 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
1446 { TGSI_OPCODE_BGNLOOP
},
1447 { TGSI_OPCODE_MOV
, {1}, {in1
}, {}},
1448 { TGSI_OPCODE_ENDLOOP
},
1449 { TGSI_OPCODE_ENDIF
},
1450 { TGSI_OPCODE_ADD
, {2}, {1,in1
}, {}},
1451 { TGSI_OPCODE_ENDLOOP
},
1452 { TGSI_OPCODE_MOV
, {out0
}, {2}, {}},
1455 run (code
, temp_lt_expect({{-1,-1}, {0,7}, {6,8}}));
1458 /* Check that a register written in a loop that is inside a conditional
1459 * is not propagated past that loop if last read is also within the
1462 TEST_F(LifetimeEvaluatorExactTest
, WriteInLoopInCondReadInCondOutsideLoop
)
1464 const vector
<FakeCodeline
> code
= {
1465 { TGSI_OPCODE_BGNLOOP
},
1466 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
1467 { TGSI_OPCODE_BGNLOOP
},
1468 { TGSI_OPCODE_MUL
, {1}, {in2
,in1
}, {}},
1469 { TGSI_OPCODE_ENDLOOP
},
1470 { TGSI_OPCODE_ADD
, {2}, {1,in1
}, {}},
1471 { TGSI_OPCODE_ENDIF
},
1472 { TGSI_OPCODE_ENDLOOP
},
1473 { TGSI_OPCODE_MOV
, {out0
}, {2}, {}},
1476 run (code
, temp_lt_expect({{-1,-1}, {3,5}, {0,8}}));
1479 /* Check that a register read before written in a loop that is
1480 * inside a conditional is propagated to the outer loop.
1482 TEST_F(LifetimeEvaluatorExactTest
, ReadWriteInLoopInCondReadInCondOutsideLoop
)
1484 const vector
<FakeCodeline
> code
= {
1485 { TGSI_OPCODE_BGNLOOP
},
1486 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
1487 { TGSI_OPCODE_BGNLOOP
},
1488 { TGSI_OPCODE_MUL
, {1}, {1,in1
}, {}},
1489 { TGSI_OPCODE_ENDLOOP
},
1490 { TGSI_OPCODE_ADD
, {2}, {1,in1
}, {}},
1491 { TGSI_OPCODE_ENDIF
},
1492 { TGSI_OPCODE_ENDLOOP
},
1493 { TGSI_OPCODE_MOV
, {out0
}, {2}, {}},
1496 run (code
, temp_lt_expect({{-1,-1}, {0,7}, {0,8}}));
1499 /* With two destinations if one value is thrown away, we must
1500 * ensure that the two output registers don't merge. In this test
1501 * case the last access for 2 and 3 is in line 4, but 4 can only
1502 * be merged with 3 because it is read,2 on the other hand is written
1503 * to, and merging it with 4 would result in a bug.
1505 TEST_F(LifetimeEvaluatorExactTest
, WritePastLastRead2
)
1507 const vector
<FakeCodeline
> code
= {
1508 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1509 { TGSI_OPCODE_MOV
, {2}, {in0
}, {}},
1510 { TGSI_OPCODE_ADD
, {3}, {1,2}, {}},
1511 { TGSI_OPCODE_DFRACEXP
, {2,4}, {3}, {}},
1512 { TGSI_OPCODE_MOV
, {out1
}, {4}, {}},
1515 run (code
, temp_lt_expect({{-1,-1}, {0,2}, {1,4}, {2,3}, {3,4}}));
1518 /* Check that three source registers are used */
1519 TEST_F(LifetimeEvaluatorExactTest
, ThreeSourceRegisters
)
1521 const vector
<FakeCodeline
> code
= {
1522 { TGSI_OPCODE_DFRACEXP
, {1,2}, {in0
}, {}},
1523 { TGSI_OPCODE_ADD
, {3}, {in0
,in1
}, {}},
1524 { TGSI_OPCODE_MAD
, {out0
}, {1,2,3}, {}},
1527 run (code
, temp_lt_expect({{-1,-1}, {0,2}, {0,2}, {1,2}}));
1530 /* Check minimal lifetime for registers only written to */
1531 TEST_F(LifetimeEvaluatorExactTest
, OverwriteWrittenOnlyTemps
)
1533 const vector
<FakeCodeline
> code
= {
1534 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1535 { TGSI_OPCODE_MOV
, {2}, {in1
}, {}},
1538 run (code
, temp_lt_expect({{-1,-1}, {0,1}, {1,2}}));
1541 /* Same register is only written twice. This should not happen,
1542 * but to handle the case we want the register to life
1543 * at least past the last write instruction
1545 TEST_F(LifetimeEvaluatorExactTest
, WriteOnlyTwiceSame
)
1547 const vector
<FakeCodeline
> code
= {
1548 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1549 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1552 run (code
, temp_lt_expect({{-1,-1}, {0,2}}));
1555 /* Dead code elimination should catch and remove the case
1556 * when a variable is written after its last read, but
1557 * we want the code to be aware of this case.
1558 * The life time of this uselessly written variable is set
1559 * to the instruction after the write, because
1560 * otherwise it could be re-used too early.
1562 TEST_F(LifetimeEvaluatorExactTest
, WritePastLastRead
)
1564 const vector
<FakeCodeline
> code
= {
1565 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1566 { TGSI_OPCODE_MOV
, {2}, {1}, {}},
1567 { TGSI_OPCODE_MOV
, {1}, {2}, {}},
1571 run (code
, temp_lt_expect({{-1,-1}, {0,3}, {1,2}}));
1574 /* If a break is in the loop, all variables written after the
1575 * break and used outside the loop the variable must survive the
1578 TEST_F(LifetimeEvaluatorExactTest
, NestedLoopWithWriteAfterBreak
)
1580 const vector
<FakeCodeline
> code
= {
1581 { TGSI_OPCODE_BGNLOOP
},
1582 { TGSI_OPCODE_BGNLOOP
},
1583 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
1585 { TGSI_OPCODE_ENDIF
},
1586 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1587 { TGSI_OPCODE_ENDLOOP
},
1588 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1589 { TGSI_OPCODE_ENDLOOP
},
1592 run (code
, temp_lt_expect({{-1,-1}, {0,8}}));
1596 #define MT(X,Y,Z) std::make_tuple(X,Y,Z)
1597 /* Check lifetime estimation with a relative addressing in src.
1598 * Note, since the lifetime estimation always extends the lifetime
1599 * at to at least one instruction after the last write, for the
1600 * test the last read must be at least two instructions after the
1601 * last write to obtain a proper test.
1604 TEST_F(LifetimeEvaluatorExactTest
, ReadIndirectReladdr1
)
1606 const vector
<FakeCodeline
> code
= {
1607 { TGSI_OPCODE_MOV
, {1}, {in1
}, {}},
1608 { TGSI_OPCODE_MOV
, {2}, {in0
}, {}},
1609 { TGSI_OPCODE_MOV
, {MT(3,0,0)}, {MT(2,1,0)}, {}, RA()},
1610 { TGSI_OPCODE_MOV
, {out0
}, {3}, {}},
1613 run (code
, temp_lt_expect({{-1,-1}, {0,2}, {1,2}, {2,3}}));
1616 /* Check lifetime estimation with a relative addressing in src */
1617 TEST_F(LifetimeEvaluatorExactTest
, ReadIndirectReladdr2
)
1619 const vector
<FakeCodeline
> code
= {
1620 { TGSI_OPCODE_MOV
, {1}, {in1
}, {}},
1621 { TGSI_OPCODE_MOV
, {2}, {in0
}, {}},
1622 { TGSI_OPCODE_MOV
, {MT(3,0,0)}, {MT(4,0,1)}, {}, RA()},
1623 { TGSI_OPCODE_MOV
, {out0
}, {3}, {}},
1626 run (code
, temp_lt_expect({{-1,-1}, {0,2}, {1,2},{2,3}}));
1629 /* Check lifetime estimation with a relative addressing in src */
1630 TEST_F(LifetimeEvaluatorExactTest
, ReadIndirectTexOffsReladdr1
)
1632 const vector
<FakeCodeline
> code
= {
1633 { TGSI_OPCODE_MOV
, {1}, {in1
}, {}},
1634 { TGSI_OPCODE_MOV
, {2}, {in0
}, {}},
1635 { TGSI_OPCODE_MOV
, {MT(3,0,0)}, {MT(in2
,0,0)}, {MT(5,1,0)}, RA()},
1636 { TGSI_OPCODE_MOV
, {out0
}, {3}, {}},
1639 run (code
, temp_lt_expect({{-1,-1}, {0,2}, {1,2}, {2,3}}));
1642 /* Check lifetime estimation with a relative addressing in src */
1643 TEST_F(LifetimeEvaluatorExactTest
, ReadIndirectTexOffsReladdr2
)
1645 const vector
<FakeCodeline
> code
= {
1646 { TGSI_OPCODE_MOV
, {1}, {in1
}, {}},
1647 { TGSI_OPCODE_MOV
, {2}, {in0
}, {}},
1648 { TGSI_OPCODE_MOV
, {MT(3,0,0)}, {MT(in2
,0,0)}, {MT(2,0,1)}, RA()},
1649 { TGSI_OPCODE_MOV
, {out0
}, {3}, {}},
1652 run (code
, temp_lt_expect({{-1,-1}, {0,2}, {1,2}, {2,3}}));
1655 /* Check lifetime estimation with a relative addressing in dst */
1656 TEST_F(LifetimeEvaluatorExactTest
, WriteIndirectReladdr1
)
1658 const vector
<FakeCodeline
> code
= {
1659 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1660 { TGSI_OPCODE_MOV
, {1}, {in1
}, {}},
1661 { TGSI_OPCODE_MOV
, {MT(5,1,0)}, {MT(in1
,0,0)}, {}, RA()},
1664 run (code
, temp_lt_expect({{-1,-1}, {0,2}}));
1667 /* Check lifetime estimation with a relative addressing in dst */
1668 TEST_F(LifetimeEvaluatorExactTest
, WriteIndirectReladdr2
)
1670 const vector
<FakeCodeline
> code
= {
1671 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1672 { TGSI_OPCODE_MOV
, {2}, {in1
}, {}},
1673 { TGSI_OPCODE_MOV
, {MT(5,0,1)}, {MT(in1
,0,0)}, {}, RA()},
1674 { TGSI_OPCODE_MOV
, {out0
}, {in0
}, {}},
1675 { TGSI_OPCODE_MOV
, {out1
}, {2}, {}},
1678 run (code
, temp_lt_expect({{-1,-1}, {0,2}, {1,4}}));
1681 /* Test remapping table of registers. The tests don't assume
1682 * that the sorting algorithm used to sort the lifetimes
1683 * based on their 'begin' is stable.
1685 TEST_F(RegisterRemappingTest
, RegisterRemapping1
)
1687 vector
<lifetime
> lt({{-1,-1},
1696 vector
<int> expect({0,1,2,1,1,2,2});
1700 TEST_F(RegisterRemappingTest
, RegisterRemapping2
)
1702 vector
<lifetime
> lt({{-1,-1},
1708 vector
<int> expect({0,1,2,1,1});
1712 TEST_F(RegisterRemappingTest
, RegisterRemappingMergeAllToOne
)
1714 vector
<lifetime
> lt({{-1,-1},
1720 vector
<int> expect({0,1,1,1,1});
1724 TEST_F(RegisterRemappingTest
, RegisterRemappingIgnoreUnused
)
1726 vector
<lifetime
> lt({{-1,-1},
1733 vector
<int> expect({0,1,1,1,4,1});
1737 TEST_F(RegisterRemappingTest
, RegisterRemappingMergeZeroLifetimeRegisters
)
1739 vector
<lifetime
> lt({{-1,-1},
1746 vector
<int> expect({0,1,1,1,1,1});
1750 TEST_F(RegisterLifetimeAndRemappingTest
, LifetimeAndRemapping
)
1752 const vector
<FakeCodeline
> code
= {
1753 { TGSI_OPCODE_USEQ
, {5}, {in0
,in1
}, {}},
1754 { TGSI_OPCODE_UCMP
, {1}, {5,in1
,1}, {}},
1755 { TGSI_OPCODE_UCMP
, {1}, {5,in1
,1}, {}},
1756 { TGSI_OPCODE_UCMP
, {1}, {5,in1
,1}, {}},
1757 { TGSI_OPCODE_UCMP
, {1}, {5,in1
,1}, {}},
1758 { TGSI_OPCODE_FSLT
, {2}, {1,in1
}, {}},
1759 { TGSI_OPCODE_UIF
, {}, {2}, {}},
1760 { TGSI_OPCODE_MOV
, {3}, {in1
}, {}},
1761 { TGSI_OPCODE_ELSE
},
1762 { TGSI_OPCODE_MOV
, {4}, {in1
}, {}},
1763 { TGSI_OPCODE_MOV
, {4}, {4}, {}},
1764 { TGSI_OPCODE_MOV
, {3}, {4}, {}},
1765 { TGSI_OPCODE_ENDIF
},
1766 { TGSI_OPCODE_MOV
, {out1
}, {3}, {}},
1769 run (code
, vector
<int>({0,1,5,5,1,5}));
1772 TEST_F(RegisterLifetimeAndRemappingTest
, LifetimeAndRemappingWithUnusedReadOnlyIgnored
)
1774 const vector
<FakeCodeline
> code
= {
1775 { TGSI_OPCODE_USEQ
, {1}, {in0
,in1
}, {}},
1776 { TGSI_OPCODE_UCMP
, {2}, {1,in1
,2}, {}},
1777 { TGSI_OPCODE_UCMP
, {4}, {2,in1
,1}, {}},
1778 { TGSI_OPCODE_ADD
, {5}, {2,4}, {}},
1779 { TGSI_OPCODE_UIF
, {}, {7}, {}},
1780 { TGSI_OPCODE_ADD
, {8}, {5,4}, {}},
1781 { TGSI_OPCODE_ENDIF
},
1782 { TGSI_OPCODE_MOV
, {out1
}, {8}, {}},
1785 /* lt: 1: 0-2,2: 1-3 3: u 4: 2-5 5: 3-5 6: u 7: 0-(-1),8: 5-7 */
1786 run (code
, vector
<int>({0,1,2,3,1,2,6,7,1}));
1789 TEST_F(RegisterLifetimeAndRemappingTest
, LifetimeAndRemappingWithUnusedReadOnlyRemappedTo
)
1791 const vector
<FakeCodeline
> code
= {
1792 { TGSI_OPCODE_USEQ
, {1}, {in0
,in1
}, {}},
1793 { TGSI_OPCODE_UIF
, {}, {7}, {}},
1794 { TGSI_OPCODE_UCMP
, {2}, {1,in1
,2}, {}},
1795 { TGSI_OPCODE_UCMP
, {4}, {2,in1
,1}, {}},
1796 { TGSI_OPCODE_ADD
, {5}, {2,4}, {}},
1797 { TGSI_OPCODE_ADD
, {8}, {5,4}, {}},
1798 { TGSI_OPCODE_ENDIF
},
1799 { TGSI_OPCODE_MOV
, {out1
}, {8}, {}},
1802 /* lt: 1: 0-3,2: 2-4 3: u 4: 3-5 5: 4-5 6: u 7: 1-1,8: 5-7 */
1803 run (code
, vector
<int>({0,1,2,3,1,2,6,7,1}));
1806 TEST_F(RegisterLifetimeAndRemappingTest
, LifetimeAndRemappingWithUnusedReadOnlyRemapped
)
1808 const vector
<FakeCodeline
> code
= {
1809 { TGSI_OPCODE_USEQ
, {0}, {in0
,in1
}, {}},
1810 { TGSI_OPCODE_UCMP
, {2}, {0,in1
,2}, {}},
1811 { TGSI_OPCODE_UCMP
, {4}, {2,in1
,0}, {}},
1812 { TGSI_OPCODE_UIF
, {}, {7}, {}},
1813 { TGSI_OPCODE_ADD
, {5}, {4,4}, {}},
1814 { TGSI_OPCODE_ADD
, {8}, {5,4}, {}},
1815 { TGSI_OPCODE_ENDIF
},
1816 { TGSI_OPCODE_MOV
, {out1
}, {8}, {}},
1819 /* lt: 0: 0-2 1: u 2: 1-2 3: u 4: 2-5 5: 4-5 6: u 7:ro 8: 5-7 */
1820 run (code
, vector
<int>({0,1,2,3,0,2,6,7,0}));