]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Teach iropt to do dead code elimination.
authorJulian Seward <jseward@acm.org>
Wed, 18 Aug 2004 16:54:52 +0000 (16:54 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 18 Aug 2004 16:54:52 +0000 (16:54 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@177

VEX/priv/host-x86/isel.c
VEX/priv/ir/irdefs.c
VEX/priv/ir/iropt.c

index d876bd5c41c440fbb561396393b81c1968b36a32..f97248db45a47fd5d856c7939eb222bdf5c783ab 100644 (file)
@@ -1265,7 +1265,8 @@ HInstrArray* iselBB_X86 ( IRBB* bb, Addr64(*find_helper)(Char*) )
 
    /* Ok, finally we can iterate over the statements. */
    for (i = 0; i < bb->stmts_used; i++)
-      iselStmt(env,bb->stmts[i]);
+      if (bb->stmts[i])
+         iselStmt(env,bb->stmts[i]);
 
    iselNext(env,bb->next,bb->jumpkind);
 
index 7415517d22c7713da1920140b27616db31a6d3b8..abe97eeaef2ad418d1793606531571ef07420c32 100644 (file)
@@ -278,8 +278,10 @@ void ppIRBB ( IRBB* bb )
    ppIRTypeEnv(bb->tyenv);
    vex_printf("\n");
    for (i = 0; i < bb->stmts_used; i++) {
-      vex_printf( "   ");
-      ppIRStmt(bb->stmts[i]);
+      if (bb->stmts[i]) {
+         vex_printf( "   ");
+         ppIRStmt(bb->stmts[i]);
+      }
       vex_printf( "\n");
    }
    vex_printf( "   goto {");
@@ -764,7 +766,7 @@ void useBeforeDef_Expr ( IRBB* bb, IRStmt* stmt, IRExpr* expr, Int* def_counts )
          if (expr->Iex.Tmp.tmp < 0 || expr->Iex.Tmp.tmp >= bb->tyenv->types_used)
             sanityCheckFail(bb,stmt, "out of range Temp in IRExpr");
          if (def_counts[expr->Iex.Tmp.tmp] < 1)
-            sanityCheckFail(bb,stmt, "IRTemp def before use in IRExpr");
+            sanityCheckFail(bb,stmt, "IRTemp use before def in IRExpr");
          break;
       case Iex_Binop:
          useBeforeDef_Expr(bb,stmt,expr->Iex.Binop.arg1,def_counts);
@@ -980,6 +982,8 @@ void sanityCheckIRBB ( IRBB* bb, IRType guest_word_size )
 
    for (i = 0; i < bb->stmts_used; i++) {
       stmt = bb->stmts[i];
+      if (!stmt)
+         continue;
       useBeforeDef_Stmt(bb,stmt,def_counts);
       if (stmt->tag == Ist_Tmp) {
          if (stmt->Ist.Tmp.tmp < 0 || stmt->Ist.Tmp.tmp >= n_temps)
@@ -992,7 +996,8 @@ void sanityCheckIRBB ( IRBB* bb, IRType guest_word_size )
 
    /* Typecheck everything. */
    for (i = 0; i < bb->stmts_used; i++)
-      tcStmt( bb, bb->stmts[i], guest_word_size );
+      if (bb->stmts[i])
+         tcStmt( bb, bb->stmts[i], guest_word_size );
    if (typeOfIRExpr(bb->tyenv,bb->next) != guest_word_size)
       sanityCheckFail(bb, NULL, "bb->next field has wrong type");
 }
index c8ff64837c6212cc395e4b4a0a7a2af85fbffc66..d9a7bddf8a648aa54b60b23c7ad7b2931b6bfa34 100644 (file)
@@ -51,7 +51,8 @@ static Bool lookupH64 ( Hash64* h, /*OUT*/ULong* val, ULong key )
    //vex_printf("lookupH64(%llx)\n", key );
    for (i = 0; i < h->used; i++) {
       if (h->inuse[i] && h->key[i] == key) {
-         *val = h->val[i];
+         if (val)
+            *val = h->val[i];
          return True;
       }
    }
@@ -539,6 +540,111 @@ static IRBB* cprop_BB ( IRBB* in )
 
 
 
+/*---------------------------------------------------------------*/
+/*--- Dead code (t = E) removal                               ---*/
+/*---------------------------------------------------------------*/
+
+/* The type of the Hash64 map is: a map from IRTemp to nothing
+   -- really just operating a set or IRTemps.
+*/
+
+static void addUses_Expr ( Hash64* set, IRExpr* e )
+{
+   Int i;
+   switch (e->tag) {
+      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_LDle:
+         addUses_Expr(set, e->Iex.LDle.addr);
+         return;
+      case Iex_Binop:
+         addUses_Expr(set, e->Iex.Binop.arg1);
+         addUses_Expr(set, e->Iex.Binop.arg2);
+         return;
+      case Iex_Unop:
+         addUses_Expr(set, e->Iex.Unop.arg);
+         return;
+      case Iex_Tmp:
+         addToH64(set, (ULong)(e->Iex.Tmp.tmp), 0);
+         return;
+      case Iex_Const:
+      case Iex_Get:
+         return;
+      default:
+         vex_printf("\n");
+         ppIRExpr(e);
+         vpanic("addUses_Expr");
+   }
+}
+
+static void addUses_Stmt ( Hash64* set, IRStmt* st )
+{
+   switch (st->tag) {
+      case Ist_Exit:
+         addUses_Expr(set, st->Ist.Exit.cond);
+         return;
+      case Ist_Tmp:
+         addUses_Expr(set, st->Ist.Tmp.expr);
+         return;
+      case Ist_Put:
+         addUses_Expr(set, st->Ist.Put.expr);
+         return;
+      case Ist_STle:
+         addUses_Expr(set, st->Ist.STle.addr);
+         addUses_Expr(set, st->Ist.STle.data);
+         return;
+      default:
+         vex_printf("\n");
+         ppIRStmt(st);
+         vpanic("addUses_Stmt");
+      }
+}
+
+
+
+/* Note, this destructively modifies the given IRBB. */
+
+/* Scan backwards through statements, carrying a set of IRTemps which
+   are known to be used after the current point.  On encountering 't =
+   E', delete the binding if it is not used.  Otherwise, add any temp
+   uses to the set and keep on moving backwards. */
+
+void dead_BB ( IRBB* bb )
+{
+   Int     i;
+   Hash64* set = newH64();
+   IRStmt* st;
+
+   /* start off by recording IRTemp uses in the next field. */
+   addUses_Expr(set, bb->next);
+
+   /* Work backwards through the stmts */
+   for (i = bb->stmts_used-1; i >= 0; i--) {
+      st = bb->stmts[i];
+      if (st->tag == Ist_Tmp
+          && !lookupH64(set, NULL, (ULong)(st->Ist.Tmp.tmp))) {
+          /* it's an IRTemp which never got used.  Delete it. */
+         if (1) {
+            vex_printf("DEAD: ");
+            ppIRStmt(st);
+            vex_printf("\n");
+         }
+         bb->stmts[i] = NULL;
+      } else {
+         /* Note any IRTemp uses made by the current statement. */
+         addUses_Stmt(set, st);
+      }
+   }
+}
+
+
 /*---------------------------------------------------------------*/
 /*--- iropt main                                              ---*/
 /*---------------------------------------------------------------*/
@@ -565,6 +671,11 @@ IRBB* do_iropt_BB ( IRBB* bb0 )
       vex_printf("\n========= CPROPD\n\n" );
       ppIRBB(cpd);
    }
+   dead_BB ( cpd );
+   if (verbose) {
+      vex_printf("\n========= DEAD\n\n" );
+      ppIRBB(cpd);
+   }
    return cpd;
 }