From: Chen Li Date: Sat, 26 Sep 2015 03:26:47 +0000 (+0000) Subject: [Bug 24848] Use range metadata to constant fold comparisons between two values X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=9cc82f0382e6fa5d35c4fbb0a18c1106dab1d7a8;p=oota-llvm.git [Bug 24848] Use range metadata to constant fold comparisons between two values Summary: This is the second part of fixing bug 24848 https://llvm.org/bugs/show_bug.cgi?id=24848. If both operands of a comparison have range metadata, they should be used to constant fold the comparison. Reviewers: sanjoy, hfinkel Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D13177 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@248650 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index 7f27d8882e7..2086337df8b 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -2403,6 +2403,32 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, } } + // 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); + if (Satisfied_CR.contains(LHS_CR)) + return ConstantInt::getTrue(RHS->getContext()); + + auto InversedSatisfied_CR = ConstantRange::makeSatisfyingICmpRegion( + CmpInst::getInversePredicate(Pred), RHS_CR); + 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); diff --git a/test/Transforms/InstCombine/icmp-range.ll b/test/Transforms/InstCombine/icmp-range.ll index effcc381697..f035683170e 100644 --- a/test/Transforms/InstCombine/icmp-range.ll +++ b/test/Transforms/InstCombine/icmp-range.ll @@ -111,8 +111,40 @@ define i1 @test_multi_range2(i32* nocapture readonly %arg) { 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}