Steven Bosscher wrote on Sonntag, 7. August 2005 12:45 :
> On Sunday 07 August 2005 09:35, Björn Haase wrote:
> > Hello,
> >
> > The avr port presently misses possible intra-procedure optimizations
> > concerning register use.
>
> What you describe is an _inter_procedural optimization.  "Between
> procedures".  You want to use the result of some analysis done in one
> function to expose extra optimization opportunities in another function.
> That is interprocedural.
OK, thank's :-).
> > Is there a way to make leaf functions to be compiled first
>
> Leaf functions _are_ compiled first.
>
> > so that when
> > starting with non-leaf functions in the same unit expand could insert
> > detailed information on which subset of registers is actually clobbered
> > by calls to leaf functions?
>
> Not at the moment.  It is probably not very hard to implement something
> like this idea, though.  Note that you can even propagate this detailed
> information across the call graph if you could compute it.

I think that such kind of optimization could help very much for my fractional 
numerics library where some functions tend to be lengthy but use very few 
registers. I would be willing to try to implement it.

I can imagine two possible approaches for addressing the issue. One that only 
needs adaptions in the back-end and implements the optimization only for one 
target and then one more generic solution.


1.) target specific approach

The back end implements a database that stores the register usage of all the 
functions that so far have been compiled and the symbol ref of these 
functions. IIUC this could be done in the final stage when generating the asm 
text output.

The define_insn for the named call pattern is replaced by a smart 
define_expand that looks in the database whether anything on the 
function-to-be-called is known. It could look whether the database already 
contains an entry with the same label ref. 
If not, it generates the usual call pattern. If there *is* an entry in the 
database it generates a call_insn where the CALL_INSN_FUNCTION_USAGE contains 
the appropriate use and clobber RTL.

2.) generic

One could of course try to store the information on register usage somewhere 
in the tree structure. 
One therefore would add a target macro CALL_FUNCTION_CLOBBERED_REGISTERS that 
returns a pointer to static memory of a struct of the same type as the 
"CALL_REALLY_USED_REGISTERS" struct with the only difference that this struct 
could change. If the value returned is not NULL, the mid end then would copy 
this struct to a new location on the heap and store a link to this storage 
somewhere in the tree data structure.

One would then make the default expander for calls do the work to adapt the 
CALL_INSN_FUNCTION_USAGE field if information is available. Probably one 
would then not make use the name of the lable ref of the function entry 
lable. The default expander probably would have a pointer to some tree node 
that describes the function to be called.?


I think that I am having a clear idea on how much work it would be to 
implement 1). IMO, it would not be too much work (only open question would 
be, where to place the code that finds out which register are used).

However, I'd prefer method 2) since I think that other targets might as well 
benefit from the optimization. I only cannot judge how much work it would be 
to get the additional information stored within the tree.

I'd appreciate opinions on whether there stand chances to get approach 2) 
integrated into gcc mainline. I also would be thankful for a short hint where 
the function is that would have to use the suggested 
CALL_FUNCTION_CLOBBERED_REGISTERS macro and where within the mid-end
I would find the default expander for insn calls (I thought it is in optabs.c 
but I did not find it immediately).


Greetings,

Bjoern Haase

Reply via email to