> -----Original Message-----
> From: Georg-Johann Lay <a...@gjlay.de>
> Sent: Wednesday, October 2, 2024 2:55 PM
> To: GCC Development <gcc@gcc.gnu.org>; Tamar Christina
> <tamar.christ...@arm.com>
> Subject: Understanding bogus? gcc.dg/signbit-6.c
> 
> I am having problems understanding test case gcc.dg/signbit-6.c
> which fails on a 16-bit platform (avr).
> 
> https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/testsuite/gcc.dg/signbit-
> 6.c;h=da186624cfa057dfc3780c8af4f6b1335ba07e7e;hb=HEAD
> 
> The relevant part of the code is:
> 
> int main ()
> {
>    TYPE a[N];
>    TYPE b[N];
> 
>    a[0] = INT_MIN;
>    b[0] = INT_MIN;
> 
>    for (int i = 1; i < N; ++i) ...
> 
>    fun1 (a, N);
>    fun2 (b, N);
> 
>    if (DEBUG)
>      printf ("%d = 0x%x == 0x%x\n", 0, a[0], b[0]);
> 
>    if (a[0] != 0x0 || b[0] != -1)
>          __builtin_abort ();   // <-- triggers
> 
> 
> where TYPE=int32_t, and the error occurs for a[0] and b[0] so
> the test can be compiled with -DN=1 and still fails.
> 
> fun1() and fun2() have the same C code but different optimization level,
> so how are a[0] and b[0] supposed to be different?
> 
> __attribute__ ((noinline, noipa))
> void fun1(TYPE *x, int n)
> {
>      for (int i = 0; i < n; i++)
>        x[i] = (-x[i]) >> 31;
> }
> 
> __attribute__ ((noinline, noipa, optimize("O0")))
> void fun2(TYPE *x, int n)
> {
>      for (int i = 0; i < n; i++)
>        x[i] = (-x[i]) >> 31;
> }
> 
> IIUC the compiler may exploit that x and -x will always have different
> sign bits because "- INT_MIN" is UB.  In fact, on x86_64 the test
> passes, here with gcc v13.2:
> 
> $ gcc signbit-6.c -O1 -o x.x -DN=1 && ./x.x
> 0 = 0x0 == 0xffffffff
> 
> With -fwrapv so that -INT_MIN is not more UB, it actually fails
> due to the bad condition  "if (a[0] != 0x0 || b[0] != -1)" :
> 

Yes, because specifying -fwrapv changes the optimization and the
point of the test *is* to exploit UB.

> $ gcc signbit-6.c -O1 -o x.x -DN=1 -fwrapv && ./x.x
> 0 = 0xffffffff == 0xffffffff
> 
> On avr (int=int16_t), the test aborts after printing "0 = 0x0 == 0x0".
> 
> 
> So as far as I can see, that test has at least 3 bugs?
> 
> 1) Missing -fwrapv so that -INT_MIN is no more UB, hence the
> test would assert that a[0] == b[0].

That's not a bug.

> 
> 2) When testing for a specific value of a[0] and b[0], it depends
> on whether int == int32_t or smaller:  Better use INT32_MIN to
> initialize a[0] and b[0] instead of just INT_MIN.
> 
> 3) The test case has bogus printf format strings and should
> use PRIx32 from inttypes.h instead of %x.

These are I suppose for platforms that indeed have 16-bit int.

Thanks,
Tamar

> 
> With theses fixes, expected result for a[0] and b[0] is
> (-INT32_MIN) >> 31  =  INT_MIN >> 31  =  INT32_C (-1)
> 
> Johann

Reply via email to