Mercurial > hg > CbC > CbC_gcc
comparison gcc/tree-optimize.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children |
comparison
equal
deleted
inserted
replaced
65:65488c3d617d | 67:f6334be47118 |
---|---|
1 /* Top-level control of tree optimizations. | 1 /* Top-level control of tree optimizations. |
2 Copyright 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 | 2 Copyright 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 |
3 Free Software Foundation, Inc. | 3 Free Software Foundation, Inc. |
4 Contributed by Diego Novillo <dnovillo@redhat.com> | 4 Contributed by Diego Novillo <dnovillo@redhat.com> |
5 | 5 |
6 This file is part of GCC. | 6 This file is part of GCC. |
7 | 7 |
25 #include "tm.h" | 25 #include "tm.h" |
26 #include "tree.h" | 26 #include "tree.h" |
27 #include "tm_p.h" | 27 #include "tm_p.h" |
28 #include "basic-block.h" | 28 #include "basic-block.h" |
29 #include "output.h" | 29 #include "output.h" |
30 #include "diagnostic.h" | |
31 #include "basic-block.h" | |
32 #include "flags.h" | 30 #include "flags.h" |
33 #include "tree-flow.h" | 31 #include "tree-flow.h" |
34 #include "tree-dump.h" | 32 #include "tree-dump.h" |
35 #include "timevar.h" | 33 #include "timevar.h" |
36 #include "function.h" | 34 #include "function.h" |
37 #include "langhooks.h" | 35 #include "langhooks.h" |
36 #include "diagnostic-core.h" | |
38 #include "toplev.h" | 37 #include "toplev.h" |
39 #include "flags.h" | 38 #include "flags.h" |
40 #include "cgraph.h" | 39 #include "cgraph.h" |
41 #include "tree-inline.h" | 40 #include "tree-inline.h" |
42 #include "tree-mudflap.h" | 41 #include "tree-mudflap.h" |
55 gate_all_optimizations (void) | 54 gate_all_optimizations (void) |
56 { | 55 { |
57 return (optimize >= 1 | 56 return (optimize >= 1 |
58 /* Don't bother doing anything if the program has errors. | 57 /* Don't bother doing anything if the program has errors. |
59 We have to pass down the queue if we already went into SSA */ | 58 We have to pass down the queue if we already went into SSA */ |
60 && (!(errorcount || sorrycount) || gimple_in_ssa_p (cfun))); | 59 && (!seen_error () || gimple_in_ssa_p (cfun))); |
61 } | 60 } |
62 | 61 |
63 struct gimple_opt_pass pass_all_optimizations = | 62 struct gimple_opt_pass pass_all_optimizations = |
64 { | 63 { |
65 { | 64 { |
68 gate_all_optimizations, /* gate */ | 67 gate_all_optimizations, /* gate */ |
69 NULL, /* execute */ | 68 NULL, /* execute */ |
70 NULL, /* sub */ | 69 NULL, /* sub */ |
71 NULL, /* next */ | 70 NULL, /* next */ |
72 0, /* static_pass_number */ | 71 0, /* static_pass_number */ |
73 TV_NONE, /* tv_id */ | 72 TV_OPTIMIZE, /* tv_id */ |
74 0, /* properties_required */ | 73 0, /* properties_required */ |
75 0, /* properties_provided */ | 74 0, /* properties_provided */ |
76 0, /* properties_destroyed */ | 75 0, /* properties_destroyed */ |
77 0, /* todo_flags_start */ | 76 0, /* todo_flags_start */ |
78 0 /* todo_flags_finish */ | 77 0 /* todo_flags_finish */ |
83 | 82 |
84 static bool | 83 static bool |
85 gate_all_early_local_passes (void) | 84 gate_all_early_local_passes (void) |
86 { | 85 { |
87 /* Don't bother doing anything if the program has errors. */ | 86 /* Don't bother doing anything if the program has errors. */ |
88 return (!errorcount && !sorrycount && !in_lto_p); | 87 return (!seen_error () && !in_lto_p); |
88 } | |
89 | |
90 static unsigned int | |
91 execute_all_early_local_passes (void) | |
92 { | |
93 /* Once this pass (and its sub-passes) are complete, all functions | |
94 will be in SSA form. Technically this state change is happening | |
95 a tad early, since the sub-passes have not yet run, but since | |
96 none of the sub-passes are IPA passes and do not create new | |
97 functions, this is ok. We're setting this value for the benefit | |
98 of IPA passes that follow. */ | |
99 if (cgraph_state < CGRAPH_STATE_IPA_SSA) | |
100 cgraph_state = CGRAPH_STATE_IPA_SSA; | |
101 return 0; | |
89 } | 102 } |
90 | 103 |
91 struct simple_ipa_opt_pass pass_early_local_passes = | 104 struct simple_ipa_opt_pass pass_early_local_passes = |
92 { | 105 { |
93 { | 106 { |
94 SIMPLE_IPA_PASS, | 107 SIMPLE_IPA_PASS, |
95 "early_local_cleanups", /* name */ | 108 "early_local_cleanups", /* name */ |
96 gate_all_early_local_passes, /* gate */ | 109 gate_all_early_local_passes, /* gate */ |
97 NULL, /* execute */ | 110 execute_all_early_local_passes, /* execute */ |
98 NULL, /* sub */ | 111 NULL, /* sub */ |
99 NULL, /* next */ | 112 NULL, /* next */ |
100 0, /* static_pass_number */ | 113 0, /* static_pass_number */ |
101 TV_NONE, /* tv_id */ | 114 TV_EARLY_LOCAL, /* tv_id */ |
102 0, /* properties_required */ | 115 0, /* properties_required */ |
103 0, /* properties_provided */ | 116 0, /* properties_provided */ |
104 0, /* properties_destroyed */ | 117 0, /* properties_destroyed */ |
105 0, /* todo_flags_start */ | 118 0, /* todo_flags_start */ |
106 TODO_remove_functions /* todo_flags_finish */ | 119 TODO_remove_functions /* todo_flags_finish */ |
107 } | 120 } |
108 }; | 121 }; |
109 | |
110 static unsigned int | |
111 execute_early_local_optimizations (void) | |
112 { | |
113 /* First time we start with early optimization we need to advance | |
114 cgraph state so newly inserted functions are also early optimized. | |
115 However we execute early local optimizations for lately inserted | |
116 functions, in that case don't reset cgraph state back to IPA_SSA. */ | |
117 if (cgraph_state < CGRAPH_STATE_IPA_SSA) | |
118 cgraph_state = CGRAPH_STATE_IPA_SSA; | |
119 return 0; | |
120 } | |
121 | 122 |
122 /* Gate: execute, or not, all of the non-trivial optimizations. */ | 123 /* Gate: execute, or not, all of the non-trivial optimizations. */ |
123 | 124 |
124 static bool | 125 static bool |
125 gate_all_early_optimizations (void) | 126 gate_all_early_optimizations (void) |
126 { | 127 { |
127 return (optimize >= 1 | 128 return (optimize >= 1 |
128 /* Don't bother doing anything if the program has errors. */ | 129 /* Don't bother doing anything if the program has errors. */ |
129 && !(errorcount || sorrycount)); | 130 && !seen_error ()); |
130 } | 131 } |
131 | 132 |
132 struct gimple_opt_pass pass_all_early_optimizations = | 133 struct gimple_opt_pass pass_all_early_optimizations = |
133 { | 134 { |
134 { | 135 { |
135 GIMPLE_PASS, | 136 GIMPLE_PASS, |
136 "early_optimizations", /* name */ | 137 "early_optimizations", /* name */ |
137 gate_all_early_optimizations, /* gate */ | 138 gate_all_early_optimizations, /* gate */ |
138 execute_early_local_optimizations, /* execute */ | 139 NULL, /* execute */ |
139 NULL, /* sub */ | 140 NULL, /* sub */ |
140 NULL, /* next */ | 141 NULL, /* next */ |
141 0, /* static_pass_number */ | 142 0, /* static_pass_number */ |
142 TV_NONE, /* tv_id */ | 143 TV_NONE, /* tv_id */ |
143 0, /* properties_required */ | 144 0, /* properties_required */ |
145 0, /* properties_destroyed */ | 146 0, /* properties_destroyed */ |
146 0, /* todo_flags_start */ | 147 0, /* todo_flags_start */ |
147 0 /* todo_flags_finish */ | 148 0 /* todo_flags_finish */ |
148 } | 149 } |
149 }; | 150 }; |
151 | |
150 | 152 |
151 /* Pass: cleanup the CFG just before expanding trees to RTL. | 153 /* Pass: cleanup the CFG just before expanding trees to RTL. |
152 This is just a round of label cleanups and case node grouping | 154 This is just a round of label cleanups and case node grouping |
153 because after the tree optimizers have run such cleanups may | 155 because after the tree optimizers have run such cleanups may |
154 be necessary. */ | 156 be necessary. */ |
155 | 157 |
156 static unsigned int | 158 static unsigned int |
157 execute_cleanup_cfg_pre_ipa (void) | |
158 { | |
159 cleanup_tree_cfg (); | |
160 return 0; | |
161 } | |
162 | |
163 struct gimple_opt_pass pass_cleanup_cfg = | |
164 { | |
165 { | |
166 GIMPLE_PASS, | |
167 "cleanup_cfg", /* name */ | |
168 NULL, /* gate */ | |
169 execute_cleanup_cfg_pre_ipa, /* execute */ | |
170 NULL, /* sub */ | |
171 NULL, /* next */ | |
172 0, /* static_pass_number */ | |
173 TV_NONE, /* tv_id */ | |
174 PROP_cfg, /* properties_required */ | |
175 0, /* properties_provided */ | |
176 0, /* properties_destroyed */ | |
177 0, /* todo_flags_start */ | |
178 TODO_dump_func /* todo_flags_finish */ | |
179 } | |
180 }; | |
181 | |
182 | |
183 /* Pass: cleanup the CFG just before expanding trees to RTL. | |
184 This is just a round of label cleanups and case node grouping | |
185 because after the tree optimizers have run such cleanups may | |
186 be necessary. */ | |
187 | |
188 static unsigned int | |
189 execute_cleanup_cfg_post_optimizing (void) | 159 execute_cleanup_cfg_post_optimizing (void) |
190 { | 160 { |
191 fold_cond_expr_cond (); | |
192 cleanup_tree_cfg (); | 161 cleanup_tree_cfg (); |
193 cleanup_dead_labels (); | 162 cleanup_dead_labels (); |
194 group_case_labels (); | 163 group_case_labels (); |
164 if ((flag_compare_debug_opt || flag_compare_debug) | |
165 && flag_dump_final_insns) | |
166 { | |
167 FILE *final_output = fopen (flag_dump_final_insns, "a"); | |
168 | |
169 if (!final_output) | |
170 { | |
171 error ("could not open final insn dump file %qs: %m", | |
172 flag_dump_final_insns); | |
173 flag_dump_final_insns = NULL; | |
174 } | |
175 else | |
176 { | |
177 int save_unnumbered = flag_dump_unnumbered; | |
178 int save_noaddr = flag_dump_noaddr; | |
179 | |
180 flag_dump_noaddr = flag_dump_unnumbered = 1; | |
181 fprintf (final_output, "\n"); | |
182 dump_enumerated_decls (final_output, dump_flags | TDF_NOUID); | |
183 flag_dump_noaddr = save_noaddr; | |
184 flag_dump_unnumbered = save_unnumbered; | |
185 if (fclose (final_output)) | |
186 { | |
187 error ("could not close final insn dump file %qs: %m", | |
188 flag_dump_final_insns); | |
189 flag_dump_final_insns = NULL; | |
190 } | |
191 } | |
192 } | |
195 return 0; | 193 return 0; |
196 } | 194 } |
197 | 195 |
198 struct gimple_opt_pass pass_cleanup_cfg_post_optimizing = | 196 struct gimple_opt_pass pass_cleanup_cfg_post_optimizing = |
199 { | 197 { |
203 NULL, /* gate */ | 201 NULL, /* gate */ |
204 execute_cleanup_cfg_post_optimizing, /* execute */ | 202 execute_cleanup_cfg_post_optimizing, /* execute */ |
205 NULL, /* sub */ | 203 NULL, /* sub */ |
206 NULL, /* next */ | 204 NULL, /* next */ |
207 0, /* static_pass_number */ | 205 0, /* static_pass_number */ |
208 TV_NONE, /* tv_id */ | 206 TV_TREE_CLEANUP_CFG, /* tv_id */ |
209 PROP_cfg, /* properties_required */ | 207 PROP_cfg, /* properties_required */ |
210 0, /* properties_provided */ | 208 0, /* properties_provided */ |
211 0, /* properties_destroyed */ | 209 0, /* properties_destroyed */ |
212 0, /* todo_flags_start */ | 210 0, /* todo_flags_start */ |
213 TODO_dump_func /* todo_flags_finish */ | 211 TODO_dump_func /* todo_flags_finish */ |
228 delete_tree_cfg_annotations (); | 226 delete_tree_cfg_annotations (); |
229 | 227 |
230 return 0; | 228 return 0; |
231 } | 229 } |
232 | 230 |
233 /* Pass: fixup_cfg. IPA passes, compilation of earlier functions or inlining | 231 /* IPA passes, compilation of earlier functions or inlining |
234 might have changed some properties, such as marked functions nothrow. | 232 might have changed some properties, such as marked functions nothrow, |
233 pure, const or noreturn. | |
235 Remove redundant edges and basic blocks, and create new ones if necessary. | 234 Remove redundant edges and basic blocks, and create new ones if necessary. |
236 | 235 |
237 This pass can't be executed as stand alone pass from pass manager, because | 236 This pass can't be executed as stand alone pass from pass manager, because |
238 in between inlining and this fixup the verify_flow_info would fail. */ | 237 in between inlining and this fixup the verify_flow_info would fail. */ |
239 | 238 |
265 { | 264 { |
266 gimple stmt = gsi_stmt (gsi); | 265 gimple stmt = gsi_stmt (gsi); |
267 tree decl = is_gimple_call (stmt) | 266 tree decl = is_gimple_call (stmt) |
268 ? gimple_call_fndecl (stmt) | 267 ? gimple_call_fndecl (stmt) |
269 : NULL; | 268 : NULL; |
270 | 269 if (decl) |
271 if (decl | |
272 && gimple_call_flags (stmt) & (ECF_CONST | |
273 | ECF_PURE | |
274 | ECF_LOOPING_CONST_OR_PURE)) | |
275 { | 270 { |
276 if (gimple_in_ssa_p (cfun)) | 271 int flags = gimple_call_flags (stmt); |
272 if (flags & (ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE)) | |
277 { | 273 { |
278 todo |= TODO_update_ssa | TODO_cleanup_cfg; | 274 if (gimple_purge_dead_abnormal_call_edges (bb)) |
279 mark_symbols_for_renaming (stmt); | 275 todo |= TODO_cleanup_cfg; |
280 update_stmt (stmt); | 276 |
277 if (gimple_in_ssa_p (cfun)) | |
278 { | |
279 todo |= TODO_update_ssa | TODO_cleanup_cfg; | |
280 update_stmt (stmt); | |
281 } | |
281 } | 282 } |
282 } | 283 |
283 | 284 if (flags & ECF_NORETURN |
284 maybe_clean_eh_stmt (stmt); | 285 && fixup_noreturn_call (stmt)) |
286 todo |= TODO_cleanup_cfg; | |
287 } | |
288 | |
289 if (maybe_clean_eh_stmt (stmt) | |
290 && gimple_purge_dead_eh_edges (bb)) | |
291 todo |= TODO_cleanup_cfg; | |
285 } | 292 } |
286 | 293 |
287 if (gimple_purge_dead_eh_edges (bb)) | |
288 todo |= TODO_cleanup_cfg; | |
289 FOR_EACH_EDGE (e, ei, bb->succs) | 294 FOR_EACH_EDGE (e, ei, bb->succs) |
290 e->count = (e->count * count_scale | 295 e->count = (e->count * count_scale |
291 + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE; | 296 + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE; |
292 } | 297 } |
293 if (count_scale != REG_BR_PROB_BASE) | 298 if (count_scale != REG_BR_PROB_BASE) |
294 compute_function_frequency (); | 299 compute_function_frequency (); |
300 | |
301 /* We just processed all calls. */ | |
302 if (cfun->gimple_df) | |
303 { | |
304 VEC_free (gimple, gc, MODIFIED_NORETURN_CALLS (cfun)); | |
305 MODIFIED_NORETURN_CALLS (cfun) = NULL; | |
306 } | |
295 | 307 |
296 /* Dump a textual representation of the flowgraph. */ | 308 /* Dump a textual representation of the flowgraph. */ |
297 if (dump_file) | 309 if (dump_file) |
298 gimple_dump_cfg (dump_file, dump_flags); | 310 gimple_dump_cfg (dump_file, dump_flags); |
299 | 311 |
375 void | 387 void |
376 tree_rest_of_compilation (tree fndecl) | 388 tree_rest_of_compilation (tree fndecl) |
377 { | 389 { |
378 location_t saved_loc; | 390 location_t saved_loc; |
379 | 391 |
380 timevar_push (TV_EXPAND); | 392 timevar_push (TV_REST_OF_COMPILATION); |
381 | 393 |
382 gcc_assert (cgraph_global_info_ready); | 394 gcc_assert (cgraph_global_info_ready); |
383 | 395 |
384 /* Initialize the default bitmap obstack. */ | 396 /* Initialize the default bitmap obstack. */ |
385 bitmap_obstack_initialize (NULL); | 397 bitmap_obstack_initialize (NULL); |
433 { | 445 { |
434 unsigned int size_as_int | 446 unsigned int size_as_int |
435 = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type)); | 447 = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type)); |
436 | 448 |
437 if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0) | 449 if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0) |
438 warning (OPT_Wlarger_than_eq, "size of return value of %q+D is %u bytes", | 450 warning (OPT_Wlarger_than_, "size of return value of %q+D is %u bytes", |
439 fndecl, size_as_int); | 451 fndecl, size_as_int); |
440 else | 452 else |
441 warning (OPT_Wlarger_than_eq, "size of return value of %q+D is larger than %wd bytes", | 453 warning (OPT_Wlarger_than_, "size of return value of %q+D is larger than %wd bytes", |
442 fndecl, larger_than_size); | 454 fndecl, larger_than_size); |
443 } | 455 } |
444 } | 456 } |
445 | 457 |
446 gimple_set_body (fndecl, NULL); | 458 gimple_set_body (fndecl, NULL); |
457 } | 469 } |
458 | 470 |
459 input_location = saved_loc; | 471 input_location = saved_loc; |
460 | 472 |
461 ggc_collect (); | 473 ggc_collect (); |
462 timevar_pop (TV_EXPAND); | 474 timevar_pop (TV_REST_OF_COMPILATION); |
463 } | 475 } |