bug in longlong.h for aarch64 sub_ddmmss

Vincent Lefevre vincent at vinc17.net
Tue Jun 16 14:11:53 UTC 2020


On 2020-06-16 14:47:23 +0200, Torbjorn Granlund wrote:
> Vincent Lefevre <vincent at vinc17.net> writes:
> 
>   On 2020-06-16 13:40:14 +0200, Torbjorn Granlund wrote:
>   > Vincent Lefevre <vincent at vinc17.net> writes:
>   > 
>   >   #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
>   >     do {                                                                  \
>   >       if (__builtin_constant_p (bl) && -(UDItype)(bl) < 0x1000)           \
>   >         __asm__ ("adds\t%1, %x4, %5\n\tsbc\t%0, %x2, %x3"                 \
>   >                  : "=r,r" (sh), "=&r,&r" (sl)                             \
>   >                  : "rZ,rZ" ((UDItype)(ah)), "rZ,rZ" ((UDItype)(bh)),      \
>   >                    "r,Z"   ((UDItype)(al)), "rI,r" (-(UDItype)(bl)) __CLOBBER_CC);\
>   >       else                                                                \
>   >         __asm__ ("subs\t%1, %x4, %5\n\tsbc\t%0, %x2, %x3"                 \
>   >                  : "=r,r" (sh), "=&r,&r" (sl)                             \
>   >                  : "rZ,rZ" ((UDItype)(ah)), "rZ,rZ" ((UDItype)(bh)),      \
>   >                    "r,Z"   ((UDItype)(al)), "rI,r"  ((UDItype)(bl)) __CLOBBER_CC);\
>   >     } while(0);
>   > 
>   > The two - signs ought to be ~, I think.  Let me think a buit more about that.
> 
>   Note that the "else" case, which doesn't have a - sign in its
>   arguments is affected too, AFAIK.
> 
> I cannot follow you here.
> 
> Are you saying that the asm in the else clause is broken too?
> Please explain.

Sorry, it seems OK (I thought that on (0,0), subs and adds would
be equivalent, but the carry out is actually different).

Note that I'm rather surprised to see that the issue disappears
if I add unrelated code. For instance, in the following testcase,
with GCC 9.1.0 -O2, I get "h = 0xffffffffffffffff", which is
incorrect, but if I define V, I get the correct "h = 0x0".

typedef unsigned int UDItype __attribute__ ((mode (DI)));
typedef unsigned long UWtype;
#define W_TYPE_SIZE 64
#define __GMP_DECLSPEC
#define __GMP_GNUC_PREREQ(maj, min) \
  ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
#include <stdio.h>
#include "longlong.h"

int v = 0;

int main (void)
{
  volatile unsigned long u0 = 0x4000000000000000, r0 = 0x7ffffffffffffffd;
  unsigned long u, r, h, l;
  u = u0;
  r = r0;
  if (r < 0x8000000000000000)
    r = 0x8000000000000000;
#ifdef V
  if (v)
    fflush (stdout);
#endif
  umul_ppmm (h, l, r, r);
  sub_ddmmss (h, l, u, 0, h, l);
  printf ("h = 0x%lx\n", h);
  return 0;
}

-- 
Vincent Lefèvre <vincent at vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


More information about the gmp-bugs mailing list