Skip to content
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

Merged
merged 7 commits into from Nov 2, 2018

Conversation

bgogul
Copy link
Collaborator

@bgogul bgogul commented Nov 1, 2018

Consider the following example:

while ... {
  if ... {
     for(...) {...} // This should be nested into the while loop.
     break;
  }
}

In the SIL CFG, the statement in the if block including the for loop will not be part of the outer while loop. One of the steps during SESE canonicalization is to transform the CFG so that the statements in the if block become part of the while loop. This PR takes care of this case by doing the following:

  • Canonicalizing the for loop first.
  • Nesting the canonicalized for loop into the while 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).

@bgogul
Copy link
Collaborator Author

bgogul commented Nov 1, 2018

@swift-ci please test tensorflow

@bgogul bgogul changed the title [WIP] SESE: deal with the case where outer loops are moved into the current loop. SESE: deal with the case where outer loops are moved into the current loop. Nov 1, 2018
@bgogul bgogul requested review from mhong and lattner November 1, 2018 19:11
Copy link
Contributor

@mhong mhong left a 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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove (). same below

Copy link
Collaborator Author

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: {{.*}}
Copy link
Contributor

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.

Copy link
Collaborator Author

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
Copy link
Contributor

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.

Copy link
Collaborator Author

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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

document the return value

Copy link
Collaborator Author

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.
Copy link
Contributor

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.

Copy link
Collaborator Author

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());
Copy link
Contributor

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?

Copy link
Collaborator Author

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
Copy link
Contributor

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?

Copy link
Collaborator Author

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.

@bgogul
Copy link
Collaborator Author

bgogul commented Nov 2, 2018

@swift-ci please test tensorflow

@bgogul
Copy link
Collaborator Author

bgogul commented Nov 2, 2018

Thanks for the review, Ming. Merging it now.

@bgogul bgogul merged commit 61ed067 into apple:tensorflow Nov 2, 2018
@bgogul bgogul deleted the sese_move_outside_loops branch November 2, 2018 23:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants