Mesa (master): tgsi/scan: correctly walk instructions in tgsi_scan_tess_ctrl()

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Jan 1 23:01:51 UTC 2019


Module: Mesa
Branch: master
Commit: 4dda4457504ee5cafa0388543620d4598b8561cf
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=4dda4457504ee5cafa0388543620d4598b8561cf

Author: Timothy Arceri <tarceri at itsqueeze.com>
Date:   Fri Dec 14 15:36:02 2018 +1100

tgsi/scan: correctly walk instructions in tgsi_scan_tess_ctrl()

The previous code used a do while loop and continues after walking
a nested loop/if-statement. This means we end up evaluating the
last instruction from the nested block against the while condition
and potentially exit early if it matches the exit condition of the
outer block.

Fixes: 386d165d8d09 ("tgsi/scan: add a new pass that analyzes tess factor writes")

Reviewed-by: Marek Olšák <marek.olsak at amd.com>

---

 src/gallium/auxiliary/tgsi/tgsi_scan.c | 72 ++++++++++++++++++++--------------
 1 file changed, 43 insertions(+), 29 deletions(-)

diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.c b/src/gallium/auxiliary/tgsi/tgsi_scan.c
index d7f7a172ee..bfb415e439 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_scan.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_scan.c
@@ -1029,11 +1029,12 @@ get_block_tessfactor_writemask(const struct tgsi_shader_info *info,
    struct tgsi_full_instruction *inst;
    unsigned writemask = 0;
 
-   do {
-      tgsi_parse_token(parse);
-      assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION);
-      inst = &parse->FullToken.FullInstruction;
-      check_no_subroutines(inst);
+   tgsi_parse_token(parse);
+   assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION);
+   inst = &parse->FullToken.FullInstruction;
+   check_no_subroutines(inst);
+
+   while (inst->Instruction.Opcode != end_opcode) {
 
       /* Recursively process nested blocks. */
       switch (inst->Instruction.Opcode) {
@@ -1041,20 +1042,26 @@ get_block_tessfactor_writemask(const struct tgsi_shader_info *info,
       case TGSI_OPCODE_UIF:
          writemask |=
             get_block_tessfactor_writemask(info, parse, TGSI_OPCODE_ENDIF);
-         continue;
+         break;
 
       case TGSI_OPCODE_BGNLOOP:
          writemask |=
             get_block_tessfactor_writemask(info, parse, TGSI_OPCODE_ENDLOOP);
-         continue;
+         break;
 
       case TGSI_OPCODE_BARRIER:
          unreachable("nested BARRIER is illegal");
-         continue;
+         break;
+
+      default:
+         writemask |= get_inst_tessfactor_writemask(info, inst);
       }
 
-      writemask |= get_inst_tessfactor_writemask(info, inst);
-   } while (inst->Instruction.Opcode != end_opcode);
+      tgsi_parse_token(parse);
+      assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION);
+      inst = &parse->FullToken.FullInstruction;
+      check_no_subroutines(inst);
+   }
 
    return writemask;
 }
@@ -1068,18 +1075,20 @@ get_if_block_tessfactor_writemask(const struct tgsi_shader_info *info,
    struct tgsi_full_instruction *inst;
    unsigned then_tessfactor_writemask = 0;
    unsigned else_tessfactor_writemask = 0;
+   unsigned writemask;
    bool is_then = true;
 
-   do {
-      tgsi_parse_token(parse);
-      assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION);
-      inst = &parse->FullToken.FullInstruction;
-      check_no_subroutines(inst);
+   tgsi_parse_token(parse);
+   assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION);
+   inst = &parse->FullToken.FullInstruction;
+   check_no_subroutines(inst);
+
+   while (inst->Instruction.Opcode != TGSI_OPCODE_ENDIF) {
 
       switch (inst->Instruction.Opcode) {
       case TGSI_OPCODE_ELSE:
          is_then = false;
-         continue;
+         break;
 
       /* Recursively process nested blocks. */
       case TGSI_OPCODE_IF:
@@ -1088,28 +1097,33 @@ get_if_block_tessfactor_writemask(const struct tgsi_shader_info *info,
                                            is_then ? &then_tessfactor_writemask :
                                                      &else_tessfactor_writemask,
                                            cond_block_tf_writemask);
-         continue;
+         break;
 
       case TGSI_OPCODE_BGNLOOP:
          *cond_block_tf_writemask |=
             get_block_tessfactor_writemask(info, parse, TGSI_OPCODE_ENDLOOP);
-         continue;
+         break;
 
       case TGSI_OPCODE_BARRIER:
          unreachable("nested BARRIER is illegal");
-         continue;
-      }
-
-      /* Process an instruction in the current block. */
-      unsigned writemask = get_inst_tessfactor_writemask(info, inst);
+         break;
+      default:
+         /* Process an instruction in the current block. */
+         writemask = get_inst_tessfactor_writemask(info, inst);
 
-      if (writemask) {
-         if (is_then)
-            then_tessfactor_writemask |= writemask;
-         else
-            else_tessfactor_writemask |= writemask;
+         if (writemask) {
+            if (is_then)
+               then_tessfactor_writemask |= writemask;
+            else
+               else_tessfactor_writemask |= writemask;
+         }
       }
-   } while (inst->Instruction.Opcode != TGSI_OPCODE_ENDIF);
+
+      tgsi_parse_token(parse);
+      assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION);
+      inst = &parse->FullToken.FullInstruction;
+      check_no_subroutines(inst);
+   }
 
    if (then_tessfactor_writemask || else_tessfactor_writemask) {
       /* If both statements write the same tess factor channels,




More information about the mesa-commit mailing list