|
From: <sv...@va...> - 2012-11-08 10:58:27
|
sewardj 2012-11-08 10:58:16 +0000 (Thu, 08 Nov 2012)
New Revision: 13108
Log:
Improve accuracy of definedness tracking through the x86 PMOVMSKB and
BSF instructions, as the lack of it causes false positives (Valgrind
side). Fixes #308627. (Patrick J. LoPresti <lop...@gm...>)
Modified files:
trunk/memcheck/mc_translate.c
trunk/memcheck/tests/vbit-test/irops.c
Modified: trunk/memcheck/mc_translate.c (+83 -4)
===================================================================
--- trunk/memcheck/mc_translate.c 2012-11-07 13:42:36 +00:00 (rev 13107)
+++ trunk/memcheck/mc_translate.c 2012-11-08 10:58:16 +00:00 (rev 13108)
@@ -887,6 +887,15 @@
tl_assert(sameKindedAtoms(vyy,yy));
switch (ty) {
+ case Ity_I16:
+ opOR = Iop_Or16;
+ opDIFD = Iop_And16;
+ opUIFU = Iop_Or16;
+ opNOT = Iop_Not16;
+ opXOR = Iop_Xor16;
+ opCMP = Iop_CmpEQ16;
+ top = mkU16(0xFFFF);
+ break;
case Ity_I32:
opOR = Iop_Or32;
opDIFD = Iop_And32;
@@ -1793,6 +1802,60 @@
}
+static
+IRAtom* expensiveCountTrailingZeroes ( MCEnv* mce, IROp czop,
+ IRAtom* atom, IRAtom* vatom )
+{
+ IRType ty;
+ IROp xorOp, subOp, andOp;
+ IRExpr *one;
+ IRAtom *improver, *improved;
+ tl_assert(isShadowAtom(mce,vatom));
+ tl_assert(isOriginalAtom(mce,atom));
+ tl_assert(sameKindedAtoms(atom,vatom));
+
+ switch (czop) {
+ case Iop_Ctz32:
+ ty = Ity_I32;
+ xorOp = Iop_Xor32;
+ subOp = Iop_Sub32;
+ andOp = Iop_And32;
+ one = mkU32(1);
+ break;
+ case Iop_Ctz64:
+ ty = Ity_I64;
+ xorOp = Iop_Xor64;
+ subOp = Iop_Sub64;
+ andOp = Iop_And64;
+ one = mkU64(1);
+ break;
+ default:
+ ppIROp(czop);
+ VG_(tool_panic)("memcheck:expensiveCountTrailingZeroes");
+ }
+
+ // improver = atom ^ (atom - 1)
+ //
+ // That is, improver has its low ctz(atom) bits equal to one;
+ // higher bits (if any) equal to zero.
+ improver = assignNew('V', mce,ty,
+ binop(xorOp,
+ atom,
+ assignNew('V', mce, ty,
+ binop(subOp, atom, one))));
+
+ // improved = vatom & improver
+ //
+ // That is, treat any V bits above the first ctz(atom) bits as
+ // "defined".
+ improved = assignNew('V', mce, ty,
+ binop(andOp, vatom, improver));
+
+ // Return pessimizing cast of improved.
+ return mkPCastTo(mce, ty, improved);
+}
+
+
/*------------------------------------------------------------*/
/*--- Scalar shifts. ---*/
/*------------------------------------------------------------*/
@@ -3426,9 +3489,14 @@
case Iop_CmpEQ64:
case Iop_CmpNE64:
if (mce->bogusLiterals)
- return expensiveCmpEQorNE(mce,Ity_I64, vatom1,vatom2, atom1,atom2 );
+ goto expensive_cmp64;
else
goto cheap_cmp64;
+
+ expensive_cmp64:
+ case Iop_ExpCmpNE64:
+ return expensiveCmpEQorNE(mce,Ity_I64, vatom1,vatom2, atom1,atom2 );
+
cheap_cmp64:
case Iop_CmpLE64S: case Iop_CmpLE64U:
case Iop_CmpLT64U: case Iop_CmpLT64S:
@@ -3437,9 +3505,14 @@
case Iop_CmpEQ32:
case Iop_CmpNE32:
if (mce->bogusLiterals)
- return expensiveCmpEQorNE(mce,Ity_I32, vatom1,vatom2, atom1,atom2 );
+ goto expensive_cmp32;
else
goto cheap_cmp32;
+
+ expensive_cmp32:
+ case Iop_ExpCmpNE32:
+ return expensiveCmpEQorNE(mce,Ity_I32, vatom1,vatom2, atom1,atom2 );
+
cheap_cmp32:
case Iop_CmpLE32S: case Iop_CmpLE32U:
case Iop_CmpLT32U: case Iop_CmpLT32S:
@@ -3448,6 +3521,9 @@
case Iop_CmpEQ16: case Iop_CmpNE16:
return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
+ case Iop_ExpCmpNE16:
+ return expensiveCmpEQorNE(mce,Ity_I16, vatom1,vatom2, atom1,atom2 );
+
case Iop_CmpEQ8: case Iop_CmpNE8:
return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
@@ -3635,7 +3711,6 @@
case Iop_RoundF64toF64_PosINF:
case Iop_RoundF64toF64_ZERO:
case Iop_Clz64:
- case Iop_Ctz64:
case Iop_D32toD64:
case Iop_ExtractExpD64: /* D64 -> I64 */
case Iop_ExtractExpD128: /* D128 -> I64 */
@@ -3647,12 +3722,15 @@
return mkPCastTo(mce, Ity_I128, vatom);
case Iop_Clz32:
- case Iop_Ctz32:
case Iop_TruncF64asF32:
case Iop_NegF32:
case Iop_AbsF32:
return mkPCastTo(mce, Ity_I32, vatom);
+ case Iop_Ctz32:
+ case Iop_Ctz64:
+ return expensiveCountTrailingZeroes(mce, op, atom, vatom);
+
case Iop_1Uto64:
case Iop_1Sto64:
case Iop_8Uto64:
@@ -3702,6 +3780,7 @@
case Iop_16HIto8:
case Iop_32to8:
case Iop_64to8:
+ case Iop_GetMSBs8x8:
return assignNew('V', mce, Ity_I8, unop(op, vatom));
case Iop_32to1:
Modified: trunk/memcheck/tests/vbit-test/irops.c (+6 -0)
===================================================================
--- trunk/memcheck/tests/vbit-test/irops.c 2012-11-07 13:42:36 +00:00 (rev 13107)
+++ trunk/memcheck/tests/vbit-test/irops.c 2012-11-08 10:58:16 +00:00 (rev 13108)
@@ -62,10 +62,15 @@
{ DEFOP(Iop_CasCmpEQ16, UNDEF_NONE), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0 },
{ DEFOP(Iop_CasCmpEQ32, UNDEF_NONE), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0 },
{ DEFOP(Iop_CasCmpEQ64, UNDEF_NONE), .s390x = 1, .amd64 = 1, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0 },
+
{ DEFOP(Iop_CasCmpNE8, UNDEF_NONE), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0 },
{ DEFOP(Iop_CasCmpNE16, UNDEF_NONE), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0 },
{ DEFOP(Iop_CasCmpNE32, UNDEF_NONE), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0 },
{ DEFOP(Iop_CasCmpNE64, UNDEF_NONE), .s390x = 1, .amd64 = 1, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0 },
+ { DEFOP(Iop_ExpCmpNE8, UNDEF_UNKNOWN), }, // exact (expensive) equality
+ { DEFOP(Iop_ExpCmpNE16, UNDEF_UNKNOWN), }, // exact (expensive) equality
+ { DEFOP(Iop_ExpCmpNE32, UNDEF_UNKNOWN), }, // exact (expensive) equality
+ { DEFOP(Iop_ExpCmpNE64, UNDEF_UNKNOWN), }, // exact (expensive) equality
{ DEFOP(Iop_MullS8, UNDEF_LEFT), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0 },
{ DEFOP(Iop_MullS16, UNDEF_LEFT), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0 },
{ DEFOP(Iop_MullS32, UNDEF_LEFT), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 1, .ppc64 = 1, .ppc32 = 1, .mips32 = 0 }, // mips asserts
@@ -468,6 +473,7 @@
{ DEFOP(Iop_Reverse64_16x4, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Reverse64_32x2, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Perm8x8, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_GetMSBs8x8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Recip32x2, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Rsqrte32x2, UNDEF_UNKNOWN), },
/* ------------------ Decimal Floating Point ------------------ */
|