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,
}
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) {
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.
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.
--- /dev/null
+; 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
+}