#include "config.h"#include "system.h"#include "coretypes.h"#include "tm.h"#include "tree.h"#include "rtl.h"#include "tm_p.h"#include "hard-reg-set.h"#include "basic-block.h"#include "output.h"#include "flags.h"#include "function.h"#include "expr.h"#include "ggc.h"#include "langhooks.h"#include "diagnostic.h"#include "tree-flow.h"#include "timevar.h"#include "tree-dump.h"#include "tree-pass.h"#include "toplev.h"#include "except.h"#include "cfgloop.h"#include "cfglayout.h"#include "hashtab.h"#include "tree-ssa-propagate.h"Include dependency graph for tree-cfg.c:

Go to the source code of this file.
Data Structures | |
| struct | edge_to_cases_elt |
| struct | cfg_stats_d |
| struct | rus_data |
| struct | move_stmt_d |
Defines | |
| #define | CHECK_OP(N, MSG) |
Functions | |
| static basic_block | create_bb (void *, void *, basic_block) |
| static void | make_blocks (tree) |
| static void | factor_computed_gotos (void) |
| static void | make_edges (void) |
| static void | make_cond_expr_edges (basic_block) |
| static void | make_switch_expr_edges (basic_block) |
| static void | make_goto_expr_edges (basic_block) |
| static edge | tree_redirect_edge_and_branch (edge, basic_block) |
| static edge | tree_try_redirect_by_replacing_jump (edge, basic_block) |
| static unsigned int | split_critical_edges (void) |
| static bool | stmt_starts_bb_p (tree, tree) |
| static int | tree_verify_flow_info (void) |
| static void | tree_make_forwarder_block (edge) |
| static void | tree_cfg2vcg (FILE *) |
| static void | change_bb_for_stmt (tree t, basic_block bb) |
| static void | tree_merge_blocks (basic_block, basic_block) |
| static bool | tree_can_merge_blocks_p (basic_block, basic_block) |
| static void | remove_bb (basic_block) |
| static edge | find_taken_edge_computed_goto (basic_block, tree) |
| static edge | find_taken_edge_cond_expr (basic_block, tree) |
| static edge | find_taken_edge_switch_expr (basic_block, tree) |
| static tree | find_case_label_for_value (tree, tree) |
| void | init_empty_tree_cfg () |
| static void | build_tree_cfg () |
| static unsigned int | execute_build_cfg () |
| static void | make_blocks () |
| static basic_block | create_bb () |
| void | fold_cond_expr_cond () |
| static void | make_cond_expr_edges () |
| static hashval_t | edge_to_cases_hash () |
| static int | edge_to_cases_eq () |
| static void | edge_to_cases_cleanup () |
| void | start_recording_case_labels () |
| static bool | recording_case_labels_p () |
| void | end_recording_case_labels () |
| static void | record_switch_edge () |
| static tree | get_cases_for_edge () |
| static void | make_switch_expr_edges () |
| basic_block | label_to_block_fn () |
| static void | make_goto_expr_edges () |
| static void | update_eh_label () |
| static tree | main_block_label () |
| void | cleanup_dead_labels () |
| void | group_case_labels () |
| static bool | tree_can_merge_blocks_p () |
| void | replace_uses_by () |
| static void | tree_merge_blocks () |
| basic_block | single_noncomplex_succ () |
| static void | remove_useless_stmts_1 (tree *, struct rus_data *) |
| static bool | remove_useless_stmts_warn_notreached () |
| static void | remove_useless_stmts_cond () |
| static void | remove_useless_stmts_tf () |
| static void | remove_useless_stmts_tc () |
| static void | remove_useless_stmts_bind () |
| static void | remove_useless_stmts_goto () |
| static void | remove_useless_stmts_label () |
| static void | update_call_expr_flags () |
| void | notice_special_calls () |
| void | clear_special_calls () |
| static void | remove_useless_stmts_1 () |
| static unsigned int | remove_useless_stmts () |
| static void | remove_phi_nodes_and_edges_for_unreachable_block () |
| static void | remove_bb () |
| edge | find_taken_edge () |
| static edge | find_taken_edge_computed_goto () |
| static edge | find_taken_edge_cond_expr () |
| static edge | find_taken_edge_switch_expr () |
| static tree | find_case_label_for_value () |
| void | tree_dump_bb () |
| void | debug_tree_bb () |
| basic_block | debug_tree_bb_n () |
| void | debug_tree_cfg () |
| void | dump_tree_cfg () |
| void | dump_cfg_stats () |
| void | debug_cfg_stats () |
| static void | tree_cfg2vcg () |
| bool | is_ctrl_stmt () |
| bool | is_ctrl_altering_stmt () |
| bool | computed_goto_p () |
| bool | simple_goto_p () |
| static bool | stmt_starts_bb_p () |
| bool | stmt_ends_bb_p () |
| void | disband_implicit_edges () |
| void | delete_tree_cfg_annotations () |
| tree | first_stmt () |
| tree | last_stmt () |
| tree * | last_stmt_ptr () |
| tree | last_and_only_stmt () |
| void | set_bb_for_stmt () |
| static void | change_bb_for_stmt () |
| block_stmt_iterator | bsi_for_stmt () |
| static void | update_modified_stmts () |
| void | bsi_insert_before () |
| void | bsi_insert_after () |
| void | bsi_remove () |
| void | bsi_move_after () |
| void | bsi_move_before () |
| void | bsi_move_to_bb_end () |
| void | bsi_replace () |
| static bool | tree_find_edge_insert_loc (edge e, block_stmt_iterator *bsi, basic_block *new_bb) |
| void | bsi_commit_edge_inserts () |
| void | bsi_commit_one_edge_insert () |
| void | bsi_insert_on_edge () |
| basic_block | bsi_insert_on_edge_immediate () |
| static void | reinstall_phi_args () |
| static basic_block | split_edge_bb_loc () |
| static basic_block | tree_split_edge () |
| static bool | has_label_p () |
| static tree | verify_expr () |
| static bool | verify_stmt () |
| static bool | tree_node_can_be_shared () |
| static tree | verify_node_sharing () |
| void | verify_stmts () |
| static void | tree_make_forwarder_block () |
| tree | tree_block_label () |
| static edge | tree_try_redirect_by_replacing_jump () |
| static edge | tree_redirect_edge_and_branch () |
| static basic_block | tree_redirect_edge_and_branch_force () |
| static basic_block | tree_split_block () |
| static bool | tree_move_block_after () |
| static bool | tree_can_duplicate_bb_p () |
| static basic_block | tree_duplicate_bb () |
| void | add_phi_args_after_copy_bb () |
| void | add_phi_args_after_copy () |
| bool | tree_duplicate_sese_region (edge entry, edge exit, basic_block *region, unsigned n_region, basic_block *region_copy) |
| static void | gather_blocks_in_sese_region (basic_block entry, basic_block exit, VEC(basic_block, heap)**bbs_p) |
| static tree | move_stmt_r () |
| static void | move_block_to_fn (struct function *dest_cfun, basic_block bb, basic_block after, bool update_edge_count_p, bitmap vars_to_remove, htab_t new_label_map, int eh_offset) |
| static int | find_outermost_region_in_block (struct function *src_cfun, basic_block bb, int region) |
| static tree | new_label_mapper () |
| basic_block | move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, basic_block exit_bb) |
| void | dump_function_to_file () |
| void | debug_function () |
| static void | print_loop (FILE *, struct loop *, int) |
| static void | print_pred_bbs (FILE *, basic_block bb) |
| static void | print_succ_bbs (FILE *, basic_block bb) |
| static void | print_pred_bbs () |
| static void | print_succ_bbs () |
| static void | print_loop () |
| void | print_loop_ir () |
| void | debug_loop_ir () |
| static bool | tree_block_ends_with_call_p () |
| static bool | tree_block_ends_with_condjump_p () |
| static bool | need_fake_edge_p () |
| static int | tree_flow_call_edges_add () |
| bool | tree_purge_dead_eh_edges () |
| bool | tree_purge_all_dead_eh_edges () |
| static void | tree_execute_on_growing_pred () |
| static void | tree_execute_on_shrinking_pred () |
| static void | tree_lv_adjust_loop_header_phi (basic_block first, basic_block second, basic_block new_head, edge e) |
| static void | tree_lv_add_condition_to_bb (basic_block first_head, basic_block second_head, basic_block cond_bb, void *cond_e) |
| tree | gimplify_val () |
| tree | gimplify_build3 (block_stmt_iterator *bsi, enum tree_code code, tree type, tree a, tree b, tree c) |
| tree | gimplify_build2 (block_stmt_iterator *bsi, enum tree_code code, tree type, tree a, tree b) |
| tree | gimplify_build1 (block_stmt_iterator *bsi, enum tree_code code, tree type, tree a) |
| static unsigned int | execute_warn_function_return () |
| void | extract_true_false_edges_from_block (basic_block b, edge *true_edge, edge *false_edge) |
| static unsigned int | execute_warn_function_noreturn () |
Variables | |
| static const int | initial_cfg_capacity = 20 |
| static htab_t | edge_to_cases |
| static struct cfg_stats_d | cfg_stats |
| static bool | found_computed_goto |
| tree_opt_pass | pass_build_cfg |
| static tree * | label_for_bb |
| tree_opt_pass | pass_remove_useless_stmts |
| cfg_hooks | tree_cfg_hooks |
| tree_opt_pass | pass_split_crit_edges |
| tree_opt_pass | pass_warn_function_return |
| tree_opt_pass | pass_warn_function_noreturn |
|
|
Value: do { if (!is_gimple_val (TREE_OPERAND (t, N))) \ { error (MSG); return TREE_OPERAND (t, N); }} while (0) Referenced by verify_expr(). |
|
|
Blocks in REGION_COPY array of length N_REGION were created by duplication of basic blocks. Add phi node arguments for edges going from these blocks. Definition at line 4360 of file tree-cfg.c. References add_phi_args_after_copy_bb(). 04361 { 04362 unsigned i; 04363 04364 for (i = 0; i < n_region; i++) 04365 region_copy[i]->flags |= BB_DUPLICATED; 04366 04367 for (i = 0; i < n_region; i++) 04368 add_phi_args_after_copy_bb (region_copy[i]); 04369 04370 for (i = 0; i < n_region; i++) 04371 region_copy[i]->flags &= ~BB_DUPLICATED; 04372 }
|
|
|
Basic block BB_COPY was created by code duplication. Add phi node arguments for edges going out of BB_COPY. The blocks that were duplicated have BB_DUPLICATED set. Definition at line 4311 of file tree-cfg.c. References add_phi_arg(), PHI_ARG_DEF_FROM_EDGE, PHI_CHAIN, and phi_nodes(). Referenced by add_phi_args_after_copy(), and copy_phi_node_args(). 04312 { 04313 basic_block bb, dest; 04314 edge e, e_copy; 04315 edge_iterator ei; 04316 tree phi, phi_copy, phi_next, def; 04317 04318 bb = get_bb_original (bb_copy); 04319 04320 FOR_EACH_EDGE (e_copy, ei, bb_copy->succs) 04321 { 04322 if (!phi_nodes (e_copy->dest)) 04323 continue; 04324 04325 if (e_copy->dest->flags & BB_DUPLICATED) 04326 dest = get_bb_original (e_copy->dest); 04327 else 04328 dest = e_copy->dest; 04329 04330 e = find_edge (bb, dest); 04331 if (!e) 04332 { 04333 /* During loop unrolling the target of the latch edge is copied. 04334 In this case we are not looking for edge to dest, but to 04335 duplicated block whose original was dest. */ 04336 FOR_EACH_EDGE (e, ei, bb->succs) 04337 if ((e->dest->flags & BB_DUPLICATED) 04338 && get_bb_original (e->dest) == dest) 04339 break; 04340 04341 gcc_assert (e != NULL); 04342 } 04343 04344 for (phi = phi_nodes (e->dest), phi_copy = phi_nodes (e_copy->dest); 04345 phi; 04346 phi = phi_next, phi_copy = PHI_CHAIN (phi_copy)) 04347 { 04348 phi_next = PHI_CHAIN (phi); 04349 def = PHI_ARG_DEF_FROM_EDGE (phi, e); 04350 add_phi_arg (phi_copy, def, e_copy); 04351 } 04352 } 04353 }
|
|
|
This routine will commit all pending edge insertions, creating any new basic blocks which are necessary. Definition at line 3045 of file tree-cfg.c. References bsi_commit_one_edge_insert(). Referenced by execute_pre(), loop_commit_inserts(), mf_decl_cache_locals(), process_assert_insertions(), scalarize_function(), tree_flow_call_edges_add(), and tree_lower_complex(). 03046 { 03047 basic_block bb; 03048 edge e; 03049 edge_iterator ei; 03050 03051 bsi_commit_one_edge_insert (single_succ_edge (ENTRY_BLOCK_PTR), NULL); 03052 03053 FOR_EACH_BB (bb) 03054 FOR_EACH_EDGE (e, ei, bb->succs) 03055 bsi_commit_one_edge_insert (e, NULL); 03056 }
|
|
|
Commit insertions pending at edge E. If a new block is created, set NEW_BB to this block, otherwise set it to NULL. Definition at line 3063 of file tree-cfg.c. References bsi_insert_after(), bsi_insert_before(), BSI_NEW_STMT, NULL_TREE, PENDING_STMT, and tree_find_edge_insert_loc(). Referenced by analyze_edges_for_bb(), and bsi_commit_edge_inserts(). 03064 { 03065 if (new_bb) 03066 *new_bb = NULL; 03067 if (PENDING_STMT (e)) 03068 { 03069 block_stmt_iterator bsi; 03070 tree stmt = PENDING_STMT (e); 03071 03072 PENDING_STMT (e) = NULL_TREE; 03073 03074 if (tree_find_edge_insert_loc (e, &bsi, new_bb)) 03075 bsi_insert_after (&bsi, stmt, BSI_NEW_STMT); 03076 else 03077 bsi_insert_before (&bsi, stmt, BSI_NEW_STMT); 03078 } 03079 }
|
|
|
Finds iterator for STMT. Definition at line 2799 of file tree-cfg.c. References bb_for_stmt(), bsi_end_p(), bsi_next(), bsi_start, and bsi_stmt(). 02800 { 02801 block_stmt_iterator bsi; 02802 02803 for (bsi = bsi_start (bb_for_stmt (stmt)); !bsi_end_p (bsi); bsi_next (&bsi)) 02804 if (bsi_stmt (bsi) == stmt) 02805 return bsi; 02806 02807 gcc_unreachable (); 02808 }
|
|
|
|
|
Add STMT to the pending list of edge E. No actual insertion is made until a call to bsi_commit_edge_inserts () is made. Definition at line 3086 of file tree-cfg.c. References append_to_statement_list(), and PENDING_STMT. Referenced by insert_copy_on_edge(), insert_edge_copies(), insert_into_preds_of_block(), move_computations_stmt(), process_assert_insertions_for(), schedule_sm(), tree_flow_call_edges_add(), tree_gen_edge_profiler(), and update_complex_components_on_edge(). 03087 { 03088 append_to_statement_list (stmt, &PENDING_STMT (e)); 03089 }
|
|
|
Similar to bsi_insert_on_edge+bsi_commit_edge_inserts. If a new block has to be created, it is returned. Definition at line 3095 of file tree-cfg.c. References bsi_insert_after(), bsi_insert_before(), BSI_NEW_STMT, PENDING_STMT, and tree_find_edge_insert_loc(). Referenced by bsi_insert_on_edge_immediate_loop(), vect_build_loop_niters(), vect_create_data_ref_ptr(), vect_gen_niters_for_prolog_loop(), vect_generate_tmps_on_preheader(), vect_init_vector(), and vectorizable_load(). 03096 { 03097 block_stmt_iterator bsi; 03098 basic_block new_bb = NULL; 03099 03100 gcc_assert (!PENDING_STMT (e)); 03101 03102 if (tree_find_edge_insert_loc (e, &bsi, &new_bb)) 03103 bsi_insert_after (&bsi, stmt, BSI_NEW_STMT); 03104 else 03105 bsi_insert_before (&bsi, stmt, BSI_NEW_STMT); 03106 03107 return new_bb; 03108 }
|
|
|
Move the statement at FROM so it comes right after the statement at TO. Definition at line 2880 of file tree-cfg.c. References bsi_insert_after(), bsi_remove(), BSI_SAME_STMT, and bsi_stmt(). Referenced by bsi_move_to_bb_end(). 02881 { 02882 tree stmt = bsi_stmt (*from); 02883 bsi_remove (from, false); 02884 bsi_insert_after (to, stmt, BSI_SAME_STMT); 02885 }
|
|
|
Move the statement at FROM so it comes right before the statement at TO. Definition at line 2891 of file tree-cfg.c. References bsi_insert_before(), bsi_remove(), BSI_SAME_STMT, and bsi_stmt(). Referenced by bsi_move_to_bb_end(), expand_call_inline(), linearize_expr(), linearize_expr_tree(), minmax_replacement(), sink_code_in_bb(), and tree_block_label(). 02892 { 02893 tree stmt = bsi_stmt (*from); 02894 bsi_remove (from, false); 02895 bsi_insert_before (to, stmt, BSI_SAME_STMT); 02896 }
|
|
|
Move the statement at FROM to the end of basic block BB. Definition at line 2902 of file tree-cfg.c. References bsi_end_p(), bsi_last, bsi_move_after(), bsi_move_before(), bsi_stmt(), and is_ctrl_stmt(). Referenced by sink_code_in_bb(). 02903 { 02904 block_stmt_iterator last = bsi_last (bb); 02905 02906 /* Have to check bsi_end_p because it could be an empty block. */ 02907 if (!bsi_end_p (last) && is_ctrl_stmt (bsi_stmt (last))) 02908 bsi_move_before (from, &last); 02909 else 02910 bsi_move_after (from, &last); 02911 }
|
|
|
|
Replace the contents of the statement pointed to by iterator BSI with STMT. If UPDATE_EH_INFO is true, the exception handling information of the original statement is moved to the new statement. Definition at line 2919 of file tree-cfg.c. References add_stmt_to_eh_region(), block_stmt_iterator::bb, bsi_stmt(), bsi_stmt_ptr(), delink_stmt_imm_use(), EXPR_LOCUS, lookup_stmt_eh_region(), mark_stmt_modified(), remove_stmt_from_eh_region(), set_bb_for_stmt(), SET_EXPR_LOCUS, and update_modified_stmts(). Referenced by adjust_return_value(), determine_invariantness_stmt(), and scalarize_ldst(). 02920 { 02921 int eh_region; 02922 tree orig_stmt = bsi_stmt (*bsi); 02923 02924 SET_EXPR_LOCUS (stmt, EXPR_LOCUS (orig_stmt)); 02925 set_bb_for_stmt (stmt, bsi->bb); 02926 02927 /* Preserve EH region information from the original statement, if 02928 requested by the caller. */ 02929 if (update_eh_info) 02930 { 02931 eh_region = lookup_stmt_eh_region (orig_stmt); 02932 if (eh_region >= 0) 02933 { 02934 remove_stmt_from_eh_region (orig_stmt); 02935 add_stmt_to_eh_region (stmt, eh_region); 02936 } 02937 } 02938 02939 delink_stmt_imm_use (orig_stmt); 02940 *bsi_stmt_ptr (*bsi) = stmt; 02941 mark_stmt_modified (stmt); 02942 update_modified_stmts (stmt); 02943 }
|
|
|
Entry point to the CFG builder for trees. TP points to the list of statements to be added to the flowgraph. Definition at line 159 of file tree-cfg.c. References cfg_stats, cleanup_dead_labels(), dump_begin(), dump_end(), dump_file, dump_flags, dump_tree_cfg(), factor_computed_gotos(), found_computed_goto, group_case_labels(), init_empty_tree_cfg(), make_blocks(), make_edges(), TDI_vcg, tree_cfg2vcg(), and verify_stmts(). Referenced by execute_build_cfg(). 00160 { 00161 /* Register specific tree functions. */ 00162 tree_register_cfg_hooks (); 00163 00164 memset ((void *) &cfg_stats, 0, sizeof (cfg_stats)); 00165 00166 init_empty_tree_cfg (); 00167 00168 found_computed_goto = 0; 00169 make_blocks (*tp); 00170 00171 /* Computed gotos are hell to deal with, especially if there are 00172 lots of them with a large number of destinations. So we factor 00173 them to a common computed goto location before we build the 00174 edge list. After we convert back to normal form, we will un-factor 00175 the computed gotos since factoring introduces an unwanted jump. */ 00176 if (found_computed_goto) 00177 factor_computed_gotos (); 00178 00179 /* Make sure there is always at least one block, even if it's empty. */ 00180 if (n_basic_blocks == NUM_FIXED_BLOCKS) 00181 create_empty_bb (ENTRY_BLOCK_PTR); 00182 00183 /* Adjust the size of the array. */ 00184 if (VEC_length (basic_block, basic_block_info) < (size_t) n_basic_blocks) 00185 { 00186 size_t old_size = VEC_length (basic_block, basic_block_info); 00187 basic_block *p; 00188 VEC_safe_grow (basic_block, gc, basic_block_info, n_basic_blocks); 00189 p = VEC_address (basic_block, basic_block_info); 00190 memset (&p[old_size], 0, 00191 sizeof (basic_block) * (n_basic_blocks - old_size)); 00192 } 00193 00194 /* To speed up statement iterator walks, we first purge dead labels. */ 00195 cleanup_dead_labels (); 00196 00197 /* Group case nodes to reduce the number of edges. 00198 We do this after cleaning up dead labels because otherwise we miss 00199 a lot of obvious case merging opportunities. */ 00200 group_case_labels (); 00201 00202 /* Create the edges of the flowgraph. */ 00203 make_edges (); 00204 00205 /* Debugging dumps. */ 00206 00207 /* Write the flowgraph to a VCG file. */ 00208 { 00209 int local_dump_flags; 00210 FILE *vcg_file = dump_begin (TDI_vcg, &local_dump_flags); 00211 if (vcg_file) 00212 { 00213 tree_cfg2vcg (vcg_file); 00214 dump_end (TDI_vcg, vcg_file); 00215 } 00216 } 00217 00218 #ifdef ENABLE_CHECKING 00219 verify_stmts (); 00220 #endif 00221 00222 /* Dump a textual representation of the flowgraph. */ 00223 if (dump_file) 00224 dump_tree_cfg (dump_file, dump_flags); 00225 }
|
|
|
Faster version of set_bb_for_stmt that assume that statement is being moved from one basic block to another. For BB splitting we can run into quadratic case, so performance is quite important and knowing that the tables are big enough, change_bb_for_stmt can inline as leaf function. Definition at line 2788 of file tree-cfg.c. References stmt_ann_d::bb, get_stmt_ann, LABEL_DECL_UID, LABEL_EXPR_LABEL, and TREE_CODE. 02789 { 02790 get_stmt_ann (t)->bb = bb; 02791 if (TREE_CODE (t) == LABEL_EXPR) 02792 VEC_replace (basic_block, label_to_block_map, 02793 LABEL_DECL_UID (LABEL_EXPR_LABEL (t)), bb); 02794 }
|
|
||||||||||||
|
|
|
|
Cleanup redundant labels. This is a three-step process:
1) Find the leading label for each block.
2) Redirect all references to labels to the leading labels.
3) Cleanup all useless labels. Definition at line 965 of file tree-cfg.c. References bsi_end_p(), bsi_next(), bsi_start, bsi_stmt(), DECL_ARTIFICIAL, LABEL_EXPR_LABEL, label_for_bb, and TREE_CODE. Referenced by build_tree_cfg(), and execute_cleanup_cfg_post_optimizing(). 00966 { 00967 basic_block bb; 00968 label_for_bb = XCNEWVEC (tree, last_basic_block); 00969 00970 /* Find a suitable label for each block. We use the first user-defined 00971 label if there is one, or otherwise just the first label we see. */ 00972 FOR_EACH_BB (bb) 00973 { 00974 block_stmt_iterator i; 00975 00976 for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i)) 00977 { 00978 tree label, stmt = bsi_stmt (i); 00979 00980 if (TREE_CODE (stmt) != LABEL_EXPR) 00981 break; 00982 00983 label = LABEL_EXPR_LABEL (stmt); 00984 00985 /* If we have not yet seen a label for the current block, 00986 remember this one and see if there are more labels. */ 00987 if (! label_for_bb[bb->index]) 00988 { 00989 label_for_bb[bb->index] = label; 00990 continue; 00991 } 00992 00993 /* If we did see a label for the current block already, but it 00994 is an artificially created label, replace it if the current 00995 label is a user defined label. */ 00996 if (! DECL_ARTIFICIAL (label) 00997 && DECL_ARTIFICIAL (label_for_bb[bb->index])) 00998 { 00999 label_for_bb[bb->index] = label; 01000 break; 01001 } 01002 } 01003 } 01004 01005 /* Now redirect all jumps/branches to the selected label. 01006 First do so for each block ending in a control statement. */ 01007 FOR_EACH_BB (bb) 01008 { 01009 tree stmt = last_stmt (bb); 01010 if (!stmt) 01011 continue; 01012 01013 switch (TREE_CODE (stmt)) 01014 { 01015 case COND_EXPR: 01016 { 01017 tree true_branch, false_branch; 01018 01019 true_branch = COND_EXPR_THEN (stmt); 01020 false_branch = COND_EXPR_ELSE (stmt); 01021 01022 GOTO_DESTINATION (true_branch) 01023 = main_block_label (GOTO_DESTINATION (true_branch)); 01024 GOTO_DESTINATION (false_branch) 01025 = main_block_label (GOTO_DESTINATION (false_branch)); 01026 01027 break; 01028 } 01029 01030 case SWITCH_EXPR: 01031 { 01032 size_t i; 01033 tree vec = SWITCH_LABELS (stmt); 01034 size_t n = TREE_VEC_LENGTH (vec); 01035 01036 /* Replace all destination labels. */ 01037 for (i = 0; i < n; ++i) 01038 { 01039 tree elt = TREE_VEC_ELT (vec, i); 01040 tree label = main_block_label (CASE_LABEL (elt)); 01041 CASE_LABEL (elt) = label; 01042 } 01043 break; 01044 } 01045 01046 /* We have to handle GOTO_EXPRs until they're removed, and we don't 01047 remove them until after we've created the CFG edges. */ 01048 case GOTO_EXPR: 01049 if (! computed_goto_p (stmt)) 01050 { 01051 GOTO_DESTINATION (stmt) 01052 = main_block_label (GOTO_DESTINATION (stmt)); 01053 break; 01054 } 01055 01056 default: 01057 break; 01058 } 01059 } 01060 01061 for_each_eh_region (update_eh_label); 01062 01063 /* Finally, purge dead labels. All user-defined labels and labels that 01064 can be the target of non-local gotos and labels which have their 01065 address taken are preserved. */ 01066 FOR_EACH_BB (bb) 01067 { 01068 block_stmt_iterator i; 01069 tree label_for_this_bb = label_for_bb[bb->index]; 01070 01071 if (! label_for_this_bb) 01072 continue; 01073 01074 for (i = bsi_start (bb); !bsi_end_p (i); ) 01075 { 01076 tree label, stmt = bsi_stmt (i); 01077 01078 if (TREE_CODE (stmt) != LABEL_EXPR) 01079 break; 01080 01081 label = LABEL_EXPR_LABEL (stmt); 01082 01083 if (label == label_for_this_bb 01084 || ! DECL_ARTIFICIAL (label) 01085 || DECL_NONLOCAL (label) 01086 || FORCED_LABEL (label)) 01087 bsi_next (&i); 01088 else 01089 bsi_remove (&i, true); 01090 } 01091 } 01092 01093 free (label_for_bb); 01094 }
|
|
|
Clear flags set by notice_special_calls. Used by dead code removal to update the flags. Definition at line 1838 of file tree-cfg.c. Referenced by eliminate_unnecessary_stmts(), and remove_useless_stmts(). 01839 { 01840 current_function_calls_alloca = false; 01841 current_function_calls_setjmp = false; 01842 }
|
|
|
Return true if T is a computed goto. Definition at line 2513 of file tree-cfg.c. References GOTO_DESTINATION, and TREE_CODE. Referenced by factor_computed_gotos(), find_taken_edge(), and make_blocks(). 02514 { 02515 return (TREE_CODE (t) == GOTO_EXPR 02516 && TREE_CODE (GOTO_DESTINATION (t)) != LABEL_DECL); 02517 }
|
|
|
Create and return a new empty basic block after bb AFTER. Definition at line 378 of file tree-cfg.c. References alloc_stmt_list(). 00379 { 00380 basic_block bb; 00381 00382 gcc_assert (!e); 00383 00384 /* Create and initialize a new basic block. Since alloc_block uses 00385 ggc_alloc_cleared to allocate a basic block, we do not have to 00386 clear the newly allocated basic block here. */ 00387 bb = alloc_block (); 00388 00389 bb->index = last_basic_block; 00390 bb->flags = BB_NEW; 00391 bb->stmt_list = h ? (tree) h : alloc_stmt_list (); 00392 00393 /* Add the new block to the linked list of blocks. */ 00394 link_block (bb, after); 00395 00396 /* Grow the basic block array if needed. */ 00397 if ((size_t) last_basic_block == VEC_length (basic_block, basic_block_info)) 00398 { 00399 size_t old_size = VEC_length (basic_block, basic_block_info); 00400 size_t new_size = last_basic_block + (last_basic_block + 3) / 4; 00401 basic_block *p; 00402 VEC_safe_grow (basic_block, gc, basic_block_info, new_size); 00403 p = VEC_address (basic_block, basic_block_info); 00404 memset (&p[old_size], 0, sizeof (basic_block) * (new_size - old_size)); 00405 } 00406 00407 /* Add the newly created block to the array. */ 00408 SET_BASIC_BLOCK (last_basic_block, bb); 0040 |