]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add a new IR statement kind: IRStmt_NoOp, to denote a no-operation.
authorJulian Seward <jseward@acm.org>
Mon, 21 Mar 2005 00:15:53 +0000 (00:15 +0000)
committerJulian Seward <jseward@acm.org>
Mon, 21 Mar 2005 00:15:53 +0000 (00:15 +0000)
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

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

index 1ba1af1d231a75564ddf4d2d3f8975bfea47f4eb..247a3148f726333d03dd3e8c87367d81ac22284f 100644 (file)
@@ -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);
 
index 0a86dbbf72dcd0bf8a0c97bb2816e54a201295da..acb58ff91d08ee5f0d3232ec5f5297d893a25e33 100644 (file)
@@ -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) {
index 99c32741bd0e84e85b6a05095aca05ad69892888..0e65d542d88f000622116a382730c60eedbb6162 100644 (file)
@@ -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;
index 06997c6827acbdce5343b1e7d5c9641fd67bc13e..d183f1869122b61e69ba39f3c598404eea9a3ae6 100644 (file)
@@ -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,