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;
}