OSDN Git Service

2013-04-12 Hristian Kirtchev <kirtchev@adacore.com>
[pf3gnuchains/gcc-fork.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   count_scale
130       = GCOV_COMPUTE_SCALE (cgraph_get_node (current_function_decl)->count,
131                             ENTRY_BLOCK_PTR->count);
132
133   ENTRY_BLOCK_PTR->count = cgraph_get_node (current_function_decl)->count;
134   EXIT_BLOCK_PTR->count = apply_probability (EXIT_BLOCK_PTR->count,
135                                              count_scale);
136
137   FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
138     e->count = apply_probability (e->count, count_scale);
139
140   FOR_EACH_BB (bb)
141     {
142       bb->count = apply_probability (bb->count, count_scale);
143       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
144         {
145           gimple stmt = gsi_stmt (gsi);
146           tree decl = is_gimple_call (stmt)
147                       ? gimple_call_fndecl (stmt)
148                       : NULL;
149           if (decl)
150             {
151               int flags = gimple_call_flags (stmt);
152               if (flags & (ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE))
153                 {
154                   if (gimple_purge_dead_abnormal_call_edges (bb))
155                     todo |= TODO_cleanup_cfg;
156
157                   if (gimple_in_ssa_p (cfun))
158                     {
159                       todo |= TODO_update_ssa | TODO_cleanup_cfg;
160                       update_stmt (stmt);
161                     }
162                 }
163
164               if (flags & ECF_NORETURN
165                   && fixup_noreturn_call (stmt))
166                 todo |= TODO_cleanup_cfg;
167              }
168
169           if (maybe_clean_eh_stmt (stmt)
170               && gimple_purge_dead_eh_edges (bb))
171             todo |= TODO_cleanup_cfg;
172         }
173
174       FOR_EACH_EDGE (e, ei, bb->succs)
175         e->count = apply_probability (e->count, count_scale);
176
177       /* If we have a basic block with no successors that does not
178          end with a control statement or a noreturn call end it with
179          a call to __builtin_unreachable.  This situation can occur
180          when inlining a noreturn call that does in fact return.  */
181       if (EDGE_COUNT (bb->succs) == 0)
182         {
183           gimple stmt = last_stmt (bb);
184           if (!stmt
185               || (!is_ctrl_stmt (stmt)
186                   && (!is_gimple_call (stmt)
187                       || (gimple_call_flags (stmt) & ECF_NORETURN) == 0)))
188             {
189               stmt = gimple_build_call
190                   (builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0);
191               gimple_stmt_iterator gsi = gsi_last_bb (bb);
192               gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
193             }
194         }
195     }
196   if (count_scale != REG_BR_PROB_BASE)
197     compute_function_frequency ();
198
199   /* We just processed all calls.  */
200   if (cfun->gimple_df)
201     vec_free (MODIFIED_NORETURN_CALLS (cfun));
202
203   /* Dump a textual representation of the flowgraph.  */
204   if (dump_file)
205     gimple_dump_cfg (dump_file, dump_flags);
206
207   return todo;
208 }
209
210 struct gimple_opt_pass pass_fixup_cfg =
211 {
212  {
213   GIMPLE_PASS,
214   "*free_cfg_annotations",              /* name */
215   OPTGROUP_NONE,                        /* optinfo_flags */
216   NULL,                                 /* gate */
217   execute_fixup_cfg,                    /* execute */
218   NULL,                                 /* sub */
219   NULL,                                 /* next */
220   0,                                    /* static_pass_number */
221   TV_NONE,                              /* tv_id */
222   PROP_cfg,                             /* properties_required */
223   0,                                    /* properties_provided */
224   0,                                    /* properties_destroyed */
225   0,                                    /* todo_flags_start */
226   0                                     /* todo_flags_finish */
227  }
228 };