llvm / llvm/llvm-project

[InstCombine] Fold x > -x to x > 0 without nsw

Open
#223,348 1 comment 0 reactions 1 assignee Claimed by @pratap9572singh View on GitHub
llvm:instcombine missed-optimization
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.