OSDN Git Service

* cgraph.h (struct varpool_node): Add const_value_known.
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 3 Sep 2010 10:15:54 +0000 (10:15 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 3 Sep 2010 10:15:54 +0000 (10:15 +0000)
(varpool_decide_const_value_known): Declare.
* tree-ssa-ccp.c (fold_const_aggregate_ref): Update initializer folding.
* lto-cgraph.c (lto_output_varpool_node): Store const_value_known.
(input_varpool_node): Restore const_value_known.
* tree-ssa-loop-ivcanon (constant_after_peeling): Check varpool for
initializer folding.
* ipa.c (ipa_discover_readonly_nonaddressable_var,
function_and_variable_visibility): Compute const_value_known.
* gimple-fold.c (get_symbol_constant_value): Use varpool for initializer
folding.
* varpool.c (varpool_decide_const_value_known): New function.

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

gcc/ChangeLog
gcc/cgraph.h
gcc/gimple-fold.c
gcc/ipa.c
gcc/lto-cgraph.c
gcc/tree-ssa-ccp.c
gcc/tree-ssa-loop-ivcanon.c
gcc/varpool.c

index bfd0889..612e020 100644 (file)
@@ -1,3 +1,18 @@
+2010-09-03  Jan Hubicka  <jh@suse.cz>
+
+       * cgraph.h (struct varpool_node): Add const_value_known.
+       (varpool_decide_const_value_known): Declare.
+       * tree-ssa-ccp.c (fold_const_aggregate_ref): Update initializer folding.
+       * lto-cgraph.c (lto_output_varpool_node): Store const_value_known.
+       (input_varpool_node): Restore const_value_known.
+       * tree-ssa-loop-ivcanon (constant_after_peeling): Check varpool for
+       initializer folding.
+       * ipa.c (ipa_discover_readonly_nonaddressable_var,
+       function_and_variable_visibility): Compute const_value_known.
+       * gimple-fold.c (get_symbol_constant_value): Use varpool for initializer
+       folding.
+       * varpool.c (varpool_decide_const_value_known): New function.
+
 2010-09-03  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/i386.md: Remove empty prepartion statements
index f77a280..c868d32 100644 (file)
@@ -503,6 +503,8 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node {
      During WPA output it is used to mark nodes that are present in
      multiple partitions.  */
   unsigned in_other_partition : 1;
+  /* True when variable is constant and its value is known.  */
+  unsigned int const_value_known : 1;
 };
 
 /* Every top level asm statement is put into a cgraph_asm_node.  */
@@ -726,6 +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);
 
 /* Walk all reachable static variables.  */
 #define FOR_EACH_STATIC_VARIABLE(node) \
index 8a48316..033023a 100644 (file)
@@ -38,9 +38,9 @@ along with GCC; see the file COPYING3.  If not see
 tree
 get_symbol_constant_value (tree sym)
 {
-  if (TREE_STATIC (sym)
-      && (TREE_READONLY (sym)
-         || TREE_CODE (sym) == CONST_DECL))
+  if ((TREE_STATIC (sym) || DECL_EXTERNAL (sym))
+      && (TREE_CODE (sym) == CONST_DECL
+         || varpool_get_node (sym)->const_value_known))
     {
       tree val = DECL_INITIAL (sym);
       if (val)
@@ -65,8 +65,6 @@ get_symbol_constant_value (tree sym)
         have zero as the initializer if they may not be
         overridden at link or run time.  */
       if (!val
-         && !DECL_EXTERNAL (sym)
-         && targetm.binds_local_p (sym)
           && (INTEGRAL_TYPE_P (TREE_TYPE (sym))
               || SCALAR_FLOAT_TYPE_P (TREE_TYPE (sym))))
        return fold_convert (TREE_TYPE (sym), integer_zero_node);
index 021398b..b199796 100644 (file)
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -561,6 +561,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);
          }
       }
   if (dump_file)
@@ -767,6 +768,9 @@ function_and_variable_visibility (bool whole_program)
              || ! (ADDR_SPACE_GENERIC_P
                    (TYPE_ADDR_SPACE (TREE_TYPE (vnode->decl))))))
        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);
     }
   for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
     {
@@ -801,6 +805,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);
      gcc_assert (TREE_STATIC (vnode->decl));
     }
   pointer_set_destroy (aliased_nodes);
