x.abs() 与 Rust 中的否定 (-x) 性能,当 x 是一个已知的负数时
x.abs() vs negation (-x) performance in Rust, when x is a known negative number
考虑到 x
是一个已知的负数,在内部哪种方法更有效?结果正数被转换为无符号类型。
let x = -1;
let y = x.abs() as u32;
let z = -x as u32;
检查 playground 中的这两种情况,我们得到以下程序集:
playground::abs:
movl %edi, %eax
negl %eax
cmovll %edi, %eax
retq
playground::negate:
movl %edi, %eax
negl %eax
retq
然而,如果优化器知道 x
的值确实是负数,那么这两个版本就变得等价了。比如这两个函数在语义上都是no-ops:
pub fn extending_abs(x: u8) -> u32 {
abs(-(x as i32))
}
pub fn extending_negate(x: u8) -> u32 {
negate(-(x as i32))
}
他们两个的集会确实consists only of the zero-extension:
playground::extending_abs:
movzbl %dil, %eax
retq
playground::extending_negate:
movzbl %dil, %eax
retq
考虑到 x
是一个已知的负数,在内部哪种方法更有效?结果正数被转换为无符号类型。
let x = -1;
let y = x.abs() as u32;
let z = -x as u32;
检查 playground 中的这两种情况,我们得到以下程序集:
playground::abs:
movl %edi, %eax
negl %eax
cmovll %edi, %eax
retq
playground::negate:
movl %edi, %eax
negl %eax
retq
然而,如果优化器知道 x
的值确实是负数,那么这两个版本就变得等价了。比如这两个函数在语义上都是no-ops:
pub fn extending_abs(x: u8) -> u32 {
abs(-(x as i32))
}
pub fn extending_negate(x: u8) -> u32 {
negate(-(x as i32))
}
他们两个的集会确实consists only of the zero-extension:
playground::extending_abs:
movzbl %dil, %eax
retq
playground::extending_negate:
movzbl %dil, %eax
retq