This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
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
> typedef unsigned int uint8_t __attribute__((__mode__(__QI__)));
>
> // from
> #define PINB (*(volatile uint8_t *)(0x16 + 0x20))
> #define PORTB (*(volatile uint8_t *)(0x18 + 0x20))
>
> // from
> 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.
Oh, this is bad news :/
Is the problem only with global register allocations, or even with local ones?
Wouldn't the approach of having register subclasses and handling them with ad-hoc contraints
(like the road I took before) be a more universally working solution?
- Jamie