mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-24 05:09:34 +00:00
[SCEV] Make isImpliedCond smarter.
Summary: This change teaches isImpliedCond to infer things like "X sgt 0" => "X - 1 sgt -1". The `ConstantRange` class has the logic to do the heavy lifting, this change simply gets ScalarEvolution to exploit that when reasonable. Depends on D8345 Reviewers: atrick Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D8346 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@232576 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
da5f3a3ca5
commit
e027d74733
@ -535,6 +535,15 @@ namespace llvm {
|
|||||||
const SCEV *FoundLHS,
|
const SCEV *FoundLHS,
|
||||||
const SCEV *FoundRHS);
|
const SCEV *FoundRHS);
|
||||||
|
|
||||||
|
/// isImpliedCondOperandsViaRanges - Test whether the condition described by
|
||||||
|
/// Pred, LHS, and RHS is true whenever the condition described by Pred,
|
||||||
|
/// FoundLHS, and FoundRHS is true. Utility function used by
|
||||||
|
/// isImpliedCondOperands.
|
||||||
|
bool isImpliedCondOperandsViaRanges(ICmpInst::Predicate Pred,
|
||||||
|
const SCEV *LHS, const SCEV *RHS,
|
||||||
|
const SCEV *FoundLHS,
|
||||||
|
const SCEV *FoundRHS);
|
||||||
|
|
||||||
/// getConstantEvolutionLoopExitValue - If we know that the specified Phi is
|
/// getConstantEvolutionLoopExitValue - If we know that the specified Phi is
|
||||||
/// in the header of its containing loop, we know the loop executes a
|
/// in the header of its containing loop, we know the loop executes a
|
||||||
/// constant number of times, and the PHI node is just a recurrence
|
/// constant number of times, and the PHI node is just a recurrence
|
||||||
|
@ -6942,6 +6942,9 @@ bool ScalarEvolution::isImpliedCondOperands(ICmpInst::Predicate Pred,
|
|||||||
const SCEV *LHS, const SCEV *RHS,
|
const SCEV *LHS, const SCEV *RHS,
|
||||||
const SCEV *FoundLHS,
|
const SCEV *FoundLHS,
|
||||||
const SCEV *FoundRHS) {
|
const SCEV *FoundRHS) {
|
||||||
|
if (isImpliedCondOperandsViaRanges(Pred, LHS, RHS, FoundLHS, FoundRHS))
|
||||||
|
return true;
|
||||||
|
|
||||||
return isImpliedCondOperandsHelper(Pred, LHS, RHS,
|
return isImpliedCondOperandsHelper(Pred, LHS, RHS,
|
||||||
FoundLHS, FoundRHS) ||
|
FoundLHS, FoundRHS) ||
|
||||||
// ~x < ~y --> x > y
|
// ~x < ~y --> x > y
|
||||||
@ -7079,6 +7082,47 @@ ScalarEvolution::isImpliedCondOperandsHelper(ICmpInst::Predicate Pred,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// isImpliedCondOperandsViaRanges - helper function for isImpliedCondOperands.
|
||||||
|
/// Tries to get cases like "X `sgt` 0 => X - 1 `sgt` -1".
|
||||||
|
bool ScalarEvolution::isImpliedCondOperandsViaRanges(ICmpInst::Predicate Pred,
|
||||||
|
const SCEV *LHS,
|
||||||
|
const SCEV *RHS,
|
||||||
|
const SCEV *FoundLHS,
|
||||||
|
const SCEV *FoundRHS) {
|
||||||
|
if (!isa<SCEVConstant>(RHS) || !isa<SCEVConstant>(FoundRHS))
|
||||||
|
// The restriction on `FoundRHS` be lifted easily -- it exists only to
|
||||||
|
// reduce the compile time impact of this optimization.
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const SCEVAddExpr *AddLHS = dyn_cast<SCEVAddExpr>(LHS);
|
||||||
|
if (!AddLHS || AddLHS->getOperand(1) != FoundLHS ||
|
||||||
|
!isa<SCEVConstant>(AddLHS->getOperand(0)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
APInt ConstFoundRHS = cast<SCEVConstant>(FoundRHS)->getValue()->getValue();
|
||||||
|
|
||||||
|
// `FoundLHSRange` is the range we know `FoundLHS` to be in by virtue of the
|
||||||
|
// antecedent "`FoundLHS` `Pred` `FoundRHS`".
|
||||||
|
ConstantRange FoundLHSRange =
|
||||||
|
ConstantRange::makeAllowedICmpRegion(Pred, ConstFoundRHS);
|
||||||
|
|
||||||
|
// Since `LHS` is `FoundLHS` + `AddLHS->getOperand(0)`, we can compute a range
|
||||||
|
// for `LHS`:
|
||||||
|
APInt Addend =
|
||||||
|
cast<SCEVConstant>(AddLHS->getOperand(0))->getValue()->getValue();
|
||||||
|
ConstantRange LHSRange = FoundLHSRange.add(ConstantRange(Addend));
|
||||||
|
|
||||||
|
// We can also compute the range of values for `LHS` that satisfy the
|
||||||
|
// consequent, "`LHS` `Pred` `RHS`":
|
||||||
|
APInt ConstRHS = cast<SCEVConstant>(RHS)->getValue()->getValue();
|
||||||
|
ConstantRange SatisfyingLHSRange =
|
||||||
|
ConstantRange::makeSatisfyingICmpRegion(Pred, ConstRHS);
|
||||||
|
|
||||||
|
// The antecedent implies the consequent if every value of `LHS` that
|
||||||
|
// satisfies the antecedent also satisfies the consequent.
|
||||||
|
return SatisfyingLHSRange.contains(LHSRange);
|
||||||
|
}
|
||||||
|
|
||||||
// Verify if an linear IV with positive stride can overflow when in a
|
// Verify if an linear IV with positive stride can overflow when in a
|
||||||
// less-than comparison, knowing the invariant term of the comparison, the
|
// less-than comparison, knowing the invariant term of the comparison, the
|
||||||
// stride and the knowledge of NSW/NUW flags on the recurrence.
|
// stride and the knowledge of NSW/NUW flags on the recurrence.
|
||||||
|
30
test/Analysis/ScalarEvolution/infer-via-ranges.ll
Normal file
30
test/Analysis/ScalarEvolution/infer-via-ranges.ll
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
; RUN: opt -indvars -S < %s | FileCheck %s
|
||||||
|
|
||||||
|
define void @infer_via_ranges(i32 *%arr, i32 %n) {
|
||||||
|
; CHECK-LABEL: @infer_via_ranges
|
||||||
|
entry:
|
||||||
|
%first.itr.check = icmp sgt i32 %n, 0
|
||||||
|
%start = sub i32 %n, 1
|
||||||
|
br i1 %first.itr.check, label %loop, label %exit
|
||||||
|
|
||||||
|
loop:
|
||||||
|
; CHECK-LABEL: loop:
|
||||||
|
%idx = phi i32 [ %start, %entry ] , [ %idx.dec, %in.bounds ]
|
||||||
|
%idx.dec = sub i32 %idx, 1
|
||||||
|
%abc = icmp sge i32 %idx, 0
|
||||||
|
; CHECK: br i1 true, label %in.bounds, label %out.of.bounds
|
||||||
|
br i1 %abc, label %in.bounds, label %out.of.bounds
|
||||||
|
|
||||||
|
in.bounds:
|
||||||
|
; CHECK-LABEL: in.bounds:
|
||||||
|
%addr = getelementptr i32, i32* %arr, i32 %idx
|
||||||
|
store i32 0, i32* %addr
|
||||||
|
%next = icmp sgt i32 %idx.dec, -1
|
||||||
|
br i1 %next, label %loop, label %exit
|
||||||
|
|
||||||
|
out.of.bounds:
|
||||||
|
ret void
|
||||||
|
|
||||||
|
exit:
|
||||||
|
ret void
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user