-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Alt optimizations #1897
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
Comments
I'd like to work on this, but if someone else gets there first, feel free to steal it :-) |
I'm not very enthusiastic about most of these. I'll give my reasons point-by-point below:
Dense enums tend to start at zero (or is it one?), so I don't think this'll help in a lot of cases.
Unless there's a ton of cases, the overhead of hashing will be more than the cost of just running down the list of cases.
Nested pattern matches are reduced to a nested set of direct tag matches by a simple algorithm.
We should first check whether LLVM doesn't already manage this. I believe we use Phi nodes in a way that would make this possible (given enough cleverness on LLVM's side).
Would need an (invasive) LLVM patch to do this. Probably not worth it.
This is what an LLVM switch instruction will do, I believe. We're already using those. |
The only one I'm enthusiastic about is string comparisons, but I think the most efficient way to do that is to basically encode a trie. For example:
Could become:
But I think there's far more low-hanging optimization fruit... |
Agreed, O(N) with small constant factors and small N does, in practice, often beat O(lg(N)) or O(1) with more substantial constant factors. Switches are usually small N, integer and string compare are the lowest-overhead operations known, and when N is large users often have their own cleverness in mind anyways. Just stick with the simple thing for now. The backend authors have already got the table-switching logic done, and they employ it when there's reason to believe it's a win. If we start seeing real world code that has this sort of thing hot in real profiles, then investigate. I'll bet it never comes up. |
I'm closing this since there seems to be consensus that LLVM is better suited to do these optimizations than our middle-end is. Feel free to open a new, more specific issue if necessary. |
Add lints `drop_non_drop` and `forget_non_drop` fixes rust-lang#1897 changelog: Add lints `drop_non_drop` and `forget_non_drop`
Let's take advantage of enum types and alt-expressions to optimize code that uses
alt
. Some of these optimizations might require teaching LLVM about the restrictions on enums, or doing the work ourselves in trans_alt.Algorithm selection
Based on the cases, pick a map structure:
i = (x - smallest)
i = perfecthash(x)
i
in a hash tableBased on the branches, pick an output type:
i
as an index into an array of valuesi * block_length
i
as an index into an array of jump offsetsIn this example, the cases are a dense enum and the branches are values:
So it can use an array of values, with no branching (even for a bounds check):
This is something Mozilla programmers do in C++ all the time, manually, often messing it up.
Optimizations for if/elif/else compilation
Omit the last "else if" check when the alt is exhaustive, turning these into a simple "if":
Reorder cases in order to put a difficult case at the end (where it can be omitted):
Collapse adjacent cases into a single less-than check:
"Pass through" optimization
Compile as "pass through" if the arms all match the values. Useful when translating between two enum types.
The text was updated successfully, but these errors were encountered: