1
2 #include "radeon_compiler.h"
3 #include "radeon_compiler_util.h"
4 #include "radeon_dataflow.h"
5 #include "radeon_program.h"
6 #include "radeon_program_constants.h"
7
8 struct vert_fc_state {
9 struct radeon_compiler *C;
10 unsigned BranchDepth;
11 unsigned LoopDepth;
12 unsigned LoopsReserved;
13 int PredStack[R500_PVS_MAX_LOOP_DEPTH];
14 int PredicateReg;
15 unsigned InCFBreak;
16 };
17
build_pred_src(struct rc_src_register * src,struct vert_fc_state * fc_state)18 static void build_pred_src(
19 struct rc_src_register * src,
20 struct vert_fc_state * fc_state)
21 {
22 src->Swizzle = RC_MAKE_SWIZZLE(RC_SWIZZLE_UNUSED, RC_SWIZZLE_UNUSED,
23 RC_SWIZZLE_UNUSED, RC_SWIZZLE_W);
24 src->File = RC_FILE_TEMPORARY;
25 src->Index = fc_state->PredicateReg;
26 }
27
build_pred_dst(struct rc_dst_register * dst,struct vert_fc_state * fc_state)28 static void build_pred_dst(
29 struct rc_dst_register * dst,
30 struct vert_fc_state * fc_state)
31 {
32 dst->WriteMask = RC_MASK_W;
33 dst->File = RC_FILE_TEMPORARY;
34 dst->Index = fc_state->PredicateReg;
35 }
36
mark_write(void * userdata,struct rc_instruction * inst,rc_register_file file,unsigned int index,unsigned int mask)37 static void mark_write(void * userdata, struct rc_instruction * inst,
38 rc_register_file file, unsigned int index, unsigned int mask)
39 {
40 unsigned int * writemasks = userdata;
41
42 if (file != RC_FILE_TEMPORARY)
43 return;
44
45 if (index >= R300_VS_MAX_TEMPS)
46 return;
47
48 writemasks[index] |= mask;
49 }
50
reserve_predicate_reg(struct vert_fc_state * fc_state)51 static int reserve_predicate_reg(struct vert_fc_state * fc_state)
52 {
53 int i;
54 unsigned int writemasks[RC_REGISTER_MAX_INDEX];
55 struct rc_instruction * inst;
56 memset(writemasks, 0, sizeof(writemasks));
57 for(inst = fc_state->C->Program.Instructions.Next;
58 inst != &fc_state->C->Program.Instructions;
59 inst = inst->Next) {
60 rc_for_all_writes_mask(inst, mark_write, writemasks);
61 }
62
63 for(i = 0; i < fc_state->C->max_temp_regs; i++) {
64 /* Most of the control flow instructions only write the
65 * W component of the Predicate Register, but
66 * the docs say that ME_PRED_SET_CLR and
67 * ME_PRED_SET_RESTORE write all components of the
68 * register, so we must reserve a register that has
69 * all its components free. */
70 if (!writemasks[i]) {
71 fc_state->PredicateReg = i;
72 break;
73 }
74 }
75 if (i == fc_state->C->max_temp_regs) {
76 rc_error(fc_state->C, "No free temporary to use for"
77 " predicate stack counter.\n");
78 return -1;
79 }
80 return 1;
81 }
82
lower_bgnloop(struct rc_instruction * inst,struct vert_fc_state * fc_state)83 static void lower_bgnloop(
84 struct rc_instruction * inst,
85 struct vert_fc_state * fc_state)
86 {
87 struct rc_instruction * new_inst =
88 rc_insert_new_instruction(fc_state->C, inst->Prev);
89
90 if ((!fc_state->C->is_r500
91 && fc_state->LoopsReserved >= R300_VS_MAX_LOOP_DEPTH)
92 || fc_state->LoopsReserved >= R500_PVS_MAX_LOOP_DEPTH) {
93 rc_error(fc_state->C, "Loops are nested too deep.");
94 return;
95 }
96
97 if (fc_state->LoopDepth == 0 && fc_state->BranchDepth == 0) {
98 if (fc_state->PredicateReg == -1) {
99 if (reserve_predicate_reg(fc_state) == -1) {
100 return;
101 }
102 }
103
104 /* Initialize the predicate bit to true. */
105 new_inst->U.I.Opcode = RC_ME_PRED_SEQ;
106 build_pred_dst(&new_inst->U.I.DstReg, fc_state);
107 new_inst->U.I.SrcReg[0].Index = 0;
108 new_inst->U.I.SrcReg[0].File = RC_FILE_NONE;
109 new_inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_0000;
110 } else {
111 fc_state->PredStack[fc_state->LoopDepth] =
112 fc_state->PredicateReg;
113 /* Copy the the current predicate value to this loop's
114 * predicate register */
115
116 /* Use the old predicate value for src0 */
117 build_pred_src(&new_inst->U.I.SrcReg[0], fc_state);
118
119 /* Reserve this loop's predicate register */
120 if (reserve_predicate_reg(fc_state) == -1) {
121 return;
122 }
123
124 /* Copy the old predicate value to the new register */
125 new_inst->U.I.Opcode = RC_OPCODE_ADD;
126 build_pred_dst(&new_inst->U.I.DstReg, fc_state);
127 new_inst->U.I.SrcReg[1].Index = 0;
128 new_inst->U.I.SrcReg[1].File = RC_FILE_NONE;
129 new_inst->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_0000;
130 }
131
132 }
133
lower_brk(struct rc_instruction * inst,struct vert_fc_state * fc_state)134 static void lower_brk(
135 struct rc_instruction * inst,
136 struct vert_fc_state * fc_state)
137 {
138 if (fc_state->LoopDepth == 1) {
139 inst->U.I.Opcode = RC_OPCODE_RCP;
140 inst->U.I.DstReg.Pred = RC_PRED_INV;
141 inst->U.I.SrcReg[0].Index = 0;
142 inst->U.I.SrcReg[0].File = RC_FILE_NONE;
143 inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_0000;
144 } else {
145 inst->U.I.Opcode = RC_ME_PRED_SET_CLR;
146 inst->U.I.DstReg.Pred = RC_PRED_SET;
147 }
148
149 build_pred_dst(&inst->U.I.DstReg, fc_state);
150 }
151
lower_endloop(struct rc_instruction * inst,struct vert_fc_state * fc_state)152 static void lower_endloop(
153 struct rc_instruction * inst,
154 struct vert_fc_state * fc_state)
155 {
156 struct rc_instruction * new_inst =
157 rc_insert_new_instruction(fc_state->C, inst);
158
159 new_inst->U.I.Opcode = RC_ME_PRED_SET_RESTORE;
160 build_pred_dst(&new_inst->U.I.DstReg, fc_state);
161 /* Restore the previous predicate register. */
162 fc_state->PredicateReg = fc_state->PredStack[fc_state->LoopDepth - 1];
163 build_pred_src(&new_inst->U.I.SrcReg[0], fc_state);
164 }
165
lower_if(struct rc_instruction * inst,struct vert_fc_state * fc_state)166 static void lower_if(
167 struct rc_instruction * inst,
168 struct vert_fc_state * fc_state)
169 {
170 /* Reserve a temporary to use as our predicate stack counter, if we
171 * don't already have one. */
172 if (fc_state->PredicateReg == -1) {
173 /* If we are inside a loop, the Predicate Register should
174 * have already been defined. */
175 assert(fc_state->LoopDepth == 0);
176
177 if (reserve_predicate_reg(fc_state) == -1) {
178 return;
179 }
180 }
181
182 if (inst->Next->U.I.Opcode == RC_OPCODE_BRK) {
183 fc_state->InCFBreak = 1;
184 }
185 if ((fc_state->BranchDepth == 0 && fc_state->LoopDepth == 0)
186 || (fc_state->LoopDepth == 1 && fc_state->InCFBreak)) {
187 if (fc_state->InCFBreak) {
188 inst->U.I.Opcode = RC_ME_PRED_SEQ;
189 inst->U.I.DstReg.Pred = RC_PRED_SET;
190 } else {
191 inst->U.I.Opcode = RC_ME_PRED_SNEQ;
192 }
193 } else {
194 unsigned swz;
195 inst->U.I.Opcode = RC_VE_PRED_SNEQ_PUSH;
196 memcpy(&inst->U.I.SrcReg[1], &inst->U.I.SrcReg[0],
197 sizeof(inst->U.I.SrcReg[1]));
198 swz = rc_get_scalar_src_swz(inst->U.I.SrcReg[1].Swizzle);
199 /* VE_PRED_SNEQ_PUSH needs to the branch condition to be in the
200 * w component */
201 inst->U.I.SrcReg[1].Swizzle = RC_MAKE_SWIZZLE(RC_SWIZZLE_UNUSED,
202 RC_SWIZZLE_UNUSED, RC_SWIZZLE_UNUSED, swz);
203 build_pred_src(&inst->U.I.SrcReg[0], fc_state);
204 }
205 build_pred_dst(&inst->U.I.DstReg, fc_state);
206 }
207
rc_vert_fc(struct radeon_compiler * c,void * user)208 void rc_vert_fc(struct radeon_compiler *c, void *user)
209 {
210 struct rc_instruction * inst;
211 struct vert_fc_state fc_state;
212
213 memset(&fc_state, 0, sizeof(fc_state));
214 fc_state.PredicateReg = -1;
215 fc_state.C = c;
216
217 for(inst = c->Program.Instructions.Next;
218 inst != &c->Program.Instructions;
219 inst = inst->Next) {
220
221 switch (inst->U.I.Opcode) {
222
223 case RC_OPCODE_BGNLOOP:
224 lower_bgnloop(inst, &fc_state);
225 fc_state.LoopDepth++;
226 break;
227
228 case RC_OPCODE_BRK:
229 lower_brk(inst, &fc_state);
230 break;
231
232 case RC_OPCODE_ENDLOOP:
233 if (fc_state.BranchDepth != 0
234 || fc_state.LoopDepth != 1) {
235 lower_endloop(inst, &fc_state);
236 }
237 fc_state.LoopDepth--;
238 /* Skip PRED_RESTORE */
239 inst = inst->Next;
240 break;
241 case RC_OPCODE_IF:
242 lower_if(inst, &fc_state);
243 fc_state.BranchDepth++;
244 break;
245
246 case RC_OPCODE_ELSE:
247 inst->U.I.Opcode = RC_ME_PRED_SET_INV;
248 build_pred_dst(&inst->U.I.DstReg, &fc_state);
249 build_pred_src(&inst->U.I.SrcReg[0], &fc_state);
250 break;
251
252 case RC_OPCODE_ENDIF:
253 if (fc_state.LoopDepth == 1 && fc_state.InCFBreak) {
254 struct rc_instruction * to_delete = inst;
255 inst = inst->Prev;
256 rc_remove_instruction(to_delete);
257 /* XXX: Delete the endif instruction */
258 } else {
259 inst->U.I.Opcode = RC_ME_PRED_SET_POP;
260 build_pred_dst(&inst->U.I.DstReg, &fc_state);
261 build_pred_src(&inst->U.I.SrcReg[0], &fc_state);
262 }
263 fc_state.InCFBreak = 0;
264 fc_state.BranchDepth--;
265 break;
266
267 default:
268 if (fc_state.BranchDepth || fc_state.LoopDepth) {
269 inst->U.I.DstReg.Pred = RC_PRED_SET;
270 }
271 break;
272 }
273
274 if (c->Error) {
275 return;
276 }
277 }
278 }
279