gimple-fold.c (static_object_in_other_unit_p): Rename to...

* gimple-fold.c (static_object_in_other_unit_p): Rename to...
	(can_refer_decl_in_current_unit_p): ... this one; reverse return
	value; handle comdats too.
	(canonicalize_constructor_val): Use it; handle function_decls
	correctly.
	(gimple_fold_obj_type_ref_known_binfo): Likewise.
	* gimple.c (get_base_address): Accept all kinds of decls.

From-SVN: r164961
This commit is contained in:
Jan Hubicka 2010-10-04 22:59:07 +02:00 committed by Jan Hubicka
parent fa37ed29b9
commit b3b9f3d0a8
3 changed files with 53 additions and 23 deletions

View File

@ -1,3 +1,13 @@
2010-10-04 Jan Hubicka <jh@suse.cz>
* gimple-fold.c (static_object_in_other_unit_p): Rename to...
(can_refer_decl_in_current_unit_p): ... this one; reverse return
value; handle comdats too.
(canonicalize_constructor_val): Use it; handle function_decls
correctly.
(gimple_fold_obj_type_ref_known_binfo): Likewise.
* gimple.c (get_base_address): Accept all kinds of decls.
2010-10-04 Joseph Myers <joseph@codesourcery.com> 2010-10-04 Joseph Myers <joseph@codesourcery.com>
* flags.h (g_switch_value, g_switch_set): Remove. * flags.h (g_switch_value, g_switch_set): Remove.

View File

@ -31,11 +31,10 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-propagate.h" #include "tree-ssa-propagate.h"
#include "target.h" #include "target.h"
/* Return true when DECL is static object in other partition. /* Return true when DECL can be referenced from current unit.
In that case we must prevent folding as we can't refer to We can get declarations that are not possible to reference for
the symbol. various reasons:
We can get into it in two ways:
1) When analyzing C++ virtual tables. 1) When analyzing C++ virtual tables.
C++ virtual tables do have known constructors even C++ virtual tables do have known constructors even
when they are keyed to other compilation unit. when they are keyed to other compilation unit.
@ -46,45 +45,64 @@ along with GCC; see the file COPYING3. If not see
to method that was partitioned elsehwere. to method that was partitioned elsehwere.
In this case we have static VAR_DECL or FUNCTION_DECL In this case we have static VAR_DECL or FUNCTION_DECL
that has no corresponding callgraph/varpool node that has no corresponding callgraph/varpool node
declaring the body. */ declaring the body.
3) COMDAT functions referred by external vtables that
we devirtualize only during final copmilation stage.
At this time we already decided that we will not output
the function body and thus we can't reference the symbol
directly. */
static bool static bool
static_object_in_other_unit_p (tree decl) can_refer_decl_in_current_unit_p (tree decl)
{ {
struct varpool_node *vnode; struct varpool_node *vnode;
struct cgraph_node *node; struct cgraph_node *node;
if (!TREE_STATIC (decl) || DECL_COMDAT (decl)) if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
return false; return true;
/* External flag is set, so we deal with C++ reference /* External flag is set, so we deal with C++ reference
to static object from other file. */ to static object from other file. */
if (DECL_EXTERNAL (decl) && TREE_CODE (decl) == VAR_DECL) if (DECL_EXTERNAL (decl) && TREE_STATIC (decl)
&& TREE_CODE (decl) == VAR_DECL)
{ {
/* Just be sure it is not big in frontend setting /* Just be sure it is not big in frontend setting
flags incorrectly. Those variables should never flags incorrectly. Those variables should never
be finalized. */ be finalized. */
gcc_checking_assert (!(vnode = varpool_get_node (decl)) gcc_checking_assert (!(vnode = varpool_get_node (decl))
|| !vnode->finalized); || !vnode->finalized);
return true; return false;
} }
if (TREE_PUBLIC (decl)) /* When function is public, we always can introduce new reference.
return false; Exception are the COMDAT functions where introducing a direct
/* We are not at ltrans stage; so don't worry about WHOPR. */ reference imply need to include function body in the curren tunit. */
if (!flag_ltrans) if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl))
return false; return true;
/* We are not at ltrans stage; so don't worry about WHOPR.
Also when still gimplifying all referred comdat functions will be
produced. */
if (!flag_ltrans && (!DECL_COMDAT (decl) || !cgraph_function_flags_ready))
return true;
/* If we already output the function body, we are safe. */
if (TREE_ASM_WRITTEN (decl))
return true;
if (TREE_CODE (decl) == FUNCTION_DECL) if (TREE_CODE (decl) == FUNCTION_DECL)
{ {
node = cgraph_get_node (decl); node = cgraph_get_node (decl);
if (!node || !node->analyzed) /* Check that we still have function body and that we didn't took
return true; the decision to eliminate offline copy of the function yet.
The second is important when devirtualization happens during final
compilation stage when making a new reference no longer makes callee
to be compiled. */
if (!node || !node->analyzed || node->global.inlined_to)
return false;
} }
else if (TREE_CODE (decl) == VAR_DECL) else if (TREE_CODE (decl) == VAR_DECL)
{ {
vnode = varpool_get_node (decl); vnode = varpool_get_node (decl);
if (!vnode || !vnode->finalized) if (!vnode || !vnode->finalized)
return true; return false;
} }
return false; return true;
} }
/* CVAL is value taken from DECL_INITIAL of variable. Try to transorm it into /* CVAL is value taken from DECL_INITIAL of variable. Try to transorm it into
@ -106,10 +124,11 @@ canonicalize_constructor_val (tree cval)
if (TREE_CODE (cval) == ADDR_EXPR) if (TREE_CODE (cval) == ADDR_EXPR)
{ {
tree base = get_base_address (TREE_OPERAND (cval, 0)); tree base = get_base_address (TREE_OPERAND (cval, 0));
if (base if (base
&& (TREE_CODE (base) == VAR_DECL && (TREE_CODE (base) == VAR_DECL
|| TREE_CODE (base) == FUNCTION_DECL) || TREE_CODE (base) == FUNCTION_DECL)
&& static_object_in_other_unit_p (base)) && !can_refer_decl_in_current_unit_p (base))
return NULL_TREE; return NULL_TREE;
if (base && TREE_CODE (base) == VAR_DECL) if (base && TREE_CODE (base) == VAR_DECL)
add_referenced_var (base); add_referenced_var (base);
@ -1446,7 +1465,7 @@ gimple_fold_obj_type_ref_known_binfo (HOST_WIDE_INT token, tree known_binfo)
devirtualize. This can happen in WHOPR when the actual method devirtualize. This can happen in WHOPR when the actual method
ends up in other partition, because we found devirtualization ends up in other partition, because we found devirtualization
possibility too late. */ possibility too late. */
if (static_object_in_other_unit_p (fndecl)) if (!can_refer_decl_in_current_unit_p (fndecl))
return NULL; return NULL;
return build_fold_addr_expr (fndecl); return build_fold_addr_expr (fndecl);
} }

View File

@ -3013,7 +3013,8 @@ get_base_address (tree t)
&& TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR) && TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR)
t = TREE_OPERAND (TREE_OPERAND (t, 0), 0); t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
if (SSA_VAR_P (t) if (TREE_CODE (t) == SSA_NAME
|| DECL_P (t)
|| TREE_CODE (t) == STRING_CST || TREE_CODE (t) == STRING_CST
|| TREE_CODE (t) == CONSTRUCTOR || TREE_CODE (t) == CONSTRUCTOR
|| INDIRECT_REF_P (t) || INDIRECT_REF_P (t)