Bug 11635 - [3.3/3.4 regression] Unnecessary store onto stack
Summary: [3.3/3.4 regression] Unnecessary store onto stack
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 3.3
: P3 enhancement
Target Milestone: 3.4.0
Assignee: Jan Hubicka
URL:
Keywords: missed-optimization
Depends on:
Blocks:
 
Reported: 2003-07-22 21:16 UTC by Debian GCC Maintainers
Modified: 2004-01-17 04:22 UTC (History)
1 user (show)

See Also:
Host: i386-linux
Target:
Build: i386-linux
Known to work:
Known to fail:
Last reconfirmed: 2003-12-19 05:35:24


Attachments
preprocessed source (3.46 KB, application/gzip)
2003-07-22 21:17 UTC, Debian GCC Maintainers
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Debian GCC Maintainers 2003-07-22 21:16:11 UTC
[forwarded from http://bugs.debian.org/202016]

seen in 3.2, 3,3 and current HEAD, "regression" from 2.95

#include <sys/socket.h>

int
main(void)
{
	struct sockaddr_storage from;
	struct sockaddr *const fromp = (void *)&from;
	socklen_t fromlen;

	fromlen = sizeof(from);
 
	if (getpeername(0, fromp, &fromlen) < 0) {
		return 1;
	}

	return 0;
}

If you compile it with

gcc -D_GNU_SOURCE -S -O2

you will get

        .file   "bug-202016.c"
        .text
        .p2align 2,,3
.globl main
        .type   main, @function
main:
        pushl   %ebp
        movl    %esp, %ebp
        leal    -144(%ebp), %eax
        subl    $156, %esp
        leal    -136(%ebp), %edx
        pushl   %eax
        pushl   %edx
        pushl   $0
        movl    $128, -144(%ebp)
        movl    %edx, -140(%ebp)
        call    getpeername
        shrl    $31, %eax
        addl    $16, %esp
        leave
        ret
        .size   main, .-main
        .section        .note.GNU-stack,"",@progbits
        .ident  "GCC: (GNU) 3.4 20030722 (experimental)"


The store into -140(%ebp) is useless.

This does not occur if you remove the -D_GNU_SOURCE, so this is related
to the __SOCKADDR_ARG magic in sys/socket.h.  I can reproduce this with
gcc 3.2.  gcc 2.95 does not have this problem.
Comment 1 Debian GCC Maintainers 2003-07-22 21:17:18 UTC
Created attachment 4454 [details]
preprocessed source
Comment 2 Andrew Pinski 2003-07-22 22:58:20 UTC
I can confirm this on 3.0.4, 3.2.3 (those both which produces worse code than 3.3.1 and the 
mainline), and 3.3.1 (20030707) and the mainline (20030719).
gcc 3.3.1 and the mainline  produces better code for after the call to getpeername.  Also before 
the call, there are the same number of instructions.
Note the store also happens when -march=i686.
It also happens on powerpc.  

Looks like the ABI changed!!
Comment 3 Andrew Pinski 2003-07-22 22:59:40 UTC
I forgot to attach the reduced sources:
typedef unsigned int __uint32_t;
typedef unsigned int __socklen_t;
typedef __socklen_t socklen_t;

typedef unsigned short int sa_family_t;

struct sockaddr
  {
    sa_family_t sa_family;
    char sa_data[14];
  };
struct sockaddr_storage
  {
    sa_family_t ss_family;
    __uint32_t __ss_align;
    char __ss_padding[(128 - (2 * sizeof (__uint32_t)))];
  };

typedef union { struct sockaddr *__restrict __sockaddr__; struct sockaddr_at *__restrict 
__sockaddr_a
t__; struct sockaddr_ax25 *__restrict __sockaddr_ax25__; struct sockaddr_dl *__restrict 
__sockaddr_dl
__; struct sockaddr_eon *__restrict __sockaddr_eon__; struct sockaddr_in *__restrict 
__sockaddr_in__;
 struct sockaddr_in6 *__restrict __sockaddr_in6__; struct sockaddr_inarp *__restrict 
__sockaddr_inarp
__; struct sockaddr_ipx *__restrict __sockaddr_ipx__; struct sockaddr_iso *__restrict 
__sockaddr_iso_
_; struct sockaddr_ns *__restrict __sockaddr_ns__; struct sockaddr_un *__restrict __sockaddr_un__; 
st
ruct sockaddr_x25 *__restrict __sockaddr_x25__;
       } __SOCKADDR_ARG __attribute__ ((__transparent_union__));
extern int getpeername (int __fd, __SOCKADDR_ARG __addr,
   socklen_t *__restrict __len) ;


int
main(void)
{
 struct sockaddr_storage from;
 struct sockaddr *const fromp = (void *)&from;
 socklen_t fromlen;

 fromlen = sizeof(from);

 if (getpeername(0, fromp, &fromlen) < 0) {
  return 1;
 }

 return 0;
}
Comment 4 Jan Hubicka 2004-01-10 13:03:28 UTC
Not really ABI change.  GCC just overactively assign stack to cast into union. 
I am testing fix for this.
Comment 5 Andrew Pinski 2004-01-10 21:06:47 UTC
Fixed for 3.4 by:
 2004-01-10  Jan Hubicka  <jh@suse.cz>
	PR opt/11635
 	* expr.c (expand_expr_real):  More curefully expand union casts.