[PATCH] ScalarEvolution incorrectly assumes that the start of certain add recurrences don't overflow
Hal Finkel
hfinkel at anl.gov
Sat Feb 7 07:44:41 PST 2015
----- Original Message -----
> From: "Hal Finkel" <hfinkel at anl.gov>
> To: "Sanjoy Das" <sanjoy at playingwithpointers.com>
> Cc: "Commit Messages and Patches for LLVM" <llvm-commits at cs.uiuc.edu>,
> reviews+D7331+public+6ea524414f9332a6 at reviews.llvm.org
> Sent: Saturday, February 7, 2015 7:46:28 AM
> Subject: Re: [PATCH] ScalarEvolution incorrectly assumes that the start of certain add recurrences don't overflow
>
> ----- Original Message -----
> > From: "Sanjoy Das" <sanjoy at playingwithpointers.com>
> > To: reviews+D7331+public+6ea524414f9332a6 at reviews.llvm.org
> > Cc: "David Majnemer" <david.majnemer at gmail.com>, "Hal Finkel"
> > <hfinkel at anl.gov>, "Andrew Trick" <atrick at apple.com>,
> > "Commit Messages and Patches for LLVM" <llvm-commits at cs.uiuc.edu>
> > Sent: Saturday, February 7, 2015 3:20:23 AM
> > Subject: Re: [PATCH] ScalarEvolution incorrectly assumes that the
> > start of certain add recurrences don't overflow
> >
> > > 1. For now, let's stick with your strongest interpretation, and
> > > assume the local check is sufficient.
> > > 2. Add a loud WARNING comment explaining that the check is only
> > > correct if we assume the overflow cases of nsw are unreachable.
> >
> > I'd consider this approach somewhat risky -- the rest of LLVM is
> > allowed to do transforms that break this assumption (i.e. they
> > assume
> > arithmetic is not side-effecting). Consider a slightly modified
> > fragment of the test case with this patch (differences commented):
>
> I understand (and thanks for working through the example), however, I
> don't want to pre-suppose here the outcome of the poison semantics
> thread. If we adopt Philip's suggestion, for example, and split nsw
> into 'nsw undef' and 'nsw unreachable', then we'll be able to keep
> this logic in one of those cases. Since removing code is easier than
> adding it, I want to keep the check here for now, and add a warning
> documenting the assumption, and we can revisit it once we resolve
> the poison semantics debate (which will hopefully be soon).
Let me revise this slightly. If this can present as a miscompile using the standard optimization pipeline, then I feel we need to fix that. If it can't, then let's wait on the outcome of the poison semantics discussion.
-Hal
>
> -Hal
>
> >
> > define i64 @foo(i32 %start, i32 %low.limit, i32 %high.limit, i32*
> > %f)
> > {
> > entry:
> > %postinc.start = add i32 %start, 1
> > br label %loop
> >
> > loop:
> > %idx = phi i32 [ %start, %entry ], [ %idx.inc, %continue ]
> > %postinc = phi i32 [ %postinc.start, %entry ], [ %postinc.inc,
> > %continue ]
> > %postinc.inc = add nsw i32 %postinc, 1
> > %postinc.sext = sext i32 %postinc to i64
> > %break.early = icmp slt i32 %postinc, %low.limit
> > store volatile i32 %idx, i32* %f ;; something to hold %idx in
> > place
> > br i1 %break.early, label %continue, label %early.exit
> >
> > continue:
> > %idx.inc = add nsw i32 %idx, 1
> > br i1 %break.early, label %loop, label %exit ;; repeated use of
> > %break.early
> >
> > exit:
> > ret i64 0
> >
> > early.exit:
> > ret i64 %postinc.sext
> > }
> >
> > For the exact same situation / reason as in the test case,
> > SCEV(%postinc)->getStart() is not nsw.
> >
> > Now if I run this through 'opt -simplifycfg -loop-rotate' I get
> >
> > define i64 @foo(i32 %start, i32 %low.limit, i32 %high.limit, i32*
> > %f)
> > {
> > entry:
> > %postinc.start = add i32 %start, 1
> > br label %loop
> >
> > loop: ; preds = %loop,
> > %entry
> > %idx = phi i32 [ %start, %entry ], [ %idx.inc, %loop ]
> > %postinc = phi i32 [ %postinc.start, %entry ], [ %postinc.inc,
> > %loop ]
> > %postinc.inc = add nsw i32 %postinc, 1
> > %postinc.sext = sext i32 %postinc to i64
> > %break.early = icmp slt i32 %postinc, %low.limit
> > store volatile i32 %idx, i32* %f
> > %idx.inc = add nsw i32 %idx, 1
> > br i1 %break.early, label %loop, label %early.exit
> >
> > early.exit: ; preds = %loop
> > %postinc.sext.lcssa = phi i64 [ %postinc.sext, %loop ]
> > ret i64 %postinc.sext.lcssa
> > }
> >
> > `L->getExitingBlock() == L->getLoopLatch()` is true for the loop
> > and
> > we'll trigger the exact same bug even if we add that additional
> > constraint. This happens with the optimization removed (i.e. with
> > this present version of the change applied) so there is no circular
> > reasoning here.
> >
> > (Btw, I've assumed Andy really meant `L->getExitingBlock() ==
> > L->getLoopLatch()` and not `L->getExitBlock() == L->getLoopLatch()`
> > since AFAICT the latter is trivially false -- the exit block is
> > always
> > outside the loop while the latch is always inside).
> >
> > Actually, pretending that a phi consuming poison is unreachable is
> > also risky since I'd expect loop-rerolling to break that
> > assumption.
> > While this means there is no good answer at this time, pretending
> > that
> > a phi consuming poison is UB has the advantage that scev already
> > assumes this; and we won't be introducing more tricky corner cases.
> >
> > -- Sanjoy
> >
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
--
Hal Finkel
Assistant Computational Scientist
Leadership Computing Facility
Argonne National Laboratory
More information about the llvm-commits
mailing list