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