Re: -mregparm=3

Benjamin C.R. LaHaise (blah@kvack.org)
Wed, 8 Jul 1998 13:13:54 -0400 (EDT)


On 8 Jul 1998, Ulrich Drepper wrote:

> "Benjamin C.R. LaHaise" <blah@kvack.org> writes:
>
> > <sigh> It's a wonderful idea that really cuts down on the cost of function
> > calls quite a bit, but alas, neither gcc nor egcs work even vaguely
> > reliably with the -mregparm option.
>
> I'm using regparm (using attributes, though) in glibc 2.1 on Intel and
> it does work. Don't spread these wrong information.

Compile the following snippet of code as indicated, and then read the
assembly generated. If you want to run the risk of bad code being
generated, fine -- but I'd rather not.

-ben

/* gcc_regparm_bug.c (gcc 2.7.2.1 on i486-linux)
*
* Compile with
* gcc -O2 -S -mregparm=3 -fomit-frame-pointer bar.c
* and take a look at the code generated for the indicated line.
* This code is based on drivers/net/8390.c from linux v2.1.27
*
* Output of 'gcc -v':
* Reading specs from /usr/lib/gcc-lib/i486-linux/2.7.2.1/specs
* gcc version 2.7.2.1
*/

struct device {
unsigned short base_addr;
void *priv;
};

struct e8390_pkt_hdr {
int count;
};

struct ei_device {
int a, b;
void (*get_8390_hdr)(struct device *, struct e8390_pkt_hdr *, int);
};

#define ei_get_8390_hdr (ei_local->get_8390_hdr)

unsigned char foo ( int );
void bar ( void *, ... );

static inline unsigned char inb ( unsigned short port )
{
unsigned char res;
__asm__("inb %%dx,%%al" : "=a" (res) : "d" (port));
return res;
}

void ei_receive(struct device *dev)
{
int e8390_base = dev->base_addr;
struct ei_device *ei_local = dev->priv;
unsigned char this_frame, next_frame;
int rx_pkt_count = 0;
struct e8390_pkt_hdr rx_frame;

while (++rx_pkt_count < 10) {
this_frame = inb(e8390_base + 1) + 1;
ei_get_8390_hdr(dev, &rx_frame, this_frame); /* bad code generated for this function call */
next_frame = this_frame + 1;
bar(&next_frame);
}
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu