• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 (src->flags & IR3_REG_CONST)
88       validate_assert(ctx, !(src->flags & IR3_REG_SHARED));
89 
90    if (reg->tied) {
91       validate_assert(ctx, reg->tied->tied == reg);
92       bool found = false;
93       foreach_dst (dst, instr) {
94          if (dst == reg->tied) {
95             found = true;
96             break;
97          }
98       }
99       validate_assert(ctx,
100                       found && "tied register not in the same instruction");
101    }
102 }
103 
104 /* phi sources are logically read at the end of the predecessor basic block,
105  * and we have to validate them then in order to correctly validate that the
106  * use comes after the definition for loop phis.
107  */
108 static void
validate_phi_src(struct ir3_validate_ctx * ctx,struct ir3_block * block,struct ir3_block * pred)109 validate_phi_src(struct ir3_validate_ctx *ctx, struct ir3_block *block,
110                  struct ir3_block *pred)
111 {
112    unsigned pred_idx = ir3_block_get_pred_index(block, pred);
113 
114    foreach_instr (phi, &block->instr_list) {
115       if (phi->opc != OPC_META_PHI)
116          break;
117 
118       ctx->current_instr = phi;
119       validate_assert(ctx, phi->srcs_count == block->predecessors_count);
120       validate_src(ctx, phi, phi->srcs[pred_idx]);
121    }
122 }
123 
124 static void
validate_phi(struct ir3_validate_ctx * ctx,struct ir3_instruction * phi)125 validate_phi(struct ir3_validate_ctx *ctx, struct ir3_instruction *phi)
126 {
127    _mesa_set_add(ctx->defs, phi);
128    validate_assert(ctx, phi->dsts_count == 1);
129    validate_assert(ctx, is_dest_gpr(phi->dsts[0]));
130 }
131 
132 static void
validate_dst(struct ir3_validate_ctx * ctx,struct ir3_instruction * instr,struct ir3_register * reg)133 validate_dst(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr,
134              struct ir3_register *reg)
135 {
136    if (reg->tied) {
137       validate_assert(ctx, reg->tied->tied == reg);
138       validate_assert(ctx, reg_class_flags(reg->tied) == reg_class_flags(reg));
139       validate_assert(ctx, reg->tied->wrmask == reg->wrmask);
140       if (reg->flags & IR3_REG_ARRAY) {
141          validate_assert(ctx, reg->tied->array.base == reg->array.base);
142          validate_assert(ctx, reg->tied->size == reg->size);
143       }
144       bool found = false;
145       foreach_src (src, instr) {
146          if (src == reg->tied) {
147             found = true;
148             break;
149          }
150       }
151       validate_assert(ctx,
152                       found && "tied register not in the same instruction");
153    }
154 
155    if (reg->flags & IR3_REG_SSA)
156       validate_assert(ctx, reg->instr == instr);
157 
158    if (reg->flags & IR3_REG_RELATIV)
159       validate_assert(ctx, instr->address);
160 }
161 
162 #define validate_reg_size(ctx, reg, type)                                      \
163    validate_assert(                                                            \
164       ctx, (type_size(type) <= 16) == !!((reg)->flags & IR3_REG_HALF))
165 
166 static void
validate_instr(struct ir3_validate_ctx * ctx,struct ir3_instruction * instr)167 validate_instr(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr)
168 {
169    struct ir3_register *last_reg = NULL;
170 
171    foreach_src_n (reg, n, instr) {
172       if (reg->flags & IR3_REG_RELATIV)
173          validate_assert(ctx, instr->address);
174 
175       validate_src(ctx, instr, reg);
176 
177       /* Validate that all src's are either half of full.
178        *
179        * Note: tex instructions w/ .s2en are a bit special in that the
180        * tex/samp src reg is half-reg for non-bindless and full for
181        * bindless, irrespective of the precision of other srcs. The
182        * tex/samp src is the first src reg when .s2en is set
183        */
184       if (reg->tied) {
185          /* must have the same size as the destination, handled in
186           * validate_reg().
187           */
188       } else if (reg == instr->address) {
189          validate_assert(ctx, reg->flags & IR3_REG_HALF);
190       } else if ((instr->flags & IR3_INSTR_S2EN) && (n < 2)) {
191          if (n == 0) {
192             if (instr->flags & IR3_INSTR_B)
193                validate_assert(ctx, !(reg->flags & IR3_REG_HALF));
194             else
195                validate_assert(ctx, reg->flags & IR3_REG_HALF);
196          }
197       } else if (opc_cat(instr->opc) == 1 || opc_cat(instr->opc) == 6) {
198          /* handled below */
199       } else if (opc_cat(instr->opc) == 0) {
200          /* end/chmask/etc are allowed to have different size sources */
201       } else if (instr->opc == OPC_META_PARALLEL_COPY) {
202          /* pcopy sources have to match with their destination but can have
203           * different sizes from each other.
204           */
205       } else if (instr->opc == OPC_ANY_MACRO || instr->opc == OPC_ALL_MACRO ||
206                  instr->opc == OPC_READ_FIRST_MACRO ||
207                  instr->opc == OPC_READ_COND_MACRO) {
208          /* nothing yet */
209       } else if (n > 0) {
210          validate_assert(ctx, (last_reg->flags & IR3_REG_HALF) ==
211                                  (reg->flags & IR3_REG_HALF));
212       }
213 
214       last_reg = reg;
215    }
216 
217    for (unsigned i = 0; i < instr->dsts_count; i++) {
218       struct ir3_register *reg = instr->dsts[i];
219 
220       validate_dst(ctx, instr, reg);
221    }
222 
223    _mesa_set_add(ctx->defs, instr);
224 
225    /* Check that src/dst types match the register types, and for
226     * instructions that have different opcodes depending on type,
227     * that the opcodes are correct.
228     */
229    switch (opc_cat(instr->opc)) {
230    case 1: /* move instructions */
231       if (instr->opc == OPC_MOVMSK || instr->opc == OPC_BALLOT_MACRO) {
232          validate_assert(ctx, instr->dsts_count == 1);
233          validate_assert(ctx, instr->dsts[0]->flags & IR3_REG_SHARED);
234          validate_assert(ctx, !(instr->dsts[0]->flags & IR3_REG_HALF));
235          validate_assert(
236             ctx, util_is_power_of_two_or_zero(instr->dsts[0]->wrmask + 1));
237       } else if (instr->opc == OPC_ANY_MACRO || instr->opc == OPC_ALL_MACRO ||
238                  instr->opc == OPC_READ_FIRST_MACRO ||
239                  instr->opc == OPC_READ_COND_MACRO) {
240          /* nothing yet */
241       } else if (instr->opc == OPC_ELECT_MACRO || instr->opc == OPC_SHPS_MACRO) {
242          validate_assert(ctx, instr->dsts_count == 1);
243          validate_assert(ctx, !(instr->dsts[0]->flags & IR3_REG_SHARED));
244       } else if (instr->opc == OPC_SCAN_MACRO) {
245          validate_assert(ctx, instr->dsts_count == 3);
246          validate_assert(ctx, instr->srcs_count == 2);
247          validate_assert(ctx, reg_class_flags(instr->dsts[0]) ==
248                               reg_class_flags(instr->srcs[0]));
249          validate_assert(ctx, reg_class_flags(instr->dsts[1]) ==
250                               reg_class_flags(instr->srcs[0]));
251          validate_assert(ctx, reg_class_flags(instr->dsts[2]) == IR3_REG_SHARED);
252       } else if (instr->opc == OPC_SCAN_CLUSTERS_MACRO) {
253          validate_assert(ctx, instr->dsts_count >= 2 && instr->dsts_count < 5);
254          validate_assert(ctx, instr->srcs_count >= 2 && instr->srcs_count < 4);
255          validate_assert(ctx,
256                          reg_class_flags(instr->dsts[0]) == IR3_REG_SHARED);
257          validate_assert(ctx, reg_class_flags(instr->dsts[1]) ==
258                                  reg_class_flags(instr->srcs[1]));
259 
260          /* exclusive scan */
261          if (instr->srcs_count == 3) {
262             validate_assert(ctx, instr->dsts_count >= 3);
263             validate_assert(ctx, reg_class_flags(instr->srcs[2]) ==
264                                     reg_class_flags(instr->srcs[1]));
265             validate_assert(ctx, reg_class_flags(instr->dsts[2]) ==
266                                     reg_class_flags(instr->srcs[1]));
267          }
268 
269          /* scratch register */
270          validate_assert(ctx,
271                          reg_class_flags(instr->dsts[instr->dsts_count - 1]) ==
272                             reg_class_flags(instr->srcs[1]));
273       } else {
274          foreach_dst (dst, instr)
275             validate_reg_size(ctx, dst, instr->cat1.dst_type);
276          foreach_src (src, instr) {
277             if (!src->tied && src != instr->address)
278                validate_reg_size(ctx, src, instr->cat1.src_type);
279          }
280 
281          switch (instr->opc) {
282          case OPC_SWZ:
283             validate_assert(ctx, instr->srcs_count == 2);
284             validate_assert(ctx, instr->dsts_count == 2);
285             break;
286          case OPC_GAT:
287             validate_assert(ctx, instr->srcs_count == 4);
288             validate_assert(ctx, instr->dsts_count == 1);
289             break;
290          case OPC_SCT:
291             validate_assert(ctx, instr->srcs_count == 1);
292             validate_assert(ctx, instr->dsts_count == 4);
293             break;
294          default:
295             break;
296          }
297       }
298 
299       if (instr->opc != OPC_MOV)
300          validate_assert(ctx, !instr->address);
301 
302       break;
303    case 3:
304       /* Validate that cat3 opc matches the src type.  We've already checked
305        * that all the src regs are same type
306        */
307       if (instr->srcs[0]->flags & IR3_REG_HALF) {
308          validate_assert(ctx, instr->opc == cat3_half_opc(instr->opc));
309       } else {
310          validate_assert(ctx, instr->opc == cat3_full_opc(instr->opc));
311       }
312       break;
313    case 4:
314       /* Validate that cat4 opc matches the dst type: */
315       if (instr->dsts[0]->flags & IR3_REG_HALF) {
316          validate_assert(ctx, instr->opc == cat4_half_opc(instr->opc));
317       } else {
318          validate_assert(ctx, instr->opc == cat4_full_opc(instr->opc));
319       }
320       break;
321    case 5:
322       validate_reg_size(ctx, instr->dsts[0], instr->cat5.type);
323       break;
324    case 6:
325       switch (instr->opc) {
326       case OPC_RESINFO:
327       case OPC_RESFMT:
328          validate_reg_size(ctx, instr->dsts[0], instr->cat6.type);
329          validate_reg_size(ctx, instr->srcs[0], instr->cat6.type);
330          break;
331       case OPC_L2G:
332       case OPC_G2L:
333          validate_assert(ctx, !(instr->dsts[0]->flags & IR3_REG_HALF));
334          validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
335          break;
336       case OPC_STG:
337          validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
338          validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
339          validate_reg_size(ctx, instr->srcs[2], instr->cat6.type);
340          validate_assert(ctx, !(instr->srcs[3]->flags & IR3_REG_HALF));
341          break;
342       case OPC_STG_A:
343          validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
344          validate_assert(ctx, !(instr->srcs[2]->flags & IR3_REG_HALF));
345          validate_assert(ctx, !(instr->srcs[3]->flags & IR3_REG_HALF));
346          validate_reg_size(ctx, instr->srcs[4], instr->cat6.type);
347          validate_assert(ctx, !(instr->srcs[5]->flags & IR3_REG_HALF));
348          break;
349       case OPC_STL:
350       case OPC_STP:
351       case OPC_STLW:
352       case OPC_SPILL_MACRO:
353          validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
354          validate_reg_size(ctx, instr->srcs[1], instr->cat6.type);
355          validate_assert(ctx, !(instr->srcs[2]->flags & IR3_REG_HALF));
356          break;
357       case OPC_STIB:
358          validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
359          validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
360          validate_reg_size(ctx, instr->srcs[2], instr->cat6.type);
361          break;
362       case OPC_GETFIBERID:
363       case OPC_GETSPID:
364       case OPC_GETWID:
365          validate_reg_size(ctx, instr->dsts[0], instr->cat6.type);
366          break;
367       case OPC_STC:
368       case OPC_STSC:
369          validate_reg_size(ctx, instr->srcs[0], instr->cat6.type);
370          validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
371          break;
372       case OPC_LDC_K:
373          validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
374          validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
375          break;
376       default:
377          validate_reg_size(ctx, instr->dsts[0], instr->cat6.type);
378          validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
379          if (instr->srcs_count > 1)
380             validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
381          break;
382       }
383    }
384 
385    if (instr->opc == OPC_META_PARALLEL_COPY) {
386       foreach_src_n (src, n, instr) {
387          validate_assert(ctx, reg_class_flags(src) ==
388                          reg_class_flags(instr->dsts[n]));
389       }
390    }
391 }
392 
393 static bool
is_physical_successor(struct ir3_block * block,struct ir3_block * succ)394 is_physical_successor(struct ir3_block *block, struct ir3_block *succ)
395 {
396    for (unsigned i = 0; i < block->physical_successors_count; i++)
397       if (block->physical_successors[i] == succ)
398          return true;
399    return false;
400 }
401 
402 void
ir3_validate(struct ir3 * ir)403 ir3_validate(struct ir3 *ir)
404 {
405 #ifdef NDEBUG
406 #define VALIDATE 0
407 #else
408 #define VALIDATE 1
409 #endif
410 
411    if (!VALIDATE)
412       return;
413 
414    struct ir3_validate_ctx *ctx = ralloc_size(NULL, sizeof(*ctx));
415 
416    ctx->ir = ir;
417    ctx->defs = _mesa_pointer_set_create(ctx);
418 
419    foreach_block (block, &ir->block_list) {
420       ctx->current_block = block;
421       ctx->current_instr = NULL;
422 
423       /* We require that the first block does not have any predecessors,
424        * which allows us to assume that phi nodes and meta:input's do not
425        * appear in the same basic block.
426        */
427       validate_assert(
428          ctx, block != ir3_start_block(ir) || block->predecessors_count == 0);
429 
430       struct ir3_instruction *prev = NULL;
431       foreach_instr (instr, &block->instr_list) {
432          ctx->current_instr = instr;
433          if (instr->opc == OPC_META_PHI) {
434             /* phis must be the first in the block */
435             validate_assert(ctx, prev == NULL || prev->opc == OPC_META_PHI);
436             validate_phi(ctx, instr);
437          } else {
438             validate_instr(ctx, instr);
439          }
440          prev = instr;
441       }
442 
443       for (unsigned i = 0; i < 2; i++) {
444          if (block->successors[i]) {
445             validate_phi_src(ctx, block->successors[i], block);
446 
447             ctx->current_instr = NULL;
448 
449             /* Each logical successor should also be a physical successor: */
450             if (block->physical_successors_count > 0)
451                validate_assert(ctx, is_physical_successor(block, block->successors[i]));
452          }
453       }
454 
455       validate_assert(ctx, block->successors[0] || !block->successors[1]);
456    }
457 
458    ralloc_free(ctx);
459 }
460