[llvm] [ValueTracking] Compute knownbits from `(icmp ult/ule (add nuw X, Y), C)` (PR #87180)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 1 11:43:03 PDT 2024
goldsteinn wrote:
> Can you have a look at the regression [dtcxzyw/llvm-opt-benchmark#465 (comment)](https://github.com/dtcxzyw/llvm-opt-benchmark/pull/465#discussion_r1546021756)?
Okay, reduced test:
```
define void @foo(i32 %x, i32 %y) {
%z = add nuw i32 %x, %y
%cmp0 = icmp ult i32 %z, 255
br i1 %cmp0, label %L0, label %L2
L0:
%sub_x = sub i32 255, %x
br label %L1
L1:
%phi = phi i32 [ 0, %L0 ], [ 1, %L1 ]
%cmp1 = icmp ult i32 %phi, %sub_x
br i1 %cmp1, label %L1, label %L2
L2:
ret void
}
```
The issue occurs due to the InstCombine fold at:
https://github.com/llvm/llvm-project/blob/main/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp#L2280-L2288
We produce:
**Bad:**
```
define void @foo(i32 %x, i32 %y) local_unnamed_addr {
%z = add nuw i32 %x, %y
%cmp0 = icmp ult i32 %z, 255
br i1 %cmp0, label %L0, label %L2
L0: ; preds = %0
%sub_x = xor i32 %x, 255
br label %L1
L1: ; preds = %L1, %L0
%phi = phi i32 [ 0, %L0 ], [ 1, %L1 ]
%cmp1 = icmp ult i32 %phi, %sub_x
br i1 %cmp1, label %L1, label %L2
L2: ; preds = %L1, %0
ret void
}
```
vs
**Good:**
```
define void @foo(i32 %x, i32 %y) local_unnamed_addr {
%z = add nuw i32 %x, %y
%cmp0 = icmp ult i32 %z, 255
br i1 %cmp0, label %L0, label %L2
L0: ; preds = %0
%sub_x = sub i32 255, %x
br label %L1
L1: ; preds = %L1, %L0
%phi = phi i32 [ 0, %L0 ], [ 1, %L1 ]
%cmp1 = icmp ult i32 %phi, %sub_x
br i1 %cmp1, label %L1, label %L2
L2: ; preds = %L1, %0
ret void
}
```
The issue then arises because we fold `(icmp eq/ne (sub C0, x), C1)` -> `(icmp eq/ne x, C2)` even if the sub has multi-use but we don't do the same for `xor`:
https://github.com/llvm/llvm-project/blob/main/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp#L3463-L3474
Ill add a patch for the `xor` case.
https://github.com/llvm/llvm-project/pull/87180
More information about the llvm-commits
mailing list