Open
Description
Consider these equivalent ways of checking whether an array of 5 booleans are all true.
pub fn iter_all(a: [bool; 5]) -> bool {
a.iter().all(|s| *s)
}
pub fn iter_fold(a: [bool; 5]) -> bool {
a.iter().fold(true, |acc, a| acc & a)
}
pub fn manual_loop(a: [bool; 5]) -> bool {
let mut b = true;
for a in a {
b &= a;
}
b
}
pub fn comparison(a: [bool; 5]) -> bool {
a == [true; 5]
}
pub fn and(a: [bool; 5]) -> bool {
a[0] & a[1] & a[2] & a[3] & a[4]
}
This is the generated assembly.
# same for `iter_all`, `iter_fold`, `manual_loop`
example::iter_all:
movabs rax, 1099511627775
and rax, rdi
test dil, dil
setne cl
test edi, 65280
setne dl
and dl, cl
test edi, 16711680
setne cl
test edi, -16777216
setne sil
and sil, cl
and sil, dl
mov ecx, 4278190080
or rcx, 16777215
cmp rax, rcx
seta al
and al, sil
ret
example::comparison:
movabs rax, 1099511627775
and rax, rdi
movabs rcx, 4311810305
cmp rax, rcx
sete al
ret
example::and:
not rdi
movabs rax, 4311810305
test rdi, rax
sete al
ret
One thing of note is that usually when functions would result in the same assembly, they get merged together. This hasn't happened here, which might indicate that the compiler did not understand that all of them do the same thing.
The assembly of and
is the best one. The other versions should compile to it. It is unfortunate that you need to manually unroll the iterator to get the better version.