Reduce size of an IRStmt from 40 bytes to 32 bytes on LP64
by allocating the details of a PutI statement into a struct
of its own and link to that (as is being done for Dirty and CAS).

These are the VEX bits.


git-svn-id: svn://svn.valgrind.org/vex/trunk@2361 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/guest_amd64_toIR.c b/priv/guest_amd64_toIR.c
index d05ed73..1896b9c 100644
--- a/priv/guest_amd64_toIR.c
+++ b/priv/guest_amd64_toIR.c
@@ -4715,7 +4715,7 @@
    IRRegArray* descr;
    vassert(typeOfIRExpr(irsb->tyenv, value) == Ity_I8);
    descr = mkIRRegArray( OFFB_FPTAGS, Ity_I8, 8 );
-   stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
+   stmt( IRStmt_PutI( mkIRPutI(descr, get_ftop(), i, value) ) );
 }
 
 /* Given i, generate an expression yielding 'ST_TAG(i)'.  This will be
@@ -4739,7 +4739,7 @@
    IRRegArray* descr;
    vassert(typeOfIRExpr(irsb->tyenv, value) == Ity_F64);
    descr = mkIRRegArray( OFFB_FPREGS, Ity_F64, 8 );
-   stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
+   stmt( IRStmt_PutI( mkIRPutI(descr, get_ftop(), i, value) ) );
    /* Mark the register as in-use. */
    put_ST_TAG(i, mkU8(1));
 }
@@ -6605,7 +6605,7 @@
    IRExpr*     tag1  = mkU8(1);
    put_ftop(zero);
    for (i = 0; i < 8; i++)
-      stmt( IRStmt_PutI( descr, zero, i, tag1 ) );
+      stmt( IRStmt_PutI( mkIRPutI(descr, zero, i, tag1) ) );
 }
 
 static void do_EMMS_preamble ( void )
@@ -6616,7 +6616,7 @@
    IRExpr*     tag0  = mkU8(0);
    put_ftop(zero);
    for (i = 0; i < 8; i++)
-      stmt( IRStmt_PutI( descr, zero, i, tag0 ) );
+      stmt( IRStmt_PutI( mkIRPutI(descr, zero, i, tag0) ) );
 }
 
 
diff --git a/priv/guest_x86_toIR.c b/priv/guest_x86_toIR.c
index 8db5b54..5cbb244 100644
--- a/priv/guest_x86_toIR.c
+++ b/priv/guest_x86_toIR.c
@@ -3522,7 +3522,7 @@
    IRRegArray* descr;
    vassert(typeOfIRExpr(irsb->tyenv, value) == Ity_I8);
    descr = mkIRRegArray( OFFB_FPTAGS, Ity_I8, 8 );
-   stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
+   stmt( IRStmt_PutI( mkIRPutI(descr, get_ftop(), i, value) ) );
 }
 
 /* Given i, generate an expression yielding 'ST_TAG(i)'.  This will be
@@ -3546,7 +3546,7 @@
    IRRegArray* descr;
    vassert(typeOfIRExpr(irsb->tyenv, value) == Ity_F64);
    descr = mkIRRegArray( OFFB_FPREGS, Ity_F64, 8 );
-   stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
+   stmt( IRStmt_PutI( mkIRPutI(descr, get_ftop(), i, value) ) );
    /* Mark the register as in-use. */
    put_ST_TAG(i, mkU8(1));
 }
@@ -5406,7 +5406,7 @@
    IRExpr*     tag1  = mkU8(1);
    put_ftop(zero);
    for (i = 0; i < 8; i++)
-      stmt( IRStmt_PutI( descr, zero, i, tag1 ) );
+      stmt( IRStmt_PutI( mkIRPutI(descr, zero, i, tag1) ) );
 }
 
 static void do_EMMS_preamble ( void )
@@ -5417,7 +5417,7 @@
    IRExpr*     tag0  = mkU8(0);
    put_ftop(zero);
    for (i = 0; i < 8; i++)
-      stmt( IRStmt_PutI( descr, zero, i, tag0 ) );
+      stmt( IRStmt_PutI( mkIRPutI(descr, zero, i, tag0) ) );
 }
 
 
