kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

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 }