diff options
| author | Sanjoy Das <sanjoy@playingwithpointers.com> | 2015-10-23 06:33:47 +0000 |
|---|---|---|
| committer | Sanjoy Das <sanjoy@playingwithpointers.com> | 2015-10-23 06:33:47 +0000 |
| commit | 0714e3e245c20e33205a078d53b3b52fa8cee815 (patch) | |
| tree | 9614b4d7793be88b7acceb5ff0a77d4be89c1fb9 /llvm | |
| parent | 57cee79f7c6302bb94a1520cd33a676c31565743 (diff) | |
| download | bcm5719-llvm-0714e3e245c20e33205a078d53b3b52fa8cee815.tar.gz bcm5719-llvm-0714e3e245c20e33205a078d53b3b52fa8cee815.zip | |
[SCEV] Fix a latent bug in `getPreStartForExtend`
I could not come up a way to test this -- I think this bug is latent
today, and will not actually result in a miscompile.
In `getPreStartForExtend`, SCEV constructs `PreStart` as a sum of all of
`SA`'s operands except `Op`. It also uses `SA`'s no-wrap flags, and
this is problematic because removing an element from an add expression
can make it signed-wrap. E.g. if `SA` was `(127 + 1 + -1)`, then it
could safely be `<nsw>` (since `sext(127) + sext(1) + sext(-1)` ==
`sext(127 + 1 + -1)`), but `(127 + 1)` (== `PreStart` if `Op` is `-1`)
is not `<nsw>`.
Transferring `<nuw>` from `SA` to `PreStart` is safe, as far as I can
tell.
llvm-svn: 251097
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Analysis/ScalarEvolution.cpp | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 42e38ca8049..108e510b6f3 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -1268,7 +1268,9 @@ static const SCEV *getPreStartForExtend(const SCEVAddRecExpr *AR, Type *Ty, // `Step`: // 1. NSW/NUW flags on the step increment. - const SCEV *PreStart = SE->getAddExpr(DiffOps, SA->getNoWrapFlags()); + auto PreStartFlags = + ScalarEvolution::maskFlags(SA->getNoWrapFlags(), SCEV::FlagNUW); + const SCEV *PreStart = SE->getAddExpr(DiffOps, PreStartFlags); const SCEVAddRecExpr *PreAR = dyn_cast<SCEVAddRecExpr>( SE->getAddRecExpr(PreStart, Step, L, SCEV::FlagAnyWrap)); |

