iropt.c
来自「The Valgrind distribution has multiple t」· C语言 代码 · 共 1,868 行 · 第 1/5 页
C
1,868 行
} } /* Mux0X */ if (e->tag == Iex_Mux0X && e->Iex.Mux0X.cond->tag == Iex_Const) { Bool zero; /* assured us by the IR type rules */ vassert(e->Iex.Mux0X.cond->Iex.Const.con->tag == Ico_U8); zero = toBool(0 == (0xFF & e->Iex.Mux0X.cond ->Iex.Const.con->Ico.U8)); e2 = zero ? e->Iex.Mux0X.expr0 : e->Iex.Mux0X.exprX; } if (DEBUG_IROPT && e2 != e) { vex_printf("FOLD: "); ppIRExpr(e); vex_printf(" -> "); ppIRExpr(e2); vex_printf("\n"); } return e2; unhandled:# if 0 vex_printf("\n\n"); ppIRExpr(e); vpanic("fold_Expr: no rule for the above");# else if (vex_control.iropt_verbosity > 0) { vex_printf("vex iropt: fold_Expr: no rule for: "); ppIRExpr(e); vex_printf("\n"); } return e2;# endif}/* Apply the subst to a simple 1-level expression -- guaranteed to be 1-level due to previous flattening pass. */static IRExpr* subst_Expr ( IRExpr** env, IRExpr* ex ){ switch (ex->tag) { case Iex_Tmp: if (env[(Int)ex->Iex.Tmp.tmp] != NULL) { return env[(Int)ex->Iex.Tmp.tmp]; } else { /* not bound in env */ return ex; } case Iex_Const: case Iex_Get: return ex; case Iex_GetI: vassert(isIRAtom(ex->Iex.GetI.ix)); return IRExpr_GetI( ex->Iex.GetI.descr, subst_Expr(env, ex->Iex.GetI.ix), ex->Iex.GetI.bias ); case Iex_Qop: vassert(isIRAtom(ex->Iex.Qop.arg1)); vassert(isIRAtom(ex->Iex.Qop.arg2)); vassert(isIRAtom(ex->Iex.Qop.arg3)); vassert(isIRAtom(ex->Iex.Qop.arg4)); return IRExpr_Qop( ex->Iex.Qop.op, subst_Expr(env, ex->Iex.Qop.arg1), subst_Expr(env, ex->Iex.Qop.arg2), subst_Expr(env, ex->Iex.Qop.arg3), subst_Expr(env, ex->Iex.Qop.arg4) ); case Iex_Triop: vassert(isIRAtom(ex->Iex.Triop.arg1)); vassert(isIRAtom(ex->Iex.Triop.arg2)); vassert(isIRAtom(ex->Iex.Triop.arg3)); return IRExpr_Triop( ex->Iex.Triop.op, subst_Expr(env, ex->Iex.Triop.arg1), subst_Expr(env, ex->Iex.Triop.arg2), subst_Expr(env, ex->Iex.Triop.arg3) ); case Iex_Binop: vassert(isIRAtom(ex->Iex.Binop.arg1)); vassert(isIRAtom(ex->Iex.Binop.arg2)); return IRExpr_Binop( ex->Iex.Binop.op, subst_Expr(env, ex->Iex.Binop.arg1), subst_Expr(env, ex->Iex.Binop.arg2) ); case Iex_Unop: vassert(isIRAtom(ex->Iex.Unop.arg)); return IRExpr_Unop( ex->Iex.Unop.op, subst_Expr(env, ex->Iex.Unop.arg) ); case Iex_Load: vassert(isIRAtom(ex->Iex.Load.addr)); return IRExpr_Load( ex->Iex.Load.end, ex->Iex.Load.ty, subst_Expr(env, ex->Iex.Load.addr) ); case Iex_CCall: { Int i; IRExpr** args2 = sopyIRExprVec(ex->Iex.CCall.args); for (i = 0; args2[i]; i++) { vassert(isIRAtom(args2[i])); args2[i] = subst_Expr(env, args2[i]); } return IRExpr_CCall( ex->Iex.CCall.cee, ex->Iex.CCall.retty, args2 ); } case Iex_Mux0X: vassert(isIRAtom(ex->Iex.Mux0X.cond)); vassert(isIRAtom(ex->Iex.Mux0X.expr0)); vassert(isIRAtom(ex->Iex.Mux0X.exprX)); return IRExpr_Mux0X( subst_Expr(env, ex->Iex.Mux0X.cond), subst_Expr(env, ex->Iex.Mux0X.expr0), subst_Expr(env, ex->Iex.Mux0X.exprX) ); default: vex_printf("\n\n"); ppIRExpr(ex); vpanic("subst_Expr"); }}/* Apply the subst to stmt, then fold the result as much as possible. Much simplified due to stmt being previously flattened. As a result of this, the stmt may wind up being turned into a no-op. */static IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st ){# if 0 vex_printf("\nsubst and fold stmt\n"); ppIRStmt(st); vex_printf("\n");# endif switch (st->tag) { case Ist_AbiHint: vassert(isIRAtom(st->Ist.AbiHint.base)); return IRStmt_AbiHint( fold_Expr(subst_Expr(env, st->Ist.AbiHint.base)), st->Ist.AbiHint.len ); case Ist_Put: vassert(isIRAtom(st->Ist.Put.data)); return IRStmt_Put( st->Ist.Put.offset, fold_Expr(subst_Expr(env, st->Ist.Put.data)) ); case Ist_PutI: vassert(isIRAtom(st->Ist.PutI.ix)); vassert(isIRAtom(st->Ist.PutI.data)); return IRStmt_PutI( st->Ist.PutI.descr, fold_Expr(subst_Expr(env, st->Ist.PutI.ix)), st->Ist.PutI.bias, fold_Expr(subst_Expr(env, st->Ist.PutI.data)) ); case Ist_Tmp: /* This is the one place where an expr (st->Ist.Tmp.data) is allowed to be more than just a constant or a tmp. */ return IRStmt_Tmp( st->Ist.Tmp.tmp, fold_Expr(subst_Expr(env, st->Ist.Tmp.data)) ); case Ist_Store: vassert(isIRAtom(st->Ist.Store.addr)); vassert(isIRAtom(st->Ist.Store.data)); return IRStmt_Store( st->Ist.Store.end, fold_Expr(subst_Expr(env, st->Ist.Store.addr)), fold_Expr(subst_Expr(env, st->Ist.Store.data)) ); case Ist_Dirty: { Int i; IRDirty *d, *d2; d = st->Ist.Dirty.details; d2 = emptyIRDirty(); *d2 = *d; d2->args = sopyIRExprVec(d2->args); if (d2->mFx != Ifx_None) { vassert(isIRAtom(d2->mAddr)); d2->mAddr = fold_Expr(subst_Expr(env, d2->mAddr)); } vassert(isIRAtom(d2->guard)); d2->guard = fold_Expr(subst_Expr(env, d2->guard)); for (i = 0; d2->args[i]; i++) { vassert(isIRAtom(d2->args[i])); d2->args[i] = fold_Expr(subst_Expr(env, d2->args[i])); } return IRStmt_Dirty(d2); } case Ist_IMark: return IRStmt_IMark(st->Ist.IMark.addr, st->Ist.IMark.len); case Ist_NoOp: return IRStmt_NoOp(); case Ist_MFence: return IRStmt_MFence(); case Ist_Exit: { IRExpr* fcond; vassert(isIRAtom(st->Ist.Exit.guard)); fcond = fold_Expr(subst_Expr(env, st->Ist.Exit.guard)); if (fcond->tag == Iex_Const) { /* Interesting. The condition on this exit has folded down to a constant. */ vassert(fcond->Iex.Const.con->tag == Ico_U1); vassert(fcond->Iex.Const.con->Ico.U1 == False || fcond->Iex.Const.con->Ico.U1 == True); if (fcond->Iex.Const.con->Ico.U1 == False) { /* exit is never going to happen, so dump the statement. */ return IRStmt_NoOp(); } else { vassert(fcond->Iex.Const.con->Ico.U1 == True); /* Hmmm. The exit has become unconditional. Leave it as it is for now, since we'd have to truncate the BB at this point, which is tricky. Such truncation is done later by the dead-code elimination pass. */ /* fall out into the reconstruct-the-exit code. */ if (vex_control.iropt_verbosity > 0) /* really a misuse of vex_control.iropt_verbosity */ vex_printf("vex iropt: IRStmt_Exit became unconditional\n"); } } return IRStmt_Exit(fcond, st->Ist.Exit.jk, st->Ist.Exit.dst); } default: vex_printf("\n"); ppIRStmt(st); vpanic("subst_and_fold_Stmt"); }}IRBB* cprop_BB ( IRBB* in ){ Int i; IRBB* out; IRStmt* st2; Int n_tmps = in->tyenv->types_used; IRExpr** env = LibVEX_Alloc(n_tmps * sizeof(IRExpr*)); out = emptyIRBB(); out->tyenv = dopyIRTypeEnv( in->tyenv ); /* Set up the env with which travels forward. This holds a substitution, mapping IRTemps to atoms, that is, IRExprs which are either IRTemps or IRConsts. Thus, copy and constant propagation is done. The environment is to be applied as we move along. Keys are IRTemps. Values are IRExpr*s. */ for (i = 0; i < n_tmps; i++) env[i] = NULL; /* For each original SSA-form stmt ... */ for (i = 0; i < in->stmts_used; i++) { /* First apply the substitution to the current stmt. This propagates in any constants and tmp-tmp assignments accumulated prior to this point. As part of the subst_Stmt call, also then fold any constant expressions resulting. */ st2 = in->stmts[i]; /* perhaps st2 is already a no-op? */ if (st2->tag == Ist_NoOp) continue; st2 = subst_and_fold_Stmt( env, st2 ); /* If the statement has been folded into a no-op, forget it. */ if (st2->tag == Ist_NoOp) continue; /* Now consider what the stmt looks like. If it's of the form 't = const' or 't1 = t2', add it to the running environment and not to the output BB. Otherwise, add it to the output BB. Note, we choose not to propagate const when const is an F64i, so that F64i literals can be CSE'd later. This helps x86 floating point code generation. */ if (st2->tag == Ist_Tmp && st2->Ist.Tmp.data->tag == Iex_Const && st2->Ist.Tmp.data->Iex.Const.con->tag != Ico_F64i) { /* 't = const' -- add to env. The pair (IRTemp, IRExpr*) is added. */ env[(Int)(st2->Ist.Tmp.tmp)] = st2->Ist.Tmp.data; } else if (st2->tag == Ist_Tmp && st2->Ist.Tmp.data->tag == Iex_Tmp) { /* 't1 = t2' -- add to env. The pair (IRTemp, IRExpr*) is added. */ env[(Int)(st2->Ist.Tmp.tmp)] = st2->Ist.Tmp.data; } else { /* Not interesting, copy st2 into the output block. */ addStmtToIRBB( out, st2 ); } } out->next = subst_Expr( env, in->next ); out->jumpkind = in->jumpkind; return out;}/*---------------------------------------------------------------*//*--- Dead code (t = E) removal ---*//*---------------------------------------------------------------*//* As a side effect, also removes all code following an unconditional side exit. *//* The type of the HashHW map is: a map from IRTemp to nothing -- really just operating a set or IRTemps.*/inlinestatic void addUses_Temp ( Bool* set, IRTemp tmp ){ set[(Int)tmp] = True;}static void addUses_Expr ( Bool* set, IRExpr* e ){ Int i; switch (e->tag) { case Iex_GetI: addUses_Expr(set, e->Iex.GetI.ix); return; case Iex_Mux0X: addUses_Expr(set, e->Iex.Mux0X.cond); addUses_Expr(set, e->Iex.Mux0X.expr0); addUses_Expr(set, e->Iex.Mux0X.exprX); return; case Iex_CCall: for (i = 0; e->Iex.CCall.args[i]; i++) addUses_Expr(set, e->Iex.CCall.args[i]); return; case Iex_Load: addUses_Expr(set, e->Iex.Load.addr); return; case Iex_Qop: addUses_Expr(set, e->Iex.Qop.arg1); addUses_Expr(set, e->Iex.Qop.arg2); addUs
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?