In the following example, the fucntion hooray() does not get inlined, even though it could. #include <stdlib.h> #include <stdio.h> static __attribute__((always_inline)) void hooray () { printf ("hooray\n"); } static __attribute__((always_inline)) void hiphip (void (*f)()) { printf ("hip hip\n"); f (); } int main (int argc, int *argv[]) { hiphip (hooray); return 0; } int d() { hiphip (hooray); return 86; } The reasons are I believe a bit more grave than the fact that this (mis)use of anlways_inline does not work. When tree-inline.c produces an inlined copy of hiphip() it remaps the destination of the call to f in remap_gimple_stmt() to call hooray. However, the new call statement has this form: call<addr_expr<function_decl>> which is a form that gimple_call_fndecl() cannot cope with. The consequence is that rebuild_cgraph_edges() sees a call with an unretrievable declaration and does not build a call graph edge for it. Therefore, when early inlining inlines hiphip into its callers, there is no call graph edge for main->hooray (or d->hooray) and so these call sites are not even considered when doing regular inlining, let alone always_inlining.
I am testing the patch below which should fix the problem: 2008-08-07 Martin Jambor <mjambor@suse.cz> * tree-inline.c (remap_gimple_stmt): Remove extraneous addr_expr from call statements. Index: iinln/gcc/tree-inline.c =================================================================== --- iinln.orig/gcc/tree-inline.c +++ iinln/gcc/tree-inline.c @@ -1209,6 +1209,14 @@ remap_gimple_stmt (gimple stmt, copy_bod wi.info = id; walk_gimple_op (copy, remap_gimple_op_r, &wi); + /* When a parameter is propagated into a call destination, it is in the form + of call<addr_expr<fndecl>> which gimple_call_fndecl does not understand. + Therefore we need to take the extra addr_expr out here. */ + if (is_gimple_call (copy) + && TREE_CODE (gimple_call_fn (copy)) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (gimple_call_fn (copy), 0)) == FUNCTION_DECL) + gimple_call_set_fn (copy, TREE_OPERAND (gimple_call_fn (copy), 0)); + /* We have to handle EH region remapping of GIMPLE_RESX specially because the region number is not an operand. */ if (gimple_code (stmt) == GIMPLE_RESX && id->eh_region_offset)
Looks good. Similar things may happen with CCP propagation for like void foo(void) {} void bar(void) { void (*fn)(void) = foo; fn(); } can you verify this as well? Thanks.
Unfortunately, I got a fortran regression: /abuild/mjambor/iinln/gcc/testsuite/gfortran.dg/char_cast_1.f90:24: internal com piler error: in expand_call_inline, at tree-inline.c:3117 The assert is gcc_assert (dest->needed); so I think I might have uncovered some unrelated hidden problem. We will see. I will try to investigate but may not be able to go all the way because I'm, leaving for vacation tomorrow. Richi, that applies, to your question too. I will try but I may not make it.
Interesting. I may have a look into the CCP problem.
(In reply to comment #4) > Interesting. I may have a look into the CCP problem. > Well, I think that we have pass_rebuild_cgraph_edges precisely because passes like CCP are not trusted to update call graph correctly. It is not an elegant solution but might just work. However, in order for it to work, gimple_call_fndecl() must be able to find the declarations (and this might also be problem for CCP generated calls too).
Parts of it is fixed by: http://gcc.gnu.org/ml/gcc-patches/2008-08/msg00549.html Or is it a full fix, I can't tell anymore :).
Subject: Re: [4.4 Regression] Inlining produces calls which gimple_call_fndecl cannot handle correctly On Sun, 10 Aug 2008, pinskia at gcc dot gnu dot org wrote: > ------- Comment #6 from pinskia at gcc dot gnu dot org 2008-08-10 20:27 ------- > Parts of it is fixed by: > http://gcc.gnu.org/ml/gcc-patches/2008-08/msg00549.html > > Or is it a full fix, I can't tell anymore :). It should fix it fully - but I'll leave it for Martin to check. Richard.
Let's just close this. Martin, please re-open if you figure that things are still broken.
I've been away from computer for a rather long time so I could not check earlier. However, the problem is indeed gone. Thanks Richi.