]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add a few new primops which allow for more concise expression of
authorJulian Seward <jseward@acm.org>
Tue, 26 Apr 2005 23:34:34 +0000 (23:34 +0000)
committerJulian Seward <jseward@acm.org>
Tue, 26 Apr 2005 23:34:34 +0000 (23:34 +0000)
the instrumentation Memcheck generates:

* CmpNEZ{8,16,32,64}, which are equivalent to CmpNE<sz> with one
  argument zero

* Neg{8,16,32,64}, which is equivalent to Sub<sz> with the first
  argument zero

For 64-bit platforms, add these primops.  This gives a complete set of
primops for conversions between the integral types (I8, I16, I32,
I64), so that a widening/narrowing from any type to any other type can
be achieved in a single primop:

* Iop_8Uto64, Iop_8Sto64, Iop_16Uto64, Iop_16Sto64

* Iop_64to8, Iop_64to16

git-svn-id: svn://svn.valgrind.org/vex/trunk@1144

VEX/priv/ir/irdefs.c
VEX/priv/ir/iropt.c
VEX/pub/libvex_ir.h

index c50b0d1dd71f52736235016f9654d315c6c24dba..3dbe71b22547c5fbabf248927f686885e9935033 100644 (file)
@@ -176,6 +176,16 @@ void ppIROp ( IROp op )
       case Iop_CmpLT64U: vex_printf("CmpLT64U"); return;
       case Iop_CmpLE64U: vex_printf("CmpLE64U"); return;
 
+      case Iop_CmpNEZ8:  vex_printf("CmpNEZ8"); return;
+      case Iop_CmpNEZ16: vex_printf("CmpNEZ16"); return;
+      case Iop_CmpNEZ32: vex_printf("CmpNEZ32"); return;
+      case Iop_CmpNEZ64: vex_printf("CmpNEZ64"); return;
+
+      case Iop_Neg8:  vex_printf("Neg8"); return;
+      case Iop_Neg16: vex_printf("Neg16"); return;
+      case Iop_Neg32: vex_printf("Neg32"); return;
+      case Iop_Neg64: vex_printf("Neg64"); return;
+
       case Iop_DivU32: vex_printf("DivU32"); return;
       case Iop_DivS32: vex_printf("DivS32"); return;
 
@@ -1206,6 +1216,8 @@ void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 )
      *t_dst = (_td); *t_arg1 = (_ta1); *t_arg2 = (_ta2); break
 #  define COMPARISON(_ta)         \
      *t_dst = Ity_I1; *t_arg1 = *t_arg2 = (_ta); break;
+#  define UNARY_COMPARISON(_ta)         \
+     *t_dst = Ity_I1; *t_arg1 = (_ta); break;
 
    *t_dst  = Ity_INVALID;
    *t_arg1 = Ity_INVALID;
@@ -1259,11 +1271,15 @@ void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 )
       case Iop_Shl64: case Iop_Shr64: case Iop_Sar64:
          BINARY(Ity_I64, Ity_I64,Ity_I8);
 
-      case Iop_Not8:   UNARY(Ity_I8,Ity_I8);
-      case Iop_Not16:  UNARY(Ity_I16,Ity_I16);
-      case Iop_Not32:  UNARY(Ity_I32,Ity_I32);
+      case Iop_Not8: case Iop_Neg8:
+         UNARY(Ity_I8,Ity_I8);
+      case Iop_Not16: case Iop_Neg16:
+         UNARY(Ity_I16,Ity_I16);
+      case Iop_Not32: case Iop_Neg32:
+         UNARY(Ity_I32,Ity_I32);
 
-      case Iop_Not64:  
+      case Iop_Neg64:
+      case Iop_Not64:
       case Iop_CmpNEZ32x2: case Iop_CmpNEZ16x4: case Iop_CmpNEZ8x8:
          UNARY(Ity_I64,Ity_I64);
 
@@ -1280,6 +1296,11 @@ void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 )
       case Iop_CmpLT64U: case Iop_CmpLE64U:
          COMPARISON(Ity_I64);
 
+      case Iop_CmpNEZ8:  UNARY_COMPARISON(Ity_I8);
+      case Iop_CmpNEZ16: UNARY_COMPARISON(Ity_I16);
+      case Iop_CmpNEZ32: UNARY_COMPARISON(Ity_I32);
+      case Iop_CmpNEZ64: UNARY_COMPARISON(Ity_I64);
+
       case Iop_MullU8: case Iop_MullS8:
          BINARY(Ity_I16, Ity_I8,Ity_I8);
       case Iop_MullU16: case Iop_MullS16:
@@ -1456,6 +1477,7 @@ void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 )
 #  undef UNARY
 #  undef BINARY
 #  undef COMPARISON
+#  undef UNARY_COMPARISON
 }
 
 
index 2f5769de82794fca8f3b55b94cc39ec76680138f..a6e31cf65c9d6568bd4a924b10bd71228a03067b 100644 (file)
@@ -846,6 +846,20 @@ static Bool notBool ( Bool b )
    vpanic("notBool");
 }
 
