• 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 (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