diff --git a/priv/host_amd64_isel.c b/priv/host_amd64_isel.c
index 4f1f5f3..99e2961 100644
--- a/priv/host_amd64_isel.c
+++ b/priv/host_amd64_isel.c
@@ -3581,24 +3581,26 @@
 
    /* --------- Indexed PUT --------- */
    case Ist_PutI: {
+      IRPutI *puti = stmt->Ist.PutI.details;
+
       AMD64AMode* am 
          = genGuestArrayOffset(
-              env, stmt->Ist.PutI.descr, 
-                   stmt->Ist.PutI.ix, stmt->Ist.PutI.bias );
+              env, puti->descr, 
+                   puti->ix, puti->bias );
 
-      IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.PutI.data);
+      IRType ty = typeOfIRExpr(env->type_env, puti->data);
       if (ty == Ity_F64) {
-         HReg val = iselDblExpr(env, stmt->Ist.PutI.data);
+         HReg val = iselDblExpr(env, puti->data);
          addInstr(env, AMD64Instr_SseLdSt( False/*store*/, 8, val, am ));
          return;
       }
       if (ty == Ity_I8) {
-         HReg r = iselIntExpr_R(env, stmt->Ist.PutI.data);
+         HReg r = iselIntExpr_R(env, puti->data);
          addInstr(env, AMD64Instr_Store( 1, r, am ));
          return;
       }
       if (ty == Ity_I64) {
-         AMD64RI* ri = iselIntExpr_RI(env, stmt->Ist.PutI.data);
+         AMD64RI* ri = iselIntExpr_RI(env, puti->data);
          addInstr(env, AMD64Instr_Alu64M( Aalu_MOV, ri, am ));
          return;
       }
diff --git a/priv/host_ppc_isel.c b/priv/host_ppc_isel.c
index c115bc1..298db5a 100644
--- a/priv/host_ppc_isel.c
+++ b/priv/host_ppc_isel.c
@@ -4666,19 +4666,21 @@
       
    /* --------- Indexed PUT --------- */
    case Ist_PutI: {
+      IRPutI *puti = stmt->Ist.PutI.details;
+
       PPCAMode* dst_am
          = genGuestArrayOffset(
-              env, stmt->Ist.PutI.descr, 
-                   stmt->Ist.PutI.ix, stmt->Ist.PutI.bias );
-      IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.PutI.data);
+              env, puti->descr, 
+                   puti->ix, puti->bias );
+      IRType ty = typeOfIRExpr(env->type_env, puti->data);
       if (mode64 && ty == Ity_I64) {
-         HReg r_src = iselWordExpr_R(env, stmt->Ist.PutI.data);
+         HReg r_src = iselWordExpr_R(env, puti->data);
          addInstr(env, PPCInstr_Store( toUChar(8),
                                        dst_am, r_src, mode64 ));
          return;
       }
       if ((!mode64) && ty == Ity_I32) {
-         HReg r_src = iselWordExpr_R(env, stmt->Ist.PutI.data);
+         HReg r_src = iselWordExpr_R(env, puti->data);
          addInstr(env, PPCInstr_Store( toUChar(4),
                                        dst_am, r_src, mode64 ));
          return;
diff --git a/priv/host_x86_isel.c b/priv/host_x86_isel.c
index 869d7cf..1b83b6f 100644
--- a/priv/host_x86_isel.c
+++ b/priv/host_x86_isel.c
@@ -3830,31 +3830,33 @@
 
    /* --------- Indexed PUT --------- */
    case Ist_PutI: {
+      IRPutI *puti = stmt->Ist.PutI.details;
+
       X86AMode* am 
          = genGuestArrayOffset(
-              env, stmt->Ist.PutI.descr, 
-                   stmt->Ist.PutI.ix, stmt->Ist.PutI.bias );
+              env, puti->descr, 
+                   puti->ix, puti->bias );
 
-      IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.PutI.data);
+      IRType ty = typeOfIRExpr(env->type_env, puti->data);
       if (ty == Ity_F64) {
-         HReg val = iselDblExpr(env, stmt->Ist.PutI.data);
+         HReg val = iselDblExpr(env, puti->data);
          addInstr(env, X86Instr_FpLdSt( False/*store*/, 8, val, am ));
          return;
       }
       if (ty == Ity_I8) {
-         HReg r = iselIntExpr_R(env, stmt->Ist.PutI.data);
+         HReg r = iselIntExpr_R(env, puti->data);
          addInstr(env, X86Instr_Store( 1, r, am ));
          return;
       }
       if (ty == Ity_I32) {
-         HReg r = iselIntExpr_R(env, stmt->Ist.PutI.data);
+         HReg r = iselIntExpr_R(env, puti->data);
          addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(r), am ));
          return;
       }
       if (ty == Ity_I64) {
          HReg rHi, rLo;
          X86AMode* am4 = advance4(am);
-         iselInt64Expr(&rHi, &rLo, env, stmt->Ist.PutI.data);
+         iselInt64Expr(&rHi, &rLo, env, puti->data);
          addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(rLo), am ));
          addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(rHi), am4 ));
          return;
