Skip to content

[Mem2Reg] Handled unreachables for single-block allocations. #39930

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

Conversation

nate-chandler
Copy link
Contributor

Previously, it was asserted that any single-block allocation which had valid memory after all instructions in the block were visited terminated in unreachable. That assertion was false--while all paths through that block must end in unreachable, the block itself need not be terminated with an unreachable inst. Here, that is corrected by walking forward from the block until blocks terminated by unreachables or blocks to which there are paths that do not go through the block containing the alloc_stack are reached. In the first case, the lifetime is ended just before the unreachable inst. In the second, the lifetime is ended just before the branch to such a successor block.

@nate-chandler
Copy link
Contributor Author

@swift-ci please test

@nate-chandler nate-chandler requested a review from atrick October 27, 2021 01:47
@nate-chandler nate-chandler force-pushed the lexical_lifetimes/mem2reg-end-single-block-lifetimes-with-valid-memory branch from 6459877 to eb8eb5e Compare October 27, 2021 04:17
@nate-chandler
Copy link
Contributor Author

@swift-ci please test

@nate-chandler
Copy link
Contributor Author

@swift-ci please clean test windows platform

Uses of an alloc_stack instruction in an unreachable block must also be
unreachable.  Don't waste time optimizing unreachable code.
Previously, it was asserted that any single-block allocation which had
valid memory after all instructions in the block were visited terminated
in unreachable.  That assertion was false--while all paths through that
block must end in unreachable, the block itself need not be terminated
with an unreachable inst.  Here, that is corrected by walking forward
from the block until blocks terminated by unreachables or blocks not
dominated by the block containing the alloc_stack are reached.  In the
first case, the lifetime is ended just before the unreachable inst.  In
the second, the lifetime is ended just before the branch to such a
successor block (i.e. just before the branch to a block which is not
dominated by the block containing the alloc_stack).
@nate-chandler nate-chandler force-pushed the lexical_lifetimes/mem2reg-end-single-block-lifetimes-with-valid-memory branch from eb8eb5e to 797eab1 Compare October 27, 2021 20:43
@nate-chandler
Copy link
Contributor Author

@swift-ci please test

runningVals->value);
// There is still valid storage after visiting all instructions in this
// block which are the only instructions involving this alloc_stack.
// This can only happen if all paths from this block end in unreachable.
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 give a SIL example here.

Copy link
Contributor

Choose a reason for hiding this comment

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

I talked with Nate. I am ok with this actually.

@nate-chandler nate-chandler merged commit 8e48fd6 into swiftlang:main Oct 28, 2021
@nate-chandler nate-chandler deleted the lexical_lifetimes/mem2reg-end-single-block-lifetimes-with-valid-memory branch October 28, 2021 22:20
Copy link
Contributor

@atrick atrick left a comment

Choose a reason for hiding this comment

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

@nate-chandler this fix looks great. I made a couple of low-priority requests.

continue;
}
bool endedLifetime = false;
for (auto *successor : block->getSuccessorBlocks()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This loop confuses me. A block with multiple successors must dominate all of them. You should be able to call something like getSingleSuccessor and only do the dominance check in that case, without any loop or confusing control flow based on a boolean flag.

To sanity check this, you can just assert that parentBlock dominates each block popped from the worklist immediately after popping it.

unreachable
}

// CHECK-LABEL: sil [ossa] @unreachable_6 : $@convention(thin) (@owned C) -> () {
Copy link
Contributor

Choose a reason for hiding this comment

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

None of these unit test are commented. Outside the context of this PR it wouldn't be obvious what's being tested. A single line like: "bailout on alloc_stack in unreachable block" helps. When updating dozens of SIL tests cases, it's not practical to look at the git log for all of them.

I know no one else comments tests, but I still think it's important.

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.

3 participants