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