public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* TMSC320C6x port: return label is being deleted
@ 2004-09-14 17:24 Adrian Strätling
  2004-09-14 18:50 ` Graham Stott
  0 siblings, 1 reply; 8+ messages in thread
From: Adrian Strätling @ 2004-09-14 17:24 UTC (permalink / raw)
  To: gcc

Hi all,

I'm currently trying to optimize a gcc port for the TI TMS320C6x chips. 
My predecessor in this task built a port for gcc 3.3. I updated it to 
the 3.5 version to benefit from general development.

Now I have the following problem:

This architecture does not have a specific call instruction, so we had 
to produce the following code:

"
push    ret_label
move   b_label, breg
branch   breg

ret_label:
    ...
"

so the callee can pop the return address from the stack and jump there.
In gcc version 3.3 after jump optimization 'ret_label' is present as a 
CODE_LABEL_DELETED_INSN,
but in version 3.5 I can't find it

3.3:
"
(insn 19 17 20 0 0x4021bf78 (set:SI (reg/f:SI 0 a0 [72])
        (label_ref:SI [23 deleted])) 0 {movsi} (nil)
    (insn_list:REG_LABEL 23 (nil)))

(insn 20 19 21 0 0x4021bf78 (set:SI (reg/f:SI 47 b15)
        (plus:SI (reg/f:SI 47 b15)
            (const_int -4 [0xfffffffc]))) 5 {*addsi3_prologue} (nil)
    (nil))

(insn 21 20 48 0 0x4021bf78 (set:SI (mem:SI (reg/f:SI 47 b15) [0 S4 A32])
        (reg/f:SI 0 a0 [72])) 0 {movsi} (nil)
    (nil))

(insn 48 21 22 0 (nil) (set (reg:SI 0 a0)
        (symbol_ref:SI ("nop"))) 0 {movsi} (nil)
    (nil))

(call_insn 22 48 23 0 0x4021bf78 (call (mem:QI (reg:SI 0 a0) [0 S1 A8])
        (const_int 0 [0x0])) 3 {*call_internal} (nil)
    (expr_list:REG_EH_REGION (const_int 0 [0x0])
        (nil))
    (nil))

(note 23 22 27 0 "" NOTE_INSN_DELETED_LABEL 5)
"

3.5
"
(insn 41 15 17 1 (set (reg:SI 36 b4)
        (label_ref:SI 19)) 2 {*movsi_big} (nil)
    (nil))

(insn 17 41 42 1 (set (mem:SI (pre_dec:SI (reg/f:SI 47 b15)) [0 S4 A32])
        (reg:SI 36 b4)) 3 {movsi} (nil)
    (insn_list:REG_LABEL 19 (nil)))

(insn 42 17 18 1 (set (reg:SI 36 b4)
        (symbol_ref:SI ("nop") [flags 0x3] <function_decl 0x402965e4 
nop>)) 2 {*movsi_big} (nil)
    (nil))

(call_insn 18 42 21 1 (call (mem:QI (reg:SI 36 b4) [0 S1 A8])
        (const_int 0 [0x0])) 6 {*call_internal} (nil)
    (expr_list:REG_EH_REGION (const_int 0 [0x0])
        (nil))
    (nil))
"

The differences in 'push' are the result of other changes. I don't think 
they matter here.

I have been able to avoid the deletion of the label by changing:
"emit_label (ret_label);"
into
"LABEL_PRESERVE_P( emit_label (ret_label) ) = 1;"
but on the one hand I don't think that's the way it has been meant (no 
one else does so) and on the other it only works without optimization. 
The scheduler would move the label next to the function label. I guess 
it handles it not as a code_label but as a note when it does so.

Does anyone know a solution to this?

Thanks in advance,

greets,
Adrian Strätling

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: TMSC320C6x port: return label is being deleted
  2004-09-14 17:24 TMSC320C6x port: return label is being deleted Adrian Strätling
@ 2004-09-14 18:50 ` Graham Stott
  2004-09-16 18:03   ` Adrian Strätling
  0 siblings, 1 reply; 8+ messages in thread
From: Graham Stott @ 2004-09-14 18:50 UTC (permalink / raw)
  To: Adrian_Strätling, gcc

Adrain,

 --- Adrian_Strätling <adrian.straetling@cs.tu-chemnitz.de> wrote: 
> Hi all,
> 
>
[snip]
> This architecture does not have a specific call instruction, so we had 
> to produce the following code:
> 
> "
> push    ret_label
> move   b_label, breg
> branch   breg
> 
> ret_label:
>     ...
> "
Yep this label is going to go walkies because it doesn't appear in the CFG.

> 
> so the callee can pop the return address from the stack and jump there.
> In gcc version 3.3 after jump optimization 'ret_label' is present as a 
> CODE_LABEL_DELETED_INSN,
> but in version 3.5 I can't find it
>
[snip] 
> 
You've just been lucky with 3.3

> I have been able to avoid the deletion of the label by changing:
> "emit_label (ret_label);"
> into
> "LABEL_PRESERVE_P( emit_label (ret_label) ) = 1;"
> but on the one hand I don't think that's the way it has been meant (no 
> one else does so) and on the other it only works without optimization. 
> The scheduler would move the label next to the function label. I guess 
> it handles it not as a code_label but as a note when it does so.
>
That *will* keep the label but it won't keep it in the right place!
 
> Does anyone know a solution to this?
Yes, The optimizers, etc don't need or want to know about this label it's an
artifact of your call sequence, so keep it hidden.

You only need a label to appear in the generated .s file so your call
pattern can take care of making one up when the time comes to output your
call fragment.

> 
> Thanks in advance,
> 
> greets,
> Adrian Strätling
> 

Graham  

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: TMSC320C6x port: return label is being deleted
  2004-09-14 18:50 ` Graham Stott
