Bug 102747 - Bad code when compiling ip_vs_core.c
Summary: Bad code when compiling ip_vs_core.c
Alias: None
Product: Red Hat Linux
Classification: Retired
Component: gcc   
(Show other bugs)
Version: 9
Hardware: i686
OS: Linux
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact: Brian Brock
Depends On:
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:
Story Points: ---
Clone Of:
Last Closed: 2003-08-29 14:26:23 UTC
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---

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:

	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
	testl	%edx, %edx
	movl	$1, %eax
	jne	.L374
	cmpb	$1, 9(%ebx)
	je	.L428
	addl	$12, %esp
	popl	%ebx
	popl	%esi
	popl	%edi
	popl	%ebp
	.p2align 2,,3
	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):

How reproducible:

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;

foo (unsigned short x)

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

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;

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.