Cranelift: fix fuzzbug in critical-edge splitting. - #4044
Merged
Conversation
Member
|
Ah I'm not really all that certain what this is doing, so I'll leave review to @fitzgen |
fitzgen
reviewed
Apr 18, 2022
cfallin
force-pushed
the
fix-empty-brtable-fuzzbug
branch
from
April 18, 2022 17:17
670ab10 to
4a04d66
Compare
Member
Author
|
Thanks! Updated, hopefully the comment is more clear now. |
regalloc2 is a bit pickier about critical edges than regalloc.rs was, because of how it inserts moves. In particular, if a branch has any arguments (e.g., a conditional branch or br_table), its successors must all have only one predecessor, so we can do edge moves at the top of successor blocks rather than at the end of this block. Otherwise, moves that semantically must come after the block's last uses (the branch's args) would be placed before it. This is almost always the case, because crit-edge splitting ensures that if we have more than one succ, all our succs will have only one pred. This is because branch kinds that take arguments (fixed args, not the blockparam args) tend to have more than one successor: conditionals and br_tables. However, a fuzzbug recently illuminated one corner case I had missed: a br_table can have *one* successor only, if it has a default target and an empty table. In this case, crit-edge splitting will happily skip a split and assume that we can insert edge moves at the end of the block with the br_table. But this will fail. regalloc2 explicitly checks this and bails with a panic, rather than continue, so no miscompilation is possible; but without this fix, we will get these panics on br_tables with empty tables.
cfallin
force-pushed
the
fix-empty-brtable-fuzzbug
branch
from
April 18, 2022 17:18
4a04d66 to
0e28ff2
Compare
fitzgen
approved these changes
Apr 18, 2022
fitzgen
left a comment
Member
There was a problem hiding this comment.
Okay, this makes sense now. Thanks for updating the comment!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
regalloc2 is a bit pickier about critical edges than regalloc.rs was,
because of how it inserts moves. In particular, if a branch has any
arguments (e.g., a conditional branch or br_table), its successors must
all have only one predecessor, so we can do edge moves at the top of
successor blocks rather than at the end of this block. Otherwise, moves
that semantically must come after the block's last uses (the branch's
args) would be placed before it.
This is almost always the case, because crit-edge splitting ensures that
if we have more than one succ, all our succs will have only one pred.
This is because branch kinds that take arguments (fixed args, not the
blockparam args) tend to have more than one successor: conditionals and
br_tables.
However, a fuzzbug recently illuminated one corner case I had missed: a
br_table can have one successor only, if it has a default target and
an empty table. In this case, crit-edge splitting will happily skip a
split and assume that we can insert edge moves at the end of the block
with the br_table. But this will fail.
regalloc2 explicitly checks this and bails with a panic, rather than
continue, so no miscompilation is possible; but without this fix, we
will get these panics on br_tables with empty tables.