+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.
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.
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;
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);
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
&& !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;
}
/* 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. */
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))
+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
// 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" } }
--- /dev/null
+/* { 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" } } */