From patchwork Sun Oct 24 20:45:45 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Botcazou X-Patchwork-Id: 69052 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 D71E2B70A7 for ; Mon, 25 Oct 2010 07:54:00 +1100 (EST) Received: (qmail 30734 invoked by alias); 24 Oct 2010 20:53:59 -0000 Received: (qmail 30726 invoked by uid 22791); 24 Oct 2010 20:53:58 -0000 X-SWARE-Spam-Status: No, hits=-2.0 required=5.0 tests=AWL,BAYES_00,TW_CF X-Spam-Check-By: sourceware.org Received: from mel.act-europe.fr (HELO mel.act-europe.fr) (194.98.77.210) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sun, 24 Oct 2010 20:53:52 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id 611DECB020C for ; Sun, 24 Oct 2010 22:53:50 +0200 (CEST) Received: from mel.act-europe.fr ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id vHBBumn6mLPi for ; Sun, 24 Oct 2010 22:53:50 +0200 (CEST) Received: from [192.168.1.2] (bon31-9-83-155-120-49.fbx.proxad.net [83.155.120.49]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mel.act-europe.fr (Postfix) with ESMTP id 2AB21CB01D4 for ; Sun, 24 Oct 2010 22:53:50 +0200 (CEST) From: Eric Botcazou To: gcc-patches@gcc.gnu.org Subject: Fix ICE on dangling unreachable block Date: Sun, 24 Oct 2010 22:45:45 +0200 User-Agent: KMail/1.9.9 MIME-Version: 1.0 Message-Id: <201010242245.45305.ebotcazou@adacore.com> 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 is a regression present on the mainline and 4.5 branch: the attached testcase yields an ICE in pre_and_rev_post_order_compute when compiled at -Os -g on the x86. It's the assertion verifying that all the blocks have been invisited by the DFS algorithm: /* The number of nodes visited should be the number of blocks minus the entry and exit blocks which are not visited here. */ gcc_assert (pre_order_num == n_basic_blocks - NUM_FIXED_BLOCKS); This is a latent issue in reg-stack.c: it purges dead edges but doesn't clean up the CFG afterward. Then pre_and_rev_post_order_compute is invoked from var-tracking.c and chokes. Fixed by cleaning up the CFG at the end of the pass if edges have been purged. Note that this should only affect the Ada and Java compilers. Tested on i586-suse-linux, applied on the mainline and 4.5 branch. 2010-10-24 Eric Botcazou * reg-stack.c (convert_regs_1): Return boolean value, true if the CFG has been modified. (convert_regs_2): Likewise. Adjust calls to convert_regs_1. (convert_regs): Adjust calls to convert_regs_2. Clean up the CFG if it has been modified. 2010-10-24 Eric Botcazou * gnat.dg/opt7.ad[sb]: New test. * gnat.dg/opt7_pkg.ads: New helper. Index: reg-stack.c =================================================================== --- reg-stack.c (revision 165881) +++ reg-stack.c (working copy) @@ -2876,9 +2876,10 @@ better_edge (edge e1, edge e2) return (e1->src->index < e2->src->index) ? e1 : e2; } -/* Convert stack register references in one block. */ +/* Convert stack register references in one block. Return true if the CFG + has been modified in the process. */ -static void +static bool convert_regs_1 (basic_block block) { struct stack_def regstack; @@ -2886,6 +2887,7 @@ convert_regs_1 (basic_block block) int reg; rtx insn, next; bool control_flow_insn_deleted = false; + bool cfg_altered = false; int debug_insns_with_starting_stack = 0; any_malformed_asm = false; @@ -3041,7 +3043,7 @@ convert_regs_1 (basic_block block) place, still, but we don't have enough information at that time. */ if (control_flow_insn_deleted) - purge_dead_edges (block); + cfg_altered |= purge_dead_edges (block); /* Something failed if the stack lives don't match. If we had malformed asms, we zapped the instruction itself, but that didn't produce the @@ -3051,14 +3053,18 @@ convert_regs_1 (basic_block block) || any_malformed_asm); bi->stack_out = regstack; bi->done = true; + + return cfg_altered; } -/* Convert registers in all blocks reachable from BLOCK. */ +/* Convert registers in all blocks reachable from BLOCK. Return true if the + CFG has been modified in the process. */ -static void +static bool convert_regs_2 (basic_block block) { basic_block *stack, *sp; + bool cfg_altered = false; /* We process the blocks in a top-down manner, in a way such that one block is only processed after all its predecessors. The number of predecessors @@ -3097,11 +3103,13 @@ convert_regs_2 (basic_block block) *sp++ = e->dest; } - convert_regs_1 (block); + cfg_altered |= convert_regs_1 (block); } while (sp != stack); free (stack); + + return cfg_altered; } /* Traverse all basic blocks in a function, converting the register @@ -3111,6 +3119,7 @@ convert_regs_2 (basic_block block) static void convert_regs (void) { + bool cfg_altered = false; int inserted; basic_block b; edge e; @@ -3129,7 +3138,7 @@ convert_regs (void) /* Process all blocks reachable from all entry points. */ FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs) - convert_regs_2 (e->dest); + cfg_altered |= convert_regs_2 (e->dest); /* ??? Process all unreachable blocks. Though there's no excuse for keeping these even when not optimizing. */ @@ -3138,7 +3147,7 @@ convert_regs (void) block_info bi = BLOCK_INFO (b); if (! bi->done) - convert_regs_2 (b); + cfg_altered |= convert_regs_2 (b); } inserted |= compensate_edges (); @@ -3149,6 +3158,9 @@ convert_regs (void) if (inserted) commit_edge_insertions (); + if (cfg_altered) + cleanup_cfg (0); + if (dump_file) fputc ('\n', dump_file); }