2012-12-01 Alessandro Fanfarillo <alessandro.fanfarillo@gmail.com>
[official-gcc.git] / gcc / tree-optimize.c
blob48f7d450b10304232497bbb4e1adf5db931b49bf
1 /* Top-level control of tree optimizations.
2 Copyright 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
4 Contributed by Diego Novillo <dnovillo@redhat.com>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "tree.h"
27 #include "tm_p.h"
28 #include "basic-block.h"
29 #include "flags.h"
30 #include "tree-flow.h"
31 #include "function.h"
32 #include "langhooks.h"
33 #include "diagnostic-core.h"
34 #include "toplev.h"
35 #include "flags.h"
36 #include "cgraph.h"
37 #include "tree-inline.h"
38 #include "tree-pass.h"
39 #include "ggc.h"
40 #include "cgraph.h"
41 #include "cfgloop.h"
42 #include "except.h"
43 #include "plugin.h"
46 /* Pass: cleanup the CFG just before expanding trees to RTL.
47 This is just a round of label cleanups and case node grouping
48 because after the tree optimizers have run such cleanups may
49 be necessary. */
51 static unsigned int
52 execute_cleanup_cfg_post_optimizing (void)
54 unsigned int todo = 0;
55 if (cleanup_tree_cfg ())
56 todo |= TODO_update_ssa;
57 maybe_remove_unreachable_handlers ();
58 cleanup_dead_labels ();
59 group_case_labels ();
60 if ((flag_compare_debug_opt || flag_compare_debug)
61 && flag_dump_final_insns)
63 FILE *final_output = fopen (flag_dump_final_insns, "a");
65 if (!final_output)
67 error ("could not open final insn dump file %qs: %m",
68 flag_dump_final_insns);
69 flag_dump_final_insns = NULL;
71 else
73 int save_unnumbered = flag_dump_unnumbered;
74 int save_noaddr = flag_dump_noaddr;
76 flag_dump_noaddr = flag_dump_unnumbered = 1;
77 fprintf (final_output, "\n");
78 dump_enumerated_decls (final_output, dump_flags | TDF_NOUID);
79 flag_dump_noaddr = save_noaddr;
80 flag_dump_unnumbered = save_unnumbered;
81 if (fclose (final_output))
83 error ("could not close final insn dump file %qs: %m",
84 flag_dump_final_insns);
85 flag_dump_final_insns = NULL;
89 return todo;
92 struct gimple_opt_pass pass_cleanup_cfg_post_optimizing =
95 GIMPLE_PASS,
96 "optimized", /* name */
97 OPTGROUP_NONE, /* optinfo_flags */
98 NULL, /* gate */
99 execute_cleanup_cfg_post_optimizing, /* execute */
100 NULL, /* sub */
101 NULL, /* next */
102 0, /* static_pass_number */
103 TV_TREE_CLEANUP_CFG, /* tv_id */
104 PROP_cfg, /* properties_required */
105 0, /* properties_provided */
106 0, /* properties_destroyed */
107 0, /* todo_flags_start */
108 TODO_remove_unused_locals /* todo_flags_finish */
112 /* IPA passes, compilation of earlier functions or inlining
113 might have changed some properties, such as marked functions nothrow,
114 pure, const or noreturn.
115 Remove redundant edges and basic blocks, and create new ones if necessary.
117 This pass can't be executed as stand alone pass from pass manager, because
118 in between inlining and this fixup the verify_flow_info would fail. */
120 unsigned int
121 execute_fixup_cfg (void)
123 basic_block bb;
124 gimple_stmt_iterator gsi;
125 int todo = gimple_in_ssa_p (cfun) ? TODO_verify_ssa : 0;
126 gcov_type count_scale;
127 edge e;
128 edge_iterator ei;
130 if (ENTRY_BLOCK_PTR->count)
131 count_scale = ((cgraph_get_node (current_function_decl)->count
132 * REG_BR_PROB_BASE + ENTRY_BLOCK_PTR->count / 2)
133 / ENTRY_BLOCK_PTR->count);
134 else
135 count_scale = REG_BR_PROB_BASE;
137 ENTRY_BLOCK_PTR->count = cgraph_get_node (current_function_decl)->count;
138 EXIT_BLOCK_PTR->count = (EXIT_BLOCK_PTR->count * count_scale
139 + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
141 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
142 e->count = (e->count * count_scale
143 + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
145 FOR_EACH_BB (bb)
147 bb->count = (bb->count * count_scale
148 + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
149 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
151 gimple stmt = gsi_stmt (gsi);
152 tree decl = is_gimple_call (stmt)
153 ? gimple_call_fndecl (stmt)
154 : NULL;
155 if (decl)
157 int flags = gimple_call_flags (stmt);
158 if (flags & (ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE))
160 if (gimple_purge_dead_abnormal_call_edges (bb))
161 todo |= TODO_cleanup_cfg;
163 if (gimple_in_ssa_p (cfun))
165 todo |= TODO_update_ssa | TODO_cleanup_cfg;
166 update_stmt (stmt);
170 if (flags & ECF_NORETURN
171 && fixup_noreturn_call (stmt))
172 todo |= TODO_cleanup_cfg;
175 if (maybe_clean_eh_stmt (stmt)
176 && gimple_purge_dead_eh_edges (bb))
177 todo |= TODO_cleanup_cfg;
180 FOR_EACH_EDGE (e, ei, bb->succs)
181 e->count = (e->count * count_scale
182 + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
184 /* If we have a basic block with no successors that does not
185 end with a control statement or a noreturn call end it with
186 a call to __builtin_unreachable. This situation can occur
187 when inlining a noreturn call that does in fact return. */
188 if (EDGE_COUNT (bb->succs) == 0)
190 gimple stmt = last_stmt (bb);
191 if (!stmt
192 || (!is_ctrl_stmt (stmt)
193 && (!is_gimple_call (stmt)
194 || (gimple_call_flags (stmt) & ECF_NORETURN) == 0)))
196 stmt = gimple_build_call
197 (builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0);
198 gimple_stmt_iterator gsi = gsi_last_bb (bb);
199 gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
203 if (count_scale != REG_BR_PROB_BASE)
204 compute_function_frequency ();
206 /* We just processed all calls. */
207 if (cfun->gimple_df)
208 vec_free (MODIFIED_NORETURN_CALLS (cfun));
210 /* Dump a textual representation of the flowgraph. */
211 if (dump_file)
212 gimple_dump_cfg (dump_file, dump_flags);
214 return todo;
217 struct gimple_opt_pass pass_fixup_cfg =
220 GIMPLE_PASS,
221 "*free_cfg_annotations", /* name */
222 OPTGROUP_NONE, /* optinfo_flags */
223 NULL, /* gate */
224 execute_fixup_cfg, /* execute */
225 NULL, /* sub */
226 NULL, /* next */
227 0, /* static_pass_number */
228 TV_NONE, /* tv_id */
229 PROP_cfg, /* properties_required */
230 0, /* properties_provided */
231 0, /* properties_destroyed */
232 0, /* todo_flags_start */
233 0 /* todo_flags_finish */