|
From: Mark W. <ma...@so...> - 2017-12-12 21:43:18
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=d6a810760ec61ddedf15445457edbbe288536a2f commit d6a810760ec61ddedf15445457edbbe288536a2f Author: Julian Seward <js...@ac...> Date: Tue Dec 12 22:31:54 2017 +0100 Fix false positive with s390x cgijnl instruction testing against sign bit. 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. Diff: --- NEWS | 1 + VEX/priv/guest_s390_helpers.c | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/NEWS b/NEWS index bb3d6c2..de4f668 100644 --- 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 diff --git a/VEX/priv/guest_s390_helpers.c b/VEX/priv/guest_s390_helpers.c index 4cccdec..aacd833 100644 --- a/VEX/priv/guest_s390_helpers.c +++ b/VEX/priv/guest_s390_helpers.c @@ -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) { |