ipareference2_0.c: New file.
authorJan Hubicka <jh@suse.cz>
Wed, 19 May 2010 23:55:38 +0000 (01:55 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Wed, 19 May 2010 23:55:38 +0000 (23:55 +0000)
* gcc.dg/lto/ipareference2_0.c: New file.
* gcc.dg/lto/ipareference2_1.c: New file.
* lto.c (promote_var, promote_fn): New functions.
(lto_promote_cross_file_statics): Compute correctly boundary including
static initializers of readonly vars.

From-SVN: r159604

gcc/lto/ChangeLog
gcc/lto/lto.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/lto/ipareference2_0.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/lto/ipareference2_1.c [new file with mode: 0644]

index b26268a3a96f19dd3ddc8ff4942993e57e035234..492cd6152dce2f0414cbee5b1e53511eb1381163 100644 (file)
@@ -1,6 +1,12 @@
+2010-05-20  Jan Hubicka  <jh@suse.cz>
+
+       * lto.c (promote_var, promote_fn): New functions.
+       (lto_promote_cross_file_statics): Compute correctly boundary including
+       static initializers of readonly vars.
+
 2010-05-18  Jan Hubicka  <jh@suse.cz>
 
-       * lto/lto.c (lto_1_to_1_map): Partition non-inline clones.
+       * lto.c (lto_1_to_1_map): Partition non-inline clones.
        (lto_promote_cross_file_statics): Deal with non-inline clones.
 
 2010-05-18  Jan Hubicka  <jh@suse.cz>
index adfeae95ce8811fcd335d457f903f0a26da188ce..92fa4dd5a3804bdddc532f420447138116f36336 100644 (file)
@@ -691,6 +691,42 @@ lto_add_all_inlinees (cgraph_node_set set)
   lto_bitmap_free (original_decls);
 }
 
+/* Promote variable VNODE to be static.  */
+
+static bool
+promote_var (struct varpool_node *vnode)
+{
+  if (TREE_PUBLIC (vnode->decl) || DECL_EXTERNAL (vnode->decl))
+    return false;
+  gcc_assert (flag_wpa);
+  TREE_PUBLIC (vnode->decl) = 1;
+  DECL_VISIBILITY (vnode->decl) = VISIBILITY_HIDDEN;
+  return true;
+}
+
+/* Promote function NODE to be static.  */
+
+static bool
+promote_fn (struct cgraph_node *node)
+{
+  gcc_assert (flag_wpa);
+  if (TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl))
+    return false;
+  TREE_PUBLIC (node->decl) = 1;
+  DECL_VISIBILITY (node->decl) = VISIBILITY_HIDDEN;
+  if (node->same_body)
+    {
+      struct cgraph_node *alias;
+      for (alias = node->same_body;
+          alias; alias = alias->next)
+       {
+         TREE_PUBLIC (alias->decl) = 1;
+         DECL_VISIBILITY (alias->decl) = VISIBILITY_HIDDEN;
+       }
+    }
+  return true;
+}
+
 /* Find out all static decls that need to be promoted to global because
    of cross file sharing.  This function must be run in the WPA mode after
    all inlinees are added.  */
@@ -704,6 +740,8 @@ lto_promote_cross_file_statics (void)
   varpool_node_set vset;
   cgraph_node_set_iterator csi;
   varpool_node_set_iterator vsi;
+  VEC(varpool_node_ptr, heap) *promoted_initializers = NULL;
+  struct pointer_set_t *inserted = pointer_set_create ();
 
   gcc_assert (flag_wpa);
 
@@ -725,21 +763,7 @@ lto_promote_cross_file_statics (void)
          if (!DECL_EXTERNAL (node->decl)
              && (referenced_from_other_partition_p (&node->ref_list, set, vset)
                  || reachable_from_other_partition_p (node, set)))
