mirror of git://gcc.gnu.org/git/gcc.git
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:
parent
c80c1ce951
commit
c44c2088f7
|
|
@ -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>
|
2012-05-18 Olivier Hainque <hainque@adacore.com>
|
||||||
|
|
||||||
* Makefile.in (FLAGS_TO_PASS): Pass $(libexecsubdir) instead of
|
* Makefile.in (FLAGS_TO_PASS): Pass $(libexecsubdir) instead of
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ record_reference (tree *tp, int *walk_subtrees, void *data)
|
||||||
tree decl;
|
tree decl;
|
||||||
struct record_reference_ctx *ctx = (struct record_reference_ctx *)data;
|
struct record_reference_ctx *ctx = (struct record_reference_ctx *)data;
|
||||||
|
|
||||||
t = canonicalize_constructor_val (t);
|
t = canonicalize_constructor_val (t, NULL);
|
||||||
if (!t)
|
if (!t)
|
||||||
t = *tp;
|
t = *tp;
|
||||||
else if (t != *tp)
|
else if (t != *tp)
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,9 @@ along with GCC; see the file COPYING3. If not see
|
||||||
#include "gimple-fold.h"
|
#include "gimple-fold.h"
|
||||||
|
|
||||||
/* Return true when DECL can be referenced from current unit.
|
/* Return true when DECL can be referenced from current unit.
|
||||||
We can get declarations that are not possible to reference for
|
FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
|
||||||
various reasons:
|
We can get declarations that are not possible to reference for various
|
||||||
|
reasons:
|
||||||
|
|
||||||
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
|
||||||
|
|
@ -54,19 +55,35 @@ along with GCC; see the file COPYING3. If not see
|
||||||
directly. */
|
directly. */
|
||||||
|
|
||||||
static bool
|
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 varpool_node *vnode;
|
||||||
struct cgraph_node *node;
|
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;
|
return true;
|
||||||
/* External flag is set, so we deal with C++ reference
|
/* We are concerned ony about static/external vars and functions. */
|
||||||
to static object from other file.
|
if ((!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
|
||||||
We also may see weakref that is always safe. */
|
|| (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL))
|
||||||
if (DECL_EXTERNAL (decl) && TREE_STATIC (decl)
|
return true;
|
||||||
&& TREE_CODE (decl) == VAR_DECL)
|
/* Weakrefs have somewhat confusing DECL_EXTERNAL flag set; they are always safe. */
|
||||||
return lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)) != NULL;
|
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.
|
/* When function is public, we always can introduce new reference.
|
||||||
Exception are the COMDAT functions where introducing a direct
|
Exception are the COMDAT functions where introducing a direct
|
||||||
reference imply need to include function body in the curren tunit. */
|
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.
|
/* We are not at ltrans stage; so don't worry about WHOPR.
|
||||||
Also when still gimplifying all referred comdat functions will be
|
Also when still gimplifying all referred comdat functions will be
|
||||||
produced.
|
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
|
As observed in PR20991 for already optimized out comdat virtual functions
|
||||||
corresponding vtable is output. */
|
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))
|
if (!flag_ltrans && (!DECL_COMDAT (decl) || !cgraph_function_flags_ready))
|
||||||
return true;
|
return true;
|
||||||
/* If we already output the function body, we are safe. */
|
|
||||||
if (TREE_ASM_WRITTEN (decl))
|
/* OK we are seeing either COMDAT or static variable. In this case we must
|
||||||
return true;
|
check that the definition is still around so we can refer it. */
|
||||||
if (TREE_CODE (decl) == FUNCTION_DECL)
|
if (TREE_CODE (decl) == FUNCTION_DECL)
|
||||||
{
|
{
|
||||||
node = cgraph_get_node (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
|
compilation stage when making a new reference no longer makes callee
|
||||||
to be compiled. */
|
to be compiled. */
|
||||||
if (!node || !node->analyzed || node->global.inlined_to)
|
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)
|
else if (TREE_CODE (decl) == VAR_DECL)
|
||||||
{
|
{
|
||||||
vnode = varpool_get_node (decl);
|
vnode = varpool_get_node (decl);
|
||||||
if (!vnode || !vnode->finalized)
|
if (!vnode || !vnode->analyzed)
|
||||||
return false;
|
{
|
||||||
|
gcc_checking_assert (!TREE_ASM_WRITTEN (decl));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CVAL is value taken from DECL_INITIAL of variable. Try to transform it into
|
/* 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
|
tree
|
||||||
canonicalize_constructor_val (tree cval)
|
canonicalize_constructor_val (tree cval, tree from_decl)
|
||||||
{
|
{
|
||||||
STRIP_NOPS (cval);
|
STRIP_NOPS (cval);
|
||||||
if (TREE_CODE (cval) == POINTER_PLUS_EXPR
|
if (TREE_CODE (cval) == POINTER_PLUS_EXPR
|
||||||
|
|
@ -130,7 +159,7 @@ canonicalize_constructor_val (tree cval)
|
||||||
|
|
||||||
if ((TREE_CODE (base) == VAR_DECL
|
if ((TREE_CODE (base) == VAR_DECL
|
||||||
|| TREE_CODE (base) == FUNCTION_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;
|
return NULL_TREE;
|
||||||
if (TREE_CODE (base) == VAR_DECL)
|
if (TREE_CODE (base) == VAR_DECL)
|
||||||
{
|
{
|
||||||
|
|
@ -163,7 +192,7 @@ get_symbol_constant_value (tree sym)
|
||||||
tree val = DECL_INITIAL (sym);
|
tree val = DECL_INITIAL (sym);
|
||||||
if (val)
|
if (val)
|
||||||
{
|
{
|
||||||
val = canonicalize_constructor_val (val);
|
val = canonicalize_constructor_val (val, sym);
|
||||||
if (val && is_gimple_min_invariant (val))
|
if (val && is_gimple_min_invariant (val))
|
||||||
return val;
|
return val;
|
||||||
else
|
else
|
||||||
|
|
@ -2627,7 +2656,7 @@ gimple_fold_stmt_to_constant (gimple stmt, tree (*valueize) (tree))
|
||||||
|
|
||||||
static tree fold_ctor_reference (tree type, tree ctor,
|
static tree fold_ctor_reference (tree type, tree ctor,
|
||||||
unsigned HOST_WIDE_INT offset,
|
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.
|
/* See if we can find constructor defining value of BASE.
|
||||||
When we know the consructor with constant offset (such as
|
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
|
static tree
|
||||||
fold_array_ctor_reference (tree type, tree ctor,
|
fold_array_ctor_reference (tree type, tree ctor,
|
||||||
unsigned HOST_WIDE_INT offset,
|
unsigned HOST_WIDE_INT offset,
|
||||||
unsigned HOST_WIDE_INT size)
|
unsigned HOST_WIDE_INT size,
|
||||||
|
tree from_decl)
|
||||||
{
|
{
|
||||||
unsigned HOST_WIDE_INT cnt;
|
unsigned HOST_WIDE_INT cnt;
|
||||||
tree cfield, cval;
|
tree cfield, cval;
|
||||||
|
|
@ -2824,7 +2854,8 @@ fold_array_ctor_reference (tree type, tree ctor,
|
||||||
/* Do we have match? */
|
/* Do we have match? */
|
||||||
if (double_int_cmp (access_index, index, 1) >= 0
|
if (double_int_cmp (access_index, index, 1) >= 0
|
||||||
&& double_int_cmp (access_index, max_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,
|
/* When memory is not explicitely mentioned in constructor,
|
||||||
it is 0 (or out of range). */
|
it is 0 (or out of range). */
|
||||||
|
|
@ -2837,7 +2868,8 @@ fold_array_ctor_reference (tree type, tree ctor,
|
||||||
static tree
|
static tree
|
||||||
fold_nonarray_ctor_reference (tree type, tree ctor,
|
fold_nonarray_ctor_reference (tree type, tree ctor,
|
||||||
unsigned HOST_WIDE_INT offset,
|
unsigned HOST_WIDE_INT offset,
|
||||||
unsigned HOST_WIDE_INT size)
|
unsigned HOST_WIDE_INT size,
|
||||||
|
tree from_decl)
|
||||||
{
|
{
|
||||||
unsigned HOST_WIDE_INT cnt;
|
unsigned HOST_WIDE_INT cnt;
|
||||||
tree cfield, cval;
|
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)
|
if (double_int_cmp (uhwi_to_double_int (offset), bitoffset, 0) < 0)
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
return fold_ctor_reference (type, cval,
|
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. */
|
/* 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
|
static tree
|
||||||
fold_ctor_reference (tree type, tree ctor, unsigned HOST_WIDE_INT offset,
|
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;
|
tree ret;
|
||||||
|
|
||||||
/* We found the field with exact match. */
|
/* We found the field with exact match. */
|
||||||
if (useless_type_conversion_p (type, TREE_TYPE (ctor))
|
if (useless_type_conversion_p (type, TREE_TYPE (ctor))
|
||||||
&& !offset)
|
&& !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
|
/* We are at the end of walk, see if we can view convert the
|
||||||
result. */
|
result. */
|
||||||
|
|
@ -2920,7 +2953,7 @@ fold_ctor_reference (tree type, tree ctor, unsigned HOST_WIDE_INT offset,
|
||||||
&& operand_equal_p (TYPE_SIZE (type),
|
&& operand_equal_p (TYPE_SIZE (type),
|
||||||
TYPE_SIZE (TREE_TYPE (ctor)), 0))
|
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);
|
ret = fold_unary (VIEW_CONVERT_EXPR, type, ret);
|
||||||
if (ret)
|
if (ret)
|
||||||
STRIP_NOPS (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
|
if (TREE_CODE (TREE_TYPE (ctor)) == ARRAY_TYPE
|
||||||
|| TREE_CODE (TREE_TYPE (ctor)) == VECTOR_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
|
else
|
||||||
return fold_nonarray_ctor_reference (type, ctor, offset, size);
|
return fold_nonarray_ctor_reference (type, ctor, offset, size,
|
||||||
|
from_decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
|
|
@ -3008,7 +3043,8 @@ fold_const_aggregate_ref_1 (tree t, tree (*valueize) (tree))
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
return fold_ctor_reference (TREE_TYPE (t), ctor, offset,
|
return fold_ctor_reference (TREE_TYPE (t), ctor, offset,
|
||||||
TREE_INT_CST_LOW (unit_size)
|
TREE_INT_CST_LOW (unit_size)
|
||||||
* BITS_PER_UNIT);
|
* BITS_PER_UNIT,
|
||||||
|
base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Fallthru. */
|
/* Fallthru. */
|
||||||
|
|
@ -3034,7 +3070,8 @@ fold_const_aggregate_ref_1 (tree t, tree (*valueize) (tree))
|
||||||
if (offset < 0)
|
if (offset < 0)
|
||||||
return NULL_TREE;
|
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 REALPART_EXPR:
|
||||||
case IMAGPART_EXPR:
|
case IMAGPART_EXPR:
|
||||||
|
|
@ -3068,9 +3105,9 @@ tree
|
||||||
gimple_get_virt_method_for_binfo (HOST_WIDE_INT token, tree known_binfo)
|
gimple_get_virt_method_for_binfo (HOST_WIDE_INT token, tree known_binfo)
|
||||||
{
|
{
|
||||||
unsigned HOST_WIDE_INT offset, size;
|
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 there is no virtual methods table, leave the OBJ_TYPE_REF alone. */
|
||||||
if (!v)
|
if (!v)
|
||||||
return NULL_TREE;
|
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);
|
size = tree_low_cst (TYPE_SIZE (TREE_TYPE (TREE_TYPE (v))), 1);
|
||||||
offset += token * size;
|
offset += token * size;
|
||||||
fn = fold_ctor_reference (TREE_TYPE (TREE_TYPE (v)), DECL_INITIAL (v),
|
fn = fold_ctor_reference (TREE_TYPE (TREE_TYPE (v)), DECL_INITIAL (v),
|
||||||
offset, size);
|
offset, size, vtable);
|
||||||
if (!fn || integer_zerop (fn))
|
if (!fn || integer_zerop (fn))
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
gcc_assert (TREE_CODE (fn) == ADDR_EXPR
|
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
|
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 (!can_refer_decl_in_current_unit_p (fn))
|
if (!can_refer_decl_in_current_unit_p (fn, vtable))
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
|
|
||||||
/* Make sure we create a cgraph node for functions we'll reference.
|
/* Make sure we create a cgraph node for functions we'll reference.
|
||||||
|
|
|
||||||
|
|
@ -5315,7 +5315,7 @@ tree gimple_fold_builtin (gimple);
|
||||||
bool fold_stmt (gimple_stmt_iterator *);
|
bool fold_stmt (gimple_stmt_iterator *);
|
||||||
bool fold_stmt_inplace (gimple_stmt_iterator *);
|
bool fold_stmt_inplace (gimple_stmt_iterator *);
|
||||||
tree get_symbol_constant_value (tree);
|
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,
|
extern tree maybe_fold_and_comparisons (enum tree_code, tree, tree,
|
||||||
enum tree_code, tree, tree);
|
enum tree_code, tree, tree);
|
||||||
extern tree maybe_fold_or_comparisons (enum tree_code, tree, tree,
|
extern tree maybe_fold_or_comparisons (enum tree_code, tree, tree,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue