diff options
author | Sandra Loosemore <sandra@codesourcery.com> | 2023-01-03 17:46:02 +0000 |
---|---|---|
committer | Sandra Loosemore <sandra@codesourcery.com> | 2023-01-03 17:49:23 +0000 |
commit | 0425ae780fb2b055d985b5719af5edfaaad5e980 (patch) | |
tree | 147cec247d54aa4c199df4074534f686fd8b42c3 /gcc/cgraphunit.cc | |
parent | 8fdef16cd5d1b89359db3cd9a9768ab2d1b5081f (diff) | |
download | gcc-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.cc | 49 |
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); |