-            {
-               gcc_assert (flag_wpa);
-               TREE_PUBLIC (node->decl) = 1;
-               DECL_VISIBILITY (node->decl) = VISIBILITY_HIDDEN;
-               if (node->same_body)
-                 {
-                   struct cgraph_node *alias;
-                   for (alias = node->same_body;
-                        alias; alias = alias->next)
-                     {
-                       TREE_PUBLIC (alias->decl) = 1;
-                       DECL_VISIBILITY (alias->decl) = VISIBILITY_HIDDEN;
-                     }
-                 }
-            }
+           promote_fn (node);
        }
       for (vsi = vsi_start (vset); !vsi_end_p (vsi); vsi_next (&vsi))
        {
@@ -748,16 +772,73 @@ lto_promote_cross_file_statics (void)
             be made global.  It is sensible to keep those ltrans local to
             allow better optimization.  */
          if (!DECL_IN_CONSTANT_POOL (vnode->decl)
-             && !vnode->externally_visible && vnode->analyzed
-             && referenced_from_other_partition_p (&vnode->ref_list, set, vset))
+            && !vnode->externally_visible && vnode->analyzed
+            && referenced_from_other_partition_p (&vnode->ref_list,
+                                                  set, vset))
+           promote_var (vnode);
+       }
+
+      /* We export initializers of read-only var into each partition
+        referencing it.  Folding might take declarations from the
+        initializers and use it; so everything referenced from the
+        initializers needs can be accessed from this partition after
+        folding.
+
+        This means that we need to promote all variables and functions
+        referenced from all initializers from readonly vars referenced
+        from this partition that are not in this partition.
+        This needs to be done recursively.  */
+      for (vnode = varpool_nodes; vnode; vnode = vnode->next)
+       if ((TREE_READONLY (vnode->decl) || DECL_IN_CONSTANT_POOL (vnode->decl))
+           && DECL_INITIAL (vnode->decl)
+           && !varpool_node_in_set_p (vnode, vset)
+           && referenced_from_this_partition_p (&vnode->ref_list, set, vset)
+           && !pointer_set_insert (inserted, vnode))
+       VEC_safe_push (varpool_node_ptr, heap, promoted_initializers, vnode);
+      while (!VEC_empty (varpool_node_ptr, promoted_initializers))
+       {
+         int i;
+         struct ipa_ref *ref;
+
+         vnode = VEC_pop (varpool_node_ptr, promoted_initializers);
+         for (i = 0; ipa_ref_list_reference_iterate (&vnode->ref_list, i, ref); i++)
            {
-             gcc_assert (flag_wpa);
-             TREE_PUBLIC (vnode->decl) = 1;
-             DECL_VISIBILITY (vnode->decl) = VISIBILITY_HIDDEN;
+             if (ref->refered_type == IPA_REF_CGRAPH)
+               {
+                 struct cgraph_node *n = ipa_ref_node (ref);
+                 gcc_assert (!n->global.inlined_to);
+                 if (!n->local.externally_visible
+                     && !cgraph_node_in_set_p (n, set))
+                   promote_fn (n);
+               }
+             else
+               {
+                 struct varpool_node *v = ipa_ref_varpool_node (ref);
+                 if (varpool_node_in_set_p (v, vset))
+                   continue;
+                 /* Constant pool references use internal labels and thus can not
+                    be made global.  It is sensible to keep those ltrans local to
+                    allow better optimization.  */
+                 if (DECL_IN_CONSTANT_POOL (v->decl))
+                   {
+                     if (!pointer_set_insert (inserted, vnode))
+                       VEC_safe_push (varpool_node_ptr, heap,
+                                      promoted_initializers, v);
+                   }
+                 else if (!DECL_IN_CONSTANT_POOL (v->decl)
+                          && !v->externally_visible && v->analyzed)
+                   {
+                     if (promote_var (v)
+                         && DECL_INITIAL (v->decl) && TREE_READONLY (v->decl)
+                         && !pointer_set_insert (inserted, vnode))
+                       VEC_safe_push (varpool_node_ptr, heap,
+                                      promoted_initializers, v);
+                   }
+               }
            }
        }
-
     }
+  pointer_set_destroy (inserted);
 }
 
 
index 3d12129edd878a7a03d657bed6267a9c270e82b5..b798cd6b4d5975e96e39d28f7585a71e33ec1e13 100644 (file)
@@ -1,3 +1,8 @@
+2010-05-19  Jan Hubicka  <jh@suse.cz>
+
+       * gcc.dg/lto/ipareference2_0.c: New file.
+       * gcc.dg/lto/ipareference2_1.c: New file.
+
 2010-05-19  Jason Merrill  <jason@redhat.com>
 
        * g++.dg/parse/fn-typedef2.C: New.
diff --git a/gcc/testsuite/gcc.dg/lto/ipareference2_0.c b/gcc/testsuite/gcc.dg/lto/ipareference2_0.c
new file mode 100644 (file)
index 0000000..b7b13e6
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-lto-options {{ -O1 -fwhopr -fwhole-program}} } */
+/* { dg-lto-do run } */
+
+/* Verify that ipa-reference marks A as constant and we fold references
+   to a[1] and a[2] to &c and that we promote C to hidden vars shared across ltrans units. */
+void abort (void);
+int b,c,d,e,f;
+int *a[5]={&b,&c,&c,&e};
+void other_ltrans (void);
+main()
+{
+  other_ltrans ();
+  if (*(a[1])!=11)
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/lto/ipareference2_1.c b/gcc/testsuite/gcc.dg/lto/ipareference2_1.c
new file mode 100644 (file)
index 0000000..c7653b0
--- /dev/null
@@ -0,0 +1,13 @@
+void abort (void);
+extern int *a[5];
+extern int b,c,d,e,f;
+__attribute__ ((noinline, noclone))
+void
+other_ltrans (void)
+{
+  if (!__builtin_constant_p (a[1]==a[2]))
+    abort ();
+  if (a[1]!=a[2])
+    abort ();
+  *(a[1])=11;
+}