Skip to content

Conversation

@topolarity
Copy link
Member

We have a special exception in our IR that allows ::Union{} marked instructions to act as an unreachable terminator.

Without this fix, we were advancing into the subsequent block despite it not being a successor.

We have a special exception in our IR that allows `::Union{}` marked
instructions to act as an `unreachable` terminator.

Without this fix, we were advancing into the subsequent block despite it
not being a successor.
@topolarity topolarity requested a review from Keno April 23, 2024 13:46

Core.Compiler.verify_ir(ir)
ir = Core.Compiler.cfg_simplify!(ir)
@test length(ir.cfg.blocks) == 3 # should have removed block 3
Copy link
Member

Choose a reason for hiding this comment

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

Verify the IR here again?

On a general note I think we have a predicate is_terminator or something similar and I don't think it handles this correctly

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, it doesn't - It has the same problem compute_basic_blocks does, which is that it expects to be able to determine a terminator from the expression alone but since #49797 it depends on the type as well

Copy link
Member

Choose a reason for hiding this comment

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

I wonder if instead we should insert an unreachable terminator instead. Normalizing the IR more.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'd be in support of that, but I believe @Keno is trying to avoid making any insertions in irinterp

Copy link
Member

Choose a reason for hiding this comment

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

Terminator normalization is #41476, but @topolarity is right, I don't want to make irinterp structurally mutating (and thus statement-index invalidating) just for this.

@topolarity topolarity force-pushed the ct/cfg-simplify-unreachable branch 2 times, most recently from d00612b to 2d05d41 Compare April 23, 2024 14:07
@topolarity topolarity force-pushed the ct/cfg-simplify-unreachable branch from 2d05d41 to cab4f53 Compare April 23, 2024 16:53
ir = make_ircode(code; ssavaluetypes=Any[Union{}, Union{}, Any, Union{}])

# Unfortunately `compute_basic_blocks` does not notice the `throw()` so it gives us
# the wrong CFG. Instead manually construct the intended CFG:
Copy link
Member

Choose a reason for hiding this comment

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

I wouldn't say the CFG is wrong. It's valid to have extra unreachable bits at the end of the basic block.

Copy link
Member Author

Choose a reason for hiding this comment

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

Right, it's not an invalid CFG - It's just not the (more precise) one we need for this test.

I'll clarify in the comment

Copy link
Member Author

Choose a reason for hiding this comment

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

Suggested change
# the wrong CFG. Instead manually construct the intended CFG:
# a slightly imprecise CFG. Instead manually construct the CFG we need for this test:

Copy link
Member Author

Choose a reason for hiding this comment

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

Thinking on this again, unfortunately I think this CFG is wrong in general, for the same reasons we encountered in #53512. Since Enter/Exit nodes add structural conditions to the CFG, spurious fallthroughs are invalid in general.

I think we might be safe from hitting this in practice because we end up not having these implicit must-throw terminators in fresh code going into inference, but nonetheless we probably need to fix that...

@Keno Keno added the merge me PR is reviewed. Merge when all tests are passing label Apr 24, 2024
@topolarity topolarity merged commit 729a8c9 into JuliaLang:master Apr 25, 2024
@topolarity topolarity deleted the ct/cfg-simplify-unreachable branch April 25, 2024 01:42
@oscardssmith oscardssmith added bugfix This change fixes an existing bug compiler:optimizer Optimization passes (mostly in base/compiler/ssair/) and removed merge me PR is reviewed. Merge when all tests are passing labels Apr 25, 2024
topolarity added a commit to topolarity/julia that referenced this pull request Apr 26, 2024
The check added JuliaLang#54216 failed to consider the `Union{}` type that
typically appears on explicit terminators. This was causing this
loop to exit early for GotoIfNot nodes, which then led them to not
schedule their fallthrough successors successfully.
topolarity added a commit to topolarity/julia that referenced this pull request Apr 26, 2024
The check added in JuliaLang#54216 failed to consider that explicit terminators
also carry a `Union{}` type, not just ϕ-nodes and non-terminators.

This was causing GotoIfNot nodes to exit scheduling early and fail to
assign a contiguous index for their fallthrough successor.
Keno added a commit that referenced this pull request Apr 26, 2024
…inator

This addresses a bug in #54216, where a `GotoIfNot` was accidentally considered
a throwing terminator. Just as I was about to PR this, I noticed that #54260
had already been opened for the same issue. However, there's three differences
in this PR that made me open it anyway:

1. There's an additional missing case where the terminator is `nothing` which
   has special case semantics of allowing any type on it, because it serves as
   a deletion marker.

2. My test also test the `EnterNode` and `:leave` terminators, just to have a
   complete sampling.

3. I like the code flow in this version slightly better.

Co-authored-by: Cody Tapscott <cody.tapscott@juliahub.com>
Keno added a commit that referenced this pull request Apr 26, 2024
…inator

This addresses a bug in #54216, where a `GotoIfNot` was accidentally considered
a throwing terminator. Just as I was about to PR this, I noticed that #54260
had already been opened for the same issue. However, there's three differences
in this PR that made me open it anyway:

1. There's an additional missing case where the terminator is `nothing` which
   has special case semantics of allowing any type on it, because it serves as
   a deletion marker.

2. My test also test the `EnterNode` and `:leave` terminators, just to have a
   complete sampling.

3. I like the code flow in this version slightly better.

Co-authored-by: Cody Tapscott <cody.tapscott@juliahub.com>
Keno added a commit that referenced this pull request Apr 26, 2024
…inator

This addresses a bug in #54216, where a `GotoIfNot` was accidentally considered
a throwing terminator. Just as I was about to PR this, I noticed that #54260
had already been opened for the same issue. However, there's three differences
in this PR that made me open it anyway:

1. There's an additional missing case where the terminator is `nothing` which
   has special case semantics of allowing any type on it, because it serves as
   a deletion marker.

2. My test also test the `EnterNode` and `:leave` terminators, just to have a
   complete sampling.

3. I like the code flow in this version slightly better.

Co-authored-by: Cody Tapscott <cody.tapscott@juliahub.com>
Keno added a commit that referenced this pull request Apr 26, 2024
…inator (#54262)

This addresses a bug in #54216, where a `GotoIfNot` was accidentally
considered a throwing terminator. Just as I was about to PR this, I
noticed that #54260 had already been opened for the same issue. However,
there's three differences in this PR that made me open it anyway:

1. There's an additional missing case where the terminator is `nothing`
which has special case semantics of allowing any type on it, because it
serves as a deletion marker.

2. My test also test the `EnterNode` and `:leave` terminators, just to
have a complete sampling.

3. I like the code flow in this version slightly better.

Co-authored-by: Cody Tapscott <cody.tapscott@juliahub.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix This change fixes an existing bug compiler:optimizer Optimization passes (mostly in base/compiler/ssair/)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants