llvm / llvm/llvm-project

(x86 & ARM) Missed subtract overflow pattern on an unsigned loop counter

Open
#170,675 9 comments 0 reactions 0 assignees View on GitHub
backend:AArch64 backend:ARM backend:X86 missed-optimization
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

https://godbolt.org/z/EzjEoehfM

```c
void func1_a(unsigned long x, unsigned long y) {
while (1) {
__asm__ ("" ::: "memory");
if (x < y)
break;
x -= y;
}
}
void func1_b(unsigned long x, unsigned long y) {
while (1) {
__asm__ ("" ::: "memory");
if (x - y > x)
break;
x -= y;
}
}
void func1_c(unsigned long x, unsigned long y) {
while (1) {
__asm__ ("" ::: "memory");
if (__builtin_usubl_overflow(x, y, &x))
break;
}
}
```

x86-64 clang 21.1.0 with `-Os` option produces:

```assembly
func1_a:
addq %rsi, %rdi
.LBB0_1:
subq %rsi, %rdi
cmpq %rsi, %rdi
jae .LBB0_1
retq
func1_b:
addq %rsi, %rdi
.LBB1_1:
subq %rsi, %rdi
cmpq %rdi, %rsi
jbe .LBB1_1
retq
func1_c:
.LBB2_1:
subq %rsi, %rdi
jae .LBB2_1
retq
```

Clang doesn't recognize `func1_a` and `func1_b` can both optimize to `func1_c`.

(Similar issue can also happen with ARM and AArch64 targets.)

This issue might be related to #161036, but I can't tell whether my report is a duplicate, since my test code uses a loop.

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.