1 /* Callgraph based interprocedural optimizations.
2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
3 Free Software Foundation, Inc.
4 Contributed by Jan Hubicka
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
24 #include "coretypes.h"
29 #include "tree-pass.h"
31 #include "gcc-plugin.h"
32 #include "highlev-plugin-internal.h"
34 void plugin_is_GPL_compatible (void);
35 static void ici_load_function_specific_optimizations (void);
38 plugin_is_GPL_compatible (void)
42 static int ici_all_ipa_passes
= 1;
43 static int ici_bypass_gimple_in_ipa
= 0;
45 /* Perform ICI internal tasks at the start of IPA passes.
46 This must run before any ICI user registered callbacks, which is why
47 register_plugin_event must unregister / re-register this callback when
48 a ICI user callback for PLUGIN_ALL_IPA_PASSES_START is added. */
50 ici_all_ipa_passes_start (void *gcc_data ATTRIBUTE_UNUSED
,
51 void *user_data ATTRIBUTE_UNUSED
)
53 ici_load_function_specific_optimizations ();
54 register_event_parameter ("all_ipa_passes", &ici_all_ipa_passes
, EP_SILENT
);
55 register_event_parameter ("bypass_gimple_in_ipa", &ici_bypass_gimple_in_ipa
,
59 /* Execute ICI internal tasks at the end of IPA passes.
60 This must run after all ICI user registered PLUGIN_ALL_IPA_PASSES_END
61 callbacks, which we get automatically be registering this callback
64 ici_all_ipa_passes_end (void *gcc_data ATTRIBUTE_UNUSED
,
65 void *user_data ATTRIBUTE_UNUSED
)
67 unregister_event_parameter ("bypass_gimple_in_ipa");
68 unregister_event_parameter ("all_ipa_passes");
71 /* This one again should run before ICI user callbacks. */
73 ici_early_gimple_passes_start (void *gcc_data ATTRIBUTE_UNUSED
,
74 void *user_data ATTRIBUTE_UNUSED
)
76 /* Switch to GIMPLE passes. */
77 ici_all_ipa_passes
= 2;
79 /* GIMPLE passes are recorded only once. ici_bypass_gimple_in_ipa
80 will be set again in ici_set_bypass_gimple_in_ipa. */
81 ici_bypass_gimple_in_ipa
= 0;
84 /* Set bypass_gimple_in_ipa back to 1 to stop recording GIMPLE passes. */
86 ici_set_bypass_gimple_in_ipa (void *gcc_data ATTRIBUTE_UNUSED
,
87 void *user_data ATTRIBUTE_UNUSED
)
89 ici_bypass_gimple_in_ipa
= 1;
92 /* The low-level callback implementation calls the last registered
93 callback first. Make sure that, if appropriate, the ICI internal
94 callback for EVENT is registered last, i.e. called first.
95 If EVENT is -1, we are called from the ICI plugin_init, and are to
96 initialize all permanent ICI internall callbacks. */
98 ici_refresh_internal_callbacks (int event
)
100 if (event
== PLUGIN_ALL_IPA_PASSES_START
)
101 unregister_callback ("ICI_INTERNAL", PLUGIN_ALL_IPA_PASSES_START
);
102 if (event
== PLUGIN_ALL_IPA_PASSES_START
|| event
< 0)
103 register_callback ("ICI_INTERNAL", PLUGIN_ALL_IPA_PASSES_START
,
104 ici_all_ipa_passes_start
, NULL
);
105 if (event
== PLUGIN_EARLY_GIMPLE_PASSES_START
)
106 unregister_callback ("ICI_INTERNAL", PLUGIN_EARLY_GIMPLE_PASSES_START
);
107 if (event
== PLUGIN_EARLY_GIMPLE_PASSES_START
|| event
< 0)
108 register_callback ("ICI_INTERNAL", PLUGIN_EARLY_GIMPLE_PASSES_START
,
109 ici_early_gimple_passes_start
, NULL
);
112 register_callback ("ICI_INTERNAL", PLUGIN_ALL_IPA_PASSES_END
,
113 ici_all_ipa_passes_end
, NULL
);
114 register_callback ("ICI_INTERNAL", PLUGIN_PASS_EXECUTION
,
115 ici_set_bypass_gimple_in_ipa
, NULL
);
120 plugin_init (struct plugin_name_args
*plugin_info ATTRIBUTE_UNUSED
,
121 struct plugin_gcc_version
*version ATTRIBUTE_UNUSED
)
123 ici_refresh_internal_callbacks (-1);
125 return 0; /* Success. */
128 /* Load function specific optimizations with parameters. */
130 /* separate string into arguments. */
132 ici_separate_arguments (const char *string
, unsigned int *argc
, char ***argv
)
140 /* Count number of args */
146 if ((c
== ' ' || c
== '\t') && len
)
158 args
= (char **) xmalloc (sizeof(char *) * (*argc
));
160 args
[0] = (char*)xmalloc(sizeof(char)); /* argv[0] unavailable */
168 if (c
== ' ' || c
== '\t')
172 *(args
+ i
) = (char *) xmalloc (sizeof(char) * (len
+ 1));
173 strncpy (*(args
+ i
), (p
- len
), len
);
185 *(args
+ i
) = (char *) xmalloc (sizeof(char) * (len
+ 1));
186 strncpy (*(args
+ i
), (p
- len
), len
);
191 /* free arguments string. */
193 ici_free_arguments (unsigned int argc
, char **argv
)
196 for (i
= 0; i
< argc
; ++i
)
205 /* load function specific option strings and save to function structures. */
207 ici_load_function_specific_optimizations (void)
209 static char *ici_function_spec_string
;
210 struct cgraph_node
*node
;
211 struct function
*old_cfun
= cfun
; /* Backup cfun. */
212 for (node
= cgraph_nodes
; node
; node
= node
->next
)
214 struct function
*fun
;
217 fun
= DECL_STRUCT_FUNCTION (node
->decl
);
222 ici_function_spec_string
= NULL
;
223 invoke_named_callbacks ("function_spec_loader", "function_spec_string",
224 EP_VOID
, (void *) &ici_function_spec_string
,
226 if (!ici_function_spec_string
)
229 fun_decl
= fun
->decl
;
230 if (TREE_CODE (fun_decl
) == FUNCTION_DECL
)
234 struct cl_optimization old_global_opts
;
235 tree old_function_opts
;
236 int saved_flag_strict_aliasing
;
237 int saved_flag_pcc_struct_return
,
238 saved_flag_omit_frame_pointer
,
239 saved_flag_asynchronous_unwind_tables
;
241 /* Save old global and function-specific optimizations. */
242 cl_optimization_save (&old_global_opts
);
244 /* Store function-specific optimizations to global. */
246 = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fun_decl
);
247 if (old_function_opts
)
248 cl_optimization_restore (TREE_OPTIMIZATION (old_function_opts
));
250 /* Parse options string. */
251 ici_separate_arguments (ici_function_spec_string
, &argc
, &argv
);
253 /* Save flags which should not be changed. */
255 /* Change global optimizations with loaded
256 function specific string */
257 saved_flag_strict_aliasing
= flag_strict_aliasing
;
258 saved_flag_omit_frame_pointer
= flag_omit_frame_pointer
;
259 saved_flag_pcc_struct_return
= flag_pcc_struct_return
;
260 saved_flag_asynchronous_unwind_tables
= flag_asynchronous_unwind_tables
;
261 decode_options (argc
, (const char **) argv
);
263 flag_strict_aliasing
= saved_flag_strict_aliasing
;
264 flag_omit_frame_pointer
= saved_flag_omit_frame_pointer
;
265 flag_asynchronous_unwind_tables
= saved_flag_asynchronous_unwind_tables
;
266 flag_pcc_struct_return
= saved_flag_pcc_struct_return
;
268 ici_free_arguments (argc
, argv
);
271 /* Restore saved flags. */
273 /* Store global optimizations to function. */
274 DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fun_decl
)
275 = build_optimization_node ();
277 /* Restore old global optmizations. */
278 cl_optimization_restore (&old_global_opts
);
281 free (ici_function_spec_string
);
287 /* ICI: Execute one IPA summary pass */
289 execute_one_ipa_summary_pass (struct opt_pass
*pass
)
291 gcc_assert (!current_function_decl
);
293 gcc_assert (pass
->type
== SIMPLE_IPA_PASS
|| pass
->type
== IPA_PASS
);
294 if (!quiet_flag
&& !cfun
)
295 fprintf (stderr
, " <summary generate>");
297 /* Generate summary as execute_ipa_summary_passes,
298 but only for current pass. */
299 if (pass
->type
== IPA_PASS
300 && (!pass
->gate
|| pass
->gate ()))
302 pass_init_dump_file (pass
);
303 ((struct ipa_opt_pass_d
*)pass
)->generate_summary ();
304 pass_fini_dump_file (pass
);
309 invoke_named_callbacks (const char *name
, ...)
315 event
= get_named_event_id (name
, NO_INSERT
);
317 retval
= invoke_plugin_callbacks (event
, &va
);