On Thu, May 26, 2011 at 2:04 AM, Richard Guenther
<richard.guent...@gmail.com> wrote:
> On Wed, May 25, 2011 at 6:53 PM, Joseph S. Myers
> <jos...@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
>> jos...@codesourcery.com
>>
>
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}

Reply via email to