• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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