OSDN Git Service

PR tree-optimize/45605
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 20 Sep 2010 15:48:42 +0000 (15:48 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 20 Sep 2010 15:48:42 +0000 (15:48 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@164438 138bc75d-0d04-0410-961f-82ee72b054a4

14 files changed:
gcc/ChangeLog
gcc/cgraph.h
gcc/expr.c
gcc/gimple-fold.c
gcc/gimplify.c
gcc/ipa.c
gcc/lto-cgraph.c
gcc/lto/ChangeLog
gcc/lto/lto.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/tree-ssa/pr45605.C [new file with mode: 0644]
gcc/tree-ssa-ccp.c
gcc/tree-ssa-loop-ivcanon.c
gcc/varpool.c

index 648dc8e..bb6ade7 100644 (file)
@@ -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
index c868d32..ec90894 100644 (file)
@@ -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) \
index 16daddc..e99eabe 100644 (file)
@@ -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
index 14031c8..8faadcc 100644 (file)
@@ -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)
index 5953160..e5b011a 100644 (file)
@@ -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;
     }
 
index e4835c1..5ff7c14 100644 (file)
--- 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);
index 22b35ee..f009fcc 100644 (file)
@@ -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);
index 59124ee..6aab1af 100644 (file)
@@ -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
index 40816e5..98a9387 100644 (file)
@@ -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)
index cef92c4..3d98cd9 100644 (file)
@@ -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 (file)
index 0000000..b47f91a
--- /dev/null
@@ -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" } } */
index 42b8a58..cf4321a 100644 (file)
@@ -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.  */
index 2ced307..187f53c 100644 (file)
@@ -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.  */
index 2b08094..3ce3bac 100644 (file)
@@ -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 ();
 }