[PATCH] D126546: [InstCombine] decomposeSimpleLinearExpr should bail out on negative operands.
wael yehia via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 6 06:11:25 PDT 2022
w2yehia added a subscriber: sfertile.
w2yehia added inline comments.
================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp:40
OverflowingBinaryOperator *OBI = dyn_cast<OverflowingBinaryOperator>(Val);
if (OBI && !OBI->hasNoUnsignedWrap() && !OBI->hasNoSignedWrap()) {
Scale = 1;
----------------
w2yehia wrote:
> nikic wrote:
> > w2yehia wrote:
> > > nikic wrote:
> > > > Isn't the actual bug here? The `&& !OBI->hasNoSignedWrap()` shouldn't be there. The number of elements is an unsigned value, so we should be checking for no unsigned wrap, not "either no unsigned or no signed wrap".
> > > i'm not that familiar with the implications of (not) having `nsw`, so you are likely correct.
> > > Does the presence of `nsw` indicate the operands of the multiplication are signed?
> > nsw indicates that there is no signed overflow, while we need no unsigned overflow here.
> Thanks for reviewing. I had to read up more about nsw/nuw and signedness in llvm in general.
> I couldn't conclude that the presence of `nuw` indicates that the operands of the mul can be safely interpreted as unsigned.
> I might be asking the wrong question, so can you please tell me why checking for `nuw` is necessary and sufficient in order to make the code (in decomposeSimpleLinearExpr and PromoteCastOfAllocation) to be sound?
@nikic I will implement your suggestion. I had to convince myself (and get educated on these flags)
After brainstorming with @sfertile about the implications of the nuw/nsw flags, we concluded that doing only the `&& !OBI->hasNoSignedWrap()` is not a sufficient condition to safely interpret `Scale` (2nd) operand of the `mul` as unsigned in isolation.
Consider this pseudo-llvm where the `-4` is intended to be signed:
```
if ( %X == 1 || %X == 0) {
%0 = mul nuw i32 %X, -4 // 1 * 4294967292 = 4294967292 (no unsigned wrap)
..
```
However, because this exit condition applies to all visited instructions (add, mul, shl), having the `nuw` means you cannot having something like `24 - 4` because it unsigned overflows. So if we expand the above example:
```
if ( %X == 1 || %X == 0) {
%0 = mul nuw i32 %X, -4 // 1 * 4294967292 = 4294967292 (no unsigned wrap)
%1 = add nuw i32 %0, C // 4294967292 + C
alloca i8, %1
```
The addition `4294967292 + C` must overflow in order to produce a positive signed number. If it does not overflow then the user-intended result is simply a large unsigned number and storing it in an unsigned is fine.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D126546/new/
https://reviews.llvm.org/D126546
More information about the llvm-commits
mailing list