r300: fix deadcode elimination in loops with breaks

We are updating the deadcode state while walking the program backwards.
When encountering ENDLOOP, we scan the loop, mark everything in the loop
as used and than continue as usuall. We were previously trying to be
smart with the breaks. This was however not working as expected.

Instead, save the most pesimistic deadcode state from the ENDLOOP and
just restore it anytime we see a break.

This keeps the code simple and more importantly does not touch the flat
and IF(-ELSE)-ENDIF paths at all so reduces the chances of regression.
No changes with my shader-db.

Fixes piglits on RV530:
    shaders/ssa/fs-if-def-else-break.shader_test
    spec/glsl-1.10/execution/vs-loop-array-index-unroll.shader_test

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/5832
Signed-off-by: Pavel Ondračka <pavel.ondracka@gmail.com>
Acked-by: Emma Anholt <emma@anholt.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14661>
This commit is contained in:
Pavel Ondračka 2022-01-21 14:08:33 +01:00
parent 9da3d714b8
commit 49f4f1ec22
1 changed files with 9 additions and 18 deletions

View File

@ -44,7 +44,7 @@ struct instruction_state {
};
struct loopinfo {
struct updatemask_state * Breaks;
struct updatemask_state StoreEndloop;
unsigned int BreakCount;
unsigned int BreaksReserved;
};
@ -88,20 +88,12 @@ static void or_updatemasks(
dst->Address = a->Address | b->Address;
}
static void push_break(struct deadcode_state *s)
{
struct loopinfo * loop = &s->LoopStack[s->LoopStackSize - 1];
memory_pool_array_reserve(&s->C->Pool, struct updatemask_state,
loop->Breaks, loop->BreakCount, loop->BreaksReserved, 1);
memcpy(&loop->Breaks[loop->BreakCount++], &s->R, sizeof(s->R));
}
static void push_loop(struct deadcode_state * s)
{
memory_pool_array_reserve(&s->C->Pool, struct loopinfo, s->LoopStack,
s->LoopStackSize, s->LoopStackReserved, 1);
memset(&s->LoopStack[s->LoopStackSize++], 0, sizeof(struct loopinfo));
memcpy(&s->LoopStack[s->LoopStackSize - 1].StoreEndloop, &s->R, sizeof(s->R));
}
static void push_branch(struct deadcode_state * s)
@ -230,7 +222,9 @@ void rc_dataflow_deadcode(struct radeon_compiler * c, void *user)
switch(opcode->Opcode){
/* Mark all sources in the loop body as used before doing
* normal deadcode analysis. This is probably not optimal.
* normal deadcode analysis. This is probably not optimal.
* Save this pessimistic deadcode state and restore it anytime
* we see a break just to be extra sure.
*/
case RC_OPCODE_ENDLOOP:
{
@ -268,17 +262,14 @@ void rc_dataflow_deadcode(struct radeon_compiler * c, void *user)
break;
}
case RC_OPCODE_BRK:
push_break(&s);
break;
case RC_OPCODE_BGNLOOP:
{
unsigned int i;
struct loopinfo * loop = &s.LoopStack[s.LoopStackSize-1];
for(i = 0; i < loop->BreakCount; i++) {
or_updatemasks(&s.R, &s.R, &loop->Breaks[i]);
}
memcpy(&s.R, &loop->StoreEndloop, sizeof(s.R));
break;
}
case RC_OPCODE_BGNLOOP:
s.LoopStackSize--;
break;
case RC_OPCODE_CONT:
break;
case RC_OPCODE_ENDIF: