aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/cgraph.h2
-rw-r--r--gcc/expr.c8
-rw-r--r--gcc/gimple-fold.c4
-rw-r--r--gcc/gimplify.c3
-rw-r--r--gcc/ipa.c6
-rw-r--r--gcc/lto-cgraph.c3
-rw-r--r--gcc/lto/ChangeLog5
-rw-r--r--gcc/lto/lto.c2
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr45605.C37
-rw-r--r--gcc/tree-ssa-ccp.c4
-rw-r--r--gcc/tree-ssa-loop-ivcanon.c6
-rw-r--r--gcc/varpool.c39
14 files changed, 109 insertions, 33 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 648dc8e..bb6ade7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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>
PR target/45726
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index c868d32..ec90894 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -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) \
diff --git a/gcc/expr.c b/gcc/expr.c
index 16daddc..e99eabe 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 14031c8..8faadcc 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -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)
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 5953160..e5b011a 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -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;
}
diff --git a/gcc/ipa.c b/gcc/ipa.c
index e4835c1..5ff7c14 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -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);
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 22b35ee..f009fcc 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -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);
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 59124ee..6aab1af 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -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>
* lto-elf.c (lto_obj_file_open): Also provide filename when
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 40816e5..98a9387 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index cef92c4..3d98cd9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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>
PR testsuite/45706
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr45605.C b/gcc/testsuite/g++.dg/tree-ssa/pr45605.C
new file mode 100644
index 0000000..b47f91a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr45605.C
@@ -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" } } */
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 42b8a58..cf4321a 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -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. */
diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c
index 2ced307..187f53c 100644
--- a/gcc/tree-ssa-loop-ivcanon.c
+++ b/gcc/tree-ssa-loop-ivcanon.c
@@ -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. */
diff --git a/gcc/varpool.c b/gcc/varpool.c
index 2b08094..3ce3bac 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -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 ();
}