index 22b4916..dac5c32 100644 (file)
@@ -575,6 +575,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node
   bp_pack_value (&bp, node->force_output, 1);
   bp_pack_value (&bp, node->finalized, 1);
   bp_pack_value (&bp, node->alias, 1);
+  bp_pack_value (&bp, node->const_value_known, 1);
   gcc_assert (!node->alias || !node->extra_name);
   gcc_assert (node->finalized || !node->analyzed);
   gcc_assert (node->needed);
@@ -1106,6 +1107,7 @@ input_varpool_node (struct lto_file_decl_data *file_data,
   node->force_output = bp_unpack_value (&bp, 1);
   node->finalized = bp_unpack_value (&bp, 1);
   node->alias = bp_unpack_value (&bp, 1);
+  node->const_value_known = bp_unpack_value (&bp, 1);
   node->analyzed = node->finalized; 
   node->used_from_other_partition = bp_unpack_value (&bp, 1);
   node->in_other_partition = bp_unpack_value (&bp, 1);
index 5551df2..8c42a63 100644 (file)
@@ -1348,7 +1348,8 @@ fold_const_aggregate_ref (tree t)
        case VAR_DECL:
          if (!TREE_READONLY (base)
              || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE
-             || !targetm.binds_local_p (base))
+             || ((TREE_STATIC (base) || DECL_EXTERNAL (base))
+                 && !varpool_get_node (base)->const_value_known))
            return NULL_TREE;
 
          ctor = DECL_INITIAL (base);
@@ -1435,7 +1436,8 @@ fold_const_aggregate_ref (tree t)
        case VAR_DECL:
          if (!TREE_READONLY (base)
              || TREE_CODE (TREE_TYPE (base)) != RECORD_TYPE
-             || !targetm.binds_local_p (base))
+             || ((TREE_STATIC (base) || DECL_EXTERNAL (base))
+                 && !varpool_get_node (base)->const_value_known))
            return NULL_TREE;
 
          ctor = DECL_INITIAL (base);
@@ -1509,7 +1511,8 @@ fold_const_aggregate_ref (tree t)
 
          if (!TREE_READONLY (base)
              || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE
-             || !targetm.binds_local_p (base))
+             || ((TREE_STATIC (base) || DECL_EXTERNAL (base))
+                 && !varpool_get_node (base)->const_value_known))
            return NULL_TREE;
 
          ctor = DECL_INITIAL (base);
index b0d45bc..2ced307 100644 (file)
@@ -165,9 +165,7 @@ constant_after_peeling (tree op, gimple stmt, struct loop *loop)
       if ((DECL_P (base)
           && TREE_STATIC (base)
           && TREE_READONLY (base)
-           && (DECL_INITIAL (base)
-              || (!DECL_EXTERNAL (base)
-                  && targetm.binds_local_p (base))))
+          && varpool_get_node (base)->const_value_known)
          || CONSTANT_CLASS_P (base))
        {
          /* If so, see if we understand all the indices.  */
index 817a319..eac488f 100644 (file)
@@ -359,6 +359,37 @@ 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.  */
+
+bool
+varpool_decide_const_value_known (struct varpool_node *node)
+{
+  tree decl = node->decl;
+
+  gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
+  gcc_assert (TREE_CODE (decl) == VAR_DECL);
+  if (!TREE_READONLY (decl))
+    return false;
+  /* Variables declared 'const' without an initializer
+     have zero as the initializer if they may not be
+     overridden at link or run time.  */
+  if (!DECL_INITIAL (decl)
+      && (DECL_EXTERNAL (decl)
+         || DECL_REPLACEABLE_P (decl)))
+    return false;
+
+  /* Variables declared `const' with an initializer are considered
+     to not be overwritable with different initializer by default. 
+
+     ??? Previously we behaved so for scalar variables but not for array
+     accesses.  */
+  return true;
+}
+
 /* Mark DECL as finalized.  By finalizing the declaration, frontend instruct the
    middle end to output the variable to asm file, if needed or externally
    visible.  */