-
Notifications
You must be signed in to change notification settings - Fork 796
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
Improved pattern compilation #11993
Merged
Merged
Improved pattern compilation #11993
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
Happypig375
suggested changes
Aug 22, 2021
dsyme
changed the title
Experiment: improved pattern analysis and codegen for problematic disjunctive/active patterns
[WIP] improved pattern analysis and codegen for type tests and problematic disjunctive/active patterns
Mar 3, 2022
dsyme
changed the title
[WIP] improved pattern analysis and codegen for type tests and problematic disjunctive/active patterns
Improved pattern compilation
Mar 3, 2022
This is ready for review @vzarytovskii @KevinRansom @TIHan |
vzarytovskii
approved these changes
Mar 4, 2022
KevinRansom
approved these changes
Mar 8, 2022
pirrmann
pushed a commit
to pirrmann/fsharp
that referenced
this pull request
Mar 22, 2022
* update * fix test case * column-based type tests * column-based type tests * update test * improved type matching analysis * improve diagnostics * fix codegen * fix baselines * fix baselines * update baselines and improve isinst codegen * missing file * update baselines Co-authored-by: Don Syme <donsyme@fastmail.com>
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.
This contains two related improvements to how we approach pattern-match compilation
Improved pattern match compilation for type tests and null tests
Using multiple "columns" of type tests and null tests was generating exponential amounts of code, e.g. see #12687
This is fixed by moving to a "column" of type tests and doing the work to properly determine when the success/failure of earlier elements of the column inform us about later patterns. For example:
Here the success of
:? string
tells us that all the other (sealed) type tests will fail. Likewise consider this:Here the failure of
:? A
tells us that:? B
will fail. Similar information can be deduced from null tests and type tests on interfaces.This removes a cause of exponential code generation, and for examples like #12687 the code goes down from, say 17MB of IL in one method to 3K - you can make this as dramatic as you like by adding extra clauses.
This also has the benefit that many new cases of "rule never matched" are detected.
There is also an improvement with generating more "fast" type tests that use the
isinst
instruction rather than a helper. Also the IL code sequenceisinst; ldnull; cgt.un; brtrue/brfalse
is improved toisinst; brtrue/brfalse
Improved pattern match compilation with
when
While looking at #11981 I went back and reconsidered out approach for "problematic pattern matching clauses" that can lead to substantial code generation. For example, consider code like this:
Previously, we were doing these clauses "one by one", because the presence of the "when" pattern led us to consider the clause set "potentially-problematic", and so the complexity of pattern matching was reduced by doing it clause-by-clause. This means we fetched and tested the tag again and again, instead of doing it in a switch. This PR uses a new way of detecting potentially-problematic clauses.
After this PR, the clauses above are considered "all together" and a
switch
is now emitted. This is because the first thing tested in pattern matching is the Tag ofU
, that is, we use aswitch
to test down the "column" A1/A2/A3/A4, all of which correspond to the same "investigation". After this investigation, the pattern logic reduces to a set of conditionals (for thewhen
clauses) and, crucially, the failure branch of awhen
clause just proceeds on to th nextwhen
clause (and the success branch goes to the necessary target). That is, the pattern logic is linear and without duplication or problematic expansion.The IL optimized code size for the above example reduces from 181 to 173. Is that important? Not in itself. Does this help performance? I'm not certain. It feels better, the code looks improved.
This comes with a gain - we now have improved detection of unused patterns! This can give rise to additional warnings (which may mean it needs a
--langversion
switch?). For example,Previously this didn't give an "unused match" warning. Now it does. This is because the presence of the initial
when
clauses don't disable unused clause warning errors.There were about 4 places in our codebase where this detected unused pattern match clauses. Two of these were in the TypeProvider SDK.
Specification of pattern clause grouping
A note from the code is copied below.