Skip to content

Slice bounds check not elided in trivial case when using a local varaible outside of a branch #134466

Closed
@ChrisDenton

Description

@ChrisDenton

I tried this code:

fn last_four(s: &[u8]) -> &[u8] {
    let start = if s.len() <= 4 {
        0
    } else {
        s.len() - 4
    };
    &s[start..]
}

Which produces the following assembly on x86_64:

last_four:
        mov     rax, rdi
        lea     rcx, [rsi - 4]
        xor     edi, edi
        cmp     rsi, 5
        cmovae  rdi, rcx
        mov     rdx, rsi
        sub     rdx, rdi
        jb      .LBB0_2
        add     rax, rdi
        ret
.LBB0_2:
        push    rax
        lea     rdx, [rip + .L__unnamed_1]
        call    qword ptr [rip + core::slice::index::slice_start_index_len_fail::hda7fe0c134770be5@GOTPCREL]

.L__unnamed_2:
        .ascii  "/app/example.rs"

.L__unnamed_1:
        .quad   .L__unnamed_2
        .asciz  "\017\000\000\000\000\000\000\000\b\000\000\000\007\000\000"

The branch with the call to slice_start_index_len_fail should be unreachable.

Indeed, I can remove it by moving the slice operation inside the if statement:

fn last_four(s: &[u8]) -> &[u8] {
    if s.len() <= 4 {
        &s[0..]
    } else {
        &s[s.len() - 4..]
    }
}

Which gives:

last_four:
        cmp     rsi, 5
        lea     rax, [rdi + rsi - 4]
        mov     edx, 4
        cmovb   rdx, rsi
        cmovb   rax, rdi
        ret

Which is what I expected.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchE-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.I-slowIssue: Problems and improvements with respect to performance of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions