Bug 102747 - Bad code when compiling ip_vs_core.c
Summary: Bad code when compiling ip_vs_core.c
Keywords:
Status: CLOSED RAWHIDE
Alias: None
Product: Red Hat Linux
Classification: Retired
Component: gcc
Version: 9
Hardware: i686
OS: Linux
medium
high
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact: Brian Brock
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2003-08-20 16:00 UTC by r6144
Modified: 2007-04-18 16:57 UTC (History)
0 users

Fixed In Version: 3.2.3-17
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2003-08-29 14:26:23 UTC
Embargoed:


Attachments (Terms of Use)
Preprocessed test case, bzip2'd (85.45 KB, application/octet-stream)
2003-08-20 16:02 UTC, r6144
no flags Details

Description r6144 2003-08-20 16:00:16 UTC
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (X11; U; Linux i686) Gecko/20030610 Galeon/1.3.7

Description of problem:
When compiling net/ipv4/ipvs/ip_vs_core.c in linux 2.6.0-test3 (with user-mode
linux patch, ARCH=um), wrong code is generated for the function ip_vs_in().  

The preprocessed file is attached, and the assembly can be generated with

gcc -O2 -fno-strict-aliasing -fomit-frame-pointer -S -o out.s out.i

The relevent part of the generated assembly code are as follows:

ip_vs_in:
	pushl	%ebp
	pushl	%edi
	pushl	%esi
	pushl	%ebx
	subl	$24, %esp
	movl	48(%esp), %ebp
	movl	(%ebp), %esi
	movl	36(%esi), %ebx
	movzbl	9(%ebx), %eax
	pushl	%eax
	call	ip_vs_proto_get
	xorl	%edx, %edx
	cmpb	$0, 114(%esi)
	movl	%eax, %edi
	jne	.L378
	cmpl	$loopback_dev, 24(%esi)
	je	.L378
.L377:
	testl	%edx, %edx
	movl	$1, %eax
	jne	.L374
	cmpb	$1, 9(%ebx)
	je	.L428
.L380:
[snip]
.L374:
	addl	$12, %esp
	popl	%ebx
	popl	%esi
	popl	%edi
	popl	%ebp
	ret
	.p2align 2,,3
[snip]
.L378:
	movl	$1, %edx
	jmp	.L377

When the path .L378->.L377->.L374 is followed (corresponding to taking the first
"if" and return in the C function), it is obvious that %esp had a net decrease
by 16, so the function will return to the wrong spot.

I have not tried rawhide, but gcc-ssa-3.5ssa-0.20030617.24 generates correct
code using the same options.

Version-Release number of selected component (if applicable):
gcc-3.2.2-5

How reproducible:
Always

Steps to Reproduce:
1. Download the attached file, decompress as out.i
2. Run "gcc -O2 -fno-strict-aliasing -fomit-frame-pointer -S -o out.s out.i"
with gcc-3.2.2-5.
3. Search for "ip_vs_in:" in out.s and observe the results.

Actual Results:  The wrong code as shown above, crashing the final program.

Expected Results:  Correct code.  %esp should not change between function entry
and exit.

Additional info:

Comment 1 r6144 2003-08-20 16:02:01 UTC
Created attachment 93781 [details]
Preprocessed test case, bzip2'd

out.i attached here.

Comment 2 Jakub Jelinek 2003-08-25 15:42:12 UTC
Reduced into:

/* { dg-do run } */
/* { dg-options "-O2 -fomit-frame-pointer" } */
/* { dg-options "-O2 -fomit-frame-pointer -march=i386" { target i?86-*-* } } */

extern void abort (void);
extern void exit (int);

struct S
{
  int *a;
  unsigned char *b, c;
};

int v;

void
foo (unsigned short x)
{
}

int
bar (struct S **x, int *y)
{
  *y = 25;
  return 0;
}

int
baz (struct S **x)
{
  struct S *y = *x;
  unsigned char *a = y->b;

  foo (*a);

  if (__builtin_expect (y->c != 0 || y->a == &v, 0))
    return 1;

  if (__builtin_expect (*a == 1, 0))
    {
      int a, b = bar (x, &a);

      if (a)
        return b;
    }

  return 0;
}

int
main (void)
{
  struct S a, *b = &a;
  unsigned char c;

  __builtin_memset (b, 0, sizeof (a));
  a.a = &v;
  a.b = &c;
  if (baz (&b) != 1)
    abort ();
  exit (0);
}

Seems to be broken on gcc-3_2-rhl8-branch and fixed on gcc-3_3-rhl-branch.


Note You need to log in before you can comment on or make changes to this bug.