diff --git a/priv/ir_defs.c b/priv/ir_defs.c
index 4d671f6..502fc20 100644
--- a/priv/ir_defs.c
+++ b/priv/ir_defs.c
@@ -1160,6 +1160,16 @@
    vex_printf(")");
 }
 
+void ppIRPutI ( IRPutI* puti )
+{
+   vex_printf( "PUTI" );
+   ppIRRegArray(puti->descr);
+   vex_printf("[");
+   ppIRExpr(puti->ix);
+   vex_printf(",%d] = ", puti->bias);
+   ppIRExpr(puti->data);
+}
+
 void ppIRJumpKind ( IRJumpKind kind )
 {
    switch (kind) {
@@ -1226,12 +1236,7 @@
          ppIRExpr(s->Ist.Put.data);
          break;
       case Ist_PutI:
-         vex_printf( "PUTI" );
-         ppIRRegArray(s->Ist.PutI.descr);
-         vex_printf("[");
-         ppIRExpr(s->Ist.PutI.ix);
-         vex_printf(",%d] = ", s->Ist.PutI.bias);
-         ppIRExpr(s->Ist.PutI.data);
+         ppIRPutI(s->Ist.PutI.details);
          break;
       case Ist_WrTmp:
          ppIRTemp(s->Ist.WrTmp.tmp);
@@ -1659,6 +1664,20 @@
 }
 
 
+/* Constructors -- IRPutI */
+
+IRPutI* mkIRPutI ( IRRegArray* descr, IRExpr* ix,
+                   Int bias, IRExpr* data )
+{
+   IRPutI* puti = LibVEX_Alloc(sizeof(IRPutI));
+   puti->descr  = descr;
+   puti->ix     = ix;
+   puti->bias   = bias;
+   puti->data   = data;
+   return puti;
+}
+
+
 /* Constructors -- IRStmt */
 
 IRStmt* IRStmt_NoOp ( void )
@@ -1691,14 +1710,10 @@
    s->Ist.Put.data   = data;
    return s;
 }
-IRStmt* IRStmt_PutI ( IRRegArray* descr, IRExpr* ix,
-                      Int bias, IRExpr* data ) {
-   IRStmt* s         = LibVEX_Alloc(sizeof(IRStmt));
-   s->tag            = Ist_PutI;
-   s->Ist.PutI.descr = descr;
-   s->Ist.PutI.ix    = ix;
-   s->Ist.PutI.bias  = bias;
-   s->Ist.PutI.data  = data;
+IRStmt* IRStmt_PutI ( IRPutI* details ) {
+   IRStmt* s          = LibVEX_Alloc(sizeof(IRStmt));
+   s->tag             = Ist_PutI;
+   s->Ist.PutI.details = details;
    return s;
 }
 IRStmt* IRStmt_WrTmp ( IRTemp tmp, IRExpr* data ) {
@@ -1929,6 +1944,14 @@
                    deepCopyIRExpr(cas->dataLo) );
 }
 
