-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
Missed optimization to elide bounds check #73827
Comments
It seems that the bounds check does get elided if I split up the if expression. pub fn get(board: &[u8; 8], x: usize, y: usize) -> u8 {
if x > 7 {
0
} else if y > 7 {
0
} else {
board[y]
}
} This generates playground::get:
orq %rdx, %rsi
cmpq $7, %rsi
jbe .LBB0_2
xorl %eax, %eax
retq
.LBB0_2:
movb (%rdi,%rdx), %al
retq |
And it seems it needs two unlikely to produce the right happy path: pub fn get4(array: &[u8; 8], x: usize, y: usize) -> u8 {
if unlikely(x > 7) {
0
} else if unlikely(y > 7) {
0
} else {
array[y]
}
} get4:
or rsi, rdx
cmp rsi, 7
ja .LBB1_1
mov al, byte ptr [rdi + rdx]
ret
.LBB1_1:
xor eax, eax
ret |
The assume intrinsic also seems to not work if a logical expression is used, maybe it's related? I.e. |
Godbolt: https://rust.godbolt.org/z/xYEszA The problem is that the condition is converted to |
InstCombine may convert conditions like (x < C) && (y < C) into (x | y) < C (for some C). This patch teaches LVI to recognize that in this case, it can infer either x < C or y < C along the edge. This fixes the issue reported at rust-lang/rust#73827. Differential Revision: https://reviews.llvm.org/D82715
Fix has landed upstream, we'll pull it in with the LLVM 11 upgrade. |
InstCombine may convert conditions like (x < C) && (y < C) into (x | y) < C (for some C). This patch teaches LVI to recognize that in this case, it can infer either x < C or y < C along the edge. This fixes the issue reported at rust-lang/rust#73827. Differential Revision: https://reviews.llvm.org/D82715
InstCombine may convert conditions like (x < C) && (y < C) into (x | y) < C (for some C). This patch teaches LVI to recognize that in this case, it can infer either x < C or y < C along the edge. This fixes the issue reported at rust-lang/rust#73827. Differential Revision: https://reviews.llvm.org/D82715
This if fixed in 1.47 with the LLVM 11 upgrade. It's probably worthwhile to add a codegen test, as bounds check optimization tends to be a bit fragile. |
Great, thanks! I can handle the test |
Add codegen test for issue rust-lang#73827 Closes rust-lang#73827
…laumeGomez Rollup of 9 pull requests Successful merges: - rust-lang#78046 (Add codegen test for issue rust-lang#73827) - rust-lang#78061 (Optimize const value interning for ZST types) - rust-lang#78070 (we can test std and core panic macros together) - rust-lang#78076 (Move orphan module-name/mod.rs files into module-name.rs files) - rust-lang#78129 (Wrapping intrinsics doc links update.) - rust-lang#78133 (Add some MIR-related regression tests) - rust-lang#78144 (Don't update `entries` in `TypedArena` if T does not need drop) - rust-lang#78145 (Drop unneeded `mut`) - rust-lang#78157 (Remove unused type from librustdoc) Failed merges: r? `@ghost`
InstCombine may convert conditions like (x < C) && (y < C) into (x | y) < C (for some C). This patch teaches LVI to recognize that in this case, it can infer either x < C or y < C along the edge. This fixes the issue reported at rust-lang/rust#73827. Differential Revision: https://reviews.llvm.org/D82715
Context: this bug was reduced from indexing into a nested array, but this shows the same problem.
(Playground link)
Rust doesn't elide the bounds check on
array[y]
, even though it's impossible fory
to be out of range due to the if condition. Rust does elide the bounds check when the if condition is justif y > 7
, however.Here is the generated ASM for the above code:
and here is the generated ASM when we change the if to just be
if y > 7
Meta
This occurs in both the latest versions of stable (1.44.1) and nightly (1.46.0-nightly (2020-06-26 7750c3d))
The text was updated successfully, but these errors were encountered: