https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107564
Bug ID: 107564
Summary: Fail to recognize overflow check for addition of
__uint128_t operands
Product: gcc
Version: 12.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: cassio.neri at gmail dot com
Target Milestone: ---
Consider:
char f128(__uint128_t m, __uint128_t n) {
#if !defined(USE_BUILTIN_ADD_OVERFLOW)
m += n;
return m < n;
#else
__uint128_t r;
return __builtin_add_overflow(m, n, &r);
#endif
}
When USE_BUILTIN_ADD_OVERFLOW is undefined, GCC fails to recognise this is an
overflow check and with -O3 generates this:
mov r8, rdi
mov rax, rsi
mov rdi, rax
mov rsi, r8
mov rax, rdx
mov rdx, rcx
add rsi, rax
adc rdi, rcx
cmp rsi, rax
mov rcx, rdi
sbb rcx, rdx
setc al
ret
When USE_BUILTIN_ADD_OVERFLOW is defined, it generates better code but still
suboptimal:
mov r8, rdi
mov rax, rsi
mov rsi, r8
mov rdi, rax
add rsi, rdx
adc rdi, rcx
setc al
ret
For other unsigned integer types GCC generates the same optimal code for both
methods. For instance for uint64_t:
add rdi, rsi
setc al
ret
https://godbolt.org/z/bj4M5no4j