aboutsummaryrefslogtreecommitdiff
path: root/gcc/cgraphunit.cc
diff options
context:
space:
mode:
authorSandra Loosemore <sandra@codesourcery.com>2023-01-03 17:46:02 +0000
committerSandra Loosemore <sandra@codesourcery.com>2023-01-03 17:49:23 +0000
commit0425ae780fb2b055d985b5719af5edfaaad5e980 (patch)
tree147cec247d54aa4c199df4074534f686fd8b42c3 /gcc/cgraphunit.cc
parent8fdef16cd5d1b89359db3cd9a9768ab2d1b5081f (diff)
downloadgcc-0425ae780fb2b055d985b5719af5edfaaad5e980.zip
gcc-0425ae780fb2b055d985b5719af5edfaaad5e980.tar.gz
gcc-0425ae780fb2b055d985b5719af5edfaaad5e980.tar.bz2
OpenMP: GC unused SIMD clones
SIMD clones are created during the IPA phase when it is not known whether or not the vectorizer can use them. Clones for functions with external linkage are part of the ABI, but local clones can be GC'ed if no calls are found in the compilation unit after vectorization. gcc/ChangeLog * cgraph.h (struct cgraph_node): Add gc_candidate bit, modify default constructor to initialize it. * cgraphunit.cc (expand_all_functions): Save gc_candidate functions for last and iterate to handle recursive calls. Delete leftover candidates at the end. * omp-simd-clone.cc (simd_clone_create): Set gc_candidate bit on local clones. * tree-vect-stmts.cc (vectorizable_simd_clone_call): Clear gc_candidate bit when a clone is used. gcc/testsuite/ChangeLog * g++.dg/gomp/target-simd-clone-1.C: Tweak to test that the unused clone is GC'ed. * gcc.dg/gomp/target-simd-clone-1.c: Likewise.
Diffstat (limited to 'gcc/cgraphunit.cc')
-rw-r--r--gcc/cgraphunit.cc49
1 files changed, 41 insertions, 8 deletions
diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc
index 548bb85..59ce270 100644
--- a/gcc/cgraphunit.cc
+++ b/gcc/cgraphunit.cc
@@ -1996,19 +1996,52 @@ expand_all_functions (void)
/* Output functions in RPO so callees get optimized before callers. This
makes ipa-ra and other propagators to work.
- FIXME: This is far from optimal code layout. */
- for (i = new_order_pos - 1; i >= 0; i--)
- {
- node = order[i];
+ FIXME: This is far from optimal code layout.
+ Make multiple passes over the list to defer processing of gc
+ candidates until all potential uses are seen. */
+ int gc_candidates = 0;
+ int prev_gc_candidates = 0;
- if (node->process)
+ while (1)
+ {
+ for (i = new_order_pos - 1; i >= 0; i--)
{
- expanded_func_count++;
- node->process = 0;
- node->expand ();
+ node = order[i];
+
+ if (node->gc_candidate)
+ gc_candidates++;
+ else if (node->process)
+ {
+ expanded_func_count++;
+ node->process = 0;
+ node->expand ();
+ }
}
+ if (!gc_candidates || gc_candidates == prev_gc_candidates)
+ break;
+ prev_gc_candidates = gc_candidates;
+ gc_candidates = 0;
}
+ /* Free any unused gc_candidate functions. */
+ if (gc_candidates)
+ for (i = new_order_pos - 1; i >= 0; i--)
+ {
+ node = order[i];
+ if (node->gc_candidate)
+ {
+ struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
+ if (symtab->dump_file)
+ fprintf (symtab->dump_file,
+ "Deleting unused function %s\n",
+ IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
+ node->process = false;
+ free_dominance_info (fn, CDI_DOMINATORS);
+ free_dominance_info (fn, CDI_POST_DOMINATORS);
+ node->release_body (false);
+ }
+ }
+
if (dump_file)
fprintf (dump_file, "Expanded functions with time profile (%s):%u/%u\n",
main_input_filename, profiled_func_count, expanded_func_count);