Update change log
[platform/upstream/gcc48.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-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"
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 struct gimple_opt_pass pass_cleanup_cfg_post_optimizing =
92 {
93  {
94   GIMPLE_PASS,
95   "optimized",                          /* name */
96   OPTGROUP_NONE,                        /* optinfo_flags */
97   NULL,                                 /* gate */
98   execute_cleanup_cfg_post_optimizing,  /* execute */
99   NULL,                                 /* sub */
100   NULL,                                 /* next */
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 */
108  }
109 };
110
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.
115
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.  */
118
119 unsigned int
120 execute_fixup_cfg (void)
121 {
122   basic_block bb;
123   gimple_stmt_iterator gsi;
124   int todo = gimple_in_ssa_p (cfun) ? TODO_verify_ssa : 0;
125   gcov_type count_scale;
126   edge e;
127   edge_iterator ei;
128
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);
133   else
134     count_scale = REG_BR_PROB_BASE;
135
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;
139
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;
143
144   FOR_EACH_BB (bb)
145     {
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))
149         {
150           gimple stmt = gsi_stmt (gsi);
151           tree decl = is_gimple_call (stmt)
152                       ? gimple_call_fndecl (stmt)
153                       : NULL;
154           if (decl)
155             {
156               int flags = gimple_call_flags (stmt);
157               if (flags & (ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE))
158                 {
159                   if (gimple_purge_dead_abnormal_call_edges (bb))
160                     todo |= TODO_cleanup_cfg;
161
162                   if (gimple_in_ssa_p (cfun))
163                     {
164                       todo |= TODO_update_ssa | TODO_cleanup_cfg;
165                       update_stmt (stmt);
166                     }
167                 }
168
169               if (flags & ECF_NORETURN
170                   && fixup_noreturn_call (stmt))
171                 todo |= TODO_cleanup_cfg;
172              }
173
174           if (maybe_clean_eh_stmt (stmt)
175               && gimple_purge_dead_eh_edges (bb))
176             todo |= TODO_cleanup_cfg;
177         }
178
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;
182
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)
188         {
189           gimple stmt = last_stmt (bb);
190           if (!stmt
191               || (!is_ctrl_stmt (stmt)
192                   && (!is_gimple_call (stmt)
193                       || (gimple_call_flags (stmt) & ECF_NORETURN) == 0)))
194             {
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);
199             }
200         }
201     }
202   if (count_scale != REG_BR_PROB_BASE)
203     compute_function_frequency ();
204
205   /* We just processed all calls.  */
206   if (cfun->gimple_df)
207     vec_free (MODIFIED_NORETURN_CALLS (cfun));
208
209   /* Dump a textual representation of the flowgraph.  */
210   if (dump_file)
211     gimple_dump_cfg (dump_file, dump_flags);
212
213   return todo;
214 }
215
216 struct gimple_opt_pass pass_fixup_cfg =
217 {
218  {
219   GIMPLE_PASS,
220   "*free_cfg_annotations",              /* name */
221   OPTGROUP_NONE,                        /* optinfo_flags */
222   NULL,                                 /* gate */
223   execute_fixup_cfg,                    /* execute */
224   NULL,                                 /* sub */
225   NULL,                                 /* next */
226   0,                                    /* static_pass_number */
227   TV_NONE,                              /* tv_id */
228   PROP_cfg,                             /* properties_required */
229   0,                                    /* properties_provided */
230   0,                                    /* properties_destroyed */
231   0,                                    /* todo_flags_start */
232   0                                     /* todo_flags_finish */
233  }
234 };