@ 2004-09-16 18:03   ` Adrian Strätling
  2004-09-16 18:30     ` Graham Stott
  0 siblings, 1 reply; 8+ messages in thread
From: Adrian Strätling @ 2004-09-16 18:03 UTC (permalink / raw)
  To: GCC

Hi,

Graham Stott wrote:

>You only need a label to appear in the generated .s file so your call
>pattern can take care of making one up when the time comes to output your
>call fragment.
>  
>
Ok,

can I somehow attach the label to the call insn, so that the output 
function can get the label number and print it?
I tried:
"
insn = gen_rtx_CALL (VOIDmode, mem, const0_rtx);
emit_call_insn(insn);
emit_label(ret_label);
REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, ret_label, 
REG_NOTES(insn));
LABEL_NUSES(ret_label)++;
"

which results in RTL:
"
(insn 17 15 18 2 (set (mem:SI (pre_dec:SI (reg/f:SI 47 b15)) [0 S4 A32])
        (label_ref:SI 19)) -1 (nil)
    (insn_list:REG_LABEL 19 (nil)))

(call_insn 18 17 19 2 (call (mem:QI (symbol_ref:SI ("nop") [flags 0x3] 
<function_decl 0x401d45e4 nop>) [0 S1 A8])
        (const_int 0 [0x0])) -1 (nil)
    (expr_list:REG_EH_REGION (const_int 0 [0x0])
        (nil))
    (nil))

(code_label 19 18 34 3 5 "" [1 uses])
"

It seems I have to emit the label to get the REFs right.
However, I miss the the "REG_LABEL  19" in the insn list of the call insn.

Another approach would be to walk the dependency list at the time of 
output, but I'd rather prefer the first one.

Thanks,
Adrian

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: TMSC320C6x port: return label is being deleted
  2004-09-16 18:03   ` Adrian Strätling
@ 2004-09-16 18:30     ` Graham Stott
  2004-09-18 21:21       ` Adrian Strätling
  2004-10-04 13:37       ` Nick Ing-Simmons
  0 siblings, 2 replies; 8+ messages in thread
From: Graham Stott @ 2004-09-16 18:30 UTC (permalink / raw)
  To: Adrian Strätling, GCC

Hi,

 --- Adrian Strätling <adrian.straetling@cs.tu-chemnitz.de> wrote: 
