public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: Fwd: RFA: plugin events for ICI
       [not found] <20091130133452.hgxpnrkgu8cw0gk8-nzlynne@webmail.spamcop.net>
@ 2009-11-30 19:11 ` Basile STARYNKEVITCH
  2009-11-30 19:49   ` Joern Rennecke
  0 siblings, 1 reply; 13+ messages in thread
From: Basile STARYNKEVITCH @ 2009-11-30 19:11 UTC (permalink / raw)
  To: ctuning-discussions, gcc-patches
  Cc: Grigori Fursin, 'Grigori Fursin',
	'Zbigniew Chamski', 'Richard Guenther',
	'Ian Lance Taylor', 'Albert Cohen',
	'Yuri Kashnikoff', 'Yuanjie Huang',
	'Liang Peng', dorit, 'Mircea Namolaru',
	'Diego Novillo'

Joern Rennecke wrote:
> 
> ----- Forwarded message from amylaar@spamcop.net -----
>      Date: Mon, 30 Nov 2009 13:29:31 -0500
>      From: Joern Rennecke <amylaar@spamcop.net>
> Reply-To: Joern Rennecke <amylaar@spamcop.net>
>   Subject: RFA: plugin events for ICI
>        To: gcc-patches@gcc.gnu.org
> 
> This patch adds the events needed to support ICI, the Interactive
> Compilation Interface used by the ctuning.org community.
> 
> 
--- gcc/gcc/doc/plugins.texi	2009-11-29 17:42:32.565901921 +0000
+++ gcc-ici-2/gcc/doc/plugins.texi	2009-11-30 16:35:59.804653957 +0000
@@ -156,18 +156,48 @@ enum plugin_event
    PLUGIN_ATTRIBUTES,            /* Called during attribute registration */
    PLUGIN_START_UNIT,            /* Called before processing a translation unit.  */
    PLUGIN_PRAGMAS,	        /* Called during pragma registration. */
-  PLUGIN_EVENT_LAST             /* Dummy event used for indexing callback
+  /* Called to allow inspection and/or modification of unroll parameters.  */
+  PLUGIN_UNROLL_PARAMETER_HANDLER:

Don't put colons here. You should have exactly the same code as in gcc/gcc-plugin.h

+  /* Called before first pass.  */
+  PLUGIN_ALL_PASSES_START:
+  /* Allows pass execution to be substituted.  */
+  PLUGIN_ALL_PASSES_EXECUTION:
+  /* Called after last pass.  */
+  PLUGIN_ALL_PASSES_END:
+  /* Called before first ipa pass.  */
+  PLUGIN_ALL_IPA_PASSES_START:
+  /* Allows ipa pass execution to be substituted.  */
+  PLUGIN_ALL_IPA_PASSES_EXECUTION:
+  /* Called after last ipa pass.  */
+  PLUGIN_ALL_IPA_PASSES_END:
+  /* Allows to override pass gate decision for current_pass.  */
+  PLUGIN_OVERRIDE_GATE:
+  /* Called before executing a pass.  */

Why?

+  PLUGIN_PASS_EXECUTION:
+  /* Called before executing subpasses of a GIMPLE_PASS in
+     execute_ipa_pass_list.  */

Why?

+  PLUGIN_EARLY_GIMPLE_PASSES_START:
+  /* Called after executing subpasses of a GIMPLE_PASS in
+     execute_ipa_pass_list.  */
+  PLUGIN_EARLY_GIMPLE_PASSES_END:
+  /* Called when a pass is first instantiated.  */
+  PLUGIN_NEW_PASS:
+
+  PLUGIN_EVENT_FIRST_DYNAMIC    /* Dummy event used for indexing callback
                                     array.  */
  @};
  @end smallexample

-static bool
+bool
  execute_one_pass (struct opt_pass *pass)
  {
    bool initializing_dump;
    unsigned int todo_after = 0;

+  bool gate_status;
+
    /* IPA passes are executed on whole program, so cfun should be NULL.
       Other passes need function context set.  */
    if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS)
@@ -1491,9 +1500,21 @@ execute_one_pass (struct opt_pass *pass)

    current_pass = pass;

-  /* See if we're supposed to run this pass.  */
-  if (pass->gate && !pass->gate ())
+  /* Check whether gate check should be avoided.
+     User controls the value of the gate through the parameter "gate_status". */
+  gate_status = (pass->gate == NULL) ? true : pass->gate();
+
+  /* Override gate with plugin.  */
+  invoke_plugin_callbacks (PLUGIN_OVERRIDE_GATE, &gate_status);
+

This something I don't fully understand. Maybe it is just lacking documentation.

What is the purpose of invoking a callback here? Plugins may add their own passes.
I would understand better if you would suggest to dynamically add gate functions into existing passes (in addition of 
their own one).

If it is your mechanism for reaordering passes, you could document it better (perhaps in plugins.texi)

And your patch contain also for gcc/tree-pass.h

+/* Declare for plugins like ICI.  */
+extern void do_per_function_toporder (void (*) (void *), void *);
+

The comment is not at all explanatory. Don't mention ICI or any specific plugin, but explain the reason behind the 
function. Please write several sentences, explaining what is the first function argument, and what is the second 
(perhaps some client data?).


But I do find your patch very interesting and hope it will be accepted for 4.5.

Thanks

Regards

-- 
Basile STARYNKEVITCH         http://starynkevitch.net/Basile/
email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359
8, rue de la Faiencerie, 92340 Bourg La Reine, France
*** opinions {are only mines, sont seulement les miennes} ***

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

* Re: Fwd: RFA: plugin events for ICI
  2009-11-30 19:11 ` Fwd: RFA: plugin events for ICI Basile STARYNKEVITCH
@ 2009-11-30 19:49   ` Joern Rennecke
  2009-11-30 20:12     ` Basile STARYNKEVITCH
  0 siblings, 1 reply; 13+ messages in thread
From: Joern Rennecke @ 2009-11-30 19:49 UTC (permalink / raw)
  To: ctuning-discussions, Basile STARYNKEVITCH
  Cc: ctuning-discussions, gcc-patches, Grigori Fursin,
	'Grigori Fursin', 'Zbigniew Chamski',
	'Richard Guenther', 'Ian Lance Taylor',
	'Albert Cohen', 'Yuri Kashnikoff',
	'Yuanjie Huang', 'Liang Peng',
	dorit, 'Mircea Namolaru', 'Diego Novillo'

Quoting Basile STARYNKEVITCH <basile@starynkevitch.net>:
> --- gcc/gcc/doc/plugins.texi	2009-11-29 17:42:32.565901921 +0000
> +++ gcc-ici-2/gcc/doc/plugins.texi	2009-11-30 16:35:59.804653957 +0000
> @@ -156,18 +156,48 @@ enum plugin_event
>     PLUGIN_ATTRIBUTES,            /* Called during attribute registration */
>     PLUGIN_START_UNIT,            /* Called before processing a   
> translation unit.  */
>     PLUGIN_PRAGMAS,	        /* Called during pragma registration. */
> -  PLUGIN_EVENT_LAST             /* Dummy event used for indexing callback
> +  /* Called to allow inspection and/or modification of unroll   
> parameters.  */
> +  PLUGIN_UNROLL_PARAMETER_HANDLER:
>
> Don't put colons here. You should have exactly the same code as in   
> gcc/gcc-plugin.h

Actually, there is only an include.  The enumeration is in plugins.def,
and I had cut & pasted the list of new plugins from a switch statement.
But you are right, unless I want to change the entire list, I should put
a comma instead of a semicolon after each enumerator.

> +  PLUGIN_OVERRIDE_GATE:
> +  /* Called before executing a pass.  */
>
> Why?

The adapt plugin wants to enable passes independently of the original
gate function.  E.g. with milepost this can be driven by machine learning.

> +  PLUGIN_PASS_EXECUTION:
> +  /* Called before executing subpasses of a GIMPLE_PASS in
> +     execute_ipa_pass_list.  */
>
> Why?

This allows recording of the passes that are executed.

> @@ -1491,9 +1500,21 @@ execute_one_pass (struct opt_pass *pass)
>
>     current_pass = pass;
>
> -  /* See if we're supposed to run this pass.  */
> -  if (pass->gate && !pass->gate ())
> +  /* Check whether gate check should be avoided.
> +     User controls the value of the gate through the parameter   
> "gate_status". */
> +  gate_status = (pass->gate == NULL) ? true : pass->gate();
> +
> +  /* Override gate with plugin.  */
> +  invoke_plugin_callbacks (PLUGIN_OVERRIDE_GATE, &gate_status);
> +
>
> This something I don't fully understand. Maybe it is just lacking   
> documentation.
>
> What is the purpose of invoking a callback here? Plugins may add   
> their own passes.
> I would understand better if you would suggest to dynamically add   
> gate functions into existing passes (in addition of
> their own one).

As explained before, this allows the adapt plugin to override the gate
decision.  This event was originally called "avoid_gate" since it was
only used to make the pass run onconditionally once you got to that point
in the code; however, I thought that was a misnomer, because the gate function
is not avoided, and the callback could be used to disable passes that
are usually enabled as well as the current usage of enabling passes
that are ordinarily disabled.

> If it is your mechanism for reaordering passes, you could document   
> it better (perhaps in plugins.texi)

There are AFAICT nine different callbacks involved in reordering passes,
and some also double up for other purposes.  Only the  
PLUGIN_ALL_PASSES_EXECUTION / PLUGIN_ALL_IPA_PASSES_EXECUTION events
have really a strong affinity to pass reordering, the other ones can
lend themselves to all kinds of other purposes.

> And your patch contain also for gcc/tree-pass.h
>
> +/* Declare for plugins like ICI.  */
> +extern void do_per_function_toporder (void (*) (void *), void *);
> +
>
> The comment is not at all explanatory. Don't mention ICI or any   
> specific plugin, but explain the reason behind the
> function. Please write several sentences, explaining what is the   
> first function argument, and what is the second
> (perhaps some client data?).

The function is explained in the passes.c, were it has been defined all along.
The change is merely to make a formerly static function globally visible.
As this is not needed by any code inside GCC, a comment is needed to explain
why this function is not (any longer) static.

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

* Re: Fwd: RFA: plugin events for ICI
  2009-11-30 19:49   ` Joern Rennecke
@ 2009-11-30 20:12     ` Basile STARYNKEVITCH
  2009-12-01  7:18       ` Joern Rennecke
  0 siblings, 1 reply; 13+ messages in thread
From: Basile STARYNKEVITCH @ 2009-11-30 20:12 UTC (permalink / raw)
  To: Joern Rennecke
  Cc: ctuning-discussions, gcc-patches, Grigori Fursin,
	'Grigori Fursin', 'Zbigniew Chamski',
	'Richard Guenther', 'Ian Lance Taylor',
	'Albert Cohen', 'Yuri Kashnikoff',
	'Yuanjie Huang', 'Liang Peng',
	dorit, 'Mircea Namolaru', 'Diego Novillo'

Joern Rennecke wrote:
> Quoting Basile STARYNKEVITCH <basile@starynkevitch.net>:
>> --- gcc/gcc/doc/plugins.texi    2009-11-29 17:42:32.565901921 +0000
>> +++ gcc-ici-2/gcc/doc/plugins.texi    2009-11-30 16:35:59.804653957 +0000
>> @@ -156,18 +156,48 @@ enum plugin_event
>>     PLUGIN_ATTRIBUTES,            /* Called during attribute 
>> registration */
>>     PLUGIN_START_UNIT,            /* Called before processing a  
>> translation unit.  */
>>     PLUGIN_PRAGMAS,            /* Called during pragma registration. */
>> -  PLUGIN_EVENT_LAST             /* Dummy event used for indexing 
>> callback
>> +  /* Called to allow inspection and/or modification of unroll  
>> parameters.  */
>> +  PLUGIN_UNROLL_PARAMETER_HANDLER:
>>
>> Don't put colons here. You should have exactly the same code as in  
>> gcc/gcc-plugin.h
> 
> Actually, there is only an include.  The enumeration is in plugins.def,
> and I had cut & pasted the list of new plugins from a switch statement.
> But you are right, unless I want to change the entire list, I should put
> a comma instead of a semicolon after each enumerator.
> 
>> +  PLUGIN_OVERRIDE_GATE:
>> +  /* Called before executing a pass.  */
>>
>> Why?
> 
> The adapt plugin wants to enable passes independently of the original
> gate function.  E.g. with milepost this can be driven by machine learning.
> 
>> +  PLUGIN_PASS_EXECUTION:
>> +  /* Called before executing subpasses of a GIMPLE_PASS in
>> +     execute_ipa_pass_list.  */
>>
>> Why?
> 
> This allows recording of the passes that are executed.
> 
>> @@ -1491,9 +1500,21 @@ execute_one_pass (struct opt_pass *pass)
>>
>>     current_pass = pass;
>>
>> -  /* See if we're supposed to run this pass.  */
>> -  if (pass->gate && !pass->gate ())
>> +  /* Check whether gate check should be avoided.
>> +     User controls the value of the gate through the parameter  
>> "gate_status". */
>> +  gate_status = (pass->gate == NULL) ? true : pass->gate();
>> +
>> +  /* Override gate with plugin.  */
>> +  invoke_plugin_callbacks (PLUGIN_OVERRIDE_GATE, &gate_status);
>> +
>>
>> This something I don't fully understand. Maybe it is just lacking  
>> documentation.


I am not sure to have understood all your explanation (but I admit being tired).
Perhaps you should add an entire subsection in doc/plugins.texi explaining what you have added and how to use them.
At the moment I am not sure to have understood how to use them.

More generally, I believe plugins ought to be quite well documented. A good enough documentation is important to make 
them successful.

>> +/* Declare for plugins like ICI.  */
>> +extern void do_per_function_toporder (void (*) (void *), void *);
>> +
>>
>> The comment is not at all explanatory. Don't mention ICI or any  
>> specific plugin, but explain the reason behind the
>> function. Please write several sentences, explaining what is the  
>> first function argument, and what is the second
>> (perhaps some client data?).
> 
> The function is explained in the passes.c, were it has been defined all 
> along.

But then, please move the explanation to header files. I can assure you that newbies first read *.h files, and only when 
needed the *.c implementing them.

I hope your patch will be accepted in 4.5. If I had the power to accept it, I'll ok it (provided you added more 
documentation).

Thanks.

Regards.

-- 
Basile STARYNKEVITCH         http://starynkevitch.net/Basile/
email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359
8, rue de la Faiencerie, 92340 Bourg La Reine, France
*** opinions {are only mines, sont seulement les miennes} ***

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

