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