pass: Run cleanup passes before SLP [PR96789]
[gcc.git] / gcc / passes.c
index 07b2613ffeaa3b8a6180686aaed72246d79e6932..f71f63918f4046b976f05f2a3ec0cc9eb8041a7d 100644 (file)
@@ -731,7 +731,54 @@ make_pass_late_compilation (gcc::context *ctxt)
   return new pass_late_compilation (ctxt);
 }
 
+/* Pre-SLP scalar cleanup, it has several cleanup passes like FRE, DSE.  */
 
+namespace {
+
+const pass_data pass_data_pre_slp_scalar_cleanup =
+{
+  GIMPLE_PASS, /* type */
+  "*pre_slp_scalar_cleanup", /* name */
+  OPTGROUP_LOOP, /* optinfo_flags */
+  TV_SCALAR_CLEANUP, /* tv_id */
+  ( PROP_cfg | PROP_ssa ), /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  0, /* todo_flags_finish */
+};
+
+class pass_pre_slp_scalar_cleanup : public gimple_opt_pass
+{
+public:
+  pass_pre_slp_scalar_cleanup (gcc::context *ctxt)
+    : gimple_opt_pass (pass_data_pre_slp_scalar_cleanup, ctxt)
+  {
+  }
+
+  virtual bool
+  gate (function *fun)
+  {
+    return flag_tree_slp_vectorize
+          && (fun->pending_TODOs & PENDING_TODO_force_next_scalar_cleanup);
+  }
+
+  virtual unsigned int
+  execute (function *fun)
+  {
+    fun->pending_TODOs &= ~PENDING_TODO_force_next_scalar_cleanup;
+    return 0;
+  }
+
+}; // class pass_pre_slp_scalar_cleanup
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_pre_slp_scalar_cleanup (gcc::context *ctxt)
+{
+  return new pass_pre_slp_scalar_cleanup (ctxt);
+}
 
 /* Set the static pass number of pass PASS to ID and record that
    in the mapping from static pass number to pass.  */
@@ -892,7 +939,7 @@ pass_manager::create_pass_tab (void) const
   if (!flag_dump_passes)
     return;
 
-  pass_tab.safe_grow_cleared (passes_by_id_size + 1);
+  pass_tab.safe_grow_cleared (passes_by_id_size + 1, true);
   m_name_to_pass_map->traverse <void *, passes_pass_traverse> (NULL);
 }
 
@@ -1046,7 +1093,7 @@ enable_disable_pass (const char *arg, bool is_enable)
     tab = &disabled_pass_uid_range_tab;
 
   if ((unsigned) pass->static_pass_number >= tab->length ())