* Re: Fwd: RFA: plugin events for ICI
  2009-11-30 20:12     ` Basile STARYNKEVITCH
@ 2009-12-01  7:18       ` Joern Rennecke
  2009-12-01 10:23         ` Richard Guenther
  0 siblings, 1 reply; 13+ messages in thread
From: Joern Rennecke @ 2009-12-01  7:18 UTC (permalink / raw)
  To: Basile STARYNKEVITCH
  Cc: ctuning-discussions, gcc-patches, Grigori Fursin,
	'Grigori Fursin', 'Zbigniew Chamski',
	'Richard Guenther', 'Ian Lance Taylor',
	'Albert Cohen', 'Yuri Kashnikoff',
	'Yuanjie Huang', 'Liang Peng',
	dorit, 'Mircea Namolaru', 'Diego Novillo'

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

Quoting Basile STARYNKEVITCH <basile@starynkevitch.net>:
> I am not sure to have understood all your explanation (but I admit
> being tired).
> Perhaps you should add an entire subsection in doc/plugins.texi
> explaining what you have added and how to use them.
> At the moment I am not sure to have understood how to use them.
>
> More generally, I believe plugins ought to be quite well documented. A
> good enough documentation is important to make them successful.

I have extended plugins.texi to describe the new events.

>> The function is explained in the passes.c, were it has been defined  
>>  all along.
>
> But then, please move the explanation to header files. I can assure you
> that newbies first read *.h files, and only when needed the *.c
> implementing them.

The common practice in GCC is to document functions where they are
defined; most global functions are simply declared in a header file,
without any comment there.
I see no reason to deviate from this practice now.

> I hope your patch will be accepted in 4.5. If I had the power to accept
> it, I'll ok it (provided you added more documentation).

The patch with the updated documentation is attached.
I have tested the updated documentation with 'make info' and 'make pdf' .

[-- Attachment #2: gcc-ici-patch-20091130-4 --]
[-- Type: text/plain, Size: 48415 bytes --]

2009-11-30  Grigori Fursin  <grigori.fursin@inria.fr>
	    Joern Rennecke  <amylaar@spamcop.net>

	* cgraphunit.c (plugin.h): Include.
	(ipa_passes): Invoke PLUGIN_ALL_IPA_PASSES_START /
	PLUGIN_ALL_IPA_PASSES_END at start / end of processing.
	Skip pass list execution if PLUGIN_ALL_IPA_PASSES_EXECUTION
	indicates so.
	* gcc-plugin.h (highlev-plugin-common.h, hashtab.h): Include.
	(enum plugin_event): Define by including plugin.def.
	Last enumerator is now called PLUGIN_EVENT_FIRST_DYNAMIC.
	(plugin_event_name): Change type to const char **.
	(event_last, get_named_event_id, unregister_callback): Declare.
	(register_callback): Change type of event argument to int.
	(highlev-plugin-common.h): New file.
	* loop-init.c (plugin.h): Include.
	(rtl_unroll_and_peel_loops): Invoke PLUGIN_UNROLL_PARAMETER_HANDLER.
	* loop-unroll.c (plugin.h): Include.
	(decide_unrolling_and_peeling): Invoke PLUGIN_UNROLL_PARAMETER_HANDLER.
	* Makefile.in (GCC_PLUGIN_H): Add highlev-plugin-common.h and
	$(HASHTAB_H)
	(tree-optimize.o passes.o, loop-unswitch.): Depend on $(PLUGIN_H).
	(PLUGIN_HEADERS): Add opts.h $(PARAMS_H) and plugin.def.
	(s-header-vars): New rule.
	(install-plugin): Depend on s-header-vars.  Install b-header-vars.
	* params.c (num_compiler_params): No longer static.
	* params.h (num_compiler_params): Declare.
	* passes.c (plugin.h): Include.
	(make_pass_instance): Invoke PLUGIN_NEW_PASS.
	(do_per_function_toporder, pass_init_dump_file): No longer static.
	(pass_fini_dump_file): Likewise.
	(execute_one_pass): Likewise.  Invoke PLUGIN_OVERRIDE_GATE and
	PLUGIN_PASS_EXECUTION.
	(execute_ipa_pass_list): Invoke PLUGIN_EARLY_GIMPLE_PASSES_START and
	PLUGIN_EARLY_GIMPLE_PASSES_END.
	* plugin.c (plugin_event_name_init): New array, defined by
	including plugin.def.
	(plugin_event_name): Change type to const char ** and initialize
	to plugin_event_name_init.
	(event_tab, event_last, event_horizon): New variable.
	(plugin_callbacks_init): New array.
	(plugin_callbacks: Change type to struct callback_info **.
	Initialize to plugin_callbacks_init.
	(htab_event_eq, get_named_event_id, unregister_callback): New function.
	(invoke_plugin_va_callbacks): Likewise.
	(register_callback): Change type of event argument to int.
	Handle new events.  Allow dynamic events.
	(invoke_plugin_callbacks): Likewise.  Return success status.
	(plugins_active_p): Allow dynamic callbacks.
	* plugin.def: Nwe file.
	* plugin.h (invoke_plugin_callbacks): Update prototype.
	(invoke_plugin_va_callbacks): Declare.
	* tree-optimize.c (plugin.h): Include.
	(tree_rest_of_compilation): Invoke PLUGIN_ALL_PASSES_START and
	PLUGIN_ALL_PASSES_END.  Don't execute pass list if
	PLUGIN_ALL_PASSES_EXECUTION indicates so.
	* tree-pass.h (execute_one_pass, pass_init_dump_file): Declare.
	(pass_fini_dump_file, do_per_function_toporder): Likewise.
	* doc/plugin.texi: Document new event types.

diff -drupN --exclude .svn gcc/gcc/cgraphunit.c gcc-ici-2/gcc/cgraphunit.c
--- gcc/gcc/cgraphunit.c	2009-11-29 17:42:48.662772536 +0000
+++ gcc-ici-2/gcc/cgraphunit.c	2009-11-30 15:44:55.055772873 +0000
@@ -135,6 +135,7 @@ along with GCC; see the file COPYING3.  
 #include "tree-dump.h"
 #include "output.h"
 #include "coverage.h"
+#include "plugin.h"
 
 static void cgraph_expand_all_functions (void);
 static void cgraph_mark_functions_to_output (void);
@@ -1707,38 +1708,48 @@ cgraph_preserve_function_body_p (tree de
 static void
 ipa_passes (void)
 {
+  int executed_p = 0;
+
   set_cfun (NULL);
   current_function_decl = NULL;
   gimple_register_cfg_hooks ();
   bitmap_obstack_initialize (NULL);
 
-  if (!in_lto_p)
-    execute_ipa_pass_list (all_small_ipa_passes);
-
-  /* If pass_all_early_optimizations was not scheduled, the state of
-     the cgraph will not be properly updated.  Update it now.  */
-  if (cgraph_state < CGRAPH_STATE_IPA_SSA)
-    cgraph_state = CGRAPH_STATE_IPA_SSA;
+  invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_START, NULL);
 
-  if (!in_lto_p)
+  invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_EXECUTION, &executed_p);
+  if (!executed_p)
     {
-      /* Generate coverage variables and constructors.  */
-      coverage_finish ();
+      if (!in_lto_p)
+	execute_ipa_pass_list (all_small_ipa_passes);
 
-      /* Process new functions added.  */
-      set_cfun (NULL);
-      current_function_decl = NULL;
-      cgraph_process_new_functions ();
+      /* If pass_all_early_optimizations was not scheduled, the state of
+	 the cgraph will not be properly updated.  Update it now.  */
+      if (cgraph_state < CGRAPH_STATE_IPA_SSA)
+	cgraph_state = CGRAPH_STATE_IPA_SSA;
 
-      execute_ipa_summary_passes ((struct ipa_opt_pass_d *) all_regular_ipa_passes);
-    }
-  execute_ipa_summary_passes ((struct ipa_opt_pass_d *) all_lto_gen_passes);
+      if (!in_lto_p)
+	{
+	  /* Generate coverage variables and constructors.  */
+	  coverage_finish ();
 
-  if (!in_lto_p)
-    ipa_write_summaries ();
+	  /* Process new functions added.  */
+	  set_cfun (NULL);
+	  current_function_decl = NULL;
+	  cgraph_process_new_functions ();
 
-  if (!flag_ltrans)
-    execute_ipa_pass_list (all_regular_ipa_passes);
+	  execute_ipa_summary_passes
+	    ((struct ipa_opt_pass_d *) all_regular_ipa_passes);
+	}
+      execute_ipa_summary_passes ((struct ipa_opt_pass_d *) all_lto_gen_passes);
+
+      if (!in_lto_p)
+	ipa_write_summaries ();
+
+      if (!flag_ltrans)
+	execute_ipa_pass_list (all_regular_ipa_passes);
+    }
+  invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_END, NULL);
 
   bitmap_obstack_release (NULL);
 }
diff -drupN --exclude .svn gcc/gcc/doc/plugins.texi gcc-ici-2/gcc/doc/plugins.texi
--- gcc/gcc/doc/plugins.texi	2009-11-29 17:42:32.565901921 +0000
+++ gcc-ici-2/gcc/doc/plugins.texi	2009-12-01 05:24:26.209780817 +0000
@@ -156,18 +156,48 @@ enum plugin_event
   PLUGIN_ATTRIBUTES,            /* Called during attribute registration */
   PLUGIN_START_UNIT,            /* Called before processing a translation unit.  */
   PLUGIN_PRAGMAS,	        /* Called during pragma registration. */
-  PLUGIN_EVENT_LAST             /* Dummy event used for indexing callback
+  /* Called to allow inspection and/or modification of unroll parameters.  */
+  PLUGIN_UNROLL_PARAMETER_HANDLER,
+  /* Called before first pass from all_passes.  */
+  PLUGIN_ALL_PASSES_START,
+  /* Allows pass execution to be substituted.  */
+  PLUGIN_ALL_PASSES_EXECUTION,
+  /* Called after last pass from all_passes.  */
+  PLUGIN_ALL_PASSES_END,
+  /* Called before first ipa pass.  */
+  PLUGIN_ALL_IPA_PASSES_START,
+  /* Allows ipa pass execution to be substituted.  */
+  PLUGIN_ALL_IPA_PASSES_EXECUTION,
+  /* Called after last ipa pass.  */
+  PLUGIN_ALL_IPA_PASSES_END,
+  /* Allows to override pass gate decision for current_pass.  */
+  PLUGIN_OVERRIDE_GATE,
+  /* Called before executing a pass.  */
+  PLUGIN_PASS_EXECUTION,
+  /* Called before executing subpasses of a GIMPLE_PASS in
+     execute_ipa_pass_list.  */
+  PLUGIN_EARLY_GIMPLE_PASSES_START,
+  /* Called after executing subpasses of a GIMPLE_PASS in
+     execute_ipa_pass_list.  */
+  PLUGIN_EARLY_GIMPLE_PASSES_END,
+  /* Called when a pass is first instantiated.  */
+  PLUGIN_NEW_PASS,
+
+  PLUGIN_EVENT_FIRST_DYNAMIC    /* Dummy event used for indexing callback
                                    array.  */
 @};
 @end smallexample
 
+In addition, plugins can also look up the enumerator of a named event,
+and / or generate new events dynamically, by calling the function
+@code{get_named_event_id}.
 
 To register a callback, the plugin calls @code{register_callback} with
 the arguments:
 
 @itemize
 @item @code{char *name}: Plugin name.
-@item @code{enum plugin_event event}: The event code.
+@item @code{int event}: The event code.
 @item @code{plugin_callback_func callback}: The function that handles @code{event}.
 @item @code{void *user_data}: Pointer to plugin-specific data.
 @end itemize
@@ -337,6 +367,138 @@ It is suggested to pass @code{"GCCPLUGIN
 your plugin) as the ``space'' argument of your pragma. 
 
 
+@section Recording information about pass execution
+
+The event PLUGIN_PASS_EXECUTION passes the pointer to the executed pass
+(the same as current_pass) as @code{gcc_data} to the callback.  You can also
+inspect cfun to find out about which function this pass is executed for.
+Note that this event will only be invoked if the gate check (if
+applicable, modified by PLUGIN_OVERRIDE_GATE) succeeds.
+You can use other hooks, like @code{PLUGIN_ALL_PASSES_START},
+@code{PLUGIN_ALL_PASSES_END}, @code{PLUGIN_ALL_IPA_PASSES_START},
+@code{PLUGIN_ALL_IPA_PASSES_END}, @code{PLUGIN_EARLY_GIMPLE_PASSES_START},
+and/or @code{PLUGIN_EARLY_GIMPLE_PASSES_END} to manipulate global state
+in your plugin(s) in order to get context for the pass execution.
+
+
+@section Controlling which passes are being run
+
+After the orginary gate function for a pass is called, the result of
+the gate test - the gate status - stored as an integer.
+Then the event @code{PLUGIN_OVERRIDE_GATE} is invoked, with a pointer
+to the gate status in the @code{gcc_data} parameter to the callback function.
+A nonzero value of the gate status means that the pass is to be executed.
+You can both read and write the gate status via the passed pointer.
+
+
+@section Controlling order and frequency of passes
+
+Before the execution of the lists of inter-procedural analysis passes,
+the event @code{PLUGIN_ALL_IPA_PASSES_EXECUTION} is invoked.  Likewise,
+before the execution of the list of ordinary passes, the event
+@code{PLUGIN_ALL_PASSES_EXECUTION} is invoked.
+The callback can than execute a sequence of passes as desired.  For both
+these events, @code{gcc_data} is a pointer to an integer.  This integer is
+initialized to zero; to stop the ordinary execution of passes after
+the plugin event, write a non-zero value to the pointed-to integer
+during the plugin callback.
+
+
+@section Keeping track of available passes
+
+When your plugin is loaded, yt the moment you can inspect the various
+pass lists to determine what passes are available.  However, other
+plugins might add new passes.  Also, future changes to GCC might cause
+generic passes to be added after plugin loading.
+When a pass is first added to one of the pass lists, the event
+@code{PLUGIN_NEW_PASS} is invoked, with the callback parameter
+@code{gcc_data} pointing to the new pass.
+
+
+@section Tracking and manipulating the execution of individual passes
+
+At the moment, only @code{PLUGIN_UNROLL_PARAMETER_HANDLER} is provided
+for this purpose, to monitor/ control the unroller.  A similar hook
+for Graphite is planned, but was not ready for inclusion in GCC 4.5 .
+
+The callback parameter @code{gcc_data} is a pointer to a @code{va_list},
+which can be manipulated as usual with macros from stdarg to retrieve
+multiple parameters.
+Each parameter is described by a triple of @code{va_arg} arguments:
+a name, a pointer to a data item, and a in into to describe the parameter
+type as detailed below.
+The list of parameters is delimted by a NULL pointer.
+The name of read-only parameters start with a "_", other names indicate
+@code{event_parameter_type}
+The values to describe the parameter type are defined when you
+include gcc-plugin.h:
+
+@smallexample
+typedef enum
+@{
+  EP_SILENT, /* Used to pass infomation between ICI and plugin,
+                parameter of this type will not be recorded.
+                The data type is int.  */
+  EP_VOID,
+  EP_CHAR,
+  EP_UNSIGNED_CHAR,
+  EP_INT,
+  EP_UNSIGNED,
+  EP_LONG,
+  EP_UNSIGNED_LONG
+@} event_parameter_type;
+@end smallexample
+
+For example, this is the code in the ICI plugin to parse the parameter
+list and enter each parameter into a hash table, before running a
+high-level callback, then parsing the parameter list again to un-register
+the parameters in the hash table.
+
+@smallexample
+extern void register_event_parameter (const char *name, void *param,
+                                      event_parameter_type type);
+...
+static void
+hash_param_callback (void *gcc_data, void *user_data)
+@{
+  struct hl_plugin_event *ev = (struct hl_plugin_event *) user_data;
+  va_list va;
+  const char *name;
+  int type;
+  void *value;
+
+  if (gcc_data != NULL)
+    @{
+      /* Possible extension:
+         Might interpret gcc_data differently for specific values of
+         ev->event, e.g. we could get a struct loop and put all the
+         struct members in named parameters.  */
+      va_copy (va, * (va_list *) gcc_data);
+
+      while ((name = va_arg (va, const char *)) != NULL)
+        @{
+          type = va_arg (va, int);
+          value = va_arg (va, void *);
+          register_event_parameter (name, value,
+                                    (event_parameter_type) type);
+        @}
+      va_end (va);
+    @}
+  ev->run ();
+  if (gcc_data != NULL)
+    @{
+      va_copy (va, * (va_list *) gcc_data);
+      while ((name = va_arg (va, const char *)) != NULL)
+        @{
+          unregister_event_parameter (name);
+          va_arg (va, void *);
+        @}
+      va_end (va);
+    @}
+@}
+@end smallexample
+
+
 @section Building GCC plugins
 
 If plugins are enabled, GCC installs the headers needed to build a
diff -drupN --exclude .svn gcc/gcc/gcc-plugin.h gcc-ici-2/gcc/gcc-plugin.h
--- gcc/gcc/gcc-plugin.h	2009-11-08 21:11:04.273376423 +0000
+++ gcc-ici-2/gcc/gcc-plugin.h	2009-11-30 15:44:55.055772873 +0000
@@ -26,29 +26,19 @@ along with GCC; see the file COPYING3.  
 
 #include "config.h"
 #include "system.h"
+#include "highlev-plugin-common.h"
+#include "hashtab.h"
 
-/* Event names.  Keep in sync with plugin_event_name[].  */
+/* Event names.  */
 enum plugin_event
 {
-  PLUGIN_PASS_MANAGER_SETUP,    /* To hook into pass manager.  */
-  PLUGIN_FINISH_TYPE,           /* After finishing parsing a type.  */
-  PLUGIN_FINISH_UNIT,           /* Useful for summary processing.  */
-  PLUGIN_CXX_CP_PRE_GENERICIZE, /* Allows to see low level AST in C++ FE.  */
-  PLUGIN_FINISH,                /* Called before GCC exits.  */
-  PLUGIN_INFO,                  /* Information about the plugin. */
-  PLUGIN_GGC_START,		/* Called at start of GCC Garbage Collection. */
-  PLUGIN_GGC_MARKING,		/* Extend the GGC marking. */
-  PLUGIN_GGC_END,		/* Called at end of GGC. */
-  PLUGIN_REGISTER_GGC_ROOTS,	/* Register an extra GGC root table. */
-  PLUGIN_REGISTER_GGC_CACHES,	/* Register an extra GGC cache table. */
-  PLUGIN_ATTRIBUTES,            /* Called during attribute registration.  */
-  PLUGIN_START_UNIT,            /* Called before processing a translation unit.  */
-  PLUGIN_PRAGMAS,	        /* Called during pragma registration.  */
-  PLUGIN_EVENT_LAST             /* Dummy event used for indexing callback
-                                   array.  */
+# define DEFEVENT(NAME) NAME,
+# include "plugin.def"
+# undef DEFEVENT
+  PLUGIN_EVENT_FIRST_DYNAMIC
 };
 
-extern const char *plugin_event_name[];
+extern const char **plugin_event_name;
 
 struct plugin_argument
 {
@@ -127,14 +117,22 @@ typedef void (*plugin_callback_func) (vo
    USER_DATA   - plugin-provided data.
 */
 
+/* Number of event ids / names registered so far.  */
+
+extern int event_last;
+
+int get_named_event_id (const char *name, enum insert_option insert);
+
 /* This is also called without a callback routine for the
    PLUGIN_PASS_MANAGER_SETUP, PLUGIN_INFO, PLUGIN_REGISTER_GGC_ROOTS and
    PLUGIN_REGISTER_GGC_CACHES pseudo-events, with a specific user_data.
   */
 
 extern void register_callback (const char *plugin_name,
-                               enum plugin_event event,
+			       int event,
                                plugin_callback_func callback,
                                void *user_data);
 
+extern int unregister_callback (const char *plugin_name, int event);
+
 #endif /* GCC_PLUGIN_H */
diff -drupN --exclude .svn gcc/gcc/highlev-plugin-common.h gcc-ici-2/gcc/highlev-plugin-common.h
--- gcc/gcc/highlev-plugin-common.h	1970-01-01 01:00:00.000000000 +0100
+++ gcc-ici-2/gcc/highlev-plugin-common.h	2009-12-01 05:29:52.504904141 +0000
@@ -0,0 +1,48 @@
+/* Interface for high-level plugins in GCC - Parts common between GCC,
+   ICI and high-level plugins.
+
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+   Contributed by INRIA.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef HIGHLEV_PLUGIN_COMMON_H
+#define HIGHLEV_PLUGIN_COMMON_H
+
+/* Return codes for invoke_plugin_{,va_}callbacks / call_plugin_event .  */
+#define PLUGEVT_SUCCESS         0
+#define PLUGEVT_NO_EVENTS       1
+#define PLUGEVT_NO_SUCH_EVENT   2
+#define PLUGEVT_NO_CALLBACK     3
+
+/* Datatype of event parameter structure.  */
+typedef enum
+{
+  EP_SILENT, /* Used to pass infomation between ICI and plugin,
+		parameter of this type will not be recorded.
+		The data type is int.  */
+  EP_VOID,
+  EP_CHAR,
+  EP_UNSIGNED_CHAR,
+  EP_INT,
+  EP_UNSIGNED,
+  EP_LONG,
+  EP_UNSIGNED_LONG
+} event_parameter_type;
+
+#endif /* HIGHLEV_PLUGIN_COMMON_H */
diff -drupN --exclude .svn gcc/gcc/loop-init.c gcc-ici-2/gcc/loop-init.c
--- gcc/gcc/loop-init.c	2009-11-29 17:42:48.681772582 +0000
+++ gcc-ici-2/gcc/loop-init.c	2009-11-30 15:44:55.056773001 +0000
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.  
 #include "flags.h"
 #include "df.h"
 #include "ggc.h"
+#include "plugin.h"
 
 \f
 /* Initialize loop structures.  This is used by the tree and RTL loop
@@ -322,17 +323,28 @@ gate_rtl_unroll_and_peel_loops (void)
 static unsigned int
 rtl_unroll_and_peel_loops (void)
 {
+  int tmp_peel_loops = flag_peel_loops;
+  int tmp_unroll_loops = flag_unroll_loops;
+  int tmp_unroll_all_loops = flag_unroll_all_loops;
+
   if (number_of_loops () > 1)
     {
       int flags = 0;
       if (dump_file)
 	df_dump (dump_file);
 
-      if (flag_peel_loops)
+      invoke_plugin_va_callbacks
+	(PLUGIN_UNROLL_PARAMETER_HANDLER,
+	 "loop.flag_peel_loops", EP_INT, &tmp_peel_loops,
+	 "loop.flag_unroll_loops", EP_INT &tmp_unroll_loops,
+	 "loop.flag_unroll_all_loops", EP_INT, &tmp_unroll_all_loops,
+	 NULL);
+
+      if (tmp_peel_loops)
 	flags |= UAP_PEEL;
-      if (flag_unroll_loops)
+      if (tmp_unroll_loops)
 	flags |= UAP_UNROLL;
-      if (flag_unroll_all_loops)
+      if (tmp_unroll_all_loops)
 	flags |= UAP_UNROLL_ALL;
 
       unroll_and_peel_loops (flags);
diff -drupN --exclude .svn gcc/gcc/loop-unroll.c gcc-ici-2/gcc/loop-unroll.c
--- gcc/gcc/loop-unroll.c	2009-11-29 17:42:48.741526000 +0000
+++ gcc-ici-2/gcc/loop-unroll.c	2009-11-30 15:44:55.057773058 +0000
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.  
 #include "expr.h"
 #include "hashtab.h"
 #include "recog.h"
+#include "plugin.h"
 
 /* This pass performs loop unrolling and peeling.  We only perform these
    optimizations on innermost loops (with single exception) because
@@ -279,14 +280,33 @@ decide_unrolling_and_peeling (int flags)
       /* Do not peel cold areas.  */
       if (optimize_loop_for_size_p (loop))
 	{
-	  if (dump_file)
-	    fprintf (dump_file, ";; Not considering loop, cold area\n");
-	  continue;
+	  static bool ici_optimize_loop_for_size_p;
+	  ici_optimize_loop_for_size_p = 1;
+	  invoke_plugin_va_callbacks
+	    (PLUGIN_UNROLL_PARAMETER_HANDLER,
+	     "_loop.id", EP_INT, &(loop->num),
+	     "loop.optimize_loop_for_size_p", EP_UNSIGNED_CHAR,
+	     &ici_optimize_loop_for_size_p, NULL);
+
+	  if (ici_optimize_loop_for_size_p)
+	    {
+	      if (dump_file)
+		fprintf (dump_file, ";; Not considering loop, cold area\n");
+	      continue;
+	    }
 	}
 
       /* Can the loop be manipulated?  */
       if (!can_duplicate_loop_p (loop))
 	{
+	  static bool ici_can_duplicate_loop_p;
+	  ici_can_duplicate_loop_p = 0;
+	  invoke_plugin_va_callbacks
+	    (PLUGIN_UNROLL_PARAMETER_HANDLER,
+	     "_loop.id", EP_INT, &(loop->num),
+	     "_loop.can_duplicate_loop_p", EP_UNSIGNED_CHAR,
+	     &ici_can_duplicate_loop_p, NULL);
+
 	  if (dump_file)
 	    fprintf (dump_file,
 		     ";; Not considering loop, cannot duplicate\n");
@@ -296,6 +316,14 @@ decide_unrolling_and_peeling (int flags)
       /* Skip non-innermost loops.  */
       if (loop->inner)
 	{
+	  static bool ici_is_inner_most;
+	  ici_is_inner_most = 0;
+	  invoke_plugin_va_callbacks
+	    (PLUGIN_UNROLL_PARAMETER_HANDLER,
+	     "_loop.id", EP_INT, &(loop->num),
+	     "_loop.is_inner_most", EP_UNSIGNED_CHAR, &ici_is_inner_most,
+	     NULL);
+
 	  if (dump_file)
 	    fprintf (dump_file, ";; Not considering loop, is not innermost\n");
 	  continue;
@@ -314,6 +342,20 @@ decide_unrolling_and_peeling (int flags)
 	decide_unroll_stupid (loop, flags);
       if (loop->lpt_decision.decision == LPT_NONE)
 	decide_peel_simple (loop, flags);
+
+      invoke_plugin_va_callbacks
+	(PLUGIN_UNROLL_PARAMETER_HANDLER,
+	 "_loop.id", EP_INT, &(loop->num),
+	 /* ICI: Number of loop insns.  */
+	 "_loop.ninsns", EP_UNSIGNED, &(loop->ninsns),
+	 /* ICI: Average number of executed insns per iteration.  */
+	 "_loop.av_ninsns", EP_UNSIGNED, &(loop->av_ninsns),
+	 /* ICI: Number of blocks contained within the loop.  */
+	 "_loop.num_nodes", EP_UNSIGNED, &(loop->num_nodes),
+	 /* ICI: Loop unrolling/peeling decision.  */
+	 "loop.lpt_decision.times", EP_UNSIGNED, &(loop->lpt_decision.times),
+	 "loop.lpt_decision.decision", EP_INT, /* Enum treated as int.  */
+	 &(loop->lpt_decision.decision), NULL);
     }
 }
 
diff -drupN --exclude .svn gcc/gcc/Makefile.in gcc-ici-2/gcc/Makefile.in
--- gcc/gcc/Makefile.in	2009-11-29 17:42:49.155526086 +0000
+++ gcc-ici-2/gcc/Makefile.in	2009-11-30 15:44:55.060773022 +0000
@@ -943,7 +943,8 @@ TREE_VECTORIZER_H = tree-vectorizer.h $(
 IPA_PROP_H = ipa-prop.h $(TREE_H) vec.h $(CGRAPH_H)
 GSTAB_H = gstab.h stab.def
 BITMAP_H = bitmap.h $(HASHTAB_H) statistics.h
-GCC_PLUGIN_H = gcc-plugin.h $(CONFIG_H) $(SYSTEM_H)
+GCC_PLUGIN_H = gcc-plugin.h highlev-plugin-common.h $(CONFIG_H) $(SYSTEM_H) \
+		$(HASHTAB_H)
 PLUGIN_H = plugin.h $(GCC_PLUGIN_H)
 PLUGIN_VERSION_H = plugin-version.h configargs.h
 
@@ -2503,8 +2504,9 @@ tree-ssa-reassoc.o : tree-ssa-reassoc.c 
    langhooks.h alloc-pool.h pointer-set.h $(CFGLOOP_H)
 tree-optimize.o : tree-optimize.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
    $(RTL_H) $(TREE_H) $(TM_P_H) hard-reg-set.h $(EXPR_H) $(GGC_H) output.h \
-   $(DIAGNOSTIC_H) $(BASIC_BLOCK_H) $(FLAGS_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
-   $(TREE_DUMP_H) $(TOPLEV_H) $(FUNCTION_H) langhooks.h $(FLAGS_H) $(CGRAPH_H) \
+   $(DIAGNOSTIC_H) $(BASIC_BLOCK_H) $(FLAGS_H) $(TIMEVAR_H) $(TM_H) \
+   coretypes.h $(TREE_DUMP_H) $(TOPLEV_H) $(FUNCTION_H) langhooks.h \
+   $(FLAGS_H) $(CGRAPH_H) $(PLUGIN_H) \
    $(TREE_INLINE_H) tree-mudflap.h $(GGC_H) graph.h $(CGRAPH_H) \
    $(TREE_PASS_H) $(CFGLOOP_H) $(EXCEPT_H)
 
@@ -2725,7 +2727,8 @@ passes.o : passes.c $(CONFIG_H) $(SYSTEM
    langhooks.h insn-flags.h $(CFGLAYOUT_H) $(REAL_H) $(CFGLOOP_H) \
    hosthooks.h $(CGRAPH_H) $(COVERAGE_H) $(TREE_PASS_H) $(TREE_DUMP_H) \
    $(GGC_H) $(INTEGRATE_H) $(CPPLIB_H) opts.h $(TREE_FLOW_H) $(TREE_INLINE_H) \
-   gt-passes.h $(DF_H) $(PREDICT_H) $(LTO_HEADER_H) $(LTO_SECTION_OUT_H)
+   gt-passes.h $(DF_H) $(PREDICT_H) $(LTO_HEADER_H) $(LTO_SECTION_OUT_H) \
+   $(PLUGIN_H)
 
 plugin.o : plugin.c $(PLUGIN_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h \
    $(TOPLEV_H) $(TREE_H) $(TREE_PASS_H) intl.h $(PLUGIN_VERSION_H) $(GGC_H)
@@ -3101,7 +3104,7 @@ loop-unswitch.o : loop-unswitch.c $(CONF
 loop-unroll.o: loop-unroll.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TM_H) \
    $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(CFGLAYOUT_H) $(PARAMS_H) \
    output.h $(EXPR_H) coretypes.h $(TM_H) $(HASHTAB_H) $(RECOG_H) \
-   $(OBSTACK_H)
+   $(OBSTACK_H) $(PLUGIN_H)
 dominance.o : dominance.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    hard-reg-set.h $(BASIC_BLOCK_H) et-forest.h $(OBSTACK_H) $(TOPLEV_H) \
    $(TIMEVAR_H) graphds.h vecprim.h pointer-set.h
@@ -4264,7 +4267,7 @@ installdirs:
 
 PLUGIN_HEADERS = $(TREE_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
   $(TOPLEV_H) $(BASIC_BLOCK_H) $(GIMPLE_H) $(TREE_PASS_H) $(GCC_PLUGIN_H) \
-  $(GGC_H) $(TREE_DUMP_H) $(PRETTY_PRINT_H) \
+  $(GGC_H) $(TREE_DUMP_H) $(PRETTY_PRINT_H) opts.h $(PARAMS_H) plugin.def \
   $(tm_file_list) $(tm_include_list) $(tm_p_file_list) $(tm_p_include_list) \
   $(host_xm_file_list) $(host_xm_include_list) $(xm_include_list) \
   intl.h $(PLUGIN_VERSION_H) $(DIAGNOSTIC_H) $(C_COMMON_H) $(C_PRETTY_PRINT_H) \
@@ -4273,8 +4276,15 @@ PLUGIN_HEADERS = $(TREE_H) $(CONFIG_H) $
   $(C_PRAGMA_H)  $(CPPLIB_H)  $(FUNCTION_H) \
   cppdefault.h flags.h $(MD5_H) params.def params.h prefix.h tree-inline.h
 
+# generate the 'build fragment' b-header-vars
+s-header-vars: Makefile
+	rm -f tmp-header-vars
+	$(foreach header_var,$(shell sed < Makefile -e 's/^\([A-Z0-9_]*_H\)[      ]*=.*/\1/p' -e d),echo $(header_var)=$(shell echo $($(header_var):$(srcdir)/%=.../%) | sed -e 's~\.\.\./config/~config/~' -e 's~\.\.\..*/~~') >> tmp-header-vars;) \
+	$(SHELL) $(srcdir)/../move-if-change tmp-header-vars b-header-vars
+	$(STAMP) s-header-vars
+
 # Install the headers needed to build a plugin.
-install-plugin: installdirs lang.install-plugin
+install-plugin: installdirs lang.install-plugin s-header-vars
 # We keep the directory structure for files in config and .def files. All
 # other files are flattened to a single directory.
 	$(mkinstalldirs) $(DESTDIR)$(plugin_includedir)
@@ -4298,6 +4308,7 @@ install-plugin: installdirs lang.install
 	  $(mkinstalldirs) $(DESTDIR)$$dir; \
 	  $(INSTALL_DATA) $$path $(DESTDIR)$$dest; \
 	done
+	$(INSTALL_DATA) b-header-vars $(DESTDIR)$(plugin_includedir)/b-header-vars
 
 # Install the compiler executables built during cross compilation.
 install-common: native lang.install-common installdirs
diff -drupN --exclude .svn gcc/gcc/params.c gcc-ici-2/gcc/params.c
--- gcc/gcc/params.c	2009-11-04 14:49:32.468125810 +0000
+++ gcc-ici-2/gcc/params.c	2009-11-30 15:44:55.081525175 +0000
@@ -32,8 +32,8 @@ along with GCC; see the file COPYING3.  
 param_info *compiler_params;
 
 /* The number of entries in the table.  */
-
-static size_t num_compiler_params;
+/* Changed for FICI0: access to list of compiler parameters */
+size_t num_compiler_params;
 
 /* Add the N PARAMS to the current list of compiler parameters.  */
 
diff -drupN --exclude .svn gcc/gcc/params.h gcc-ici-2/gcc/params.h
--- gcc/gcc/params.h	2009-11-29 17:42:48.652772589 +0000
+++ gcc-ici-2/gcc/params.h	2009-11-30 15:44:55.081525175 +0000
@@ -65,6 +65,10 @@ typedef struct param_info
 
 extern param_info *compiler_params;
 
+/* The number of entries in the table.  */
+/* Changed for FICI0: access to list of compiler parameters */
+extern size_t num_compiler_params;
+
 /* Add the N PARAMS to the current list of compiler parameters.  */
 
 extern void add_params (const param_info params[], size_t n);
diff -drupN --exclude .svn gcc/gcc/passes.c gcc-ici-2/gcc/passes.c
--- gcc/gcc/passes.c	2009-11-29 17:42:49.163525359 +0000
+++ gcc-ici-2/gcc/passes.c	2009-11-30 15:44:55.082773099 +0000
@@ -85,6 +85,7 @@ along with GCC; see the file COPYING3.  
 #include "df.h"
 #include "predict.h"
 #include "lto-streamer.h"
+#include "plugin.h"
 
 #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
 #include "dwarf2out.h"
@@ -104,7 +105,8 @@ along with GCC; see the file COPYING3.  
 #endif
 
 /* This is used for debugging.  It allows the current pass to printed
-   from anywhere in compilation.  */
+   from anywhere in compilation.
+   The variable current_pass is also used for statistics and plugins.  */
 struct opt_pass *current_pass;
 
 /* Call from anywhere to find out what pass this is.  Useful for
@@ -479,6 +481,8 @@ make_pass_instance (struct opt_pass *pas
     {
       pass->todo_flags_start |= TODO_mark_first_instance;
       pass->static_pass_number = -1;
+
+      invoke_plugin_callbacks (PLUGIN_NEW_PASS, pass);
     }
   return pass;
 }
@@ -1092,7 +1096,8 @@ static GTY ((length ("nnodes"))) struct 
    function CALLBACK for every function in the call graph.  Otherwise,
    call CALLBACK on the current function.  */
 
-static void
+/* This function is global so that plugins like ICI can use it.  */
+void
 do_per_function_toporder (void (*callback) (void *data), void *data)
 {
   int i;
@@ -1317,8 +1322,9 @@ verify_curr_properties (void *data)
 #endif
 
 /* Initialize pass dump file.  */
+/* This is non-static so that the ICI pass manager can use it.  */
 
-static bool
+bool
 pass_init_dump_file (struct opt_pass *pass)
 {
   /* If a dump file name is present, open it if enabled.  */
@@ -1347,8 +1353,9 @@ pass_init_dump_file (struct opt_pass *pa
 }
 
 /* Flush PASS dump file.  */
+/* This is non-static so that the ICI pass manager can use it.  */
 
-static void
+void
 pass_fini_dump_file (struct opt_pass *pass)
 {
   /* Flush and close dump file.  */
@@ -1476,12 +1483,14 @@ execute_all_ipa_transforms (void)
 
 /* Execute PASS. */
 
-static bool
+bool
 execute_one_pass (struct opt_pass *pass)
 {
   bool initializing_dump;
   unsigned int todo_after = 0;
 
+  bool gate_status;
+
   /* IPA passes are executed on whole program, so cfun should be NULL.
      Other passes need function context set.  */
   if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS)
@@ -1491,9 +1500,21 @@ execute_one_pass (struct opt_pass *pass)
 
   current_pass = pass;
 
-  /* See if we're supposed to run this pass.  */
-  if (pass->gate && !pass->gate ())
+  /* Check whether gate check should be avoided.
+     User controls the value of the gate through the parameter "gate_status". */
+  gate_status = (pass->gate == NULL) ? true : pass->gate();
+
+  /* Override gate with plugin.  */
+  invoke_plugin_callbacks (PLUGIN_OVERRIDE_GATE, &gate_status);
+
+  if (!gate_status) {
+    current_pass = NULL;
     return false;
+  }
+
+  /* Pass execution event trigger: useful to identify passes being
+     executed.  */
+  invoke_plugin_callbacks (PLUGIN_PASS_EXECUTION, pass);
 
   if (!quiet_flag && !cfun)
     fprintf (stderr, " <%s>", pass->name ? pass->name : "");
@@ -1756,8 +1777,12 @@ execute_ipa_pass_list (struct opt_pass *
       if (execute_one_pass (pass) && pass->sub)
 	{
 	  if (pass->sub->type == GIMPLE_PASS)
-	    do_per_function_toporder ((void (*)(void *))execute_pass_list,
-				      pass->sub);
+	    {
+	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL);
+	      do_per_function_toporder ((void (*)(void *))execute_pass_list,
+					pass->sub);
+	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL);
+	    }
 	  else if (pass->sub->type == SIMPLE_IPA_PASS
 		   || pass->sub->type == IPA_PASS)
 	    execute_ipa_pass_list (pass->sub);
diff -drupN --exclude .svn gcc/gcc/plugin.c gcc-ici-2/gcc/plugin.c
--- gcc/gcc/plugin.c	2009-11-29 17:42:49.053525413 +0000
+++ gcc-ici-2/gcc/plugin.c	2009-11-30 15:44:55.089525707 +0000
@@ -44,28 +44,30 @@ along with GCC; see the file COPYING3.  
 #include "plugin-version.h"
 #endif
 
+#define GCC_PLUGIN_STRINGIFY0(X) #X
+#define GCC_PLUGIN_STRINGIFY1(X) GCC_PLUGIN_STRINGIFY0 (X)
+
 /* Event names as strings.  Keep in sync with enum plugin_event.  */
-const char *plugin_event_name[] =
+static const char *plugin_event_name_init[] =
 {
-  "PLUGIN_PASS_MANAGER_SETUP",
-  "PLUGIN_FINISH_TYPE",
-  "PLUGIN_FINISH_UNIT",
-  "PLUGIN_CXX_CP_PRE_GENERICIZE",
-  "PLUGIN_FINISH",
-  "PLUGIN_INFO",
-  "PLUGIN_GGC_START",
-  "PLUGIN_GGC_MARKING",
-  "PLUGIN_GGC_END",
-  "PLUGIN_REGISTER_GGC_ROOTS",
-  "PLUGIN_REGISTER_GGC_CACHES",
-  "PLUGIN_ATTRIBUTES",
-  "PLUGIN_START_UNIT",
-  "PLUGIN_PRAGMAS",
-  "PLUGIN_EVENT_LAST"
+# define DEFEVENT(NAME) GCC_PLUGIN_STRINGIFY1 (NAME),
+# include "plugin.def"
+# undef DEFEVENT
 };
 
 /* A printf format large enough for the largest event above.  */
-#define FMT_FOR_PLUGIN_EVENT "%-26s"
+#define FMT_FOR_PLUGIN_EVENT "%-32s"
+
+const char **plugin_event_name = plugin_event_name_init;
+
+/* A hash table to map event names to the position of the names in the
+   plugin_event_name table.  */
+static htab_t event_tab;
+
+/* Keep track of the limit of allocated events and space ready for
+   allocating events.  */
+int event_last = PLUGIN_EVENT_FIRST_DYNAMIC;
+static int event_horizon = PLUGIN_EVENT_FIRST_DYNAMIC;
 
 /* Hash table for the plugin_name_args objects created during command-line
    parsing.  */
@@ -81,7 +83,8 @@ struct callback_info
 };
 
 /* An array of lists of 'callback_info' objects indexed by the event id.  */
-static struct callback_info *plugin_callbacks[PLUGIN_EVENT_LAST] = { NULL };
+static struct callback_info *plugin_callbacks_init[PLUGIN_EVENT_FIRST_DYNAMIC];
+static struct callback_info **plugin_callbacks = plugin_callbacks_init;
 
 
 #ifdef ENABLE_PLUGIN
@@ -290,6 +293,70 @@ register_plugin_info (const char* name, 
   plugin->help = info->help;
 }
 
+/* Helper function for the event hash table that compares the name of an
+   existing entry (E1) with the given string (S2).  */
+
+static int
+htab_event_eq (const void *e1, const void *s2)
+{
+  const char *s1= *(const char * const *) e1;
+  return !strcmp (s1, (const char *) s2);
+}
+
+/* Look up the event id for NAME.  If the name is not found, return -1
+   if INSERT is NO_INSERT.  */
+int
+get_named_event_id (const char *name, enum insert_option insert)
+{
+  void **slot;
+
+  if (!event_tab)
+    {
+      int i;
+
+      event_tab = htab_create (150, htab_hash_string, htab_event_eq, NULL);
+      for (i = 0; i < PLUGIN_EVENT_FIRST_DYNAMIC; i++)
+	{
+	  slot = htab_find_slot (event_tab, plugin_event_name[i], INSERT);
+	  gcc_assert (*slot == HTAB_EMPTY_ENTRY);
+	  *slot = &plugin_event_name[i];
+	}
+    }
+  slot = htab_find_slot (event_tab, name, insert);
+  if (slot == NULL)
+    return -1;
+  if (*slot != HTAB_EMPTY_ENTRY)
+    return (const char **) *slot - &plugin_event_name[0];
+
+  if (event_last >= event_horizon)
+    {
+      event_horizon = event_last * 2;
+      if (plugin_event_name == plugin_event_name_init)
+	{
+	  plugin_event_name = XNEWVEC (const char *, event_horizon);
+	  memcpy (plugin_event_name, plugin_event_name_init,
+		  sizeof plugin_event_name_init);
+	  plugin_callbacks = XNEWVEC (struct callback_info *, event_horizon);
+	  memcpy (plugin_callbacks, plugin_callbacks_init,
+		  sizeof plugin_callbacks_init);
+	}
+      else
+	{
+	  plugin_event_name
+	    = XRESIZEVEC (const char *, plugin_event_name, event_horizon);
+	  plugin_callbacks = XRESIZEVEC (struct callback_info *,
+					 plugin_callbacks, event_horizon);
+	}
+      /* All the pointers in the hash table will need to be updated.  */
+      htab_delete (event_tab);
+      event_tab = NULL;
+    }
+  else
+    *slot = &plugin_event_name[event_last];
+  plugin_event_name[event_last] = name;
+  return event_last++;
+}
+
 /* Called from the plugin's initialization code. Register a single callback.
    This function can be called multiple times.
 
@@ -300,7 +367,7 @@ register_plugin_info (const char* name, 
 
 void
 register_callback (const char *plugin_name,
-                   enum plugin_event event,
+		   int event,
                    plugin_callback_func callback,
                    void *user_data)
 {
@@ -322,6 +389,15 @@ register_callback (const char *plugin_na
 	gcc_assert (!callback);
         ggc_register_cache_tab ((const struct ggc_cache_tab*) user_data);
 	break;
+      case PLUGIN_EVENT_FIRST_DYNAMIC:
+      default:
+	if (event < PLUGIN_EVENT_FIRST_DYNAMIC || event >= event_last)
+	  {
+	    error ("Unknown callback event registered by plugin %s",
+		   plugin_name);
+	    return;
+	  }
+      /* Fall through.  */
       case PLUGIN_FINISH_TYPE:
       case PLUGIN_START_UNIT:
       case PLUGIN_FINISH_UNIT:
@@ -332,6 +408,18 @@ register_callback (const char *plugin_na
       case PLUGIN_ATTRIBUTES:
       case PLUGIN_PRAGMAS:
       case PLUGIN_FINISH:
+      case PLUGIN_UNROLL_PARAMETER_HANDLER:
+      case PLUGIN_ALL_PASSES_START:
+      case PLUGIN_ALL_PASSES_EXECUTION:
+      case PLUGIN_ALL_PASSES_END:
+      case PLUGIN_ALL_IPA_PASSES_START:
+      case PLUGIN_ALL_IPA_PASSES_EXECUTION:
+      case PLUGIN_ALL_IPA_PASSES_END:
+      case PLUGIN_OVERRIDE_GATE:
+      case PLUGIN_PASS_EXECUTION:
+      case PLUGIN_EARLY_GIMPLE_PASSES_START:
+      case PLUGIN_EARLY_GIMPLE_PASSES_END:
+      case PLUGIN_NEW_PASS:
         {
           struct callback_info *new_callback;
           if (!callback)
@@ -348,13 +436,25 @@ register_callback (const char *plugin_na
           plugin_callbacks[event] = new_callback;
         }
         break;
-      case PLUGIN_EVENT_LAST:
-      default:
-        error ("Unknown callback event registered by plugin %s",
-               plugin_name);
     }
 }
 
+int
+unregister_callback (const char *plugin_name, int event)
+{
+  struct callback_info *callback, **cbp;
+
+  if (event >= event_last)
+    return PLUGEVT_NO_SUCH_EVENT;
+
+  for (cbp = &plugin_callbacks[event]; (callback = *cbp); cbp = &callback->next)
+    if (strcmp (callback->plugin_name, plugin_name) == 0)
+      {
+	*cbp = callback->next;
+	return PLUGEVT_SUCCESS;
+      }
+  return PLUGEVT_NO_CALLBACK;
+}
 
 /* Called from inside GCC.  Invoke all plug-in callbacks registered with
    the specified event.
@@ -362,13 +462,20 @@ register_callback (const char *plugin_na
    EVENT    - the event identifier
    GCC_DATA - event-specific data provided by the compiler  */
 
-void
-invoke_plugin_callbacks (enum plugin_event event, void *gcc_data)
+int
+invoke_plugin_callbacks (int event, void *gcc_data)
 {
+  int retval = PLUGEVT_SUCCESS;
+
   timevar_push (TV_PLUGIN_RUN);
 
   switch (event)
     {
+      case PLUGIN_EVENT_FIRST_DYNAMIC:
+      default:
+	gcc_assert (event >= PLUGIN_EVENT_FIRST_DYNAMIC);
+	gcc_assert (event < event_last);
+      /* Fall through.  */
       case PLUGIN_FINISH_TYPE:
       case PLUGIN_START_UNIT:
       case PLUGIN_FINISH_UNIT:
@@ -379,24 +486,50 @@ invoke_plugin_callbacks (enum plugin_eve
       case PLUGIN_GGC_START:
       case PLUGIN_GGC_MARKING:
       case PLUGIN_GGC_END:
+      case PLUGIN_UNROLL_PARAMETER_HANDLER:
+      case PLUGIN_ALL_PASSES_START:
+      case PLUGIN_ALL_PASSES_EXECUTION:
+      case PLUGIN_ALL_PASSES_END:
+      case PLUGIN_ALL_IPA_PASSES_START:
+      case PLUGIN_ALL_IPA_PASSES_EXECUTION:
+      case PLUGIN_ALL_IPA_PASSES_END:
+      case PLUGIN_OVERRIDE_GATE:
+      case PLUGIN_PASS_EXECUTION:
+      case PLUGIN_EARLY_GIMPLE_PASSES_START:
+      case PLUGIN_EARLY_GIMPLE_PASSES_END:
+      case PLUGIN_NEW_PASS:
         {
           /* Iterate over every callback registered with this event and
              call it.  */
           struct callback_info *callback = plugin_callbacks[event];
+
+	  if (!callback)
+	    retval = PLUGEVT_NO_CALLBACK;
           for ( ; callback; callback = callback->next)
             (*callback->func) (gcc_data, callback->user_data);
         }
         break;
 
       case PLUGIN_PASS_MANAGER_SETUP:
-      case PLUGIN_EVENT_LAST:
       case PLUGIN_REGISTER_GGC_ROOTS:
       case PLUGIN_REGISTER_GGC_CACHES:
-      default:
         gcc_assert (false);
     }
 
   timevar_pop (TV_PLUGIN_RUN);
+  return retval;
+}
+
+int
+invoke_plugin_va_callbacks (int event, ...)
+{
+  va_list va;
+  int retval;
+
+  va_start (va, event);
+  retval = invoke_plugin_callbacks (event, &va);
+  va_end (va);
+  return retval;
 }
 
 #ifdef ENABLE_PLUGIN
@@ -621,7 +754,7 @@ plugins_active_p (void)
 {
   int event;
 
-  for (event = PLUGIN_PASS_MANAGER_SETUP; event < PLUGIN_EVENT_LAST; event++)
+  for (event = PLUGIN_PASS_MANAGER_SETUP; event < event_last; event++)
     if (plugin_callbacks[event])
       return true;
 
@@ -641,7 +774,7 @@ dump_active_plugins (FILE *file)
     return;
 
   fprintf (file, FMT_FOR_PLUGIN_EVENT " | %s\n", _("Event"), _("Plugins"));
-  for (event = PLUGIN_PASS_MANAGER_SETUP; event < PLUGIN_EVENT_LAST; event++)
+  for (event = PLUGIN_PASS_MANAGER_SETUP; event < event_last; event++)
     if (plugin_callbacks[event])
       {
 	struct callback_info *ci;
diff -drupN --exclude .svn gcc/gcc/plugin.def gcc-ici-2/gcc/plugin.def
--- gcc/gcc/plugin.def	1970-01-01 01:00:00.000000000 +0100
+++ gcc-ici-2/gcc/plugin.def	2009-12-01 05:35:13.171654092 +0000
@@ -0,0 +1,103 @@
+/* This file contains the definitions for plugin events in GCC.
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+/* To hook into pass manager.  */
+DEFEVENT (PLUGIN_PASS_MANAGER_SETUP)
+
+/* After finishing parsing a type.  */
+DEFEVENT (PLUGIN_FINISH_TYPE)
+
+/* Useful for summary processing.  */
+DEFEVENT (PLUGIN_FINISH_UNIT)
+
+/* Allows to see low level AST in C++ FE.  */
+DEFEVENT (PLUGIN_CXX_CP_PRE_GENERICIZE)
+
+/* Called before GCC exits.  */
+DEFEVENT (PLUGIN_FINISH)
+
+/* Information about the plugin. */
+DEFEVENT (PLUGIN_INFO)
+
+/* Called at start of GCC Garbage Collection. */
+DEFEVENT (PLUGIN_GGC_START)
+
+/* Extend the GGC marking. */
+DEFEVENT (PLUGIN_GGC_MARKING)
+
+/* Called at end of GGC. */
+DEFEVENT (PLUGIN_GGC_END)
+
+/* Register an extra GGC root table. */
+DEFEVENT (PLUGIN_REGISTER_GGC_ROOTS)
+
+/* Register an extra GGC cache table. */
+DEFEVENT (PLUGIN_REGISTER_GGC_CACHES)
+
+/* Called during attribute registration.  */
+DEFEVENT (PLUGIN_ATTRIBUTES)
+
+/* Called before processing a translation unit.  */
+DEFEVENT (PLUGIN_START_UNIT)
+
+/* Called during pragma registration.  */
+DEFEVENT (PLUGIN_PRAGMAS)
+
+/* Called to allow inspection and/or modification of unroll parameters.  */
+DEFEVENT (PLUGIN_UNROLL_PARAMETER_HANDLER)
+
+/* Called before first pass from all_passes.  */
+DEFEVENT (PLUGIN_ALL_PASSES_START)
+
+/* Allows pass execution to be substituted.  */
+DEFEVENT (PLUGIN_ALL_PASSES_EXECUTION)
+
+/* Called after last pass from all_passes.  */
+DEFEVENT (PLUGIN_ALL_PASSES_END)
+
+/* Called before first ipa pass.  */
+DEFEVENT (PLUGIN_ALL_IPA_PASSES_START)
+
+/* Allows ipa pass execution to be substituted.  */
+DEFEVENT (PLUGIN_ALL_IPA_PASSES_EXECUTION)
+
+/* Called after last ipa pass.  */
+DEFEVENT (PLUGIN_ALL_IPA_PASSES_END)
+
+/* Allows to override pass gate decision for current_pass.  */
+DEFEVENT (PLUGIN_OVERRIDE_GATE)
+
+/* Called before executing a pass.  */
+DEFEVENT (PLUGIN_PASS_EXECUTION)
+
+/* Called before executing subpasses of a GIMPLE_PASS in
+   execute_ipa_pass_list.  */
+DEFEVENT (PLUGIN_EARLY_GIMPLE_PASSES_START)
+
+/* Called after executing subpasses of a GIMPLE_PASS in
+   execute_ipa_pass_list.  */
+DEFEVENT (PLUGIN_EARLY_GIMPLE_PASSES_END)
+
+/* Called when a pass is first instantiated.  */
+DEFEVENT (PLUGIN_NEW_PASS)
+
+/* After the hard-coded events above, plugins can dynamically allocate events
+   at run time.
+   PLUGIN_EVENT_FIRST_DYNAMIC only appears as last enum element.  */
diff -drupN --exclude .svn gcc/gcc/plugin.h gcc-ici-2/gcc/plugin.h
--- gcc/gcc/plugin.h	2009-11-04 14:49:32.602125905 +0000
+++ gcc-ici-2/gcc/plugin.h	2009-11-30 15:44:55.089525707 +0000
@@ -26,7 +26,8 @@ struct attribute_spec;
 
 extern void add_new_plugin (const char *);
 extern void parse_plugin_arg_opt (const char *);
-extern void invoke_plugin_callbacks (enum plugin_event, void *);
+extern int invoke_plugin_callbacks (int, void *);
+extern int invoke_plugin_va_callbacks (int, ...);
 extern void initialize_plugins (void);
 extern bool plugins_active_p (void);
 extern void dump_active_plugins (FILE *);
diff -drupN --exclude .svn gcc/gcc/tree-optimize.c gcc-ici-2/gcc/tree-optimize.c
--- gcc/gcc/tree-optimize.c	2009-11-29 17:42:49.047772795 +0000
+++ gcc-ici-2/gcc/tree-optimize.c	2009-11-30 15:44:55.090773072 +0000
@@ -49,6 +49,7 @@ along with GCC; see the file COPYING3.  
 #include "graph.h"
 #include "cfgloop.h"
 #include "except.h"
+#include "plugin.h"
 
 
 /* Gate: execute, or not, all of the non-trivial optimizations.  */
@@ -378,6 +379,7 @@ void
 tree_rest_of_compilation (tree fndecl)
 {
   location_t saved_loc;
+  int substitute_status;
 
   timevar_push (TV_EXPAND);
 
@@ -405,7 +407,20 @@ tree_rest_of_compilation (tree fndecl)
   execute_all_ipa_transforms ();
 
   /* Perform all tree transforms and optimizations.  */
-  execute_pass_list (all_passes);
+
+  /* Signal the start of passes.  */
+  invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL);
+
+  /* ICI Event: Substitution of pass manager.  */
+  /* Try calling the event - if not successful, or if the plugin did not
+     manipulate passes, fall back on the default pass ordering.  */
+  substitute_status = 0;
+  invoke_plugin_callbacks (PLUGIN_ALL_PASSES_EXECUTION, &substitute_status);
+  if (substitute_status == 0)
+    execute_pass_list (all_passes);
+
+  /* Signal the end of passes.  */
+  invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL);
 
   bitmap_obstack_release (&reg_obstack);
 
diff -drupN --exclude .svn gcc/gcc/tree-pass.h gcc-ici-2/gcc/tree-pass.h
--- gcc/gcc/tree-pass.h	2009-11-29 17:42:48.639772819 +0000
+++ gcc-ici-2/gcc/tree-pass.h	2009-11-30 15:44:55.090773072 +0000
@@ -565,12 +565,16 @@ extern struct opt_pass *all_passes, *all
 extern struct opt_pass *current_pass;
 
 extern struct opt_pass * get_pass_for_id (int);
+extern bool execute_one_pass (struct opt_pass *);
 extern void execute_pass_list (struct opt_pass *);
 extern void execute_ipa_pass_list (struct opt_pass *);
 extern void execute_ipa_summary_passes (struct ipa_opt_pass_d *);
 extern void execute_all_ipa_transforms (void);
 extern void execute_all_ipa_stmt_fixups (struct cgraph_node *, gimple *);
+extern bool pass_init_dump_file (struct opt_pass *);
+extern void pass_fini_dump_file (struct opt_pass *);
 
+extern const char *get_current_pass_name (void);
 extern void print_current_pass (FILE *);
 extern void debug_pass (void);
 extern void ipa_write_summaries (void);
@@ -590,4 +594,7 @@ extern void register_pass (struct regist
    directly in jump threading, and avoid peeling them next time.  */
 extern bool first_pass_instance;
 
+/* Declare for plugins like ICI.  */
+extern void do_per_function_toporder (void (*) (void *), void *);
+
 #endif /* GCC_TREE_PASS_H */

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

* Re: Fwd: RFA: plugin events for ICI
  2009-12-01  7:18       ` Joern Rennecke
