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
;
91 struct gimple_opt_pass pass_cleanup_cfg_post_optimizing
=
95 "optimized", /* name */
96 OPTGROUP_NONE
, /* optinfo_flags */
98 execute_cleanup_cfg_post_optimizing
, /* execute */
101 0, /* static_pass_number */
102 TV_TREE_CLEANUP_CFG
, /* tv_id */
103 PROP_cfg
, /* properties_required */
104 0, /* properties_provided */
105 0, /* properties_destroyed */
106 0, /* todo_flags_start */
107 TODO_remove_unused_locals
/* todo_flags_finish */
111 /* IPA passes, compilation of earlier functions or inlining
112 might have changed some properties, such as marked functions nothrow,
113 pure, const or noreturn.
114 Remove redundant edges and basic blocks, and create new ones if necessary.
116 This pass can't be executed as stand alone pass from pass manager, because
117 in between inlining and this fixup the verify_flow_info would fail. */
120 execute_fixup_cfg (void)
123 gimple_stmt_iterator gsi
;
124 int todo
= gimple_in_ssa_p (cfun
) ? TODO_verify_ssa
: 0;
125 gcov_type count_scale
;
129 if (ENTRY_BLOCK_PTR
->count
)
130 count_scale
= ((cgraph_get_node (current_function_decl
)->count
131 * REG_BR_PROB_BASE
+ ENTRY_BLOCK_PTR
->count
/ 2)
132 / ENTRY_BLOCK_PTR
->count
);
134 count_scale
= REG_BR_PROB_BASE
;
136 ENTRY_BLOCK_PTR
->count
= cgraph_get_node (current_function_decl
)->count
;
137 EXIT_BLOCK_PTR
->count
= (EXIT_BLOCK_PTR
->count
* count_scale
138 + REG_BR_PROB_BASE
/ 2) / REG_BR_PROB_BASE
;
140 FOR_EACH_EDGE (e
, ei
, ENTRY_BLOCK_PTR
->succs
)
141 e
->count
= (e
->count
* count_scale
142 + REG_BR_PROB_BASE
/ 2) / REG_BR_PROB_BASE
;
146 bb
->count
= (bb
->count
* count_scale
147 + REG_BR_PROB_BASE
/ 2) / REG_BR_PROB_BASE
;
148 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
150 gimple stmt
= gsi_stmt (gsi
);
151 tree decl
= is_gimple_call (stmt
)
152 ? gimple_call_fndecl (stmt
)
156 int flags
= gimple_call_flags (stmt
);
157 if (flags
& (ECF_CONST
| ECF_PURE
| ECF_LOOPING_CONST_OR_PURE
))
159 if (gimple_purge_dead_abnormal_call_edges (bb
))
160 todo
|= TODO_cleanup_cfg
;
162 if (gimple_in_ssa_p (cfun
))
164 todo
|= TODO_update_ssa
| TODO_cleanup_cfg
;
169 if (flags
& ECF_NORETURN
170 && fixup_noreturn_call (stmt
))
171 todo
|= TODO_cleanup_cfg
;
174 if (maybe_clean_eh_stmt (stmt
)
175 && gimple_purge_dead_eh_edges (bb
))
176 todo
|= TODO_cleanup_cfg
;
179 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
180 e
->count
= (e
->count
* count_scale
181 + REG_BR_PROB_BASE
/ 2) / REG_BR_PROB_BASE
;
183 /* If we have a basic block with no successors that does not
184 end with a control statement or a noreturn call end it with
185 a call to __builtin_unreachable. This situation can occur
186 when inlining a noreturn call that does in fact return. */
187 if (EDGE_COUNT (bb
->succs
) == 0)
189 gimple stmt
= last_stmt (bb
);
191 || (!is_ctrl_stmt (stmt
)
192 && (!is_gimple_call (stmt
)
193 || (gimple_call_flags (stmt
) & ECF_NORETURN
) == 0)))
195 stmt
= gimple_build_call
196 (builtin_decl_implicit (BUILT_IN_UNREACHABLE
), 0);
197 gimple_stmt_iterator gsi
= gsi_last_bb (bb
);
198 gsi_insert_after (&gsi
, stmt
, GSI_NEW_STMT
);
202 if (count_scale
!= REG_BR_PROB_BASE
)
203 compute_function_frequency ();
205 /* We just processed all calls. */
207 vec_free (MODIFIED_NORETURN_CALLS (cfun
));
209 /* Dump a textual representation of the flowgraph. */
211 gimple_dump_cfg (dump_file
, dump_flags
);
216 struct gimple_opt_pass pass_fixup_cfg
=
220 "*free_cfg_annotations", /* name */
221 OPTGROUP_NONE
, /* optinfo_flags */
223 execute_fixup_cfg
, /* execute */
226 0, /* static_pass_number */
228 PROP_cfg
, /* properties_required */
229 0, /* properties_provided */
230 0, /* properties_destroyed */
231 0, /* todo_flags_start */
232 0 /* todo_flags_finish */