-    tab->safe_grow_cleared (pass->static_pass_number + 1);
+    tab->safe_grow_cleared (pass->static_pass_number + 1, true);
 
   if (!range_str)
     {
@@ -1850,10 +1897,15 @@ pass_manager::dump_profile_report () const
 
   if (!profile_record)
     return;
-  fprintf (stderr, "\nProfile consistency report:\n\n");
-  fprintf (stderr, "                                 |mismatch     |mismatch     |                     |\n");
-  fprintf (stderr, "Pass name                        |IN    |IN    |OUT   |OUT   |overall              |\n");
-  fprintf (stderr, "                                 |freq  |count |freq  |count |size      |time      |\n");
+
+  FILE *dump_file = dump_begin (TDI_profile_report, NULL);
+  if (dump_file == NULL)
+    dump_file = stderr;
+
+  fprintf (dump_file, "Profile consistency report:\n\n");
+  fprintf (dump_file, "                                 |mismatch     |mismatch     |                     |\n");
+  fprintf (dump_file, "Pass name                        |IN    |IN    |OUT   |OUT   |overall              |\n");
+  fprintf (dump_file, "                                 |freq  |count |freq  |count |size      |time      |\n");
           
   for (int i = 1; i < passes_by_id_size; i++)
     if (profile_record[i].run)
@@ -1876,47 +1928,47 @@ pass_manager::dump_profile_report () const
            || rel_time_change || rel_size_change)
          {
            last_reported = i;
-           fprintf (stderr, "%-33s", passes_by_id[i]->name);
+           fprintf (dump_file, "%-33s", passes_by_id[i]->name);
            if (profile_record[i].num_mismatched_freq_in != last_freq_in)
-             fprintf (stderr, "| %+5i",
+             fprintf (dump_file, "| %+5i",
                       profile_record[i].num_mismatched_freq_in
                       - last_freq_in);
            else
-             fprintf (stderr, "|      ");
+             fprintf (dump_file, "|      ");
            if (profile_record[i].num_mismatched_count_in != last_count_in)
-             fprintf (stderr, "| %+5i",
+             fprintf (dump_file, "| %+5i",
                       profile_record[i].num_mismatched_count_in
                       - last_count_in);
            else
-             fprintf (stderr, "|      ");
+             fprintf (dump_file, "|      ");
            if (profile_record[i].num_mismatched_freq_out != last_freq_out)
-             fprintf (stderr, "| %+5i",
+             fprintf (dump_file, "| %+5i",
                       profile_record[i].num_mismatched_freq_out
                       - last_freq_out);
            else
-             fprintf (stderr, "|      ");
+             fprintf (dump_file, "|      ");
            if (profile_record[i].num_mismatched_count_out != last_count_out)
-             fprintf (stderr, "| %+5i",
+             fprintf (dump_file, "| %+5i",
                       profile_record[i].num_mismatched_count_out
                       - last_count_out);
            else
-             fprintf (stderr, "|      ");
+             fprintf (dump_file, "|      ");
 
            /* Size/time units change across gimple and RTL.  */
            if (i == pass_expand_1->static_pass_number)
-             fprintf (stderr, "|----------|----------");
+             fprintf (dump_file, "|----------|----------");
            else
              {
                if (rel_size_change)
-                 fprintf (stderr, "| %+8.1f%%", rel_size_change);
+                 fprintf (dump_file, "| %+8.1f%%", rel_size_change);
                else
-                 fprintf (stderr, "|          ");
+                 fprintf (dump_file, "|          ");
                if (rel_time_change)
-                 fprintf (stderr, "| %+8.1f%%", rel_time_change);
+                 fprintf (dump_file, "| %+8.1f%%", rel_time_change);
                else
-                 fprintf (stderr, "|          ");
+                 fprintf (dump_file, "|          ");
              }
-           fprintf (stderr, "|\n");
+           fprintf (dump_file, "|\n");
            last_freq_in = profile_record[i].num_mismatched_freq_in;
            last_freq_out = profile_record[i].num_mismatched_freq_out;
            last_count_in = profile_record[i].num_mismatched_count_in;
@@ -1925,12 +1977,14 @@ pass_manager::dump_profile_report () const
        else if (last_reported != i)
          {
            last_reported = i;
-           fprintf (stderr, "%-20s ------------|      |      |      |      |          |          |\n",
+           fprintf (dump_file, "%-20s ------------|      |      |      |      |          |          |\n",
                     passes_by_id[i]->name);
          }
        last_time = profile_record[i].time;
        last_size = profile_record[i].size;
       }
+
+  dump_end (TDI_profile_report, dump_file);
 }
 
 /* Perform all TODO actions that ought to be done on each function.  */
@@ -2264,6 +2318,14 @@ execute_all_ipa_transforms (bool do_not_collect)
     return;
   node = cgraph_node::get (current_function_decl);
 
+  cgraph_node *next_clone;
+  for (cgraph_node *n = node->clones; n; n = next_clone)
+    {
+      next_clone = n->next_sibling_clone;
+      if (n->decl != node->decl)
+       n->materialize_clone ();
+    }
+
   if (node->ipa_transforms_to_apply.exists ())
     {
       unsigned int i;
@@ -2551,7 +2613,8 @@ execute_one_pass (opt_pass *pass)
     {
       struct cgraph_node *node;
       FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
-       node->ipa_transforms_to_apply.safe_push ((ipa_opt_pass_d *)pass);
+       if (!node->inlined_to)
+         node->ipa_transforms_to_apply.safe_push ((ipa_opt_pass_d *)pass);
     }
   else if (dump_file)
     do_per_function (execute_function_dump, pass);
@@ -2715,7 +2778,8 @@ ipa_write_summaries (void)
     {
       struct cgraph_node *node = order[i];
 
-      if (node->definition && node->need_lto_streaming)
+      if ((node->definition || node->declare_variant_alt)
+         && node->need_lto_streaming)
        {
          if (gimple_has_body_p (node->decl))
            lto_prepare_function_for_streaming (node);