From patchwork Mon Jun 14 07:03:26 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 55480 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id CCED2B7D85 for ; Mon, 14 Jun 2010 17:03:45 +1000 (EST) Received: (qmail 3800 invoked by alias); 14 Jun 2010 07:03:43 -0000 Received: (qmail 3791 invoked by uid 22791); 14 Jun 2010 07:03:42 -0000 X-SWARE-Spam-Status: No, hits=-2.1 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, SPF_HELO_PASS, TW_CC, TW_TM, T_RP_MATCHES_RCVD, T_TVD_MIME_NO_HEADERS X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (216.239.44.51) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 14 Jun 2010 07:03:37 +0000 Received: from hpaq1.eem.corp.google.com (hpaq1.eem.corp.google.com [172.25.149.1]) by smtp-out.google.com with ESMTP id o5E73X68020914 for ; Mon, 14 Jun 2010 00:03:34 -0700 Received: from pwi1 (pwi1.prod.google.com [10.241.219.1]) by hpaq1.eem.corp.google.com with ESMTP id o5E73Vdh022545 for ; Mon, 14 Jun 2010 00:03:32 -0700 Received: by pwi1 with SMTP id 1so2575359pwi.19 for ; Mon, 14 Jun 2010 00:03:31 -0700 (PDT) Received: by 10.114.10.14 with SMTP id 14mr4191769waj.72.1276499011030; Mon, 14 Jun 2010 00:03:31 -0700 (PDT) Received: from coign.google.com (adsl-71-133-8-30.dsl.pltn13.pacbell.net [71.133.8.30]) by mx.google.com with ESMTPS id b6sm51468953wam.9.2010.06.14.00.03.29 (version=TLSv1/SSLv3 cipher=RC4-MD5); Mon, 14 Jun 2010 00:03:30 -0700 (PDT) To: gcc-patches@gcc.gnu.org Subject: [gccgo] Fixes for tree-eh.c From: Ian Lance Taylor Date: Mon, 14 Jun 2010 00:03:26 -0700 Message-ID: User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.1 (gnu/linux) MIME-Version: 1.0 X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org This patch fixes a problem which arose when compiling some Go code with -O0. The code looked like this after ehcleanup2: # BLOCK 11 # PRED: 2 : resx 2 # SUCC: 12 (eh) # BLOCK 12 # PRED: 11 (eh) : finally_tmp.1007_15 = 1; goto ; # SUCC: 5 (fallthru) The resx pass turned it into this, via code with this comment: /* We can wind up with no source region when pass_cleanup_eh shows that there are no entries into an eh region and deletes it, but then the block that contains the resx isn't removed. This can happen without optimization when the switch statement created by lower_try_finally_switch isn't simplified to remove the eh case. Resolve this by expanding the resx node to an abort. */ # BLOCK 11 # PRED: 2 : __builtin_trap (); # SUCC: # BLOCK 12 # PRED: : finally_tmp.1007_15 = 1; goto ; # SUCC: 5 (fallthru) Now block 12 exists but has no predecessors. That causes the dominator pass to crash later. This patch avoids the problem by removing block 12 in this case. I haven't been able to find a C or C++ test case which replicates this. I think the problem is that I can't figure out how to generate a try/finally clause in which the finally clause does not make any function calls and hence can not throw an exception. This patch also brings in the trunk fix for PR 43365. I will try to do a merge from trunk to gccgo branch soon. This patch committed to gccgo branch. Ian Index: tree-eh.c =================================================================== --- tree-eh.c (revision 155628) +++ tree-eh.c (working copy) @@ -578,6 +578,7 @@ replace_goto_queue (struct leh_tf_state if (tf->goto_queue_active == 0) return; replace_goto_queue_stmt_list (tf->top_p_seq, tf); + replace_goto_queue_stmt_list (eh_seq, tf); } /* Add a new record to the goto queue contained in TF. NEW_STMT is the @@ -658,7 +659,6 @@ record_in_goto_queue_label (struct leh_t labels. */ new_stmt = stmt; record_in_goto_queue (tf, new_stmt, index, true); - } /* For any GIMPLE_GOTO or GIMPLE_RETURN, decide whether it leaves a try_finally @@ -1545,6 +1545,7 @@ lower_try_finally (struct leh_state *sta struct leh_tf_state this_tf; struct leh_state this_state; int ndests; + gimple_seq old_eh_seq; /* Process the try block. */ @@ -1561,6 +1562,9 @@ lower_try_finally (struct leh_state *sta this_state.ehp_region = state->ehp_region; this_state.tf = &this_tf; + old_eh_seq = eh_seq; + eh_seq = NULL; + lower_eh_constructs_1 (&this_state, gimple_try_eval(tp)); /* Determine if the try block is escaped through the bottom. */ @@ -1616,6 +1620,20 @@ lower_try_finally (struct leh_state *sta if (this_tf.goto_queue_map) pointer_map_destroy (this_tf.goto_queue_map); + /* If there was an old (aka outer) eh_seq, append the current eh_seq. + If there was no old eh_seq, then the append is trivially already done. */ + if (old_eh_seq) + { + if (eh_seq == NULL) + eh_seq = old_eh_seq; + else + { + gimple_seq new_eh_seq = eh_seq; + eh_seq = old_eh_seq; + gimple_seq_add_seq(&eh_seq, new_eh_seq); + } + } + return this_tf.top_p_seq; } @@ -2844,7 +2862,8 @@ struct gimple_opt_pass pass_refactor_eh /* At the end of gimple optimization, we can lower RESX. */ static bool -lower_resx (basic_block bb, gimple stmt, struct pointer_map_t *mnt_map) +lower_resx (basic_block bb, gimple stmt, struct pointer_map_t *mnt_map, + bool *any_removed) { int lp_nr; eh_region src_r, dst_r; @@ -2877,7 +2896,31 @@ lower_resx (basic_block bb, gimple stmt, gsi_insert_before (&gsi, x, GSI_SAME_STMT); while (EDGE_COUNT (bb->succs) > 0) - remove_edge (EDGE_SUCC (bb, 0)); + { + edge e = EDGE_SUCC (bb, 0); + basic_block bbnext = e->dest; + + remove_edge (e); + + /* If we removed the last exception edge to the destination + block, remove the landing pad. */ + if (lp_nr >= 0) + { + edge_iterator ei; + + FOR_EACH_EDGE (e, ei, bbnext->preds) + if (e->flags & EDGE_EH) + break; + if (e == NULL) + { + eh_landing_pad lp = get_eh_landing_pad_from_number (lp_nr); + remove_eh_landing_pad (lp); + if (EDGE_COUNT (bbnext->preds) == 0) + *any_removed = true; + ret = true; + } + } + } } else if (dst_r) { @@ -2998,6 +3041,8 @@ execute_lower_resx (void) struct pointer_map_t *mnt_map; bool dominance_invalidated = false; bool any_rewritten = false; + bool any_removed = false; + unsigned int todo; mnt_map = pointer_map_create (); @@ -3006,7 +3051,8 @@ execute_lower_resx (void) gimple last = last_stmt (bb); if (last && is_gimple_resx (last)) { - dominance_invalidated |= lower_resx (bb, last, mnt_map); + dominance_invalidated |= lower_resx (bb, last, mnt_map, + &any_removed); any_rewritten = true; } } @@ -3019,7 +3065,12 @@ execute_lower_resx (void) free_dominance_info (CDI_POST_DOMINATORS); } - return any_rewritten ? TODO_update_ssa_only_virtuals : 0; + todo = 0; + if (any_removed) + todo |= TODO_cleanup_cfg; + if (any_rewritten) + todo |= TODO_update_ssa_only_virtuals; + return todo; } static bool