Index: lib/Analysis/InstructionSimplify.cpp =================================================================== --- lib/Analysis/InstructionSimplify.cpp +++ lib/Analysis/InstructionSimplify.cpp @@ -2403,6 +2403,32 @@ } } + // If both operands have range metadata, use the metadata + // to simplify the comparison. + if (isa(RHS) && isa(LHS)) { + auto RHS_Instr = dyn_cast(RHS); + auto LHS_Instr = dyn_cast(LHS); + + if (RHS_Instr->getMetadata(LLVMContext::MD_range) && + LHS_Instr->getMetadata(LLVMContext::MD_range)) { + uint32_t BitWidth = Q.DL.getTypeSizeInBits(RHS->getType()); + + auto RHS_CR = GetConstantRangeFromMetadata( + RHS_Instr->getMetadata(LLVMContext::MD_range), BitWidth); + auto LHS_CR = GetConstantRangeFromMetadata( + LHS_Instr->getMetadata(LLVMContext::MD_range), BitWidth); + + auto Satisfied_CR = ConstantRange::makeSatisfyingICmpRegion(Pred, RHS_CR); + auto InversedSatisfied_CR = ConstantRange::makeSatisfyingICmpRegion( + CmpInst::getInversePredicate(Pred), RHS_CR); + + if (Satisfied_CR.contains(LHS_CR)) + return ConstantInt::getTrue(RHS->getContext()); + if (InversedSatisfied_CR.contains(LHS_CR)) + return ConstantInt::getFalse(RHS->getContext()); + } + } + // Compare of cast, for example (zext X) != 0 -> X != 0 if (isa(LHS) && (isa(RHS) || isa(RHS))) { Instruction *LI = cast(LHS); Index: test/Transforms/InstCombine/icmp-range.ll =================================================================== --- test/Transforms/InstCombine/icmp-range.ll +++ test/Transforms/InstCombine/icmp-range.ll @@ -111,8 +111,40 @@ ret i1 %rval } +; Values' ranges overlap each other, so it can not be simplified. +define i1 @test_two_ranges(i32* nocapture readonly %arg1, i32* nocapture readonly %arg2) { +; CHECK-LABEL: test_two_ranges +; CHECK: icmp ult i32 %val2, %val1 + %val1 = load i32, i32* %arg1, !range !5 + %val2 = load i32, i32* %arg2, !range !6 + %rval = icmp ult i32 %val2, %val1 + ret i1 %rval +} + +; Values' ranges do not overlap each other, so it can simplified to false. +define i1 @test_two_ranges2(i32* nocapture readonly %arg1, i32* nocapture readonly %arg2) { +; CHECK-LABEL: test_two_ranges2 +; CHECK: ret i1 false + %val1 = load i32, i32* %arg1, !range !0 + %val2 = load i32, i32* %arg2, !range !6 + %rval = icmp ult i32 %val2, %val1 + ret i1 %rval +} + +; Values' ranges do not overlap each other, so it can simplified to true. +define i1 @test_two_ranges3(i32* nocapture readonly %arg1, i32* nocapture readonly %arg2) { +; CHECK-LABEL: test_two_ranges3 +; CHECK: ret i1 true + %val1 = load i32, i32* %arg1, !range !0 + %val2 = load i32, i32* %arg2, !range !6 + %rval = icmp ugt i32 %val2, %val1 + ret i1 %rval +} + !0 = !{i32 1, i32 6} !1 = !{i32 0, i32 6} !2 = !{i8 0, i8 1} !3 = !{i8 0, i8 6} !4 = !{i32 1, i32 6, i32 8, i32 10} +!5 = !{i32 5, i32 10} +!6 = !{i32 8, i32 16}