This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
gcc optimizer bug
- To: egcs-bugs at egcs dot cygnus dot com
- Subject: gcc optimizer bug
- From: Luoqi Chen <luoqi at chen dot ml dot org>
- Date: Wed, 21 Apr 1999 12:04:44 -0400 (EDT)
Gcc compiles following piece of C code: (completed source file is attached)
u_short *ptr;
int sum, oddbyte;
oddbyte = 0;
*((u_char *) &oddbyte) = *(u_char *) ptr;
sum += oddbyte;
into compiled into (%esi = ptr, %ecx = sum)
0x28067038 <TcpChecksum+80>: movb (%esi),%al
0x2806703a <TcpChecksum+82>: addl %eax,%ecx
note that higher bytes of %eax are not cleared.
This machine is a P5 133Mhz PC running FreeBSD-current, and here is
gcc -v --save-temps output:
Using builtin specs.
gcc version egcs-2.91.66 19990314 (egcs-1.1.2 release)
/usr/libexec/cpp -lang-c -v -undef -D__GNUC__=2 -D__GNUC_MINOR__=91 -Di386 -Dunix -D__FreeBSD__=4 -D__FreeBSD_cc_version=400002 -D__i386__ -D__unix__ -D__FreeBSD__=4 -D__FreeBSD_cc_version=400002 -D__i386 -D__unix -Acpu(i386) -Amachine(i386) -Asystem(unix) -Asystem(FreeBSD) -D__OPTIMIZE__ -D__ELF__ a.c a.i
GNU CPP version egcs-2.91.66 19990314 (egcs-1.1.2 release) (i386 FreeBSD/ELF)
#include "..." search starts here:
#include <...> search starts here:
/usr/include
End of search list.
/usr/libexec/cc1 a.i -quiet -dumpbase a.c -O -version -o a.s
GNU C version egcs-2.91.66 19990314 (egcs-1.1.2 release) (i386-unknown-freebsd) compiled by GNU C version egcs-2.91.66 19990314 (egcs-1.1.2 release).
/usr/libexec/elf/as -v -o a.o a.s
GNU assembler version 2.9.1 (i386-unknown-freebsdelf), using BFD version 2.9.1
/usr/libexec/elf/ld -m elf_i386 -dynamic-linker /usr/libexec/ld-elf.so.1 -o a /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/crtbegin.o -L/usr/libdata/gcc -L/usr/libexec/elf -L/usr/libexec a.o /usr/lib/libgcc.a -lc /usr/lib/libgcc.a /usr/lib/crtend.o /usr/lib/crtn.o
The complete C source file. pkt is an actual tcp packet captured by tcpdump
which has a bad tcp checksum generated by TcpChecksum().
#include <sys/types.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
u_short pkt[] = {
0x4510, 0x0051, 0x3f17, 0x4000, 0x3f06, 0xc9ca, 0xcfca, 0x49aa,
0xcfca, 0x4976, 0x040c, 0x0015, 0x5e7a, 0x8495, 0xb73b, 0xbf64,
0x8018, 0x43e0, 0xf71c, 0x0000, 0x0101, 0x080a, 0x0000, 0x410a,
0x0000, 0x7e28, 0x504f, 0x5254, 0x2032, 0x3037, 0x2c32, 0x3032,
0x2c37, 0x332c, 0x3137, 0x302c, 0x3232, 0x392c, 0x3231, 0x340d,
0x0a00,
};
#define NPKT (sizeof(pkt)/sizeof(pkt[0]))
extern u_short TcpChecksum(struct ip *);
main()
{
int i;
int sum;
u_short buf[NPKT];
for (i = 0; i < NPKT; i++)
buf[i] = htons(pkt[i]);
sum = TcpChecksum((struct ip *)buf);
printf("sum = %x, %x\n", sum, sum % 0xffff);
#if 0
sum = htons(pkt[4] & 0xff);
for (i = 6; i < NPKT; i++) {
sum += htons(pkt[i]);
}
sum += htons(pkt[1] - 0x14);
printf("sum = %x, %x\n", sum, sum % 0xffff);
#endif
}
u_short
TcpChecksum(struct ip *pip)
{
u_short *ptr;
struct tcphdr *tc;
int nhdr, ntcp, nbytes;
int sum, oddbyte;
nhdr = pip->ip_hl << 2;
ntcp = ntohs(pip->ip_len) - nhdr;
tc = (struct tcphdr *) ((char *) pip + nhdr);
ptr = (u_short *) tc;
/* Add up TCP header and data */
nbytes = ntcp;
sum = 0;
while (nbytes > 1)
{
sum += *ptr++;
nbytes -= 2;
}
if (nbytes == 1)
{
oddbyte = 0;
*((u_char *) &oddbyte) = *(u_char *) ptr;
sum += oddbyte;
}
/* "Pseudo-header" data */
ptr = (u_short *) &(pip->ip_dst);
sum += *ptr++;
sum += *ptr;
ptr = (u_short *) &(pip->ip_src);
sum += *ptr++;
sum += *ptr;
sum += htons((u_short) ntcp);
sum += htons((u_short) pip->ip_p);
/* Roll over carry bits */
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
/* Return checksum */
return((u_short) ~sum);
}