> Hi,
> 
> Graham Stott wrote:
> 
> >You only need a label to appear in the generated .s file so your call
> >pattern can take care of making one up when the time comes to output your
> >call fragment.
> >  
> >
> Ok,
> 
> can I somehow attach the label to the call insn, so that the output 
> function can get the label number and print it?
Not you are looking at it from the wrong angle.

> I tried:
> "
> insn = gen_rtx_CALL (VOIDmode, mem, const0_rtx);
> emit_call_insn(insn);
> emit_label(ret_label);
> REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, ret_label, 
> REG_NOTES(insn));
> LABEL_NUSES(ret_label)++;
> "
You don't need/want all the stuff after after your emit_call_insn

> 
> which results in RTL:
> "
> (insn 17 15 18 2 (set (mem:SI (pre_dec:SI (reg/f:SI 47 b15)) [0 S4 A32])
>         (label_ref:SI 19)) -1 (nil)
>     (insn_list:REG_LABEL 19 (nil)))
> 
> (call_insn 18 17 19 2 (call (mem:QI (symbol_ref:SI ("nop") [flags 0x3] 
> <function_decl 0x401d45e4 nop>) [0 S1 A8])
>         (const_int 0 [0x0])) -1 (nil)
>     (expr_list:REG_EH_REGION (const_int 0 [0x0])
>         (nil))
>     (nil))
> 
> (code_label 19 18 34 3 5 "" [1 uses])
> "
> 
> It seems I have to emit the label to get the REFs right.
> However, I miss the the "REG_LABEL  19" in the insn list of the call insn.
> 
> Another approach would be to walk the dependency list at the time of 
> output, but I'd rather prefer the first one.
No you are making life hard for yourself it;s much easier that you think
do it all in your define_insn for the call.