+/* Make a zero which has the same type as the result of the given
+   primop. */
+static IRExpr* mkZeroForXor ( IROp op )
+{
+   switch (op) {
+      case Iop_Xor8:  return IRExpr_Const(IRConst_U8(0));
+      case Iop_Xor16: return IRExpr_Const(IRConst_U16(0));
+      case Iop_Xor32: return IRExpr_Const(IRConst_U32(0));
+      case Iop_Xor64: return IRExpr_Const(IRConst_U64(0));
+      default: vpanic("mkZeroForXor: bad primop");
+   }
+}
+
+
 static IRExpr* fold_Expr ( IRExpr* e )
 {
    Int     shift;
@@ -928,6 +942,15 @@ static IRExpr* fold_Expr ( IRExpr* e )
                     notBool(e->Iex.Unop.arg->Iex.Const.con->Ico.U1)));
             break;
 
+         case Iop_Neg32:
+            e2 = IRExpr_Const(IRConst_U32(
+                    - (e->Iex.Unop.arg->Iex.Const.con->Ico.U32)));
+            break;
+         case Iop_Neg8:
+            e2 = IRExpr_Const(IRConst_U8(
+                    - (e->Iex.Unop.arg->Iex.Const.con->Ico.U8)));
+            break;
+
          case Iop_64to32: {
             ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
             w64 &= 0x00000000FFFFFFFFULL;
@@ -946,6 +969,24 @@ static IRExpr* fold_Expr ( IRExpr* e )
                     & e->Iex.Unop.arg->Iex.Const.con->Ico.U32));
             break;
 
+         case Iop_CmpNEZ8:
+            e2 = IRExpr_Const(IRConst_U1(toBool(
+                    0 != 
+                    (0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U8)
+                 )));
+            break;
+         case Iop_CmpNEZ32:
+            e2 = IRExpr_Const(IRConst_U1(toBool(
+                    0 != 
+                    (0xFFFFFFFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)
+                 )));
+            break;
+         case Iop_CmpNEZ64:
+            e2 = IRExpr_Const(IRConst_U1(toBool(
+                    0ULL != e->Iex.Unop.arg->Iex.Const.con->Ico.U64
+                 )));
+            break;
+
          default: 
             goto unhandled;
       }
@@ -1235,6 +1276,13 @@ static IRExpr* fold_Expr ( IRExpr* e )
             e2 = e->Iex.Binop.arg1;
          } else
 
+         /* Or16(x,0) ==> x */
+         if ((e->Iex.Binop.op == Iop_Or16)
+             && e->Iex.Binop.arg2->tag == Iex_Const
+             && e->Iex.Binop.arg2->Iex.Const.con->Ico.U16 == 0) {
+            e2 = e->Iex.Binop.arg1;
+         } else
+
          /* Or32/Add32(x,0) ==> x */
          if ((e->Iex.Binop.op == Iop_Add32 || e->Iex.Binop.op == Iop_Or32)
              && e->Iex.Binop.arg2->tag == Iex_Const
@@ -1277,6 +1325,16 @@ static IRExpr* fold_Expr ( IRExpr* e )
             e2 = e->Iex.Binop.arg1;
          }
 
+         /* Xor8/16/32/64(t,t) ==> 0, for some IRTemp t */
+         if (   (e->Iex.Binop.op == Iop_Xor64
+              || e->Iex.Binop.op == Iop_Xor32
+              || e->Iex.Binop.op == Iop_Xor16
+              || e->Iex.Binop.op == Iop_Xor8)
+             && sameIRTemps(e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
+            vassert(0); /* awaiting test case */
+            e2 = mkZeroForXor(e->Iex.Binop.op);
+         }
+
       }
    }
 
index 8036c7e916cfa6e291d5731ac68685e1d1edb8c5..808c63c918a1af4bf18a2ca59ea1d473717e28d6 100644 (file)
@@ -235,6 +235,10 @@ typedef
       Iop_CmpLT32U, Iop_CmpLT64U,
       Iop_CmpLE32U, Iop_CmpLE64U,
 
+      /* As a sop to Valgrind-Memcheck, the following are useful. */
+      Iop_CmpNEZ8, Iop_CmpNEZ16,  Iop_CmpNEZ32,  Iop_CmpNEZ64,
+      Iop_Neg8, Iop_Neg16, Iop_Neg32, Iop_Neg64,
+
       /* Division */
       /* TODO: clarify semantics wrt rounding, negative values, whatever */
       Iop_DivU32,   // :: I32,I32 -> I32 (simple div, no mod)
@@ -248,11 +252,21 @@ typedef
                           // of which lo half is div and hi half is mod
       Iop_DivModS128to64, // ditto, signed
 
+      /* Integer conversions.  Some of these are redundant (eg
+         Iop_64to8 is the same as Iop_64to32 and then Iop_32to8), but
+         having a complete set reduces the typical dynamic size of IR
+         and makes the instruction selectors easier to write. */
+
       /* Widening conversions */
-      Iop_8Uto16, Iop_8Uto32, Iop_16Uto32, Iop_32Uto64,
-      Iop_8Sto16, Iop_8Sto32, Iop_16Sto32, Iop_32Sto64,
+      Iop_8Uto16, Iop_8Uto32,  Iop_8Uto64,
+                  Iop_16Uto32, Iop_16Uto64,
+                               Iop_32Uto64,
+      Iop_8Sto16, Iop_8Sto32,  Iop_8Sto64,
+                  Iop_16Sto32, Iop_16Sto64,
+                               Iop_32Sto64,
+
       /* Narrowing conversions */
-      Iop_32to8,
+      Iop_64to8, Iop_32to8, Iop_64to16,
       /* 8 <-> 16 bit conversions */
       Iop_16to8,      // :: I16 -> I8, low half
       Iop_16HIto8,    // :: I16 -> I8, high half