https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79173
--- Comment #14 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Unfortunately, the clang __builtin_addc* and __builtin_subc* builtins are badly
designed.
Instead of adding or subtracting a 1-bit carry, where the result is guaranteed
to have 1-bit carry as well, they are:
unsigned __builtin_addc (unsigned x, unsigned y, unsigned carry_in, unsigned
*carry_out)
{
unsigned r;
unsigned c1 = __builtin_add_overflow (x, y, &r);
unsigned c2 = __builtin_add_overflow (r, carry_in, &r);
*carry_out = c1 + c2;
return r;
}
unsigned __builtin_subc (unsigned x, unsigned y, unsigned carry_in, unsigned
*carry_out)
{
unsigned r;
unsigned c1 = __builtin_sub_overflow (x, y, &r);
unsigned c2 = __builtin_sub_overflow (r, carry_in, &r);
*carry_out = c1 + c2;
return r;
}
So, instead of doing [0, 0xffffffff] + [0, 0xffffffff] + [0, 1] resulting in
[0, 0xffffffff] plus [0, 1] carry they actually do
[0, 0xffffffff] + [0, 0xffffffff] + [0, 0xffffffff] resulting in [0,
0xffffffff] plus [0, 2] carry. So far for good "design".
So, am not really sure if it is worth implementing those builtins, one can use
__builtin_add_overflow/__builtin_sub_overflow instead, all we need is pattern
detect if they are chained and so start with 0 carry in and then the carry outs
are guaranteed to be [0, 1] and further pairs of .ADD_OVERFLOW/.SUB_OVERFLOW
again can count on [0, 1]
carry in and produce [0, 1] carry out. And pattern detect that into some new
IFN which will try to produce efficient code for these.