New vectorizer messages; message format change.
[official-gcc.git] / gcc / tree-optimize.c
blob9c99ec23a2e7bd623d0f498bdbdb1f18d73a291c
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)
10 any later version.
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/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "tree.h"
26 #include "tm_p.h"
27 #include "basic-block.h"
28 #include "flags.h"
29 #include "tree-flow.h"
30 #include "function.h"
31 #include "langhooks.h"
32 #include "diagnostic-core.h"
33 #include "toplev.h"
34 #include "flags.h"
35 #include "cgraph.h"
36 #include "tree-inline.h"
37 #include "tree-pass.h"
38 #include "ggc.h"
39 #include "cgraph.h"
40 #include "cfgloop.h"
41 #include "except.h"
42 #include "plugin.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
48 be necessary. */
50 static unsigned int
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 ();
58 group_case_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");
64 if (!final_output)
66 error ("could not open final insn dump file %qs: %m",
67 flag_dump_final_insns);
68 flag_dump_final_insns = NULL;
70 else
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;
88 return todo;
91 namespace {
93 const pass_data pass_data_cleanup_cfg_post_optimizing =
95 GIMPLE_PASS, /* type */
96 "optimized", /* name */
97 OPTGROUP_NONE, /* optinfo_flags */
98 false, /* has_gate */
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
110 public:
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
122 } // anon namespace
124 gimple_opt_pass *
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. */
138 unsigned int
139 execute_fixup_cfg (void)
141 basic_block bb;
142 gimple_stmt_iterator gsi;
143 int todo = gimple_in_ssa_p (cfun) ? TODO_verify_ssa : 0;
144 gcov_type count_scale;
145 edge e;
146 edge_iterator ei;
148 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,
154 count_scale);
156 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
157 e->count = apply_scale (e->count, count_scale);
159 FOR_EACH_BB (bb)
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)
167 : NULL;
168 if (decl)
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;
179 update_stmt (stmt);
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);
203 if (!stmt
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. */
219 if (cfun->gimple_df)
220 vec_free (MODIFIED_NORETURN_CALLS (cfun));
222 /* Dump a textual representation of the flowgraph. */
223 if (dump_file)
224 gimple_dump_cfg (dump_file, dump_flags);
226 if (current_loops
227 && (todo & TODO_cleanup_cfg))
228 loops_state_set (LOOPS_NEED_FIXUP);
230 return todo;
233 namespace {
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 */
242 TV_NONE, /* tv_id */
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
252 public:
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
263 } // anon namespace
265 gimple_opt_pass *
266 make_pass_fixup_cfg (gcc::context *ctxt)
268 return new pass_fixup_cfg (ctxt);