[Bug c/40579] New: gcc -O2 optimization causes infinite loop and wrong output

2009-06-29 Thread dentongosnell at yahoo dot com
$ gcc -v
Using built-in specs.
Target: i686-pc-linux-gnu
Configured with: /root/gcc-4.4.0/configure --prefix=/opt/gcc-4.4.0
--enable-languages=c,c++
Thread model: posix
gcc version 4.4.0 (GCC)

Here is a program to reproduce this problem :-

#include 
#include 

#define MinWordStr "-2147483648"
#define MinWord  ((long)0x8000)   /* smallest word */

/* Simple function to convert long to a string */
static char * itos(long num)
{
char *p;
static char buff[64];

p = buff + sizeof(buff) - 1;

*p = '\0';
if (num >= 0L)
do {
*--p = num % 10L + '0';
num /= 10L;
} while (num != 0L);
else {
if (num == MinWord) {  /* max negative value */
p -= strlen (MinWordStr);
strcpy (p, MinWordStr);
}
else {
num = -num;
do {
*--p = '0' + (num % 10L);
num /= 10L;
} while (num != 0L);
*--p = '-';
}
}

return p;
}

int main() {
char *p;
long x = -2147483645;
int i;

for (i = 0; i < 4; ++i) {
p = itos(x);
printf("i=%d p=%s\n",i,p);
--x;
}

return 0;
}


When run with -O1 it runs okay.

$ gcc -O1 prog.c && ./a.out
i=0 p=-2147483645
i=1 p=-2147483646
i=2 p=-2147483647
i=3 p=-2147483648

But with -O2 it goes haywire.
$ gcc -O2 progg.c && ./a.out
i=0 p=-2147483645
i=1 p=-2147483646
i=2 p=-2147483647
i=3 p=-2147483648
i=4 p=-./,),(-*,)
i=5 p=-./,),(-*,*
i=6 p=-./,),(-*,+
i=7 p=-./,),(-*,,
...etc ad infinitum

Note that if the line
if (num == MinWord) {  /* max negative value */
is changed to
if (num == -num) {  /* max negative value */

a different (and also incorrect) result occurs with -O2
$ gcc -O2 prog.c && ./a.out
i=0 p=-2147483645
i=1 p=-2147483646
i=2 p=-2147483647
i=3 p=-./,),(-*,(

Other points:
1) this has something to do with the value of x reaching the most negative
32-bit long (ie: -2147483648, or 0x8000) - if it stays away from that by
initializing x = -2147483644 instead of -2147483645 it is okay.
2) gcc 2.95.3 seems to work okay with -O2


-- 
   Summary: gcc -O2 optimization causes infinite loop and wrong
output
   Product: gcc
   Version: 4.4.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
     Component: c
    AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: dentongosnell at yahoo dot com
 GCC build triplet: i686-pc-linux
  GCC host triplet: i686-pc-linux
GCC target triplet: i686-pc-linux


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40579



[Bug c/40645] New: Bus error caused by ldd/std instructions in struct copy.

2009-07-03 Thread dentongosnell at yahoo dot com
$ gcc -v
Using built-in specs.
Target: sparc-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.3.2-1.1'
--with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs
--enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared
--with-system-zlib --libexecdir=/usr/lib --without-included-gettext
--enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3
--program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug
--enable-objc-gc --enable-mpfr --with-cpu=v8 --with-long-double-128
--enable-checking=release --build=sparc-linux-gnu --host=sparc-linux-gnu
--target=sparc-linux-gnu
Thread model: posix
gcc version 4.3.2 (Debian 4.3.2-1.1)

To trigger the bug :-

$ gcc align_bug.c
$ ./a.out
Bus error
$

Here is align_bug.c :-

-

#include 

struct b_one {
  int i;
  double d;
};

struct b_two {
  int i1;
  int i2;
};

union myblock {
struct b_one one;
struct b_two two;
};

void myfunc(union myblock *dp1, union myblock *dp2)
{
  dp2->two = dp1->two;
}

int main()
{
  int w;
  struct b_two a = {1,2};
  struct b_two b;

  myfunc((union myblock *)&a, (union myblock *)&b);

  printf("%d %d\n", b.i1, b.i2);

  return 0;
}

--

The problem seems to happen in "myfunc" when the compiled code tries
to copy the 8-byte structure dp2->two to dp1->two, using a ldd/std
instruction pair.  The problem seems to be that dp1 and dp2 (ie a and
b in main) aren't strictly enough aligned for that.  If you take out
the redundant "int w" in main then a and b happen to be aligned okay
and the bus error doesn't happen.

I think the compiler is assuming "union myblock" has the same
alignment as "struct b_one", which is more strictly aligned than
"struct b_two" because of its double member.

I realise that casting &a to (union myblock*) in main may technically
invoke undefined behaviour... but I think the cast is reasonable given
that union myblock contains the type of a.

One other thing, there is a flag "-mno-faster-structs" which this page
suggests would prevent this sort of ldd/std use
(http://gcc.gnu.org/onlinedocs/gcc/SPARC-Options.html).  Unfortunately
this flag doesn't seem to make any difference to this case.


-- 
   Summary: Bus error caused by ldd/std instructions in struct copy.
   Product: gcc
   Version: 4.3.2
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
         Component: c
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: dentongosnell at yahoo dot com
 GCC build triplet: sparc-linux-gnu
  GCC host triplet: sparc-linux-gnu
GCC target triplet: sparc-linux-gnu


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40645



[Bug c/40645] Bus error caused by ldd/std instructions in struct copy.

2009-07-04 Thread dentongosnell at yahoo dot com


--- Comment #3 from dentongosnell at yahoo dot com  2009-07-04 13:32 ---
(In reply to comment #2)

> 
> > One other thing, there is a flag "-mno-faster-structs" which this page
> > suggests would prevent this sort of ldd/std use
> > (http://gcc.gnu.org/onlinedocs/gcc/SPARC-Options.html).  Unfortunately
> > this flag doesn't seem to make any difference to this case.
> 
> -mno-faster-structs is the default.
> 

If "-mno-faster-structs" is the default, then surely it shouldn't be generating
ldd/std in this case (and assuming the 8-byte alignment for "union myblock"). 
The code it is generating is what I would expect if I passed
"-mfaster-structs", based on the above-mentioned documentation page.

In other words, gcc align_bug.c should give just ld/st pairs, and hence should
work without a bus error.

I think either the compiler or the documentation has a bug!


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40645