[InstCombine] Fold x > -x to x > 0 without nsw
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
InstCombine simplifies `x >s -x` to `x >s 0` when the negation has `nsw`. The same fold is valid for ordinary wrapping negation, but is missed for the following LLVM IR:
```llvm
define i1 @src(i32 %x) {
entry:
%neg = sub i32 0, %x
%r = icmp sgt i32 %x, %neg
ret i1 %r
}
```
`opt -O3`leaves it as is without fold (godbolt: https://godbolt.org/z/7YYaM4x53):
```llvm
define i1 @src(i32 %x) {
entry:
%neg = sub i32 0, %x
%r = icmp sgt i32 %x, %neg
ret i1 %r
}
```
Adding `nsw` to the negation enables the fold:
```llvm
define i1 @nsw_control(i32 %x) {
entry:
%neg = sub nsw i32 0, %x. ;; removed
%r = icmp sgt i32 %x, %neg ;; %neg -> 0
ret i1 %r
}
```
The zero comparison is still valid without `nsw`: at zero and `INT_MIN`, `%x` equals its wrapping negation, so the strict comparison is false. For all other values, `%x` and `-%x` have opposite signs. Thus `x >s -x` is equivalent to `x >s 0` (alive2: https://alive2.llvm.org/ce/z/zuDKGb).
`foldICmpXNegX()` in `InstCombineCompares.cpp` already simplifies `x >s -x` to `x >s 0`, but requires `nsw` on the negation. A fix is to allow this signed greater-than fold without nsw.
Contributor guide
Assessment
This issue has not been assessed yet.