1*e4b17023SJohn Marino /* Top-level control of tree optimizations.
2*e4b17023SJohn Marino Copyright 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
3*e4b17023SJohn Marino Free Software Foundation, Inc.
4*e4b17023SJohn Marino Contributed by Diego Novillo <dnovillo@redhat.com>
5*e4b17023SJohn Marino
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify
9*e4b17023SJohn Marino it under the terms of the GNU General Public License as published by
10*e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option)
11*e4b17023SJohn Marino any later version.
12*e4b17023SJohn Marino
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful,
14*e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
15*e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16*e4b17023SJohn Marino GNU General Public License for more details.
17*e4b17023SJohn Marino
18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
21*e4b17023SJohn Marino
22*e4b17023SJohn Marino #include "config.h"
23*e4b17023SJohn Marino #include "system.h"
24*e4b17023SJohn Marino #include "coretypes.h"
25*e4b17023SJohn Marino #include "tm.h"
26*e4b17023SJohn Marino #include "tree.h"
27*e4b17023SJohn Marino #include "tm_p.h"
28*e4b17023SJohn Marino #include "basic-block.h"
29*e4b17023SJohn Marino #include "output.h"
30*e4b17023SJohn Marino #include "flags.h"
31*e4b17023SJohn Marino #include "tree-flow.h"
32*e4b17023SJohn Marino #include "tree-dump.h"
33*e4b17023SJohn Marino #include "timevar.h"
34*e4b17023SJohn Marino #include "function.h"
35*e4b17023SJohn Marino #include "langhooks.h"
36*e4b17023SJohn Marino #include "diagnostic-core.h"
37*e4b17023SJohn Marino #include "toplev.h"
38*e4b17023SJohn Marino #include "flags.h"
39*e4b17023SJohn Marino #include "cgraph.h"
40*e4b17023SJohn Marino #include "tree-inline.h"
41*e4b17023SJohn Marino #include "tree-pass.h"
42*e4b17023SJohn Marino #include "ggc.h"
43*e4b17023SJohn Marino #include "cgraph.h"
44*e4b17023SJohn Marino #include "graph.h"
45*e4b17023SJohn Marino #include "cfgloop.h"
46*e4b17023SJohn Marino #include "except.h"
47*e4b17023SJohn Marino #include "plugin.h"
48*e4b17023SJohn Marino #include "regset.h" /* FIXME: For reg_obstack. */
49*e4b17023SJohn Marino
50*e4b17023SJohn Marino /* Gate: execute, or not, all of the non-trivial optimizations. */
51*e4b17023SJohn Marino
52*e4b17023SJohn Marino static bool
gate_all_optimizations(void)53*e4b17023SJohn Marino gate_all_optimizations (void)
54*e4b17023SJohn Marino {
55*e4b17023SJohn Marino return (optimize >= 1
56*e4b17023SJohn Marino /* Don't bother doing anything if the program has errors.
57*e4b17023SJohn Marino We have to pass down the queue if we already went into SSA */
58*e4b17023SJohn Marino && (!seen_error () || gimple_in_ssa_p (cfun)));
59*e4b17023SJohn Marino }
60*e4b17023SJohn Marino
61*e4b17023SJohn Marino struct gimple_opt_pass pass_all_optimizations =
62*e4b17023SJohn Marino {
63*e4b17023SJohn Marino {
64*e4b17023SJohn Marino GIMPLE_PASS,
65*e4b17023SJohn Marino "*all_optimizations", /* name */
66*e4b17023SJohn Marino gate_all_optimizations, /* gate */
67*e4b17023SJohn Marino NULL, /* execute */
68*e4b17023SJohn Marino NULL, /* sub */
69*e4b17023SJohn Marino NULL, /* next */
70*e4b17023SJohn Marino 0, /* static_pass_number */
71*e4b17023SJohn Marino TV_OPTIMIZE, /* tv_id */
72*e4b17023SJohn Marino 0, /* properties_required */
73*e4b17023SJohn Marino 0, /* properties_provided */
74*e4b17023SJohn Marino 0, /* properties_destroyed */
75*e4b17023SJohn Marino 0, /* todo_flags_start */
76*e4b17023SJohn Marino 0 /* todo_flags_finish */
77*e4b17023SJohn Marino }
78*e4b17023SJohn Marino };
79*e4b17023SJohn Marino
80*e4b17023SJohn Marino /* Gate: execute, or not, all of the non-trivial optimizations. */
81*e4b17023SJohn Marino
82*e4b17023SJohn Marino static bool
gate_all_early_local_passes(void)83*e4b17023SJohn Marino gate_all_early_local_passes (void)
84*e4b17023SJohn Marino {
85*e4b17023SJohn Marino /* Don't bother doing anything if the program has errors. */
86*e4b17023SJohn Marino return (!seen_error () && !in_lto_p);
87*e4b17023SJohn Marino }
88*e4b17023SJohn Marino
89*e4b17023SJohn Marino static unsigned int
execute_all_early_local_passes(void)90*e4b17023SJohn Marino execute_all_early_local_passes (void)
91*e4b17023SJohn Marino {
92*e4b17023SJohn Marino /* Once this pass (and its sub-passes) are complete, all functions
93*e4b17023SJohn Marino will be in SSA form. Technically this state change is happening
94*e4b17023SJohn Marino a tad early, since the sub-passes have not yet run, but since
95*e4b17023SJohn Marino none of the sub-passes are IPA passes and do not create new
96*e4b17023SJohn Marino functions, this is ok. We're setting this value for the benefit
97*e4b17023SJohn Marino of IPA passes that follow. */
98*e4b17023SJohn Marino if (cgraph_state < CGRAPH_STATE_IPA_SSA)
99*e4b17023SJohn Marino cgraph_state = CGRAPH_STATE_IPA_SSA;
100*e4b17023SJohn Marino return 0;
101*e4b17023SJohn Marino }
102*e4b17023SJohn Marino
103*e4b17023SJohn Marino struct simple_ipa_opt_pass pass_early_local_passes =
104*e4b17023SJohn Marino {
105*e4b17023SJohn Marino {
106*e4b17023SJohn Marino SIMPLE_IPA_PASS,
107*e4b17023SJohn Marino "early_local_cleanups", /* name */
108*e4b17023SJohn Marino gate_all_early_local_passes, /* gate */
109*e4b17023SJohn Marino execute_all_early_local_passes, /* execute */
110*e4b17023SJohn Marino NULL, /* sub */
111*e4b17023SJohn Marino NULL, /* next */
112*e4b17023SJohn Marino 0, /* static_pass_number */
113*e4b17023SJohn Marino TV_EARLY_LOCAL, /* tv_id */
114*e4b17023SJohn Marino 0, /* properties_required */
115*e4b17023SJohn Marino 0, /* properties_provided */
116*e4b17023SJohn Marino 0, /* properties_destroyed */
117*e4b17023SJohn Marino 0, /* todo_flags_start */
118*e4b17023SJohn Marino TODO_remove_functions /* todo_flags_finish */
119*e4b17023SJohn Marino }
120*e4b17023SJohn Marino };
121*e4b17023SJohn Marino
122*e4b17023SJohn Marino /* Gate: execute, or not, all of the non-trivial optimizations. */
123*e4b17023SJohn Marino
124*e4b17023SJohn Marino static bool
gate_all_early_optimizations(void)125*e4b17023SJohn Marino gate_all_early_optimizations (void)
126*e4b17023SJohn Marino {
127*e4b17023SJohn Marino return (optimize >= 1
128*e4b17023SJohn Marino /* Don't bother doing anything if the program has errors. */
129*e4b17023SJohn Marino && !seen_error ());
130*e4b17023SJohn Marino }
131*e4b17023SJohn Marino
132*e4b17023SJohn Marino struct gimple_opt_pass pass_all_early_optimizations =
133*e4b17023SJohn Marino {
134*e4b17023SJohn Marino {
135*e4b17023SJohn Marino GIMPLE_PASS,
136*e4b17023SJohn Marino "early_optimizations", /* name */
137*e4b17023SJohn Marino gate_all_early_optimizations, /* gate */
138*e4b17023SJohn Marino NULL, /* execute */
139*e4b17023SJohn Marino NULL, /* sub */
140*e4b17023SJohn Marino NULL, /* next */
141*e4b17023SJohn Marino 0, /* static_pass_number */
142*e4b17023SJohn Marino TV_NONE, /* tv_id */
143*e4b17023SJohn Marino 0, /* properties_required */
144*e4b17023SJohn Marino 0, /* properties_provided */
145*e4b17023SJohn Marino 0, /* properties_destroyed */
146*e4b17023SJohn Marino 0, /* todo_flags_start */
147*e4b17023SJohn Marino 0 /* todo_flags_finish */
148*e4b17023SJohn Marino }
149*e4b17023SJohn Marino };
150*e4b17023SJohn Marino
151*e4b17023SJohn Marino
152*e4b17023SJohn Marino /* Pass: cleanup the CFG just before expanding trees to RTL.
153*e4b17023SJohn Marino This is just a round of label cleanups and case node grouping
154*e4b17023SJohn Marino because after the tree optimizers have run such cleanups may
155*e4b17023SJohn Marino be necessary. */
156*e4b17023SJohn Marino
157*e4b17023SJohn Marino static unsigned int
execute_cleanup_cfg_post_optimizing(void)158*e4b17023SJohn Marino execute_cleanup_cfg_post_optimizing (void)
159*e4b17023SJohn Marino {
160*e4b17023SJohn Marino unsigned int todo = 0;
161*e4b17023SJohn Marino if (cleanup_tree_cfg ())
162*e4b17023SJohn Marino todo |= TODO_update_ssa;
163*e4b17023SJohn Marino maybe_remove_unreachable_handlers ();
164*e4b17023SJohn Marino cleanup_dead_labels ();
165*e4b17023SJohn Marino group_case_labels ();
166*e4b17023SJohn Marino if ((flag_compare_debug_opt || flag_compare_debug)
167*e4b17023SJohn Marino && flag_dump_final_insns)
168*e4b17023SJohn Marino {
169*e4b17023SJohn Marino FILE *final_output = fopen (flag_dump_final_insns, "a");
170*e4b17023SJohn Marino
171*e4b17023SJohn Marino if (!final_output)
172*e4b17023SJohn Marino {
173*e4b17023SJohn Marino error ("could not open final insn dump file %qs: %m",
174*e4b17023SJohn Marino flag_dump_final_insns);
175*e4b17023SJohn Marino flag_dump_final_insns = NULL;
176*e4b17023SJohn Marino }
177*e4b17023SJohn Marino else
178*e4b17023SJohn Marino {
179*e4b17023SJohn Marino int save_unnumbered = flag_dump_unnumbered;
180*e4b17023SJohn Marino int save_noaddr = flag_dump_noaddr;
181*e4b17023SJohn Marino
182*e4b17023SJohn Marino flag_dump_noaddr = flag_dump_unnumbered = 1;
183*e4b17023SJohn Marino fprintf (final_output, "\n");
184*e4b17023SJohn Marino dump_enumerated_decls (final_output, dump_flags | TDF_NOUID);
185*e4b17023SJohn Marino flag_dump_noaddr = save_noaddr;
186*e4b17023SJohn Marino flag_dump_unnumbered = save_unnumbered;
187*e4b17023SJohn Marino if (fclose (final_output))
188*e4b17023SJohn Marino {
189*e4b17023SJohn Marino error ("could not close final insn dump file %qs: %m",
190*e4b17023SJohn Marino flag_dump_final_insns);
191*e4b17023SJohn Marino flag_dump_final_insns = NULL;
192*e4b17023SJohn Marino }
193*e4b17023SJohn Marino }
194*e4b17023SJohn Marino }
195*e4b17023SJohn Marino return todo;
196*e4b17023SJohn Marino }
197*e4b17023SJohn Marino
198*e4b17023SJohn Marino struct gimple_opt_pass pass_cleanup_cfg_post_optimizing =
199*e4b17023SJohn Marino {
200*e4b17023SJohn Marino {
201*e4b17023SJohn Marino GIMPLE_PASS,
202*e4b17023SJohn Marino "optimized", /* name */
203*e4b17023SJohn Marino NULL, /* gate */
204*e4b17023SJohn Marino execute_cleanup_cfg_post_optimizing, /* execute */
205*e4b17023SJohn Marino NULL, /* sub */
206*e4b17023SJohn Marino NULL, /* next */
207*e4b17023SJohn Marino 0, /* static_pass_number */
208*e4b17023SJohn Marino TV_TREE_CLEANUP_CFG, /* tv_id */
209*e4b17023SJohn Marino PROP_cfg, /* properties_required */
210*e4b17023SJohn Marino 0, /* properties_provided */
211*e4b17023SJohn Marino 0, /* properties_destroyed */
212*e4b17023SJohn Marino 0, /* todo_flags_start */
213*e4b17023SJohn Marino TODO_remove_unused_locals /* todo_flags_finish */
214*e4b17023SJohn Marino }
215*e4b17023SJohn Marino };
216*e4b17023SJohn Marino
217*e4b17023SJohn Marino /* Pass: do the actions required to finish with tree-ssa optimization
218*e4b17023SJohn Marino passes. */
219*e4b17023SJohn Marino
220*e4b17023SJohn Marino unsigned int
execute_free_datastructures(void)221*e4b17023SJohn Marino execute_free_datastructures (void)
222*e4b17023SJohn Marino {
223*e4b17023SJohn Marino free_dominance_info (CDI_DOMINATORS);
224*e4b17023SJohn Marino free_dominance_info (CDI_POST_DOMINATORS);
225*e4b17023SJohn Marino
226*e4b17023SJohn Marino /* And get rid of annotations we no longer need. */
227*e4b17023SJohn Marino delete_tree_cfg_annotations ();
228*e4b17023SJohn Marino
229*e4b17023SJohn Marino return 0;
230*e4b17023SJohn Marino }
231*e4b17023SJohn Marino
232*e4b17023SJohn Marino /* IPA passes, compilation of earlier functions or inlining
233*e4b17023SJohn Marino might have changed some properties, such as marked functions nothrow,
234*e4b17023SJohn Marino pure, const or noreturn.
235*e4b17023SJohn Marino Remove redundant edges and basic blocks, and create new ones if necessary.
236*e4b17023SJohn Marino
237*e4b17023SJohn Marino This pass can't be executed as stand alone pass from pass manager, because
238*e4b17023SJohn Marino in between inlining and this fixup the verify_flow_info would fail. */
239*e4b17023SJohn Marino
240*e4b17023SJohn Marino unsigned int
execute_fixup_cfg(void)241*e4b17023SJohn Marino execute_fixup_cfg (void)
242*e4b17023SJohn Marino {
243*e4b17023SJohn Marino basic_block bb;
244*e4b17023SJohn Marino gimple_stmt_iterator gsi;
245*e4b17023SJohn Marino int todo = gimple_in_ssa_p (cfun) ? TODO_verify_ssa : 0;
246*e4b17023SJohn Marino gcov_type count_scale;
247*e4b17023SJohn Marino edge e;
248*e4b17023SJohn Marino edge_iterator ei;
249*e4b17023SJohn Marino
250*e4b17023SJohn Marino if (ENTRY_BLOCK_PTR->count)
251*e4b17023SJohn Marino count_scale = ((cgraph_get_node (current_function_decl)->count
252*e4b17023SJohn Marino * REG_BR_PROB_BASE + ENTRY_BLOCK_PTR->count / 2)
253*e4b17023SJohn Marino / ENTRY_BLOCK_PTR->count);
254*e4b17023SJohn Marino else
255*e4b17023SJohn Marino count_scale = REG_BR_PROB_BASE;
256*e4b17023SJohn Marino
257*e4b17023SJohn Marino ENTRY_BLOCK_PTR->count = cgraph_get_node (current_function_decl)->count;
258*e4b17023SJohn Marino EXIT_BLOCK_PTR->count = (EXIT_BLOCK_PTR->count * count_scale
259*e4b17023SJohn Marino + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
260*e4b17023SJohn Marino
261*e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
262*e4b17023SJohn Marino e->count = (e->count * count_scale
263*e4b17023SJohn Marino + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
264*e4b17023SJohn Marino
265*e4b17023SJohn Marino FOR_EACH_BB (bb)
266*e4b17023SJohn Marino {
267*e4b17023SJohn Marino bb->count = (bb->count * count_scale
268*e4b17023SJohn Marino + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
269*e4b17023SJohn Marino for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
270*e4b17023SJohn Marino {
271*e4b17023SJohn Marino gimple stmt = gsi_stmt (gsi);
272*e4b17023SJohn Marino tree decl = is_gimple_call (stmt)
273*e4b17023SJohn Marino ? gimple_call_fndecl (stmt)
274*e4b17023SJohn Marino : NULL;
275*e4b17023SJohn Marino if (decl)
276*e4b17023SJohn Marino {
277*e4b17023SJohn Marino int flags = gimple_call_flags (stmt);
278*e4b17023SJohn Marino if (flags & (ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE))
279*e4b17023SJohn Marino {
280*e4b17023SJohn Marino if (gimple_purge_dead_abnormal_call_edges (bb))
281*e4b17023SJohn Marino todo |= TODO_cleanup_cfg;
282*e4b17023SJohn Marino
283*e4b17023SJohn Marino if (gimple_in_ssa_p (cfun))
284*e4b17023SJohn Marino {
285*e4b17023SJohn Marino todo |= TODO_update_ssa | TODO_cleanup_cfg;
286*e4b17023SJohn Marino update_stmt (stmt);
287*e4b17023SJohn Marino }
288*e4b17023SJohn Marino }
289*e4b17023SJohn Marino
290*e4b17023SJohn Marino if (flags & ECF_NORETURN
291*e4b17023SJohn Marino && fixup_noreturn_call (stmt))
292*e4b17023SJohn Marino todo |= TODO_cleanup_cfg;
293*e4b17023SJohn Marino }
294*e4b17023SJohn Marino
295*e4b17023SJohn Marino if (maybe_clean_eh_stmt (stmt)
296*e4b17023SJohn Marino && gimple_purge_dead_eh_edges (bb))
297*e4b17023SJohn Marino todo |= TODO_cleanup_cfg;
298*e4b17023SJohn Marino }
299*e4b17023SJohn Marino
300*e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs)
301*e4b17023SJohn Marino e->count = (e->count * count_scale
302*e4b17023SJohn Marino + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
303*e4b17023SJohn Marino }
304*e4b17023SJohn Marino if (count_scale != REG_BR_PROB_BASE)
305*e4b17023SJohn Marino compute_function_frequency ();
306*e4b17023SJohn Marino
307*e4b17023SJohn Marino /* We just processed all calls. */
308*e4b17023SJohn Marino if (cfun->gimple_df)
309*e4b17023SJohn Marino {
310*e4b17023SJohn Marino VEC_free (gimple, gc, MODIFIED_NORETURN_CALLS (cfun));
311*e4b17023SJohn Marino MODIFIED_NORETURN_CALLS (cfun) = NULL;
312*e4b17023SJohn Marino }
313*e4b17023SJohn Marino
314*e4b17023SJohn Marino /* Dump a textual representation of the flowgraph. */
315*e4b17023SJohn Marino if (dump_file)
316*e4b17023SJohn Marino gimple_dump_cfg (dump_file, dump_flags);
317*e4b17023SJohn Marino
318*e4b17023SJohn Marino return todo;
319*e4b17023SJohn Marino }
320*e4b17023SJohn Marino
321*e4b17023SJohn Marino struct gimple_opt_pass pass_fixup_cfg =
322*e4b17023SJohn Marino {
323*e4b17023SJohn Marino {
324*e4b17023SJohn Marino GIMPLE_PASS,
325*e4b17023SJohn Marino "*free_cfg_annotations", /* name */
326*e4b17023SJohn Marino NULL, /* gate */
327*e4b17023SJohn Marino execute_fixup_cfg, /* execute */
328*e4b17023SJohn Marino NULL, /* sub */
329*e4b17023SJohn Marino NULL, /* next */
330*e4b17023SJohn Marino 0, /* static_pass_number */
331*e4b17023SJohn Marino TV_NONE, /* tv_id */
332*e4b17023SJohn Marino PROP_cfg, /* properties_required */
333*e4b17023SJohn Marino 0, /* properties_provided */
334*e4b17023SJohn Marino 0, /* properties_destroyed */
335*e4b17023SJohn Marino 0, /* todo_flags_start */
336*e4b17023SJohn Marino 0 /* todo_flags_finish */
337*e4b17023SJohn Marino }
338*e4b17023SJohn Marino };
339*e4b17023SJohn Marino
340*e4b17023SJohn Marino /* Do the actions required to initialize internal data structures used
341*e4b17023SJohn Marino in tree-ssa optimization passes. */
342*e4b17023SJohn Marino
343*e4b17023SJohn Marino static unsigned int
execute_init_datastructures(void)344*e4b17023SJohn Marino execute_init_datastructures (void)
345*e4b17023SJohn Marino {
346*e4b17023SJohn Marino /* Allocate hash tables, arrays and other structures. */
347*e4b17023SJohn Marino init_tree_ssa (cfun);
348*e4b17023SJohn Marino return 0;
349*e4b17023SJohn Marino }
350*e4b17023SJohn Marino
351*e4b17023SJohn Marino struct gimple_opt_pass pass_init_datastructures =
352*e4b17023SJohn Marino {
353*e4b17023SJohn Marino {
354*e4b17023SJohn Marino GIMPLE_PASS,
355*e4b17023SJohn Marino "*init_datastructures", /* name */
356*e4b17023SJohn Marino NULL, /* gate */
357*e4b17023SJohn Marino execute_init_datastructures, /* execute */
358*e4b17023SJohn Marino NULL, /* sub */
359*e4b17023SJohn Marino NULL, /* next */
360*e4b17023SJohn Marino 0, /* static_pass_number */
361*e4b17023SJohn Marino TV_NONE, /* tv_id */
362*e4b17023SJohn Marino PROP_cfg, /* properties_required */
363*e4b17023SJohn Marino 0, /* properties_provided */
364*e4b17023SJohn Marino 0, /* properties_destroyed */
365*e4b17023SJohn Marino 0, /* todo_flags_start */
366*e4b17023SJohn Marino 0 /* todo_flags_finish */
367*e4b17023SJohn Marino }
368*e4b17023SJohn Marino };
369*e4b17023SJohn Marino
370*e4b17023SJohn Marino void
tree_lowering_passes(tree fn)371*e4b17023SJohn Marino tree_lowering_passes (tree fn)
372*e4b17023SJohn Marino {
373*e4b17023SJohn Marino tree saved_current_function_decl = current_function_decl;
374*e4b17023SJohn Marino
375*e4b17023SJohn Marino current_function_decl = fn;
376*e4b17023SJohn Marino push_cfun (DECL_STRUCT_FUNCTION (fn));
377*e4b17023SJohn Marino gimple_register_cfg_hooks ();
378*e4b17023SJohn Marino bitmap_obstack_initialize (NULL);
379*e4b17023SJohn Marino execute_pass_list (all_lowering_passes);
380*e4b17023SJohn Marino if (optimize && cgraph_global_info_ready)
381*e4b17023SJohn Marino execute_pass_list (pass_early_local_passes.pass.sub);
382*e4b17023SJohn Marino free_dominance_info (CDI_POST_DOMINATORS);
383*e4b17023SJohn Marino free_dominance_info (CDI_DOMINATORS);
384*e4b17023SJohn Marino compact_blocks ();
385*e4b17023SJohn Marino current_function_decl = saved_current_function_decl;
386*e4b17023SJohn Marino bitmap_obstack_release (NULL);
387*e4b17023SJohn Marino pop_cfun ();
388*e4b17023SJohn Marino }
389*e4b17023SJohn Marino
390*e4b17023SJohn Marino /* For functions-as-trees languages, this performs all optimization and
391*e4b17023SJohn Marino compilation for FNDECL. */
392*e4b17023SJohn Marino
393*e4b17023SJohn Marino void
tree_rest_of_compilation(tree fndecl)394*e4b17023SJohn Marino tree_rest_of_compilation (tree fndecl)
395*e4b17023SJohn Marino {
396*e4b17023SJohn Marino location_t saved_loc;
397*e4b17023SJohn Marino
398*e4b17023SJohn Marino timevar_push (TV_REST_OF_COMPILATION);
399*e4b17023SJohn Marino
400*e4b17023SJohn Marino gcc_assert (cgraph_global_info_ready);
401*e4b17023SJohn Marino
402*e4b17023SJohn Marino /* Initialize the default bitmap obstack. */
403*e4b17023SJohn Marino bitmap_obstack_initialize (NULL);
404*e4b17023SJohn Marino
405*e4b17023SJohn Marino /* Initialize the RTL code for the function. */
406*e4b17023SJohn Marino current_function_decl = fndecl;
407*e4b17023SJohn Marino saved_loc = input_location;
408*e4b17023SJohn Marino input_location = DECL_SOURCE_LOCATION (fndecl);
409*e4b17023SJohn Marino init_function_start (fndecl);
410*e4b17023SJohn Marino
411*e4b17023SJohn Marino gimple_register_cfg_hooks ();
412*e4b17023SJohn Marino
413*e4b17023SJohn Marino bitmap_obstack_initialize (®_obstack); /* FIXME, only at RTL generation*/
414*e4b17023SJohn Marino
415*e4b17023SJohn Marino execute_all_ipa_transforms ();
416*e4b17023SJohn Marino
417*e4b17023SJohn Marino /* Perform all tree transforms and optimizations. */
418*e4b17023SJohn Marino
419*e4b17023SJohn Marino /* Signal the start of passes. */
420*e4b17023SJohn Marino invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL);
421*e4b17023SJohn Marino
422*e4b17023SJohn Marino execute_pass_list (all_passes);
423*e4b17023SJohn Marino
424*e4b17023SJohn Marino /* Signal the end of passes. */
425*e4b17023SJohn Marino invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL);
426*e4b17023SJohn Marino
427*e4b17023SJohn Marino bitmap_obstack_release (®_obstack);
428*e4b17023SJohn Marino
429*e4b17023SJohn Marino /* Release the default bitmap obstack. */
430*e4b17023SJohn Marino bitmap_obstack_release (NULL);
431*e4b17023SJohn Marino
432*e4b17023SJohn Marino set_cfun (NULL);
433*e4b17023SJohn Marino
434*e4b17023SJohn Marino /* If requested, warn about function definitions where the function will
435*e4b17023SJohn Marino return a value (usually of some struct or union type) which itself will
436*e4b17023SJohn Marino take up a lot of stack space. */
437*e4b17023SJohn Marino if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl))
438*e4b17023SJohn Marino {
439*e4b17023SJohn Marino tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
440*e4b17023SJohn Marino
441*e4b17023SJohn Marino if (ret_type && TYPE_SIZE_UNIT (ret_type)
442*e4b17023SJohn Marino && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
443*e4b17023SJohn Marino && 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type),
444*e4b17023SJohn Marino larger_than_size))
445*e4b17023SJohn Marino {
446*e4b17023SJohn Marino unsigned int size_as_int
447*e4b17023SJohn Marino = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
448*e4b17023SJohn Marino
449*e4b17023SJohn Marino if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
450*e4b17023SJohn Marino warning (OPT_Wlarger_than_, "size of return value of %q+D is %u bytes",
451*e4b17023SJohn Marino fndecl, size_as_int);
452*e4b17023SJohn Marino else
453*e4b17023SJohn Marino warning (OPT_Wlarger_than_, "size of return value of %q+D is larger than %wd bytes",
454*e4b17023SJohn Marino fndecl, larger_than_size);
455*e4b17023SJohn Marino }
456*e4b17023SJohn Marino }
457*e4b17023SJohn Marino
458*e4b17023SJohn Marino gimple_set_body (fndecl, NULL);
459*e4b17023SJohn Marino if (DECL_STRUCT_FUNCTION (fndecl) == 0
460*e4b17023SJohn Marino && !cgraph_get_node (fndecl)->origin)
461*e4b17023SJohn Marino {
462*e4b17023SJohn Marino /* Stop pointing to the local nodes about to be freed.
463*e4b17023SJohn Marino But DECL_INITIAL must remain nonzero so we know this
464*e4b17023SJohn Marino was an actual function definition.
465*e4b17023SJohn Marino For a nested function, this is done in c_pop_function_context.
466*e4b17023SJohn Marino If rest_of_compilation set this to 0, leave it 0. */
467*e4b17023SJohn Marino if (DECL_INITIAL (fndecl) != 0)
468*e4b17023SJohn Marino DECL_INITIAL (fndecl) = error_mark_node;
469*e4b17023SJohn Marino }
470*e4b17023SJohn Marino
471*e4b17023SJohn Marino input_location = saved_loc;
472*e4b17023SJohn Marino
473*e4b17023SJohn Marino ggc_collect ();
474*e4b17023SJohn Marino timevar_pop (TV_REST_OF_COMPILATION);
475*e4b17023SJohn Marino }
476