This is an archive of the discontinued LLVM Phabricator instance.

Fix bug 22641
ClosedPublic

Authored by sanjoy on Feb 21 2015, 12:00 AM.

Details

Summary

Fix bug 22641 by partially reinstating the original change for D7331.

Point to note: 22641 is _not_ caused by SCEV "forgetting" control flow. PreAR is marked as nuw by SCEV itself when it sees that Start + BECount * Step won't overflow for PreAR (since BECount is 0).

Diff Detail

Repository
rL LLVM

Event Timeline

sanjoy updated this revision to Diff 20458.Feb 21 2015, 12:00 AM
sanjoy retitled this revision from to Fix bug 22641.
sanjoy updated this object.
sanjoy edited the test plan for this revision. (Show Details)
sanjoy added reviewers: atrick, hfinkel, spatel.
sanjoy added a subscriber: Unknown Object (MLST).
atrick accepted this revision.Feb 23 2015, 11:44 AM
atrick edited edge metadata.

Wow! Thank you Sanjoy. This is an awesome catch and these test cases are invaluable.

I think the most obvious bug here is my implicit assumption that the step is positive. So we're looking at a post-increment recurrence and calling it PreAR. Maybe we should have a comment about that?

That said, I think your proposed check makes sense:
!isa<SCEVCouldNotCompute>(BECount) && SE->isKnownPositive(BECount)

I like that better than checking the ExitingBlock. Sorry if you proposed that earlier and I directed you down the wrong path. At least we got a great test case out of it.

This revision is now accepted and ready to land.Feb 23 2015, 11:44 AM

I think the most obvious bug here is my implicit assumption that the step is positive. So we're looking at a post-increment recurrence and calling it PreAR. Maybe we should have a comment about that?

I'm not sure if I understand you -- what does the sign (or
non-zeroness) of step have to do with this transform? From
AR={S+X,+,X} we constructed PreAR={S,+,X} so isn't PreAR the
pre-increment recurrence for AR irrespective of the sign of X?

  • Sanjoy

You're right. The direction of the Step shouldn't matter. That was my code's original intention, and it looks like that's valid.

I asked that question because I thought the test case was failed when postinc recurrence was marked NUW but the preinc recurrence was not. Now I can see that *any* recurrence on this loop will be NUW. That may make sense in theory, but could cause some real practical problems within SCEV. It looks like you already caught one in SCEVExpander.

My main takeaway from this is that the recurrence's wrapping flags are a property of the pre-incremented value within the loop. So that IV increment may actually wrap on the last iteration. I've been making the assumption that the post-incremented value would be tested on the last iteration and was guaranteed not to wrap. That's slightly shady because the value might not actually be used (and isn't even "consumed" by a phi), but it seemed to be the expectation based on other code I'd seen.

Do you have a better explanation?

I asked that question because I thought the test case was failed when postinc recurrence was marked NUW but the preinc recurrence was not. Now I can see that *any* recurrence on this loop will be NUW. That may make sense in theory, but could cause some real practical problems within SCEV. It looks like you already caught one in SCEVExpander.

(fwiw, I had this exact same discussion with Philip a few hours ago).

This is very similar to the discussion we had w.r.t. the <nw> flag.
Given that the algebraic condition that decides if a recurrence is
<nw> is satisfied by BECount == 0, all recurrences in a loop that
never takes a backedge are trivially <nw>. The same is true for <nuw>
and <nsw>, as far as I can tell.

My main takeaway from this is that the recurrence's wrapping flags are a property of the pre-incremented value within the loop. So that IV increment may actually wrap on the last iteration. I've been making the assumption that the post-incremented value would be tested on the last iteration and was guaranteed not to wrap. That's slightly shady because the value might not actually be used (and isn't even "consumed" by a phi), but it seemed to be the expectation based on other code I'd seen.

I agree; that is my mental model also -- the "next" value of a SCEV is
computed as loop takes the backedge, and that is when all the nuw,
nsw, nw flags apply. In this sense, add recs have a very structured
form of control dependence.

Unless we allow this, we won't be able to mark add recs as nuw/nsw/nw
for loops with variable trip count. I also don't think this is very
problematic (though a little subtle, I'll have to admit) -- we just
have be very explicit that the no-wrap flags on a add rec are valid
for that scev only; and do not apply to the pre-inc or post-inc
version of that scev. So sext({S,+,X}<nsw>) is still {sext S,+,sext
X} and {S,+,1}<nsw> is still always sge 1. {S,+,X}+X == {S+X,+,X} is
a totally different scev and the no-wrap behavior of the former does
not apply to the latter.

Does this sound sensible?

I'll check in a change that adds some more elaborate comments
detailing whatever we decide once we've reached a fixed point.

  • Sanjoy

Do you have a better explanation?

http://reviews.llvm.org/D7808

EMAIL PREFERENCES

http://reviews.llvm.org/settings/panel/emailpreferences/
This revision was automatically updated to reflect the committed changes.