Description
Compiling a bunch of icmp
s against zero
define noundef zeroext i1 @check_slt(i8 %0) unnamed_addr #0 {
start:
%r = icmp slt i8 %0, 0
ret i1 %r
}
define noundef zeroext i1 @check_sle(i8 %0) unnamed_addr #0 {
start:
%r = icmp sle i8 %0, 0
ret i1 %r
}
define noundef zeroext i1 @check_sgt(i8 %0) unnamed_addr #0 {
start:
%r = icmp sgt i8 %0, 0
ret i1 %r
}
define noundef zeroext i1 @check_sge(i8 %0) unnamed_addr #0 {
start:
%r = icmp sge i8 %0, 0
ret i1 %r
}
Gives two rather different kinds of checks https://llvm.godbolt.org/z/4sh47s1bn
check_slt: # @check_slt
mov eax, edi
shr al, 7
ret
check_sle: # @check_sle
test dil, dil
setle al
ret
check_sgt: # @check_sgt
test dil, dil
setg al
ret
check_sge: # @check_sge
mov eax, edi
not al
shr al, 7
ret
My instinct is that check_sge
should just be test
+setge
, more like how check_sgt
is, rather than needing a shift-by-immediate.
But I'm also really not familiar with the nuances of codegen. I suppose it's also possible that flags are so bad that not using them is better. If that's the case, though, should the others be changed too? Maybe check_sgt
could be done with neg
and shifting, for example.
(Or perhaps how it is currently is is already best, and I should just go read more architecture manuals to learn what matters.)
Inspired by a conversation about the Rust's Ordering::is_lt
& friends, and the different ways those could be written https://rust.godbolt.org/z/fq96Yezq7.