Skip to content

Two subsequent labels and unnecessary jmp with opt-level=s #126585

Closed
@mickvangelderen

Description

@mickvangelderen

The following code:

const fn checked_div_round(a: u64, b: u64) -> Option<u64> {
    match b {
        0 => None,
        1 => Some(a),
        // `a / b` is computable and `(a % b) * 2` can not overflow since `b >= 2`. UPDATE <- this is wrong
        b => Some(a / b + if (a % b) * 2 >= b { 1 } else { 0 }),
    }
}

Generates two subsequent labels and an unnecessary jmp instruction:

checked_div_round:
        test    rsi, rsi
        je      .LBB0_1
        cmp     rsi, 1
        je      .LBB0_3
        mov     rax, rdi
        xor     edx, edx
        div     rsi
        add     rdx, rdx
        cmp     rdx, rsi
        mov     rdi, rax
        sbb     rdi, -1
.LBB0_3:
        mov     esi, 1
        jmp     .LBB0_4   ; this jump does not seem necessary since `.LBB0_1` is empty
.LBB0_1:
.LBB0_4:
        mov     rax, rsi
        mov     rdx, rdi
        ret

When compiled with -C opt-level=s using rustc 1.79.0.

Godbolt: https://godbolt.org/z/fhTq3ssnK

P.S. For context, I am not too familiar with asm. I did not find any similar results while searching through the rustc and llvm issue trackers for "double | subsequent | unnecessary label" or "unnecessary jmp | jump". Please let me know how I can improve the quality of my issue reporting.

Metadata

Metadata

Assignees

Labels

A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.A-codegenArea: Code generationC-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.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