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