Closed
Description
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
Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Area: Code generationCategory: An issue highlighting optimization opportunities or PRs implementing suchCall for participation: An issue has been fixed and does not reproduce, but no test has been added.Relevant to the compiler team, which will review and decide on the PR/issue.