Bug 43249 - unsigned int arg with no prototype gets full 64-bit reg
Summary: unsigned int arg with no prototype gets full 64-bit reg
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.5.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2010-03-03 19:11 UTC by Janis Johnson
Modified: 2012-04-20 14:45 UTC (History)
3 users (show)

See Also:
Host:
Target: powerpc64-linux
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Janis Johnson 2010-03-03 19:11:29 UTC
For a function with no prototype that defines an argument as unsigned
int, GCC for powerpc64-linux with -m64 and optimization uses the
entire 64-bit argument register rather than masking off the lower
32 bits.  This problem was discoverd with 176.gcc using options
"-m64 -O2 -ftree-vectorize -maltivec -fdata-sections", which changed
the order of 32-element arrays so that accessing element 63 instead of
element 31 started getting garbage that no longer happened to work.

Here's a simple testcase that works with -O0 and fails with -O1.
It's useful to compare this with a a version whose argument is
unsigned short.  For the GCC testsuite, just remove references to
printf.

-------------------------------------------------------------------
extern int printf (const char *, ...);

int
__attribute__((noinline))
floor_log2_wide (x)
  unsigned int x;
{
  int log = -1;
  while (x != 0)
    log++,
    x >>= 1;
  return log;
}

int
main ()
{
  int m;
  unsigned int n = 4294967259U;

  m = floor_log2_wide ((int)n);
  printf ("n = %u, m = %d\n", n, m);
  if (m != 31)
    __builtin_abort ();
  return 0;
}
-------------------------------------------------------------------

elm3c105% /home/janis/tools/gcc-trunk-anonsvn/bin/gcc -m64 -O0 bug.c && ./a.out
n = 4294967259, m = 31
elm3c105% /home/janis/tools/gcc-trunk-anonsvn/bin/gcc -m64 -O1 bug.c && ./a.out
n = 4294967259, m = 63
Aborted

I've tried compilers back to GCC 4.1 and they all have the same problem;
it's probably not a regression.
Comment 1 Janis Johnson 2010-03-10 18:35:42 UTC
GCC 3.4 also has this bug.
Comment 2 Alan Modra 2010-05-26 13:22:48 UTC
I think this testcase may invoke undefined behaviour.  Section 6.5.2.2 of the ISO C spec says of function calls without a prototype that if "the types of the arguments after promotion are not compatible with those of the parameters after promotion, the behavior is undefined, except for the following cases" and the relevant case is "one promoted type is a signed integer type, the other promoted type is the corresponding unsigned integer type, and the value is representable in both types".

The value you are passing, (int)4294967259U, is a negative number so not representable as an unsigned int.
Comment 3 Bill Schmidt 2012-04-20 14:45:52 UTC
Closing per comment #2.