]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/45307 (Stores expanding to no RTL not removed by tree optimizers...
authorJan Hubicka <jh@suse.cz>
Sat, 21 Aug 2010 09:46:15 +0000 (11:46 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sat, 21 Aug 2010 09:46:15 +0000 (09:46 +0000)
PR c++/45307
PR c++/17736
* cgraph.h (cgraph_only_called_directly_p,
cgraph_can_remove_if_no_direct_calls_and_refs_p): Handle
static cdtors.
* cgraphunit.c (cgraph_decide_is_function_needed): Static cdtors
are not needed.
(cgraph_finalize_function): Static cdtors are reachable.
(cgraph_mark_functions_to_output): Use cgraph_only_called_directly_p.

* gcc.dg/ipa/ctor-empty-1.c: Add testcase.
* g++.dg/tree-ssa/empty-2.C: Check that constructor got optimized out.

From-SVN: r163439

gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/cgraphunit.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/tree-ssa/empty-2.C
gcc/testsuite/gcc.dg/ipa/ctor-empty-1.c [new file with mode: 0644]

index 56fef865fa524b95f6e08a0bee8a34915da4cef9..4f467cac8a982bfb105c7f074c812dc41a30b6ce 100644 (file)
@@ -1,3 +1,15 @@
+2010-08-20  Jan Hubicka  <jh@suse.cz>
+
+       PR c++/45307
+       PR c++/17736
+       * cgraph.h (cgraph_only_called_directly_p,
+       cgraph_can_remove_if_no_direct_calls_and_refs_p): Handle
+       static cdtors.
+       * cgraphunit.c (cgraph_decide_is_function_needed): Static cdtors
+       are not needed.
+       (cgraph_finalize_function): Static cdtors are reachable.
+       (cgraph_mark_functions_to_output): Use cgraph_only_called_directly_p.
+
 2010-08-20  Jan Hubicka  <jh@suse.cz>
 
        * lto-cgraph.c (lto_output_edge): Use gimple_has_body_p instead of flag_wpa.
index 32ad190135b296f236924ef53247027c3ec90298..470fb5a78fb4afa66cfb628290fc04243f39d062 100644 (file)
@@ -2709,6 +2709,33 @@ cgraph_edge_cannot_lead_to_return (struct cgraph_edge *e)
     return cgraph_node_cannot_return (e->callee);
 }
 
+/* Return true when function NODE can be removed from callgraph
+   if all direct calls are eliminated.  */
+
+bool
+cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node)
+{
+  /* When function is needed, we can not remove it.  */
+  if (node->needed || node->reachable_from_other_partition)
+    return false;
+  /* Only COMDAT functions can be removed if externally visible.  */
+  if (node->local.externally_visible
+      && (!DECL_COMDAT (node->decl) || node->local.used_from_object_file))
+    return false;
+  /* Constructors and destructors are executed by the runtime, however
+     we can get rid of all pure constructors and destructors.  */
+  if (DECL_STATIC_CONSTRUCTOR (node->decl)
+      || DECL_STATIC_DESTRUCTOR (node->decl))
+    {
+      int flags = flags_from_decl_or_type (node->decl);
+      if (!optimize
+         || !(flags & (ECF_CONST | ECF_PURE))
+         || (flags & ECF_LOOPING_CONST_OR_PURE))
+       return false;
+    }
+  return true;
+}
+
 /* Return true when function NODE can be excpected to be removed
    from program when direct calls in this compilation unit are removed.
 
index 2dcdf2f22f3d0c3d704efa55b94bbd5e63a93804..f77a280d12f7f435ed66b5f07eea39050a224ae6 100644 (file)
@@ -608,6 +608,10 @@ void cgraph_set_looping_const_or_pure_flag (struct cgraph_node *, bool);
 tree clone_function_name (tree decl, const char *);
 bool cgraph_node_cannot_return (struct cgraph_node *);
 bool cgraph_edge_cannot_lead_to_return (struct cgraph_edge *);
+bool cgraph_will_be_removed_from_program_if_no_direct_calls
+  (struct cgraph_node *node);
+bool cgraph_can_remove_if_no_direct_calls_and_refs_p
+  (struct cgraph_node *node);
 
 /* In cgraphunit.c  */
 extern FILE *cgraph_dump_file;
@@ -664,8 +668,6 @@ void cgraph_remove_node_duplication_hook (struct cgraph_2node_hook_list *);
 void cgraph_materialize_all_clones (void);
 gimple cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *);
 bool cgraph_propagate_frequency (struct cgraph_node *node);
