1 |
From a7a8f906d40205005f7cd3104f714c28593e87fd Mon Sep 17 00:00:00 2001 |
2 |
From: Timothy Arceri <tarceri@itsqueeze.com> |
3 |
Date: Fri, 14 Dec 2018 15:36:02 +1100 |
4 |
Subject: [PATCH 48/78] tgsi/scan: correctly walk instructions in |
5 |
tgsi_scan_tess_ctrl() |
6 |
MIME-Version: 1.0 |
7 |
Content-Type: text/plain; charset=UTF-8 |
8 |
Content-Transfer-Encoding: 8bit |
9 |
|
10 |
The previous code used a do while loop and continues after walking |
11 |
a nested loop/if-statement. This means we end up evaluating the |
12 |
last instruction from the nested block against the while condition |
13 |
and potentially exit early if it matches the exit condition of the |
14 |
outer block. |
15 |
|
16 |
Fixes: 386d165d8d09 ("tgsi/scan: add a new pass that analyzes tess factor writes") |
17 |
|
18 |
Reviewed-by: Marek Olšák <marek.olsak@amd.com> |
19 |
(cherry picked from commit 4dda4457504ee5cafa0388543620d4598b8561cf) |
20 |
--- |
21 |
src/gallium/auxiliary/tgsi/tgsi_scan.c | 72 +++++++++++++++----------- |
22 |
1 file changed, 43 insertions(+), 29 deletions(-) |
23 |
|
24 |
diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.c b/src/gallium/auxiliary/tgsi/tgsi_scan.c |
25 |
index ecd0b379c2..75c2e08632 100644 |
26 |
--- a/src/gallium/auxiliary/tgsi/tgsi_scan.c |
27 |
+++ b/src/gallium/auxiliary/tgsi/tgsi_scan.c |
28 |
@@ -1004,11 +1004,12 @@ get_block_tessfactor_writemask(const struct tgsi_shader_info *info, |
29 |
struct tgsi_full_instruction *inst; |
30 |
unsigned writemask = 0; |
31 |
|
32 |
- do { |
33 |
- tgsi_parse_token(parse); |
34 |
- assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION); |
35 |
- inst = &parse->FullToken.FullInstruction; |
36 |
- check_no_subroutines(inst); |
37 |
+ tgsi_parse_token(parse); |
38 |
+ assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION); |
39 |
+ inst = &parse->FullToken.FullInstruction; |
40 |
+ check_no_subroutines(inst); |
41 |
+ |
42 |
+ while (inst->Instruction.Opcode != end_opcode) { |
43 |
|
44 |
/* Recursively process nested blocks. */ |
45 |
switch (inst->Instruction.Opcode) { |
46 |
@@ -1016,20 +1017,26 @@ get_block_tessfactor_writemask(const struct tgsi_shader_info *info, |
47 |
case TGSI_OPCODE_UIF: |
48 |
writemask |= |
49 |
get_block_tessfactor_writemask(info, parse, TGSI_OPCODE_ENDIF); |
50 |
- continue; |
51 |
+ break; |
52 |
|
53 |
case TGSI_OPCODE_BGNLOOP: |
54 |
writemask |= |
55 |
get_block_tessfactor_writemask(info, parse, TGSI_OPCODE_ENDLOOP); |
56 |
- continue; |
57 |
+ break; |
58 |
|
59 |
case TGSI_OPCODE_BARRIER: |
60 |
unreachable("nested BARRIER is illegal"); |
61 |
- continue; |
62 |
+ break; |
63 |
+ |
64 |
+ default: |
65 |
+ writemask |= get_inst_tessfactor_writemask(info, inst); |
66 |
} |
67 |
|
68 |
- writemask |= get_inst_tessfactor_writemask(info, inst); |
69 |
- } while (inst->Instruction.Opcode != end_opcode); |
70 |
+ tgsi_parse_token(parse); |
71 |
+ assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION); |
72 |
+ inst = &parse->FullToken.FullInstruction; |
73 |
+ check_no_subroutines(inst); |
74 |
+ } |
75 |
|
76 |
return writemask; |
77 |
} |
78 |
@@ -1043,18 +1050,20 @@ get_if_block_tessfactor_writemask(const struct tgsi_shader_info *info, |
79 |
struct tgsi_full_instruction *inst; |
80 |
unsigned then_tessfactor_writemask = 0; |
81 |
unsigned else_tessfactor_writemask = 0; |
82 |
+ unsigned writemask; |
83 |
bool is_then = true; |
84 |
|
85 |
- do { |
86 |
- tgsi_parse_token(parse); |
87 |
- assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION); |
88 |
- inst = &parse->FullToken.FullInstruction; |
89 |
- check_no_subroutines(inst); |
90 |
+ tgsi_parse_token(parse); |
91 |
+ assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION); |
92 |
+ inst = &parse->FullToken.FullInstruction; |
93 |
+ check_no_subroutines(inst); |
94 |
+ |
95 |
+ while (inst->Instruction.Opcode != TGSI_OPCODE_ENDIF) { |
96 |
|
97 |
switch (inst->Instruction.Opcode) { |
98 |
case TGSI_OPCODE_ELSE: |
99 |
is_then = false; |
100 |
- continue; |
101 |
+ break; |
102 |
|
103 |
/* Recursively process nested blocks. */ |
104 |
case TGSI_OPCODE_IF: |
105 |
@@ -1063,28 +1072,33 @@ get_if_block_tessfactor_writemask(const struct tgsi_shader_info *info, |
106 |
is_then ? &then_tessfactor_writemask : |
107 |
&else_tessfactor_writemask, |
108 |
cond_block_tf_writemask); |
109 |
- continue; |
110 |
+ break; |
111 |
|
112 |
case TGSI_OPCODE_BGNLOOP: |
113 |
*cond_block_tf_writemask |= |
114 |
get_block_tessfactor_writemask(info, parse, TGSI_OPCODE_ENDLOOP); |
115 |
- continue; |
116 |
+ break; |
117 |
|
118 |
case TGSI_OPCODE_BARRIER: |
119 |
unreachable("nested BARRIER is illegal"); |
120 |
- continue; |
121 |
- } |
122 |
- |
123 |
- /* Process an instruction in the current block. */ |
124 |
- unsigned writemask = get_inst_tessfactor_writemask(info, inst); |
125 |
+ break; |
126 |
+ default: |
127 |
+ /* Process an instruction in the current block. */ |
128 |
+ writemask = get_inst_tessfactor_writemask(info, inst); |
129 |
|
130 |
- if (writemask) { |
131 |
- if (is_then) |
132 |
- then_tessfactor_writemask |= writemask; |
133 |
- else |
134 |
- else_tessfactor_writemask |= writemask; |
135 |
+ if (writemask) { |
136 |
+ if (is_then) |
137 |
+ then_tessfactor_writemask |= writemask; |
138 |
+ else |
139 |
+ else_tessfactor_writemask |= writemask; |
140 |
+ } |
141 |
} |
142 |
- } while (inst->Instruction.Opcode != TGSI_OPCODE_ENDIF); |
143 |
+ |
144 |
+ tgsi_parse_token(parse); |
145 |
+ assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION); |
146 |
+ inst = &parse->FullToken.FullInstruction; |
147 |
+ check_no_subroutines(inst); |
148 |
+ } |
149 |
|
150 |
if (then_tessfactor_writemask || else_tessfactor_writemask) { |
151 |
/* If both statements write the same tess factor channels, |
152 |
-- |
153 |
2.20.1 |
154 |
|