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.

Reply via email to