OSDN Git Service

Clarify comments and use build_pddr.
[pf3gnuchains/gcc-fork.git] / gcc / passes.c
index 0c39a7a..a04a5ef 100644 (file)
@@ -85,6 +85,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "df.h"
 #include "predict.h"
 #include "lto-streamer.h"
+#include "plugin.h"
 
 #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
 #include "dwarf2out.h"
@@ -104,7 +105,8 @@ along with GCC; see the file COPYING3.  If not see
 #endif
 
 /* This is used for debugging.  It allows the current pass to printed
-   from anywhere in compilation.  */
+   from anywhere in compilation.
+   The variable current_pass is also used for statistics and plugins.  */
 struct opt_pass *current_pass;
 
 /* Call from anywhere to find out what pass this is.  Useful for
@@ -114,7 +116,7 @@ void
 print_current_pass (FILE *file)
 {
   if (current_pass)
-    fprintf (file, "current pass = %s (%d)\n", 
+    fprintf (file, "current pass = %s (%d)\n",
             current_pass->name, current_pass->static_pass_number);
   else
     fprintf (file, "no current pass.\n");
@@ -126,7 +128,7 @@ void
 debug_pass (void)
 {
   print_current_pass (stderr);
-} 
+}
 
 
 
@@ -335,6 +337,11 @@ struct rtl_opt_pass pass_postreload =
 struct opt_pass *all_passes, *all_small_ipa_passes, *all_lowering_passes,
   *all_regular_ipa_passes, *all_lto_gen_passes;
 
+/* This is used by plugins, and should also be used in register_pass.  */
+#define DEF_PASS_LIST(LIST) &LIST,
+struct opt_pass **gcc_pass_lists[] = { GCC_PASS_LISTS NULL };
+#undef DEF_PASS_LIST
+
 /* A map from static pass id to optimization pass.  */
 struct opt_pass **passes_by_id;
 int passes_by_id_size;
@@ -407,7 +414,7 @@ register_one_dump_file (struct opt_pass *pass)
 
 /* Recursive worker function for register_dump_files.  */
 
-static int 
+static int
 register_dump_files_1 (struct opt_pass *pass, int properties)
 {
   do
@@ -435,11 +442,11 @@ register_dump_files_1 (struct opt_pass *pass, int properties)
   return properties;
 }
 
-/* Register the dump files for the pipeline starting at PASS. 
+/* Register the dump files for the pipeline starting at PASS.
    PROPERTIES reflects the properties that are guaranteed to be available at
    the beginning of the pipeline.  */
 
