From 202184079b7539450a99d7cdbd07b0af4874d3de Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Thu, 21 Nov 2019 20:03:47 +0100 Subject: [PATCH] Tidy up ir_opt.c aspects relating to the 'grail' work. In particular: * Rewrite do_minimal_initial_iropt_BB so it doesn't do full constant folding; that is unnecessary expense at this point, and later passes will do it anyway * do_iropt_BB: don't flatten the incoming block, because do_minimal_initial_iropt_BB will have run earlier and done so. But at least for the moment, assert that it really is flat. * VEX/priv/guest_generic_bb_to_IR.c create_self_checks_as_needed: generate flat IR so as not to fail the abovementioned assertion. I believe this completes the target-independent aspects of this work, and also the x86_64 specifics (of which there are very few). --- VEX/priv/guest_generic_bb_to_IR.c | 82 +++++++++++++--------- VEX/priv/ir_defs.c | 16 ++++- VEX/priv/ir_opt.c | 139 +++++++++++++++++++------------------- VEX/pub/libvex_ir.h | 3 +- 4 files changed, 136 insertions(+), 104 deletions(-) diff --git a/VEX/priv/guest_generic_bb_to_IR.c b/VEX/priv/guest_generic_bb_to_IR.c index 747764150..f890c3338 100644 --- a/VEX/priv/guest_generic_bb_to_IR.c +++ b/VEX/priv/guest_generic_bb_to_IR.c @@ -128,7 +128,7 @@ static void create_self_checks_as_needed( Addr base2check; UInt len2check; HWord expectedhW; - IRTemp tistart_tmp, tilen_tmp; + IRTemp tistart_tmp, tilen_tmp, callresult_tmp, exitguard_tmp; HWord VEX_REGPARM(2) (*fn_generic)(HWord, HWord); HWord VEX_REGPARM(1) (*fn_spec)(HWord); const HChar* nm_generic; @@ -161,7 +161,7 @@ static void create_self_checks_as_needed( const Int n_extent_slots = sizeof(vge->base) / sizeof(vge->base[0]); vassert(n_extent_slots == 3); - vassert(selfcheck_idx + (n_extent_slots - 1) * 5 + 4 < irsb->stmts_used); + vassert(selfcheck_idx + (n_extent_slots - 1) * 7 + 6 < irsb->stmts_used); for (Int i = 0; i < vge->n_used; i++) { /* Do we need to generate a check for this extent? */ @@ -297,16 +297,20 @@ static void create_self_checks_as_needed( = guest_word_type==Ity_I32 ? IRConst_U32(len2check) : IRConst_U64(len2check); - IRStmt** stmt0 = &irsb->stmts[selfcheck_idx + i * 5 + 0]; - IRStmt** stmt1 = &irsb->stmts[selfcheck_idx + i * 5 + 1]; - IRStmt** stmt2 = &irsb->stmts[selfcheck_idx + i * 5 + 2]; - IRStmt** stmt3 = &irsb->stmts[selfcheck_idx + i * 5 + 3]; - IRStmt** stmt4 = &irsb->stmts[selfcheck_idx + i * 5 + 4]; + IRStmt** stmt0 = &irsb->stmts[selfcheck_idx + i * 7 + 0]; + IRStmt** stmt1 = &irsb->stmts[selfcheck_idx + i * 7 + 1]; + IRStmt** stmt2 = &irsb->stmts[selfcheck_idx + i * 7 + 2]; + IRStmt** stmt3 = &irsb->stmts[selfcheck_idx + i * 7 + 3]; + IRStmt** stmt4 = &irsb->stmts[selfcheck_idx + i * 7 + 4]; + IRStmt** stmt5 = &irsb->stmts[selfcheck_idx + i * 7 + 5]; + IRStmt** stmt6 = &irsb->stmts[selfcheck_idx + i * 7 + 6]; vassert((*stmt0)->tag == Ist_NoOp); vassert((*stmt1)->tag == Ist_NoOp); vassert((*stmt2)->tag == Ist_NoOp); vassert((*stmt3)->tag == Ist_NoOp); vassert((*stmt4)->tag == Ist_NoOp); + vassert((*stmt5)->tag == Ist_NoOp); + vassert((*stmt6)->tag == Ist_NoOp); *stmt0 = IRStmt_WrTmp(tistart_tmp, IRExpr_Const(base2check_IRConst) ); *stmt1 = IRStmt_WrTmp(tilen_tmp, IRExpr_Const(len2check_IRConst) ); @@ -332,6 +336,8 @@ static void create_self_checks_as_needed( } } + /* Generate the call to the relevant function, and the comparison of + the result against the expected value. */ IRExpr* callexpr = NULL; if (fn_spec) { callexpr = mkIRExprCCall( @@ -352,36 +358,46 @@ static void create_self_checks_as_needed( ); } - *stmt4 - = IRStmt_Exit( - IRExpr_Binop( - host_word_type==Ity_I64 ? Iop_CmpNE64 : Iop_CmpNE32, - callexpr, - host_word_type==Ity_I64 - ? IRExpr_Const(IRConst_U64(expectedhW)) - : IRExpr_Const(IRConst_U32(expectedhW)) - ), - Ijk_InvalICache, - /* Where we must restart if there's a failure: at the - first extent, regardless of which extent the - failure actually happened in. */ - guest_IP_sbstart_IRConst, - offB_GUEST_IP - ); + callresult_tmp = newIRTemp(irsb->tyenv, host_word_type); + *stmt4 = IRStmt_WrTmp(callresult_tmp, callexpr); + + exitguard_tmp = newIRTemp(irsb->tyenv, Ity_I1); + *stmt5 = IRStmt_WrTmp( + exitguard_tmp, + IRExpr_Binop( + host_word_type==Ity_I64 ? Iop_CmpNE64 : Iop_CmpNE32, + IRExpr_RdTmp(callresult_tmp), + host_word_type==Ity_I64 + ? IRExpr_Const(IRConst_U64(expectedhW)) + : IRExpr_Const(IRConst_U32(expectedhW)))); + + *stmt6 = IRStmt_Exit( + IRExpr_RdTmp(exitguard_tmp), + Ijk_InvalICache, + /* Where we must restart if there's a failure: at the + first extent, regardless of which extent the failure + actually happened in. */ + guest_IP_sbstart_IRConst, + offB_GUEST_IP + ); } /* for (i = 0; i < vge->n_used; i++) */ for (Int i = vge->n_used; i < sizeof(vge->base) / sizeof(vge->base[0]); i++) { - IRStmt* stmt0 = irsb->stmts[selfcheck_idx + i * 5 + 0]; - IRStmt* stmt1 = irsb->stmts[selfcheck_idx + i * 5 + 1]; - IRStmt* stmt2 = irsb->stmts[selfcheck_idx + i * 5 + 2]; - IRStmt* stmt3 = irsb->stmts[selfcheck_idx + i * 5 + 3]; - IRStmt* stmt4 = irsb->stmts[selfcheck_idx + i * 5 + 4]; + IRStmt* stmt0 = irsb->stmts[selfcheck_idx + i * 7 + 0]; + IRStmt* stmt1 = irsb->stmts[selfcheck_idx + i * 7 + 1]; + IRStmt* stmt2 = irsb->stmts[selfcheck_idx + i * 7 + 2]; + IRStmt* stmt3 = irsb->stmts[selfcheck_idx + i * 7 + 3]; + IRStmt* stmt4 = irsb->stmts[selfcheck_idx + i * 7 + 4]; + IRStmt* stmt5 = irsb->stmts[selfcheck_idx + i * 7 + 5]; + IRStmt* stmt6 = irsb->stmts[selfcheck_idx + i * 7 + 6]; vassert(stmt0->tag == Ist_NoOp); vassert(stmt1->tag == Ist_NoOp); vassert(stmt2->tag == Ist_NoOp); vassert(stmt3->tag == Ist_NoOp); vassert(stmt4->tag == Ist_NoOp); + vassert(stmt5->tag == Ist_NoOp); + vassert(stmt6->tag == Ist_NoOp); } } } @@ -1260,13 +1276,13 @@ IRSB* bb_to_IR ( /* And a new IR superblock to dump the result into. */ IRSB* irsb = emptyIRSB(); - /* Leave 15 spaces in which to put the check statements for a self - checking translation (up to 3 extents, and 5 stmts required for + /* Leave 21 spaces in which to put the check statements for a self + checking translation (up to 3 extents, and 7 stmts required for each). We won't know until later the extents and checksums of the areas, if any, that need to be checked. */ IRStmt* nop = IRStmt_NoOp(); Int selfcheck_idx = irsb->stmts_used; - for (Int i = 0; i < 3 * 5; i++) + for (Int i = 0; i < 3 * 7; i++) addStmtToIRSB( irsb, nop ); /* If the caller supplied a function to add its own preamble, use @@ -1277,7 +1293,7 @@ IRSB* bb_to_IR ( /* The callback has completed the IR block without any guest insns being disassembled into it, so just return it at this point, even if a self-check was requested - as there - is nothing to self-check. The 15 self-check no-ops will + is nothing to self-check. The 21 self-check no-ops will still be in place, but they are harmless. */ vge->n_used = 1; vge->base[0] = guest_IP_sbstart; @@ -1586,7 +1602,7 @@ IRSB* bb_to_IR ( /* We're almost done. The only thing that might need attending to is that a self-checking preamble may need to be created. If so it gets placed - in the 15 slots reserved above. */ + in the 21 slots reserved above. */ create_self_checks_as_needed( irsb, n_sc_extents, pxControl, callback_opaque, needs_self_check, vge, abiinfo_both, guest_word_type, selfcheck_idx, offB_GUEST_CMSTART, diff --git a/VEX/priv/ir_defs.c b/VEX/priv/ir_defs.c index d687d8f0a..7b6e847fd 100644 --- a/VEX/priv/ir_defs.c +++ b/VEX/priv/ir_defs.c @@ -4270,7 +4270,7 @@ static inline Bool isIRAtom_or_VECRET_or_GSPTR ( const IRExpr* e ) return UNLIKELY(is_IRExpr_VECRET_or_GSPTR(e)); } -Bool isFlatIRStmt ( const IRStmt* st ) +inline Bool isFlatIRStmt ( const IRStmt* st ) { Int i; const IRExpr* e; @@ -4374,6 +4374,20 @@ Bool isFlatIRStmt ( const IRStmt* st ) } } +Bool isFlatIRSB ( const IRSB* sb ) +{ + for (Int i = 0; i < sb->stmts_used; i++) { + if (!isFlatIRStmt(sb->stmts[i])) + return False; + } + + if (!isIRAtom(sb->next)) { + return False; + } + + return True; +} + /*---------------------------------------------------------------*/ /*--- Sanity checking ---*/ diff --git a/VEX/priv/ir_opt.c b/VEX/priv/ir_opt.c index 9e9c02601..aa259ae5f 100644 --- a/VEX/priv/ir_opt.c +++ b/VEX/priv/ir_opt.c @@ -1374,7 +1374,8 @@ static IRExpr* chase1 ( IRExpr** env, IRExpr* e ) return env[(Int)e->Iex.RdTmp.tmp]; } -static IRExpr* fold_Expr ( IRExpr** env, IRExpr* e ) +__attribute__((noinline)) +static IRExpr* fold_Expr_WRK ( IRExpr** env, IRExpr* e ) { Int shift; IRExpr* e2 = e; /* e2 is the result of folding e, if possible */ @@ -2460,7 +2461,7 @@ static IRExpr* fold_Expr ( IRExpr** env, IRExpr* e ) && !debug_only_hack_sameIRExprs_might_assert(e->Iex.Binop.arg1, e->Iex.Binop.arg2) && sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) { - vex_printf("vex iropt: fold_Expr: no ident rule for: "); + vex_printf("vex iropt: fold_Expr_WRK: no ident rule for: "); ppIRExpr(e); vex_printf("\n"); } @@ -2481,7 +2482,7 @@ static IRExpr* fold_Expr ( IRExpr** env, IRExpr* e ) vpanic("fold_Expr: no rule for the above"); # else if (vex_control.iropt_verbosity > 0) { - vex_printf("vex iropt: fold_Expr: no const rule for: "); + vex_printf("vex iropt: fold_Expr_WRK: no const rule for: "); ppIRExpr(e); vex_printf("\n"); } @@ -2489,6 +2490,14 @@ static IRExpr* fold_Expr ( IRExpr** env, IRExpr* e ) # endif } +/* Fold |e| as much as possible, given the bindings in |env|. If no folding is + possible, just return |e|. Also, if |env| is NULL, don't even try to + fold; just return |e| directly. */ +inline +static IRExpr* fold_Expr ( IRExpr** env, IRExpr* e ) +{ + return env == NULL ? e : fold_Expr_WRK(env, e); +} /* Apply the subst to a simple 1-level expression -- guaranteed to be 1-level due to previous flattening pass. */ @@ -2604,32 +2613,36 @@ static IRExpr* subst_Expr ( IRExpr** env, IRExpr* ex ) } -/* 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. +/* Apply the subst to stmt, then, if |doFolding| is |True|, 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 ) +static IRStmt* subst_and_maybe_fold_Stmt ( Bool doFolding, + IRExpr** env, IRStmt* st ) { # if 0 - vex_printf("\nsubst and fold stmt\n"); + vex_printf("\nsubst and maybe fold stmt\n"); ppIRStmt(st); vex_printf("\n"); # endif + IRExpr** s_env = env; + IRExpr** f_env = doFolding ? env : NULL; + switch (st->tag) { case Ist_AbiHint: vassert(isIRAtom(st->Ist.AbiHint.base)); vassert(isIRAtom(st->Ist.AbiHint.nia)); return IRStmt_AbiHint( - fold_Expr(env, subst_Expr(env, st->Ist.AbiHint.base)), + fold_Expr(f_env, subst_Expr(s_env, st->Ist.AbiHint.base)), st->Ist.AbiHint.len, - fold_Expr(env, subst_Expr(env, st->Ist.AbiHint.nia)) + fold_Expr(f_env, subst_Expr(s_env, st->Ist.AbiHint.nia)) ); case Ist_Put: vassert(isIRAtom(st->Ist.Put.data)); return IRStmt_Put( st->Ist.Put.offset, - fold_Expr(env, subst_Expr(env, st->Ist.Put.data)) + fold_Expr(f_env, subst_Expr(s_env, st->Ist.Put.data)) ); case Ist_PutI: { @@ -2638,9 +2651,9 @@ static IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st ) vassert(isIRAtom(puti->ix)); vassert(isIRAtom(puti->data)); puti2 = mkIRPutI(puti->descr, - fold_Expr(env, subst_Expr(env, puti->ix)), + fold_Expr(f_env, subst_Expr(s_env, puti->ix)), puti->bias, - fold_Expr(env, subst_Expr(env, puti->data))); + fold_Expr(f_env, subst_Expr(s_env, puti->data))); return IRStmt_PutI(puti2); } @@ -2649,7 +2662,7 @@ static IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st ) allowed to be more than just a constant or a tmp. */ return IRStmt_WrTmp( st->Ist.WrTmp.tmp, - fold_Expr(env, subst_Expr(env, st->Ist.WrTmp.data)) + fold_Expr(f_env, subst_Expr(s_env, st->Ist.WrTmp.data)) ); case Ist_Store: @@ -2657,8 +2670,8 @@ static IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st ) vassert(isIRAtom(st->Ist.Store.data)); return IRStmt_Store( st->Ist.Store.end, - fold_Expr(env, subst_Expr(env, st->Ist.Store.addr)), - fold_Expr(env, subst_Expr(env, st->Ist.Store.data)) + fold_Expr(f_env, subst_Expr(s_env, st->Ist.Store.addr)), + fold_Expr(f_env, subst_Expr(s_env, st->Ist.Store.data)) ); case Ist_StoreG: { @@ -2666,9 +2679,9 @@ static IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st ) vassert(isIRAtom(sg->addr)); vassert(isIRAtom(sg->data)); vassert(isIRAtom(sg->guard)); - IRExpr* faddr = fold_Expr(env, subst_Expr(env, sg->addr)); - IRExpr* fdata = fold_Expr(env, subst_Expr(env, sg->data)); - IRExpr* fguard = fold_Expr(env, subst_Expr(env, sg->guard)); + IRExpr* faddr = fold_Expr(f_env, subst_Expr(s_env, sg->addr)); + IRExpr* fdata = fold_Expr(f_env, subst_Expr(s_env, sg->data)); + IRExpr* fguard = fold_Expr(f_env, subst_Expr(s_env, sg->guard)); if (fguard->tag == Iex_Const) { /* The condition on this store has folded down to a constant. */ vassert(fguard->Iex.Const.con->tag == Ico_U1); @@ -2693,9 +2706,9 @@ static IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st ) vassert(isIRAtom(lg->addr)); vassert(isIRAtom(lg->alt)); vassert(isIRAtom(lg->guard)); - IRExpr* faddr = fold_Expr(env, subst_Expr(env, lg->addr)); - IRExpr* falt = fold_Expr(env, subst_Expr(env, lg->alt)); - IRExpr* fguard = fold_Expr(env, subst_Expr(env, lg->guard)); + IRExpr* faddr = fold_Expr(f_env, subst_Expr(s_env, lg->addr)); + IRExpr* falt = fold_Expr(f_env, subst_Expr(s_env, lg->alt)); + IRExpr* fguard = fold_Expr(f_env, subst_Expr(s_env, lg->guard)); if (fguard->tag == Iex_Const) { /* The condition on this load has folded down to a constant. */ vassert(fguard->Iex.Const.con->tag == Ico_U1); @@ -2727,13 +2740,15 @@ static IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st ) vassert(isIRAtom(cas->dataLo)); cas2 = mkIRCAS( cas->oldHi, cas->oldLo, cas->end, - fold_Expr(env, subst_Expr(env, cas->addr)), - cas->expdHi ? fold_Expr(env, subst_Expr(env, cas->expdHi)) + fold_Expr(f_env, subst_Expr(s_env, cas->addr)), + cas->expdHi ? fold_Expr(f_env, + subst_Expr(s_env, cas->expdHi)) : NULL, - fold_Expr(env, subst_Expr(env, cas->expdLo)), - cas->dataHi ? fold_Expr(env, subst_Expr(env, cas->dataHi)) + fold_Expr(f_env, subst_Expr(s_env, cas->expdLo)), + cas->dataHi ? fold_Expr(f_env, + subst_Expr(s_env, cas->dataHi)) : NULL, - fold_Expr(env, subst_Expr(env, cas->dataLo)) + fold_Expr(f_env, subst_Expr(s_env, cas->dataLo)) ); return IRStmt_CAS(cas2); } @@ -2745,9 +2760,10 @@ static IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st ) return IRStmt_LLSC( st->Ist.LLSC.end, st->Ist.LLSC.result, - fold_Expr(env, subst_Expr(env, st->Ist.LLSC.addr)), + fold_Expr(f_env, subst_Expr(s_env, st->Ist.LLSC.addr)), st->Ist.LLSC.storedata - ? fold_Expr(env, subst_Expr(env, st->Ist.LLSC.storedata)) + ? fold_Expr(f_env, + subst_Expr(s_env, st->Ist.LLSC.storedata)) : NULL ); @@ -2760,15 +2776,15 @@ static IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st ) d2->args = shallowCopyIRExprVec(d2->args); if (d2->mFx != Ifx_None) { vassert(isIRAtom(d2->mAddr)); - d2->mAddr = fold_Expr(env, subst_Expr(env, d2->mAddr)); + d2->mAddr = fold_Expr(f_env, subst_Expr(s_env, d2->mAddr)); } vassert(isIRAtom(d2->guard)); - d2->guard = fold_Expr(env, subst_Expr(env, d2->guard)); + d2->guard = fold_Expr(f_env, subst_Expr(s_env, d2->guard)); for (i = 0; d2->args[i]; i++) { IRExpr* arg = d2->args[i]; if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg))) { vassert(isIRAtom(arg)); - d2->args[i] = fold_Expr(env, subst_Expr(env, arg)); + d2->args[i] = fold_Expr(f_env, subst_Expr(s_env, arg)); } } return IRStmt_Dirty(d2); @@ -2788,7 +2804,7 @@ static IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st ) case Ist_Exit: { IRExpr* fcond; vassert(isIRAtom(st->Ist.Exit.guard)); - fcond = fold_Expr(env, subst_Expr(env, st->Ist.Exit.guard)); + fcond = fold_Expr(f_env, subst_Expr(s_env, st->Ist.Exit.guard)); if (fcond->tag == Iex_Const) { /* Interesting. The condition on this exit has folded down to a constant. */ @@ -2819,7 +2835,8 @@ static IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st ) } -static IRSB* cprop_BB_wrk ( IRSB* in, Bool mustRetainNoOps ) +__attribute__((noinline)) +static IRSB* cprop_BB_WRK ( IRSB* in, Bool mustRetainNoOps, Bool doFolding ) { Int i; IRSB* out; @@ -2856,7 +2873,7 @@ static IRSB* cprop_BB_wrk ( IRSB* in, Bool mustRetainNoOps ) /* perhaps st2 is already a no-op? */ if (st2->tag == Ist_NoOp && !mustRetainNoOps) continue; - st2 = subst_and_fold_Stmt( env, st2 ); + st2 = subst_and_maybe_fold_Stmt( doFolding, env, st2 ); /* Deal with some post-folding special cases. */ switch (st2->tag) { @@ -2899,7 +2916,7 @@ static IRSB* cprop_BB_wrk ( IRSB* in, Bool mustRetainNoOps ) IRExpr* guard = lg->guard; if (guard->tag == Iex_Const) { /* The guard has folded to a constant, and that - constant must be 1:I1, since subst_and_fold_Stmt + constant must be 1:I1, since subst_and_maybe_fold_Stmt folds out the case 0:I1 by itself. */ vassert(guard->Iex.Const.con->tag == Ico_U1); vassert(guard->Iex.Const.con->Ico.U1 == True); @@ -2987,7 +3004,7 @@ static IRSB* cprop_BB_wrk ( IRSB* in, Bool mustRetainNoOps ) IRSB* cprop_BB ( IRSB* in ) { - return cprop_BB_wrk(in, /*mustRetainNoOps=*/False); + return cprop_BB_WRK(in, /*mustRetainNoOps=*/False, /*doFolding=*/True); } @@ -6654,23 +6671,18 @@ IRSB* do_iropt_BB( static Int n_expensive = 0; Bool hasGetIorPutI, hasVorFtemps; - IRSB *bb, *bb2; n_total++; - /* First flatten the block out, since all other - phases assume flat code. */ - // FIXME this is no longer necessary, since minimal_iropt should have - // flattened it - bb = flatten_BB ( bb0 ); - - if (iropt_verbose) { - vex_printf("\n========= FLAT\n\n" ); - ppIRSB(bb); - } + /* Flatness: this function assumes that the incoming block is already flat. + That's because all blocks that arrive here should already have been + processed by do_minimal_initial_iropt_BB. And that will have flattened + them out. */ + // FIXME Remove this assertion once the 'grail' machinery seems stable + vassert(isFlatIRSB(bb0)); /* If at level 0, stop now. */ - if (vex_control.iropt_level <= 0) return bb; + if (vex_control.iropt_level <= 0) return bb0; /* Now do a preliminary cleanup pass, and figure out if we also need to do 'expensive' optimisations. Expensive optimisations @@ -6678,7 +6690,8 @@ IRSB* do_iropt_BB( If needed, do expensive transformations and then another cheap cleanup pass. */ - bb = cheap_transformations( bb, specHelper, preciseMemExnsFn, pxControl ); + IRSB* bb = cheap_transformations( bb0, specHelper, + preciseMemExnsFn, pxControl ); if (guest_arch == VexArchARM) { /* Translating Thumb2 code produces a lot of chaff. We have to @@ -6733,7 +6746,7 @@ IRSB* do_iropt_BB( /* Now have a go at unrolling simple (single-BB) loops. If successful, clean up the results as much as possible. */ - bb2 = maybe_loop_unroll_BB( bb, guest_addr ); + IRSB* bb2 = maybe_loop_unroll_BB( bb, guest_addr ); if (bb2) { bb = cheap_transformations( bb2, specHelper, preciseMemExnsFn, pxControl ); @@ -6754,22 +6767,7 @@ IRSB* do_iropt_BB( return bb; } -//static Bool alwaysPrecise ( Int minoff, Int maxoff, -// VexRegisterUpdates pxControl ) -//{ -// return True; -//} - -// FIXME make this as cheap as possible -IRSB* do_minimal_initial_iropt_BB( - IRSB* bb0 - //IRExpr* (*specHelper) (const HChar*, IRExpr**, IRStmt**, Int), - //Bool (*preciseMemExnsFn)(Int,Int,VexRegisterUpdates), - //VexRegisterUpdates pxControl, - //Addr guest_addr, - //VexArch guest_arch - ) -{ +IRSB* do_minimal_initial_iropt_BB(IRSB* bb0) { /* First flatten the block out, since all other phases assume flat code. */ IRSB* bb = flatten_BB ( bb0 ); @@ -6778,9 +6776,12 @@ IRSB* do_minimal_initial_iropt_BB( ppIRSB(bb); } + // Remove redundant GETs redundant_get_removal_BB ( bb ); - bb = cprop_BB_wrk ( bb, /*mustRetainNoOps=*/True ); // FIXME - // This is overkill. We only really want constant prop, not folding + + // Do minimal constant prop: copy prop and constant prop only. No folding. + bb = cprop_BB_WRK ( bb, /*mustRetainNoOps=*/True, + /*doFolding=*/False ); // Minor tidying of the block end, to remove a redundant Put of the IP right // at the end: diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h index 9120a49fc..6a854e43f 100644 --- a/VEX/pub/libvex_ir.h +++ b/VEX/pub/libvex_ir.h @@ -2388,7 +2388,7 @@ IRExpr* mkIRExprCCall ( IRType retty, /* Convenience functions for atoms (IRExprs which are either Iex_Tmp or * Iex_Const). */ static inline Bool isIRAtom ( const IRExpr* e ) { - return toBool(e->tag == Iex_RdTmp || e->tag == Iex_Const); + return e->tag == Iex_RdTmp || e->tag == Iex_Const; } /* Are these two IR atoms identical? Causes an assertion @@ -3195,6 +3195,7 @@ extern void sanityCheckIRSB ( const IRSB* bb, Bool require_flatness, IRType guest_word_size ); extern Bool isFlatIRStmt ( const IRStmt* ); +extern Bool isFlatIRSB ( const IRSB* ); /* Is this any value actually in the enumeration 'IRType' ? */ extern Bool isPlausibleIRType ( IRType ty ); -- 2.11.4.GIT