-bool cgraph_will_be_removed_from_program_if_no_direct_calls
-  (struct cgraph_node *node);
 /* In cgraphbuild.c  */
 unsigned int rebuild_cgraph_edges (void);
 void cgraph_rebuild_references (void);
@@ -903,17 +905,11 @@ varpool_node_set_nonempty_p (varpool_node_set set)
 static inline bool
 cgraph_only_called_directly_p (struct cgraph_node *node)
 {
-  return !node->needed && !node->address_taken && !node->local.externally_visible;
-}
-
-/* Return true when function NODE can be removed from callgraph
-   if all direct calls are eliminated.  */
-
-static inline bool
-cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node)
-{
-  return (!node->needed && !node->reachable_from_other_partition
-         && (DECL_COMDAT (node->decl) || !node->local.externally_visible));
+  return (!node->needed && !node->address_taken
+         && !node->reachable_from_other_partition
+         && !DECL_STATIC_CONSTRUCTOR (node->decl)
+         && !DECL_STATIC_DESTRUCTOR (node->decl)
+         && !node->local.externally_visible);
 }
 
 /* Return true when function NODE can be removed from callgraph
index 4ef63a2d350766e2fa2a3a4bb5d4c9089b30e2c0..57b7a8d9efa3fe13a64c159f59811586fea21f08 100644 (file)
@@ -367,11 +367,6 @@ cgraph_decide_is_function_needed (struct cgraph_node *node, tree decl)
       && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
     return true;
 
-  /* Constructors and destructors are reachable from the runtime by
-     some mechanism.  */
-  if (DECL_STATIC_CONSTRUCTOR (decl) || DECL_STATIC_DESTRUCTOR (decl))
-    return true;
-
   return false;
 }
 
@@ -532,7 +527,9 @@ cgraph_finalize_function (tree decl, bool nested)
   /* Since we reclaim unreachable nodes at the end of every language
      level unit, we need to be conservative about possible entry points
      there.  */
-  if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)))
+  if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
+      || DECL_STATIC_CONSTRUCTOR (decl)
+      || DECL_STATIC_DESTRUCTOR (decl))
     cgraph_mark_reachable_node (node);
 
   /* If we've not yet emitted decl, tell the debug info about it.  */
@@ -1219,8 +1216,7 @@ cgraph_mark_functions_to_output (void)
         outside the current compilation unit.  */
       if (node->analyzed
          && !node->global.inlined_to
-         && (node->needed || node->reachable_from_other_partition
-             || node->address_taken
+         && (!cgraph_only_called_directly_p (node)
              || (e && node->reachable))
          && !TREE_ASM_WRITTEN (decl)
          && !DECL_EXTERNAL (decl))
index 878b6aa242e3fe6c7414b74a10622ab7c23df4f6..423729ba81aa0e3f60873d727834a66ebff2a657 100644 (file)
@@ -1,3 +1,10 @@
+2010-08-20  Jan Hubicka  <jh@suse.cz>
+
+       PR c++/45307
+       PR c++/17736
+       * gcc.dg/ipa/ctor-empty-1.c: Add testcase.
+       * g++.dg/tree-ssa/empty-2.C: Check that constructor got optimized out.
+
 2010-08-20  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR target/45336
index 728678af30e15f17a0e2245946aa3d38647f20ff..2036bebe3046b36be844efc95bbce64344dcaaff 100644 (file)
@@ -1,8 +1,11 @@
 // PR c++/45307
-// { dg-options -fdump-tree-gimple }
+// { dg-options "-fdump-tree-gimple -fdump-tree-optimized" }
 
 struct fallible_t { };
 const fallible_t fallible = fallible_t();
 
 // { dg-final { scan-tree-dump-not "fallible" "gimple" } }
+// Whole constructor should be optimized away.
+// { dg-final { scan-tree-dump-not "int" "optimized" } }
 // { dg-final { cleanup-tree-dump "gimple" } }
+// { dg-final { cleanup-tree-dump "optimized" } }
diff --git a/gcc/testsuite/gcc.dg/ipa/ctor-empty-1.c b/gcc/testsuite/gcc.dg/ipa/ctor-empty-1.c
new file mode 100644 (file)
index 0000000..9cd2b09
--- /dev/null
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -c -fdump-ipa-whole-program"  } */
+static __attribute__((constructor))
+void empty_constructor()
+{
+}
+/* { dg-final { scan-ipa-dump "Reclaiming functions: empty_constructor"  "whole-program"  } } */
+/* { dg-final { cleanup-ipa-dump "whole-program" } } */