Commit d6063d7f by Richard Henderson

re PR tree-optimization/41377 (gimple EH rewrite causes ICE with PPRE (enabled at -O3))

        PR tree-optimization/41377
        * tree-eh.c (unsplit_eh): Propagate degenerate PHIs.
        (cleanup_empty_eh_merge_phis): New change_region parameter;
        pass it on to redirect_eh_edge_1.  Update callers.
        (cleanup_empty_eh_unsplit): Don't require an existing EH label
        at the destination block.

From-SVN: r152728
parent f43085aa
2009-10-13 Richard Henderson <rth@redhat.com>
PR tree-optimization/41377
* tree-eh.c (unsplit_eh): Propagate degenerate PHIs.
(cleanup_empty_eh_merge_phis): New change_region parameter;
pass it on to redirect_eh_edge_1. Update callers.
(cleanup_empty_eh_unsplit): Don't require an existing EH label
at the destination block.
2009-10-13 Basile Starynkevitch <basile@starynkevitch.net> 2009-10-13 Basile Starynkevitch <basile@starynkevitch.net>
* passes.c (register_pass): Replaced gcc_unreachable by
fatal_error on failure. Mentions plugins in comments & messages. * passes.c (register_pass): Replaced gcc_unreachable by
fatal_error on failure. Mentions plugins in comments & messages.
2009-10-13 Jakub Jelinek <jakub@redhat.com> 2009-10-13 Jakub Jelinek <jakub@redhat.com>
// PR 41377
// { dg-do compile }
// { dg-options "-O3" }
struct A
{
bool foo(int*) const;
} a;
struct B {};
struct B1 : B
{
bool (A::*pmf)(int*) const;
const A* pa;
B1() : pmf(&A::foo), pa(&a) {}
bool operator()() const { return (pa->*pmf)(new int); }
};
struct B2 : B
{
B1 b1;
B2(const B1& _b1) : b1(_b1) {}
bool operator()() const { return b1(); }
};
template<int> struct C
{
void bar(B2 b2) { while (b2()) ; }
C() { bar(B2(B1())); }
};
void baz(int i)
{
switch(i)
{
case 0: new C<0>;
case 1: new C<1>;
case 2: new C<2>;
}
}
...@@ -3381,12 +3381,31 @@ unsplit_eh (eh_landing_pad lp) ...@@ -3381,12 +3381,31 @@ unsplit_eh (eh_landing_pad lp)
if (find_edge (e_in->src, e_out->dest)) if (find_edge (e_in->src, e_out->dest))
return false; return false;
/* ??? I can't imagine there would be PHI nodes, since by nature /* ??? We can get degenerate phis due to cfg cleanups. I would have
of critical edge splitting this block should never have been thought this should have been cleaned up by a phicprop pass, but
a dominance frontier. If cfg cleanups somehow confuse this, that doesn't appear to handle virtuals. Propagate by hand. */
due to single edges in and out we ought to have degenerate PHIs if (!gimple_seq_empty_p (phi_nodes (bb)))
and can easily propagate the PHI arguments. */ {
gcc_assert (gimple_seq_empty_p (phi_nodes (bb))); for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); )
{
gimple use_stmt, phi = gsi_stmt (gsi);
tree lhs = gimple_phi_result (phi);
tree rhs = gimple_phi_arg_def (phi, 0);
use_operand_p use_p;
imm_use_iterator iter;
FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
{
FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
SET_USE (use_p, rhs);
}
if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs) = 1;
remove_phi_node (&gsi, true);
}
}
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Unsplit EH landing pad %d to block %i.\n", fprintf (dump_file, "Unsplit EH landing pad %d to block %i.\n",
...@@ -3431,7 +3450,7 @@ unsplit_all_eh (void) ...@@ -3431,7 +3450,7 @@ unsplit_all_eh (void)
static bool static bool
cleanup_empty_eh_merge_phis (basic_block new_bb, basic_block old_bb, cleanup_empty_eh_merge_phis (basic_block new_bb, basic_block old_bb,
edge old_bb_out) edge old_bb_out, bool change_region)
{ {
gimple_stmt_iterator ngsi, ogsi; gimple_stmt_iterator ngsi, ogsi;
edge_iterator ei; edge_iterator ei;
...@@ -3531,7 +3550,7 @@ cleanup_empty_eh_merge_phis (basic_block new_bb, basic_block old_bb, ...@@ -3531,7 +3550,7 @@ cleanup_empty_eh_merge_phis (basic_block new_bb, basic_block old_bb,
for (ei = ei_start (old_bb->preds); (e = ei_safe_edge (ei)); ) for (ei = ei_start (old_bb->preds); (e = ei_safe_edge (ei)); )
if (e->flags & EDGE_EH) if (e->flags & EDGE_EH)
{ {
redirect_eh_edge_1 (e, new_bb, true); redirect_eh_edge_1 (e, new_bb, change_region);
redirect_edge_succ (e, new_bb); redirect_edge_succ (e, new_bb);
flush_pending_stmts (e); flush_pending_stmts (e);
} }
...@@ -3583,10 +3602,9 @@ cleanup_empty_eh_move_lp (basic_block bb, edge e_out, ...@@ -3583,10 +3602,9 @@ cleanup_empty_eh_move_lp (basic_block bb, edge e_out,
multiple incoming edges and phis are involved. */ multiple incoming edges and phis are involved. */
static bool static bool
cleanup_empty_eh_unsplit (basic_block bb, edge e_out, eh_landing_pad olp) cleanup_empty_eh_unsplit (basic_block bb, edge e_out, eh_landing_pad lp)
{ {
gimple_stmt_iterator gsi; gimple_stmt_iterator gsi;
eh_landing_pad nlp;
tree lab; tree lab;
/* We really ought not have totally lost everything following /* We really ought not have totally lost everything following
...@@ -3594,35 +3612,30 @@ cleanup_empty_eh_unsplit (basic_block bb, edge e_out, eh_landing_pad olp) ...@@ -3594,35 +3612,30 @@ cleanup_empty_eh_unsplit (basic_block bb, edge e_out, eh_landing_pad olp)
be a successor. */ be a successor. */
gcc_assert (e_out != NULL); gcc_assert (e_out != NULL);
/* Look for an EH label in the successor block. */ /* The destination block must not already have a landing pad
for a different region. */
lab = NULL; lab = NULL;
for (gsi = gsi_start_bb (e_out->dest); !gsi_end_p (gsi); gsi_next (&gsi)) for (gsi = gsi_start_bb (e_out->dest); !gsi_end_p (gsi); gsi_next (&gsi))
{ {
gimple stmt = gsi_stmt (gsi); gimple stmt = gsi_stmt (gsi);
int lp_nr;
if (gimple_code (stmt) != GIMPLE_LABEL) if (gimple_code (stmt) != GIMPLE_LABEL)
break; break;
lab = gimple_label_label (stmt); lab = gimple_label_label (stmt);
if (EH_LANDING_PAD_NR (lab)) lp_nr = EH_LANDING_PAD_NR (lab);
goto found; if (lp_nr && get_eh_region_from_lp_number (lp_nr) != lp->region)
return false;
} }
return false;
found:
/* The other label had better be part of the same EH region. Given that
we've not lowered RESX, there should be no way to have a totally empty
landing pad that crosses to another EH region. */
nlp = get_eh_landing_pad_from_number (EH_LANDING_PAD_NR (lab));
gcc_assert (nlp->region == olp->region);
/* Attempt to move the PHIs into the successor block. */ /* Attempt to move the PHIs into the successor block. */
if (cleanup_empty_eh_merge_phis (e_out->dest, bb, e_out)) if (cleanup_empty_eh_merge_phis (e_out->dest, bb, e_out, false))
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, fprintf (dump_file,
"Unsplit EH landing pad %d to block %d via lp %d.\n", "Unsplit EH landing pad %d to block %i "
olp->index, e_out->dest->index, nlp->index); "(via cleanup_empty_eh).\n",
lp->index, e_out->dest->index);
remove_eh_landing_pad (olp);
return true; return true;
} }
...@@ -3725,7 +3738,7 @@ cleanup_empty_eh (eh_landing_pad lp) ...@@ -3725,7 +3738,7 @@ cleanup_empty_eh (eh_landing_pad lp)
landing pad block. If the merge succeeds, we'll already have redirected landing pad block. If the merge succeeds, we'll already have redirected
all the EH edges. The handler itself will go unreachable if there were all the EH edges. The handler itself will go unreachable if there were
no normal edges. */ no normal edges. */
if (cleanup_empty_eh_merge_phis (e_out->dest, bb, e_out)) if (cleanup_empty_eh_merge_phis (e_out->dest, bb, e_out, true))
goto succeed; goto succeed;
/* Finally, if all input edges are EH edges, then we can (potentially) /* Finally, if all input edges are EH edges, then we can (potentially)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment