Closed
Description
I tried this code:
pub fn change_value(val: Result<i32, ()>) -> Result<i32, ()> {
if let Ok(x) = val {
Ok(x * 2)
} else {
Err(())
}
}
pub fn change_value2(val: Result<i32, ()>) -> Result<i32, ()> {
match val {
Ok(x) => Ok(x * 2),
Err(()) => Err(())
}
}
I expected to see this happen:
in release build this code would translated into exact the same assembly/llvm-ir
Instead, this happened:
change_value:
xorl %eax, %eax
testl %edi, %edi
setne %al
leal (%rsi,%rsi), %edx
retq
change_value2:
movl %edi, %eax
leal (%rsi,%rsi), %edx
retq
and the llvm-ir is different:
define { i32, i32 } @_ZN10playground12change_value17h0230bd4091fd6529E(i32 noundef %0, i32 %1) unnamed_addr #0 {
start:
%2 = icmp eq i32 %0, 0
%_4 = shl i32 %1, 1
%not. = xor i1 %2, true
%.sroa.0.0 = zext i1 %not. to i32
%.sroa.3.0 = select i1 %2, i32 %_4, i32 undef
%3 = insertvalue { i32, i32 } undef, i32 %.sroa.0.0, 0
%4 = insertvalue { i32, i32 } %3, i32 %.sroa.3.0, 1
ret { i32, i32 } %4
}
define { i32, i32 } @_ZN10playground13change_value217h3302fbc2853d0a41E(i32 noundef %0, i32 %1) unnamed_addr #0 {
start:
%switch = icmp eq i32 %0, 0
%_4 = shl i32 %1, 1
%.sroa.3.0 = select i1 %switch, i32 %_4, i32 undef
%2 = insertvalue { i32, i32 } undef, i32 %0, 0
%3 = insertvalue { i32, i32 } %2, i32 %.sroa.3.0, 1
ret { i32, i32 } %3
}
Meta
I tried thin in rust-playground for 1.68.2, beta and nightly.
See also https://internals.rust-lang.org/t/why-match-is-better-then-if/18636