diff options
| author | Sanjoy Das <sanjoy@playingwithpointers.com> | 2014-10-15 19:25:28 +0000 |
|---|---|---|
| committer | Sanjoy Das <sanjoy@playingwithpointers.com> | 2014-10-15 19:25:28 +0000 |
| commit | 90c2f1455ae1e88aa31e68f4e7cdcdf955c945ed (patch) | |
| tree | add8f3ca67de38efd5a3ee5741212f281e41f196 /llvm/lib/Analysis/ScalarEvolution.cpp | |
| parent | 74cd020fcaa1e5abd31fcbad1c0be0319a3bf790 (diff) | |
| download | bcm5719-llvm-90c2f1455ae1e88aa31e68f4e7cdcdf955c945ed.tar.gz bcm5719-llvm-90c2f1455ae1e88aa31e68f4e7cdcdf955c945ed.zip | |
Teach ScalarEvolution to sharpen range information.
If x is known to have the range [a, b) in a loop predicated by (icmp
ne x, a), its range can be sharpened to [a + 1, b). Get
ScalarEvolution and hence IndVars to exploit this fact.
This change triggers an optimization to widen-loop-comp.ll, so it had
to be edited to get it to pass.
phabricator: http://reviews.llvm.org/D5639
llvm-svn: 219834
Diffstat (limited to 'llvm/lib/Analysis/ScalarEvolution.cpp')
| -rw-r--r-- | llvm/lib/Analysis/ScalarEvolution.cpp | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index b015481b76c..8d1c632008a 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -6782,6 +6782,44 @@ bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, RHS, LHS, FoundLHS, FoundRHS); } + if (FoundPred == ICmpInst::ICMP_NE) { + // If we are predicated on something with range [a, b) known not + // equal to a, the range can be sharpened to [a + 1, b). Use this + // fact. + auto CheckRange = [this, Pred, LHS, RHS](const SCEV *C, const SCEV *V) { + if (!isa<SCEVConstant>(C)) return false; + + ConstantInt *CI = cast<SCEVConstant>(C)->getValue(); + APInt Min = ICmpInst::isSigned(Pred) ? + getSignedRange(V).getSignedMin() : getUnsignedRange(V).getUnsignedMin(); + + if (Min!= CI->getValue()) return false; // nothing to sharpen + Min++; + + // We know V >= Min, in the same signedness as in Pred. We can + // use this to simplify slt and ult. If the range had a single + // value, Min, we now know that FoundValue can never be true; + // and any answer is a correct answer. + + switch (Pred) { + case ICmpInst::ICMP_SGT: + case ICmpInst::ICMP_UGT: + return isImpliedCondOperands(Pred, LHS, RHS, V, getConstant(Min)); + + default: + llvm_unreachable("don't call with predicates other than ICMP_SGT " + "and ICMP_UGT"); + } + }; + + if ((Pred == ICmpInst::ICMP_SGT) || (Pred == ICmpInst::ICMP_UGT)) { + // Inequality is reflexive -- check both the combinations. + if (CheckRange(FoundLHS, FoundRHS) || CheckRange(FoundRHS, FoundLHS)) { + return true; + } + } + } + // Check whether the actual condition is beyond sufficient. if (FoundPred == ICmpInst::ICMP_EQ) if (ICmpInst::isTrueWhenEqual(Pred)) |

