-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Simplify and compact switch ZIR, and resolve union payload captures with PTR #15880
Merged
Conversation
This file contains 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
mlugg
force-pushed
the
feat/better-switch-zir-2
branch
3 times, most recently
from
May 30, 2023 06:14
ad0c2ef
to
b6f22fc
Compare
By indexing from the very first switch case rather than into scalar and multi cases separately, the instructions for capturing in multi cases become unnecessary, freeing up 2 ZIR tags.
This is in preparation for ziglang#2473. Also fixes a bug where switching on bools allows invalid case combinations.
These tags are unnecessary, as this information can be more efficiently encoded within the switch_block instruction itself. We also use a neat little trick to avoid needing a dummy instruction (like is used for errdefer captures): since the switch_block itself cannot otherwise be referenced within a prong, we can repurpose its index within prongs to refer to the captured value.
This is a follow-up to a previous commit which eliminated switch_capture and switch_capture_ref. All captures are now handled directly by `switch_block`, which has also eliminated some unnecessary Block data in Sema.
This finishes the process of consolidating switch expressions in ZIR into as simple and compact a representation as is possible. There are now just two ZIR tags dedicated to switch expressions: switch_block and switch_block_ref, with the latter being for an operand passed by reference.
This is a bit harder than it seems at first glance. Actually resolving the type is the easy part: the interesting thing is actually getting the capture value. We split this into three cases: * If all payload types are the same (as is required in status quo), we can just do what we already do: get the first field value. * If all payloads are in-memory coercible to the resolved type, we still fetch the first field, but we also emit a `bitcast` to convert to the resolved type. * Otherwise, we need to handle each case separately. We emit a nested `switch_br` which, for each possible case, gets the corresponding union field, and coerces it to the resolved type. As an optimization, the inner switch's 'else' prong is used for any peer which is in-memory coercible to the target type, and the bitcast approach described above is used. Pointer captures have the additional constraint that all payload types must be in-memory coercible to the resolved type. Resolves: ziglang#2812
To do this, I expanded SwitchProngSrc a bit. Several of the tags there aren't actually used by any current errors, but they're there for consistency and if we ever need them. Also delete a now-redundant test and fix another.
mlugg
force-pushed
the
feat/better-switch-zir-2
branch
from
June 13, 2023 12:19
b6f22fc
to
42dc753
Compare
perf data point for self-hosted compiler (2% slower):
|
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.
While looking to implement #2473 (Coming Soon ™️), I found that the existing representation of switch expressions in ZIR was incompatible with that proposal. Further inspection led me to conclude that the existing representation in ZIR is unnecessarily large, and also uses far more tags than it needs to.
All but the last commit of this PR are dedicated to simplifying this ZIR. The 8 tags used in master for switch expressions have been reduced down to 2, and the size in memory of the ZIR for switch expressions is decreased across the board (stats below).
The new encoding has two instructions:
switch_block
andswitch_block_ref
, where the latter is for passing the operand by reference. Some bits in the trailing data are repurposed to provide information about captures. The main capture is referenced through the switch block instruction itself (since this otherwise can't be referenced inside a prong), and inline tag captures, if present, are referenced through a dummy instruction, like howerrdefer
captures work.The final commit of this PR implements #2812. See its commit message for a bit more information on the strategy there.
ZIR stats (prior to proposal implementation, which will not affect the ZIR):
test/behavior/inline_switch.zig
test/behavior/switch.zig
src/Sema.zig
src/value.zig