From: Sanjoy Das Date: Wed, 28 Oct 2015 03:20:15 +0000 (+0000) Subject: [ValueTracking] Use !range metadata more aggressively in KnownBits X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=e06e113689ab0c2628198e8e1459b42f99d2fd59;p=oota-llvm.git [ValueTracking] Use !range metadata more aggressively in KnownBits Summary: Teach `computeKnownBitsFromRangeMetadata` to use `!range` metadata more aggressively. Reviewers: majnemer, nlewycky, jingyue Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D14100 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@251487 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index 6216c4ddfd8..f9e0386a4ed 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -49,8 +49,9 @@ namespace llvm { const DominatorTree *DT = nullptr); /// Compute known bits from the range metadata. /// \p KnownZero the set of bits that are known to be zero + /// \p KnownOne the set of bits that are known to be one void computeKnownBitsFromRangeMetadata(const MDNode &Ranges, - APInt &KnownZero); + APInt &KnownZero, APInt &KnownOne); /// Return true if LHS and RHS have no common bits set. bool haveNoCommonBitsSet(Value *LHS, Value *RHS, const DataLayout &DL, AssumptionCache *AC = nullptr, diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index e25087e6911..fda1dbf8825 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -367,24 +367,30 @@ static void computeKnownBitsMul(Value *Op0, Value *Op1, bool NSW, } void llvm::computeKnownBitsFromRangeMetadata(const MDNode &Ranges, - APInt &KnownZero) { + APInt &KnownZero, + APInt &KnownOne) { unsigned BitWidth = KnownZero.getBitWidth(); unsigned NumRanges = Ranges.getNumOperands() / 2; assert(NumRanges >= 1); - // Use the high end of the ranges to find leading zeros. - unsigned MinLeadingZeros = BitWidth; + KnownZero.setAllBits(); + KnownOne.setAllBits(); + for (unsigned i = 0; i < NumRanges; ++i) { ConstantInt *Lower = mdconst::extract(Ranges.getOperand(2 * i + 0)); ConstantInt *Upper = mdconst::extract(Ranges.getOperand(2 * i + 1)); ConstantRange Range(Lower->getValue(), Upper->getValue()); - unsigned LeadingZeros = Range.getUnsignedMax().countLeadingZeros(); - MinLeadingZeros = std::min(LeadingZeros, MinLeadingZeros); - } - KnownZero = APInt::getHighBitsSet(BitWidth, MinLeadingZeros); + // The first CommonPrefixBits of all values in Range are equal. + unsigned CommonPrefixBits = + (Range.getUnsignedMax() ^ Range.getUnsignedMin()).countLeadingZeros(); + + APInt Mask = APInt::getHighBitsSet(BitWidth, CommonPrefixBits); + KnownOne &= Range.getUnsignedMax() & Mask; + KnownZero &= ~Range.getUnsignedMax() & Mask; + } } static bool isEphemeralValueOf(Instruction *I, const Value *E) { @@ -1060,7 +1066,7 @@ static void computeKnownBitsFromOperator(Operator *I, APInt &KnownZero, default: break; case Instruction::Load: if (MDNode *MD = cast(I)->getMetadata(LLVMContext::MD_range)) - computeKnownBitsFromRangeMetadata(*MD, KnownZero); + computeKnownBitsFromRangeMetadata(*MD, KnownZero, KnownOne); break; case Instruction::And: { // If either the LHS or the RHS are Zero, the result is zero. @@ -1452,7 +1458,7 @@ static void computeKnownBitsFromOperator(Operator *I, APInt &KnownZero, case Instruction::Call: case Instruction::Invoke: if (MDNode *MD = cast(I)->getMetadata(LLVMContext::MD_range)) - computeKnownBitsFromRangeMetadata(*MD, KnownZero); + computeKnownBitsFromRangeMetadata(*MD, KnownZero, KnownOne); // If a range metadata is attached to this IntrinsicInst, intersect the // explicit range specified by the metadata and the implicit range of // the intrinsic. diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 66f5ba7f5dd..3296eb41e78 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -2285,7 +2285,7 @@ void SelectionDAG::computeKnownBits(SDValue Op, APInt &KnownZero, KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - MemBits); } else if (const MDNode *Ranges = LD->getRanges()) { if (LD->getExtensionType() == ISD::NON_EXTLOAD) - computeKnownBitsFromRangeMetadata(*Ranges, KnownZero); + computeKnownBitsFromRangeMetadata(*Ranges, KnownZero, KnownOne); } break; } diff --git a/test/Analysis/ValueTracking/known-bits-from-range-md.ll b/test/Analysis/ValueTracking/known-bits-from-range-md.ll new file mode 100644 index 00000000000..e1de089b350 --- /dev/null +++ b/test/Analysis/ValueTracking/known-bits-from-range-md.ll @@ -0,0 +1,34 @@ +; RUN: opt -S -instsimplify < %s | FileCheck %s + +define i1 @test0(i8* %ptr) { +; CHECK-LABEL: @test0( + entry: + %val = load i8, i8* %ptr, !range !{i8 -50, i8 0} + %and = and i8 %val, 128 + %is.eq = icmp eq i8 %and, 128 + ret i1 %is.eq +; CHECK: ret i1 true +} + +define i1 @test1(i8* %ptr) { +; CHECK-LABEL: @test1( + entry: + %val = load i8, i8* %ptr, !range !{i8 64, i8 128} + %and = and i8 %val, 64 + %is.eq = icmp eq i8 %and, 64 + ret i1 %is.eq +; CHECK: ret i1 true +} + +define i1 @test2(i8* %ptr) { +; CHECK-LABEL: @test2( + entry: +; CHECK: load +; CHECK: and +; CHECK: icmp eq +; CHECK: ret + %val = load i8, i8* %ptr, !range !{i8 64, i8 129} + %and = and i8 %val, 64 + %is.eq = icmp eq i8 %and, 64 + ret i1 %is.eq +}