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