]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
OpenMP: GC unused SIMD clones
authorSandra Loosemore <sandra@codesourcery.com>
Tue, 3 Jan 2023 17:46:02 +0000 (17:46 +0000)
committerSandra Loosemore <sandra@codesourcery.com>
Tue, 3 Jan 2023 17:49:23 +0000 (17:49 +0000)
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.

gcc/cgraph.h
gcc/cgraphunit.cc
gcc/omp-simd-clone.cc
gcc/testsuite/g++.dg/gomp/target-simd-clone-1.C
gcc/testsuite/gcc.dg/gomp/target-simd-clone-1.c
gcc/tree-vect-stmts.cc

index 8dee2f6e59173010f2549775f1ba082cb4ac9ba6..5d3ced1b5d5eb8e1e761952a936f952b8d1785d3 100644 (file)
@@ -891,7 +891,8 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
       versionable (false), can_change_signature (false),
       redefined_extern_inline (false), tm_may_enter_irr (false),
       ipcp_clone (false), declare_variant_alt (false),
-      calls_declare_variant_alt (false), m_uid (uid), m_summary_id (-1)
+      calls_declare_variant_alt (false), gc_candidate (false),
+      m_uid (uid), m_summary_id (-1)
   {}
 
   /* Remove the node from cgraph and all inline clones inlined into it.
@@ -1490,6 +1491,10 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
   unsigned declare_variant_alt : 1;
   /* True if the function calls declare_variant_alt functions.  */
   unsigned calls_declare_variant_alt : 1;
+  /* True if the function should only be emitted if it is used.  This flag
+     is set for local SIMD clones when they are created and cleared if the
+     vectorizer uses them.  */
+  unsigned gc_candidate : 1;
 
 private:
   /* Unique id of the node.  */
index 548bb853a183884cac9db1b3714e92f93f1af8dc..59ce2708b7be00cc36d450aa3f8e374c0054e5b1 100644 (file)
@@ -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);
index b0fd2d2ddc55f2ad41e4363b09c0ea32567c7976..92b629b1021c744e40ece399fb16de294da29981 100644 (file)
@@ -702,6 +702,11 @@ simd_clone_create (struct cgraph_node *old_node, bool force_local)
        = old_node->calls_declare_variant_alt;
     }
 
+  /* Mark clones with internal linkage as gc'able, so they will not be
+     emitted unless the vectorizer can actually use them.  */
+  if (!TREE_PUBLIC (new_node->decl))
+    new_node->gc_candidate = true;
+
   return new_node;
 }
 
index 10b5ac38812a05bb60a14f319f2e435754c61ec6..b96473642bbe53392dd5a08f6823bf6b939b794d 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-options "-fopenmp -O2" } */
-/* { dg-additional-options "-fopenmp-target-simd-clone=any -fdump-ipa-simdclone-details" } */
+/* { dg-additional-options "-fopenmp-target-simd-clone=any -fdump-ipa-simdclone-details -fdump-ipa-cgraph" } */
 
 /* Test that simd clones are generated for functions with "declare target".  */
 
@@ -23,3 +23,8 @@ void callit (int *a, int *b, int *c)
 
 /* { dg-final { scan-ipa-dump "Generated local clone _ZGV.*N.*__Z5additii" "simdclone" { target x86_64-*-* } } } */
 /* { dg-final { scan-ipa-dump "Generated local clone _ZGV.*M.*__Z5additii" "simdclone" { target x86_64-*-* } } } */
+
+/* Only the "N" clone is used.  The other one should be GC'ed.  */
+
+/* { dg-final { scan-ipa-dump "Deleting unused function _ZGV.*M.*__Z5additii" "cgraph" { target x86_64-*-* } } } */
+
index 388dc2a956cafdb7b36734b9a3f5619c4866e7c2..0d74aa971f93dff49499a54e6f1fbe966f4f10de 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-options "-fopenmp -O2" } */
-/* { dg-additional-options "-fopenmp-target-simd-clone=any -fdump-ipa-simdclone-details" } */
+/* { dg-additional-options "-fopenmp-target-simd-clone=any -fdump-ipa-simdclone-details -fdump-ipa-cgraph" } */
 
 /* Test that simd clones are generated for functions with "declare target".  */
 
@@ -23,3 +23,7 @@ void callit (int *a, int *b, int *c)
 
 /* { dg-final { scan-ipa-dump "Generated local clone _ZGV.*N.*_addit" "simdclone" { target x86_64-*-* } } } */
 /* { dg-final { scan-ipa-dump "Generated local clone _ZGV.*M.*_addit" "simdclone" { target x86_64-*-* } } } */
+
+/* Only the "N" clone is used.  The other one should be GC'ed.  */
+
+/* { dg-final { scan-ipa-dump "Deleting unused function _ZGV.*M.*_addit" "cgraph" { target x86_64-*-* } } } */
index fb3675183969cd7507c4e53ae613840dff9a9bb8..6ddd41fb4733dfb86db62c1a29f965944c9370bf 100644 (file)
@@ -4620,6 +4620,9 @@ vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info,
     }
   vargs.release ();
 
+  /* Mark the clone as no longer being a candidate for GC.  */
+  bestn->gc_candidate = false;
+
   /* The call in STMT might prevent it from being removed in dce.
      We however cannot remove it here, due to the way the ssa name
      it defines is mapped to the new definition.  So just replace