Issue 133344
Summary `(trunc nuw A) == (trunc nuw B)` should not take multiple `xor`s [InstCombine]
Labels new issue
Assignees
Reporter scottmcm
    Take this input IR:
```llvm
define noundef i1 @src(i8 noundef %a, i8 noundef %b) local_unnamed_addr {
  %at = trunc nuw i8 %a to i1
  %bt = trunc nuw i8 %b to i1
  %eq = icmp eq i1 %at, %bt
  ret i1 %eq
}
```
(That's the kind of thing you might see from looking at `bool`s in `Option`s or `union`s in Rust.)

Today, it "optimizes" to a lossy truncation and a couple of xors:
```llvm
define noundef i1 @src(i8 noundef %a, i8 noundef %b) local_unnamed_addr #0 {
  %1 = xor i8 %b, %a
 %2 = trunc i8 %1 to i1
  %eq = xor i1 %2, true
  ret i1 %eq
}
```

Now, if the `nuw`s weren't there that would make sense, but *with* the `nuw`s it would be *much* better to simplify it to
```llvm
define noundef i1 @tgt(i8 noundef %a, i8 noundef %b) local_unnamed_addr {
  %eq = icmp eq i8 %a, %b
 ret i1 %eq
}
```
instead.  Alive2 proof: <https://alive2.llvm.org/ce/z/X3Uh23>

Notably, that *does* happen already if you truncate to something that's *not* `i1`, like <https://alive2.llvm.org/ce/z/H-QrGZ>
```llvm
define noundef i1 @src(i8 noundef %a, i8 noundef %b) local_unnamed_addr {
  %at = trunc nuw i8 %a to i2
  %bt = trunc nuw i8 %b to i2
  %eq = icmp eq i2 %at, %bt
  ret i1 %eq
}
```

So hopefully this is just a matter of disabling an `i1` special case in InstCombine when `nuw` is there.

cc @nikic -- I think this might be part of the enduring problem of [`Option<bool>::eq` being terrible](https://rust.godbolt.org/z/hPn8TvvYP) you've mentioned before.

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

Reply via email to