The recently pushed hreg-constraints (HRCs) feature has this in
the docs:
<docs>
register asm may not only be clobbered by function calls but also by
inline asm in conjunction with hard register constraints. For example,
in the following
register int x asm ("r5") = 42;
int y;
asm ("" : "={r5}" (y));
asm ("" : "+r" (x));
variable x materializes before the very first inline asm which writes to
register r5 and therefore clobbers x which in turn is read by the
subsequent inline asm.
</docs>
As far as I understand this is quite different from local reg vars,
which are only applied when they are an operand to an inline asm. I.e.
register int x __asm ("r5") = 42;
does NOT mean that x lives in r5 throughout the function, but only that
x lives in r5 in places where x is an operand to an inline asm.
On places other that inline asm that refers x, x is treated just like
a local variable (e.g. across function calls or across asm that doesn't
reference x).
Take this example on AVR:
char func (char x) // incoming r24
{
register char z __asm("24") = x + 1;
__asm ("; clobber r24" ::: "24");
__asm ("inc %0" : "+r" (z));
return x; // returning in r24
}
The 1st asm is clobbering r24, and therefore x must not be kept in
r24 at that point. This is demonstrated by the generated code:
$ avr-gcc asm.c -S -Os -dp
func:
mov r25,r24 ; 20 [c=4 l=1] movqi_insn/0
/* #APP */
; clobber r24
/* #NOAPP */
mov r24,r25 ; 21 [c=4 l=1] movqi_insn/0
/* #APP */
inc r24
/* #NOAPP */
ret ; 24 [c=0 l=1] return
As you can see, insn 20 moves r24 to r25 so it doesn't collide with
the inline asm that clobbers r24.
Replacing the clobber with
__asm volatile ("; clobber %0" : "={r24}" (tmp));
Gives the same code, so I wonder why HRCs are so much weaker than local
reg vars?
I think I saw some discussion on the HRC threads and problems in gimple,
thougjh I wonder why gimple deals with hard regs to begin with?
Then I think this feature (or the absence of it) is a can of worms,
because you cannot just port local reg vars to HRCs.
Johann