aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2010-10-04 22:59:07 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2010-10-04 20:59:07 +0000
commitb3b9f3d0a808a2e0773e90d70dff2048270cc359 (patch)
tree1d98e516244d02c9fedbab147a5e449884c9d35c
parentfa37ed29b9a77b698c67548a82484c5fab584b07 (diff)
downloadgcc-b3b9f3d0a808a2e0773e90d70dff2048270cc359.zip
gcc-b3b9f3d0a808a2e0773e90d70dff2048270cc359.tar.gz
gcc-b3b9f3d0a808a2e0773e90d70dff2048270cc359.tar.bz2
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
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/gimple-fold.c63
-rw-r--r--gcc/gimple.c3
3 files changed, 53 insertions, 23 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 01e3381..4511232 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index b8c0fd4..0a6c746 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -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);
}
diff --git a/gcc/gimple.c b/gcc/gimple.c
index fa8acd0..54e6857 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -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)