Hi,
when looking at another PR, I found out that inliner refused to even
consider __final_test2_T/0 because, according to the dump, "redefined
extern inline functions are not considered for inlining." When I
looked at why, I realized that the function is "finalized" (by
cgraph_finalize_function) twice. Once directly from front-end and
second time from un-nesting nested functions.
This patch makes sure that the Fortran front-end does not do that.
Some details about the patch development over the time is in bugzilla.
Bootstrapped and tested on x86_64-linux without any problems, OK for
trunk?
Thanks,
Martin
2013-08-01 Martin Jambor
* cgraphunit.c (cgraph_finalize_function): Assert that nested function
is not re-finalized. Rename second parameter to no_collect.
fortran/
* trans-decl.c (gfc_generate_function_code): Never call
cgraph_finalize_function on nested functions.
testsuite/
* gfortran.dg/pr57987.f90: New test.
Index: src/gcc/cgraphunit.c
===
--- src.orig/gcc/cgraphunit.c
+++ src/gcc/cgraphunit.c
@@ -405,17 +405,20 @@ referred_to_p (symtab_node node)
}
/* DECL has been parsed. Take it, queue it, compile it at the whim of the
- logic in effect. If NESTED is true, then our caller cannot stand to have
+ logic in effect. If NO_COLLECT is true, then our caller cannot stand to
have
the garbage collector run at the moment. We would need to either create
a new GC context, or just not compile right now. */
void
-cgraph_finalize_function (tree decl, bool nested)
+cgraph_finalize_function (tree decl, bool no_collect)
{
struct cgraph_node *node = cgraph_get_create_node (decl);
if (node->symbol.definition)
{
+ /* Nested functions should only be defined once. */
+ gcc_assert (!DECL_CONTEXT (decl)
+ || TREE_CODE (DECL_CONTEXT (decl)) != FUNCTION_DECL);
cgraph_reset_node (node);
node->local.redefined_extern_inline = true;
}
@@ -454,7 +457,7 @@ cgraph_finalize_function (tree decl, boo
if (warn_unused_parameter)
do_warn_unused_parameter (decl);
- if (!nested)
+ if (!no_collect)
ggc_collect ();
if (cgraph_state == CGRAPH_STATE_CONSTRUCTION
Index: src/gcc/fortran/trans-decl.c
===
--- src.orig/gcc/fortran/trans-decl.c
+++ src/gcc/fortran/trans-decl.c
@@ -5640,14 +5640,16 @@ gfc_generate_function_code (gfc_namespac
}
current_function_decl = old_context;
- if (decl_function_context (fndecl) && gfc_option.coarray != GFC_FCOARRAY_LIB
- && has_coarray_vars)
-/* Register this function with cgraph just far enough to get it
- added to our parent's nested function list.
- If there are static coarrays in this function, the nested _caf_init
- function has already called cgraph_create_node, which also created
- the cgraph node for this function. */
-(void) cgraph_create_node (fndecl);
+ if (decl_function_context (fndecl))
+{
+ /* Register this function with cgraph just far enough to get it
+added to our parent's nested function list.
+If there are static coarrays in this function, the nested _caf_init
+function has already called cgraph_create_node, which also created
+the cgraph node for this function. */
+ if (!has_coarray_vars || gfc_option.coarray != GFC_FCOARRAY_LIB)
+ (void) cgraph_create_node (fndecl);
+}
else
cgraph_finalize_function (fndecl, true);
Index: src/gcc/testsuite/gfortran.dg/pr57987.f90
===
--- /dev/null
+++ src/gcc/testsuite/gfortran.dg/pr57987.f90
@@ -0,0 +1,24 @@
+! { dg-do compile }
+! { dg-options "-O3 -fno-ipa-cp -fdump-ipa-inline" }
+
+program test
+ call test2 ()
+contains
+ subroutine test2 ()
+type t
+ integer, allocatable :: x
+end type t
+
+type t2
+ class(t), allocatable :: a
+end type t2
+
+type(t2) :: one, two
+
+allocate (two%a)
+one = two
+ end subroutine test2
+end program test
+
+! { dg-final { scan-ipa-dump-not "redefined extern inline functions are not
considered for inlining" "inline" } }
+! { dg-final { cleanup-ipa-dump "inline" } }