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>
* 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 "target.h"
/* Return true when DECL is static object in other partition.
In that case we must prevent folding as we can't refer to
the symbol.
/* Return true when DECL can be referenced from current unit.
We can get declarations that are not possible to reference for
various reasons:
We can get into it in two ways:
1) When analyzing C++ virtual tables.
C++ virtual tables do have known constructors even
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.
In this case we have static VAR_DECL or FUNCTION_DECL
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_object_in_other_unit_p (tree decl)
can_refer_decl_in_current_unit_p (tree decl)
{
struct varpool_node *vnode;
struct cgraph_node *node;
if (!TREE_STATIC (decl) || DECL_COMDAT (decl))
return false;
if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
return true;
/* External flag is set, so we deal with C++ reference
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
flags incorrectly. Those variables should never
be finalized. */
gcc_checking_assert (!(vnode = varpool_get_node (decl))
|| !vnode->finalized);
return true;
return false;
}
if (TREE_PUBLIC (decl))
return false;
/* We are not at ltrans stage; so don't worry about WHOPR. */
if (!flag_ltrans)
return false;
/* When function is public, we always can introduce new reference.
Exception are the COMDAT functions where introducing a direct
reference imply need to include function body in the curren tunit. */
if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl))
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)
{
node = cgraph_get_node (decl);
if (!node || !node->analyzed)
return true;
/* Check that we still have function body and that we didn't took
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)
{
vnode = varpool_get_node (decl);
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
@ -106,10 +124,11 @@ canonicalize_constructor_val (tree cval)
if (TREE_CODE (cval) == ADDR_EXPR)
{
tree base = get_base_address (TREE_OPERAND (cval, 0));
if (base
&& (TREE_CODE (base) == VAR_DECL
|| TREE_CODE (base) == FUNCTION_DECL)
&& static_object_in_other_unit_p (base))
&& !can_refer_decl_in_current_unit_p (base))
return NULL_TREE;
if (base && TREE_CODE (base) == VAR_DECL)
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
ends up in other partition, because we found devirtualization
possibility too late. */
if (static_object_in_other_unit_p (fndecl))
if (!can_refer_decl_in_current_unit_p (fndecl))
return NULL;
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)
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) == CONSTRUCTOR
|| INDIRECT_REF_P (t)