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
00026 #include "config.h"
00027 #include "system.h"
00028 #include "coretypes.h"
00029 #include "tm.h"
00030 #include "tree.h"
00031 #include "rtl.h"
00032 #include "tm_p.h"
00033 #include "hard-reg-set.h"
00034 #include "basic-block.h"
00035 #include "output.h"
00036 #include "expr.h"
00037 #include "diagnostic.h"
00038 #include "basic-block.h"
00039 #include "flags.h"
00040 #include "tree-flow.h"
00041 #include "tree-dump.h"
00042 #include "timevar.h"
00043 #include "function.h"
00044 #include "langhooks.h"
00045 #include "toplev.h"
00046 #include "flags.h"
00047 #include "cgraph.h"
00048 #include "tree-inline.h"
00049 #include "tree-mudflap.h"
00050 #include "tree-pass.h"
00051 #include "ggc.h"
00052 #include "cgraph.h"
00053 #include "graph.h"
00054
00055
00056
00057 int dump_flags;
00058 bitmap vars_to_rename;
00059 bool in_gimple_form;
00060
00061
00062 static struct tree_opt_pass *all_passes;
00063
00064
00065
00066 static struct tree_opt_pass pass_gimple =
00067 {
00068 "gimple",
00069 NULL,
00070 NULL,
00071 NULL,
00072 NULL,
00073 0,
00074 0,
00075 0,
00076 PROP_gimple_any,
00077 0,
00078 0,
00079 TODO_dump_func,
00080 0
00081 };
00082
00083
00084
00085 static bool
00086 gate_all_optimizations (void)
00087 {
00088 return (optimize >= 1
00089
00090 && !(errorcount || sorrycount));
00091 }
00092
00093 static struct tree_opt_pass pass_all_optimizations =
00094 {
00095 NULL,
00096 gate_all_optimizations,
00097 NULL,
00098 NULL,
00099 NULL,
00100 0,
00101 0,
00102 0,
00103 0,
00104 0,
00105 0,
00106 0,
00107 0
00108 };
00109
00110
00111
00112
00113
00114
00115 static void
00116 execute_cleanup_cfg_post_optimizing (void)
00117 {
00118 cleanup_tree_cfg ();
00119 cleanup_dead_labels ();
00120 group_case_labels ();
00121 }
00122
00123 static struct tree_opt_pass pass_cleanup_cfg_post_optimizing =
00124 {
00125 "final_cleanup",
00126 NULL,
00127 execute_cleanup_cfg_post_optimizing,
00128 NULL,
00129 NULL,
00130 0,
00131 0,
00132 PROP_cfg,
00133 0,
00134 0,
00135 0,
00136 TODO_dump_func,
00137 0
00138 };
00139
00140
00141
00142
00143 static void
00144 execute_free_datastructures (void)
00145 {
00146 tree *chain;
00147
00148
00149
00150 free_dominance_info (CDI_DOMINATORS);
00151
00152
00153 disband_implicit_edges ();
00154
00155
00156
00157 delete_tree_ssa ();
00158
00159
00160 chain = &DECL_SAVED_TREE (current_function_decl);
00161 *chain = alloc_stmt_list ();
00162
00163
00164 delete_tree_cfg_annotations ();
00165 }
00166
00167 static struct tree_opt_pass pass_free_datastructures =
00168 {
00169 NULL,
00170 NULL,
00171 execute_free_datastructures,
00172 NULL,
00173 NULL,
00174 0,
00175 0,
00176 PROP_cfg,
00177 0,
00178 0,
00179 0,
00180 0,
00181 0
00182 };
00183
00184
00185
00186
00187
00188 static void
00189 execute_init_datastructures (void)
00190 {
00191
00192 init_tree_ssa ();
00193 }
00194
00195 static struct tree_opt_pass pass_init_datastructures =
00196 {
00197 NULL,
00198 NULL,
00199 execute_init_datastructures,
00200 NULL,
00201 NULL,
00202 0,
00203 0,
00204 PROP_cfg,
00205 0,
00206 0,
00207 0,
00208 0,
00209 0
00210 };
00211
00212
00213
00214
00215
00216 static void
00217 register_one_dump_file (struct tree_opt_pass *pass, int n)
00218 {
00219 char *dot_name, *flag_name, *glob_name;
00220 char num[10];
00221
00222
00223 num[0] = '\0';
00224 if (pass->static_pass_number != -1)
00225 sprintf (num, "%d", ((int) pass->static_pass_number < 0
00226 ? 1 : pass->static_pass_number));
00227
00228 dot_name = concat (".", pass->name, num, NULL);
00229 if (pass->properties_provided & PROP_trees)
00230 {
00231 flag_name = concat ("tree-", pass->name, num, NULL);
00232 glob_name = concat ("tree-", pass->name, NULL);
00233 pass->static_pass_number = dump_register (dot_name, flag_name, glob_name,
00234 TDF_TREE, n + TDI_tree_all, 0);
00235 }
00236 else
00237 {
00238 flag_name = concat ("rtl-", pass->name, num, NULL);
00239 glob_name = concat ("rtl-", pass->name, NULL);
00240 pass->static_pass_number = dump_register (dot_name, flag_name, glob_name,
00241 TDF_RTL, n, pass->letter);
00242 }
00243 }
00244
00245 static int
00246 register_dump_files (struct tree_opt_pass *pass, int properties)
00247 {
00248 static int n = 0;
00249 do
00250 {
00251 int new_properties;
00252 int pass_number;
00253
00254 pass->properties_required = properties;
00255 new_properties =
00256 (properties | pass->properties_provided) & ~pass->properties_destroyed;
00257
00258
00259 if ((pass->properties_provided ^ pass->properties_required) & PROP_rtl)
00260 n = 0;
00261
00262 pass_number = n;
00263 if (pass->name)
00264 n++;
00265
00266 if (pass->sub)
00267 new_properties = register_dump_files (pass->sub, new_properties);
00268
00269
00270
00271 if (pass->gate)
00272 properties &= new_properties;
00273 else
00274 properties = new_properties;
00275
00276 pass->properties_provided = properties;
00277 if (pass->name)
00278 register_one_dump_file (pass, pass_number);
00279
00280 pass = pass->next;
00281 }
00282 while (pass);
00283
00284 return properties;
00285 }
00286
00287
00288
00289
00290 static struct tree_opt_pass **
00291 next_pass_1 (struct tree_opt_pass **list, struct tree_opt_pass *pass)
00292 {
00293
00294
00295
00296 if (pass->static_pass_number)
00297 {
00298 struct tree_opt_pass *new;
00299
00300 new = xmalloc (sizeof (*new));
00301 memcpy (new, pass, sizeof (*new));
00302
00303
00304
00305
00306
00307 if (pass->name)
00308 {
00309 pass->static_pass_number -= 1;
00310 new->static_pass_number = -pass->static_pass_number;
00311 }
00312
00313 *list = new;
00314 }
00315 else
00316 {
00317 pass->static_pass_number = -1;
00318 *list = pass;
00319 }
00320
00321 return &(*list)->next;
00322
00323 }
00324
00325
00326
00327 void
00328 init_tree_optimization_passes (void)
00329 {
00330 struct tree_opt_pass **p;
00331
00332 #define NEXT_PASS(PASS) (p = next_pass_1 (p, &PASS))
00333
00334 p = &all_passes;
00335 NEXT_PASS (pass_gimple);
00336 NEXT_PASS (pass_remove_useless_stmts);
00337 NEXT_PASS (pass_mudflap_1);
00338 NEXT_PASS (pass_lower_cf);
00339 NEXT_PASS (pass_lower_eh);
00340 NEXT_PASS (pass_build_cfg);
00341 NEXT_PASS (pass_pre_expand);
00342 NEXT_PASS (pass_tree_profile);
00343 NEXT_PASS (pass_init_datastructures);
00344 NEXT_PASS (pass_all_optimizations);
00345 NEXT_PASS (pass_warn_function_return);
00346 NEXT_PASS (pass_mudflap_2);
00347 NEXT_PASS (pass_free_datastructures);
00348 NEXT_PASS (pass_expand);
00349 NEXT_PASS (pass_rest_of_compilation);
00350 *p = NULL;
00351
00352 p = &pass_all_optimizations.sub;
00353 NEXT_PASS (pass_referenced_vars);
00354 NEXT_PASS (pass_build_ssa);
00355 NEXT_PASS (pass_may_alias);
00356 NEXT_PASS (pass_rename_ssa_copies);
00357 NEXT_PASS (pass_early_warn_uninitialized);
00358 NEXT_PASS (pass_dce);
00359 NEXT_PASS (pass_dominator);
00360 NEXT_PASS (pass_redundant_phi);
00361 NEXT_PASS (pass_dce);
00362 NEXT_PASS (pass_merge_phi);
00363 NEXT_PASS (pass_forwprop);
00364 NEXT_PASS (pass_phiopt);
00365 NEXT_PASS (pass_may_alias);
00366 NEXT_PASS (pass_tail_recursion);
00367 NEXT_PASS (pass_ch);
00368 NEXT_PASS (pass_profile);
00369 NEXT_PASS (pass_sra);
00370
00371
00372
00373 NEXT_PASS (pass_may_alias);
00374 NEXT_PASS (pass_rename_ssa_copies);
00375 NEXT_PASS (pass_dominator);
00376 NEXT_PASS (pass_redundant_phi);
00377 NEXT_PASS (pass_dce);
00378 NEXT_PASS (pass_dse);
00379 NEXT_PASS (pass_may_alias);
00380 NEXT_PASS (pass_forwprop);
00381 NEXT_PASS (pass_phiopt);
00382 NEXT_PASS (pass_ccp);
00383 NEXT_PASS (pass_redundant_phi);
00384 NEXT_PASS (pass_fold_builtins);
00385
00386
00387
00388 NEXT_PASS (pass_may_alias);
00389 NEXT_PASS (pass_split_crit_edges);
00390 NEXT_PASS (pass_pre);
00391 NEXT_PASS (pass_loop);
00392 NEXT_PASS (pass_dominator);
00393 NEXT_PASS (pass_redundant_phi);
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 NEXT_PASS (pass_late_warn_uninitialized);
00404 NEXT_PASS (pass_cd_dce);
00405 NEXT_PASS (pass_dse);
00406 NEXT_PASS (pass_forwprop);
00407 NEXT_PASS (pass_phiopt);
00408 NEXT_PASS (pass_tail_calls);
00409 NEXT_PASS (pass_rename_ssa_copies);
00410 NEXT_PASS (pass_del_ssa);
00411 NEXT_PASS (pass_nrv);
00412 NEXT_PASS (pass_remove_useless_vars);
00413 NEXT_PASS (pass_mark_used_blocks);
00414 NEXT_PASS (pass_cleanup_cfg_post_optimizing);
00415 *p = NULL;
00416
00417 p = &pass_loop.sub;
00418 NEXT_PASS (pass_loop_init);
00419 NEXT_PASS (pass_lim);
00420 NEXT_PASS (pass_unswitch);
00421 NEXT_PASS (pass_record_bounds);
00422 NEXT_PASS (pass_linear_transform);
00423 NEXT_PASS (pass_iv_canon);
00424 NEXT_PASS (pass_if_conversion);
00425 NEXT_PASS (pass_vectorize);
00426 NEXT_PASS (pass_complete_unroll);
00427 NEXT_PASS (pass_iv_optimize);
00428 NEXT_PASS (pass_loop_done);
00429 *p = NULL;
00430
00431 #undef NEXT_PASS
00432
00433
00434 register_dump_files (all_passes, 0);
00435 }
00436
00437 static void execute_pass_list (struct tree_opt_pass *);
00438
00439 static unsigned int last_verified;
00440
00441 static void
00442 execute_todo (int properties, unsigned int flags)
00443 {
00444 if (flags & TODO_rename_vars)
00445 {
00446 rewrite_into_ssa (false);
00447 bitmap_clear (vars_to_rename);
00448 }
00449 if (flags & TODO_fix_def_def_chains)
00450 {
00451 rewrite_def_def_chains ();
00452 bitmap_clear (vars_to_rename);
00453 }
00454
00455 if (flags & TODO_cleanup_cfg)
00456 cleanup_tree_cfg ();
00457
00458 if ((flags & TODO_dump_func) && dump_file)
00459 {
00460 if (properties & PROP_trees)
00461 dump_function_to_file (current_function_decl,
00462 dump_file, dump_flags);
00463 else if (properties & PROP_cfg)
00464 print_rtl_with_bb (dump_file, get_insns ());
00465 else
00466 print_rtl (dump_file, get_insns ());
00467
00468
00469
00470 fflush (dump_file);
00471 }
00472
00473 if (flags & TODO_ggc_collect)
00474 ggc_collect ();
00475
00476 #ifdef ENABLE_CHECKING
00477 if (flags & TODO_verify_ssa)
00478 verify_ssa ();
00479 if (flags & TODO_verify_flow)
00480 verify_flow_info ();
00481 if (flags & TODO_verify_stmts)
00482 verify_stmts ();
00483 #endif
00484 }
00485
00486 static bool
00487 execute_one_pass (struct tree_opt_pass *pass)
00488 {
00489 unsigned int todo;
00490
00491
00492 if (pass->gate && !pass->gate ())
00493 return false;
00494
00495
00496
00497 in_gimple_form = (pass->properties_provided & PROP_trees) != 0;
00498
00499
00500 todo = pass->todo_flags_start & ~last_verified;
00501 if (todo)
00502 execute_todo (pass->properties_required, todo);
00503
00504
00505 if (pass->static_pass_number != -1)
00506 {
00507 dump_file_name = get_dump_file_name (pass->static_pass_number);
00508 dump_file = dump_begin (pass->static_pass_number, &dump_flags);
00509 if (dump_file)
00510 {
00511 const char *dname, *aname;
00512 dname = lang_hooks.decl_printable_name (current_function_decl, 2);
00513 aname = (IDENTIFIER_POINTER
00514 (DECL_ASSEMBLER_NAME (current_function_decl)));
00515 fprintf (dump_file, "\n;; Function %s (%s)%s\n\n", dname, aname,
00516 cfun->function_frequency == FUNCTION_FREQUENCY_HOT
00517 ? " (hot)"
00518 : cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED
00519 ? " (unlikely executed)"
00520 : "");
00521 }
00522 }
00523
00524
00525 if (pass->tv_id)
00526 timevar_push (pass->tv_id);
00527
00528
00529 if (pass->execute)
00530 pass->execute ();
00531
00532
00533 if (pass->tv_id)
00534 timevar_pop (pass->tv_id);
00535
00536 if (dump_file
00537 && (pass->properties_provided & (PROP_cfg | PROP_rtl))
00538 == (PROP_cfg | PROP_rtl))
00539 print_rtl_with_bb (dump_file, get_insns ());
00540
00541
00542 todo = pass->todo_flags_finish;
00543 last_verified = todo & TODO_verify_all;
00544 if (todo)
00545 execute_todo (pass->properties_provided, todo);
00546
00547
00548 if (dump_file_name)
00549 {
00550 free ((char *) dump_file_name);
00551 dump_file_name = NULL;
00552 }
00553 if (dump_file)
00554 {
00555 dump_end (pass->static_pass_number, dump_file);
00556 dump_file = NULL;
00557 }
00558
00559 return true;
00560 }
00561
00562 static void
00563 execute_pass_list (struct tree_opt_pass *pass)
00564 {
00565 do
00566 {
00567 if (execute_one_pass (pass) && pass->sub)
00568 execute_pass_list (pass->sub);
00569 pass = pass->next;
00570 }
00571 while (pass);
00572 }
00573
00574
00575
00576
00577 static void
00578 update_inlined_to_pointers (struct cgraph_node *node,
00579 struct cgraph_node *inlined_to)
00580 {
00581 struct cgraph_edge *e;
00582 for (e = node->callees; e; e = e->next_callee)
00583 {
00584 if (e->callee->global.inlined_to)
00585 {
00586 e->callee->global.inlined_to = inlined_to;
00587 update_inlined_to_pointers (e->callee, inlined_to);
00588 }
00589 }
00590 }
00591
00592
00593
00594
00595
00596 void
00597 tree_rest_of_compilation (tree fndecl)
00598 {
00599 location_t saved_loc;
00600 struct cgraph_node *saved_node = NULL, *node;
00601
00602 #ifdef KEY
00603
00604
00605 if (!strcmp("GNU C++", lang_hooks.name) &&
00606 flag_spin_file &&
00607 lang_hooks.cp_genericize ) {
00608 gs_x_func_decl(fndecl);
00609
00610 lang_hooks.cp_genericize(fndecl);
00611
00612 walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
00613 lang_hooks.simplify_aggr_init_exprs_r,
00614 NULL);
00615 }
00616 #endif
00617 timevar_push (TV_EXPAND);
00618
00619 gcc_assert (!flag_unit_at_a_time || cgraph_global_info_ready);
00620
00621
00622 current_function_decl = fndecl;
00623 saved_loc = input_location;
00624 input_location = DECL_SOURCE_LOCATION (fndecl);
00625 init_function_start (fndecl);
00626
00627
00628
00629
00630
00631 cfun->x_dont_save_pending_sizes_p = 1;
00632
00633 node = cgraph_node (fndecl);
00634
00635
00636
00637
00638 if (cgraph_preserve_function_body_p (fndecl))
00639 {
00640 if (!flag_unit_at_a_time)
00641 {
00642 struct cgraph_edge *e;
00643
00644 saved_node = cgraph_clone_node (node);
00645 for (e = saved_node->callees; e; e = e->next_callee)
00646 if (!e->inline_failed)
00647 cgraph_clone_inlined_nodes (e, true);
00648 }
00649 cfun->saved_static_chain_decl = cfun->static_chain_decl;
00650 cfun->saved_tree = save_body (fndecl, &cfun->saved_args,
00651 &cfun->saved_static_chain_decl);
00652 }
00653
00654 if (flag_inline_trees)
00655 {
00656 struct cgraph_edge *e;
00657 for (e = node->callees; e; e = e->next_callee)
00658 if (!e->inline_failed || warn_inline)
00659 break;
00660 if (e)
00661 {
00662 timevar_push (TV_INTEGRATION);
00663 optimize_inline_calls (fndecl);
00664 timevar_pop (TV_INTEGRATION);
00665 }
00666 }
00667
00668
00669
00670 cgraph_node_remove_callees (node);
00671
00672
00673
00674 bitmap_obstack_initialize (NULL);
00675 bitmap_obstack_initialize (®_obstack);
00676
00677 vars_to_rename = BITMAP_ALLOC (NULL);
00678
00679
00680 execute_pass_list (all_passes);
00681
00682 bitmap_obstack_release (®_obstack);
00683
00684
00685 bitmap_obstack_release (NULL);
00686
00687
00688 if (cfun->saved_tree)
00689 {
00690 DECL_SAVED_TREE (fndecl) = cfun->saved_tree;
00691 DECL_ARGUMENTS (fndecl) = cfun->saved_args;
00692 cfun->static_chain_decl = cfun->saved_static_chain_decl;
00693
00694
00695
00696
00697 if (!flag_unit_at_a_time)
00698 {
00699 struct cgraph_edge *e;
00700
00701 cgraph_node_remove_callees (node);
00702 node->callees = saved_node->callees;
00703 saved_node->callees = NULL;
00704 update_inlined_to_pointers (node, node);
00705 for (e = node->callees; e; e = e->next_callee)
00706 e->caller = node;
00707 cgraph_remove_node (saved_node);
00708 }
00709 }
00710 else
00711 DECL_SAVED_TREE (fndecl) = NULL;
00712 cfun = 0;
00713
00714
00715
00716
00717 if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl))
00718 {
00719 tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
00720
00721 if (ret_type && TYPE_SIZE_UNIT (ret_type)
00722 && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
00723 && 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type),
00724 larger_than_size))
00725 {
00726 unsigned int size_as_int
00727 = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
00728
00729 if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
00730 warning ("%Jsize of return value of %qD is %u bytes",
00731 fndecl, fndecl, size_as_int);
00732 else
00733 warning ("%Jsize of return value of %qD is larger than %wd bytes",
00734 fndecl, fndecl, larger_than_size);
00735 }
00736 }
00737
00738 if (!flag_inline_trees)
00739 {
00740 DECL_SAVED_TREE (fndecl) = NULL;
00741 if (DECL_STRUCT_FUNCTION (fndecl) == 0
00742 && !cgraph_node (fndecl)->origin)
00743 {
00744
00745
00746
00747
00748
00749 if (DECL_INITIAL (fndecl) != 0)
00750 DECL_INITIAL (fndecl) = error_mark_node;
00751 }
00752 }
00753
00754 input_location = saved_loc;
00755
00756 ggc_collect ();
00757 timevar_pop (TV_EXPAND);
00758 }