https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106786
Bug ID: 106786
Summary: Regression in cmp+sbb
Product: gcc
Version: 12.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: chfast at gmail dot com
Target Milestone: ---
I noticed a regression when using the builtin for sbb instruction
(__builtin_ia32_sbb_u64).
typedef unsigned long long u64;
struct R {
u64 value;
bool carry;
};
inline R subc(u64 x, u64 y, bool carry) noexcept {
u64 d;
const u64 carryout = __builtin_ia32_sbb_u64(carry, x, y, &d);
return {d, carryout != 0};
}
bool bad(u64 x, u64 y) {
const R z = subc(x, y, false);
R a = subc(x, y, z.carry);
return a.carry;
}
https://godbolt.org/z/f41KKe19q
The expected assembly is
cmp rdi, rsi
sbb rdi, rsi
But GCC 12.2.0 and trunk produces
cmp rdi, rsi
setb al
movzx eax, al
add al, -1
sbb rdi, rsi
The regression is in 12.2.0, the 11.3.0 optimizes properly.
There are simple changes which will bring back the expected optimization:
- change `const R z` to `R z`,
- change `bool carry` to `u64 carry`.
This may be related to calling convention / ABI because I noticed in one of the
tree optimization outputs for 12.2.0 that the `bool carry` is forced to be in
memory: `MEM <unsigned char> [(struct R *)&z + 8B]`.
https://godbolt.org/z/7zh7GxraK