https://gcc.gnu.org/bugzilla/show_bug.cgi?id=30484

--- Comment #23 from Richard Biener <rguenth at gcc dot gnu.org> ---
RTL documents no specific behavior for 'div' but says 'ss_div' "ensures that an
out-of-bounds result saturates to the maximum or minimum signed value".

I'm not sure we want target specific semantics for the RTL IL, but since
x86 at least has a valid 'div' for the case overflow is undefined we probably
have to assume div by minus one might trap.  Practically we already assume
that give we simplify division by -1 to negate and have to assume that
division by a non-constant amount traps since it could be a division by zero.

That means practically speaking the -fwrapv issue remains.  Since RTL
doesn't document any specific behavior we have to generally expand signed
division differently.

Using

  b == -1 ? -a : a / b

will for example generate

        cmpl    $-1, %esi
        je      .L5
        cltd
        idivl   %esi
...

.L5:
        negl    %eax
...


We'd expect the following to pass.  I wonder how many targets FAIL it, thus
whether we can require that RTL sdiv has the desired overflow behavior for
-fwrapv (it always appeared to me that RTL behaves as if -fwrapv).  It
works fine with the libgcc implementation for int128.

/* { dg-additional-options "-fwrapv" } */

#define TYPE int
#define UTYPE unsigned

//#define TYPE __int128_t
//#define UTYPE __uint128_t

TYPE __attribute__((noipa))
div (TYPE a, TYPE b)
{
  return a / b;
}

TYPE __attribute__((noipa))
neg (TYPE a)
{
  return -a;
}

int main()
{
  TYPE min = (TYPE)((UTYPE)1 << (sizeof(TYPE)*8-1));
  if (div (min, -1) != min
      || neg (min) != min)
    __builtin_abort ();
  return 0;
}

Reply via email to