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:
parent
9da3d714b8
commit
49f4f1ec22
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue