Skip to content

[SILOptimizer] Clean up infinite recursion diagnostic pass #19710

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

Merged

Conversation

harlanhaskins
Copy link
Contributor

NFC. This cleans up the pass to avoid the extra lambda and to clear up
the ordering of what check is supposed to come before what. It also
adds a little more documentation about what the pass is checking for.

NFC. This cleans up the pass to avoid the extra lambda and to clear up
the ordering of what check is supposed to come before what.
// If we found a recursive call, keep track of it. We can't just `return
// true` here because that would mark every recursive function infinitely
// recursive.
if (hasRecursiveCallInPath(*CurBlock, TargetFn, TargetModule)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

It also defeats the purpose of doing a depth first search!

SILFunction *TargetFn) {
/// Perform a DFS through the target function to find any paths to an exit node
/// that do not call into the target.
static bool hasInfinitelyRecursiveApply(SILFunction *TargetFn) {
Copy link
Contributor

Choose a reason for hiding this comment

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

N.B. I had the extra parameter here because I intended to extend this pass to compute mutually-recursive applies in the initializer thunks for lazy vars.

for (SILBasicBlock *Succ : CurBlock->getSuccessorBlocks())
foundRecursion |= analyzeSuccessor(Succ);
// Otherwise, push the successors onto the stack.
WorkList.append(CurBlock->succblock_begin(),
Copy link
Contributor

Choose a reason for hiding this comment

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

This is where one would do the visited check.

SmallVector<SILBasicBlock *, 16> WorkList;
// Keep track of whether we found at least one recursive path.
bool foundRecursion = false;
SmallVector<SILBasicBlock *, 16> WorkList = { TargetFn->getEntryBlock() };
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not do 32 instead of 16? Seems better for medium sized functions and you aren't going to have multiple invocations of this function so the stack usage isn't too crazy to me.

while (!WorkList.empty()) {
SILBasicBlock *CurBlock = WorkList.pop_back_val();
// Found a path to the exit node without a recursive call.
if (!Visited.insert(CurBlock).second)
Copy link
Contributor

Choose a reason for hiding this comment

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

It is more efficient to do the check when you know you are going to insert something into the worklist. So you would insert TargetFn->getEntryBlock() as visited and then below when you copy into the worklist, skip anyone that has already been visited.

// If we found a recursive call, keep track of it. We can't just `return
// true` here because that would mark every recursive function infinitely
// recursive.
if (hasRecursiveCallInPath(*CurBlock, TargetFn, TargetModule)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you change the comment here to make it clear that we are only interested in functions that are recursive along /all/ paths. I think that would get this across better.

@harlanhaskins
Copy link
Contributor Author

@swift-ci please smoke test

Copy link
Contributor

@gottesmm gottesmm left a comment

Choose a reason for hiding this comment

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

Thanks! LGTM!

@harlanhaskins harlanhaskins merged commit b08a3b7 into swiftlang:master Oct 4, 2018
@graydon
Copy link
Contributor

graydon commented Oct 8, 2018

This is causing failures. See rdar://45080912. Backing out.

@graydon
Copy link
Contributor

graydon commented Oct 8, 2018

Oops, sorry, not this one, the other one (#19724)

modelorganism pushed a commit to modelorganism/swift that referenced this pull request Oct 11, 2018
…#19710)

* [SILOptimizer] Clean up infinite recursion diagnostic pass

NFC. This cleans up the pass to avoid the extra lambda and to clear up
the ordering of what check is supposed to come before what.

* Address review comments
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.

4 participants