llvm / llvm/llvm-project

[aarch64] [missed-opt] Irrelevant subtraction pessimizes llvm.uadd/usub.with.overflow

Open
#171,884 5 comments 0 reactions 0 assignees View on GitHub
backend:AArch64 missed-optimization
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

[Godbolt](https://godbolt.org/z/948EWPoqM)

```cpp
#include

uint64_t f(uint64_t x, uint64_t y) {
uint64_t sum;
if (__builtin_uaddl_overflow(x, y, &sum)) {
return sum - 100;
} else {
return 0;
}
}

uint64_t g(uint64_t x, uint64_t y) {
uint64_t sum;
if (__builtin_uaddl_overflow(x, y, &sum)) {
return sum - 100;
} else {
return sum;
}
}
```

```asm
f(unsigned long, unsigned long):
adds x8, x0, x1
sub x8, x8, #100
cmn x0, x1
csel x0, x8, xzr, hs
ret

g(unsigned long, unsigned long):
adds x8, x0, x1
sub x8, x8, #100
adds x9, x0, x1
csel x0, x8, x9, hs
ret
```

In `f`, note `adds` computing the sum and having its output flag is ignored and recomputed with `cmn`. In `g`, note `adds` being run twice.

This problem affects `__builtin_uaddl_overflow` and `__builtin_usubl_overflow` equally.

Replacing `- 100` with `+ 100` miraculously fixes the lowering, but obviously changes semantics.

Contributor guide

Open the contributing guide

Research direction

Start with the Godbolt reproducer and compare the AArch64 lowering of f and g for the overflow builtins. Trace the lowering of llvm.uadd.with.overflow and llvm.usub.with.overflow to determine why subtraction causes redundant flag computation or addition. Done means the generated AArch64 avoids the unnecessary recomputation while preserving the subtraction semantics for both functions.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.