iropt: implement flattening (into SSA form).  This caused various
primops to become exposed when previously they were treated as part
of a pattern, hence the changes to host-x86/*.c to handle them.



git-svn-id: svn://svn.valgrind.org/vex/trunk@173 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/host-x86/hdefs.c b/priv/host-x86/hdefs.c
index 451bf9b..ccc6b5f 100644
--- a/priv/host-x86/hdefs.c
+++ b/priv/host-x86/hdefs.c
@@ -537,6 +537,13 @@
    vassert(sz == 1 || sz == 2);
    return i;
 }
+X86Instr* X86Instr_Set32 ( X86CondCode cond, HReg dst ) {
+   X86Instr* i       = LibVEX_Alloc(sizeof(X86Instr));
+   i->tag            = Xin_Set32;
+   i->Xin.Set32.cond = cond;
+   i->Xin.Set32.dst  = dst;
+   return i;
+}
 X86Instr* X86Instr_FpUnary ( X86FpOp op, HReg src, HReg dst ) {
    X86Instr* i        = LibVEX_Alloc(sizeof(X86Instr));
    i->tag             = Xin_FpUnary;
@@ -675,6 +682,10 @@
          vex_printf(",");
          ppX86AMode(i->Xin.Store.dst);
          return;
+      case Xin_Set32:
+         vex_printf("setl%s ", showX86CondCode(i->Xin.Set32.cond));
+         ppHRegX86(i->Xin.Set32.dst);
+         return;
       case Xin_FpUnary:
          vex_printf("g%sD ", showX86FpOp(i->Xin.FpUnary.op));
          ppHRegX86(i->Xin.FpUnary.src);
@@ -800,6 +811,9 @@
          addHRegUse(u, HRmRead, i->Xin.Store.src);
          addRegUsage_X86AMode(u, i->Xin.Store.dst);
          return;
+      case Xin_Set32:
+         addHRegUse(u, HRmWrite, i->Xin.Set32.dst);
+         return;
       case Xin_FpUnary:
          addHRegUse(u, HRmRead, i->Xin.FpUnary.src);
          addHRegUse(u, HRmWrite, i->Xin.FpUnary.dst);
@@ -887,6 +901,9 @@
          mapReg(m, &i->Xin.Store.src);
          mapRegs_X86AMode(m, i->Xin.Store.dst);
          return;
+      case Xin_Set32:
+         mapReg(m, &i->Xin.Set32.dst);
+         return;
       case Xin_FpBinary:
          mapReg(m, &i->Xin.FpBinary.srcL);
          mapReg(m, &i->Xin.FpBinary.srcR);
@@ -1425,6 +1442,9 @@
             *p++ = 0x68;
             p = emit32(p, i->Xin.Push.src->Xrmi.Imm.imm32);
             goto done;
+         case Xrmi_Reg:
+            *p++ = 0x50 + iregNo(i->Xin.Push.src->Xrmi.Reg.reg);
+            goto done;
         default: 
             goto bad;
       }
@@ -1550,6 +1570,36 @@
       }
       break;
 
+   case Xin_Set32:
+      /* Make the destination register be 1 or 0, depending on whether
+         the relevant condition holds.  We have to dodge and weave
+         when the destination is %esi or %edi as we cannot directly
+         emit the native 'setb %reg' for those.  Further complication:
+         the top 24 bits of the destination should be forced to zero,
+         but doing 'xor %r,%r' kills the flag(s) we are about to read.
+         Sigh. */
+      /* First: movl $0, %dst */
+      *p++ = 0xB8 + iregNo(i->Xin.Set32.dst);
+      p = emit32(p, 0);
+      /* Do we need to swap in %eax? */
+
+      if (iregNo(i->Xin.Set32.dst) >= 4) {
+         /* xchg %eax, %dst */
+         *p++ = 0x90 + iregNo(i->Xin.Set32.dst);
+         /* setb lo8(%reg) */
+         *p++ = 0x0F; 
+         *p++ = 0x90 + (UChar)(i->Xin.Set32.cond);
+         p = doAMode_R(p, fake(0), hregX86_EAX());
+         /* xchg %eax, %dst */
+         *p++ = 0x90 + iregNo(i->Xin.Set32.dst);
+      } else {
+         /* setb lo8(%reg) */
+         *p++ = 0x0F; 
+         *p++ = 0x90 + (UChar)(i->Xin.Set32.cond);
+         p = doAMode_R(p, fake(0), i->Xin.Set32.dst);
+      }
+      goto done;
+
    case Xin_Store:
       if (i->Xin.Store.sz == 2) {
          /* This case, at least, is simple, given that we can
@@ -1652,13 +1702,13 @@
         /* ffree %st(7) */
         p = do_ffree_st7(p);
         /* pushl %hi ; pushl %lo */
-        *p++ = 0x50 + hregNumber(i->Xin.FpI64.iregHi);
-        *p++ = 0x50 + hregNumber(i->Xin.FpI64.iregLo);
+        *p++ = 0x50 + iregNo(i->Xin.FpI64.iregHi);
+        *p++ = 0x50 + iregNo(i->Xin.FpI64.iregLo);
         /* fildll 0(%esp) */
         *p++ = 0xDF; *p++ = 0x6C; *p++ = 0x24; *p++ = 0x00; 
         /* addl $8, %esp */
         *p++ = 0x83; *p++ = 0xC4; *p++ = 0x08; 
-        p = do_fstp_st(p, 1+hregNumber(i->Xin.FpI64.freg));
+        p = do_fstp_st(p, 1+iregNo(i->Xin.FpI64.freg));
         goto done;
      }
 