In your define_insn for your call you use something like.
(define_insn "..."
  []
  ""
{
  rtx label = gen_label_rtx ();

  output your call sequence
  ..

  now output the label
  
  return "";
}

See how the rest of the compiler doesn't know or care
about these labels.

> 
> Thanks,
> Adrian
>  

Graham

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: TMSC320C6x port: return label is being deleted
  2004-09-16 18:30     ` Graham Stott
@ 2004-09-18 21:21       ` Adrian Strätling
  2004-10-04 13:37       ` Nick Ing-Simmons
  1 sibling, 0 replies; 8+ messages in thread
From: Adrian Strätling @ 2004-09-18 21:21 UTC (permalink / raw)
  To: GCC

Graham Stott wrote:

>Hi,
>
> --- Adrian Strätling <adrian.straetling@cs.tu-chemnitz.de> wrote: 
>  
>
>>can I somehow attach the label to the call insn, so that the output 
>>function can get the label number and print it?
>>    
>>
>Not you are looking at it from the wrong angle.
>
>  
>
>>I tried:
>>"
>>insn = gen_rtx_CALL (VOIDmode, mem, const0_rtx);
>>emit_call_insn(insn);
>>emit_label(ret_label);
>>REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, ret_label, 
>>REG_NOTES(insn));
>>LABEL_NUSES(ret_label)++;
>>"
>>    
>>
>You don't need/want all the stuff after after your emit_call_insn
>
>  
>
>>which results in RTL:
>>"
>>(insn 17 15 18 2 (set (mem:SI (pre_dec:SI (reg/f:SI 47 b15)) [0 S4 A32])
>>        (label_ref:SI 19)) -1 (nil)
>>    (insn_list:REG_LABEL 19 (nil)))
>>
>>(call_insn 18 17 19 2 (call (mem:QI (symbol_ref:SI ("nop") [flags 0x3] 
>><function_decl 0x401d45e4 nop>) [0 S1 A8])
>>        (const_int 0 [0x0])) -1 (nil)
>>    (expr_list:REG_EH_REGION (const_int 0 [0x0])
>>        (nil))
>>    (nil))
>>
>>(code_label 19 18 34 3 5 "" [1 uses])
>>"
>>
>>It seems I have to emit the label to get the REFs right.
>>However, I miss the the "REG_LABEL  19" in the insn list of the call insn.
>>
>>Another approach would be to walk the dependency list at the time of 
>>output, but I'd rather prefer the first one.
>>    
>>
>No you are making life hard for yourself it;s much easier that you think
>do it all in your define_insn for the call.
>
>In your define_insn for your call you use something like.
>(define_insn "..."
>  []
>  ""
>{
>  rtx label = gen_label_rtx ();
>
>  output your call sequence
>  ..
>
>  now output the label
>  
>  return "";
>}
>
>See how the rest of the compiler doesn't know or care
>about these labels.
>
>  
>
Thanks.
This is a solution for the problem, but I'd really like to find a better 
(faster) one.
Pleas, let me explain why I do not really want to do it that way. :)

This call sequence would look like:
   mvkl   L5   a0      ; move low part of return address
|| mvkl   foo  b0      ; move low part of function address
   mvkh   L5   a0      ; move high part of return address
|| mvkh   foo  b0      ; move high part of function address
   b      b0           ; call function
   stw    a0   *--b15  ; push return address onto stack (delay slot 1)
   nop    4            ; delay slots 2 - 5  (banch has 5)
L5:

This is the shortest sequence I can momentarily think of (6 insns, 8 
cycles).
The architecture theoretically supports 8 parallel insns (||) per cycle 
(that makes 64 possible instructions instead of the 6). If all 
instructions are separate rtl insn, the scheduler can group them in a 
way so that more than one task can be done simultaneously, though of 
course there are a lot of constraints.

If I follow my previous thoughts, I need a way to tag information to 
particular insns, preferably a buit-in one.

I would also like passing some scheduling details and I guessed I could 
do that similarly. For instance: The cpu_unit the scheduler assigns to 
each insn should appear in the output. If that would not be possible, I 
had to recalculate this units myself, as the assembler I wrote does not 
do that either.
A possible solution would be to build up a private data structure of 
some kind to connect the needed info to the UID of the insn, but I would 
prefer an easier way.

Thanks for your patience ;-)

greets,
Adrian



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: TMSC320C6x port: return label is being deleted
  2004-09-16 18:30     ` Graham Stott
  2004-09-18 21:21       ` Adrian Strätling
@ 2004-10-04 13:37       ` Nick Ing-Simmons
  2004-10-04 16:31         ` Adrian Strätling
  1 sibling, 1 reply; 8+ messages in thread
From: Nick Ing-Simmons @ 2004-10-04 13:37 UTC (permalink / raw)
  To: graham.stott; +Cc: GCC, Adrian "Strätling"

Graham Stott <graham.stott@btinternet.com> writes:
>> "
>You don't need/want all the stuff after after your emit_call_insn
>
>In your define_insn for your call you use something like.
>(define_insn "..."
>  []
>  ""
>{
>  rtx label = gen_label_rtx ();
>
>  output your call sequence
>  ..
>
>  now output the label
>  
>  return "";
>}
>
>See how the rest of the compiler doesn't know or care
>about these labels.

I don't know if Adrian's port does this but when I was at TI and 
playing with a GCC port of C6x I wanted to avoid "clever" output sections.
Reason was that C6x is a VLIW - so it can execute instructions in parallel.
So my port tried to make each 'insn' a one-cycle RISC-like one
(define_expand-ing as required).

Then there was a custom output pass that walked the RTL and collected 
RISC-like things into VLIW execute packets.
Multi-cycle things are a pain in such a scheme.
I haven't got my code anymore - I left it at TI.
But I seem to recall that my call define expanded 
into the load-return and the jump. And the jump had a (fake) dependancy 
on the return address register to keep them in right order.

 





>
>> 
>> Thanks,
>> Adrian
>>  
>
>Graham

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: TMSC320C6x port: return label is being deleted
  2004-10-04 13:37       ` Nick Ing-Simmons
@ 2004-10-04 16:31         ` Adrian Strätling
  2004-10-08 13:56           ` Nick Ing-Simmons
  0 siblings, 1 reply; 8+ messages in thread
From: Adrian Strätling @ 2004-10-04 16:31 UTC (permalink / raw)
  To: Nick Ing-Simmons; +Cc: GCC

Nick Ing-Simmons wrote:

>Graham Stott <graham.stott@btinternet.com> writes:
>
>>>"
>>>
>>You don't need/want all the stuff after after your emit_call_insn
>>
>>In your define_insn for your call you use something like.
>>(define_insn "..."
>> []
>> ""
>>{
>> rtx label = gen_label_rtx ();
>>
>> output your call sequence
>> ..
>>
>> now output the label
>> 
>> return "";
>>}
>>
>>See how the rest of the compiler doesn't know or care
>>about these labels.
>>
>
>I don't know if Adrian's port does this but when I was at TI and 
>playing with a GCC port of C6x I wanted to avoid "clever" output sections.
>Reason was that C6x is a VLIW - so it can execute instructions in parallel.
>So my port tried to make each 'insn' a one-cycle RISC-like one
>(define_expand-ing as required).
>
Yes, I'm trying to do exactly that.

>
>Then there was a custom output pass that walked the RTL and collected 
>RISC-like things into VLIW execute packets.
>Multi-cycle things are a pain in such a scheme.
>I haven't got my code anymore - I left it at TI.
>But I seem to recall that my call define expanded 
>into the load-return and the jump. And the jump had a (fake) dependancy 
>on the return address register to keep them in right order.
>
Thanks, I'll keep that in mind. For the moment I'll stick to the 
solution that's based on the idea: "the compiler doesn't need to know". 
The call_expand function inserts the labelno with the appropriate 
insn_uid of the call insn into a 'private' hash_table. The output code 
later looks into this table to find the labelno and put it out after the 
call.

In the same has table I store information about the cycle this insn was 
scheduled. This way I recognize how many nops (if any) need to be 
inserted to preserve dependencies.
The drawback of that solution is that I am not able to use the delay 
branch scheduler because it destroys those information when regrouping insn.

Do you recall how you did the NOP insertion back then?
Thanks,

Adrian

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: TMSC320C6x port: return label is being deleted
  2004-10-04 16:31         ` Adrian Strätling
@ 2004-10-08 13:56           ` Nick Ing-Simmons
  0 siblings, 0 replies; 8+ messages in thread
From: Nick Ing-Simmons @ 2004-10-08 13:56 UTC (permalink / raw)
  To: adrian.straetling; +Cc: GCC, Nick Ing-Simmons

=?UTF-8?B?QWRyaWFuIFN0csOkdGxpbmc=?= <adrian.straetling@cs.tu-chemnitz.de> writes:
>>I haven't got my code anymore - I left it at TI.
>>But I seem to recall that my call define expanded 
>>into the load-return and the jump. And the jump had a (fake) dependancy 
>>on the return address register to keep them in right order.
>>
>Thanks, I'll keep that in mind. For the moment I'll stick to the 
>solution that's based on the idea: "the compiler doesn't need to know". 
>The call_expand function inserts the labelno with the appropriate 
>insn_uid of the call insn into a 'private' hash_table. The output code 
>later looks into this table to find the labelno and put it out after the 
>call.
>
>In the same has table I store information about the cycle this insn was 
>scheduled. This way I recognize how many nops (if any) need to be 
>inserted to preserve dependencies.
>The drawback of that solution is that I am not able to use the delay 
>branch scheduler because it destroys those information when regrouping insn.
>
>Do you recall how you did the NOP insertion back then?

I am reasonably sure that I used the normal branch scheduler.
Almost always the "load return" ended up in the delay slots :-)


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2004-10-08 13:48 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-09-14 17:24 TMSC320C6x port: return label is being deleted Adrian Strätling
2004-09-14 18:50 ` Graham Stott
2004-09-16 18:03   ` Adrian Strätling
2004-09-16 18:30     ` Graham Stott
2004-09-18 21:21       ` Adrian Strätling
2004-10-04 13:37       ` Nick Ing-Simmons
2004-10-04 16:31         ` Adrian Strätling
2004-10-08 13:56           ` Nick Ing-Simmons

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).