public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* New options to disable/enable any pass for any functions (issue4550056)
@ 2011-05-18 19:49 David Li
  2011-05-18 20:21 ` Joseph S. Myers
                   ` (2 more replies)
  0 siblings, 3 replies; 32+ messages in thread
From: David Li @ 2011-05-18 19:49 UTC (permalink / raw)
  To: reply, gcc-patches


In gcc, not all passes have user level control to turn it on/off, and
there is no way to flip on/off the pass for a subset of functions. I
implemented a generic option handling scheme in gcc to allow
disabling/enabling any gcc pass for any specified function(s).  The
new options will be very useful for things like performance
experiments and bug triaging (gcc has dbgcnt mechanism, but not all
passes have the counter).

The option syntax is very similar to -fdump- options. The following
are some examples:

-fdisable-tree-ccp1    <--- disable ccp1 for all functions
-fenable-tree-cunroll=1   <--- enable complete unroll for the function
                           whose cgraphnode uid is 1
-fdisable-rtl-gcse2=1:100,300,400:1000   <-- disable gcse2 for
                                           functions at the following
                                            ranges [1,1], [300,400], and [400,1000]
-fdisable-tree-einline --> disable early inlining for all callers
-fdisable-ipa-inline --> disable ipa inlininig

In the gcc dumps, the uid numbers are displayed in the function header.

The options are intended to be used internally by gcc developers.

Ok for trunk ? (There is a little LIPO specific change that can be removed).

David

2011-05-18  David Li  <davidxl@google.com>

	* final.c (rest_of_clean_state): Call function header dumper.
	* opts-global.c (handle_common_deferred_options): Handle new options.
	* tree-cfg.c (gimple_dump_cfg): Call function header dumper.
	* passes.c (register_one_dump_file): Call register_pass_name.
	(pass_init_dump_file): Call function header dumper.
	(execute_one_pass): Check explicit enable/disable flag.
	(passr_hash): New function.
	(passr_eq): 
	(register_pass_name):
	(get_pass_by_name):
	(pass_hash):
	(pass_eq):
	(enable_disable_pass):
	(is_pass_explicitly_enabled_or_disabled):
	(is_pass_explicitly_enabled):
	(is_pass_explicitly_disabled):


Index: tree-pass.h
===================================================================
--- tree-pass.h	(revision 173635)
+++ tree-pass.h	(working copy)
@@ -644,4 +644,12 @@ extern bool first_pass_instance;
 /* Declare for plugins.  */
 extern void do_per_function_toporder (void (*) (void *), void *);
 
+extern void enable_disable_pass (const char *, bool);
+extern bool is_pass_explicitly_disabled (struct opt_pass *, tree);
+extern bool is_pass_explicitly_enabled (struct opt_pass *, tree);
+extern void register_pass_name (struct opt_pass *, const char *);
+extern struct opt_pass *get_pass_by_name (const char *);
+struct function;
+extern void pass_dump_function_header (FILE *, tree, struct function *);
+
 #endif /* GCC_TREE_PASS_H */
Index: final.c
===================================================================
--- final.c	(revision 173635)
+++ final.c	(working copy)
@@ -4456,19 +4456,7 @@ rest_of_clean_state (void)
 	}
       else
 	{
-	  const char *aname;
-	  struct cgraph_node *node = cgraph_node (current_function_decl);
-
-	  aname = (IDENTIFIER_POINTER
-		   (DECL_ASSEMBLER_NAME (current_function_decl)));
-	  fprintf (final_output, "\n;; Function (%s) %s\n\n", aname,
-	     node->frequency == NODE_FREQUENCY_HOT
-	     ? " (hot)"
-	     : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
-	     ? " (unlikely executed)"
-	     : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
-	     ? " (executed once)"
-	     : "");
+	  pass_dump_function_header (final_output, current_function_decl, cfun);
 
 	  flag_dump_noaddr = flag_dump_unnumbered = 1;
 	  if (flag_compare_debug_opt || flag_compare_debug)
Index: common.opt
===================================================================
--- common.opt	(revision 173635)
+++ common.opt	(working copy)
@@ -1018,6 +1018,14 @@ fdiagnostics-show-option
 Common Var(flag_diagnostics_show_option) Init(1)
 Amend appropriate diagnostic messages with the command line option that controls them
 
+fdisable-
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fdisable-[tree|rtl|ipa]-<pass>=range1+range2 disables an optimization pass
+
+fenable-
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fenable-[tree|rtl|ipa]-<pass>=range1+range2 enables an optimization pass
+
 fdump-
 Common Joined RejectNegative Var(common_deferred_options) Defer
 -fdump-<type>	Dump various compiler internals to a file
Index: opts-global.c
===================================================================
--- opts-global.c	(revision 173635)
+++ opts-global.c	(working copy)
@@ -411,6 +411,12 @@ handle_common_deferred_options (void)
 	    error ("unrecognized command line option %<-fdump-%s%>", opt->arg);
 	  break;
 
+	case OPT_fenable_:
+	case OPT_fdisable_:
+	  enable_disable_pass (opt->arg, (opt->opt_index == OPT_fenable_?
+	                       true : false));
+          break;
+
 	case OPT_ffixed_:
 	  /* Deferred.  */
 	  fix_register (opt->arg, 1, 1);
Index: tree-cfg.c
===================================================================
--- tree-cfg.c	(revision 173636)
+++ tree-cfg.c	(working copy)
@@ -2090,11 +2090,7 @@ gimple_dump_cfg (FILE *file, int flags)
 {
   if (flags & TDF_DETAILS)
     {
-      const char *funcname
-	= lang_hooks.decl_printable_name (current_function_decl, 2);
-
-      fputc ('\n', file);
-      fprintf (file, ";; Function %s\n\n", funcname);
+      pass_dump_function_header (file, current_function_decl, cfun);
       fprintf (file, ";; \n%d basic blocks, %d edges, last basic block %d.\n\n",
 	       n_basic_blocks, n_edges, last_basic_block);
 
Index: passes.c
===================================================================
--- passes.c	(revision 173635)
+++ passes.c	(working copy)
@@ -382,7 +382,7 @@ void
 register_one_dump_file (struct opt_pass *pass)
 {
   char *dot_name, *flag_name, *glob_name;
-  const char *name, *prefix;
+  const char *name, *full_name, *prefix;
   char num[10];
   int flags, id;
 
@@ -411,6 +411,8 @@ register_one_dump_file (struct opt_pass 
   glob_name = concat (prefix, name, NULL);
   id = dump_register (dot_name, flag_name, glob_name, flags);
   set_pass_for_id (id, pass);
+  full_name = concat (prefix, pass->name, num, NULL);
+  register_pass_name (pass, full_name);
 }
 
 /* Recursive worker function for register_dump_files.  */
@@ -454,6 +456,298 @@ register_dump_files (struct opt_pass *pa
   register_dump_files_1 (pass, properties);
 }
 
+struct pass_registry
+{
+  const char* unique_name;
+  struct opt_pass *pass;
+};
+
+/* Pass registry hash function.  */
+
+static hashval_t
+passr_hash (const void *p)
+{
+  const struct pass_registry *const s = (const struct pass_registry *const) p;
+  return htab_hash_string (s->unique_name);
+}
+
+/* Hash equal function  */
+
+static int
+passr_eq (const void *p1, const void *p2)
+{
+  const struct pass_registry *const s1 = (const struct pass_registry *const) p1;
+  const struct pass_registry *const s2 = (const struct pass_registry *const) p2;
+
+  return !strcmp (s1->unique_name, s2->unique_name);
+}
+
+static htab_t pass_name_tab = NULL;
+
+/* Register PASS with NAME.  */
+
+void
+register_pass_name (struct opt_pass *pass, const char *name)
+{
+  struct pass_registry **slot;
+  struct pass_registry pr;
+
+  if (!pass_name_tab)
+    pass_name_tab = htab_create (10, passr_hash, passr_eq, NULL);
+
+  pr.unique_name = name;
+  slot = (struct pass_registry **) htab_find_slot (pass_name_tab, &pr, INSERT);
+  if (!*slot)
+    {
+      struct pass_registry *new_pr;
+
+      new_pr = XCNEW (struct pass_registry);
+      new_pr->unique_name = xstrdup (name);
+      new_pr->pass = pass;
+      *slot = new_pr;
+    }
+  else
+    gcc_assert ((*slot)->pass == pass);
+}
+
+/* Returns the pass with NAME.  */
+
+struct opt_pass *
+get_pass_by_name (const char *name)
+{
+  struct pass_registry **slot, pr;
+
+  gcc_assert (pass_name_tab);
+  pr.unique_name = name;
+  slot = (struct pass_registry **) htab_find_slot (pass_name_tab, &pr, NO_INSERT);
+
+  if (!slot || !*slot)
+    return NULL;
+
+  return (*slot)->pass;
+}
+
+
+/* Range [start, last].  */
+
+struct uid_range
+{
+  struct opt_pass *pass;
+  unsigned int start;
+  unsigned int last;
+  struct uid_range *next;
+};
+
+/* Hash function for pass structure.  */
+
+static hashval_t
+pass_hash (const void *s)
+{
+  const struct uid_range *const p = (const struct uid_range *const) s;
+  return p->pass->static_pass_number;
+}
+
+/* Pass equal function  */
+
+static int
+pass_eq (const void *s1, const void *s2)
+{
+  const struct uid_range *const p1 = (const struct uid_range *const) s1;
+  const struct uid_range *const p2 = (const struct uid_range *const) s2;
+  return p1->pass->static_pass_number == p2->pass->static_pass_number;
+}
+
+htab_t enabled_pass_uid_range_tab = NULL;
+htab_t disabled_pass_uid_range_tab = NULL;
+
+/* Parse option string for -fdisable- and -fenabler-
+   The syntax of the options:
+
+   -fenable-<pass_name>
+   -fdisable-<pass_name>
+
+   -fenable-<pass_name>=s1:e1,s2:e2,...
+   -fdisable-<pass_name>=s1:e1,s2:e2,...
+*/
+
+void
+enable_disable_pass (const char *arg, bool is_enable)
+{
+  struct opt_pass *pass;
+  htab_t the_tab;
+  char *range_str, *phase_name;
+  char *argstr = xstrdup (arg);
+
+  range_str = strchr (argstr,'=');
+  if (range_str)
+    {
+      *range_str = '\0';
+      range_str++;
+    }
+
+  phase_name = argstr;
+  if (!*phase_name)
+    {
+      error ("Unrecognized option %s", is_enable ? "-fenable" : "-fdisable");
+      free (argstr);
+      return;
+    }
+  pass = get_pass_by_name (phase_name);
+  if (!pass)
+    {
+      error ("Unknown pass %s specified in %s",
+	     phase_name,
+	     is_enable ? "-fenable" : "-fdisable");
+      free (argstr);
+      return;
+    }
+  if (is_enable)
+    {
+      if (!enabled_pass_uid_range_tab)
+	enabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
+      the_tab = enabled_pass_uid_range_tab;
+    }
+  else
+    {
+      if (!disabled_pass_uid_range_tab)
+	disabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
+      the_tab = disabled_pass_uid_range_tab;
+    }
+
+  if (!range_str)
+    {
+      struct uid_range **slot;
+      struct uid_range *new_range = XCNEW (struct uid_range);
+
+      new_range->pass = pass;
+      new_range->start = 0;
+      new_range->last = (unsigned)-1;
+
+      slot = (struct uid_range **) htab_find_slot (the_tab, new_range, INSERT);
+      new_range->next = *slot;
+      *slot = new_range;
+      inform (UNKNOWN_LOCATION, "%s pass %s for functions in the range of [%u, %u]\n",
+              is_enable? "Enable":"Disable", phase_name, new_range->start, new_range->last);
+    }
+  else
+    {
+      char *next_range = NULL;
+      char *one_range = range_str;
+      char *end_val = NULL;
+
+      do
+	{
+	  struct uid_range **slot;
+	  struct uid_range *new_range;
+	  char *invalid = NULL;
+	  long start;
+
+	  next_range = strchr (one_range, ',');
+	  if (next_range)
+	    {
+	      *next_range = '\0';
+	      next_range++;
+	    }
+
+	  end_val = strchr (one_range, ':');
+	  if (end_val)
+	    {
+	      *end_val = '\0';
+	      end_val++;
+	    }
+	  start = strtol (one_range, &invalid, 10);
+	  if (*invalid || start < 0)
+	    {
+	      error ("Invalid range %s in option %s",
+		     one_range,
+		     is_enable ? "-fenable" : "-fdisable");
+	      free (argstr);
+	      return;
+	    }
+	  if (!end_val)
+	    {
+	      new_range = XCNEW (struct uid_range);
+              new_range->pass = pass;
+	      new_range->start = (unsigned) start;
+	      new_range->last = (unsigned) start;
+	    }
+	  else
+	    {
+	      long last = strtol (end_val, &invalid, 10);
+	      if (*invalid || last < start)
+		{
+		  error ("Invalid range %s in option %s",
+			 end_val,
+			 is_enable ? "-fenable" : "-fdisable");
+		  free (argstr);
+		  return;
+		}
+	      new_range = XCNEW (struct uid_range);
+              new_range->pass = pass;
+	      new_range->start = (unsigned) start;
+	      new_range->last = (unsigned) last;
+	    }
+	  slot = (struct uid_range **) htab_find_slot (the_tab, new_range, INSERT);
+	  new_range->next = *slot;
+	  *slot = new_range;
+          inform (UNKNOWN_LOCATION, "%s pass %s for functions in the range of [%u, %u]\n",
+                  is_enable? "Enable":"Disable", phase_name, new_range->start, new_range->last);
+
+	  one_range = next_range;
+	} while (next_range);
+    }
+
+  free (argstr);
+}
+
+/* Returns true if PASS is explicitly enabled/disabled for FUNC.  */
+
+static bool
+is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
+					tree func, htab_t tab)
+{
+  struct uid_range **slot, *range, key;
+  int cgraph_uid;
+
+  if (!tab)
+    return false;
+
+  key.pass = pass;
+  slot = (struct uid_range **) htab_find_slot (tab, &key, NO_INSERT);
+  if (!slot || !*slot)
+    return false;
+
+  cgraph_uid = func ? cgraph_node (func)->uid : 0;
+
+  range = *slot;
+  while (range)
+    {
+      if ((unsigned) cgraph_uid >= range->start
+	  && (unsigned) cgraph_uid <= range->last)
+	return true;
+      range = range->next;
+    }
+
+  return false;
+}
+
+/* Returns true if PASS is explicitly enabled for FUNC.  */
+
+bool
+is_pass_explicitly_enabled (struct opt_pass *pass, tree func)
+{
+  return is_pass_explicitly_enabled_or_disabled (pass, func, enabled_pass_uid_range_tab);
+}
+
+/* Returns true if PASS is explicitly disabled for FUNC.  */
+
+bool
+is_pass_explicitly_disabled (struct opt_pass *pass, tree func)
+{
+  return is_pass_explicitly_enabled_or_disabled (pass, func, disabled_pass_uid_range_tab);
+}
+
+
 /* Look at the static_pass_number and duplicate the pass
    if it is already added to a list. */
 
@@ -1349,6 +1643,29 @@ verify_curr_properties (void *data)
 }
 #endif
 
+void
+pass_dump_function_header (FILE *dump_file, tree fdecl, struct function *fun)
+{
+  const char *dname, *aname;
+  struct cgraph_node *node = cgraph_node (fdecl);
+  dname = lang_hooks.decl_printable_name (fdecl, 2);
+  aname = (IDENTIFIER_POINTER
+	   (DECL_ASSEMBLER_NAME (fdecl)));
+  if (L_IPO_COMP_MODE)
+    fprintf (dump_file, "\n;; Function %s (%s)[%d:%d][uid=%d]", dname, aname,
+	     FUNC_DECL_MODULE_ID (fun), FUNC_DECL_FUNC_ID (fun), node->uid);
+  else
+    fprintf (dump_file, "\n;; Function %s (%s)[uid=%d]", dname, aname, node->uid);
+  fprintf (dump_file, "%s\n\n",
+           node->frequency == NODE_FREQUENCY_HOT
+           ? " (hot)"
+           : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
+           ? " (unlikely executed)"
+           : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
+           ? " (executed once)"
+           : "");
+}
+
 /* Initialize pass dump file.  */
 /* This is non-static so that the plugins can use it.  */
 
@@ -1362,26 +1679,7 @@ pass_init_dump_file (struct opt_pass *pa
       dump_file_name = get_dump_file_name (pass->static_pass_number);
       dump_file = dump_begin (pass->static_pass_number, &dump_flags);
       if (dump_file && current_function_decl)
-	{
-	  const char *dname, *aname;
-	  struct cgraph_node *node = cgraph_node (current_function_decl);
-	  dname = lang_hooks.decl_printable_name (current_function_decl, 2);
-	  aname = (IDENTIFIER_POINTER
-		   (DECL_ASSEMBLER_NAME (current_function_decl)));
-	  if (L_IPO_COMP_MODE)
-	    fprintf (dump_file, "\n;; Function %s (%s)[%d:%d]", dname, aname,
-		     FUNC_DECL_MODULE_ID (cfun), FUNC_DECL_FUNC_ID (cfun));
-	  else
-	    fprintf (dump_file, "\n;; Function %s (%s)", dname, aname);
-	  fprintf (dump_file, "%s\n\n",
-	     node->frequency == NODE_FREQUENCY_HOT
-	     ? " (hot)"
-	     : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
-	     ? " (unlikely executed)"
-	     : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
-	     ? " (executed once)"
-	     : "");
-	}
+        pass_dump_function_header (dump_file, current_function_decl, cfun);
       return initializing_dump;
     }
   else
@@ -1525,6 +1823,8 @@ execute_one_pass (struct opt_pass *pass)
 {
   bool initializing_dump;
   unsigned int todo_after = 0;
+  bool explicitly_enabled = false;
+  bool explicitly_disabled = false;
 
   bool gate_status;
 
@@ -1535,11 +1835,15 @@ execute_one_pass (struct opt_pass *pass)
   else
     gcc_assert (cfun && current_function_decl);
 
+  explicitly_enabled = is_pass_explicitly_enabled (pass, current_function_decl);
+  explicitly_disabled = is_pass_explicitly_disabled (pass, current_function_decl);
+
   current_pass = pass;
 
   /* 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();
+  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
 
   /* Override gate with plugin.  */
   invoke_plugin_callbacks (PLUGIN_OVERRIDE_GATE, &gate_status);

--
This patch is available for review at http://codereview.appspot.com/4550056

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-18 19:49 New options to disable/enable any pass for any functions (issue4550056) David Li
@ 2011-05-18 20:21 ` Joseph S. Myers
  2011-05-18 20:33   ` Xinliang David Li
  2011-05-20 16:44   ` Xinliang David Li
  2011-05-18 21:01 ` Richard Guenther
  2011-05-19 19:23 ` Andi Kleen
  2 siblings, 2 replies; 32+ messages in thread
From: Joseph S. Myers @ 2011-05-18 20:21 UTC (permalink / raw)
  To: David Li; +Cc: reply, gcc-patches

On Wed, 18 May 2011, David Li wrote:

> +      error ("Unrecognized option %s", is_enable ? "-fenable" : "-fdisable");

> +      error ("Unknown pass %s specified in %s",
> +	     phase_name,
> +	     is_enable ? "-fenable" : "-fdisable");

Follow GNU Coding Standards for diagnostics (start with lowercase letter).

> +      inform (UNKNOWN_LOCATION, "%s pass %s for functions in the range of [%u, %u]\n",
> +              is_enable? "Enable":"Disable", phase_name, new_range->start, new_range->last);

Use separate calls to inform for the enable and disable cases, so that 
full sentences can be extracted for translation.

> +	      error ("Invalid range %s in option %s",
> +		     one_range,
> +		     is_enable ? "-fenable" : "-fdisable");

GNU Coding Standards.

> +		  error ("Invalid range %s in option %s",

Likewise.

> +          inform (UNKNOWN_LOCATION, "%s pass %s for functions in the range of [%u, %u]\n",
> +                  is_enable? "Enable":"Disable", phase_name, new_range->start, new_range->last);

Again needs GCS and i18n fixes.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-18 20:21 ` Joseph S. Myers
@ 2011-05-18 20:33   ` Xinliang David Li
  2011-05-20 16:44   ` Xinliang David Li
  1 sibling, 0 replies; 32+ messages in thread
From: Xinliang David Li @ 2011-05-18 20:33 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: reply, gcc-patches

Thanks for the comment. Will fix those.

David

On Wed, May 18, 2011 at 12:30 PM, Joseph S. Myers
<joseph@codesourcery.com> wrote:
> On Wed, 18 May 2011, David Li wrote:
>
>> +      error ("Unrecognized option %s", is_enable ? "-fenable" : "-fdisable");
>
>> +      error ("Unknown pass %s specified in %s",
>> +          phase_name,
>> +          is_enable ? "-fenable" : "-fdisable");
>
> Follow GNU Coding Standards for diagnostics (start with lowercase letter).
>
>> +      inform (UNKNOWN_LOCATION, "%s pass %s for functions in the range of [%u, %u]\n",
>> +              is_enable? "Enable":"Disable", phase_name, new_range->start, new_range->last);
>
> Use separate calls to inform for the enable and disable cases, so that
> full sentences can be extracted for translation.
>
>> +           error ("Invalid range %s in option %s",
>> +                  one_range,
>> +                  is_enable ? "-fenable" : "-fdisable");
>
> GNU Coding Standards.
>
>> +               error ("Invalid range %s in option %s",
>
> Likewise.
>
>> +          inform (UNKNOWN_LOCATION, "%s pass %s for functions in the range of [%u, %u]\n",
>> +                  is_enable? "Enable":"Disable", phase_name, new_range->start, new_range->last);
>
> Again needs GCS and i18n fixes.
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-18 19:49 New options to disable/enable any pass for any functions (issue4550056) David Li
  2011-05-18 20:21 ` Joseph S. Myers
@ 2011-05-18 21:01 ` Richard Guenther
  2011-05-18 21:20   ` Xinliang David Li
  2011-05-19 19:23 ` Andi Kleen
  2 siblings, 1 reply; 32+ messages in thread
From: Richard Guenther @ 2011-05-18 21:01 UTC (permalink / raw)
  To: David Li; +Cc: reply, gcc-patches

On Wed, May 18, 2011 at 8:37 PM, David Li <davidxl@google.com> wrote:
>
> In gcc, not all passes have user level control to turn it on/off, and
> there is no way to flip on/off the pass for a subset of functions. I
> implemented a generic option handling scheme in gcc to allow
> disabling/enabling any gcc pass for any specified function(s).  The
> new options will be very useful for things like performance
> experiments and bug triaging (gcc has dbgcnt mechanism, but not all
> passes have the counter).
>
> The option syntax is very similar to -fdump- options. The following
> are some examples:
>
> -fdisable-tree-ccp1    <--- disable ccp1 for all functions
> -fenable-tree-cunroll=1   <--- enable complete unroll for the function
>                           whose cgraphnode uid is 1
> -fdisable-rtl-gcse2=1:100,300,400:1000   <-- disable gcse2 for
>                                           functions at the following
>                                            ranges [1,1], [300,400], and [400,1000]
> -fdisable-tree-einline --> disable early inlining for all callers
> -fdisable-ipa-inline --> disable ipa inlininig
>
> In the gcc dumps, the uid numbers are displayed in the function header.
>
> The options are intended to be used internally by gcc developers.
>
> Ok for trunk ? (There is a little LIPO specific change that can be removed).
>
> David
>
> 2011-05-18  David Li  <davidxl@google.com>
>
>        * final.c (rest_of_clean_state): Call function header dumper.
>        * opts-global.c (handle_common_deferred_options): Handle new options.
>        * tree-cfg.c (gimple_dump_cfg): Call function header dumper.
>        * passes.c (register_one_dump_file): Call register_pass_name.
>        (pass_init_dump_file): Call function header dumper.
>        (execute_one_pass): Check explicit enable/disable flag.
>        (passr_hash): New function.
>        (passr_eq):
>        (register_pass_name):
>        (get_pass_by_name):
>        (pass_hash):
>        (pass_eq):
>        (enable_disable_pass):
>        (is_pass_explicitly_enabled_or_disabled):
>        (is_pass_explicitly_enabled):
>        (is_pass_explicitly_disabled):

Bogus changelog entry.

New options need documenting in doc/invoke.texi.

Richard.

>
> Index: tree-pass.h
> ===================================================================
> --- tree-pass.h (revision 173635)
> +++ tree-pass.h (working copy)
> @@ -644,4 +644,12 @@ extern bool first_pass_instance;
>  /* Declare for plugins.  */
>  extern void do_per_function_toporder (void (*) (void *), void *);
>
> +extern void enable_disable_pass (const char *, bool);
> +extern bool is_pass_explicitly_disabled (struct opt_pass *, tree);
> +extern bool is_pass_explicitly_enabled (struct opt_pass *, tree);
> +extern void register_pass_name (struct opt_pass *, const char *);
> +extern struct opt_pass *get_pass_by_name (const char *);
> +struct function;
> +extern void pass_dump_function_header (FILE *, tree, struct function *);
> +
>  #endif /* GCC_TREE_PASS_H */
> Index: final.c
> ===================================================================
> --- final.c     (revision 173635)
> +++ final.c     (working copy)
> @@ -4456,19 +4456,7 @@ rest_of_clean_state (void)
>        }
>       else
>        {
> -         const char *aname;
> -         struct cgraph_node *node = cgraph_node (current_function_decl);
> -
> -         aname = (IDENTIFIER_POINTER
> -                  (DECL_ASSEMBLER_NAME (current_function_decl)));
> -         fprintf (final_output, "\n;; Function (%s) %s\n\n", aname,
> -            node->frequency == NODE_FREQUENCY_HOT
> -            ? " (hot)"
> -            : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
> -            ? " (unlikely executed)"
> -            : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
> -            ? " (executed once)"
> -            : "");
> +         pass_dump_function_header (final_output, current_function_decl, cfun);
>
>          flag_dump_noaddr = flag_dump_unnumbered = 1;
>          if (flag_compare_debug_opt || flag_compare_debug)
> Index: common.opt
> ===================================================================
> --- common.opt  (revision 173635)
> +++ common.opt  (working copy)
> @@ -1018,6 +1018,14 @@ fdiagnostics-show-option
>  Common Var(flag_diagnostics_show_option) Init(1)
>  Amend appropriate diagnostic messages with the command line option that controls them
>
> +fdisable-
> +Common Joined RejectNegative Var(common_deferred_options) Defer
> +-fdisable-[tree|rtl|ipa]-<pass>=range1+range2 disables an optimization pass
> +
> +fenable-
> +Common Joined RejectNegative Var(common_deferred_options) Defer
> +-fenable-[tree|rtl|ipa]-<pass>=range1+range2 enables an optimization pass
> +
>  fdump-
>  Common Joined RejectNegative Var(common_deferred_options) Defer
>  -fdump-<type>  Dump various compiler internals to a file
> Index: opts-global.c
> ===================================================================
> --- opts-global.c       (revision 173635)
> +++ opts-global.c       (working copy)
> @@ -411,6 +411,12 @@ handle_common_deferred_options (void)
>            error ("unrecognized command line option %<-fdump-%s%>", opt->arg);
>          break;
>
> +       case OPT_fenable_:
> +       case OPT_fdisable_:
> +         enable_disable_pass (opt->arg, (opt->opt_index == OPT_fenable_?
> +                              true : false));
> +          break;
> +
>        case OPT_ffixed_:
>          /* Deferred.  */
>          fix_register (opt->arg, 1, 1);
> Index: tree-cfg.c
> ===================================================================
> --- tree-cfg.c  (revision 173636)
> +++ tree-cfg.c  (working copy)
> @@ -2090,11 +2090,7 @@ gimple_dump_cfg (FILE *file, int flags)
>  {
>   if (flags & TDF_DETAILS)
>     {
> -      const char *funcname
> -       = lang_hooks.decl_printable_name (current_function_decl, 2);
> -
> -      fputc ('\n', file);
> -      fprintf (file, ";; Function %s\n\n", funcname);
> +      pass_dump_function_header (file, current_function_decl, cfun);
>       fprintf (file, ";; \n%d basic blocks, %d edges, last basic block %d.\n\n",
>               n_basic_blocks, n_edges, last_basic_block);
>
> Index: passes.c
> ===================================================================
> --- passes.c    (revision 173635)
> +++ passes.c    (working copy)
> @@ -382,7 +382,7 @@ void
>  register_one_dump_file (struct opt_pass *pass)
>  {
>   char *dot_name, *flag_name, *glob_name;
> -  const char *name, *prefix;
> +  const char *name, *full_name, *prefix;
>   char num[10];
>   int flags, id;
>
> @@ -411,6 +411,8 @@ register_one_dump_file (struct opt_pass
>   glob_name = concat (prefix, name, NULL);
>   id = dump_register (dot_name, flag_name, glob_name, flags);
>   set_pass_for_id (id, pass);
> +  full_name = concat (prefix, pass->name, num, NULL);
> +  register_pass_name (pass, full_name);
>  }
>
>  /* Recursive worker function for register_dump_files.  */
> @@ -454,6 +456,298 @@ register_dump_files (struct opt_pass *pa
>   register_dump_files_1 (pass, properties);
>  }
>
> +struct pass_registry
> +{
> +  const char* unique_name;
> +  struct opt_pass *pass;
> +};
> +
> +/* Pass registry hash function.  */
> +
> +static hashval_t
> +passr_hash (const void *p)
> +{
> +  const struct pass_registry *const s = (const struct pass_registry *const) p;
> +  return htab_hash_string (s->unique_name);
> +}
> +
> +/* Hash equal function  */
> +
> +static int
> +passr_eq (const void *p1, const void *p2)
> +{
> +  const struct pass_registry *const s1 = (const struct pass_registry *const) p1;
> +  const struct pass_registry *const s2 = (const struct pass_registry *const) p2;
> +
> +  return !strcmp (s1->unique_name, s2->unique_name);
> +}
> +
> +static htab_t pass_name_tab = NULL;
> +
> +/* Register PASS with NAME.  */
> +
> +void
> +register_pass_name (struct opt_pass *pass, const char *name)
> +{
> +  struct pass_registry **slot;
> +  struct pass_registry pr;
> +
> +  if (!pass_name_tab)
> +    pass_name_tab = htab_create (10, passr_hash, passr_eq, NULL);
> +
> +  pr.unique_name = name;
> +  slot = (struct pass_registry **) htab_find_slot (pass_name_tab, &pr, INSERT);
> +  if (!*slot)
> +    {
> +      struct pass_registry *new_pr;
> +
> +      new_pr = XCNEW (struct pass_registry);
> +      new_pr->unique_name = xstrdup (name);
> +      new_pr->pass = pass;
> +      *slot = new_pr;
> +    }
> +  else
> +    gcc_assert ((*slot)->pass == pass);
> +}
> +
> +/* Returns the pass with NAME.  */
> +
> +struct opt_pass *
> +get_pass_by_name (const char *name)
> +{
> +  struct pass_registry **slot, pr;
> +
> +  gcc_assert (pass_name_tab);
> +  pr.unique_name = name;
> +  slot = (struct pass_registry **) htab_find_slot (pass_name_tab, &pr, NO_INSERT);
> +
> +  if (!slot || !*slot)
> +    return NULL;
> +
> +  return (*slot)->pass;
> +}
> +
> +
> +/* Range [start, last].  */
> +
> +struct uid_range
> +{
> +  struct opt_pass *pass;
> +  unsigned int start;
> +  unsigned int last;
> +  struct uid_range *next;
> +};
> +
> +/* Hash function for pass structure.  */
> +
> +static hashval_t
> +pass_hash (const void *s)
> +{
> +  const struct uid_range *const p = (const struct uid_range *const) s;
> +  return p->pass->static_pass_number;
> +}
> +
> +/* Pass equal function  */
> +
> +static int
> +pass_eq (const void *s1, const void *s2)
> +{
> +  const struct uid_range *const p1 = (const struct uid_range *const) s1;
> +  const struct uid_range *const p2 = (const struct uid_range *const) s2;
> +  return p1->pass->static_pass_number == p2->pass->static_pass_number;
> +}
> +
> +htab_t enabled_pass_uid_range_tab = NULL;
> +htab_t disabled_pass_uid_range_tab = NULL;
> +
> +/* Parse option string for -fdisable- and -fenabler-
> +   The syntax of the options:
> +
> +   -fenable-<pass_name>
> +   -fdisable-<pass_name>
> +
> +   -fenable-<pass_name>=s1:e1,s2:e2,...
> +   -fdisable-<pass_name>=s1:e1,s2:e2,...
> +*/
> +
> +void
> +enable_disable_pass (const char *arg, bool is_enable)
> +{
> +  struct opt_pass *pass;
> +  htab_t the_tab;
> +  char *range_str, *phase_name;
> +  char *argstr = xstrdup (arg);
> +
> +  range_str = strchr (argstr,'=');
> +  if (range_str)
> +    {
> +      *range_str = '\0';
> +      range_str++;
> +    }
> +
> +  phase_name = argstr;
> +  if (!*phase_name)
> +    {
> +      error ("Unrecognized option %s", is_enable ? "-fenable" : "-fdisable");
> +      free (argstr);
> +      return;
> +    }
> +  pass = get_pass_by_name (phase_name);
> +  if (!pass)
> +    {
> +      error ("Unknown pass %s specified in %s",
> +            phase_name,
> +            is_enable ? "-fenable" : "-fdisable");
> +      free (argstr);
> +      return;
> +    }
> +  if (is_enable)
> +    {
> +      if (!enabled_pass_uid_range_tab)
> +       enabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
> +      the_tab = enabled_pass_uid_range_tab;
> +    }
> +  else
> +    {
> +      if (!disabled_pass_uid_range_tab)
> +       disabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
> +      the_tab = disabled_pass_uid_range_tab;
> +    }
> +
> +  if (!range_str)
> +    {
> +      struct uid_range **slot;
> +      struct uid_range *new_range = XCNEW (struct uid_range);
> +
> +      new_range->pass = pass;
> +      new_range->start = 0;
> +      new_range->last = (unsigned)-1;
> +
> +      slot = (struct uid_range **) htab_find_slot (the_tab, new_range, INSERT);
> +      new_range->next = *slot;
> +      *slot = new_range;
> +      inform (UNKNOWN_LOCATION, "%s pass %s for functions in the range of [%u, %u]\n",
> +              is_enable? "Enable":"Disable", phase_name, new_range->start, new_range->last);
> +    }
> +  else
> +    {
> +      char *next_range = NULL;
> +      char *one_range = range_str;
> +      char *end_val = NULL;
> +
> +      do
> +       {
> +         struct uid_range **slot;
> +         struct uid_range *new_range;
> +         char *invalid = NULL;
> +         long start;
> +
> +         next_range = strchr (one_range, ',');
> +         if (next_range)
> +           {
> +             *next_range = '\0';
> +             next_range++;
> +           }
> +
> +         end_val = strchr (one_range, ':');
> +         if (end_val)
> +           {
> +             *end_val = '\0';
> +             end_val++;
> +           }
> +         start = strtol (one_range, &invalid, 10);
> +         if (*invalid || start < 0)
> +           {
> +             error ("Invalid range %s in option %s",
> +                    one_range,
> +                    is_enable ? "-fenable" : "-fdisable");
> +             free (argstr);
> +             return;
> +           }
> +         if (!end_val)
> +           {
> +             new_range = XCNEW (struct uid_range);
> +              new_range->pass = pass;
> +             new_range->start = (unsigned) start;
> +             new_range->last = (unsigned) start;
> +           }
> +         else
> +           {
> +             long last = strtol (end_val, &invalid, 10);
> +             if (*invalid || last < start)
> +               {
> +                 error ("Invalid range %s in option %s",
> +                        end_val,
> +                        is_enable ? "-fenable" : "-fdisable");
> +                 free (argstr);
> +                 return;
> +               }
> +             new_range = XCNEW (struct uid_range);
> +              new_range->pass = pass;
> +             new_range->start = (unsigned) start;
> +             new_range->last = (unsigned) last;
> +           }
> +         slot = (struct uid_range **) htab_find_slot (the_tab, new_range, INSERT);
> +         new_range->next = *slot;
> +         *slot = new_range;
> +          inform (UNKNOWN_LOCATION, "%s pass %s for functions in the range of [%u, %u]\n",
> +                  is_enable? "Enable":"Disable", phase_name, new_range->start, new_range->last);
> +
> +         one_range = next_range;
> +       } while (next_range);
> +    }
> +
> +  free (argstr);
> +}
> +
> +/* Returns true if PASS is explicitly enabled/disabled for FUNC.  */
> +
> +static bool
> +is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
> +                                       tree func, htab_t tab)
> +{
> +  struct uid_range **slot, *range, key;
> +  int cgraph_uid;
> +
> +  if (!tab)
> +    return false;
> +
> +  key.pass = pass;
> +  slot = (struct uid_range **) htab_find_slot (tab, &key, NO_INSERT);
> +  if (!slot || !*slot)
> +    return false;
> +
> +  cgraph_uid = func ? cgraph_node (func)->uid : 0;
> +
> +  range = *slot;
> +  while (range)
> +    {
> +      if ((unsigned) cgraph_uid >= range->start
> +         && (unsigned) cgraph_uid <= range->last)
> +       return true;
> +      range = range->next;
> +    }
> +
> +  return false;
> +}
> +
> +/* Returns true if PASS is explicitly enabled for FUNC.  */
> +
> +bool
> +is_pass_explicitly_enabled (struct opt_pass *pass, tree func)
> +{
> +  return is_pass_explicitly_enabled_or_disabled (pass, func, enabled_pass_uid_range_tab);
> +}
> +
> +/* Returns true if PASS is explicitly disabled for FUNC.  */
> +
> +bool
> +is_pass_explicitly_disabled (struct opt_pass *pass, tree func)
> +{
> +  return is_pass_explicitly_enabled_or_disabled (pass, func, disabled_pass_uid_range_tab);
> +}
> +
> +
>  /* Look at the static_pass_number and duplicate the pass
>    if it is already added to a list. */
>
> @@ -1349,6 +1643,29 @@ verify_curr_properties (void *data)
>  }
>  #endif
>
> +void
> +pass_dump_function_header (FILE *dump_file, tree fdecl, struct function *fun)
> +{
> +  const char *dname, *aname;
> +  struct cgraph_node *node = cgraph_node (fdecl);
> +  dname = lang_hooks.decl_printable_name (fdecl, 2);
> +  aname = (IDENTIFIER_POINTER
> +          (DECL_ASSEMBLER_NAME (fdecl)));
> +  if (L_IPO_COMP_MODE)
> +    fprintf (dump_file, "\n;; Function %s (%s)[%d:%d][uid=%d]", dname, aname,
> +            FUNC_DECL_MODULE_ID (fun), FUNC_DECL_FUNC_ID (fun), node->uid);
> +  else
> +    fprintf (dump_file, "\n;; Function %s (%s)[uid=%d]", dname, aname, node->uid);
> +  fprintf (dump_file, "%s\n\n",
> +           node->frequency == NODE_FREQUENCY_HOT
> +           ? " (hot)"
> +           : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
> +           ? " (unlikely executed)"
> +           : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
> +           ? " (executed once)"
> +           : "");
> +}
> +
>  /* Initialize pass dump file.  */
>  /* This is non-static so that the plugins can use it.  */
>
> @@ -1362,26 +1679,7 @@ pass_init_dump_file (struct opt_pass *pa
>       dump_file_name = get_dump_file_name (pass->static_pass_number);
>       dump_file = dump_begin (pass->static_pass_number, &dump_flags);
>       if (dump_file && current_function_decl)
> -       {
> -         const char *dname, *aname;
> -         struct cgraph_node *node = cgraph_node (current_function_decl);
> -         dname = lang_hooks.decl_printable_name (current_function_decl, 2);
> -         aname = (IDENTIFIER_POINTER
> -                  (DECL_ASSEMBLER_NAME (current_function_decl)));
> -         if (L_IPO_COMP_MODE)
> -           fprintf (dump_file, "\n;; Function %s (%s)[%d:%d]", dname, aname,
> -                    FUNC_DECL_MODULE_ID (cfun), FUNC_DECL_FUNC_ID (cfun));
> -         else
> -           fprintf (dump_file, "\n;; Function %s (%s)", dname, aname);
> -         fprintf (dump_file, "%s\n\n",
> -            node->frequency == NODE_FREQUENCY_HOT
> -            ? " (hot)"
> -            : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
> -            ? " (unlikely executed)"
> -            : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
> -            ? " (executed once)"
> -            : "");
> -       }
> +        pass_dump_function_header (dump_file, current_function_decl, cfun);
>       return initializing_dump;
>     }
>   else
> @@ -1525,6 +1823,8 @@ execute_one_pass (struct opt_pass *pass)
>  {
>   bool initializing_dump;
>   unsigned int todo_after = 0;
> +  bool explicitly_enabled = false;
> +  bool explicitly_disabled = false;
>
>   bool gate_status;
>
> @@ -1535,11 +1835,15 @@ execute_one_pass (struct opt_pass *pass)
>   else
>     gcc_assert (cfun && current_function_decl);
>
> +  explicitly_enabled = is_pass_explicitly_enabled (pass, current_function_decl);
> +  explicitly_disabled = is_pass_explicitly_disabled (pass, current_function_decl);
> +
>   current_pass = pass;
>
>   /* 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();
> +  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
>
>   /* Override gate with plugin.  */
>   invoke_plugin_callbacks (PLUGIN_OVERRIDE_GATE, &gate_status);
>
> --
> This patch is available for review at http://codereview.appspot.com/4550056
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-18 21:01 ` Richard Guenther
@ 2011-05-18 21:20   ` Xinliang David Li
  2011-05-19  8:04     ` Xinliang David Li
  0 siblings, 1 reply; 32+ messages in thread
From: Xinliang David Li @ 2011-05-18 21:20 UTC (permalink / raw)
  To: Richard Guenther; +Cc: reply, gcc-patches

Will fix the Changelog, and add documentation.

Thanks,

David



On Wed, May 18, 2011 at 1:26 PM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Wed, May 18, 2011 at 8:37 PM, David Li <davidxl@google.com> wrote:
>>
>> In gcc, not all passes have user level control to turn it on/off, and
>> there is no way to flip on/off the pass for a subset of functions. I
>> implemented a generic option handling scheme in gcc to allow
>> disabling/enabling any gcc pass for any specified function(s).  The
>> new options will be very useful for things like performance
>> experiments and bug triaging (gcc has dbgcnt mechanism, but not all
>> passes have the counter).
>>
>> The option syntax is very similar to -fdump- options. The following
>> are some examples:
>>
>> -fdisable-tree-ccp1    <--- disable ccp1 for all functions
>> -fenable-tree-cunroll=1   <--- enable complete unroll for the function
>>                           whose cgraphnode uid is 1
>> -fdisable-rtl-gcse2=1:100,300,400:1000   <-- disable gcse2 for
>>                                           functions at the following
>>                                            ranges [1,1], [300,400], and [400,1000]
>> -fdisable-tree-einline --> disable early inlining for all callers
>> -fdisable-ipa-inline --> disable ipa inlininig
>>
>> In the gcc dumps, the uid numbers are displayed in the function header.
>>
>> The options are intended to be used internally by gcc developers.
>>
>> Ok for trunk ? (There is a little LIPO specific change that can be removed).
>>
>> David
>>
>> 2011-05-18  David Li  <davidxl@google.com>
>>
>>        * final.c (rest_of_clean_state): Call function header dumper.
>>        * opts-global.c (handle_common_deferred_options): Handle new options.
>>        * tree-cfg.c (gimple_dump_cfg): Call function header dumper.
>>        * passes.c (register_one_dump_file): Call register_pass_name.
>>        (pass_init_dump_file): Call function header dumper.
>>        (execute_one_pass): Check explicit enable/disable flag.
>>        (passr_hash): New function.
>>        (passr_eq):
>>        (register_pass_name):
>>        (get_pass_by_name):
>>        (pass_hash):
>>        (pass_eq):
>>        (enable_disable_pass):
>>        (is_pass_explicitly_enabled_or_disabled):
>>        (is_pass_explicitly_enabled):
>>        (is_pass_explicitly_disabled):
>
> Bogus changelog entry.
>
> New options need documenting in doc/invoke.texi.
>
> Richard.
>
>>
>> Index: tree-pass.h
>> ===================================================================
>> --- tree-pass.h (revision 173635)
>> +++ tree-pass.h (working copy)
>> @@ -644,4 +644,12 @@ extern bool first_pass_instance;
>>  /* Declare for plugins.  */
>>  extern void do_per_function_toporder (void (*) (void *), void *);
>>
>> +extern void enable_disable_pass (const char *, bool);
>> +extern bool is_pass_explicitly_disabled (struct opt_pass *, tree);
>> +extern bool is_pass_explicitly_enabled (struct opt_pass *, tree);
>> +extern void register_pass_name (struct opt_pass *, const char *);
>> +extern struct opt_pass *get_pass_by_name (const char *);
>> +struct function;
>> +extern void pass_dump_function_header (FILE *, tree, struct function *);
>> +
>>  #endif /* GCC_TREE_PASS_H */
>> Index: final.c
>> ===================================================================
>> --- final.c     (revision 173635)
>> +++ final.c     (working copy)
>> @@ -4456,19 +4456,7 @@ rest_of_clean_state (void)
>>        }
>>       else
>>        {
>> -         const char *aname;
>> -         struct cgraph_node *node = cgraph_node (current_function_decl);
>> -
>> -         aname = (IDENTIFIER_POINTER
>> -                  (DECL_ASSEMBLER_NAME (current_function_decl)));
>> -         fprintf (final_output, "\n;; Function (%s) %s\n\n", aname,
>> -            node->frequency == NODE_FREQUENCY_HOT
>> -            ? " (hot)"
>> -            : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
>> -            ? " (unlikely executed)"
>> -            : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
>> -            ? " (executed once)"
>> -            : "");
>> +         pass_dump_function_header (final_output, current_function_decl, cfun);
>>
>>          flag_dump_noaddr = flag_dump_unnumbered = 1;
>>          if (flag_compare_debug_opt || flag_compare_debug)
>> Index: common.opt
>> ===================================================================
>> --- common.opt  (revision 173635)
>> +++ common.opt  (working copy)
>> @@ -1018,6 +1018,14 @@ fdiagnostics-show-option
>>  Common Var(flag_diagnostics_show_option) Init(1)
>>  Amend appropriate diagnostic messages with the command line option that controls them
>>
>> +fdisable-
>> +Common Joined RejectNegative Var(common_deferred_options) Defer
>> +-fdisable-[tree|rtl|ipa]-<pass>=range1+range2 disables an optimization pass
>> +
>> +fenable-
>> +Common Joined RejectNegative Var(common_deferred_options) Defer
>> +-fenable-[tree|rtl|ipa]-<pass>=range1+range2 enables an optimization pass
>> +
>>  fdump-
>>  Common Joined RejectNegative Var(common_deferred_options) Defer
>>  -fdump-<type>  Dump various compiler internals to a file
>> Index: opts-global.c
>> ===================================================================
>> --- opts-global.c       (revision 173635)
>> +++ opts-global.c       (working copy)
>> @@ -411,6 +411,12 @@ handle_common_deferred_options (void)
>>            error ("unrecognized command line option %<-fdump-%s%>", opt->arg);
>>          break;
>>
>> +       case OPT_fenable_:
>> +       case OPT_fdisable_:
>> +         enable_disable_pass (opt->arg, (opt->opt_index == OPT_fenable_?
>> +                              true : false));
>> +          break;
>> +
>>        case OPT_ffixed_:
>>          /* Deferred.  */
>>          fix_register (opt->arg, 1, 1);
>> Index: tree-cfg.c
>> ===================================================================
>> --- tree-cfg.c  (revision 173636)
>> +++ tree-cfg.c  (working copy)
>> @@ -2090,11 +2090,7 @@ gimple_dump_cfg (FILE *file, int flags)
>>  {
>>   if (flags & TDF_DETAILS)
>>     {
>> -      const char *funcname
>> -       = lang_hooks.decl_printable_name (current_function_decl, 2);
>> -
>> -      fputc ('\n', file);
>> -      fprintf (file, ";; Function %s\n\n", funcname);
>> +      pass_dump_function_header (file, current_function_decl, cfun);
>>       fprintf (file, ";; \n%d basic blocks, %d edges, last basic block %d.\n\n",
>>               n_basic_blocks, n_edges, last_basic_block);
>>
>> Index: passes.c
>> ===================================================================
>> --- passes.c    (revision 173635)
>> +++ passes.c    (working copy)
>> @@ -382,7 +382,7 @@ void
>>  register_one_dump_file (struct opt_pass *pass)
>>  {
>>   char *dot_name, *flag_name, *glob_name;
>> -  const char *name, *prefix;
>> +  const char *name, *full_name, *prefix;
>>   char num[10];
>>   int flags, id;
>>
>> @@ -411,6 +411,8 @@ register_one_dump_file (struct opt_pass
>>   glob_name = concat (prefix, name, NULL);
>>   id = dump_register (dot_name, flag_name, glob_name, flags);
>>   set_pass_for_id (id, pass);
>> +  full_name = concat (prefix, pass->name, num, NULL);
>> +  register_pass_name (pass, full_name);
>>  }
>>
>>  /* Recursive worker function for register_dump_files.  */
>> @@ -454,6 +456,298 @@ register_dump_files (struct opt_pass *pa
>>   register_dump_files_1 (pass, properties);
>>  }
>>
>> +struct pass_registry
>> +{
>> +  const char* unique_name;
>> +  struct opt_pass *pass;
>> +};
>> +
>> +/* Pass registry hash function.  */
>> +
>> +static hashval_t
>> +passr_hash (const void *p)
>> +{
>> +  const struct pass_registry *const s = (const struct pass_registry *const) p;
>> +  return htab_hash_string (s->unique_name);
>> +}
>> +
>> +/* Hash equal function  */
>> +
>> +static int
>> +passr_eq (const void *p1, const void *p2)
>> +{
>> +  const struct pass_registry *const s1 = (const struct pass_registry *const) p1;
>> +  const struct pass_registry *const s2 = (const struct pass_registry *const) p2;
>> +
>> +  return !strcmp (s1->unique_name, s2->unique_name);
>> +}
>> +
>> +static htab_t pass_name_tab = NULL;
>> +
>> +/* Register PASS with NAME.  */
>> +
>> +void
>> +register_pass_name (struct opt_pass *pass, const char *name)
>> +{
>> +  struct pass_registry **slot;
>> +  struct pass_registry pr;
>> +
>> +  if (!pass_name_tab)
>> +    pass_name_tab = htab_create (10, passr_hash, passr_eq, NULL);
>> +
>> +  pr.unique_name = name;
>> +  slot = (struct pass_registry **) htab_find_slot (pass_name_tab, &pr, INSERT);
>> +  if (!*slot)
>> +    {
>> +      struct pass_registry *new_pr;
>> +
>> +      new_pr = XCNEW (struct pass_registry);
>> +      new_pr->unique_name = xstrdup (name);
>> +      new_pr->pass = pass;
>> +      *slot = new_pr;
>> +    }
>> +  else
>> +    gcc_assert ((*slot)->pass == pass);
>> +}
>> +
>> +/* Returns the pass with NAME.  */
>> +
>> +struct opt_pass *
>> +get_pass_by_name (const char *name)
>> +{
>> +  struct pass_registry **slot, pr;
>> +
>> +  gcc_assert (pass_name_tab);
>> +  pr.unique_name = name;
>> +  slot = (struct pass_registry **) htab_find_slot (pass_name_tab, &pr, NO_INSERT);
>> +
>> +  if (!slot || !*slot)
>> +    return NULL;
>> +
>> +  return (*slot)->pass;
>> +}
>> +
>> +
>> +/* Range [start, last].  */
>> +
>> +struct uid_range
>> +{
>> +  struct opt_pass *pass;
>> +  unsigned int start;
>> +  unsigned int last;
>> +  struct uid_range *next;
>> +};
>> +
>> +/* Hash function for pass structure.  */
>> +
>> +static hashval_t
>> +pass_hash (const void *s)
>> +{
>> +  const struct uid_range *const p = (const struct uid_range *const) s;
>> +  return p->pass->static_pass_number;
>> +}
>> +
>> +/* Pass equal function  */
>> +
>> +static int
>> +pass_eq (const void *s1, const void *s2)
>> +{
>> +  const struct uid_range *const p1 = (const struct uid_range *const) s1;
>> +  const struct uid_range *const p2 = (const struct uid_range *const) s2;
>> +  return p1->pass->static_pass_number == p2->pass->static_pass_number;
>> +}
>> +
>> +htab_t enabled_pass_uid_range_tab = NULL;
>> +htab_t disabled_pass_uid_range_tab = NULL;
>> +
>> +/* Parse option string for -fdisable- and -fenabler-
>> +   The syntax of the options:
>> +
>> +   -fenable-<pass_name>
>> +   -fdisable-<pass_name>
>> +
>> +   -fenable-<pass_name>=s1:e1,s2:e2,...
>> +   -fdisable-<pass_name>=s1:e1,s2:e2,...
>> +*/
>> +
>> +void
>> +enable_disable_pass (const char *arg, bool is_enable)
>> +{
>> +  struct opt_pass *pass;
>> +  htab_t the_tab;
>> +  char *range_str, *phase_name;
>> +  char *argstr = xstrdup (arg);
>> +
>> +  range_str = strchr (argstr,'=');
>> +  if (range_str)
>> +    {
>> +      *range_str = '\0';
>> +      range_str++;
>> +    }
>> +
>> +  phase_name = argstr;
>> +  if (!*phase_name)
>> +    {
>> +      error ("Unrecognized option %s", is_enable ? "-fenable" : "-fdisable");
>> +      free (argstr);
>> +      return;
>> +    }
>> +  pass = get_pass_by_name (phase_name);
>> +  if (!pass)
>> +    {
>> +      error ("Unknown pass %s specified in %s",
>> +            phase_name,
>> +            is_enable ? "-fenable" : "-fdisable");
>> +      free (argstr);
>> +      return;
>> +    }
>> +  if (is_enable)
>> +    {
>> +      if (!enabled_pass_uid_range_tab)
>> +       enabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
>> +      the_tab = enabled_pass_uid_range_tab;
>> +    }
>> +  else
>> +    {
>> +      if (!disabled_pass_uid_range_tab)
>> +       disabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
>> +      the_tab = disabled_pass_uid_range_tab;
>> +    }
>> +
>> +  if (!range_str)
>> +    {
>> +      struct uid_range **slot;
>> +      struct uid_range *new_range = XCNEW (struct uid_range);
>> +
>> +      new_range->pass = pass;
>> +      new_range->start = 0;
>> +      new_range->last = (unsigned)-1;
>> +
>> +      slot = (struct uid_range **) htab_find_slot (the_tab, new_range, INSERT);
>> +      new_range->next = *slot;
>> +      *slot = new_range;
>> +      inform (UNKNOWN_LOCATION, "%s pass %s for functions in the range of [%u, %u]\n",
>> +              is_enable? "Enable":"Disable", phase_name, new_range->start, new_range->last);
>> +    }
>> +  else
>> +    {
>> +      char *next_range = NULL;
>> +      char *one_range = range_str;
>> +      char *end_val = NULL;
>> +
>> +      do
>> +       {
>> +         struct uid_range **slot;
>> +         struct uid_range *new_range;
>> +         char *invalid = NULL;
>> +         long start;
>> +
>> +         next_range = strchr (one_range, ',');
>> +         if (next_range)
>> +           {
>> +             *next_range = '\0';
>> +             next_range++;
>> +           }
>> +
>> +         end_val = strchr (one_range, ':');
>> +         if (end_val)
>> +           {
>> +             *end_val = '\0';
>> +             end_val++;
>> +           }
>> +         start = strtol (one_range, &invalid, 10);
>> +         if (*invalid || start < 0)
>> +           {
>> +             error ("Invalid range %s in option %s",
>> +                    one_range,
>> +                    is_enable ? "-fenable" : "-fdisable");
>> +             free (argstr);
>> +             return;
>> +           }
>> +         if (!end_val)
>> +           {
>> +             new_range = XCNEW (struct uid_range);
>> +              new_range->pass = pass;
>> +             new_range->start = (unsigned) start;
>> +             new_range->last = (unsigned) start;
>> +           }
>> +         else
>> +           {
>> +             long last = strtol (end_val, &invalid, 10);
>> +             if (*invalid || last < start)
>> +               {
>> +                 error ("Invalid range %s in option %s",
>> +                        end_val,
>> +                        is_enable ? "-fenable" : "-fdisable");
>> +                 free (argstr);
>> +                 return;
>> +               }
>> +             new_range = XCNEW (struct uid_range);
>> +              new_range->pass = pass;
>> +             new_range->start = (unsigned) start;
>> +             new_range->last = (unsigned) last;
>> +           }
>> +         slot = (struct uid_range **) htab_find_slot (the_tab, new_range, INSERT);
>> +         new_range->next = *slot;
>> +         *slot = new_range;
>> +          inform (UNKNOWN_LOCATION, "%s pass %s for functions in the range of [%u, %u]\n",
>> +                  is_enable? "Enable":"Disable", phase_name, new_range->start, new_range->last);
>> +
>> +         one_range = next_range;
>> +       } while (next_range);
>> +    }
>> +
>> +  free (argstr);
>> +}
>> +
>> +/* Returns true if PASS is explicitly enabled/disabled for FUNC.  */
>> +
>> +static bool
>> +is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
>> +                                       tree func, htab_t tab)
>> +{
>> +  struct uid_range **slot, *range, key;
>> +  int cgraph_uid;
>> +
>> +  if (!tab)
>> +    return false;
>> +
>> +  key.pass = pass;
>> +  slot = (struct uid_range **) htab_find_slot (tab, &key, NO_INSERT);
>> +  if (!slot || !*slot)
>> +    return false;
>> +
>> +  cgraph_uid = func ? cgraph_node (func)->uid : 0;
>> +
>> +  range = *slot;
>> +  while (range)
>> +    {
>> +      if ((unsigned) cgraph_uid >= range->start
>> +         && (unsigned) cgraph_uid <= range->last)
>> +       return true;
>> +      range = range->next;
>> +    }
>> +
>> +  return false;
>> +}
>> +
>> +/* Returns true if PASS is explicitly enabled for FUNC.  */
>> +
>> +bool
>> +is_pass_explicitly_enabled (struct opt_pass *pass, tree func)
>> +{
>> +  return is_pass_explicitly_enabled_or_disabled (pass, func, enabled_pass_uid_range_tab);
>> +}
>> +
>> +/* Returns true if PASS is explicitly disabled for FUNC.  */
>> +
>> +bool
>> +is_pass_explicitly_disabled (struct opt_pass *pass, tree func)
>> +{
>> +  return is_pass_explicitly_enabled_or_disabled (pass, func, disabled_pass_uid_range_tab);
>> +}
>> +
>> +
>>  /* Look at the static_pass_number and duplicate the pass
>>    if it is already added to a list. */
>>
>> @@ -1349,6 +1643,29 @@ verify_curr_properties (void *data)
>>  }
>>  #endif
>>
>> +void
>> +pass_dump_function_header (FILE *dump_file, tree fdecl, struct function *fun)
>> +{
>> +  const char *dname, *aname;
>> +  struct cgraph_node *node = cgraph_node (fdecl);
>> +  dname = lang_hooks.decl_printable_name (fdecl, 2);
>> +  aname = (IDENTIFIER_POINTER
>> +          (DECL_ASSEMBLER_NAME (fdecl)));
>> +  if (L_IPO_COMP_MODE)
>> +    fprintf (dump_file, "\n;; Function %s (%s)[%d:%d][uid=%d]", dname, aname,
>> +            FUNC_DECL_MODULE_ID (fun), FUNC_DECL_FUNC_ID (fun), node->uid);
>> +  else
>> +    fprintf (dump_file, "\n;; Function %s (%s)[uid=%d]", dname, aname, node->uid);
>> +  fprintf (dump_file, "%s\n\n",
>> +           node->frequency == NODE_FREQUENCY_HOT
>> +           ? " (hot)"
>> +           : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
>> +           ? " (unlikely executed)"
>> +           : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
>> +           ? " (executed once)"
>> +           : "");
>> +}
>> +
>>  /* Initialize pass dump file.  */
>>  /* This is non-static so that the plugins can use it.  */
>>
>> @@ -1362,26 +1679,7 @@ pass_init_dump_file (struct opt_pass *pa
>>       dump_file_name = get_dump_file_name (pass->static_pass_number);
>>       dump_file = dump_begin (pass->static_pass_number, &dump_flags);
>>       if (dump_file && current_function_decl)
>> -       {
>> -         const char *dname, *aname;
>> -         struct cgraph_node *node = cgraph_node (current_function_decl);
>> -         dname = lang_hooks.decl_printable_name (current_function_decl, 2);
>> -         aname = (IDENTIFIER_POINTER
>> -                  (DECL_ASSEMBLER_NAME (current_function_decl)));
>> -         if (L_IPO_COMP_MODE)
>> -           fprintf (dump_file, "\n;; Function %s (%s)[%d:%d]", dname, aname,
>> -                    FUNC_DECL_MODULE_ID (cfun), FUNC_DECL_FUNC_ID (cfun));
>> -         else
>> -           fprintf (dump_file, "\n;; Function %s (%s)", dname, aname);
>> -         fprintf (dump_file, "%s\n\n",
>> -            node->frequency == NODE_FREQUENCY_HOT
>> -            ? " (hot)"
>> -            : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
>> -            ? " (unlikely executed)"
>> -            : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
>> -            ? " (executed once)"
>> -            : "");
>> -       }
>> +        pass_dump_function_header (dump_file, current_function_decl, cfun);
>>       return initializing_dump;
>>     }
>>   else
>> @@ -1525,6 +1823,8 @@ execute_one_pass (struct opt_pass *pass)
>>  {
>>   bool initializing_dump;
>>   unsigned int todo_after = 0;
>> +  bool explicitly_enabled = false;
>> +  bool explicitly_disabled = false;
>>
>>   bool gate_status;
>>
>> @@ -1535,11 +1835,15 @@ execute_one_pass (struct opt_pass *pass)
>>   else
>>     gcc_assert (cfun && current_function_decl);
>>
>> +  explicitly_enabled = is_pass_explicitly_enabled (pass, current_function_decl);
>> +  explicitly_disabled = is_pass_explicitly_disabled (pass, current_function_decl);
>> +
>>   current_pass = pass;
>>
>>   /* 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();
>> +  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
>>
>>   /* Override gate with plugin.  */
>>   invoke_plugin_callbacks (PLUGIN_OVERRIDE_GATE, &gate_status);
>>
>> --
>> This patch is available for review at http://codereview.appspot.com/4550056
>>
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-18 21:20   ` Xinliang David Li
@ 2011-05-19  8:04     ` Xinliang David Li
  0 siblings, 0 replies; 32+ messages in thread
From: Xinliang David Li @ 2011-05-19  8:04 UTC (permalink / raw)
  To: Richard Guenther; +Cc: reply, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 20983 bytes --]

The attached is the revised patch. Bootstrap and regression tested in
trunk on x86-64/linux.

Ok for checkin?

Thanks,

David

On Wed, May 18, 2011 at 1:34 PM, Xinliang David Li <davidxl@google.com> wrote:
> Will fix the Changelog, and add documentation.
>
> Thanks,
>
> David
>
>
>
> On Wed, May 18, 2011 at 1:26 PM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Wed, May 18, 2011 at 8:37 PM, David Li <davidxl@google.com> wrote:
>>>
>>> In gcc, not all passes have user level control to turn it on/off, and
>>> there is no way to flip on/off the pass for a subset of functions. I
>>> implemented a generic option handling scheme in gcc to allow
>>> disabling/enabling any gcc pass for any specified function(s).  The
>>> new options will be very useful for things like performance
>>> experiments and bug triaging (gcc has dbgcnt mechanism, but not all
>>> passes have the counter).
>>>
>>> The option syntax is very similar to -fdump- options. The following
>>> are some examples:
>>>
>>> -fdisable-tree-ccp1    <--- disable ccp1 for all functions
>>> -fenable-tree-cunroll=1   <--- enable complete unroll for the function
>>>                           whose cgraphnode uid is 1
>>> -fdisable-rtl-gcse2=1:100,300,400:1000   <-- disable gcse2 for
>>>                                           functions at the following
>>>                                            ranges [1,1], [300,400], and [400,1000]
>>> -fdisable-tree-einline --> disable early inlining for all callers
>>> -fdisable-ipa-inline --> disable ipa inlininig
>>>
>>> In the gcc dumps, the uid numbers are displayed in the function header.
>>>
>>> The options are intended to be used internally by gcc developers.
>>>
>>> Ok for trunk ? (There is a little LIPO specific change that can be removed).
>>>
>>> David
>>>
>>> 2011-05-18  David Li  <davidxl@google.com>
>>>
>>>        * final.c (rest_of_clean_state): Call function header dumper.
>>>        * opts-global.c (handle_common_deferred_options): Handle new options.
>>>        * tree-cfg.c (gimple_dump_cfg): Call function header dumper.
>>>        * passes.c (register_one_dump_file): Call register_pass_name.
>>>        (pass_init_dump_file): Call function header dumper.
>>>        (execute_one_pass): Check explicit enable/disable flag.
>>>        (passr_hash): New function.
>>>        (passr_eq):
>>>        (register_pass_name):
>>>        (get_pass_by_name):
>>>        (pass_hash):
>>>        (pass_eq):
>>>        (enable_disable_pass):
>>>        (is_pass_explicitly_enabled_or_disabled):
>>>        (is_pass_explicitly_enabled):
>>>        (is_pass_explicitly_disabled):
>>
>> Bogus changelog entry.
>>
>> New options need documenting in doc/invoke.texi.
>>
>> Richard.
>>
>>>
>>> Index: tree-pass.h
>>> ===================================================================
>>> --- tree-pass.h (revision 173635)
>>> +++ tree-pass.h (working copy)
>>> @@ -644,4 +644,12 @@ extern bool first_pass_instance;
>>>  /* Declare for plugins.  */
>>>  extern void do_per_function_toporder (void (*) (void *), void *);
>>>
>>> +extern void enable_disable_pass (const char *, bool);
>>> +extern bool is_pass_explicitly_disabled (struct opt_pass *, tree);
>>> +extern bool is_pass_explicitly_enabled (struct opt_pass *, tree);
>>> +extern void register_pass_name (struct opt_pass *, const char *);
>>> +extern struct opt_pass *get_pass_by_name (const char *);
>>> +struct function;
>>> +extern void pass_dump_function_header (FILE *, tree, struct function *);
>>> +
>>>  #endif /* GCC_TREE_PASS_H */
>>> Index: final.c
>>> ===================================================================
>>> --- final.c     (revision 173635)
>>> +++ final.c     (working copy)
>>> @@ -4456,19 +4456,7 @@ rest_of_clean_state (void)
>>>        }
>>>       else
>>>        {
>>> -         const char *aname;
>>> -         struct cgraph_node *node = cgraph_node (current_function_decl);
>>> -
>>> -         aname = (IDENTIFIER_POINTER
>>> -                  (DECL_ASSEMBLER_NAME (current_function_decl)));
>>> -         fprintf (final_output, "\n;; Function (%s) %s\n\n", aname,
>>> -            node->frequency == NODE_FREQUENCY_HOT
>>> -            ? " (hot)"
>>> -            : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
>>> -            ? " (unlikely executed)"
>>> -            : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
>>> -            ? " (executed once)"
>>> -            : "");
>>> +         pass_dump_function_header (final_output, current_function_decl, cfun);
>>>
>>>          flag_dump_noaddr = flag_dump_unnumbered = 1;
>>>          if (flag_compare_debug_opt || flag_compare_debug)
>>> Index: common.opt
>>> ===================================================================
>>> --- common.opt  (revision 173635)
>>> +++ common.opt  (working copy)
>>> @@ -1018,6 +1018,14 @@ fdiagnostics-show-option
>>>  Common Var(flag_diagnostics_show_option) Init(1)
>>>  Amend appropriate diagnostic messages with the command line option that controls them
>>>
>>> +fdisable-
>>> +Common Joined RejectNegative Var(common_deferred_options) Defer
>>> +-fdisable-[tree|rtl|ipa]-<pass>=range1+range2 disables an optimization pass
>>> +
>>> +fenable-
>>> +Common Joined RejectNegative Var(common_deferred_options) Defer
>>> +-fenable-[tree|rtl|ipa]-<pass>=range1+range2 enables an optimization pass
>>> +
>>>  fdump-
>>>  Common Joined RejectNegative Var(common_deferred_options) Defer
>>>  -fdump-<type>  Dump various compiler internals to a file
>>> Index: opts-global.c
>>> ===================================================================
>>> --- opts-global.c       (revision 173635)
>>> +++ opts-global.c       (working copy)
>>> @@ -411,6 +411,12 @@ handle_common_deferred_options (void)
>>>            error ("unrecognized command line option %<-fdump-%s%>", opt->arg);
>>>          break;
>>>
>>> +       case OPT_fenable_:
>>> +       case OPT_fdisable_:
>>> +         enable_disable_pass (opt->arg, (opt->opt_index == OPT_fenable_?
>>> +                              true : false));
>>> +          break;
>>> +
>>>        case OPT_ffixed_:
>>>          /* Deferred.  */
>>>          fix_register (opt->arg, 1, 1);
>>> Index: tree-cfg.c
>>> ===================================================================
>>> --- tree-cfg.c  (revision 173636)
>>> +++ tree-cfg.c  (working copy)
>>> @@ -2090,11 +2090,7 @@ gimple_dump_cfg (FILE *file, int flags)
>>>  {
>>>   if (flags & TDF_DETAILS)
>>>     {
>>> -      const char *funcname
>>> -       = lang_hooks.decl_printable_name (current_function_decl, 2);
>>> -
>>> -      fputc ('\n', file);
>>> -      fprintf (file, ";; Function %s\n\n", funcname);
>>> +      pass_dump_function_header (file, current_function_decl, cfun);
>>>       fprintf (file, ";; \n%d basic blocks, %d edges, last basic block %d.\n\n",
>>>               n_basic_blocks, n_edges, last_basic_block);
>>>
>>> Index: passes.c
>>> ===================================================================
>>> --- passes.c    (revision 173635)
>>> +++ passes.c    (working copy)
>>> @@ -382,7 +382,7 @@ void
>>>  register_one_dump_file (struct opt_pass *pass)
>>>  {
>>>   char *dot_name, *flag_name, *glob_name;
>>> -  const char *name, *prefix;
>>> +  const char *name, *full_name, *prefix;
>>>   char num[10];
>>>   int flags, id;
>>>
>>> @@ -411,6 +411,8 @@ register_one_dump_file (struct opt_pass
>>>   glob_name = concat (prefix, name, NULL);
>>>   id = dump_register (dot_name, flag_name, glob_name, flags);
>>>   set_pass_for_id (id, pass);
>>> +  full_name = concat (prefix, pass->name, num, NULL);
>>> +  register_pass_name (pass, full_name);
>>>  }
>>>
>>>  /* Recursive worker function for register_dump_files.  */
>>> @@ -454,6 +456,298 @@ register_dump_files (struct opt_pass *pa
>>>   register_dump_files_1 (pass, properties);
>>>  }
>>>
>>> +struct pass_registry
>>> +{
>>> +  const char* unique_name;
>>> +  struct opt_pass *pass;
>>> +};
>>> +
>>> +/* Pass registry hash function.  */
>>> +
>>> +static hashval_t
>>> +passr_hash (const void *p)
>>> +{
>>> +  const struct pass_registry *const s = (const struct pass_registry *const) p;
>>> +  return htab_hash_string (s->unique_name);
>>> +}
>>> +
>>> +/* Hash equal function  */
>>> +
>>> +static int
>>> +passr_eq (const void *p1, const void *p2)
>>> +{
>>> +  const struct pass_registry *const s1 = (const struct pass_registry *const) p1;
>>> +  const struct pass_registry *const s2 = (const struct pass_registry *const) p2;
>>> +
>>> +  return !strcmp (s1->unique_name, s2->unique_name);
>>> +}
>>> +
>>> +static htab_t pass_name_tab = NULL;
>>> +
>>> +/* Register PASS with NAME.  */
>>> +
>>> +void
>>> +register_pass_name (struct opt_pass *pass, const char *name)
>>> +{
>>> +  struct pass_registry **slot;
>>> +  struct pass_registry pr;
>>> +
>>> +  if (!pass_name_tab)
>>> +    pass_name_tab = htab_create (10, passr_hash, passr_eq, NULL);
>>> +
>>> +  pr.unique_name = name;
>>> +  slot = (struct pass_registry **) htab_find_slot (pass_name_tab, &pr, INSERT);
>>> +  if (!*slot)
>>> +    {
>>> +      struct pass_registry *new_pr;
>>> +
>>> +      new_pr = XCNEW (struct pass_registry);
>>> +      new_pr->unique_name = xstrdup (name);
>>> +      new_pr->pass = pass;
>>> +      *slot = new_pr;
>>> +    }
>>> +  else
>>> +    gcc_assert ((*slot)->pass == pass);
>>> +}
>>> +
>>> +/* Returns the pass with NAME.  */
>>> +
>>> +struct opt_pass *
>>> +get_pass_by_name (const char *name)
>>> +{
>>> +  struct pass_registry **slot, pr;
>>> +
>>> +  gcc_assert (pass_name_tab);
>>> +  pr.unique_name = name;
>>> +  slot = (struct pass_registry **) htab_find_slot (pass_name_tab, &pr, NO_INSERT);
>>> +
>>> +  if (!slot || !*slot)
>>> +    return NULL;
>>> +
>>> +  return (*slot)->pass;
>>> +}
>>> +
>>> +
>>> +/* Range [start, last].  */
>>> +
>>> +struct uid_range
>>> +{
>>> +  struct opt_pass *pass;
>>> +  unsigned int start;
>>> +  unsigned int last;
>>> +  struct uid_range *next;
>>> +};
>>> +
>>> +/* Hash function for pass structure.  */
>>> +
>>> +static hashval_t
>>> +pass_hash (const void *s)
>>> +{
>>> +  const struct uid_range *const p = (const struct uid_range *const) s;
>>> +  return p->pass->static_pass_number;
>>> +}
>>> +
>>> +/* Pass equal function  */
>>> +
>>> +static int
>>> +pass_eq (const void *s1, const void *s2)
>>> +{
>>> +  const struct uid_range *const p1 = (const struct uid_range *const) s1;
>>> +  const struct uid_range *const p2 = (const struct uid_range *const) s2;
>>> +  return p1->pass->static_pass_number == p2->pass->static_pass_number;
>>> +}
>>> +
>>> +htab_t enabled_pass_uid_range_tab = NULL;
>>> +htab_t disabled_pass_uid_range_tab = NULL;
>>> +
>>> +/* Parse option string for -fdisable- and -fenabler-
>>> +   The syntax of the options:
>>> +
>>> +   -fenable-<pass_name>
>>> +   -fdisable-<pass_name>
>>> +
>>> +   -fenable-<pass_name>=s1:e1,s2:e2,...
>>> +   -fdisable-<pass_name>=s1:e1,s2:e2,...
>>> +*/
>>> +
>>> +void
>>> +enable_disable_pass (const char *arg, bool is_enable)
>>> +{
>>> +  struct opt_pass *pass;
>>> +  htab_t the_tab;
>>> +  char *range_str, *phase_name;
>>> +  char *argstr = xstrdup (arg);
>>> +
>>> +  range_str = strchr (argstr,'=');
>>> +  if (range_str)
>>> +    {
>>> +      *range_str = '\0';
>>> +      range_str++;
>>> +    }
>>> +
>>> +  phase_name = argstr;
>>> +  if (!*phase_name)
>>> +    {
>>> +      error ("Unrecognized option %s", is_enable ? "-fenable" : "-fdisable");
>>> +      free (argstr);
>>> +      return;
>>> +    }
>>> +  pass = get_pass_by_name (phase_name);
>>> +  if (!pass)
>>> +    {
>>> +      error ("Unknown pass %s specified in %s",
>>> +            phase_name,
>>> +            is_enable ? "-fenable" : "-fdisable");
>>> +      free (argstr);
>>> +      return;
>>> +    }
>>> +  if (is_enable)
>>> +    {
>>> +      if (!enabled_pass_uid_range_tab)
>>> +       enabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
>>> +      the_tab = enabled_pass_uid_range_tab;
>>> +    }
>>> +  else
>>> +    {
>>> +      if (!disabled_pass_uid_range_tab)
>>> +       disabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
>>> +      the_tab = disabled_pass_uid_range_tab;
>>> +    }
>>> +
>>> +  if (!range_str)
>>> +    {
>>> +      struct uid_range **slot;
>>> +      struct uid_range *new_range = XCNEW (struct uid_range);
>>> +
>>> +      new_range->pass = pass;
>>> +      new_range->start = 0;
>>> +      new_range->last = (unsigned)-1;
>>> +
>>> +      slot = (struct uid_range **) htab_find_slot (the_tab, new_range, INSERT);
>>> +      new_range->next = *slot;
>>> +      *slot = new_range;
>>> +      inform (UNKNOWN_LOCATION, "%s pass %s for functions in the range of [%u, %u]\n",
>>> +              is_enable? "Enable":"Disable", phase_name, new_range->start, new_range->last);
>>> +    }
>>> +  else
>>> +    {
>>> +      char *next_range = NULL;
>>> +      char *one_range = range_str;
>>> +      char *end_val = NULL;
>>> +
>>> +      do
>>> +       {
>>> +         struct uid_range **slot;
>>> +         struct uid_range *new_range;
>>> +         char *invalid = NULL;
>>> +         long start;
>>> +
>>> +         next_range = strchr (one_range, ',');
>>> +         if (next_range)
>>> +           {
>>> +             *next_range = '\0';
>>> +             next_range++;
>>> +           }
>>> +
>>> +         end_val = strchr (one_range, ':');
>>> +         if (end_val)
>>> +           {
>>> +             *end_val = '\0';
>>> +             end_val++;
>>> +           }
>>> +         start = strtol (one_range, &invalid, 10);
>>> +         if (*invalid || start < 0)
>>> +           {
>>> +             error ("Invalid range %s in option %s",
>>> +                    one_range,
>>> +                    is_enable ? "-fenable" : "-fdisable");
>>> +             free (argstr);
>>> +             return;
>>> +           }
>>> +         if (!end_val)
>>> +           {
>>> +             new_range = XCNEW (struct uid_range);
>>> +              new_range->pass = pass;
>>> +             new_range->start = (unsigned) start;
>>> +             new_range->last = (unsigned) start;
>>> +           }
>>> +         else
>>> +           {
>>> +             long last = strtol (end_val, &invalid, 10);
>>> +             if (*invalid || last < start)
>>> +               {
>>> +                 error ("Invalid range %s in option %s",
>>> +                        end_val,
>>> +                        is_enable ? "-fenable" : "-fdisable");
>>> +                 free (argstr);
>>> +                 return;
>>> +               }
>>> +             new_range = XCNEW (struct uid_range);
>>> +              new_range->pass = pass;
>>> +             new_range->start = (unsigned) start;
>>> +             new_range->last = (unsigned) last;
>>> +           }
>>> +         slot = (struct uid_range **) htab_find_slot (the_tab, new_range, INSERT);
>>> +         new_range->next = *slot;
>>> +         *slot = new_range;
>>> +          inform (UNKNOWN_LOCATION, "%s pass %s for functions in the range of [%u, %u]\n",
>>> +                  is_enable? "Enable":"Disable", phase_name, new_range->start, new_range->last);
>>> +
>>> +         one_range = next_range;
>>> +       } while (next_range);
>>> +    }
>>> +
>>> +  free (argstr);
>>> +}
>>> +
>>> +/* Returns true if PASS is explicitly enabled/disabled for FUNC.  */
>>> +
>>> +static bool
>>> +is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
>>> +                                       tree func, htab_t tab)
>>> +{
>>> +  struct uid_range **slot, *range, key;
>>> +  int cgraph_uid;
>>> +
>>> +  if (!tab)
>>> +    return false;
>>> +
>>> +  key.pass = pass;
>>> +  slot = (struct uid_range **) htab_find_slot (tab, &key, NO_INSERT);
>>> +  if (!slot || !*slot)
>>> +    return false;
>>> +
>>> +  cgraph_uid = func ? cgraph_node (func)->uid : 0;
>>> +
>>> +  range = *slot;
>>> +  while (range)
>>> +    {
>>> +      if ((unsigned) cgraph_uid >= range->start
>>> +         && (unsigned) cgraph_uid <= range->last)
>>> +       return true;
>>> +      range = range->next;
>>> +    }
>>> +
>>> +  return false;
>>> +}
>>> +
>>> +/* Returns true if PASS is explicitly enabled for FUNC.  */
>>> +
>>> +bool
>>> +is_pass_explicitly_enabled (struct opt_pass *pass, tree func)
>>> +{
>>> +  return is_pass_explicitly_enabled_or_disabled (pass, func, enabled_pass_uid_range_tab);
>>> +}
>>> +
>>> +/* Returns true if PASS is explicitly disabled for FUNC.  */
>>> +
>>> +bool
>>> +is_pass_explicitly_disabled (struct opt_pass *pass, tree func)
>>> +{
>>> +  return is_pass_explicitly_enabled_or_disabled (pass, func, disabled_pass_uid_range_tab);
>>> +}
>>> +
>>> +
>>>  /* Look at the static_pass_number and duplicate the pass
>>>    if it is already added to a list. */
>>>
>>> @@ -1349,6 +1643,29 @@ verify_curr_properties (void *data)
>>>  }
>>>  #endif
>>>
>>> +void
>>> +pass_dump_function_header (FILE *dump_file, tree fdecl, struct function *fun)
>>> +{
>>> +  const char *dname, *aname;
>>> +  struct cgraph_node *node = cgraph_node (fdecl);
>>> +  dname = lang_hooks.decl_printable_name (fdecl, 2);
>>> +  aname = (IDENTIFIER_POINTER
>>> +          (DECL_ASSEMBLER_NAME (fdecl)));
>>> +  if (L_IPO_COMP_MODE)
>>> +    fprintf (dump_file, "\n;; Function %s (%s)[%d:%d][uid=%d]", dname, aname,
>>> +            FUNC_DECL_MODULE_ID (fun), FUNC_DECL_FUNC_ID (fun), node->uid);
>>> +  else
>>> +    fprintf (dump_file, "\n;; Function %s (%s)[uid=%d]", dname, aname, node->uid);
>>> +  fprintf (dump_file, "%s\n\n",
>>> +           node->frequency == NODE_FREQUENCY_HOT
>>> +           ? " (hot)"
>>> +           : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
>>> +           ? " (unlikely executed)"
>>> +           : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
>>> +           ? " (executed once)"
>>> +           : "");
>>> +}
>>> +
>>>  /* Initialize pass dump file.  */
>>>  /* This is non-static so that the plugins can use it.  */
>>>
>>> @@ -1362,26 +1679,7 @@ pass_init_dump_file (struct opt_pass *pa
>>>       dump_file_name = get_dump_file_name (pass->static_pass_number);
>>>       dump_file = dump_begin (pass->static_pass_number, &dump_flags);
>>>       if (dump_file && current_function_decl)
>>> -       {
>>> -         const char *dname, *aname;
>>> -         struct cgraph_node *node = cgraph_node (current_function_decl);
>>> -         dname = lang_hooks.decl_printable_name (current_function_decl, 2);
>>> -         aname = (IDENTIFIER_POINTER
>>> -                  (DECL_ASSEMBLER_NAME (current_function_decl)));
>>> -         if (L_IPO_COMP_MODE)
>>> -           fprintf (dump_file, "\n;; Function %s (%s)[%d:%d]", dname, aname,
>>> -                    FUNC_DECL_MODULE_ID (cfun), FUNC_DECL_FUNC_ID (cfun));
>>> -         else
>>> -           fprintf (dump_file, "\n;; Function %s (%s)", dname, aname);
>>> -         fprintf (dump_file, "%s\n\n",
>>> -            node->frequency == NODE_FREQUENCY_HOT
>>> -            ? " (hot)"
>>> -            : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
>>> -            ? " (unlikely executed)"
>>> -            : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
>>> -            ? " (executed once)"
>>> -            : "");
>>> -       }
>>> +        pass_dump_function_header (dump_file, current_function_decl, cfun);
>>>       return initializing_dump;
>>>     }
>>>   else
>>> @@ -1525,6 +1823,8 @@ execute_one_pass (struct opt_pass *pass)
>>>  {
>>>   bool initializing_dump;
>>>   unsigned int todo_after = 0;
>>> +  bool explicitly_enabled = false;
>>> +  bool explicitly_disabled = false;
>>>
>>>   bool gate_status;
>>>
>>> @@ -1535,11 +1835,15 @@ execute_one_pass (struct opt_pass *pass)
>>>   else
>>>     gcc_assert (cfun && current_function_decl);
>>>
>>> +  explicitly_enabled = is_pass_explicitly_enabled (pass, current_function_decl);
>>> +  explicitly_disabled = is_pass_explicitly_disabled (pass, current_function_decl);
>>> +
>>>   current_pass = pass;
>>>
>>>   /* 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();
>>> +  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
>>>
>>>   /* Override gate with plugin.  */
>>>   invoke_plugin_callbacks (PLUGIN_OVERRIDE_GATE, &gate_status);
>>>
>>> --
>>> This patch is available for review at http://codereview.appspot.com/4550056
>>>
>>
>

[-- Attachment #2: pass_option4.p --]
[-- Type: text/x-pascal, Size: 20685 bytes --]

Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(revision 173837)
+++ doc/invoke.texi	(working copy)
@@ -282,6 +282,11 @@ Objective-C and Objective-C++ Dialects}.
 @xref{Debugging Options,,Options for Debugging Your Program or GCC}.
 @gccoptlist{-d@var{letters}  -dumpspecs  -dumpmachine  -dumpversion @gol
 -fdbg-cnt-list -fdbg-cnt=@var{counter-value-list} @gol
+-fdisable-ipa-@var{pass_name} @gol
+-fdisable-rtl-@var{pass_name} @gol
+-fdisable-rtl-@var{pass-name}=@var{range-list} @gol
+-fdisable-tree-@var{pass_name} @gol
+-fdisable-tree-@var{pass-name}=@var{range-list} @gol
 -fdump-noaddr -fdump-unnumbered -fdump-unnumbered-links @gol
 -fdump-translation-unit@r{[}-@var{n}@r{]} @gol
 -fdump-class-hierarchy@r{[}-@var{n}@r{]} @gol
@@ -313,6 +318,10 @@ Objective-C and Objective-C++ Dialects}.
 -fcompare-debug@r{[}=@var{opts}@r{]}  -fcompare-debug-second @gol
 -feliminate-dwarf2-dups -feliminate-unused-debug-types @gol
 -feliminate-unused-debug-symbols -femit-class-debug-always @gol
+-fenable-ipa-@var{pass} @gol
+-fenable-rtl-@var{pass} @gol
+-fenable-rtl-@var{pass}=@var{range-list} @gol
+-fenable-tree-@var{pass} @gol
 -fdebug-types-section @gol
 -fmem-report -fpre-ipa-mem-report -fpost-ipa-mem-report -fprofile-arcs @gol
 -frandom-seed=@var{string} -fsched-verbose=@var{n} @gol
@@ -4993,7 +5002,36 @@ All debug counters have the initial uppe
 thus dbg_cnt() returns true always unless the upper bound is set by this option.
 e.g. With -fdbg-cnt=dce:10,tail_call:0
 dbg_cnt(dce) will return true only for first 10 invocations
-and dbg_cnt(tail_call) will return false always.
+
+@item -fdisable-ipa-@var{pass}
+@opindex fdisable-ipa
+Disable ipa pass @var{pass}. @var{pass} is the pass name. If the same pass is statically invoked in the compiler multiple times, the pass name should be appended with a sequential number starting from 1.
+
+@item -fdisable-rtl-@var{pass}
+@itemx -fdisable-rtl-@var{pass}=@var{range-list} 
+@opindex fdisable-rtl
+Disable rtl pass @var{pass}. @var{pass} is the pass name. If the same pass is statically invoked in the compiler multiple times, the pass name should be appended with a sequential number starting from 1. @var{range-list} is a comma seperated list of function ranges. Each range is a number pair seperated by a colon. The range is inclusive in both ends. If the range is trivial, the number pair can be simplified a a single number. If the function's cgraph node's @var{uid} is falling within one of the specified ranges, the @var{pass} is disabled for that function. The @var{uid} is shown in the function header of a dump file.
+
+@item -fdisable-tree-@var{pass}
+@itemx -fdisable-tree-@var{pass}=@var{range-list} 
+@opindex fdisable-tree
+Disable tree pass @var{pass}. See @option{-fdisable-rtl} for the description of option arguments.
+
+@smallexample
+
+# disable ccp1 for all functions
+   -fdisable-tree-ccp1 
+# disable complete unroll for function whose cgraph node uid is 1
+   -fenable-tree-cunroll=1   
+# disable gcse2 for functions at the following ranges [1,1],
+# [300,400], and [400,1000]                          
+   -fdisable-rtl-gcse2=1:100,300,400:1000 
+# disable early inlining
+   -fdisable-tree-einline
+# disable ipa inlining
+   -fdisable-ipa-inline 
+
+@end smallexample
 
 @item -d@var{letters}
 @itemx -fdump-rtl-@var{pass}
@@ -5583,6 +5621,20 @@ is made by appending @file{.vrp} to the 
 Enable all the available tree dumps with the flags provided in this option.
 @end table
 
+@item -fenable-ipa-@var{pass}
+@opindex fenable-ipa
+Enable ipa pass @var{pass}. @var{pass} is the pass name. If the same pass is statically invoked in the compiler multiple times, the pass name should be appended with a sequential number starting from 1.
+
+@item -fenable-rtl-@var{pass}
+@itemx -fenable-rtl-@var{pass}=@var{range-list} 
+@opindex fenable-rtl
+Enable rtl pass @var{pass}. See @option{-fdisable-rtl} for option argument description and examples.
+
+@item -fenable-tree-@var{pass}
+@itemx -fenable-tree-@var{pass}=@var{range-list} 
+@opindex fenable-tree
+Enable tree pass @var{pass}. See @option{-fdisable-rtl} for the description of option arguments and examples.
+
 @item -ftree-vectorizer-verbose=@var{n}
 @opindex ftree-vectorizer-verbose
 This option controls the amount of debugging output the vectorizer prints.
Index: tree-pass.h
===================================================================
--- tree-pass.h	(revision 173837)
+++ tree-pass.h	(working copy)
@@ -637,4 +637,12 @@ extern bool first_pass_instance;
 /* Declare for plugins.  */
 extern void do_per_function_toporder (void (*) (void *), void *);
 
+extern void enable_disable_pass (const char *, bool);
+extern bool is_pass_explicitly_disabled (struct opt_pass *, tree);
+extern bool is_pass_explicitly_enabled (struct opt_pass *, tree);
+extern void register_pass_name (struct opt_pass *, const char *);
+extern struct opt_pass *get_pass_by_name (const char *);
+struct function;
+extern void pass_dump_function_header (FILE *, tree, struct function *);
+
 #endif /* GCC_TREE_PASS_H */
Index: final.c
===================================================================
--- final.c	(revision 173837)
+++ final.c	(working copy)
@@ -4360,20 +4360,7 @@ rest_of_clean_state (void)
 	}
       else
 	{
-	  const char *aname;
-	  struct cgraph_node *node = cgraph_get_node (current_function_decl);
-
-	  aname = (IDENTIFIER_POINTER
-		   (DECL_ASSEMBLER_NAME (current_function_decl)));
-	  fprintf (final_output, "\n;; Function (%s) %s\n\n", aname,
-	     node->frequency == NODE_FREQUENCY_HOT
-	     ? " (hot)"
-	     : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
-	     ? " (unlikely executed)"
-	     : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
-	     ? " (executed once)"
-	     : "");
-
+	  pass_dump_function_header (final_output, current_function_decl, cfun);
 	  flag_dump_noaddr = flag_dump_unnumbered = 1;
 	  if (flag_compare_debug_opt || flag_compare_debug)
 	    dump_flags |= TDF_NOUID;
Index: tree-ssa-loop-ivopts.c
===================================================================
--- tree-ssa-loop-ivopts.c	(revision 173837)
+++ tree-ssa-loop-ivopts.c	(working copy)
@@ -3968,7 +3968,7 @@ get_computation_cost_at (struct ivopts_d
                          int *inv_expr_id)
 {
   tree ubase = use->iv->base, ustep = use->iv->step;
-  tree cbase, cstep;
+  tree cbase, cstep, cbase_strip;
   tree utype = TREE_TYPE (ubase), ctype;
   unsigned HOST_WIDE_INT cstepi, offset = 0;
   HOST_WIDE_INT ratio, aratio;
@@ -4026,6 +4026,13 @@ get_computation_cost_at (struct ivopts_d
   if (!constant_multiple_of (ustep, cstep, &rat))
     return infinite_cost;
 
+  cbase_strip = STRIP_NOPS (cbase);
+  /* Avoid confusing aliaser.  */
+  if (TREE_CODE (cbase_strip) == ADDR_EXPR
+      && TREE_CODE (TREE_OPERAND (cbase_strip, 0)) == VAR_DECL
+      && (HOST_WIDE_INT) cstepi < 0)
+    return infinite_cost;
+
   if (double_int_fits_in_shwi_p (rat))
     ratio = double_int_to_shwi (rat);
   else
Index: common.opt
===================================================================
--- common.opt	(revision 173837)
+++ common.opt	(working copy)
@@ -974,6 +974,14 @@ fdiagnostics-show-option
 Common Var(flag_diagnostics_show_option) Init(1)
 Amend appropriate diagnostic messages with the command line option that controls them
 
+fdisable-
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fdisable-[tree|rtl|ipa]-<pass>=range1+range2 disables an optimization pass
+
+fenable-
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fenable-[tree|rtl|ipa]-<pass>=range1+range2 enables an optimization pass
+
 fdump-
 Common Joined RejectNegative Var(common_deferred_options) Defer
 -fdump-<type>	Dump various compiler internals to a file
Index: opts-global.c
===================================================================
--- opts-global.c	(revision 173837)
+++ opts-global.c	(working copy)
@@ -370,6 +370,12 @@ handle_common_deferred_options (void)
 	    error ("unrecognized command line option %<-fdump-%s%>", opt->arg);
 	  break;
 
+	case OPT_fenable_:
+	case OPT_fdisable_:
+	  enable_disable_pass (opt->arg, (opt->opt_index == OPT_fenable_?
+	                       true : false));
+          break;
+
 	case OPT_ffixed_:
 	  /* Deferred.  */
 	  fix_register (opt->arg, 1, 1);
Index: tree-cfg.c
===================================================================
--- tree-cfg.c	(revision 173837)
+++ tree-cfg.c	(working copy)
@@ -2052,11 +2052,7 @@ gimple_dump_cfg (FILE *file, int flags)
 {
   if (flags & TDF_DETAILS)
     {
-      const char *funcname
-	= lang_hooks.decl_printable_name (current_function_decl, 2);
-
-      fputc ('\n', file);
-      fprintf (file, ";; Function %s\n\n", funcname);
+      pass_dump_function_header (file, current_function_decl, cfun);
       fprintf (file, ";; \n%d basic blocks, %d edges, last basic block %d.\n\n",
 	       n_basic_blocks, n_edges, last_basic_block);
 
Index: passes.c
===================================================================
--- passes.c	(revision 173837)
+++ passes.c	(working copy)
@@ -375,7 +375,7 @@ void
 register_one_dump_file (struct opt_pass *pass)
 {
   char *dot_name, *flag_name, *glob_name;
-  const char *name, *prefix;
+  const char *name, *full_name, *prefix;
   char num[10];
   int flags, id;
 
@@ -404,6 +404,8 @@ register_one_dump_file (struct opt_pass 
   glob_name = concat (prefix, name, NULL);
   id = dump_register (dot_name, flag_name, glob_name, flags);
   set_pass_for_id (id, pass);
+  full_name = concat (prefix, pass->name, num, NULL);
+  register_pass_name (pass, full_name);
 }
 
 /* Recursive worker function for register_dump_files.  */
@@ -447,6 +449,317 @@ register_dump_files (struct opt_pass *pa
   register_dump_files_1 (pass, properties);
 }
 
+struct pass_registry
+{
+  const char* unique_name;
+  struct opt_pass *pass;
+};
+
+/* Pass registry hash function.  */
+
+static hashval_t
+passr_hash (const void *p)
+{
+  const struct pass_registry *const s = (const struct pass_registry *const) p;
+  return htab_hash_string (s->unique_name);
+}
+
+/* Hash equal function  */
+
+static int
+passr_eq (const void *p1, const void *p2)
+{
+  const struct pass_registry *const s1 = (const struct pass_registry *const) p1;
+  const struct pass_registry *const s2 = (const struct pass_registry *const) p2;
+
+  return !strcmp (s1->unique_name, s2->unique_name);
+}
+
+static htab_t pass_name_tab = NULL;
+
+/* Register PASS with NAME.  */
+
+void
+register_pass_name (struct opt_pass *pass, const char *name)
+{
+  struct pass_registry **slot;
+  struct pass_registry pr;
+
+  if (!pass_name_tab)
+    pass_name_tab = htab_create (10, passr_hash, passr_eq, NULL);
+
+  pr.unique_name = name;
+  slot = (struct pass_registry **) htab_find_slot (pass_name_tab, &pr, INSERT);
+  if (!*slot)
+    {
+      struct pass_registry *new_pr;
+
+      new_pr = XCNEW (struct pass_registry);
+      new_pr->unique_name = xstrdup (name);
+      new_pr->pass = pass;
+      *slot = new_pr;
+    }
+  else
+    return; /* Ignore plugin passes.  */
+}
+
+/* Returns the pass with NAME.  */
+
+struct opt_pass *
+get_pass_by_name (const char *name)
+{
+  struct pass_registry **slot, pr;
+
+  gcc_assert (pass_name_tab);
+  pr.unique_name = name;
+  slot = (struct pass_registry **) htab_find_slot (pass_name_tab,
+                                                   &pr, NO_INSERT);
+
+  if (!slot || !*slot)
+    return NULL;
+
+  return (*slot)->pass;
+}
+
+
+/* Range [start, last].  */
+
+struct uid_range
+{
+  struct opt_pass *pass;
+  unsigned int start;
+  unsigned int last;
+  struct uid_range *next;
+};
+
+/* Hash function for pass structure.  */
+
+static hashval_t
+pass_hash (const void *s)
+{
+  const struct uid_range *const p = (const struct uid_range *const) s;
+  return p->pass->static_pass_number;
+}
+
+/* Pass equal function  */
+
+static int
+pass_eq (const void *s1, const void *s2)
+{
+  const struct uid_range *const p1 = (const struct uid_range *const) s1;
+  const struct uid_range *const p2 = (const struct uid_range *const) s2;
+  return p1->pass->static_pass_number == p2->pass->static_pass_number;
+}
+
+htab_t enabled_pass_uid_range_tab = NULL;
+htab_t disabled_pass_uid_range_tab = NULL;
+
+/* Parse option string for -fdisable- and -fenable-
+   The syntax of the options:
+
+   -fenable-<pass_name>
+   -fdisable-<pass_name>
+
+   -fenable-<pass_name>=s1:e1,s2:e2,...
+   -fdisable-<pass_name>=s1:e1,s2:e2,...
+*/
+
+void
+enable_disable_pass (const char *arg, bool is_enable)
+{
+  struct opt_pass *pass;
+  htab_t the_tab;
+  char *range_str, *phase_name;
+  char *argstr = xstrdup (arg);
+
+  range_str = strchr (argstr,'=');
+  if (range_str)
+    {
+      *range_str = '\0';
+      range_str++;
+    }
+
+  phase_name = argstr;
+  if (!*phase_name)
+    {
+      if (is_enable)
+        error ("unrecognized option -fenable");
+      else
+        error ("unrecognized option -fdisable");
+      free (argstr);
+      return;
+    }
+  pass = get_pass_by_name (phase_name);
+  if (!pass)
+    {
+      if (is_enable)
+        error ("unknown pass %s specified in -fenable", phase_name);
+      else
+        error ("unknown pass %s specified in -fdisble", phase_name);
+      free (argstr);
+      return;
+    }
+  if (is_enable)
+    {
+      if (!enabled_pass_uid_range_tab)
+	enabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
+      the_tab = enabled_pass_uid_range_tab;
+    }
+  else
+    {
+      if (!disabled_pass_uid_range_tab)
+	disabled_pass_uid_range_tab = htab_create (10, pass_hash,
+                                                   pass_eq, NULL);
+      the_tab = disabled_pass_uid_range_tab;
+    }
+
+  if (!range_str)
+    {
+      struct uid_range **slot;
+      struct uid_range *new_range = XCNEW (struct uid_range);
+
+      new_range->pass = pass;
+      new_range->start = 0;
+      new_range->last = (unsigned)-1;
+
+      slot = (struct uid_range **) htab_find_slot (the_tab, new_range, INSERT);
+      new_range->next = *slot;
+      *slot = new_range;
+      if (is_enable)
+        inform (UNKNOWN_LOCATION, "enable pass %s for functions in the range "
+                "of [%u, %u]", phase_name, new_range->start, new_range->last);
+      else
+        inform (UNKNOWN_LOCATION, "disable pass %s for functions in the range "
+                "of [%u, %u]", phase_name, new_range->start, new_range->last);
+    }
+  else
+    {
+      char *next_range = NULL;
+      char *one_range = range_str;
+      char *end_val = NULL;
+
+      do
+	{
+	  struct uid_range **slot;
+	  struct uid_range *new_range;
+	  char *invalid = NULL;
+	  long start;
+
+	  next_range = strchr (one_range, ',');
+	  if (next_range)
+	    {
+	      *next_range = '\0';
+	      next_range++;
+	    }
+
+	  end_val = strchr (one_range, ':');
+	  if (end_val)
+	    {
+	      *end_val = '\0';
+	      end_val++;
+	    }
+	  start = strtol (one_range, &invalid, 10);
+	  if (*invalid || start < 0)
+	    {
+	      error ("Invalid range %s in option %s",
+		     one_range,
+		     is_enable ? "-fenable" : "-fdisable");
+	      free (argstr);
+	      return;
+	    }
+	  if (!end_val)
+	    {
+	      new_range = XCNEW (struct uid_range);
+              new_range->pass = pass;
+	      new_range->start = (unsigned) start;
+	      new_range->last = (unsigned) start;
+	    }
+	  else
+	    {
+	      long last = strtol (end_val, &invalid, 10);
+	      if (*invalid || last < start)
+		{
+		  error ("Invalid range %s in option %s",
+			 end_val,
+			 is_enable ? "-fenable" : "-fdisable");
+		  free (argstr);
+		  return;
+		}
+	      new_range = XCNEW (struct uid_range);
+              new_range->pass = pass;
+	      new_range->start = (unsigned) start;
+	      new_range->last = (unsigned) last;
+	    }
+	  slot = (struct uid_range **) htab_find_slot (the_tab, new_range,
+                                                       INSERT);
+	  new_range->next = *slot;
+	  *slot = new_range;
+          if (is_enable)
+            inform (UNKNOWN_LOCATION,
+                    "enable pass %s for functions in the range of [%u, %u]",
+                    phase_name, new_range->start, new_range->last);
+          else
+            inform (UNKNOWN_LOCATION,
+                    "disable pass %s for functions in the range of [%u, %u]",
+                    phase_name, new_range->start, new_range->last);
+
+	  one_range = next_range;
+	} while (next_range);
+    }
+
+  free (argstr);
+}
+
+/* Returns true if PASS is explicitly enabled/disabled for FUNC.  */
+
+static bool
+is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
+					tree func, htab_t tab)
+{
+  struct uid_range **slot, *range, key;
+  int cgraph_uid;
+
+  if (!tab)
+    return false;
+
+  key.pass = pass;
+  slot = (struct uid_range **) htab_find_slot (tab, &key, NO_INSERT);
+  if (!slot || !*slot)
+    return false;
+
+  cgraph_uid = func ? cgraph_get_node (func)->uid : 0;
+
+  range = *slot;
+  while (range)
+    {
+      if ((unsigned) cgraph_uid >= range->start
+	  && (unsigned) cgraph_uid <= range->last)
+	return true;
+      range = range->next;
+    }
+
+  return false;
+}
+
+/* Returns true if PASS is explicitly enabled for FUNC.  */
+
+bool
+is_pass_explicitly_enabled (struct opt_pass *pass, tree func)
+{
+  return is_pass_explicitly_enabled_or_disabled (pass, func,
+                                                 enabled_pass_uid_range_tab);
+}
+
+/* Returns true if PASS is explicitly disabled for FUNC.  */
+
+bool
+is_pass_explicitly_disabled (struct opt_pass *pass, tree func)
+{
+  return is_pass_explicitly_enabled_or_disabled (pass, func,
+                                                 disabled_pass_uid_range_tab);
+}
+
+
 /* Look at the static_pass_number and duplicate the pass
    if it is already added to a list. */
 
@@ -1329,6 +1642,26 @@ verify_curr_properties (void *data)
 }
 #endif
 
+void
+pass_dump_function_header (FILE *dump_file, tree fdecl, struct function *fun)
+{
+  const char *dname, *aname;
+  struct cgraph_node *node = cgraph_get_node (fdecl);
+  dname = lang_hooks.decl_printable_name (fdecl, 2);
+  aname = (IDENTIFIER_POINTER
+	   (DECL_ASSEMBLER_NAME (fdecl)));
+  fprintf (dump_file, "\n;; Function %s (%s)[fundef_no:%d][uid=%d]",
+           dname, aname, fun->funcdef_no, node->uid);
+  fprintf (dump_file, "%s\n\n",
+           node->frequency == NODE_FREQUENCY_HOT
+           ? " (hot)"
+           : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
+           ? " (unlikely executed)"
+           : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
+           ? " (executed once)"
+           : "");
+}
+
 /* Initialize pass dump file.  */
 /* This is non-static so that the plugins can use it.  */
 
@@ -1342,21 +1675,7 @@ pass_init_dump_file (struct opt_pass *pa
       dump_file_name = get_dump_file_name (pass->static_pass_number);
       dump_file = dump_begin (pass->static_pass_number, &dump_flags);
       if (dump_file && current_function_decl)
-	{
-	  const char *dname, *aname;
-	  struct cgraph_node *node = cgraph_get_node (current_function_decl);
-	  dname = lang_hooks.decl_printable_name (current_function_decl, 2);
-	  aname = (IDENTIFIER_POINTER
-		   (DECL_ASSEMBLER_NAME (current_function_decl)));
-	  fprintf (dump_file, "\n;; Function %s (%s)%s\n\n", dname, aname,
-	     node->frequency == NODE_FREQUENCY_HOT
-	     ? " (hot)"
-	     : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
-	     ? " (unlikely executed)"
-	     : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
-	     ? " (executed once)"
-	     : "");
-	}
+      	pass_dump_function_header (dump_file, current_function_decl, cfun);
       return initializing_dump;
     }
   else
@@ -1500,6 +1819,8 @@ execute_one_pass (struct opt_pass *pass)
 {
   bool initializing_dump;
   unsigned int todo_after = 0;
+  bool explicitly_enabled = false;
+  bool explicitly_disabled = false;
 
   bool gate_status;
 
@@ -1510,11 +1831,15 @@ execute_one_pass (struct opt_pass *pass)
   else
     gcc_assert (cfun && current_function_decl);
 
+  explicitly_enabled = is_pass_explicitly_enabled (pass, current_function_decl);
+  explicitly_disabled = is_pass_explicitly_disabled (pass, current_function_decl);
+
   current_pass = pass;
 
   /* 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();
+  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
 
   /* Override gate with plugin.  */
   invoke_plugin_callbacks (PLUGIN_OVERRIDE_GATE, &gate_status);

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-18 19:49 New options to disable/enable any pass for any functions (issue4550056) David Li
  2011-05-18 20:21 ` Joseph S. Myers
  2011-05-18 21:01 ` Richard Guenther
@ 2011-05-19 19:23 ` Andi Kleen
  2011-05-19 19:33   ` Xinliang David Li
  2 siblings, 1 reply; 32+ messages in thread
From: Andi Kleen @ 2011-05-19 19:23 UTC (permalink / raw)
  To: David Li; +Cc: reply, gcc-patches

davidxl@google.com (David Li) writes:

> -fdisable-tree-ccp1    <--- disable ccp1 for all functions
> -fenable-tree-cunroll=1   <--- enable complete unroll for the function
>                            whose cgraphnode uid is 1
> -fdisable-rtl-gcse2=1:100,300,400:1000   <-- disable gcse2 for
>                                            functions at the following
>                                             ranges [1,1], [300,400],
> and [400,1000]

How are the ranges defined? I doubt numbers are a good interface here
to specify functions.

This would be better done with #pragmas? 

-Andi



-- 
ak@linux.intel.com -- Speaking for myself only

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-19 19:23 ` Andi Kleen
@ 2011-05-19 19:33   ` Xinliang David Li
  2011-05-19 20:25     ` Andi Kleen
  0 siblings, 1 reply; 32+ messages in thread
From: Xinliang David Li @ 2011-05-19 19:33 UTC (permalink / raw)
  To: Andi Kleen; +Cc: reply, gcc-patches

On Thu, May 19, 2011 at 11:04 AM, Andi Kleen <andi@firstfloor.org> wrote:
> davidxl@google.com (David Li) writes:
>
>> -fdisable-tree-ccp1    <--- disable ccp1 for all functions
>> -fenable-tree-cunroll=1   <--- enable complete unroll for the function
>>                            whose cgraphnode uid is 1
>> -fdisable-rtl-gcse2=1:100,300,400:1000   <-- disable gcse2 for
>>                                            functions at the following
>>                                             ranges [1,1], [300,400],
>> and [400,1000]
>
> How are the ranges defined? I doubt numbers are a good interface here
> to specify functions.

The numbers are cgraph uids for the functions. The form that takes the
range is mainly for developers who use scripts to auto search (bug
triaging and optimization space traverse).

>
> This would be better done with #pragmas?

This is not good for automation. However, I do plan (later after this
patch is in) to add another form of the option which takes a comma
separated list of assembler names --- this form will be quite useful
to workaround compiler bugs temporarily in the make file.

David

>
> -Andi
>
>
>
> --
> ak@linux.intel.com -- Speaking for myself only
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-19 19:33   ` Xinliang David Li
@ 2011-05-19 20:25     ` Andi Kleen
  2011-05-19 21:36       ` Xinliang David Li
  0 siblings, 1 reply; 32+ messages in thread
From: Andi Kleen @ 2011-05-19 20:25 UTC (permalink / raw)
  To: Xinliang David Li; +Cc: Andi Kleen, reply, gcc-patches

On Thu, May 19, 2011 at 11:10:24AM -0700, Xinliang David Li wrote:
> On Thu, May 19, 2011 at 11:04 AM, Andi Kleen <andi@firstfloor.org> wrote:
> > davidxl@google.com (David Li) writes:
> >
> >> -fdisable-tree-ccp1    <--- disable ccp1 for all functions
> >> -fenable-tree-cunroll=1   <--- enable complete unroll for the function
> >>                            whose cgraphnode uid is 1
> >> -fdisable-rtl-gcse2=1:100,300,400:1000   <-- disable gcse2 for
> >>                                            functions at the following
> >>                                             ranges [1,1], [300,400],
> >> and [400,1000]
> >
> > How are the ranges defined? I doubt numbers are a good interface here
> > to specify functions.
> 
> The numbers are cgraph uids for the functions. The form that takes the
> range is mainly for developers who use scripts to auto search (bug
> triaging and optimization space traverse).

How about function names?


> > This would be better done with #pragmas?
> 
> This is not good for automation. However, I do plan (later after this

Why not? It should be easy enough to write a script to add such
pragmas given a dwarf2 symbol->file:line dump

I think pragmas would be a lot more useful for non compiler developers.

-Andi

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-19 20:25     ` Andi Kleen
@ 2011-05-19 21:36       ` Xinliang David Li
  0 siblings, 0 replies; 32+ messages in thread
From: Xinliang David Li @ 2011-05-19 21:36 UTC (permalink / raw)
  To: Andi Kleen; +Cc: reply, gcc-patches

On Thu, May 19, 2011 at 11:17 AM, Andi Kleen <andi@firstfloor.org> wrote:
> On Thu, May 19, 2011 at 11:10:24AM -0700, Xinliang David Li wrote:
>> On Thu, May 19, 2011 at 11:04 AM, Andi Kleen <andi@firstfloor.org> wrote:
>> > davidxl@google.com (David Li) writes:
>> >
>> >> -fdisable-tree-ccp1    <--- disable ccp1 for all functions
>> >> -fenable-tree-cunroll=1   <--- enable complete unroll for the function
>> >>                            whose cgraphnode uid is 1
>> >> -fdisable-rtl-gcse2=1:100,300,400:1000   <-- disable gcse2 for
>> >>                                            functions at the following
>> >>                                             ranges [1,1], [300,400],
>> >> and [400,1000]
>> >
>> > How are the ranges defined? I doubt numbers are a good interface here
>> > to specify functions.
>>
>> The numbers are cgraph uids for the functions. The form that takes the
>> range is mainly for developers who use scripts to auto search (bug
>> triaging and optimization space traverse).
>
> How about function names?

Not so easy for things like binary search.

>
>
>> > This would be better done with #pragmas?
>>
>> This is not good for automation. However, I do plan (later after this
>
> Why not? It should be easy enough to write a script to add such
> pragmas given a dwarf2 symbol->file:line dump

This may require changes many many sources files as compared to a
simple command line tweak -- for most of the cases, you don't even
need to know the id ranges, and can be blindly set to a large initial
value.

>
> I think pragmas would be a lot more useful for non compiler developers.
>

As compared with the -fdisable-tree-xxx=func1,func2?

The semantics of the pragma is also in question -- does it apply to
all inline instances of the function with pragma or just the emitted
instance?

(The pragma scheme can be implemented independently if it is considered useful).

Thanks,

David


> -Andi
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-18 20:21 ` Joseph S. Myers
  2011-05-18 20:33   ` Xinliang David Li
@ 2011-05-20 16:44   ` Xinliang David Li
  2011-05-23  9:17     ` Xinliang David Li
  1 sibling, 1 reply; 32+ messages in thread
From: Xinliang David Li @ 2011-05-20 16:44 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: reply, GCC Patches

Ok to check in this one?

Thanks,

David

On Wed, May 18, 2011 at 12:30 PM, Joseph S. Myers
<joseph@codesourcery.com> wrote:
> On Wed, 18 May 2011, David Li wrote:
>
>> +      error ("Unrecognized option %s", is_enable ? "-fenable" : "-fdisable");
>
>> +      error ("Unknown pass %s specified in %s",
>> +          phase_name,
>> +          is_enable ? "-fenable" : "-fdisable");
>
> Follow GNU Coding Standards for diagnostics (start with lowercase letter).
>
>> +      inform (UNKNOWN_LOCATION, "%s pass %s for functions in the range of [%u, %u]\n",
>> +              is_enable? "Enable":"Disable", phase_name, new_range->start, new_range->last);
>
> Use separate calls to inform for the enable and disable cases, so that
> full sentences can be extracted for translation.
>
>> +           error ("Invalid range %s in option %s",
>> +                  one_range,
>> +                  is_enable ? "-fenable" : "-fdisable");
>
> GNU Coding Standards.
>
>> +               error ("Invalid range %s in option %s",
>
> Likewise.
>
>> +          inform (UNKNOWN_LOCATION, "%s pass %s for functions in the range of [%u, %u]\n",
>> +                  is_enable? "Enable":"Disable", phase_name, new_range->start, new_range->last);
>
> Again needs GCS and i18n fixes.
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-20 16:44   ` Xinliang David Li
@ 2011-05-23  9:17     ` Xinliang David Li
  2011-05-25 17:21       ` Xinliang David Li
  0 siblings, 1 reply; 32+ messages in thread
From: Xinliang David Li @ 2011-05-23  9:17 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: reply, GCC Patches

Ping.

David


On Fri, May 20, 2011 at 9:06 AM, Xinliang David Li <davidxl@google.com> wrote:
> Ok to check in this one?
>
> Thanks,
>
> David
>
> On Wed, May 18, 2011 at 12:30 PM, Joseph S. Myers
> <joseph@codesourcery.com> wrote:
>> On Wed, 18 May 2011, David Li wrote:
>>
>>> +      error ("Unrecognized option %s", is_enable ? "-fenable" : "-fdisable");
>>
>>> +      error ("Unknown pass %s specified in %s",
>>> +          phase_name,
>>> +          is_enable ? "-fenable" : "-fdisable");
>>
>> Follow GNU Coding Standards for diagnostics (start with lowercase letter).
>>
>>> +      inform (UNKNOWN_LOCATION, "%s pass %s for functions in the range of [%u, %u]\n",
>>> +              is_enable? "Enable":"Disable", phase_name, new_range->start, new_range->last);
>>
>> Use separate calls to inform for the enable and disable cases, so that
>> full sentences can be extracted for translation.
>>
>>> +           error ("Invalid range %s in option %s",
>>> +                  one_range,
>>> +                  is_enable ? "-fenable" : "-fdisable");
>>
>> GNU Coding Standards.
>>
>>> +               error ("Invalid range %s in option %s",
>>
>> Likewise.
>>
>>> +          inform (UNKNOWN_LOCATION, "%s pass %s for functions in the range of [%u, %u]\n",
>>> +                  is_enable? "Enable":"Disable", phase_name, new_range->start, new_range->last);
>>
>> Again needs GCS and i18n fixes.
>>
>> --
>> Joseph S. Myers
>> joseph@codesourcery.com
>>
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-23  9:17     ` Xinliang David Li
@ 2011-05-25 17:21       ` Xinliang David Li
  2011-05-25 17:44         ` Joseph S. Myers
  0 siblings, 1 reply; 32+ messages in thread
From: Xinliang David Li @ 2011-05-25 17:21 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: reply, GCC Patches

Ping. The link to the message:

http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01303.html

Thanks,

David

On Sun, May 22, 2011 at 4:17 PM, Xinliang David Li <davidxl@google.com> wrote:
> Ping.
>
> David
>
>
> On Fri, May 20, 2011 at 9:06 AM, Xinliang David Li <davidxl@google.com> wrote:
>> Ok to check in this one?
>>
>> Thanks,
>>
>> David
>>
>> On Wed, May 18, 2011 at 12:30 PM, Joseph S. Myers
>> <joseph@codesourcery.com> wrote:
>>> On Wed, 18 May 2011, David Li wrote:
>>>
>>>> +      error ("Unrecognized option %s", is_enable ? "-fenable" : "-fdisable");
>>>
>>>> +      error ("Unknown pass %s specified in %s",
>>>> +          phase_name,
>>>> +          is_enable ? "-fenable" : "-fdisable");
>>>
>>> Follow GNU Coding Standards for diagnostics (start with lowercase letter).
>>>
>>>> +      inform (UNKNOWN_LOCATION, "%s pass %s for functions in the range of [%u, %u]\n",
>>>> +              is_enable? "Enable":"Disable", phase_name, new_range->start, new_range->last);
>>>
>>> Use separate calls to inform for the enable and disable cases, so that
>>> full sentences can be extracted for translation.
>>>
>>>> +           error ("Invalid range %s in option %s",
>>>> +                  one_range,
>>>> +                  is_enable ? "-fenable" : "-fdisable");
>>>
>>> GNU Coding Standards.
>>>
>>>> +               error ("Invalid range %s in option %s",
>>>
>>> Likewise.
>>>
>>>> +          inform (UNKNOWN_LOCATION, "%s pass %s for functions in the range of [%u, %u]\n",
>>>> +                  is_enable? "Enable":"Disable", phase_name, new_range->start, new_range->last);
>>>
>>> Again needs GCS and i18n fixes.
>>>
>>> --
>>> Joseph S. Myers
>>> joseph@codesourcery.com
>>>
>>
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-25 17:21       ` Xinliang David Li
@ 2011-05-25 17:44         ` Joseph S. Myers
  2011-05-25 18:07           ` Xinliang David Li
  2011-05-26 10:20           ` Richard Guenther
  0 siblings, 2 replies; 32+ messages in thread
From: Joseph S. Myers @ 2011-05-25 17:44 UTC (permalink / raw)
  To: Xinliang David Li; +Cc: reply, GCC Patches

On Wed, 25 May 2011, Xinliang David Li wrote:

> Ping. The link to the message:
> 
> http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01303.html

I don't consider this an option handling patch.  Patches adding whole new 
features involving new options should be reviewed by maintainers for the 
part of the compiler relevant to those features (since there isn't a pass 
manager maintainer, I guess that means middle-end).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-25 17:44         ` Joseph S. Myers
@ 2011-05-25 18:07           ` Xinliang David Li
  2011-05-26 10:20           ` Richard Guenther
  1 sibling, 0 replies; 32+ messages in thread
From: Xinliang David Li @ 2011-05-25 18:07 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: reply, GCC Patches, Richard Guenther

Fair enough.  Richard?

Thanks,

David

On Wed, May 25, 2011 at 9:53 AM, Joseph S. Myers
<joseph@codesourcery.com> wrote:
> On Wed, 25 May 2011, Xinliang David Li wrote:
>
>> Ping. The link to the message:
>>
>> http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01303.html
>
> I don't consider this an option handling patch.  Patches adding whole new
> features involving new options should be reviewed by maintainers for the
> part of the compiler relevant to those features (since there isn't a pass
> manager maintainer, I guess that means middle-end).
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-25 17:44         ` Joseph S. Myers
  2011-05-25 18:07           ` Xinliang David Li
@ 2011-05-26 10:20           ` Richard Guenther
  2011-05-26 13:00             ` Joseph S. Myers
  2011-05-26 23:48             ` Xinliang David Li
  1 sibling, 2 replies; 32+ messages in thread
From: Richard Guenther @ 2011-05-26 10:20 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: Xinliang David Li, reply, GCC Patches

On Wed, May 25, 2011 at 6:53 PM, Joseph S. Myers
<joseph@codesourcery.com> wrote:
> On Wed, 25 May 2011, Xinliang David Li wrote:
>
>> Ping. The link to the message:
>>
>> http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01303.html
>
> I don't consider this an option handling patch.  Patches adding whole new
> features involving new options should be reviewed by maintainers for the
> part of the compiler relevant to those features (since there isn't a pass
> manager maintainer, I guess that means middle-end).

Hmm, I suppose then you reviewed the option handling parts and they
are ok?  Those globbing options always cause headache to me.

+-fenable-ipa-@var{pass} @gol
+-fenable-rtl-@var{pass} @gol
+-fenable-rtl-@var{pass}=@var{range-list} @gol
+-fenable-tree-@var{pass} @gol

so, no -fenable-tree-@var{pass}=@var{range-list}?

Does the pass name match 1:1 with the dump file name?  In which
case

+Disable ipa pass @var{pass}. @var{pass} is the pass name. If the same
pass is statically invoked in the compiler multiple times, the pass
name should be appended with a sequential number starting from 1.

isn't true as passes that are invoked only a single time lack the number
suffix (yes, I'd really like that to be changed ...)

Please break likes also in .texi files and stick to 80 columns.  Please
document that these options are debugging options and regular
options for enabling/disabling passes should be used.  I would suggest
to group documentation differently and document -fenable-* and
-fdisable-*, thus,

+ -fdisable-@var{kind}-@var{pass}
+ -fenable-@var{kind}-@var{pass}

Even in .texi files please two spaces after a full-stop.

+extern void enable_disable_pass (const char *, bool);

I'd rather have both enable_pass and disable_pass ;)

+struct function;
+extern void pass_dump_function_header (FILE *, tree, struct function *);

that's odd and probably should be split out, the function should
maybe reside in tree-pretty-print.c.

Index: tree-ssa-loop-ivopts.c
===================================================================
--- tree-ssa-loop-ivopts.c      (revision 173837)
+++ tree-ssa-loop-ivopts.c      (working copy)
@@ -3968,7 +3968,7 @@ get_computation_cost_at (struct ivopts_d

well - doesn't belong here ;)

+static hashval_t
+passr_hash (const void *p)
+{
+  const struct pass_registry *const s = (const struct pass_registry *const) p;
+  return htab_hash_string (s->unique_name);
+}
+
+/* Hash equal function  */
+
+static int
+passr_eq (const void *p1, const void *p2)
+{
+  const struct pass_registry *const s1 = (const struct pass_registry
*const) p1;
+  const struct pass_registry *const s2 = (const struct pass_registry
*const) p2;
+
+  return !strcmp (s1->unique_name, s2->unique_name);
+}

you can use htab_hash_string and strcmp directly, no need for these
wrappers.

+void
+register_pass_name (struct opt_pass *pass, const char *name)

doesn't seem to need exporting, so don't and make it static.

+  if (!pass_name_tab)
+    pass_name_tab = htab_create (10, passr_hash, passr_eq, NULL);

see above, the initial size should be larger - we have 223 passes at the
moment, so use 256.

+  else
+    return; /* Ignore plugin passes.  */

?  You mean they might clash?

+struct opt_pass *
+get_pass_by_name (const char *name)

doesn't need exporting either.

+      if (is_enable)
+        error ("unrecognized option -fenable");
+      else
+        error ("unrecognized option -fdisable");

I think that should be fatal_error - Joseph?

+      if (is_enable)
+        error ("unknown pass %s specified in -fenable", phase_name);
+      else
+        error ("unknown pass %s specified in -fdisble", phase_name);

likewise.

+      if (!enabled_pass_uid_range_tab)
+       enabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);

instead of using a hashtable here please use a VEC indexed by
the static_pass_number which shoud speed up

+static bool
+is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
+                                       tree func, htab_t tab)
+{
+  struct uid_range **slot, *range, key;
+  int cgraph_uid;
+
+  if (!tab)
+    return false;
+
+  key.pass = pass;
+  slot = (struct uid_range **) htab_find_slot (tab, &key, NO_INSERT);
+  if (!slot || !*slot)
+    return false;

and simplify the code quite a bit.

+  cgraph_uid = func ? cgraph_get_node (func)->uid : 0;

note that cgraph uids are recycled, so it might not be the best idea
to use them as discriminator (though I don't have a good idea how
to represent ranges without them).

+  explicitly_enabled = is_pass_explicitly_enabled (pass,
current_function_decl);
+  explicitly_disabled = is_pass_explicitly_disabled (pass,
current_function_decl);
+
   current_pass = pass;

   /* 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();
+  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);

so explicitly disabling wins over explicit enabling ;)  I think this
implementation detail and the fact that you always query both
hints at that the interface should be like

gate_status = override_gate_status (pass, current_function_decl, gate_status);

instead.

Thus, please split out the function header dumping changes and rework
the rest of the patch as suggested.

Thanks,
Richard.

> --
> Joseph S. Myers
> joseph@codesourcery.com
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-26 10:20           ` Richard Guenther
@ 2011-05-26 13:00             ` Joseph S. Myers
  2011-05-26 23:48             ` Xinliang David Li
  1 sibling, 0 replies; 32+ messages in thread
From: Joseph S. Myers @ 2011-05-26 13:00 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Xinliang David Li, reply, GCC Patches

On Thu, 26 May 2011, Richard Guenther wrote:

> +      if (is_enable)
> +        error ("unrecognized option -fenable");
> +      else
> +        error ("unrecognized option -fdisable");
> 
> I think that should be fatal_error - Joseph?

No, all existing errors for unknown options are ordinary errors rather 
than fatal errors (though if the driver detects a problem it won't then 
run cc1).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-26 10:20           ` Richard Guenther
  2011-05-26 13:00             ` Joseph S. Myers
@ 2011-05-26 23:48             ` Xinliang David Li
  2011-05-27  2:32               ` Xinliang David Li
  1 sibling, 1 reply; 32+ messages in thread
From: Xinliang David Li @ 2011-05-26 23:48 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Joseph S. Myers, reply, GCC Patches

[-- Attachment #1: Type: text/plain, Size: 6955 bytes --]

On Thu, May 26, 2011 at 2:04 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Wed, May 25, 2011 at 6:53 PM, Joseph S. Myers
> <joseph@codesourcery.com> wrote:
>> On Wed, 25 May 2011, Xinliang David Li wrote:
>>
>>> Ping. The link to the message:
>>>
>>> http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01303.html
>>
>> I don't consider this an option handling patch.  Patches adding whole new
>> features involving new options should be reviewed by maintainers for the
>> part of the compiler relevant to those features (since there isn't a pass
>> manager maintainer, I guess that means middle-end).
>
> Hmm, I suppose then you reviewed the option handling parts and they
> are ok?  Those globbing options always cause headache to me.
>
> +-fenable-ipa-@var{pass} @gol
> +-fenable-rtl-@var{pass} @gol
> +-fenable-rtl-@var{pass}=@var{range-list} @gol
> +-fenable-tree-@var{pass} @gol
>
> so, no -fenable-tree-@var{pass}=@var{range-list}?
>

Missed. Will add.


> Does the pass name match 1:1 with the dump file name?  In which
> case

Yes.

>
> +Disable ipa pass @var{pass}. @var{pass} is the pass name. If the same
> pass is statically invoked in the compiler multiple times, the pass
> name should be appended with a sequential number starting from 1.
>
> isn't true as passes that are invoked only a single time lack the number
> suffix (yes, I'd really like that to be changed ...)

Yes, pass with single static instance does not need number suffix.

>
> Please break likes also in .texi files and stick to 80 columns.

Done.

>  Please
> document that these options are debugging options and regular
> options for enabling/disabling passes should be used.  I would suggest
> to group documentation differently and document -fenable-* and
> -fdisable-*, thus,
>
> + -fdisable-@var{kind}-@var{pass}
> + -fenable-@var{kind}-@var{pass}
>
> Even in .texi files please two spaces after a full-stop.

Done

>
> +extern void enable_disable_pass (const char *, bool);
>
> I'd rather have both enable_pass and disable_pass ;)

Ok.

>
> +struct function;
> +extern void pass_dump_function_header (FILE *, tree, struct function *);
>
> that's odd and probably should be split out, the function should
> maybe reside in tree-pretty-print.c.

Ok.

>
> Index: tree-ssa-loop-ivopts.c
> ===================================================================
> --- tree-ssa-loop-ivopts.c      (revision 173837)
> +++ tree-ssa-loop-ivopts.c      (working copy)
> @@ -3968,7 +3968,7 @@ get_computation_cost_at (struct ivopts_d
>
> well - doesn't belong here ;)

Sorry -- many things in the same client -- not needed with your latest
change anyway.

>
> +static hashval_t
> +passr_hash (const void *p)
> +{
> +  const struct pass_registry *const s = (const struct pass_registry *const) p;
> +  return htab_hash_string (s->unique_name);
> +}
> +
> +/* Hash equal function  */
> +
> +static int
> +passr_eq (const void *p1, const void *p2)
> +{
> +  const struct pass_registry *const s1 = (const struct pass_registry
> *const) p1;
> +  const struct pass_registry *const s2 = (const struct pass_registry
> *const) p2;
> +
> +  return !strcmp (s1->unique_name, s2->unique_name);
> +}
>
> you can use htab_hash_string and strcmp directly, no need for these
> wrappers.

The hashtable entry is not string in this case. It is pass_registry,
thus the wrapper.

>
> +void
> +register_pass_name (struct opt_pass *pass, const char *name)
>
> doesn't seem to need exporting, so don't and make it static.

Done.

>
> +  if (!pass_name_tab)
> +    pass_name_tab = htab_create (10, passr_hash, passr_eq, NULL);
>
> see above, the initial size should be larger - we have 223 passes at the
> moment, so use 256.

Done.

>
> +  else
> +    return; /* Ignore plugin passes.  */
>
> ?  You mean they might clash?

Yes, name clash.

>
> +struct opt_pass *
> +get_pass_by_name (const char *name)
>
> doesn't need exporting either.

Done.

>
> +      if (is_enable)
> +        error ("unrecognized option -fenable");
> +      else
> +        error ("unrecognized option -fdisable");
>
> I think that should be fatal_error - Joseph?
>
> +      if (is_enable)
> +        error ("unknown pass %s specified in -fenable", phase_name);
> +      else
> +        error ("unknown pass %s specified in -fdisble", phase_name);
>
> likewise.
>
> +      if (!enabled_pass_uid_range_tab)
> +       enabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
>
> instead of using a hashtable here please use a VEC indexed by
> the static_pass_number which shoud speed up

Ok.  The reason I did not use it is because in most of the cases, the
htab will be very small -- it is determined by the number of passes
specified in the command line, while the VEC requires allocating const
size array. Not an issue as long as by default the array is not
allocated.

>
> +static bool
> +is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
> +                                       tree func, htab_t tab)
> +{
> +  struct uid_range **slot, *range, key;
> +  int cgraph_uid;
> +
> +  if (!tab)
> +    return false;
> +
> +  key.pass = pass;
> +  slot = (struct uid_range **) htab_find_slot (tab, &key, NO_INSERT);
> +  if (!slot || !*slot)
> +    return false;
>
> and simplify the code quite a bit.
>
> +  cgraph_uid = func ? cgraph_get_node (func)->uid : 0;
>
> note that cgraph uids are recycled, so it might not be the best idea
> to use them as discriminator (though I don't have a good idea how
> to represent ranges without them).

Yes. It is not a big problem as the blind search does not need to know
the id->name mapping. Once the id s found, it can be easily discovered
via dump.

>
> +  explicitly_enabled = is_pass_explicitly_enabled (pass,
> current_function_decl);
> +  explicitly_disabled = is_pass_explicitly_disabled (pass,
> current_function_decl);
> +
>   current_pass = pass;
>
>   /* 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();
> +  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
>
> so explicitly disabling wins over explicit enabling ;)  I think this
> implementation detail and the fact that you always query both
> hints at that the interface should be like
>
> gate_status = override_gate_status (pass, current_function_decl, gate_status);

Done.

>
> instead.
>
> Thus, please split out the function header dumping changes and rework
> the rest of the patch as suggested.

Split out. The new patch is attached.

Ok after testing is done?

Thanks,

David

>
> Thanks,
> Richard.
>
>> --
>> Joseph S. Myers
>> joseph@codesourcery.com
>>
>

[-- Attachment #2: newopt.p --]
[-- Type: text/x-pascal, Size: 17144 bytes --]

Index: tree-pass.h
===================================================================
--- tree-pass.h	(revision 174076)
+++ tree-pass.h	(working copy)
@@ -637,4 +637,10 @@ extern bool first_pass_instance;
 /* Declare for plugins.  */
 extern void do_per_function_toporder (void (*) (void *), void *);
 
+extern void disable_pass (const char *);
+extern void enable_pass (const char *);
+extern bool is_pass_explicitly_disabled (struct opt_pass *, tree);
+extern bool is_pass_explicitly_enabled (struct opt_pass *, tree);
+struct function;
+
 #endif /* GCC_TREE_PASS_H */
Index: passes.c
===================================================================
--- passes.c	(revision 174076)
+++ passes.c	(working copy)
@@ -97,6 +97,8 @@ along with GCC; see the file COPYING3.  
    The variable current_pass is also used for statistics and plugins.  */
 struct opt_pass *current_pass;
 
+static void register_pass_name (struct opt_pass *, const char *);
+
 /* Call from anywhere to find out what pass this is.  Useful for
    printing out debugging information deep inside an service
    routine.  */
@@ -375,7 +377,7 @@ void
 register_one_dump_file (struct opt_pass *pass)
 {
   char *dot_name, *flag_name, *glob_name;
-  const char *name, *prefix;
+  const char *name, *full_name, *prefix;
   char num[10];
   int flags, id;
 
@@ -404,6 +406,8 @@ register_one_dump_file (struct opt_pass 
   glob_name = concat (prefix, name, NULL);
   id = dump_register (dot_name, flag_name, glob_name, flags);
   set_pass_for_id (id, pass);
+  full_name = concat (prefix, pass->name, num, NULL);
+  register_pass_name (pass, full_name);
 }
 
 /* Recursive worker function for register_dump_files.  */
@@ -447,6 +451,322 @@ register_dump_files (struct opt_pass *pa
   register_dump_files_1 (pass, properties);
 }
 
+struct pass_registry
+{
+  const char* unique_name;
+  struct opt_pass *pass;
+};
+
+/* Pass registry hash function.  */
+
+static hashval_t
+passr_hash (const void *p)
+{
+  const struct pass_registry *const s = (const struct pass_registry *const) p;
+  return htab_hash_string (s->unique_name);
+}
+
+/* Hash equal function  */
+
+static int
+passr_eq (const void *p1, const void *p2)
+{
+  const struct pass_registry *const s1 = (const struct pass_registry *const) p1;
+  const struct pass_registry *const s2 = (const struct pass_registry *const) p2;
+
+  return !strcmp (s1->unique_name, s2->unique_name);
+}
+
+static htab_t pass_name_tab = NULL;
+
+/* Register PASS with NAME.  */
+
+static void
+register_pass_name (struct opt_pass *pass, const char *name)
+{
+  struct pass_registry **slot;
+  struct pass_registry pr;
+
+  if (!pass_name_tab)
+    pass_name_tab = htab_create (256, passr_hash, passr_eq, NULL);
+
+  pr.unique_name = name;
+  slot = (struct pass_registry **) htab_find_slot (pass_name_tab, &pr, INSERT);
+  if (!*slot)
+    {
+      struct pass_registry *new_pr;
+
+      new_pr = XCNEW (struct pass_registry);
+      new_pr->unique_name = xstrdup (name);
+      new_pr->pass = pass;
+      *slot = new_pr;
+    }
+  else
+    return; /* Ignore plugin passes.  */
+}
+
+/* Returns the pass with NAME.  */
+
+static struct opt_pass *
+get_pass_by_name (const char *name)
+{
+  struct pass_registry **slot, pr;
+
+  gcc_assert (pass_name_tab);
+  pr.unique_name = name;
+  slot = (struct pass_registry **) htab_find_slot (pass_name_tab,
+                                                   &pr, NO_INSERT);
+
+  if (!slot || !*slot)
+    return NULL;
+
+  return (*slot)->pass;
+}
+
+
+/* Range [start, last].  */
+
+struct uid_range
+{
+  unsigned int start;
+  unsigned int last;
+  struct uid_range *next;
+};
+
+typedef struct uid_range *uid_range_p;
+
+#define MAX_PASS_ID 512
+
+DEF_VEC_P(uid_range_p);
+DEF_VEC_ALLOC_P(uid_range_p, heap);
+
+static VEC(uid_range_p, heap) *enabled_pass_uid_range_tab = NULL;
+static VEC(uid_range_p, heap) *disabled_pass_uid_range_tab = NULL;
+
+/* Parse option string for -fdisable- and -fenable-
+   The syntax of the options:
+
+   -fenable-<pass_name>
+   -fdisable-<pass_name>
+
+   -fenable-<pass_name>=s1:e1,s2:e2,...
+   -fdisable-<pass_name>=s1:e1,s2:e2,...
+*/
+
+static void
+enable_disable_pass (const char *arg, bool is_enable)
+{
+  struct opt_pass *pass;
+  VEC(uid_range_p, heap) *the_tab;
+  char *range_str, *phase_name;
+  char *argstr = xstrdup (arg);
+
+  range_str = strchr (argstr,'=');
+  if (range_str)
+    {
+      *range_str = '\0';
+      range_str++;
+    }
+
+  phase_name = argstr;
+  if (!*phase_name)
+    {
+      if (is_enable)
+        error ("unrecognized option -fenable");
+      else
+        error ("unrecognized option -fdisable");
+      free (argstr);
+      return;
+    }
+  pass = get_pass_by_name (phase_name);
+  if (!pass || pass->static_pass_number >= MAX_PASS_ID)
+    {
+      if (is_enable)
+        error ("unknown pass %s specified in -fenable", phase_name);
+      else
+        error ("unknown pass %s specified in -fdisble", phase_name);
+      free (argstr);
+      return;
+    }
+  if (is_enable)
+    {
+      if (!enabled_pass_uid_range_tab)
+        VEC_safe_grow_cleared (uid_range_p, heap,
+                               enabled_pass_uid_range_tab, MAX_PASS_ID);
+      the_tab = enabled_pass_uid_range_tab;
+    }
+  else
+    {
+      if (!disabled_pass_uid_range_tab)
+        VEC_safe_grow_cleared (uid_range_p, heap,
+                               disabled_pass_uid_range_tab, MAX_PASS_ID);
+      the_tab = disabled_pass_uid_range_tab;
+    }
+
+  if (!range_str)
+    {
+      uid_range_p slot;
+      uid_range_p new_range = XCNEW (struct uid_range);
+
+      new_range->start = 0;
+      new_range->last = (unsigned)-1;
+
+      slot = VEC_index (uid_range_p, the_tab, pass->static_pass_number);
+      new_range->next = slot;
+      VEC_replace (uid_range_p, the_tab, pass->static_pass_number,
+                   new_range);
+      if (is_enable)
+        inform (UNKNOWN_LOCATION, "enable pass %s for functions in the range "
+                "of [%u, %u]", phase_name, new_range->start, new_range->last);
+      else
+        inform (UNKNOWN_LOCATION, "disable pass %s for functions in the range "
+                "of [%u, %u]", phase_name, new_range->start, new_range->last);
+    }
+  else
+    {
+      char *next_range = NULL;
+      char *one_range = range_str;
+      char *end_val = NULL;
+
+      do
+	{
+	  uid_range_p slot;
+	  uid_range_p new_range;
+	  char *invalid = NULL;
+	  long start;
+
+	  next_range = strchr (one_range, ',');
+	  if (next_range)
+	    {
+	      *next_range = '\0';
+	      next_range++;
+	    }
+
+	  end_val = strchr (one_range, ':');
+	  if (end_val)
+	    {
+	      *end_val = '\0';
+	      end_val++;
+	    }
+	  start = strtol (one_range, &invalid, 10);
+	  if (*invalid || start < 0)
+	    {
+	      error ("Invalid range %s in option %s",
+		     one_range,
+		     is_enable ? "-fenable" : "-fdisable");
+	      free (argstr);
+	      return;
+	    }
+	  if (!end_val)
+	    {
+	      new_range = XCNEW (struct uid_range);
+	      new_range->start = (unsigned) start;
+	      new_range->last = (unsigned) start;
+	    }
+	  else
+	    {
+	      long last = strtol (end_val, &invalid, 10);
+	      if (*invalid || last < start)
+		{
+		  error ("Invalid range %s in option %s",
+			 end_val,
+			 is_enable ? "-fenable" : "-fdisable");
+		  free (argstr);
+		  return;
+		}
+	      new_range = XCNEW (struct uid_range);
+	      new_range->start = (unsigned) start;
+	      new_range->last = (unsigned) last;
+	    }
+
+          slot = VEC_index (uid_range_p, the_tab, pass->static_pass_number);
+          new_range->next = slot;
+          VEC_replace (uid_range_p, the_tab, pass->static_pass_number,
+                       new_range);
+
+          if (is_enable)
+            inform (UNKNOWN_LOCATION,
+                    "enable pass %s for functions in the range of [%u, %u]",
+                    phase_name, new_range->start, new_range->last);
+          else
+            inform (UNKNOWN_LOCATION,
+                    "disable pass %s for functions in the range of [%u, %u]",
+                    phase_name, new_range->start, new_range->last);
+
+	  one_range = next_range;
+	} while (next_range);
+    }
+
+  free (argstr);
+}
+
+/* Enable pass specified by ARG.  */
+
+void
+enable_pass (const char *arg)
+{
+  enable_disable_pass (arg, true);
+}
+
+/* Disable pass specified by ARG.  */
+
+void
+disable_pass (const char *arg)
+{
+  enable_disable_pass (arg, false);
+}
+
+/* Returns true if PASS is explicitly enabled/disabled for FUNC.  */
+
+static bool
+is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
+					tree func,
+					VEC(uid_range_p, heap) *tab)
+{
+  uid_range_p slot, range;
+  int cgraph_uid;
+
+  if (!tab
+      || pass->static_pass_number >= MAX_PASS_ID
+      || pass->static_pass_number == -1)
+    return false;
+
+  slot = VEC_index (uid_range_p, tab, pass->static_pass_number);
+  if (!slot)
+    return false;
+
+  cgraph_uid = func ? cgraph_get_node (func)->uid : 0;
+
+  range = slot;
+  while (range)
+    {
+      if ((unsigned) cgraph_uid >= range->start
+	  && (unsigned) cgraph_uid <= range->last)
+	return true;
+      range = range->next;
+    }
+
+  return false;
+}
+
+/* Returns true if PASS is explicitly enabled for FUNC.  */
+
+bool
+is_pass_explicitly_enabled (struct opt_pass *pass, tree func)
+{
+  return is_pass_explicitly_enabled_or_disabled (pass, func,
+                                                 enabled_pass_uid_range_tab);
+}
+
+/* Returns true if PASS is explicitly disabled for FUNC.  */
+
+bool
+is_pass_explicitly_disabled (struct opt_pass *pass, tree func)
+{
+  return is_pass_explicitly_enabled_or_disabled (pass, func,
+                                                 disabled_pass_uid_range_tab);
+}
+
 /* Look at the static_pass_number and duplicate the pass
    if it is already added to a list. */
 
@@ -1493,6 +1813,26 @@ execute_all_ipa_transforms (void)
     }
 }
 
+/* Check if PASS is explicitly disabled or enabled and return
+   the gate status.  FUNC is the function to be processed, and
+   GATE_STATUS is the gate status determined by pass manager by
+   default.  */
+
+static bool
+override_gate_status (struct opt_pass *pass, tree func, bool gate_status)
+{
+  bool explicitly_enabled = false;
+  bool explicitly_disabled = false;
+
+  explicitly_enabled = is_pass_explicitly_enabled (pass, func);
+  explicitly_disabled = is_pass_explicitly_disabled (pass, func);
+
+  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
+
+  return gate_status;
+}
+
+
 /* Execute PASS. */
 
 bool
@@ -1515,6 +1855,7 @@ execute_one_pass (struct opt_pass *pass)
   /* 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();
+  gate_status = override_gate_status (pass, current_function_decl, gate_status);
 
   /* Override gate with plugin.  */
   invoke_plugin_callbacks (PLUGIN_OVERRIDE_GATE, &gate_status);
Index: common.opt
===================================================================
--- common.opt	(revision 174076)
+++ common.opt	(working copy)
@@ -977,6 +977,14 @@ fdiagnostics-show-option
 Common Var(flag_diagnostics_show_option) Init(1)
 Amend appropriate diagnostic messages with the command line option that controls them
 
+fdisable-
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fdisable-[tree|rtl|ipa]-<pass>=range1+range2 disables an optimization pass
+
+fenable-
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fenable-[tree|rtl|ipa]-<pass>=range1+range2 enables an optimization pass
+
 fdump-
 Common Joined RejectNegative Var(common_deferred_options) Defer
 -fdump-<type>	Dump various compiler internals to a file
Index: opts-global.c
===================================================================
--- opts-global.c	(revision 174076)
+++ opts-global.c	(working copy)
@@ -370,6 +370,14 @@ handle_common_deferred_options (void)
 	    error ("unrecognized command line option %<-fdump-%s%>", opt->arg);
 	  break;
 
+	case OPT_fenable_:
+	case OPT_fdisable_:
+	  if (opt->opt_index == OPT_fenable_)
+	    enable_pass (opt->arg);
+          else
+	    disable_pass (opt->arg);
+          break;
+
 	case OPT_ffixed_:
 	  /* Deferred.  */
 	  fix_register (opt->arg, 1, 1);
Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(revision 174076)
+++ doc/invoke.texi	(working copy)
@@ -282,6 +282,11 @@ Objective-C and Objective-C++ Dialects}.
 @xref{Debugging Options,,Options for Debugging Your Program or GCC}.
 @gccoptlist{-d@var{letters}  -dumpspecs  -dumpmachine  -dumpversion @gol
 -fdbg-cnt-list -fdbg-cnt=@var{counter-value-list} @gol
+-fdisable-ipa-@var{pass_name} @gol
+-fdisable-rtl-@var{pass_name} @gol
+-fdisable-rtl-@var{pass-name}=@var{range-list} @gol
+-fdisable-tree-@var{pass_name} @gol
+-fdisable-tree-@var{pass-name}=@var{range-list} @gol
 -fdump-noaddr -fdump-unnumbered -fdump-unnumbered-links @gol
 -fdump-translation-unit@r{[}-@var{n}@r{]} @gol
 -fdump-class-hierarchy@r{[}-@var{n}@r{]} @gol
@@ -313,6 +318,11 @@ Objective-C and Objective-C++ Dialects}.
 -fcompare-debug@r{[}=@var{opts}@r{]}  -fcompare-debug-second @gol
 -feliminate-dwarf2-dups -feliminate-unused-debug-types @gol
 -feliminate-unused-debug-symbols -femit-class-debug-always @gol
+-fenable-ipa-@var{pass} @gol
+-fenable-rtl-@var{pass} @gol
+-fenable-rtl-@var{pass}=@var{range-list} @gol
+-fenable-tree-@var{pass} @gol
+-fenable-tree-@var{pass}=@var{range-list} @gol
 -fdebug-types-section @gol
 -fmem-report -fpre-ipa-mem-report -fpost-ipa-mem-report -fprofile-arcs @gol
 -frandom-seed=@var{string} -fsched-verbose=@var{n} @gol
@@ -4986,6 +4996,7 @@ more closely, if you do not optimize.
 @opindex fdbg-cnt-list
 Print the name and the counter upper bound for all debug counters.
 
+
 @item -fdbg-cnt=@var{counter-value-list}
 @opindex fdbg-cnt
 Set the internal debug counter upper bound.  @var{counter-value-list}
@@ -4995,7 +5006,75 @@ All debug counters have the initial uppe
 thus dbg_cnt() returns true always unless the upper bound is set by this option.
 e.g. With -fdbg-cnt=dce:10,tail_call:0
 dbg_cnt(dce) will return true only for first 10 invocations
-and dbg_cnt(tail_call) will return false always.
+
+@item -fdisable-@var{ipa|tree|rtl}-@var{pass}
+@itemx -fenable-@var{ipa|tree|rtl}-@var{pass}
+@itemx -fdisable-@var{tree|rtl}-@var{pass}=@var{range-list}
+@itemx -fenable-@var{tree|rtl}-@var{pass}=@var{range-list}
+@opindex fdisable-
+@opindex fenable-
+
+This is a set of debugging options that are used to explicitly disable/enable
+optimization passes. For compiler users, regular options for enabling/disabling
+passes should be used instead.
+
+@itemize
+
+@item -fdisable-ipa-@var{pass}
+Disable ipa pass @var{pass}. @var{pass} is the pass name.  If the same pass is
+statically invoked in the compiler multiple times, the pass name should be
+appended with a sequential number starting from 1.
+
+@item -fdisable-rtl-@var{pass}
+@item -fdisable-rtl-@var{pass}=@var{range-list}
+Disable rtl pass @var{pass}.  @var{pass} is the pass name.  If the same pass is
+statically invoked in the compiler multiple times, the pass name should be
+appended with a sequential number starting from 1.  @var{range-list} is a comma
+seperated list of function ranges.  Each range is a number pair seperated by a colon.
+The range is inclusive in both ends.  If the range is trivial, the number pair can be
+simplified a a single number.  If the function's cgraph node's @var{uid} is falling
+within one of the specified ranges, the @var{pass} is disabled for that function.
+The @var{uid} is shown in the function header of a dump file.
+
+@item -fdisable-tree-@var{pass}
+@item -fdisable-tree-@var{pass}=@var{range-list}
+Disable tree pass @var{pass}.  See @option{-fdisable-rtl} for the description of
+option arguments.
+
+@item -fenable-ipa-@var{pass}
+Enable ipa pass @var{pass}.  @var{pass} is the pass name.  If the same pass is
+statically invoked in the compiler multiple times, the pass name should be
+appended with a sequential number starting from 1.
+
+@item -fenable-rtl-@var{pass}
+@item -fenable-rtl-@var{pass}=@var{range-list}
+Enable rtl pass @var{pass}.  See @option{-fdisable-rtl} for option argument
+description and examples.
+
+@item -fenable-tree-@var{pass}
+@item -fenable-tree-@var{pass}=@var{range-list}
+Enable tree pass @var{pass}.  See @option{-fdisable-rtl} for the description
+of option arguments.
+
+@smallexample
+
+# disable ccp1 for all functions
+   -fdisable-tree-ccp1
+# disable complete unroll for function whose cgraph node uid is 1
+   -fenable-tree-cunroll=1
+# disable gcse2 for functions at the following ranges [1,1],
+# [300,400], and [400,1000]
+   -fdisable-rtl-gcse2=1:100,300,400:1000
+# disable early inlining
+   -fdisable-tree-einline
+# disable ipa inlining
+   -fdisable-ipa-inline
+# enable tree full unroll
+   -fenable-tree-unroll
+
+@end smallexample
+
+@end itemize
 
 @item -d@var{letters}
 @itemx -fdump-rtl-@var{pass}

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-26 23:48             ` Xinliang David Li
@ 2011-05-27  2:32               ` Xinliang David Li
  2011-05-27 12:50                 ` Richard Guenther
  0 siblings, 1 reply; 32+ messages in thread
From: Xinliang David Li @ 2011-05-27  2:32 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Joseph S. Myers, reply, GCC Patches

[-- Attachment #1: Type: text/plain, Size: 7394 bytes --]

The latest version that only exports 2 functions from passes.c.

David

On Thu, May 26, 2011 at 2:04 PM, Xinliang David Li <davidxl@google.com> wrote:
> On Thu, May 26, 2011 at 2:04 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Wed, May 25, 2011 at 6:53 PM, Joseph S. Myers
>> <joseph@codesourcery.com> wrote:
>>> On Wed, 25 May 2011, Xinliang David Li wrote:
>>>
>>>> Ping. The link to the message:
>>>>
>>>> http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01303.html
>>>
>>> I don't consider this an option handling patch.  Patches adding whole new
>>> features involving new options should be reviewed by maintainers for the
>>> part of the compiler relevant to those features (since there isn't a pass
>>> manager maintainer, I guess that means middle-end).
>>
>> Hmm, I suppose then you reviewed the option handling parts and they
>> are ok?  Those globbing options always cause headache to me.
>>
>> +-fenable-ipa-@var{pass} @gol
>> +-fenable-rtl-@var{pass} @gol
>> +-fenable-rtl-@var{pass}=@var{range-list} @gol
>> +-fenable-tree-@var{pass} @gol
>>
>> so, no -fenable-tree-@var{pass}=@var{range-list}?
>>
>
> Missed. Will add.
>
>
>> Does the pass name match 1:1 with the dump file name?  In which
>> case
>
> Yes.
>
>>
>> +Disable ipa pass @var{pass}. @var{pass} is the pass name. If the same
>> pass is statically invoked in the compiler multiple times, the pass
>> name should be appended with a sequential number starting from 1.
>>
>> isn't true as passes that are invoked only a single time lack the number
>> suffix (yes, I'd really like that to be changed ...)
>
> Yes, pass with single static instance does not need number suffix.
>
>>
>> Please break likes also in .texi files and stick to 80 columns.
>
> Done.
>
>>  Please
>> document that these options are debugging options and regular
>> options for enabling/disabling passes should be used.  I would suggest
>> to group documentation differently and document -fenable-* and
>> -fdisable-*, thus,
>>
>> + -fdisable-@var{kind}-@var{pass}
>> + -fenable-@var{kind}-@var{pass}
>>
>> Even in .texi files please two spaces after a full-stop.
>
> Done
>
>>
>> +extern void enable_disable_pass (const char *, bool);
>>
>> I'd rather have both enable_pass and disable_pass ;)
>
> Ok.
>
>>
>> +struct function;
>> +extern void pass_dump_function_header (FILE *, tree, struct function *);
>>
>> that's odd and probably should be split out, the function should
>> maybe reside in tree-pretty-print.c.
>
> Ok.
>
>>
>> Index: tree-ssa-loop-ivopts.c
>> ===================================================================
>> --- tree-ssa-loop-ivopts.c      (revision 173837)
>> +++ tree-ssa-loop-ivopts.c      (working copy)
>> @@ -3968,7 +3968,7 @@ get_computation_cost_at (struct ivopts_d
>>
>> well - doesn't belong here ;)
>
> Sorry -- many things in the same client -- not needed with your latest
> change anyway.
>
>>
>> +static hashval_t
>> +passr_hash (const void *p)
>> +{
>> +  const struct pass_registry *const s = (const struct pass_registry *const) p;
>> +  return htab_hash_string (s->unique_name);
>> +}
>> +
>> +/* Hash equal function  */
>> +
>> +static int
>> +passr_eq (const void *p1, const void *p2)
>> +{
>> +  const struct pass_registry *const s1 = (const struct pass_registry
>> *const) p1;
>> +  const struct pass_registry *const s2 = (const struct pass_registry
>> *const) p2;
>> +
>> +  return !strcmp (s1->unique_name, s2->unique_name);
>> +}
>>
>> you can use htab_hash_string and strcmp directly, no need for these
>> wrappers.
>
> The hashtable entry is not string in this case. It is pass_registry,
> thus the wrapper.
>
>>
>> +void
>> +register_pass_name (struct opt_pass *pass, const char *name)
>>
>> doesn't seem to need exporting, so don't and make it static.
>
> Done.
>
>>
>> +  if (!pass_name_tab)
>> +    pass_name_tab = htab_create (10, passr_hash, passr_eq, NULL);
>>
>> see above, the initial size should be larger - we have 223 passes at the
>> moment, so use 256.
>
> Done.
>
>>
>> +  else
>> +    return; /* Ignore plugin passes.  */
>>
>> ?  You mean they might clash?
>
> Yes, name clash.
>
>>
>> +struct opt_pass *
>> +get_pass_by_name (const char *name)
>>
>> doesn't need exporting either.
>
> Done.
>
>>
>> +      if (is_enable)
>> +        error ("unrecognized option -fenable");
>> +      else
>> +        error ("unrecognized option -fdisable");
>>
>> I think that should be fatal_error - Joseph?
>>
>> +      if (is_enable)
>> +        error ("unknown pass %s specified in -fenable", phase_name);
>> +      else
>> +        error ("unknown pass %s specified in -fdisble", phase_name);
>>
>> likewise.
>>
>> +      if (!enabled_pass_uid_range_tab)
>> +       enabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
>>
>> instead of using a hashtable here please use a VEC indexed by
>> the static_pass_number which shoud speed up
>
> Ok.  The reason I did not use it is because in most of the cases, the
> htab will be very small -- it is determined by the number of passes
> specified in the command line, while the VEC requires allocating const
> size array. Not an issue as long as by default the array is not
> allocated.
>
>>
>> +static bool
>> +is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
>> +                                       tree func, htab_t tab)
>> +{
>> +  struct uid_range **slot, *range, key;
>> +  int cgraph_uid;
>> +
>> +  if (!tab)
>> +    return false;
>> +
>> +  key.pass = pass;
>> +  slot = (struct uid_range **) htab_find_slot (tab, &key, NO_INSERT);
>> +  if (!slot || !*slot)
>> +    return false;
>>
>> and simplify the code quite a bit.
>>
>> +  cgraph_uid = func ? cgraph_get_node (func)->uid : 0;
>>
>> note that cgraph uids are recycled, so it might not be the best idea
>> to use them as discriminator (though I don't have a good idea how
>> to represent ranges without them).
>
> Yes. It is not a big problem as the blind search does not need to know
> the id->name mapping. Once the id s found, it can be easily discovered
> via dump.
>
>>
>> +  explicitly_enabled = is_pass_explicitly_enabled (pass,
>> current_function_decl);
>> +  explicitly_disabled = is_pass_explicitly_disabled (pass,
>> current_function_decl);
>> +
>>   current_pass = pass;
>>
>>   /* 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();
>> +  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
>>
>> so explicitly disabling wins over explicit enabling ;)  I think this
>> implementation detail and the fact that you always query both
>> hints at that the interface should be like
>>
>> gate_status = override_gate_status (pass, current_function_decl, gate_status);
>
> Done.
>
>>
>> instead.
>>
>> Thus, please split out the function header dumping changes and rework
>> the rest of the patch as suggested.
>
> Split out. The new patch is attached.
>
> Ok after testing is done?
>
> Thanks,
>
> David
>
>>
>> Thanks,
>> Richard.
>>
>>> --
>>> Joseph S. Myers
>>> joseph@codesourcery.com
>>>
>>
>

[-- Attachment #2: newopt2.p --]
[-- Type: text/x-pascal, Size: 17022 bytes --]

Index: passes.c
===================================================================
--- passes.c	(revision 174076)
+++ passes.c	(working copy)
@@ -97,6 +97,8 @@ along with GCC; see the file COPYING3.  
    The variable current_pass is also used for statistics and plugins.  */
 struct opt_pass *current_pass;
 
+static void register_pass_name (struct opt_pass *, const char *);
+
 /* Call from anywhere to find out what pass this is.  Useful for
    printing out debugging information deep inside an service
    routine.  */
@@ -375,7 +377,7 @@ void
 register_one_dump_file (struct opt_pass *pass)
 {
   char *dot_name, *flag_name, *glob_name;
-  const char *name, *prefix;
+  const char *name, *full_name, *prefix;
   char num[10];
   int flags, id;
 
@@ -404,6 +406,8 @@ register_one_dump_file (struct opt_pass 
   glob_name = concat (prefix, name, NULL);
   id = dump_register (dot_name, flag_name, glob_name, flags);
   set_pass_for_id (id, pass);
+  full_name = concat (prefix, pass->name, num, NULL);
+  register_pass_name (pass, full_name);
 }
 
 /* Recursive worker function for register_dump_files.  */
@@ -447,6 +451,322 @@ register_dump_files (struct opt_pass *pa
   register_dump_files_1 (pass, properties);
 }
 
+struct pass_registry
+{
+  const char* unique_name;
+  struct opt_pass *pass;
+};
+
+/* Pass registry hash function.  */
+
+static hashval_t
+passr_hash (const void *p)
+{
+  const struct pass_registry *const s = (const struct pass_registry *const) p;
+  return htab_hash_string (s->unique_name);
+}
+
+/* Hash equal function  */
+
+static int
+passr_eq (const void *p1, const void *p2)
+{
+  const struct pass_registry *const s1 = (const struct pass_registry *const) p1;
+  const struct pass_registry *const s2 = (const struct pass_registry *const) p2;
+
+  return !strcmp (s1->unique_name, s2->unique_name);
+}
+
+static htab_t pass_name_tab = NULL;
+
+/* Register PASS with NAME.  */
+
+static void
+register_pass_name (struct opt_pass *pass, const char *name)
+{
+  struct pass_registry **slot;
+  struct pass_registry pr;
+
+  if (!pass_name_tab)
+    pass_name_tab = htab_create (256, passr_hash, passr_eq, NULL);
+
+  pr.unique_name = name;
+  slot = (struct pass_registry **) htab_find_slot (pass_name_tab, &pr, INSERT);
+  if (!*slot)
+    {
+      struct pass_registry *new_pr;
+
+      new_pr = XCNEW (struct pass_registry);
+      new_pr->unique_name = xstrdup (name);
+      new_pr->pass = pass;
+      *slot = new_pr;
+    }
+  else
+    return; /* Ignore plugin passes.  */
+}
+
+/* Returns the pass with NAME.  */
+
+static struct opt_pass *
+get_pass_by_name (const char *name)
+{
+  struct pass_registry **slot, pr;
+
+  gcc_assert (pass_name_tab);
+  pr.unique_name = name;
+  slot = (struct pass_registry **) htab_find_slot (pass_name_tab,
+                                                   &pr, NO_INSERT);
+
+  if (!slot || !*slot)
+    return NULL;
+
+  return (*slot)->pass;
+}
+
+
+/* Range [start, last].  */
+
+struct uid_range
+{
+  unsigned int start;
+  unsigned int last;
+  struct uid_range *next;
+};
+
+typedef struct uid_range *uid_range_p;
+
+#define MAX_PASS_ID 512
+
+DEF_VEC_P(uid_range_p);
+DEF_VEC_ALLOC_P(uid_range_p, heap);
+
+static VEC(uid_range_p, heap) *enabled_pass_uid_range_tab = NULL;
+static VEC(uid_range_p, heap) *disabled_pass_uid_range_tab = NULL;
+
+/* Parse option string for -fdisable- and -fenable-
+   The syntax of the options:
+
+   -fenable-<pass_name>
+   -fdisable-<pass_name>
+
+   -fenable-<pass_name>=s1:e1,s2:e2,...
+   -fdisable-<pass_name>=s1:e1,s2:e2,...
+*/
+
+static void
+enable_disable_pass (const char *arg, bool is_enable)
+{
+  struct opt_pass *pass;
+  VEC(uid_range_p, heap) *the_tab;
+  char *range_str, *phase_name;
+  char *argstr = xstrdup (arg);
+
+  range_str = strchr (argstr,'=');
+  if (range_str)
+    {
+      *range_str = '\0';
+      range_str++;
+    }
+
+  phase_name = argstr;
+  if (!*phase_name)
+    {
+      if (is_enable)
+        error ("unrecognized option -fenable");
+      else
+        error ("unrecognized option -fdisable");
+      free (argstr);
+      return;
+    }
+  pass = get_pass_by_name (phase_name);
+  if (!pass || pass->static_pass_number >= MAX_PASS_ID)
+    {
+      if (is_enable)
+        error ("unknown pass %s specified in -fenable", phase_name);
+      else
+        error ("unknown pass %s specified in -fdisble", phase_name);
+      free (argstr);
+      return;
+    }
+  if (is_enable)
+    {
+      if (!enabled_pass_uid_range_tab)
+        VEC_safe_grow_cleared (uid_range_p, heap,
+                               enabled_pass_uid_range_tab, MAX_PASS_ID);
+      the_tab = enabled_pass_uid_range_tab;
+    }
+  else
+    {
+      if (!disabled_pass_uid_range_tab)
+        VEC_safe_grow_cleared (uid_range_p, heap,
+                               disabled_pass_uid_range_tab, MAX_PASS_ID);
+      the_tab = disabled_pass_uid_range_tab;
+    }
+
+  if (!range_str)
+    {
+      uid_range_p slot;
+      uid_range_p new_range = XCNEW (struct uid_range);
+
+      new_range->start = 0;
+      new_range->last = (unsigned)-1;
+
+      slot = VEC_index (uid_range_p, the_tab, pass->static_pass_number);
+      new_range->next = slot;
+      VEC_replace (uid_range_p, the_tab, pass->static_pass_number,
+                   new_range);
+      if (is_enable)
+        inform (UNKNOWN_LOCATION, "enable pass %s for functions in the range "
+                "of [%u, %u]", phase_name, new_range->start, new_range->last);
+      else
+        inform (UNKNOWN_LOCATION, "disable pass %s for functions in the range "
+                "of [%u, %u]", phase_name, new_range->start, new_range->last);
+    }
+  else
+    {
+      char *next_range = NULL;
+      char *one_range = range_str;
+      char *end_val = NULL;
+
+      do
+	{
+	  uid_range_p slot;
+	  uid_range_p new_range;
+	  char *invalid = NULL;
+	  long start;
+
+	  next_range = strchr (one_range, ',');
+	  if (next_range)
+	    {
+	      *next_range = '\0';
+	      next_range++;
+	    }
+
+	  end_val = strchr (one_range, ':');
+	  if (end_val)
+	    {
+	      *end_val = '\0';
+	      end_val++;
+	    }
+	  start = strtol (one_range, &invalid, 10);
+	  if (*invalid || start < 0)
+	    {
+	      error ("Invalid range %s in option %s",
+		     one_range,
+		     is_enable ? "-fenable" : "-fdisable");
+	      free (argstr);
+	      return;
+	    }
+	  if (!end_val)
+	    {
+	      new_range = XCNEW (struct uid_range);
+	      new_range->start = (unsigned) start;
+	      new_range->last = (unsigned) start;
+	    }
+	  else
+	    {
+	      long last = strtol (end_val, &invalid, 10);
+	      if (*invalid || last < start)
+		{
+		  error ("Invalid range %s in option %s",
+			 end_val,
+			 is_enable ? "-fenable" : "-fdisable");
+		  free (argstr);
+		  return;
+		}
+	      new_range = XCNEW (struct uid_range);
+	      new_range->start = (unsigned) start;
+	      new_range->last = (unsigned) last;
+	    }
+
+          slot = VEC_index (uid_range_p, the_tab, pass->static_pass_number);
+          new_range->next = slot;
+          VEC_replace (uid_range_p, the_tab, pass->static_pass_number,
+                       new_range);
+
+          if (is_enable)
+            inform (UNKNOWN_LOCATION,
+                    "enable pass %s for functions in the range of [%u, %u]",
+                    phase_name, new_range->start, new_range->last);
+          else
+            inform (UNKNOWN_LOCATION,
+                    "disable pass %s for functions in the range of [%u, %u]",
+                    phase_name, new_range->start, new_range->last);
+
+	  one_range = next_range;
+	} while (next_range);
+    }
+
+  free (argstr);
+}
+
+/* Enable pass specified by ARG.  */
+
+void
+enable_pass (const char *arg)
+{
+  enable_disable_pass (arg, true);
+}
+
+/* Disable pass specified by ARG.  */
+
+void
+disable_pass (const char *arg)
+{
+  enable_disable_pass (arg, false);
+}
+
+/* Returns true if PASS is explicitly enabled/disabled for FUNC.  */
+
+static bool
+is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
+					tree func,
+					VEC(uid_range_p, heap) *tab)
+{
+  uid_range_p slot, range;
+  int cgraph_uid;
+
+  if (!tab
+      || pass->static_pass_number >= MAX_PASS_ID
+      || pass->static_pass_number == -1)
+    return false;
+
+  slot = VEC_index (uid_range_p, tab, pass->static_pass_number);
+  if (!slot)
+    return false;
+
+  cgraph_uid = func ? cgraph_get_node (func)->uid : 0;
+
+  range = slot;
+  while (range)
+    {
+      if ((unsigned) cgraph_uid >= range->start
+	  && (unsigned) cgraph_uid <= range->last)
+	return true;
+      range = range->next;
+    }
+
+  return false;
+}
+
+/* Returns true if PASS is explicitly enabled for FUNC.  */
+
+static bool
+is_pass_explicitly_enabled (struct opt_pass *pass, tree func)
+{
+  return is_pass_explicitly_enabled_or_disabled (pass, func,
+                                                 enabled_pass_uid_range_tab);
+}
+
+/* Returns true if PASS is explicitly disabled for FUNC.  */
+
+static bool
+is_pass_explicitly_disabled (struct opt_pass *pass, tree func)
+{
+  return is_pass_explicitly_enabled_or_disabled (pass, func,
+                                                 disabled_pass_uid_range_tab);
+}
+
 /* Look at the static_pass_number and duplicate the pass
    if it is already added to a list. */
 
@@ -1493,6 +1813,26 @@ execute_all_ipa_transforms (void)
     }
 }
 
+/* Check if PASS is explicitly disabled or enabled and return
+   the gate status.  FUNC is the function to be processed, and
+   GATE_STATUS is the gate status determined by pass manager by
+   default.  */
+
+static bool
+override_gate_status (struct opt_pass *pass, tree func, bool gate_status)
+{
+  bool explicitly_enabled = false;
+  bool explicitly_disabled = false;
+
+  explicitly_enabled = is_pass_explicitly_enabled (pass, func);
+  explicitly_disabled = is_pass_explicitly_disabled (pass, func);
+
+  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
+
+  return gate_status;
+}
+
+
 /* Execute PASS. */
 
 bool
@@ -1515,6 +1855,7 @@ execute_one_pass (struct opt_pass *pass)
   /* 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();
+  gate_status = override_gate_status (pass, current_function_decl, gate_status);
 
   /* Override gate with plugin.  */
   invoke_plugin_callbacks (PLUGIN_OVERRIDE_GATE, &gate_status);
Index: tree-pass.h
===================================================================
--- tree-pass.h	(revision 174076)
+++ tree-pass.h	(working copy)
@@ -637,4 +637,8 @@ extern bool first_pass_instance;
 /* Declare for plugins.  */
 extern void do_per_function_toporder (void (*) (void *), void *);
 
+extern void disable_pass (const char *);
+extern void enable_pass (const char *);
+struct function;
+
 #endif /* GCC_TREE_PASS_H */
Index: opts-global.c
===================================================================
--- opts-global.c	(revision 174076)
+++ opts-global.c	(working copy)
@@ -370,6 +370,14 @@ handle_common_deferred_options (void)
 	    error ("unrecognized command line option %<-fdump-%s%>", opt->arg);
 	  break;
 
+	case OPT_fenable_:
+	case OPT_fdisable_:
+	  if (opt->opt_index == OPT_fenable_)
+	    enable_pass (opt->arg);
+          else
+	    disable_pass (opt->arg);
+          break;
+
 	case OPT_ffixed_:
 	  /* Deferred.  */
 	  fix_register (opt->arg, 1, 1);
Index: common.opt
===================================================================
--- common.opt	(revision 174076)
+++ common.opt	(working copy)
@@ -977,6 +977,14 @@ fdiagnostics-show-option
 Common Var(flag_diagnostics_show_option) Init(1)
 Amend appropriate diagnostic messages with the command line option that controls them
 
+fdisable-
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fdisable-[tree|rtl|ipa]-<pass>=range1+range2 disables an optimization pass
+
+fenable-
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fenable-[tree|rtl|ipa]-<pass>=range1+range2 enables an optimization pass
+
 fdump-
 Common Joined RejectNegative Var(common_deferred_options) Defer
 -fdump-<type>	Dump various compiler internals to a file
Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(revision 174076)
+++ doc/invoke.texi	(working copy)
@@ -282,6 +282,11 @@ Objective-C and Objective-C++ Dialects}.
 @xref{Debugging Options,,Options for Debugging Your Program or GCC}.
 @gccoptlist{-d@var{letters}  -dumpspecs  -dumpmachine  -dumpversion @gol
 -fdbg-cnt-list -fdbg-cnt=@var{counter-value-list} @gol
+-fdisable-ipa-@var{pass_name} @gol
+-fdisable-rtl-@var{pass_name} @gol
+-fdisable-rtl-@var{pass-name}=@var{range-list} @gol
+-fdisable-tree-@var{pass_name} @gol
+-fdisable-tree-@var{pass-name}=@var{range-list} @gol
 -fdump-noaddr -fdump-unnumbered -fdump-unnumbered-links @gol
 -fdump-translation-unit@r{[}-@var{n}@r{]} @gol
 -fdump-class-hierarchy@r{[}-@var{n}@r{]} @gol
@@ -313,6 +318,11 @@ Objective-C and Objective-C++ Dialects}.
 -fcompare-debug@r{[}=@var{opts}@r{]}  -fcompare-debug-second @gol
 -feliminate-dwarf2-dups -feliminate-unused-debug-types @gol
 -feliminate-unused-debug-symbols -femit-class-debug-always @gol
+-fenable-ipa-@var{pass} @gol
+-fenable-rtl-@var{pass} @gol
+-fenable-rtl-@var{pass}=@var{range-list} @gol
+-fenable-tree-@var{pass} @gol
+-fenable-tree-@var{pass}=@var{range-list} @gol
 -fdebug-types-section @gol
 -fmem-report -fpre-ipa-mem-report -fpost-ipa-mem-report -fprofile-arcs @gol
 -frandom-seed=@var{string} -fsched-verbose=@var{n} @gol
@@ -4986,6 +4996,7 @@ more closely, if you do not optimize.
 @opindex fdbg-cnt-list
 Print the name and the counter upper bound for all debug counters.
 
+
 @item -fdbg-cnt=@var{counter-value-list}
 @opindex fdbg-cnt
 Set the internal debug counter upper bound.  @var{counter-value-list}
@@ -4995,7 +5006,75 @@ All debug counters have the initial uppe
 thus dbg_cnt() returns true always unless the upper bound is set by this option.
 e.g. With -fdbg-cnt=dce:10,tail_call:0
 dbg_cnt(dce) will return true only for first 10 invocations
-and dbg_cnt(tail_call) will return false always.
+
+@item -fdisable-@var{ipa|tree|rtl}-@var{pass}
+@itemx -fenable-@var{ipa|tree|rtl}-@var{pass}
+@itemx -fdisable-@var{tree|rtl}-@var{pass}=@var{range-list}
+@itemx -fenable-@var{tree|rtl}-@var{pass}=@var{range-list}
+@opindex fdisable-
+@opindex fenable-
+
+This is a set of debugging options that are used to explicitly disable/enable
+optimization passes. For compiler users, regular options for enabling/disabling
+passes should be used instead.
+
+@itemize
+
+@item -fdisable-ipa-@var{pass}
+Disable ipa pass @var{pass}. @var{pass} is the pass name.  If the same pass is
+statically invoked in the compiler multiple times, the pass name should be
+appended with a sequential number starting from 1.
+
+@item -fdisable-rtl-@var{pass}
+@item -fdisable-rtl-@var{pass}=@var{range-list}
+Disable rtl pass @var{pass}.  @var{pass} is the pass name.  If the same pass is
+statically invoked in the compiler multiple times, the pass name should be
+appended with a sequential number starting from 1.  @var{range-list} is a comma
+seperated list of function ranges.  Each range is a number pair seperated by a colon.
+The range is inclusive in both ends.  If the range is trivial, the number pair can be
+simplified a a single number.  If the function's cgraph node's @var{uid} is falling
+within one of the specified ranges, the @var{pass} is disabled for that function.
+The @var{uid} is shown in the function header of a dump file.
+
+@item -fdisable-tree-@var{pass}
+@item -fdisable-tree-@var{pass}=@var{range-list}
+Disable tree pass @var{pass}.  See @option{-fdisable-rtl} for the description of
+option arguments.
+
+@item -fenable-ipa-@var{pass}
+Enable ipa pass @var{pass}.  @var{pass} is the pass name.  If the same pass is
+statically invoked in the compiler multiple times, the pass name should be
+appended with a sequential number starting from 1.
+
+@item -fenable-rtl-@var{pass}
+@item -fenable-rtl-@var{pass}=@var{range-list}
+Enable rtl pass @var{pass}.  See @option{-fdisable-rtl} for option argument
+description and examples.
+
+@item -fenable-tree-@var{pass}
+@item -fenable-tree-@var{pass}=@var{range-list}
+Enable tree pass @var{pass}.  See @option{-fdisable-rtl} for the description
+of option arguments.
+
+@smallexample
+
+# disable ccp1 for all functions
+   -fdisable-tree-ccp1
+# disable complete unroll for function whose cgraph node uid is 1
+   -fenable-tree-cunroll=1
+# disable gcse2 for functions at the following ranges [1,1],
+# [300,400], and [400,1000]
+   -fdisable-rtl-gcse2=1:100,300,400:1000
+# disable early inlining
+   -fdisable-tree-einline
+# disable ipa inlining
+   -fdisable-ipa-inline
+# enable tree full unroll
+   -fenable-tree-unroll
+
+@end smallexample
+
+@end itemize
 
 @item -d@var{letters}
 @itemx -fdump-rtl-@var{pass}

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-27  2:32               ` Xinliang David Li
@ 2011-05-27 12:50                 ` Richard Guenther
  2011-05-31  4:54                   ` Xinliang David Li
  0 siblings, 1 reply; 32+ messages in thread
From: Richard Guenther @ 2011-05-27 12:50 UTC (permalink / raw)
  To: Xinliang David Li; +Cc: Joseph S. Myers, reply, GCC Patches

On Fri, May 27, 2011 at 12:02 AM, Xinliang David Li <davidxl@google.com> wrote:
> The latest version that only exports 2 functions from passes.c.

Ok with ...

@@ -637,4 +637,8 @@ extern bool first_pass_instance;
 /* Declare for plugins.  */
 extern void do_per_function_toporder (void (*) (void *), void *);

+extern void disable_pass (const char *);
+extern void enable_pass (const char *);
+struct function;
+

struct function forward decl removed.

+  explicitly_enabled = is_pass_explicitly_enabled (pass, func);
+  explicitly_disabled = is_pass_explicitly_disabled (pass, func);

both functions inlined here and removed.

+#define MAX_PASS_ID 512

this removed and instead a VEC_safe_grow_cleared () or VEC_length ()
before the accesses.

+-fenable-ipa-@var{pass} @gol
+-fenable-rtl-@var{pass} @gol
+-fenable-rtl-@var{pass}=@var{range-list} @gol
+-fenable-tree-@var{pass} @gol
+-fenable-tree-@var{pass}=@var{range-list} @gol

-fenable-@var{kind}-@var{pass}, etc.

+@item -fdisable-@var{ipa|tree|rtl}-@var{pass}
+@itemx -fenable-@var{ipa|tree|rtl}-@var{pass}
+@itemx -fdisable-@var{tree|rtl}-@var{pass}=@var{range-list}
+@itemx -fenable-@var{tree|rtl}-@var{pass}=@var{range-list}

likewise.

Thanks,
Richard.

> David
>
> On Thu, May 26, 2011 at 2:04 PM, Xinliang David Li <davidxl@google.com> wrote:
>> On Thu, May 26, 2011 at 2:04 AM, Richard Guenther
>> <richard.guenther@gmail.com> wrote:
>>> On Wed, May 25, 2011 at 6:53 PM, Joseph S. Myers
>>> <joseph@codesourcery.com> wrote:
>>>> On Wed, 25 May 2011, Xinliang David Li wrote:
>>>>
>>>>> Ping. The link to the message:
>>>>>
>>>>> http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01303.html
>>>>
>>>> I don't consider this an option handling patch.  Patches adding whole new
>>>> features involving new options should be reviewed by maintainers for the
>>>> part of the compiler relevant to those features (since there isn't a pass
>>>> manager maintainer, I guess that means middle-end).
>>>
>>> Hmm, I suppose then you reviewed the option handling parts and they
>>> are ok?  Those globbing options always cause headache to me.
>>>
>>> +-fenable-ipa-@var{pass} @gol
>>> +-fenable-rtl-@var{pass} @gol
>>> +-fenable-rtl-@var{pass}=@var{range-list} @gol
>>> +-fenable-tree-@var{pass} @gol
>>>
>>> so, no -fenable-tree-@var{pass}=@var{range-list}?
>>>
>>
>> Missed. Will add.
>>
>>
>>> Does the pass name match 1:1 with the dump file name?  In which
>>> case
>>
>> Yes.
>>
>>>
>>> +Disable ipa pass @var{pass}. @var{pass} is the pass name. If the same
>>> pass is statically invoked in the compiler multiple times, the pass
>>> name should be appended with a sequential number starting from 1.
>>>
>>> isn't true as passes that are invoked only a single time lack the number
>>> suffix (yes, I'd really like that to be changed ...)
>>
>> Yes, pass with single static instance does not need number suffix.
>>
>>>
>>> Please break likes also in .texi files and stick to 80 columns.
>>
>> Done.
>>
>>>  Please
>>> document that these options are debugging options and regular
>>> options for enabling/disabling passes should be used.  I would suggest
>>> to group documentation differently and document -fenable-* and
>>> -fdisable-*, thus,
>>>
>>> + -fdisable-@var{kind}-@var{pass}
>>> + -fenable-@var{kind}-@var{pass}
>>>
>>> Even in .texi files please two spaces after a full-stop.
>>
>> Done
>>
>>>
>>> +extern void enable_disable_pass (const char *, bool);
>>>
>>> I'd rather have both enable_pass and disable_pass ;)
>>
>> Ok.
>>
>>>
>>> +struct function;
>>> +extern void pass_dump_function_header (FILE *, tree, struct function *);
>>>
>>> that's odd and probably should be split out, the function should
>>> maybe reside in tree-pretty-print.c.
>>
>> Ok.
>>
>>>
>>> Index: tree-ssa-loop-ivopts.c
>>> ===================================================================
>>> --- tree-ssa-loop-ivopts.c      (revision 173837)
>>> +++ tree-ssa-loop-ivopts.c      (working copy)
>>> @@ -3968,7 +3968,7 @@ get_computation_cost_at (struct ivopts_d
>>>
>>> well - doesn't belong here ;)
>>
>> Sorry -- many things in the same client -- not needed with your latest
>> change anyway.
>>
>>>
>>> +static hashval_t
>>> +passr_hash (const void *p)
>>> +{
>>> +  const struct pass_registry *const s = (const struct pass_registry *const) p;
>>> +  return htab_hash_string (s->unique_name);
>>> +}
>>> +
>>> +/* Hash equal function  */
>>> +
>>> +static int
>>> +passr_eq (const void *p1, const void *p2)
>>> +{
>>> +  const struct pass_registry *const s1 = (const struct pass_registry
>>> *const) p1;
>>> +  const struct pass_registry *const s2 = (const struct pass_registry
>>> *const) p2;
>>> +
>>> +  return !strcmp (s1->unique_name, s2->unique_name);
>>> +}
>>>
>>> you can use htab_hash_string and strcmp directly, no need for these
>>> wrappers.
>>
>> The hashtable entry is not string in this case. It is pass_registry,
>> thus the wrapper.
>>
>>>
>>> +void
>>> +register_pass_name (struct opt_pass *pass, const char *name)
>>>
>>> doesn't seem to need exporting, so don't and make it static.
>>
>> Done.
>>
>>>
>>> +  if (!pass_name_tab)
>>> +    pass_name_tab = htab_create (10, passr_hash, passr_eq, NULL);
>>>
>>> see above, the initial size should be larger - we have 223 passes at the
>>> moment, so use 256.
>>
>> Done.
>>
>>>
>>> +  else
>>> +    return; /* Ignore plugin passes.  */
>>>
>>> ?  You mean they might clash?
>>
>> Yes, name clash.
>>
>>>
>>> +struct opt_pass *
>>> +get_pass_by_name (const char *name)
>>>
>>> doesn't need exporting either.
>>
>> Done.
>>
>>>
>>> +      if (is_enable)
>>> +        error ("unrecognized option -fenable");
>>> +      else
>>> +        error ("unrecognized option -fdisable");
>>>
>>> I think that should be fatal_error - Joseph?
>>>
>>> +      if (is_enable)
>>> +        error ("unknown pass %s specified in -fenable", phase_name);
>>> +      else
>>> +        error ("unknown pass %s specified in -fdisble", phase_name);
>>>
>>> likewise.
>>>
>>> +      if (!enabled_pass_uid_range_tab)
>>> +       enabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
>>>
>>> instead of using a hashtable here please use a VEC indexed by
>>> the static_pass_number which shoud speed up
>>
>> Ok.  The reason I did not use it is because in most of the cases, the
>> htab will be very small -- it is determined by the number of passes
>> specified in the command line, while the VEC requires allocating const
>> size array. Not an issue as long as by default the array is not
>> allocated.
>>
>>>
>>> +static bool
>>> +is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
>>> +                                       tree func, htab_t tab)
>>> +{
>>> +  struct uid_range **slot, *range, key;
>>> +  int cgraph_uid;
>>> +
>>> +  if (!tab)
>>> +    return false;
>>> +
>>> +  key.pass = pass;
>>> +  slot = (struct uid_range **) htab_find_slot (tab, &key, NO_INSERT);
>>> +  if (!slot || !*slot)
>>> +    return false;
>>>
>>> and simplify the code quite a bit.
>>>
>>> +  cgraph_uid = func ? cgraph_get_node (func)->uid : 0;
>>>
>>> note that cgraph uids are recycled, so it might not be the best idea
>>> to use them as discriminator (though I don't have a good idea how
>>> to represent ranges without them).
>>
>> Yes. It is not a big problem as the blind search does not need to know
>> the id->name mapping. Once the id s found, it can be easily discovered
>> via dump.
>>
>>>
>>> +  explicitly_enabled = is_pass_explicitly_enabled (pass,
>>> current_function_decl);
>>> +  explicitly_disabled = is_pass_explicitly_disabled (pass,
>>> current_function_decl);
>>> +
>>>   current_pass = pass;
>>>
>>>   /* 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();
>>> +  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
>>>
>>> so explicitly disabling wins over explicit enabling ;)  I think this
>>> implementation detail and the fact that you always query both
>>> hints at that the interface should be like
>>>
>>> gate_status = override_gate_status (pass, current_function_decl, gate_status);
>>
>> Done.
>>
>>>
>>> instead.
>>>
>>> Thus, please split out the function header dumping changes and rework
>>> the rest of the patch as suggested.
>>
>> Split out. The new patch is attached.
>>
>> Ok after testing is done?
>>
>> Thanks,
>>
>> David
>>
>>>
>>> Thanks,
>>> Richard.
>>>
>>>> --
>>>> Joseph S. Myers
>>>> joseph@codesourcery.com
>>>>
>>>
>>
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-27 12:50                 ` Richard Guenther
@ 2011-05-31  4:54                   ` Xinliang David Li
  2011-05-31  7:05                     ` Xinliang David Li
  2011-05-31  9:57                     ` Richard Guenther
  0 siblings, 2 replies; 32+ messages in thread
From: Xinliang David Li @ 2011-05-31  4:54 UTC (permalink / raw)
  To: GCC Patches; +Cc: reply, Richard Guenther, Jan Hubicka

[-- Attachment #1: Type: text/plain, Size: 9756 bytes --]

The attached are two simple follow up patches

1) the first patch does some refactorization on function header
dumping (with more information printed)

2) the second patch cleans up some pass names. Part of the cleanup
results from a previous discussion with Honza -- a) rename
'tree_profile_ipa' into 'profile', and make 'ipa_profile' and
'profile' into 'profile_estimate'. The rest of cleanups are needed to
make sure pass names are unique.

Ok for trunk?

Thanks,

David

On Fri, May 27, 2011 at 2:58 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Fri, May 27, 2011 at 12:02 AM, Xinliang David Li <davidxl@google.com> wrote:
>> The latest version that only exports 2 functions from passes.c.
>
> Ok with ...
>
> @@ -637,4 +637,8 @@ extern bool first_pass_instance;
>  /* Declare for plugins.  */
>  extern void do_per_function_toporder (void (*) (void *), void *);
>
> +extern void disable_pass (const char *);
> +extern void enable_pass (const char *);
> +struct function;
> +
>
> struct function forward decl removed.
>
> +  explicitly_enabled = is_pass_explicitly_enabled (pass, func);
> +  explicitly_disabled = is_pass_explicitly_disabled (pass, func);
>
> both functions inlined here and removed.
>
> +#define MAX_PASS_ID 512
>
> this removed and instead a VEC_safe_grow_cleared () or VEC_length ()
> before the accesses.
>
> +-fenable-ipa-@var{pass} @gol
> +-fenable-rtl-@var{pass} @gol
> +-fenable-rtl-@var{pass}=@var{range-list} @gol
> +-fenable-tree-@var{pass} @gol
> +-fenable-tree-@var{pass}=@var{range-list} @gol
>
> -fenable-@var{kind}-@var{pass}, etc.
>
> +@item -fdisable-@var{ipa|tree|rtl}-@var{pass}
> +@itemx -fenable-@var{ipa|tree|rtl}-@var{pass}
> +@itemx -fdisable-@var{tree|rtl}-@var{pass}=@var{range-list}
> +@itemx -fenable-@var{tree|rtl}-@var{pass}=@var{range-list}
>
> likewise.
>
> Thanks,
> Richard.
>
>> David
>>
>> On Thu, May 26, 2011 at 2:04 PM, Xinliang David Li <davidxl@google.com> wrote:
>>> On Thu, May 26, 2011 at 2:04 AM, Richard Guenther
>>> <richard.guenther@gmail.com> wrote:
>>>> On Wed, May 25, 2011 at 6:53 PM, Joseph S. Myers
>>>> <joseph@codesourcery.com> wrote:
>>>>> On Wed, 25 May 2011, Xinliang David Li wrote:
>>>>>
>>>>>> Ping. The link to the message:
>>>>>>
>>>>>> http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01303.html
>>>>>
>>>>> I don't consider this an option handling patch.  Patches adding whole new
>>>>> features involving new options should be reviewed by maintainers for the
>>>>> part of the compiler relevant to those features (since there isn't a pass
>>>>> manager maintainer, I guess that means middle-end).
>>>>
>>>> Hmm, I suppose then you reviewed the option handling parts and they
>>>> are ok?  Those globbing options always cause headache to me.
>>>>
>>>> +-fenable-ipa-@var{pass} @gol
>>>> +-fenable-rtl-@var{pass} @gol
>>>> +-fenable-rtl-@var{pass}=@var{range-list} @gol
>>>> +-fenable-tree-@var{pass} @gol
>>>>
>>>> so, no -fenable-tree-@var{pass}=@var{range-list}?
>>>>
>>>
>>> Missed. Will add.
>>>
>>>
>>>> Does the pass name match 1:1 with the dump file name?  In which
>>>> case
>>>
>>> Yes.
>>>
>>>>
>>>> +Disable ipa pass @var{pass}. @var{pass} is the pass name. If the same
>>>> pass is statically invoked in the compiler multiple times, the pass
>>>> name should be appended with a sequential number starting from 1.
>>>>
>>>> isn't true as passes that are invoked only a single time lack the number
>>>> suffix (yes, I'd really like that to be changed ...)
>>>
>>> Yes, pass with single static instance does not need number suffix.
>>>
>>>>
>>>> Please break likes also in .texi files and stick to 80 columns.
>>>
>>> Done.
>>>
>>>>  Please
>>>> document that these options are debugging options and regular
>>>> options for enabling/disabling passes should be used.  I would suggest
>>>> to group documentation differently and document -fenable-* and
>>>> -fdisable-*, thus,
>>>>
>>>> + -fdisable-@var{kind}-@var{pass}
>>>> + -fenable-@var{kind}-@var{pass}
>>>>
>>>> Even in .texi files please two spaces after a full-stop.
>>>
>>> Done
>>>
>>>>
>>>> +extern void enable_disable_pass (const char *, bool);
>>>>
>>>> I'd rather have both enable_pass and disable_pass ;)
>>>
>>> Ok.
>>>
>>>>
>>>> +struct function;
>>>> +extern void pass_dump_function_header (FILE *, tree, struct function *);
>>>>
>>>> that's odd and probably should be split out, the function should
>>>> maybe reside in tree-pretty-print.c.
>>>
>>> Ok.
>>>
>>>>
>>>> Index: tree-ssa-loop-ivopts.c
>>>> ===================================================================
>>>> --- tree-ssa-loop-ivopts.c      (revision 173837)
>>>> +++ tree-ssa-loop-ivopts.c      (working copy)
>>>> @@ -3968,7 +3968,7 @@ get_computation_cost_at (struct ivopts_d
>>>>
>>>> well - doesn't belong here ;)
>>>
>>> Sorry -- many things in the same client -- not needed with your latest
>>> change anyway.
>>>
>>>>
>>>> +static hashval_t
>>>> +passr_hash (const void *p)
>>>> +{
>>>> +  const struct pass_registry *const s = (const struct pass_registry *const) p;
>>>> +  return htab_hash_string (s->unique_name);
>>>> +}
>>>> +
>>>> +/* Hash equal function  */
>>>> +
>>>> +static int
>>>> +passr_eq (const void *p1, const void *p2)
>>>> +{
>>>> +  const struct pass_registry *const s1 = (const struct pass_registry
>>>> *const) p1;
>>>> +  const struct pass_registry *const s2 = (const struct pass_registry
>>>> *const) p2;
>>>> +
>>>> +  return !strcmp (s1->unique_name, s2->unique_name);
>>>> +}
>>>>
>>>> you can use htab_hash_string and strcmp directly, no need for these
>>>> wrappers.
>>>
>>> The hashtable entry is not string in this case. It is pass_registry,
>>> thus the wrapper.
>>>
>>>>
>>>> +void
>>>> +register_pass_name (struct opt_pass *pass, const char *name)
>>>>
>>>> doesn't seem to need exporting, so don't and make it static.
>>>
>>> Done.
>>>
>>>>
>>>> +  if (!pass_name_tab)
>>>> +    pass_name_tab = htab_create (10, passr_hash, passr_eq, NULL);
>>>>
>>>> see above, the initial size should be larger - we have 223 passes at the
>>>> moment, so use 256.
>>>
>>> Done.
>>>
>>>>
>>>> +  else
>>>> +    return; /* Ignore plugin passes.  */
>>>>
>>>> ?  You mean they might clash?
>>>
>>> Yes, name clash.
>>>
>>>>
>>>> +struct opt_pass *
>>>> +get_pass_by_name (const char *name)
>>>>
>>>> doesn't need exporting either.
>>>
>>> Done.
>>>
>>>>
>>>> +      if (is_enable)
>>>> +        error ("unrecognized option -fenable");
>>>> +      else
>>>> +        error ("unrecognized option -fdisable");
>>>>
>>>> I think that should be fatal_error - Joseph?
>>>>
>>>> +      if (is_enable)
>>>> +        error ("unknown pass %s specified in -fenable", phase_name);
>>>> +      else
>>>> +        error ("unknown pass %s specified in -fdisble", phase_name);
>>>>
>>>> likewise.
>>>>
>>>> +      if (!enabled_pass_uid_range_tab)
>>>> +       enabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
>>>>
>>>> instead of using a hashtable here please use a VEC indexed by
>>>> the static_pass_number which shoud speed up
>>>
>>> Ok.  The reason I did not use it is because in most of the cases, the
>>> htab will be very small -- it is determined by the number of passes
>>> specified in the command line, while the VEC requires allocating const
>>> size array. Not an issue as long as by default the array is not
>>> allocated.
>>>
>>>>
>>>> +static bool
>>>> +is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
>>>> +                                       tree func, htab_t tab)
>>>> +{
>>>> +  struct uid_range **slot, *range, key;
>>>> +  int cgraph_uid;
>>>> +
>>>> +  if (!tab)
>>>> +    return false;
>>>> +
>>>> +  key.pass = pass;
>>>> +  slot = (struct uid_range **) htab_find_slot (tab, &key, NO_INSERT);
>>>> +  if (!slot || !*slot)
>>>> +    return false;
>>>>
>>>> and simplify the code quite a bit.
>>>>
>>>> +  cgraph_uid = func ? cgraph_get_node (func)->uid : 0;
>>>>
>>>> note that cgraph uids are recycled, so it might not be the best idea
>>>> to use them as discriminator (though I don't have a good idea how
>>>> to represent ranges without them).
>>>
>>> Yes. It is not a big problem as the blind search does not need to know
>>> the id->name mapping. Once the id s found, it can be easily discovered
>>> via dump.
>>>
>>>>
>>>> +  explicitly_enabled = is_pass_explicitly_enabled (pass,
>>>> current_function_decl);
>>>> +  explicitly_disabled = is_pass_explicitly_disabled (pass,
>>>> current_function_decl);
>>>> +
>>>>   current_pass = pass;
>>>>
>>>>   /* 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();
>>>> +  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
>>>>
>>>> so explicitly disabling wins over explicit enabling ;)  I think this
>>>> implementation detail and the fact that you always query both
>>>> hints at that the interface should be like
>>>>
>>>> gate_status = override_gate_status (pass, current_function_decl, gate_status);
>>>
>>> Done.
>>>
>>>>
>>>> instead.
>>>>
>>>> Thus, please split out the function header dumping changes and rework
>>>> the rest of the patch as suggested.
>>>
>>> Split out. The new patch is attached.
>>>
>>> Ok after testing is done?
>>>
>>> Thanks,
>>>
>>> David
>>>
>>>>
>>>> Thanks,
>>>> Richard.
>>>>
>>>>> --
>>>>> Joseph S. Myers
>>>>> joseph@codesourcery.com
>>>>>
>>>>
>>>
>>
>

[-- Attachment #2: header-print.p --]
[-- Type: application/octet-stream, Size: 5080 bytes --]

2011-05-30  David Li  <davidxl@google.com>

	* tree-pretty-print.c (pass_dump_function_header): New function.
	* final.c (rest_of_clean_state): Use header dumper.
	* tree-cfg.c (gimple_dump_cfg): Use header dumper.
	* passes.c (pass_init_dump_file): Use header dumper.

Index: tree-pretty-print.c
===================================================================
--- tree-pretty-print.c	(revision 174424)
+++ tree-pretty-print.c	(working copy)
@@ -3013,3 +3013,23 @@ pp_base_tree_identifier (pretty_printer 
     pp_append_text (pp, IDENTIFIER_POINTER (id),
 		    IDENTIFIER_POINTER (id) + IDENTIFIER_LENGTH (id));
 }
+
+void
+pass_dump_function_header (FILE *dump_file, tree fdecl, struct function *fun)
+{
+  const char *dname, *aname;
+  struct cgraph_node *node = cgraph_get_node (fdecl);
+  dname = lang_hooks.decl_printable_name (fdecl, 2);
+  aname = (IDENTIFIER_POINTER
+	   (DECL_ASSEMBLER_NAME (fdecl)));
+  fprintf (dump_file, "\n;; Function %s (%s, funcdef_no=%d, uid=%d)",
+           dname, aname, fun->funcdef_no, node->uid);
+  fprintf (dump_file, "%s\n\n",
+           node->frequency == NODE_FREQUENCY_HOT
+           ? " (hot)"
+           : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
+           ? " (unlikely executed)"
+           : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
+           ? " (executed once)"
+           : "");
+}
Index: tree-pretty-print.h
===================================================================
--- tree-pretty-print.h	(revision 174422)
+++ tree-pretty-print.h	(working copy)
@@ -50,6 +50,8 @@ extern void debug_generic_expr (tree);
 extern void debug_generic_stmt (tree);
 extern void debug_tree_chain (tree);
 extern void percent_K_format (text_info *);
+struct function;
+extern void pass_dump_function_header (FILE *, tree, struct function *);
 
 /* In toplev.c  */
 extern bool default_tree_printer (pretty_printer *, text_info *, const char *,
Index: final.c
===================================================================
--- final.c	(revision 174422)
+++ final.c	(working copy)
@@ -83,6 +83,7 @@ along with GCC; see the file COPYING3.  
 #include "ggc.h"
 #include "cfgloop.h"
 #include "params.h"
+#include "tree-pretty-print.h"
 
 #ifdef XCOFF_DEBUGGING_INFO
 #include "xcoffout.h"		/* Needed for external data
@@ -4360,20 +4361,7 @@ rest_of_clean_state (void)
 	}
       else
 	{
-	  const char *aname;
-	  struct cgraph_node *node = cgraph_get_node (current_function_decl);
-
-	  aname = (IDENTIFIER_POINTER
-		   (DECL_ASSEMBLER_NAME (current_function_decl)));
-	  fprintf (final_output, "\n;; Function (%s) %s\n\n", aname,
-	     node->frequency == NODE_FREQUENCY_HOT
-	     ? " (hot)"
-	     : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
-	     ? " (unlikely executed)"
-	     : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
-	     ? " (executed once)"
-	     : "");
-
+	  pass_dump_function_header (final_output, current_function_decl, cfun);
 	  flag_dump_noaddr = flag_dump_unnumbered = 1;
 	  if (flag_compare_debug_opt || flag_compare_debug)
 	    dump_flags |= TDF_NOUID;
Index: tree-cfg.c
===================================================================
--- tree-cfg.c	(revision 174422)
+++ tree-cfg.c	(working copy)
@@ -2052,11 +2052,7 @@ gimple_dump_cfg (FILE *file, int flags)
 {
   if (flags & TDF_DETAILS)
     {
-      const char *funcname
-	= lang_hooks.decl_printable_name (current_function_decl, 2);
-
-      fputc ('\n', file);
-      fprintf (file, ";; Function %s\n\n", funcname);
+      pass_dump_function_header (file, current_function_decl, cfun);
       fprintf (file, ";; \n%d basic blocks, %d edges, last basic block %d.\n\n",
 	       n_basic_blocks, n_edges, last_basic_block);
 
Index: passes.c
===================================================================
--- passes.c	(revision 174423)
+++ passes.c	(working copy)
@@ -74,6 +74,7 @@ along with GCC; see the file COPYING3.  
 #include "lto-streamer.h"
 #include "plugin.h"
 #include "ipa-utils.h"
+#include "tree-pretty-print.h"
 
 #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
 #include "dwarf2out.h"
@@ -1637,21 +1638,7 @@ pass_init_dump_file (struct opt_pass *pa
       dump_file_name = get_dump_file_name (pass->static_pass_number);
       dump_file = dump_begin (pass->static_pass_number, &dump_flags);
       if (dump_file && current_function_decl)
-	{
-	  const char *dname, *aname;
-	  struct cgraph_node *node = cgraph_get_node (current_function_decl);
-	  dname = lang_hooks.decl_printable_name (current_function_decl, 2);
-	  aname = (IDENTIFIER_POINTER
-		   (DECL_ASSEMBLER_NAME (current_function_decl)));
-	  fprintf (dump_file, "\n;; Function %s (%s)%s\n\n", dname, aname,
-	     node->frequency == NODE_FREQUENCY_HOT
-	     ? " (hot)"
-	     : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
-	     ? " (unlikely executed)"
-	     : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
-	     ? " (executed once)"
-	     : "");
-	}
+        pass_dump_function_header (dump_file, current_function_decl, cfun);
       return initializing_dump;
     }
   else

[-- Attachment #3: pass-name-clean.p --]
[-- Type: application/octet-stream, Size: 2570 bytes --]

Index: predict.c
===================================================================
--- predict.c	(revision 174422)
+++ predict.c	(working copy)
@@ -2306,7 +2306,7 @@ struct gimple_opt_pass pass_profile =
 {
  {
   GIMPLE_PASS,
-  "profile",				/* name */
+  "profile_estimate",			/* name */
   gate_estimate_probability,		/* gate */
   tree_estimate_probability_driver,	/* execute */
   NULL,					/* sub */
Index: ipa.c
===================================================================
--- ipa.c	(revision 174422)
+++ ipa.c	(working copy)
@@ -1145,7 +1145,7 @@ struct ipa_opt_pass_d pass_ipa_profile =
 {
  {
   IPA_PASS,
-  "ipa-profile",			/* name */
+  "profile_estimate",			/* name */
   gate_ipa_profile,			/* gate */
   ipa_profile,			        /* execute */
   NULL,					/* sub */
Index: except.c
===================================================================
--- except.c	(revision 174422)
+++ except.c	(working copy)
@@ -1457,7 +1457,7 @@ struct rtl_opt_pass pass_rtl_eh =
 {
  {
   RTL_PASS,
-  "rtl eh",                             /* name */
+  "rtl_eh",                             /* name */
   gate_handle_eh,                       /* gate */
   rest_of_handle_eh,			/* execute */
   NULL,                                 /* sub */
Index: tree-profile.c
===================================================================
--- tree-profile.c	(revision 174422)
+++ tree-profile.c	(working copy)
@@ -579,7 +579,7 @@ struct simple_ipa_opt_pass pass_ipa_tree
 {
  {
   SIMPLE_IPA_PASS,
-  "tree_profile_ipa",                  /* name */
+  "profile",  		               /* name */
   gate_tree_profile_ipa,               /* gate */
   tree_profiling,                      /* execute */
   NULL,                                /* sub */
Index: dce.c
===================================================================
--- dce.c	(revision 174422)
+++ dce.c	(working copy)
@@ -734,7 +734,7 @@ struct rtl_opt_pass pass_ud_rtl_dce =
 {
  {
   RTL_PASS,
-  "ud dce",                             /* name */
+  "ud_dce",                             /* name */
   gate_ud_dce,                          /* gate */
   rest_of_handle_ud_dce,                /* execute */
   NULL,                                 /* sub */
@@ -1086,7 +1086,7 @@ struct rtl_opt_pass pass_fast_rtl_dce =
 {
  {
   RTL_PASS,
-  "rtl dce",                            /* name */
+  "rtl_dce",                            /* name */
   gate_fast_dce,                        /* gate */
   rest_of_handle_fast_dce,              /* execute */
   NULL,                                 /* sub */

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-31  4:54                   ` Xinliang David Li
@ 2011-05-31  7:05                     ` Xinliang David Li
  2011-05-31 10:03                       ` Richard Guenther
  2011-06-01 19:19                       ` H.J. Lu
  2011-05-31  9:57                     ` Richard Guenther
  1 sibling, 2 replies; 32+ messages in thread
From: Xinliang David Li @ 2011-05-31  7:05 UTC (permalink / raw)
  To: GCC Patches; +Cc: reply, Richard Guenther, Jan Hubicka

[-- Attachment #1: Type: text/plain, Size: 10258 bytes --]

This is the complete patch for pass name fixes (with test case changes).

David


On Mon, May 30, 2011 at 1:16 PM, Xinliang David Li <davidxl@google.com> wrote:
> The attached are two simple follow up patches
>
> 1) the first patch does some refactorization on function header
> dumping (with more information printed)
>
> 2) the second patch cleans up some pass names. Part of the cleanup
> results from a previous discussion with Honza -- a) rename
> 'tree_profile_ipa' into 'profile', and make 'ipa_profile' and
> 'profile' into 'profile_estimate'. The rest of cleanups are needed to
> make sure pass names are unique.
>
> Ok for trunk?
>
> Thanks,
>
> David
>
> On Fri, May 27, 2011 at 2:58 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Fri, May 27, 2011 at 12:02 AM, Xinliang David Li <davidxl@google.com> wrote:
>>> The latest version that only exports 2 functions from passes.c.
>>
>> Ok with ...
>>
>> @@ -637,4 +637,8 @@ extern bool first_pass_instance;
>>  /* Declare for plugins.  */
>>  extern void do_per_function_toporder (void (*) (void *), void *);
>>
>> +extern void disable_pass (const char *);
>> +extern void enable_pass (const char *);
>> +struct function;
>> +
>>
>> struct function forward decl removed.
>>
>> +  explicitly_enabled = is_pass_explicitly_enabled (pass, func);
>> +  explicitly_disabled = is_pass_explicitly_disabled (pass, func);
>>
>> both functions inlined here and removed.
>>
>> +#define MAX_PASS_ID 512
>>
>> this removed and instead a VEC_safe_grow_cleared () or VEC_length ()
>> before the accesses.
>>
>> +-fenable-ipa-@var{pass} @gol
>> +-fenable-rtl-@var{pass} @gol
>> +-fenable-rtl-@var{pass}=@var{range-list} @gol
>> +-fenable-tree-@var{pass} @gol
>> +-fenable-tree-@var{pass}=@var{range-list} @gol
>>
>> -fenable-@var{kind}-@var{pass}, etc.
>>
>> +@item -fdisable-@var{ipa|tree|rtl}-@var{pass}
>> +@itemx -fenable-@var{ipa|tree|rtl}-@var{pass}
>> +@itemx -fdisable-@var{tree|rtl}-@var{pass}=@var{range-list}
>> +@itemx -fenable-@var{tree|rtl}-@var{pass}=@var{range-list}
>>
>> likewise.
>>
>> Thanks,
>> Richard.
>>
>>> David
>>>
>>> On Thu, May 26, 2011 at 2:04 PM, Xinliang David Li <davidxl@google.com> wrote:
>>>> On Thu, May 26, 2011 at 2:04 AM, Richard Guenther
>>>> <richard.guenther@gmail.com> wrote:
>>>>> On Wed, May 25, 2011 at 6:53 PM, Joseph S. Myers
>>>>> <joseph@codesourcery.com> wrote:
>>>>>> On Wed, 25 May 2011, Xinliang David Li wrote:
>>>>>>
>>>>>>> Ping. The link to the message:
>>>>>>>
>>>>>>> http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01303.html
>>>>>>
>>>>>> I don't consider this an option handling patch.  Patches adding whole new
>>>>>> features involving new options should be reviewed by maintainers for the
>>>>>> part of the compiler relevant to those features (since there isn't a pass
>>>>>> manager maintainer, I guess that means middle-end).
>>>>>
>>>>> Hmm, I suppose then you reviewed the option handling parts and they
>>>>> are ok?  Those globbing options always cause headache to me.
>>>>>
>>>>> +-fenable-ipa-@var{pass} @gol
>>>>> +-fenable-rtl-@var{pass} @gol
>>>>> +-fenable-rtl-@var{pass}=@var{range-list} @gol
>>>>> +-fenable-tree-@var{pass} @gol
>>>>>
>>>>> so, no -fenable-tree-@var{pass}=@var{range-list}?
>>>>>
>>>>
>>>> Missed. Will add.
>>>>
>>>>
>>>>> Does the pass name match 1:1 with the dump file name?  In which
>>>>> case
>>>>
>>>> Yes.
>>>>
>>>>>
>>>>> +Disable ipa pass @var{pass}. @var{pass} is the pass name. If the same
>>>>> pass is statically invoked in the compiler multiple times, the pass
>>>>> name should be appended with a sequential number starting from 1.
>>>>>
>>>>> isn't true as passes that are invoked only a single time lack the number
>>>>> suffix (yes, I'd really like that to be changed ...)
>>>>
>>>> Yes, pass with single static instance does not need number suffix.
>>>>
>>>>>
>>>>> Please break likes also in .texi files and stick to 80 columns.
>>>>
>>>> Done.
>>>>
>>>>>  Please
>>>>> document that these options are debugging options and regular
>>>>> options for enabling/disabling passes should be used.  I would suggest
>>>>> to group documentation differently and document -fenable-* and
>>>>> -fdisable-*, thus,
>>>>>
>>>>> + -fdisable-@var{kind}-@var{pass}
>>>>> + -fenable-@var{kind}-@var{pass}
>>>>>
>>>>> Even in .texi files please two spaces after a full-stop.
>>>>
>>>> Done
>>>>
>>>>>
>>>>> +extern void enable_disable_pass (const char *, bool);
>>>>>
>>>>> I'd rather have both enable_pass and disable_pass ;)
>>>>
>>>> Ok.
>>>>
>>>>>
>>>>> +struct function;
>>>>> +extern void pass_dump_function_header (FILE *, tree, struct function *);
>>>>>
>>>>> that's odd and probably should be split out, the function should
>>>>> maybe reside in tree-pretty-print.c.
>>>>
>>>> Ok.
>>>>
>>>>>
>>>>> Index: tree-ssa-loop-ivopts.c
>>>>> ===================================================================
>>>>> --- tree-ssa-loop-ivopts.c      (revision 173837)
>>>>> +++ tree-ssa-loop-ivopts.c      (working copy)
>>>>> @@ -3968,7 +3968,7 @@ get_computation_cost_at (struct ivopts_d
>>>>>
>>>>> well - doesn't belong here ;)
>>>>
>>>> Sorry -- many things in the same client -- not needed with your latest
>>>> change anyway.
>>>>
>>>>>
>>>>> +static hashval_t
>>>>> +passr_hash (const void *p)
>>>>> +{
>>>>> +  const struct pass_registry *const s = (const struct pass_registry *const) p;
>>>>> +  return htab_hash_string (s->unique_name);
>>>>> +}
>>>>> +
>>>>> +/* Hash equal function  */
>>>>> +
>>>>> +static int
>>>>> +passr_eq (const void *p1, const void *p2)
>>>>> +{
>>>>> +  const struct pass_registry *const s1 = (const struct pass_registry
>>>>> *const) p1;
>>>>> +  const struct pass_registry *const s2 = (const struct pass_registry
>>>>> *const) p2;
>>>>> +
>>>>> +  return !strcmp (s1->unique_name, s2->unique_name);
>>>>> +}
>>>>>
>>>>> you can use htab_hash_string and strcmp directly, no need for these
>>>>> wrappers.
>>>>
>>>> The hashtable entry is not string in this case. It is pass_registry,
>>>> thus the wrapper.
>>>>
>>>>>
>>>>> +void
>>>>> +register_pass_name (struct opt_pass *pass, const char *name)
>>>>>
>>>>> doesn't seem to need exporting, so don't and make it static.
>>>>
>>>> Done.
>>>>
>>>>>
>>>>> +  if (!pass_name_tab)
>>>>> +    pass_name_tab = htab_create (10, passr_hash, passr_eq, NULL);
>>>>>
>>>>> see above, the initial size should be larger - we have 223 passes at the
>>>>> moment, so use 256.
>>>>
>>>> Done.
>>>>
>>>>>
>>>>> +  else
>>>>> +    return; /* Ignore plugin passes.  */
>>>>>
>>>>> ?  You mean they might clash?
>>>>
>>>> Yes, name clash.
>>>>
>>>>>
>>>>> +struct opt_pass *
>>>>> +get_pass_by_name (const char *name)
>>>>>
>>>>> doesn't need exporting either.
>>>>
>>>> Done.
>>>>
>>>>>
>>>>> +      if (is_enable)
>>>>> +        error ("unrecognized option -fenable");
>>>>> +      else
>>>>> +        error ("unrecognized option -fdisable");
>>>>>
>>>>> I think that should be fatal_error - Joseph?
>>>>>
>>>>> +      if (is_enable)
>>>>> +        error ("unknown pass %s specified in -fenable", phase_name);
>>>>> +      else
>>>>> +        error ("unknown pass %s specified in -fdisble", phase_name);
>>>>>
>>>>> likewise.
>>>>>
>>>>> +      if (!enabled_pass_uid_range_tab)
>>>>> +       enabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
>>>>>
>>>>> instead of using a hashtable here please use a VEC indexed by
>>>>> the static_pass_number which shoud speed up
>>>>
>>>> Ok.  The reason I did not use it is because in most of the cases, the
>>>> htab will be very small -- it is determined by the number of passes
>>>> specified in the command line, while the VEC requires allocating const
>>>> size array. Not an issue as long as by default the array is not
>>>> allocated.
>>>>
>>>>>
>>>>> +static bool
>>>>> +is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
>>>>> +                                       tree func, htab_t tab)
>>>>> +{
>>>>> +  struct uid_range **slot, *range, key;
>>>>> +  int cgraph_uid;
>>>>> +
>>>>> +  if (!tab)
>>>>> +    return false;
>>>>> +
>>>>> +  key.pass = pass;
>>>>> +  slot = (struct uid_range **) htab_find_slot (tab, &key, NO_INSERT);
>>>>> +  if (!slot || !*slot)
>>>>> +    return false;
>>>>>
>>>>> and simplify the code quite a bit.
>>>>>
>>>>> +  cgraph_uid = func ? cgraph_get_node (func)->uid : 0;
>>>>>
>>>>> note that cgraph uids are recycled, so it might not be the best idea
>>>>> to use them as discriminator (though I don't have a good idea how
>>>>> to represent ranges without them).
>>>>
>>>> Yes. It is not a big problem as the blind search does not need to know
>>>> the id->name mapping. Once the id s found, it can be easily discovered
>>>> via dump.
>>>>
>>>>>
>>>>> +  explicitly_enabled = is_pass_explicitly_enabled (pass,
>>>>> current_function_decl);
>>>>> +  explicitly_disabled = is_pass_explicitly_disabled (pass,
>>>>> current_function_decl);
>>>>> +
>>>>>   current_pass = pass;
>>>>>
>>>>>   /* 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();
>>>>> +  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
>>>>>
>>>>> so explicitly disabling wins over explicit enabling ;)  I think this
>>>>> implementation detail and the fact that you always query both
>>>>> hints at that the interface should be like
>>>>>
>>>>> gate_status = override_gate_status (pass, current_function_decl, gate_status);
>>>>
>>>> Done.
>>>>
>>>>>
>>>>> instead.
>>>>>
>>>>> Thus, please split out the function header dumping changes and rework
>>>>> the rest of the patch as suggested.
>>>>
>>>> Split out. The new patch is attached.
>>>>
>>>> Ok after testing is done?
>>>>
>>>> Thanks,
>>>>
>>>> David
>>>>
>>>>>
>>>>> Thanks,
>>>>> Richard.
>>>>>
>>>>>> --
>>>>>> Joseph S. Myers
>>>>>> joseph@codesourcery.com
>>>>>>
>>>>>
>>>>
>>>
>>
>

[-- Attachment #2: pass-name-cleanup.p --]
[-- Type: application/octet-stream, Size: 20964 bytes --]

2011-05-30  David Li  <davidxl@google.com>

	* predict.c : Change pass name
	* ipa.c: Ditto.
	* dce.c: Ditto.
	* tree-profile.c: Ditto.
	* except.c: Ditto.

2011-05-30  David Li  <davidxl@google.com>

	* testsuite/gcc.dg/profile-dir-1.c: Change pass name.
	* testsuite/gcc.dg/profile-dir-2.c: Ditto.
	* testsuite/gcc.dg/tree-ssa/dump-1.c: Ditto.
	* testsuite/gcc.dg/tree-ssa/loop-25.c: Ditto.
	* testsuite/gcc.dg/tree-prof/stringop-1.c: Ditto.
	* testsuite/gcc.dg/tree-prof/update-loopch.c: Ditto.
	* testsuite/gcc.dg/tree-prof/stringop-2.c: Ditto.
	* testsuite/gcc.dg/tree-prof/ic-misattribution-1.c: Ditto.
	* testsuite/gcc.dg/tree-prof/ic-misattribution-1a.c: Ditto.
	* testsuite/gcc.dg/tree-prof/indir-call-prof.c: Ditto.
	* testsuite/gcc.dg/tree-prof/val-prof-1.c: Ditto.
	* testsuite/gcc.dg/tree-prof/val-prof-2.c: Ditto.
	* testsuite/gcc.dg/tree-prof/val-prof-3.c: Ditto.
	* testsuite/gcc.dg/tree-prof/val-prof-4.c: Ditto.
	* testsuite/gcc.dg/tree-prof/val-prof-5.c: Ditto.
	* testsuite/gcc.dg/tree-prof/val-prof-7.c: Ditto.
	* testsuite/gcc.dg/profile-dir-3.c: Ditto.
	* testsuite/g++.dg/tree-prof/indir-call-prof.C: Ditto.

Index: predict.c
===================================================================
--- predict.c	(revision 174422)
+++ predict.c	(working copy)
@@ -2306,7 +2306,7 @@ struct gimple_opt_pass pass_profile =
 {
  {
   GIMPLE_PASS,
-  "profile",				/* name */
+  "profile_estimate",			/* name */
   gate_estimate_probability,		/* gate */
   tree_estimate_probability_driver,	/* execute */
   NULL,					/* sub */
Index: ipa.c
===================================================================
--- ipa.c	(revision 174422)
+++ ipa.c	(working copy)
@@ -1145,7 +1145,7 @@ struct ipa_opt_pass_d pass_ipa_profile =
 {
  {
   IPA_PASS,
-  "ipa-profile",			/* name */
+  "profile_estimate",			/* name */
   gate_ipa_profile,			/* gate */
   ipa_profile,			        /* execute */
   NULL,					/* sub */
Index: dce.c
===================================================================
--- dce.c	(revision 174422)
+++ dce.c	(working copy)
@@ -734,7 +734,7 @@ struct rtl_opt_pass pass_ud_rtl_dce =
 {
  {
   RTL_PASS,
-  "ud dce",                             /* name */
+  "ud_dce",                             /* name */
   gate_ud_dce,                          /* gate */
   rest_of_handle_ud_dce,                /* execute */
   NULL,                                 /* sub */
@@ -1086,7 +1086,7 @@ struct rtl_opt_pass pass_fast_rtl_dce =
 {
  {
   RTL_PASS,
-  "rtl dce",                            /* name */
+  "rtl_dce",                            /* name */
   gate_fast_dce,                        /* gate */
   rest_of_handle_fast_dce,              /* execute */
   NULL,                                 /* sub */
Index: tree-profile.c
===================================================================
--- tree-profile.c	(revision 174422)
+++ tree-profile.c	(working copy)
@@ -579,7 +579,7 @@ struct simple_ipa_opt_pass pass_ipa_tree
 {
  {
   SIMPLE_IPA_PASS,
-  "tree_profile_ipa",                  /* name */
+  "profile",  		               /* name */
   gate_tree_profile_ipa,               /* gate */
   tree_profiling,                      /* execute */
   NULL,                                /* sub */
Index: except.c
===================================================================
--- except.c	(revision 174422)
+++ except.c	(working copy)
@@ -1457,7 +1457,7 @@ struct rtl_opt_pass pass_rtl_eh =
 {
  {
   RTL_PASS,
-  "rtl eh",                             /* name */
+  "rtl_eh",                             /* name */
   gate_handle_eh,                       /* gate */
   rest_of_handle_eh,			/* execute */
   NULL,                                 /* sub */
Index: testsuite/gcc.dg/profile-dir-1.c
===================================================================
--- testsuite/gcc.dg/profile-dir-1.c	(revision 174422)
+++ testsuite/gcc.dg/profile-dir-1.c	(working copy)
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
-/* { dg-options "-O -fprofile-generate=. -fdump-ipa-tree_profile_ipa" } */
-/* { dg-final { scan-ipa-dump " ./profile-dir-1.gcda" "tree_profile_ipa" } } */
+/* { dg-options "-O -fprofile-generate=. -fdump-ipa-profile" } */
+/* { dg-final { scan-ipa-dump " ./profile-dir-1.gcda" "profile" } } */
 
 int
 main(void)
@@ -8,4 +8,4 @@ main(void)
   return 0;
 }
 
-/* { dg-final { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/profile-dir-2.c
===================================================================
--- testsuite/gcc.dg/profile-dir-2.c	(revision 174422)
+++ testsuite/gcc.dg/profile-dir-2.c	(working copy)
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
-/* { dg-options "-O -fprofile-generate -fdump-ipa-tree_profile_ipa" } */
-/* { dg-final { scan-ipa-dump "/profile-dir-2.gcda" "tree_profile_ipa" } } */
+/* { dg-options "-O -fprofile-generate -fdump-ipa-profile" } */
+/* { dg-final { scan-ipa-dump "/profile-dir-2.gcda" "profile" } } */
 
 int
 main(void)
@@ -8,4 +8,4 @@ main(void)
   return 0;
 }
 
-/* { dg-final { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-ssa/dump-1.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/dump-1.c	(revision 174422)
+++ testsuite/gcc.dg/tree-ssa/dump-1.c	(working copy)
@@ -1,9 +1,9 @@
 /* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-profile-details" } */
+/* { dg-options "-O1 -fdump-tree-profile_estimate-details" } */
 
 int f(void)
 {
   return 0;
 }
 
-/* { dg-final { cleanup-tree-dump "profile" } } */
+/* { dg-final { cleanup-tree-dump "profile_estimate" } } */
Index: testsuite/gcc.dg/tree-ssa/loop-25.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/loop-25.c	(revision 174422)
+++ testsuite/gcc.dg/tree-ssa/loop-25.c	(working copy)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-profile" } */
+/* { dg-options "-O1 -fdump-tree-profile_estimate" } */
 
 int foo(void);
 void bla(void);
@@ -118,12 +118,12 @@ void test5 (void)
     }
 }
 
-/* { dg-final { scan-tree-dump-times "Disambiguating loop" 5 "profile" } } */
+/* { dg-final { scan-tree-dump-times "Disambiguating loop" 5 "profile_estimate" } } */
 /* For the following xfail marks, see PR35629.  */
-/* { dg-final { scan-tree-dump-times "Found latch edge" 5 "profile" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump-times "Merged latch edges" 2 "profile" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump-times "4 loops found" 2 "profile" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump-times "3 loops found" 2 "profile" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump-times "2 loops found" 1 "profile" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "Found latch edge" 5 "profile_estimate" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "Merged latch edges" 2 "profile_estimate" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "4 loops found" 2 "profile_estimate" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "3 loops found" 2 "profile_estimate" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "2 loops found" 1 "profile_estimate" { xfail *-*-* } } } */
 
-/* { dg-final { cleanup-tree-dump "profile" } } */
+/* { dg-final { cleanup-tree-dump "profile_estimate" } } */
Index: testsuite/gcc.dg/tree-prof/stringop-1.c
===================================================================
--- testsuite/gcc.dg/tree-prof/stringop-1.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/stringop-1.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-profile" } */
 int a[1000];
 int b[1000];
 int size=1;
@@ -13,10 +13,10 @@ main()
     }
    return 0;
 }
-/* { dg-final-use { scan-ipa-dump "Single value 4 stringop" "tree_profile_ipa"} } */
+/* { dg-final-use { scan-ipa-dump "Single value 4 stringop" "profile"} } */
 /* Really this ought to simplify into assignment, but we are not there yet.  */
 /* a[0] = b[0] is what we fold the resulting memcpy into.  */
 /* { dg-final-use { scan-tree-dump " = MEM.*&b" "optimized"} } */
 /* { dg-final-use { scan-tree-dump "MEM.*&a\\\] = " "optimized"} } */
 /* { dg-final-use { cleanup-tree-dump "optimized" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-prof/update-loopch.c
===================================================================
--- testsuite/gcc.dg/tree-prof/update-loopch.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/update-loopch.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-ipa-tree_profile_ipa-blocks -fdump-tree-optimized-blocks" } */
+/* { dg-options "-O2 -fdump-ipa-profile-blocks -fdump-tree-optimized-blocks" } */
 int max = 33333;
 int a[8];
 int
@@ -14,8 +14,8 @@ main ()
 /* Loop header copying will peel away the initial conditional, so the loop body
    is once reached directly from entry point of function, rest via loopback
    edge.  */
-/* { dg-final-use { scan-ipa-dump "count:33333" "tree_profile_ipa"} } */
+/* { dg-final-use { scan-ipa-dump "count:33333" "profile"} } */
 /* { dg-final-use { scan-tree-dump "count:33332" "optimized"} } */
 /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
 /* { dg-final-use { cleanup-tree-dump "optimized" } } */
Index: testsuite/gcc.dg/tree-prof/stringop-2.c
===================================================================
--- testsuite/gcc.dg/tree-prof/stringop-2.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/stringop-2.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-profile" } */
 int a[1000];
 int b[1000];
 int size=1;
@@ -13,8 +13,8 @@ main()
     }
    return 0;
 }
-/* { dg-final-use { scan-ipa-dump "Single value 4 stringop" "tree_profile_ipa"} } */
+/* { dg-final-use { scan-ipa-dump "Single value 4 stringop" "profile"} } */
 /* The versioned memset of size 4 should be optimized to an assignment.  */
 /* { dg-final-use { scan-tree-dump "a\\\[0\\\] = 168430090" "optimized"} } */
 /* { dg-final-use { cleanup-tree-dump "optimized" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-prof/ic-misattribution-1.c
===================================================================
--- testsuite/gcc.dg/tree-prof/ic-misattribution-1.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/ic-misattribution-1.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-ipa-tree_profile_ipa" } */
+/* { dg-options "-O2 -fdump-ipa-profile" } */
 /* { dg-additional-sources "ic-misattribution-1a.c" } */
 
 extern void other_caller (void);
@@ -15,5 +15,5 @@ caller(void (*func) (void))
   func ();
 }
 
-/* { dg-final-use { scan-ipa-dump "hist->count 1 hist->all 1" "tree_profile_ipa" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { scan-ipa-dump "hist->count 1 hist->all 1" "profile" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-prof/ic-misattribution-1a.c
===================================================================
--- testsuite/gcc.dg/tree-prof/ic-misattribution-1a.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/ic-misattribution-1a.c	(working copy)
@@ -19,4 +19,4 @@ main ()
   return 0;
 }
 
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-prof/indir-call-prof.c
===================================================================
--- testsuite/gcc.dg/tree-prof/indir-call-prof.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/indir-call-prof.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-profile" } */
 
 static int a1 (void)
 {
@@ -37,7 +37,7 @@ main (void)
   return 0;
 }
 
-/* { dg-final-use { scan-ipa-dump "Indirect call -> direct call.* a1 transformation on insn" "tree_profile_ipa"} } */
+/* { dg-final-use { scan-ipa-dump "Indirect call -> direct call.* a1 transformation on insn" "profile"} } */
 /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
 /* { dg-final-use { cleanup-tree-dump "optimized" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-prof/val-prof-1.c
===================================================================
--- testsuite/gcc.dg/tree-prof/val-prof-1.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/val-prof-1.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-profile" } */
 int a[1000];
 int b = 256;
 int c = 257;
@@ -15,8 +15,8 @@ main ()
     }
   return 0;
 }
-/* { dg-final-use { scan-ipa-dump "Div.mod by constant n_\[0-9\]*=257 transformation on insn" "tree_profile_ipa"} } */
+/* { dg-final-use { scan-ipa-dump "Div.mod by constant n_\[0-9\]*=257 transformation on insn" "profile"} } */
 /* { dg-final-use { scan-tree-dump "if \\(n_\[0-9\]* != 257\\)" "optimized"} } */
 /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
 /* { dg-final-use { cleanup-tree-dump "optimized" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-prof/val-prof-2.c
===================================================================
--- testsuite/gcc.dg/tree-prof/val-prof-2.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/val-prof-2.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-profile" } */
 unsigned int a[1000];
 unsigned int b = 256;
 unsigned int c = 1024;
@@ -23,10 +23,10 @@ main ()
     }
   return 0;
 }
-/* { dg-final-use { scan-ipa-dump "Mod power of 2 transformation on insn" "tree_profile_ipa" } } */
+/* { dg-final-use { scan-ipa-dump "Mod power of 2 transformation on insn" "profile" } } */
 /* This is part of code checking that n is power of 2, so we are sure that the transformation
    didn't get optimized out.  */
 /* { dg-final-use { scan-tree-dump "n_\[0-9\]* \\+ (4294967295|0x0*ffffffff)" "optimized"} } */
 /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
 /* { dg-final-use { cleanup-tree-dump "optimized" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-prof/val-prof-3.c
===================================================================
--- testsuite/gcc.dg/tree-prof/val-prof-3.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/val-prof-3.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-profile" } */
 unsigned int a[1000];
 unsigned int b = 257;
 unsigned int c = 1023;
@@ -23,10 +23,10 @@ main ()
     }
   return 0;
 }
-/* { dg-final-use { scan-ipa-dump "Mod subtract transformation on insn" "tree_profile_ipa" } } */
+/* { dg-final-use { scan-ipa-dump "Mod subtract transformation on insn" "profile" } } */
 /* This is part of code checking that n is greater than the divisor so we are sure that it
    didn't get optimized out.  */
 /* { dg-final-use { scan-tree-dump "if \\(n_\[0-9\]* \\>" "optimized"} } */
 /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
 /* { dg-final-use { cleanup-tree-dump "optimized" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-prof/val-prof-4.c
===================================================================
--- testsuite/gcc.dg/tree-prof/val-prof-4.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/val-prof-4.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-profile" } */
 unsigned int a[1000];
 unsigned int b = 999;
 unsigned int c = 1002;
@@ -23,10 +23,10 @@ main ()
     }
   return 0;
 }
-/* { dg-final-use { scan-ipa-dump "Mod subtract transformation on insn" "tree_profile_ipa" } } */
+/* { dg-final-use { scan-ipa-dump "Mod subtract transformation on insn" "profile" } } */
 /* This is part of code checking that n is greater than the divisor so we are sure that it
    didn't get optimized out.  */
 /* { dg-final-use { scan-tree-dump "if \\(n_\[0-9\]* \\>" "optimized"} } */
 /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
 /* { dg-final-use { cleanup-tree-dump "optimized" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-prof/val-prof-5.c
===================================================================
--- testsuite/gcc.dg/tree-prof/val-prof-5.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/val-prof-5.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-profile" } */
 int a[1000];
 int b=997;
 main()
@@ -11,7 +11,7 @@ main()
 			a[i]/=b;
 	return 0;
 }
-/* { dg-final-use { scan-ipa-dump "Div.mod by constant b.*=997 transformation on insn" "tree_profile_ipa" } } */
+/* { dg-final-use { scan-ipa-dump "Div.mod by constant b.*=997 transformation on insn" "profile" } } */
 /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
 /* { dg-final-use { cleanup-tree-dump "optimized" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-prof/val-prof-7.c
===================================================================
--- testsuite/gcc.dg/tree-prof/val-prof-7.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/val-prof-7.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-ipa-tree_profile_ipa -mtune=core2" } */
+/* { dg-options "-O2 -fdump-ipa-profile -mtune=core2" } */
 /* { dg-skip-if "" { ! { i?86-*-* x86_64-*-* } } { "*" } { "" } } */
 
 #include <strings.h>
@@ -22,5 +22,5 @@ int main() {
   return 0;
 }
 
-/* { dg-final-use { scan-ipa-dump "Single value 8 stringop transformation on bzero" "tree_profile_ipa" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { scan-ipa-dump "Single value 8 stringop transformation on bzero" "profile" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/profile-dir-3.c
===================================================================
--- testsuite/gcc.dg/profile-dir-3.c	(revision 174422)
+++ testsuite/gcc.dg/profile-dir-3.c	(working copy)
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
-/* { dg-options "-O -fprofile-generate -fprofile-dir=. -fdump-ipa-tree_profile_ipa" } */
-/* { dg-final { scan-ipa-dump " ./profile-dir-3.gcda" "tree_profile_ipa" } } */
+/* { dg-options "-O -fprofile-generate -fprofile-dir=. -fdump-ipa-profile" } */
+/* { dg-final { scan-ipa-dump " ./profile-dir-3.gcda" "profile" } } */
 
 int
 main(void)
@@ -8,4 +8,4 @@ main(void)
   return 0;
 }
 
-/* { dg-final { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final { cleanup-ipa-dump "profile" } } */
Index: testsuite/g++.dg/tree-prof/indir-call-prof.C
===================================================================
--- testsuite/g++.dg/tree-prof/indir-call-prof.C	(revision 174422)
+++ testsuite/g++.dg/tree-prof/indir-call-prof.C	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-profile" } */
 
 struct A {
   A () {}
@@ -33,7 +33,7 @@ main (void)
   return 0;
 }
 
-/* { dg-final-use { scan-ipa-dump "Indirect call -> direct call.* AA transformation on insn" "tree_profile_ipa" } } */
+/* { dg-final-use { scan-ipa-dump "Indirect call -> direct call.* AA transformation on insn" "profile" } } */
 /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized" } } */
 /* { dg-final-use { cleanup-tree-dump "optimized" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-31  4:54                   ` Xinliang David Li
  2011-05-31  7:05                     ` Xinliang David Li
@ 2011-05-31  9:57                     ` Richard Guenther
  2011-05-31 17:30                       ` Xinliang David Li
  1 sibling, 1 reply; 32+ messages in thread
From: Richard Guenther @ 2011-05-31  9:57 UTC (permalink / raw)
  To: Xinliang David Li; +Cc: GCC Patches, reply, Jan Hubicka

On Mon, May 30, 2011 at 10:16 PM, Xinliang David Li <davidxl@google.com> wrote:
> The attached are two simple follow up patches
>
> 1) the first patch does some refactorization on function header
> dumping (with more information printed)
>
> 2) the second patch cleans up some pass names. Part of the cleanup
> results from a previous discussion with Honza -- a) rename
> 'tree_profile_ipa' into 'profile', and make 'ipa_profile' and
> 'profile' into 'profile_estimate'. The rest of cleanups are needed to
> make sure pass names are unique.
>
> Ok for trunk?

+
+void
+pass_dump_function_header (FILE *dump_file, tree fdecl, struct function *fun)

This function needs documentation, the ChangeLog entry misses
the tree-pretty-print.h change.

+struct function;

instead of this please include coretypes.h from tree-pretty-print.h
and add the struct function forward declaration there if it isn't already
present.

You change the output of the header, so please make sure you
have bootstrapped and tested with _all_ languages included
(and also watch for bugreports for target specific bugs).

+  fprintf (dump_file, "\n;; Function %s (%s, funcdef_no=%d, uid=%d)",
+           dname, aname, fun->funcdef_no, node->uid);

I see no point in dumping funcdef_no - it wasn't dumped before in
any place.  Instead I miss dumping of the DECL_UID and thus
a more specific 'uid', like 'cgraph-uid'.

+  aname = (IDENTIFIER_POINTER
+          (DECL_ASSEMBLER_NAME (fdecl)));

using DECL_ASSEMBLER_NAME is bad - it might trigger computation
of DECL_ASSEMBLER_NAME which certainly shouldn't be done
only for dumping purposes.  Instead do sth like

   if (DECL_ASSEMBLER_NAME_SET_P (fdecl))
     aname = DECL_ASSEMBLER_NAME (fdecl);
   else
     aname = '<unset-asm-name>';

and please also watch for cgraph_get_node returning NULL.

Also please call the function dump_function_header instead of
pass_dump_function_header.

Please re-post with appropriate changes.

Thanks,
Richard.

> Thanks,
>
> David
>
> On Fri, May 27, 2011 at 2:58 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Fri, May 27, 2011 at 12:02 AM, Xinliang David Li <davidxl@google.com> wrote:
>>> The latest version that only exports 2 functions from passes.c.
>>
>> Ok with ...
>>
>> @@ -637,4 +637,8 @@ extern bool first_pass_instance;
>>  /* Declare for plugins.  */
>>  extern void do_per_function_toporder (void (*) (void *), void *);
>>
>> +extern void disable_pass (const char *);
>> +extern void enable_pass (const char *);
>> +struct function;
>> +
>>
>> struct function forward decl removed.
>>
>> +  explicitly_enabled = is_pass_explicitly_enabled (pass, func);
>> +  explicitly_disabled = is_pass_explicitly_disabled (pass, func);
>>
>> both functions inlined here and removed.
>>
>> +#define MAX_PASS_ID 512
>>
>> this removed and instead a VEC_safe_grow_cleared () or VEC_length ()
>> before the accesses.
>>
>> +-fenable-ipa-@var{pass} @gol
>> +-fenable-rtl-@var{pass} @gol
>> +-fenable-rtl-@var{pass}=@var{range-list} @gol
>> +-fenable-tree-@var{pass} @gol
>> +-fenable-tree-@var{pass}=@var{range-list} @gol
>>
>> -fenable-@var{kind}-@var{pass}, etc.
>>
>> +@item -fdisable-@var{ipa|tree|rtl}-@var{pass}
>> +@itemx -fenable-@var{ipa|tree|rtl}-@var{pass}
>> +@itemx -fdisable-@var{tree|rtl}-@var{pass}=@var{range-list}
>> +@itemx -fenable-@var{tree|rtl}-@var{pass}=@var{range-list}
>>
>> likewise.
>>
>> Thanks,
>> Richard.
>>
>>> David
>>>
>>> On Thu, May 26, 2011 at 2:04 PM, Xinliang David Li <davidxl@google.com> wrote:
>>>> On Thu, May 26, 2011 at 2:04 AM, Richard Guenther
>>>> <richard.guenther@gmail.com> wrote:
>>>>> On Wed, May 25, 2011 at 6:53 PM, Joseph S. Myers
>>>>> <joseph@codesourcery.com> wrote:
>>>>>> On Wed, 25 May 2011, Xinliang David Li wrote:
>>>>>>
>>>>>>> Ping. The link to the message:
>>>>>>>
>>>>>>> http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01303.html
>>>>>>
>>>>>> I don't consider this an option handling patch.  Patches adding whole new
>>>>>> features involving new options should be reviewed by maintainers for the
>>>>>> part of the compiler relevant to those features (since there isn't a pass
>>>>>> manager maintainer, I guess that means middle-end).
>>>>>
>>>>> Hmm, I suppose then you reviewed the option handling parts and they
>>>>> are ok?  Those globbing options always cause headache to me.
>>>>>
>>>>> +-fenable-ipa-@var{pass} @gol
>>>>> +-fenable-rtl-@var{pass} @gol
>>>>> +-fenable-rtl-@var{pass}=@var{range-list} @gol
>>>>> +-fenable-tree-@var{pass} @gol
>>>>>
>>>>> so, no -fenable-tree-@var{pass}=@var{range-list}?
>>>>>
>>>>
>>>> Missed. Will add.
>>>>
>>>>
>>>>> Does the pass name match 1:1 with the dump file name?  In which
>>>>> case
>>>>
>>>> Yes.
>>>>
>>>>>
>>>>> +Disable ipa pass @var{pass}. @var{pass} is the pass name. If the same
>>>>> pass is statically invoked in the compiler multiple times, the pass
>>>>> name should be appended with a sequential number starting from 1.
>>>>>
>>>>> isn't true as passes that are invoked only a single time lack the number
>>>>> suffix (yes, I'd really like that to be changed ...)
>>>>
>>>> Yes, pass with single static instance does not need number suffix.
>>>>
>>>>>
>>>>> Please break likes also in .texi files and stick to 80 columns.
>>>>
>>>> Done.
>>>>
>>>>>  Please
>>>>> document that these options are debugging options and regular
>>>>> options for enabling/disabling passes should be used.  I would suggest
>>>>> to group documentation differently and document -fenable-* and
>>>>> -fdisable-*, thus,
>>>>>
>>>>> + -fdisable-@var{kind}-@var{pass}
>>>>> + -fenable-@var{kind}-@var{pass}
>>>>>
>>>>> Even in .texi files please two spaces after a full-stop.
>>>>
>>>> Done
>>>>
>>>>>
>>>>> +extern void enable_disable_pass (const char *, bool);
>>>>>
>>>>> I'd rather have both enable_pass and disable_pass ;)
>>>>
>>>> Ok.
>>>>
>>>>>
>>>>> +struct function;
>>>>> +extern void pass_dump_function_header (FILE *, tree, struct function *);
>>>>>
>>>>> that's odd and probably should be split out, the function should
>>>>> maybe reside in tree-pretty-print.c.
>>>>
>>>> Ok.
>>>>
>>>>>
>>>>> Index: tree-ssa-loop-ivopts.c
>>>>> ===================================================================
>>>>> --- tree-ssa-loop-ivopts.c      (revision 173837)
>>>>> +++ tree-ssa-loop-ivopts.c      (working copy)
>>>>> @@ -3968,7 +3968,7 @@ get_computation_cost_at (struct ivopts_d
>>>>>
>>>>> well - doesn't belong here ;)
>>>>
>>>> Sorry -- many things in the same client -- not needed with your latest
>>>> change anyway.
>>>>
>>>>>
>>>>> +static hashval_t
>>>>> +passr_hash (const void *p)
>>>>> +{
>>>>> +  const struct pass_registry *const s = (const struct pass_registry *const) p;
>>>>> +  return htab_hash_string (s->unique_name);
>>>>> +}
>>>>> +
>>>>> +/* Hash equal function  */
>>>>> +
>>>>> +static int
>>>>> +passr_eq (const void *p1, const void *p2)
>>>>> +{
>>>>> +  const struct pass_registry *const s1 = (const struct pass_registry
>>>>> *const) p1;
>>>>> +  const struct pass_registry *const s2 = (const struct pass_registry
>>>>> *const) p2;
>>>>> +
>>>>> +  return !strcmp (s1->unique_name, s2->unique_name);
>>>>> +}
>>>>>
>>>>> you can use htab_hash_string and strcmp directly, no need for these
>>>>> wrappers.
>>>>
>>>> The hashtable entry is not string in this case. It is pass_registry,
>>>> thus the wrapper.
>>>>
>>>>>
>>>>> +void
>>>>> +register_pass_name (struct opt_pass *pass, const char *name)
>>>>>
>>>>> doesn't seem to need exporting, so don't and make it static.
>>>>
>>>> Done.
>>>>
>>>>>
>>>>> +  if (!pass_name_tab)
>>>>> +    pass_name_tab = htab_create (10, passr_hash, passr_eq, NULL);
>>>>>
>>>>> see above, the initial size should be larger - we have 223 passes at the
>>>>> moment, so use 256.
>>>>
>>>> Done.
>>>>
>>>>>
>>>>> +  else
>>>>> +    return; /* Ignore plugin passes.  */
>>>>>
>>>>> ?  You mean they might clash?
>>>>
>>>> Yes, name clash.
>>>>
>>>>>
>>>>> +struct opt_pass *
>>>>> +get_pass_by_name (const char *name)
>>>>>
>>>>> doesn't need exporting either.
>>>>
>>>> Done.
>>>>
>>>>>
>>>>> +      if (is_enable)
>>>>> +        error ("unrecognized option -fenable");
>>>>> +      else
>>>>> +        error ("unrecognized option -fdisable");
>>>>>
>>>>> I think that should be fatal_error - Joseph?
>>>>>
>>>>> +      if (is_enable)
>>>>> +        error ("unknown pass %s specified in -fenable", phase_name);
>>>>> +      else
>>>>> +        error ("unknown pass %s specified in -fdisble", phase_name);
>>>>>
>>>>> likewise.
>>>>>
>>>>> +      if (!enabled_pass_uid_range_tab)
>>>>> +       enabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
>>>>>
>>>>> instead of using a hashtable here please use a VEC indexed by
>>>>> the static_pass_number which shoud speed up
>>>>
>>>> Ok.  The reason I did not use it is because in most of the cases, the
>>>> htab will be very small -- it is determined by the number of passes
>>>> specified in the command line, while the VEC requires allocating const
>>>> size array. Not an issue as long as by default the array is not
>>>> allocated.
>>>>
>>>>>
>>>>> +static bool
>>>>> +is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
>>>>> +                                       tree func, htab_t tab)
>>>>> +{
>>>>> +  struct uid_range **slot, *range, key;
>>>>> +  int cgraph_uid;
>>>>> +
>>>>> +  if (!tab)
>>>>> +    return false;
>>>>> +
>>>>> +  key.pass = pass;
>>>>> +  slot = (struct uid_range **) htab_find_slot (tab, &key, NO_INSERT);
>>>>> +  if (!slot || !*slot)
>>>>> +    return false;
>>>>>
>>>>> and simplify the code quite a bit.
>>>>>
>>>>> +  cgraph_uid = func ? cgraph_get_node (func)->uid : 0;
>>>>>
>>>>> note that cgraph uids are recycled, so it might not be the best idea
>>>>> to use them as discriminator (though I don't have a good idea how
>>>>> to represent ranges without them).
>>>>
>>>> Yes. It is not a big problem as the blind search does not need to know
>>>> the id->name mapping. Once the id s found, it can be easily discovered
>>>> via dump.
>>>>
>>>>>
>>>>> +  explicitly_enabled = is_pass_explicitly_enabled (pass,
>>>>> current_function_decl);
>>>>> +  explicitly_disabled = is_pass_explicitly_disabled (pass,
>>>>> current_function_decl);
>>>>> +
>>>>>   current_pass = pass;
>>>>>
>>>>>   /* 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();
>>>>> +  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
>>>>>
>>>>> so explicitly disabling wins over explicit enabling ;)  I think this
>>>>> implementation detail and the fact that you always query both
>>>>> hints at that the interface should be like
>>>>>
>>>>> gate_status = override_gate_status (pass, current_function_decl, gate_status);
>>>>
>>>> Done.
>>>>
>>>>>
>>>>> instead.
>>>>>
>>>>> Thus, please split out the function header dumping changes and rework
>>>>> the rest of the patch as suggested.
>>>>
>>>> Split out. The new patch is attached.
>>>>
>>>> Ok after testing is done?
>>>>
>>>> Thanks,
>>>>
>>>> David
>>>>
>>>>>
>>>>> Thanks,
>>>>> Richard.
>>>>>
>>>>>> --
>>>>>> Joseph S. Myers
>>>>>> joseph@codesourcery.com
>>>>>>
>>>>>
>>>>
>>>
>>
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-31  7:05                     ` Xinliang David Li
@ 2011-05-31 10:03                       ` Richard Guenther
  2011-06-01  0:02                         ` Xinliang David Li
  2011-06-01 19:19                       ` H.J. Lu
  1 sibling, 1 reply; 32+ messages in thread
From: Richard Guenther @ 2011-05-31 10:03 UTC (permalink / raw)
  To: Xinliang David Li; +Cc: GCC Patches, reply, Jan Hubicka

On Mon, May 30, 2011 at 11:44 PM, Xinliang David Li <davidxl@google.com> wrote:
> This is the complete patch for pass name fixes (with test case changes).

This is ok if Honza thinks the profile pass names make more sense this
way.

Thanks,
Richard.

> David
>
>
> On Mon, May 30, 2011 at 1:16 PM, Xinliang David Li <davidxl@google.com> wrote:
>> The attached are two simple follow up patches
>>
>> 1) the first patch does some refactorization on function header
>> dumping (with more information printed)
>>
>> 2) the second patch cleans up some pass names. Part of the cleanup
>> results from a previous discussion with Honza -- a) rename
>> 'tree_profile_ipa' into 'profile', and make 'ipa_profile' and
>> 'profile' into 'profile_estimate'. The rest of cleanups are needed to
>> make sure pass names are unique.
>>
>> Ok for trunk?
>>
>> Thanks,
>>
>> David
>>
>> On Fri, May 27, 2011 at 2:58 AM, Richard Guenther
>> <richard.guenther@gmail.com> wrote:
>>> On Fri, May 27, 2011 at 12:02 AM, Xinliang David Li <davidxl@google.com> wrote:
>>>> The latest version that only exports 2 functions from passes.c.
>>>
>>> Ok with ...
>>>
>>> @@ -637,4 +637,8 @@ extern bool first_pass_instance;
>>>  /* Declare for plugins.  */
>>>  extern void do_per_function_toporder (void (*) (void *), void *);
>>>
>>> +extern void disable_pass (const char *);
>>> +extern void enable_pass (const char *);
>>> +struct function;
>>> +
>>>
>>> struct function forward decl removed.
>>>
>>> +  explicitly_enabled = is_pass_explicitly_enabled (pass, func);
>>> +  explicitly_disabled = is_pass_explicitly_disabled (pass, func);
>>>
>>> both functions inlined here and removed.
>>>
>>> +#define MAX_PASS_ID 512
>>>
>>> this removed and instead a VEC_safe_grow_cleared () or VEC_length ()
>>> before the accesses.
>>>
>>> +-fenable-ipa-@var{pass} @gol
>>> +-fenable-rtl-@var{pass} @gol
>>> +-fenable-rtl-@var{pass}=@var{range-list} @gol
>>> +-fenable-tree-@var{pass} @gol
>>> +-fenable-tree-@var{pass}=@var{range-list} @gol
>>>
>>> -fenable-@var{kind}-@var{pass}, etc.
>>>
>>> +@item -fdisable-@var{ipa|tree|rtl}-@var{pass}
>>> +@itemx -fenable-@var{ipa|tree|rtl}-@var{pass}
>>> +@itemx -fdisable-@var{tree|rtl}-@var{pass}=@var{range-list}
>>> +@itemx -fenable-@var{tree|rtl}-@var{pass}=@var{range-list}
>>>
>>> likewise.
>>>
>>> Thanks,
>>> Richard.
>>>
>>>> David
>>>>
>>>> On Thu, May 26, 2011 at 2:04 PM, Xinliang David Li <davidxl@google.com> wrote:
>>>>> On Thu, May 26, 2011 at 2:04 AM, Richard Guenther
>>>>> <richard.guenther@gmail.com> wrote:
>>>>>> On Wed, May 25, 2011 at 6:53 PM, Joseph S. Myers
>>>>>> <joseph@codesourcery.com> wrote:
>>>>>>> On Wed, 25 May 2011, Xinliang David Li wrote:
>>>>>>>
>>>>>>>> Ping. The link to the message:
>>>>>>>>
>>>>>>>> http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01303.html
>>>>>>>
>>>>>>> I don't consider this an option handling patch.  Patches adding whole new
>>>>>>> features involving new options should be reviewed by maintainers for the
>>>>>>> part of the compiler relevant to those features (since there isn't a pass
>>>>>>> manager maintainer, I guess that means middle-end).
>>>>>>
>>>>>> Hmm, I suppose then you reviewed the option handling parts and they
>>>>>> are ok?  Those globbing options always cause headache to me.
>>>>>>
>>>>>> +-fenable-ipa-@var{pass} @gol
>>>>>> +-fenable-rtl-@var{pass} @gol
>>>>>> +-fenable-rtl-@var{pass}=@var{range-list} @gol
>>>>>> +-fenable-tree-@var{pass} @gol
>>>>>>
>>>>>> so, no -fenable-tree-@var{pass}=@var{range-list}?
>>>>>>
>>>>>
>>>>> Missed. Will add.
>>>>>
>>>>>
>>>>>> Does the pass name match 1:1 with the dump file name?  In which
>>>>>> case
>>>>>
>>>>> Yes.
>>>>>
>>>>>>
>>>>>> +Disable ipa pass @var{pass}. @var{pass} is the pass name. If the same
>>>>>> pass is statically invoked in the compiler multiple times, the pass
>>>>>> name should be appended with a sequential number starting from 1.
>>>>>>
>>>>>> isn't true as passes that are invoked only a single time lack the number
>>>>>> suffix (yes, I'd really like that to be changed ...)
>>>>>
>>>>> Yes, pass with single static instance does not need number suffix.
>>>>>
>>>>>>
>>>>>> Please break likes also in .texi files and stick to 80 columns.
>>>>>
>>>>> Done.
>>>>>
>>>>>>  Please
>>>>>> document that these options are debugging options and regular
>>>>>> options for enabling/disabling passes should be used.  I would suggest
>>>>>> to group documentation differently and document -fenable-* and
>>>>>> -fdisable-*, thus,
>>>>>>
>>>>>> + -fdisable-@var{kind}-@var{pass}
>>>>>> + -fenable-@var{kind}-@var{pass}
>>>>>>
>>>>>> Even in .texi files please two spaces after a full-stop.
>>>>>
>>>>> Done
>>>>>
>>>>>>
>>>>>> +extern void enable_disable_pass (const char *, bool);
>>>>>>
>>>>>> I'd rather have both enable_pass and disable_pass ;)
>>>>>
>>>>> Ok.
>>>>>
>>>>>>
>>>>>> +struct function;
>>>>>> +extern void pass_dump_function_header (FILE *, tree, struct function *);
>>>>>>
>>>>>> that's odd and probably should be split out, the function should
>>>>>> maybe reside in tree-pretty-print.c.
>>>>>
>>>>> Ok.
>>>>>
>>>>>>
>>>>>> Index: tree-ssa-loop-ivopts.c
>>>>>> ===================================================================
>>>>>> --- tree-ssa-loop-ivopts.c      (revision 173837)
>>>>>> +++ tree-ssa-loop-ivopts.c      (working copy)
>>>>>> @@ -3968,7 +3968,7 @@ get_computation_cost_at (struct ivopts_d
>>>>>>
>>>>>> well - doesn't belong here ;)
>>>>>
>>>>> Sorry -- many things in the same client -- not needed with your latest
>>>>> change anyway.
>>>>>
>>>>>>
>>>>>> +static hashval_t
>>>>>> +passr_hash (const void *p)
>>>>>> +{
>>>>>> +  const struct pass_registry *const s = (const struct pass_registry *const) p;
>>>>>> +  return htab_hash_string (s->unique_name);
>>>>>> +}
>>>>>> +
>>>>>> +/* Hash equal function  */
>>>>>> +
>>>>>> +static int
>>>>>> +passr_eq (const void *p1, const void *p2)
>>>>>> +{
>>>>>> +  const struct pass_registry *const s1 = (const struct pass_registry
>>>>>> *const) p1;
>>>>>> +  const struct pass_registry *const s2 = (const struct pass_registry
>>>>>> *const) p2;
>>>>>> +
>>>>>> +  return !strcmp (s1->unique_name, s2->unique_name);
>>>>>> +}
>>>>>>
>>>>>> you can use htab_hash_string and strcmp directly, no need for these
>>>>>> wrappers.
>>>>>
>>>>> The hashtable entry is not string in this case. It is pass_registry,
>>>>> thus the wrapper.
>>>>>
>>>>>>
>>>>>> +void
>>>>>> +register_pass_name (struct opt_pass *pass, const char *name)
>>>>>>
>>>>>> doesn't seem to need exporting, so don't and make it static.
>>>>>
>>>>> Done.
>>>>>
>>>>>>
>>>>>> +  if (!pass_name_tab)
>>>>>> +    pass_name_tab = htab_create (10, passr_hash, passr_eq, NULL);
>>>>>>
>>>>>> see above, the initial size should be larger - we have 223 passes at the
>>>>>> moment, so use 256.
>>>>>
>>>>> Done.
>>>>>
>>>>>>
>>>>>> +  else
>>>>>> +    return; /* Ignore plugin passes.  */
>>>>>>
>>>>>> ?  You mean they might clash?
>>>>>
>>>>> Yes, name clash.
>>>>>
>>>>>>
>>>>>> +struct opt_pass *
>>>>>> +get_pass_by_name (const char *name)
>>>>>>
>>>>>> doesn't need exporting either.
>>>>>
>>>>> Done.
>>>>>
>>>>>>
>>>>>> +      if (is_enable)
>>>>>> +        error ("unrecognized option -fenable");
>>>>>> +      else
>>>>>> +        error ("unrecognized option -fdisable");
>>>>>>
>>>>>> I think that should be fatal_error - Joseph?
>>>>>>
>>>>>> +      if (is_enable)
>>>>>> +        error ("unknown pass %s specified in -fenable", phase_name);
>>>>>> +      else
>>>>>> +        error ("unknown pass %s specified in -fdisble", phase_name);
>>>>>>
>>>>>> likewise.
>>>>>>
>>>>>> +      if (!enabled_pass_uid_range_tab)
>>>>>> +       enabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
>>>>>>
>>>>>> instead of using a hashtable here please use a VEC indexed by
>>>>>> the static_pass_number which shoud speed up
>>>>>
>>>>> Ok.  The reason I did not use it is because in most of the cases, the
>>>>> htab will be very small -- it is determined by the number of passes
>>>>> specified in the command line, while the VEC requires allocating const
>>>>> size array. Not an issue as long as by default the array is not
>>>>> allocated.
>>>>>
>>>>>>
>>>>>> +static bool
>>>>>> +is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
>>>>>> +                                       tree func, htab_t tab)
>>>>>> +{
>>>>>> +  struct uid_range **slot, *range, key;
>>>>>> +  int cgraph_uid;
>>>>>> +
>>>>>> +  if (!tab)
>>>>>> +    return false;
>>>>>> +
>>>>>> +  key.pass = pass;
>>>>>> +  slot = (struct uid_range **) htab_find_slot (tab, &key, NO_INSERT);
>>>>>> +  if (!slot || !*slot)
>>>>>> +    return false;
>>>>>>
>>>>>> and simplify the code quite a bit.
>>>>>>
>>>>>> +  cgraph_uid = func ? cgraph_get_node (func)->uid : 0;
>>>>>>
>>>>>> note that cgraph uids are recycled, so it might not be the best idea
>>>>>> to use them as discriminator (though I don't have a good idea how
>>>>>> to represent ranges without them).
>>>>>
>>>>> Yes. It is not a big problem as the blind search does not need to know
>>>>> the id->name mapping. Once the id s found, it can be easily discovered
>>>>> via dump.
>>>>>
>>>>>>
>>>>>> +  explicitly_enabled = is_pass_explicitly_enabled (pass,
>>>>>> current_function_decl);
>>>>>> +  explicitly_disabled = is_pass_explicitly_disabled (pass,
>>>>>> current_function_decl);
>>>>>> +
>>>>>>   current_pass = pass;
>>>>>>
>>>>>>   /* 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();
>>>>>> +  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
>>>>>>
>>>>>> so explicitly disabling wins over explicit enabling ;)  I think this
>>>>>> implementation detail and the fact that you always query both
>>>>>> hints at that the interface should be like
>>>>>>
>>>>>> gate_status = override_gate_status (pass, current_function_decl, gate_status);
>>>>>
>>>>> Done.
>>>>>
>>>>>>
>>>>>> instead.
>>>>>>
>>>>>> Thus, please split out the function header dumping changes and rework
>>>>>> the rest of the patch as suggested.
>>>>>
>>>>> Split out. The new patch is attached.
>>>>>
>>>>> Ok after testing is done?
>>>>>
>>>>> Thanks,
>>>>>
>>>>> David
>>>>>
>>>>>>
>>>>>> Thanks,
>>>>>> Richard.
>>>>>>
>>>>>>> --
>>>>>>> Joseph S. Myers
>>>>>>> joseph@codesourcery.com
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-31  9:57                     ` Richard Guenther
@ 2011-05-31 17:30                       ` Xinliang David Li
  2011-06-01  0:01                         ` Xinliang David Li
  0 siblings, 1 reply; 32+ messages in thread
From: Xinliang David Li @ 2011-05-31 17:30 UTC (permalink / raw)
  To: Richard Guenther; +Cc: GCC Patches, reply, Jan Hubicka

On Tue, May 31, 2011 at 2:05 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Mon, May 30, 2011 at 10:16 PM, Xinliang David Li <davidxl@google.com> wrote:
>> The attached are two simple follow up patches
>>
>> 1) the first patch does some refactorization on function header
>> dumping (with more information printed)
>>
>> 2) the second patch cleans up some pass names. Part of the cleanup
>> results from a previous discussion with Honza -- a) rename
>> 'tree_profile_ipa' into 'profile', and make 'ipa_profile' and
>> 'profile' into 'profile_estimate'. The rest of cleanups are needed to
>> make sure pass names are unique.
>>
>> Ok for trunk?
>
> +
> +void
> +pass_dump_function_header (FILE *dump_file, tree fdecl, struct function *fun)
>
> This function needs documentation, the ChangeLog entry misses
> the tree-pretty-print.h change.
>
> +struct function;
>
> instead of this please include coretypes.h from tree-pretty-print.h
> and add the struct function forward declaration there if it isn't already
> present.
>
> You change the output of the header, so please make sure you
> have bootstrapped and tested with _all_ languages included
> (and also watch for bugreports for target specific bugs).
>

Ok.

> +  fprintf (dump_file, "\n;; Function %s (%s, funcdef_no=%d, uid=%d)",
> +           dname, aname, fun->funcdef_no, node->uid);
>
> I see no point in dumping funcdef_no - it wasn't dumped before in
> any place.  Instead I miss dumping of the DECL_UID and thus
> a more specific 'uid', like 'cgraph-uid'.

Ok will add decl_uid. Funcdef_no is very useful for debugging FDO
coverage mismatch related problems as it is the id used in profile
hashing.

>
> +  aname = (IDENTIFIER_POINTER
> +          (DECL_ASSEMBLER_NAME (fdecl)));
>
> using DECL_ASSEMBLER_NAME is bad - it might trigger computation
> of DECL_ASSEMBLER_NAME which certainly shouldn't be done
> only for dumping purposes.  Instead do sth like
>
>   if (DECL_ASSEMBLER_NAME_SET_P (fdecl))
>     aname = DECL_ASSEMBLER_NAME (fdecl);
>   else
>     aname = '<unset-asm-name>';

Ok.

>
> and please also watch for cgraph_get_node returning NULL.
>
> Also please call the function dump_function_header instead of
> pass_dump_function_header.
>

Ok.

Thanks,

David
> Please re-post with appropriate changes.
>
> Thanks,
> Richard.
>
>> Thanks,
>>
>> David
>>
>> On Fri, May 27, 2011 at 2:58 AM, Richard Guenther
>> <richard.guenther@gmail.com> wrote:
>>> On Fri, May 27, 2011 at 12:02 AM, Xinliang David Li <davidxl@google.com> wrote:
>>>> The latest version that only exports 2 functions from passes.c.
>>>
>>> Ok with ...
>>>
>>> @@ -637,4 +637,8 @@ extern bool first_pass_instance;
>>>  /* Declare for plugins.  */
>>>  extern void do_per_function_toporder (void (*) (void *), void *);
>>>
>>> +extern void disable_pass (const char *);
>>> +extern void enable_pass (const char *);
>>> +struct function;
>>> +
>>>
>>> struct function forward decl removed.
>>>
>>> +  explicitly_enabled = is_pass_explicitly_enabled (pass, func);
>>> +  explicitly_disabled = is_pass_explicitly_disabled (pass, func);
>>>
>>> both functions inlined here and removed.
>>>
>>> +#define MAX_PASS_ID 512
>>>
>>> this removed and instead a VEC_safe_grow_cleared () or VEC_length ()
>>> before the accesses.
>>>
>>> +-fenable-ipa-@var{pass} @gol
>>> +-fenable-rtl-@var{pass} @gol
>>> +-fenable-rtl-@var{pass}=@var{range-list} @gol
>>> +-fenable-tree-@var{pass} @gol
>>> +-fenable-tree-@var{pass}=@var{range-list} @gol
>>>
>>> -fenable-@var{kind}-@var{pass}, etc.
>>>
>>> +@item -fdisable-@var{ipa|tree|rtl}-@var{pass}
>>> +@itemx -fenable-@var{ipa|tree|rtl}-@var{pass}
>>> +@itemx -fdisable-@var{tree|rtl}-@var{pass}=@var{range-list}
>>> +@itemx -fenable-@var{tree|rtl}-@var{pass}=@var{range-list}
>>>
>>> likewise.
>>>
>>> Thanks,
>>> Richard.
>>>
>>>> David
>>>>
>>>> On Thu, May 26, 2011 at 2:04 PM, Xinliang David Li <davidxl@google.com> wrote:
>>>>> On Thu, May 26, 2011 at 2:04 AM, Richard Guenther
>>>>> <richard.guenther@gmail.com> wrote:
>>>>>> On Wed, May 25, 2011 at 6:53 PM, Joseph S. Myers
>>>>>> <joseph@codesourcery.com> wrote:
>>>>>>> On Wed, 25 May 2011, Xinliang David Li wrote:
>>>>>>>
>>>>>>>> Ping. The link to the message:
>>>>>>>>
>>>>>>>> http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01303.html
>>>>>>>
>>>>>>> I don't consider this an option handling patch.  Patches adding whole new
>>>>>>> features involving new options should be reviewed by maintainers for the
>>>>>>> part of the compiler relevant to those features (since there isn't a pass
>>>>>>> manager maintainer, I guess that means middle-end).
>>>>>>
>>>>>> Hmm, I suppose then you reviewed the option handling parts and they
>>>>>> are ok?  Those globbing options always cause headache to me.
>>>>>>
>>>>>> +-fenable-ipa-@var{pass} @gol
>>>>>> +-fenable-rtl-@var{pass} @gol
>>>>>> +-fenable-rtl-@var{pass}=@var{range-list} @gol
>>>>>> +-fenable-tree-@var{pass} @gol
>>>>>>
>>>>>> so, no -fenable-tree-@var{pass}=@var{range-list}?
>>>>>>
>>>>>
>>>>> Missed. Will add.
>>>>>
>>>>>
>>>>>> Does the pass name match 1:1 with the dump file name?  In which
>>>>>> case
>>>>>
>>>>> Yes.
>>>>>
>>>>>>
>>>>>> +Disable ipa pass @var{pass}. @var{pass} is the pass name. If the same
>>>>>> pass is statically invoked in the compiler multiple times, the pass
>>>>>> name should be appended with a sequential number starting from 1.
>>>>>>
>>>>>> isn't true as passes that are invoked only a single time lack the number
>>>>>> suffix (yes, I'd really like that to be changed ...)
>>>>>
>>>>> Yes, pass with single static instance does not need number suffix.
>>>>>
>>>>>>
>>>>>> Please break likes also in .texi files and stick to 80 columns.
>>>>>
>>>>> Done.
>>>>>
>>>>>>  Please
>>>>>> document that these options are debugging options and regular
>>>>>> options for enabling/disabling passes should be used.  I would suggest
>>>>>> to group documentation differently and document -fenable-* and
>>>>>> -fdisable-*, thus,
>>>>>>
>>>>>> + -fdisable-@var{kind}-@var{pass}
>>>>>> + -fenable-@var{kind}-@var{pass}
>>>>>>
>>>>>> Even in .texi files please two spaces after a full-stop.
>>>>>
>>>>> Done
>>>>>
>>>>>>
>>>>>> +extern void enable_disable_pass (const char *, bool);
>>>>>>
>>>>>> I'd rather have both enable_pass and disable_pass ;)
>>>>>
>>>>> Ok.
>>>>>
>>>>>>
>>>>>> +struct function;
>>>>>> +extern void pass_dump_function_header (FILE *, tree, struct function *);
>>>>>>
>>>>>> that's odd and probably should be split out, the function should
>>>>>> maybe reside in tree-pretty-print.c.
>>>>>
>>>>> Ok.
>>>>>
>>>>>>
>>>>>> Index: tree-ssa-loop-ivopts.c
>>>>>> ===================================================================
>>>>>> --- tree-ssa-loop-ivopts.c      (revision 173837)
>>>>>> +++ tree-ssa-loop-ivopts.c      (working copy)
>>>>>> @@ -3968,7 +3968,7 @@ get_computation_cost_at (struct ivopts_d
>>>>>>
>>>>>> well - doesn't belong here ;)
>>>>>
>>>>> Sorry -- many things in the same client -- not needed with your latest
>>>>> change anyway.
>>>>>
>>>>>>
>>>>>> +static hashval_t
>>>>>> +passr_hash (const void *p)
>>>>>> +{
>>>>>> +  const struct pass_registry *const s = (const struct pass_registry *const) p;
>>>>>> +  return htab_hash_string (s->unique_name);
>>>>>> +}
>>>>>> +
>>>>>> +/* Hash equal function  */
>>>>>> +
>>>>>> +static int
>>>>>> +passr_eq (const void *p1, const void *p2)
>>>>>> +{
>>>>>> +  const struct pass_registry *const s1 = (const struct pass_registry
>>>>>> *const) p1;
>>>>>> +  const struct pass_registry *const s2 = (const struct pass_registry
>>>>>> *const) p2;
>>>>>> +
>>>>>> +  return !strcmp (s1->unique_name, s2->unique_name);
>>>>>> +}
>>>>>>
>>>>>> you can use htab_hash_string and strcmp directly, no need for these
>>>>>> wrappers.
>>>>>
>>>>> The hashtable entry is not string in this case. It is pass_registry,
>>>>> thus the wrapper.
>>>>>
>>>>>>
>>>>>> +void
>>>>>> +register_pass_name (struct opt_pass *pass, const char *name)
>>>>>>
>>>>>> doesn't seem to need exporting, so don't and make it static.
>>>>>
>>>>> Done.
>>>>>
>>>>>>
>>>>>> +  if (!pass_name_tab)
>>>>>> +    pass_name_tab = htab_create (10, passr_hash, passr_eq, NULL);
>>>>>>
>>>>>> see above, the initial size should be larger - we have 223 passes at the
>>>>>> moment, so use 256.
>>>>>
>>>>> Done.
>>>>>
>>>>>>
>>>>>> +  else
>>>>>> +    return; /* Ignore plugin passes.  */
>>>>>>
>>>>>> ?  You mean they might clash?
>>>>>
>>>>> Yes, name clash.
>>>>>
>>>>>>
>>>>>> +struct opt_pass *
>>>>>> +get_pass_by_name (const char *name)
>>>>>>
>>>>>> doesn't need exporting either.
>>>>>
>>>>> Done.
>>>>>
>>>>>>
>>>>>> +      if (is_enable)
>>>>>> +        error ("unrecognized option -fenable");
>>>>>> +      else
>>>>>> +        error ("unrecognized option -fdisable");
>>>>>>
>>>>>> I think that should be fatal_error - Joseph?
>>>>>>
>>>>>> +      if (is_enable)
>>>>>> +        error ("unknown pass %s specified in -fenable", phase_name);
>>>>>> +      else
>>>>>> +        error ("unknown pass %s specified in -fdisble", phase_name);
>>>>>>
>>>>>> likewise.
>>>>>>
>>>>>> +      if (!enabled_pass_uid_range_tab)
>>>>>> +       enabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
>>>>>>
>>>>>> instead of using a hashtable here please use a VEC indexed by
>>>>>> the static_pass_number which shoud speed up
>>>>>
>>>>> Ok.  The reason I did not use it is because in most of the cases, the
>>>>> htab will be very small -- it is determined by the number of passes
>>>>> specified in the command line, while the VEC requires allocating const
>>>>> size array. Not an issue as long as by default the array is not
>>>>> allocated.
>>>>>
>>>>>>
>>>>>> +static bool
>>>>>> +is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
>>>>>> +                                       tree func, htab_t tab)
>>>>>> +{
>>>>>> +  struct uid_range **slot, *range, key;
>>>>>> +  int cgraph_uid;
>>>>>> +
>>>>>> +  if (!tab)
>>>>>> +    return false;
>>>>>> +
>>>>>> +  key.pass = pass;
>>>>>> +  slot = (struct uid_range **) htab_find_slot (tab, &key, NO_INSERT);
>>>>>> +  if (!slot || !*slot)
>>>>>> +    return false;
>>>>>>
>>>>>> and simplify the code quite a bit.
>>>>>>
>>>>>> +  cgraph_uid = func ? cgraph_get_node (func)->uid : 0;
>>>>>>
>>>>>> note that cgraph uids are recycled, so it might not be the best idea
>>>>>> to use them as discriminator (though I don't have a good idea how
>>>>>> to represent ranges without them).
>>>>>
>>>>> Yes. It is not a big problem as the blind search does not need to know
>>>>> the id->name mapping. Once the id s found, it can be easily discovered
>>>>> via dump.
>>>>>
>>>>>>
>>>>>> +  explicitly_enabled = is_pass_explicitly_enabled (pass,
>>>>>> current_function_decl);
>>>>>> +  explicitly_disabled = is_pass_explicitly_disabled (pass,
>>>>>> current_function_decl);
>>>>>> +
>>>>>>   current_pass = pass;
>>>>>>
>>>>>>   /* 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();
>>>>>> +  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
>>>>>>
>>>>>> so explicitly disabling wins over explicit enabling ;)  I think this
>>>>>> implementation detail and the fact that you always query both
>>>>>> hints at that the interface should be like
>>>>>>
>>>>>> gate_status = override_gate_status (pass, current_function_decl, gate_status);
>>>>>
>>>>> Done.
>>>>>
>>>>>>
>>>>>> instead.
>>>>>>
>>>>>> Thus, please split out the function header dumping changes and rework
>>>>>> the rest of the patch as suggested.
>>>>>
>>>>> Split out. The new patch is attached.
>>>>>
>>>>> Ok after testing is done?
>>>>>
>>>>> Thanks,
>>>>>
>>>>> David
>>>>>
>>>>>>
>>>>>> Thanks,
>>>>>> Richard.
>>>>>>
>>>>>>> --
>>>>>>> Joseph S. Myers
>>>>>>> joseph@codesourcery.com
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-31 17:30                       ` Xinliang David Li
@ 2011-06-01  0:01                         ` Xinliang David Li
  2011-06-01  0:04                           ` Xinliang David Li
  0 siblings, 1 reply; 32+ messages in thread
From: Xinliang David Li @ 2011-06-01  0:01 UTC (permalink / raw)
  To: Richard Guenther; +Cc: GCC Patches, reply, Jan Hubicka

[-- Attachment #1: Type: text/plain, Size: 12886 bytes --]

The new patch is attached. The test (c,c++,fortran, java, ada) is on going.

Thanks,

David

On Tue, May 31, 2011 at 9:06 AM, Xinliang David Li <davidxl@google.com> wrote:
> On Tue, May 31, 2011 at 2:05 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Mon, May 30, 2011 at 10:16 PM, Xinliang David Li <davidxl@google.com> wrote:
>>> The attached are two simple follow up patches
>>>
>>> 1) the first patch does some refactorization on function header
>>> dumping (with more information printed)
>>>
>>> 2) the second patch cleans up some pass names. Part of the cleanup
>>> results from a previous discussion with Honza -- a) rename
>>> 'tree_profile_ipa' into 'profile', and make 'ipa_profile' and
>>> 'profile' into 'profile_estimate'. The rest of cleanups are needed to
>>> make sure pass names are unique.
>>>
>>> Ok for trunk?
>>
>> +
>> +void
>> +pass_dump_function_header (FILE *dump_file, tree fdecl, struct function *fun)
>>
>> This function needs documentation, the ChangeLog entry misses
>> the tree-pretty-print.h change.
>>
>> +struct function;
>>
>> instead of this please include coretypes.h from tree-pretty-print.h
>> and add the struct function forward declaration there if it isn't already
>> present.
>>
>> You change the output of the header, so please make sure you
>> have bootstrapped and tested with _all_ languages included
>> (and also watch for bugreports for target specific bugs).
>>
>
> Ok.
>
>> +  fprintf (dump_file, "\n;; Function %s (%s, funcdef_no=%d, uid=%d)",
>> +           dname, aname, fun->funcdef_no, node->uid);
>>
>> I see no point in dumping funcdef_no - it wasn't dumped before in
>> any place.  Instead I miss dumping of the DECL_UID and thus
>> a more specific 'uid', like 'cgraph-uid'.
>
> Ok will add decl_uid. Funcdef_no is very useful for debugging FDO
> coverage mismatch related problems as it is the id used in profile
> hashing.
>
>>
>> +  aname = (IDENTIFIER_POINTER
>> +          (DECL_ASSEMBLER_NAME (fdecl)));
>>
>> using DECL_ASSEMBLER_NAME is bad - it might trigger computation
>> of DECL_ASSEMBLER_NAME which certainly shouldn't be done
>> only for dumping purposes.  Instead do sth like
>>
>>   if (DECL_ASSEMBLER_NAME_SET_P (fdecl))
>>     aname = DECL_ASSEMBLER_NAME (fdecl);
>>   else
>>     aname = '<unset-asm-name>';
>
> Ok.
>
>>
>> and please also watch for cgraph_get_node returning NULL.
>>
>> Also please call the function dump_function_header instead of
>> pass_dump_function_header.
>>
>
> Ok.
>
> Thanks,
>
> David
>> Please re-post with appropriate changes.
>>
>> Thanks,
>> Richard.
>>
>>> Thanks,
>>>
>>> David
>>>
>>> On Fri, May 27, 2011 at 2:58 AM, Richard Guenther
>>> <richard.guenther@gmail.com> wrote:
>>>> On Fri, May 27, 2011 at 12:02 AM, Xinliang David Li <davidxl@google.com> wrote:
>>>>> The latest version that only exports 2 functions from passes.c.
>>>>
>>>> Ok with ...
>>>>
>>>> @@ -637,4 +637,8 @@ extern bool first_pass_instance;
>>>>  /* Declare for plugins.  */
>>>>  extern void do_per_function_toporder (void (*) (void *), void *);
>>>>
>>>> +extern void disable_pass (const char *);
>>>> +extern void enable_pass (const char *);
>>>> +struct function;
>>>> +
>>>>
>>>> struct function forward decl removed.
>>>>
>>>> +  explicitly_enabled = is_pass_explicitly_enabled (pass, func);
>>>> +  explicitly_disabled = is_pass_explicitly_disabled (pass, func);
>>>>
>>>> both functions inlined here and removed.
>>>>
>>>> +#define MAX_PASS_ID 512
>>>>
>>>> this removed and instead a VEC_safe_grow_cleared () or VEC_length ()
>>>> before the accesses.
>>>>
>>>> +-fenable-ipa-@var{pass} @gol
>>>> +-fenable-rtl-@var{pass} @gol
>>>> +-fenable-rtl-@var{pass}=@var{range-list} @gol
>>>> +-fenable-tree-@var{pass} @gol
>>>> +-fenable-tree-@var{pass}=@var{range-list} @gol
>>>>
>>>> -fenable-@var{kind}-@var{pass}, etc.
>>>>
>>>> +@item -fdisable-@var{ipa|tree|rtl}-@var{pass}
>>>> +@itemx -fenable-@var{ipa|tree|rtl}-@var{pass}
>>>> +@itemx -fdisable-@var{tree|rtl}-@var{pass}=@var{range-list}
>>>> +@itemx -fenable-@var{tree|rtl}-@var{pass}=@var{range-list}
>>>>
>>>> likewise.
>>>>
>>>> Thanks,
>>>> Richard.
>>>>
>>>>> David
>>>>>
>>>>> On Thu, May 26, 2011 at 2:04 PM, Xinliang David Li <davidxl@google.com> wrote:
>>>>>> On Thu, May 26, 2011 at 2:04 AM, Richard Guenther
>>>>>> <richard.guenther@gmail.com> wrote:
>>>>>>> On Wed, May 25, 2011 at 6:53 PM, Joseph S. Myers
>>>>>>> <joseph@codesourcery.com> wrote:
>>>>>>>> On Wed, 25 May 2011, Xinliang David Li wrote:
>>>>>>>>
>>>>>>>>> Ping. The link to the message:
>>>>>>>>>
>>>>>>>>> http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01303.html
>>>>>>>>
>>>>>>>> I don't consider this an option handling patch.  Patches adding whole new
>>>>>>>> features involving new options should be reviewed by maintainers for the
>>>>>>>> part of the compiler relevant to those features (since there isn't a pass
>>>>>>>> manager maintainer, I guess that means middle-end).
>>>>>>>
>>>>>>> Hmm, I suppose then you reviewed the option handling parts and they
>>>>>>> are ok?  Those globbing options always cause headache to me.
>>>>>>>
>>>>>>> +-fenable-ipa-@var{pass} @gol
>>>>>>> +-fenable-rtl-@var{pass} @gol
>>>>>>> +-fenable-rtl-@var{pass}=@var{range-list} @gol
>>>>>>> +-fenable-tree-@var{pass} @gol
>>>>>>>
>>>>>>> so, no -fenable-tree-@var{pass}=@var{range-list}?
>>>>>>>
>>>>>>
>>>>>> Missed. Will add.
>>>>>>
>>>>>>
>>>>>>> Does the pass name match 1:1 with the dump file name?  In which
>>>>>>> case
>>>>>>
>>>>>> Yes.
>>>>>>
>>>>>>>
>>>>>>> +Disable ipa pass @var{pass}. @var{pass} is the pass name. If the same
>>>>>>> pass is statically invoked in the compiler multiple times, the pass
>>>>>>> name should be appended with a sequential number starting from 1.
>>>>>>>
>>>>>>> isn't true as passes that are invoked only a single time lack the number
>>>>>>> suffix (yes, I'd really like that to be changed ...)
>>>>>>
>>>>>> Yes, pass with single static instance does not need number suffix.
>>>>>>
>>>>>>>
>>>>>>> Please break likes also in .texi files and stick to 80 columns.
>>>>>>
>>>>>> Done.
>>>>>>
>>>>>>>  Please
>>>>>>> document that these options are debugging options and regular
>>>>>>> options for enabling/disabling passes should be used.  I would suggest
>>>>>>> to group documentation differently and document -fenable-* and
>>>>>>> -fdisable-*, thus,
>>>>>>>
>>>>>>> + -fdisable-@var{kind}-@var{pass}
>>>>>>> + -fenable-@var{kind}-@var{pass}
>>>>>>>
>>>>>>> Even in .texi files please two spaces after a full-stop.
>>>>>>
>>>>>> Done
>>>>>>
>>>>>>>
>>>>>>> +extern void enable_disable_pass (const char *, bool);
>>>>>>>
>>>>>>> I'd rather have both enable_pass and disable_pass ;)
>>>>>>
>>>>>> Ok.
>>>>>>
>>>>>>>
>>>>>>> +struct function;
>>>>>>> +extern void pass_dump_function_header (FILE *, tree, struct function *);
>>>>>>>
>>>>>>> that's odd and probably should be split out, the function should
>>>>>>> maybe reside in tree-pretty-print.c.
>>>>>>
>>>>>> Ok.
>>>>>>
>>>>>>>
>>>>>>> Index: tree-ssa-loop-ivopts.c
>>>>>>> ===================================================================
>>>>>>> --- tree-ssa-loop-ivopts.c      (revision 173837)
>>>>>>> +++ tree-ssa-loop-ivopts.c      (working copy)
>>>>>>> @@ -3968,7 +3968,7 @@ get_computation_cost_at (struct ivopts_d
>>>>>>>
>>>>>>> well - doesn't belong here ;)
>>>>>>
>>>>>> Sorry -- many things in the same client -- not needed with your latest
>>>>>> change anyway.
>>>>>>
>>>>>>>
>>>>>>> +static hashval_t
>>>>>>> +passr_hash (const void *p)
>>>>>>> +{
>>>>>>> +  const struct pass_registry *const s = (const struct pass_registry *const) p;
>>>>>>> +  return htab_hash_string (s->unique_name);
>>>>>>> +}
>>>>>>> +
>>>>>>> +/* Hash equal function  */
>>>>>>> +
>>>>>>> +static int
>>>>>>> +passr_eq (const void *p1, const void *p2)
>>>>>>> +{
>>>>>>> +  const struct pass_registry *const s1 = (const struct pass_registry
>>>>>>> *const) p1;
>>>>>>> +  const struct pass_registry *const s2 = (const struct pass_registry
>>>>>>> *const) p2;
>>>>>>> +
>>>>>>> +  return !strcmp (s1->unique_name, s2->unique_name);
>>>>>>> +}
>>>>>>>
>>>>>>> you can use htab_hash_string and strcmp directly, no need for these
>>>>>>> wrappers.
>>>>>>
>>>>>> The hashtable entry is not string in this case. It is pass_registry,
>>>>>> thus the wrapper.
>>>>>>
>>>>>>>
>>>>>>> +void
>>>>>>> +register_pass_name (struct opt_pass *pass, const char *name)
>>>>>>>
>>>>>>> doesn't seem to need exporting, so don't and make it static.
>>>>>>
>>>>>> Done.
>>>>>>
>>>>>>>
>>>>>>> +  if (!pass_name_tab)
>>>>>>> +    pass_name_tab = htab_create (10, passr_hash, passr_eq, NULL);
>>>>>>>
>>>>>>> see above, the initial size should be larger - we have 223 passes at the
>>>>>>> moment, so use 256.
>>>>>>
>>>>>> Done.
>>>>>>
>>>>>>>
>>>>>>> +  else
>>>>>>> +    return; /* Ignore plugin passes.  */
>>>>>>>
>>>>>>> ?  You mean they might clash?
>>>>>>
>>>>>> Yes, name clash.
>>>>>>
>>>>>>>
>>>>>>> +struct opt_pass *
>>>>>>> +get_pass_by_name (const char *name)
>>>>>>>
>>>>>>> doesn't need exporting either.
>>>>>>
>>>>>> Done.
>>>>>>
>>>>>>>
>>>>>>> +      if (is_enable)
>>>>>>> +        error ("unrecognized option -fenable");
>>>>>>> +      else
>>>>>>> +        error ("unrecognized option -fdisable");
>>>>>>>
>>>>>>> I think that should be fatal_error - Joseph?
>>>>>>>
>>>>>>> +      if (is_enable)
>>>>>>> +        error ("unknown pass %s specified in -fenable", phase_name);
>>>>>>> +      else
>>>>>>> +        error ("unknown pass %s specified in -fdisble", phase_name);
>>>>>>>
>>>>>>> likewise.
>>>>>>>
>>>>>>> +      if (!enabled_pass_uid_range_tab)
>>>>>>> +       enabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
>>>>>>>
>>>>>>> instead of using a hashtable here please use a VEC indexed by
>>>>>>> the static_pass_number which shoud speed up
>>>>>>
>>>>>> Ok.  The reason I did not use it is because in most of the cases, the
>>>>>> htab will be very small -- it is determined by the number of passes
>>>>>> specified in the command line, while the VEC requires allocating const
>>>>>> size array. Not an issue as long as by default the array is not
>>>>>> allocated.
>>>>>>
>>>>>>>
>>>>>>> +static bool
>>>>>>> +is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
>>>>>>> +                                       tree func, htab_t tab)
>>>>>>> +{
>>>>>>> +  struct uid_range **slot, *range, key;
>>>>>>> +  int cgraph_uid;
>>>>>>> +
>>>>>>> +  if (!tab)
>>>>>>> +    return false;
>>>>>>> +
>>>>>>> +  key.pass = pass;
>>>>>>> +  slot = (struct uid_range **) htab_find_slot (tab, &key, NO_INSERT);
>>>>>>> +  if (!slot || !*slot)
>>>>>>> +    return false;
>>>>>>>
>>>>>>> and simplify the code quite a bit.
>>>>>>>
>>>>>>> +  cgraph_uid = func ? cgraph_get_node (func)->uid : 0;
>>>>>>>
>>>>>>> note that cgraph uids are recycled, so it might not be the best idea
>>>>>>> to use them as discriminator (though I don't have a good idea how
>>>>>>> to represent ranges without them).
>>>>>>
>>>>>> Yes. It is not a big problem as the blind search does not need to know
>>>>>> the id->name mapping. Once the id s found, it can be easily discovered
>>>>>> via dump.
>>>>>>
>>>>>>>
>>>>>>> +  explicitly_enabled = is_pass_explicitly_enabled (pass,
>>>>>>> current_function_decl);
>>>>>>> +  explicitly_disabled = is_pass_explicitly_disabled (pass,
>>>>>>> current_function_decl);
>>>>>>> +
>>>>>>>   current_pass = pass;
>>>>>>>
>>>>>>>   /* 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();
>>>>>>> +  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
>>>>>>>
>>>>>>> so explicitly disabling wins over explicit enabling ;)  I think this
>>>>>>> implementation detail and the fact that you always query both
>>>>>>> hints at that the interface should be like
>>>>>>>
>>>>>>> gate_status = override_gate_status (pass, current_function_decl, gate_status);
>>>>>>
>>>>>> Done.
>>>>>>
>>>>>>>
>>>>>>> instead.
>>>>>>>
>>>>>>> Thus, please split out the function header dumping changes and rework
>>>>>>> the rest of the patch as suggested.
>>>>>>
>>>>>> Split out. The new patch is attached.
>>>>>>
>>>>>> Ok after testing is done?
>>>>>>
>>>>>> Thanks,
>>>>>>
>>>>>> David
>>>>>>
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Richard.
>>>>>>>
>>>>>>>> --
>>>>>>>> Joseph S. Myers
>>>>>>>> joseph@codesourcery.com
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>

[-- Attachment #2: header-print2.p --]
[-- Type: text/x-pascal, Size: 25899 bytes --]

Index: tree-pretty-print.c
===================================================================
--- tree-pretty-print.c	(revision 174424)
+++ tree-pretty-print.c	(working copy)
@@ -3013,3 +3013,36 @@ pp_base_tree_identifier (pretty_printer 
     pp_append_text (pp, IDENTIFIER_POINTER (id),
 		    IDENTIFIER_POINTER (id) + IDENTIFIER_LENGTH (id));
 }
+
+/* A helper function that is used to dump function information before the
+   function dump.  */
+
+void
+dump_function_header (FILE *dump_file, tree fdecl, struct function *fun)
+{
+  const char *dname, *aname;
+  struct cgraph_node *node = cgraph_get_node (fdecl);
+  dname = lang_hooks.decl_printable_name (fdecl, 2);
+
+  if (DECL_ASSEMBLER_NAME_SET_P (fdecl))
+    aname = (IDENTIFIER_POINTER
+             (DECL_ASSEMBLER_NAME (fdecl)));
+  else
+    aname = "<unset-asm-name>";
+
+  if (node)
+    fprintf (dump_file, "\n;; Function %s (%s, funcdef_no=%d, decl_uid = %d, cgraph_uid=%d)",
+             dname, aname, fun->funcdef_no, DECL_UID(fdecl), node->uid);
+  else
+    fprintf (dump_file, "\n;; Function %s (%s, funcdef_no=%d, decl_uid = %d)",
+             dname, aname, fun->funcdef_no, DECL_UID(fdecl));
+
+  fprintf (dump_file, "%s\n\n",
+           node->frequency == NODE_FREQUENCY_HOT
+           ? " (hot)"
+           : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
+           ? " (unlikely executed)"
+           : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
+           ? " (executed once)"
+           : "");
+}
Index: tree-pretty-print.h
===================================================================
--- tree-pretty-print.h	(revision 174422)
+++ tree-pretty-print.h	(working copy)
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.  
 #define GCC_TREE_PRETTY_PRINT_H
 
 #include "pretty-print.h"
+#include "coretypes.h"
 
 #define pp_tree_identifier(PP, T)                      \
   pp_base_tree_identifier (pp_base (PP), T)
@@ -50,6 +51,7 @@ extern void debug_generic_expr (tree);
 extern void debug_generic_stmt (tree);
 extern void debug_tree_chain (tree);
 extern void percent_K_format (text_info *);
+extern void dump_function_header (FILE *, tree, struct function *);
 
 /* In toplev.c  */
 extern bool default_tree_printer (pretty_printer *, text_info *, const char *,
Index: final.c
===================================================================
--- final.c	(revision 174422)
+++ final.c	(working copy)
@@ -83,6 +83,7 @@ along with GCC; see the file COPYING3.  
 #include "ggc.h"
 #include "cfgloop.h"
 #include "params.h"
+#include "tree-pretty-print.h"
 
 #ifdef XCOFF_DEBUGGING_INFO
 #include "xcoffout.h"		/* Needed for external data
@@ -4360,20 +4361,7 @@ rest_of_clean_state (void)
 	}
       else
 	{
-	  const char *aname;
-	  struct cgraph_node *node = cgraph_get_node (current_function_decl);
-
-	  aname = (IDENTIFIER_POINTER
-		   (DECL_ASSEMBLER_NAME (current_function_decl)));
-	  fprintf (final_output, "\n;; Function (%s) %s\n\n", aname,
-	     node->frequency == NODE_FREQUENCY_HOT
-	     ? " (hot)"
-	     : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
-	     ? " (unlikely executed)"
-	     : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
-	     ? " (executed once)"
-	     : "");
-
+	  dump_function_header (final_output, current_function_decl, cfun);
 	  flag_dump_noaddr = flag_dump_unnumbered = 1;
 	  if (flag_compare_debug_opt || flag_compare_debug)
 	    dump_flags |= TDF_NOUID;
Index: testsuite/gcc.dg/profile-dir-1.c
===================================================================
--- testsuite/gcc.dg/profile-dir-1.c	(revision 174422)
+++ testsuite/gcc.dg/profile-dir-1.c	(working copy)
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
-/* { dg-options "-O -fprofile-generate=. -fdump-ipa-tree_profile_ipa" } */
-/* { dg-final { scan-ipa-dump " ./profile-dir-1.gcda" "tree_profile_ipa" } } */
+/* { dg-options "-O -fprofile-generate=. -fdump-ipa-profile" } */
+/* { dg-final { scan-ipa-dump " ./profile-dir-1.gcda" "profile" } } */
 
 int
 main(void)
@@ -8,4 +8,4 @@ main(void)
   return 0;
 }
 
-/* { dg-final { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/profile-dir-2.c
===================================================================
--- testsuite/gcc.dg/profile-dir-2.c	(revision 174422)
+++ testsuite/gcc.dg/profile-dir-2.c	(working copy)
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
-/* { dg-options "-O -fprofile-generate -fdump-ipa-tree_profile_ipa" } */
-/* { dg-final { scan-ipa-dump "/profile-dir-2.gcda" "tree_profile_ipa" } } */
+/* { dg-options "-O -fprofile-generate -fdump-ipa-profile" } */
+/* { dg-final { scan-ipa-dump "/profile-dir-2.gcda" "profile" } } */
 
 int
 main(void)
@@ -8,4 +8,4 @@ main(void)
   return 0;
 }
 
-/* { dg-final { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-ssa/dump-1.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/dump-1.c	(revision 174422)
+++ testsuite/gcc.dg/tree-ssa/dump-1.c	(working copy)
@@ -1,9 +1,9 @@
 /* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-profile-details" } */
+/* { dg-options "-O1 -fdump-tree-profile_estimate-details" } */
 
 int f(void)
 {
   return 0;
 }
 
-/* { dg-final { cleanup-tree-dump "profile" } } */
+/* { dg-final { cleanup-tree-dump "profile_estimate" } } */
Index: testsuite/gcc.dg/tree-ssa/loop-25.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/loop-25.c	(revision 174422)
+++ testsuite/gcc.dg/tree-ssa/loop-25.c	(working copy)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-profile" } */
+/* { dg-options "-O1 -fdump-tree-profile_estimate" } */
 
 int foo(void);
 void bla(void);
@@ -118,12 +118,12 @@ void test5 (void)
     }
 }
 
-/* { dg-final { scan-tree-dump-times "Disambiguating loop" 5 "profile" } } */
+/* { dg-final { scan-tree-dump-times "Disambiguating loop" 5 "profile_estimate" } } */
 /* For the following xfail marks, see PR35629.  */
-/* { dg-final { scan-tree-dump-times "Found latch edge" 5 "profile" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump-times "Merged latch edges" 2 "profile" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump-times "4 loops found" 2 "profile" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump-times "3 loops found" 2 "profile" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump-times "2 loops found" 1 "profile" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "Found latch edge" 5 "profile_estimate" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "Merged latch edges" 2 "profile_estimate" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "4 loops found" 2 "profile_estimate" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "3 loops found" 2 "profile_estimate" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "2 loops found" 1 "profile_estimate" { xfail *-*-* } } } */
 
-/* { dg-final { cleanup-tree-dump "profile" } } */
+/* { dg-final { cleanup-tree-dump "profile_estimate" } } */
Index: testsuite/gcc.dg/tree-prof/stringop-1.c
===================================================================
--- testsuite/gcc.dg/tree-prof/stringop-1.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/stringop-1.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-profile" } */
 int a[1000];
 int b[1000];
 int size=1;
@@ -13,10 +13,10 @@ main()
     }
    return 0;
 }
-/* { dg-final-use { scan-ipa-dump "Single value 4 stringop" "tree_profile_ipa"} } */
+/* { dg-final-use { scan-ipa-dump "Single value 4 stringop" "profile"} } */
 /* Really this ought to simplify into assignment, but we are not there yet.  */
 /* a[0] = b[0] is what we fold the resulting memcpy into.  */
 /* { dg-final-use { scan-tree-dump " = MEM.*&b" "optimized"} } */
 /* { dg-final-use { scan-tree-dump "MEM.*&a\\\] = " "optimized"} } */
 /* { dg-final-use { cleanup-tree-dump "optimized" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-prof/update-loopch.c
===================================================================
--- testsuite/gcc.dg/tree-prof/update-loopch.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/update-loopch.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-ipa-tree_profile_ipa-blocks -fdump-tree-optimized-blocks" } */
+/* { dg-options "-O2 -fdump-ipa-profile-blocks -fdump-tree-optimized-blocks" } */
 int max = 33333;
 int a[8];
 int
@@ -14,8 +14,8 @@ main ()
 /* Loop header copying will peel away the initial conditional, so the loop body
    is once reached directly from entry point of function, rest via loopback
    edge.  */
-/* { dg-final-use { scan-ipa-dump "count:33333" "tree_profile_ipa"} } */
+/* { dg-final-use { scan-ipa-dump "count:33333" "profile"} } */
 /* { dg-final-use { scan-tree-dump "count:33332" "optimized"} } */
 /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
 /* { dg-final-use { cleanup-tree-dump "optimized" } } */
Index: testsuite/gcc.dg/tree-prof/stringop-2.c
===================================================================
--- testsuite/gcc.dg/tree-prof/stringop-2.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/stringop-2.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-profile" } */
 int a[1000];
 int b[1000];
 int size=1;
@@ -13,8 +13,8 @@ main()
     }
    return 0;
 }
-/* { dg-final-use { scan-ipa-dump "Single value 4 stringop" "tree_profile_ipa"} } */
+/* { dg-final-use { scan-ipa-dump "Single value 4 stringop" "profile"} } */
 /* The versioned memset of size 4 should be optimized to an assignment.  */
 /* { dg-final-use { scan-tree-dump "a\\\[0\\\] = 168430090" "optimized"} } */
 /* { dg-final-use { cleanup-tree-dump "optimized" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-prof/ic-misattribution-1.c
===================================================================
--- testsuite/gcc.dg/tree-prof/ic-misattribution-1.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/ic-misattribution-1.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-ipa-tree_profile_ipa" } */
+/* { dg-options "-O2 -fdump-ipa-profile" } */
 /* { dg-additional-sources "ic-misattribution-1a.c" } */
 
 extern void other_caller (void);
@@ -15,5 +15,5 @@ caller(void (*func) (void))
   func ();
 }
 
-/* { dg-final-use { scan-ipa-dump "hist->count 1 hist->all 1" "tree_profile_ipa" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { scan-ipa-dump "hist->count 1 hist->all 1" "profile" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-prof/ic-misattribution-1a.c
===================================================================
--- testsuite/gcc.dg/tree-prof/ic-misattribution-1a.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/ic-misattribution-1a.c	(working copy)
@@ -19,4 +19,4 @@ main ()
   return 0;
 }
 
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-prof/indir-call-prof.c
===================================================================
--- testsuite/gcc.dg/tree-prof/indir-call-prof.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/indir-call-prof.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-profile" } */
 
 static int a1 (void)
 {
@@ -37,7 +37,7 @@ main (void)
   return 0;
 }
 
-/* { dg-final-use { scan-ipa-dump "Indirect call -> direct call.* a1 transformation on insn" "tree_profile_ipa"} } */
+/* { dg-final-use { scan-ipa-dump "Indirect call -> direct call.* a1 transformation on insn" "profile"} } */
 /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
 /* { dg-final-use { cleanup-tree-dump "optimized" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-prof/val-prof-1.c
===================================================================
--- testsuite/gcc.dg/tree-prof/val-prof-1.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/val-prof-1.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-profile" } */
 int a[1000];
 int b = 256;
 int c = 257;
@@ -15,8 +15,8 @@ main ()
     }
   return 0;
 }
-/* { dg-final-use { scan-ipa-dump "Div.mod by constant n_\[0-9\]*=257 transformation on insn" "tree_profile_ipa"} } */
+/* { dg-final-use { scan-ipa-dump "Div.mod by constant n_\[0-9\]*=257 transformation on insn" "profile"} } */
 /* { dg-final-use { scan-tree-dump "if \\(n_\[0-9\]* != 257\\)" "optimized"} } */
 /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
 /* { dg-final-use { cleanup-tree-dump "optimized" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-prof/val-prof-2.c
===================================================================
--- testsuite/gcc.dg/tree-prof/val-prof-2.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/val-prof-2.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-profile" } */
 unsigned int a[1000];
 unsigned int b = 256;
 unsigned int c = 1024;
@@ -23,10 +23,10 @@ main ()
     }
   return 0;
 }
-/* { dg-final-use { scan-ipa-dump "Mod power of 2 transformation on insn" "tree_profile_ipa" } } */
+/* { dg-final-use { scan-ipa-dump "Mod power of 2 transformation on insn" "profile" } } */
 /* This is part of code checking that n is power of 2, so we are sure that the transformation
    didn't get optimized out.  */
 /* { dg-final-use { scan-tree-dump "n_\[0-9\]* \\+ (4294967295|0x0*ffffffff)" "optimized"} } */
 /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
 /* { dg-final-use { cleanup-tree-dump "optimized" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-prof/val-prof-3.c
===================================================================
--- testsuite/gcc.dg/tree-prof/val-prof-3.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/val-prof-3.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-profile" } */
 unsigned int a[1000];
 unsigned int b = 257;
 unsigned int c = 1023;
@@ -23,10 +23,10 @@ main ()
     }
   return 0;
 }
-/* { dg-final-use { scan-ipa-dump "Mod subtract transformation on insn" "tree_profile_ipa" } } */
+/* { dg-final-use { scan-ipa-dump "Mod subtract transformation on insn" "profile" } } */
 /* This is part of code checking that n is greater than the divisor so we are sure that it
    didn't get optimized out.  */
 /* { dg-final-use { scan-tree-dump "if \\(n_\[0-9\]* \\>" "optimized"} } */
 /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
 /* { dg-final-use { cleanup-tree-dump "optimized" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-prof/val-prof-4.c
===================================================================
--- testsuite/gcc.dg/tree-prof/val-prof-4.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/val-prof-4.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-profile" } */
 unsigned int a[1000];
 unsigned int b = 999;
 unsigned int c = 1002;
@@ -23,10 +23,10 @@ main ()
     }
   return 0;
 }
-/* { dg-final-use { scan-ipa-dump "Mod subtract transformation on insn" "tree_profile_ipa" } } */
+/* { dg-final-use { scan-ipa-dump "Mod subtract transformation on insn" "profile" } } */
 /* This is part of code checking that n is greater than the divisor so we are sure that it
    didn't get optimized out.  */
 /* { dg-final-use { scan-tree-dump "if \\(n_\[0-9\]* \\>" "optimized"} } */
 /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
 /* { dg-final-use { cleanup-tree-dump "optimized" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-prof/val-prof-5.c
===================================================================
--- testsuite/gcc.dg/tree-prof/val-prof-5.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/val-prof-5.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-profile" } */
 int a[1000];
 int b=997;
 main()
@@ -11,7 +11,7 @@ main()
 			a[i]/=b;
 	return 0;
 }
-/* { dg-final-use { scan-ipa-dump "Div.mod by constant b.*=997 transformation on insn" "tree_profile_ipa" } } */
+/* { dg-final-use { scan-ipa-dump "Div.mod by constant b.*=997 transformation on insn" "profile" } } */
 /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
 /* { dg-final-use { cleanup-tree-dump "optimized" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/tree-prof/val-prof-7.c
===================================================================
--- testsuite/gcc.dg/tree-prof/val-prof-7.c	(revision 174422)
+++ testsuite/gcc.dg/tree-prof/val-prof-7.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-ipa-tree_profile_ipa -mtune=core2" } */
+/* { dg-options "-O2 -fdump-ipa-profile -mtune=core2" } */
 /* { dg-skip-if "" { ! { i?86-*-* x86_64-*-* } } { "*" } { "" } } */
 
 #include <strings.h>
@@ -22,5 +22,5 @@ int main() {
   return 0;
 }
 
-/* { dg-final-use { scan-ipa-dump "Single value 8 stringop transformation on bzero" "tree_profile_ipa" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { scan-ipa-dump "Single value 8 stringop transformation on bzero" "profile" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: testsuite/gcc.dg/profile-dir-3.c
===================================================================
--- testsuite/gcc.dg/profile-dir-3.c	(revision 174422)
+++ testsuite/gcc.dg/profile-dir-3.c	(working copy)
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
-/* { dg-options "-O -fprofile-generate -fprofile-dir=. -fdump-ipa-tree_profile_ipa" } */
-/* { dg-final { scan-ipa-dump " ./profile-dir-3.gcda" "tree_profile_ipa" } } */
+/* { dg-options "-O -fprofile-generate -fprofile-dir=. -fdump-ipa-profile" } */
+/* { dg-final { scan-ipa-dump " ./profile-dir-3.gcda" "profile" } } */
 
 int
 main(void)
@@ -8,4 +8,4 @@ main(void)
   return 0;
 }
 
-/* { dg-final { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final { cleanup-ipa-dump "profile" } } */
Index: testsuite/g++.dg/tree-prof/indir-call-prof.C
===================================================================
--- testsuite/g++.dg/tree-prof/indir-call-prof.C	(revision 174422)
+++ testsuite/g++.dg/tree-prof/indir-call-prof.C	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-profile" } */
 
 struct A {
   A () {}
@@ -33,7 +33,7 @@ main (void)
   return 0;
 }
 
-/* { dg-final-use { scan-ipa-dump "Indirect call -> direct call.* AA transformation on insn" "tree_profile_ipa" } } */
+/* { dg-final-use { scan-ipa-dump "Indirect call -> direct call.* AA transformation on insn" "profile" } } */
 /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized" } } */
 /* { dg-final-use { cleanup-tree-dump "optimized" } } */
-/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
Index: predict.c
===================================================================
--- predict.c	(revision 174422)
+++ predict.c	(working copy)
@@ -2306,7 +2306,7 @@ struct gimple_opt_pass pass_profile =
 {
  {
   GIMPLE_PASS,
-  "profile",				/* name */
+  "profile_estimate",			/* name */
   gate_estimate_probability,		/* gate */
   tree_estimate_probability_driver,	/* execute */
   NULL,					/* sub */
Index: ipa.c
===================================================================
--- ipa.c	(revision 174422)
+++ ipa.c	(working copy)
@@ -1145,7 +1145,7 @@ struct ipa_opt_pass_d pass_ipa_profile =
 {
  {
   IPA_PASS,
-  "ipa-profile",			/* name */
+  "profile_estimate",			/* name */
   gate_ipa_profile,			/* gate */
   ipa_profile,			        /* execute */
   NULL,					/* sub */
Index: coretypes.h
===================================================================
--- coretypes.h	(revision 174422)
+++ coretypes.h	(working copy)
@@ -75,6 +75,7 @@ typedef struct diagnostic_context diagno
 struct gimple_seq_d;
 typedef struct gimple_seq_d *gimple_seq;
 typedef const struct gimple_seq_d *const_gimple_seq;
+struct function;
 
 /* Address space number for named address space support.  */
 typedef unsigned char addr_space_t;
@@ -172,4 +173,3 @@ union _dont_use_tree_here_;
 #endif
 
 #endif /* coretypes.h */
-
Index: except.c
===================================================================
--- except.c	(revision 174422)
+++ except.c	(working copy)
@@ -1457,7 +1457,7 @@ struct rtl_opt_pass pass_rtl_eh =
 {
  {
   RTL_PASS,
-  "rtl eh",                             /* name */
+  "rtl_eh",                             /* name */
   gate_handle_eh,                       /* gate */
   rest_of_handle_eh,			/* execute */
   NULL,                                 /* sub */
Index: tree-profile.c
===================================================================
--- tree-profile.c	(revision 174422)
+++ tree-profile.c	(working copy)
@@ -579,7 +579,7 @@ struct simple_ipa_opt_pass pass_ipa_tree
 {
  {
   SIMPLE_IPA_PASS,
-  "tree_profile_ipa",                  /* name */
+  "profile",  		               /* name */
   gate_tree_profile_ipa,               /* gate */
   tree_profiling,                      /* execute */
   NULL,                                /* sub */
Index: tree-cfg.c
===================================================================
--- tree-cfg.c	(revision 174422)
+++ tree-cfg.c	(working copy)
@@ -2052,11 +2052,7 @@ gimple_dump_cfg (FILE *file, int flags)
 {
   if (flags & TDF_DETAILS)
     {
-      const char *funcname
-	= lang_hooks.decl_printable_name (current_function_decl, 2);
-
-      fputc ('\n', file);
-      fprintf (file, ";; Function %s\n\n", funcname);
+      dump_function_header (file, current_function_decl, cfun);
       fprintf (file, ";; \n%d basic blocks, %d edges, last basic block %d.\n\n",
 	       n_basic_blocks, n_edges, last_basic_block);
 
@@ -7525,4 +7521,3 @@ struct gimple_opt_pass pass_warn_unused_
     0,					/* todo_flags_finish */
   }
 };
-
Index: passes.c
===================================================================
--- passes.c	(revision 174423)
+++ passes.c	(working copy)
@@ -74,6 +74,7 @@ along with GCC; see the file COPYING3.  
 #include "lto-streamer.h"
 #include "plugin.h"
 #include "ipa-utils.h"
+#include "tree-pretty-print.h"
 
 #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
 #include "dwarf2out.h"
@@ -1637,21 +1638,7 @@ pass_init_dump_file (struct opt_pass *pa
       dump_file_name = get_dump_file_name (pass->static_pass_number);
       dump_file = dump_begin (pass->static_pass_number, &dump_flags);
       if (dump_file && current_function_decl)
-	{
-	  const char *dname, *aname;
-	  struct cgraph_node *node = cgraph_get_node (current_function_decl);
-	  dname = lang_hooks.decl_printable_name (current_function_decl, 2);
-	  aname = (IDENTIFIER_POINTER
-		   (DECL_ASSEMBLER_NAME (current_function_decl)));
-	  fprintf (dump_file, "\n;; Function %s (%s)%s\n\n", dname, aname,
-	     node->frequency == NODE_FREQUENCY_HOT
-	     ? " (hot)"
-	     : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
-	     ? " (unlikely executed)"
-	     : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
-	     ? " (executed once)"
-	     : "");
-	}
+        dump_function_header (dump_file, current_function_decl, cfun);
       return initializing_dump;
     }
   else
Index: dce.c
===================================================================
--- dce.c	(revision 174422)
+++ dce.c	(working copy)
@@ -734,7 +734,7 @@ struct rtl_opt_pass pass_ud_rtl_dce =
 {
  {
   RTL_PASS,
-  "ud dce",                             /* name */
+  "ud_dce",                             /* name */
   gate_ud_dce,                          /* gate */
   rest_of_handle_ud_dce,                /* execute */
   NULL,                                 /* sub */
@@ -1086,7 +1086,7 @@ struct rtl_opt_pass pass_fast_rtl_dce =
 {
  {
   RTL_PASS,
-  "rtl dce",                            /* name */
+  "rtl_dce",                            /* name */
   gate_fast_dce,                        /* gate */
   rest_of_handle_fast_dce,              /* execute */
   NULL,                                 /* sub */

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-31 10:03                       ` Richard Guenther
@ 2011-06-01  0:02                         ` Xinliang David Li
  0 siblings, 0 replies; 32+ messages in thread
From: Xinliang David Li @ 2011-06-01  0:02 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: GCC Patches, reply

Honza, are you ok with the pass name change?

David

On Tue, May 31, 2011 at 2:07 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Mon, May 30, 2011 at 11:44 PM, Xinliang David Li <davidxl@google.com> wrote:
>> This is the complete patch for pass name fixes (with test case changes).
>
> This is ok if Honza thinks the profile pass names make more sense this
> way.
>
> Thanks,
> Richard.
>
>> David
>>
>>
>> On Mon, May 30, 2011 at 1:16 PM, Xinliang David Li <davidxl@google.com> wrote:
>>> The attached are two simple follow up patches
>>>
>>> 1) the first patch does some refactorization on function header
>>> dumping (with more information printed)
>>>
>>> 2) the second patch cleans up some pass names. Part of the cleanup
>>> results from a previous discussion with Honza -- a) rename
>>> 'tree_profile_ipa' into 'profile', and make 'ipa_profile' and
>>> 'profile' into 'profile_estimate'. The rest of cleanups are needed to
>>> make sure pass names are unique.
>>>
>>> Ok for trunk?
>>>
>>> Thanks,
>>>
>>> David
>>>
>>> On Fri, May 27, 2011 at 2:58 AM, Richard Guenther
>>> <richard.guenther@gmail.com> wrote:
>>>> On Fri, May 27, 2011 at 12:02 AM, Xinliang David Li <davidxl@google.com> wrote:
>>>>> The latest version that only exports 2 functions from passes.c.
>>>>
>>>> Ok with ...
>>>>
>>>> @@ -637,4 +637,8 @@ extern bool first_pass_instance;
>>>>  /* Declare for plugins.  */
>>>>  extern void do_per_function_toporder (void (*) (void *), void *);
>>>>
>>>> +extern void disable_pass (const char *);
>>>> +extern void enable_pass (const char *);
>>>> +struct function;
>>>> +
>>>>
>>>> struct function forward decl removed.
>>>>
>>>> +  explicitly_enabled = is_pass_explicitly_enabled (pass, func);
>>>> +  explicitly_disabled = is_pass_explicitly_disabled (pass, func);
>>>>
>>>> both functions inlined here and removed.
>>>>
>>>> +#define MAX_PASS_ID 512
>>>>
>>>> this removed and instead a VEC_safe_grow_cleared () or VEC_length ()
>>>> before the accesses.
>>>>
>>>> +-fenable-ipa-@var{pass} @gol
>>>> +-fenable-rtl-@var{pass} @gol
>>>> +-fenable-rtl-@var{pass}=@var{range-list} @gol
>>>> +-fenable-tree-@var{pass} @gol
>>>> +-fenable-tree-@var{pass}=@var{range-list} @gol
>>>>
>>>> -fenable-@var{kind}-@var{pass}, etc.
>>>>
>>>> +@item -fdisable-@var{ipa|tree|rtl}-@var{pass}
>>>> +@itemx -fenable-@var{ipa|tree|rtl}-@var{pass}
>>>> +@itemx -fdisable-@var{tree|rtl}-@var{pass}=@var{range-list}
>>>> +@itemx -fenable-@var{tree|rtl}-@var{pass}=@var{range-list}
>>>>
>>>> likewise.
>>>>
>>>> Thanks,
>>>> Richard.
>>>>
>>>>> David
>>>>>
>>>>> On Thu, May 26, 2011 at 2:04 PM, Xinliang David Li <davidxl@google.com> wrote:
>>>>>> On Thu, May 26, 2011 at 2:04 AM, Richard Guenther
>>>>>> <richard.guenther@gmail.com> wrote:
>>>>>>> On Wed, May 25, 2011 at 6:53 PM, Joseph S. Myers
>>>>>>> <joseph@codesourcery.com> wrote:
>>>>>>>> On Wed, 25 May 2011, Xinliang David Li wrote:
>>>>>>>>
>>>>>>>>> Ping. The link to the message:
>>>>>>>>>
>>>>>>>>> http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01303.html
>>>>>>>>
>>>>>>>> I don't consider this an option handling patch.  Patches adding whole new
>>>>>>>> features involving new options should be reviewed by maintainers for the
>>>>>>>> part of the compiler relevant to those features (since there isn't a pass
>>>>>>>> manager maintainer, I guess that means middle-end).
>>>>>>>
>>>>>>> Hmm, I suppose then you reviewed the option handling parts and they
>>>>>>> are ok?  Those globbing options always cause headache to me.
>>>>>>>
>>>>>>> +-fenable-ipa-@var{pass} @gol
>>>>>>> +-fenable-rtl-@var{pass} @gol
>>>>>>> +-fenable-rtl-@var{pass}=@var{range-list} @gol
>>>>>>> +-fenable-tree-@var{pass} @gol
>>>>>>>
>>>>>>> so, no -fenable-tree-@var{pass}=@var{range-list}?
>>>>>>>
>>>>>>
>>>>>> Missed. Will add.
>>>>>>
>>>>>>
>>>>>>> Does the pass name match 1:1 with the dump file name?  In which
>>>>>>> case
>>>>>>
>>>>>> Yes.
>>>>>>
>>>>>>>
>>>>>>> +Disable ipa pass @var{pass}. @var{pass} is the pass name. If the same
>>>>>>> pass is statically invoked in the compiler multiple times, the pass
>>>>>>> name should be appended with a sequential number starting from 1.
>>>>>>>
>>>>>>> isn't true as passes that are invoked only a single time lack the number
>>>>>>> suffix (yes, I'd really like that to be changed ...)
>>>>>>
>>>>>> Yes, pass with single static instance does not need number suffix.
>>>>>>
>>>>>>>
>>>>>>> Please break likes also in .texi files and stick to 80 columns.
>>>>>>
>>>>>> Done.
>>>>>>
>>>>>>>  Please
>>>>>>> document that these options are debugging options and regular
>>>>>>> options for enabling/disabling passes should be used.  I would suggest
>>>>>>> to group documentation differently and document -fenable-* and
>>>>>>> -fdisable-*, thus,
>>>>>>>
>>>>>>> + -fdisable-@var{kind}-@var{pass}
>>>>>>> + -fenable-@var{kind}-@var{pass}
>>>>>>>
>>>>>>> Even in .texi files please two spaces after a full-stop.
>>>>>>
>>>>>> Done
>>>>>>
>>>>>>>
>>>>>>> +extern void enable_disable_pass (const char *, bool);
>>>>>>>
>>>>>>> I'd rather have both enable_pass and disable_pass ;)
>>>>>>
>>>>>> Ok.
>>>>>>
>>>>>>>
>>>>>>> +struct function;
>>>>>>> +extern void pass_dump_function_header (FILE *, tree, struct function *);
>>>>>>>
>>>>>>> that's odd and probably should be split out, the function should
>>>>>>> maybe reside in tree-pretty-print.c.
>>>>>>
>>>>>> Ok.
>>>>>>
>>>>>>>
>>>>>>> Index: tree-ssa-loop-ivopts.c
>>>>>>> ===================================================================
>>>>>>> --- tree-ssa-loop-ivopts.c      (revision 173837)
>>>>>>> +++ tree-ssa-loop-ivopts.c      (working copy)
>>>>>>> @@ -3968,7 +3968,7 @@ get_computation_cost_at (struct ivopts_d
>>>>>>>
>>>>>>> well - doesn't belong here ;)
>>>>>>
>>>>>> Sorry -- many things in the same client -- not needed with your latest
>>>>>> change anyway.
>>>>>>
>>>>>>>
>>>>>>> +static hashval_t
>>>>>>> +passr_hash (const void *p)
>>>>>>> +{
>>>>>>> +  const struct pass_registry *const s = (const struct pass_registry *const) p;
>>>>>>> +  return htab_hash_string (s->unique_name);
>>>>>>> +}
>>>>>>> +
>>>>>>> +/* Hash equal function  */
>>>>>>> +
>>>>>>> +static int
>>>>>>> +passr_eq (const void *p1, const void *p2)
>>>>>>> +{
>>>>>>> +  const struct pass_registry *const s1 = (const struct pass_registry
>>>>>>> *const) p1;
>>>>>>> +  const struct pass_registry *const s2 = (const struct pass_registry
>>>>>>> *const) p2;
>>>>>>> +
>>>>>>> +  return !strcmp (s1->unique_name, s2->unique_name);
>>>>>>> +}
>>>>>>>
>>>>>>> you can use htab_hash_string and strcmp directly, no need for these
>>>>>>> wrappers.
>>>>>>
>>>>>> The hashtable entry is not string in this case. It is pass_registry,
>>>>>> thus the wrapper.
>>>>>>
>>>>>>>
>>>>>>> +void
>>>>>>> +register_pass_name (struct opt_pass *pass, const char *name)
>>>>>>>
>>>>>>> doesn't seem to need exporting, so don't and make it static.
>>>>>>
>>>>>> Done.
>>>>>>
>>>>>>>
>>>>>>> +  if (!pass_name_tab)
>>>>>>> +    pass_name_tab = htab_create (10, passr_hash, passr_eq, NULL);
>>>>>>>
>>>>>>> see above, the initial size should be larger - we have 223 passes at the
>>>>>>> moment, so use 256.
>>>>>>
>>>>>> Done.
>>>>>>
>>>>>>>
>>>>>>> +  else
>>>>>>> +    return; /* Ignore plugin passes.  */
>>>>>>>
>>>>>>> ?  You mean they might clash?
>>>>>>
>>>>>> Yes, name clash.
>>>>>>
>>>>>>>
>>>>>>> +struct opt_pass *
>>>>>>> +get_pass_by_name (const char *name)
>>>>>>>
>>>>>>> doesn't need exporting either.
>>>>>>
>>>>>> Done.
>>>>>>
>>>>>>>
>>>>>>> +      if (is_enable)
>>>>>>> +        error ("unrecognized option -fenable");
>>>>>>> +      else
>>>>>>> +        error ("unrecognized option -fdisable");
>>>>>>>
>>>>>>> I think that should be fatal_error - Joseph?
>>>>>>>
>>>>>>> +      if (is_enable)
>>>>>>> +        error ("unknown pass %s specified in -fenable", phase_name);
>>>>>>> +      else
>>>>>>> +        error ("unknown pass %s specified in -fdisble", phase_name);
>>>>>>>
>>>>>>> likewise.
>>>>>>>
>>>>>>> +      if (!enabled_pass_uid_range_tab)
>>>>>>> +       enabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
>>>>>>>
>>>>>>> instead of using a hashtable here please use a VEC indexed by
>>>>>>> the static_pass_number which shoud speed up
>>>>>>
>>>>>> Ok.  The reason I did not use it is because in most of the cases, the
>>>>>> htab will be very small -- it is determined by the number of passes
>>>>>> specified in the command line, while the VEC requires allocating const
>>>>>> size array. Not an issue as long as by default the array is not
>>>>>> allocated.
>>>>>>
>>>>>>>
>>>>>>> +static bool
>>>>>>> +is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
>>>>>>> +                                       tree func, htab_t tab)
>>>>>>> +{
>>>>>>> +  struct uid_range **slot, *range, key;
>>>>>>> +  int cgraph_uid;
>>>>>>> +
>>>>>>> +  if (!tab)
>>>>>>> +    return false;
>>>>>>> +
>>>>>>> +  key.pass = pass;
>>>>>>> +  slot = (struct uid_range **) htab_find_slot (tab, &key, NO_INSERT);
>>>>>>> +  if (!slot || !*slot)
>>>>>>> +    return false;
>>>>>>>
>>>>>>> and simplify the code quite a bit.
>>>>>>>
>>>>>>> +  cgraph_uid = func ? cgraph_get_node (func)->uid : 0;
>>>>>>>
>>>>>>> note that cgraph uids are recycled, so it might not be the best idea
>>>>>>> to use them as discriminator (though I don't have a good idea how
>>>>>>> to represent ranges without them).
>>>>>>
>>>>>> Yes. It is not a big problem as the blind search does not need to know
>>>>>> the id->name mapping. Once the id s found, it can be easily discovered
>>>>>> via dump.
>>>>>>
>>>>>>>
>>>>>>> +  explicitly_enabled = is_pass_explicitly_enabled (pass,
>>>>>>> current_function_decl);
>>>>>>> +  explicitly_disabled = is_pass_explicitly_disabled (pass,
>>>>>>> current_function_decl);
>>>>>>> +
>>>>>>>   current_pass = pass;
>>>>>>>
>>>>>>>   /* 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();
>>>>>>> +  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
>>>>>>>
>>>>>>> so explicitly disabling wins over explicit enabling ;)  I think this
>>>>>>> implementation detail and the fact that you always query both
>>>>>>> hints at that the interface should be like
>>>>>>>
>>>>>>> gate_status = override_gate_status (pass, current_function_decl, gate_status);
>>>>>>
>>>>>> Done.
>>>>>>
>>>>>>>
>>>>>>> instead.
>>>>>>>
>>>>>>> Thus, please split out the function header dumping changes and rework
>>>>>>> the rest of the patch as suggested.
>>>>>>
>>>>>> Split out. The new patch is attached.
>>>>>>
>>>>>> Ok after testing is done?
>>>>>>
>>>>>> Thanks,
>>>>>>
>>>>>> David
>>>>>>
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Richard.
>>>>>>>
>>>>>>>> --
>>>>>>>> Joseph S. Myers
>>>>>>>> joseph@codesourcery.com
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-06-01  0:01                         ` Xinliang David Li
@ 2011-06-01  0:04                           ` Xinliang David Li
  2011-06-01  8:14                             ` Jan Hubicka
  2011-06-01  9:23                             ` Richard Guenther
  0 siblings, 2 replies; 32+ messages in thread
From: Xinliang David Li @ 2011-06-01  0:04 UTC (permalink / raw)
  To: Richard Guenther; +Cc: GCC Patches, reply, Jan Hubicka

[-- Attachment #1: Type: text/plain, Size: 13436 bytes --]

Please discard the previous one. This is the right one:

David

On Tue, May 31, 2011 at 5:01 PM, Xinliang David Li <davidxl@google.com> wrote:
> The new patch is attached. The test (c,c++,fortran, java, ada) is on going.
>
> Thanks,
>
> David
>
> On Tue, May 31, 2011 at 9:06 AM, Xinliang David Li <davidxl@google.com> wrote:
>> On Tue, May 31, 2011 at 2:05 AM, Richard Guenther
>> <richard.guenther@gmail.com> wrote:
>>> On Mon, May 30, 2011 at 10:16 PM, Xinliang David Li <davidxl@google.com> wrote:
>>>> The attached are two simple follow up patches
>>>>
>>>> 1) the first patch does some refactorization on function header
>>>> dumping (with more information printed)
>>>>
>>>> 2) the second patch cleans up some pass names. Part of the cleanup
>>>> results from a previous discussion with Honza -- a) rename
>>>> 'tree_profile_ipa' into 'profile', and make 'ipa_profile' and
>>>> 'profile' into 'profile_estimate'. The rest of cleanups are needed to
>>>> make sure pass names are unique.
>>>>
>>>> Ok for trunk?
>>>
>>> +
>>> +void
>>> +pass_dump_function_header (FILE *dump_file, tree fdecl, struct function *fun)
>>>
>>> This function needs documentation, the ChangeLog entry misses
>>> the tree-pretty-print.h change.
>>>
>>> +struct function;
>>>
>>> instead of this please include coretypes.h from tree-pretty-print.h
>>> and add the struct function forward declaration there if it isn't already
>>> present.
>>>
>>> You change the output of the header, so please make sure you
>>> have bootstrapped and tested with _all_ languages included
>>> (and also watch for bugreports for target specific bugs).
>>>
>>
>> Ok.
>>
>>> +  fprintf (dump_file, "\n;; Function %s (%s, funcdef_no=%d, uid=%d)",
>>> +           dname, aname, fun->funcdef_no, node->uid);
>>>
>>> I see no point in dumping funcdef_no - it wasn't dumped before in
>>> any place.  Instead I miss dumping of the DECL_UID and thus
>>> a more specific 'uid', like 'cgraph-uid'.
>>
>> Ok will add decl_uid. Funcdef_no is very useful for debugging FDO
>> coverage mismatch related problems as it is the id used in profile
>> hashing.
>>
>>>
>>> +  aname = (IDENTIFIER_POINTER
>>> +          (DECL_ASSEMBLER_NAME (fdecl)));
>>>
>>> using DECL_ASSEMBLER_NAME is bad - it might trigger computation
>>> of DECL_ASSEMBLER_NAME which certainly shouldn't be done
>>> only for dumping purposes.  Instead do sth like
>>>
>>>   if (DECL_ASSEMBLER_NAME_SET_P (fdecl))
>>>     aname = DECL_ASSEMBLER_NAME (fdecl);
>>>   else
>>>     aname = '<unset-asm-name>';
>>
>> Ok.
>>
>>>
>>> and please also watch for cgraph_get_node returning NULL.
>>>
>>> Also please call the function dump_function_header instead of
>>> pass_dump_function_header.
>>>
>>
>> Ok.
>>
>> Thanks,
>>
>> David
>>> Please re-post with appropriate changes.
>>>
>>> Thanks,
>>> Richard.
>>>
>>>> Thanks,
>>>>
>>>> David
>>>>
>>>> On Fri, May 27, 2011 at 2:58 AM, Richard Guenther
>>>> <richard.guenther@gmail.com> wrote:
>>>>> On Fri, May 27, 2011 at 12:02 AM, Xinliang David Li <davidxl@google.com> wrote:
>>>>>> The latest version that only exports 2 functions from passes.c.
>>>>>
>>>>> Ok with ...
>>>>>
>>>>> @@ -637,4 +637,8 @@ extern bool first_pass_instance;
>>>>>  /* Declare for plugins.  */
>>>>>  extern void do_per_function_toporder (void (*) (void *), void *);
>>>>>
>>>>> +extern void disable_pass (const char *);
>>>>> +extern void enable_pass (const char *);
>>>>> +struct function;
>>>>> +
>>>>>
>>>>> struct function forward decl removed.
>>>>>
>>>>> +  explicitly_enabled = is_pass_explicitly_enabled (pass, func);
>>>>> +  explicitly_disabled = is_pass_explicitly_disabled (pass, func);
>>>>>
>>>>> both functions inlined here and removed.
>>>>>
>>>>> +#define MAX_PASS_ID 512
>>>>>
>>>>> this removed and instead a VEC_safe_grow_cleared () or VEC_length ()
>>>>> before the accesses.
>>>>>
>>>>> +-fenable-ipa-@var{pass} @gol
>>>>> +-fenable-rtl-@var{pass} @gol
>>>>> +-fenable-rtl-@var{pass}=@var{range-list} @gol
>>>>> +-fenable-tree-@var{pass} @gol
>>>>> +-fenable-tree-@var{pass}=@var{range-list} @gol
>>>>>
>>>>> -fenable-@var{kind}-@var{pass}, etc.
>>>>>
>>>>> +@item -fdisable-@var{ipa|tree|rtl}-@var{pass}
>>>>> +@itemx -fenable-@var{ipa|tree|rtl}-@var{pass}
>>>>> +@itemx -fdisable-@var{tree|rtl}-@var{pass}=@var{range-list}
>>>>> +@itemx -fenable-@var{tree|rtl}-@var{pass}=@var{range-list}
>>>>>
>>>>> likewise.
>>>>>
>>>>> Thanks,
>>>>> Richard.
>>>>>
>>>>>> David
>>>>>>
>>>>>> On Thu, May 26, 2011 at 2:04 PM, Xinliang David Li <davidxl@google.com> wrote:
>>>>>>> On Thu, May 26, 2011 at 2:04 AM, Richard Guenther
>>>>>>> <richard.guenther@gmail.com> wrote:
>>>>>>>> On Wed, May 25, 2011 at 6:53 PM, Joseph S. Myers
>>>>>>>> <joseph@codesourcery.com> wrote:
>>>>>>>>> On Wed, 25 May 2011, Xinliang David Li wrote:
>>>>>>>>>
>>>>>>>>>> Ping. The link to the message:
>>>>>>>>>>
>>>>>>>>>> http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01303.html
>>>>>>>>>
>>>>>>>>> I don't consider this an option handling patch.  Patches adding whole new
>>>>>>>>> features involving new options should be reviewed by maintainers for the
>>>>>>>>> part of the compiler relevant to those features (since there isn't a pass
>>>>>>>>> manager maintainer, I guess that means middle-end).
>>>>>>>>
>>>>>>>> Hmm, I suppose then you reviewed the option handling parts and they
>>>>>>>> are ok?  Those globbing options always cause headache to me.
>>>>>>>>
>>>>>>>> +-fenable-ipa-@var{pass} @gol
>>>>>>>> +-fenable-rtl-@var{pass} @gol
>>>>>>>> +-fenable-rtl-@var{pass}=@var{range-list} @gol
>>>>>>>> +-fenable-tree-@var{pass} @gol
>>>>>>>>
>>>>>>>> so, no -fenable-tree-@var{pass}=@var{range-list}?
>>>>>>>>
>>>>>>>
>>>>>>> Missed. Will add.
>>>>>>>
>>>>>>>
>>>>>>>> Does the pass name match 1:1 with the dump file name?  In which
>>>>>>>> case
>>>>>>>
>>>>>>> Yes.
>>>>>>>
>>>>>>>>
>>>>>>>> +Disable ipa pass @var{pass}. @var{pass} is the pass name. If the same
>>>>>>>> pass is statically invoked in the compiler multiple times, the pass
>>>>>>>> name should be appended with a sequential number starting from 1.
>>>>>>>>
>>>>>>>> isn't true as passes that are invoked only a single time lack the number
>>>>>>>> suffix (yes, I'd really like that to be changed ...)
>>>>>>>
>>>>>>> Yes, pass with single static instance does not need number suffix.
>>>>>>>
>>>>>>>>
>>>>>>>> Please break likes also in .texi files and stick to 80 columns.
>>>>>>>
>>>>>>> Done.
>>>>>>>
>>>>>>>>  Please
>>>>>>>> document that these options are debugging options and regular
>>>>>>>> options for enabling/disabling passes should be used.  I would suggest
>>>>>>>> to group documentation differently and document -fenable-* and
>>>>>>>> -fdisable-*, thus,
>>>>>>>>
>>>>>>>> + -fdisable-@var{kind}-@var{pass}
>>>>>>>> + -fenable-@var{kind}-@var{pass}
>>>>>>>>
>>>>>>>> Even in .texi files please two spaces after a full-stop.
>>>>>>>
>>>>>>> Done
>>>>>>>
>>>>>>>>
>>>>>>>> +extern void enable_disable_pass (const char *, bool);
>>>>>>>>
>>>>>>>> I'd rather have both enable_pass and disable_pass ;)
>>>>>>>
>>>>>>> Ok.
>>>>>>>
>>>>>>>>
>>>>>>>> +struct function;
>>>>>>>> +extern void pass_dump_function_header (FILE *, tree, struct function *);
>>>>>>>>
>>>>>>>> that's odd and probably should be split out, the function should
>>>>>>>> maybe reside in tree-pretty-print.c.
>>>>>>>
>>>>>>> Ok.
>>>>>>>
>>>>>>>>
>>>>>>>> Index: tree-ssa-loop-ivopts.c
>>>>>>>> ===================================================================
>>>>>>>> --- tree-ssa-loop-ivopts.c      (revision 173837)
>>>>>>>> +++ tree-ssa-loop-ivopts.c      (working copy)
>>>>>>>> @@ -3968,7 +3968,7 @@ get_computation_cost_at (struct ivopts_d
>>>>>>>>
>>>>>>>> well - doesn't belong here ;)
>>>>>>>
>>>>>>> Sorry -- many things in the same client -- not needed with your latest
>>>>>>> change anyway.
>>>>>>>
>>>>>>>>
>>>>>>>> +static hashval_t
>>>>>>>> +passr_hash (const void *p)
>>>>>>>> +{
>>>>>>>> +  const struct pass_registry *const s = (const struct pass_registry *const) p;
>>>>>>>> +  return htab_hash_string (s->unique_name);
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +/* Hash equal function  */
>>>>>>>> +
>>>>>>>> +static int
>>>>>>>> +passr_eq (const void *p1, const void *p2)
>>>>>>>> +{
>>>>>>>> +  const struct pass_registry *const s1 = (const struct pass_registry
>>>>>>>> *const) p1;
>>>>>>>> +  const struct pass_registry *const s2 = (const struct pass_registry
>>>>>>>> *const) p2;
>>>>>>>> +
>>>>>>>> +  return !strcmp (s1->unique_name, s2->unique_name);
>>>>>>>> +}
>>>>>>>>
>>>>>>>> you can use htab_hash_string and strcmp directly, no need for these
>>>>>>>> wrappers.
>>>>>>>
>>>>>>> The hashtable entry is not string in this case. It is pass_registry,
>>>>>>> thus the wrapper.
>>>>>>>
>>>>>>>>
>>>>>>>> +void
>>>>>>>> +register_pass_name (struct opt_pass *pass, const char *name)
>>>>>>>>
>>>>>>>> doesn't seem to need exporting, so don't and make it static.
>>>>>>>
>>>>>>> Done.
>>>>>>>
>>>>>>>>
>>>>>>>> +  if (!pass_name_tab)
>>>>>>>> +    pass_name_tab = htab_create (10, passr_hash, passr_eq, NULL);
>>>>>>>>
>>>>>>>> see above, the initial size should be larger - we have 223 passes at the
>>>>>>>> moment, so use 256.
>>>>>>>
>>>>>>> Done.
>>>>>>>
>>>>>>>>
>>>>>>>> +  else
>>>>>>>> +    return; /* Ignore plugin passes.  */
>>>>>>>>
>>>>>>>> ?  You mean they might clash?
>>>>>>>
>>>>>>> Yes, name clash.
>>>>>>>
>>>>>>>>
>>>>>>>> +struct opt_pass *
>>>>>>>> +get_pass_by_name (const char *name)
>>>>>>>>
>>>>>>>> doesn't need exporting either.
>>>>>>>
>>>>>>> Done.
>>>>>>>
>>>>>>>>
>>>>>>>> +      if (is_enable)
>>>>>>>> +        error ("unrecognized option -fenable");
>>>>>>>> +      else
>>>>>>>> +        error ("unrecognized option -fdisable");
>>>>>>>>
>>>>>>>> I think that should be fatal_error - Joseph?
>>>>>>>>
>>>>>>>> +      if (is_enable)
>>>>>>>> +        error ("unknown pass %s specified in -fenable", phase_name);
>>>>>>>> +      else
>>>>>>>> +        error ("unknown pass %s specified in -fdisble", phase_name);
>>>>>>>>
>>>>>>>> likewise.
>>>>>>>>
>>>>>>>> +      if (!enabled_pass_uid_range_tab)
>>>>>>>> +       enabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
>>>>>>>>
>>>>>>>> instead of using a hashtable here please use a VEC indexed by
>>>>>>>> the static_pass_number which shoud speed up
>>>>>>>
>>>>>>> Ok.  The reason I did not use it is because in most of the cases, the
>>>>>>> htab will be very small -- it is determined by the number of passes
>>>>>>> specified in the command line, while the VEC requires allocating const
>>>>>>> size array. Not an issue as long as by default the array is not
>>>>>>> allocated.
>>>>>>>
>>>>>>>>
>>>>>>>> +static bool
>>>>>>>> +is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
>>>>>>>> +                                       tree func, htab_t tab)
>>>>>>>> +{
>>>>>>>> +  struct uid_range **slot, *range, key;
>>>>>>>> +  int cgraph_uid;
>>>>>>>> +
>>>>>>>> +  if (!tab)
>>>>>>>> +    return false;
>>>>>>>> +
>>>>>>>> +  key.pass = pass;
>>>>>>>> +  slot = (struct uid_range **) htab_find_slot (tab, &key, NO_INSERT);
>>>>>>>> +  if (!slot || !*slot)
>>>>>>>> +    return false;
>>>>>>>>
>>>>>>>> and simplify the code quite a bit.
>>>>>>>>
>>>>>>>> +  cgraph_uid = func ? cgraph_get_node (func)->uid : 0;
>>>>>>>>
>>>>>>>> note that cgraph uids are recycled, so it might not be the best idea
>>>>>>>> to use them as discriminator (though I don't have a good idea how
>>>>>>>> to represent ranges without them).
>>>>>>>
>>>>>>> Yes. It is not a big problem as the blind search does not need to know
>>>>>>> the id->name mapping. Once the id s found, it can be easily discovered
>>>>>>> via dump.
>>>>>>>
>>>>>>>>
>>>>>>>> +  explicitly_enabled = is_pass_explicitly_enabled (pass,
>>>>>>>> current_function_decl);
>>>>>>>> +  explicitly_disabled = is_pass_explicitly_disabled (pass,
>>>>>>>> current_function_decl);
>>>>>>>> +
>>>>>>>>   current_pass = pass;
>>>>>>>>
>>>>>>>>   /* 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();
>>>>>>>> +  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
>>>>>>>>
>>>>>>>> so explicitly disabling wins over explicit enabling ;)  I think this
>>>>>>>> implementation detail and the fact that you always query both
>>>>>>>> hints at that the interface should be like
>>>>>>>>
>>>>>>>> gate_status = override_gate_status (pass, current_function_decl, gate_status);
>>>>>>>
>>>>>>> Done.
>>>>>>>
>>>>>>>>
>>>>>>>> instead.
>>>>>>>>
>>>>>>>> Thus, please split out the function header dumping changes and rework
>>>>>>>> the rest of the patch as suggested.
>>>>>>>
>>>>>>> Split out. The new patch is attached.
>>>>>>>
>>>>>>> Ok after testing is done?
>>>>>>>
>>>>>>> Thanks,
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>>>
>>>>>>>> Thanks,
>>>>>>>> Richard.
>>>>>>>>
>>>>>>>>> --
>>>>>>>>> Joseph S. Myers
>>>>>>>>> joseph@codesourcery.com
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>

[-- Attachment #2: header-print3.p --]
[-- Type: text/x-pascal, Size: 6068 bytes --]

Index: tree-pretty-print.c
===================================================================
--- tree-pretty-print.c	(revision 174424)
+++ tree-pretty-print.c	(working copy)
@@ -3013,3 +3013,36 @@ pp_base_tree_identifier (pretty_printer 
     pp_append_text (pp, IDENTIFIER_POINTER (id),
 		    IDENTIFIER_POINTER (id) + IDENTIFIER_LENGTH (id));
 }
+
+/* A helper function that is used to dump function information before the
+   function dump.  */
+
+void
+dump_function_header (FILE *dump_file, tree fdecl, struct function *fun)
+{
+  const char *dname, *aname;
+  struct cgraph_node *node = cgraph_get_node (fdecl);
+  dname = lang_hooks.decl_printable_name (fdecl, 2);
+
+  if (DECL_ASSEMBLER_NAME_SET_P (fdecl))
+    aname = (IDENTIFIER_POINTER
+             (DECL_ASSEMBLER_NAME (fdecl)));
+  else
+    aname = "<unset-asm-name>";
+
+  if (node)
+    fprintf (dump_file, "\n;; Function %s (%s, funcdef_no=%d, decl_uid = %d, cgraph_uid=%d)",
+             dname, aname, fun->funcdef_no, DECL_UID(fdecl), node->uid);
+  else
+    fprintf (dump_file, "\n;; Function %s (%s, funcdef_no=%d, decl_uid = %d)",
+             dname, aname, fun->funcdef_no, DECL_UID(fdecl));
+
+  fprintf (dump_file, "%s\n\n",
+           node->frequency == NODE_FREQUENCY_HOT
+           ? " (hot)"
+           : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
+           ? " (unlikely executed)"
+           : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
+           ? " (executed once)"
+           : "");
+}
Index: tree-pretty-print.h
===================================================================
--- tree-pretty-print.h	(revision 174422)
+++ tree-pretty-print.h	(working copy)
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.  
 #define GCC_TREE_PRETTY_PRINT_H
 
 #include "pretty-print.h"
+#include "coretypes.h"
 
 #define pp_tree_identifier(PP, T)                      \
   pp_base_tree_identifier (pp_base (PP), T)
@@ -50,6 +51,7 @@ extern void debug_generic_expr (tree);
 extern void debug_generic_stmt (tree);
 extern void debug_tree_chain (tree);
 extern void percent_K_format (text_info *);
+extern void dump_function_header (FILE *, tree, struct function *);
 
 /* In toplev.c  */
 extern bool default_tree_printer (pretty_printer *, text_info *, const char *,
Index: tree-cfg.c
===================================================================
--- tree-cfg.c	(revision 174422)
+++ tree-cfg.c	(working copy)
@@ -2052,11 +2052,7 @@ gimple_dump_cfg (FILE *file, int flags)
 {
   if (flags & TDF_DETAILS)
     {
-      const char *funcname
-	= lang_hooks.decl_printable_name (current_function_decl, 2);
-
-      fputc ('\n', file);
-      fprintf (file, ";; Function %s\n\n", funcname);
+      dump_function_header (file, current_function_decl, cfun);
       fprintf (file, ";; \n%d basic blocks, %d edges, last basic block %d.\n\n",
 	       n_basic_blocks, n_edges, last_basic_block);
 
@@ -7525,4 +7521,3 @@ struct gimple_opt_pass pass_warn_unused_
     0,					/* todo_flags_finish */
   }
 };
-
Index: coretypes.h
===================================================================
--- coretypes.h	(revision 174422)
+++ coretypes.h	(working copy)
@@ -75,6 +75,7 @@ typedef struct diagnostic_context diagno
 struct gimple_seq_d;
 typedef struct gimple_seq_d *gimple_seq;
 typedef const struct gimple_seq_d *const_gimple_seq;
+struct function;
 
 /* Address space number for named address space support.  */
 typedef unsigned char addr_space_t;
@@ -172,4 +173,3 @@ union _dont_use_tree_here_;
 #endif
 
 #endif /* coretypes.h */
-
Index: final.c
===================================================================
--- final.c	(revision 174422)
+++ final.c	(working copy)
@@ -83,6 +83,7 @@ along with GCC; see the file COPYING3.  
 #include "ggc.h"
 #include "cfgloop.h"
 #include "params.h"
+#include "tree-pretty-print.h"
 
 #ifdef XCOFF_DEBUGGING_INFO
 #include "xcoffout.h"		/* Needed for external data
@@ -4360,20 +4361,7 @@ rest_of_clean_state (void)
 	}
       else
 	{
-	  const char *aname;
-	  struct cgraph_node *node = cgraph_get_node (current_function_decl);
-
-	  aname = (IDENTIFIER_POINTER
-		   (DECL_ASSEMBLER_NAME (current_function_decl)));
-	  fprintf (final_output, "\n;; Function (%s) %s\n\n", aname,
-	     node->frequency == NODE_FREQUENCY_HOT
-	     ? " (hot)"
-	     : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
-	     ? " (unlikely executed)"
-	     : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
-	     ? " (executed once)"
-	     : "");
-
+	  dump_function_header (final_output, current_function_decl, cfun);
 	  flag_dump_noaddr = flag_dump_unnumbered = 1;
 	  if (flag_compare_debug_opt || flag_compare_debug)
 	    dump_flags |= TDF_NOUID;
Index: passes.c
===================================================================
--- passes.c	(revision 174423)
+++ passes.c	(working copy)
@@ -74,6 +74,7 @@ along with GCC; see the file COPYING3.  
 #include "lto-streamer.h"
 #include "plugin.h"
 #include "ipa-utils.h"
+#include "tree-pretty-print.h"
 
 #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
 #include "dwarf2out.h"
@@ -1637,21 +1638,7 @@ pass_init_dump_file (struct opt_pass *pa
       dump_file_name = get_dump_file_name (pass->static_pass_number);
       dump_file = dump_begin (pass->static_pass_number, &dump_flags);
       if (dump_file && current_function_decl)
-	{
-	  const char *dname, *aname;
-	  struct cgraph_node *node = cgraph_get_node (current_function_decl);
-	  dname = lang_hooks.decl_printable_name (current_function_decl, 2);
-	  aname = (IDENTIFIER_POINTER
-		   (DECL_ASSEMBLER_NAME (current_function_decl)));
-	  fprintf (dump_file, "\n;; Function %s (%s)%s\n\n", dname, aname,
-	     node->frequency == NODE_FREQUENCY_HOT
-	     ? " (hot)"
-	     : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
-	     ? " (unlikely executed)"
-	     : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
-	     ? " (executed once)"
-	     : "");
-	}
+        dump_function_header (dump_file, current_function_decl, cfun);
       return initializing_dump;
     }
   else

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-06-01  0:04                           ` Xinliang David Li
@ 2011-06-01  8:14                             ` Jan Hubicka
  2011-06-01  9:23                             ` Richard Guenther
  1 sibling, 0 replies; 32+ messages in thread
From: Jan Hubicka @ 2011-06-01  8:14 UTC (permalink / raw)
  To: Xinliang David Li; +Cc: Richard Guenther, GCC Patches, reply, Jan Hubicka

> Please discard the previous one. This is the right one:
> 
> David
> Index: tree-pretty-print.c
> ===================================================================
> --- tree-pretty-print.c	(revision 174424)
> +++ tree-pretty-print.c	(working copy)
> @@ -3013,3 +3013,36 @@ pp_base_tree_identifier (pretty_printer 
>      pp_append_text (pp, IDENTIFIER_POINTER (id),
>  		    IDENTIFIER_POINTER (id) + IDENTIFIER_LENGTH (id));
>  }
> +
> +/* A helper function that is used to dump function information before the
> +   function dump.  */
> +
> +void
> +dump_function_header (FILE *dump_file, tree fdecl, struct function *fun)

You can get to FUN via DECL_STRUCT_FUNCTION (fndecl) that would save you a parameter...
> Index: tree-pretty-print.h
> ===================================================================
> --- tree-pretty-print.h	(revision 174422)
> +++ tree-pretty-print.h	(working copy)
> @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.  
>  #define GCC_TREE_PRETTY_PRINT_H
>  
>  #include "pretty-print.h"
> +#include "coretypes.h"

.. and need for this
> Index: coretypes.h
> ===================================================================
> --- coretypes.h	(revision 174422)
> +++ coretypes.h	(working copy)
> @@ -75,6 +75,7 @@ typedef struct diagnostic_context diagno
>  struct gimple_seq_d;
>  typedef struct gimple_seq_d *gimple_seq;
>  typedef const struct gimple_seq_d *const_gimple_seq;
> +struct function;

... and this.

Otherwise the patch seems OK.  You need to update Makefile.in for new dependencies.

Honza

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-06-01  0:04                           ` Xinliang David Li
  2011-06-01  8:14                             ` Jan Hubicka
@ 2011-06-01  9:23                             ` Richard Guenther
  2011-06-01  9:27                               ` Jan Hubicka
  1 sibling, 1 reply; 32+ messages in thread
From: Richard Guenther @ 2011-06-01  9:23 UTC (permalink / raw)
  To: Xinliang David Li; +Cc: GCC Patches, reply, Jan Hubicka

On Wed, Jun 1, 2011 at 2:03 AM, Xinliang David Li <davidxl@google.com> wrote:
> Please discard the previous one. This is the right one:

See also Honzas comments (on the wrong patch presumably ;)).

+  if (node)
+    fprintf (dump_file, "\n;; Function %s (%s, funcdef_no=%d,
decl_uid = %d, cgraph_uid=%d)",
+             dname, aname, fun->funcdef_no, DECL_UID(fdecl), node->uid);
+  else
+    fprintf (dump_file, "\n;; Function %s (%s, funcdef_no=%d, decl_uid = %d)",
+             dname, aname, fun->funcdef_no, DECL_UID(fdecl));
+
+  fprintf (dump_file, "%s\n\n",
+           node->frequency == NODE_FREQUENCY_HOT

you also need to check for node == NULL here.

Ok with this (and honzas suggested change for not passing struct
function *).

Thanks,
Richard.

> David
>
> On Tue, May 31, 2011 at 5:01 PM, Xinliang David Li <davidxl@google.com> wrote:
>> The new patch is attached. The test (c,c++,fortran, java, ada) is on going.
>>
>> Thanks,
>>
>> David
>>
>> On Tue, May 31, 2011 at 9:06 AM, Xinliang David Li <davidxl@google.com> wrote:
>>> On Tue, May 31, 2011 at 2:05 AM, Richard Guenther
>>> <richard.guenther@gmail.com> wrote:
>>>> On Mon, May 30, 2011 at 10:16 PM, Xinliang David Li <davidxl@google.com> wrote:
>>>>> The attached are two simple follow up patches
>>>>>
>>>>> 1) the first patch does some refactorization on function header
>>>>> dumping (with more information printed)
>>>>>
>>>>> 2) the second patch cleans up some pass names. Part of the cleanup
>>>>> results from a previous discussion with Honza -- a) rename
>>>>> 'tree_profile_ipa' into 'profile', and make 'ipa_profile' and
>>>>> 'profile' into 'profile_estimate'. The rest of cleanups are needed to
>>>>> make sure pass names are unique.
>>>>>
>>>>> Ok for trunk?
>>>>
>>>> +
>>>> +void
>>>> +pass_dump_function_header (FILE *dump_file, tree fdecl, struct function *fun)
>>>>
>>>> This function needs documentation, the ChangeLog entry misses
>>>> the tree-pretty-print.h change.
>>>>
>>>> +struct function;
>>>>
>>>> instead of this please include coretypes.h from tree-pretty-print.h
>>>> and add the struct function forward declaration there if it isn't already
>>>> present.
>>>>
>>>> You change the output of the header, so please make sure you
>>>> have bootstrapped and tested with _all_ languages included
>>>> (and also watch for bugreports for target specific bugs).
>>>>
>>>
>>> Ok.
>>>
>>>> +  fprintf (dump_file, "\n;; Function %s (%s, funcdef_no=%d, uid=%d)",
>>>> +           dname, aname, fun->funcdef_no, node->uid);
>>>>
>>>> I see no point in dumping funcdef_no - it wasn't dumped before in
>>>> any place.  Instead I miss dumping of the DECL_UID and thus
>>>> a more specific 'uid', like 'cgraph-uid'.
>>>
>>> Ok will add decl_uid. Funcdef_no is very useful for debugging FDO
>>> coverage mismatch related problems as it is the id used in profile
>>> hashing.
>>>
>>>>
>>>> +  aname = (IDENTIFIER_POINTER
>>>> +          (DECL_ASSEMBLER_NAME (fdecl)));
>>>>
>>>> using DECL_ASSEMBLER_NAME is bad - it might trigger computation
>>>> of DECL_ASSEMBLER_NAME which certainly shouldn't be done
>>>> only for dumping purposes.  Instead do sth like
>>>>
>>>>   if (DECL_ASSEMBLER_NAME_SET_P (fdecl))
>>>>     aname = DECL_ASSEMBLER_NAME (fdecl);
>>>>   else
>>>>     aname = '<unset-asm-name>';
>>>
>>> Ok.
>>>
>>>>
>>>> and please also watch for cgraph_get_node returning NULL.
>>>>
>>>> Also please call the function dump_function_header instead of
>>>> pass_dump_function_header.
>>>>
>>>
>>> Ok.
>>>
>>> Thanks,
>>>
>>> David
>>>> Please re-post with appropriate changes.
>>>>
>>>> Thanks,
>>>> Richard.
>>>>
>>>>> Thanks,
>>>>>
>>>>> David
>>>>>
>>>>> On Fri, May 27, 2011 at 2:58 AM, Richard Guenther
>>>>> <richard.guenther@gmail.com> wrote:
>>>>>> On Fri, May 27, 2011 at 12:02 AM, Xinliang David Li <davidxl@google.com> wrote:
>>>>>>> The latest version that only exports 2 functions from passes.c.
>>>>>>
>>>>>> Ok with ...
>>>>>>
>>>>>> @@ -637,4 +637,8 @@ extern bool first_pass_instance;
>>>>>>  /* Declare for plugins.  */
>>>>>>  extern void do_per_function_toporder (void (*) (void *), void *);
>>>>>>
>>>>>> +extern void disable_pass (const char *);
>>>>>> +extern void enable_pass (const char *);
>>>>>> +struct function;
>>>>>> +
>>>>>>
>>>>>> struct function forward decl removed.
>>>>>>
>>>>>> +  explicitly_enabled = is_pass_explicitly_enabled (pass, func);
>>>>>> +  explicitly_disabled = is_pass_explicitly_disabled (pass, func);
>>>>>>
>>>>>> both functions inlined here and removed.
>>>>>>
>>>>>> +#define MAX_PASS_ID 512
>>>>>>
>>>>>> this removed and instead a VEC_safe_grow_cleared () or VEC_length ()
>>>>>> before the accesses.
>>>>>>
>>>>>> +-fenable-ipa-@var{pass} @gol
>>>>>> +-fenable-rtl-@var{pass} @gol
>>>>>> +-fenable-rtl-@var{pass}=@var{range-list} @gol
>>>>>> +-fenable-tree-@var{pass} @gol
>>>>>> +-fenable-tree-@var{pass}=@var{range-list} @gol
>>>>>>
>>>>>> -fenable-@var{kind}-@var{pass}, etc.
>>>>>>
>>>>>> +@item -fdisable-@var{ipa|tree|rtl}-@var{pass}
>>>>>> +@itemx -fenable-@var{ipa|tree|rtl}-@var{pass}
>>>>>> +@itemx -fdisable-@var{tree|rtl}-@var{pass}=@var{range-list}
>>>>>> +@itemx -fenable-@var{tree|rtl}-@var{pass}=@var{range-list}
>>>>>>
>>>>>> likewise.
>>>>>>
>>>>>> Thanks,
>>>>>> Richard.
>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> On Thu, May 26, 2011 at 2:04 PM, Xinliang David Li <davidxl@google.com> wrote:
>>>>>>>> On Thu, May 26, 2011 at 2:04 AM, Richard Guenther
>>>>>>>> <richard.guenther@gmail.com> wrote:
>>>>>>>>> On Wed, May 25, 2011 at 6:53 PM, Joseph S. Myers
>>>>>>>>> <joseph@codesourcery.com> wrote:
>>>>>>>>>> On Wed, 25 May 2011, Xinliang David Li wrote:
>>>>>>>>>>
>>>>>>>>>>> Ping. The link to the message:
>>>>>>>>>>>
>>>>>>>>>>> http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01303.html
>>>>>>>>>>
>>>>>>>>>> I don't consider this an option handling patch.  Patches adding whole new
>>>>>>>>>> features involving new options should be reviewed by maintainers for the
>>>>>>>>>> part of the compiler relevant to those features (since there isn't a pass
>>>>>>>>>> manager maintainer, I guess that means middle-end).
>>>>>>>>>
>>>>>>>>> Hmm, I suppose then you reviewed the option handling parts and they
>>>>>>>>> are ok?  Those globbing options always cause headache to me.
>>>>>>>>>
>>>>>>>>> +-fenable-ipa-@var{pass} @gol
>>>>>>>>> +-fenable-rtl-@var{pass} @gol
>>>>>>>>> +-fenable-rtl-@var{pass}=@var{range-list} @gol
>>>>>>>>> +-fenable-tree-@var{pass} @gol
>>>>>>>>>
>>>>>>>>> so, no -fenable-tree-@var{pass}=@var{range-list}?
>>>>>>>>>
>>>>>>>>
>>>>>>>> Missed. Will add.
>>>>>>>>
>>>>>>>>
>>>>>>>>> Does the pass name match 1:1 with the dump file name?  In which
>>>>>>>>> case
>>>>>>>>
>>>>>>>> Yes.
>>>>>>>>
>>>>>>>>>
>>>>>>>>> +Disable ipa pass @var{pass}. @var{pass} is the pass name. If the same
>>>>>>>>> pass is statically invoked in the compiler multiple times, the pass
>>>>>>>>> name should be appended with a sequential number starting from 1.
>>>>>>>>>
>>>>>>>>> isn't true as passes that are invoked only a single time lack the number
>>>>>>>>> suffix (yes, I'd really like that to be changed ...)
>>>>>>>>
>>>>>>>> Yes, pass with single static instance does not need number suffix.
>>>>>>>>
>>>>>>>>>
>>>>>>>>> Please break likes also in .texi files and stick to 80 columns.
>>>>>>>>
>>>>>>>> Done.
>>>>>>>>
>>>>>>>>>  Please
>>>>>>>>> document that these options are debugging options and regular
>>>>>>>>> options for enabling/disabling passes should be used.  I would suggest
>>>>>>>>> to group documentation differently and document -fenable-* and
>>>>>>>>> -fdisable-*, thus,
>>>>>>>>>
>>>>>>>>> + -fdisable-@var{kind}-@var{pass}
>>>>>>>>> + -fenable-@var{kind}-@var{pass}
>>>>>>>>>
>>>>>>>>> Even in .texi files please two spaces after a full-stop.
>>>>>>>>
>>>>>>>> Done
>>>>>>>>
>>>>>>>>>
>>>>>>>>> +extern void enable_disable_pass (const char *, bool);
>>>>>>>>>
>>>>>>>>> I'd rather have both enable_pass and disable_pass ;)
>>>>>>>>
>>>>>>>> Ok.
>>>>>>>>
>>>>>>>>>
>>>>>>>>> +struct function;
>>>>>>>>> +extern void pass_dump_function_header (FILE *, tree, struct function *);
>>>>>>>>>
>>>>>>>>> that's odd and probably should be split out, the function should
>>>>>>>>> maybe reside in tree-pretty-print.c.
>>>>>>>>
>>>>>>>> Ok.
>>>>>>>>
>>>>>>>>>
>>>>>>>>> Index: tree-ssa-loop-ivopts.c
>>>>>>>>> ===================================================================
>>>>>>>>> --- tree-ssa-loop-ivopts.c      (revision 173837)
>>>>>>>>> +++ tree-ssa-loop-ivopts.c      (working copy)
>>>>>>>>> @@ -3968,7 +3968,7 @@ get_computation_cost_at (struct ivopts_d
>>>>>>>>>
>>>>>>>>> well - doesn't belong here ;)
>>>>>>>>
>>>>>>>> Sorry -- many things in the same client -- not needed with your latest
>>>>>>>> change anyway.
>>>>>>>>
>>>>>>>>>
>>>>>>>>> +static hashval_t
>>>>>>>>> +passr_hash (const void *p)
>>>>>>>>> +{
>>>>>>>>> +  const struct pass_registry *const s = (const struct pass_registry *const) p;
>>>>>>>>> +  return htab_hash_string (s->unique_name);
>>>>>>>>> +}
>>>>>>>>> +
>>>>>>>>> +/* Hash equal function  */
>>>>>>>>> +
>>>>>>>>> +static int
>>>>>>>>> +passr_eq (const void *p1, const void *p2)
>>>>>>>>> +{
>>>>>>>>> +  const struct pass_registry *const s1 = (const struct pass_registry
>>>>>>>>> *const) p1;
>>>>>>>>> +  const struct pass_registry *const s2 = (const struct pass_registry
>>>>>>>>> *const) p2;
>>>>>>>>> +
>>>>>>>>> +  return !strcmp (s1->unique_name, s2->unique_name);
>>>>>>>>> +}
>>>>>>>>>
>>>>>>>>> you can use htab_hash_string and strcmp directly, no need for these
>>>>>>>>> wrappers.
>>>>>>>>
>>>>>>>> The hashtable entry is not string in this case. It is pass_registry,
>>>>>>>> thus the wrapper.
>>>>>>>>
>>>>>>>>>
>>>>>>>>> +void
>>>>>>>>> +register_pass_name (struct opt_pass *pass, const char *name)
>>>>>>>>>
>>>>>>>>> doesn't seem to need exporting, so don't and make it static.
>>>>>>>>
>>>>>>>> Done.
>>>>>>>>
>>>>>>>>>
>>>>>>>>> +  if (!pass_name_tab)
>>>>>>>>> +    pass_name_tab = htab_create (10, passr_hash, passr_eq, NULL);
>>>>>>>>>
>>>>>>>>> see above, the initial size should be larger - we have 223 passes at the
>>>>>>>>> moment, so use 256.
>>>>>>>>
>>>>>>>> Done.
>>>>>>>>
>>>>>>>>>
>>>>>>>>> +  else
>>>>>>>>> +    return; /* Ignore plugin passes.  */
>>>>>>>>>
>>>>>>>>> ?  You mean they might clash?
>>>>>>>>
>>>>>>>> Yes, name clash.
>>>>>>>>
>>>>>>>>>
>>>>>>>>> +struct opt_pass *
>>>>>>>>> +get_pass_by_name (const char *name)
>>>>>>>>>
>>>>>>>>> doesn't need exporting either.
>>>>>>>>
>>>>>>>> Done.
>>>>>>>>
>>>>>>>>>
>>>>>>>>> +      if (is_enable)
>>>>>>>>> +        error ("unrecognized option -fenable");
>>>>>>>>> +      else
>>>>>>>>> +        error ("unrecognized option -fdisable");
>>>>>>>>>
>>>>>>>>> I think that should be fatal_error - Joseph?
>>>>>>>>>
>>>>>>>>> +      if (is_enable)
>>>>>>>>> +        error ("unknown pass %s specified in -fenable", phase_name);
>>>>>>>>> +      else
>>>>>>>>> +        error ("unknown pass %s specified in -fdisble", phase_name);
>>>>>>>>>
>>>>>>>>> likewise.
>>>>>>>>>
>>>>>>>>> +      if (!enabled_pass_uid_range_tab)
>>>>>>>>> +       enabled_pass_uid_range_tab = htab_create (10, pass_hash, pass_eq, NULL);
>>>>>>>>>
>>>>>>>>> instead of using a hashtable here please use a VEC indexed by
>>>>>>>>> the static_pass_number which shoud speed up
>>>>>>>>
>>>>>>>> Ok.  The reason I did not use it is because in most of the cases, the
>>>>>>>> htab will be very small -- it is determined by the number of passes
>>>>>>>> specified in the command line, while the VEC requires allocating const
>>>>>>>> size array. Not an issue as long as by default the array is not
>>>>>>>> allocated.
>>>>>>>>
>>>>>>>>>
>>>>>>>>> +static bool
>>>>>>>>> +is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
>>>>>>>>> +                                       tree func, htab_t tab)
>>>>>>>>> +{
>>>>>>>>> +  struct uid_range **slot, *range, key;
>>>>>>>>> +  int cgraph_uid;
>>>>>>>>> +
>>>>>>>>> +  if (!tab)
>>>>>>>>> +    return false;
>>>>>>>>> +
>>>>>>>>> +  key.pass = pass;
>>>>>>>>> +  slot = (struct uid_range **) htab_find_slot (tab, &key, NO_INSERT);
>>>>>>>>> +  if (!slot || !*slot)
>>>>>>>>> +    return false;
>>>>>>>>>
>>>>>>>>> and simplify the code quite a bit.
>>>>>>>>>
>>>>>>>>> +  cgraph_uid = func ? cgraph_get_node (func)->uid : 0;
>>>>>>>>>
>>>>>>>>> note that cgraph uids are recycled, so it might not be the best idea
>>>>>>>>> to use them as discriminator (though I don't have a good idea how
>>>>>>>>> to represent ranges without them).
>>>>>>>>
>>>>>>>> Yes. It is not a big problem as the blind search does not need to know
>>>>>>>> the id->name mapping. Once the id s found, it can be easily discovered
>>>>>>>> via dump.
>>>>>>>>
>>>>>>>>>
>>>>>>>>> +  explicitly_enabled = is_pass_explicitly_enabled (pass,
>>>>>>>>> current_function_decl);
>>>>>>>>> +  explicitly_disabled = is_pass_explicitly_disabled (pass,
>>>>>>>>> current_function_decl);
>>>>>>>>> +
>>>>>>>>>   current_pass = pass;
>>>>>>>>>
>>>>>>>>>   /* 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();
>>>>>>>>> +  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
>>>>>>>>>
>>>>>>>>> so explicitly disabling wins over explicit enabling ;)  I think this
>>>>>>>>> implementation detail and the fact that you always query both
>>>>>>>>> hints at that the interface should be like
>>>>>>>>>
>>>>>>>>> gate_status = override_gate_status (pass, current_function_decl, gate_status);
>>>>>>>>
>>>>>>>> Done.
>>>>>>>>
>>>>>>>>>
>>>>>>>>> instead.
>>>>>>>>>
>>>>>>>>> Thus, please split out the function header dumping changes and rework
>>>>>>>>> the rest of the patch as suggested.
>>>>>>>>
>>>>>>>> Split out. The new patch is attached.
>>>>>>>>
>>>>>>>> Ok after testing is done?
>>>>>>>>
>>>>>>>> Thanks,
>>>>>>>>
>>>>>>>> David
>>>>>>>>
>>>>>>>>>
>>>>>>>>> Thanks,
>>>>>>>>> Richard.
>>>>>>>>>
>>>>>>>>>> --
>>>>>>>>>> Joseph S. Myers
>>>>>>>>>> joseph@codesourcery.com
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-06-01  9:23                             ` Richard Guenther
@ 2011-06-01  9:27                               ` Jan Hubicka
  0 siblings, 0 replies; 32+ messages in thread
From: Jan Hubicka @ 2011-06-01  9:27 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Xinliang David Li, GCC Patches, reply, Jan Hubicka

> On Wed, Jun 1, 2011 at 2:03 AM, Xinliang David Li <davidxl@google.com> wrote:
> > Please discard the previous one. This is the right one:
> 
> See also Honzas comments (on the wrong patch presumably ;)).
> 
> +  if (node)
> +    fprintf (dump_file, "\n;; Function %s (%s, funcdef_no=%d,
> decl_uid = %d, cgraph_uid=%d)",
> +             dname, aname, fun->funcdef_no, DECL_UID(fdecl), node->uid);
> +  else
> +    fprintf (dump_file, "\n;; Function %s (%s, funcdef_no=%d, decl_uid = %d)",
> +             dname, aname, fun->funcdef_no, DECL_UID(fdecl));
> +
> +  fprintf (dump_file, "%s\n\n",
> +           node->frequency == NODE_FREQUENCY_HOT
> 
> you also need to check for node == NULL here.
> 
> Ok with this (and honzas suggested change for not passing struct
> function *).
Also I still think the function funcdef_no is quite redundant UID. For debugging profiling
I would go for cgraph_uid instead.  It has also the advantage of being available at WPA stage.
But I have nothing against printing it here.

Honza

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: New options to disable/enable any pass for any functions (issue4550056)
  2011-05-31  7:05                     ` Xinliang David Li
  2011-05-31 10:03                       ` Richard Guenther
@ 2011-06-01 19:19                       ` H.J. Lu
  1 sibling, 0 replies; 32+ messages in thread
From: H.J. Lu @ 2011-06-01 19:19 UTC (permalink / raw)
  To: Xinliang David Li; +Cc: GCC Patches, reply, Richard Guenther, Jan Hubicka

On Mon, May 30, 2011 at 2:44 PM, Xinliang David Li <davidxl@google.com> wrote:
> This is the complete patch for pass name fixes (with test case changes).
>
> David
>
>

I think your change caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49261


H.J.

^ permalink raw reply	[flat|nested] 32+ messages in thread

end of thread, other threads:[~2011-06-01 19:19 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-18 19:49 New options to disable/enable any pass for any functions (issue4550056) David Li
2011-05-18 20:21 ` Joseph S. Myers
2011-05-18 20:33   ` Xinliang David Li
2011-05-20 16:44   ` Xinliang David Li
2011-05-23  9:17     ` Xinliang David Li
2011-05-25 17:21       ` Xinliang David Li
2011-05-25 17:44         ` Joseph S. Myers
2011-05-25 18:07           ` Xinliang David Li
2011-05-26 10:20           ` Richard Guenther
2011-05-26 13:00             ` Joseph S. Myers
2011-05-26 23:48             ` Xinliang David Li
2011-05-27  2:32               ` Xinliang David Li
2011-05-27 12:50                 ` Richard Guenther
2011-05-31  4:54                   ` Xinliang David Li
2011-05-31  7:05                     ` Xinliang David Li
2011-05-31 10:03                       ` Richard Guenther
2011-06-01  0:02                         ` Xinliang David Li
2011-06-01 19:19                       ` H.J. Lu
2011-05-31  9:57                     ` Richard Guenther
2011-05-31 17:30                       ` Xinliang David Li
2011-06-01  0:01                         ` Xinliang David Li
2011-06-01  0:04                           ` Xinliang David Li
2011-06-01  8:14                             ` Jan Hubicka
2011-06-01  9:23                             ` Richard Guenther
2011-06-01  9:27                               ` Jan Hubicka
2011-05-18 21:01 ` Richard Guenther
2011-05-18 21:20   ` Xinliang David Li
2011-05-19  8:04     ` Xinliang David Li
2011-05-19 19:23 ` Andi Kleen
2011-05-19 19:33   ` Xinliang David Li
2011-05-19 20:25     ` Andi Kleen
2011-05-19 21:36       ` Xinliang David Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).