@ 2009-12-01 10:23         ` Richard Guenther
  2009-12-01 13:06           ` Joern Rennecke
  2009-12-01 14:39           ` Joern Rennecke
  0 siblings, 2 replies; 13+ messages in thread
From: Richard Guenther @ 2009-12-01 10:23 UTC (permalink / raw)
  To: Joern Rennecke
  Cc: Basile STARYNKEVITCH, ctuning-discussions, gcc-patches,
	Grigori Fursin, Grigori Fursin, Zbigniew Chamski,
	Ian Lance Taylor, Albert Cohen, Yuri Kashnikoff, Yuanjie Huang,
	Liang Peng, dorit, Mircea Namolaru, Diego Novillo

On Tue, Dec 1, 2009 at 6:54 AM, Joern Rennecke <amylaar@spamcop.net> wrote:
> Quoting Basile STARYNKEVITCH <basile@starynkevitch.net>:
>>
>> I am not sure to have understood all your explanation (but I admit
>> being tired).
>> Perhaps you should add an entire subsection in doc/plugins.texi
>> explaining what you have added and how to use them.
>> At the moment I am not sure to have understood how to use them.
>>
>> More generally, I believe plugins ought to be quite well documented. A
>> good enough documentation is important to make them successful.
>
> I have extended plugins.texi to describe the new events.
>
>>> The function is explained in the passes.c, were it has been defined  all
>>> along.
>>
>> But then, please move the explanation to header files. I can assure you
>> that newbies first read *.h files, and only when needed the *.c
>> implementing them.
>
> The common practice in GCC is to document functions where they are
> defined; most global functions are simply declared in a header file,
> without any comment there.
> I see no reason to deviate from this practice now.
>
>> I hope your patch will be accepted in 4.5. If I had the power to accept
>> it, I'll ok it (provided you added more documentation).
>
> The patch with the updated documentation is attached.
> I have tested the updated documentation with 'make info' and 'make pdf' .

There is a lot of useful general cleanup mixed with more questionable
changes.  For one, comments like 'Changed for FICI0: ' or
'ICI Event: Substitution of pass manager.' do not belong in GCC
source code.

I do not particularly like the loop unroll changes (you have a pass
start / end hook, why can't you modify the globals from there?).
It smells like very specific to ICI.

Likewise I do not like

+  /* ICI Event: Substitution of pass manager.  */
+  /* Try calling the event - if not successful, or if the plugin did not
+     manipulate passes, fall back on the default pass ordering.  */
+  substitute_status = 0;
+  invoke_plugin_callbacks (PLUGIN_ALL_PASSES_EXECUTION, &substitute_status);
+  if (substitute_status == 0)
+    execute_pass_list (all_passes);
+

The rest looks reasonable, so if you can re-submit without the
above changes...?

Thanks,
Richard.

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

* Re: Fwd: RFA: plugin events for ICI
  2009-12-01 10:23         ` Richard Guenther
@ 2009-12-01 13:06           ` Joern Rennecke
  2009-12-01 13:48             ` Richard Guenther
  2009-12-01 14:39           ` Joern Rennecke
  1 sibling, 1 reply; 13+ messages in thread
From: Joern Rennecke @ 2009-12-01 13:06 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Basile STARYNKEVITCH, ctuning-discussions, gcc-patches,
	Grigori Fursin, Grigori Fursin, Zbigniew Chamski,
	Ian Lance Taylor, Albert Cohen, Yuri Kashnikoff, Yuanjie Huang,
	Liang Peng, dorit, Mircea Namolaru, Diego Novillo

Quoting Richard Guenther <richard.guenther@gmail.com>:
> There is a lot of useful general cleanup mixed with more questionable
> changes.  For one, comments like 'Changed for FICI0: ' or
> 'ICI Event: Substitution of pass manager.' do not belong in GCC
> source code.

Ok, I'll work on changing these.
So, where a symbol has been made global for the benefit of ICI, I should
only say that it has been made global so that plugins can use it, without
mentioning any plugin in particular?
>
> I do not particularly like the loop unroll changes (you have a pass
> start / end hook, why can't you modify the globals from there?).

I suppose I could replace the loop-init.c:rtl_unroll_and_peel_loops
patch with a PLUGIN_PASS_EXECUTION callback.  It will be somewhat ugly to
get the different PLUGIN_PASS_EXECUTION callbacks in the desired order,
and the globals will be changed after pass execution (there is not actually
a pass end hook), but I suppose the end result will be the same.

However, this approach could not be used for the loop-unroll.c patches.
The features exposed and the heuristics manipulation work on a per-loop
basis.

> It smells like very specific to ICI.

Are you referring to comments and identifier names, or do you have objections
to the functionality and/or interface?

> Likewise I do not like
>
> +  /* ICI Event: Substitution of pass manager.  */
> +  /* Try calling the event - if not successful, or if the plugin did not
> +     manipulate passes, fall back on the default pass ordering.  */
> +  substitute_status = 0;
> +  invoke_plugin_callbacks (PLUGIN_ALL_PASSES_EXECUTION, &substitute_status);
> +  if (substitute_status == 0)
> +    execute_pass_list (all_passes);
> +

Again - is this about the comment, or about the functionality too?
The functionality is central to the pass reordering in ICI.

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

* Re: Fwd: RFA: plugin events for ICI
  2009-12-01 13:06           ` Joern Rennecke
@ 2009-12-01 13:48             ` Richard Guenther
  0 siblings, 0 replies; 13+ messages in thread
From: Richard Guenther @ 2009-12-01 13:48 UTC (permalink / raw)
  To: Joern Rennecke
  Cc: Basile STARYNKEVITCH, ctuning-discussions, gcc-patches,
	Grigori Fursin, Grigori Fursin, Zbigniew Chamski,
	Ian Lance Taylor, Albert Cohen, Yuri Kashnikoff, Yuanjie Huang,
	Liang Peng, dorit, Mircea Namolaru, Diego Novillo

On Tue, Dec 1, 2009 at 2:05 PM, Joern Rennecke <amylaar@spamcop.net> wrote:
> Quoting Richard Guenther <richard.guenther@gmail.com>:
>>
>> There is a lot of useful general cleanup mixed with more questionable
>> changes.  For one, comments like 'Changed for FICI0: ' or
>> 'ICI Event: Substitution of pass manager.' do not belong in GCC
>> source code.
>
> Ok, I'll work on changing these.
> So, where a symbol has been made global for the benefit of ICI, I should
> only say that it has been made global so that plugins can use it, without
> mentioning any plugin in particular?

Yes.

>> I do not particularly like the loop unroll changes (you have a pass
>> start / end hook, why can't you modify the globals from there?).
>
> I suppose I could replace the loop-init.c:rtl_unroll_and_peel_loops
> patch with a PLUGIN_PASS_EXECUTION callback.  It will be somewhat ugly to
> get the different PLUGIN_PASS_EXECUTION callbacks in the desired order,
> and the globals will be changed after pass execution (there is not actually
> a pass end hook), but I suppose the end result will be the same.
>
> However, this approach could not be used for the loop-unroll.c patches.
> The features exposed and the heuristics manipulation work on a per-loop
> basis.

Still I'd like to see a more general approach for this kind of stuff
(and thus the best is to leave it out of the current patch and
discuss it separately).

>> It smells like very specific to ICI.
>
> Are you referring to comments and identifier names, or do you have
> objections
> to the functionality and/or interface?

Mostly the interface.

>> Likewise I do not like
>>
>> +  /* ICI Event: Substitution of pass manager.  */
>> +  /* Try calling the event - if not successful, or if the plugin did not
>> +     manipulate passes, fall back on the default pass ordering.  */
>> +  substitute_status = 0;
>> +  invoke_plugin_callbacks (PLUGIN_ALL_PASSES_EXECUTION,
>> &substitute_status);
>> +  if (substitute_status == 0)
>> +    execute_pass_list (all_passes);
>> +
>
> Again - is this about the comment, or about the functionality too?
> The functionality is central to the pass reordering in ICI.

It's about the interface.  Please split it out from the patch and
submit it separately so a focused discussion is possible.

For example I don't see what the hook is supposed to do?
It seems it is supposed to be the pass manager itself?
(Btw, why does invoke_plugin_callbacks not return a value,
that would make code way more readable than going through
the passed by reference appearant return value ...)

So, why not instead re-use

invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL);

to do this?  Or rather, why not have this or another hook
mess with all_passes directly?

Personally I would have expected that execute_pass_list
and execute_one_pass itself become hooks in a pass-manager
hook table and a plugin could replace these.  The current
hooking seems to be glued ontop of things without considering
a more reasonable design...

Thanks,
Richard.

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

* Re: Fwd: RFA: plugin events for ICI
  2009-12-01 10:23         ` Richard Guenther
  2009-12-01 13:06           ` Joern Rennecke
@ 2009-12-01 14:39           ` Joern Rennecke
  2009-12-01 14:52             ` Richard Guenther
                               ` (2 more replies)
  1 sibling, 3 replies; 13+ messages in thread
From: Joern Rennecke @ 2009-12-01 14:39 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Basile STARYNKEVITCH, ctuning-discussions, gcc-patches,
	Grigori Fursin, Grigori Fursin, Zbigniew Chamski,
	Ian Lance Taylor, Albert Cohen, Yuri Kashnikoff, Yuanjie Huang,
	Liang Peng, dorit, Mircea Namolaru, Diego Novillo

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

Quoting Richard Guenther <richard.guenther@gmail.com>:
> The rest looks reasonable, so if you can re-submit without the
> above changes...?

Please find attached the reduced patch that I am currently testing.

