[InstCombine] Missed fold: xor(zext(or disjoint X, C1), C2) -> xor(zext(X), C2 ^ zext(C1))
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
InstCombine does not currently fold the following pattern:
```llvm
define i64 @src(i32 %x) {
%or = or disjoint i32 %x, 1
%z = zext i32 %or to i64
%r = xor i64 %z, 2611923443488327891
ret i64 %r
}
```
into:
```llvm
define i64 @tgt(i32 %x) {
%z = zext i32 %x to i64
%r = xor i64 %z, 2611923443488327890
ret i64 %r
}
```
`or disjoint` guarantees that `X` and `C1` have no overlapping set bits, so
`X | C1` is equivalent to `X ^ C1`. Therefore, the constant introduced by the
inner `or` can be absorbed into the outer XOR after zero-extension:
```text
xor(zext(or disjoint X, C1), C2)
-> xor(zext(X), C2 ^ zext(C1))
```
This removes the intermediate `or`, reducing the IR sequence from three
instructions to two. The primary benefit of this fold is IR simplification
and canonicalization.
## Verification
Current LLVM trunk:
https://godbolt.org/z/M75jvGerP
Alive2:
https://alive2.llvm.org/ce/z/zsnvLo
## Codegen comparison
Compiler Explorer:
https://compiler-explorer.com/z/MhKsdnMoz
cc @ParkHanbum
Contributor guide
Assessment
This issue has not been assessed yet.