aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/optimize.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/optimize.cc')
-rw-r--r--gcc/cp/optimize.cc55
1 files changed, 55 insertions, 0 deletions
diff --git a/gcc/cp/optimize.cc b/gcc/cp/optimize.cc
index ff4fb5b..7147f5e 100644
--- a/gcc/cp/optimize.cc
+++ b/gcc/cp/optimize.cc
@@ -723,3 +723,58 @@ maybe_clone_body (tree fn)
/* We don't need to process the original function any further. */
return 1;
}
+
+/* If maybe_clone_body is called while the cdtor is still tentative,
+ DECL_ONE_ONLY will be false and so will be can_alias_cdtor (fn).
+ In that case we wouldn't try to optimize using an alias and instead
+ would emit separate base and complete cdtor. The following function
+ attempts to still optimize that case when we import_export_decl
+ is called first time on one of the clones. */
+
+void
+maybe_optimize_cdtor (tree orig_decl)
+{
+ tree fns[3];
+ tree fn = DECL_CLONED_FUNCTION (orig_decl);
+ gcc_checking_assert (DECL_MAYBE_IN_CHARGE_CDTOR_P (fn));
+ if (DECL_INTERFACE_KNOWN (fn)
+ || !TREE_ASM_WRITTEN (fn)
+ || !DECL_ONE_ONLY (orig_decl)
+ || symtab->global_info_ready)
+ return;
+
+ populate_clone_array (fn, fns);
+
+ if (!fns[0] || !fns[1])
+ return;
+ for (int i = 2 - !fns[2]; i >= 0; --i)
+ if (fns[i] != orig_decl && DECL_INTERFACE_KNOWN (fns[i]))
+ return;
+ DECL_INTERFACE_KNOWN (fn) = 1;
+ comdat_linkage (fn);
+ if (!can_alias_cdtor (fn))
+ return;
+ /* For comdat base and complete cdtors put them into the same,
+ *[CD]5* comdat group instead of *[CD][12]*. */
+ auto n0 = cgraph_node::get_create (fns[0]);
+ auto n1 = cgraph_node::get_create (fns[1]);
+ auto n2 = fns[2] ? cgraph_node::get_create (fns[1]) : NULL;
+ if (n0->lowered || n1->lowered || (n2 && n2->lowered))
+ return;
+ import_export_decl (fns[0]);
+ n1->definition = false;
+ if (!n0->create_same_body_alias (fns[1], fns[0]))
+ return;
+
+ tree comdat_group = cdtor_comdat_group (fns[1], fns[0]);
+ n1 = cgraph_node::get (fns[1]);
+ n0->set_comdat_group (comdat_group);
+ if (n1->same_comdat_group)
+ n1->remove_from_same_comdat_group ();
+ n1->add_to_same_comdat_group (n0);
+ if (fns[2])
+ n2->add_to_same_comdat_group (n0);
+ import_export_decl (fns[1]);
+ /* Remove the body now that it is an alias. */
+ release_function_body (fns[1]);
+}