Index: llvm/trunk/include/llvm/Analysis/ValueTracking.h =================================================================== --- llvm/trunk/include/llvm/Analysis/ValueTracking.h +++ llvm/trunk/include/llvm/Analysis/ValueTracking.h @@ -49,8 +49,9 @@ 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, Index: llvm/trunk/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/trunk/lib/Analysis/ValueTracking.cpp +++ llvm/trunk/lib/Analysis/ValueTracking.cpp @@ -367,24 +367,30 @@ } 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 @@ 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 @@ 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. Index: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -2285,7 +2285,7 @@ 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; } Index: llvm/trunk/test/Analysis/ValueTracking/known-bits-from-range-md.ll =================================================================== --- llvm/trunk/test/Analysis/ValueTracking/known-bits-from-range-md.ll +++ llvm/trunk/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 +}