lto-cgraph.c (get_alias_symbol): Remove weakref sanity check.
[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-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_scale (EXIT_BLOCK_PTR->count,
135 count_scale);
136
137 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
138 e->count = apply_scale (e->count, count_scale);
139
140 FOR_EACH_BB (bb)
141 {
142 bb->count = apply_scale (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_scale (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 if (current_loops
208 && (todo & TODO_cleanup_cfg))
209 loops_state_set (LOOPS_NEED_FIXUP);
210
211 return todo;
212 }
213
214 struct gimple_opt_pass pass_fixup_cfg =
215 {
216 {
217 GIMPLE_PASS,
218 "*free_cfg_annotations", /* name */
219 OPTGROUP_NONE, /* optinfo_flags */
220 NULL, /* gate */
221 execute_fixup_cfg, /* execute */
222 NULL, /* sub */
223 NULL, /* next */
224 0, /* static_pass_number */
225 TV_NONE, /* tv_id */
226 PROP_cfg, /* properties_required */
227 0, /* properties_provided */
228 0, /* properties_destroyed */
229 0, /* todo_flags_start */
230 0 /* todo_flags_finish */
231 }
232 };