This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Fix tree-ssa-dce Ada LTO bootstrap ice
- From: Richard Biener <richard dot guenther at gmail dot com>
- To: Jan Hubicka <hubicka at ucw dot cz>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>, Eric Botcazou <ebotcazou at adacore dot com>
- Date: Wed, 25 Nov 2015 13:37:05 +0100
- Subject: Re: Fix tree-ssa-dce Ada LTO bootstrap ice
- Authentication-results: sourceware.org; auth=none
- References: <20151122184933 dot GA88607 at kam dot mff dot cuni dot cz>
On Sun, Nov 22, 2015 at 7:49 PM, Jan Hubicka <hubicka@ucw.cz> wrote:
> Hi,
> this patch fixes tree-ssa-dce ICE seen during Ada bootstrap. It is updated
> version of https://gcc.gnu.org/ml/gcc-patches/2015-05/msg02876.html for
> current mainline
>
> Bootstrapped/regtested x86_64-linux, OK?
Ok.
Thanks,
Richard.
> PR middle-end/65337
> * tree-ssa-dce.c (bb_postorder): New static var.
> (forward_edge_to_pdom): Remove.
> (remove_dead_stmt): Instead of redirecting edges only keep an edge
> on a path to nearest live BB.
> (eliminate_unnecessary_stmts): Free bb_postorder.
> * cfganal.c (dfs_find_deadend): Add START_POINTES.
> * cfganal.h (inverted_post_order_compute): Update prototype.
> Index: tree-ssa-dce.c
> ===================================================================
> --- tree-ssa-dce.c (revision 230718)
> +++ tree-ssa-dce.c (working copy)
> @@ -112,6 +112,9 @@ static sbitmap visited_control_parents;
> to be recomputed. */
> static bool cfg_altered;
>
> +/* When non-NULL holds map from basic block index into the postorder. */
> +static int *bb_postorder;
> +
>
> /* If STMT is not already marked necessary, mark it, and add it to the
> worklist if ADD_TO_WORKLIST is true. */
> @@ -997,65 +1000,6 @@ remove_dead_phis (basic_block bb)
> return something_changed;
> }
>
> -/* Forward edge E to respective POST_DOM_BB and update PHIs. */
> -
> -static edge
> -forward_edge_to_pdom (edge e, basic_block post_dom_bb)
> -{
> - gphi_iterator gsi;
> - edge e2 = NULL;
> - edge_iterator ei;
> -
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - fprintf (dump_file, "Redirecting edge %i->%i to %i\n", e->src->index,
> - e->dest->index, post_dom_bb->index);
> -
> - e2 = redirect_edge_and_branch (e, post_dom_bb);
> - cfg_altered = true;
> -
> - /* If edge was already around, no updating is necessary. */
> - if (e2 != e)
> - return e2;
> -
> - if (!gimple_seq_empty_p (phi_nodes (post_dom_bb)))
> - {
> - /* We are sure that for every live PHI we are seeing control dependent BB.
> - This means that we can pick any edge to duplicate PHI args from. */
> - FOR_EACH_EDGE (e2, ei, post_dom_bb->preds)
> - if (e2 != e)
> - break;
> - for (gsi = gsi_start_phis (post_dom_bb); !gsi_end_p (gsi);)
> - {
> - gphi *phi = gsi.phi ();
> - tree op;
> - source_location locus;
> -
> - /* PHIs for virtuals have no control dependency relation on them.
> - We are lost here and must force renaming of the symbol. */
> - if (virtual_operand_p (gimple_phi_result (phi)))
> - {
> - mark_virtual_phi_result_for_renaming (phi);
> - remove_phi_node (&gsi, true);
> - continue;
> - }
> -
> - /* Dead PHI do not imply control dependency. */
> - if (!gimple_plf (phi, STMT_NECESSARY))
> - {
> - gsi_next (&gsi);
> - continue;
> - }
> -
> - op = gimple_phi_arg_def (phi, e2->dest_idx);
> - locus = gimple_phi_arg_location (phi, e2->dest_idx);
> - add_phi_arg (phi, op, e, locus);
> - /* The resulting PHI if not dead can only be degenerate. */
> - gcc_assert (degenerate_phi_p (phi));
> - gsi_next (&gsi);
> - }
> - }
> - return e;
> -}
>
> /* Remove dead statement pointed to by iterator I. Receives the basic block BB
> containing I so that we don't have to look it up. */
> @@ -1075,38 +1019,48 @@ remove_dead_stmt (gimple_stmt_iterator *
> stats.removed++;
>
> /* If we have determined that a conditional branch statement contributes
> - nothing to the program, then we not only remove it, but we also change
> - the flow graph so that the current block will simply fall-thru to its
> - immediate post-dominator. The blocks we are circumventing will be
> - removed by cleanup_tree_cfg if this change in the flow graph makes them
> - unreachable. */
> + nothing to the program, then we not only remove it, but we need to update
> + the CFG. We can chose any of edges out of BB as long as we are sure to not
> + close infinite loops. This is done by always choosing the edge closer to
> + exit in inverted_post_order_compute order. */
> if (is_ctrl_stmt (stmt))
> {
> - basic_block post_dom_bb;
> - edge e, e2;
> edge_iterator ei;
> + edge e = NULL, e2;
>
> - post_dom_bb = get_immediate_dominator (CDI_POST_DOMINATORS, bb);
> -
> - e = find_edge (bb, post_dom_bb);
> -
> - /* If edge is already there, try to use it. This avoids need to update
> - PHI nodes. Also watch for cases where post dominator does not exists
> - or is exit block. These can happen for infinite loops as we create
> - fake edges in the dominator tree. */
> - if (e)
> - ;
> - else if (! post_dom_bb || post_dom_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
> - e = EDGE_SUCC (bb, 0);
> - else
> - e = forward_edge_to_pdom (EDGE_SUCC (bb, 0), post_dom_bb);
> + /* See if there is only one non-abnormal edge. */
> + if (single_succ_p (bb))
> + e = single_succ_edge (bb);
> + /* Otherwise chose one that is closer to bb with live statement in it.
> + To be able to chose one, we compute inverted post order starting from
> + all BBs with live statements. */
> + if (!e)
> + {
> + if (!bb_postorder)
> + {
> + int *postorder = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
> + int postorder_num
> + = inverted_post_order_compute (postorder, &bb_contains_live_stmts);
> + bb_postorder = XNEWVEC (int, last_basic_block_for_fn (cfun));
> + for (int i = 0; i < postorder_num; ++i)
> + bb_postorder[postorder[i]] = i;
> + free (postorder);
> + }
> + FOR_EACH_EDGE (e2, ei, bb->succs)
> + if (!e || e2->dest == EXIT_BLOCK_PTR_FOR_FN (cfun)
> + || bb_postorder [e->dest->index] < bb_postorder [e2->dest->index])
> + e = e2;
> + }
> gcc_assert (e);
> e->probability = REG_BR_PROB_BASE;
> e->count = bb->count;
>
> /* The edge is no longer associated with a conditional, so it does
> - not have TRUE/FALSE flags. */
> - e->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
> + not have TRUE/FALSE flags.
> + We are also safe to drop EH/ABNORMAL flags and turn them into
> + normal control flow, because we know that all the destinations (including
> + those odd edges) are equivalent for program execution. */
> + e->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE | EDGE_EH | EDGE_ABNORMAL);
>
> /* The lone outgoing edge from BB will be a fallthru edge. */
> e->flags |= EDGE_FALLTHRU;
> @@ -1516,6 +1470,10 @@ eliminate_unnecessary_stmts (void)
> something_changed |= remove_dead_phis (bb);
> }
>
> + if (bb_postorder)
> + free (bb_postorder);
> + bb_postorder = NULL;
> +
> return something_changed;
> }
>
> Index: cfganal.c
> ===================================================================
> --- cfganal.c (revision 230718)
> +++ cfganal.c (working copy)
> @@ -759,6 +759,9 @@ dfs_find_deadend (basic_block bb)
> (from successors to predecessors).
> This ordering can be used for forward dataflow problems among others.
>
> + Optionally if START_POINTS is specified, start from exit block and all
> + basic blocks in START_POINTS. This is used by CD-DCE.
> +
> This function assumes that all blocks in the CFG are reachable
> from the ENTRY (but not necessarily from EXIT).
>
> @@ -776,7 +779,8 @@ dfs_find_deadend (basic_block bb)
> and do another inverted traversal from that block. */
>
> int
> -inverted_post_order_compute (int *post_order)
> +inverted_post_order_compute (int *post_order,
> + sbitmap *start_points)
> {
> basic_block bb;
> edge_iterator *stack;
> @@ -797,6 +801,22 @@ inverted_post_order_compute (int *post_o
> /* None of the nodes in the CFG have been visited yet. */
> bitmap_clear (visited);
>
> + if (start_points)
> + {
> + FOR_ALL_BB_FN (bb, cfun)
> + if (bitmap_bit_p (*start_points, bb->index)
> + && EDGE_COUNT (bb->preds) > 0)
> + {
> + stack[sp++] = ei_start (bb->preds);
> + bitmap_set_bit (visited, bb->index);
> + }
> + if (EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds))
> + {
> + stack[sp++] = ei_start (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds);
> + bitmap_set_bit (visited, EXIT_BLOCK_PTR_FOR_FN (cfun)->index);
> + }
> + }
> + else
> /* Put all blocks that have no successor into the initial work list. */
> FOR_ALL_BB_FN (bb, cfun)
> if (EDGE_COUNT (bb->succs) == 0)
> Index: cfganal.h
> ===================================================================
> --- cfganal.h (revision 230718)
> +++ cfganal.h (working copy)
> @@ -62,7 +62,7 @@ extern void add_noreturn_fake_exit_edges
> extern void connect_infinite_loops_to_exit (void);
> extern int post_order_compute (int *, bool, bool);
> extern basic_block dfs_find_deadend (basic_block);
> -extern int inverted_post_order_compute (int *);
> +extern int inverted_post_order_compute (int *, sbitmap *start_points = 0);
> extern int pre_and_rev_post_order_compute_fn (struct function *,
> int *, int *, bool);
> extern int pre_and_rev_post_order_compute (int *, int *, bool);