mirror of git://gcc.gnu.org/git/gcc.git
re PR tree-optimization/45605 (Missed devirtualization)
PR tree-optimize/45605 * cgraph.h (const_value_known_p): Declare. (varpool_decide_const_value_known): Remove. * tree-ssa-ccp.c (get_base_constructor): Use it. * lto-cgraph.c (compute_ltrans_boundary): Likewise. * expr.c (string_constant): Likewise. * tree-ssa-loop-ivcanon.c (constant_after_peeling): Likewise. * ipa.c (ipa_discover_readonly_nonaddressable_var, function_and_variable_visibility): Likewise. * gimplify.c (gimplify_call_expr): Likewise. * gimple-fold.c (get_symbol_constant_value): Likewise. * varpool.c (varpool_decide_const_value_known): Replace by... (const_value_known_p): ... this one; handle other kinds of DECLs too and work for automatic vars. (varpool_finalize_decl): Use const_value_known_p. * lto.c (lto_promote_cross_file_statics): Use const_value_known_p. * g++.dg/tree-ssa/pr45605.C: New testcase. From-SVN: r164438
This commit is contained in:
parent
4ce9b2b20f
commit
64e0f5ff1f
|
|
@ -1,3 +1,21 @@
|
||||||
|
2010-09-20 Jan Hubicka <jh@suse.cz>
|
||||||
|
|
||||||
|
PR tree-optimize/45605
|
||||||
|
* cgraph.h (const_value_known_p): Declare.
|
||||||
|
(varpool_decide_const_value_known): Remove.
|
||||||
|
* tree-ssa-ccp.c (get_base_constructor): Use it.
|
||||||
|
* lto-cgraph.c (compute_ltrans_boundary): Likewise.
|
||||||
|
* expr.c (string_constant): Likewise.
|
||||||
|
* tree-ssa-loop-ivcanon.c (constant_after_peeling): Likewise.
|
||||||
|
* ipa.c (ipa_discover_readonly_nonaddressable_var,
|
||||||
|
function_and_variable_visibility): Likewise.
|
||||||
|
* gimplify.c (gimplify_call_expr): Likewise.
|
||||||
|
* gimple-fold.c (get_symbol_constant_value): Likewise.
|
||||||
|
* varpool.c (varpool_decide_const_value_known): Replace by...
|
||||||
|
(const_value_known_p): ... this one; handle other kinds of DECLs
|
||||||
|
too and work for automatic vars.
|
||||||
|
(varpool_finalize_decl): Use const_value_known_p.
|
||||||
|
|
||||||
2010-09-20 Rafael Carre <rafael.carre@gmail.com>
|
2010-09-20 Rafael Carre <rafael.carre@gmail.com>
|
||||||
|
|
||||||
PR target/45726
|
PR target/45726
|
||||||
|
|
|
||||||
|
|
@ -728,7 +728,7 @@ void varpool_empty_needed_queue (void);
|
||||||
bool varpool_extra_name_alias (tree, tree);
|
bool varpool_extra_name_alias (tree, tree);
|
||||||
const char * varpool_node_name (struct varpool_node *node);
|
const char * varpool_node_name (struct varpool_node *node);
|
||||||
void varpool_reset_queue (void);
|
void varpool_reset_queue (void);
|
||||||
bool varpool_decide_const_value_known (struct varpool_node *node);
|
bool const_value_known_p (tree);
|
||||||
|
|
||||||
/* Walk all reachable static variables. */
|
/* Walk all reachable static variables. */
|
||||||
#define FOR_EACH_STATIC_VARIABLE(node) \
|
#define FOR_EACH_STATIC_VARIABLE(node) \
|
||||||
|
|
|
||||||
|
|
@ -9851,16 +9851,10 @@ string_constant (tree arg, tree *ptr_offset)
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
/* Variables initialized to string literals can be handled too. */
|
/* Variables initialized to string literals can be handled too. */
|
||||||
if (DECL_INITIAL (array) == NULL_TREE
|
if (!const_value_known_p (array)
|
||||||
|| TREE_CODE (DECL_INITIAL (array)) != STRING_CST)
|
|| TREE_CODE (DECL_INITIAL (array)) != STRING_CST)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* If they are read-only, non-volatile and bind locally. */
|
|
||||||
if (! TREE_READONLY (array)
|
|
||||||
|| TREE_SIDE_EFFECTS (array)
|
|
||||||
|| ! targetm.binds_local_p (array))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Avoid const char foo[4] = "abcde"; */
|
/* Avoid const char foo[4] = "abcde"; */
|
||||||
if (DECL_SIZE_UNIT (array) == NULL_TREE
|
if (DECL_SIZE_UNIT (array) == NULL_TREE
|
||||||
|| TREE_CODE (DECL_SIZE_UNIT (array)) != INTEGER_CST
|
|| TREE_CODE (DECL_SIZE_UNIT (array)) != INTEGER_CST
|
||||||
|
|
|
||||||
|
|
@ -122,9 +122,7 @@ canonicalize_constructor_val (tree cval)
|
||||||
tree
|
tree
|
||||||
get_symbol_constant_value (tree sym)
|
get_symbol_constant_value (tree sym)
|
||||||
{
|
{
|
||||||
if ((TREE_STATIC (sym) || DECL_EXTERNAL (sym))
|
if (const_value_known_p (sym))
|
||||||
&& (TREE_CODE (sym) == CONST_DECL
|
|
||||||
|| varpool_get_node (sym)->const_value_known))
|
|
||||||
{
|
{
|
||||||
tree val = DECL_INITIAL (sym);
|
tree val = DECL_INITIAL (sym);
|
||||||
if (val)
|
if (val)
|
||||||
|
|
|
||||||
|
|
@ -2479,8 +2479,11 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
|
||||||
{
|
{
|
||||||
/* The CALL_EXPR in *EXPR_P is already in GIMPLE form, so all we
|
/* The CALL_EXPR in *EXPR_P is already in GIMPLE form, so all we
|
||||||
have to do is replicate it as a GIMPLE_CALL tuple. */
|
have to do is replicate it as a GIMPLE_CALL tuple. */
|
||||||
|
gimple_stmt_iterator gsi;
|
||||||
call = gimple_build_call_from_tree (*expr_p);
|
call = gimple_build_call_from_tree (*expr_p);
|
||||||
gimplify_seq_add_stmt (pre_p, call);
|
gimplify_seq_add_stmt (pre_p, call);
|
||||||
|
gsi = gsi_last (*pre_p);
|
||||||
|
fold_stmt (&gsi);
|
||||||
*expr_p = NULL_TREE;
|
*expr_p = NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -570,7 +570,7 @@ ipa_discover_readonly_nonaddressable_vars (void)
|
||||||
if (dump_file)
|
if (dump_file)
|
||||||
fprintf (dump_file, " %s (read-only)", varpool_node_name (vnode));
|
fprintf (dump_file, " %s (read-only)", varpool_node_name (vnode));
|
||||||
TREE_READONLY (vnode->decl) = 1;
|
TREE_READONLY (vnode->decl) = 1;
|
||||||
vnode->const_value_known |= varpool_decide_const_value_known (vnode);
|
vnode->const_value_known |= const_value_known_p (vnode->decl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dump_file)
|
if (dump_file)
|
||||||
|
|
@ -779,7 +779,7 @@ function_and_variable_visibility (bool whole_program)
|
||||||
DECL_COMMON (vnode->decl) = 0;
|
DECL_COMMON (vnode->decl) = 0;
|
||||||
/* Even extern variables might have initializers known.
|
/* Even extern variables might have initializers known.
|
||||||
See, for example testsuite/g++.dg/opt/static3.C */
|
See, for example testsuite/g++.dg/opt/static3.C */
|
||||||
vnode->const_value_known |= varpool_decide_const_value_known (vnode);
|
vnode->const_value_known |= const_value_known_p (vnode->decl);
|
||||||
}
|
}
|
||||||
for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
|
for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
|
||||||
{
|
{
|
||||||
|
|
@ -814,7 +814,7 @@ function_and_variable_visibility (bool whole_program)
|
||||||
gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->decl));
|
gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->decl));
|
||||||
cgraph_make_decl_local (vnode->decl);
|
cgraph_make_decl_local (vnode->decl);
|
||||||
}
|
}
|
||||||
vnode->const_value_known |= varpool_decide_const_value_known (vnode);
|
vnode->const_value_known |= const_value_known_p (vnode->decl);
|
||||||
gcc_assert (TREE_STATIC (vnode->decl));
|
gcc_assert (TREE_STATIC (vnode->decl));
|
||||||
}
|
}
|
||||||
pointer_set_destroy (aliased_nodes);
|
pointer_set_destroy (aliased_nodes);
|
||||||
|
|
|
||||||
|
|
@ -813,8 +813,7 @@ compute_ltrans_boundary (struct lto_out_decl_state *state,
|
||||||
if (DECL_INITIAL (vnode->decl)
|
if (DECL_INITIAL (vnode->decl)
|
||||||
&& !lto_varpool_encoder_encode_initializer_p (varpool_encoder,
|
&& !lto_varpool_encoder_encode_initializer_p (varpool_encoder,
|
||||||
vnode)
|
vnode)
|
||||||
&& (DECL_IN_CONSTANT_POOL (vnode->decl)
|
&& const_value_known_p (vnode->decl))
|
||||||
|| vnode->const_value_known))
|
|
||||||
{
|
{
|
||||||
lto_set_varpool_encoder_encode_initializer (varpool_encoder, vnode);
|
lto_set_varpool_encoder_encode_initializer (varpool_encoder, vnode);
|
||||||
add_references (encoder, varpool_encoder, &vnode->ref_list);
|
add_references (encoder, varpool_encoder, &vnode->ref_list);
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
2010-09-20 Jan Hubicka <jh@suse.cz>
|
||||||
|
|
||||||
|
PR tree-optimize/45605
|
||||||
|
* lto.c (lto_promote_cross_file_statics): Use const_value_known_p.
|
||||||
|
|
||||||
2010-09-18 Gerald Pfeifer <gerald@pfeifer.com>
|
2010-09-18 Gerald Pfeifer <gerald@pfeifer.com>
|
||||||
|
|
||||||
* lto-elf.c (lto_obj_file_open): Also provide filename when
|
* lto-elf.c (lto_obj_file_open): Also provide filename when
|
||||||
|
|
|
||||||
|
|
@ -1008,7 +1008,7 @@ lto_promote_cross_file_statics (void)
|
||||||
from this partition that are not in this partition.
|
from this partition that are not in this partition.
|
||||||
This needs to be done recursively. */
|
This needs to be done recursively. */
|
||||||
for (vnode = varpool_nodes; vnode; vnode = vnode->next)
|
for (vnode = varpool_nodes; vnode; vnode = vnode->next)
|
||||||
if ((vnode->const_value_known || DECL_IN_CONSTANT_POOL (vnode->decl))
|
if (const_value_known_p (vnode->decl)
|
||||||
&& DECL_INITIAL (vnode->decl)
|
&& DECL_INITIAL (vnode->decl)
|
||||||
&& !varpool_node_in_set_p (vnode, vset)
|
&& !varpool_node_in_set_p (vnode, vset)
|
||||||
&& referenced_from_this_partition_p (&vnode->ref_list, set, vset)
|
&& referenced_from_this_partition_p (&vnode->ref_list, set, vset)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
2010-09-20 Jan Hubicka <jh@suse.cz>
|
||||||
|
|
||||||
|
PR tree-optimize/45605
|
||||||
|
* g++.dg/tree-ssa/pr45605.C: New testcase.
|
||||||
|
|
||||||
2010-09-20 Michael Matz <matz@suse.de>
|
2010-09-20 Michael Matz <matz@suse.de>
|
||||||
|
|
||||||
PR testsuite/45706
|
PR testsuite/45706
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
/* { dg-do compile } */
|
||||||
|
/* { dg-options "-O1 -fdump-tree-ssa" } */
|
||||||
|
extern "C" void abort();
|
||||||
|
bool destructor_called = false;
|
||||||
|
|
||||||
|
struct B {
|
||||||
|
virtual void Run(){};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct D : public B {
|
||||||
|
virtual void Run()
|
||||||
|
{
|
||||||
|
struct O {
|
||||||
|
~O() { destructor_called = true; };
|
||||||
|
} o;
|
||||||
|
|
||||||
|
struct Raiser {
|
||||||
|
Raiser() throw( int ) {throw 1;};
|
||||||
|
} raiser;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
try {
|
||||||
|
D d;
|
||||||
|
static_cast<B&>(d).Run();
|
||||||
|
} catch (...) {}
|
||||||
|
|
||||||
|
if (!destructor_called)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* We should devirtualize call to D::Run */
|
||||||
|
/* { dg-final { scan-tree-dump-times "D::Run (" 1 "ssa"} } */
|
||||||
|
/* { dg-final { cleanup-tree-dump "ssa" } } */
|
||||||
|
|
@ -1342,9 +1342,7 @@ get_base_constructor (tree base, tree *offset)
|
||||||
switch (TREE_CODE (base))
|
switch (TREE_CODE (base))
|
||||||
{
|
{
|
||||||
case VAR_DECL:
|
case VAR_DECL:
|
||||||
if (!TREE_READONLY (base)
|
if (!const_value_known_p (base))
|
||||||
|| ((TREE_STATIC (base) || DECL_EXTERNAL (base))
|
|
||||||
&& !varpool_get_node (base)->const_value_known))
|
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
|
|
||||||
/* Fallthru. */
|
/* Fallthru. */
|
||||||
|
|
|
||||||
|
|
@ -162,10 +162,8 @@ constant_after_peeling (tree op, gimple stmt, struct loop *loop)
|
||||||
/* First make fast look if we see constant array inside. */
|
/* First make fast look if we see constant array inside. */
|
||||||
while (handled_component_p (base))
|
while (handled_component_p (base))
|
||||||
base = TREE_OPERAND (base, 0);
|
base = TREE_OPERAND (base, 0);
|
||||||
if ((DECL_P (base)
|
if ((DECL_P (base) == VAR_DECL
|
||||||
&& TREE_STATIC (base)
|
&& const_value_known_p (base))
|
||||||
&& TREE_READONLY (base)
|
|
||||||
&& varpool_get_node (base)->const_value_known)
|
|
||||||
|| CONSTANT_CLASS_P (base))
|
|| CONSTANT_CLASS_P (base))
|
||||||
{
|
{
|
||||||
/* If so, see if we understand all the indices. */
|
/* If so, see if we understand all the indices. */
|
||||||
|
|
|
||||||
|
|
@ -359,21 +359,42 @@ decide_is_variable_needed (struct varpool_node *node, tree decl)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return if NODE is constant and its initial value is known (so we can do
|
/* Return if DECL is constant and its initial value is known (so we can do
|
||||||
constant folding). The decision depends on whole program decisions
|
constant folding using DECL_INITIAL (decl)). */
|
||||||
and can not be recomputed at ltrans stage for variables from other
|
|
||||||
partitions. For this reason the new value should be always combined
|
|
||||||
with the previous knowledge. */
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
varpool_decide_const_value_known (struct varpool_node *node)
|
const_value_known_p (tree decl)
|
||||||
{
|
{
|
||||||
tree decl = node->decl;
|
struct varpool_node *vnode;
|
||||||
|
|
||||||
|
if (TREE_CODE (decl) == PARM_DECL
|
||||||
|
|| TREE_CODE (decl) == RESULT_DECL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (TREE_CODE (decl) == CONST_DECL
|
||||||
|
|| DECL_IN_CONSTANT_POOL (decl))
|
||||||
|
return true;
|
||||||
|
|
||||||
gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
|
|
||||||
gcc_assert (TREE_CODE (decl) == VAR_DECL);
|
gcc_assert (TREE_CODE (decl) == VAR_DECL);
|
||||||
|
|
||||||
if (!TREE_READONLY (decl))
|
if (!TREE_READONLY (decl))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
/* Gimplifier takes away constructors of local vars */
|
||||||
|
if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
|
||||||
|
return DECL_INITIAL (decl) != NULL;
|
||||||
|
|
||||||
|
gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
|
||||||
|
|
||||||
|
/* In WHOPR mode we can put variable into one partition
|
||||||
|
and make it external in the other partition. In this
|
||||||
|
case we still know the value, but it can't be determined
|
||||||
|
from DECL flags. For this reason we keep const_value_known
|
||||||
|
flag in varpool nodes. */
|
||||||
|
if ((vnode = varpool_get_node (decl))
|
||||||
|
&& vnode->const_value_known)
|
||||||
|
return true;
|
||||||
|
|
||||||
/* Variables declared 'const' without an initializer
|
/* Variables declared 'const' without an initializer
|
||||||
have zero as the initializer if they may not be
|
have zero as the initializer if they may not be
|
||||||
overridden at link or run time. */
|
overridden at link or run time. */
|
||||||
|
|
@ -423,7 +444,7 @@ varpool_finalize_decl (tree decl)
|
||||||
there. */
|
there. */
|
||||||
else if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
|
else if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
|
||||||
varpool_mark_needed_node (node);
|
varpool_mark_needed_node (node);
|
||||||
node->const_value_known |= varpool_decide_const_value_known (node);
|
node->const_value_known |= const_value_known_p (node->decl);
|
||||||
if (cgraph_global_info_ready)
|
if (cgraph_global_info_ready)
|
||||||
varpool_assemble_pending_decls ();
|
varpool_assemble_pending_decls ();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue