cgraphbuild.c (record_reference): Update.

* cgraphbuild.c (record_reference): Update.
	* lto-cgraph.c (lto_output_varpool_node): External vars
	are not in other partition even if they are not output
	in current partition.
	* gimple-fold.c (can_refer_decl_in_current_unit_p): Take FROM_DECL
	argument; fix.
	(canonicalize_constructor_val): Take FROM_DECL argument.
	(fold_ctor_reference, fold_string_cst_ctor_reference,
	fold_array_ctor_reference, fold_nonarray_ctor_reference,
	fold_ctor_reference): Likewise.
	(fold_const_aggregate_ref_1, gimple_get_virt_method_for_binfo): Update.
	* gimple.h (gimple_fold_builtin): Likewise.

From-SVN: r187678
This commit is contained in:
Jan Hubicka 2012-05-19 11:49:47 +02:00 committed by Jan Hubicka
parent c80c1ce951
commit c44c2088f7
4 changed files with 93 additions and 41 deletions

View File

@ -1,3 +1,18 @@
2012-05-18 Jan Hubicka <jh@suse.cz>
* cgraphbuild.c (record_reference): Update.
* lto-cgraph.c (lto_output_varpool_node): External vars
are not in other partition even if they are not output
in current partition.
* gimple-fold.c (can_refer_decl_in_current_unit_p): Take FROM_DECL
argument; fix.
(canonicalize_constructor_val): Take FROM_DECL argument.
(fold_ctor_reference, fold_string_cst_ctor_reference,
fold_array_ctor_reference, fold_nonarray_ctor_reference,
fold_ctor_reference): Likewise.
(fold_const_aggregate_ref_1, gimple_get_virt_method_for_binfo): Update.
* gimple.h (gimple_fold_builtin): Likewise.
2012-05-18 Olivier Hainque <hainque@adacore.com>
* Makefile.in (FLAGS_TO_PASS): Pass $(libexecsubdir) instead of

View File

@ -54,7 +54,7 @@ record_reference (tree *tp, int *walk_subtrees, void *data)
tree decl;
struct record_reference_ctx *ctx = (struct record_reference_ctx *)data;
t = canonicalize_constructor_val (t);
t = canonicalize_constructor_val (t, NULL);
if (!t)
t = *tp;
else if (t != *tp)

View File

