This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: At linktime, consider linkonces as ones that will go away


> Hi,
> 
> On Thu, 8 Jul 2010, Jan Hubicka wrote:
> 
> > cgraph_only_called_directly_p when we know function is only called directly
> > and we see all the calls.  I.e. it is not having address taken, not externally
> > visible and not used in funnny way (alias, __attribute__ ((used)) etc.).
> > Such functions go away when all direct calls disappear.
> > 
> > This is used for deciding when function is local and some other cases.
> 
> So this one is only a sub-predicate with many users, not all of them 
> related to "will the function go away?" questions.
> 
> > Then we have cgraph_can_remove_if_no_direct_calls_p that in addition 
> > knows that COMDAT functions can disappear even when they can be called 
> > in hidden way from other unit if they are there.  This is used i.e. by 
> > inliner to decide whether offline copy is needed after all calls are 
> > inlined.
> > 
> > Then there is cgraph_can_remove_if_no_direct_calls_and_refs_p that is 
> > stronger by not checking for addresses taken and is used by unreachable 
> > function removal.
> > 
> > And finally we have new predicate that is somewhere in between these 
> > two.
> 
> What differentiates the users of the first predicate from those of the 
> second two?  The first case reads to me like "decide if offline copy is 
> needed".  The second case reads the same to me.  And the third case too.  
> Why do you need three predicates, aren't you always asking "do I need an 
> offline copy of this function, even if I can resolve all calls?"

Well, it is all about stuble differences ;)) Sadly those differences matter
a lot in practice, this is why I worry about them at first place.

Function that is only caled directly can have API changes, i.e. one can take
some code from function body and move it into all callers.  (or propagate
constant into it in ipa-cp, or let ipa-pta to compute PTA sets of its argument)

You can't do that with cgraph_can_remove_if_no_direct_calls_p function since it
would break with COMDAT function without address taken that is called from
other unit (but won't if you eliminate all direct calls as it will die).

So cgraph_only_called_directly is used to guard transofrms that are only safe
if you know all the callers (thus no removing in name),
cgraph_can_remove_if_no_direct_calls_p is used by dead function elimination,
in ipa-inline.

The difference in between cgraph_can_remove_if_no_direct_calls_p and
cgraph_can_remove_if_no_direct_calls_and_refs_p is whether pass cares of
indirect calls too.  I could make ipa-inline to use
cgraph_can_remove_if_no_direct_calls_and_refs_p and test if address is taken,
but since the former existed longer and I think it could be useful elsewhere I
decided to keep it.

The new predicate is used in cases where you want to see if doing code
duplication eliminating direct calls to given function will make the function
to disappear from program (not only current unit as
cgraph_can_remove_if_no_direct_calls_p).  So it is useful for metrics deciding
on how those transforms affect program size, but not for actual removal of
function.

Currently we use cgraph_only_called_directly_p for that but it is too
conservative in LTO and whole program mode where we know that COMDAT functions
won't exist in unbounded number of copies. 
> 
> The circumstance should always be the same.  They depend on compilation 
> modes and several computed flags.  But I don't see how different questions 
> than the above are to be asked.
> 
> For instance even your first predicate 
> (cgraph_can_remove_if_no_direct_calls_p) needs to take into account 
> non-dead references (aka address-takens) to the function (in which case we 
> need an offline copy).  Your second predicate seemingly doesn't take
> node->address_taken into account, which I find strange.
> 
> And the third predicate also just adds a variant for answering the 
> question "will this function be removed?".
> 
> In addition the pre-existing two predicates are each used exactly once, 
> and all uses are itself in between a number of conditions.  This just adds 
> the confusion between the different predicates (for instance why the 
> surrounding condition isn't part of the predicate), e.g. here:
> 
>       if (!e->callee->callers->next_caller
>           && cgraph_can_remove_if_no_direct_calls_p (e->callee)
>           /* Don't reuse if more than one function shares a comdat group.
>              If the other function(s) are needed, we need to emit even
>              this function out of line.  */
>           && !e->callee->same_comdat_group
> 
> So, why do you need three cgraph_can_remove predicates (and why don't they 
> contain all conditions necessary?)

Well the code test if the function can be removed and has precisely 1 call and
has no comdat group.  First test is because we know we are going to inline that
last call and the second test because inliner is stupid and is not able to deal
with comdat groups well.

This probably can't be broken up into independent predicate with resonable
meaning.

> 
> > So cgraph_removed_p name does not make it very clear how that predicate 
> > differs from other.  Also it is not removed from program at the timewe 
> > call it, only will be removed as consequence of transformation and 
> > unreachable function removal later...
> 
> (that's what the _p is for, isn't it?)

_p is shorcut for predicate ;) I would read the function as predicate testing
if my pointer to node points to node that has been removed from cgraph.
cgraph_removable_p would probably work better for my Czenglish, but that won't
make much diference above.

Honza
> 
> 
> Ciao,
> Michael.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]