-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Constructing an iterator from a slice or Vec doesn't optimise completely #11751
Comments
Implementing #9546 would fix this. |
This uses a vector iterator to avoid the necessity for unsafe indexing, and makes this function slightly faster. Unfortunately rust-lang#11751 means that the iterator comes with repeated `null` checks which means the pure-ASCII case still has room for significant improvement (and the other cases too, but it's most significant for just ASCII). Before: is_utf8_100_ascii ... bench: 143 ns/iter (+/- 6) is_utf8_100_multibyte ... bench: 134 ns/iter (+/- 4) After: is_utf8_100_ascii ... bench: 123 ns/iter (+/- 4) is_utf8_100_multibyte ... bench: 115 ns/iter (+/- 5)
In theory, LLVM should be able to determine that this null check is unnecessary without additional metadata. There are two separate changes to LLVM's optimizer that are required:
Correctly implementing the rule for poison values in LazyValueInfo would be quite difficult, because it requires reasoning about control-dependence with respect to poison values. Also, the cost of making LazyValueInfo optimistic might be too high in compile time to get the patch landed. In #9546 there is a proposal to add metadata on LLVM instructions that indicates that the instruction produces a nonnull value. There are two reasons why this proposal would be a bit more difficult than it seems at first:
Another option would be to write a pass that looks for chains of |
Sounds like the last option is the easiest. I also like the fact that it's a separate pass, meaning that if we have trouble getting it upstream we can maintain it in our branch for a while. |
I wrote the optimization pass I described. It is able to optimize the first case (with |
Unfortunately, my pass causes the compiled |
I found the issue and put a first cut of my pass up as rust-lang/llvm#13. |
\o/
|
The pass that was landed handles the
|
Actually, that second point applies to the IR generated by |
I have local changes that fix those two items. In order to make this apply to |
Those changes are up as rust-lang/llvm#14. I'll need to add less conservative control dependence checking, and then it should be able to handle arbitrary chaining of zipped iterators. |
…p1995 Add `lint_groups_priority` lint Warns when a lint group in Cargo.toml's `[lints]` section shares the same priority as a lint. This is in the cargo section but is categorised as `correctness` so it's on by default, it doesn't call `cargo metadata` though and parses the `Cargo.toml` directly The lint should be temporary until rust-lang/cargo#12918 is resolved, but in the meanwhile this is an common issue to run into - rust-lang#11237 - rust-lang#11751 - rust-lang#11830 changelog: Add [`lint_groups_priority`] lint r? `@flip1995`
Compiled with
-O --lib --emit-llvm -S
gives the following. The only major difference between&[]
/Vec
and~[]
are two lines markedTHIS CHECK
, which, we think, is because when constructing an iterator from~[]
we do a pointer offset and dereference, so LLVM knows the pointers are non-null (in the slice/Vec
case, thematch it.next() { None => ... }
part of the for loop isn't removed).The text was updated successfully, but these errors were encountered: