From: Julian Seward Date: Mon, 21 Mar 2005 00:15:53 +0000 (+0000) Subject: Add a new IR statement kind: IRStmt_NoOp, to denote a no-operation. X-Git-Tag: svn/VALGRIND_3_0_1^2~273 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9aa2874a241aa337857bd0b4cc85bd146b80f627;p=thirdparty%2Fvalgrind.git Add a new IR statement kind: IRStmt_NoOp, to denote a no-operation. These are generated by the IR optimiser. The use of no-ops replaces the old practice of allowing a BB to contain NULL pointers in its statement array as a way of denoting no-ops. NULL stmts are now no longer allowed under any circumstances, and the IR sanity checker will reject any BB containing them. git-svn-id: svn://svn.valgrind.org/vex/trunk@1061 --- diff --git a/VEX/priv/host-x86/isel.c b/VEX/priv/host-x86/isel.c index 1ba1af1d23..247a3148f7 100644 --- a/VEX/priv/host-x86/isel.c +++ b/VEX/priv/host-x86/isel.c @@ -3377,6 +3377,11 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) case Ist_IMark: return; + /* --------- NO-OP --------- */ + /* Fairly self-explanatory, wouldn't you say? */ + case Ist_NoOp: + return; + /* --------- EXIT --------- */ case Ist_Exit: { X86RI* dst; @@ -3476,8 +3481,7 @@ HInstrArray* iselBB_X86 ( IRBB* bb, VexSubArch subarch_host ) /* Ok, finally we can iterate over the statements. */ for (i = 0; i < bb->stmts_used; i++) - if (bb->stmts[i]) - iselStmt(env,bb->stmts[i]); + iselStmt(env,bb->stmts[i]); iselNext(env,bb->next,bb->jumpkind); diff --git a/VEX/priv/ir/irdefs.c b/VEX/priv/ir/irdefs.c index 0a86dbbf72..acb58ff91d 100644 --- a/VEX/priv/ir/irdefs.c +++ b/VEX/priv/ir/irdefs.c @@ -576,7 +576,14 @@ void ppIRJumpKind ( IRJumpKind kind ) void ppIRStmt ( IRStmt* s ) { + if (!s) { + vex_printf("!!! IRStmt* which is NULL !!!"); + return; + } switch (s->tag) { + case Ist_NoOp: + vex_printf("IR-NoOp"); + break; case Ist_IMark: vex_printf( "------ IMark(0x%llx, %d) ------", s->Ist.IMark.addr, s->Ist.IMark.len); @@ -608,7 +615,7 @@ void ppIRStmt ( IRStmt* s ) ppIRDirty(s->Ist.Dirty.details); break; case Ist_MFence: - vex_printf("IRMemoryFence"); + vex_printf("IR-MFence"); break; case Ist_Exit: vex_printf( "if (" ); @@ -647,10 +654,8 @@ void ppIRBB ( IRBB* bb ) ppIRTypeEnv(bb->tyenv); vex_printf("\n"); for (i = 0; i < bb->stmts_used; i++) { - if (bb->stmts[i]) { - vex_printf( " "); - ppIRStmt(bb->stmts[i]); - } + vex_printf( " "); + ppIRStmt(bb->stmts[i]); vex_printf( "\n"); } vex_printf( " goto {"); @@ -904,6 +909,13 @@ IRDirty* emptyIRDirty ( void ) { /* Constructors -- IRStmt */ +IRStmt* IRStmt_NoOp ( void ) +{ + /* Just use a single static closure. */ + static IRStmt static_closure; + static_closure.tag = Ist_NoOp; + return &static_closure; +} IRStmt* IRStmt_IMark ( Addr64 addr, Int len ) { IRStmt* s = LibVEX_Alloc(sizeof(IRStmt)); s->tag = Ist_IMark; @@ -951,9 +963,10 @@ IRStmt* IRStmt_Dirty ( IRDirty* d ) } IRStmt* IRStmt_MFence ( void ) { - IRStmt* s = LibVEX_Alloc(sizeof(IRStmt)); - s->tag = Ist_MFence; - return s; + /* Just use a single static closure. */ + static IRStmt static_closure; + static_closure.tag = Ist_MFence; + return &static_closure; } IRStmt* IRStmt_Exit ( IRExpr* guard, IRJumpKind jk, IRConst* dst ) { IRStmt* s = LibVEX_Alloc(sizeof(IRStmt)); @@ -1113,6 +1126,8 @@ IRDirty* dopyIRDirty ( IRDirty* d ) IRStmt* dopyIRStmt ( IRStmt* s ) { switch (s->tag) { + case Ist_NoOp: + return IRStmt_NoOp(); case Ist_IMark: return IRStmt_IMark(s->Ist.IMark.addr, s->Ist.IMark.len); case Ist_Put: @@ -1131,6 +1146,8 @@ IRStmt* dopyIRStmt ( IRStmt* s ) dopyIRExpr(s->Ist.STle.data)); case Ist_Dirty: return IRStmt_Dirty(dopyIRDirty(s->Ist.Dirty.details)); + case Ist_MFence: + return IRStmt_MFence(); case Ist_Exit: return IRStmt_Exit(dopyIRExpr(s->Ist.Exit.guard), s->Ist.Exit.jk, @@ -1161,7 +1178,7 @@ IRBB* dopyIRBB ( IRBB* bb ) bb2->stmts_used = bb2->stmts_size = bb->stmts_used; sts2 = LibVEX_Alloc(bb2->stmts_used * sizeof(IRStmt*)); for (i = 0; i < bb2->stmts_used; i++) - sts2[i] = bb->stmts[i]==NULL ? NULL : dopyIRStmt(bb->stmts[i]); + sts2[i] = dopyIRStmt(bb->stmts[i]); bb2->stmts = sts2; bb2->next = dopyIRExpr(bb->next); bb2->jumpkind = bb->jumpkind; @@ -1625,6 +1642,7 @@ Bool isFlatIRStmt ( IRStmt* st ) if (di->mAddr && !isIRAtom(di->mAddr)) return False; return True; + case Ist_NoOp: case Ist_IMark: case Ist_MFence: return True; @@ -1786,6 +1804,7 @@ void useBeforeDef_Stmt ( IRBB* bb, IRStmt* stmt, Int* def_counts ) if (d->mFx != Ifx_None) useBeforeDef_Expr(bb,stmt,d->mAddr,def_counts); break; + case Ist_NoOp: case Ist_MFence: break; case Ist_Exit: @@ -1981,6 +2000,7 @@ void tcStmt ( IRBB* bb, IRStmt* stmt, IRType gWordTy ) break; bad_dirty: sanityCheckFail(bb,stmt,"IRStmt.Dirty: ill-formed"); + case Ist_NoOp: case Ist_MFence: break; case Ist_Exit: @@ -2031,7 +2051,7 @@ void sanityCheckIRBB ( IRBB* bb, HChar* caller, for (i = 0; i < bb->stmts_used; i++) { stmt = bb->stmts[i]; if (!stmt) - continue; + sanityCheckFail(bb, stmt, "IRStmt: is NULL"); if (!isFlatIRStmt(stmt)) sanityCheckFail(bb, stmt, "IRStmt: is not flat"); } @@ -2047,8 +2067,6 @@ void sanityCheckIRBB ( IRBB* bb, HChar* caller, 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) { diff --git a/VEX/priv/ir/iropt.c b/VEX/priv/ir/iropt.c index 99c32741bd..0e65d542d8 100644 --- a/VEX/priv/ir/iropt.c +++ b/VEX/priv/ir/iropt.c @@ -359,9 +359,6 @@ static void flatten_Stmt ( IRBB* bb, IRStmt* st ) IRExpr *e1, *e2; IRDirty *d, *d2; switch (st->tag) { - case Ist_IMark: - addStmtToIRBB(bb, st); - break; case Ist_Put: if (isIRAtom(st->Ist.Put.data)) { /* optimisation to reduce the amount of heap wasted @@ -412,7 +409,9 @@ static void flatten_Stmt ( IRBB* bb, IRStmt* st ) d2->args[i] = flatten_Expr(bb, d2->args[i]); addStmtToIRBB(bb, IRStmt_Dirty(d2)); break; + case Ist_NoOp: case Ist_MFence: + case Ist_IMark: addStmtToIRBB(bb, st); break; case Ist_Exit: @@ -695,6 +694,7 @@ static void handle_gets_Stmt ( vassert(isIRAtom(st->Ist.PutI.data)); break; + case Ist_NoOp: case Ist_IMark: break; @@ -804,7 +804,7 @@ static void redundant_put_removal_BB ( vex_printf("rPUT: "); ppIRStmt(st); vex_printf("\n"); } - bb->stmts[i] = NULL; + bb->stmts[i] = IRStmt_NoOp(); } else { /* We can't demonstrate that this Put is redundant, so add it to the running collection. */ @@ -1381,9 +1381,9 @@ 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. Returning - NULL means the statement has been turned into a no-op. */ - + 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 @@ -1449,6 +1449,9 @@ static IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st ) 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(); @@ -1464,7 +1467,7 @@ static IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st ) || 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 NULL; + return IRStmt_NoOp(); } else { vassert(fcond->Iex.Const.con->Ico.U1 == True); /* Hmmm. The exit has become unconditional. Leave it as @@ -1637,6 +1640,7 @@ static void addUses_Stmt ( Bool* set, IRStmt* st ) for (i = 0; d->args[i] != NULL; i++) addUses_Expr(set, d->args[i]); return; + case Ist_NoOp: case Ist_IMark: case Ist_MFence: return; @@ -1693,14 +1697,15 @@ static Bool isZeroU1 ( IRExpr* e ) ppIRStmt(st); vex_printf("\n"); } - bb->stmts[i] = NULL; + bb->stmts[i] = IRStmt_NoOp(); } else if (st->tag == Ist_Dirty && st->Ist.Dirty.details->guard && isZeroU1(st->Ist.Dirty.details->guard)) { - /* This is a dirty helper which will never get called. Delete it. */ - bb->stmts[i] = NULL; + /* This is a dirty helper which will never get called. + Delete it. */ + bb->stmts[i] = IRStmt_NoOp(); } else { /* Note any IRTemp uses made by the current statement. */ @@ -2449,6 +2454,7 @@ Bool guestAccessWhichMightOverlapPutI ( getArrayBounds(pi->Ist.PutI.descr, &minoffP, &maxoffP); switch (s2->tag) { + case Ist_NoOp: case Ist_IMark: return False; @@ -2621,7 +2627,7 @@ void do_redundant_PutI_elimination ( IRBB* bb ) ppIRStmt(st); vex_printf("\n"); } - bb->stmts[i] = NULL; + bb->stmts[i] = IRStmt_NoOp(); } } @@ -2681,6 +2687,7 @@ static void deltaIRStmt ( IRStmt* st, Int delta ) Int i; IRDirty* d; switch (st->tag) { + case Ist_NoOp: case Ist_IMark: break; case Ist_Put: @@ -3068,6 +3075,7 @@ static void occCount_Stmt ( TmpInfo** env, IRStmt* st ) for (i = 0; d->args[i]; i++) occCount_Expr(env, d->args[i]); return; + case Ist_NoOp: case Ist_IMark: case Ist_MFence: return; @@ -3203,6 +3211,8 @@ static IRStmt* tbSubst_Stmt ( TmpInfo** env, IRStmt* st ) ); 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_Dirty: @@ -3594,6 +3604,7 @@ static Bool hasGetIorPutI ( IRBB* bb ) if (d->mFx != Ifx_None) vassert(isIRAtom(d->mAddr)); break; + case Ist_NoOp: case Ist_IMark: case Ist_MFence: break; diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h index 06997c6827..d183f18691 100644 --- a/VEX/pub/libvex_ir.h +++ b/VEX/pub/libvex_ir.h @@ -865,7 +865,8 @@ IRDirty* unsafeIRDirty_1_N ( IRTemp dst, /* The possible kinds of statements are as follows: */ typedef - enum { + enum { + Ist_NoOp, /* no-op (usually resulting from IR optimisation) */ Ist_IMark, /* instruction mark: describe addr/len of guest insn whose IR follows */ Ist_Put, /* write guest state, fixed offset */ @@ -882,6 +883,8 @@ typedef struct _IRStmt { IRStmtTag tag; union { + struct { + } NoOp; struct { Addr64 addr; Int len; @@ -918,6 +921,7 @@ typedef } IRStmt; +extern IRStmt* IRStmt_NoOp ( void ); extern IRStmt* IRStmt_IMark ( Addr64 addr, Int len ); extern IRStmt* IRStmt_Put ( Int off, IRExpr* data ); extern IRStmt* IRStmt_PutI ( IRArray* descr, IRExpr* ix, Int bias,