Skip to content

folds for icmp-of-sum-of-extended-i1 aren't happening in more complex code #73417

Open
@scottmcm

Description

@scottmcm

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
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions