Skip to content
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

Rust is unable to figure out that if inside the nested loop is executed at most once per outer loop iteration #65969

Open
95th opened this issue Oct 30, 2019 · 2 comments
Labels
I-slow Issue: Problems and improvements with respect to performance of generated code. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@95th
Copy link
Contributor

95th commented Oct 30, 2019

Rust unable to figure out that if inside the nested loop is executed at most once per outer loop iteration.

https://users.rust-lang.org/t/how-to-make-compiler-automatically-elide-bound-checks/34148/6

pub fn foo() -> usize {
    let mut index = 0;
    for i in 0..100 {
        assert!(index <= i);  // This generates a panic jmp
        for j in 0..100 {
            if i == j {
                index += 1;
                break;
            }
        }
    }
    index
}

Generated asm:

foo::foo:
 push    rax
 mov     rcx, -1
 mov     dl, 1
 xor     r8d, r8d
 xor     esi, esi
 test    r8b, r8b
 je      .LBB7_2
 jmp     .LBB7_9       // here
.LBB7_7:
 add     rcx, -1
 add     dl, 1
 mov     rsi, rax
 cmp     rax, 100
 je      .LBB7_8
 test    r8b, r8b
 jne     .LBB7_9         // here
.LBB7_2:
 lea     rax, [rsi, +, 1]
 mov     edi, eax
 and     edi, 7
 cmp     rsi, 7
 jb      .LBB7_5
 movzx   esi, dl
 and     esi, 7
 add     rsi, rcx
.LBB7_4:
 add     rsi, 8
 jne     .LBB7_4
.LBB7_5:
 test    rdi, rdi
 je      .LBB7_7
.LBB7_6:
 add     rdi, -1
 jne     .LBB7_6
 jmp     .LBB7_7
.LBB7_8:
 pop     rcx
 ret
.LBB7_9:
 call    std::panicking::begin_panic
 ud2

Rust version: 1.38 (stable)
platform: Ubuntu 18.04

@Centril Centril added I-slow Issue: Problems and improvements with respect to performance of generated code. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. O-linux Operating system: Linux labels Oct 30, 2019
@95th
Copy link
Contributor Author

95th commented Nov 5, 2019

Sample C++ which handles this case correctly (no exception call generated): https://godbolt.org/z/dPJSxZ

#include <vector>

int foo(std::vector<int> const& a, std::vector<int> const& b) {
    int index = 0;
    int x = 0;
    for (int i = 0; i < a.size(); i++) {
        for (int j = 0; j < b.size(); i++) {
            if (i == j) {
                x = a.at(index);  // no exception generate by this
                index += 1;
                break;
            }
        }
    }
    return x;
}

clang (https://godbolt.org/z/gj8Xoe) still produces the exception call. (I guess because the LLVM doesn't handle this properly).

@mati865

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
I-slow Issue: Problems and improvements with respect to performance of generated code. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants