Blame valgrind-3.14.0-transform-popcount64-ctznat64.patch

Mark Wielaard b3eda9
commit cb5d7e047598bff6d0f1d707a70d9fb1a1c7f0e2
Mark Wielaard b3eda9
Author: Julian Seward <jseward@acm.org>
Mark Wielaard b3eda9
Date:   Tue Nov 20 11:46:55 2018 +0100
Mark Wielaard b3eda9
Mark Wielaard b3eda9
    VEX/priv/ir_opt.c
Mark Wielaard b3eda9
    
Mark Wielaard b3eda9
    fold_Expr: transform PopCount64(And64(Add64(x,-1),Not64(x))) into CtzNat64(x).
Mark Wielaard b3eda9
    
Mark Wielaard b3eda9
    This is part of the fix for bug 386945.
Mark Wielaard b3eda9
Mark Wielaard b3eda9
diff --git a/VEX/priv/ir_opt.c b/VEX/priv/ir_opt.c
Mark Wielaard b3eda9
index f40870b..23964be 100644
Mark Wielaard b3eda9
--- a/VEX/priv/ir_opt.c
Mark Wielaard b3eda9
+++ b/VEX/priv/ir_opt.c
Mark Wielaard b3eda9
@@ -1377,6 +1377,8 @@ static IRExpr* fold_Expr ( IRExpr** env, IRExpr* e )
Mark Wielaard b3eda9
    case Iex_Unop:
Mark Wielaard b3eda9
       /* UNARY ops */
Mark Wielaard b3eda9
       if (e->Iex.Unop.arg->tag == Iex_Const) {
Mark Wielaard b3eda9
+
Mark Wielaard b3eda9
+         /* cases where the arg is a const */
Mark Wielaard b3eda9
          switch (e->Iex.Unop.op) {
Mark Wielaard b3eda9
          case Iop_1Uto8:
Mark Wielaard b3eda9
             e2 = IRExpr_Const(IRConst_U8(toUChar(
Mark Wielaard b3eda9
@@ -1690,8 +1692,56 @@ static IRExpr* fold_Expr ( IRExpr** env, IRExpr* e )
Mark Wielaard b3eda9
 
Mark Wielaard b3eda9
          default: 
Mark Wielaard b3eda9
             goto unhandled;
Mark Wielaard b3eda9
-      }
Mark Wielaard b3eda9
-      }
Mark Wielaard b3eda9
+         } // switch (e->Iex.Unop.op)
Mark Wielaard b3eda9
+
Mark Wielaard b3eda9
+      } else {
Mark Wielaard b3eda9
+
Mark Wielaard b3eda9
+         /* other cases (identities, etc) */
Mark Wielaard b3eda9
+         switch (e->Iex.Unop.op) {
Mark Wielaard b3eda9
+         case Iop_PopCount64: {
Mark Wielaard b3eda9
+            // PopCount64( And64( Add64(x,-1), Not64(x) ) ) ==> CtzNat64(x)
Mark Wielaard b3eda9
+            // bindings:
Mark Wielaard b3eda9
+            //   a1:And64( a11:Add64(a111:x,a112:-1), a12:Not64(a121:x) )
Mark Wielaard b3eda9
+            IRExpr* a1 = chase(env, e->Iex.Unop.arg);
Mark Wielaard b3eda9
+            if (!a1)
Mark Wielaard b3eda9
+               goto nomatch;
Mark Wielaard b3eda9
+            if (a1->tag != Iex_Binop || a1->Iex.Binop.op != Iop_And64)
Mark Wielaard b3eda9
+               goto nomatch;
Mark Wielaard b3eda9
+            // a1 is established
Mark Wielaard b3eda9
+            IRExpr* a11 = chase(env, a1->Iex.Binop.arg1);
Mark Wielaard b3eda9
+            if (!a11)
Mark Wielaard b3eda9
+               goto nomatch;
Mark Wielaard b3eda9
+            if (a11->tag != Iex_Binop || a11->Iex.Binop.op != Iop_Add64)
Mark Wielaard b3eda9
+               goto nomatch;
Mark Wielaard b3eda9
+            // a11 is established
Mark Wielaard b3eda9
+            IRExpr* a12 = chase(env, a1->Iex.Binop.arg2);
Mark Wielaard b3eda9
+            if (!a12)
Mark Wielaard b3eda9
+               goto nomatch;
Mark Wielaard b3eda9
+            if (a12->tag != Iex_Unop || a12->Iex.Unop.op != Iop_Not64)
Mark Wielaard b3eda9
+               goto nomatch;
Mark Wielaard b3eda9
+            // a12 is established
Mark Wielaard b3eda9
+            IRExpr* a111 = a11->Iex.Binop.arg1;
Mark Wielaard b3eda9
+            IRExpr* a112 = chase(env, a11->Iex.Binop.arg2);
Mark Wielaard b3eda9
+            IRExpr* a121 = a12->Iex.Unop.arg;
Mark Wielaard b3eda9
+            if (!a111 || !a112 || !a121)
Mark Wielaard b3eda9
+               goto nomatch;
Mark Wielaard b3eda9
+            // a111 and a121 need to be the same temp.
Mark Wielaard b3eda9
+            if (!eqIRAtom(a111, a121))
Mark Wielaard b3eda9
+               goto nomatch;
Mark Wielaard b3eda9
+            // Finally, a112 must be a 64-bit version of -1.
Mark Wielaard b3eda9
+            if (!isOnesU(a112))
Mark Wielaard b3eda9
+               goto nomatch;
Mark Wielaard b3eda9
+            // Match established.  Transform.
Mark Wielaard b3eda9
+            e2 = IRExpr_Unop(Iop_CtzNat64, a111);
Mark Wielaard b3eda9
+            break;
Mark Wielaard b3eda9
+           nomatch:
Mark Wielaard b3eda9
+            break;
Mark Wielaard b3eda9
+         }
Mark Wielaard b3eda9
+         default:
Mark Wielaard b3eda9
+            break;
Mark Wielaard b3eda9
+         } // switch (e->Iex.Unop.op)
Mark Wielaard b3eda9
+
Mark Wielaard b3eda9
+      } // if (e->Iex.Unop.arg->tag == Iex_Const)
Mark Wielaard b3eda9
       break;
Mark Wielaard b3eda9
 
Mark Wielaard b3eda9
    case Iex_Binop: