0c278d0292c09ae09784bef70fe3fe06229dd015
[platform/upstream/linaro-gcc.git] / gcc / tree-optimize.c
1 /* Top-level control of tree optimizations.
2    Copyright (C) 2001-2013 Free Software Foundation, Inc.
3    Contributed by Diego Novillo <dnovillo@redhat.com>
4
5 This file is part of GCC.
6
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.
11
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.
16
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/>.  */
20
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-ssa.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"
43
44
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.  */
49
50 static unsigned int
51 execute_cleanup_cfg_post_optimizing (void)
52 {
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)
61     {
62       FILE *final_output = fopen (flag_dump_final_insns, "a");
63
64       if (!final_output)
65         {
66           error ("could not open final insn dump file %qs: %m",
67                  flag_dump_final_insns);
68           flag_dump_final_insns = NULL;
69         }
70       else
71         {
72           int save_unnumbered = flag_dump_unnumbered;
73           int save_noaddr = flag_dump_noaddr;
74
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))
81             {
82               error ("could not close final insn dump file %qs: %m",
83                      flag_dump_final_insns);
84               flag_dump_final_insns = NULL;
85             }
86         }
87     }
88   return todo;
89 }
90
91 namespace {
92
93 const pass_data pass_data_cleanup_cfg_post_optimizing =
94 {
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 */
106 };
107
108 class pass_cleanup_cfg_post_optimizing : public gimple_opt_pass
109 {
110 public:
111   pass_cleanup_cfg_post_optimizing(gcc::context *ctxt)
112     : gimple_opt_pass(pass_data_cleanup_cfg_post_optimizing, ctxt)
113   {}
114
115   /* opt_pass methods: */
116   unsigned int execute () {
117     return execute_cleanup_cfg_post_optimizing ();
118   }
119
120 }; // class pass_cleanup_cfg_post_optimizing
121
122 } // anon namespace
123
124 gimple_opt_pass *
125 make_pass_cleanup_cfg_post_optimizing (gcc::context *ctxt)
126 {
127   return new pass_cleanup_cfg_post_optimizing (ctxt);
128 }
129
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.
134
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.  */
137
138 unsigned int
139 execute_fixup_cfg (void)
140 {
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;
147
148   count_scale
149       = GCOV_COMPUTE_SCALE (cgraph_get_node (current_function_decl)->count,
150                             ENTRY_BLOCK_PTR->count);
151
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);
155
156   FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
157     e->count = apply_scale (e->count, count_scale);
158
159   FOR_EACH_BB (bb)
160     {
161       bb->count = apply_scale (bb->count, count_scale);
162       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
163         {
164           gimple stmt = gsi_stmt (gsi);
165           tree decl = is_gimple_call (stmt)
166                       ? gimple_call_fndecl (stmt)
167                       : NULL;
168           if (decl)
169             {
170               int flags = gimple_call_flags (stmt);
171               if (flags & (ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE))
172                 {
173                   if (gimple_purge_dead_abnormal_call_edges (bb))
174                     todo |= TODO_cleanup_cfg;
175
176                   if (gimple_in_ssa_p (cfun))
177                     {
178                       todo |= TODO_update_ssa | TODO_cleanup_cfg;
179                       update_stmt (stmt);
180                     }
181                 }
182
183               if (flags & ECF_NORETURN
184                   && fixup_noreturn_call (stmt))
185                 todo |= TODO_cleanup_cfg;
186              }
187
188           if (maybe_clean_eh_stmt (stmt)
189               && gimple_purge_dead_eh_edges (bb))
190             todo |= TODO_cleanup_cfg;
191         }
192
193       FOR_EACH_EDGE (e, ei, bb->succs)
194         e->count = apply_scale (e->count, count_scale);
195
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)
201         {
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)))
207             {
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);
212             }
213         }
214     }
215   if (count_scale != REG_BR_PROB_BASE)
216     compute_function_frequency ();
217
218   /* We just processed all calls.  */
219   if (cfun->gimple_df)
220     vec_free (MODIFIED_NORETURN_CALLS (cfun));
221
222   /* Dump a textual representation of the flowgraph.  */
223   if (dump_file)
224     gimple_dump_cfg (dump_file, dump_flags);
225
226   if (current_loops
227       && (todo & TODO_cleanup_cfg))
228     loops_state_set (LOOPS_NEED_FIXUP);
229
230   return todo;
231 }
232
233 namespace {
234
235 const pass_data pass_data_fixup_cfg =
236 {
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 */
248 };
249
250 class pass_fixup_cfg : public gimple_opt_pass
251 {
252 public:
253   pass_fixup_cfg(gcc::context *ctxt)
254     : gimple_opt_pass(pass_data_fixup_cfg, ctxt)
255   {}
256
257   /* opt_pass methods: */
258   opt_pass * clone () { return new pass_fixup_cfg (ctxt_); }
259   unsigned int execute () { return execute_fixup_cfg (); }
260
261 }; // class pass_fixup_cfg
262
263 } // anon namespace
264
265 gimple_opt_pass *
266 make_pass_fixup_cfg (gcc::context *ctxt)
267 {
268   return new pass_fixup_cfg (ctxt);
269 }