folds for icmp-of-sum-of-extended-i1 aren't happening in more complex code · Issue #73417 · llvm/llvm-project (original) (raw)

I'm trying to take advantage of the folds from dd31a3b (cc @bcl5980 ) in Rust's standard library. They're working great for single fields, but in more complex cases they don't seem to be triggering, leaving poor IR.

For example, if I change Rust'd Ord::cmp for primitives to use the sext + zext implementation, then I get the following for < on a rust tuple of (i16, u16):

define noundef zeroext i1 @check_lt_direct(i16 noundef %0, i16 noundef %1, i16 noundef %2, i16 noundef %3) unnamed_addr #0 { start: %lhs.i.i = icmp sgt i16 %0, %2 %rhs.i.i = icmp slt i16 %0, %2 %self1.i.i = zext i1 %lhs.i.i to i8 %rhs2.neg.i.i = sext i1 %rhs.i.i to i8 %diff.i.i = add nsw i8 %rhs2.neg.i.i, %self1.i.i %4 = icmp eq i8 %diff.i.i, 0 %_0.i.i = icmp ult i16 %1, %3 %5 = icmp slt i8 %diff.i.i, 0 %_0.0.i = select i1 %4, i1 %_0.i.i, i1 %5 ret i1 %_0.0.i }

But it could just be (proof: https://alive2.llvm.org/ce/z/4dD_qc)

define noundef zeroext i1 @tgt(i16 noundef %0, i16 noundef %1, i16 noundef %2, i16 noundef %3) unnamed_addr #0 { start: ; No longer needed %lhs.i.i = icmp sgt i16 %0, %2 ; No longer needed %rhs.i.i = icmp slt i16 %0, %2 ; No longer needed %self1.i.i = zext i1 %lhs.i.i to i8 ; No longer needed %rhs2.neg.i.i = sext i1 %rhs.i.i to i8 ; No longer needed %diff.i.i = add nsw i8 %rhs2.neg.i.i, %self1.i.i %4 = icmp eq i16 %0, %2 %_0.i.i = icmp ult i16 %1, %3 %5 = icmp slt i16 %0, %2 %_0.0.i = select i1 %4, i1 %_0.i.i, i1 %5 ret i1 %_0.0.i }

By replacing those checks against %diff.i.i with the simplified forms.

A simpler change to just edit the icmp eq i8 %diff.i.i, 0 also works https://alive2.llvm.org/ce/z/gUqUi7

define noundef zeroext i1 @tgt(i16 noundef %0, i16 noundef %1, i16 noundef %2, i16 noundef %3) unnamed_addr #0 { start: %lhs.i.i = icmp sgt i16 %0, %2 %rhs.i.i = icmp slt i16 %0, %2 %self1.i.i = zext i1 %lhs.i.i to i8 %rhs2.neg.i.i = sext i1 %rhs.i.i to i8 %diff.i.i = add nsw i8 %rhs2.neg.i.i, %self1.i.i %4 = icmp eq i1 %lhs.i.i, %rhs.i.i ; <-- %_0.i.i = icmp ult i16 %1, %3 %5 = icmp slt i8 %diff.i.i, 0 %_0.0.i = select i1 %4, i1 %_0.i.i, i1 %5 ret i1 %_0.0.i }

with the the other existing folds then able to do their magic to get it down to

define noundef zeroext i1 @tgt(i16 noundef %0, i16 noundef %1, i16 noundef %2, i16 noundef %3) unnamed_addr #0 { %rhs.i.i = icmp slt i16 %0, %2 %.not = icmp eq i16 %0, %2 %_0.i.i = icmp ult i16 %1, %3 %_0.0.i = select i1 %.not, i1 %_0.i.i, i1 %rhs.i.i ret i1 %_0.0.i }