[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 llvm-svn: 251487
This commit is contained in:
parent
4ff3cf6d92
commit
1d1929aace
@ -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,
|
||||
|
||||
@ -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<ConstantInt>(Ranges.getOperand(2 * i + 0));
|
||||
ConstantInt *Upper =
|
||||
mdconst::extract<ConstantInt>(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<LoadInst>(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<Instruction>(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.
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
34
llvm/test/Analysis/ValueTracking/known-bits-from-range-md.ll
Normal file
34
llvm/test/Analysis/ValueTracking/known-bits-from-range-md.ll
Normal file
@ -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
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user