00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "config.h"
00026 #include "system.h"
00027 #include "coretypes.h"
00028 #include "tm.h"
00029 #include "tree.h"
00030 #include "rtl.h"
00031 #include "tm_p.h"
00032 #include "hard-reg-set.h"
00033 #include "basic-block.h"
00034 #include "output.h"
00035 #include "expr.h"
00036 #include "diagnostic.h"
00037 #include "basic-block.h"
00038 #include "flags.h"
00039 #include "tree-flow.h"
00040 #include "tree-dump.h"
00041 #include "timevar.h"
00042 #include "function.h"
00043 #include "langhooks.h"
00044 #include "toplev.h"
00045 #include "flags.h"
00046 #include "cgraph.h"
00047 #include "tree-inline.h"
00048 #include "tree-mudflap.h"
00049 #include "tree-pass.h"
00050 #include "ggc.h"
00051 #include "cgraph.h"
00052 #include "graph.h"
00053 #include "cfgloop.h"
00054 #include "except.h"
00055
00056
00057
00058
00059 static bool
00060 gate_all_optimizations (void)
00061 {
00062 return (optimize >= 1
00063
00064 && !(errorcount || sorrycount));
00065 }
00066
00067 struct tree_opt_pass pass_all_optimizations =
00068 {
00069 NULL,
00070 gate_all_optimizations,
00071 NULL,
00072 NULL,
00073 NULL,
00074 0,
00075 0,
00076 0,
00077 0,
00078 0,
00079 0,
00080 0,
00081 0
00082 };
00083
00084 struct tree_opt_pass pass_early_local_passes =
00085 {
00086 NULL,
00087 gate_all_optimizations,
00088 NULL,
00089 NULL,
00090 NULL,
00091 0,
00092 0,
00093 0,
00094 0,
00095 0,
00096 0,
00097 0,
00098 0
00099 };
00100
00101
00102
00103
00104
00105
00106 static unsigned int
00107 execute_cleanup_cfg_pre_ipa (void)
00108 {
00109 cleanup_tree_cfg ();
00110 return 0;
00111 }
00112
00113 struct tree_opt_pass pass_cleanup_cfg =
00114 {
00115 "cleanup_cfg",
00116 NULL,
00117 execute_cleanup_cfg_pre_ipa,
00118 NULL,
00119 NULL,
00120 0,
00121 0,
00122 PROP_cfg,
00123 0,
00124 0,
00125 0,
00126 TODO_dump_func,
00127 0
00128 };
00129
00130
00131
00132
00133
00134
00135
00136 static unsigned int
00137 execute_cleanup_cfg_post_optimizing (void)
00138 {
00139 fold_cond_expr_cond ();
00140 cleanup_tree_cfg ();
00141 cleanup_dead_labels ();
00142 group_case_labels ();
00143 return 0;
00144 }
00145
00146 struct tree_opt_pass pass_cleanup_cfg_post_optimizing =
00147 {
00148 "final_cleanup",
00149 NULL,
00150 execute_cleanup_cfg_post_optimizing,
00151 NULL,
00152 NULL,
00153 0,
00154 0,
00155 PROP_cfg,
00156 0,
00157 0,
00158 0,
00159 TODO_dump_func,
00160 0
00161 };
00162
00163
00164
00165
00166 static unsigned int
00167 execute_free_datastructures (void)
00168 {
00169
00170
00171 free_dominance_info (CDI_DOMINATORS);
00172 free_dominance_info (CDI_POST_DOMINATORS);
00173
00174
00175
00176 delete_tree_ssa ();
00177 return 0;
00178 }
00179
00180 struct tree_opt_pass pass_free_datastructures =
00181 {
00182 NULL,
00183 NULL,
00184 execute_free_datastructures,
00185 NULL,
00186 NULL,
00187 0,
00188 0,
00189 PROP_cfg,
00190 0,
00191 0,
00192 0,
00193 0,
00194 0
00195 };
00196
00197
00198 static unsigned int
00199 execute_free_cfg_annotations (void)
00200 {
00201 basic_block bb;
00202 block_stmt_iterator bsi;
00203
00204
00205 disband_implicit_edges ();
00206
00207
00208 FOR_EACH_BB (bb)
00209 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
00210 {
00211 tree stmt = bsi_stmt (bsi);
00212 ggc_free (stmt->common.ann);
00213 stmt->common.ann = NULL;
00214 }
00215
00216
00217 delete_tree_cfg_annotations ();
00218
00219 #ifdef ENABLE_CHECKING
00220
00221
00222 verify_eh_throw_table_statements ();
00223 #endif
00224 return 0;
00225 }
00226
00227 struct tree_opt_pass pass_free_cfg_annotations =
00228 {
00229 NULL,
00230 NULL,
00231 execute_free_cfg_annotations,
00232 NULL,
00233 NULL,
00234 0,
00235 0,
00236 PROP_cfg,
00237 0,
00238 0,
00239 0,
00240 0,
00241 0
00242 };
00243
00244
00245
00246 static inline bool
00247 has_abnormal_outgoing_edge_p (basic_block bb)
00248 {
00249 edge e;
00250 edge_iterator ei;
00251
00252 FOR_EACH_EDGE (e, ei, bb->succs)
00253 if (e->flags & EDGE_ABNORMAL)
00254 return true;
00255
00256 return false;
00257 }
00258
00259
00260
00261
00262
00263
00264 static unsigned int
00265 execute_fixup_cfg (void)
00266 {
00267 basic_block bb;
00268 block_stmt_iterator bsi;
00269
00270 if (cfun->eh)
00271 FOR_EACH_BB (bb)
00272 {
00273 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
00274 {
00275 tree stmt = bsi_stmt (bsi);
00276 tree call = get_call_expr_in (stmt);
00277
00278 if (call && call_expr_flags (call) & (ECF_CONST | ECF_PURE))
00279 TREE_SIDE_EFFECTS (call) = 0;
00280 if (!tree_could_throw_p (stmt) && lookup_stmt_eh_region (stmt))
00281 remove_stmt_from_eh_region (stmt);
00282 }
00283 tree_purge_dead_eh_edges (bb);
00284 }
00285
00286 if (current_function_has_nonlocal_label)
00287 FOR_EACH_BB (bb)
00288 {
00289 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
00290 {
00291 tree stmt = bsi_stmt (bsi);
00292 if (tree_can_make_abnormal_goto (stmt))
00293 {
00294 if (stmt == bsi_stmt (bsi_last (bb)))
00295 {
00296 if (!has_abnormal_outgoing_edge_p (bb))
00297 make_abnormal_goto_edges (bb, true);
00298 }
00299 else
00300 {
00301 edge e = split_block (bb, stmt);
00302 bb = e->src;
00303 make_abnormal_goto_edges (bb, true);
00304 }
00305 break;
00306 }
00307 }
00308 }
00309
00310 cleanup_tree_cfg ();
00311
00312
00313 if (dump_file)
00314 dump_tree_cfg (dump_file, dump_flags);
00315
00316 return 0;
00317 }
00318
00319 struct tree_opt_pass pass_fixup_cfg =
00320 {
00321 "fixupcfg",
00322 NULL,
00323 execute_fixup_cfg,
00324 NULL,
00325 NULL,
00326 0,
00327 0,
00328 PROP_cfg,
00329 0,
00330 0,
00331 0,
00332 0,
00333 0
00334 };
00335
00336
00337
00338
00339 static unsigned int
00340 execute_init_datastructures (void)
00341 {
00342
00343 init_tree_ssa ();
00344 return 0;
00345 }
00346
00347 struct tree_opt_pass pass_init_datastructures =
00348 {
00349 NULL,
00350 NULL,
00351 execute_init_datastructures,
00352 NULL,
00353 NULL,
00354 0,
00355 0,
00356 PROP_cfg,
00357 0,
00358 0,
00359 0,
00360 0,
00361 0
00362 };
00363
00364 void
00365 tree_lowering_passes (tree fn)
00366 {
00367 tree saved_current_function_decl = current_function_decl;
00368
00369 current_function_decl = fn;
00370 push_cfun (DECL_STRUCT_FUNCTION (fn));
00371
00372 #ifdef KEY
00373
00374
00375 if (!strcmp("GNU C++", lang_hooks.name) &&
00376 flag_spin_file &&
00377 lang_hooks.cp_genericize ) {
00378 gs_x_func_decl(fn);
00379
00380 lang_hooks.cp_genericize(fn);
00381
00382 walk_tree_without_duplicates (&DECL_SAVED_TREE (fn),
00383 lang_hooks.simplify_aggr_init_exprs_r,
00384 NULL);
00385 }
00386 #endif
00387
00388 tree_register_cfg_hooks ();
00389 bitmap_obstack_initialize (NULL);
00390 execute_pass_list (all_lowering_passes);
00391 free_dominance_info (CDI_POST_DOMINATORS);
00392 compact_blocks ();
00393 current_function_decl = saved_current_function_decl;
00394 bitmap_obstack_release (NULL);
00395 pop_cfun ();
00396 }
00397
00398
00399
00400 static void
00401 update_inlined_to_pointers (struct cgraph_node *node,
00402 struct cgraph_node *inlined_to)
00403 {
00404 struct cgraph_edge *e;
00405 for (e = node->callees; e; e = e->next_callee)
00406 {
00407 if (e->callee->global.inlined_to)
00408 {
00409 e->callee->global.inlined_to = inlined_to;
00410 update_inlined_to_pointers (e->callee, inlined_to);
00411 }
00412 }
00413 }
00414
00415
00416
00417
00418
00419 void
00420 tree_rest_of_compilation (tree fndecl)
00421 {
00422 location_t saved_loc;
00423 struct cgraph_node *node;
00424
00425 timevar_push (TV_EXPAND);
00426
00427 gcc_assert (!flag_unit_at_a_time || cgraph_global_info_ready);
00428
00429 node = cgraph_node (fndecl);
00430
00431
00432
00433 if (cgraph_preserve_function_body_p (fndecl))
00434 save_inline_function_body (node);
00435
00436
00437 current_function_decl = fndecl;
00438 saved_loc = input_location;
00439 input_location = DECL_SOURCE_LOCATION (fndecl);
00440 init_function_start (fndecl);
00441
00442
00443
00444
00445
00446 cfun->x_dont_save_pending_sizes_p = 1;
00447 cfun->after_inlining = true;
00448
00449 if (flag_inline_trees)
00450 {
00451 struct cgraph_edge *e;
00452 for (e = node->callees; e; e = e->next_callee)
00453 if (!e->inline_failed || warn_inline)
00454 break;
00455 if (e)
00456 {
00457 timevar_push (TV_INTEGRATION);
00458 optimize_inline_calls (fndecl);
00459 timevar_pop (TV_INTEGRATION);
00460 }
00461 }
00462
00463
00464 if (!flag_unit_at_a_time)
00465 {
00466 struct cgraph_edge *e;
00467 for (e = node->callees; e; e = e->next_callee)
00468 if (e->callee->analyzed)
00469 cgraph_mark_needed_node (e->callee);
00470 }
00471
00472
00473
00474 cgraph_node_remove_callees (node);
00475
00476
00477
00478 bitmap_obstack_initialize (NULL);
00479 bitmap_obstack_initialize (®_obstack);
00480
00481 tree_register_cfg_hooks ();
00482
00483 execute_pass_list (all_passes);
00484
00485 bitmap_obstack_release (®_obstack);
00486
00487
00488 bitmap_obstack_release (NULL);
00489
00490 DECL_SAVED_TREE (fndecl) = NULL;
00491 cfun = 0;
00492
00493
00494
00495
00496 if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl))
00497 {
00498 tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
00499
00500 if (ret_type && TYPE_SIZE_UNIT (ret_type)
00501 && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
00502 && 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type),
00503 larger_than_size))
00504 {
00505 unsigned int size_as_int
00506 = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
00507
00508 if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
00509 warning (0, "size of return value of %q+D is %u bytes",
00510 fndecl, size_as_int);
00511 else
00512 warning (0, "size of return value of %q+D is larger than %wd bytes",
00513 fndecl, larger_than_size);
00514 }
00515 }
00516
00517 if (!flag_inline_trees)
00518 {
00519 DECL_SAVED_TREE (fndecl) = NULL;
00520 if (DECL_STRUCT_FUNCTION (fndecl) == 0
00521 && !cgraph_node (fndecl)->origin)
00522 {
00523
00524
00525
00526
00527
00528 if (DECL_INITIAL (fndecl) != 0)
00529 DECL_INITIAL (fndecl) = error_mark_node;
00530 }
00531 }
00532
00533 input_location = saved_loc;
00534
00535 ggc_collect ();
00536 timevar_pop (TV_EXPAND);
00537 }