pass_analysis.c (31714B)
1 #include <string.h> 2 3 #include "core/arena.h" 4 #include "core/core.h" 5 #include "core/slice.h" 6 #include "opt/opt_internal.h" 7 8 #define OPT_BLK_NONE 0xffffffffu 9 10 #ifndef NDEBUG 11 static SrcLoc opt_no_loc(void) { 12 SrcLoc loc = {0, 0, 0}; 13 return loc; 14 } 15 16 static void opt_fail(Func* f, const char* stage, const char* msg, u32 a, 17 u32 b) { 18 compiler_panic(f->c, opt_no_loc(), "opt verify[%.*s]: %.*s (%u, %u)", 19 SLICE_ARG(slice_from_cstr(stage ? stage : "?")), 20 SLICE_ARG(slice_from_cstr(msg)), (unsigned)a, (unsigned)b); 21 } 22 23 /* Does `hay` contain the bytes of NUL-terminated `needle`? Length-explicit 24 * substring search; no strstr. */ 25 static int slice_contains_cstr(Slice hay, const char* needle) { 26 Slice n = slice_from_cstr(needle); 27 size_t i; 28 if (n.len == 0) return 1; 29 if (hay.len < n.len) return 0; 30 for (i = 0; i + n.len <= hay.len; ++i) 31 if (memcmp(hay.s + i, n.s, n.len) == 0) return 1; 32 return 0; 33 } 34 35 static int verify_stage_is_ssa(const char* stage) { 36 Slice s = slice_from_cstr(stage); 37 return stage && slice_contains_cstr(s, "ssa") && 38 !slice_contains_cstr(s, "pre-ssa"); 39 } 40 41 static u8 verify_type_reg_class(Func* f, KitCgTypeId ty) { 42 return opt_value_reg_class(f->c, ty); 43 } 44 45 static void verify_frame_slot(Func* f, const char* stage, FrameSlot slot, 46 const char* msg) { 47 if (slot == FRAME_SLOT_NONE || slot > f->nframe_slots) 48 opt_fail(f, stage, msg, slot, f->nframe_slots); 49 } 50 51 static void verify_storage(Func* f, const char* stage, CGLocalStorage st, 52 KitCgTypeId type, u8 expect_cls, const char* msg) { 53 switch ((CGLocalStorageKind)st.kind) { 54 case CG_LOCAL_STORAGE_FRAME: 55 verify_frame_slot(f, stage, st.v.frame_slot, msg); 56 break; 57 case CG_LOCAL_STORAGE_REG: { 58 PReg r = (PReg)st.v.reg; 59 if (r == PREG_NONE || r == 0 || r >= opt_reg_count(f)) 60 opt_fail(f, stage, msg, r, opt_reg_count(f)); 61 if (!f->opt_reg_ssa && f->preg_cls && f->preg_cls[r] != expect_cls) 62 opt_fail(f, stage, "storage class mismatch", r, f->preg_cls[r]); 63 if (!f->opt_reg_ssa && type && f->preg_type && f->preg_type[r] && 64 f->preg_type[r] != type) 65 opt_fail(f, stage, "storage type mismatch", r, type); 66 break; 67 } 68 default: 69 opt_fail(f, stage, "bad storage kind", st.kind, 0); 70 break; 71 } 72 } 73 74 static void verify_operand_shape(Func* f, const char* stage, const Operand* op, 75 int physical_regs) { 76 if (!op) return; 77 switch ((OptOperandKind)op->kind) { 78 case OPK_IMM: 79 case OPK_GLOBAL: 80 break; 81 case OPK_LOCAL: 82 verify_frame_slot(f, stage, op->v.frame_slot, "bad local frame slot"); 83 break; 84 case OPK_REG: 85 if (op->cls >= OPT_REG_CLASSES) 86 opt_fail(f, stage, "bad operand class", op->cls, OPT_REG_CLASSES); 87 if (physical_regs) { 88 if (op->v.reg == (Reg)REG_NONE || op->v.reg >= OPT_MAX_HARD_REGS) 89 opt_fail(f, stage, "bad physical operand reg", op->v.reg, 90 OPT_MAX_HARD_REGS); 91 } 92 break; 93 case OPK_INDIRECT: 94 if (op->cls >= OPT_REG_CLASSES) 95 opt_fail(f, stage, "bad indirect class", op->cls, OPT_REG_CLASSES); 96 if (physical_regs) { 97 if (op->v.ind.base == (Reg)REG_NONE || 98 op->v.ind.base >= OPT_MAX_HARD_REGS) 99 opt_fail(f, stage, "bad physical indirect base", op->v.ind.base, 100 OPT_MAX_HARD_REGS); 101 if (op->v.ind.index != (Reg)REG_NONE && 102 op->v.ind.index >= OPT_MAX_HARD_REGS) 103 opt_fail(f, stage, "bad physical indirect index", op->v.ind.index, 104 OPT_MAX_HARD_REGS); 105 } 106 break; 107 default: 108 opt_fail(f, stage, "bad operand kind", op->kind, 0); 109 break; 110 } 111 } 112 113 static void verify_abivalue_shape(Func* f, const char* stage, CGABIValue* v, 114 int physical_regs) { 115 if (!v) return; 116 verify_operand_shape(f, stage, &v->storage, physical_regs); 117 for (u32 i = 0; i < v->nparts; ++i) 118 verify_operand_shape(f, stage, &v->parts[i].op, physical_regs); 119 } 120 121 static void verify_call_plan_shape(Func* f, const char* stage, CGCallPlan* plan, 122 int physical_regs) { 123 if (!plan) return; 124 verify_operand_shape(f, stage, &plan->callee, physical_regs); 125 for (u32 i = 0; i < plan->nargs; ++i) { 126 verify_operand_shape(f, stage, &plan->args[i].src, physical_regs); 127 if (plan->args[i].dst_kind == CG_CALL_PLAN_REG && 128 plan->args[i].dst_reg >= OPT_MAX_HARD_REGS) 129 opt_fail(f, stage, "bad call-plan dst reg", plan->args[i].dst_reg, 130 OPT_MAX_HARD_REGS); 131 } 132 for (u32 i = 0; i < plan->nrets; ++i) { 133 verify_operand_shape(f, stage, &plan->rets[i].dst, physical_regs); 134 if (plan->rets[i].src_reg >= OPT_MAX_HARD_REGS) 135 opt_fail(f, stage, "bad call-plan ret reg", plan->rets[i].src_reg, 136 OPT_MAX_HARD_REGS); 137 } 138 } 139 140 static void verify_aux_shapes(Func* f, const char* stage, Inst* in, 141 int physical_regs) { 142 switch ((IROp)in->op) { 143 case IR_CALL: { 144 IRCallAux* aux = (IRCallAux*)in->extra.aux; 145 if (!aux) break; 146 if (aux->use_plan_replay) { 147 verify_call_plan_shape(f, stage, &aux->plan, physical_regs); 148 } else { 149 verify_operand_shape(f, stage, &aux->desc.callee, physical_regs); 150 for (u32 i = 0; i < aux->desc.nargs; ++i) 151 verify_abivalue_shape(f, stage, (CGABIValue*)&aux->desc.args[i], 152 physical_regs); 153 verify_abivalue_shape(f, stage, &aux->desc.ret, physical_regs); 154 } 155 break; 156 } 157 case IR_RET: { 158 IRRetAux* aux = (IRRetAux*)in->extra.aux; 159 if (aux && aux->present) 160 verify_abivalue_shape(f, stage, &aux->val, physical_regs); 161 break; 162 } 163 case IR_SCOPE_BEGIN: 164 break; 165 case IR_ASM_BLOCK: { 166 IRAsmAux* aux = (IRAsmAux*)in->extra.aux; 167 if (!aux) break; 168 for (u32 i = 0; i < aux->nin; ++i) 169 verify_operand_shape(f, stage, &aux->in_ops[i], physical_regs); 170 for (u32 i = 0; i < aux->nout; ++i) 171 verify_operand_shape(f, stage, &aux->out_ops[i], physical_regs); 172 break; 173 } 174 case IR_INTRINSIC: { 175 IRIntrinAux* aux = (IRIntrinAux*)in->extra.aux; 176 if (!aux) break; 177 for (u32 i = 0; i < aux->narg; ++i) 178 verify_operand_shape(f, stage, &aux->args[i], physical_regs); 179 for (u32 i = 0; i < aux->ndst; ++i) 180 verify_operand_shape(f, stage, &aux->dsts[i], physical_regs); 181 break; 182 } 183 default: 184 break; 185 } 186 } 187 #endif 188 189 void opt_analysis_mark_valid(Func* f, u32 flags) { 190 if (!f) return; 191 f->opt_valid_analyses |= flags; 192 } 193 194 void opt_analysis_invalidate(Func* f, u32 flags) { 195 if (!f) return; 196 f->opt_valid_analyses &= ~flags; 197 } 198 199 int opt_analysis_has(Func* f, u32 flags) { 200 return f && (f->opt_valid_analyses & flags) == flags; 201 } 202 203 static void block_list_add(Arena* arena, OptBlockList* list, u32 block) { 204 if (list->n == list->cap) { 205 u32 ncap = list->cap ? list->cap * 2u : 4u; 206 u32* items = arena_array(arena, u32, ncap); 207 if (list->items) memcpy(items, list->items, sizeof(items[0]) * list->n); 208 list->items = items; 209 list->cap = ncap; 210 } 211 list->items[list->n++] = block; 212 } 213 214 static void block_list_add_unique(Arena* arena, OptBlockList* list, u32 block) { 215 for (u32 i = 0; i < list->n; ++i) 216 if (list->items[i] == block) return; 217 block_list_add(arena, list, block); 218 } 219 220 static void order_dfs(OptAnalysis* a, u32 block); 221 222 static void order_label_addr_target(OptAnalysis* a, const Inst* in) { 223 switch ((IROp)in->op) { 224 case IR_LOAD_LABEL_ADDR: 225 order_dfs(a, (u32)in->extra.imm); 226 break; 227 case IR_LOCAL_STATIC_DATA_LABEL_ADDR: { 228 CgIrLocalStaticLabelAux* aux = 229 (CgIrLocalStaticLabelAux*)in->extra.aux; 230 if (aux) order_dfs(a, (u32)aux->target); 231 break; 232 } 233 default: 234 break; 235 } 236 } 237 238 static void order_dfs(OptAnalysis* a, u32 block) { 239 if (block >= a->nblocks || a->reachable[block]) return; 240 a->reachable[block] = 1; 241 Block* bl = &a->f->blocks[block]; 242 for (u32 i = 0; i < bl->nsucc; ++i) order_dfs(a, bl->succ[i]); 243 for (u32 i = 0; i < bl->ninsts; ++i) 244 order_label_addr_target(a, &bl->insts[i]); 245 a->po[a->npo] = block; 246 a->po_index[block] = a->npo; 247 ++a->npo; 248 } 249 250 void opt_analysis_build_order(Func* f, OptAnalysis* a) { 251 memset(a, 0, sizeof *a); 252 a->arena = f->arena; 253 a->f = f; 254 a->nblocks = f->nblocks; 255 a->entry = f->entry; 256 u32 n = f->nblocks ? f->nblocks : 1u; 257 a->po = arena_array(f->arena, u32, n); 258 a->rpo = arena_array(f->arena, u32, n); 259 a->po_index = arena_array(f->arena, u32, n); 260 a->reachable = arena_zarray(f->arena, u8, n); 261 for (u32 i = 0; i < n; ++i) a->po_index[i] = OPT_BLK_NONE; 262 if (f->entry < f->nblocks) order_dfs(a, f->entry); 263 a->nrpo = a->npo; 264 for (u32 i = 0; i < a->npo; ++i) a->rpo[i] = a->po[a->npo - 1u - i]; 265 } 266 267 static u32 dom_intersect(u32 b1, u32 b2, const u32* idom, const u32* po_index) { 268 while (b1 != b2) { 269 while (po_index[b1] < po_index[b2]) b1 = idom[b1]; 270 while (po_index[b2] < po_index[b1]) b2 = idom[b2]; 271 } 272 return b1; 273 } 274 275 void opt_analysis_build_dominators(Func* f, OptAnalysis* a) { 276 if (!a->reachable) opt_analysis_build_order(f, a); 277 u32 n = f->nblocks ? f->nblocks : 1u; 278 a->idom = arena_array(f->arena, u32, n); 279 a->dom_children = arena_zarray(f->arena, OptBlockList, n); 280 for (u32 i = 0; i < n; ++i) a->idom[i] = OPT_BLK_NONE; 281 if (f->entry >= f->nblocks || !a->reachable[f->entry]) { 282 opt_analysis_mark_valid(f, OPT_ANALYSIS_DOM); 283 return; 284 } 285 a->idom[f->entry] = f->entry; 286 287 int changed = 1; 288 while (changed) { 289 changed = 0; 290 for (u32 ri = 0; ri < a->nrpo; ++ri) { 291 u32 b = a->rpo[ri]; 292 if (b == f->entry) continue; 293 Block* bl = &f->blocks[b]; 294 u32 new_idom = OPT_BLK_NONE; 295 for (u32 p = 0; p < bl->npreds; ++p) { 296 u32 pred = bl->preds[p]; 297 if (pred >= f->nblocks || !a->reachable[pred]) continue; 298 if (a->idom[pred] == OPT_BLK_NONE) continue; 299 new_idom = new_idom == OPT_BLK_NONE 300 ? pred 301 : dom_intersect(pred, new_idom, a->idom, a->po_index); 302 } 303 if (new_idom != OPT_BLK_NONE && a->idom[b] != new_idom) { 304 a->idom[b] = new_idom; 305 changed = 1; 306 } 307 } 308 } 309 310 for (u32 i = 0; i < a->npo; ++i) { 311 u32 b = a->po[i]; 312 u32 idom = a->idom[b]; 313 if (idom == OPT_BLK_NONE || idom == b) continue; 314 block_list_add(f->arena, &a->dom_children[idom], b); 315 } 316 opt_analysis_mark_valid(f, OPT_ANALYSIS_DOM); 317 } 318 319 void opt_analysis_build_dom_frontier(Func* f, OptAnalysis* a) { 320 if (!a->idom) opt_analysis_build_dominators(f, a); 321 u32 n = f->nblocks ? f->nblocks : 1u; 322 a->dom_frontier = arena_zarray(f->arena, OptBlockList, n); 323 for (u32 i = 0; i < a->npo; ++i) { 324 u32 b = a->po[i]; 325 Block* bl = &f->blocks[b]; 326 if (bl->npreds < 2 || a->idom[b] == OPT_BLK_NONE) continue; 327 for (u32 p = 0; p < bl->npreds; ++p) { 328 u32 runner = bl->preds[p]; 329 while (runner != OPT_BLK_NONE && runner != a->idom[b]) { 330 block_list_add_unique(f->arena, &a->dom_frontier[runner], b); 331 runner = a->idom[runner]; 332 } 333 } 334 } 335 } 336 337 int opt_analysis_dominates(const OptAnalysis* a, u32 dom, u32 node) { 338 if (!a || !a->idom || dom >= a->nblocks || node >= a->nblocks) return 0; 339 if (!a->reachable || !a->reachable[dom] || !a->reachable[node]) return 0; 340 u32 cur = node; 341 while (cur != OPT_BLK_NONE) { 342 if (cur == dom) return 1; 343 if (cur == a->entry) break; 344 cur = a->idom[cur]; 345 } 346 return 0; 347 } 348 349 #ifndef NDEBUG 350 static int block_has_pred(const Block* bl, u32 pred) { 351 for (u32 i = 0; i < bl->npreds; ++i) 352 if (bl->preds[i] == pred) return 1; 353 return 0; 354 } 355 356 static int block_has_succ(const Block* bl, u32 succ) { 357 for (u32 i = 0; i < bl->nsucc; ++i) 358 if (bl->succ[i] == succ) return 1; 359 return 0; 360 } 361 362 static int fixed_terminator_succ_count(const Inst* in, u32* count_out) { 363 switch ((IROp)in->op) { 364 case IR_RET: 365 case IR_UNREACHABLE: 366 *count_out = 0; 367 return 1; 368 case IR_BR: 369 case IR_BREAK_TO: 370 case IR_CONTINUE_TO: 371 *count_out = 1; 372 return 1; 373 case IR_CONDBR: 374 case IR_CMP_BRANCH: 375 *count_out = 2; 376 return 1; 377 case IR_INTRINSIC: { 378 IRIntrinAux* aux = (IRIntrinAux*)in->extra.aux; 379 if (aux && (aux->kind == INTRIN_LONGJMP || aux->kind == INTRIN_TRAP)) { 380 *count_out = 0; 381 return 1; 382 } 383 return 0; 384 } 385 default: 386 return 0; 387 } 388 } 389 #endif /* !NDEBUG (verify-only helpers) */ 390 391 static void opt_use_add(Func* f, Val v, u32 b, u32 i, u8 kind, u32 op_idx, 392 u32 pred_idx, Operand* op) { 393 if (v == VAL_NONE || v >= f->nvals) return; 394 if (f->opt_nuses == f->opt_uses_cap) { 395 u32 ncap = f->opt_uses_cap ? f->opt_uses_cap * 2u : 32u; 396 OptUse* uses = arena_zarray(f->arena, OptUse, ncap); 397 if (f->opt_uses) memcpy(uses, f->opt_uses, sizeof(uses[0]) * f->opt_nuses); 398 f->opt_uses = uses; 399 f->opt_uses_cap = ncap; 400 } 401 u32 id = f->opt_nuses++; 402 OptUse* u = &f->opt_uses[id]; 403 u->val = v; 404 u->block = b; 405 u->inst = i; 406 u->inst_id = f->blocks[b].insts[i].id; 407 u->kind = kind; 408 u->operand_index = op_idx; 409 u->phi_pred_index = pred_idx; 410 u->operand = op; 411 u->next_for_val = f->opt_first_use_by_val[v]; 412 f->opt_first_use_by_val[v] = id; 413 } 414 415 static void opt_use_add_operand(Func* f, u32 b, u32 i, u32 op_idx, Operand* op, 416 int is_def) { 417 if (!op || is_def) return; 418 if (op->kind == OPK_REG) { 419 opt_use_add(f, (Val)op->v.reg, b, i, OPT_USE_OPERAND, op_idx, OPT_USE_NONE, 420 op); 421 } else if (op->kind == OPK_INDIRECT) { 422 opt_use_add(f, (Val)op->v.ind.base, b, i, OPT_USE_INDIRECT_BASE, op_idx, 423 OPT_USE_NONE, op); 424 if (op->v.ind.index != (Reg)REG_NONE) { 425 opt_use_add(f, (Val)op->v.ind.index, b, i, OPT_USE_INDIRECT_INDEX, op_idx, 426 OPT_USE_NONE, op); 427 } 428 } 429 } 430 431 static void opt_use_add_abivalue(Func* f, u32 b, u32 i, CGABIValue* v, 432 int storage_def) { 433 if (!v) return; 434 opt_use_add_operand(f, b, i, OPT_USE_NONE, &v->storage, storage_def); 435 for (u32 p = 0; p < v->nparts; ++p) 436 opt_use_add_operand(f, b, i, p, (Operand*)&v->parts[p].op, storage_def); 437 } 438 439 static int collect_operand_index_is_def(const Inst* in, u32 i) { 440 if (!in || i >= in->nopnds || in->opnds[i].kind != OPK_REG) return 0; 441 if (!opt_val_in_inst_defs(in, (Val)in->opnds[i].v.reg)) return 0; 442 switch ((IROp)in->op) { 443 case IR_ATOMIC_CAS: 444 return i == 0 || i == 1; 445 default: 446 return i == 0; 447 } 448 } 449 450 static void opt_collect_inst_uses(Func* f, u32 b, u32 i, Inst* in) { 451 for (u32 o = 0; o < in->nopnds; ++o) { 452 int is_def = collect_operand_index_is_def(in, o); 453 opt_use_add_operand(f, b, i, o, &in->opnds[o], is_def); 454 } 455 456 switch ((IROp)in->op) { 457 case IR_PHI: { 458 IRPhiAux* aux = (IRPhiAux*)in->extra.aux; 459 if (!aux) break; 460 for (u32 p = 0; p < aux->npreds; ++p) 461 opt_use_add(f, aux->pred_vals[p], b, i, OPT_USE_PHI_INPUT, OPT_USE_NONE, 462 p, NULL); 463 break; 464 } 465 case IR_CALL: { 466 IRCallAux* aux = (IRCallAux*)in->extra.aux; 467 if (!aux) break; 468 if (aux->use_plan_replay) { 469 opt_use_add_operand(f, b, i, OPT_USE_NONE, &aux->plan.callee, 0); 470 for (u32 a = 0; a < aux->plan.nargs; ++a) 471 opt_use_add_operand(f, b, i, a, &aux->plan.args[a].src, 0); 472 } else { 473 opt_use_add_operand(f, b, i, OPT_USE_NONE, &aux->desc.callee, 0); 474 for (u32 a = 0; a < aux->desc.nargs; ++a) 475 opt_use_add_abivalue(f, b, i, (CGABIValue*)&aux->desc.args[a], 0); 476 } 477 break; 478 } 479 case IR_RET: { 480 IRRetAux* aux = (IRRetAux*)in->extra.aux; 481 if (aux && aux->present) opt_use_add_abivalue(f, b, i, &aux->val, 0); 482 break; 483 } 484 case IR_SCOPE_BEGIN: 485 break; 486 case IR_ASM_BLOCK: { 487 IRAsmAux* aux = (IRAsmAux*)in->extra.aux; 488 if (!aux) break; 489 for (u32 a = 0; a < aux->nin; ++a) 490 opt_use_add_operand(f, b, i, a, &aux->in_ops[a], 0); 491 break; 492 } 493 case IR_INTRINSIC: { 494 IRIntrinAux* aux = (IRIntrinAux*)in->extra.aux; 495 if (!aux) break; 496 for (u32 a = 0; a < aux->narg; ++a) 497 opt_use_add_operand(f, b, i, a, &aux->args[a], 0); 498 break; 499 } 500 default: 501 break; 502 } 503 } 504 505 void opt_rebuild_def_use(Func* f) { 506 u32 nheads; 507 if (!f) return; 508 f->opt_nuses = 0; 509 nheads = f->nvals ? f->nvals : 1u; 510 if (nheads > f->opt_first_use_by_val_cap) { 511 u32 ncap = f->opt_first_use_by_val_cap ? f->opt_first_use_by_val_cap : 16u; 512 while (ncap < nheads) ncap *= 2u; 513 f->opt_first_use_by_val = arena_array(f->arena, u32, ncap); 514 f->opt_first_use_by_val_cap = ncap; 515 } 516 for (u32 v = 0; v < f->nvals; ++v) f->opt_first_use_by_val[v] = OPT_USE_NONE; 517 for (u32 b = 0; b < f->nblocks; ++b) { 518 Block* bl = &f->blocks[b]; 519 for (u32 i = 0; i < bl->ninsts; ++i) 520 opt_collect_inst_uses(f, b, i, &bl->insts[i]); 521 } 522 opt_analysis_mark_valid(f, OPT_ANALYSIS_DEF_USE); 523 } 524 525 #ifndef NDEBUG 526 static void verify_operand(Func* f, Inst* in, Operand* op, int is_def, 527 void* arg) { 528 (void)in; 529 const char* stage = (const char*)arg; 530 if (op->kind != OPK_REG) return; 531 Val v = (Val)op->v.reg; 532 u32 nregs = verify_stage_is_ssa(stage) ? f->nvals : opt_reg_count(f); 533 if (v == VAL_NONE || v >= nregs) 534 opt_fail(f, stage, is_def ? "bad def val" : "bad use val", v, nregs); 535 if (!verify_stage_is_ssa(stage)) return; 536 if (op->cls != f->val_cls[v]) 537 opt_fail(f, stage, is_def ? "def class mismatch" : "use class mismatch", v, 538 op->cls); 539 } 540 541 static void verify_values(Func* f, const char* stage) { 542 if (f->opt_rewritten) return; 543 u32 inst_cap = f->next_inst_id ? f->next_inst_id : 1u; 544 u8* seen_inst = arena_zarray(f->arena, u8, inst_cap); 545 for (u32 b = 0; b < f->nblocks; ++b) { 546 Block* bl = &f->blocks[b]; 547 for (u32 i = 0; i < bl->ninsts; ++i) { 548 Inst* in = &bl->insts[i]; 549 if (in->id == INST_ID_NONE || in->id >= f->next_inst_id) 550 opt_fail(f, stage, "bad inst id", b, i); 551 if (seen_inst[in->id]) opt_fail(f, stage, "duplicate inst id", in->id, b); 552 seen_inst[in->id] = 1; 553 if (in->def != VAL_NONE) { 554 u32 ndefs = verify_stage_is_ssa(stage) ? f->nvals : opt_reg_count(f); 555 if (in->def >= ndefs) opt_fail(f, stage, "bad inst def", b, i); 556 if (verify_stage_is_ssa(stage) && (IROp)in->op == IR_PHI && in->type && 557 f->val_type[in->def] && in->type != f->val_type[in->def]) 558 opt_fail(f, stage, "inst def type mismatch", in->def, b); 559 } 560 for (u32 d = 0; d < in->ndefs; ++d) { 561 Val v = in->defs[d]; 562 u32 ndefs = verify_stage_is_ssa(stage) ? f->nvals : opt_reg_count(f); 563 if (v == VAL_NONE || v >= ndefs) 564 opt_fail(f, stage, "bad inst multi-def", b, d); 565 } 566 for (u32 o = 0; o < in->nopnds; ++o) 567 verify_operand_shape(f, stage, &in->opnds[o], 0); 568 verify_aux_shapes(f, stage, in, 0); 569 opt_walk_inst_operands(f, in, verify_operand, (void*)stage); 570 if ((IROp)in->op == IR_PHI) { 571 IRPhiAux* aux = (IRPhiAux*)in->extra.aux; 572 if (!aux) opt_fail(f, stage, "phi missing aux", b, i); 573 if (in->def == VAL_NONE) opt_fail(f, stage, "phi missing def", b, i); 574 if (in->nopnds || in->opnds) 575 opt_fail(f, stage, "phi should not carry operands", b, i); 576 if (aux->slot_id > f->nframe_slots) 577 opt_fail(f, stage, "phi bad slot id", aux->slot_id, f->nframe_slots); 578 if (aux->reg_id != 0 && aux->reg_id >= f->npregs) 579 opt_fail(f, stage, "phi bad reg id", aux->reg_id, f->npregs); 580 if (aux->npreds != bl->npreds) 581 opt_fail(f, stage, "phi pred count mismatch", aux->npreds, 582 bl->npreds); 583 for (u32 p = 0; p < aux->npreds; ++p) { 584 if (p >= bl->npreds || aux->pred_blocks[p] != bl->preds[p]) 585 opt_fail(f, stage, "phi pred block mismatch", b, p); 586 if (aux->pred_vals[p] != VAL_NONE && aux->pred_vals[p] >= f->nvals) 587 opt_fail(f, stage, "phi bad pred value", aux->pred_vals[p], 588 f->nvals); 589 if (aux->pred_vals[p] != VAL_NONE && f->val_type[aux->pred_vals[p]] && 590 f->val_type[aux->pred_vals[p]] != in->type) 591 opt_fail(f, stage, "phi input type mismatch", b, p); 592 } 593 } else if ((IROp)in->op == IR_PARAM_DECL) { 594 IRParamDeclAux* aux = (IRParamDeclAux*)in->extra.aux; 595 if (in->nopnds || in->opnds) 596 opt_fail(f, stage, "param_decl should not carry operands", b, i); 597 if ((!aux || aux->desc.storage.kind == CG_LOCAL_STORAGE_REG) && 598 in->def == VAL_NONE) 599 opt_fail(f, stage, "param_decl missing def", b, i); 600 } 601 } 602 } 603 } 604 605 static void verify_function_storage(Func* f, const char* stage) { 606 for (u32 i = 0; i < f->nframe_slots; ++i) { 607 IRFrameSlot* s = &f->frame_slots[i]; 608 if (s->id != i + 1u) opt_fail(f, stage, "frame slot id mismatch", s->id, i); 609 if (s->kind > FS_SPILL) 610 opt_fail(f, stage, "bad frame slot kind", s->kind, i); 611 } 612 for (u32 i = 0; i < f->nparams; ++i) { 613 IRParam* p = &f->params[i]; 614 u8 cls = verify_type_reg_class(f, p->type); 615 if (p->index != i) opt_fail(f, stage, "param index mismatch", p->index, i); 616 verify_storage(f, stage, p->storage, p->type, cls, "bad param storage"); 617 } 618 for (u32 i = 0; i < f->nlocals; ++i) { 619 IRLocal* l = &f->locals[i]; 620 u8 cls = verify_type_reg_class(f, l->desc.type); 621 verify_storage(f, stage, l->storage, l->desc.type, cls, 622 "bad local storage"); 623 if (l->home_slot != FRAME_SLOT_NONE) 624 verify_frame_slot(f, stage, l->home_slot, "bad local home slot"); 625 } 626 } 627 628 static void verify_allocations(Func* f, const char* stage) { 629 if (!f->preg_info && !f->preg_locs) return; 630 for (PReg r = 1; r < opt_reg_count(f); ++r) { 631 OptPRegInfo* pi = f->preg_info ? &f->preg_info[r] : NULL; 632 OptLoc* loc = f->preg_locs ? &f->preg_locs[r] : NULL; 633 u8 alloc_kind = opt_preg_alloc_kind(f, r); 634 u8 cls = opt_preg_loc_cls(f, r); 635 if (cls >= OPT_REG_CLASSES) 636 opt_fail(f, stage, "bad preg alloc class", r, cls); 637 if (pi && pi->alloc_kind != alloc_kind && 638 !(pi->alloc_kind == OPT_ALLOC_SPLIT && alloc_kind == OPT_ALLOC_SPLIT)) 639 opt_fail(f, stage, "alloc kind mirror mismatch", r, pi->alloc_kind); 640 switch ((OptAllocKind)alloc_kind) { 641 case OPT_ALLOC_NONE: 642 if (loc && loc->kind != OPT_LOC_NONE) 643 opt_fail(f, stage, "alloc location mismatch", r, loc->kind); 644 break; 645 case OPT_ALLOC_HARD: 646 if (opt_preg_hard_reg(f, r) == (Reg)REG_NONE || 647 opt_preg_hard_reg(f, r) >= OPT_MAX_HARD_REGS) 648 opt_fail(f, stage, "bad hard allocation", r, opt_preg_hard_reg(f, r)); 649 if (pi && (pi->cls != cls || pi->hard_reg != opt_preg_hard_reg(f, r))) 650 opt_fail(f, stage, "hard alloc mirror mismatch", r, pi->hard_reg); 651 if (loc && (loc->kind != OPT_LOC_HARD || loc->cls != cls)) 652 opt_fail(f, stage, "hard alloc location mismatch", r, 653 opt_preg_hard_reg(f, r)); 654 break; 655 case OPT_ALLOC_SPILL: 656 verify_frame_slot(f, stage, opt_preg_spill_slot(f, r), 657 "bad spill slot"); 658 if (f->frame_slots[opt_preg_spill_slot(f, r) - 1u].kind != FS_SPILL) 659 opt_fail(f, stage, "spill slot is not FS_SPILL", r, 660 opt_preg_spill_slot(f, r)); 661 if (pi && 662 (pi->cls != cls || pi->spill_slot != opt_preg_spill_slot(f, r))) 663 opt_fail(f, stage, "spill alloc mirror mismatch", r, pi->spill_slot); 664 if (loc && (loc->kind != OPT_LOC_STACK || loc->cls != cls)) 665 opt_fail(f, stage, "spill alloc location mismatch", r, 666 opt_preg_spill_slot(f, r)); 667 break; 668 case OPT_ALLOC_SPLIT: 669 if (!f->opt_first_segment_by_preg) 670 opt_fail(f, stage, "split allocation missing segments", r, 0); 671 if (loc && loc->kind != OPT_LOC_NONE) 672 opt_fail(f, stage, "split alloc location mismatch", r, loc->kind); 673 break; 674 default: 675 opt_fail(f, stage, "bad allocation kind", r, alloc_kind); 676 break; 677 } 678 } 679 if (f->opt_first_segment_by_preg && f->opt_alloc_segments) { 680 for (PReg r = 1; r < opt_reg_count(f); ++r) { 681 for (u32 si = f->opt_first_segment_by_preg[r]; si != OPT_RANGE_NONE; 682 si = f->opt_alloc_segments[si].next) { 683 OptAllocSegment* s = &f->opt_alloc_segments[si]; 684 if (s->block >= f->nblocks) 685 opt_fail(f, stage, "bad split block", r, si); 686 if (s->start > s->end) opt_fail(f, stage, "bad split range", r, si); 687 if (s->cls >= OPT_REG_CLASSES) 688 opt_fail(f, stage, "bad split class", r, s->cls); 689 if (s->loc_kind == OPT_LOC_HARD) { 690 if (s->hard_reg == (Reg)REG_NONE || s->hard_reg >= OPT_MAX_HARD_REGS) 691 opt_fail(f, stage, "bad split hard reg", r, s->hard_reg); 692 } else if (s->loc_kind == OPT_LOC_STACK) { 693 verify_frame_slot(f, stage, s->spill_slot, "bad split spill slot"); 694 } else if (s->loc_kind != OPT_LOC_NONE) { 695 opt_fail(f, stage, "bad split loc kind", r, s->loc_kind); 696 } 697 } 698 } 699 } 700 } 701 702 static void verify_rewritten(Func* f, const char* stage) { 703 if (!f->opt_rewritten) return; 704 for (u32 b = 0; b < f->nblocks; ++b) { 705 Block* bl = &f->blocks[b]; 706 for (u32 i = 0; i < bl->ninsts; ++i) { 707 Inst* in = &bl->insts[i]; 708 if ((IROp)in->op == IR_PHI) 709 opt_fail(f, stage, "phi survived rewrite", b, i); 710 if ((IROp)in->op == IR_PARAM_DECL) { 711 IRParamDeclAux* aux = (IRParamDeclAux*)in->extra.aux; 712 if (in->nopnds || in->opnds) 713 opt_fail(f, stage, "param_decl carries operands after rewrite", b, i); 714 if ((!aux || aux->desc.storage.kind == CG_LOCAL_STORAGE_REG) && 715 (in->def == VAL_NONE || in->def >= opt_reg_count(f))) 716 opt_fail(f, stage, "bad param_decl def after rewrite", b, i); 717 continue; 718 } 719 for (u32 o = 0; o < in->nopnds; ++o) 720 verify_operand_shape(f, stage, &in->opnds[o], 1); 721 verify_aux_shapes(f, stage, in, 1); 722 } 723 } 724 } 725 726 static void verify_use_site(Func* f, const char* stage, const OptUse* use) { 727 Inst* in = &f->blocks[use->block].insts[use->inst]; 728 if (in->id != use->inst_id) 729 opt_fail(f, stage, "def-use stale inst id", use->inst_id, in->id); 730 switch ((OptUseKind)use->kind) { 731 case OPT_USE_OPERAND: 732 if (!use->operand) 733 opt_fail(f, stage, "def-use missing operand", use->block, use->inst); 734 if (use->operand->kind != OPK_REG || (Val)use->operand->v.reg != use->val) 735 opt_fail(f, stage, "def-use operand mismatch", use->val, use->kind); 736 break; 737 case OPT_USE_INDIRECT_BASE: 738 if (!use->operand || use->operand->kind != OPK_INDIRECT || 739 (Val)use->operand->v.ind.base != use->val) 740 opt_fail(f, stage, "def-use indirect mismatch", use->val, use->kind); 741 break; 742 case OPT_USE_INDIRECT_INDEX: 743 if (!use->operand || use->operand->kind != OPK_INDIRECT || 744 use->operand->v.ind.index == (Reg)REG_NONE || 745 (Val)use->operand->v.ind.index != use->val) 746 opt_fail(f, stage, "def-use indirect index mismatch", use->val, 747 use->kind); 748 break; 749 case OPT_USE_PHI_INPUT: { 750 if ((IROp)in->op != IR_PHI) 751 opt_fail(f, stage, "def-use phi site mismatch", use->block, use->inst); 752 IRPhiAux* aux = (IRPhiAux*)in->extra.aux; 753 if (!aux || use->phi_pred_index >= aux->npreds) 754 opt_fail(f, stage, "def-use phi pred mismatch", use->val, 755 use->phi_pred_index); 756 if (aux->pred_vals[use->phi_pred_index] != use->val) 757 opt_fail(f, stage, "def-use phi value mismatch", use->val, 758 use->phi_pred_index); 759 break; 760 } 761 default: 762 opt_fail(f, stage, "def-use bad kind", use->kind, use->val); 763 } 764 } 765 766 static void verify_def_use(Func* f, const char* stage) { 767 if (f->opt_rewritten) return; 768 if (opt_analysis_has(f, OPT_ANALYSIS_DEF_USE)) { 769 for (u32 u = 0; u < f->opt_nuses; ++u) { 770 OptUse* use = &f->opt_uses[u]; 771 if (use->val == VAL_NONE || use->val >= f->nvals) 772 opt_fail(f, stage, "def-use bad cached val", use->val, f->nvals); 773 if (use->block >= f->nblocks) 774 opt_fail(f, stage, "def-use bad cached block", use->block, f->nblocks); 775 if (use->inst >= f->blocks[use->block].ninsts) 776 opt_fail(f, stage, "def-use bad cached inst", use->inst, 777 f->blocks[use->block].ninsts); 778 verify_use_site(f, stage, use); 779 } 780 } 781 opt_rebuild_def_use(f); 782 for (u32 u = 0; u < f->opt_nuses; ++u) { 783 OptUse* use = &f->opt_uses[u]; 784 if (use->val == VAL_NONE || use->val >= f->nvals) 785 opt_fail(f, stage, "def-use bad use val", use->val, f->nvals); 786 if (use->block >= f->nblocks) 787 opt_fail(f, stage, "def-use bad block", use->block, f->nblocks); 788 if (use->inst >= f->blocks[use->block].ninsts) 789 opt_fail(f, stage, "def-use bad inst", use->inst, 790 f->blocks[use->block].ninsts); 791 verify_use_site(f, stage, use); 792 if (f->val_def_block[use->val] >= f->nblocks) 793 opt_fail(f, stage, "def-use bad def block", use->val, 794 f->val_def_block[use->val]); 795 } 796 for (Val v = 1; v < f->nvals; ++v) { 797 for (u32 u = f->opt_first_use_by_val[v]; u != OPT_USE_NONE; 798 u = f->opt_uses[u].next_for_val) { 799 if (u >= f->opt_nuses) opt_fail(f, stage, "def-use bad next", v, u); 800 if (f->opt_uses[u].val != v) 801 opt_fail(f, stage, "def-use wrong value list", v, u); 802 } 803 } 804 } 805 806 #endif /* !NDEBUG */ 807 808 void opt_verify(Func* f, const char* stage) { 809 #ifdef NDEBUG 810 (void)f; 811 (void)stage; 812 return; 813 #else 814 if (!f) return; 815 if (f->nblocks && f->entry >= f->nblocks) 816 opt_fail(f, stage, "entry out of range", f->entry, f->nblocks); 817 OptAnalysis a; 818 opt_analysis_build_order(f, &a); 819 for (u32 b = 0; b < f->nblocks; ++b) { 820 Block* bl = &f->blocks[b]; 821 if (bl->id != b) opt_fail(f, stage, "block id mismatch", bl->id, b); 822 if (!a.reachable[b] && (bl->ninsts || bl->nsucc || bl->npreds)) 823 opt_fail(f, stage, "unreachable block still connected", b, bl->ninsts); 824 if (bl->ninsts) { 825 u32 expected = 0; 826 if (fixed_terminator_succ_count(&bl->insts[bl->ninsts - 1], &expected) && 827 bl->nsucc != expected) 828 opt_fail(f, stage, "terminator successor count mismatch", b, bl->nsucc); 829 } 830 for (u32 s = 0; s < bl->nsucc; ++s) { 831 u32 succ = bl->succ[s]; 832 if (succ >= f->nblocks) 833 opt_fail(f, stage, "successor out of range", b, s); 834 if (!block_has_pred(&f->blocks[succ], b)) 835 opt_fail(f, stage, "successor missing reciprocal predecessor", b, succ); 836 } 837 for (u32 p = 0; p < bl->npreds; ++p) { 838 u32 pred = bl->preds[p]; 839 if (pred >= f->nblocks) 840 opt_fail(f, stage, "predecessor out of range", b, p); 841 if (!block_has_succ(&f->blocks[pred], b)) 842 opt_fail(f, stage, "predecessor missing reciprocal successor", b, pred); 843 } 844 } 845 u8* seen_emit = arena_zarray(f->arena, u8, f->nblocks ? f->nblocks : 1u); 846 for (u32 i = 0; i < f->emit_order_n; ++i) { 847 u32 b = f->emit_order[i]; 848 if (b >= f->nblocks) opt_fail(f, stage, "emit block out of range", b, i); 849 if (seen_emit[b]) opt_fail(f, stage, "duplicate emit block", b, i); 850 seen_emit[b] = 1; 851 } 852 verify_function_storage(f, stage); 853 verify_allocations(f, stage); 854 verify_values(f, stage); 855 verify_rewritten(f, stage); 856 verify_def_use(f, stage); 857 #endif 858 }