Index: include/llvm/Analysis/ValueTracking.h =================================================================== --- include/llvm/Analysis/ValueTracking.h +++ 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: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -367,11 +367,14 @@ } void llvm::computeKnownBitsFromRangeMetadata(const MDNode &Ranges, - APInt &KnownZero) { + APInt &KnownZero, + APInt &KnownOne) { unsigned BitWidth = KnownZero.getBitWidth(); unsigned NumRanges = Ranges.getNumOperands() / 2; assert(NumRanges >= 1); + bool AlwaysNegative = true; + // Use the high end of the ranges to find leading zeros. unsigned MinLeadingZeros = BitWidth; for (unsigned i = 0; i < NumRanges; ++i) { @@ -382,9 +385,14 @@ ConstantRange Range(Lower->getValue(), Upper->getValue()); unsigned LeadingZeros = Range.getUnsignedMax().countLeadingZeros(); MinLeadingZeros = std::min(LeadingZeros, MinLeadingZeros); + AlwaysNegative &= Range.getSignedMax().isNegative(); } KnownZero = APInt::getHighBitsSet(BitWidth, MinLeadingZeros); + if (AlwaysNegative) { + assert(MinLeadingZeros == 0 && "We found at least one negative number!"); + KnownOne = APInt::getHighBitsSet(BitWidth, 1); + } } static bool isEphemeralValueOf(Instruction *I, const Value *E) { @@ -1060,7 +1068,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 +1460,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: lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -2284,7 +2284,7 @@ unsigned MemBits = VT.getScalarType().getSizeInBits(); KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - MemBits); } else if (const MDNode *Ranges = LD->getRanges()) { - computeKnownBitsFromRangeMetadata(*Ranges, KnownZero); + computeKnownBitsFromRangeMetadata(*Ranges, KnownZero, KnownOne); } break; } Index: test/Analysis/ValueTracking/sign-bit-from-md.ll =================================================================== --- /dev/null +++ test/Analysis/ValueTracking/sign-bit-from-md.ll @@ -0,0 +1,13 @@ +; RUN: opt -S -instsimplify < %s | FileCheck %s + +define i1 @f(i8* %ptr) { +; CHECK-LABEL: @f( + entry: + %val = load i8, i8* %ptr, !range !0 + %and = and i8 %val, 128 + %is.eq = icmp eq i8 %and, 128 + ret i1 %is.eq +; CHECK: true +} + +!0 = !{i8 -50, i8 0}