<div dir="ltr"><div>For the series:</div><div><br></div><div>Reviewed-by: Marek Olšák <<a href="mailto:marek.olsak@amd.com">marek.olsak@amd.com</a>></div><div><br></div><div>Marek<br></div></div><br><div class="gmail_quote"><div dir="ltr">On Fri, Dec 14, 2018 at 12:33 AM Timothy Arceri <<a href="mailto:tarceri@itsqueeze.com">tarceri@itsqueeze.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">The previous code used a do while loop and continues after walking<br>
a nested loop/if-statement. This means we end up evaluating the<br>
last instruction from the nested block against the while condition<br>
and potentially exit early if it matches the exit condition of the<br>
outer block.<br>
<br>
Fixes: 386d165d8d09 ("tgsi/scan: add a new pass that analyzes tess factor writes")<br>
---<br>
No changes in shader-db. Didn't run against piglit.<br>
<br>
src/gallium/auxiliary/tgsi/tgsi_scan.c | 72 +++++++++++++++-----------<br>
1 file changed, 43 insertions(+), 29 deletions(-)<br>
<br>
diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.c b/src/gallium/auxiliary/tgsi/tgsi_scan.c<br>
index 6e2e23822c..d56844bdc2 100644<br>
--- a/src/gallium/auxiliary/tgsi/tgsi_scan.c<br>
+++ b/src/gallium/auxiliary/tgsi/tgsi_scan.c<br>
@@ -1028,11 +1028,12 @@ get_block_tessfactor_writemask(const struct tgsi_shader_info *info,<br>
struct tgsi_full_instruction *inst;<br>
unsigned writemask = 0;<br>
<br>
- do {<br>
- tgsi_parse_token(parse);<br>
- assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION);<br>
- inst = &parse->FullToken.FullInstruction;<br>
- check_no_subroutines(inst);<br>
+ tgsi_parse_token(parse);<br>
+ assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION);<br>
+ inst = &parse->FullToken.FullInstruction;<br>
+ check_no_subroutines(inst);<br>
+<br>
+ while (inst->Instruction.Opcode != end_opcode) {<br>
<br>
/* Recursively process nested blocks. */<br>
switch (inst->Instruction.Opcode) {<br>
@@ -1040,20 +1041,26 @@ get_block_tessfactor_writemask(const struct tgsi_shader_info *info,<br>
case TGSI_OPCODE_UIF:<br>
writemask |=<br>
get_block_tessfactor_writemask(info, parse, TGSI_OPCODE_ENDIF);<br>
- continue;<br>
+ break;<br>
<br>
case TGSI_OPCODE_BGNLOOP:<br>
writemask |=<br>
get_block_tessfactor_writemask(info, parse, TGSI_OPCODE_ENDLOOP);<br>
- continue;<br>
+ break;<br>
<br>
case TGSI_OPCODE_BARRIER:<br>
unreachable("nested BARRIER is illegal");<br>
- continue;<br>
+ break;<br>
+<br>
+ default:<br>
+ writemask |= get_inst_tessfactor_writemask(info, inst);<br>
}<br>
<br>
- writemask |= get_inst_tessfactor_writemask(info, inst);<br>
- } while (inst->Instruction.Opcode != end_opcode);<br>
+ tgsi_parse_token(parse);<br>
+ assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION);<br>
+ inst = &parse->FullToken.FullInstruction;<br>
+ check_no_subroutines(inst);<br>
+ }<br>
<br>
return writemask;<br>
}<br>
@@ -1067,18 +1074,20 @@ get_if_block_tessfactor_writemask(const struct tgsi_shader_info *info,<br>
struct tgsi_full_instruction *inst;<br>
unsigned then_tessfactor_writemask = 0;<br>
unsigned else_tessfactor_writemask = 0;<br>
+ unsigned writemask;<br>
bool is_then = true;<br>
<br>
- do {<br>
- tgsi_parse_token(parse);<br>
- assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION);<br>
- inst = &parse->FullToken.FullInstruction;<br>
- check_no_subroutines(inst);<br>
+ tgsi_parse_token(parse);<br>
+ assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION);<br>
+ inst = &parse->FullToken.FullInstruction;<br>
+ check_no_subroutines(inst);<br>
+<br>
+ while (inst->Instruction.Opcode != TGSI_OPCODE_ENDIF) {<br>
<br>
switch (inst->Instruction.Opcode) {<br>
case TGSI_OPCODE_ELSE:<br>
is_then = false;<br>
- continue;<br>
+ break;<br>
<br>
/* Recursively process nested blocks. */<br>
case TGSI_OPCODE_IF:<br>
@@ -1087,28 +1096,33 @@ get_if_block_tessfactor_writemask(const struct tgsi_shader_info *info,<br>
is_then ? &then_tessfactor_writemask :<br>
&else_tessfactor_writemask,<br>
cond_block_tf_writemask);<br>
- continue;<br>
+ break;<br>
<br>
case TGSI_OPCODE_BGNLOOP:<br>
*cond_block_tf_writemask |=<br>
get_block_tessfactor_writemask(info, parse, TGSI_OPCODE_ENDLOOP);<br>
- continue;<br>
+ break;<br>
<br>
case TGSI_OPCODE_BARRIER:<br>
unreachable("nested BARRIER is illegal");<br>
- continue;<br>
- }<br>
-<br>
- /* Process an instruction in the current block. */<br>
- unsigned writemask = get_inst_tessfactor_writemask(info, inst);<br>
+ break;<br>
+ default:<br>
+ /* Process an instruction in the current block. */<br>
+ writemask = get_inst_tessfactor_writemask(info, inst);<br>
<br>
- if (writemask) {<br>
- if (is_then)<br>
- then_tessfactor_writemask |= writemask;<br>
- else<br>
- else_tessfactor_writemask |= writemask;<br>
+ if (writemask) {<br>
+ if (is_then)<br>
+ then_tessfactor_writemask |= writemask;<br>
+ else<br>
+ else_tessfactor_writemask |= writemask;<br>
+ }<br>
}<br>
- } while (inst->Instruction.Opcode != TGSI_OPCODE_ENDIF);<br>
+<br>
+ tgsi_parse_token(parse);<br>
+ assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION);<br>
+ inst = &parse->FullToken.FullInstruction;<br>
+ check_no_subroutines(inst);<br>
+ }<br>
<br>
if (then_tessfactor_writemask || else_tessfactor_writemask) {<br>
/* If both statements write the same tess factor channels,<br>
-- <br>
2.19.2<br>
<br>
</blockquote></div>