1 /*
2 * Copyright © 2020 Google, Inc.
3 * SPDX-License-Identifier: MIT
4 */
5
6 #include <stdlib.h>
7
8 #include "util/ralloc.h"
9
10 #include "ir3.h"
11 #include "ir3_compiler.h"
12
13 struct ir3_validate_ctx {
14 struct ir3 *ir;
15
16 /* Current block being validated: */
17 struct ir3_block *current_block;
18
19 /* Current instruction being validated: */
20 struct ir3_instruction *current_instr;
21
22 /* Set of instructions found so far, used to validate that we
23 * don't have SSA uses that occure before def's
24 */
25 struct set *defs;
26 };
27
28 static void
validate_error(struct ir3_validate_ctx * ctx,const char * condstr)29 validate_error(struct ir3_validate_ctx *ctx, const char *condstr)
30 {
31 fprintf(stderr, "validation fail: %s\n", condstr);
32 if (ctx->current_instr) {
33 fprintf(stderr, " -> for instruction: ");
34 ir3_print_instr(ctx->current_instr);
35 } else {
36 fprintf(stderr, " -> for block%u\n", block_id(ctx->current_block));
37 }
38 abort();
39 }
40
41 #define validate_assert(ctx, cond) \
42 do { \
43 if (!(cond)) { \
44 validate_error(ctx, #cond); \
45 } \
46 } while (0)
47
48 static unsigned
reg_class_flags(struct ir3_register * reg)49 reg_class_flags(struct ir3_register *reg)
50 {
51 return reg->flags & (IR3_REG_HALF | IR3_REG_SHARED | IR3_REG_PREDICATE);
52 }
53
54 static void
validate_reg(struct ir3_validate_ctx * ctx,struct ir3_register * reg)55 validate_reg(struct ir3_validate_ctx *ctx, struct ir3_register *reg)
56 {
57 if ((reg->flags & IR3_REG_SHARED) && reg->num != INVALID_REG) {
58 validate_assert(ctx, reg->num >= SHARED_REG_START);
59 validate_assert(ctx, reg->num - SHARED_REG_START < SHARED_REG_SIZE);
60 }
61 }
62
63 static void
validate_src(struct ir3_validate_ctx * ctx,struct ir3_instruction * instr,struct ir3_register * reg)64 validate_src(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr,
65 struct ir3_register *reg)
66 {
67 if (reg->flags & IR3_REG_IMMED)
68 validate_assert(ctx, ir3_valid_immediate(instr, reg->iim_val));
69
70 if (!(reg->flags & IR3_REG_SSA) || !reg->def)
71 return;
72
73 if (reg->flags & IR3_REG_PREDICATE)
74 validate_assert(ctx, !(reg->flags & (IR3_REG_SHARED | IR3_REG_HALF)));
75
76 struct ir3_register *src = reg->def;
77
78 validate_assert(ctx, _mesa_set_search(ctx->defs, src->instr));
79 validate_assert(ctx, src->wrmask == reg->wrmask);
80 validate_assert(ctx, reg_class_flags(src) == reg_class_flags(reg));
81
82 if (src->flags & IR3_REG_CONST)
83 validate_assert(ctx, !(src->flags & IR3_REG_SHARED));
84
85 if (reg->tied) {
86 validate_assert(ctx, reg->tied->tied == reg);
87 validate_assert(ctx, reg_class_flags(reg) == reg_class_flags(reg->tied));
88 validate_assert(ctx, !(reg->flags & (IR3_REG_CONST | IR3_REG_IMMED)));
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 validate_reg(ctx, reg);
101 }
102
103 /* phi sources are logically read at the end of the predecessor basic block,
104 * and we have to validate them then in order to correctly validate that the
105 * use comes after the definition for loop phis.
106 */
107 static void
validate_phi_src(struct ir3_validate_ctx * ctx,struct ir3_block * block,struct ir3_block * pred)108 validate_phi_src(struct ir3_validate_ctx *ctx, struct ir3_block *block,
109 struct ir3_block *pred)
110 {
111 unsigned pred_idx = ir3_block_get_pred_index(block, pred);
112
113 foreach_instr (phi, &block->instr_list) {
114 if (phi->opc != OPC_META_PHI)
115 break;
116
117 ctx->current_instr = phi;
118 validate_assert(ctx, phi->srcs_count == block->predecessors_count);
119 validate_src(ctx, phi, phi->srcs[pred_idx]);
120 }
121 }
122
123 static void
validate_phi(struct ir3_validate_ctx * ctx,struct ir3_instruction * phi)124 validate_phi(struct ir3_validate_ctx *ctx, struct ir3_instruction *phi)
125 {
126 _mesa_set_add(ctx->defs, phi);
127 validate_assert(ctx, phi->dsts_count == 1);
128 validate_assert(ctx, is_dest_gpr(phi->dsts[0]));
129 }
130
131 static void
validate_dst(struct ir3_validate_ctx * ctx,struct ir3_instruction * instr,struct ir3_register * reg)132 validate_dst(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr,
133 struct ir3_register *reg)
134 {
135 if (reg->tied) {
136 validate_assert(ctx, reg->tied->tied == reg);
137 validate_assert(ctx, reg_class_flags(reg->tied) == reg_class_flags(reg));
138 validate_assert(ctx, reg->tied->wrmask == reg->wrmask);
139 if (reg->flags & IR3_REG_ARRAY) {
140 validate_assert(ctx, reg->tied->array.base == reg->array.base);
141 validate_assert(ctx, reg->tied->size == reg->size);
142 }
143 bool found = false;
144 foreach_src (src, instr) {
145 if (src == reg->tied) {
146 found = true;
147 break;
148 }
149 }
150 validate_assert(ctx,
151 found && "tied register not in the same instruction");
152 }
153
154 if (reg->flags & IR3_REG_SSA)
155 validate_assert(ctx, reg->instr == instr);
156
157 if (reg->flags & IR3_REG_RELATIV)
158 validate_assert(ctx, instr->address);
159
160 validate_reg(ctx, reg);
161 }
162
163 #define validate_reg_size(ctx, reg, type) \
164 validate_assert( \
165 ctx, (type_size(type) <= 16) == !!((reg)->flags & IR3_REG_HALF))
166
167 static bool
block_contains(struct ir3_block * block,struct ir3_instruction * instr)168 block_contains(struct ir3_block *block, struct ir3_instruction *instr)
169 {
170 foreach_instr (block_instr, &block->instr_list) {
171 if (block_instr == instr)
172 return true;
173 }
174
175 return false;
176 }
177
178 static void
validate_rpt(struct ir3_validate_ctx * ctx,struct ir3_instruction * instr)179 validate_rpt(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr)
180 {
181 if (ir3_instr_is_first_rpt(instr)) {
182 /* All instructions in a repeat group should be in the same block as the
183 * first one.
184 */
185 foreach_instr_rpt (rpt, instr) {
186 validate_assert(ctx, rpt->block == instr->block);
187
188 /* Validate that the block actually contains the repeat. This would
189 * fail if, for example, list_delinit is called instead of
190 * ir3_instr_remove.
191 */
192 validate_assert(ctx, block_contains(instr->block, rpt));
193 }
194 } else if (instr->repeat) {
195 validate_assert(ctx, ir3_supports_rpt(ctx->ir->compiler, instr->opc));
196 validate_assert(ctx, !instr->nop);
197 }
198 }
199
200 static void
validate_instr(struct ir3_validate_ctx * ctx,struct ir3_instruction * instr)201 validate_instr(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr)
202 {
203 struct ir3_register *last_reg = NULL;
204
205 validate_rpt(ctx, instr);
206
207 foreach_src_n (reg, n, instr) {
208 if (reg->flags & IR3_REG_RELATIV)
209 validate_assert(ctx, instr->address);
210
211 validate_src(ctx, instr, reg);
212
213 /* Validate that all src's are either half of full.
214 *
215 * Note: tex instructions w/ .s2en are a bit special in that the
216 * tex/samp src reg is half-reg for non-bindless and full for
217 * bindless, irrespective of the precision of other srcs. The
218 * tex/samp src is the first src reg when .s2en is set
219 */
220 if (reg->tied) {
221 /* must have the same size as the destination, handled in
222 * validate_reg().
223 */
224 } else if (reg == instr->address) {
225 validate_assert(ctx, reg->flags & IR3_REG_HALF);
226 } else if ((instr->flags & IR3_INSTR_S2EN) && (n < 2)) {
227 if (n == 0) {
228 if (instr->flags & IR3_INSTR_B)
229 validate_assert(ctx, !(reg->flags & IR3_REG_HALF));
230 else
231 validate_assert(ctx, reg->flags & IR3_REG_HALF);
232 }
233 } else if (opc_cat(instr->opc) == 1 || opc_cat(instr->opc) == 6) {
234 /* handled below */
235 } else if (opc_cat(instr->opc) == 0) {
236 /* end/chmask/etc are allowed to have different size sources */
237 } else if (instr->opc == OPC_META_PARALLEL_COPY) {
238 /* pcopy sources have to match with their destination but can have
239 * different sizes from each other.
240 */
241 } else if (instr->opc == OPC_ANY_MACRO || instr->opc == OPC_ALL_MACRO ||
242 instr->opc == OPC_READ_FIRST_MACRO ||
243 instr->opc == OPC_READ_COND_MACRO) {
244 /* nothing yet */
245 } else if (n > 0) {
246 validate_assert(ctx, (last_reg->flags & IR3_REG_HALF) ==
247 (reg->flags & IR3_REG_HALF));
248 }
249
250 if (is_scalar_alu(instr, ctx->ir->compiler) && reg != instr->address)
251 validate_assert(ctx, reg->flags & (IR3_REG_SHARED | IR3_REG_IMMED |
252 IR3_REG_CONST));
253
254 last_reg = reg;
255 }
256
257 for (unsigned i = 0; i < instr->dsts_count; i++) {
258 struct ir3_register *reg = instr->dsts[i];
259
260 validate_dst(ctx, instr, reg);
261 }
262
263 _mesa_set_add(ctx->defs, instr);
264
265 if ((opc_cat(instr->opc) == 2 || opc_cat(instr->opc) == 3 ||
266 opc_cat(instr->opc) == 4)) {
267 validate_assert(ctx, !(instr->dsts[0]->flags & IR3_REG_SHARED) ||
268 ctx->ir->compiler->has_scalar_alu);
269 }
270
271 /* Check that src/dst types match the register types, and for
272 * instructions that have different opcodes depending on type,
273 * that the opcodes are correct.
274 */
275 switch (opc_cat(instr->opc)) {
276 case 1: /* move instructions */
277 if (instr->opc == OPC_MOVMSK || instr->opc == OPC_BALLOT_MACRO) {
278 validate_assert(ctx, instr->dsts_count == 1);
279 validate_assert(ctx, instr->dsts[0]->flags & IR3_REG_SHARED);
280 validate_assert(ctx, !(instr->dsts[0]->flags & IR3_REG_HALF));
281 validate_assert(
282 ctx, util_is_power_of_two_or_zero(instr->dsts[0]->wrmask + 1));
283 } else if (instr->opc == OPC_ANY_MACRO || instr->opc == OPC_ALL_MACRO ||
284 instr->opc == OPC_READ_FIRST_MACRO ||
285 instr->opc == OPC_READ_COND_MACRO) {
286 /* nothing yet */
287 } else if (instr->opc == OPC_ELECT_MACRO || instr->opc == OPC_SHPS_MACRO) {
288 validate_assert(ctx, instr->dsts_count == 1);
289 validate_assert(ctx, !(instr->dsts[0]->flags & IR3_REG_SHARED));
290 } else if (instr->opc == OPC_SCAN_MACRO) {
291 validate_assert(ctx, instr->dsts_count == 3);
292 validate_assert(ctx, instr->srcs_count == 2);
293 validate_assert(ctx, reg_class_flags(instr->dsts[0]) ==
294 reg_class_flags(instr->srcs[0]));
295 validate_assert(ctx, reg_class_flags(instr->dsts[1]) ==
296 reg_class_flags(instr->srcs[0]));
297 validate_assert(ctx, reg_class_flags(instr->dsts[2]) == IR3_REG_SHARED);
298 } else if (instr->opc == OPC_SCAN_CLUSTERS_MACRO) {
299 validate_assert(ctx, instr->dsts_count >= 2 && instr->dsts_count < 5);
300 validate_assert(ctx, instr->srcs_count >= 2 && instr->srcs_count < 4);
301 validate_assert(ctx,
302 reg_class_flags(instr->dsts[0]) == IR3_REG_SHARED);
303 validate_assert(ctx, reg_class_flags(instr->dsts[1]) ==
304 reg_class_flags(instr->srcs[1]));
305
306 /* exclusive scan */
307 if (instr->srcs_count == 3) {
308 validate_assert(ctx, instr->dsts_count >= 3);
309 validate_assert(ctx, reg_class_flags(instr->srcs[2]) ==
310 reg_class_flags(instr->srcs[1]));
311 validate_assert(ctx, reg_class_flags(instr->dsts[2]) ==
312 reg_class_flags(instr->srcs[1]));
313 }
314
315 /* scratch register */
316 validate_assert(ctx,
317 reg_class_flags(instr->dsts[instr->dsts_count - 1]) ==
318 reg_class_flags(instr->srcs[1]));
319 } else {
320 foreach_dst (dst, instr)
321 validate_reg_size(ctx, dst, instr->cat1.dst_type);
322 foreach_src (src, instr) {
323 if (!src->tied && src != instr->address)
324 validate_reg_size(ctx, src, instr->cat1.src_type);
325 }
326
327 switch (instr->opc) {
328 case OPC_SWZ:
329 validate_assert(ctx, instr->srcs_count == 2);
330 validate_assert(ctx, instr->dsts_count == 2);
331 break;
332 case OPC_GAT:
333 validate_assert(ctx, instr->srcs_count == 4);
334 validate_assert(ctx, instr->dsts_count == 1);
335 break;
336 case OPC_SCT:
337 validate_assert(ctx, instr->srcs_count == 1);
338 validate_assert(ctx, instr->dsts_count == 4);
339 break;
340 default:
341 break;
342 }
343 }
344
345 if (instr->opc != OPC_MOV)
346 validate_assert(ctx, !instr->address);
347
348 break;
349 case 3:
350 /* Validate that cat3 opc matches the src type. We've already checked
351 * that all the src regs are same type
352 */
353 if (instr->srcs[0]->flags & IR3_REG_HALF) {
354 validate_assert(ctx, instr->opc == cat3_half_opc(instr->opc));
355 } else {
356 validate_assert(ctx, instr->opc == cat3_full_opc(instr->opc));
357 }
358 break;
359 case 4:
360 /* Validate that cat4 opc matches the dst type: */
361 if (instr->dsts[0]->flags & IR3_REG_HALF) {
362 validate_assert(ctx, instr->opc == cat4_half_opc(instr->opc));
363 } else {
364 validate_assert(ctx, instr->opc == cat4_full_opc(instr->opc));
365 }
366 break;
367 case 5:
368 validate_reg_size(ctx, instr->dsts[0], instr->cat5.type);
369 break;
370 case 6:
371 switch (instr->opc) {
372 case OPC_RESINFO:
373 case OPC_RESFMT:
374 if (instr->dsts_count > 0)
375 validate_reg_size(ctx, instr->dsts[0], instr->cat6.type);
376 validate_reg_size(ctx, instr->srcs[0], instr->cat6.type);
377 break;
378 case OPC_L2G:
379 case OPC_G2L:
380 validate_assert(ctx, !(instr->dsts[0]->flags & IR3_REG_HALF));
381 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
382 break;
383 case OPC_STG:
384 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
385 validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
386 validate_reg_size(ctx, instr->srcs[2], instr->cat6.type);
387 validate_assert(ctx, !(instr->srcs[3]->flags & IR3_REG_HALF));
388 break;
389 case OPC_STG_A:
390 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
391 validate_assert(ctx, !(instr->srcs[2]->flags & IR3_REG_HALF));
392 validate_assert(ctx, !(instr->srcs[3]->flags & IR3_REG_HALF));
393 validate_reg_size(ctx, instr->srcs[4], instr->cat6.type);
394 validate_assert(ctx, !(instr->srcs[5]->flags & IR3_REG_HALF));
395 break;
396 case OPC_STL:
397 case OPC_STP:
398 case OPC_STLW:
399 case OPC_SPILL_MACRO:
400 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
401 validate_reg_size(ctx, instr->srcs[1], instr->cat6.type);
402 validate_assert(ctx, !(instr->srcs[2]->flags & IR3_REG_HALF));
403 break;
404 case OPC_STIB:
405 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
406 validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
407 validate_reg_size(ctx, instr->srcs[3], instr->cat6.type);
408 break;
409 case OPC_GETFIBERID:
410 case OPC_GETSPID:
411 case OPC_GETWID:
412 validate_reg_size(ctx, instr->dsts[0], instr->cat6.type);
413 break;
414 case OPC_STC:
415 case OPC_STSC:
416 validate_reg_size(ctx, instr->srcs[0], instr->cat6.type);
417 validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
418 break;
419 case OPC_PUSH_CONSTS_LOAD_MACRO:
420 break;
421 case OPC_LDC:
422 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
423 validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
424 validate_assert(ctx, !!(instr->dsts[0]->flags & IR3_REG_SHARED) ==
425 !!(instr->flags & IR3_INSTR_U));
426 break;
427 case OPC_LDC_K:
428 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
429 validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
430 break;
431 case OPC_LDP:
432 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
433 validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
434 validate_assert(ctx, !(instr->srcs[2]->flags & IR3_REG_HALF));
435 validate_reg_size(ctx, instr->dsts[0], instr->cat6.type);
436 break;
437 default:
438 validate_reg_size(ctx, instr->dsts[0], instr->cat6.type);
439 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
440 if (instr->srcs_count > 1)
441 validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
442 break;
443 }
444 }
445
446 if (instr->opc == OPC_META_PARALLEL_COPY) {
447 foreach_src_n (src, n, instr) {
448 validate_assert(ctx, (src->flags & IR3_REG_HALF) ==
449 (instr->dsts[n]->flags & IR3_REG_HALF));
450 if (instr->dsts[n]->flags & IR3_REG_SHARED) {
451 validate_assert(ctx, src->flags & (IR3_REG_SHARED | IR3_REG_CONST |
452 IR3_REG_IMMED));
453 } else {
454 validate_assert(ctx, !(src->flags & IR3_REG_SHARED));
455 }
456 }
457 }
458 }
459
460 static bool
is_physical_successor(struct ir3_block * block,struct ir3_block * succ)461 is_physical_successor(struct ir3_block *block, struct ir3_block *succ)
462 {
463 for (unsigned i = 0; i < block->physical_successors_count; i++)
464 if (block->physical_successors[i] == succ)
465 return true;
466 return false;
467 }
468
469 void
ir3_validate(struct ir3 * ir)470 ir3_validate(struct ir3 *ir)
471 {
472 #ifdef NDEBUG
473 #define VALIDATE 0
474 #else
475 #define VALIDATE 1
476 #endif
477
478 if (!VALIDATE)
479 return;
480
481 struct ir3_validate_ctx *ctx = ralloc_size(NULL, sizeof(*ctx));
482
483 ctx->ir = ir;
484 ctx->defs = _mesa_pointer_set_create(ctx);
485
486 foreach_block (block, &ir->block_list) {
487 ctx->current_block = block;
488 ctx->current_instr = NULL;
489
490 /* We require that the first block does not have any predecessors,
491 * which allows us to assume that phi nodes and meta:input's do not
492 * appear in the same basic block.
493 */
494 validate_assert(
495 ctx, block != ir3_start_block(ir) || block->predecessors_count == 0);
496
497 struct ir3_instruction *prev = NULL;
498 foreach_instr (instr, &block->instr_list) {
499 ctx->current_instr = instr;
500 validate_assert(ctx, instr->block == block);
501 if (instr->opc == OPC_META_PHI) {
502 /* phis must be the first in the block */
503 validate_assert(ctx, prev == NULL || prev->opc == OPC_META_PHI);
504 validate_phi(ctx, instr);
505 } else {
506 validate_instr(ctx, instr);
507 }
508 prev = instr;
509 }
510
511 for (unsigned i = 0; i < 2; i++) {
512 if (block->successors[i]) {
513 validate_phi_src(ctx, block->successors[i], block);
514
515 ctx->current_instr = NULL;
516
517 /* Each logical successor should also be a physical successor: */
518 if (block->physical_successors_count > 0)
519 validate_assert(ctx, is_physical_successor(block, block->successors[i]));
520 }
521 }
522
523 validate_assert(ctx, block->successors[0] || !block->successors[1]);
524 }
525
526 ralloc_free(ctx);
527 }
528