Johannes Doerfert via llvm-dev
2016-Apr-10 17:55 UTC
[llvm-dev] ScalarEvolution "add nsw" question
Hello, I was wondering under which circumstances ScalarEvolution will propagate the no wrap flags from binary operators. In particular I looked at non-loop carried code, e.g., as in the following function: int add(int x, int y) { return x + y; } for which clang uses an "add nsw" instruction but ScalarEvolution does not propagate this information. The -analyze output looks like this: Classifying expressions for: @add %add = add nsw i32 %x, %y --> (%x + %y) U: full-set S: full-set The piece of code that causes this (for me) unexpected result is located in the ScalarEvolution::getNoWrapFlagsFromUB(...) function and looks like this: if (InnermostContainingLoop == nullptr || InnermostContainingLoop->getHeader() != BinOp->getParent()) return SCEV::FlagAnyWrap; If the "InnermostContainingLoop" is a nullptr, thus if the binary operator is not contained in a loop, all overflow annotations are simply discarded. I do not know if I am missing something or if simply nobody cared so far. In any case, I would appreciate any documentation on the current implementation as well as pointer to were it could be improved. Cheers, Johannes P.S. I have another problem with the way we currently discard the "nsw" information for accesses ("gep inbounds" apparently only implies nuw). I will probably start another thread for that one [after I read the GEP handling in more detail]. -- Johannes Doerfert Researcher / PhD Student Compiler Design Lab (Prof. Hack) Saarland University, Computer Science Building E1.3, Room 4.31 Tel. +49 (0)681 302-57521 : doerfert at cs.uni-saarland.de Fax. +49 (0)681 302-3065 : http://www.cdl.uni-saarland.de/people/doerfert -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 213 bytes Desc: Digital signature URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160410/8ad3fb1f/attachment.sig>
Sanjoy Das via llvm-dev
2016-Apr-10 22:55 UTC
[llvm-dev] ScalarEvolution "add nsw" question
[+CC Bjarke who wrote getNoWrapFlagsFromUB + related bits] Hi Johannes, One fundamental reason why we cannot reason about NoWrap flags in SCEV for arithmetic outside of loops is to avoid issues like this: if (cond) { val[x +nsw y] = 42; } else { val[x + y] = 42; } Now *both* the "x +nsw y" and "x + y" will get mapped to the same SCEV expression (this is by design [0]), and therefore we cannot mark *the* SCEV expression for "x + y" with NSW, otherwise we may incorrectly simplify the "val[x + y] = 42" branch. (Btw, I'm sure you're aware of this, but "x +nsw y" by itself does not guarantee no-wrap, it only does so if "x +nsw y" is used in a side-effecting way.) getNoWrapFlagsFromUB() avoids the problem above by adding NSW (resp. NUW) to operations on add recurrences (i.e. an add-rec + 2, say) that are guaranteed to execute at least once per loop iteration. Thus we are guaranteed that the *arithmetic operation* (not //that// specific instruction, but the arithmetic itself) does not overflow on any iteration and thus can be safely marked as non-wrapping, since if it didn't the program is guaranteed to be UB. [0]: IOW, we don't "key" on the no-wrap tag, we just key on the arithmetic bits of the operation and mutate SCEV expression in-place when we discover NUW / NSW. -- Sanjoy Johannes Doerfert via llvm-dev wrote:> Hello, > > I was wondering under which circumstances ScalarEvolution will propagate > the no wrap flags from binary operators. In particular I looked at > non-loop carried code, e.g., as in the following function: > > int add(int x, int y) { return x + y; } > > for which clang uses an "add nsw" instruction but ScalarEvolution does > not propagate this information. The -analyze output looks like this: > > Classifying expressions for: @add > %add = add nsw i32 %x, %y > --> (%x + %y) U: full-set S: full-set > > The piece of code that causes this (for me) unexpected result is located > in the ScalarEvolution::getNoWrapFlagsFromUB(...) function and looks > like this: > > if (InnermostContainingLoop == nullptr || > InnermostContainingLoop->getHeader() != BinOp->getParent()) > return SCEV::FlagAnyWrap; > > If the "InnermostContainingLoop" is a nullptr, thus if the binary > operator is not contained in a loop, all overflow annotations are simply > discarded. > > I do not know if I am missing something or if simply nobody cared so > far. In any case, I would appreciate any documentation on the current > implementation as well as pointer to were it could be improved. > > Cheers, > Johannes > > > P.S. > I have another problem with the way we currently discard the "nsw" > information for accesses ("gep inbounds" apparently only implies nuw). > I will probably start another thread for that one [after I read the > GEP handling in more detail]. > > > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Johannes Doerfert via llvm-dev
2016-Apr-10 23:47 UTC
[llvm-dev] ScalarEvolution "add nsw" question
Hey Sanjoy, Thanks for the quick repsonse. On 04/10, Sanjoy Das wrote:> [+CC Bjarke who wrote getNoWrapFlagsFromUB + related bits]Also thanks.> One fundamental reason why we cannot reason about NoWrap flags in SCEV > for arithmetic outside of loops is to avoid issues like this: > > if (cond) { > val[x +nsw y] = 42; > } else { > val[x + y] = 42; > } > > Now *both* the "x +nsw y" and "x + y" will get mapped to the same SCEV > expression (this is by design [0]), and therefore we cannot mark *the* > SCEV expression for "x + y" with NSW, otherwise we may incorrectly > simplify the "val[x + y] = 42" branch.OK. I might have to look at the IR then since I am interested in the particular instructions that make up the computation not the abstract "arithmetic".> (Btw, I'm sure you're aware of this, but "x +nsw y" by itself does not > guarantee no-wrap, it only does so if "x +nsw y" is used in a > side-effecting way.)I was not (in particular) but that makes sense. For my work the poison value will (almost) always cause a side-effect to have undefined behaviour so that should not be a problem.> getNoWrapFlagsFromUB() avoids the problem above by adding NSW > (resp. NUW) to operations on add recurrences (i.e. an add-rec + 2, > say) that are guaranteed to execute at least once per loop iteration. > Thus we are guaranteed that the *arithmetic operation* (not //that// > specific instruction, but the arithmetic itself) does not overflow on > any iteration and thus can be safely marked as non-wrapping, since if > it didn't the program is guaranteed to be UB.Mh, I have to think about this a bit... Is there any plan to use e.g., post-dominance information to propagate wrapping flags? If x +nsw y post-dominates the entry block [and is used in some side-effect instruction] the SCEV could be marked as non-wrapping, couldn't it? How do you determine if the operation will poison a side-effect instruction anyway?> [0]: IOW, we don't "key" on the no-wrap tag, we just key on the > arithmetic bits of the operation and mutate SCEV expression in-place > when we discover NUW / NSW. > > -- SanjoyCheers, Johannes> Johannes Doerfert via llvm-dev wrote: > >Hello, > > > >I was wondering under which circumstances ScalarEvolution will propagate > >the no wrap flags from binary operators. In particular I looked at > >non-loop carried code, e.g., as in the following function: > > > > int add(int x, int y) { return x + y; } > > > >for which clang uses an "add nsw" instruction but ScalarEvolution does > >not propagate this information. The -analyze output looks like this: > > > > Classifying expressions for: @add > > %add = add nsw i32 %x, %y > > --> (%x + %y) U: full-set S: full-set > > > >The piece of code that causes this (for me) unexpected result is located > >in the ScalarEvolution::getNoWrapFlagsFromUB(...) function and looks > >like this: > > > > if (InnermostContainingLoop == nullptr || > > InnermostContainingLoop->getHeader() != BinOp->getParent()) > > return SCEV::FlagAnyWrap; > > > >If the "InnermostContainingLoop" is a nullptr, thus if the binary > >operator is not contained in a loop, all overflow annotations are simply > >discarded. > > > >I do not know if I am missing something or if simply nobody cared so > >far. In any case, I would appreciate any documentation on the current > >implementation as well as pointer to were it could be improved. > > > >Cheers, > > Johannes > > > > > >P.S. > > I have another problem with the way we currently discard the "nsw" > > information for accesses ("gep inbounds" apparently only implies nuw). > > I will probably start another thread for that one [after I read the > > GEP handling in more detail]. > > > > > >_______________________________________________ > >LLVM Developers mailing list > >llvm-dev at lists.llvm.org > >http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev > > -- > You received this message because you are subscribed to the Google Groups "Polly Development" group. > To unsubscribe from this group and stop receiving emails from it, send an email to polly-dev+unsubscribe at googlegroups.com. > For more options, visit https://groups.google.com/d/optout.-- Johannes Doerfert Researcher / PhD Student Compiler Design Lab (Prof. Hack) Saarland University, Computer Science Building E1.3, Room 4.31 Tel. +49 (0)681 302-57521 : doerfert at cs.uni-saarland.de Fax. +49 (0)681 302-3065 : http://www.cdl.uni-saarland.de/people/doerfert -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 213 bytes Desc: Digital signature URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160411/5701d0c2/attachment.sig>
Possibly Parallel Threads
- ScalarEvolution "add nsw" question
- ScalarEvolution "add nsw" question
- [ScalarEvolution][SCEV] no-wrap flags dependent on order of getSCEV() calls
- [LLVMdev] SCEV getMulExpr() not propagating Wrap flags
- [ScalarEvolution][SCEV] no-wrap flags dependent on order of getSCEV() calls