opt_util.c (4393B)
1 #include <string.h> 2 3 #include "opt/opt_internal.h" 4 5 int opt_val_in_inst_defs(const Inst* in, Val v) { 6 if (!in || v == VAL_NONE) return 0; 7 if (in->def == v) return 1; 8 for (u32 i = 0; i < in->ndefs; ++i) 9 if (in->defs[i] == v) return 1; 10 return 0; 11 } 12 13 static int opt_operand_index_is_def(const Inst* in, u32 i) { 14 if (!in || i >= in->nopnds || in->opnds[i].kind != OPK_REG) return 0; 15 if (!opt_val_in_inst_defs(in, (Val)in->opnds[i].v.reg)) return 0; 16 switch ((IROp)in->op) { 17 case IR_ATOMIC_CAS: 18 return i == 0 || i == 1; 19 default: 20 return i == 0; 21 } 22 } 23 24 void opt_walk_operand(Func* f, Inst* in, Operand* op, int is_def, 25 OptOperandWalkFn fn, void* ctx) { 26 if (!op || !fn) return; 27 if (op->kind == OPK_REG) { 28 fn(f, in, op, is_def, ctx); 29 } else if (op->kind == OPK_INDIRECT) { 30 Operand base = *op; 31 base.kind = OPK_REG; 32 base.cls = RC_INT; 33 base.v.reg = op->v.ind.base; 34 if ((PReg)base.v.reg < opt_reg_count(f) && opt_reg_type(f, base.v.reg)) 35 base.type = opt_reg_type(f, base.v.reg); 36 fn(f, in, &base, 0, ctx); 37 op->v.ind.base = base.v.reg; 38 if (op->v.ind.index != (Reg)REG_NONE) { 39 Operand idx = *op; 40 idx.kind = OPK_REG; 41 idx.cls = RC_INT; 42 idx.v.reg = op->v.ind.index; 43 if ((PReg)idx.v.reg < opt_reg_count(f) && opt_reg_type(f, idx.v.reg)) 44 idx.type = opt_reg_type(f, idx.v.reg); 45 fn(f, in, &idx, 0, ctx); 46 op->v.ind.index = idx.v.reg; 47 } 48 } 49 } 50 51 void opt_walk_abivalue(Func* f, Inst* in, CGABIValue* v, int storage_def, 52 OptOperandWalkFn fn, void* ctx) { 53 if (!v) return; 54 opt_walk_operand(f, in, &v->storage, storage_def, fn, ctx); 55 for (u32 i = 0; i < v->nparts; ++i) 56 opt_walk_operand(f, in, (Operand*)&v->parts[i].op, storage_def, fn, ctx); 57 } 58 59 void opt_walk_inst_operands(Func* f, Inst* in, OptOperandWalkFn fn, void* ctx) { 60 if (!in || !fn) return; 61 for (u32 i = 0; i < in->nopnds; ++i) { 62 int is_def = opt_operand_index_is_def(in, i); 63 if (!is_def) opt_walk_operand(f, in, &in->opnds[i], 0, fn, ctx); 64 } 65 for (u32 i = 0; i < in->nopnds; ++i) { 66 int is_def = opt_operand_index_is_def(in, i); 67 if (is_def) opt_walk_operand(f, in, &in->opnds[i], 1, fn, ctx); 68 } 69 70 switch ((IROp)in->op) { 71 case IR_PARAM_DECL: { 72 Operand def; 73 if (in->def == VAL_NONE) break; 74 memset(&def, 0, sizeof def); 75 def.kind = OPK_REG; 76 def.cls = (f->preg_info && in->def < opt_reg_count(f)) 77 ? f->preg_info[in->def].cls 78 : 0; 79 def.type = in->type; 80 def.v.reg = (Reg)in->def; 81 opt_walk_operand(f, in, &def, 1, fn, ctx); 82 break; 83 } 84 case IR_CALL: { 85 IRCallAux* aux = (IRCallAux*)in->extra.aux; 86 if (!aux) break; 87 if (aux->use_plan_replay) { 88 opt_walk_operand(f, in, &aux->plan.callee, 0, fn, ctx); 89 for (u32 i = 0; i < aux->plan.nargs; ++i) 90 opt_walk_operand(f, in, &aux->plan.args[i].src, 0, fn, ctx); 91 for (u32 i = 0; i < aux->plan.nrets; ++i) 92 opt_walk_operand(f, in, &aux->plan.rets[i].dst, 1, fn, ctx); 93 } else { 94 opt_walk_operand(f, in, &aux->desc.callee, 0, fn, ctx); 95 for (u32 i = 0; i < aux->desc.nargs; ++i) 96 opt_walk_abivalue(f, in, (CGABIValue*)&aux->desc.args[i], 0, fn, ctx); 97 opt_walk_abivalue(f, in, &aux->desc.ret, 1, fn, ctx); 98 } 99 break; 100 } 101 case IR_RET: { 102 IRRetAux* aux = (IRRetAux*)in->extra.aux; 103 if (aux && aux->present) opt_walk_abivalue(f, in, &aux->val, 0, fn, ctx); 104 break; 105 } 106 case IR_SCOPE_BEGIN: 107 break; 108 case IR_ASM_BLOCK: { 109 IRAsmAux* aux = (IRAsmAux*)in->extra.aux; 110 if (!aux) break; 111 for (u32 i = 0; i < aux->nin; ++i) 112 opt_walk_operand(f, in, &aux->in_ops[i], 0, fn, ctx); 113 for (u32 i = 0; i < aux->nout; ++i) 114 opt_walk_operand(f, in, &aux->out_ops[i], 1, fn, ctx); 115 break; 116 } 117 case IR_INTRINSIC: { 118 IRIntrinAux* aux = (IRIntrinAux*)in->extra.aux; 119 if (!aux) break; 120 for (u32 i = 0; i < aux->narg; ++i) 121 opt_walk_operand(f, in, &aux->args[i], 0, fn, ctx); 122 for (u32 i = 0; i < aux->ndst; ++i) 123 opt_walk_operand(f, in, &aux->dsts[i], 1, fn, ctx); 124 break; 125 } 126 default: 127 break; 128 } 129 } 130 131 int opt_mem_observable(const MemAccess* m) { 132 return (m->flags & (MF_VOLATILE | MF_ATOMIC)) != 0; 133 }