[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