Move ici specific files to new directory ici; add new file ici/ici.c
[official-gcc.git] / gcc / ici / ici.c
blob81ce5729dc31fac016805730e7c723f768cfc24b
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
11 version.
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
16 for more details.
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/>. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "tree.h"
27 #include "cgraph.h"
28 #include "function.h"
29 #include "tree-pass.h"
30 #include "opts.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);
37 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. */
49 static void
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,
56 EP_SILENT);
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
62 first. */
63 static void
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. */
72 static void
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. */
85 static void
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. */
97 void
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);
110 if (event < 0)
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);
124 load_ici_plugin ();
125 return 0; /* Success. */
128 /* Load function specific optimizations with parameters. */
130 /* separate string into arguments. */
131 static void
132 ici_separate_arguments (const char *string, unsigned int *argc, char ***argv)
134 const char *p;
135 char c;
136 char **args;
137 unsigned int len;
138 int i;
140 /* Count number of args */
141 p = string;
142 c = *p;
143 *argc = 1;
144 while (c)
146 if ((c == ' ' || c == '\t') && len)
148 len = 0;
149 ++*argc;
151 else
152 len = 1;
153 c = *++p;
155 if (len)
156 ++*argc;
158 args = (char **) xmalloc (sizeof(char *) * (*argc));
159 *argv = args;
160 args[0] = (char*)xmalloc(sizeof(char)); /* argv[0] unavailable */
161 args[0][0]='\0';
162 i = 1;
163 p = string;
164 c = *p;
165 len = 0;
166 while (c)
168 if (c == ' ' || c == '\t')
170 if (len)
172 *(args + i) = (char *) xmalloc (sizeof(char) * (len + 1));
173 strncpy (*(args + i), (p - len), len);
174 args[i][len] = '\0';
175 ++i;
176 len = 0;
179 else
180 ++len;
181 c = *++p;
183 if (len)
185 *(args + i) = (char *) xmalloc (sizeof(char) * (len + 1));
186 strncpy (*(args + i), (p - len), len);
187 args[i][len] = '\0';
191 /* free arguments string. */
192 static void
193 ici_free_arguments (unsigned int argc, char **argv)
195 unsigned int i;
196 for (i = 0; i < argc; ++i)
198 free (argv[i]);
200 free (argv);
205 /* load function specific option strings and save to function structures. */
206 static void
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;
215 tree fun_decl;
217 fun = DECL_STRUCT_FUNCTION (node->decl);
218 if (!fun)
219 continue;
220 set_cfun (fun);
222 ici_function_spec_string = NULL;
223 invoke_named_callbacks ("function_spec_loader", "function_spec_string",
224 EP_VOID, (void *) &ici_function_spec_string,
225 NULL);
226 if (!ici_function_spec_string)
227 continue;
229 fun_decl = fun->decl;
230 if (TREE_CODE (fun_decl) == FUNCTION_DECL)
232 unsigned int argc;
233 char **argv;
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. */
245 old_function_opts
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);
269 argv = NULL;
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);
283 /* Restore cfun */
284 set_cfun (old_cfun);
287 /* ICI: Execute one IPA summary pass */
288 void
289 execute_one_ipa_summary_pass (struct opt_pass *pass)
291 gcc_assert (!current_function_decl);
292 gcc_assert (!cfun);
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, ...)
311 va_list va;
312 int retval;
313 int event = name;
315 event = get_named_event_id (name, NO_INSERT);
316 va_start (va, name);
317 retval = invoke_plugin_callbacks (event, &va);
318 va_end (va);
319 return retval;