Implementing <=
via 3-way comparison doesn't optimize down · Issue #59666 · llvm/llvm-project (original) (raw)
I ended up here from code doing essentially a spaceship operator, then comparing against zero: ((a > b) - (a < b)) <= 0
.
That could optimize away: https://alive2.llvm.org/ce/z/_jFfvV
define i1 @src(i16 %0, i16 %1) noundef { %start: %_8.i.i.i = icmp ult i16 %0, %1 %_7.neg.i.i.i = sext i1 %_8.i.i.i to i8 %_12.i.i.i = icmp ugt i16 %0, %1 %_11.i.i.i = zext i1 %_12.i.i.i to i8 %2 = add nsw i8 %_7.neg.i.i.i, %_11.i.i.i %3 = icmp slt i8 %2, 1 ret i1 %3 } => define i1 @tgt(i16 %0, i16 %1) noundef { %start: %x = icmp ule i16 %0, %1 ret i1 %x } Transformation seems to be correct!
But today it doesn't: https://llvm.godbolt.org/z/WerxaczEc
Original Rust repro: https://rust.godbolt.org/z/n6b5KWWhG
pub fn spaceship(x: i16, y: i16) -> i8 { (x > y) as i8 - (x < y) as i8 }
pub fn check_lt(x: i16, y: i16) -> bool { spaceship(x, y) < 0 } pub fn check_le(x: i16, y: i16) -> bool { spaceship(x, y) <= 0 } pub fn check_gt(x: i16, y: i16) -> bool { spaceship(x, y) > 0 } pub fn check_ge(x: i16, y: i16) -> bool { spaceship(x, y) >= 0 }
Interestingly, check_lt
and check_ge
both optimize down to a single icmp
, exactly as hoped. But neither check_le
nor check_gt
does.