[-- Attachment #2: gcc-ici-patch-20091201-2 --]
[-- Type: text/plain, Size: 36108 bytes --]

2009-12-01  Grigori Fursin  <grigori.fursin@inria.fr>
	    Joern Rennecke  <amylaar@spamcop.net>

	* cgraphunit.c (plugin.h): Include.
	(ipa_passes): Invoke PLUGIN_ALL_IPA_PASSES_START /
	PLUGIN_ALL_IPA_PASSES_END at start / end of processing.
	* gcc-plugin.h (highlev-plugin-common.h, hashtab.h): Include.
	(enum plugin_event): Define by including plugin.def.
	Last enumerator is now called PLUGIN_EVENT_FIRST_DYNAMIC.
	(plugin_event_name): Change type to const char **.
	(event_last, get_named_event_id, unregister_callback): Declare.
	(register_callback): Change type of event argument to int.
	(highlev-plugin-common.h): New file.
	* Makefile.in (GCC_PLUGIN_H): Add highlev-plugin-common.h and
	$(HASHTAB_H)
	(tree-optimize.o passes.o): Depend on $(PLUGIN_H).
	(PLUGIN_HEADERS): Add opts.h, $(PARAMS_H) and plugin.def.
	(s-header-vars): New rule.
	(install-plugin): Depend on s-header-vars.  Install b-header-vars.
	* params.c (num_compiler_params): No longer static.
	* params.h (num_compiler_params): Declare.
	* passes.c (plugin.h): Include.
	(make_pass_instance): Invoke PLUGIN_NEW_PASS.
	(do_per_function_toporder, pass_init_dump_file): No longer static.
	(pass_fini_dump_file): Likewise.
	(execute_one_pass): Likewise.  Invoke PLUGIN_OVERRIDE_GATE and
	PLUGIN_PASS_EXECUTION.
	(execute_ipa_pass_list): Invoke PLUGIN_EARLY_GIMPLE_PASSES_START and
	PLUGIN_EARLY_GIMPLE_PASSES_END.
	* plugin.c (plugin_event_name_init): New array, defined by
	including plugin.def.
	(FMT_FOR_PLUGIN_EVENT): Update.
	(plugin_event_name): Change type to const char ** and initialize
	to plugin_event_name_init.
	(event_tab, event_last, event_horizon): New variable.
	(plugin_callbacks_init): New array.
	(plugin_callbacks: Change type to struct callback_info **.
	Initialize to plugin_callbacks_init.
	(htab_event_eq, get_named_event_id, unregister_callback): New function.
	(invoke_plugin_va_callbacks): Likewise.
	(register_callback): Change type of event argument to int.
	Handle new events.  Allow dynamic events.
	(invoke_plugin_callbacks): Likewise.  Return success status.
	(plugins_active_p): Allow dynamic callbacks.
	* plugin.def: New file.
	* plugin.h (invoke_plugin_callbacks): Update prototype.
	(invoke_plugin_va_callbacks): Declare.
	* tree-optimize.c (plugin.h): Include.
	(tree_rest_of_compilation): Invoke PLUGIN_ALL_PASSES_START and
	PLUGIN_ALL_PASSES_END.
	* tree-pass.h (execute_one_pass, pass_init_dump_file): Declare.
	(pass_fini_dump_file, do_per_function_toporder): Likewise.
	* doc/plugin.texi: Document new event types.

diff -drupN --exclude .svn gcc/gcc/cgraphunit.c gcc-ici-3/gcc/cgraphunit.c
--- gcc/gcc/cgraphunit.c	2009-11-29 17:42:48.662772536 +0000
+++ gcc-ici-3/gcc/cgraphunit.c	2009-12-01 13:54:02.833653857 +0000
@@ -135,6 +135,7 @@ along with GCC; see the file COPYING3.  
 #include "tree-dump.h"
 #include "output.h"
 #include "coverage.h"
+#include "plugin.h"
 
 static void cgraph_expand_all_functions (void);
 static void cgraph_mark_functions_to_output (void);
@@ -1712,6 +1713,8 @@ ipa_passes (void)
   gimple_register_cfg_hooks ();
   bitmap_obstack_initialize (NULL);
 
+  invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_START, NULL);
+
   if (!in_lto_p)
     execute_ipa_pass_list (all_small_ipa_passes);
 
@@ -1730,7 +1733,8 @@ ipa_passes (void)
       current_function_decl = NULL;
       cgraph_process_new_functions ();
 
-      execute_ipa_summary_passes ((struct ipa_opt_pass_d *) all_regular_ipa_passes);
+      execute_ipa_summary_passes
+	((struct ipa_opt_pass_d *) all_regular_ipa_passes);
     }
   execute_ipa_summary_passes ((struct ipa_opt_pass_d *) all_lto_gen_passes);
 
@@ -1739,6 +1743,7 @@ ipa_passes (void)
 
   if (!flag_ltrans)
     execute_ipa_pass_list (all_regular_ipa_passes);
+  invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_END, NULL);
 
   bitmap_obstack_release (NULL);
 }
diff -drupN --exclude .svn gcc/gcc/doc/plugins.texi gcc-ici-3/gcc/doc/plugins.texi
--- gcc/gcc/doc/plugins.texi	2009-11-29 17:42:32.565901921 +0000
+++ gcc-ici-3/gcc/doc/plugins.texi	2009-12-01 13:44:38.837653549 +0000
@@ -156,18 +156,42 @@ enum plugin_event
   PLUGIN_ATTRIBUTES,            /* Called during attribute registration */
   PLUGIN_START_UNIT,            /* Called before processing a translation unit.  */
   PLUGIN_PRAGMAS,	        /* Called during pragma registration. */
-  PLUGIN_EVENT_LAST             /* Dummy event used for indexing callback
+  /* Called before first pass from all_passes.  */
+  PLUGIN_ALL_PASSES_START,
+  /* Called after last pass from all_passes.  */
+  PLUGIN_ALL_PASSES_END,
+  /* Called before first ipa pass.  */
+  PLUGIN_ALL_IPA_PASSES_START,
+  /* Called after last ipa pass.  */
+  PLUGIN_ALL_IPA_PASSES_END,
+  /* Allows to override pass gate decision for current_pass.  */
+  PLUGIN_OVERRIDE_GATE,
+  /* Called before executing a pass.  */
+  PLUGIN_PASS_EXECUTION,
+  /* Called before executing subpasses of a GIMPLE_PASS in
+     execute_ipa_pass_list.  */
+  PLUGIN_EARLY_GIMPLE_PASSES_START,
+  /* Called after executing subpasses of a GIMPLE_PASS in
+     execute_ipa_pass_list.  */
+  PLUGIN_EARLY_GIMPLE_PASSES_END,
+  /* Called when a pass is first instantiated.  */
+  PLUGIN_NEW_PASS,
+
+  PLUGIN_EVENT_FIRST_DYNAMIC    /* Dummy event used for indexing callback
                                    array.  */
 @};
 @end smallexample
 
+In addition, plugins can also look up the enumerator of a named event,
+and / or generate new events dynamically, by calling the function
+@code{get_named_event_id}.
 
 To register a callback, the plugin calls @code{register_callback} with
 the arguments:
 
 @itemize
 @item @code{char *name}: Plugin name.
-@item @code{enum plugin_event event}: The event code.
+@item @code{int event}: The event code.
 @item @code{plugin_callback_func callback}: The function that handles @code{event}.
 @item @code{void *user_data}: Pointer to plugin-specific data.
 @end itemize
@@ -337,6 +361,41 @@ It is suggested to pass @code{"GCCPLUGIN
 your plugin) as the ``space'' argument of your pragma. 
 
 
+@section Recording information about pass execution
+
+The event PLUGIN_PASS_EXECUTION passes the pointer to the executed pass
+(the same as current_pass) as @code{gcc_data} to the callback.  You can also
+inspect cfun to find out about which function this pass is executed for.
+Note that this event will only be invoked if the gate check (if
+applicable, modified by PLUGIN_OVERRIDE_GATE) succeeds.
+You can use other hooks, like @code{PLUGIN_ALL_PASSES_START},
+@code{PLUGIN_ALL_PASSES_END}, @code{PLUGIN_ALL_IPA_PASSES_START},
+@code{PLUGIN_ALL_IPA_PASSES_END}, @code{PLUGIN_EARLY_GIMPLE_PASSES_START},
+and/or @code{PLUGIN_EARLY_GIMPLE_PASSES_END} to manipulate global state
+in your plugin(s) in order to get context for the pass execution.
+
+
+@section Controlling which passes are being run
+
+After the orginary gate function for a pass is called, the result of
+the gate test - the gate status - stored as an integer.
+Then the event @code{PLUGIN_OVERRIDE_GATE} is invoked, with a pointer
+to the gate status in the @code{gcc_data} parameter to the callback function.
+A nonzero value of the gate status means that the pass is to be executed.
+You can both read and write the gate status via the passed pointer.
+
+
+@section Keeping track of available passes
+
+When your plugin is loaded, yt the moment you can inspect the various
+pass lists to determine what passes are available.  However, other
+plugins might add new passes.  Also, future changes to GCC might cause
+generic passes to be added after plugin loading.
+When a pass is first added to one of the pass lists, the event
+@code{PLUGIN_NEW_PASS} is invoked, with the callback parameter
+@code{gcc_data} pointing to the new pass.
+
+
 @section Building GCC plugins
 
 If plugins are enabled, GCC installs the headers needed to build a
diff -drupN --exclude .svn gcc/gcc/gcc-plugin.h gcc-ici-3/gcc/gcc-plugin.h
--- gcc/gcc/gcc-plugin.h	2009-11-08 21:11:04.273376423 +0000
+++ gcc-ici-3/gcc/gcc-plugin.h	2009-11-30 15:44:55.055772873 +0000
@@ -26,29 +26,19 @@ along with GCC; see the file COPYING3.  
 
 #include "config.h"
 #include "system.h"
+#include "highlev-plugin-common.h"
+#include "hashtab.h"
 
-/* Event names.  Keep in sync with plugin_event_name[].  */
+/* Event names.  */
 enum plugin_event
 {
-  PLUGIN_PASS_MANAGER_SETUP,    /* To hook into pass manager.  */
-  PLUGIN_FINISH_TYPE,           /* After finishing parsing a type.  */
-  PLUGIN_FINISH_UNIT,           /* Useful for summary processing.  */
-  PLUGIN_CXX_CP_PRE_GENERICIZE, /* Allows to see low level AST in C++ FE.  */
-  PLUGIN_FINISH,                /* Called before GCC exits.  */
-  PLUGIN_INFO,                  /* Information about the plugin. */
-  PLUGIN_GGC_START,		/* Called at start of GCC Garbage Collection. */
-  PLUGIN_GGC_MARKING,		/* Extend the GGC marking. */
-  PLUGIN_GGC_END,		/* Called at end of GGC. */
-  PLUGIN_REGISTER_GGC_ROOTS,	/* Register an extra GGC root table. */
-  PLUGIN_REGISTER_GGC_CACHES,	/* Register an extra GGC cache table. */
-  PLUGIN_ATTRIBUTES,            /* Called during attribute registration.  */
-  PLUGIN_START_UNIT,            /* Called before processing a translation unit.  */
-  PLUGIN_PRAGMAS,	        /* Called during pragma registration.  */
-  PLUGIN_EVENT_LAST             /* Dummy event used for indexing callback
-                                   array.  */
+# define DEFEVENT(NAME) NAME,
+# include "plugin.def"
+# undef DEFEVENT
+  PLUGIN_EVENT_FIRST_DYNAMIC
 };
 
