Mercurial > hg > CbC > CbC_gcc
diff gcc/tree-cfgcleanup.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
line wrap: on
line diff
--- a/gcc/tree-cfgcleanup.c Fri Oct 27 22:46:09 2017 +0900 +++ b/gcc/tree-cfgcleanup.c Thu Oct 25 07:37:49 2018 +0900 @@ -1,5 +1,5 @@ /* CFG cleanup for trees. - Copyright (C) 2001-2017 Free Software Foundation, Inc. + Copyright (C) 2001-2018 Free Software Foundation, Inc. This file is part of GCC. @@ -84,13 +84,12 @@ return false; tree index = gimple_switch_index (swtch); - tree default_label = CASE_LABEL (gimple_switch_default_label (swtch)); tree label = gimple_switch_label (swtch, 1); tree low = CASE_LOW (label); tree high = CASE_HIGH (label); - basic_block default_bb = label_to_block_fn (cfun, default_label); - basic_block case_bb = label_to_block_fn (cfun, CASE_LABEL (label)); + basic_block default_bb = gimple_switch_default_bb (cfun, swtch); + basic_block case_bb = label_to_block (cfun, CASE_LABEL (label)); basic_block bb = gimple_bb (swtch); gcond *cond; @@ -122,8 +121,7 @@ at block BB. */ static bool -cleanup_control_expr_graph (basic_block bb, gimple_stmt_iterator gsi, - bool first_p) +cleanup_control_expr_graph (basic_block bb, gimple_stmt_iterator gsi) { edge taken_edge; bool retval = false; @@ -146,25 +144,13 @@ switch (gimple_code (stmt)) { case GIMPLE_COND: - /* During a first iteration on the CFG only remove trivially - dead edges but mark other conditions for re-evaluation. */ - if (first_p) - { - val = const_binop (gimple_cond_code (stmt), boolean_type_node, - gimple_cond_lhs (stmt), - gimple_cond_rhs (stmt)); - if (! val) - bitmap_set_bit (cfgcleanup_altered_bbs, bb->index); - } - else - { - code_helper rcode; - tree ops[3] = {}; - if (gimple_simplify (stmt, &rcode, ops, NULL, no_follow_ssa_edges, - no_follow_ssa_edges) - && rcode == INTEGER_CST) - val = ops[0]; - } + { + gimple_match_op res_op; + if (gimple_simplify (stmt, &res_op, NULL, no_follow_ssa_edges, + no_follow_ssa_edges) + && res_op.code == INTEGER_CST) + val = res_op.ops[0]; + } break; case GIMPLE_SWITCH: @@ -235,7 +221,7 @@ true if anything changes. */ static bool -cleanup_control_flow_bb (basic_block bb, bool first_p) +cleanup_control_flow_bb (basic_block bb) { gimple_stmt_iterator gsi; bool retval = false; @@ -258,7 +244,7 @@ || gimple_code (stmt) == GIMPLE_SWITCH) { gcc_checking_assert (gsi_stmt (gsi_last_bb (bb)) == stmt); - retval |= cleanup_control_expr_graph (bb, gsi, first_p); + retval |= cleanup_control_expr_graph (bb, gsi); } else if (gimple_code (stmt) == GIMPLE_GOTO && TREE_CODE (gimple_goto_dest (stmt)) == ADDR_EXPR @@ -279,7 +265,7 @@ label = TREE_OPERAND (gimple_goto_dest (stmt), 0); if (DECL_CONTEXT (label) != cfun->decl) return retval; - target_block = label_to_block (label); + target_block = label_to_block (cfun, label); for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); ) { if (e->dest != target_block) @@ -359,8 +345,11 @@ if (e->src == ENTRY_BLOCK_PTR_FOR_FN (cfun) || (e->flags & EDGE_EH)) return false; /* If goto_locus of any of the edges differs, prevent removing - the forwarder block for -O0. */ - else if (optimize == 0 && e->goto_locus != locus) + the forwarder block when not optimizing. */ + else if (!optimize + && (LOCATION_LOCUS (e->goto_locus) != UNKNOWN_LOCATION + || LOCATION_LOCUS (locus) != UNKNOWN_LOCATION) + && e->goto_locus != locus) return false; } @@ -375,7 +364,10 @@ case GIMPLE_LABEL: if (DECL_NONLOCAL (gimple_label_label (as_a <glabel *> (stmt)))) return false; - if (optimize == 0 && gimple_location (stmt) != locus) + if (!optimize + && (gimple_has_location (stmt) + || LOCATION_LOCUS (locus) != UNKNOWN_LOCATION) + && gimple_location (stmt) != locus) return false; break; @@ -456,7 +448,7 @@ { edge succ = single_succ_edge (bb), e, s; basic_block dest = succ->dest; - gimple *label; + gimple *stmt; edge_iterator ei; gimple_stmt_iterator gsi, gsi_to; bool can_move_debug_stmts; @@ -469,9 +461,9 @@ /* If the destination block consists of a nonlocal label or is a EH landing pad, do not merge it. */ - label = first_stmt (dest); - if (label) - if (glabel *label_stmt = dyn_cast <glabel *> (label)) + stmt = first_stmt (dest); + if (stmt) + if (glabel *label_stmt = dyn_cast <glabel *> (stmt)) if (DECL_NONLOCAL (gimple_label_label (label_stmt)) || EH_LANDING_PAD_NR (gimple_label_label (label_stmt)) != 0) return false; @@ -552,35 +544,34 @@ gsi_to = gsi_start_bb (dest); for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); ) { - tree decl; - label = gsi_stmt (gsi); - if (is_gimple_debug (label)) + stmt = gsi_stmt (gsi); + if (is_gimple_debug (stmt)) break; - decl = gimple_label_label (as_a <glabel *> (label)); + + /* Forwarder blocks can only contain labels and debug stmts, and + labels must come first, so if we get to this point, we know + we're looking at a label. */ + tree decl = gimple_label_label (as_a <glabel *> (stmt)); if (EH_LANDING_PAD_NR (decl) != 0 || DECL_NONLOCAL (decl) || FORCED_LABEL (decl) || !DECL_ARTIFICIAL (decl)) - { - gsi_remove (&gsi, false); - gsi_insert_before (&gsi_to, label, GSI_SAME_STMT); - } + gsi_move_before (&gsi, &gsi_to); else gsi_next (&gsi); } /* Move debug statements if the destination has a single predecessor. */ - if (can_move_debug_stmts) + if (can_move_debug_stmts && !gsi_end_p (gsi)) { gsi_to = gsi_after_labels (dest); - for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); ) + do { gimple *debug = gsi_stmt (gsi); - if (!is_gimple_debug (debug)) - break; - gsi_remove (&gsi, false); - gsi_insert_before (&gsi_to, debug, GSI_SAME_STMT); + gcc_assert (is_gimple_debug (debug)); + gsi_move_before (&gsi, &gsi_to); } + while (!gsi_end_p (gsi)); } bitmap_set_bit (cfgcleanup_altered_bbs, dest->index); @@ -698,8 +689,8 @@ } -/* Tries to cleanup cfg in basic block BB. Returns true if anything - changes. */ +/* Tries to cleanup cfg in basic block BB by merging blocks. Returns + true if anything changes. */ static bool cleanup_tree_cfg_bb (basic_block bb) @@ -732,76 +723,79 @@ return false; } -/* Iterate the cfg cleanups, while anything changes. */ +/* Do cleanup_control_flow_bb in PRE order. */ static bool -cleanup_tree_cfg_1 (void) +cleanup_control_flow_pre () { bool retval = false; - basic_block bb; - unsigned i, n; - /* Prepare the worklists of altered blocks. */ - cfgcleanup_altered_bbs = BITMAP_ALLOC (NULL); + /* We want remove_edge_and_dominated_blocks to only remove edges, + not dominated blocks which it does when dom info isn't available. + Pretend so. */ + dom_state saved_state = dom_info_state (CDI_DOMINATORS); + set_dom_info_availability (CDI_DOMINATORS, DOM_NONE); - /* During forwarder block cleanup, we may redirect edges out of - SWITCH_EXPRs, which can get expensive. So we want to enable - recording of edge to CASE_LABEL_EXPR. */ - start_recording_case_labels (); + auto_vec<edge_iterator, 20> stack (n_basic_blocks_for_fn (cfun) + 1); + auto_sbitmap visited (last_basic_block_for_fn (cfun)); + bitmap_clear (visited); + + stack.quick_push (ei_start (ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs)); - /* We cannot use FOR_EACH_BB_FN for the BB iterations below - since the basic blocks may get removed. */ + while (! stack.is_empty ()) + { + /* Look at the edge on the top of the stack. */ + edge_iterator ei = stack.last (); + basic_block dest = ei_edge (ei)->dest; - /* Start by iterating over all basic blocks looking for edge removal - opportunities. Do this first because incoming SSA form may be - invalid and we want to avoid performing SSA related tasks such - as propgating out a PHI node during BB merging in that state. */ - n = last_basic_block_for_fn (cfun); - for (i = NUM_FIXED_BLOCKS; i < n; i++) - { - bb = BASIC_BLOCK_FOR_FN (cfun, i); - if (bb) - retval |= cleanup_control_flow_bb (bb, true); + if (dest != EXIT_BLOCK_PTR_FOR_FN (cfun) + && ! bitmap_bit_p (visited, dest->index)) + { + bitmap_set_bit (visited, dest->index); + /* We only possibly remove edges from DEST here, leaving + possibly unreachable code in the IL. */ + retval |= cleanup_control_flow_bb (dest); + if (EDGE_COUNT (dest->succs) > 0) + stack.quick_push (ei_start (dest->succs)); + } + else + { + if (!ei_one_before_end_p (ei)) + ei_next (&stack.last ()); + else + stack.pop (); + } } - /* After doing the above SSA form should be valid (or an update SSA - should be required). */ + set_dom_info_availability (CDI_DOMINATORS, saved_state); + + /* We are deleting BBs in non-reverse dominator order, make sure + insert_debug_temps_for_defs is prepared for that. */ + if (retval) + free_dominance_info (CDI_DOMINATORS); - /* Continue by iterating over all basic blocks looking for BB merging - opportunities. */ - n = last_basic_block_for_fn (cfun); - for (i = NUM_FIXED_BLOCKS; i < n; i++) + /* Remove all now (and previously) unreachable blocks. */ + for (int i = NUM_FIXED_BLOCKS; i < last_basic_block_for_fn (cfun); ++i) { - bb = BASIC_BLOCK_FOR_FN (cfun, i); - if (bb) - retval |= cleanup_tree_cfg_bb (bb); + basic_block bb = BASIC_BLOCK_FOR_FN (cfun, i); + if (bb && !bitmap_bit_p (visited, bb->index)) + { + if (!retval) + free_dominance_info (CDI_DOMINATORS); + delete_basic_block (bb); + retval = true; + } } - /* Now process the altered blocks, as long as any are available. */ - while (!bitmap_empty_p (cfgcleanup_altered_bbs)) - { - i = bitmap_first_set_bit (cfgcleanup_altered_bbs); - bitmap_clear_bit (cfgcleanup_altered_bbs, i); - if (i < NUM_FIXED_BLOCKS) - continue; - - bb = BASIC_BLOCK_FOR_FN (cfun, i); - if (!bb) - continue; - - retval |= cleanup_control_flow_bb (bb, false); - retval |= cleanup_tree_cfg_bb (bb); - } - - end_recording_case_labels (); - BITMAP_FREE (cfgcleanup_altered_bbs); return retval; } static bool mfb_keep_latches (edge e) { - return ! dominated_by_p (CDI_DOMINATORS, e->src, e->dest); + return !((dom_info_available_p (CDI_DOMINATORS) + && dominated_by_p (CDI_DOMINATORS, e->src, e->dest)) + || (e->flags & EDGE_DFS_BACK)); } /* Remove unreachable blocks and other miscellaneous clean up work. @@ -810,26 +804,8 @@ static bool cleanup_tree_cfg_noloop (void) { - bool changed; - timevar_push (TV_TREE_CLEANUP_CFG); - /* Iterate until there are no more cleanups left to do. If any - iteration changed the flowgraph, set CHANGED to true. - - If dominance information is available, there cannot be any unreachable - blocks. */ - if (!dom_info_available_p (CDI_DOMINATORS)) - { - changed = delete_unreachable_blocks (); - calculate_dominance_info (CDI_DOMINATORS); - } - else - { - checking_verify_dominators (CDI_DOMINATORS); - changed = false; - } - /* Ensure that we have single entries into loop headers. Otherwise if one of the entries is becoming a latch due to CFG cleanup (from formerly being part of an irreducible region) then we mess @@ -839,6 +815,10 @@ we need to capture the dominance state before the pending transform. */ if (current_loops) { + /* This needs backedges or dominators. */ + if (!dom_info_available_p (CDI_DOMINATORS)) + mark_dfs_back_edges (); + loop_p loop; unsigned i; FOR_EACH_VEC_ELT (*get_loops (cfun), i, loop) @@ -860,7 +840,9 @@ any_abnormal = true; break; } - if (dominated_by_p (CDI_DOMINATORS, e->src, bb)) + if ((dom_info_available_p (CDI_DOMINATORS) + && dominated_by_p (CDI_DOMINATORS, e->src, bb)) + || (e->flags & EDGE_DFS_BACK)) { found_latch = true; continue; @@ -888,7 +870,63 @@ } } - changed |= cleanup_tree_cfg_1 (); + /* Prepare the worklists of altered blocks. */ + cfgcleanup_altered_bbs = BITMAP_ALLOC (NULL); + + /* Start by iterating over all basic blocks in PRE order looking for + edge removal opportunities. Do this first because incoming SSA form + may be invalid and we want to avoid performing SSA related tasks such + as propgating out a PHI node during BB merging in that state. This + also gets rid of unreachable blocks. */ + bool changed = cleanup_control_flow_pre (); + + /* After doing the above SSA form should be valid (or an update SSA + should be required). */ + + /* Compute dominator info which we need for the iterative process below. */ + if (!dom_info_available_p (CDI_DOMINATORS)) + calculate_dominance_info (CDI_DOMINATORS); + else + checking_verify_dominators (CDI_DOMINATORS); + + /* During forwarder block cleanup, we may redirect edges out of + SWITCH_EXPRs, which can get expensive. So we want to enable + recording of edge to CASE_LABEL_EXPR. */ + start_recording_case_labels (); + + /* Continue by iterating over all basic blocks looking for BB merging + opportunities. We cannot use FOR_EACH_BB_FN for the BB iteration + since the basic blocks may get removed. */ + unsigned n = last_basic_block_for_fn (cfun); + for (unsigned i = NUM_FIXED_BLOCKS; i < n; i++) + { + basic_block bb = BASIC_BLOCK_FOR_FN (cfun, i); + if (bb) + changed |= cleanup_tree_cfg_bb (bb); + } + + /* Now process the altered blocks, as long as any are available. */ + while (!bitmap_empty_p (cfgcleanup_altered_bbs)) + { + unsigned i = bitmap_first_set_bit (cfgcleanup_altered_bbs); + bitmap_clear_bit (cfgcleanup_altered_bbs, i); + if (i < NUM_FIXED_BLOCKS) + continue; + + basic_block bb = BASIC_BLOCK_FOR_FN (cfun, i); + if (!bb) + continue; + + /* BB merging done by cleanup_tree_cfg_bb can end up propagating + out single-argument PHIs which in turn can expose + cleanup_control_flow_bb opportunities so we have to repeat + that here. */ + changed |= cleanup_control_flow_bb (bb); + changed |= cleanup_tree_cfg_bb (bb); + } + + end_recording_case_labels (); + BITMAP_FREE (cfgcleanup_altered_bbs); gcc_assert (dom_info_available_p (CDI_DOMINATORS)); @@ -1288,7 +1326,8 @@ flag_dump_noaddr = flag_dump_unnumbered = 1; fprintf (final_output, "\n"); - dump_enumerated_decls (final_output, dump_flags | TDF_NOUID); + dump_enumerated_decls (final_output, + dump_flags | TDF_SLIM | TDF_NOUID); flag_dump_noaddr = save_noaddr; flag_dump_unnumbered = save_unnumbered; if (fclose (final_output))