Skip to content

Commit

Permalink
[Bug 24848] Use range metadata to constant fold comparisons between t…
Browse files Browse the repository at this point in the history
…wo 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
  • Loading branch information
lic9 committed Sep 26, 2015
1 parent c03102a commit 9cc82f0
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 0 deletions.
26 changes: 26 additions & 0 deletions lib/Analysis/InstructionSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<Instruction>(RHS) && isa<Instruction>(LHS)) {
auto RHS_Instr = dyn_cast<Instruction>(RHS);
auto LHS_Instr = dyn_cast<Instruction>(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<CastInst>(LHS) && (isa<Constant>(RHS) || isa<CastInst>(RHS))) {
Instruction *LI = cast<CastInst>(LHS);
Expand Down
32 changes: 32 additions & 0 deletions test/Transforms/InstCombine/icmp-range.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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}

0 comments on commit 9cc82f0

Please sign in to comment.