-extern const char *plugin_event_name[];
+extern const char **plugin_event_name;
 
 struct plugin_argument
 {
@@ -127,14 +117,22 @@ typedef void (*plugin_callback_func) (vo
    USER_DATA   - plugin-provided data.
 */
 
+/* Number of event ids / names registered so far.  */
+
+extern int event_last;
+
+int get_named_event_id (const char *name, enum insert_option insert);
+
 /* This is also called without a callback routine for the
    PLUGIN_PASS_MANAGER_SETUP, PLUGIN_INFO, PLUGIN_REGISTER_GGC_ROOTS and
    PLUGIN_REGISTER_GGC_CACHES pseudo-events, with a specific user_data.
   */
 
 extern void register_callback (const char *plugin_name,
-                               enum plugin_event event,
+			       int event,
                                plugin_callback_func callback,
                                void *user_data);
 
+extern int unregister_callback (const char *plugin_name, int event);
+
 #endif /* GCC_PLUGIN_H */
diff -drupN --exclude .svn gcc/gcc/highlev-plugin-common.h gcc-ici-3/gcc/highlev-plugin-common.h
--- gcc/gcc/highlev-plugin-common.h	1970-01-01 01:00:00.000000000 +0100
+++ gcc-ici-3/gcc/highlev-plugin-common.h	2009-12-01 13:49:26.129669583 +0000
@@ -0,0 +1,33 @@
+/* Interface for high-level plugins in GCC - Parts common between GCC,
+   ICI and high-level plugins.
+
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+   Contributed by INRIA.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef HIGHLEV_PLUGIN_COMMON_H
+#define HIGHLEV_PLUGIN_COMMON_H
+
+/* Return codes for invoke_plugin_callbacks / call_plugin_event .  */
+#define PLUGEVT_SUCCESS         0
+#define PLUGEVT_NO_EVENTS       1
+#define PLUGEVT_NO_SUCH_EVENT   2
+#define PLUGEVT_NO_CALLBACK     3
+
+#endif /* HIGHLEV_PLUGIN_COMMON_H */
diff -drupN --exclude .svn gcc/gcc/Makefile.in gcc-ici-3/gcc/Makefile.in
--- gcc/gcc/Makefile.in	2009-11-29 17:42:49.155526086 +0000
+++ gcc-ici-3/gcc/Makefile.in	2009-12-01 14:08:00.428897667 +0000
@@ -943,7 +943,8 @@ TREE_VECTORIZER_H = tree-vectorizer.h $(
 IPA_PROP_H = ipa-prop.h $(TREE_H) vec.h $(CGRAPH_H)
 GSTAB_H = gstab.h stab.def
 BITMAP_H = bitmap.h $(HASHTAB_H) statistics.h
-GCC_PLUGIN_H = gcc-plugin.h $(CONFIG_H) $(SYSTEM_H)
+GCC_PLUGIN_H = gcc-plugin.h highlev-plugin-common.h $(CONFIG_H) $(SYSTEM_H) \
+		$(HASHTAB_H)
 PLUGIN_H = plugin.h $(GCC_PLUGIN_H)
 PLUGIN_VERSION_H = plugin-version.h configargs.h
 
@@ -2503,8 +2504,9 @@ tree-ssa-reassoc.o : tree-ssa-reassoc.c 
    langhooks.h alloc-pool.h pointer-set.h $(CFGLOOP_H)
 tree-optimize.o : tree-optimize.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
    $(RTL_H) $(TREE_H) $(TM_P_H) hard-reg-set.h $(EXPR_H) $(GGC_H) output.h \
-   $(DIAGNOSTIC_H) $(BASIC_BLOCK_H) $(FLAGS_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
-   $(TREE_DUMP_H) $(TOPLEV_H) $(FUNCTION_H) langhooks.h $(FLAGS_H) $(CGRAPH_H) \
+   $(DIAGNOSTIC_H) $(BASIC_BLOCK_H) $(FLAGS_H) $(TIMEVAR_H) $(TM_H) \
+   coretypes.h $(TREE_DUMP_H) $(TOPLEV_H) $(FUNCTION_H) langhooks.h \
+   $(FLAGS_H) $(CGRAPH_H) $(PLUGIN_H) \
    $(TREE_INLINE_H) tree-mudflap.h $(GGC_H) graph.h $(CGRAPH_H) \
    $(TREE_PASS_H) $(CFGLOOP_H) $(EXCEPT_H)
 
@@ -2725,7 +2727,8 @@ passes.o : passes.c $(CONFIG_H) $(SYSTEM
    langhooks.h insn-flags.h $(CFGLAYOUT_H) $(REAL_H) $(CFGLOOP_H) \
    hosthooks.h $(CGRAPH_H) $(COVERAGE_H) $(TREE_PASS_H) $(TREE_DUMP_H) \
    $(GGC_H) $(INTEGRATE_H) $(CPPLIB_H) opts.h $(TREE_FLOW_H) $(TREE_INLINE_H) \
-   gt-passes.h $(DF_H) $(PREDICT_H) $(LTO_HEADER_H) $(LTO_SECTION_OUT_H)
+   gt-passes.h $(DF_H) $(PREDICT_H) $(LTO_HEADER_H) $(LTO_SECTION_OUT_H) \
+   $(PLUGIN_H)
 
 plugin.o : plugin.c $(PLUGIN_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h \
    $(TOPLEV_H) $(TREE_H) $(TREE_PASS_H) intl.h $(PLUGIN_VERSION_H) $(GGC_H)
@@ -4264,7 +4267,7 @@ installdirs:
 
 PLUGIN_HEADERS = $(TREE_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
   $(TOPLEV_H) $(BASIC_BLOCK_H) $(GIMPLE_H) $(TREE_PASS_H) $(GCC_PLUGIN_H) \
-  $(GGC_H) $(TREE_DUMP_H) $(PRETTY_PRINT_H) \
+  $(GGC_H) $(TREE_DUMP_H) $(PRETTY_PRINT_H) opts.h $(PARAMS_H) plugin.def \
   $(tm_file_list) $(tm_include_list) $(tm_p_file_list) $(tm_p_include_list) \
   $(host_xm_file_list) $(host_xm_include_list) $(xm_include_list) \
   intl.h $(PLUGIN_VERSION_H) $(DIAGNOSTIC_H) $(C_COMMON_H) $(C_PRETTY_PRINT_H) \
@@ -4273,8 +4276,15 @@ PLUGIN_HEADERS = $(TREE_H) $(CONFIG_H) $
   $(C_PRAGMA_H)  $(CPPLIB_H)  $(FUNCTION_H) \
   cppdefault.h flags.h $(MD5_H) params.def params.h prefix.h tree-inline.h
 
+# generate the 'build fragment' b-header-vars
+s-header-vars: Makefile
+	rm -f tmp-header-vars
+	$(foreach header_var,$(shell sed < Makefile -e 's/^\([A-Z0-9_]*_H\)[      ]*=.*/\1/p' -e d),echo $(header_var)=$(shell echo $($(header_var):$(srcdir)/%=.../%) | sed -e 's~\.\.\./config/~config/~' -e 's~\.\.\..*/~~') >> tmp-header-vars;) \
+	$(SHELL) $(srcdir)/../move-if-change tmp-header-vars b-header-vars
+	$(STAMP) s-header-vars
+
 # Install the headers needed to build a plugin.
-install-plugin: installdirs lang.install-plugin
+install-plugin: installdirs lang.install-plugin s-header-vars
 # We keep the directory structure for files in config and .def files. All
 # other files are flattened to a single directory.
 	$(mkinstalldirs) $(DESTDIR)$(plugin_includedir)
@@ -4298,6 +4308,7 @@ install-plugin: installdirs lang.install
 	  $(mkinstalldirs) $(DESTDIR)$$dir; \
 	  $(INSTALL_DATA) $$path $(DESTDIR)$$dest; \
 	done
+	$(INSTALL_DATA) b-header-vars $(DESTDIR)$(plugin_includedir)/b-header-vars
 
 # Install the compiler executables built during cross compilation.
 install-common: native lang.install-common installdirs
diff -drupN --exclude .svn gcc/gcc/params.c gcc-ici-3/gcc/params.c
--- gcc/gcc/params.c	2009-11-04 14:49:32.468125810 +0000
+++ gcc-ici-3/gcc/params.c	2009-12-01 13:12:17.318654080 +0000
@@ -32,8 +32,8 @@ along with GCC; see the file COPYING3.  
 param_info *compiler_params;
 
 /* The number of entries in the table.  */
-
-static size_t num_compiler_params;
+/* This symbol is global for the benefit of plugins.  */
+size_t num_compiler_params;
 
 /* Add the N PARAMS to the current list of compiler parameters.  */
 
diff -drupN --exclude .svn gcc/gcc/params.h gcc-ici-3/gcc/params.h
--- gcc/gcc/params.h	2009-11-29 17:42:48.652772589 +0000
+++ gcc-ici-3/gcc/params.h	2009-12-01 13:12:57.879653579 +0000
@@ -65,6 +65,10 @@ typedef struct param_info
 
 extern param_info *compiler_params;
 
+/* The number of entries in the table.  */
+/* This symbols is global for the benefit of plugins.  */
+extern size_t num_compiler_params;
+
 /* Add the N PARAMS to the current list of compiler parameters.  */
 
 extern void add_params (const param_info params[], size_t n);
diff -drupN --exclude .svn gcc/gcc/passes.c gcc-ici-3/gcc/passes.c
--- gcc/gcc/passes.c	2009-11-29 17:42:49.163525359 +0000
+++ gcc-ici-3/gcc/passes.c	2009-12-01 13:15:47.660653747 +0000
@@ -85,6 +85,7 @@ along with GCC; see the file COPYING3.  
 #include "df.h"
 #include "predict.h"
 #include "lto-streamer.h"
+#include "plugin.h"
 
 #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
 #include "dwarf2out.h"
@@ -104,7 +105,8 @@ along with GCC; see the file COPYING3.  
 #endif
 
 /* This is used for debugging.  It allows the current pass to printed
-   from anywhere in compilation.  */
+   from anywhere in compilation.
+   The variable current_pass is also used for statistics and plugins.  */
 struct opt_pass *current_pass;
 
 /* Call from anywhere to find out what pass this is.  Useful for
@@ -479,6 +481,8 @@ make_pass_instance (struct opt_pass *pas
     {
       pass->todo_flags_start |= TODO_mark_first_instance;
       pass->static_pass_number = -1;
+
+      invoke_plugin_callbacks (PLUGIN_NEW_PASS, pass);
     }
   return pass;
 }
@@ -1092,7 +1096,8 @@ static GTY ((length ("nnodes"))) struct 
    function CALLBACK for every function in the call graph.  Otherwise,
    call CALLBACK on the current function.  */
 
-static void
+/* This function is global so that plugins can use it.  */
+void
 do_per_function_toporder (void (*callback) (void *data), void *data)
 {
   int i;
@@ -1317,8 +1322,9 @@ verify_curr_properties (void *data)
 #endif
 
 /* Initialize pass dump file.  */
+/* This is non-static so that the plugins can use it.  */
 
-static bool
+bool
 pass_init_dump_file (struct opt_pass *pass)
 {
   /* If a dump file name is present, open it if enabled.  */
@@ -1347,8 +1353,9 @@ pass_init_dump_file (struct opt_pass *pa
 }
 
 /* Flush PASS dump file.  */
+/* This is non-static so that plugins can use it.  */
 
-static void
+void
 pass_fini_dump_file (struct opt_pass *pass)
 {
   /* Flush and close dump file.  */
@@ -1476,12 +1483,14 @@ execute_all_ipa_transforms (void)
 
 /* Execute PASS. */
 
-static bool
+bool
 execute_one_pass (struct opt_pass *pass)
 {
   bool initializing_dump;
   unsigned int todo_after = 0;
 
+  bool gate_status;
+
   /* IPA passes are executed on whole program, so cfun should be NULL.
      Other passes need function context set.  */
   if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS)
@@ -1491,9 +1500,21 @@ execute_one_pass (struct opt_pass *pass)
 
   current_pass = pass;
 
-  /* See if we're supposed to run this pass.  */
-  if (pass->gate && !pass->gate ())
+  /* Check whether gate check should be avoided.
+     User controls the value of the gate through the parameter "gate_status". */
+  gate_status = (pass->gate == NULL) ? true : pass->gate();
+
+  /* Override gate with plugin.  */
+  invoke_plugin_callbacks (PLUGIN_OVERRIDE_GATE, &gate_status);
+
+  if (!gate_status) {
+    current_pass = NULL;
     return false;
+  }
+
+  /* Pass execution event trigger: useful to identify passes being
+     executed.  */
+  invoke_plugin_callbacks (PLUGIN_PASS_EXECUTION, pass);
 
   if (!quiet_flag && !cfun)
     fprintf (stderr, " <%s>", pass->name ? pass->name : "");
@@ -1756,8 +1777,12 @@ execute_ipa_pass_list (struct opt_pass *
       if (execute_one_pass (pass) && pass->sub)
 	{
 	  if (pass->sub->type == GIMPLE_PASS)
-	    do_per_function_toporder ((void (*)(void *))execute_pass_list,
-				      pass->sub);
+	    {
+	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL);
+	      do_per_function_toporder ((void (*)(void *))execute_pass_list,
+					pass->sub);
+	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL);
+	    }
 	  else if (pass->sub->type == SIMPLE_IPA_PASS
 		   || pass->sub->type == IPA_PASS)
 	    execute_ipa_pass_list (pass->sub);
diff -drupN --exclude .svn gcc/gcc/plugin.c gcc-ici-3/gcc/plugin.c
--- gcc/gcc/plugin.c	2009-11-29 17:42:49.053525413 +0000
+++ gcc-ici-3/gcc/plugin.c	2009-12-01 13:58:01.215653243 +0000
@@ -44,28 +44,30 @@ along with GCC; see the file COPYING3.  
 #include "plugin-version.h"
 #endif
 
+#define GCC_PLUGIN_STRINGIFY0(X) #X
+#define GCC_PLUGIN_STRINGIFY1(X) GCC_PLUGIN_STRINGIFY0 (X)
+
 /* Event names as strings.  Keep in sync with enum plugin_event.  */
-const char *plugin_event_name[] =
+static const char *plugin_event_name_init[] =
 {
-  "PLUGIN_PASS_MANAGER_SETUP",
-  "PLUGIN_FINISH_TYPE",
-  "PLUGIN_FINISH_UNIT",
-  "PLUGIN_CXX_CP_PRE_GENERICIZE",
-  "PLUGIN_FINISH",
-  "PLUGIN_INFO",
-  "PLUGIN_GGC_START",
-  "PLUGIN_GGC_MARKING",
-  "PLUGIN_GGC_END",
-  "PLUGIN_REGISTER_GGC_ROOTS",
-  "PLUGIN_REGISTER_GGC_CACHES",
-  "PLUGIN_ATTRIBUTES",
-  "PLUGIN_START_UNIT",
-  "PLUGIN_PRAGMAS",
-  "PLUGIN_EVENT_LAST"
+# define DEFEVENT(NAME) GCC_PLUGIN_STRINGIFY1 (NAME),
+# include "plugin.def"
+# undef DEFEVENT
 };
 
 /* A printf format large enough for the largest event above.  */
-#define FMT_FOR_PLUGIN_EVENT "%-26s"
+#define FMT_FOR_PLUGIN_EVENT "%-32s"
+
+const char **plugin_event_name = plugin_event_name_init;
+
+/* A hash table to map event names to the position of the names in the
+   plugin_event_name table.  */
+static htab_t event_tab;
+
+/* Keep track of the limit of allocated events and space ready for
+   allocating events.  */
+int event_last = PLUGIN_EVENT_FIRST_DYNAMIC;
+static int event_horizon = PLUGIN_EVENT_FIRST_DYNAMIC;
 
 /* Hash table for the plugin_name_args objects created during command-line
    parsing.  */
@@ -81,7 +83,8 @@ struct callback_info
 };
 
 /* An array of lists of 'callback_info' objects indexed by the event id.  */
-static struct callback_info *plugin_callbacks[PLUGIN_EVENT_LAST] = { NULL };
+static struct callback_info *plugin_callbacks_init[PLUGIN_EVENT_FIRST_DYNAMIC];
+static struct callback_info **plugin_callbacks = plugin_callbacks_init;
 
 
 #ifdef ENABLE_PLUGIN
@@ -290,6 +293,70 @@ register_plugin_info (const char* name, 
   plugin->help = info->help;
 }
 
+/* Helper function for the event hash table that compares the name of an
+   existing entry (E1) with the given string (S2).  */
+
+static int
+htab_event_eq (const void *e1, const void *s2)
+{
+  const char *s1= *(const char * const *) e1;
+  return !strcmp (s1, (const char *) s2);
+}
+
+/* Look up the event id for NAME.  If the name is not found, return -1
+   if INSERT is NO_INSERT.  */
+int
+get_named_event_id (const char *name, enum insert_option insert)
+{
+  void **slot;
+
+  if (!event_tab)
+    {
+      int i;
+
+      event_tab = htab_create (150, htab_hash_string, htab_event_eq, NULL);
+      for (i = 0; i < PLUGIN_EVENT_FIRST_DYNAMIC; i++)
+	{
+	  slot = htab_find_slot (event_tab, plugin_event_name[i], INSERT);
+	  gcc_assert (*slot == HTAB_EMPTY_ENTRY);
+	  *slot = &plugin_event_name[i];
+	}
+    }
+  slot = htab_find_slot (event_tab, name, insert);
+  if (slot == NULL)
+    return -1;
+  if (*slot != HTAB_EMPTY_ENTRY)
+    return (const char **) *slot - &plugin_event_name[0];
+
+  if (event_last >= event_horizon)
+    {
+      event_horizon = event_last * 2;
+      if (plugin_event_name == plugin_event_name_init)
+	{
+	  plugin_event_name = XNEWVEC (const char *, event_horizon);
+	  memcpy (plugin_event_name, plugin_event_name_init,
+		  sizeof plugin_event_name_init);
+	  plugin_callbacks = XNEWVEC (struct callback_info *, event_horizon);
+	  memcpy (plugin_callbacks, plugin_callbacks_init,
+		  sizeof plugin_callbacks_init);
+	}
+      else
+	{
+	  plugin_event_name
+	    = XRESIZEVEC (const char *, plugin_event_name, event_horizon);
+	  plugin_callbacks = XRESIZEVEC (struct callback_info *,
+					 plugin_callbacks, event_horizon);
+	}
+      /* All the pointers in the hash table will need to be updated.  */
+      htab_delete (event_tab);
+      event_tab = NULL;
+    }
+  else
+    *slot = &plugin_event_name[event_last];
+  plugin_event_name[event_last] = name;
+  return event_last++;
+}
+
 /* Called from the plugin's initialization code. Register a single callback.
    This function can be called multiple times.
 
@@ -300,7 +367,7 @@ register_plugin_info (const char* name, 
 
 void
 register_callback (const char *plugin_name,
-                   enum plugin_event event,
+		   int event,
                    plugin_callback_func callback,
                    void *user_data)
 {
@@ -322,6 +389,15 @@ register_callback (const char *plugin_na
 	gcc_assert (!callback);
         ggc_register_cache_tab ((const struct ggc_cache_tab*) user_data);
 	break;
+      case PLUGIN_EVENT_FIRST_DYNAMIC:
+      default:
+	if (event < PLUGIN_EVENT_FIRST_DYNAMIC || event >= event_last)
+	  {
+	    error ("Unknown callback event registered by plugin %s",
+		   plugin_name);
+	    return;
+	  }
+      /* Fall through.  */
       case PLUGIN_FINISH_TYPE:
       case PLUGIN_START_UNIT:
       case PLUGIN_FINISH_UNIT:
@@ -332,6 +408,15 @@ register_callback (const char *plugin_na
       case PLUGIN_ATTRIBUTES:
       case PLUGIN_PRAGMAS:
       case PLUGIN_FINISH:
+      case PLUGIN_ALL_PASSES_START:
+      case PLUGIN_ALL_PASSES_END:
+      case PLUGIN_ALL_IPA_PASSES_START:
+      case PLUGIN_ALL_IPA_PASSES_END:
+      case PLUGIN_OVERRIDE_GATE:
+      case PLUGIN_PASS_EXECUTION:
+      case PLUGIN_EARLY_GIMPLE_PASSES_START:
+      case PLUGIN_EARLY_GIMPLE_PASSES_END:
+      case PLUGIN_NEW_PASS:
         {
           struct callback_info *new_callback;
           if (!callback)
@@ -348,13 +433,25 @@ register_callback (const char *plugin_na
           plugin_callbacks[event] = new_callback;
         }
         break;
-      case PLUGIN_EVENT_LAST:
-      default:
-        error ("Unknown callback event registered by plugin %s",
-               plugin_name);
     }
 }
 
+int
+unregister_callback (const char *plugin_name, int event)
+{
+  struct callback_info *callback, **cbp;
+
+  if (event >= event_last)
+    return PLUGEVT_NO_SUCH_EVENT;
+
+  for (cbp = &plugin_callbacks[event]; (callback = *cbp); cbp = &callback->next)
+    if (strcmp (callback->plugin_name, plugin_name) == 0)
+      {
+	*cbp = callback->next;
+	return PLUGEVT_SUCCESS;
+      }
+  return PLUGEVT_NO_CALLBACK;
+}
 
 /* Called from inside GCC.  Invoke all plug-in callbacks registered with
    the specified event.
@@ -362,13 +459,20 @@ register_callback (const char *plugin_na
    EVENT    - the event identifier
    GCC_DATA - event-specific data provided by the compiler  */
 
-void
-invoke_plugin_callbacks (enum plugin_event event, void *gcc_data)
+int
+invoke_plugin_callbacks (int event, void *gcc_data)
 {
+  int retval = PLUGEVT_SUCCESS;
+
   timevar_push (TV_PLUGIN_RUN);
 
   switch (event)
     {
+      case PLUGIN_EVENT_FIRST_DYNAMIC:
+      default:
+	gcc_assert (event >= PLUGIN_EVENT_FIRST_DYNAMIC);
+	gcc_assert (event < event_last);
+      /* Fall through.  */
       case PLUGIN_FINISH_TYPE:
       case PLUGIN_START_UNIT:
       case PLUGIN_FINISH_UNIT:
@@ -379,24 +483,35 @@ invoke_plugin_callbacks (enum plugin_eve
       case PLUGIN_GGC_START:
       case PLUGIN_GGC_MARKING:
       case PLUGIN_GGC_END:
+      case PLUGIN_ALL_PASSES_START:
+      case PLUGIN_ALL_PASSES_END:
+      case PLUGIN_ALL_IPA_PASSES_START:
+      case PLUGIN_ALL_IPA_PASSES_END:
+      case PLUGIN_OVERRIDE_GATE:
+      case PLUGIN_PASS_EXECUTION:
+      case PLUGIN_EARLY_GIMPLE_PASSES_START:
+      case PLUGIN_EARLY_GIMPLE_PASSES_END:
+      case PLUGIN_NEW_PASS:
         {
           /* Iterate over every callback registered with this event and
              call it.  */
           struct callback_info *callback = plugin_callbacks[event];
+
+	  if (!callback)
+	    retval = PLUGEVT_NO_CALLBACK;
           for ( ; callback; callback = callback->next)
             (*callback->func) (gcc_data, callback->user_data);
         }
         break;
 
       case PLUGIN_PASS_MANAGER_SETUP:
-      case PLUGIN_EVENT_LAST:
       case PLUGIN_REGISTER_GGC_ROOTS:
       case PLUGIN_REGISTER_GGC_CACHES:
-      default:
         gcc_assert (false);
     }
 
   timevar_pop (TV_PLUGIN_RUN);
+  return retval;
 }
 
 #ifdef ENABLE_PLUGIN
@@ -621,7 +736,7 @@ plugins_active_p (void)
 {
   int event;
 
-  for (event = PLUGIN_PASS_MANAGER_SETUP; event < PLUGIN_EVENT_LAST; event++)
+  for (event = PLUGIN_PASS_MANAGER_SETUP; event < event_last; event++)
     if (plugin_callbacks[event])
       return true;
 
@@ -641,7 +756,7 @@ dump_active_plugins (FILE *file)
     return;
 
   fprintf (file, FMT_FOR_PLUGIN_EVENT " | %s\n", _("Event"), _("Plugins"));
-  for (event = PLUGIN_PASS_MANAGER_SETUP; event < PLUGIN_EVENT_LAST; event++)
+  for (event = PLUGIN_PASS_MANAGER_SETUP; event < event_last; event++)
     if (plugin_callbacks[event])
       {
 	struct callback_info *ci;
diff -drupN --exclude .svn gcc/gcc/plugin.def gcc-ici-3/gcc/plugin.def
--- gcc/gcc/plugin.def	1970-01-01 01:00:00.000000000 +0100
+++ gcc-ici-3/gcc/plugin.def	2009-12-01 13:45:58.662653796 +0000
@@ -0,0 +1,94 @@
+/* This file contains the definitions for plugin events in GCC.
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+/* To hook into pass manager.  */
+DEFEVENT (PLUGIN_PASS_MANAGER_SETUP)
+
+/* After finishing parsing a type.  */
+DEFEVENT (PLUGIN_FINISH_TYPE)
+
+/* Useful for summary processing.  */
+DEFEVENT (PLUGIN_FINISH_UNIT)
+
+/* Allows to see low level AST in C++ FE.  */
+DEFEVENT (PLUGIN_CXX_CP_PRE_GENERICIZE)
+
+/* Called before GCC exits.  */
+DEFEVENT (PLUGIN_FINISH)
+
+/* Information about the plugin. */
+DEFEVENT (PLUGIN_INFO)
+
+/* Called at start of GCC Garbage Collection. */
+DEFEVENT (PLUGIN_GGC_START)
+
+/* Extend the GGC marking. */
+DEFEVENT (PLUGIN_GGC_MARKING)
+
+/* Called at end of GGC. */
+DEFEVENT (PLUGIN_GGC_END)
+
+/* Register an extra GGC root table. */
+DEFEVENT (PLUGIN_REGISTER_GGC_ROOTS)
+
+/* Register an extra GGC cache table. */
+DEFEVENT (PLUGIN_REGISTER_GGC_CACHES)
+
+/* Called during attribute registration.  */
+DEFEVENT (PLUGIN_ATTRIBUTES)
+
+/* Called before processing a translation unit.  */
+DEFEVENT (PLUGIN_START_UNIT)
+
+/* Called during pragma registration.  */
+DEFEVENT (PLUGIN_PRAGMAS)
+
+/* Called before first pass from all_passes.  */
+DEFEVENT (PLUGIN_ALL_PASSES_START)
+
+/* Called after last pass from all_passes.  */
+DEFEVENT (PLUGIN_ALL_PASSES_END)
+
+/* Called before first ipa pass.  */
+DEFEVENT (PLUGIN_ALL_IPA_PASSES_START)
+
+/* Called after last ipa pass.  */
+DEFEVENT (PLUGIN_ALL_IPA_PASSES_END)
+
+/* Allows to override pass gate decision for current_pass.  */
+DEFEVENT (PLUGIN_OVERRIDE_GATE)
+
+/* Called before executing a pass.  */
+DEFEVENT (PLUGIN_PASS_EXECUTION)
+
+/* Called before executing subpasses of a GIMPLE_PASS in
+   execute_ipa_pass_list.  */
+DEFEVENT (PLUGIN_EARLY_GIMPLE_PASSES_START)
+
+/* Called after executing subpasses of a GIMPLE_PASS in
+   execute_ipa_pass_list.  */
+DEFEVENT (PLUGIN_EARLY_GIMPLE_PASSES_END)
+
+/* Called when a pass is first instantiated.  */
+DEFEVENT (PLUGIN_NEW_PASS)
+
+/* After the hard-coded events above, plugins can dynamically allocate events
+   at run time.
+   PLUGIN_EVENT_FIRST_DYNAMIC only appears as last enum element.  */
diff -drupN --exclude .svn gcc/gcc/plugin.h gcc-ici-3/gcc/plugin.h
--- gcc/gcc/plugin.h	2009-11-04 14:49:32.602125905 +0000
+++ gcc-ici-3/gcc/plugin.h	2009-12-01 13:41:08.259654594 +0000
@@ -26,7 +26,7 @@ struct attribute_spec;
 
 extern void add_new_plugin (const char *);
 extern void parse_plugin_arg_opt (const char *);
-extern void invoke_plugin_callbacks (enum plugin_event, void *);
+extern int invoke_plugin_callbacks (int, void *);
 extern void initialize_plugins (void);
 extern bool plugins_active_p (void);
 extern void dump_active_plugins (FILE *);
diff -drupN --exclude .svn gcc/gcc/tree-optimize.c gcc-ici-3/gcc/tree-optimize.c
--- gcc/gcc/tree-optimize.c	2009-11-29 17:42:49.047772795 +0000
+++ gcc-ici-3/gcc/tree-optimize.c	2009-12-01 13:57:08.926528800 +0000
@@ -49,6 +49,7 @@ along with GCC; see the file COPYING3.  
 #include "graph.h"
 #include "cfgloop.h"
 #include "except.h"
+#include "plugin.h"
 
 
 /* Gate: execute, or not, all of the non-trivial optimizations.  */
@@ -405,8 +406,15 @@ tree_rest_of_compilation (tree fndecl)
   execute_all_ipa_transforms ();
 
   /* Perform all tree transforms and optimizations.  */
+
+  /* Signal the start of passes.  */
+  invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL);
+
   execute_pass_list (all_passes);
 
+  /* Signal the end of passes.  */
+  invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL);
+
   bitmap_obstack_release (&reg_obstack);
 
   /* Release the default bitmap obstack.  */
diff -drupN --exclude .svn gcc/gcc/tree-pass.h gcc-ici-3/gcc/tree-pass.h
--- gcc/gcc/tree-pass.h	2009-11-29 17:42:48.639772819 +0000
+++ gcc-ici-3/gcc/tree-pass.h	2009-12-01 13:13:57.689528409 +0000
@@ -565,12 +565,16 @@ extern struct opt_pass *all_passes, *all
 extern struct opt_pass *current_pass;
 
 extern struct opt_pass * get_pass_for_id (int);
+extern bool execute_one_pass (struct opt_pass *);
 extern void execute_pass_list (struct opt_pass *);
 extern void execute_ipa_pass_list (struct opt_pass *);
 extern void execute_ipa_summary_passes (struct ipa_opt_pass_d *);
 extern void execute_all_ipa_transforms (void);
 extern void execute_all_ipa_stmt_fixups (struct cgraph_node *, gimple *);
+extern bool pass_init_dump_file (struct opt_pass *);
+extern void pass_fini_dump_file (struct opt_pass *);
 
+extern const char *get_current_pass_name (void);
 extern void print_current_pass (FILE *);
 extern void debug_pass (void);
 extern void ipa_write_summaries (void);
@@ -590,4 +594,7 @@ extern void register_pass (struct regist
    directly in jump threading, and avoid peeling them next time.  */
 extern bool first_pass_instance;
 
+/* Declare for plugins.  */
+extern void do_per_function_toporder (void (*) (void *), void *);
+
 #endif /* GCC_TREE_PASS_H */

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

* Re: Fwd: RFA: plugin events for ICI
  2009-12-01 14:39           ` Joern Rennecke
@ 2009-12-01 14:52             ` Richard Guenther
  2009-12-01 14:55             ` Basile STARYNKEVITCH
  2009-12-01 15:57             ` Diego Novillo
  2 siblings, 0 replies; 13+ messages in thread
From: Richard Guenther @ 2009-12-01 14:52 UTC (permalink / raw)
  To: Joern Rennecke
  Cc: Basile STARYNKEVITCH, ctuning-discussions, gcc-patches,
	Grigori Fursin, Grigori Fursin, Zbigniew Chamski,
	Ian Lance Taylor, Albert Cohen, Yuri Kashnikoff, Yuanjie Huang,
	Liang Peng, dorit, Mircea Namolaru, Diego Novillo, Paolo Bonzini

On Tue, Dec 1, 2009 at 3:29 PM, Joern Rennecke <amylaar@spamcop.net> wrote:
> Quoting Richard Guenther <richard.guenther@gmail.com>:
>>
>> The rest looks reasonable, so if you can re-submit without the
>> above changes...?
>
> Please find attached the reduced patch that I am currently testing.

@@ -1092,7 +1096,8 @@ static GTY ((length ("nnodes"))) struct
    function CALLBACK for every function in the call graph.  Otherwise,
    call CALLBACK on the current function.  */

-static void
+/* This function is global so that plugins can use it.  */

please merge this comments with the overall function comments.

+int
+unregister_callback (const char *plugin_name, int event)

this function needs a comment.

The middle-end changes are ok with the above changes.  Please
get approval from plugin maintainers for the changes therein
and from a build-system maintainer for the gcc/Makefile.in
change.

Thanks,
Richard.

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

* Re: Fwd: RFA: plugin events for ICI
  2009-12-01 14:39           ` Joern Rennecke
  2009-12-01 14:52             ` Richard Guenther
@ 2009-12-01 14:55             ` Basile STARYNKEVITCH
  2009-12-01 15:57             ` Diego Novillo
  2 siblings, 0 replies; 13+ messages in thread
From: Basile STARYNKEVITCH @ 2009-12-01 14:55 UTC (permalink / raw)
  To: ctuning-discussions
  Cc: Richard Guenther, gcc-patches, Grigori Fursin, Grigori Fursin,
	Zbigniew Chamski, Ian Lance Taylor, Albert Cohen,
	Yuri Kashnikoff, Yuanjie Huang, Liang Peng, dorit,
	Mircea Namolaru, Diego Novillo, Rafael Espindola

Joern Rennecke wrote:
> Quoting Richard Guenther <richard.guenther@gmail.com>:
>> The rest looks reasonable, so if you can re-submit without the
>> above changes...?
> 
> Please find attached the reduced patch that I am currently testing.


I am not authorised to approve the patch, but I find it nice, in particular from the plugin point of view, and hope that 
some nice plugin or global reviewer (Rafael Espindola, Diego Novillo?) could approve it.

Thanks.

-- 
Basile STARYNKEVITCH         http://starynkevitch.net/Basile/
email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359
8, rue de la Faiencerie, 92340 Bourg La Reine, France
*** opinions {are only mines, sont seulement les miennes} ***

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

* Re: Fwd: RFA: plugin events for ICI
  2009-12-01 14:39           ` Joern Rennecke
  2009-12-01 14:52             ` Richard Guenther
  2009-12-01 14:55             ` Basile STARYNKEVITCH
@ 2009-12-01 15:57             ` Diego Novillo
  2009-12-01 17:25               ` Joern Rennecke
  2 siblings, 1 reply; 13+ messages in thread
From: Diego Novillo @ 2009-12-01 15:57 UTC (permalink / raw)
  To: Joern Rennecke
  Cc: Richard Guenther, Basile STARYNKEVITCH, ctuning-discussions,
	gcc-patches, Grigori Fursin, Grigori Fursin, Zbigniew Chamski,
	Ian Lance Taylor, Albert Cohen, Yuri Kashnikoff, Yuanjie Huang,
	Liang Peng, dorit, Mircea Namolaru

On Tue, Dec 1, 2009 at 09:29, Joern Rennecke <amylaar@spamcop.net> wrote:

> +
> +@section Controlling which passes are being run
> +
> +After the orginary gate function for a pass is called, the result of

s/orginary/original/

> +the gate test - the gate status - stored as an integer.

I can't parse this.

> +Then the event @code{PLUGIN_OVERRIDE_GATE} is invoked, with a pointer
> +to the gate status in the @code{gcc_data} parameter to the callback function.
> +A nonzero value of the gate status means that the pass is to be executed.
> +You can both read and write the gate status via the passed pointer.
> +
> +
> +@section Keeping track of available passes
> +
> +When your plugin is loaded, yt the moment you can inspect the various
> +pass lists to determine what passes are available.

I'm not sure what you are trying to say here.  Did you meant 'at'
instead of 'yt'?  Still, this is hard to parse.

> +/* Number of event ids / names registered so far.  */
> +
> +extern int event_last;

Why is this a global?  I'd rather have it as a static variable
that is updated every time an event is registered.

>  /* The number of entries in the table.  */
> -
> -static size_t num_compiler_params;
> +/* This symbol is global for the benefit of plugins.  */
> +size_t num_compiler_params;

No.  Just add a function get_num_compiler_params() that returns
its value.  Let's not keep adding global state, if we can avoid
it.

> +  gate_status = (pass->gate == NULL) ? true : pass->gate();
> +
> +  /* Override gate with plugin.  */
> +  invoke_plugin_callbacks (PLUGIN_OVERRIDE_GATE, &gate_status);
> +
> +  if (!gate_status) {

Brace on the next line.

> +/* Look up the event id for NAME.  If the name is not found, return -1
> +   if INSERT is NO_INSERT.  */
> +int

Blank line after comment.

>
> +int
> +unregister_callback (const char *plugin_name, int event)

Needs documentation.

> -void
> -invoke_plugin_callbacks (enum plugin_event event, void *gcc_data)
> +int
> +invoke_plugin_callbacks (int event, void *gcc_data)

Needs documentation on the value being returned.


The rest looks OK.


Diego.

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

* Re: Fwd: RFA: plugin events for ICI
  2009-12-01 15:57             ` Diego Novillo
@ 2009-12-01 17:25               ` Joern Rennecke
  2009-12-01 18:05                 ` Diego Novillo
  0 siblings, 1 reply; 13+ messages in thread
From: Joern Rennecke @ 2009-12-01 17:25 UTC (permalink / raw)
  To: Diego Novillo
  Cc: Richard Guenther, Basile STARYNKEVITCH, ctuning-discussions,
	gcc-patches, Grigori Fursin, Grigori Fursin, Zbigniew Chamski,
	Ian Lance Taylor, Albert Cohen, Yuri Kashnikoff, Yuanjie Huang,
	Liang Peng, dorit, Mircea Namolaru

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

Quoting Diego Novillo <dnovillo@google.com>:
>> +the gate test - the gate status - stored as an integer.
>
> I can't parse this.

New text:

After the original gate function for a pass is called, its result
- the gate status - is stored as an integer.
Then the event @code{PLUGIN_OVERRIDE_GATE} is invoked, with a pointer
to the gate status in the @code{gcc_data} parameter to the callback function.
A nonzero value of the gate status means that the pass is to be executed.
You can both read and write the gate status via the passed pointer.

>> +When your plugin is loaded, yt the moment you can inspect the various
>> +pass lists to determine what passes are available.
>
> I'm not sure what you are trying to say here.  Did you meant 'at'
> instead of 'yt'?  Still, this is hard to parse.

Yes, less is more here:

When your plugin is loaded, you can inspect the various
pass lists to determine what passes are available.  However, other
plugins might add new passes.  Also, future changes to GCC might cause
generic passes to be added after plugin loading.
When a pass is first added to one of the pass lists, the event
@code{PLUGIN_NEW_PASS} is invoked, with the callback parameter
@code{gcc_data} pointing to the new pass.

>> +/* Number of event ids / names registered so far.  */
>> +
>> +extern int event_last;
>
> Why is this a global?  I'd rather have it as a static variable
> that is updated every time an event is registered.

Changed to file static + query function.

I am currently testing the attached patch locally & on gcc14.

[-- Attachment #2: gcc-ici-patch-20091201-4 --]
[-- Type: text/plain, Size: 37305 bytes --]

2009-12-01  Grigori Fursin  <grigori.fursin@inria.fr>
	    Joern Rennecke  <amylaar@spamcop.net>

	* cgraphunit.c (plugin.h): Include.
	(ipa_passes): Invoke PLUGIN_ALL_IPA_PASSES_START /
	PLUGIN_ALL_IPA_PASSES_END at start / end of processing.
	* gcc-plugin.h (highlev-plugin-common.h, hashtab.h): Include.
	(enum plugin_event): Define by including plugin.def.
	Last enumerator is now called PLUGIN_EVENT_FIRST_DYNAMIC.
	(plugin_event_name): Change type to const char **.
	(get_event_last, get_named_event_id, unregister_callback): Declare.
	(register_callback): Change type of event argument to int.
	(highlev-plugin-common.h): New file.
	* Makefile.in (GCC_PLUGIN_H): Add highlev-plugin-common.h and
	$(HASHTAB_H)
	(tree-optimize.o passes.o): Depend on $(PLUGIN_H).
	(PLUGIN_HEADERS): Add opts.h, $(PARAMS_H) and plugin.def.
	(s-header-vars): New rule.
	(install-plugin): Depend on s-header-vars.  Install b-header-vars.
	* params.c (get_num_compiler_params): New function.
	* params.h (get_num_compiler_params): Declare.
	* passes.c (plugin.h): Include.
	(make_pass_instance): Invoke PLUGIN_NEW_PASS.
	(do_per_function_toporder, pass_init_dump_file): No longer static.
	(pass_fini_dump_file): Likewise.
	(execute_one_pass): Likewise.  Invoke PLUGIN_OVERRIDE_GATE and
	PLUGIN_PASS_EXECUTION.
	(execute_ipa_pass_list): Invoke PLUGIN_EARLY_GIMPLE_PASSES_START and
	PLUGIN_EARLY_GIMPLE_PASSES_END.
	* plugin.c (plugin_event_name_init): New array, defined by
	including plugin.def.
	(FMT_FOR_PLUGIN_EVENT): Update.
	(plugin_event_name): Change type to const char ** and initialize
	to plugin_event_name_init.
	(event_tab, event_last, event_horizon): New variable.
	(get_event_last): New function.
	(plugin_callbacks_init): New array.
	(plugin_callbacks: Change type to struct callback_info **.
	Initialize to plugin_callbacks_init.
	(htab_event_eq, get_named_event_id, unregister_callback): New function.
	(invoke_plugin_va_callbacks): Likewise.
	(register_callback): Change type of event argument to int.
	Handle new events.  Allow dynamic events.
	(invoke_plugin_callbacks): Likewise.  Return success status.
	(plugins_active_p): Allow dynamic callbacks.
	* plugin.def: New file.
	* plugin.h (invoke_plugin_callbacks): Update prototype.
	(invoke_plugin_va_callbacks): Declare.
	* tree-optimize.c (plugin.h): Include.
	(tree_rest_of_compilation): Invoke PLUGIN_ALL_PASSES_START and
	PLUGIN_ALL_PASSES_END.
	* tree-pass.h (execute_one_pass, pass_init_dump_file): Declare.
	(pass_fini_dump_file, do_per_function_toporder): Likewise.
	* doc/plugin.texi: Document new event types.

diff -drupN --exclude .svn gcc/gcc/cgraphunit.c gcc-ici-4/gcc/cgraphunit.c
--- gcc/gcc/cgraphunit.c	2009-11-29 17:42:48.662772536 +0000
+++ gcc-ici-4/gcc/cgraphunit.c	2009-12-01 13:54:02.833653857 +0000
@@ -135,6 +135,7 @@ along with GCC; see the file COPYING3.  
 #include "tree-dump.h"
 #include "output.h"
 #include "coverage.h"
+#include "plugin.h"
 
 static void cgraph_expand_all_functions (void);
 static void cgraph_mark_functions_to_output (void);
@@ -1712,6 +1713,8 @@ ipa_passes (void)
   gimple_register_cfg_hooks ();
   bitmap_obstack_initialize (NULL);
 
+  invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_START, NULL);
+
   if (!in_lto_p)
     execute_ipa_pass_list (all_small_ipa_passes);
 
@@ -1730,7 +1733,8 @@ ipa_passes (void)
       current_function_decl = NULL;
       cgraph_process_new_functions ();
 
-      execute_ipa_summary_passes ((struct ipa_opt_pass_d *) all_regular_ipa_passes);
+      execute_ipa_summary_passes
+	((struct ipa_opt_pass_d *) all_regular_ipa_passes);
     }
   execute_ipa_summary_passes ((struct ipa_opt_pass_d *) all_lto_gen_passes);
 
@@ -1739,6 +1743,7 @@ ipa_passes (void)
 
   if (!flag_ltrans)
     execute_ipa_pass_list (all_regular_ipa_passes);
+  invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_END, NULL);
 
   bitmap_obstack_release (NULL);
 }
diff -drupN --exclude .svn gcc/gcc/doc/plugins.texi gcc-ici-4/gcc/doc/plugins.texi
--- gcc/gcc/doc/plugins.texi	2009-11-29 17:42:32.565901921 +0000
+++ gcc-ici-4/gcc/doc/plugins.texi	2009-12-01 16:31:15.979654130 +0000
@@ -156,18 +156,42 @@ enum plugin_event
   PLUGIN_ATTRIBUTES,            /* Called during attribute registration */
   PLUGIN_START_UNIT,            /* Called before processing a translation unit.  */
   PLUGIN_PRAGMAS,	        /* Called during pragma registration. */
-  PLUGIN_EVENT_LAST             /* Dummy event used for indexing callback
+  /* Called before first pass from all_passes.  */
+  PLUGIN_ALL_PASSES_START,
+  /* Called after last pass from all_passes.  */
+  PLUGIN_ALL_PASSES_END,
+  /* Called before first ipa pass.  */
+  PLUGIN_ALL_IPA_PASSES_START,
+  /* Called after last ipa pass.  */
+  PLUGIN_ALL_IPA_PASSES_END,
+  /* Allows to override pass gate decision for current_pass.  */
+  PLUGIN_OVERRIDE_GATE,
+  /* Called before executing a pass.  */
+  PLUGIN_PASS_EXECUTION,
+  /* Called before executing subpasses of a GIMPLE_PASS in
+     execute_ipa_pass_list.  */
+  PLUGIN_EARLY_GIMPLE_PASSES_START,
+  /* Called after executing subpasses of a GIMPLE_PASS in
+     execute_ipa_pass_list.  */
+  PLUGIN_EARLY_GIMPLE_PASSES_END,
+  /* Called when a pass is first instantiated.  */
+  PLUGIN_NEW_PASS,
+
+  PLUGIN_EVENT_FIRST_DYNAMIC    /* Dummy event used for indexing callback
                                    array.  */
 @};
 @end smallexample
 
+In addition, plugins can also look up the enumerator of a named event,
+and / or generate new events dynamically, by calling the function
+@code{get_named_event_id}.
 
 To register a callback, the plugin calls @code{register_callback} with
 the arguments:
 
 @itemize
 @item @code{char *name}: Plugin name.
-@item @code{enum plugin_event event}: The event code.
+@item @code{int event}: The event code.
 @item @code{plugin_callback_func callback}: The function that handles @code{event}.
 @item @code{void *user_data}: Pointer to plugin-specific data.
 @end itemize
@@ -337,6 +361,41 @@ It is suggested to pass @code{"GCCPLUGIN
 your plugin) as the ``space'' argument of your pragma. 
 
 
+@section Recording information about pass execution
+
+The event PLUGIN_PASS_EXECUTION passes the pointer to the executed pass
+(the same as current_pass) as @code{gcc_data} to the callback.  You can also
+inspect cfun to find out about which function this pass is executed for.
+Note that this event will only be invoked if the gate check (if
+applicable, modified by PLUGIN_OVERRIDE_GATE) succeeds.
+You can use other hooks, like @code{PLUGIN_ALL_PASSES_START},
+@code{PLUGIN_ALL_PASSES_END}, @code{PLUGIN_ALL_IPA_PASSES_START},
+@code{PLUGIN_ALL_IPA_PASSES_END}, @code{PLUGIN_EARLY_GIMPLE_PASSES_START},
+and/or @code{PLUGIN_EARLY_GIMPLE_PASSES_END} to manipulate global state
+in your plugin(s) in order to get context for the pass execution.
+
+
+@section Controlling which passes are being run
+
+After the original gate function for a pass is called, its result
+- the gate status - is stored as an integer.
+Then the event @code{PLUGIN_OVERRIDE_GATE} is invoked, with a pointer
+to the gate status in the @code{gcc_data} parameter to the callback function.
+A nonzero value of the gate status means that the pass is to be executed.
+You can both read and write the gate status via the passed pointer.
+
+
+@section Keeping track of available passes
+
+When your plugin is loaded, you can inspect the various
+pass lists to determine what passes are available.  However, other
+plugins might add new passes.  Also, future changes to GCC might cause
+generic passes to be added after plugin loading.
+When a pass is first added to one of the pass lists, the event
+@code{PLUGIN_NEW_PASS} is invoked, with the callback parameter
+@code{gcc_data} pointing to the new pass.
+
+
 @section Building GCC plugins
 
 If plugins are enabled, GCC installs the headers needed to build a
diff -drupN --exclude .svn gcc/gcc/gcc-plugin.h gcc-ici-4/gcc/gcc-plugin.h
--- gcc/gcc/gcc-plugin.h	2009-11-08 21:11:04.273376423 +0000
+++ gcc-ici-4/gcc/gcc-plugin.h	2009-12-01 17:01:11.379653175 +0000
@@ -26,29 +26,19 @@ along with GCC; see the file COPYING3.  
 
 #include "config.h"
 #include "system.h"
+#include "highlev-plugin-common.h"
+#include "hashtab.h"
 
-/* Event names.  Keep in sync with plugin_event_name[].  */
+/* Event names.  */
 enum plugin_event
 {
-  PLUGIN_PASS_MANAGER_SETUP,    /* To hook into pass manager.  */
-  PLUGIN_FINISH_TYPE,           /* After finishing parsing a type.  */
-  PLUGIN_FINISH_UNIT,           /* Useful for summary processing.  */
-  PLUGIN_CXX_CP_PRE_GENERICIZE, /* Allows to see low level AST in C++ FE.  */
-  PLUGIN_FINISH,                /* Called before GCC exits.  */
-  PLUGIN_INFO,                  /* Information about the plugin. */
-  PLUGIN_GGC_START,		/* Called at start of GCC Garbage Collection. */
-  PLUGIN_GGC_MARKING,		/* Extend the GGC marking. */
-  PLUGIN_GGC_END,		/* Called at end of GGC. */
-  PLUGIN_REGISTER_GGC_ROOTS,	/* Register an extra GGC root table. */
-  PLUGIN_REGISTER_GGC_CACHES,	/* Register an extra GGC cache table. */
-  PLUGIN_ATTRIBUTES,            /* Called during attribute registration.  */
-  PLUGIN_START_UNIT,            /* Called before processing a translation unit.  */
-  PLUGIN_PRAGMAS,	        /* Called during pragma registration.  */
-  PLUGIN_EVENT_LAST             /* Dummy event used for indexing callback
-                                   array.  */
+# define DEFEVENT(NAME) NAME,
+# include "plugin.def"
+# undef DEFEVENT
+  PLUGIN_EVENT_FIRST_DYNAMIC
 };
 
-extern const char *plugin_event_name[];
+extern const char **plugin_event_name;
 
 struct plugin_argument
 {
@@ -127,14 +117,22 @@ typedef void (*plugin_callback_func) (vo
    USER_DATA   - plugin-provided data.
 */
 
+/* Number of event ids / names registered so far.  */
+
+extern int get_event_last (void);
+
+int get_named_event_id (const char *name, enum insert_option insert);
+
 /* This is also called without a callback routine for the
    PLUGIN_PASS_MANAGER_SETUP, PLUGIN_INFO, PLUGIN_REGISTER_GGC_ROOTS and
    PLUGIN_REGISTER_GGC_CACHES pseudo-events, with a specific user_data.
   */
 
 extern void register_callback (const char *plugin_name,
-                               enum plugin_event event,
+			       int event,
                                plugin_callback_func callback,
                                void *user_data);
 
+extern int unregister_callback (const char *plugin_name, int event);
+
 #endif /* GCC_PLUGIN_H */
diff -drupN --exclude .svn gcc/gcc/highlev-plugin-common.h gcc-ici-4/gcc/highlev-plugin-common.h
--- gcc/gcc/highlev-plugin-common.h	1970-01-01 01:00:00.000000000 +0100
+++ gcc-ici-4/gcc/highlev-plugin-common.h	2009-12-01 13:49:26.129669583 +0000
@@ -0,0 +1,33 @@
+/* Interface for high-level plugins in GCC - Parts common between GCC,
+   ICI and high-level plugins.
+
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+   Contributed by INRIA.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef HIGHLEV_PLUGIN_COMMON_H
+#define HIGHLEV_PLUGIN_COMMON_H
+
+/* Return codes for invoke_plugin_callbacks / call_plugin_event .  */
+#define PLUGEVT_SUCCESS         0
+#define PLUGEVT_NO_EVENTS       1
+#define PLUGEVT_NO_SUCH_EVENT   2
+#define PLUGEVT_NO_CALLBACK     3
+
+#endif /* HIGHLEV_PLUGIN_COMMON_H */
diff -drupN --exclude .svn gcc/gcc/Makefile.in gcc-ici-4/gcc/Makefile.in
--- gcc/gcc/Makefile.in	2009-11-29 17:42:49.155526086 +0000
+++ gcc-ici-4/gcc/Makefile.in	2009-12-01 14:08:00.428897667 +0000
@@ -943,7 +943,8 @@ TREE_VECTORIZER_H = tree-vectorizer.h $(
 IPA_PROP_H = ipa-prop.h $(TREE_H) vec.h $(CGRAPH_H)
 GSTAB_H = gstab.h stab.def
 BITMAP_H = bitmap.h $(HASHTAB_H) statistics.h
-GCC_PLUGIN_H = gcc-plugin.h $(CONFIG_H) $(SYSTEM_H)
+GCC_PLUGIN_H = gcc-plugin.h highlev-plugin-common.h $(CONFIG_H) $(SYSTEM_H) \
+		$(HASHTAB_H)
 PLUGIN_H = plugin.h $(GCC_PLUGIN_H)
 PLUGIN_VERSION_H = plugin-version.h configargs.h
 
@@ -2503,8 +2504,9 @@ tree-ssa-reassoc.o : tree-ssa-reassoc.c 
    langhooks.h alloc-pool.h pointer-set.h $(CFGLOOP_H)
 tree-optimize.o : tree-optimize.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
    $(RTL_H) $(TREE_H) $(TM_P_H) hard-reg-set.h $(EXPR_H) $(GGC_H) output.h \
-   $(DIAGNOSTIC_H) $(BASIC_BLOCK_H) $(FLAGS_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
-   $(TREE_DUMP_H) $(TOPLEV_H) $(FUNCTION_H) langhooks.h $(FLAGS_H) $(CGRAPH_H) \
+   $(DIAGNOSTIC_H) $(BASIC_BLOCK_H) $(FLAGS_H) $(TIMEVAR_H) $(TM_H) \
+   coretypes.h $(TREE_DUMP_H) $(TOPLEV_H) $(FUNCTION_H) langhooks.h \
+   $(FLAGS_H) $(CGRAPH_H) $(PLUGIN_H) \
    $(TREE_INLINE_H) tree-mudflap.h $(GGC_H) graph.h $(CGRAPH_H) \
    $(TREE_PASS_H) $(CFGLOOP_H) $(EXCEPT_H)
 
@@ -2725,7 +2727,8 @@ passes.o : passes.c $(CONFIG_H) $(SYSTEM
    langhooks.h insn-flags.h $(CFGLAYOUT_H) $(REAL_H) $(CFGLOOP_H) \
    hosthooks.h $(CGRAPH_H) $(COVERAGE_H) $(TREE_PASS_H) $(TREE_DUMP_H) \
    $(GGC_H) $(INTEGRATE_H) $(CPPLIB_H) opts.h $(TREE_FLOW_H) $(TREE_INLINE_H) \
-   gt-passes.h $(DF_H) $(PREDICT_H) $(LTO_HEADER_H) $(LTO_SECTION_OUT_H)
+   gt-passes.h $(DF_H) $(PREDICT_H) $(LTO_HEADER_H) $(LTO_SECTION_OUT_H) \
+   $(PLUGIN_H)
 
 plugin.o : plugin.c $(PLUGIN_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h \
    $(TOPLEV_H) $(TREE_H) $(TREE_PASS_H) intl.h $(PLUGIN_VERSION_H) $(GGC_H)
@@ -4264,7 +4267,7 @@ installdirs:
 
 PLUGIN_HEADERS = $(TREE_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
   $(TOPLEV_H) $(BASIC_BLOCK_H) $(GIMPLE_H) $(TREE_PASS_H) $(GCC_PLUGIN_H) \
-  $(GGC_H) $(TREE_DUMP_H) $(PRETTY_PRINT_H) \
+  $(GGC_H) $(TREE_DUMP_H) $(PRETTY_PRINT_H) opts.h $(PARAMS_H) plugin.def \
   $(tm_file_list) $(tm_include_list) $(tm_p_file_list) $(tm_p_include_list) \
   $(host_xm_file_list) $(host_xm_include_list) $(xm_include_list) \
   intl.h $(PLUGIN_VERSION_H) $(DIAGNOSTIC_H) $(C_COMMON_H) $(C_PRETTY_PRINT_H) \
@@ -4273,8 +4276,15 @@ PLUGIN_HEADERS = $(TREE_H) $(CONFIG_H) $
   $(C_PRAGMA_H)  $(CPPLIB_H)  $(FUNCTION_H) \
   cppdefault.h flags.h $(MD5_H) params.def params.h prefix.h tree-inline.h
 
+# generate the 'build fragment' b-header-vars
+s-header-vars: Makefile
+	rm -f tmp-header-vars
+	$(foreach header_var,$(shell sed < Makefile -e 's/^\([A-Z0-9_]*_H\)[      ]*=.*/\1/p' -e d),echo $(header_var)=$(shell echo $($(header_var):$(srcdir)/%=.../%) | sed -e 's~\.\.\./config/~config/~' -e 's~\.\.\..*/~~') >> tmp-header-vars;) \
+	$(SHELL) $(srcdir)/../move-if-change tmp-header-vars b-header-vars
+	$(STAMP) s-header-vars
+
 # Install the headers needed to build a plugin.
-install-plugin: installdirs lang.install-plugin
+install-plugin: installdirs lang.install-plugin s-header-vars
 # We keep the directory structure for files in config and .def files. All
 # other files are flattened to a single directory.
 	$(mkinstalldirs) $(DESTDIR)$(plugin_includedir)
@@ -4298,6 +4308,7 @@ install-plugin: installdirs lang.install
 	  $(mkinstalldirs) $(DESTDIR)$$dir; \
 	  $(INSTALL_DATA) $$path $(DESTDIR)$$dest; \
 	done
+	$(INSTALL_DATA) b-header-vars $(DESTDIR)$(plugin_includedir)/b-header-vars
 
 # Install the compiler executables built during cross compilation.
 install-common: native lang.install-common installdirs
diff -drupN --exclude .svn gcc/gcc/params.c gcc-ici-4/gcc/params.c
--- gcc/gcc/params.c	2009-11-04 14:49:32.468125810 +0000
+++ gcc-ici-4/gcc/params.c	2009-12-01 16:44:30.849653237 +0000
@@ -32,7 +32,6 @@ along with GCC; see the file COPYING3.  
 param_info *compiler_params;
 
 /* The number of entries in the table.  */
-
 static size_t num_compiler_params;
 
 /* Add the N PARAMS to the current list of compiler parameters.  */
@@ -85,3 +84,12 @@ set_param_value (const char *name, int v
   /* If we didn't find this parameter, issue an error message.  */
   error ("invalid parameter %qs", name);
 }
+
+/* Return the current value of num_compiler_params, for the benefit of
+   plugins that use parameters as features.  */
+
+size_t
+get_num_compiler_params (void)
+{
+  return num_compiler_params;
+}
diff -drupN --exclude .svn gcc/gcc/params.h gcc-ici-4/gcc/params.h
--- gcc/gcc/params.h	2009-11-29 17:42:48.652772589 +0000
+++ gcc-ici-4/gcc/params.h	2009-12-01 16:44:50.248653402 +0000
@@ -65,6 +65,9 @@ typedef struct param_info
 
 extern param_info *compiler_params;
 
+/* Returns the number of entries in the table, for the use by plugins.  */
+extern size_t get_num_compiler_params (void);
+
 /* Add the N PARAMS to the current list of compiler parameters.  */
 
 extern void add_params (const param_info params[], size_t n);
diff -drupN --exclude .svn gcc/gcc/passes.c gcc-ici-4/gcc/passes.c
--- gcc/gcc/passes.c	2009-11-29 17:42:49.163525359 +0000
+++ gcc-ici-4/gcc/passes.c	2009-12-01 16:43:31.059530137 +0000
@@ -85,6 +85,7 @@ along with GCC; see the file COPYING3.  
 #include "df.h"
 #include "predict.h"
 #include "lto-streamer.h"
+#include "plugin.h"
 
 #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
 #include "dwarf2out.h"
@@ -104,7 +105,8 @@ along with GCC; see the file COPYING3.  
 #endif
 
 /* This is used for debugging.  It allows the current pass to printed
-   from anywhere in compilation.  */
+   from anywhere in compilation.
+   The variable current_pass is also used for statistics and plugins.  */
 struct opt_pass *current_pass;
 
 /* Call from anywhere to find out what pass this is.  Useful for
@@ -479,6 +481,8 @@ make_pass_instance (struct opt_pass *pas
     {
       pass->todo_flags_start |= TODO_mark_first_instance;
       pass->static_pass_number = -1;
+
+      invoke_plugin_callbacks (PLUGIN_NEW_PASS, pass);
     }
   return pass;
 }
@@ -1090,9 +1094,9 @@ static GTY ((length ("nnodes"))) struct 
 
 /* If we are in IPA mode (i.e., current_function_decl is NULL), call
    function CALLBACK for every function in the call graph.  Otherwise,
-   call CALLBACK on the current function.  */
-
-static void
+   call CALLBACK on the current function.
+   This function is global so that plugins can use it.  */
+void
 do_per_function_toporder (void (*callback) (void *data), void *data)
 {
   int i;
@@ -1317,8 +1321,9 @@ verify_curr_properties (void *data)
 #endif
 
 /* Initialize pass dump file.  */
+/* This is non-static so that the plugins can use it.  */
 
-static bool
+bool
 pass_init_dump_file (struct opt_pass *pass)
 {
   /* If a dump file name is present, open it if enabled.  */
@@ -1347,8 +1352,9 @@ pass_init_dump_file (struct opt_pass *pa
 }
 
 /* Flush PASS dump file.  */
+/* This is non-static so that plugins can use it.  */
 
-static void
+void
 pass_fini_dump_file (struct opt_pass *pass)
 {
   /* Flush and close dump file.  */
@@ -1476,12 +1482,14 @@ execute_all_ipa_transforms (void)
 
 /* Execute PASS. */
 
-static bool
+bool
 execute_one_pass (struct opt_pass *pass)
 {
   bool initializing_dump;
   unsigned int todo_after = 0;
 
+  bool gate_status;
+
   /* IPA passes are executed on whole program, so cfun should be NULL.
      Other passes need function context set.  */
   if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS)
@@ -1491,9 +1499,22 @@ execute_one_pass (struct opt_pass *pass)
 
   current_pass = pass;
 
-  /* See if we're supposed to run this pass.  */
-  if (pass->gate && !pass->gate ())
-    return false;
+  /* Check whether gate check should be avoided.
+     User controls the value of the gate through the parameter "gate_status". */
+  gate_status = (pass->gate == NULL) ? true : pass->gate();
+
+  /* Override gate with plugin.  */
+  invoke_plugin_callbacks (PLUGIN_OVERRIDE_GATE, &gate_status);
+
+  if (!gate_status)
+    {
+      current_pass = NULL;
+      return false;
+    }
+
+  /* Pass execution event trigger: useful to identify passes being
+     executed.  */
+  invoke_plugin_callbacks (PLUGIN_PASS_EXECUTION, pass);
 
   if (!quiet_flag && !cfun)
     fprintf (stderr, " <%s>", pass->name ? pass->name : "");
@@ -1756,8 +1777,12 @@ execute_ipa_pass_list (struct opt_pass *
       if (execute_one_pass (pass) && pass->sub)
 	{
 	  if (pass->sub->type == GIMPLE_PASS)
-	    do_per_function_toporder ((void (*)(void *))execute_pass_list,
-				      pass->sub);
+	    {
+	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL);
+	      do_per_function_toporder ((void (*)(void *))execute_pass_list,
+					pass->sub);
+	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL);
+	    }
 	  else if (pass->sub->type == SIMPLE_IPA_PASS
 		   || pass->sub->type == IPA_PASS)
 	    execute_ipa_pass_list (pass->sub);
diff -drupN --exclude .svn gcc/gcc/plugin.c gcc-ici-4/gcc/plugin.c
--- gcc/gcc/plugin.c	2009-11-29 17:42:49.053525413 +0000
+++ gcc-ici-4/gcc/plugin.c	2009-12-01 16:49:06.384654230 +0000
@@ -44,28 +44,30 @@ along with GCC; see the file COPYING3.  
 #include "plugin-version.h"
 #endif
 
+#define GCC_PLUGIN_STRINGIFY0(X) #X
+#define GCC_PLUGIN_STRINGIFY1(X) GCC_PLUGIN_STRINGIFY0 (X)
+
 /* Event names as strings.  Keep in sync with enum plugin_event.  */
-const char *plugin_event_name[] =
+static const char *plugin_event_name_init[] =
 {
-  "PLUGIN_PASS_MANAGER_SETUP",
-  "PLUGIN_FINISH_TYPE",
-  "PLUGIN_FINISH_UNIT",
-  "PLUGIN_CXX_CP_PRE_GENERICIZE",
-  "PLUGIN_FINISH",
-  "PLUGIN_INFO",
-  "PLUGIN_GGC_START",
-  "PLUGIN_GGC_MARKING",
-  "PLUGIN_GGC_END",
-  "PLUGIN_REGISTER_GGC_ROOTS",
-  "PLUGIN_REGISTER_GGC_CACHES",
-  "PLUGIN_ATTRIBUTES",
-  "PLUGIN_START_UNIT",
-  "PLUGIN_PRAGMAS",
-  "PLUGIN_EVENT_LAST"
+# define DEFEVENT(NAME) GCC_PLUGIN_STRINGIFY1 (NAME),
+# include "plugin.def"
+# undef DEFEVENT
 };
 
 /* A printf format large enough for the largest event above.  */
-#define FMT_FOR_PLUGIN_EVENT "%-26s"
+#define FMT_FOR_PLUGIN_EVENT "%-32s"
+
+const char **plugin_event_name = plugin_event_name_init;
+
+/* A hash table to map event names to the position of the names in the
+   plugin_event_name table.  */
+static htab_t event_tab;
+
+/* Keep track of the limit of allocated events and space ready for
+   allocating events.  */
+static int event_last = PLUGIN_EVENT_FIRST_DYNAMIC;
+static int event_horizon = PLUGIN_EVENT_FIRST_DYNAMIC;
 
 /* Hash table for the plugin_name_args objects created during command-line
    parsing.  */
@@ -81,7 +83,8 @@ struct callback_info
 };
 
 /* An array of lists of 'callback_info' objects indexed by the event id.  */
-static struct callback_info *plugin_callbacks[PLUGIN_EVENT_LAST] = { NULL };
+static struct callback_info *plugin_callbacks_init[PLUGIN_EVENT_FIRST_DYNAMIC];
+static struct callback_info **plugin_callbacks = plugin_callbacks_init;
 
 
 #ifdef ENABLE_PLUGIN
@@ -290,6 +293,71 @@ register_plugin_info (const char* name, 
   plugin->help = info->help;
 }
 
+/* Helper function for the event hash table that compares the name of an
+   existing entry (E1) with the given string (S2).  */
+
+static int
+htab_event_eq (const void *e1, const void *s2)
+{
+  const char *s1= *(const char * const *) e1;
+  return !strcmp (s1, (const char *) s2);
+}
+
+/* Look up the event id for NAME.  If the name is not found, return -1
+   if INSERT is NO_INSERT.  */
+
+int
+get_named_event_id (const char *name, enum insert_option insert)
+{
+  void **slot;
+
+  if (!event_tab)
+    {
+      int i;
+
+      event_tab = htab_create (150, htab_hash_string, htab_event_eq, NULL);
+      for (i = 0; i < PLUGIN_EVENT_FIRST_DYNAMIC; i++)
+	{
+	  slot = htab_find_slot (event_tab, plugin_event_name[i], INSERT);
+	  gcc_assert (*slot == HTAB_EMPTY_ENTRY);
+	  *slot = &plugin_event_name[i];
+	}
+    }
+  slot = htab_find_slot (event_tab, name, insert);
+  if (slot == NULL)
+    return -1;
+  if (*slot != HTAB_EMPTY_ENTRY)
+    return (const char **) *slot - &plugin_event_name[0];
+
+  if (event_last >= event_horizon)
+    {
+      event_horizon = event_last * 2;
+      if (plugin_event_name == plugin_event_name_init)
+	{
+	  plugin_event_name = XNEWVEC (const char *, event_horizon);
+	  memcpy (plugin_event_name, plugin_event_name_init,
+		  sizeof plugin_event_name_init);
+	  plugin_callbacks = XNEWVEC (struct callback_info *, event_horizon);
+	  memcpy (plugin_callbacks, plugin_callbacks_init,
+		  sizeof plugin_callbacks_init);
+	}
+      else
+	{
+	  plugin_event_name
+	    = XRESIZEVEC (const char *, plugin_event_name, event_horizon);
+	  plugin_callbacks = XRESIZEVEC (struct callback_info *,
+					 plugin_callbacks, event_horizon);
+	}
+      /* All the pointers in the hash table will need to be updated.  */
+      htab_delete (event_tab);
+      event_tab = NULL;
+    }
+  else
+    *slot = &plugin_event_name[event_last];
+  plugin_event_name[event_last] = name;
+  return event_last++;
+}
+
 /* Called from the plugin's initialization code. Register a single callback.
    This function can be called multiple times.
 
@@ -300,7 +368,7 @@ register_plugin_info (const char* name, 
 
 void
 register_callback (const char *plugin_name,
-                   enum plugin_event event,
+		   int event,
                    plugin_callback_func callback,
                    void *user_data)
 {
@@ -322,6 +390,15 @@ register_callback (const char *plugin_na
 	gcc_assert (!callback);
         ggc_register_cache_tab ((const struct ggc_cache_tab*) user_data);
 	break;
+      case PLUGIN_EVENT_FIRST_DYNAMIC:
+      default:
+	if (event < PLUGIN_EVENT_FIRST_DYNAMIC || event >= event_last)
+	  {
+	    error ("Unknown callback event registered by plugin %s",
+		   plugin_name);
+	    return;
+	  }
+      /* Fall through.  */
       case PLUGIN_FINISH_TYPE:
       case PLUGIN_START_UNIT:
       case PLUGIN_FINISH_UNIT:
@@ -332,6 +409,15 @@ register_callback (const char *plugin_na
       case PLUGIN_ATTRIBUTES:
       case PLUGIN_PRAGMAS:
       case PLUGIN_FINISH:
+      case PLUGIN_ALL_PASSES_START:
+      case PLUGIN_ALL_PASSES_END:
+      case PLUGIN_ALL_IPA_PASSES_START:
+      case PLUGIN_ALL_IPA_PASSES_END:
+      case PLUGIN_OVERRIDE_GATE:
+      case PLUGIN_PASS_EXECUTION:
+      case PLUGIN_EARLY_GIMPLE_PASSES_START:
+      case PLUGIN_EARLY_GIMPLE_PASSES_END:
+      case PLUGIN_NEW_PASS:
         {
           struct callback_info *new_callback;
           if (!callback)
@@ -348,27 +434,52 @@ register_callback (const char *plugin_na
           plugin_callbacks[event] = new_callback;
         }
         break;
-      case PLUGIN_EVENT_LAST:
-      default:
-        error ("Unknown callback event registered by plugin %s",
-               plugin_name);
     }
 }
 
+/* Remove a callback for EVENT which has been registered with for a plugin
+   PLUGIN_NAME.  Return PLUGEVT_SUCCESS if a matching callback was
+   found & removed, PLUGEVT_NO_CALLBACK if the event does not have a matching
+   callback, and PLUGEVT_NO_SUCH_EVENT if EVENT is invalid.  */
+int
+unregister_callback (const char *plugin_name, int event)
+{
+  struct callback_info *callback, **cbp;
+
+  if (event >= event_last)
+    return PLUGEVT_NO_SUCH_EVENT;
+
+  for (cbp = &plugin_callbacks[event]; (callback = *cbp); cbp = &callback->next)
+    if (strcmp (callback->plugin_name, plugin_name) == 0)
+      {
+	*cbp = callback->next;
+	return PLUGEVT_SUCCESS;
+      }
+  return PLUGEVT_NO_CALLBACK;
+}
 
 /* Called from inside GCC.  Invoke all plug-in callbacks registered with
    the specified event.
+   Return PLUGEVT_SUCCESS if at least one callback was called,
+   PLUGEVT_NO_CALLBACK if there was no callback.
 
    EVENT    - the event identifier
    GCC_DATA - event-specific data provided by the compiler  */
 
-void
-invoke_plugin_callbacks (enum plugin_event event, void *gcc_data)
+int
+invoke_plugin_callbacks (int event, void *gcc_data)
 {
+  int retval = PLUGEVT_SUCCESS;
+
   timevar_push (TV_PLUGIN_RUN);
 
   switch (event)
     {
+      case PLUGIN_EVENT_FIRST_DYNAMIC:
+      default:
+	gcc_assert (event >= PLUGIN_EVENT_FIRST_DYNAMIC);
+	gcc_assert (event < event_last);
+      /* Fall through.  */
       case PLUGIN_FINISH_TYPE:
       case PLUGIN_START_UNIT:
       case PLUGIN_FINISH_UNIT:
@@ -379,24 +490,35 @@ invoke_plugin_callbacks (enum plugin_eve
       case PLUGIN_GGC_START:
       case PLUGIN_GGC_MARKING:
       case PLUGIN_GGC_END:
+      case PLUGIN_ALL_PASSES_START:
+      case PLUGIN_ALL_PASSES_END:
+      case PLUGIN_ALL_IPA_PASSES_START:
+      case PLUGIN_ALL_IPA_PASSES_END:
+      case PLUGIN_OVERRIDE_GATE:
+      case PLUGIN_PASS_EXECUTION:
+      case PLUGIN_EARLY_GIMPLE_PASSES_START:
+      case PLUGIN_EARLY_GIMPLE_PASSES_END:
+      case PLUGIN_NEW_PASS:
         {
           /* Iterate over every callback registered with this event and
              call it.  */
           struct callback_info *callback = plugin_callbacks[event];
+
+	  if (!callback)
+	    retval = PLUGEVT_NO_CALLBACK;
           for ( ; callback; callback = callback->next)
             (*callback->func) (gcc_data, callback->user_data);
         }
         break;
 
       case PLUGIN_PASS_MANAGER_SETUP:
-      case PLUGIN_EVENT_LAST:
       case PLUGIN_REGISTER_GGC_ROOTS:
       case PLUGIN_REGISTER_GGC_CACHES:
-      default:
         gcc_assert (false);
     }
 
   timevar_pop (TV_PLUGIN_RUN);
+  return retval;
 }
 
 #ifdef ENABLE_PLUGIN
@@ -621,7 +743,7 @@ plugins_active_p (void)
 {
   int event;
 
-  for (event = PLUGIN_PASS_MANAGER_SETUP; event < PLUGIN_EVENT_LAST; event++)
+  for (event = PLUGIN_PASS_MANAGER_SETUP; event < event_last; event++)
     if (plugin_callbacks[event])
       return true;
 
@@ -641,7 +763,7 @@ dump_active_plugins (FILE *file)
     return;
 
   fprintf (file, FMT_FOR_PLUGIN_EVENT " | %s\n", _("Event"), _("Plugins"));
-  for (event = PLUGIN_PASS_MANAGER_SETUP; event < PLUGIN_EVENT_LAST; event++)
+  for (event = PLUGIN_PASS_MANAGER_SETUP; event < event_last; event++)
     if (plugin_callbacks[event])
       {
 	struct callback_info *ci;
@@ -686,3 +808,13 @@ plugin_default_version_check (struct plu
     return false;
   return true;
 }
+
+/* Return the current value of event_last, so that plugins which provide
+   additional functionality for events for the benefit of high-level plugins
+   know how many valid entries plugin_event_name holds.  */
+
+int
+get_event_last (void)
+{
+  return event_last;
+}
diff -drupN --exclude .svn gcc/gcc/plugin.def gcc-ici-4/gcc/plugin.def
--- gcc/gcc/plugin.def	1970-01-01 01:00:00.000000000 +0100
+++ gcc-ici-4/gcc/plugin.def	2009-12-01 13:45:58.662653796 +0000
@@ -0,0 +1,94 @@
+/* This file contains the definitions for plugin events in GCC.
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+/* To hook into pass manager.  */
+DEFEVENT (PLUGIN_PASS_MANAGER_SETUP)
+
+/* After finishing parsing a type.  */
+DEFEVENT (PLUGIN_FINISH_TYPE)
+
+/* Useful for summary processing.  */
+DEFEVENT (PLUGIN_FINISH_UNIT)
+
+/* Allows to see low level AST in C++ FE.  */
+DEFEVENT (PLUGIN_CXX_CP_PRE_GENERICIZE)
+
+/* Called before GCC exits.  */
+DEFEVENT (PLUGIN_FINISH)
+
+/* Information about the plugin. */
+DEFEVENT (PLUGIN_INFO)
+
+/* Called at start of GCC Garbage Collection. */
+DEFEVENT (PLUGIN_GGC_START)
+
+/* Extend the GGC marking. */
+DEFEVENT (PLUGIN_GGC_MARKING)
+
+/* Called at end of GGC. */
+DEFEVENT (PLUGIN_GGC_END)
+
+/* Register an extra GGC root table. */
+DEFEVENT (PLUGIN_REGISTER_GGC_ROOTS)
+
+/* Register an extra GGC cache table. */
+DEFEVENT (PLUGIN_REGISTER_GGC_CACHES)
+
+/* Called during attribute registration.  */
+DEFEVENT (PLUGIN_ATTRIBUTES)
+
+/* Called before processing a translation unit.  */
+DEFEVENT (PLUGIN_START_UNIT)
+
+/* Called during pragma registration.  */
+DEFEVENT (PLUGIN_PRAGMAS)
+
+/* Called before first pass from all_passes.  */
+DEFEVENT (PLUGIN_ALL_PASSES_START)
+
+/* Called after last pass from all_passes.  */
+DEFEVENT (PLUGIN_ALL_PASSES_END)
+
+/* Called before first ipa pass.  */
+DEFEVENT (PLUGIN_ALL_IPA_PASSES_START)
+
+/* Called after last ipa pass.  */
+DEFEVENT (PLUGIN_ALL_IPA_PASSES_END)
+
+/* Allows to override pass gate decision for current_pass.  */
+DEFEVENT (PLUGIN_OVERRIDE_GATE)
+
+/* Called before executing a pass.  */
+DEFEVENT (PLUGIN_PASS_EXECUTION)
+
+/* Called before executing subpasses of a GIMPLE_PASS in
+   execute_ipa_pass_list.  */
+DEFEVENT (PLUGIN_EARLY_GIMPLE_PASSES_START)
+
+/* Called after executing subpasses of a GIMPLE_PASS in
+   execute_ipa_pass_list.  */
+DEFEVENT (PLUGIN_EARLY_GIMPLE_PASSES_END)
+
+/* Called when a pass is first instantiated.  */
+DEFEVENT (PLUGIN_NEW_PASS)
+
+/* After the hard-coded events above, plugins can dynamically allocate events
+   at run time.
+   PLUGIN_EVENT_FIRST_DYNAMIC only appears as last enum element.  */
diff -drupN --exclude .svn gcc/gcc/plugin.h gcc-ici-4/gcc/plugin.h
--- gcc/gcc/plugin.h	2009-11-04 14:49:32.602125905 +0000
+++ gcc-ici-4/gcc/plugin.h	2009-12-01 13:41:08.259654594 +0000
@@ -26,7 +26,7 @@ struct attribute_spec;
 
 extern void add_new_plugin (const char *);
 extern void parse_plugin_arg_opt (const char *);
-extern void invoke_plugin_callbacks (enum plugin_event, void *);
+extern int invoke_plugin_callbacks (int, void *);
 extern void initialize_plugins (void);
 extern bool plugins_active_p (void);
 extern void dump_active_plugins (FILE *);
diff -drupN --exclude .svn gcc/gcc/tree-optimize.c gcc-ici-4/gcc/tree-optimize.c
--- gcc/gcc/tree-optimize.c	2009-11-29 17:42:49.047772795 +0000
+++ gcc-ici-4/gcc/tree-optimize.c	2009-12-01 13:57:08.926528800 +0000
@@ -49,6 +49,7 @@ along with GCC; see the file COPYING3.  
 #include "graph.h"
 #include "cfgloop.h"
 #include "except.h"
+#include "plugin.h"
 
 
 /* Gate: execute, or not, all of the non-trivial optimizations.  */
@@ -405,8 +406,15 @@ tree_rest_of_compilation (tree fndecl)
   execute_all_ipa_transforms ();
 
   /* Perform all tree transforms and optimizations.  */
+
+  /* Signal the start of passes.  */
+  invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL);
+
   execute_pass_list (all_passes);
 
+  /* Signal the end of passes.  */
+  invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL);
+
   bitmap_obstack_release (&reg_obstack);
 
   /* Release the default bitmap obstack.  */
diff -drupN --exclude .svn gcc/gcc/tree-pass.h gcc-ici-4/gcc/tree-pass.h
--- gcc/gcc/tree-pass.h	2009-11-29 17:42:48.639772819 +0000
+++ gcc-ici-4/gcc/tree-pass.h	2009-12-01 13:13:57.689528409 +0000
@@ -565,12 +565,16 @@ extern struct opt_pass *all_passes, *all
 extern struct opt_pass *current_pass;
 
 extern struct opt_pass * get_pass_for_id (int);
+extern bool execute_one_pass (struct opt_pass *);
 extern void execute_pass_list (struct opt_pass *);
 extern void execute_ipa_pass_list (struct opt_pass *);
 extern void execute_ipa_summary_passes (struct ipa_opt_pass_d *);
 extern void execute_all_ipa_transforms (void);
 extern void execute_all_ipa_stmt_fixups (struct cgraph_node *, gimple *);
+extern bool pass_init_dump_file (struct opt_pass *);
+extern void pass_fini_dump_file (struct opt_pass *);
 
+extern const char *get_current_pass_name (void);
 extern void print_current_pass (FILE *);
 extern void debug_pass (void);
 extern void ipa_write_summaries (void);
@@ -590,4 +594,7 @@ extern void register_pass (struct regist
    directly in jump threading, and avoid peeling them next time.  */
 extern bool first_pass_instance;
 
+/* Declare for plugins.  */
+extern void do_per_function_toporder (void (*) (void *), void *);
+
 #endif /* GCC_TREE_PASS_H */

[-- Attachment #3: gcc-ici-patch-20091201-4 --]
[-- Type: text/plain, Size: 37305 bytes --]

2009-12-01  Grigori Fursin  <grigori.fursin@inria.fr>
	    Joern Rennecke  <amylaar@spamcop.net>

	* cgraphunit.c (plugin.h): Include.
	(ipa_passes): Invoke PLUGIN_ALL_IPA_PASSES_START /
	PLUGIN_ALL_IPA_PASSES_END at start / end of processing.
	* gcc-plugin.h (highlev-plugin-common.h, hashtab.h): Include.
	(enum plugin_event): Define by including plugin.def.
	Last enumerator is now called PLUGIN_EVENT_FIRST_DYNAMIC.
	(plugin_event_name): Change type to const char **.
	(get_event_last, get_named_event_id, unregister_callback): Declare.
	(register_callback): Change type of event argument to int.
	(highlev-plugin-common.h): New file.
	* Makefile.in (GCC_PLUGIN_H): Add highlev-plugin-common.h and
	$(HASHTAB_H)
	(tree-optimize.o passes.o): Depend on $(PLUGIN_H).
	(PLUGIN_HEADERS): Add opts.h, $(PARAMS_H) and plugin.def.
	(s-header-vars): New rule.
	(install-plugin): Depend on s-header-vars.  Install b-header-vars.
	* params.c (get_num_compiler_params): New function.
	* params.h (get_num_compiler_params): Declare.
	* passes.c (plugin.h): Include.
	(make_pass_instance): Invoke PLUGIN_NEW_PASS.
	(do_per_function_toporder, pass_init_dump_file): No longer static.
	(pass_fini_dump_file): Likewise.
	(execute_one_pass): Likewise.  Invoke PLUGIN_OVERRIDE_GATE and
	PLUGIN_PASS_EXECUTION.
	(execute_ipa_pass_list): Invoke PLUGIN_EARLY_GIMPLE_PASSES_START and
	PLUGIN_EARLY_GIMPLE_PASSES_END.
	* plugin.c (plugin_event_name_init): New array, defined by
	including plugin.def.
	(FMT_FOR_PLUGIN_EVENT): Update.
	(plugin_event_name): Change type to const char ** and initialize
	to plugin_event_name_init.
	(event_tab, event_last, event_horizon): New variable.
	(get_event_last): New function.
	(plugin_callbacks_init): New array.
	(plugin_callbacks: Change type to struct callback_info **.
	Initialize to plugin_callbacks_init.
	(htab_event_eq, get_named_event_id, unregister_callback): New function.
	(invoke_plugin_va_callbacks): Likewise.
	(register_callback): Change type of event argument to int.
	Handle new events.  Allow dynamic events.
	(invoke_plugin_callbacks): Likewise.  Return success status.
	(plugins_active_p): Allow dynamic callbacks.
	* plugin.def: New file.
	* plugin.h (invoke_plugin_callbacks): Update prototype.
	(invoke_plugin_va_callbacks): Declare.
	* tree-optimize.c (plugin.h): Include.
	(tree_rest_of_compilation): Invoke PLUGIN_ALL_PASSES_START and
	PLUGIN_ALL_PASSES_END.
	* tree-pass.h (execute_one_pass, pass_init_dump_file): Declare.
	(pass_fini_dump_file, do_per_function_toporder): Likewise.
	* doc/plugin.texi: Document new event types.

diff -drupN --exclude .svn gcc/gcc/cgraphunit.c gcc-ici-4/gcc/cgraphunit.c
--- gcc/gcc/cgraphunit.c	2009-11-29 17:42:48.662772536 +0000
+++ gcc-ici-4/gcc/cgraphunit.c	2009-12-01 13:54:02.833653857 +0000
@@ -135,6 +135,7 @@ along with GCC; see the file COPYING3.  
 #include "tree-dump.h"
 #include "output.h"
 #include "coverage.h"
+#include "plugin.h"
 
 static void cgraph_expand_all_functions (void);
 static void cgraph_mark_functions_to_output (void);
@@ -1712,6 +1713,8 @@ ipa_passes (void)
   gimple_register_cfg_hooks ();
   bitmap_obstack_initialize (NULL);
 
+  invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_START, NULL);
+
   if (!in_lto_p)
     execute_ipa_pass_list (all_small_ipa_passes);
 
@@ -1730,7 +1733,8 @@ ipa_passes (void)
       current_function_decl = NULL;
       cgraph_process_new_functions ();
 
-      execute_ipa_summary_passes ((struct ipa_opt_pass_d *) all_regular_ipa_passes);
+      execute_ipa_summary_passes
+	((struct ipa_opt_pass_d *) all_regular_ipa_passes);
     }
   execute_ipa_summary_passes ((struct ipa_opt_pass_d *) all_lto_gen_passes);
 
@@ -1739,6 +1743,7 @@ ipa_passes (void)
 
   if (!flag_ltrans)
     execute_ipa_pass_list (all_regular_ipa_passes);
+  invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_END, NULL);
 
   bitmap_obstack_release (NULL);
 }
diff -drupN --exclude .svn gcc/gcc/doc/plugins.texi gcc-ici-4/gcc/doc/plugins.texi
--- gcc/gcc/doc/plugins.texi	2009-11-29 17:42:32.565901921 +0000
+++ gcc-ici-4/gcc/doc/plugins.texi	2009-12-01 16:31:15.979654130 +0000
@@ -156,18 +156,42 @@ enum plugin_event
   PLUGIN_ATTRIBUTES,            /* Called during attribute registration */
   PLUGIN_START_UNIT,            /* Called before processing a translation unit.  */
   PLUGIN_PRAGMAS,	        /* Called during pragma registration. */
-  PLUGIN_EVENT_LAST             /* Dummy event used for indexing callback
+  /* Called before first pass from all_passes.  */
+  PLUGIN_ALL_PASSES_START,
+  /* Called after last pass from all_passes.  */
+  PLUGIN_ALL_PASSES_END,
+  /* Called before first ipa pass.  */
+  PLUGIN_ALL_IPA_PASSES_START,
+  /* Called after last ipa pass.  */
+  PLUGIN_ALL_IPA_PASSES_END,
+  /* Allows to override pass gate decision for current_pass.  */
+  PLUGIN_OVERRIDE_GATE,
+  /* Called before executing a pass.  */
+  PLUGIN_PASS_EXECUTION,
+  /* Called before executing subpasses of a GIMPLE_PASS in
+     execute_ipa_pass_list.  */
+  PLUGIN_EARLY_GIMPLE_PASSES_START,
+  /* Called after executing subpasses of a GIMPLE_PASS in
+     execute_ipa_pass_list.  */
+  PLUGIN_EARLY_GIMPLE_PASSES_END,
+  /* Called when a pass is first instantiated.  */
+  PLUGIN_NEW_PASS,
+
+  PLUGIN_EVENT_FIRST_DYNAMIC    /* Dummy event used for indexing callback
                                    array.  */
 @};
 @end smallexample
 
+In addition, plugins can also look up the enumerator of a named event,
+and / or generate new events dynamically, by calling the function
+@code{get_named_event_id}.
 
 To register a callback, the plugin calls @code{register_callback} with
 the arguments:
 
 @itemize
 @item @code{char *name}: Plugin name.
-@item @code{enum plugin_event event}: The event code.
+@item @code{int event}: The event code.
 @item @code{plugin_callback_func callback}: The function that handles @code{event}.
 @item @code{void *user_data}: Pointer to plugin-specific data.
 @end itemize
@@ -337,6 +361,41 @@ It is suggested to pass @code{"GCCPLUGIN
 your plugin) as the ``space'' argument of your pragma. 
 
 
+@section Recording information about pass execution
+
+The event PLUGIN_PASS_EXECUTION passes the pointer to the executed pass
+(the same as current_pass) as @code{gcc_data} to the callback.  You can also
+inspect cfun to find out about which function this pass is executed for.
+Note that this event will only be invoked if the gate check (if
+applicable, modified by PLUGIN_OVERRIDE_GATE) succeeds.
+You can use other hooks, like @code{PLUGIN_ALL_PASSES_START},
+@code{PLUGIN_ALL_PASSES_END}, @code{PLUGIN_ALL_IPA_PASSES_START},
+@code{PLUGIN_ALL_IPA_PASSES_END}, @code{PLUGIN_EARLY_GIMPLE_PASSES_START},
+and/or @code{PLUGIN_EARLY_GIMPLE_PASSES_END} to manipulate global state
+in your plugin(s) in order to get context for the pass execution.
+
+
+@section Controlling which passes are being run
+
+After the original gate function for a pass is called, its result
+- the gate status - is stored as an integer.
+Then the event @code{PLUGIN_OVERRIDE_GATE} is invoked, with a pointer
+to the gate status in the @code{gcc_data} parameter to the callback function.
+A nonzero value of the gate status means that the pass is to be executed.
+You can both read and write the gate status via the passed pointer.
+
+
+@section Keeping track of available passes
+
+When your plugin is loaded, you can inspect the various
+pass lists to determine what passes are available.  However, other
+plugins might add new passes.  Also, future changes to GCC might cause
+generic passes to be added after plugin loading.
+When a pass is first added to one of the pass lists, the event
+@code{PLUGIN_NEW_PASS} is invoked, with the callback parameter
+@code{gcc_data} pointing to the new pass.
+
+
 @section Building GCC plugins
 
 If plugins are enabled, GCC installs the headers needed to build a
diff -drupN --exclude .svn gcc/gcc/gcc-plugin.h gcc-ici-4/gcc/gcc-plugin.h
--- gcc/gcc/gcc-plugin.h	2009-11-08 21:11:04.273376423 +0000
+++ gcc-ici-4/gcc/gcc-plugin.h	2009-12-01 17:01:11.379653175 +0000
@@ -26,29 +26,19 @@ along with GCC; see the file COPYING3.  
 
 #include "config.h"
 #include "system.h"
+#include "highlev-plugin-common.h"
+#include "hashtab.h"
 
-/* Event names.  Keep in sync with plugin_event_name[].  */
+/* Event names.  */
 enum plugin_event
 {
-  PLUGIN_PASS_MANAGER_SETUP,    /* To hook into pass manager.  */
-  PLUGIN_FINISH_TYPE,           /* After finishing parsing a type.  */
-  PLUGIN_FINISH_UNIT,           /* Useful for summary processing.  */
-  PLUGIN_CXX_CP_PRE_GENERICIZE, /* Allows to see low level AST in C++ FE.  */
-  PLUGIN_FINISH,                /* Called before GCC exits.  */
-  PLUGIN_INFO,                  /* Information about the plugin. */
-  PLUGIN_GGC_START,		/* Called at start of GCC Garbage Collection. */
-  PLUGIN_GGC_MARKING,		/* Extend the GGC marking. */
-  PLUGIN_GGC_END,		/* Called at end of GGC. */
-  PLUGIN_REGISTER_GGC_ROOTS,	/* Register an extra GGC root table. */
-  PLUGIN_REGISTER_GGC_CACHES,	/* Register an extra GGC cache table. */
-  PLUGIN_ATTRIBUTES,            /* Called during attribute registration.  */
-  PLUGIN_START_UNIT,            /* Called before processing a translation unit.  */
-  PLUGIN_PRAGMAS,	        /* Called during pragma registration.  */
-  PLUGIN_EVENT_LAST             /* Dummy event used for indexing callback
-                                   array.  */
+# define DEFEVENT(NAME) NAME,
+# include "plugin.def"
+# undef DEFEVENT
+  PLUGIN_EVENT_FIRST_DYNAMIC
 };
 
-extern const char *plugin_event_name[];
+extern const char **plugin_event_name;
 
 struct plugin_argument
 {
@@ -127,14 +117,22 @@ typedef void (*plugin_callback_func) (vo
    USER_DATA   - plugin-provided data.
 */
 
+/* Number of event ids / names registered so far.  */
+
+extern int get_event_last (void);
+
+int get_named_event_id (const char *name, enum insert_option insert);
+
 /* This is also called without a callback routine for the
    PLUGIN_PASS_MANAGER_SETUP, PLUGIN_INFO, PLUGIN_REGISTER_GGC_ROOTS and
    PLUGIN_REGISTER_GGC_CACHES pseudo-events, with a specific user_data.
   */
 
 extern void register_callback (const char *plugin_name,
-                               enum plugin_event event,
+			       int event,
                                plugin_callback_func callback,
                                void *user_data);
 
+extern int unregister_callback (const char *plugin_name, int event);
+
 #endif /* GCC_PLUGIN_H */
diff -drupN --exclude .svn gcc/gcc/highlev-plugin-common.h gcc-ici-4/gcc/highlev-plugin-common.h
--- gcc/gcc/highlev-plugin-common.h	1970-01-01 01:00:00.000000000 +0100
+++ gcc-ici-4/gcc/highlev-plugin-common.h	2009-12-01 13:49:26.129669583 +0000
@@ -0,0 +1,33 @@
+/* Interface for high-level plugins in GCC - Parts common between GCC,
+   ICI and high-level plugins.
+
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+   Contributed by INRIA.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef HIGHLEV_PLUGIN_COMMON_H
+#define HIGHLEV_PLUGIN_COMMON_H
+
+/* Return codes for invoke_plugin_callbacks / call_plugin_event .  */
+#define PLUGEVT_SUCCESS         0
+#define PLUGEVT_NO_EVENTS       1
+#define PLUGEVT_NO_SUCH_EVENT   2
+#define PLUGEVT_NO_CALLBACK     3
+
+#endif /* HIGHLEV_PLUGIN_COMMON_H */
diff -drupN --exclude .svn gcc/gcc/Makefile.in gcc-ici-4/gcc/Makefile.in
--- gcc/gcc/Makefile.in	2009-11-29 17:42:49.155526086 +0000
+++ gcc-ici-4/gcc/Makefile.in	2009-12-01 14:08:00.428897667 +0000
@@ -943,7 +943,8 @@ TREE_VECTORIZER_H = tree-vectorizer.h $(
 IPA_PROP_H = ipa-prop.h $(TREE_H) vec.h $(CGRAPH_H)
 GSTAB_H = gstab.h stab.def
 BITMAP_H = bitmap.h $(HASHTAB_H) statistics.h
-GCC_PLUGIN_H = gcc-plugin.h $(CONFIG_H) $(SYSTEM_H)
+GCC_PLUGIN_H = gcc-plugin.h highlev-plugin-common.h $(CONFIG_H) $(SYSTEM_H) \
+		$(HASHTAB_H)
 PLUGIN_H = plugin.h $(GCC_PLUGIN_H)
 PLUGIN_VERSION_H = plugin-version.h configargs.h
 
@@ -2503,8 +2504,9 @@ tree-ssa-reassoc.o : tree-ssa-reassoc.c 
    langhooks.h alloc-pool.h pointer-set.h $(CFGLOOP_H)
 tree-optimize.o : tree-optimize.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
    $(RTL_H) $(TREE_H) $(TM_P_H) hard-reg-set.h $(EXPR_H) $(GGC_H) output.h \
-   $(DIAGNOSTIC_H) $(BASIC_BLOCK_H) $(FLAGS_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
-   $(TREE_DUMP_H) $(TOPLEV_H) $(FUNCTION_H) langhooks.h $(FLAGS_H) $(CGRAPH_H) \
+   $(DIAGNOSTIC_H) $(BASIC_BLOCK_H) $(FLAGS_H) $(TIMEVAR_H) $(TM_H) \
+   coretypes.h $(TREE_DUMP_H) $(TOPLEV_H) $(FUNCTION_H) langhooks.h \
+   $(FLAGS_H) $(CGRAPH_H) $(PLUGIN_H) \
    $(TREE_INLINE_H) tree-mudflap.h $(GGC_H) graph.h $(CGRAPH_H) \
    $(TREE_PASS_H) $(CFGLOOP_H) $(EXCEPT_H)
 
@@ -2725,7 +2727,8 @@ passes.o : passes.c $(CONFIG_H) $(SYSTEM
    langhooks.h insn-flags.h $(CFGLAYOUT_H) $(REAL_H) $(CFGLOOP_H) \
    hosthooks.h $(CGRAPH_H) $(COVERAGE_H) $(TREE_PASS_H) $(TREE_DUMP_H) \
    $(GGC_H) $(INTEGRATE_H) $(CPPLIB_H) opts.h $(TREE_FLOW_H) $(TREE_INLINE_H) \
-   gt-passes.h $(DF_H) $(PREDICT_H) $(LTO_HEADER_H) $(LTO_SECTION_OUT_H)
+   gt-passes.h $(DF_H) $(PREDICT_H) $(LTO_HEADER_H) $(LTO_SECTION_OUT_H) \
+   $(PLUGIN_H)
 
 plugin.o : plugin.c $(PLUGIN_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h \
    $(TOPLEV_H) $(TREE_H) $(TREE_PASS_H) intl.h $(PLUGIN_VERSION_H) $(GGC_H)
@@ -4264,7 +4267,7 @@ installdirs:
 
 PLUGIN_HEADERS = $(TREE_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
   $(TOPLEV_H) $(BASIC_BLOCK_H) $(GIMPLE_H) $(TREE_PASS_H) $(GCC_PLUGIN_H) \
-  $(GGC_H) $(TREE_DUMP_H) $(PRETTY_PRINT_H) \
+  $(GGC_H) $(TREE_DUMP_H) $(PRETTY_PRINT_H) opts.h $(PARAMS_H) plugin.def \
   $(tm_file_list) $(tm_include_list) $(tm_p_file_list) $(tm_p_include_list) \
   $(host_xm_file_list) $(host_xm_include_list) $(xm_include_list) \
   intl.h $(PLUGIN_VERSION_H) $(DIAGNOSTIC_H) $(C_COMMON_H) $(C_PRETTY_PRINT_H) \
@@ -4273,8 +4276,15 @@ PLUGIN_HEADERS = $(TREE_H) $(CONFIG_H) $
   $(C_PRAGMA_H)  $(CPPLIB_H)  $(FUNCTION_H) \
   cppdefault.h flags.h $(MD5_H) params.def params.h prefix.h tree-inline.h
 
+# generate the 'build fragment' b-header-vars
+s-header-vars: Makefile
+	rm -f tmp-header-vars
+	$(foreach header_var,$(shell sed < Makefile -e 's/^\([A-Z0-9_]*_H\)[      ]*=.*/\1/p' -e d),echo $(header_var)=$(shell echo $($(header_var):$(srcdir)/%=.../%) | sed -e 's~\.\.\./config/~config/~' -e 's~\.\.\..*/~~') >> tmp-header-vars;) \
+	$(SHELL) $(srcdir)/../move-if-change tmp-header-vars b-header-vars
+	$(STAMP) s-header-vars
+
 # Install the headers needed to build a plugin.
-install-plugin: installdirs lang.install-plugin
+install-plugin: installdirs lang.install-plugin s-header-vars
 # We keep the directory structure for files in config and .def files. All
 # other files are flattened to a single directory.
 	$(mkinstalldirs) $(DESTDIR)$(plugin_includedir)
@@ -4298,6 +4308,7 @@ install-plugin: installdirs lang.install
 	  $(mkinstalldirs) $(DESTDIR)$$dir; \
 	  $(INSTALL_DATA) $$path $(DESTDIR)$$dest; \
 	done
+	$(INSTALL_DATA) b-header-vars $(DESTDIR)$(plugin_includedir)/b-header-vars
 
 # Install the compiler executables built during cross compilation.
 install-common: native lang.install-common installdirs
diff -drupN --exclude .svn gcc/gcc/params.c gcc-ici-4/gcc/params.c
--- gcc/gcc/params.c	2009-11-04 14:49:32.468125810 +0000
+++ gcc-ici-4/gcc/params.c	2009-12-01 16:44:30.849653237 +0000
@@ -32,7 +32,6 @@ along with GCC; see the file COPYING3.  
 param_info *compiler_params;
 
 /* The number of entries in the table.  */
-
 static size_t num_compiler_params;
 
 /* Add the N PARAMS to the current list of compiler parameters.  */
@@ -85,3 +84,12 @@ set_param_value (const char *name, int v
   /* If we didn't find this parameter, issue an error message.  */
   error ("invalid parameter %qs", name);
 }
+
+/* Return the current value of num_compiler_params, for the benefit of
+   plugins that use parameters as features.  */
+
+size_t
+get_num_compiler_params (void)
+{
+  return num_compiler_params;
+}
diff -drupN --exclude .svn gcc/gcc/params.h gcc-ici-4/gcc/params.h
--- gcc/gcc/params.h	2009-11-29 17:42:48.652772589 +0000
+++ gcc-ici-4/gcc/params.h	2009-12-01 16:44:50.248653402 +0000
@@ -65,6 +65,9 @@ typedef struct param_info
 
 extern param_info *compiler_params;
 
+/* Returns the number of entries in the table, for the use by plugins.  */
+extern size_t get_num_compiler_params (void);
+
 /* Add the N PARAMS to the current list of compiler parameters.  */
 
 extern void add_params (const param_info params[], size_t n);
diff -drupN --exclude .svn gcc/gcc/passes.c gcc-ici-4/gcc/passes.c
--- gcc/gcc/passes.c	2009-11-29 17:42:49.163525359 +0000
+++ gcc-ici-4/gcc/passes.c	2009-12-01 16:43:31.059530137 +0000
@@ -85,6 +85,7 @@ along with GCC; see the file COPYING3.  
 #include "df.h"
 #include "predict.h"
 #include "lto-streamer.h"
+#include "plugin.h"
 
 #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
 #include "dwarf2out.h"
@@ -104,7 +105,8 @@ along with GCC; see the file COPYING3.  
 #endif
 
 /* This is used for debugging.  It allows the current pass to printed
-   from anywhere in compilation.  */
+   from anywhere in compilation.
+   The variable current_pass is also used for statistics and plugins.  */
 struct opt_pass *current_pass;
 
 /* Call from anywhere to find out what pass this is.  Useful for
@@ -479,6 +481,8 @@ make_pass_instance (struct opt_pass *pas
     {
       pass->todo_flags_start |= TODO_mark_first_instance;
       pass->static_pass_number = -1;
+
+      invoke_plugin_callbacks (PLUGIN_NEW_PASS, pass);
     }
   return pass;
 }
@@ -1090,9 +1094,9 @@ static GTY ((length ("nnodes"))) struct 
 
 /* If we are in IPA mode (i.e., current_function_decl is NULL), call
    function CALLBACK for every function in the call graph.  Otherwise,
-   call CALLBACK on the current function.  */
-
-static void
+   call CALLBACK on the current function.
+   This function is global so that plugins can use it.  */
+void
 do_per_function_toporder (void (*callback) (void *data), void *data)
 {
   int i;
@@ -1317,8 +1321,9 @@ verify_curr_properties (void *data)
 #endif
 
 /* Initialize pass dump file.  */
+/* This is non-static so that the plugins can use it.  */
 
-static bool
+bool
 pass_init_dump_file (struct opt_pass *pass)
 {
   /* If a dump file name is present, open it if enabled.  */
@@ -1347,8 +1352,9 @@ pass_init_dump_file (struct opt_pass *pa
 }
 
 /* Flush PASS dump file.  */
+/* This is non-static so that plugins can use it.  */
 
-static void
+void
 pass_fini_dump_file (struct opt_pass *pass)
 {
   /* Flush and close dump file.  */
@@ -1476,12 +1482,14 @@ execute_all_ipa_transforms (void)
 
 /* Execute PASS. */
 
-static bool
+bool
 execute_one_pass (struct opt_pass *pass)
 {
   bool initializing_dump;
   unsigned int todo_after = 0;
 
+  bool gate_status;
+
   /* IPA passes are executed on whole program, so cfun should be NULL.
      Other passes need function context set.  */
   if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS)
@@ -1491,9 +1499,22 @@ execute_one_pass (struct opt_pass *pass)
 
   current_pass = pass;
 
-  /* See if we're supposed to run this pass.  */
-  if (pass->gate && !pass->gate ())
-    return false;
+  /* Check whether gate check should be avoided.
+     User controls the value of the gate through the parameter "gate_status". */
+  gate_status = (pass->gate == NULL) ? true : pass->gate();
+
+  /* Override gate with plugin.  */
+  invoke_plugin_callbacks (PLUGIN_OVERRIDE_GATE, &gate_status);
+
+  if (!gate_status)
+    {
+      current_pass = NULL;
+      return false;
+    }
+
+  /* Pass execution event trigger: useful to identify passes being
+     executed.  */
+  invoke_plugin_callbacks (PLUGIN_PASS_EXECUTION, pass);
 
   if (!quiet_flag && !cfun)
     fprintf (stderr, " <%s>", pass->name ? pass->name : "");
@@ -1756,8 +1777,12 @@ execute_ipa_pass_list (struct opt_pass *
       if (execute_one_pass (pass) && pass->sub)
 	{
 	  if (pass->sub->type == GIMPLE_PASS)
-	    do_per_function_toporder ((void (*)(void *))execute_pass_list,
-				      pass->sub);
+	    {
+	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL);
+	      do_per_function_toporder ((void (*)(void *))execute_pass_list,
+					pass->sub);
+	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL);
+	    }
 	  else if (pass->sub->type == SIMPLE_IPA_PASS
 		   || pass->sub->type == IPA_PASS)
 	    execute_ipa_pass_list (pass->sub);
diff -drupN --exclude .svn gcc/gcc/plugin.c gcc-ici-4/gcc/plugin.c
--- gcc/gcc/plugin.c	2009-11-29 17:42:49.053525413 +0000
+++ gcc-ici-4/gcc/plugin.c	2009-12-01 16:49:06.384654230 +0000
@@ -44,28 +44,30 @@ along with GCC; see the file COPYING3.  
 #include "plugin-version.h"
 #endif
 
+#define GCC_PLUGIN_STRINGIFY0(X) #X
+#define GCC_PLUGIN_STRINGIFY1(X) GCC_PLUGIN_STRINGIFY0 (X)
+
 /* Event names as strings.  Keep in sync with enum plugin_event.  */
-const char *plugin_event_name[] =
+static const char *plugin_event_name_init[] =
 {
-  "PLUGIN_PASS_MANAGER_SETUP",
-  "PLUGIN_FINISH_TYPE",
-  "PLUGIN_FINISH_UNIT",
-  "PLUGIN_CXX_CP_PRE_GENERICIZE",
-  "PLUGIN_FINISH",
-  "PLUGIN_INFO",
-  "PLUGIN_GGC_START",
-  "PLUGIN_GGC_MARKING",
-  "PLUGIN_GGC_END",
-  "PLUGIN_REGISTER_GGC_ROOTS",
-  "PLUGIN_REGISTER_GGC_CACHES",
-  "PLUGIN_ATTRIBUTES",
-  "PLUGIN_START_UNIT",
-  "PLUGIN_PRAGMAS",
-  "PLUGIN_EVENT_LAST"
+# define DEFEVENT(NAME) GCC_PLUGIN_STRINGIFY1 (NAME),
+# include "plugin.def"
+# undef DEFEVENT
 };
 
 /* A printf format large enough for the largest event above.  */
-#define FMT_FOR_PLUGIN_EVENT "%-26s"
+#define FMT_FOR_PLUGIN_EVENT "%-32s"
+
+const char **plugin_event_name = plugin_event_name_init;
+
+/* A hash table to map event names to the position of the names in the
+   plugin_event_name table.  */
+static htab_t event_tab;
+
+/* Keep track of the limit of allocated events and space ready for
+   allocating events.  */
+static int event_last = PLUGIN_EVENT_FIRST_DYNAMIC;
+static int event_horizon = PLUGIN_EVENT_FIRST_DYNAMIC;
 
 /* Hash table for the plugin_name_args objects created during command-line
    parsing.  */
@@ -81,7 +83,8 @@ struct callback_info
 };
 
 /* An array of lists of 'callback_info' objects indexed by the event id.  */
-static struct callback_info *plugin_callbacks[PLUGIN_EVENT_LAST] = { NULL };
+static struct callback_info *plugin_callbacks_init[PLUGIN_EVENT_FIRST_DYNAMIC];
+static struct callback_info **plugin_callbacks = plugin_callbacks_init;
 
 
 #ifdef ENABLE_PLUGIN
@@ -290,6 +293,71 @@ register_plugin_info (const char* name, 
   plugin->help = info->help;
 }
 
+/* Helper function for the event hash table that compares the name of an
+   existing entry (E1) with the given string (S2).  */
+
+static int
+htab_event_eq (const void *e1, const void *s2)
+{
+  const char *s1= *(const char * const *) e1;
+  return !strcmp (s1, (const char *) s2);
+}
+
+/* Look up the event id for NAME.  If the name is not found, return -1
+   if INSERT is NO_INSERT.  */
+
+int
+get_named_event_id (const char *name, enum insert_option insert)
+{
+  void **slot;
+
+  if (!event_tab)
+    {
+      int i;
+
+      event_tab = htab_create (150, htab_hash_string, htab_event_eq, NULL);
+      for (i = 0; i < PLUGIN_EVENT_FIRST_DYNAMIC; i++)
+	{
+	  slot = htab_find_slot (event_tab, plugin_event_name[i], INSERT);
+	  gcc_assert (*slot == HTAB_EMPTY_ENTRY);
+	  *slot = &plugin_event_name[i];
+	}
+    }
+  slot = htab_find_slot (event_tab, name, insert);
+  if (slot == NULL)
+    return -1;
+  if (*slot != HTAB_EMPTY_ENTRY)
+    return (const char **) *slot - &plugin_event_name[0];
+
+  if (event_last >= event_horizon)
+    {
+      event_horizon = event_last * 2;
+      if (plugin_event_name == plugin_event_name_init)
+	{
+	  plugin_event_name = XNEWVEC (const char *, event_horizon);
+	  memcpy (plugin_event_name, plugin_event_name_init,
+		  sizeof plugin_event_name_init);
+	  plugin_callbacks = XNEWVEC (struct callback_info *, event_horizon);
+	  memcpy (plugin_callbacks, plugin_callbacks_init,
+		  sizeof plugin_callbacks_init);
+	}
+      else
+	{
+	  plugin_event_name
+	    = XRESIZEVEC (const char *, plugin_event_name, event_horizon);
+	  plugin_callbacks = XRESIZEVEC (struct callback_info *,
+					 plugin_callbacks, event_horizon);
+	}
+      /* All the pointers in the hash table will need to be updated.  */
+      htab_delete (event_tab);
+      event_tab = NULL;
+    }
+  else
+    *slot = &plugin_event_name[event_last];
+  plugin_event_name[event_last] = name;
+  return event_last++;
+}
+
 /* Called from the plugin's initialization code. Register a single callback.
    This function can be called multiple times.
 
@@ -300,7 +368,7 @@ register_plugin_info (const char* name, 
 
 void
 register_callback (const char *plugin_name,
-                   enum plugin_event event,
+		   int event,
                    plugin_callback_func callback,
                    void *user_data)
 {
@@ -322,6 +390,15 @@ register_callback (const char *plugin_na
 	gcc_assert (!callback);
         ggc_register_cache_tab ((const struct ggc_cache_tab*) user_data);
 	break;
+      case PLUGIN_EVENT_FIRST_DYNAMIC:
+      default:
+	if (event < PLUGIN_EVENT_FIRST_DYNAMIC || event >= event_last)
+	  {
+	    error ("Unknown callback event registered by plugin %s",
+		   plugin_name);
+	    return;
+	  }
+      /* Fall through.  */
       case PLUGIN_FINISH_TYPE:
       case PLUGIN_START_UNIT:
       case PLUGIN_FINISH_UNIT:
@@ -332,6 +409,15 @@ register_callback (const char *plugin_na
       case PLUGIN_ATTRIBUTES:
       case PLUGIN_PRAGMAS:
       case PLUGIN_FINISH:
+      case PLUGIN_ALL_PASSES_START:
+      case PLUGIN_ALL_PASSES_END:
+      case PLUGIN_ALL_IPA_PASSES_START:
+      case PLUGIN_ALL_IPA_PASSES_END:
+      case PLUGIN_OVERRIDE_GATE:
+      case PLUGIN_PASS_EXECUTION:
+      case PLUGIN_EARLY_GIMPLE_PASSES_START:
+      case PLUGIN_EARLY_GIMPLE_PASSES_END:
+      case PLUGIN_NEW_PASS:
         {
           struct callback_info *new_callback;
           if (!callback)
@@ -348,27 +434,52 @@ register_callback (const char *plugin_na
           plugin_callbacks[event] = new_callback;
         }
         break;
-      case PLUGIN_EVENT_LAST:
-      default:
-        error ("Unknown callback event registered by plugin %s",
-               plugin_name);
     }
 }
 
+/* Remove a callback for EVENT which has been registered with for a plugin
+   PLUGIN_NAME.  Return PLUGEVT_SUCCESS if a matching callback was
+   found & removed, PLUGEVT_NO_CALLBACK if the event does not have a matching
+   callback, and PLUGEVT_NO_SUCH_EVENT if EVENT is invalid.  */
+int
+unregister_callback (const char *plugin_name, int event)
+{
+  struct callback_info *callback, **cbp;
+
+  if (event >= event_last)
+    return PLUGEVT_NO_SUCH_EVENT;
+
+  for (cbp = &plugin_callbacks[event]; (callback = *cbp); cbp = &callback->next)
+    if (strcmp (callback->plugin_name, plugin_name) == 0)
+      {
+	*cbp = callback->next;
+	return PLUGEVT_SUCCESS;
+      }
+  return PLUGEVT_NO_CALLBACK;
+}
 
 /* Called from inside GCC.  Invoke all plug-in callbacks registered with
    the specified event.
+   Return PLUGEVT_SUCCESS if at least one callback was called,
+   PLUGEVT_NO_CALLBACK if there was no callback.
 
    EVENT    - the event identifier
    GCC_DATA - event-specific data provided by the compiler  */
 
-void
-invoke_plugin_callbacks (enum plugin_event event, void *gcc_data)
+int
+invoke_plugin_callbacks (int event, void *gcc_data)
 {
+  int retval = PLUGEVT_SUCCESS;
+
   timevar_push (TV_PLUGIN_RUN);
 
   switch (event)
     {
+      case PLUGIN_EVENT_FIRST_DYNAMIC:
+      default:
+	gcc_assert (event >= PLUGIN_EVENT_FIRST_DYNAMIC);
+	gcc_assert (event < event_last);
+      /* Fall through.  */
       case PLUGIN_FINISH_TYPE:
       case PLUGIN_START_UNIT:
       case PLUGIN_FINISH_UNIT:
@@ -379,24 +490,35 @@ invoke_plugin_callbacks (enum plugin_eve
       case PLUGIN_GGC_START:
       case PLUGIN_GGC_MARKING:
       case PLUGIN_GGC_END:
+      case PLUGIN_ALL_PASSES_START:
+      case PLUGIN_ALL_PASSES_END:
+      case PLUGIN_ALL_IPA_PASSES_START:
+      case PLUGIN_ALL_IPA_PASSES_END:
+      case PLUGIN_OVERRIDE_GATE:
+      case PLUGIN_PASS_EXECUTION:
+      case PLUGIN_EARLY_GIMPLE_PASSES_START:
+      case PLUGIN_EARLY_GIMPLE_PASSES_END:
+      case PLUGIN_NEW_PASS:
         {
           /* Iterate over every callback registered with this event and
              call it.  */
           struct callback_info *callback = plugin_callbacks[event];
+
+	  if (!callback)
+	    retval = PLUGEVT_NO_CALLBACK;
           for ( ; callback; callback = callback->next)
             (*callback->func) (gcc_data, callback->user_data);
         }
         break;
 
       case PLUGIN_PASS_MANAGER_SETUP:
-      case PLUGIN_EVENT_LAST:
       case PLUGIN_REGISTER_GGC_ROOTS:
       case PLUGIN_REGISTER_GGC_CACHES:
-      default:
         gcc_assert (false);
     }
 
   timevar_pop (TV_PLUGIN_RUN);
+  return retval;
 }
 
 #ifdef ENABLE_PLUGIN
@@ -621,7 +743,7 @@ plugins_active_p (void)
 {
   int event;
 
-  for (event = PLUGIN_PASS_MANAGER_SETUP; event < PLUGIN_EVENT_LAST; event++)
+  for (event = PLUGIN_PASS_MANAGER_SETUP; event < event_last; event++)
     if (plugin_callbacks[event])
       return true;
 
@@ -641,7 +763,7 @@ dump_active_plugins (FILE *file)
     return;
 
   fprintf (file, FMT_FOR_PLUGIN_EVENT " | %s\n", _("Event"), _("Plugins"));
-  for (event = PLUGIN_PASS_MANAGER_SETUP; event < PLUGIN_EVENT_LAST; event++)
+  for (event = PLUGIN_PASS_MANAGER_SETUP; event < event_last; event++)
     if (plugin_callbacks[event])
       {
 	struct callback_info *ci;
@@ -686,3 +808,13 @@ plugin_default_version_check (struct plu
     return false;
   return true;
 }
+
+/* Return the current value of event_last, so that plugins which provide
+   additional functionality for events for the benefit of high-level plugins
+   know how many valid entries plugin_event_name holds.  */
+
+int
+get_event_last (void)
+{
+  return event_last;
+}
diff -drupN --exclude .svn gcc/gcc/plugin.def gcc-ici-4/gcc/plugin.def
--- gcc/gcc/plugin.def	1970-01-01 01:00:00.000000000 +0100
+++ gcc-ici-4/gcc/plugin.def	2009-12-01 13:45:58.662653796 +0000
@@ -0,0 +1,94 @@
+/* This file contains the definitions for plugin events in GCC.
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+/* To hook into pass manager.  */
+DEFEVENT (PLUGIN_PASS_MANAGER_SETUP)
+
+/* After finishing parsing a type.  */
+DEFEVENT (PLUGIN_FINISH_TYPE)
+
+/* Useful for summary processing.  */
+DEFEVENT (PLUGIN_FINISH_UNIT)
+
+/* Allows to see low level AST in C++ FE.  */
+DEFEVENT (PLUGIN_CXX_CP_PRE_GENERICIZE)
+
+/* Called before GCC exits.  */
+DEFEVENT (PLUGIN_FINISH)
+
+/* Information about the plugin. */
+DEFEVENT (PLUGIN_INFO)
+
+/* Called at start of GCC Garbage Collection. */
+DEFEVENT (PLUGIN_GGC_START)
+
+/* Extend the GGC marking. */
+DEFEVENT (PLUGIN_GGC_MARKING)
+
+/* Called at end of GGC. */
+DEFEVENT (PLUGIN_GGC_END)
+
+/* Register an extra GGC root table. */
+DEFEVENT (PLUGIN_REGISTER_GGC_ROOTS)
+
+/* Register an extra GGC cache table. */
+DEFEVENT (PLUGIN_REGISTER_GGC_CACHES)
+
+/* Called during attribute registration.  */
+DEFEVENT (PLUGIN_ATTRIBUTES)
+
+/* Called before processing a translation unit.  */
+DEFEVENT (PLUGIN_START_UNIT)
+
+/* Called during pragma registration.  */
+DEFEVENT (PLUGIN_PRAGMAS)
+
+/* Called before first pass from all_passes.  */
+DEFEVENT (PLUGIN_ALL_PASSES_START)
+
+/* Called after last pass from all_passes.  */
+DEFEVENT (PLUGIN_ALL_PASSES_END)
+
+/* Called before first ipa pass.  */
+DEFEVENT (PLUGIN_ALL_IPA_PASSES_START)
+
+/* Called after last ipa pass.  */
+DEFEVENT (PLUGIN_ALL_IPA_PASSES_END)
+
+/* Allows to override pass gate decision for current_pass.  */
+DEFEVENT (PLUGIN_OVERRIDE_GATE)
+
+/* Called before executing a pass.  */
+DEFEVENT (PLUGIN_PASS_EXECUTION)
+
+/* Called before executing subpasses of a GIMPLE_PASS in
+   execute_ipa_pass_list.  */
+DEFEVENT (PLUGIN_EARLY_GIMPLE_PASSES_START)
+
+/* Called after executing subpasses of a GIMPLE_PASS in
+   execute_ipa_pass_list.  */
+DEFEVENT (PLUGIN_EARLY_GIMPLE_PASSES_END)
+
+/* Called when a pass is first instantiated.  */
+DEFEVENT (PLUGIN_NEW_PASS)
+
+/* After the hard-coded events above, plugins can dynamically allocate events
+   at run time.
+   PLUGIN_EVENT_FIRST_DYNAMIC only appears as last enum element.  */
diff -drupN --exclude .svn gcc/gcc/plugin.h gcc-ici-4/gcc/plugin.h
--- gcc/gcc/plugin.h	2009-11-04 14:49:32.602125905 +0000
+++ gcc-ici-4/gcc/plugin.h	2009-12-01 13:41:08.259654594 +0000
@@ -26,7 +26,7 @@ struct attribute_spec;
 
 extern void add_new_plugin (const char *);
 extern void parse_plugin_arg_opt (const char *);
-extern void invoke_plugin_callbacks (enum plugin_event, void *);
+extern int invoke_plugin_callbacks (int, void *);
 extern void initialize_plugins (void);
 extern bool plugins_active_p (void);
 extern void dump_active_plugins (FILE *);
diff -drupN --exclude .svn gcc/gcc/tree-optimize.c gcc-ici-4/gcc/tree-optimize.c
--- gcc/gcc/tree-optimize.c	2009-11-29 17:42:49.047772795 +0000
+++ gcc-ici-4/gcc/tree-optimize.c	2009-12-01 13:57:08.926528800 +0000
@@ -49,6 +49,7 @@ along with GCC; see the file COPYING3.  
 #include "graph.h"
 #include "cfgloop.h"
 #include "except.h"
+#include "plugin.h"
 
 
 /* Gate: execute, or not, all of the non-trivial optimizations.  */
@@ -405,8 +406,15 @@ tree_rest_of_compilation (tree fndecl)
   execute_all_ipa_transforms ();
 
   /* Perform all tree transforms and optimizations.  */
+
+  /* Signal the start of passes.  */
+  invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL);
+
   execute_pass_list (all_passes);
 
+  /* Signal the end of passes.  */
+  invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL);
+
   bitmap_obstack_release (&reg_obstack);
 
   /* Release the default bitmap obstack.  */
diff -drupN --exclude .svn gcc/gcc/tree-pass.h gcc-ici-4/gcc/tree-pass.h
--- gcc/gcc/tree-pass.h	2009-11-29 17:42:48.639772819 +0000
+++ gcc-ici-4/gcc/tree-pass.h	2009-12-01 13:13:57.689528409 +0000
@@ -565,12 +565,16 @@ extern struct opt_pass *all_passes, *all
 extern struct opt_pass *current_pass;
 
 extern struct opt_pass * get_pass_for_id (int);
+extern bool execute_one_pass (struct opt_pass *);
 extern void execute_pass_list (struct opt_pass *);
 extern void execute_ipa_pass_list (struct opt_pass *);
 extern void execute_ipa_summary_passes (struct ipa_opt_pass_d *);
 extern void execute_all_ipa_transforms (void);
 extern void execute_all_ipa_stmt_fixups (struct cgraph_node *, gimple *);
+extern bool pass_init_dump_file (struct opt_pass *);
+extern void pass_fini_dump_file (struct opt_pass *);
 
+extern const char *get_current_pass_name (void);
 extern void print_current_pass (FILE *);
 extern void debug_pass (void);
 extern void ipa_write_summaries (void);
@@ -590,4 +594,7 @@ extern void register_pass (struct regist
    directly in jump threading, and avoid peeling them next time.  */
 extern bool first_pass_instance;
 
+/* Declare for plugins.  */
+extern void do_per_function_toporder (void (*) (void *), void *);
+
 #endif /* GCC_TREE_PASS_H */

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

* Re: Fwd: RFA: plugin events for ICI
  2009-12-01 17:25               ` Joern Rennecke
@ 2009-12-01 18:05                 ` Diego Novillo
  0 siblings, 0 replies; 13+ messages in thread
From: Diego Novillo @ 2009-12-01 18:05 UTC (permalink / raw)
  To: Joern Rennecke
  Cc: Richard Guenther, Basile STARYNKEVITCH, ctuning-discussions,
	gcc-patches, Grigori Fursin, Grigori Fursin, Zbigniew Chamski,
	Ian Lance Taylor, Albert Cohen, Yuri Kashnikoff, Yuanjie Huang,
	Liang Peng, dorit, Mircea Namolaru

On Tue, Dec 1, 2009 at 12:23, Joern Rennecke <amylaar@spamcop.net> wrote:

> I am currently testing the attached patch locally & on gcc14.

This version looks OK.  Thanks.


Diego.

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

end of thread, other threads:[~2009-12-01 18:01 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20091130133452.hgxpnrkgu8cw0gk8-nzlynne@webmail.spamcop.net>
2009-11-30 19:11 ` Fwd: RFA: plugin events for ICI Basile STARYNKEVITCH
2009-11-30 19:49   ` Joern Rennecke
2009-11-30 20:12     ` Basile STARYNKEVITCH
2009-12-01  7:18       ` Joern Rennecke
2009-12-01 10:23         ` Richard Guenther
2009-12-01 13:06           ` Joern Rennecke
2009-12-01 13:48             ` Richard Guenther
2009-12-01 14:39           ` Joern Rennecke
2009-12-01 14:52             ` Richard Guenther
2009-12-01 14:55             ` Basile STARYNKEVITCH
2009-12-01 15:57             ` Diego Novillo
2009-12-01 17:25               ` Joern Rennecke
2009-12-01 18:05                 ` Diego Novillo

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