New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SESE: deal with the case where outer loops are moved into the current loop. #20222
Conversation
@swift-ci please test tensorflow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Congrats on completing the feature and bug fix work!
(There's still some clean-up work remaining, but pls feel free to resolve the bug first if you prefer.)
let maxCount: Int32 = 100 | ||
while i <= maxCount { | ||
sum += i | ||
if (i == breakIndex) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove ()
. same below
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
|
||
// CHECK-LABEL: --- XLA CFG Loops Before Canonicalize: {{.*}}testLoopMovementFromOutside{{.*}} | ||
// CHECK: Loop at depth 1 containing: {{.*}} | ||
// CHECK: Loop at depth 1 containing: {{.*}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a comment that this is the inner while loop above, but it's considered unnested from the outer while from loop info perspective.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -361,3 +361,88 @@ bb8: | |||
bb9(%18 : $Builtin.Int32): | |||
return %18 : $Builtin.Int32 | |||
} | |||
|
|||
// The following example is similar to loopThatRequiresNodeCloning, where the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
given the swift level test in the next file below, what is the value of having this SIL level test?
I feel it could take non-trivial work to read and maintain such tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is representing a case where we need to move an outside loop into the currently processed loop. However, the header of the outside loop is not dominated by the currently processed loop. In this case, we will have to clone the loop and make sure the LoopInfo is updated.
We want a very specific CFG to test this scenario. See the ASCII graph in the test file for the CFG. With a swift file, the generated CFG can change depending upon the version of the compiler. (Also, the compiler did generate a similar CFG for an example.)
assert(latch && "Canonicalization should have given us one latch block"); | ||
initialize(); | ||
public: | ||
static bool doIt(GraphFunctionDeviceInfo *deviceInfo, SILLoopInfo *LI, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
document the return value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
// } | ||
SmallPtrSet<SILBasicBlock *, 32> unrelatedPreheaders; | ||
for (auto *otherLoop : *LI) { | ||
// If loop and otherLoop are not nested into either, remember the preheader. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider moving this comment right above line 745, to describe the semantics of unrelatedPreheaders
.
Here the comment feels more "operational", and a more "declarative" comment on the semantics / spec of unrelatedPreheaders
could be more useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
// the entire loop now so that we can also incrementally update LoopInfo. | ||
if (succBlockLoop) { | ||
SILLoop *clonedLoop = | ||
cloner.cloneLoop(LI, succBlockLoop, succBlockLoop->getHeader()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
based on earlier discussion, should this API be renamed to sth like cloneOrUnroll?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done and updated the comment as well.
outsideBlockLoop->removeBlockFromLoop(outsideBlock); | ||
LI->changeLoopFor(outsideBlock, nullptr); | ||
if (outsideBlockLoop->contains(loop)) { | ||
// If our `loop` is nested within `outsideBlockLoop`. Move the node |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there test coverage on both this if branch, and the else below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we have coverage for both. The if
branch was handled even before this PR (and is covered by the example with labeled breaks).
The else branch is the new behavior and the tests in this PR provide coverage.
ab5fee2
to
3fb0e2e
Compare
@swift-ci please test tensorflow |
Thanks for the review, Ming. Merging it now. |
Consider the following example:
In the SIL CFG, the statement in the
if
block including thefor
loop will not be part of the outerwhile
loop. One of the steps during SESE canonicalization is to transform the CFG so that the statements in theif
block become part of thewhile
loop. This PR takes care of this case by doing the following:for
loop first.for
loop into thewhile
loop and updating LoopInfo as needed.This also takes care of the case with loops analogous to the situation handled in #19570 (See the example added to sese_loop_canonicalization.sil in this PR.)
This is the final PR for https://bugs.swift.org/browse/SR-7765 (modulo unknown bugs).