Issue 134024
Summary Remove common `add`s when `icmp eq`ing two `select`s [InstCombine]
Labels new issue
Assignees
Reporter scottmcm
    Take the following IR, extracted from part of how Rust generates `==` on enums:

```llvm
define noundef i64 @get_discr(i8 noundef %x) unnamed_addr {
start:
  %_4 = icmp ule i8 %x, 1
 %small = select i1 %_4, i8 3, i8 %x
  %_5 = sub i8 %small, 2
  %_0 = zext i8 %_5 to i64
  ret i64 %_0
}

define noundef zeroext i1 @discr_eq(i8 noundef %a, i8 noundef %b) unnamed_addr {
start:
  %_3 = call noundef i64 @get_discr(i8 noundef %a)
  %_4 = call noundef i64 @get_discr(i8 noundef %b)
  %_0 = icmp eq i64 %_3, %_4
  ret i1 %_0
}
```

Today, when optimizing `get_discr` InstCombine will change the <https://llvm.godbolt.org/z/6Eq87h6h7>
```c
(x <= 1 ? 3 : x) - 2
```
to
```c
(x <= 1 ? 1 : x - 2)
```
which is reasonable on its own.

The problem, though, is that that makes things worse later in `discr_eq`.

It's unable to undo that transformation after the inlining, and thus ends up as <https://llvm.godbolt.org/z/31MdEhfcv>
```llvm
define noundef zeroext i1 @discr_eq(i8 noundef %a, i8 noundef %b) unnamed_addr #0 {
  %0 = add i8 %a, -2
  %_4.inv.i = icmp ugt i8 %a, 1
  %_5.i = select i1 %_4.inv.i, i8 %0, i8 1
  %1 = add i8 %b, -2
  %_4.inv.i1 = icmp ugt i8 %b, 1
  %_5.i2 = select i1 %_4.inv.i1, i8 %1, i8 1
  %_0 = icmp eq i8 %_5.i, %_5.i2
  ret i1 %_0
}
```

But there's no reason to do those `add`s any more -- they could be pulled outside the `select`s where they'd cancel out.

Phrased as C, it's doing
```c
(x <= 1 ? 1 : x - 2) == (y <= 1 ? 1 : y - 2)
```
when instead it could be doing
```c
(x <= 1 ? 3 : x) == (y <= 1 ? 3 : y)
```

So InstCombine should be able to detect this case, and rewrite it back to
```llvm
define noundef zeroext i1 @discr_eq(i8 noundef %a, i8 noundef %b) unnamed_addr #0 {
  %_4.inv.i = icmp ugt i8 %a, 1
 %_5.i = select i1 %_4.inv.i, i8 %a, i8 3
  %_4.inv.i1 = icmp ugt i8 %b, 1
 %_5.i2 = select i1 %_4.inv.i1, i8 %b, i8 3
  %_0 = icmp eq i8 %_5.i, %_5.i2
  ret i1 %_0
}
```
Alive2 proof of correctness for that: <https://alive2.llvm.org/ce/z/AWCmDs>


_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to