optimization/7291: off-by-one in generated inline bzero code for i386 (64bit)
fvdl@wasabisystems.com
fvdl@wasabisystems.com
Fri Jul 12 13:36:00 GMT 2002
>Number: 7291
>Category: optimization
>Synopsis: off-by-one in generated inline bzero code for i386 (64bit)
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: unassigned
>State: open
>Class: wrong-code
>Submitter-Id: net
>Arrival-Date: Fri Jul 12 13:16:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator: Frank van der Linden
>Release: 3.1.1 20020711 (prerelease)
>Organization:
Wasabi Systems, Inc.
>Environment:
System: NetBSD k2 1.6A NetBSD 1.6A (K2) #0: Mon Jul 8 00:59:23 CEST 2002 fvdl@k2:/work/trees/empee/sys/arch/i386/compile/K2 i386
host: i386-unknown-netbsdelf1.6A
build: i386-unknown-netbsdelf1.6A
target: x86_64--netbsd
configured with: ../../toolchain/gcc-3-1-branch/configure --target=x86_64--netbsd --with-gnu-ld --with-gas --enable-languages=c c++ --disable-shared --prefix=/work/fvdl/toolchain
>Description:
When inlining a call to bzero, gcc 3.1(.1) and gcc-current can some-
times (depending how much it knows about alignment) generate incorrect
code for a 64bit i386 (x86-64) target. The code that zeroes out the
leftover bytes (i.e. bytes left to zero out after a multiple of 8
has been done) tests for the wrong bit in the number of bytes left.
>How-To-Repeat:
Consider the following program:
====================================================
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int
foo(int n)
{
unsigned ia[64];
int i;
if (n > 64)
return;
for (i = 0; i < 64; i++)
ia[i] = 0xdeadbeef;
bzero(ia, n * sizeof (unsigned));
for (i = 0; i < n; i++) {
if (ia[i] != 0) {
printf("index %d is %x, should be 0\n", i, ia[i]);
return -1;
}
}
return 0;
}
int
main(int argc, char **argv)
{
if (argc != 2)
exit(1);
if (foo(atoi(argv[1])) < 0)
printf("check failed\n");
else
printf("check ok\n");
return 0;
}
==================================================
When compiled with -O, it shows the off-by-one (in units of 4 bytes)
error:
$ uname -srm
NetBSD 1.6D x86_64
$ ./a.out 31
index 30 is deadbeef, should be 0
check failed
$ ./a.out 32
check ok
$ ./a.out 33
index 32 is deadbeef, should be 0
check failed
$ ./a.out 34
check ok
$
>Fix:
The following change to gcc/config/i386/i386.c fixes it:
*** i386.c.orig Thu Jul 11 21:45:55 2002
--- i386.c Fri Jul 12 22:12:23 2002
***************
*** 9493,9499 ****
gen_rtx_SUBREG (SImode, zeroreg, 0)));
if (TARGET_64BIT && (align <= 4 || count == 0))
{
! rtx label = ix86_expand_aligntest (countreg, 2);
emit_insn (gen_strsetsi (destreg,
gen_rtx_SUBREG (SImode, zeroreg, 0)));
emit_label (label);
--- 9493,9499 ----
gen_rtx_SUBREG (SImode, zeroreg, 0)));
if (TARGET_64BIT && (align <= 4 || count == 0))
{
! rtx label = ix86_expand_aligntest (countreg, 4);
emit_insn (gen_strsetsi (destreg,
gen_rtx_SUBREG (SImode, zeroreg, 0)));
emit_label (label);
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the Gcc-bugs
mailing list