Index: lib/Analysis/InstructionSimplify.cpp =================================================================== --- lib/Analysis/InstructionSimplify.cpp +++ lib/Analysis/InstructionSimplify.cpp @@ -2128,6 +2128,15 @@ return nullptr; } +static Value *FirstRangeContainsSecond(ConstantRange &FirstCR, ConstantRange &SecondCR, LLVMContext &Context) { + if (FirstCR.contains(SecondCR)) + return ConstantInt::getTrue(Context); + if (FirstCR.inverse().contains(SecondCR)) + return ConstantInt::getFalse(Context); + + return nullptr; +} + /// SimplifyICmpInst - Given operands for an ICmpInst, see if we can /// fold the result. If not, this returns null. static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, @@ -2366,10 +2375,31 @@ } if (Lower != Upper) { ConstantRange LHS_CR = ConstantRange(Lower, Upper); - if (RHS_CR.contains(LHS_CR)) - return ConstantInt::getTrue(RHS->getContext()); - if (RHS_CR.inverse().contains(LHS_CR)) - return ConstantInt::getFalse(RHS->getContext()); + + if (Value *RetVal = + FirstRangeContainsSecond(RHS_CR, LHS_CR, RHS->getContext())) { + return RetVal; + } + } + + // Try to fold the comparison with range metadata if available. + if (Instruction* I = dyn_cast(LHS)) { + if (MDNode *Ranges = I->getMetadata(LLVMContext::MD_range)) { + const unsigned NumRanges = Ranges->getNumOperands() / 2; + assert(NumRanges >= 1); + for (unsigned i = 0; i < NumRanges; ++i) { + ConstantInt *LowerBound = + mdconst::extract(Ranges->getOperand(2 * i + 0)); + ConstantInt *UpperBound = + mdconst::extract(Ranges->getOperand(2 * i + 1)); + ConstantRange Range(LowerBound->getValue(), UpperBound->getValue()); + + if (Value *RetVal = + FirstRangeContainsSecond(RHS_CR, Range, RHS->getContext())) { + return RetVal; + } + } + } } } Index: test/Transforms/InstCombine/icmp-range.ll =================================================================== --- test/Transforms/InstCombine/icmp-range.ll +++ test/Transforms/InstCombine/icmp-range.ll @@ -54,6 +54,14 @@ ret i1 %rval } +; Constant not in range, should return true +define i1 @test_not_in_range(i32* nocapture readonly %arg) { +; CHECK-LABEL: test_not_in_range +; CHECK: ret i1 true + %val = load i32, i32* %arg, !range !1 + %rval = icmp ne i32 %val, 6 + ret i1 %rval +} !0 = !{i32 1, i32 6} !1 = !{i32 0, i32 6}