-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Rust doesn't unroll a loop with constant data #38694
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
Oh, and FWIW, analogous C code with Clang does constant-evaluate in all cases. |
Interestingly if I take g2 and build without -O and then pass the result to llvm-opt -O2 I get
Instead of
I don't know what causes this difference. I'm actually surprised the calls to __rust_allocate are being eliminated as it seems like OOM could still happen. |
What was the C code that you were using? |
@jrmuizel Something like this seems to be the closest to what Rust is supposed to do in |
Hmm this is getting even weirder. I played a bit more with constant slices (not vector) versions of functions here: https://godbolt.org/g/FzynPE As you can see, I've added pub fn f3() -> bool {
let v = [1,2,3];
v.iter().any(|&x| x == 2)
}
pub fn f4() -> bool {
[1,2,3].iter().any(|&x| x == 2)
} And first one is not optimized to a constant, but second one is... Not sure if it's a different issue or sheds a light on what's happening in vector one too. |
Is this simply the following? “LLVM cannot unroll loops with multiple exits“ https://llvm.org/bugs/show_bug.cgi?id=27360 I've looked at in context of #37972 which aimed to unroll some searching loops manually for this reason. |
@bluss Might be related, but how come Clang constant-evaluates a very similar implementation of |
Also, doesn't explain that last |
Re-testing with Rust 1.26 shows the original example to have been resolved. pub fn g0() -> bool {
vec![1,2,3].contains(&2)
} results in example::g0:
push rbp
mov rbp, rsp
mov al, 1
pop rbp
ret |
@Emerentius Indeed, I suppose I can close this one. |
I was playing with http://rust.godbolt.org/ and noticed one weird thing where Rust (all of stable, beta and nightly versions) seems to prevent loop unroll and/or constant propagation optimizations.
Here is original minimal code using which I can reproduce an issue:
So it basically creates a vector out of constant values with constant length & capacity, and then searches for a constant value within it, which is a perfect case for constant propagation. And yet the generated assembly looks like:
I tried writing down a plain "dumb" loop instead, with an
assert
+ static loop bounds:But output assembly is almost 100% the same (even though
assert
was successfully removed by DCE, so apparently constant propagation works as expected).However, unrolling this same loop by hand at the next step seems to suddenly enable optimization:
compiles to
as originally expected.
Initially I though this is a missing attribute on Rust allocation functions that doesn't allow LLVM to reason about pointer contents, but after playing with replacing allocator with system one, replacing vectors with pure static-length slices (
[i32; 3]
) and finally unrolling loop by hand as above, figured it's not an issue, otherwise 1) slices would be still optimized or 2) unrolled loop would still be not.I would be happy to help to fix whatever is preventing those optimizations, but so far I don't really understand what's happening here or where to look for the potential bug.
Online playground URL with all these examples (plus slices): https://godbolt.org/g/TRQgg8
The text was updated successfully, but these errors were encountered: