]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Tidy up ir_opt.c aspects relating to the 'grail' work. In particular:
authorJulian Seward <jseward@acm.org>
Thu, 21 Nov 2019 19:03:47 +0000 (20:03 +0100)
committerJulian Seward <jseward@acm.org>
Thu, 21 Nov 2019 19:03:47 +0000 (20:03 +0100)
* 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
VEX/priv/ir_defs.c
VEX/priv/ir_opt.c
VEX/pub/libvex_ir.h

index 7477641500b9df4e4375dc6745ab7d54d15a3dfc..f890c3338b7f04134c7e2bc4eaab07f2e91638f2 100644 (file)
@@ -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,
index d687d8f0a4629f4bafdd66fdc4dc82d7b0e2c3a2..7b6e847fdb87caeb4579098fda903f5e786237e7 100644 (file)
@@ -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                                         ---*/
index ca677128df3cdd702bc9426cb72c41324f74c298..d3bc989e4551fd47d717c9b9eb52d51b2b3b8c6e 100644 (file)
@@ -1376,7 +1376,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 */
@@ -2463,7 +2464,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");
    }
@@ -2484,7 +2485,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");
    }
@@ -2492,6 +2493,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. */
@@ -2607,32 +2616,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: {
@@ -2641,9 +2654,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);
       }
 
@@ -2652,7 +2665,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:
@@ -2660,8 +2673,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: {
@@ -2669,9 +2682,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);
@@ -2696,9 +2709,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);
@@ -2730,13 +2743,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);
       }
@@ -2748,9 +2763,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
                 );
 
@@ -2763,15 +2779,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);
@@ -2791,7 +2807,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. */
@@ -2822,7 +2838,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;
@@ -2859,7 +2876,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) {
@@ -2902,7 +2919,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);
@@ -2990,7 +3007,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);
 }
 
 
@@ -6657,23 +6674,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
@@ -6681,7 +6693,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
@@ -6736,7 +6749,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 );
@@ -6757,22 +6770,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 );
 
@@ -6781,9 +6779,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:
index 9120a49fc422658bb69c06a8b6774f25a6f58e0e..6a854e43f19fd58dd1fea79f19e64276fdaf52d6 100644 (file)
@@ -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 );