From: Sanjay Patel Date: Wed, 30 Dec 2015 22:40:52 +0000 (+0000) Subject: [ValueTracking] fix bug computing isKnownToBeAPowerOfTwo() with arithmetic shift... X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=08e3bf995e6be976e55d34c1aace8370c61f68fb [ValueTracking] fix bug computing isKnownToBeAPowerOfTwo() with arithmetic shift right (PR25900) This is a fix for: https://llvm.org/bugs/show_bug.cgi?id=25900 If we think that an arithmetic right shift of a power of two is always a power of two, an sdiv gets wrongly converted to udiv. Differential Revision: http://reviews.llvm.org/D15827 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@256655 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index 314ec9c1886..d6a78411388 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -1743,9 +1743,10 @@ bool isKnownToBeAPowerOfTwo(Value *V, bool OrZero, unsigned Depth, return false; Value *X = nullptr, *Y = nullptr; - // A shift of a power of two is a power of two or zero. + // A shift left or a logical shift right of a power of two is a power of two + // or zero. if (OrZero && (match(V, m_Shl(m_Value(X), m_Value())) || - match(V, m_Shr(m_Value(X), m_Value())))) + match(V, m_LShr(m_Value(X), m_Value())))) return isKnownToBeAPowerOfTwo(X, /*OrZero*/ true, Depth, Q, DL); if (ZExtInst *ZI = dyn_cast(V)) diff --git a/test/Analysis/ValueTracking/known-power-of-two.ll b/test/Analysis/ValueTracking/known-power-of-two.ll new file mode 100644 index 00000000000..ed98a8f5361 --- /dev/null +++ b/test/Analysis/ValueTracking/known-power-of-two.ll @@ -0,0 +1,20 @@ +; RUN: opt -S -instcombine < %s | FileCheck %s + +; https://llvm.org/bugs/show_bug.cgi?id=25900 +; An arithmetic shift right of a power of two is not a power +; of two if the original value is the sign bit. Therefore, +; we can't transform the sdiv into a udiv. + +define i32 @pr25900(i32 %d) { + %and = and i32 %d, -2147483648 +; The next 3 lines prevent another fold from masking the bug. + %ext = zext i32 %and to i64 + %or = or i64 %ext, 4294967296 + %trunc = trunc i64 %or to i32 + %ashr = ashr exact i32 %trunc, 31 + %div = sdiv i32 4, %ashr + ret i32 %div + +; CHECK: sdiv +} +