Issue 53015
Summary Optimization: combine unlikely branches
Labels new issue
Assignees
Reporter tczajka
    This Rust code:
```rust
fn sum(a: &[i32]) -> i32 {
    a[0] + a[1] + a[2]
}
```
performs bounds checks on each array access in order. Effectively it translates to something like this:

```rust
fn sum(a: &[i32]) -> i32 {
    if a.len() == 0 {
        panic!("0 out of range");
    } else if a.len() == 1 {
        panic!("1 out of range");
    } else if a.len() <= 2 {
        panic!("2 out of range");
    } else {
        unsafe { a.get_unchecked(0) + a.get_unchecked(1) + a.get_unchecked(2) }
    }
}
```

Generated assembly:
```asm
        push    rax
        test    rsi, rsi
        je      .LBB0_4
        cmp     rsi, 1
        je      .LBB0_5
        cmp     rsi, 2
        jbe     .LBB0_3
        mov     eax, dword ptr [rdi + 4]
        add     eax, dword ptr [rdi]
        add     eax, dword ptr [rdi + 8]
        pop     rcx
        ret
```

All three "panic" cases unconditionally call an error handling function marked `cold`.

This could be optimized by combining the tests into one test covering all three unlikely cases, so that there is only one check on the hot path. If we have to go into the cold code, only then differentiate between the different cold cases. Like this:
```rust
fn sum(a: &[i32]) -> i32 {
    if a.len() <= 2 {
        if a.len() == 0 {
            panic!("0 out of range");
        } else if a.len() == 1 {
            panic!("1 out of range");
        } else {
            panic!("2 out of range");
        }
    } else {
        unsafe { a.get_unchecked(0) + a.get_unchecked(1) + a.get_unchecked(2) }
    }
}
```
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to