Closed
Description
The following code:
type CSSFloat = f32;
pub enum ViewportPercentageLength {
Vw(CSSFloat),
Vh(CSSFloat),
Vmin(CSSFloat),
Vmax(CSSFloat),
}
impl ViewportPercentageLength {
fn try_sum(&self, other: &Self) -> Result<Self, ()> {
use self::ViewportPercentageLength::*;
Ok(match (self, other) {
(&Vw(one), &Vw(other)) => Vw(one + other),
(&Vh(one), &Vh(other)) => Vh(one + other),
(&Vmin(one), &Vmin(other)) => Vmin(one + other),
(&Vmax(one), &Vmax(other)) => Vmax(one + other),
_ => return Err(()),
})
}
}
#[no_mangle]
pub extern "C" fn sum_them(
one: &ViewportPercentageLength,
other: &ViewportPercentageLength,
out: &mut ViewportPercentageLength,
) -> bool {
match one.try_sum(other) {
Ok(v) => {
*out = v;
true
}
Err(()) => false,
}
}
Generates the following assembly on Rust Nightly when compiled with -C opt-level=3
:
sum_them:
mov eax, dword ptr [rdi]
movss xmm0, dword ptr [rdi + 4]
mov ecx, dword ptr [rsi]
movss xmm1, dword ptr [rsi + 4]
lea rsi, [rip + .LJTI0_0]
movsxd rax, dword ptr [rsi + 4*rax]
add rax, rsi
jmp rax
.LBB0_1:
xor eax, eax
test ecx, ecx
je .LBB0_8
ret
.LBB0_3:
mov eax, 2
cmp ecx, 2
je .LBB0_8
.LBB0_9:
xor eax, eax
ret
.LBB0_5:
mov eax, 3
cmp ecx, 3
jne .LBB0_9
.LBB0_8:
addss xmm0, xmm1
mov dword ptr [rdx], eax
movss dword ptr [rdx + 4], xmm0
mov al, 1
ret
.LBB0_7:
mov eax, 1
cmp ecx, 1
jne .LBB0_9
jmp .LBB0_8
.LJTI0_0:
.long .LBB0_1-.LJTI0_0
.long .LBB0_7-.LJTI0_0
.long .LBB0_3-.LJTI0_0
.long .LBB0_5-.LJTI0_0
Godbolt link: https://rust.godbolt.org/z/JfkEez
It seems to generate one branch for each case of the statement, when I would've expected it to look more like:
if one.enum_discriminant != other.enum_discriminant {
jump to error case
}
write enum into outparam with tag = one.error_discriminant and value one.value != other.value