[LLVMdev] confusion w.r.t. scalar evolution and nuw

David Majnemer david.majnemer at gmail.com
Wed Jan 14 20:52:06 PST 2015


Seems like it's a bug.

We are permitted to turn 'sub nsw i32 %x, 1' into 'add nsw i32 %x, -1'

We are *not* permitted to turn 'sub nuw i32 %x, 1' into 'add nuw i32 %x, -1'

I don't think we are permitted to keep the nuw in your example.  We would
need something like SCEVSubRecExpr to be able to notionally represent that.



On Wed, Jan 14, 2015 at 8:05 PM, Sanjoy Das <sanjoy at playingwithpointers.com>
wrote:

> I've been doing some digging in this area (scev, wrapping arithmetic),
> learning as much as I can, and have reached a point where I'm fairly
> confused about the semantics of nuw in scalar evolution expressions.
> Consider the following program:
>
> define void @foo(i32 %begin) {
>  entry:
>   br label %loop
>
>  loop:
>   %idx = phi i32 [ %begin, %entry ], [ %idx.dec, %loop ]
>   %idx.dec = sub nuw i32 %idx, 1
>   %exit.condition = icmp eq i32 %idx.dec, 0
>   br i1 %exit.condition, label %loop.exit, label %loop
>
>  loop.exit:
>   ret void
> }
>
> As long as %begin is positive, %idx.dec is not poison and the function
> has defined behavior.
>
> When I run opt -analyze -scalar-evolution on the IR, I get
>
> Printing analysis 'Scalar Evolution Analysis' for function 'foo':
> Classifying expressions for: @foo
>   %idx = phi i32 [ %begin, %entry ], [ %idx.dec, %loop ]
>   -->  {%begin,+,-1}<nuw><%loop>                Exits: 1
>   %idx.dec = sub nuw i32 %idx, 1
>   -->  {(-1 + %begin),+,-1}<nuw><%loop>         Exits: 0
> Determining loop execution counts for: @foo
> Loop %loop: backedge-taken count is (-1 + %begin)
> Loop %loop: max backedge-taken count is -1
>
> SCEV has mapped `%idx.dec' to `{(-1 + %begin),+,-1}<nuw>'!  This means
> SCEV thinks `%idx.dec' will be poison in the very first iteration if
> %begin is ult 1.
>
> As an example on how this could blow up, if %begin was constant
> (or LLVM was got smarter about ranges someday and learned to handle
> non-constant ranges) in ScalarEvolution::getUnsignedRange, the
> following code could fire:
>
>   if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S)) {
>     // If there's no unsigned wrap, the value will never be less than its
>     // initial value.
>     if (AddRec->getNoWrapFlags(SCEV::FlagNUW))
>       if (const SCEVConstant *C =
> dyn_cast<SCEVConstant>(AddRec->getStart()))
>         if (!C->getValue()->isZero())
>           ConservativeResult =
>             ConservativeResult.intersectWith(
>               ConstantRange(C->getValue()->getValue(), APInt(BitWidth,
> 0)));
>
> and conclude that %idx.dec is always UGE %begin.  This is a real bug
> waiting to happen.
>
> As far as I can tell, in the presence of no-wrap flags, 'sub X Y' is
> not the same as 'add X -Y', and subtractions can be expressed as
> additions only if they don't have any no-wrap flags on them.  While
> I have not thought about nsw in depth, but it is possible there are
> similar issues with nsw as well.
>
> Is my reasoning broken at some point?  What gives?
>
> -- Sanjoy
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150114/408370e8/attachment.html>


More information about the llvm-dev mailing list