1 /*
2 * Copyright © 2020 Google, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #include <stdlib.h>
25
26 #include "util/ralloc.h"
27
28 #include "ir3.h"
29
30 struct ir3_validate_ctx {
31 struct ir3 *ir;
32
33 /* Current block being validated: */
34 struct ir3_block *current_block;
35
36 /* Current instruction being validated: */
37 struct ir3_instruction *current_instr;
38
39 /* Set of instructions found so far, used to validate that we
40 * don't have SSA uses that occure before def's
41 */
42 struct set *defs;
43 };
44
45 static void
validate_error(struct ir3_validate_ctx * ctx,const char * condstr)46 validate_error(struct ir3_validate_ctx *ctx, const char *condstr)
47 {
48 fprintf(stderr, "validation fail: %s\n", condstr);
49 if (ctx->current_instr) {
50 fprintf(stderr, " -> for instruction: ");
51 ir3_print_instr(ctx->current_instr);
52 } else {
53 fprintf(stderr, " -> for block%u\n", block_id(ctx->current_block));
54 }
55 abort();
56 }
57
58 #define validate_assert(ctx, cond) \
59 do { \
60 if (!(cond)) { \
61 validate_error(ctx, #cond); \
62 } \
63 } while (0)
64
65 static unsigned
reg_class_flags(struct ir3_register * reg)66 reg_class_flags(struct ir3_register *reg)
67 {
68 return reg->flags & (IR3_REG_HALF | IR3_REG_SHARED);
69 }
70
71 static void
validate_src(struct ir3_validate_ctx * ctx,struct ir3_instruction * instr,struct ir3_register * reg)72 validate_src(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr,
73 struct ir3_register *reg)
74 {
75 if (reg->flags & IR3_REG_IMMED)
76 validate_assert(ctx, ir3_valid_immediate(instr, reg->iim_val));
77
78 if (!(reg->flags & IR3_REG_SSA) || !reg->def)
79 return;
80
81 struct ir3_register *src = reg->def;
82
83 validate_assert(ctx, _mesa_set_search(ctx->defs, src->instr));
84 validate_assert(ctx, src->wrmask == reg->wrmask);
85 validate_assert(ctx, reg_class_flags(src) == reg_class_flags(reg));
86
87 if (reg->tied) {
88 validate_assert(ctx, reg->tied->tied == reg);
89 bool found = false;
90 foreach_dst (dst, instr) {
91 if (dst == reg->tied) {
92 found = true;
93 break;
94 }
95 }
96 validate_assert(ctx,
97 found && "tied register not in the same instruction");
98 }
99 }
100
101 /* phi sources are logically read at the end of the predecessor basic block,
102 * and we have to validate them then in order to correctly validate that the
103 * use comes after the definition for loop phis.
104 */
105 static void
validate_phi_src(struct ir3_validate_ctx * ctx,struct ir3_block * block,struct ir3_block * pred)106 validate_phi_src(struct ir3_validate_ctx *ctx, struct ir3_block *block,
107 struct ir3_block *pred)
108 {
109 unsigned pred_idx = ir3_block_get_pred_index(block, pred);
110
111 foreach_instr (phi, &block->instr_list) {
112 if (phi->opc != OPC_META_PHI)
113 break;
114
115 ctx->current_instr = phi;
116 validate_assert(ctx, phi->srcs_count == block->predecessors_count);
117 validate_src(ctx, phi, phi->srcs[pred_idx]);
118 }
119 }
120
121 static void
validate_phi(struct ir3_validate_ctx * ctx,struct ir3_instruction * phi)122 validate_phi(struct ir3_validate_ctx *ctx, struct ir3_instruction *phi)
123 {
124 _mesa_set_add(ctx->defs, phi);
125 validate_assert(ctx, phi->dsts_count == 1);
126 validate_assert(ctx, is_dest_gpr(phi->dsts[0]));
127 }
128
129 static void
validate_dst(struct ir3_validate_ctx * ctx,struct ir3_instruction * instr,struct ir3_register * reg)130 validate_dst(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr,
131 struct ir3_register *reg)
132 {
133 if (reg->tied) {
134 validate_assert(ctx, reg->tied->tied == reg);
135 validate_assert(ctx, reg_class_flags(reg->tied) == reg_class_flags(reg));
136 validate_assert(ctx, reg->tied->wrmask == reg->wrmask);
137 if (reg->flags & IR3_REG_ARRAY) {
138 validate_assert(ctx, reg->tied->array.base == reg->array.base);
139 validate_assert(ctx, reg->tied->size == reg->size);
140 }
141 bool found = false;
142 foreach_src (src, instr) {
143 if (src == reg->tied) {
144 found = true;
145 break;
146 }
147 }
148 validate_assert(ctx,
149 found && "tied register not in the same instruction");
150 }
151
152 if (reg->flags & IR3_REG_SSA)
153 validate_assert(ctx, reg->instr == instr);
154
155 if (reg->flags & IR3_REG_RELATIV)
156 validate_assert(ctx, instr->address);
157 }
158
159 #define validate_reg_size(ctx, reg, type) \
160 validate_assert( \
161 ctx, type_size(type) == (((reg)->flags & IR3_REG_HALF) ? 16 : 32))
162
163 static void
validate_instr(struct ir3_validate_ctx * ctx,struct ir3_instruction * instr)164 validate_instr(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr)
165 {
166 struct ir3_register *last_reg = NULL;
167
168 foreach_src_n (reg, n, instr) {
169 if (reg->flags & IR3_REG_RELATIV)
170 validate_assert(ctx, instr->address);
171
172 validate_src(ctx, instr, reg);
173
174 /* Validate that all src's are either half of full.
175 *
176 * Note: tex instructions w/ .s2en are a bit special in that the
177 * tex/samp src reg is half-reg for non-bindless and full for
178 * bindless, irrespective of the precision of other srcs. The
179 * tex/samp src is the first src reg when .s2en is set
180 */
181 if (reg->tied) {
182 /* must have the same size as the destination, handled in
183 * validate_reg().
184 */
185 } else if (reg == instr->address) {
186 validate_assert(ctx, reg->flags & IR3_REG_HALF);
187 } else if ((instr->flags & IR3_INSTR_S2EN) && (n < 2)) {
188 if (n == 0) {
189 if (instr->flags & IR3_INSTR_B)
190 validate_assert(ctx, !(reg->flags & IR3_REG_HALF));
191 else
192 validate_assert(ctx, reg->flags & IR3_REG_HALF);
193 }
194 } else if (opc_cat(instr->opc) == 1 || opc_cat(instr->opc) == 6) {
195 /* handled below */
196 } else if (opc_cat(instr->opc) == 0) {
197 /* end/chmask/etc are allowed to have different size sources */
198 } else if (instr->opc == OPC_META_PARALLEL_COPY) {
199 /* pcopy sources have to match with their destination but can have
200 * different sizes from each other.
201 */
202 } else if (n > 0) {
203 validate_assert(ctx, (last_reg->flags & IR3_REG_HALF) ==
204 (reg->flags & IR3_REG_HALF));
205 }
206
207 last_reg = reg;
208 }
209
210 for (unsigned i = 0; i < instr->dsts_count; i++) {
211 struct ir3_register *reg = instr->dsts[i];
212
213 validate_dst(ctx, instr, reg);
214 }
215
216 _mesa_set_add(ctx->defs, instr);
217
218 /* Check that src/dst types match the register types, and for
219 * instructions that have different opcodes depending on type,
220 * that the opcodes are correct.
221 */
222 switch (opc_cat(instr->opc)) {
223 case 1: /* move instructions */
224 if (instr->opc == OPC_MOVMSK || instr->opc == OPC_BALLOT_MACRO) {
225 validate_assert(ctx, instr->dsts_count == 1);
226 validate_assert(ctx, instr->dsts[0]->flags & IR3_REG_SHARED);
227 validate_assert(ctx, !(instr->dsts[0]->flags & IR3_REG_HALF));
228 validate_assert(
229 ctx, util_is_power_of_two_or_zero(instr->dsts[0]->wrmask + 1));
230 } else if (instr->opc == OPC_ANY_MACRO || instr->opc == OPC_ALL_MACRO ||
231 instr->opc == OPC_READ_FIRST_MACRO ||
232 instr->opc == OPC_READ_COND_MACRO) {
233 /* nothing yet */
234 } else if (instr->opc == OPC_ELECT_MACRO) {
235 validate_assert(ctx, instr->dsts_count == 1);
236 validate_assert(ctx, !(instr->dsts[0]->flags & IR3_REG_SHARED));
237 } else {
238 foreach_dst (dst, instr)
239 validate_reg_size(ctx, dst, instr->cat1.dst_type);
240 foreach_src (src, instr) {
241 if (!src->tied && src != instr->address)
242 validate_reg_size(ctx, src, instr->cat1.src_type);
243 }
244
245 switch (instr->opc) {
246 case OPC_SWZ:
247 validate_assert(ctx, instr->srcs_count == 2);
248 validate_assert(ctx, instr->dsts_count == 2);
249 break;
250 case OPC_GAT:
251 validate_assert(ctx, instr->srcs_count == 4);
252 validate_assert(ctx, instr->dsts_count == 1);
253 break;
254 case OPC_SCT:
255 validate_assert(ctx, instr->srcs_count == 1);
256 validate_assert(ctx, instr->dsts_count == 4);
257 break;
258 default:
259 break;
260 }
261 }
262
263 if (instr->opc != OPC_MOV)
264 validate_assert(ctx, !instr->address);
265
266 break;
267 case 3:
268 /* Validate that cat3 opc matches the src type. We've already checked
269 * that all the src regs are same type
270 */
271 if (instr->srcs[0]->flags & IR3_REG_HALF) {
272 validate_assert(ctx, instr->opc == cat3_half_opc(instr->opc));
273 } else {
274 validate_assert(ctx, instr->opc == cat3_full_opc(instr->opc));
275 }
276 break;
277 case 4:
278 /* Validate that cat4 opc matches the dst type: */
279 if (instr->dsts[0]->flags & IR3_REG_HALF) {
280 validate_assert(ctx, instr->opc == cat4_half_opc(instr->opc));
281 } else {
282 validate_assert(ctx, instr->opc == cat4_full_opc(instr->opc));
283 }
284 break;
285 case 5:
286 validate_reg_size(ctx, instr->dsts[0], instr->cat5.type);
287 break;
288 case 6:
289 switch (instr->opc) {
290 case OPC_RESINFO:
291 case OPC_RESFMT:
292 validate_reg_size(ctx, instr->dsts[0], instr->cat6.type);
293 validate_reg_size(ctx, instr->srcs[0], instr->cat6.type);
294 break;
295 case OPC_L2G:
296 case OPC_G2L:
297 validate_assert(ctx, !(instr->dsts[0]->flags & IR3_REG_HALF));
298 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
299 break;
300 case OPC_STG:
301 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
302 validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
303 validate_reg_size(ctx, instr->srcs[2], instr->cat6.type);
304 validate_assert(ctx, !(instr->srcs[3]->flags & IR3_REG_HALF));
305 break;
306 case OPC_STG_A:
307 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
308 validate_assert(ctx, !(instr->srcs[2]->flags & IR3_REG_HALF));
309 validate_assert(ctx, !(instr->srcs[3]->flags & IR3_REG_HALF));
310 validate_reg_size(ctx, instr->srcs[4], instr->cat6.type);
311 validate_assert(ctx, !(instr->srcs[5]->flags & IR3_REG_HALF));
312 break;
313 case OPC_STL:
314 case OPC_STP:
315 case OPC_STLW:
316 case OPC_SPILL_MACRO:
317 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
318 validate_reg_size(ctx, instr->srcs[1], instr->cat6.type);
319 validate_assert(ctx, !(instr->srcs[2]->flags & IR3_REG_HALF));
320 break;
321 case OPC_STIB:
322 if (instr->flags & IR3_INSTR_B) {
323 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
324 validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
325 validate_reg_size(ctx, instr->srcs[2], instr->cat6.type);
326 } else {
327 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
328 validate_reg_size(ctx, instr->srcs[1], instr->cat6.type);
329 validate_assert(ctx, !(instr->srcs[2]->flags & IR3_REG_HALF));
330 }
331 break;
332 default:
333 validate_reg_size(ctx, instr->dsts[0], instr->cat6.type);
334 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
335 if (instr->srcs_count > 1)
336 validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
337 break;
338 }
339 }
340
341 if (instr->opc == OPC_META_PARALLEL_COPY) {
342 foreach_src_n (src, n, instr) {
343 validate_assert(ctx, reg_class_flags(src) ==
344 reg_class_flags(instr->dsts[n]));
345 }
346 }
347 }
348
349 static bool
is_physical_successor(struct ir3_block * block,struct ir3_block * succ)350 is_physical_successor(struct ir3_block *block, struct ir3_block *succ)
351 {
352 for (unsigned i = 0; i < ARRAY_SIZE(block->physical_successors); i++)
353 if (block->physical_successors[i] == succ)
354 return true;
355 return false;
356 }
357
358 void
ir3_validate(struct ir3 * ir)359 ir3_validate(struct ir3 *ir)
360 {
361 #ifdef NDEBUG
362 #define VALIDATE 0
363 #else
364 #define VALIDATE 1
365 #endif
366
367 if (!VALIDATE)
368 return;
369
370 struct ir3_validate_ctx *ctx = ralloc_size(NULL, sizeof(*ctx));
371
372 ctx->ir = ir;
373 ctx->defs = _mesa_pointer_set_create(ctx);
374
375 foreach_block (block, &ir->block_list) {
376 ctx->current_block = block;
377 ctx->current_instr = NULL;
378
379 /* We require that the first block does not have any predecessors,
380 * which allows us to assume that phi nodes and meta:input's do not
381 * appear in the same basic block.
382 */
383 validate_assert(
384 ctx, block != ir3_start_block(ir) || block->predecessors_count == 0);
385
386 struct ir3_instruction *prev = NULL;
387 foreach_instr (instr, &block->instr_list) {
388 ctx->current_instr = instr;
389 if (instr->opc == OPC_META_PHI) {
390 /* phis must be the first in the block */
391 validate_assert(ctx, prev == NULL || prev->opc == OPC_META_PHI);
392 validate_phi(ctx, instr);
393 } else {
394 validate_instr(ctx, instr);
395 }
396 prev = instr;
397 }
398
399 for (unsigned i = 0; i < 2; i++) {
400 if (block->successors[i]) {
401 validate_phi_src(ctx, block->successors[i], block);
402
403 ctx->current_instr = NULL;
404
405 /* Each logical successor should also be a physical successor: */
406 validate_assert(ctx, is_physical_successor(block, block->successors[i]));
407 }
408 }
409
410 validate_assert(ctx, block->successors[0] || !block->successors[1]);
411 validate_assert(ctx, block->physical_successors[0] || !block->physical_successors[1]);
412 }
413
414 ralloc_free(ctx);
415 }
416