diff options
author | Sanjoy Das <sanjoy@playingwithpointers.com> | 2015-02-08 22:52:17 +0000 |
---|---|---|
committer | Sanjoy Das <sanjoy@playingwithpointers.com> | 2015-02-08 22:52:17 +0000 |
commit | f2e931cae902667c27897d5435593216711b73e1 (patch) | |
tree | 83f7cc0af773c4c6f60e09c4f60e98aeef533966 /llvm/lib/Analysis/ScalarEvolution.cpp | |
parent | 68ab0465a02a3991a4ea496c823850296c8bcfdf (diff) | |
download | bcm5719-llvm-f2e931cae902667c27897d5435593216711b73e1.tar.gz bcm5719-llvm-f2e931cae902667c27897d5435593216711b73e1.zip |
Bugfix: ScalarEvolution incorrectly assumes that the start of certain
add recurrences don't overflow.
This change makes the optimization more restrictive. It still assumes
that an overflowing `add nsw` is undefined behavior; and this change
will need revisiting once we have a consistent semantics for poison
values.
Differential Revision: http://reviews.llvm.org/D7331
llvm-svn: 228552
Diffstat (limited to 'llvm/lib/Analysis/ScalarEvolution.cpp')
-rw-r--r-- | llvm/lib/Analysis/ScalarEvolution.cpp | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 9b9e7dc5eea..8f2e4f2ba28 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -1364,7 +1364,24 @@ static const SCEV *getPreStartForSignExtend(const SCEVAddRecExpr *AR, const SCEVAddRecExpr *PreAR = dyn_cast<SCEVAddRecExpr>( SE->getAddRecExpr(PreStart, Step, L, SCEV::FlagAnyWrap)); - if (PreAR && PreAR->getNoWrapFlags(SCEV::FlagNSW)) + // WARNING: FIXME: the optimization below assumes that a sign-overflowing nsw + // operation is undefined behavior. This is strictly more aggressive than the + // interpretation of nsw in other parts of LLVM (for instance, they may + // unconditionally hoist nsw arithmetic through control flow). This logic + // needs to be revisited once we have a consistent semantics for poison + // values. + // + // "{S,+,X} is <nsw>" and "{S,+,X} is evaluated at least once" implies "S+X + // does not sign-overflow" (we'd have undefined behavior if it did). If + // `L->getExitingBlock() == L->getLoopLatch()` then `PreAR` (= {S,+,X}<nsw>) + // is evaluated every-time `AR` (= {S+X,+,X}) is evaluated, and hence within + // `AR` we are safe to assume that "S+X" will not sign-overflow. + // + + BasicBlock *ExitingBlock = L->getExitingBlock(); + BasicBlock *LatchBlock = L->getLoopLatch(); + if (PreAR && PreAR->getNoWrapFlags(SCEV::FlagNSW) && + ExitingBlock != nullptr && ExitingBlock == LatchBlock) return PreStart; // 2. Direct overflow check on the step operation's expression. |