diff options
author | Gert Wollny <[email protected]> | 2017-10-03 09:49:37 +0200 |
---|---|---|
committer | Brian Paul <[email protected]> | 2018-01-24 10:23:00 -0700 |
commit | 517e34c62f18c6067781370401d26c8162dfde4c (patch) | |
tree | f5bac5c6e89213db972946cf4e7f8087580972b9 /src/mesa/state_tracker | |
parent | 807e2539e512ca6c96f059da855473eb7be99ba1 (diff) |
mesa/st/tests: Add tests for improved tracking of temporaries
Additional tests are added that check the tracking of access to temporaries
in if-else branches.
Reviewed-by: Brian Paul <[email protected]>
Signed-off-by: Gert Wollny <[email protected]>
Diffstat (limited to 'src/mesa/state_tracker')
-rw-r--r-- | src/mesa/state_tracker/tests/test_glsl_to_tgsi_lifetime.cpp | 493 |
1 files changed, 486 insertions, 7 deletions
diff --git a/src/mesa/state_tracker/tests/test_glsl_to_tgsi_lifetime.cpp b/src/mesa/state_tracker/tests/test_glsl_to_tgsi_lifetime.cpp index 84a91f59889..a1dc28a3875 100644 --- a/src/mesa/state_tracker/tests/test_glsl_to_tgsi_lifetime.cpp +++ b/src/mesa/state_tracker/tests/test_glsl_to_tgsi_lifetime.cpp @@ -164,7 +164,7 @@ TEST_F(LifetimeEvaluatorExactTest, MoveInIfInNestedLoop) * - value must survive from first write to last read in loop * for now we only check that the minimum life time is correct. */ -TEST_F(LifetimeEvaluatorAtLeastTest, WriteInIfAndElseInLoop) +TEST_F(LifetimeEvaluatorExactTest, WriteInIfAndElseInLoop) { const vector<FakeCodeline> code = { { TGSI_OPCODE_MOV, {1}, {in0}, {}}, @@ -206,6 +206,137 @@ TEST_F(LifetimeEvaluatorExactTest, WriteInIfAndElseReadInElseInLoop) run (code, temp_lt_expect({{-1,-1}, {0,9}, {1,9}, {7,10}})); } + +/* Test that a write in ELSE path only in loop is properly tracked: + * In loop if/else value written in else path and read outside + * - value must survive the whole loop. + */ +TEST_F(LifetimeEvaluatorExactTest, WriteInElseReadInLoop) +{ + const vector<FakeCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {1}, {}}, + { TGSI_OPCODE_UADD, {2}, {1,in0}, {}}, + { TGSI_OPCODE_ELSE }, + { TGSI_OPCODE_ADD, {3}, {1,2}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_UADD, {1}, {3,in1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_END} + }; + run (code, temp_lt_expect({{-1,-1}, {0,9}, {1,8}, {1,8}})); +} + +/* Test that tracking a second write in an ELSE path is not attributed + * to the IF path: In loop if/else value written in else path twice and + * read outside - value must survive the whole loop + */ +TEST_F(LifetimeEvaluatorExactTest, WriteInElseTwiceReadInLoop) +{ + const vector<FakeCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {1}, {}}, + { TGSI_OPCODE_UADD, {2}, {1,in0}, {}}, + { TGSI_OPCODE_ELSE }, + { TGSI_OPCODE_ADD, {3}, {1,2}, {}}, + { TGSI_OPCODE_ADD, {3}, {1,3}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_UADD, {1}, {3,in1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_END} + }; + run (code, temp_lt_expect({{-1,-1}, {0,10}, {1,9}, {1,9}})); +} + +/* Test that the IF and ELSE scopes from different IF/ELSE pairs are not + * merged: In loop if/else value written in if, and then in different else path + * and read outside - value must survive the whole loop + */ +TEST_F(LifetimeEvaluatorExactTest, WriteInOneIfandInAnotherElseInLoop) +{ + const vector<FakeCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {1}, {}}, + { TGSI_OPCODE_UADD, {2}, {1,in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_IF, {}, {1}, {}}, + { TGSI_OPCODE_ELSE }, + { TGSI_OPCODE_ADD, {2}, {1,1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_UADD, {1}, {2,in1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_END} + }; + run (code, temp_lt_expect({{-1,-1}, {0,11}, {1,10}})); +} + +/* Test that with a new loop the resolution of the IF/ELSE write conditionality + * is restarted: In first loop value is written in both if and else, in second + * loop value is written only in if - must survive the second loop. + * However, the tracking is currently not able to restrict the lifetime + * in the first loop, hence the "AtLeast" test. + */ +TEST_F(LifetimeEvaluatorAtLeastTest, UnconditionalInFirstLoopConditionalInSecond) +{ + const vector<FakeCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {1}, {}}, + { TGSI_OPCODE_UADD, {2}, {1,in0}, {}}, + { TGSI_OPCODE_ELSE }, + { TGSI_OPCODE_UADD, {2}, {1,in1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {1}, {}}, + { TGSI_OPCODE_ADD, {2}, {in0,1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_UADD, {1}, {2,in1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_END} + }; + run (code, temp_lt_expect({{-1,-1}, {0,14}, {3,13}})); +} + +/* Test that with a new loop the resolution of the IF/ELSE write conditionality + * is restarted, and also takes care of write before read in else scope: + * In first loop value is written in both if and else, in second loop value is + * also written in both, but first read in if - must survive the second loop. + * However, the tracking is currently not able to restrict the lifetime + * in the first loop, hence the "AtLeast" test. + */ +TEST_F(LifetimeEvaluatorAtLeastTest, UnconditionalInFirstLoopConditionalInSecond2) +{ + const vector<FakeCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {1}, {}}, + { TGSI_OPCODE_UADD, {2}, {1,in0}, {}}, + { TGSI_OPCODE_ELSE }, + { TGSI_OPCODE_UADD, {2}, {1,in1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in1}, {}}, + { TGSI_OPCODE_ADD, {2}, {2,1}, {}}, + { TGSI_OPCODE_ELSE }, + { TGSI_OPCODE_MOV, {2}, {1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_UADD, {1}, {2,in1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_END} + }; + run (code, temp_lt_expect({{-1,-1}, {0,16}, {3,15}})); +} + /* In loop if/else read in one path before written in the same loop * - value must survive the whole loop */ @@ -262,12 +393,12 @@ TEST_F(LifetimeEvaluatorExactTest, ReadInLoopBeforeWriteAndLifeToTheEnd) run (code, temp_lt_expect({{-1,-1}, {0,4}})); } - -/* Write in nested ifs in loop, for now we do test whether the - * life time is at least what is required, but we know that the - * implementation doesn't do a full check and sets larger boundaries +/* Test whether nesting IF/ELSE pairs within a loop is resolved: + * Write in all conditional branches if the inner nesting level and + * read after the outer IF/ELSE pair is closed. The lifetime doesn't have + * to be extended to the full loop. */ -TEST_F(LifetimeEvaluatorAtLeastTest, NestedIfInLoopAlwaysWriteButNotPropagated) +TEST_F(LifetimeEvaluatorExactTest, NestedIfInLoopAlwaysWriteButNotPropagated) { const vector<FakeCodeline> code = { { TGSI_OPCODE_BGNLOOP }, @@ -291,7 +422,178 @@ TEST_F(LifetimeEvaluatorAtLeastTest, NestedIfInLoopAlwaysWriteButNotPropagated) run (code, temp_lt_expect({{-1,-1}, {3,14}})); } -/* The value is written in a loop and in a nested if, but +/* Test that nested chaining of IF/ELSE scopes is resolved: + * Write in each IF branch, and open another IF/ELSE scope pair in the ELSE + * branch. At the last nesting level, the temporary is also written in the + * ELSE branch, hence the full constrict results in an unconditional write. + */ +TEST_F(LifetimeEvaluatorExactTest, DeeplyNestedIfElseInLoopResolved) +{ + const vector<FakeCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ADD, {2}, {1, in1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {2}, {}}, + { TGSI_OPCODE_END} + }; + run (code, temp_lt_expect({{-1,-1}, {2,18}, {18, 20}})); +} + +/* The complementary case of the above: Open deeply nested IF/ELSE clauses + * and only at the deepest nesting level the temporary is written in the IF + * branch, but for all ELSE scopes the value is also written. Like above, when + * the full construct has been executed, the temporary has been written + * unconditionally. + */ +TEST_F(LifetimeEvaluatorExactTest, DeeplyNestedIfElseInLoopResolved2) +{ + const vector<FakeCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ADD, {2}, {1, in1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {2}, {}}, + { TGSI_OPCODE_END} + }; + run (code, temp_lt_expect({{-1,-1}, {5,18}, {18, 20}})); +} + +/* Test that a write in an IF scope within IF scope where the temporary already + * can be ignored. + */ +TEST_F(LifetimeEvaluatorExactTest, NestedIfElseInLoopResolvedInOuterScope) +{ + const vector<FakeCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ADD, {2}, {1, in1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {2}, {}}, + { TGSI_OPCODE_END} + }; + run (code, temp_lt_expect({{-1,-1}, {2,9}, {9, 11}})); +} + +/* Here the read before write in the nested if is of no consequence to the + * life time because the variable was already written in the enclosing if-branch. + */ +TEST_F(LifetimeEvaluatorExactTest, NestedIfElseInLoopWithReadResolvedInOuterScope) +{ + const vector<FakeCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_ADD, {1}, {in0, 1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ADD, {2}, {1, in1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {2}, {}}, + { TGSI_OPCODE_END} + }; + run (code, temp_lt_expect({{-1,-1}, {2,9}, {9, 11}})); +} + +/* Here the nested if condition is of no consequence to the life time + * because the variable was already written in the enclosing else-branch. + */ +TEST_F(LifetimeEvaluatorExactTest, NestedIfElseInLoopResolvedInOuterScope2) +{ + const vector<FakeCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ADD, {2}, {1, in1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {2}, {}}, + { TGSI_OPCODE_END} + }; + run (code, temp_lt_expect({{-1,-1}, {2,9}, {9, 11}})); +} + +/* Test that tracking of IF/ELSE scopes does not unnessesarily cross loops, + * i.e. if the inner IF/ELSE pair is enclosed by a loop which is enclosed + * by another IF statement: The resolution of unconditionality of the write + * within the loop is not changed by the fact that the loop is enclosed by + * an IF scope. + */ +TEST_F(LifetimeEvaluatorExactTest, NestedIfInLoopAlwaysWriteParentIfOutsideLoop) +{ + const vector<FakeCodeline> code = { + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_MOV, {2}, {1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {2}, {in1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_MOV, {out0}, {2}, {}}, + + { TGSI_OPCODE_END} + }; + run (code, temp_lt_expect({{-1,-1}, {3,12}, {12, 17}})); +} + +/* The value is written in a loop and in a nested IF, but * not in all code paths, hence the value must survive the loop. */ TEST_F(LifetimeEvaluatorExactTest, NestedIfInLoopWriteNotAlways) @@ -316,6 +618,183 @@ TEST_F(LifetimeEvaluatorExactTest, NestedIfInLoopWriteNotAlways) run (code, temp_lt_expect({{-1,-1}, {0,13}})); } +/* Test that reading in an ELSE branach after writing is ignored: + * The value is written in a loop in both branches of if-else but also + * read in the else after writing, should have no effect on lifetime. + */ +TEST_F(LifetimeEvaluatorExactTest, IfElseWriteInLoopAlsoReadInElse) +{ + const vector<FakeCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {1}, {in1}, {}}, + { TGSI_OPCODE_MUL, {1}, {in0, 1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_END} + }; + run (code, temp_lt_expect({{-1,-1}, {2,7}})); +} + +/* Test that a write in an inner IF/ELSE pair is propagated to the outer + * ELSE branch: The value is written in a loop in both branches of a nested + * IF/ELSE pair, but only within the outer else, hence in summary the write is + * conditional within the loop. + */ +TEST_F(LifetimeEvaluatorExactTest, WriteInNestedIfElseOuterElseOnly) +{ + const vector<FakeCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_ADD, {1}, {in1, in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_END} + }; + run (code, temp_lt_expect({{-1,-1}, {0,10}})); +} + +/* Test that reads in an inner ELSE after write within the enclosing IF branch + * is of no consequence (i.e. check that the read in the ELSE branch is not + * attributed as read before write when the outer ELSE branch is scanned: + * Nested if-else in loop. The value is written in the outer if and else and + * read in one inner else, should limit lifetime. + */ +TEST_F(LifetimeEvaluatorExactTest, WriteUnconditionallyReadInNestedElse) +{ + const vector<FakeCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {out1}, {1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_END} + }; + run (code, temp_lt_expect({{-1,-1}, {2,10}})); +} + + +/* Nested if-else in loop. The value is written in a loop in both branches + * of if-else but also read in the second nested else before writing. + * Is conditional. + */ +TEST_F(LifetimeEvaluatorExactTest, NestedIfelseReadFirstInInnerElseInLoop) +{ + const vector<FakeCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {1}, {in1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_ADD, {1}, {in1, 1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_END} + }; + run (code, temp_lt_expect({{-1,-1}, {0,15}})); +} + +/* Test that read before write is properly tracked for nested IF branches. + * The value is written in a loop in both branches of IF/ELSE but also read in + * the second nested IF before writing - is conditional. + */ +TEST_F(LifetimeEvaluatorExactTest, NestedIfelseReadFirstInInnerIfInLoop) +{ + const vector<FakeCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {1}, {in1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_ADD, {1}, {in1, 1}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_END} + }; + run (code, temp_lt_expect({{-1,-1}, {0,15}})); +} + +/* Same as above, but for the secondary ELSE branch: + * The value is written in a loop in both branches of IF/ELSE but also read in + * the second nested ELSE branch before writing - is conditional. + */ +TEST_F(LifetimeEvaluatorExactTest, WriteInOneElseBranchReadFirstInOtherInLoop) +{ + const vector<FakeCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {1}, {in1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_ADD, {1}, {in1, 1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_END} + }; + run (code, temp_lt_expect({{-1,-1}, {2,11}})); +} + +/* Test that the "write is unconditional" resolution is not overwritten within + * a loop: The value is written in a loop in both branches of an IF/ELSE clause, + * hence the second IF doesn't make it conditional. + */ +TEST_F(LifetimeEvaluatorExactTest, WriteInIfElseBranchSecondIfInLoop) +{ + const vector<FakeCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {1}, {in1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_END} + }; + run (code, temp_lt_expect({{-1,-1}, {2,9}})); +} + + /* A continue in the loop is not relevant */ TEST_F(LifetimeEvaluatorExactTest, LoopWithWriteAfterContinue) { |