]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Fix false positive with s390x cgijnl instruction testing against sign bit.
authorJulian Seward <jseward@acm.org>
Tue, 12 Dec 2017 21:31:54 +0000 (22:31 +0100)
committerMark Wielaard <mark@klomp.org>
Tue, 12 Dec 2017 21:31:54 +0000 (22:31 +0100)
https://bugs.kde.org/show_bug.cgi?id=387712

When the cgij "compare immediate and branch relative" instruction
compares 0 <=signed dep1, that means dep1 >=signed 0, so it is a test
against the most significant bit of dep1. So only that bit needs
to be defined.

NEWS
VEX/priv/guest_s390_helpers.c

diff --git a/NEWS b/NEWS
index bb3d6c2a8edccc4d270f0ae54a37ea92c101a6f5..de4f6687ea7cdc2227d1f4021484cad14f220ed4 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -77,6 +77,7 @@ where XXXXXX is the bug number as listed below.
 385912  none/tests/rlimit_nofile fails on newer glibc/kernel.
 385939  Optionally exit on the first error
 386397  PPC64, valgrind truncates powerpc timebase to 32-bits.
+387712  s390x cgijnl reports Conditional jump depends on uninitialised value
 
 n-i-bz  Fix missing workq_ops operations (macOS)
 n-i-bz  fix bug in strspn replacement
index 4cccdec79f68d939516605504b85b682cb9c1cab..aacd833b542048405f1306eaa602c5baf9a25e96 100644 (file)
@@ -1818,6 +1818,13 @@ isC64(const IRExpr *expr)
    return expr->tag == Iex_Const && expr->Iex.Const.con->tag == Ico_U64;
 }
 
+static inline Bool
+isC64_exactly(const IRExpr *expr, ULong n)
+{
+   return expr->tag == Iex_Const && expr->Iex.Const.con->tag == Ico_U64
+          && expr->Iex.Const.con->Ico.U64 == n;
+}
+
 
 /* The returned expression is NULL if no specialization was found. In that
    case the helper function will be called. Otherwise, the expression has
@@ -1895,9 +1902,25 @@ guest_s390x_spechelper(const HChar *function_name, IRExpr **args,
          }
          /* cc_dep1 > cc_dep2  ---->  cc_dep2 < cc_dep1 */
          if (cond == 2 || cond == 2 + 1) {
+            /* If we ever need the counterpart of the bug387712 fix just
+               below, then here is the place.  We'll need to give an
+               alternative expression for the case "cc_dep2 <s 0".  From a
+               bit of simple testing, I've yet to see any such cases,
+               however. */
             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep2, cc_dep1));
          }
          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
+            if (isC64_exactly(cc_dep2, 0)) {
+               /*     0    <=signed dep1
+                  --> dep1 >=signed 0
+                  --> m.s.bit of dep1 == 0 */
+               /* See bug 387712.  This is an old trick from gcc to extract
+                  the most significant bit of a word. */
+               return unop(Iop_64to32,
+                           binop(Iop_Xor64,
+                                 binop(Iop_Shr64, cc_dep1, mkU8(63)),
+                                 mkU64(1)));
+            }
             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep2, cc_dep1));
          }
          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {