Question about function body and function specialization

Martin Jambor mjambor@suse.cz
Wed Jul 15 12:03:48 GMT 2020


Hi,

On Tue, Jul 14 2020, Erick Ochoa wrote:
> On 14/07/2020 12:37, Erick Ochoa wrote:
>> Hello,
>> 
>> I have a function foo defined on a source file. Sometimes, a function 
>> pointer pointing to foo is passed as a parameter to other functions 
>> where foo is called indirectly. This indirect call is specialized during 
>> link time. Still at link time, I analyze the function call the following 

Does "at link time" mean that all of the below happens as part of the
execute method of an IPA pass?  Statements and call graph do diverge for
a while at that stage (perhaps watching
https://youtu.be/LBn-0jYKLb8?t=2604 from time 26:04 until about 50:20
might help a little).

>> way:
>> 
>>    // s is the gimple statement which corresponds to the indirect call
>>    tree fn = gimple_call_fndecl(s);
>>    // for this particular call the assertions are true
>>    gcc_assert(fn)

That can't be.  If s was an indirect call, gimple_call_fndecl(s) would
return NULL (because gimple_call_fn(gs) would be an SSA_NAME).  Perhaps
early inlining already converted it to a direct one?

>>    cgraph_node *node = cgraph_node::get(fn)
>>    gcc_assert(node)
>> 
>> I have analyzed the body of this function previously by using the 
>> FOR_EACH_FUNCTION_WITH_GIMPLE_BODY macro. However, I do not know if 
>> there's a way to link the cnode_graph (or function decl) analyzed in the 
>> macro with the one obtained at the call site. What would be the best way 
>> to say something like:
>> 
>>    tree fn = gimple_call_fndecl(s);
>>    // for this particular call the assertions are true
>>    gcc_assert(fn)
>>    cgraph_node *node = cgraph_node::get(fn)
>>    gcc_assert(node)
>>    bool i_want_this_to_be_true = saw_fn_in_loop_before(node, fn);

At IPA time, the best way is always to look at the call graph edges,
something like:

   cgraph_edge *cs = caller_cgraph_node->get_edge (s);
   examine (e->callee);

Note that if the call is truly an indirect one cs->callee will be NULL
(and cs->indirect_unknown_callee will be set).  Things can also get
quite a bit more complicated if cs->speculative is set, then there is
both an indirect and guessed direct edge for a single call.

>> 
>> I don't think that using storing the for loop and checking in 
>> saw_fn_in_loop_before is the way to go because I believe cnode->decl 
>> pointers can be different. Is this correct? In other words
>> 
>> 
>> FOR_EACH_FUNCTION_WITH_GIMPLE_BODY(cnode)
>> {
>>    a_std_set.insert(cnode->decl)
>> }
>> 
>> // later
>> 
>> bool
>> saw_fn_in_loop_before(cnode_graph *cn, tree fn)
>> {
>>    return a_std_set.find(fn) != a_std_set.end();
>> }
>> 
>> Should not work. Something I found interesting is that for the fndecl 
>> obtained through the callsite gimple_has_body_p returns false. Even 
>> though I saw a fndecl which corresponds to the same function in the 
>> FOR_EACH_FUNCTION_WITH_GIMPLE_BODY.

I can only guess but it seems that something has created specialized
clone for all contexts and you happen to be looking at the gimple bodies
after clone materialization but before edge redirection... but I am only
guessing.

>
> Actually, another interesting hint is that the original foo function 
> takes two parameters. The function I am seeing inside the 
> FOR_EACH_FUNCTION_WITH_GIMPLE_BODY is a specialized function of foo with 
> only 1 parameter. However, the indirect function call is a version of 
> foo which has not been specialized (i.e. it takes the original two 
> parameters).
>
> I guess my questions would be:
>
> * Does FOR_EACH_FUNCTION_WITH_GIMPLE_BODY only iterates across functions 
> which are reachable for main across the call graph?

No.  But functions which are known not to be reachable are of course
removed from the call graph and from the entire compilation too.

> * Is the the underlying mechanism for FOR_EACH_FUNCTION_WITH_GIMPLE_BODY 
> not updated after ipa-prop discovers targets of indirect functions?

I am not sure I understand the question but I guess that no.  The
mechanism is simple, just look it up.

> * Or is it just that the new callsite does not have a gimple body for 
> its function? (This seems implausible since the new direct callsite 
> should refer to the original function implementation.) How can I access 
> this function's body?
>

In the IPA scheme of things, call-sites are updated last, even when the
function where they are keeps its body from the start until the end.  It
seems to me that you really want to be looking at the call graph edges
instead.

Generally speaking, at IPA time you want to work only with the call
graph and the data you collected in summary building stage and look at
actual function bodies only as the last resort.

Martin


More information about the Gcc mailing list