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 {");
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);
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)
/* 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");
}
//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;
}
}
+/*---------------------------------------------------------------*/
+/*--- 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 ---*/
/*---------------------------------------------------------------*/
vex_printf("\n========= CPROPD\n\n" );
ppIRBB(cpd);
}
+ dead_BB ( cpd );
+ if (verbose) {
+ vex_printf("\n========= DEAD\n\n" );
+ ppIRBB(cpd);
+ }
return cpd;
}