This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: New options to disable/enable any pass for any functions (issue4550056)


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
>>>
>>
>
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);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]