diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-11-30 14:33:00 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-11-30 14:33:00 +0000 |
commit | 955700fa8efe0bea6504de4db67f750ee24ad574 (patch) | |
tree | 16a1ccec49b0641047dbd3739de6833a0dffdf78 /gcc/value-prof.c | |
parent | 9c0515a25d2fb09435ed58556574d6ea2442e393 (diff) | |
download | gcc-955700fa8efe0bea6504de4db67f750ee24ad574.tar.gz |
2010-11-30 Richard Guenther <rguenther@suse.de>
PR tree-optimization/46717
* value-prof.c (gimple_ic): Preserve EH edges of the indirect
call. Manually create EH edges for the direct call and update
target PHI nodes.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@167298 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/value-prof.c')
-rw-r--r-- | gcc/value-prof.c | 34 |
1 files changed, 22 insertions, 12 deletions
diff --git a/gcc/value-prof.c b/gcc/value-prof.c index ea70e2a15e7..9e27a9679fc 100644 --- a/gcc/value-prof.c +++ b/gcc/value-prof.c @@ -1145,7 +1145,11 @@ gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call, icall_bb = e_di->dest; icall_bb->count = all - count; - e_ij = split_block (icall_bb, icall_stmt); + /* Do not disturb existing EH edges from the indirect call. */ + if (last_stmt (icall_bb) != icall_stmt) + e_ij = split_block (icall_bb, icall_stmt); + else + e_ij = find_fallthru_edge (icall_bb->succs); join_bb = e_ij->dest; join_bb->count = all; @@ -1181,21 +1185,27 @@ gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call, add_phi_arg (phi, gimple_call_lhs (dcall_stmt), e_dj, UNKNOWN_LOCATION); } - /* Fix eh edges */ + /* Build an EH edge for the direct call if necessary. */ lp_nr = lookup_stmt_eh_lp (icall_stmt); - if (lp_nr != 0) + if (lp_nr != 0 + && stmt_could_throw_p (dcall_stmt)) { - if (stmt_could_throw_p (dcall_stmt)) + edge e_eh, e; + edge_iterator ei; + gimple_stmt_iterator psi; + + add_stmt_to_eh_lp (dcall_stmt, lp_nr); + FOR_EACH_EDGE (e_eh, ei, icall_bb->succs) + if (e_eh->flags & EDGE_EH) + break; + e = make_edge (dcall_bb, e_eh->dest, EDGE_EH); + for (psi = gsi_start_phis (e_eh->dest); + !gsi_end_p (psi); gsi_next (&psi)) { - add_stmt_to_eh_lp (dcall_stmt, lp_nr); - make_eh_edges (dcall_stmt); + gimple phi = gsi_stmt (psi); + SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), + PHI_ARG_DEF_FROM_EDGE (phi, e_eh)); } - - gcc_assert (stmt_could_throw_p (icall_stmt)); - make_eh_edges (icall_stmt); - - /* The old EH edges are sill on the join BB, purge them. */ - gimple_purge_dead_eh_edges (join_bb); } return dcall_stmt; |