https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122004
Bug ID: 122004
Summary: x86 optimization: (x > INT_MAX - c) can utilize
overflow flag to save code size
Product: gcc
Version: 15.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: Explorer09 at gmail dot com
Target Milestone: ---
When `x` is a signed integer, and the conditional is `(x > INT_MAX - c)` (`c`
is a compile time constant and 0 < c <= 0x7F), it's possible to check whether
`(x + c)` will overflow. This can save code size by using a one-byte immediate
operand instead of four-byte operand.
The conditional `(x < INT_MIN + c)` (1 < c <= 0x7F) can optimize in a similar
way, by checking whether `(x - c)` will overflow. (If c == 1, the `(x ==
INT_MIN)` case can use even smaller code by using the NEG instruction - see the
example code below.)
Although I file this optimization request for x86, I'm sure such optimization
is possible also for ARM and AArch64 targets (where there are CMP (immediate)
instructions).
```c
#include <stdbool.h>
#include <stdint.h>
bool func1a(int32_t x) {
return x > 0x7FFFFFFF - 0x7F;
}
bool func1b(int32_t x) {
int32_t res;
return __builtin_sub_overflow(x, -0x7F, &res);
}
bool func2a(int32_t x) {
return x < (-0x7FFFFFFF - 1) + 0x7F;
}
bool func2b(int32_t x) {
int32_t res;
return __builtin_sub_overflow(x, 0x7F, &res);
}
bool func3a(int32_t x) {
return x < (-0x7FFFFFFF - 1) + 1;
}
bool func3b(int32_t x) {
int32_t res;
return __builtin_sub_overflow(x, 1, &res);
}
bool func3c(int32_t x) {
int32_t res;
return __builtin_sub_overflow(0, x, &res);
}
```
```assembly
func1a:
cmpl $2147483520, %edi
setg %al
ret
func1b:
addl $127, %edi
seto %al
ret
func2a:
cmpl $-2147483521, %edi
setl %al
ret
func2b:
addl $-127, %edi
seto %al
ret
func3a:
cmpl $-2147483648, %edi
sete %al
ret
func3b:
addl $-1, %edi
seto %al
ret
func3c:
negl %edi
seto %al
ret
```
I would like to thank to this report for pointing out such optimization
opportunity: https://github.com/llvm/llvm-project/issues/159578