Commit 64e0f5ff by Jan Hubicka Committed by Jan Hubicka

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
parent 4ce9b2b2
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>
PR target/45726
......
......@@ -728,7 +728,7 @@ void varpool_empty_needed_queue (void);
bool varpool_extra_name_alias (tree, tree);
const char * varpool_node_name (struct varpool_node *node);
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. */
#define FOR_EACH_STATIC_VARIABLE(node) \
......
......@@ -9851,16 +9851,10 @@ string_constant (tree arg, tree *ptr_offset)
int length;
/* 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)
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"; */
if (DECL_SIZE_UNIT (array) == NULL_TREE
|| TREE_CODE (DECL_SIZE_UNIT (array)) != INTEGER_CST
......
......@@ -122,9 +122,7 @@ canonicalize_constructor_val (tree cval)
tree
get_symbol_constant_value (tree sym)
{
if ((TREE_STATIC (sym) || DECL_EXTERNAL (sym))
&& (TREE_CODE (sym) == CONST_DECL
|| varpool_get_node (sym)->const_value_known))
if (const_value_known_p (sym))
{
tree val = DECL_INITIAL (sym);
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
have to do is replicate it as a GIMPLE_CALL tuple. */
gimple_stmt_iterator gsi;
call = gimple_build_call_from_tree (*expr_p);
gimplify_seq_add_stmt (pre_p, call);
gsi = gsi_last (*pre_p);
fold_stmt (&gsi);
*expr_p = NULL_TREE;
}
......
......@@ -570,7 +570,7 @@ ipa_discover_readonly_nonaddressable_vars (void)
if (dump_file)
fprintf (dump_file, " %s (read-only)", varpool_node_name (vnode));
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)
......@@ -779,7 +779,7 @@ function_and_variable_visibility (bool whole_program)
DECL_COMMON (vnode->decl) = 0;
/* Even extern variables might have initializers known.
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)
{
......@@ -814,7 +814,7 @@ function_and_variable_visibility (bool whole_program)
gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (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));
}
pointer_set_destroy (aliased_nodes);
......
......@@ -813,8 +813,7 @@ compute_ltrans_boundary (struct lto_out_decl_state *state,
if (DECL_INITIAL (vnode->decl)
&& !lto_varpool_encoder_encode_initializer_p (varpool_encoder,
vnode)
&& (DECL_IN_CONSTANT_POOL (vnode->decl)
|| vnode->const_value_known))
&& const_value_known_p (vnode->decl))
{
lto_set_varpool_encoder_encode_initializer (varpool_encoder, vnode);
add_references (encoder, varpool_encoder, &vnode->ref_list);
......
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>
* 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.
This needs to be done recursively. */
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)
&& !varpool_node_in_set_p (vnode, vset)
&& referenced_from_this_partition_p (&vnode->ref_list, set, vset)
......
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>
PR testsuite/45706
......
/* { 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))
{
case VAR_DECL:
if (!TREE_READONLY (base)
|| ((TREE_STATIC (base) || DECL_EXTERNAL (base))
&& !varpool_get_node (base)->const_value_known))
if (!const_value_known_p (base))
return NULL_TREE;
/* 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. */
while (handled_component_p (base))
base = TREE_OPERAND (base, 0);
if ((DECL_P (base)
&& TREE_STATIC (base)
&& TREE_READONLY (base)
&& varpool_get_node (base)->const_value_known)
if ((DECL_P (base) == VAR_DECL
&& const_value_known_p (base))
|| CONSTANT_CLASS_P (base))
{
/* 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 if NODE is constant and its initial value is known (so we can do
constant folding). The decision depends on whole program decisions
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. */
/* Return if DECL is constant and its initial value is known (so we can do
constant folding using DECL_INITIAL (decl)). */
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);
if (!TREE_READONLY (decl))
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
have zero as the initializer if they may not be
overridden at link or run time. */
......@@ -423,7 +444,7 @@ varpool_finalize_decl (tree decl)
there. */
else if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
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)
varpool_assemble_pending_decls ();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment