mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[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 llvm-svn: 248650
This commit is contained in:
parent
eb0d6b9ea5
commit
11db69b00f
@ -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);
|
||||
|
@ -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}
|
||||
|
Loading…
x
Reference in New Issue
Block a user