PR rtl-optimization/53827
[official-gcc.git] / gcc / tree-optimize.c
blobb48c5c50e48ab3cd8287c4952413787302116555
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 "tree-dump.h"
32 #include "timevar.h"
33 #include "function.h"
34 #include "langhooks.h"
35 #include "diagnostic-core.h"
36 #include "toplev.h"
37 #include "flags.h"
38 #include "cgraph.h"
39 #include "tree-inline.h"
40 #include "tree-pass.h"
41 #include "ggc.h"
42 #include "cgraph.h"
43 #include "graph.h"
44 #include "cfgloop.h"
45 #include "except.h"
46 #include "plugin.h"
49 /* Pass: cleanup the CFG just before expanding trees to RTL.
50 This is just a round of label cleanups and case node grouping
51 because after the tree optimizers have run such cleanups may
52 be necessary. */
54 static unsigned int
55 execute_cleanup_cfg_post_optimizing (void)
57 unsigned int todo = 0;
58 if (cleanup_tree_cfg ())
59 todo |= TODO_update_ssa;
60 maybe_remove_unreachable_handlers ();
61 cleanup_dead_labels ();
62 group_case_labels ();
63 if ((flag_compare_debug_opt || flag_compare_debug)
64 && flag_dump_final_insns)
66 FILE *final_output = fopen (flag_dump_final_insns, "a");
68 if (!final_output)
70 error ("could not open final insn dump file %qs: %m",
71 flag_dump_final_insns);
72 flag_dump_final_insns = NULL;
74 else
76 int save_unnumbered = flag_dump_unnumbered;
77 int save_noaddr = flag_dump_noaddr;
79 flag_dump_noaddr = flag_dump_unnumbered = 1;
80 fprintf (final_output, "\n");
81 dump_enumerated_decls (final_output, dump_flags | TDF_NOUID);
82 flag_dump_noaddr = save_noaddr;
83 flag_dump_unnumbered = save_unnumbered;
84 if (fclose (final_output))
86 error ("could not close final insn dump file %qs: %m",
87 flag_dump_final_insns);
88 flag_dump_final_insns = NULL;
92 return todo;
95 struct gimple_opt_pass pass_cleanup_cfg_post_optimizing =
98 GIMPLE_PASS,
99 "optimized", /* name */
100 NULL, /* gate */
101 execute_cleanup_cfg_post_optimizing, /* execute */
102 NULL, /* sub */
103 NULL, /* next */
104 0, /* static_pass_number */
105 TV_TREE_CLEANUP_CFG, /* tv_id */
106 PROP_cfg, /* properties_required */
107 0, /* properties_provided */
108 0, /* properties_destroyed */
109 0, /* todo_flags_start */
110 TODO_remove_unused_locals /* todo_flags_finish */
114 /* IPA passes, compilation of earlier functions or inlining
115 might have changed some properties, such as marked functions nothrow,
116 pure, const or noreturn.
117 Remove redundant edges and basic blocks, and create new ones if necessary.
119 This pass can't be executed as stand alone pass from pass manager, because
120 in between inlining and this fixup the verify_flow_info would fail. */
122 unsigned int
123 execute_fixup_cfg (void)
125 basic_block bb;
126 gimple_stmt_iterator gsi;
127 int todo = gimple_in_ssa_p (cfun) ? TODO_verify_ssa : 0;
128 gcov_type count_scale;
129 edge e;
130 edge_iterator ei;
132 if (ENTRY_BLOCK_PTR->count)
133 count_scale = ((cgraph_get_node (current_function_decl)->count
134 * REG_BR_PROB_BASE + ENTRY_BLOCK_PTR->count / 2)
135 / ENTRY_BLOCK_PTR->count);
136 else
137 count_scale = REG_BR_PROB_BASE;
139 ENTRY_BLOCK_PTR->count = cgraph_get_node (current_function_decl)->count;
140 EXIT_BLOCK_PTR->count = (EXIT_BLOCK_PTR->count * count_scale
141 + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
143 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
144 e->count = (e->count * count_scale
145 + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
147 FOR_EACH_BB (bb)
149 bb->count = (bb->count * count_scale
150 + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
151 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
153 gimple stmt = gsi_stmt (gsi);
154 tree decl = is_gimple_call (stmt)
155 ? gimple_call_fndecl (stmt)
156 : NULL;
157 if (decl)
159 int flags = gimple_call_flags (stmt);
160 if (flags & (ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE))
162 if (gimple_purge_dead_abnormal_call_edges (bb))
163 todo |= TODO_cleanup_cfg;
165 if (gimple_in_ssa_p (cfun))
167 todo |= TODO_update_ssa | TODO_cleanup_cfg;
168 update_stmt (stmt);
172 if (flags & ECF_NORETURN
173 && fixup_noreturn_call (stmt))
174 todo |= TODO_cleanup_cfg;
177 if (maybe_clean_eh_stmt (stmt)
178 && gimple_purge_dead_eh_edges (bb))
179 todo |= TODO_cleanup_cfg;
182 FOR_EACH_EDGE (e, ei, bb->succs)
183 e->count = (e->count * count_scale
184 + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
186 if (count_scale != REG_BR_PROB_BASE)
187 compute_function_frequency ();
189 /* We just processed all calls. */
190 if (cfun->gimple_df)
192 VEC_free (gimple, gc, MODIFIED_NORETURN_CALLS (cfun));
193 MODIFIED_NORETURN_CALLS (cfun) = NULL;
196 /* Dump a textual representation of the flowgraph. */
197 if (dump_file)
198 gimple_dump_cfg (dump_file, dump_flags);
200 return todo;
203 struct gimple_opt_pass pass_fixup_cfg =
206 GIMPLE_PASS,
207 "*free_cfg_annotations", /* name */
208 NULL, /* gate */
209 execute_fixup_cfg, /* execute */
210 NULL, /* sub */
211 NULL, /* next */
212 0, /* static_pass_number */
213 TV_NONE, /* tv_id */
214 PROP_cfg, /* properties_required */
215 0, /* properties_provided */
216 0, /* properties_destroyed */
217 0, /* todo_flags_start */
218 0 /* todo_flags_finish */