diff options
author | rus <rus@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-11-09 20:58:24 +0000 |
---|---|---|
committer | rus <rus@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-11-09 20:58:24 +0000 |
commit | 7f4db7c80779ecbc57d1146654daf0acfe18de66 (patch) | |
tree | 3af522a3b5e149c3fd498ecb1255994daae2129a /gcc/tree-eh.c | |
parent | 611349f0ec42a37591db2cd02974a11a48d10edb (diff) | |
download | gcc-profile-stdlib.tar.gz |
merge from trunkprofile-stdlib
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/profile-stdlib@154052 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-eh.c')
-rw-r--r-- | gcc/tree-eh.c | 204 |
1 files changed, 114 insertions, 90 deletions
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index 3ed92a59bc7..c5c7f7146c8 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -340,7 +340,7 @@ static gimple_seq eh_seq; /* Record whether an EH region contains something that can throw, indexed by EH region number. */ -static bitmap eh_region_may_contain_throw; +static bitmap eh_region_may_contain_throw_map; /* The GOTO_QUEUE is is an array of GIMPLE_GOTO and GIMPLE_RETURN statements that are seen to escape this GIMPLE_TRY_FINALLY node. @@ -863,15 +863,24 @@ emit_eh_dispatch (gimple_seq *seq, eh_region region) static void note_eh_region_may_contain_throw (eh_region region) { - while (!bitmap_bit_p (eh_region_may_contain_throw, region->index)) + while (!bitmap_bit_p (eh_region_may_contain_throw_map, region->index)) { - bitmap_set_bit (eh_region_may_contain_throw, region->index); + bitmap_set_bit (eh_region_may_contain_throw_map, region->index); region = region->outer; if (region == NULL) break; } } +/* Check if REGION has been marked as containing a throw. If REGION is + NULL, this predicate is false. */ + +static inline bool +eh_region_may_contain_throw (eh_region r) +{ + return r && bitmap_bit_p (eh_region_may_contain_throw_map, r->index); +} + /* We want to transform try { body; } catch { stuff; } to @@ -1192,12 +1201,11 @@ lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf) if (tf->may_throw) { - emit_post_landing_pad (&eh_seq, tf->region); - seq = lower_try_finally_dup_block (finally, state); lower_eh_constructs_1 (state, seq); - gimple_seq_add_seq (&eh_seq, seq); + emit_post_landing_pad (&eh_seq, tf->region); + gimple_seq_add_seq (&eh_seq, seq); emit_resx (&eh_seq, tf->region); } @@ -1560,8 +1568,7 @@ lower_try_finally (struct leh_state *state, gimple tp) /* Determine if any exceptions are possible within the try block. */ if (using_eh_for_cleanups_p) - this_tf.may_throw = bitmap_bit_p (eh_region_may_contain_throw, - this_tf.region->index); + this_tf.may_throw = eh_region_may_contain_throw (this_tf.region); if (this_tf.may_throw) honor_protect_cleanup_actions (state, &this_state, &this_tf); @@ -1619,22 +1626,23 @@ lower_try_finally (struct leh_state *state, gimple tp) static gimple_seq lower_catch (struct leh_state *state, gimple tp) { - eh_region try_region; - struct leh_state this_state; + eh_region try_region = NULL; + struct leh_state this_state = *state; gimple_stmt_iterator gsi; tree out_label; gimple_seq new_seq; gimple x; location_t try_catch_loc = gimple_location (tp); - try_region = gen_eh_region_try (state->cur_region); - - this_state = *state; - this_state.cur_region = try_region; + if (flag_exceptions) + { + try_region = gen_eh_region_try (state->cur_region); + this_state.cur_region = try_region; + } lower_eh_constructs_1 (&this_state, gimple_try_eval (tp)); - if (!bitmap_bit_p (eh_region_may_contain_throw, try_region->index)) + if (!eh_region_may_contain_throw (try_region)) return gimple_try_eval (tp); new_seq = NULL; @@ -1687,21 +1695,23 @@ lower_catch (struct leh_state *state, gimple tp) static gimple_seq lower_eh_filter (struct leh_state *state, gimple tp) { - struct leh_state this_state; - eh_region this_region; + struct leh_state this_state = *state; + eh_region this_region = NULL; gimple inner, x; gimple_seq new_seq; inner = gimple_seq_first_stmt (gimple_try_cleanup (tp)); - this_region = gen_eh_region_allowed (state->cur_region, - gimple_eh_filter_types (inner)); - this_state = *state; - this_state.cur_region = this_region; + if (flag_exceptions) + { + this_region = gen_eh_region_allowed (state->cur_region, + gimple_eh_filter_types (inner)); + this_state.cur_region = this_region; + } lower_eh_constructs_1 (&this_state, gimple_try_eval (tp)); - if (!bitmap_bit_p (eh_region_may_contain_throw, this_region->index)) + if (!eh_region_may_contain_throw (this_region)) return gimple_try_eval (tp); new_seq = NULL; @@ -1730,24 +1740,25 @@ lower_eh_filter (struct leh_state *state, gimple tp) static gimple_seq lower_eh_must_not_throw (struct leh_state *state, gimple tp) { - struct leh_state this_state; - eh_region this_region; - gimple inner; + struct leh_state this_state = *state; - inner = gimple_seq_first_stmt (gimple_try_cleanup (tp)); + if (flag_exceptions) + { + gimple inner = gimple_seq_first_stmt (gimple_try_cleanup (tp)); + eh_region this_region; - this_region = gen_eh_region_must_not_throw (state->cur_region); - this_region->u.must_not_throw.failure_decl - = gimple_eh_must_not_throw_fndecl (inner); - this_region->u.must_not_throw.failure_loc = gimple_location (tp); + this_region = gen_eh_region_must_not_throw (state->cur_region); + this_region->u.must_not_throw.failure_decl + = gimple_eh_must_not_throw_fndecl (inner); + this_region->u.must_not_throw.failure_loc = gimple_location (tp); - /* In order to get mangling applied to this decl, we must mark it - used now. Otherwise, pass_ipa_free_lang_data won't think it - needs to happen. */ - TREE_USED (this_region->u.must_not_throw.failure_decl) = 1; + /* In order to get mangling applied to this decl, we must mark it + used now. Otherwise, pass_ipa_free_lang_data won't think it + needs to happen. */ + TREE_USED (this_region->u.must_not_throw.failure_decl) = 1; - this_state = *state; - this_state.cur_region = this_region; + this_state.cur_region = this_region; + } lower_eh_constructs_1 (&this_state, gimple_try_eval (tp)); @@ -1760,26 +1771,20 @@ lower_eh_must_not_throw (struct leh_state *state, gimple tp) static gimple_seq lower_cleanup (struct leh_state *state, gimple tp) { - struct leh_state this_state; - eh_region this_region; + struct leh_state this_state = *state; + eh_region this_region = NULL; struct leh_tf_state fake_tf; gimple_seq result; - /* If not using eh, then exception-only cleanups are no-ops. */ - if (!flag_exceptions) + if (flag_exceptions) { - result = gimple_try_eval (tp); - lower_eh_constructs_1 (state, result); - return result; + this_region = gen_eh_region_cleanup (state->cur_region); + this_state.cur_region = this_region; } - this_region = gen_eh_region_cleanup (state->cur_region); - this_state = *state; - this_state.cur_region = this_region; - lower_eh_constructs_1 (&this_state, gimple_try_eval (tp)); - if (!bitmap_bit_p (eh_region_may_contain_throw, this_region->index)) + if (!eh_region_may_contain_throw (this_region)) return gimple_try_eval (tp); /* Build enough of a try-finally state so that we can reuse @@ -1919,21 +1924,27 @@ lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi) else { x = gimple_seq_first_stmt (gimple_try_cleanup (stmt)); - switch (gimple_code (x)) + if (!x) { - case GIMPLE_CATCH: - replace = lower_catch (state, stmt); - break; - case GIMPLE_EH_FILTER: - replace = lower_eh_filter (state, stmt); - break; - case GIMPLE_EH_MUST_NOT_THROW: - replace = lower_eh_must_not_throw (state, stmt); - break; - default: - replace = lower_cleanup (state, stmt); - break; + replace = gimple_try_eval (stmt); + lower_eh_constructs_1 (state, replace); } + else + switch (gimple_code (x)) + { + case GIMPLE_CATCH: + replace = lower_catch (state, stmt); + break; + case GIMPLE_EH_FILTER: + replace = lower_eh_filter (state, stmt); + break; + case GIMPLE_EH_MUST_NOT_THROW: + replace = lower_eh_must_not_throw (state, stmt); + break; + default: + replace = lower_cleanup (state, stmt); + break; + } } /* Remove the old stmt and insert the transformed sequence @@ -1974,7 +1985,7 @@ lower_eh_constructs (void) return 0; finally_tree = htab_create (31, struct_ptr_hash, struct_ptr_eq, free); - eh_region_may_contain_throw = BITMAP_ALLOC (NULL); + eh_region_may_contain_throw_map = BITMAP_ALLOC (NULL); memset (&null_state, 0, sizeof (null_state)); collect_finally_tree_1 (bodyp, NULL); @@ -1991,7 +2002,7 @@ lower_eh_constructs (void) gcc_assert (bodyp == gimple_body (current_function_decl)); htab_delete (finally_tree); - BITMAP_FREE (eh_region_may_contain_throw); + BITMAP_FREE (eh_region_may_contain_throw_map); eh_seq = NULL; /* If this function needs a language specific EH personality routine @@ -3375,12 +3386,31 @@ unsplit_eh (eh_landing_pad lp) if (find_edge (e_in->src, e_out->dest)) return false; - /* ??? I can't imagine there would be PHI nodes, since by nature - of critical edge splitting this block should never have been - a dominance frontier. If cfg cleanups somehow confuse this, - due to single edges in and out we ought to have degenerate PHIs - and can easily propagate the PHI arguments. */ - gcc_assert (gimple_seq_empty_p (phi_nodes (bb))); + /* ??? We can get degenerate phis due to cfg cleanups. I would have + thought this should have been cleaned up by a phicprop pass, but + that doesn't appear to handle virtuals. Propagate by hand. */ + if (!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)) fprintf (dump_file, "Unsplit EH landing pad %d to block %i.\n", @@ -3425,7 +3455,7 @@ unsplit_all_eh (void) static bool 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; edge_iterator ei; @@ -3525,7 +3555,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)); ) 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); flush_pending_stmts (e); } @@ -3577,10 +3607,9 @@ cleanup_empty_eh_move_lp (basic_block bb, edge e_out, multiple incoming edges and phis are involved. */ 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; - eh_landing_pad nlp; tree lab; /* We really ought not have totally lost everything following @@ -3588,35 +3617,30 @@ cleanup_empty_eh_unsplit (basic_block bb, edge e_out, eh_landing_pad olp) be a successor. */ 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; for (gsi = gsi_start_bb (e_out->dest); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple stmt = gsi_stmt (gsi); + int lp_nr; + if (gimple_code (stmt) != GIMPLE_LABEL) break; lab = gimple_label_label (stmt); - if (EH_LANDING_PAD_NR (lab)) - goto found; + lp_nr = EH_LANDING_PAD_NR (lab); + 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. */ - 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)) fprintf (dump_file, - "Unsplit EH landing pad %d to block %d via lp %d.\n", - olp->index, e_out->dest->index, nlp->index); - - remove_eh_landing_pad (olp); + "Unsplit EH landing pad %d to block %i " + "(via cleanup_empty_eh).\n", + lp->index, e_out->dest->index); return true; } @@ -3719,7 +3743,7 @@ cleanup_empty_eh (eh_landing_pad lp) 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 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; /* Finally, if all input edges are EH edges, then we can (potentially) |