1 /* Top-level control of tree optimizations.
2 Copyright (C) 2001-2013 Free Software Foundation, Inc.
3 Contributed by Diego Novillo <dnovillo@redhat.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
27 #include "basic-block.h"
29 #include "tree-flow.h"
31 #include "langhooks.h"
32 #include "diagnostic-core.h"
36 #include "tree-inline.h"
37 #include "tree-pass.h"
45 /* Pass: cleanup the CFG just before expanding trees to RTL.
46 This is just a round of label cleanups and case node grouping
47 because after the tree optimizers have run such cleanups may
51 execute_cleanup_cfg_post_optimizing (void)
53 unsigned int todo
= 0;
54 if (cleanup_tree_cfg ())
55 todo
|= TODO_update_ssa
;
56 maybe_remove_unreachable_handlers ();
57 cleanup_dead_labels ();
59 if ((flag_compare_debug_opt
|| flag_compare_debug
)
60 && flag_dump_final_insns
)
62 FILE *final_output
= fopen (flag_dump_final_insns
, "a");
66 error ("could not open final insn dump file %qs: %m",
67 flag_dump_final_insns
);
68 flag_dump_final_insns
= NULL
;
72 int save_unnumbered
= flag_dump_unnumbered
;
73 int save_noaddr
= flag_dump_noaddr
;
75 flag_dump_noaddr
= flag_dump_unnumbered
= 1;
76 fprintf (final_output
, "\n");
77 dump_enumerated_decls (final_output
, dump_flags
| TDF_NOUID
);
78 flag_dump_noaddr
= save_noaddr
;
79 flag_dump_unnumbered
= save_unnumbered
;
80 if (fclose (final_output
))
82 error ("could not close final insn dump file %qs: %m",
83 flag_dump_final_insns
);
84 flag_dump_final_insns
= NULL
;
93 const pass_data pass_data_cleanup_cfg_post_optimizing
=
95 GIMPLE_PASS
, /* type */
96 "optimized", /* name */
97 OPTGROUP_NONE
, /* optinfo_flags */
99 true, /* has_execute */
100 TV_TREE_CLEANUP_CFG
, /* tv_id */
101 PROP_cfg
, /* properties_required */
102 0, /* properties_provided */
103 0, /* properties_destroyed */
104 0, /* todo_flags_start */
105 TODO_remove_unused_locals
, /* todo_flags_finish */
108 class pass_cleanup_cfg_post_optimizing
: public gimple_opt_pass
111 pass_cleanup_cfg_post_optimizing(gcc::context
*ctxt
)
112 : gimple_opt_pass(pass_data_cleanup_cfg_post_optimizing
, ctxt
)
115 /* opt_pass methods: */
116 unsigned int execute () {
117 return execute_cleanup_cfg_post_optimizing ();
120 }; // class pass_cleanup_cfg_post_optimizing
125 make_pass_cleanup_cfg_post_optimizing (gcc::context
*ctxt
)
127 return new pass_cleanup_cfg_post_optimizing (ctxt
);
130 /* IPA passes, compilation of earlier functions or inlining
131 might have changed some properties, such as marked functions nothrow,
132 pure, const or noreturn.
133 Remove redundant edges and basic blocks, and create new ones if necessary.
135 This pass can't be executed as stand alone pass from pass manager, because
136 in between inlining and this fixup the verify_flow_info would fail. */
139 execute_fixup_cfg (void)
142 gimple_stmt_iterator gsi
;
143 int todo
= gimple_in_ssa_p (cfun
) ? TODO_verify_ssa
: 0;
144 gcov_type count_scale
;
149 = GCOV_COMPUTE_SCALE (cgraph_get_node (current_function_decl
)->count
,
150 ENTRY_BLOCK_PTR
->count
);
152 ENTRY_BLOCK_PTR
->count
= cgraph_get_node (current_function_decl
)->count
;
153 EXIT_BLOCK_PTR
->count
= apply_scale (EXIT_BLOCK_PTR
->count
,
156 FOR_EACH_EDGE (e
, ei
, ENTRY_BLOCK_PTR
->succs
)
157 e
->count
= apply_scale (e
->count
, count_scale
);
161 bb
->count
= apply_scale (bb
->count
, count_scale
);
162 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
164 gimple stmt
= gsi_stmt (gsi
);
165 tree decl
= is_gimple_call (stmt
)
166 ? gimple_call_fndecl (stmt
)
170 int flags
= gimple_call_flags (stmt
);
171 if (flags
& (ECF_CONST
| ECF_PURE
| ECF_LOOPING_CONST_OR_PURE
))
173 if (gimple_purge_dead_abnormal_call_edges (bb
))
174 todo
|= TODO_cleanup_cfg
;
176 if (gimple_in_ssa_p (cfun
))
178 todo
|= TODO_update_ssa
| TODO_cleanup_cfg
;
183 if (flags
& ECF_NORETURN
184 && fixup_noreturn_call (stmt
))
185 todo
|= TODO_cleanup_cfg
;
188 if (maybe_clean_eh_stmt (stmt
)
189 && gimple_purge_dead_eh_edges (bb
))
190 todo
|= TODO_cleanup_cfg
;
193 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
194 e
->count
= apply_scale (e
->count
, count_scale
);
196 /* If we have a basic block with no successors that does not
197 end with a control statement or a noreturn call end it with
198 a call to __builtin_unreachable. This situation can occur
199 when inlining a noreturn call that does in fact return. */
200 if (EDGE_COUNT (bb
->succs
) == 0)
202 gimple stmt
= last_stmt (bb
);
204 || (!is_ctrl_stmt (stmt
)
205 && (!is_gimple_call (stmt
)
206 || (gimple_call_flags (stmt
) & ECF_NORETURN
) == 0)))
208 stmt
= gimple_build_call
209 (builtin_decl_implicit (BUILT_IN_UNREACHABLE
), 0);
210 gimple_stmt_iterator gsi
= gsi_last_bb (bb
);
211 gsi_insert_after (&gsi
, stmt
, GSI_NEW_STMT
);
215 if (count_scale
!= REG_BR_PROB_BASE
)
216 compute_function_frequency ();
218 /* We just processed all calls. */
220 vec_free (MODIFIED_NORETURN_CALLS (cfun
));
222 /* Dump a textual representation of the flowgraph. */
224 gimple_dump_cfg (dump_file
, dump_flags
);
227 && (todo
& TODO_cleanup_cfg
))
228 loops_state_set (LOOPS_NEED_FIXUP
);
235 const pass_data pass_data_fixup_cfg
=
237 GIMPLE_PASS
, /* type */
238 "*free_cfg_annotations", /* name */
239 OPTGROUP_NONE
, /* optinfo_flags */
240 false, /* has_gate */
241 true, /* has_execute */
243 PROP_cfg
, /* properties_required */
244 0, /* properties_provided */
245 0, /* properties_destroyed */
246 0, /* todo_flags_start */
247 0, /* todo_flags_finish */
250 class pass_fixup_cfg
: public gimple_opt_pass
253 pass_fixup_cfg(gcc::context
*ctxt
)
254 : gimple_opt_pass(pass_data_fixup_cfg
, ctxt
)
257 /* opt_pass methods: */
258 opt_pass
* clone () { return new pass_fixup_cfg (ctxt_
); }
259 unsigned int execute () { return execute_fixup_cfg (); }
261 }; // class pass_fixup_cfg
266 make_pass_fixup_cfg (gcc::context
*ctxt
)
268 return new pass_fixup_cfg (ctxt
);