This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: inline asm in an inline function
- To: Geoff Keating <geoffk at geoffk dot org>
- Subject: Re: inline asm in an inline function
- From: Aldy Hernandez <aldyh at redhat dot com>
- Date: 07 Jun 2001 12:11:57 +0100
- Cc: gcc at gcc dot gnu dot org
- References: <991761446.2753.26.camel.cygnus.gcc@culebra.cygnus.com><jmn17m6df9.fsf@geoffk.org>
>>>>> "Geoff" == Geoff Keating <geoffk@geoffk.org> writes:
> aldyh@redhat.com (Aldy Hernandez) writes:
>> a customer is having problems with some inline asms. they have the
>> following code that is supposed to clobber %r4:
>>
>> unsigned inline flying_carpet( ) {
>> unsigned tmp ;
>> asm (" mfmsr %0;"
>> " rlwinm %%r4,%0,0,17,15;"
>> " mtmsr %%r4"
>> : "=r" (tmp) /* outputs */
>> : /* no inputs */
>> : "%r4", "%r5" /* trashes r4 */); <-- clobber %r4, %r5 please
>> return (int) tmp;
>> }
>>
>> however, gcc doesn't respect that and expects %r4 to be live across the
>> asm:
>>
>> lwz %r0,0(%r4) <-- use of %r4
>> cmpwi %cr0,%r0,-1
>> bc 12,2,.L7
>> mfmsr %r29; rlwinm %r4,%r29,0,17,15; mtmsr %r4
>> .L8:
>> lwz %r0,0(%r4) <-- use of r4 (boo hiss!)
>>
>> is this actually a bug, or should they be using "asm volatile" (cuz that
>> for sure fixes the problem)?
> That seems to be a bug. Most likely, the '%' is confusing GCC.
Actually, I don't think that's the case.
gcc translates the above into:
(insn/i 79 78 80 (parallel[
(set (reg/v:SI 90)
(asm_operands (" mfmsr %0; rlwinm %%r4,%0,0,17,15; mtmsr
%%r4") ("=r") 0[ ]
[ ] ("test.cc") 8))
(clobber (reg:QI 5 r5))
(clobber (reg:QI 4 r4))
] ) -1 (nil)
(nil))
the clobbers are exactly what we need, however later on, scan_loop wants
to combine these two insns:
(insn/i 79 78 80 (parallel[
(set (reg/v:SI 90)
(asm_operands (" mfmsr %0; rlwinm %%r4,%0,0,17,15; mtmsr
%%r4") ("=r") 0[ ]
[ ] ("test.cc") 8))
(clobber (reg:QI 5 r5))
(clobber (reg:QI 4 r4))
] ) -1 (nil)
(nil))
(insn/i 80 79 83 (set (reg/v:SI 89)
(reg/v:SI 90)) 541 {movsi+1} (nil)
(nil))
the code in loop that wants to do it is around this:
Therefore, if this register is marked as being used exactly
once if we are in a loop with calls (a "large loop"),see if
we can replace the usage of this register with the source
of this SET. If we can, delete this insn.
the prob is that replace_rtx() is called with a "to" of:
(asm_operands (" mfmsr %0; rlwinm %%r4,%0,0,17,15; mtmsr %%r4") ("=r")
0[ ]
[ ] ("test.cc") 8)
we have lost our clobbers (!@#$), because scan_loop did:
if (GET_CODE (p) == INSN
&& (set = single_set (p)) <-- single_set(), boo hiss
and single_set ripped the original parallel of the clobbers because
that is what single_set is supposed to do.
so.. what should i do?
i'm thinking i can:
1. save the clobbers, or whatever follows the set in a parallel
2. do the replace_rtx
3. parallelize the replaced insn and add the clobbers to the resulting
insn.
so basically, remember what was clobbered and add it later after
scan_loop combined the insns.
ideas welcome.
cheers
aldy
--
Aldy Hernandez E-mail: aldyh@redhat.com
Professional Gypsy
Red Hat, Inc.