xref: /dflybsd-src/contrib/gcc-4.7/gcc/tree-optimize.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
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 (&reg_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 (&reg_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