-static void 
+static void
 register_dump_files (struct opt_pass *pass,int properties)
 {
   pass->properties_required |= properties;
@@ -458,8 +465,21 @@ make_pass_instance (struct opt_pass *pass, bool track_duplicates)
     {
       struct opt_pass *new_pass;
 
-      new_pass = XNEW (struct opt_pass);
-      memcpy (new_pass, pass, sizeof (*new_pass));
+      if (pass->type == GIMPLE_PASS
+          || pass->type == RTL_PASS
+          || pass->type == SIMPLE_IPA_PASS)
+        {
+          new_pass = XNEW (struct opt_pass);
+          memcpy (new_pass, pass, sizeof (struct opt_pass));
+        }
+      else if (pass->type == IPA_PASS)
+        {
+          new_pass = (struct opt_pass *)XNEW (struct ipa_opt_pass_d);
+          memcpy (new_pass, pass, sizeof (struct ipa_opt_pass_d));
+        }
+      else
+        gcc_unreachable ();
+
       new_pass->next = NULL;
 
       new_pass->todo_flags_start &= ~TODO_mark_first_instance;
@@ -479,8 +499,10 @@ make_pass_instance (struct opt_pass *pass, bool track_duplicates)
     {
       pass->todo_flags_start |= TODO_mark_first_instance;
       pass->static_pass_number = -1;
-    } 
-  return pass; 
+
+      invoke_plugin_callbacks (PLUGIN_NEW_PASS, pass);
+    }
+  return pass;
 }
 
 /* Add a pass to the pass list. Duplicate the pass if it's already
@@ -493,7 +515,7 @@ next_pass_1 (struct opt_pass **list, struct opt_pass *pass)
   gcc_assert (pass->name != NULL);
 
   *list = make_pass_instance (pass, false);
-  
+
   return &(*list)->next;
 }
 
@@ -513,7 +535,7 @@ struct pass_list_node
 static struct pass_list_node *added_pass_nodes = NULL;
 static struct pass_list_node *prev_added_pass_node;
 
-/* Insert the pass at the proper position. Return true if the pass 
+/* Insert the pass at the proper position. Return true if the pass
    is successfully added.
 
    NEW_PASS_INFO - new pass to be inserted
@@ -543,7 +565,7 @@ position_pass (struct register_pass_info *new_pass_info,
           struct pass_list_node *new_pass_node;
 
          new_pass = make_pass_instance (new_pass_info->pass, true);
-  
+
           /* Insert the new pass instance based on the positioning op.  */
           switch (new_pass_info->pos_op)
             {
@@ -554,7 +576,7 @@ position_pass (struct register_pass_info *new_pass_info,
                /* Skip newly inserted pass to avoid repeated
                   insertions in the case where the new pass and the
                   existing one have the same name.  */
-                pass = new_pass; 
+                pass = new_pass;
                 break;
               case PASS_POS_INSERT_BEFORE:
                 new_pass->next = pass;
@@ -706,7 +728,6 @@ init_optimization_passes (void)
   NEXT_PASS (pass_refactor_eh);
   NEXT_PASS (pass_lower_eh);
   NEXT_PASS (pass_build_cfg);
-  NEXT_PASS (pass_lower_complex_O0);
   NEXT_PASS (pass_lower_vector);
   NEXT_PASS (pass_warn_function_return);
   NEXT_PASS (pass_build_cgraph_edges);
@@ -779,7 +800,7 @@ init_optimization_passes (void)
   NEXT_PASS (pass_ipa_cp);
   NEXT_PASS (pass_ipa_inline);
   NEXT_PASS (pass_ipa_reference);
-  NEXT_PASS (pass_ipa_pure_const); 
+  NEXT_PASS (pass_ipa_pure_const);
   NEXT_PASS (pass_ipa_type_escape);
   NEXT_PASS (pass_ipa_pta);
   NEXT_PASS (pass_ipa_struct_reorg);
@@ -906,7 +927,7 @@ init_optimization_passes (void)
         we may get false warnings (e.g., testsuite/gcc.dg/uninit-5.c).
         However, this also causes us to misdiagnose cases that should be
         real warnings (e.g., testsuite/gcc.dg/pr18501.c).
-        
+
         To fix the false positives in uninit-5.c, we would have to
         account for the predicates protecting the set and the use of each
         variable.  Using a representation like Gated Single Assignment
@@ -921,6 +942,7 @@ init_optimization_passes (void)
       NEXT_PASS (pass_uncprop);
       NEXT_PASS (pass_local_pure_const);
     }
+  NEXT_PASS (pass_lower_complex_O0);
   NEXT_PASS (pass_cleanup_eh);
   NEXT_PASS (pass_lower_resx);
   NEXT_PASS (pass_nrv);
@@ -1037,23 +1059,23 @@ init_optimization_passes (void)
 
   /* Register the passes with the tree dump code.  */
   register_dump_files (all_lowering_passes, PROP_gimple_any);
-  register_dump_files (all_small_ipa_passes, 
+  register_dump_files (all_small_ipa_passes,
                       PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh
                       | PROP_cfg);
-  register_dump_files (all_regular_ipa_passes, 
+  register_dump_files (all_regular_ipa_passes,
                       PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh
                       | PROP_cfg);
-  register_dump_files (all_lto_gen_passes, 
+  register_dump_files (all_lto_gen_passes,
                       PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh
                       | PROP_cfg);
-  register_dump_files (all_passes, 
+  register_dump_files (all_passes,
                       PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh
                       | PROP_cfg);
 }
 
 /* If we are in IPA mode (i.e., current_function_decl is NULL), call
    function CALLBACK for every function in the call graph.  Otherwise,
-   call CALLBACK on the current function.  */ 
+   call CALLBACK on the current function.  */
 
 static void
 do_per_function (void (*callback) (void *data), void *data)
@@ -1090,9 +1112,9 @@ static GTY ((length ("nnodes"))) struct cgraph_node **order;
 
 /* If we are in IPA mode (i.e., current_function_decl is NULL), call
    function CALLBACK for every function in the call graph.  Otherwise,
-   call CALLBACK on the current function.  */ 
-
-static void
+   call CALLBACK on the current function.
+   This function is global so that plugins can use it.  */
+void
 do_per_function_toporder (void (*callback) (void *data), void *data)
 {
   int i;
@@ -1152,7 +1174,7 @@ execute_function_todo (void *data)
 
       if (cleanup && (cfun->curr_properties & PROP_ssa))
        flags |= TODO_remove_unused_locals;
-       
+
       /* When cleanup_tree_cfg merges consecutive blocks, it may
         perform some simplistic propagation when removing single
         valued PHI nodes.  This propagation may, in turn, cause the
@@ -1169,7 +1191,7 @@ execute_function_todo (void *data)
       update_ssa (update_flags);
       cfun->last_verified &= ~TODO_verify_ssa;
     }
-  
+
   if (flags & TODO_update_address_taken)
     execute_update_addresses_taken (true);
 
@@ -1179,7 +1201,7 @@ execute_function_todo (void *data)
        execute_update_addresses_taken (true);
       compute_may_aliases ();
     }
-  
+
   if (flags & TODO_remove_unused_locals)
     remove_unused_locals ();
 
@@ -1279,7 +1301,7 @@ execute_todo (unsigned int flags)
   if (flags & TODO_ggc_collect)
     ggc_collect ();
 
-  /* Now that the dumping has been done, we can get rid of the optional 
+  /* Now that the dumping has been done, we can get rid of the optional
      df problems.  */
   if (flags & TODO_df_finish)
     df_finish_pass ((flags & TODO_df_verify) != 0);
@@ -1317,8 +1339,9 @@ verify_curr_properties (void *data)
 #endif
 
 /* Initialize pass dump file.  */
+/* This is non-static so that the plugins can use it.  */
 
-static bool
+bool
 pass_init_dump_file (struct opt_pass *pass)
 {
   /* If a dump file name is present, open it if enabled.  */
@@ -1347,8 +1370,9 @@ pass_init_dump_file (struct opt_pass *pass)
 }
 
 /* Flush PASS dump file.  */
+/* This is non-static so that plugins can use it.  */
 
-static void
+void
 pass_fini_dump_file (struct opt_pass *pass)
 {
   /* Flush and close dump file.  */
@@ -1386,7 +1410,7 @@ execute_ipa_summary_passes (struct ipa_opt_pass_d *ipa_pass)
       struct opt_pass *pass = &ipa_pass->pass;
 
       /* Execute all of the IPA_PASSes in the list.  */
-      if (ipa_pass->pass.type == IPA_PASS 
+      if (ipa_pass->pass.type == IPA_PASS
          && (!pass->gate || pass->gate ())
          && ipa_pass->generate_summary)
        {
@@ -1476,12 +1500,14 @@ execute_all_ipa_transforms (void)
 
 /* Execute PASS. */
 
-static bool
+bool
 execute_one_pass (struct opt_pass *pass)
 {
   bool initializing_dump;
   unsigned int todo_after = 0;
 
+  bool gate_status;
+
   /* IPA passes are executed on whole program, so cfun should be NULL.
      Other passes need function context set.  */
   if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS)
@@ -1491,9 +1517,22 @@ execute_one_pass (struct opt_pass *pass)
 
   current_pass = pass;
 
-  /* See if we're supposed to run this pass.  */
-  if (pass->gate && !pass->gate ())
-    return false;
+  /* Check whether gate check should be avoided.
+     User controls the value of the gate through the parameter "gate_status". */
+  gate_status = (pass->gate == NULL) ? true : pass->gate();
+
+  /* Override gate with plugin.  */
+  invoke_plugin_callbacks (PLUGIN_OVERRIDE_GATE, &gate_status);
+
+  if (!gate_status)
+    {
+      current_pass = NULL;
+      return false;
+    }
+
+  /* Pass execution event trigger: useful to identify passes being
+     executed.  */
+  invoke_plugin_callbacks (PLUGIN_PASS_EXECUTION, pass);
 
   if (!quiet_flag && !cfun)
     fprintf (stderr, " <%s>", pass->name ? pass->name : "");
@@ -1644,7 +1683,7 @@ ipa_write_summaries (void)
   cgraph_node_set set;
   struct cgraph_node **order;
   int i, order_pos;
+
   if (!flag_generate_lto || errorcount || sorrycount)
     return;
 
@@ -1756,8 +1795,12 @@ execute_ipa_pass_list (struct opt_pass *pass)
       if (execute_one_pass (pass) && pass->sub)
        {
          if (pass->sub->type == GIMPLE_PASS)
-           do_per_function_toporder ((void (*)(void *))execute_pass_list,
-                                     pass->sub);
+           {
+             invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL);
+             do_per_function_toporder ((void (*)(void *))execute_pass_list,
+                                       pass->sub);
+             invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL);
+           }
          else if (pass->sub->type == SIMPLE_IPA_PASS
                   || pass->sub->type == IPA_PASS)
            execute_ipa_pass_list (pass->sub);
@@ -1840,6 +1883,8 @@ dump_properties (FILE *dump, unsigned int props)
     fprintf (dump, "PROP_rtl\n");
   if (props & PROP_gimple_lomp)
     fprintf (dump, "PROP_gimple_lomp\n");
+  if (props & PROP_gimple_lcx)
+    fprintf (dump, "PROP_gimple_lcx\n");
 }
 
 void