This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
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 <pinskia@gmail.com>
To: Jamie Prescott <jpresss@yahoo.com>
Cc: gcc@gcc.gnu.org
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:
Hi!
I wanted to add finer (one per) register subclasses, so that I can more finely
control
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) );
}
Thanks,
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;
else
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:
foo:
/* prologue: function */
/* frame size = 0 */
.L13:
sbic 54-32,0 ; 12 *sbix_branch [length = 2]
rjmp .L13
.L10:
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.
Georg-Johann