diff options
author | Philip Reames <listmail@philipreames.com> | 2016-02-12 19:05:16 +0000 |
---|---|---|
committer | Philip Reames <listmail@philipreames.com> | 2016-02-12 19:05:16 +0000 |
commit | 2b9100dfbd4219727c6904e76403efda0d2d5e63 (patch) | |
tree | a07c77238f9e6b6fe6c1d79e867ae81aa49a0b76 /llvm/lib | |
parent | f6892eda24f1666c9dbd64bdff0994b04554c681 (diff) | |
download | bcm5719-llvm-2b9100dfbd4219727c6904e76403efda0d2d5e63.tar.gz bcm5719-llvm-2b9100dfbd4219727c6904e76403efda0d2d5e63.zip |
[LVI] Exploit nsw/nuw when computing constant ranges
As the title says. Modelled after similar code in SCEV.
This is useful when analysing induction variables in loops which have been canonicalized by other passes. I wrote the tests as non-loops specifically to avoid the generality introduced in http://reviews.llvm.org/D17174. While that can handle many induction variables without *needing* to exploit nsw, there's no reason not to use it if we've already proven it.
Differential Revision: http://reviews.llvm.org/D17177
llvm-svn: 260705
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Analysis/LazyValueInfo.cpp | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp index 8f121110051..d21b1bd8937 100644 --- a/llvm/lib/Analysis/LazyValueInfo.cpp +++ b/llvm/lib/Analysis/LazyValueInfo.cpp @@ -961,6 +961,27 @@ bool LazyValueInfoCache::solveBlockValueConstantRange(LVILatticeVal &BBLV, if (isa<BinaryOperator>(BBI)) { if (ConstantInt *RHS = dyn_cast<ConstantInt>(BBI->getOperand(1))) { RHSRange = ConstantRange(RHS->getValue()); + + // Try to use information about wrap flags to refine the range LHS can + // legally have. This is a slightly weird way to implement forward + // propagation over overflowing instructions, but it seems to be the only + // clean one we have. NOTE: Because we may have speculated the + // instruction, we can't constrain other uses of LHS even if they would + // seem to be equivelent control dependent with this op. + if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(BBI)) { + unsigned WrapKind = 0; + if (OBO->hasNoSignedWrap()) + WrapKind |= OverflowingBinaryOperator::NoSignedWrap; + if (OBO->hasNoUnsignedWrap()) + WrapKind |= OverflowingBinaryOperator::NoUnsignedWrap; + + if (WrapKind) { + auto OpCode = static_cast<Instruction::BinaryOps>(BBI->getOpcode()); + auto NoWrapCR = + ConstantRange::makeNoWrapRegion(OpCode, RHS->getValue(), WrapKind); + LHSRange = LHSRange.intersectWith(NoWrapCR); + } + } } else { BBLV.markOverdefined(); return true; |