+IRPutI* deepCopyIRPutI ( IRPutI * puti )
+{
+  return mkIRPutI( deepCopyIRRegArray(puti->descr),
+                   deepCopyIRExpr(puti->ix),
+                   puti->bias, 
+                   deepCopyIRExpr(puti->data));
+}
+
 IRStmt* deepCopyIRStmt ( IRStmt* s )
 {
    switch (s->tag) {
@@ -1946,10 +1969,7 @@
          return IRStmt_Put(s->Ist.Put.offset, 
                            deepCopyIRExpr(s->Ist.Put.data));
       case Ist_PutI: 
-         return IRStmt_PutI(deepCopyIRRegArray(s->Ist.PutI.descr),
-                            deepCopyIRExpr(s->Ist.PutI.ix),
-                            s->Ist.PutI.bias, 
-                            deepCopyIRExpr(s->Ist.PutI.data));
+         return IRStmt_PutI(deepCopyIRPutI(s->Ist.PutI.details));
       case Ist_WrTmp:
          return IRStmt_WrTmp(s->Ist.WrTmp.tmp,
                              deepCopyIRExpr(s->Ist.WrTmp.data));
@@ -2910,6 +2930,7 @@
    IRExpr*  e;
    IRDirty* di;
    IRCAS*   cas;
+   IRPutI*  puti;
 
    switch (st->tag) {
       case Ist_AbiHint:
@@ -2918,8 +2939,9 @@
       case Ist_Put:
          return isIRAtom(st->Ist.Put.data);
       case Ist_PutI:
-         return toBool( isIRAtom(st->Ist.PutI.ix) 
-                        && isIRAtom(st->Ist.PutI.data) );
+         puti = st->Ist.PutI.details;
+         return toBool( isIRAtom(puti->ix) 
+                        && isIRAtom(puti->data) );
       case Ist_WrTmp:
          /* This is the only interesting case.  The RHS can be any
             expression, *but* all its subexpressions *must* be
@@ -3131,6 +3153,7 @@
    Int      i;
    IRDirty* d;
    IRCAS*   cas;
+   IRPutI*  puti;
    switch (stmt->tag) {
       case Ist_IMark:
          break;
@@ -3142,8 +3165,9 @@
          useBeforeDef_Expr(bb,stmt,stmt->Ist.Put.data,def_counts);
          break;
       case Ist_PutI:
-         useBeforeDef_Expr(bb,stmt,stmt->Ist.PutI.ix,def_counts);
-         useBeforeDef_Expr(bb,stmt,stmt->Ist.PutI.data,def_counts);
+         puti = stmt->Ist.PutI.details;
+         useBeforeDef_Expr(bb,stmt,puti->ix,def_counts);
+         useBeforeDef_Expr(bb,stmt,puti->data,def_counts);
          break;
       case Ist_WrTmp:
          useBeforeDef_Expr(bb,stmt,stmt->Ist.WrTmp.data,def_counts);
@@ -3394,6 +3418,7 @@
    Int        i;
    IRDirty*   d;
    IRCAS*     cas;
+   IRPutI*    puti;
    IRType     tyExpd, tyData;
    IRTypeEnv* tyenv = bb->tyenv;
    switch (stmt->tag) {
@@ -3419,16 +3444,17 @@
             sanityCheckFail(bb,stmt,"IRStmt.Put.data: cannot Put :: Ity_I1");
          break;
       case Ist_PutI:
-         tcExpr( bb, stmt, stmt->Ist.PutI.data, gWordTy );
-         tcExpr( bb, stmt, stmt->Ist.PutI.ix, gWordTy );
-         if (typeOfIRExpr(tyenv,stmt->Ist.PutI.data) == Ity_I1)
+         puti = stmt->Ist.PutI.details;
+         tcExpr( bb, stmt, puti->data, gWordTy );
+         tcExpr( bb, stmt, puti->ix, gWordTy );
+         if (typeOfIRExpr(tyenv,puti->data) == Ity_I1)
             sanityCheckFail(bb,stmt,"IRStmt.PutI.data: cannot PutI :: Ity_I1");
-         if (typeOfIRExpr(tyenv,stmt->Ist.PutI.data) 
-             != stmt->Ist.PutI.descr->elemTy)
+         if (typeOfIRExpr(tyenv,puti->data) 
+             != puti->descr->elemTy)
             sanityCheckFail(bb,stmt,"IRStmt.PutI.data: data ty != elem ty");
-         if (typeOfIRExpr(tyenv,stmt->Ist.PutI.ix) != Ity_I32)
+         if (typeOfIRExpr(tyenv,puti->ix) != Ity_I32)
             sanityCheckFail(bb,stmt,"IRStmt.PutI.ix: not :: Ity_I32");
-         if (!saneIRRegArray(stmt->Ist.PutI.descr))
+         if (!saneIRRegArray(puti->descr))
             sanityCheckFail(bb,stmt,"IRStmt.PutI.descr: invalid descr");
          break;
       case Ist_WrTmp:
diff --git a/priv/ir_opt.c b/priv/ir_opt.c
index bec7e06..397f579 100644
--- a/priv/ir_opt.c
+++ b/priv/ir_opt.c
@@ -384,6 +384,7 @@
    IRExpr  *e1, *e2, *e3, *e4, *e5;
    IRDirty *d,  *d2;
    IRCAS   *cas, *cas2;
+   IRPutI  *puti, *puti2;
    switch (st->tag) {
       case Ist_Put:
          if (isIRAtom(st->Ist.Put.data)) {
@@ -397,12 +398,11 @@
          }
          break;
       case Ist_PutI:
-         e1 = flatten_Expr(bb, st->Ist.PutI.ix);
-         e2 = flatten_Expr(bb, st->Ist.PutI.data);
-         addStmtToIRSB(bb, IRStmt_PutI(st->Ist.PutI.descr,
-                                       e1,
-                                       st->Ist.PutI.bias,
-                                       e2));
+         puti = st->Ist.PutI.details;
+         e1 = flatten_Expr(bb, puti->ix);
+         e2 = flatten_Expr(bb, puti->data);
+         puti2 = mkIRPutI(puti->descr, e1, puti->bias, e2);
+         addStmtToIRSB(bb, IRStmt_PutI(puti2));
          break;
       case Ist_WrTmp:
          if (isFlat(st->Ist.WrTmp.data)) {
@@ -628,7 +628,7 @@
                                  typeOfIRExpr(bb->tyenv,st->Ist.Put.data) );
          } else {
             vassert(st->tag == Ist_PutI);
-            key = mk_key_GetIPutI( st->Ist.PutI.descr );
+            key = mk_key_GetIPutI( st->Ist.PutI.details->descr );
          }
 
          k_lo = (key >> 16) & 0xFFFF;
@@ -750,8 +750,8 @@
          break;
 
       case Ist_PutI:
-         vassert(isIRAtom(st->Ist.PutI.ix));
-         vassert(isIRAtom(st->Ist.PutI.data));
+         vassert(isIRAtom(st->Ist.PutI.details->ix));
+         vassert(isIRAtom(st->Ist.PutI.details->data));
          break;
 
       case Ist_NoOp:
@@ -872,9 +872,9 @@
             break;
          case Ist_PutI:
             isPut = True;
-            key = mk_key_GetIPutI( st->Ist.PutI.descr );
-            vassert(isIRAtom(st->Ist.PutI.ix));
-            vassert(isIRAtom(st->Ist.PutI.data));
+            key = mk_key_GetIPutI( st->Ist.PutI.details->descr );
+            vassert(isIRAtom(st->Ist.PutI.details->ix));
+            vassert(isIRAtom(st->Ist.PutI.details->data));
             break;
          default: 
             isPut = False;
@@ -2146,15 +2146,17 @@
                    fold_Expr(env, subst_Expr(env, st->Ist.Put.data)) 
                 );
 
-      case Ist_PutI:
-         vassert(isIRAtom(st->Ist.PutI.ix));
-         vassert(isIRAtom(st->Ist.PutI.data));
-         return IRStmt_PutI(
-                   st->Ist.PutI.descr,
-                   fold_Expr(env, subst_Expr(env, st->Ist.PutI.ix)),
-                   st->Ist.PutI.bias,
-                   fold_Expr(env, subst_Expr(env, st->Ist.PutI.data))
-                );
+      case Ist_PutI: {
+         IRPutI *puti, *puti2;
+         puti = st->Ist.PutI.details;
+         vassert(isIRAtom(puti->ix));
+         vassert(isIRAtom(puti->data));
+         puti2 = mkIRPutI(puti->descr,
+                          fold_Expr(env, subst_Expr(env, puti->ix)),
+                          puti->bias,
+                          fold_Expr(env, subst_Expr(env, puti->data)));
+         return IRStmt_PutI(puti2);
+      }
 
       case Ist_WrTmp:
          /* This is the one place where an expr (st->Ist.WrTmp.data) is
@@ -2422,8 +2424,8 @@
          addUses_Expr(set, st->Ist.AbiHint.nia);
          return;
       case Ist_PutI:
-         addUses_Expr(set, st->Ist.PutI.ix);
-         addUses_Expr(set, st->Ist.PutI.data);
+         addUses_Expr(set, st->Ist.PutI.details->ix);
+         addUses_Expr(set, st->Ist.PutI.details->data);
          return;
       case Ist_WrTmp:
          addUses_Expr(set, st->Ist.WrTmp.data);
@@ -3210,13 +3212,14 @@
                }
                else 
                if (st->tag == Ist_PutI) {
+                  IRPutI *puti = st->Ist.PutI.details;
                   if (getAliasingRelation_II(
                          ae->u.GetIt.descr, 
                          IRExpr_RdTmp(ae->u.GetIt.ix), 
                          ae->u.GetIt.bias,
-                         st->Ist.PutI.descr,
-                         st->Ist.PutI.ix,
-                         st->Ist.PutI.bias
+                         puti->descr,
+                         puti->ix,
+                         puti->bias
                       ) != NoAlias)
                      invalidate = True;
                }
@@ -3427,22 +3430,22 @@
       }
 
       /* Perhaps st is PutI[t, con] ? */
-
+      IRPutI *puti = st->Ist.PutI.details;
       if (st->tag == Ist_PutI
-          && st->Ist.PutI.ix->tag == Iex_RdTmp
-          && collapseChain(bb, i-1, st->Ist.PutI.ix->Iex.RdTmp.tmp, 
+          && puti->ix->tag == Iex_RdTmp
+          && collapseChain(bb, i-1, puti->ix->Iex.RdTmp.tmp, 
                                &var2, &con2)) {
          if (DEBUG_IROPT) {
             vex_printf("replacing2 ");
             ppIRStmt(st);
             vex_printf(" with ");
          }
-         con2 += st->Ist.PutI.bias;
+         con2 += puti->bias;
          bb->stmts[i]
-           = IRStmt_PutI(st->Ist.PutI.descr,
-                         IRExpr_RdTmp(var2),
-                         con2,
-                         st->Ist.PutI.data);
+            = IRStmt_PutI(mkIRPutI(puti->descr,
+                                   IRExpr_RdTmp(var2),
+                                   con2,
+                                   puti->data));
          if (DEBUG_IROPT) {
             ppIRStmt(bb->stmts[i]);
             vex_printf("\n");
@@ -3514,12 +3517,13 @@
       }
 
       if (st->tag == Ist_PutI) {
+         IRPutI *puti = st->Ist.PutI.details;
 
          relation = getAliasingRelation_II(
                        descrG, ixG, biasG,
-                       st->Ist.PutI.descr,
-                       st->Ist.PutI.ix,
-                       st->Ist.PutI.bias
+                       puti->descr,
+                       puti->ix,
+                       puti->bias
                     );
 
          if (relation == NoAlias) {
@@ -3536,7 +3540,7 @@
 
          /* Otherwise, we've found what we're looking for.  */
          vassert(relation == ExactAlias);
-         return st->Ist.PutI.data;
+         return puti->data;
 
       } /* if (st->tag == Ist_PutI) */
 
@@ -3566,10 +3570,13 @@
    if (s2->tag != Ist_PutI)
       return False;
 
+   IRPutI *p1 = pi->Ist.PutI.details;
+   IRPutI *p2 = s2->Ist.PutI.details;
+
    return toBool(
           getAliasingRelation_II( 
-             pi->Ist.PutI.descr, pi->Ist.PutI.ix, pi->Ist.PutI.bias, 
-             s2->Ist.PutI.descr, s2->Ist.PutI.ix, s2->Ist.PutI.bias
+             p1->descr, p1->ix, p1->bias, 
+             p2->descr, p2->ix, p2->bias
           )
           == ExactAlias
           );
@@ -3589,7 +3596,10 @@
    UInt       minoffP, maxoffP;
 
    vassert(pi->tag == Ist_PutI);
-   getArrayBounds(pi->Ist.PutI.descr, &minoffP, &maxoffP);
+
+   IRPutI *p1 = pi->Ist.PutI.details;
+
+   getArrayBounds(p1->descr, &minoffP, &maxoffP);
    switch (s2->tag) {
 
       case Ist_NoOp:
@@ -3619,28 +3629,30 @@
          vassert(isIRAtom(s2->Ist.Put.data));
          relation 
             = getAliasingRelation_IC(
-                 pi->Ist.PutI.descr, pi->Ist.PutI.ix,
+                 p1->descr, p1->ix,
                  s2->Ist.Put.offset, 
                  typeOfIRExpr(tyenv,s2->Ist.Put.data)
               );
          goto have_relation;
 
-      case Ist_PutI:
-         vassert(isIRAtom(s2->Ist.PutI.ix));
-         vassert(isIRAtom(s2->Ist.PutI.data));
+      case Ist_PutI: {
+         IRPutI *p2 = s2->Ist.PutI.details;
+
+         vassert(isIRAtom(p2->ix));
+         vassert(isIRAtom(p2->data));
          relation
             = getAliasingRelation_II(
-                 pi->Ist.PutI.descr, pi->Ist.PutI.ix, pi->Ist.PutI.bias, 
-                 s2->Ist.PutI.descr, s2->Ist.PutI.ix, s2->Ist.PutI.bias
+                 p1->descr, p1->ix, p1->bias, 
+                 p2->descr, p2->ix, p2->bias
               );
          goto have_relation;
+      }
 
       case Ist_WrTmp:
          if (s2->Ist.WrTmp.data->tag == Iex_GetI) {
             relation
                = getAliasingRelation_II(
-                    pi->Ist.PutI.descr, pi->Ist.PutI.ix, 
-                                        pi->Ist.PutI.bias, 
+                    p1->descr, p1->ix, p1->bias, 
                     s2->Ist.WrTmp.data->Iex.GetI.descr,
                     s2->Ist.WrTmp.data->Iex.GetI.ix,
                     s2->Ist.WrTmp.data->Iex.GetI.bias
@@ -3650,7 +3662,7 @@
          if (s2->Ist.WrTmp.data->tag == Iex_Get) {
             relation
                = getAliasingRelation_IC(
-                    pi->Ist.PutI.descr, pi->Ist.PutI.ix,
+                    p1->descr, p1->ix,
                     s2->Ist.WrTmp.data->Iex.Get.offset,
                     s2->Ist.WrTmp.data->Iex.Get.ty
                  );
@@ -3856,8 +3868,8 @@
          deltaIRExpr(st->Ist.Put.data, delta);
          break;
       case Ist_PutI:
-         deltaIRExpr(st->Ist.PutI.ix, delta);
-         deltaIRExpr(st->Ist.PutI.data, delta);
+         deltaIRExpr(st->Ist.PutI.details->ix, delta);
+         deltaIRExpr(st->Ist.PutI.details->data, delta);
          break;
       case Ist_WrTmp: 
          st->Ist.WrTmp.tmp += delta;
@@ -4335,8 +4347,8 @@
          aoccCount_Expr(uses, st->Ist.Put.data);
          return;
       case Ist_PutI:
-         aoccCount_Expr(uses, st->Ist.PutI.ix);
-         aoccCount_Expr(uses, st->Ist.PutI.data);
+         aoccCount_Expr(uses, st->Ist.PutI.details->ix);
+         aoccCount_Expr(uses, st->Ist.PutI.details->data);
          return;
       case Ist_Store:
          aoccCount_Expr(uses, st->Ist.Store.addr);
@@ -4643,6 +4655,8 @@
    Int     i;
    IRDirty *d, *d2;
    IRCAS   *cas, *cas2;
+   IRPutI  *puti, *puti2;
+
    switch (st->tag) {
       case Ist_AbiHint:
          return IRStmt_AbiHint(
@@ -4667,12 +4681,12 @@
                    atbSubst_Expr(env, st->Ist.Put.data)
                 );
       case Ist_PutI:
-         return IRStmt_PutI(
-                   st->Ist.PutI.descr,
-                   atbSubst_Expr(env, st->Ist.PutI.ix),
-                   st->Ist.PutI.bias,
-                   atbSubst_Expr(env, st->Ist.PutI.data)
-                );
+         puti  = st->Ist.PutI.details;
+         puti2 = mkIRPutI(puti->descr, 
+                          atbSubst_Expr(env, puti->ix),
+                          puti->bias,
+                          atbSubst_Expr(env, puti->data));
+         return IRStmt_PutI(puti2);
 
       case Ist_Exit:
          return IRStmt_Exit(
diff --git a/priv/main_main.c b/priv/main_main.c
index a627d67..a65867d 100644
--- a/priv/main_main.c
+++ b/priv/main_main.c
@@ -163,7 +163,7 @@
               || sizeof(IRStmt) == 24 /* arm */);
    } else {
       vassert(sizeof(IRExpr) == 48);
-      vassert(sizeof(IRStmt) == 40);
+      vassert(sizeof(IRStmt) == 32);
    }
 
    /* Really start up .. */
diff --git a/pub/libvex_ir.h b/pub/libvex_ir.h
index 502dcf6..ed59617 100644
--- a/pub/libvex_ir.h
+++ b/pub/libvex_ir.h
@@ -2034,6 +2034,23 @@
 
 extern IRCAS* deepCopyIRCAS ( IRCAS* );
 
+
+/* ------------------ Circular Array Put ------------------ */
+typedef
+   struct {
+      IRRegArray* descr; /* Part of guest state treated as circular */
+      IRExpr*     ix;    /* Variable part of index into array */
+      Int         bias;  /* Constant offset part of index into array */
+      IRExpr*     data;  /* The value to write */
+   } IRPutI;
+
+extern void ppIRPutI ( IRPutI* puti );
+
+extern IRPutI* mkIRPutI ( IRRegArray* descr, IRExpr* ix,
+                          Int bias, IRExpr* data );
+
+extern IRPutI* deepCopyIRPutI ( IRPutI* );
+
 /* ------------------ Statements ------------------ */
 
 /* The different kinds of statements.  Their meaning is explained
@@ -2149,10 +2166,7 @@
                          eg. PUTI(64:8xF64)[t5,0] = t1
          */
          struct {
-            IRRegArray* descr; /* Part of guest state treated as circular */
-            IRExpr*     ix;    /* Variable part of index into array */
-            Int         bias;  /* Constant offset part of index into array */
-            IRExpr*     data;  /* The value to write */
+            IRPutI* details;
          } PutI;
 
          /* Assign a value to a temporary.  Note that SSA rules require
@@ -2281,8 +2295,8 @@
          */
          struct {
             IRExpr*    guard;    /* Conditional expression */
-            IRJumpKind jk;       /* Jump kind */
             IRConst*   dst;      /* Jump target (constant only) */
+            IRJumpKind jk;       /* Jump kind */
             Int        offsIP;   /* Guest state offset for IP */
          } Exit;
       } Ist;
@@ -2294,8 +2308,7 @@
 extern IRStmt* IRStmt_IMark   ( Addr64 addr, Int len, UChar delta );
 extern IRStmt* IRStmt_AbiHint ( IRExpr* base, Int len, IRExpr* nia );
 extern IRStmt* IRStmt_Put     ( Int off, IRExpr* data );
-extern IRStmt* IRStmt_PutI    ( IRRegArray* descr, IRExpr* ix, Int bias, 
-                                IRExpr* data );
+extern IRStmt* IRStmt_PutI    ( IRPutI* details );
 extern IRStmt* IRStmt_WrTmp   ( IRTemp tmp, IRExpr* data );
 extern IRStmt* IRStmt_Store   ( IREndness end, IRExpr* addr, IRExpr* data );
 extern IRStmt* IRStmt_CAS     ( IRCAS* details );