@ -33,8 +33,9 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-fold.h"
/* Return true when DECL can be referenced from current unit.
We can get declarations that are not possible to reference for
various reasons:
FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
We can get declarations that are not possible to reference for various
reasons:
1) When analyzing C++ virtual tables.
C++ virtual tables do have known constructors even
@ -54,19 +55,35 @@ along with GCC; see the file COPYING3. If not see
directly. */
static bool
can_refer_decl_in_current_unit_p (tree decl)
can_refer_decl_in_current_unit_p (tree decl, tree from_decl)
{
struct varpool_node *vnode;
struct cgraph_node *node;
symtab_node snode;
if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
/* We will later output the initializer, so we can reffer to it.
So we are concerned only when DECL comes from initializer of
external var. */
if (!from_decl
|| TREE_CODE (from_decl) != VAR_DECL
|| !DECL_EXTERNAL (from_decl)
|| (symtab_get_node (from_decl)->symbol.in_other_partition))
return true;
/* External flag is set, so we deal with C++ reference
to static object from other file.
We also may see weakref that is always safe. */
if (DECL_EXTERNAL (decl) && TREE_STATIC (decl)
&& TREE_CODE (decl) == VAR_DECL)
return lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)) != NULL;
/* We are concerned ony about static/external vars and functions. */
if ((!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
|| (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL))
return true;
/* Weakrefs have somewhat confusing DECL_EXTERNAL flag set; they are always safe. */
if (DECL_EXTERNAL (decl)
&& lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
return true;
/* We are folding reference from external vtable. The vtable may reffer
to a symbol keyed to other compilation unit. The other compilation
unit may be in separate DSO and the symbol may be hidden. */
if (DECL_VISIBILITY_SPECIFIED (decl)
&& DECL_EXTERNAL (decl)
&& (!(snode = symtab_get_node (decl)) || !snode->symbol.in_other_partition))
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. */
@ -75,14 +92,19 @@ can_refer_decl_in_current_unit_p (tree decl)
/* We are not at ltrans stage; so don't worry about WHOPR.
Also when still gimplifying all referred comdat functions will be
produced.
??? as observed in PR20991 for already optimized out comdat virtual functions
we may not neccesarily give up because the copy will be output elsewhere when
corresponding vtable is output. */
As observed in PR20991 for already optimized out comdat virtual functions
it may be tempting to not neccesarily give up because the copy will be
output elsewhere when corresponding vtable is output.
This is however not possible - ABI specify that COMDATs are output in
units where they are used and when the other unit was compiled with LTO
it is possible that vtable was kept public while the function itself
was privatized. */
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;
/* OK we are seeing either COMDAT or static variable. In this case we must
check that the definition is still around so we can refer it. */
if (TREE_CODE (decl) == FUNCTION_DECL)
{
node = cgraph_get_node (decl);
@ -92,22 +114,29 @@ can_refer_decl_in_current_unit_p (tree decl)
compilation stage when making a new reference no longer makes callee
to be compiled. */
if (!node || !node->analyzed || node->global.inlined_to)
return false;
{
gcc_checking_assert (!TREE_ASM_WRITTEN (decl));
return false;
}
}
else if (TREE_CODE (decl) == VAR_DECL)
{
vnode = varpool_get_node (decl);
if (!vnode || !vnode->finalized)
return false;
if (!vnode || !vnode->analyzed)
{
gcc_checking_assert (!TREE_ASM_WRITTEN (decl));
return false;
}
}
return true;
}
/* CVAL is value taken from DECL_INITIAL of variable. Try to transform it into
acceptable form for is_gimple_min_invariant. */
acceptable form for is_gimple_min_invariant.
FROM_DECL (if non-NULL) specify variable whose constructor contains CVAL. */
tree
canonicalize_constructor_val (tree cval)
canonicalize_constructor_val (tree cval, tree from_decl)
{
STRIP_NOPS (cval);
if (TREE_CODE (cval) == POINTER_PLUS_EXPR
@ -130,7 +159,7 @@ canonicalize_constructor_val (tree cval)
if ((TREE_CODE (base) == VAR_DECL
|| TREE_CODE (base) == FUNCTION_DECL)
&& !can_refer_decl_in_current_unit_p (base))
&& !can_refer_decl_in_current_unit_p (base, from_decl))
return NULL_TREE;
if (TREE_CODE (base) == VAR_DECL)
{
@ -163,7 +192,7 @@ get_symbol_constant_value (tree sym)
tree val = DECL_INITIAL (sym);
if (val)
{
val = canonicalize_constructor_val (val);
val = canonicalize_constructor_val (val, sym);
if (val && is_gimple_min_invariant (val))
return val;
else
@ -2627,7 +2656,7 @@ gimple_fold_stmt_to_constant (gimple stmt, tree (*valueize) (tree))
static tree fold_ctor_reference (tree type, tree ctor,
unsigned HOST_WIDE_INT offset,
unsigned HOST_WIDE_INT size);
unsigned HOST_WIDE_INT size, tree);
/* See if we can find constructor defining value of BASE.
When we know the consructor with constant offset (such as
@ -2735,7 +2764,8 @@ fold_string_cst_ctor_reference (tree type, tree ctor,
static tree
fold_array_ctor_reference (tree type, tree ctor,
unsigned HOST_WIDE_INT offset,
unsigned HOST_WIDE_INT size)
unsigned HOST_WIDE_INT size,
tree from_decl)
{
unsigned HOST_WIDE_INT cnt;
tree cfield, cval;
@ -2824,7 +2854,8 @@ fold_array_ctor_reference (tree type, tree ctor,
/* Do we have match? */
if (double_int_cmp (access_index, index, 1) >= 0
&& double_int_cmp (access_index, max_index, 1) <= 0)
return fold_ctor_reference (type, cval, inner_offset, size);
return fold_ctor_reference (type, cval, inner_offset, size,
from_decl);
}
/* When memory is not explicitely mentioned in constructor,
it is 0 (or out of range). */
@ -2837,7 +2868,8 @@ fold_array_ctor_reference (tree type, tree ctor,
static tree
fold_nonarray_ctor_reference (tree type, tree ctor,
unsigned HOST_WIDE_INT offset,
unsigned HOST_WIDE_INT size)
unsigned HOST_WIDE_INT size,
tree from_decl)
{
unsigned HOST_WIDE_INT cnt;
tree cfield, cval;
@ -2892,7 +2924,8 @@ fold_nonarray_ctor_reference (tree type, tree ctor,
if (double_int_cmp (uhwi_to_double_int (offset), bitoffset, 0) < 0)
return NULL_TREE;
return fold_ctor_reference (type, cval,
double_int_to_uhwi (inner_offset), size);
double_int_to_uhwi (inner_offset), size,
from_decl);
}
}
/* When memory is not explicitely mentioned in constructor, it is 0. */
@ -2904,14 +2937,14 @@ fold_nonarray_ctor_reference (tree type, tree ctor,
static tree
fold_ctor_reference (tree type, tree ctor, unsigned HOST_WIDE_INT offset,
unsigned HOST_WIDE_INT size)
unsigned HOST_WIDE_INT size, tree from_decl)
{
tree ret;
/* We found the field with exact match. */
if (useless_type_conversion_p (type, TREE_TYPE (ctor))
&& !offset)
return canonicalize_constructor_val (ctor);
return canonicalize_constructor_val (ctor, from_decl);
/* We are at the end of walk, see if we can view convert the
result. */
@ -2920,7 +2953,7 @@ fold_ctor_reference (tree type, tree ctor, unsigned HOST_WIDE_INT offset,
&& operand_equal_p (TYPE_SIZE (type),
TYPE_SIZE (TREE_TYPE (ctor)), 0))
{
ret = canonicalize_constructor_val (ctor);
ret = canonicalize_constructor_val (ctor, from_decl);
ret = fold_unary (VIEW_CONVERT_EXPR, type, ret);
if (ret)
STRIP_NOPS (ret);
@ -2933,9 +2966,11 @@ fold_ctor_reference (tree type, tree ctor, unsigned HOST_WIDE_INT offset,
if (TREE_CODE (TREE_TYPE (ctor)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (ctor)) == VECTOR_TYPE)
return fold_array_ctor_reference (type, ctor, offset, size);
return fold_array_ctor_reference (type, ctor, offset, size,
from_decl);
else
return fold_nonarray_ctor_reference (type, ctor, offset, size);
return fold_nonarray_ctor_reference (type, ctor, offset, size,
from_decl);
}
return NULL_TREE;
@ -3008,7 +3043,8 @@ fold_const_aggregate_ref_1 (tree t, tree (*valueize) (tree))
return NULL_TREE;
return fold_ctor_reference (TREE_TYPE (t), ctor, offset,
TREE_INT_CST_LOW (unit_size)
* BITS_PER_UNIT);
* BITS_PER_UNIT,
base);
}
}
/* Fallthru. */
@ -3034,7 +3070,8 @@ fold_const_aggregate_ref_1 (tree t, tree (*valueize) (tree))
if (offset < 0)
return NULL_TREE;
return fold_ctor_reference (TREE_TYPE (t), ctor, offset, size);
return fold_ctor_reference (TREE_TYPE (t), ctor, offset, size,
base);
case REALPART_EXPR:
case IMAGPART_EXPR:
@ -3068,9 +3105,9 @@ tree
gimple_get_virt_method_for_binfo (HOST_WIDE_INT token, tree known_binfo)
{
unsigned HOST_WIDE_INT offset, size;
tree v, fn;
tree v, fn, vtable;
v = BINFO_VTABLE (known_binfo);
vtable = v = BINFO_VTABLE (known_binfo);
/* If there is no virtual methods table, leave the OBJ_TYPE_REF alone. */
if (!v)
return NULL_TREE;
@ -3096,7 +3133,7 @@ gimple_get_virt_method_for_binfo (HOST_WIDE_INT token, tree known_binfo)
size = tree_low_cst (TYPE_SIZE (TREE_TYPE (TREE_TYPE (v))), 1);
offset += token * size;
fn = fold_ctor_reference (TREE_TYPE (TREE_TYPE (v)), DECL_INITIAL (v),
offset, size);
offset, size, vtable);
if (!fn || integer_zerop (fn))
return NULL_TREE;
gcc_assert (TREE_CODE (fn) == ADDR_EXPR
@ -3108,7 +3145,7 @@ gimple_get_virt_method_for_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 (!can_refer_decl_in_current_unit_p (fn))
if (!can_refer_decl_in_current_unit_p (fn, vtable))
return NULL_TREE;
/* Make sure we create a cgraph node for functions we'll reference.

View File

@ -5315,7 +5315,7 @@ tree gimple_fold_builtin (gimple);
bool fold_stmt (gimple_stmt_iterator *);
bool fold_stmt_inplace (gimple_stmt_iterator *);
tree get_symbol_constant_value (tree);
tree canonicalize_constructor_val (tree);
tree canonicalize_constructor_val (tree, tree);
extern tree maybe_fold_and_comparisons (enum tree_code, tree, tree,
enum tree_code, tree, tree);
extern tree maybe_fold_or_comparisons (enum tree_code, tree, tree,