This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Extending constraints using register subclasses

Jamie Prescott schrieb:
Thank you Andrew, I wasn't aware of that. Will be going that way.
Just out of curiosity, was there something flawed in the way I took before?
Meaning, could have been done that way, but my code was wrong somewhere?

- Jamie

----- Original Message ----

From: Andrew Pinski <>
To: Jamie Prescott <>
Sent: Monday, May 11, 2009 4:47:57 PM
Subject: Re: Extending constraints using register subclasses

On Mon, May 11, 2009 at 4:45 PM, Jamie Prescott wrote:

I wanted to add finer (one per) register subclasses, so that I can more finely
the register placement inside the inline assembly.

You don't need that. You can just use asm("registername") on variables. like so:

int f(int a)
 register int r0 __asm__("r0");
 asm("use %0": "+r"(r0) );

Andrew Pinski

That works with gcc 3.x but causes trouble and won't work smooth with gcc 4.x.

Here are just two examples that will crash for target AVR:

// ice.c ////////////////////////////////////////////////
typedef union
    unsigned char  asByte[2];
    unsigned short asWord;
} data16_t;

data16_t mac10 (data16_t);

void put_sfrac16 (data16_t q)
    unsigned char i;
    for (i=0; i < 2; i++)
        register data16_t digit asm ("r24");
        digit.asByte[1] = 0;

        digit.asByte[0] = q.asByte[0];
        digit = mac10 (digit);
        q.asByte[0] = digit.asByte[0];

compiling this with
> avr-gcc ice.c -Os -S
rund into ICE in fwprop:

ice.c: In function 'put_sfrac16':
ice.c:21: internal compiler error: in propagate_rtx, at fwprop.c:469

> GNU C (WinAVR 20090313) version 4.3.2 (avr) compiled by GNU C
> version 3.4.5 (mingw-vista special r3), GMP version 4.2.3,
> MPFR version 2.4.0.

The second example shows that global register variables are pretty much useless in gcc 4.x. I am using global registers in gcc 3.4.6 and it work smooth. Without global regs I would have to pay considerable performance penalties, so I am still using avr-gcc 3.4.6 (which produces code that is both faster and smaller than code from any avr-gcc 4.x I tested so far: from 4.1 up to 4.5). Here it is:

// bug.c ///////////////////////////////////////////////
// avr-gcc bug.c -Os -S -ffixed-2 -ffixed-3

register unsigned int currData asm ("r2");

// from <inttypes.h>
typedef unsigned int uint8_t __attribute__((__mode__(__QI__)));

// from <avr/io.h>
#define PINB (*(volatile uint8_t *)(0x16 + 0x20))
#define PORTB (*(volatile uint8_t *)(0x18 + 0x20))

// from <avr/interrupt.h>
void __vector_1 (void) __attribute__ ((signal,used,externally_visible));
void __vector_1 (void)
    // Nothing special, just an ISR that depends on currData
    if (currData & 0x4000)
        PORTB |= 2;
        PORTB &= ~2;

    currData = currData << 1;

void foo (void)
    for (;;)
        while (PINB & 1);
        currData = 0x2123;
        while (!(PINB & 1));

CSE decides that currData in foo is dead. As everyone can see, the produced assembler does not touch the global register R3:R2. Making global reg vars volatile is iseless (gcc goesn' even warn about that and gcc doesn't even have a flag to tag a global reg volatile).

There are just (conditional) branches left that jump around and poll SFRs:

/* prologue: function */
/* frame size = 0 */
	sbic 54-32,0	 ;  12	*sbix_branch	[length = 2]
	rjmp .L13
	sbis 54-32,0	 ;  22	*sbix_branch	[length = 2]
	rjmp .L10
	rjmp .L13	 ;  50	jump	[length = 1]
	.size	foo, .-foo

Global register variables can boost performance in embedded applications. It's a pitty that this is pretty much useless in "modern" gcc 4.x.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]