diff --git a/priv/host-x86/hdefs.h b/priv/host-x86/hdefs.h
index 5e698f7..b77e30d 100644
--- a/priv/host-x86/hdefs.h
+++ b/priv/host-x86/hdefs.h
@@ -273,6 +273,7 @@
       Xin_CMov32,    /* conditional move */
       Xin_LoadEX,    /* mov{s,z}{b,w}l from mem to reg */
       Xin_Store,     /* store 16/8 bit value in memory */
+      Xin_Set32,     /* convert condition code to 32-bit value */
       Xin_FpUnary,   /* FP fake unary op */
       Xin_FpBinary,  /* FP fake binary op */
       Xin_FpLdSt,    /* FP fake load/store */
@@ -366,6 +367,11 @@
             HReg      src;
             X86AMode* dst;
          } Store;
+         /* Convert a x86 condition code to a 32-bit value (0 or 1). */
+         struct {
+            X86CondCode cond;
+            HReg        dst;
+         } Set32;
          /* X86 Floating point (fake 3-operand, "flat reg file" insns) */
          struct {
             X86FpOp op;
@@ -409,6 +415,7 @@
 extern X86Instr* X86Instr_LoadEX   ( UChar szSmall, Bool syned,
                                      X86AMode* src, HReg dst );
 extern X86Instr* X86Instr_Store    ( UChar sz, HReg src, X86AMode* dst );
+extern X86Instr* X86Instr_Set32    ( X86CondCode cond, HReg dst );
 extern X86Instr* X86Instr_FpUnary  ( X86FpOp op, HReg src, HReg dst );
 extern X86Instr* X86Instr_FpBinary ( X86FpOp op, HReg srcL, HReg srcR, HReg dst );
 extern X86Instr* X86Instr_FpLdSt   ( Bool isLoad, UChar sz, HReg reg, X86AMode* );
diff --git a/priv/host-x86/isel.c b/priv/host-x86/isel.c
index a653da2..1dca90d 100644
--- a/priv/host-x86/isel.c
+++ b/priv/host-x86/isel.c
@@ -230,6 +230,7 @@
 static X86AMode* iselIntExpr_AMode ( ISelEnv* env, IRExpr* e );
 static void      iselIntExpr64     ( HReg* rHi, HReg* rLo, 
                                      ISelEnv* env, IRExpr* e );
+static X86CondCode iselCondCode ( ISelEnv* env, IRExpr* e );
 
 
 static X86Instr* mk_MOVsd_RR ( HReg src, HReg dst )
@@ -487,6 +488,12 @@
             addInstr(env, X86Instr_Sh32(Xsh_SHR, shift, X86RM_Reg(dst)));
             return dst;
          }
+         case Iop_1Uto8: {
+            HReg dst         = newVRegI(env);
+            X86CondCode cond = iselCondCode(env, e->Iex.Unop.arg);
+            addInstr(env, X86Instr_Set32(cond,dst));
+            return dst;
+         }
          case Iop_16to8:
          case Iop_32to8:
          case Iop_32to16:
@@ -776,6 +783,15 @@
       return Xcc_Z;
    }
 
+   /* var */
+   if (e->tag == Iex_Tmp) {
+      HReg r32 = lookupIRTemp(env, e->Iex.Tmp.tmp);
+      HReg dst = newVRegI(env);
+      addInstr(env, mk_MOVsd_RR(r32,dst));
+      addInstr(env, X86Instr_Alu32R(Xalu_AND,X86RMI_Imm(1),dst));
+      return Xcc_NZ;
+   }
+
    ppIRExpr(e);
    vpanic("iselCondCode");
 }
@@ -1145,6 +1161,12 @@
          addInstr(env, mk_MOVsd_RR(rLo,dstLo) );
          return;
       }
+      if (ty == Ity_Bit) {
+         X86CondCode cond = iselCondCode(env, stmt->Ist.Tmp.expr);
+         HReg dst = lookupIRTemp(env, tmp);
+         addInstr(env, X86Instr_Set32(cond, dst));
+         return;
+      }
       if (ty == Ity_F64) {
          HReg dst = lookupIRTemp(env, tmp);
          HReg src = iselDblExpr(env, stmt->Ist.Tmp.expr);
@@ -1202,7 +1224,6 @@
 {
    Int     i, j;
    HReg    hreg, hregHI;
-   IRStmt* stmt;
 
    /* Make up an initial environment to use. */
    ISelEnv* env = LibVEX_Alloc(sizeof(ISelEnv));
@@ -1245,8 +1266,8 @@
    env->vreg_ctr = j;
 
    /* Ok, finally we can iterate over the statements. */
-   for (stmt = bb->stmts; stmt; stmt=stmt->link)
-      iselStmt(env,stmt);
+   for (i = 0; i < bb->stmts_used; i++)
+      iselStmt(env,bb->stmts[i]);
 
    iselNext(env,bb->next,bb->jumpkind);