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 /* Within an IF clause within a loop test that if a write occured in both
798 * branches of a nested IF/ELSE clause, followed by the last read within the
799 * enclosing IF or ELSE clause, the combined read is registered as unconditional,
800 * i.e.that it doesn't extend its live range beyond that enclosing IF or ELSE
803 TEST_F(LifetimeEvaluatorExactTest
, DeeplyNestedinLoop
)
805 const vector
<FakeCodeline
> code
= {
806 { TGSI_OPCODE_BGNLOOP
},
807 { TGSI_OPCODE_UIF
, {}, {in0
}, {}},
808 { TGSI_OPCODE_FSEQ
, {1}, {in1
,in2
}, {}},
809 { TGSI_OPCODE_UIF
, {}, {1}, {}},
810 { TGSI_OPCODE_MOV
, {2}, {in1
}, {}},
811 { TGSI_OPCODE_ELSE
},
812 { TGSI_OPCODE_MOV
, {2}, {in2
}, {}},
813 { TGSI_OPCODE_ENDIF
},
814 { TGSI_OPCODE_MOV
, {3}, {2}, {}},
815 { TGSI_OPCODE_ENDIF
},
816 { TGSI_OPCODE_ADD
, {out0
}, {3, in1
}, {}},
817 { TGSI_OPCODE_ENDLOOP
}
819 run (code
, temp_lt_expect({{-1,-1}, {2,3}, {4, 8}, {0,11}}));
822 /** Regression test for bug #104803,
823 * Read and write in if/else path outside loop and later read in conditional
824 * within a loop. The first write is to be considered the dominant write.
826 TEST_F(LifetimeEvaluatorExactTest
, IfElseWriteInBothOutsideLoopReadInElseInLoop
)
828 const vector
<FakeCodeline
> code
= {
829 { TGSI_OPCODE_IF
, {}, {in0
}, {} },
830 { TGSI_OPCODE_MOV
, {1}, {in0
}, {} },
831 { TGSI_OPCODE_ELSE
, {}, {}, {} },
832 { TGSI_OPCODE_MOV
, {1}, {in1
}, {} },
833 { TGSI_OPCODE_ENDIF
, {}, {}, {} },
834 { TGSI_OPCODE_BGNLOOP
},
835 { TGSI_OPCODE_IF
, {}, {in0
}, {} },
836 { TGSI_OPCODE_MOV
, {2}, {in1
}, {} },
837 { TGSI_OPCODE_ELSE
, {}, {}, {} },
838 { TGSI_OPCODE_MOV
, {2}, {1}, {} },
839 { TGSI_OPCODE_ENDIF
, {}, {}, {} },
840 { TGSI_OPCODE_ENDLOOP
},
841 { TGSI_OPCODE_MOV
, {out0
}, {2}, {}},
844 run (code
, temp_lt_expect({{-1,-1}, {1,11}, {7, 12}}));
847 /* A continue in the loop is not relevant */
848 TEST_F(LifetimeEvaluatorExactTest
, LoopWithWriteAfterContinue
)
850 const vector
<FakeCodeline
> code
= {
851 { TGSI_OPCODE_BGNLOOP
},
852 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
854 { TGSI_OPCODE_ENDIF
},
855 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
856 { TGSI_OPCODE_ENDLOOP
},
857 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
860 run (code
, temp_lt_expect({{-1,-1}, {4,6}}));
863 /* Temporary used to in case must live up to the case
864 * statement where it is used, the switch we only keep
865 * for the actual SWITCH opcode like it is in tgsi_exec.c, the
866 * only current use case.
868 TEST_F(LifetimeEvaluatorExactTest
, UseSwitchCase
)
870 const vector
<FakeCodeline
> code
= {
871 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
872 { TGSI_OPCODE_MOV
, {2}, {in1
}, {}},
873 { TGSI_OPCODE_MOV
, {3}, {in2
}, {}},
874 { TGSI_OPCODE_SWITCH
, {}, {3}, {}},
875 { TGSI_OPCODE_CASE
, {}, {2}, {}},
876 { TGSI_OPCODE_CASE
, {}, {1}, {}},
878 { TGSI_OPCODE_DEFAULT
},
879 { TGSI_OPCODE_ENDSWITCH
},
882 run (code
, temp_lt_expect({{-1,-1}, {0,5}, {1,4}, {2,3}}));
885 /* With two destinations, if one result is thrown away, the
886 * register must be kept past the writing instructions.
888 TEST_F(LifetimeEvaluatorExactTest
, WriteTwoOnlyUseOne
)
890 const vector
<FakeCodeline
> code
= {
891 { TGSI_OPCODE_DFRACEXP
, {1,2}, {in0
}, {}},
892 { TGSI_OPCODE_ADD
, {3}, {2,in0
}, {}},
893 { TGSI_OPCODE_MOV
, {out1
}, {3}, {}},
897 run (code
, temp_lt_expect({{-1,-1}, {0,1}, {0,1}, {1,2}}));
900 /* If a break is in the loop, all variables written after the
901 * break and used outside the loop must be maintained for the
904 TEST_F(LifetimeEvaluatorExactTest
, LoopWithWriteAfterBreak
)
906 const vector
<FakeCodeline
> code
= {
907 { TGSI_OPCODE_BGNLOOP
},
908 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
910 { TGSI_OPCODE_ENDIF
},
911 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
912 { TGSI_OPCODE_ENDLOOP
},
913 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
916 run (code
, temp_lt_expect({{-1,-1}, {0,6}}));
919 /* If a break is in the loop, all variables written after the
920 * break and used outside the loop must be maintained for the
921 * whole loop. The first break in the loop is the defining one.
923 TEST_F(LifetimeEvaluatorExactTest
, LoopWithWriteAfterBreak2Breaks
)
925 const vector
<FakeCodeline
> code
= {
926 { TGSI_OPCODE_BGNLOOP
},
927 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
929 { TGSI_OPCODE_ENDIF
},
930 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
932 { TGSI_OPCODE_ENDLOOP
},
933 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
936 run (code
, temp_lt_expect({{-1,-1}, {0,7}}));
939 /* Loop with a break at the beginning and read/write in the post
940 * break loop scope. The value written and read within the loop
941 * can be limited to [write, read], but the value read outside the
942 * loop must survive the whole loop. This is the typical code for
943 * while and for loops, where the breaking condition is tested at
946 TEST_F(LifetimeEvaluatorExactTest
, LoopWithWriteAndReadAfterBreak
)
948 const vector
<FakeCodeline
> code
= {
949 { TGSI_OPCODE_BGNLOOP
},
950 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
952 { TGSI_OPCODE_ENDIF
},
953 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
954 { TGSI_OPCODE_MOV
, {2}, {1}, {}},
955 { TGSI_OPCODE_ENDLOOP
},
956 { TGSI_OPCODE_MOV
, {out0
}, {2}, {}},
959 run (code
, temp_lt_expect({{-1,-1}, {4,5}, {0,7}}));
962 /* Same as above, just make sure that the life time of the local variable
963 * in the outer loop (3) is not accidently promoted to the whole loop.
965 TEST_F(LifetimeEvaluatorExactTest
, NestedLoopWithWriteAndReadAfterBreak
)
967 const vector
<FakeCodeline
> code
= {
968 { TGSI_OPCODE_BGNLOOP
},
969 { TGSI_OPCODE_IF
, {}, {in1
}, {}},
971 { TGSI_OPCODE_ENDIF
},
972 { TGSI_OPCODE_BGNLOOP
},
973 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
975 { TGSI_OPCODE_ENDIF
},
976 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
977 { TGSI_OPCODE_MOV
, {2}, {1}, {}},
978 { TGSI_OPCODE_ENDLOOP
},
979 { TGSI_OPCODE_ADD
, {3}, {2,in0
}, {}},
980 { TGSI_OPCODE_ADD
, {4}, {3,in2
}, {}},
981 { TGSI_OPCODE_ENDLOOP
},
982 { TGSI_OPCODE_MOV
, {out0
}, {4}, {}},
985 run (code
, temp_lt_expect({{-1,-1}, {8,9}, {0,13}, {11,12}, {0,14}}));
988 /* If a break is in the loop inside a switch case, make sure it is
989 * interpreted as breaking that inner loop, i.e. the variable has to
992 TEST_F(LifetimeEvaluatorExactTest
, LoopWithWriteAfterBreakInSwitchInLoop
)
994 const vector
<FakeCodeline
> code
= {
995 { TGSI_OPCODE_SWITCH
, {}, {in1
}, {}},
996 { TGSI_OPCODE_CASE
, {}, {in1
}, {}},
997 { TGSI_OPCODE_BGNLOOP
},
998 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
1000 { TGSI_OPCODE_ENDIF
},
1001 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1002 { TGSI_OPCODE_ENDLOOP
},
1003 { TGSI_OPCODE_DEFAULT
, {}, {}, {}},
1004 { TGSI_OPCODE_ENDSWITCH
, {}, {}, {}},
1005 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1008 run (code
, temp_lt_expect({{-1,-1}, {2,10}}));
1011 /* Value written conditionally in one loop and read in another loop,
1012 * and both of these loops are within yet another loop. Here the value
1013 * has to survive the outer loop.
1015 TEST_F(LifetimeEvaluatorExactTest
, LoopsWithDifferntScopesConditionalWrite
)
1017 const vector
<FakeCodeline
> code
= {
1018 { TGSI_OPCODE_BGNLOOP
},
1019 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
1020 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1021 { TGSI_OPCODE_ENDIF
},
1022 { TGSI_OPCODE_ENDLOOP
},
1023 { TGSI_OPCODE_BGNLOOP
},
1024 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1025 { TGSI_OPCODE_ENDLOOP
},
1028 run (code
, temp_lt_expect({{-1,-1}, {0,7}}));
1031 /* Value written and read in one loop and last read in another loop,
1032 * Here the value has to survive both loops.
1034 TEST_F(LifetimeEvaluatorExactTest
, LoopsWithDifferntScopesFirstReadBeforeWrite
)
1036 const vector
<FakeCodeline
> code
= {
1037 { TGSI_OPCODE_BGNLOOP
},
1038 { TGSI_OPCODE_MUL
, {1}, {1,in0
}, {}},
1039 { TGSI_OPCODE_ENDLOOP
},
1040 { TGSI_OPCODE_BGNLOOP
},
1041 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1042 { TGSI_OPCODE_ENDLOOP
},
1045 run (code
, temp_lt_expect({{-1,-1}, {0,5}}));
1049 /* Value is written in one switch code path within a loop
1050 * must survive the full loop.
1052 TEST_F(LifetimeEvaluatorExactTest
, LoopWithWriteInSwitch
)
1054 const vector
<FakeCodeline
> code
= {
1055 { TGSI_OPCODE_BGNLOOP
},
1056 { TGSI_OPCODE_SWITCH
, {}, {in0
}, {} },
1057 { TGSI_OPCODE_CASE
, {}, {in0
}, {} },
1058 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1059 { TGSI_OPCODE_BRK
},
1060 { TGSI_OPCODE_DEFAULT
},
1061 { TGSI_OPCODE_BRK
},
1062 { TGSI_OPCODE_ENDSWITCH
},
1063 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1064 { TGSI_OPCODE_ENDLOOP
},
1067 run (code
, temp_lt_expect({{-1,-1}, {0,9}}));
1070 /* Value written in one case, and read in other,in loop
1071 * - must survive the loop.
1073 TEST_F(LifetimeEvaluatorExactTest
, LoopWithReadWriteInSwitchDifferentCase
)
1075 const vector
<FakeCodeline
> code
= {
1076 { TGSI_OPCODE_BGNLOOP
},
1077 { TGSI_OPCODE_SWITCH
, {}, {in0
}, {} },
1078 { TGSI_OPCODE_CASE
, {}, {in0
}, {} },
1079 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1080 { TGSI_OPCODE_BRK
},
1081 { TGSI_OPCODE_DEFAULT
},
1082 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1083 { TGSI_OPCODE_BRK
},
1084 { TGSI_OPCODE_ENDSWITCH
},
1085 { TGSI_OPCODE_ENDLOOP
},
1088 run (code
, temp_lt_expect({{-1,-1}, {0,9}}));
1091 /* Value written in one case, and read in other,in loop
1092 * - must survive the loop, even if the write case falls through.
1094 TEST_F(LifetimeEvaluatorExactTest
, LoopWithReadWriteInSwitchDifferentCaseFallThrough
)
1096 const vector
<FakeCodeline
> code
= {
1097 { TGSI_OPCODE_BGNLOOP
},
1098 { TGSI_OPCODE_SWITCH
, {}, {in0
}, {} },
1099 { TGSI_OPCODE_CASE
, {}, {in0
}, {} },
1100 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1101 { TGSI_OPCODE_DEFAULT
},
1102 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1103 { TGSI_OPCODE_BRK
},
1104 { TGSI_OPCODE_ENDSWITCH
},
1105 { TGSI_OPCODE_ENDLOOP
},
1108 run (code
, temp_lt_expect({{-1,-1}, {0,8}}));
1111 /* Here we read and write from an to the same temp in the same instruction,
1112 * but the read is conditional (select operation), hence the lifetime must
1113 * start with the first write.
1115 TEST_F(LifetimeEvaluatorExactTest
, WriteSelectFromSelf
)
1117 const vector
<FakeCodeline
> code
= {
1118 { TGSI_OPCODE_USEQ
, {5}, {in0
,in1
}, {}},
1119 { TGSI_OPCODE_UCMP
, {1}, {5,in1
,1}, {}},
1120 { TGSI_OPCODE_UCMP
, {1}, {5,in1
,1}, {}},
1121 { TGSI_OPCODE_UCMP
, {1}, {5,in1
,1}, {}},
1122 { TGSI_OPCODE_UCMP
, {1}, {5,in1
,1}, {}},
1123 { TGSI_OPCODE_FSLT
, {2}, {1,in1
}, {}},
1124 { TGSI_OPCODE_UIF
, {}, {2}, {}},
1125 { TGSI_OPCODE_MOV
, {3}, {in1
}, {}},
1126 { TGSI_OPCODE_ELSE
},
1127 { TGSI_OPCODE_MOV
, {4}, {in1
}, {}},
1128 { TGSI_OPCODE_MOV
, {4}, {4}, {}},
1129 { TGSI_OPCODE_MOV
, {3}, {4}, {}},
1130 { TGSI_OPCODE_ENDIF
},
1131 { TGSI_OPCODE_MOV
, {out1
}, {3}, {}},
1134 run (code
, temp_lt_expect({{-1,-1}, {1,5}, {5,6}, {7,13}, {9,11}, {0,4}}));
1137 /* This test checks wheter the ENDSWITCH is handled properly if the
1138 * last switch case/default doesn't stop with a BRK.
1140 TEST_F(LifetimeEvaluatorExactTest
, LoopRWInSwitchCaseLastCaseWithoutBreak
)
1142 const vector
<FakeCodeline
> code
= {
1143 { TGSI_OPCODE_BGNLOOP
},
1144 { TGSI_OPCODE_SWITCH
, {}, {in0
}, {} },
1145 { TGSI_OPCODE_CASE
, {}, {in0
}, {} },
1146 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1147 { TGSI_OPCODE_BRK
},
1148 { TGSI_OPCODE_DEFAULT
},
1149 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1150 { TGSI_OPCODE_ENDSWITCH
},
1151 { TGSI_OPCODE_ENDLOOP
},
1154 run (code
, temp_lt_expect({{-1,-1}, {0,8}}));
1157 /* Value read/write in same case, stays there */
1158 TEST_F(LifetimeEvaluatorExactTest
, LoopWithReadWriteInSwitchSameCase
)
1160 const vector
<FakeCodeline
> code
= {
1161 { TGSI_OPCODE_BGNLOOP
},
1162 { TGSI_OPCODE_SWITCH
, {}, {in0
}, {} },
1163 { TGSI_OPCODE_CASE
, {}, {in0
}, {} },
1164 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1165 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1166 { TGSI_OPCODE_BRK
},
1167 { TGSI_OPCODE_DEFAULT
},
1168 { TGSI_OPCODE_BRK
},
1169 { TGSI_OPCODE_ENDSWITCH
},
1170 { TGSI_OPCODE_ENDLOOP
},
1173 run (code
, temp_lt_expect({{-1,-1}, {3,4}}));
1176 /* Value read/write in all cases, should only live from first
1177 * write to last read, but currently the whole loop is used.
1179 TEST_F(LifetimeEvaluatorAtLeastTest
, LoopWithReadWriteInSwitchSameCase
)
1181 const vector
<FakeCodeline
> code
= {
1182 { TGSI_OPCODE_BGNLOOP
},
1183 { TGSI_OPCODE_SWITCH
, {}, {in0
}, {}},
1184 { TGSI_OPCODE_CASE
, {}, {in0
}, {} },
1185 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1186 { TGSI_OPCODE_BRK
},
1187 { TGSI_OPCODE_DEFAULT
},
1188 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1189 { TGSI_OPCODE_BRK
},
1190 { TGSI_OPCODE_ENDSWITCH
},
1191 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1192 { TGSI_OPCODE_ENDLOOP
},
1195 run (code
, temp_lt_expect({{-1,-1}, {3,9}}));
1198 /* First read before first write with nested loops */
1199 TEST_F(LifetimeEvaluatorExactTest
, LoopsWithDifferentScopesCondReadBeforeWrite
)
1201 const vector
<FakeCodeline
> code
= {
1202 { TGSI_OPCODE_BGNLOOP
},
1203 { TGSI_OPCODE_BGNLOOP
},
1204 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
1205 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1206 { TGSI_OPCODE_ENDIF
},
1207 { TGSI_OPCODE_ENDLOOP
},
1208 { TGSI_OPCODE_BGNLOOP
},
1209 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1210 { TGSI_OPCODE_ENDLOOP
},
1211 { TGSI_OPCODE_ENDLOOP
},
1214 run (code
, temp_lt_expect({{-1,-1}, {0,9}}));
1217 /* First read before first write wiredness with nested loops.
1218 * Here the first read of 2 is logically before the first, dominant
1219 * write, therfore, the 2 has to survive both loops.
1221 TEST_F(LifetimeEvaluatorExactTest
, FirstWriteAtferReadInNestedLoop
)
1223 const vector
<FakeCodeline
> code
= {
1224 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1225 { TGSI_OPCODE_BGNLOOP
},
1226 { TGSI_OPCODE_BGNLOOP
},
1227 { TGSI_OPCODE_MUL
, {2}, {2,1}, {}},
1228 { TGSI_OPCODE_MOV
, {3}, {2}, {}},
1229 { TGSI_OPCODE_ENDLOOP
},
1230 { TGSI_OPCODE_ADD
, {1}, {1,in1
}, {}},
1231 { TGSI_OPCODE_ENDLOOP
},
1232 { TGSI_OPCODE_MOV
, {out0
}, {3}, {}},
1235 run (code
, temp_lt_expect({{-1,-1}, {0,7}, {1,7}, {4,8}}));
1239 #define DST(X, W) vector<pair<int,int>>(1, make_pair(X, W))
1240 #define SRC(X, S) vector<pair<int, const char *>>(1, make_pair(X, S))
1241 #define SRC2(X, S, Y, T) vector<pair<int, const char *>>({make_pair(X, S), make_pair(Y, T)})
1243 /* Partial write to components: one component was written unconditionally
1244 * but another conditionally, temporary must survive the whole loop.
1245 * Test series for all components.
1247 TEST_F(LifetimeEvaluatorExactTest
, LoopWithConditionalComponentWrite_X
)
1249 const vector
<FakeCodeline
> code
= {
1250 { TGSI_OPCODE_BGNLOOP
},
1251 { TGSI_OPCODE_MOV
, DST(1, WRITEMASK_Y
), SRC(in1
, "x"), {}, SWZ()},
1252 { TGSI_OPCODE_IF
, {}, SRC(in0
, "xxxx"), {}, SWZ()},
1253 { TGSI_OPCODE_MOV
, DST(1, WRITEMASK_X
), SRC(in1
, "y"), {}, SWZ()},
1254 { TGSI_OPCODE_ENDIF
},
1255 { TGSI_OPCODE_MOV
, DST(2, WRITEMASK_XY
), SRC(1, "xy"), {}, SWZ()},
1256 { TGSI_OPCODE_ENDLOOP
},
1257 { TGSI_OPCODE_MOV
, DST(out0
, WRITEMASK_XYZW
), SRC(2, "xyxy"), {}, SWZ()},
1260 run (code
, temp_lt_expect({{-1,-1}, {0,6}, {5,7}}));
1263 TEST_F(LifetimeEvaluatorExactTest
, LoopWithConditionalComponentWrite_Y
)
1265 const vector
<FakeCodeline
> code
= {
1266 { TGSI_OPCODE_BGNLOOP
},
1267 { TGSI_OPCODE_MOV
, DST(1, WRITEMASK_X
), SRC(in1
, "x"), {}, SWZ()},
1268 { TGSI_OPCODE_IF
, {}, SRC(in0
, "xxxx"), {}, SWZ()},
1269 { TGSI_OPCODE_MOV
, DST(1, WRITEMASK_Y
), SRC(in1
, "y"), {}, SWZ()},
1270 { TGSI_OPCODE_ENDIF
},
1271 { TGSI_OPCODE_MOV
, DST(2, WRITEMASK_XY
), SRC(1, "xy"), {}, SWZ()},
1272 { TGSI_OPCODE_ENDLOOP
},
1273 { TGSI_OPCODE_MOV
, DST(out0
, WRITEMASK_XYZW
), SRC(2, "xyxy"), {}, SWZ()},
1276 run (code
, temp_lt_expect({{-1,-1}, {0,6}, {5,7}}));
1279 TEST_F(LifetimeEvaluatorExactTest
, LoopWithConditionalComponentWrite_Z
)
1281 const vector
<FakeCodeline
> code
= {
1282 { TGSI_OPCODE_BGNLOOP
},
1283 { TGSI_OPCODE_MOV
, DST(1, WRITEMASK_X
), SRC(in1
, "x"), {}, SWZ()},
1284 { TGSI_OPCODE_IF
, {}, SRC(in0
, "xxxx"), {}, SWZ()},
1285 { TGSI_OPCODE_MOV
, DST(1, WRITEMASK_Z
), SRC(in1
, "y"), {}, SWZ()},
1286 { TGSI_OPCODE_ENDIF
},
1287 { TGSI_OPCODE_MOV
, DST(2, WRITEMASK_XY
), SRC(1, "xz"), {}, SWZ()},
1288 { TGSI_OPCODE_ENDLOOP
},
1289 { TGSI_OPCODE_MOV
, DST(out0
, WRITEMASK_XYZW
), SRC(2, "xyxy"), {}, SWZ()},
1292 run (code
, temp_lt_expect({{-1,-1}, {0,6}, {5,7}}));
1295 TEST_F(LifetimeEvaluatorExactTest
, LoopWithConditionalComponentWrite_W
)
1297 const vector
<FakeCodeline
> code
= {
1298 { TGSI_OPCODE_BGNLOOP
},
1299 { TGSI_OPCODE_MOV
, DST(1, WRITEMASK_X
), SRC(in1
, "x"), {}, SWZ()},
1300 { TGSI_OPCODE_IF
, {}, SRC(in0
, "xxxx"), {}, SWZ()},
1301 { TGSI_OPCODE_MOV
, DST(1, WRITEMASK_W
), SRC(in1
, "y"), {}, SWZ()},
1302 { TGSI_OPCODE_ENDIF
},
1303 { TGSI_OPCODE_MOV
, DST(2, WRITEMASK_XY
), SRC(1, "xw"), {}, SWZ()},
1304 { TGSI_OPCODE_ENDLOOP
},
1305 { TGSI_OPCODE_MOV
, DST(out0
, WRITEMASK_XYZW
), SRC(2, "xyxy"), {}, SWZ()},
1308 run (code
, temp_lt_expect({{-1,-1}, {0,6}, {5,7}}));
1311 TEST_F(LifetimeEvaluatorExactTest
, LoopWithConditionalComponentWrite_X_Read_Y_Before
)
1313 const vector
<FakeCodeline
> code
= {
1314 { TGSI_OPCODE_BGNLOOP
},
1315 { TGSI_OPCODE_MOV
, DST(1, WRITEMASK_X
), SRC(in1
, "x"), {}, SWZ()},
1316 { TGSI_OPCODE_IF
, {}, SRC(in0
, "xxxx"), {}, SWZ()},
1317 { TGSI_OPCODE_MOV
, DST(2, WRITEMASK_XYZW
), SRC(1, "yyyy"), {}, SWZ()},
1318 { TGSI_OPCODE_ENDIF
},
1319 { TGSI_OPCODE_MOV
, DST(1, WRITEMASK_YZW
), SRC(2, "yyzw"), {}, SWZ()},
1320 { TGSI_OPCODE_ENDLOOP
},
1321 { TGSI_OPCODE_ADD
, DST(out0
, WRITEMASK_XYZW
),
1322 SRC2(2, "yyzw", 1, "xyxy"), {}, SWZ()},
1325 run (code
, temp_lt_expect({{-1,-1}, {0,7}, {0,7}}));
1328 /* The variable is conditionally read before first written, so
1329 * it has to surive all the loops.
1331 TEST_F(LifetimeEvaluatorExactTest
, FRaWSameInstructionInLoopAndCondition
)
1333 const vector
<FakeCodeline
> code
= {
1334 { TGSI_OPCODE_BGNLOOP
},
1335 { TGSI_OPCODE_BGNLOOP
},
1336 { TGSI_OPCODE_IF
, {}, {in0
}, {} },
1337 { TGSI_OPCODE_ADD
, {1}, {1,in0
}, {}},
1338 { TGSI_OPCODE_ENDIF
},
1339 { TGSI_OPCODE_MOV
, {1}, {in1
}, {}},
1340 { TGSI_OPCODE_ENDLOOP
},
1341 { TGSI_OPCODE_ENDLOOP
},
1345 run (code
, temp_lt_expect({{-1,-1}, {0,7}}));
1348 /* If unconditionally first written and read in the same
1349 * instruction, then the register must be kept for the
1350 * one write, but not more (undefined behaviour)
1352 TEST_F(LifetimeEvaluatorExactTest
, FRaWSameInstruction
)
1354 const vector
<FakeCodeline
> code
= {
1355 { TGSI_OPCODE_ADD
, {1}, {1,in0
}, {}},
1359 run (code
, temp_lt_expect({{-1,-1}, {0,1}}));
1362 /* If unconditionally written and read in the same
1363 * instruction, various times then the register must be
1364 * kept past the last write, but not longer (undefined behaviour)
1366 TEST_F(LifetimeEvaluatorExactTest
, FRaWSameInstructionMoreThenOnce
)
1368 const vector
<FakeCodeline
> code
= {
1369 { TGSI_OPCODE_ADD
, {1}, {1,in0
}, {}},
1370 { TGSI_OPCODE_ADD
, {1}, {1,in0
}, {}},
1371 { TGSI_OPCODE_MOV
, {out0
}, {in0
}, {}},
1375 run (code
, temp_lt_expect({{-1,-1}, {0,2}}));
1378 /* Register is only written. This should not happen,
1379 * but to handle the case we want the register to life
1380 * at least one instruction
1382 TEST_F(LifetimeEvaluatorExactTest
, WriteOnly
)
1384 const vector
<FakeCodeline
> code
= {
1385 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1388 run (code
, temp_lt_expect({{-1,-1}, {0,1}}));
1391 /* Register is read in IF.
1393 TEST_F(LifetimeEvaluatorExactTest
, SimpleReadForIf
)
1395 const vector
<FakeCodeline
> code
= {
1396 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1397 { TGSI_OPCODE_ADD
, {out0
}, {in0
,in1
}, {}},
1398 { TGSI_OPCODE_IF
, {}, {1}, {}},
1399 { TGSI_OPCODE_ENDIF
}
1401 run (code
, temp_lt_expect({{-1,-1}, {0,2}}));
1404 TEST_F(LifetimeEvaluatorExactTest
, WriteTwoReadOne
)
1406 const vector
<FakeCodeline
> code
= {
1407 { TGSI_OPCODE_DFRACEXP
, {1,2}, {in0
}, {}},
1408 { TGSI_OPCODE_ADD
, {3}, {2,in0
}, {}},
1409 { TGSI_OPCODE_MOV
, {out1
}, {3}, {}},
1412 run (code
, temp_lt_expect({{-1,-1}, {0,1}, {0,1}, {1,2}}));
1415 TEST_F(LifetimeEvaluatorExactTest
, ReadOnly
)
1417 const vector
<FakeCodeline
> code
= {
1418 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1421 run (code
, temp_lt_expect({{-1,-1}, {-1,-1}}));
1424 /* Test handling of missing END marker
1426 TEST_F(LifetimeEvaluatorExactTest
, SomeScopesAndNoEndProgramId
)
1428 const vector
<FakeCodeline
> code
= {
1429 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1430 { TGSI_OPCODE_IF
, {}, {1}, {}},
1431 { TGSI_OPCODE_MOV
, {2}, {1}, {}},
1432 { TGSI_OPCODE_ENDIF
},
1433 { TGSI_OPCODE_IF
, {}, {1}, {}},
1434 { TGSI_OPCODE_MOV
, {out0
}, {2}, {}},
1435 { TGSI_OPCODE_ENDIF
},
1437 run (code
, temp_lt_expect({{-1,-1}, {0,4}, {2,5}}));
1440 TEST_F(LifetimeEvaluatorExactTest
, SerialReadWrite
)
1442 const vector
<FakeCodeline
> code
= {
1443 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1444 { TGSI_OPCODE_MOV
, {2}, {1}, {}},
1445 { TGSI_OPCODE_MOV
, {3}, {2}, {}},
1446 { TGSI_OPCODE_MOV
, {out0
}, {3}, {}},
1449 run (code
, temp_lt_expect({{-1,-1}, {0,1}, {1,2}, {2,3}}));
1452 /* Check that two destination registers are used */
1453 TEST_F(LifetimeEvaluatorExactTest
, TwoDestRegisters
)
1455 const vector
<FakeCodeline
> code
= {
1456 { TGSI_OPCODE_DFRACEXP
, {1,2}, {in0
}, {}},
1457 { TGSI_OPCODE_ADD
, {out0
}, {1,2}, {}},
1460 run (code
, temp_lt_expect({{-1,-1}, {0,1}, {0,1}}));
1463 /* Check that writing within a loop in a conditional is propagated
1464 * to the outer loop.
1466 TEST_F(LifetimeEvaluatorExactTest
, WriteInLoopInConditionalReadOutside
)
1468 const vector
<FakeCodeline
> code
= {
1469 { TGSI_OPCODE_BGNLOOP
},
1470 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
1471 { TGSI_OPCODE_BGNLOOP
},
1472 { TGSI_OPCODE_MOV
, {1}, {in1
}, {}},
1473 { TGSI_OPCODE_ENDLOOP
},
1474 { TGSI_OPCODE_ENDIF
},
1475 { TGSI_OPCODE_ADD
, {2}, {1,in1
}, {}},
1476 { TGSI_OPCODE_ENDLOOP
},
1477 { TGSI_OPCODE_MOV
, {out0
}, {2}, {}},
1480 run (code
, temp_lt_expect({{-1,-1}, {0,7}, {6,8}}));
1483 /* Check that a register written in a loop that is inside a conditional
1484 * is not propagated past that loop if last read is also within the
1487 TEST_F(LifetimeEvaluatorExactTest
, WriteInLoopInCondReadInCondOutsideLoop
)
1489 const vector
<FakeCodeline
> code
= {
1490 { TGSI_OPCODE_BGNLOOP
},
1491 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
1492 { TGSI_OPCODE_BGNLOOP
},
1493 { TGSI_OPCODE_MUL
, {1}, {in2
,in1
}, {}},
1494 { TGSI_OPCODE_ENDLOOP
},
1495 { TGSI_OPCODE_ADD
, {2}, {1,in1
}, {}},
1496 { TGSI_OPCODE_ENDIF
},
1497 { TGSI_OPCODE_ENDLOOP
},
1498 { TGSI_OPCODE_MOV
, {out0
}, {2}, {}},
1501 run (code
, temp_lt_expect({{-1,-1}, {3,5}, {0,8}}));
1504 /* Check that a register read before written in a loop that is
1505 * inside a conditional is propagated to the outer loop.
1507 TEST_F(LifetimeEvaluatorExactTest
, ReadWriteInLoopInCondReadInCondOutsideLoop
)
1509 const vector
<FakeCodeline
> code
= {
1510 { TGSI_OPCODE_BGNLOOP
},
1511 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
1512 { TGSI_OPCODE_BGNLOOP
},
1513 { TGSI_OPCODE_MUL
, {1}, {1,in1
}, {}},
1514 { TGSI_OPCODE_ENDLOOP
},
1515 { TGSI_OPCODE_ADD
, {2}, {1,in1
}, {}},
1516 { TGSI_OPCODE_ENDIF
},
1517 { TGSI_OPCODE_ENDLOOP
},
1518 { TGSI_OPCODE_MOV
, {out0
}, {2}, {}},
1521 run (code
, temp_lt_expect({{-1,-1}, {0,7}, {0,8}}));
1524 /* With two destinations if one value is thrown away, we must
1525 * ensure that the two output registers don't merge. In this test
1526 * case the last access for 2 and 3 is in line 4, but 4 can only
1527 * be merged with 3 because it is read,2 on the other hand is written
1528 * to, and merging it with 4 would result in a bug.
1530 TEST_F(LifetimeEvaluatorExactTest
, WritePastLastRead2
)
1532 const vector
<FakeCodeline
> code
= {
1533 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1534 { TGSI_OPCODE_MOV
, {2}, {in0
}, {}},
1535 { TGSI_OPCODE_ADD
, {3}, {1,2}, {}},
1536 { TGSI_OPCODE_DFRACEXP
, {2,4}, {3}, {}},
1537 { TGSI_OPCODE_MOV
, {out1
}, {4}, {}},
1540 run (code
, temp_lt_expect({{-1,-1}, {0,2}, {1,4}, {2,3}, {3,4}}));
1543 /* Check that three source registers are used */
1544 TEST_F(LifetimeEvaluatorExactTest
, ThreeSourceRegisters
)
1546 const vector
<FakeCodeline
> code
= {
1547 { TGSI_OPCODE_DFRACEXP
, {1,2}, {in0
}, {}},
1548 { TGSI_OPCODE_ADD
, {3}, {in0
,in1
}, {}},
1549 { TGSI_OPCODE_MAD
, {out0
}, {1,2,3}, {}},
1552 run (code
, temp_lt_expect({{-1,-1}, {0,2}, {0,2}, {1,2}}));
1555 /* Check minimal lifetime for registers only written to */
1556 TEST_F(LifetimeEvaluatorExactTest
, OverwriteWrittenOnlyTemps
)
1558 const vector
<FakeCodeline
> code
= {
1559 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1560 { TGSI_OPCODE_MOV
, {2}, {in1
}, {}},
1563 run (code
, temp_lt_expect({{-1,-1}, {0,1}, {1,2}}));
1566 /* Same register is only written twice. This should not happen,
1567 * but to handle the case we want the register to life
1568 * at least past the last write instruction
1570 TEST_F(LifetimeEvaluatorExactTest
, WriteOnlyTwiceSame
)
1572 const vector
<FakeCodeline
> code
= {
1573 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1574 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1577 run (code
, temp_lt_expect({{-1,-1}, {0,2}}));
1580 /* Dead code elimination should catch and remove the case
1581 * when a variable is written after its last read, but
1582 * we want the code to be aware of this case.
1583 * The life time of this uselessly written variable is set
1584 * to the instruction after the write, because
1585 * otherwise it could be re-used too early.
1587 TEST_F(LifetimeEvaluatorExactTest
, WritePastLastRead
)
1589 const vector
<FakeCodeline
> code
= {
1590 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1591 { TGSI_OPCODE_MOV
, {2}, {1}, {}},
1592 { TGSI_OPCODE_MOV
, {1}, {2}, {}},
1596 run (code
, temp_lt_expect({{-1,-1}, {0,3}, {1,2}}));
1599 /* If a break is in the loop, all variables written after the
1600 * break and used outside the loop the variable must survive the
1603 TEST_F(LifetimeEvaluatorExactTest
, NestedLoopWithWriteAfterBreak
)
1605 const vector
<FakeCodeline
> code
= {
1606 { TGSI_OPCODE_BGNLOOP
},
1607 { TGSI_OPCODE_BGNLOOP
},
1608 { TGSI_OPCODE_IF
, {}, {in0
}, {}},
1610 { TGSI_OPCODE_ENDIF
},
1611 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1612 { TGSI_OPCODE_ENDLOOP
},
1613 { TGSI_OPCODE_MOV
, {out0
}, {1}, {}},
1614 { TGSI_OPCODE_ENDLOOP
},
1617 run (code
, temp_lt_expect({{-1,-1}, {0,8}}));
1621 #define MT(X,Y,Z) std::make_tuple(X,Y,Z)
1622 /* Check lifetime estimation with a relative addressing in src.
1623 * Note, since the lifetime estimation always extends the lifetime
1624 * at to at least one instruction after the last write, for the
1625 * test the last read must be at least two instructions after the
1626 * last write to obtain a proper test.
1629 TEST_F(LifetimeEvaluatorExactTest
, ReadIndirectReladdr1
)
1631 const vector
<FakeCodeline
> code
= {
1632 { TGSI_OPCODE_MOV
, {1}, {in1
}, {}},
1633 { TGSI_OPCODE_MOV
, {2}, {in0
}, {}},
1634 { TGSI_OPCODE_MOV
, {MT(3,0,0)}, {MT(2,1,0)}, {}, RA()},
1635 { TGSI_OPCODE_MOV
, {out0
}, {3}, {}},
1638 run (code
, temp_lt_expect({{-1,-1}, {0,2}, {1,2}, {2,3}}));
1641 /* Check lifetime estimation with a relative addressing in src */
1642 TEST_F(LifetimeEvaluatorExactTest
, ReadIndirectReladdr2
)
1644 const vector
<FakeCodeline
> code
= {
1645 { TGSI_OPCODE_MOV
, {1}, {in1
}, {}},
1646 { TGSI_OPCODE_MOV
, {2}, {in0
}, {}},
1647 { TGSI_OPCODE_MOV
, {MT(3,0,0)}, {MT(4,0,1)}, {}, RA()},
1648 { TGSI_OPCODE_MOV
, {out0
}, {3}, {}},
1651 run (code
, temp_lt_expect({{-1,-1}, {0,2}, {1,2},{2,3}}));
1654 /* Check lifetime estimation with a relative addressing in src */
1655 TEST_F(LifetimeEvaluatorExactTest
, ReadIndirectTexOffsReladdr1
)
1657 const vector
<FakeCodeline
> code
= {
1658 { TGSI_OPCODE_MOV
, {1}, {in1
}, {}},
1659 { TGSI_OPCODE_MOV
, {2}, {in0
}, {}},
1660 { TGSI_OPCODE_MOV
, {MT(3,0,0)}, {MT(in2
,0,0)}, {MT(5,1,0)}, RA()},
1661 { TGSI_OPCODE_MOV
, {out0
}, {3}, {}},
1664 run (code
, temp_lt_expect({{-1,-1}, {0,2}, {1,2}, {2,3}}));
1667 /* Check lifetime estimation with a relative addressing in src */
1668 TEST_F(LifetimeEvaluatorExactTest
, ReadIndirectTexOffsReladdr2
)
1670 const vector
<FakeCodeline
> code
= {
1671 { TGSI_OPCODE_MOV
, {1}, {in1
}, {}},
1672 { TGSI_OPCODE_MOV
, {2}, {in0
}, {}},
1673 { TGSI_OPCODE_MOV
, {MT(3,0,0)}, {MT(in2
,0,0)}, {MT(2,0,1)}, RA()},
1674 { TGSI_OPCODE_MOV
, {out0
}, {3}, {}},
1677 run (code
, temp_lt_expect({{-1,-1}, {0,2}, {1,2}, {2,3}}));
1680 /* Check lifetime estimation with a relative addressing in dst */
1681 TEST_F(LifetimeEvaluatorExactTest
, WriteIndirectReladdr1
)
1683 const vector
<FakeCodeline
> code
= {
1684 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1685 { TGSI_OPCODE_MOV
, {1}, {in1
}, {}},
1686 { TGSI_OPCODE_MOV
, {MT(5,1,0)}, {MT(in1
,0,0)}, {}, RA()},
1689 run (code
, temp_lt_expect({{-1,-1}, {0,2}}));
1692 /* Check lifetime estimation with a relative addressing in dst */
1693 TEST_F(LifetimeEvaluatorExactTest
, WriteIndirectReladdr2
)
1695 const vector
<FakeCodeline
> code
= {
1696 { TGSI_OPCODE_MOV
, {1}, {in0
}, {}},
1697 { TGSI_OPCODE_MOV
, {2}, {in1
}, {}},
1698 { TGSI_OPCODE_MOV
, {MT(5,0,1)}, {MT(in1
,0,0)}, {}, RA()},
1699 { TGSI_OPCODE_MOV
, {out0
}, {in0
}, {}},
1700 { TGSI_OPCODE_MOV
, {out1
}, {2}, {}},
1703 run (code
, temp_lt_expect({{-1,-1}, {0,2}, {1,4}}));
1706 /* Test remapping table of registers. The tests don't assume
1707 * that the sorting algorithm used to sort the lifetimes
1708 * based on their 'begin' is stable.
1710 TEST_F(RegisterRemappingTest
, RegisterRemapping1
)
1712 vector
<register_live_range
> lt({{-1,-1},
1721 vector
<int> expect({0,1,2,1,1,2,2});
1725 TEST_F(RegisterRemappingTest
, RegisterRemapping2
)
1727 vector
<register_live_range
> lt({{-1,-1},
1733 vector
<int> expect({0,1,2,1,1});
1737 TEST_F(RegisterRemappingTest
, RegisterRemappingMergeAllToOne
)
1739 vector
<register_live_range
> lt({{-1,-1},
1745 vector
<int> expect({0,1,1,1,1});
1749 TEST_F(RegisterRemappingTest
, RegisterRemappingIgnoreUnused
)
1751 vector
<register_live_range
> lt({{-1,-1},
1758 vector
<int> expect({0,1,1,1,4,1});
1762 TEST_F(RegisterRemappingTest
, RegisterRemappingMergeZeroLifetimeRegisters
)
1764 vector
<register_live_range
> lt({{-1,-1},
1771 vector
<int> expect({0,1,1,1,1,1});
1775 TEST_F(RegisterLifetimeAndRemappingTest
, LifetimeAndRemapping
)
1777 const vector
<FakeCodeline
> code
= {
1778 { TGSI_OPCODE_USEQ
, {5}, {in0
,in1
}, {}},
1779 { TGSI_OPCODE_UCMP
, {1}, {5,in1
,1}, {}},
1780 { TGSI_OPCODE_UCMP
, {1}, {5,in1
,1}, {}},
1781 { TGSI_OPCODE_UCMP
, {1}, {5,in1
,1}, {}},
1782 { TGSI_OPCODE_UCMP
, {1}, {5,in1
,1}, {}},
1783 { TGSI_OPCODE_FSLT
, {2}, {1,in1
}, {}},
1784 { TGSI_OPCODE_UIF
, {}, {2}, {}},
1785 { TGSI_OPCODE_MOV
, {3}, {in1
}, {}},
1786 { TGSI_OPCODE_ELSE
},
1787 { TGSI_OPCODE_MOV
, {4}, {in1
}, {}},
1788 { TGSI_OPCODE_MOV
, {4}, {4}, {}},
1789 { TGSI_OPCODE_MOV
, {3}, {4}, {}},
1790 { TGSI_OPCODE_ENDIF
},
1791 { TGSI_OPCODE_MOV
, {out1
}, {3}, {}},
1794 run (code
, vector
<int>({0,1,5,5,1,5}));
1797 TEST_F(RegisterLifetimeAndRemappingTest
, LifetimeAndRemappingWithUnusedReadOnlyIgnored
)
1799 const vector
<FakeCodeline
> code
= {
1800 { TGSI_OPCODE_USEQ
, {1}, {in0
,in1
}, {}},
1801 { TGSI_OPCODE_UCMP
, {2}, {1,in1
,2}, {}},
1802 { TGSI_OPCODE_UCMP
, {4}, {2,in1
,1}, {}},
1803 { TGSI_OPCODE_ADD
, {5}, {2,4}, {}},
1804 { TGSI_OPCODE_UIF
, {}, {7}, {}},
1805 { TGSI_OPCODE_ADD
, {8}, {5,4}, {}},
1806 { TGSI_OPCODE_ENDIF
},
1807 { TGSI_OPCODE_MOV
, {out1
}, {8}, {}},
1810 /* lt: 1: 0-2,2: 1-3 3: u 4: 2-5 5: 3-5 6: u 7: 0-(-1),8: 5-7 */
1811 run (code
, vector
<int>({0,1,2,3,1,2,6,7,1}));
1814 TEST_F(RegisterLifetimeAndRemappingTest
, LifetimeAndRemappingWithUnusedReadOnlyRemappedTo
)
1816 const vector
<FakeCodeline
> code
= {
1817 { TGSI_OPCODE_USEQ
, {1}, {in0
,in1
}, {}},
1818 { TGSI_OPCODE_UIF
, {}, {7}, {}},
1819 { TGSI_OPCODE_UCMP
, {2}, {1,in1
,2}, {}},
1820 { TGSI_OPCODE_UCMP
, {4}, {2,in1
,1}, {}},
1821 { TGSI_OPCODE_ADD
, {5}, {2,4}, {}},
1822 { TGSI_OPCODE_ADD
, {8}, {5,4}, {}},
1823 { TGSI_OPCODE_ENDIF
},
1824 { TGSI_OPCODE_MOV
, {out1
}, {8}, {}},
1827 /* lt: 1: 0-3,2: 2-4 3: u 4: 3-5 5: 4-5 6: u 7: 1-1,8: 5-7 */
1828 run (code
, vector
<int>({0,1,2,3,1,2,6,7,1}));
1831 TEST_F(RegisterLifetimeAndRemappingTest
, LifetimeAndRemappingWithUnusedReadOnlyRemapped
)
1833 const vector
<FakeCodeline
> code
= {
1834 { TGSI_OPCODE_USEQ
, {0}, {in0
,in1
}, {}},
1835 { TGSI_OPCODE_UCMP
, {2}, {0,in1
,2}, {}},
1836 { TGSI_OPCODE_UCMP
, {4}, {2,in1
,0}, {}},
1837 { TGSI_OPCODE_UIF
, {}, {7}, {}},
1838 { TGSI_OPCODE_ADD
, {5}, {4,4}, {}},
1839 { TGSI_OPCODE_ADD
, {8}, {5,4}, {}},
1840 { TGSI_OPCODE_ENDIF
},
1841 { TGSI_OPCODE_MOV
, {out1
}, {8}, {}},
1844 /* lt: 0: 0-2 1: u 2: 1-2 3: u 4: 2-5 5: 4-5 6: u 7:ro 8: 5-7 */
1845 run (code
, vector
<int>({0,1,2,3,0,2,6,7,0}));