From patchwork Fri Apr 13 15:58:50 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Oliva X-Patchwork-Id: 152330 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 B7A9EB6EEB for ; Sat, 14 Apr 2012 01:59:33 +1000 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1334937575; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:Received:From:To:Cc:Subject:References:Date: In-Reply-To:Message-ID:User-Agent:MIME-Version:Content-Type: Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:Sender:Delivered-To; bh=pj6220INMpFVzgDIIgqu eIQIzpk=; b=Ldg1qimCdQMs9/LfALB6yKI4dD3igHoqa9Ti2ZyHukLoBDsXmcWc tXOHtvNNZhuWUuyxLN2pz5MRtoET/raq/d7bTT/BMZ1Vfc8bzsiUE1l+xt4Fzt4U j7rxnrUzNvEqoSgMMXslsPm6e4lMWZ0Tt2N8mH6DJEOH9z8E2faKPT4= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Received:Received:Received:From:To:Cc:Subject:References:Date:In-Reply-To:Message-ID:User-Agent:MIME-Version:Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=okISaHOBYd/bPSiJUy1bZiYYfx4lZmHpm3YjdHwg04V8m1tkiAwsZ6wGh0EU3T XFoncfgC3NMrEU7ywrfghW0xuufz9XsCWyZzViteRrJ/D2GCNdBkRDRNdccYxu/N 71fHc/VZZUPQqFp80Bs/eABpuhrkWS62DxSHVSKy16eeY=; Received: (qmail 31529 invoked by alias); 13 Apr 2012 15:59:27 -0000 Received: (qmail 31516 invoked by uid 22791); 13 Apr 2012 15:59:24 -0000 X-SWARE-Spam-Status: No, hits=-5.5 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, RCVD_IN_DNSWL_HI, RCVD_IN_HOSTKARMA_W, SPF_HELO_PASS, TW_MW, T_RP_MATCHES_RCVD, T_TVD_MIME_NO_HEADERS X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 13 Apr 2012 15:59:10 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q3DFwuov007090 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 13 Apr 2012 11:58:56 -0400 Received: from freie.oliva.athome.lsd.ic.unicamp.br (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q3DFws68026141 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 13 Apr 2012 11:58:55 -0400 Received: from livre.localdomain (livre-to-gw.oliva.athome.lsd.ic.unicamp.br [172.31.160.19]) by freie.oliva.athome.lsd.ic.unicamp.br (8.14.5/8.14.5) with ESMTP id q3DFwr8L005417; Fri, 13 Apr 2012 12:58:53 -0300 Received: from livre.localdomain (aoliva@localhost.localdomain [127.0.0.1]) by livre.localdomain (8.14.3/8.14.3/Debian-5+lenny1) with ESMTP id q3DFwqSb019506; Fri, 13 Apr 2012 12:58:53 -0300 Received: (from aoliva@localhost) by livre.localdomain (8.14.3/8.14.3/Submit) id q3DFwpxl019504; Fri, 13 Apr 2012 12:58:51 -0300 From: Alexandre Oliva To: Eric Botcazou Cc: gcc-patches@gcc.gnu.org Subject: Re: fix left-over debug insns in DCE References: <201204091541.27484.ebotcazou@adacore.com> Date: Fri, 13 Apr 2012 12:58:50 -0300 In-Reply-To: <201204091541.27484.ebotcazou@adacore.com> (Eric Botcazou's message of "Mon, 9 Apr 2012 15:41:27 +0200") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 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 On Apr 9, 2012, Eric Botcazou wrote: > Could you add a comment for each value? Done > Missing "extern" for all declarations. Thanks, added. > I don't understand the "or _WITH_VALUE otherwise" part of the comment. Sorry, my bad. It didn't make sense. Fixed. > Please add a comment explaining what this is doing. How's this? I've just installed the patch, but if you find the need for any further improvement, let me know and I'll do it right away. Thanks, for gcc/ChangeLog from Alexandre Oliva PR debug/48866 * df.h (enum debug_temp_where): New. (dead_debug_init, dead_debug_finish) Declare. (dead_debug_add, dead_debug_insert_temp): Declare. (struct dead_debug_use, struct dead_debug): Moved from... * df-problems.c: ... here. (df_set_unused_notes_for_mw): Bind debug uses of unused regno to a debug temp. (df_create_unused_note): Likewise. (df_set_dead_notes_for_mw): Move comment where it belongs. (dead_debug_init): Export. (dead_debug_reset_uses): New, factored out of... (dead_debug_finish): ...this. Export. (dead_debug_reset): Remove. (dead_debug_add): Export. (dead_debug_insert_before): Rename to... (dead_debug_insert_temp): ... this. Add where argument. Export. Locate stored value for BEFORE_WITH_VALUE. Avoid repeat inserts. Return insertion count. (df_note_bb_compute): Adjust. * dce.c (word_dce_process_block): Adjust dead debug uses. (dce_process_block): Likewise. Index: gcc/df.h =================================================================== --- gcc/df.h.orig 2012-04-13 05:18:29.140781640 -0300 +++ gcc/df.h 2012-04-13 07:13:18.000000000 -0300 @@ -1101,4 +1101,46 @@ extern void union_defs (df_ref, struct w unsigned int *used, struct web_entry *, bool (*fun) (struct web_entry *, struct web_entry *)); +/* Debug uses of dead regs. */ + +/* Node of a linked list of uses of dead REGs in debug insns. */ +struct dead_debug_use +{ + df_ref use; + struct dead_debug_use *next; +}; + +/* Linked list of the above, with a bitmap of the REGs in the + list. */ +struct dead_debug +{ + struct dead_debug_use *head; + bitmap used; + bitmap to_rescan; +}; + +/* This type controls the behavior of dead_debug_insert_temp WRT + UREGNO and INSN. */ +enum debug_temp_where + { + /* Bind a newly-created debug temporary to a REG for UREGNO, and + insert the debug insn before INSN. REG is expected to die at + INSN. */ + DEBUG_TEMP_BEFORE_WITH_REG = -1, + /* Bind a newly-created debug temporary to the value INSN stores + in REG, and insert the debug insn before INSN. */ + DEBUG_TEMP_BEFORE_WITH_VALUE = 0, + /* Bind a newly-created debug temporary to a REG for UREGNO, and + insert the debug insn after INSN. REG is expected to be set at + INSN. */ + DEBUG_TEMP_AFTER_WITH_REG = 1 + }; + +extern void dead_debug_init (struct dead_debug *, bitmap); +extern void dead_debug_finish (struct dead_debug *, bitmap); +extern void dead_debug_add (struct dead_debug *, df_ref, unsigned int); +extern int dead_debug_insert_temp (struct dead_debug *, + unsigned int uregno, rtx insn, + enum debug_temp_where); + #endif /* GCC_DF_H */ Index: gcc/df-problems.c =================================================================== --- gcc/df-problems.c.orig 2012-04-13 06:58:42.053258184 -0300 +++ gcc/df-problems.c 2012-04-13 07:29:33.000000000 -0300 @@ -2886,25 +2886,6 @@ df_whole_mw_reg_unused_p (struct df_mw_h } -/* Node of a linked list of uses of dead REGs in debug insns. */ -struct dead_debug_use -{ - df_ref use; - struct dead_debug_use *next; -}; - -/* Linked list of the above, with a bitmap of the REGs in the - list. */ -struct dead_debug -{ - struct dead_debug_use *head; - bitmap used; - bitmap to_rescan; -}; - -static void dead_debug_reset (struct dead_debug *, unsigned int); - - /* Set the REG_UNUSED notes for the multiword hardreg defs in INSN based on the bits in LIVE. Do not generate notes for registers in artificial uses. DO_NOT_GEN is updated so that REG_DEAD notes are @@ -2930,7 +2911,7 @@ df_set_unused_notes_for_mw (rtx insn, st { unsigned int regno = mws->start_regno; df_set_note (REG_UNUSED, insn, mws->mw_reg); - dead_debug_reset (debug, regno); + dead_debug_insert_temp (debug, regno, insn, DEBUG_TEMP_AFTER_WITH_REG); #ifdef REG_DEAD_DEBUGGING df_print_note ("adding 1: ", insn, REG_NOTES (insn)); @@ -2945,7 +2926,7 @@ df_set_unused_notes_for_mw (rtx insn, st && !bitmap_bit_p (artificial_uses, r)) { df_set_note (REG_UNUSED, insn, regno_reg_rtx[r]); - dead_debug_reset (debug, r); + dead_debug_insert_temp (debug, r, insn, DEBUG_TEMP_AFTER_WITH_REG); #ifdef REG_DEAD_DEBUGGING df_print_note ("adding 2: ", insn, REG_NOTES (insn)); #endif @@ -3013,12 +2994,12 @@ df_set_dead_notes_for_mw (rtx insn, stru if (df_whole_mw_reg_dead_p (mws, live, artificial_uses, do_not_gen)) { - /* Add a dead note for the entire multi word register. */ if (is_debug) { *added_notes_p = true; return; } + /* Add a dead note for the entire multi word register. */ df_set_note (REG_DEAD, insn, mws->mw_reg); #ifdef REG_DEAD_DEBUGGING df_print_note ("adding 1: ", insn, REG_NOTES (insn)); @@ -3072,7 +3053,7 @@ df_create_unused_note (rtx insn, df_ref rtx reg = (DF_REF_LOC (def)) ? *DF_REF_REAL_LOC (def): DF_REF_REG (def); df_set_note (REG_UNUSED, insn, reg); - dead_debug_reset (debug, dregno); + dead_debug_insert_temp (debug, dregno, insn, DEBUG_TEMP_AFTER_WITH_REG); #ifdef REG_DEAD_DEBUGGING df_print_note ("adding 3: ", insn, REG_NOTES (insn)); #endif @@ -3083,7 +3064,7 @@ df_create_unused_note (rtx insn, df_ref /* Initialize DEBUG to an empty list, and clear USED, if given. */ -static inline void +void dead_debug_init (struct dead_debug *debug, bitmap used) { debug->head = NULL; @@ -3093,32 +3074,83 @@ dead_debug_init (struct dead_debug *debu bitmap_clear (used); } -/* Reset all debug insns with pending uses. Release the bitmap in it, - unless it is USED. USED must be the same bitmap passed to - dead_debug_init. */ -static inline void -dead_debug_finish (struct dead_debug *debug, bitmap used) +/* Reset all debug uses in HEAD, and clear DEBUG->to_rescan bits of + each reset insn. DEBUG is not otherwise modified. If HEAD is + DEBUG->head, DEBUG->head will be set to NULL at the end. + Otherwise, entries from DEBUG->head that pertain to reset insns + will be removed, and only then rescanned. */ + +static void +dead_debug_reset_uses (struct dead_debug *debug, struct dead_debug_use *head) { - struct dead_debug_use *head; - rtx insn = NULL; + bool got_head = (debug->head == head); + bitmap rescan; + struct dead_debug_use **tailp = &debug->head; + struct dead_debug_use *cur; + bitmap_iterator bi; + unsigned int uid; - if (debug->used != used) - BITMAP_FREE (debug->used); + if (got_head) + rescan = NULL; + else + rescan = BITMAP_ALLOC (NULL); - while ((head = debug->head)) + while (head) { + struct dead_debug_use *next = head->next; + rtx insn; + insn = DF_REF_INSN (head->use); - if (!head->next || DF_REF_INSN (head->next->use) != insn) + if (!next || DF_REF_INSN (next->use) != insn) { INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC (); - df_insn_rescan_debug_internal (insn); + if (got_head) + df_insn_rescan_debug_internal (insn); + else + bitmap_set_bit (rescan, INSN_UID (insn)); if (debug->to_rescan) bitmap_clear_bit (debug->to_rescan, INSN_UID (insn)); } - debug->head = head->next; XDELETE (head); + head = next; } + if (got_head) + { + debug->head = NULL; + return; + } + + while ((cur = *tailp)) + if (bitmap_bit_p (rescan, INSN_UID (DF_REF_INSN (cur->use)))) + { + *tailp = cur->next; + XDELETE (cur); + } + else + tailp = &cur->next; + + EXECUTE_IF_SET_IN_BITMAP (rescan, 0, uid, bi) + { + struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid); + if (insn_info) + df_insn_rescan_debug_internal (insn_info->insn); + } + + BITMAP_FREE (rescan); +} + +/* Reset all debug insns with pending uses. Release the bitmap in it, + unless it is USED. USED must be the same bitmap passed to + dead_debug_init. */ +void +dead_debug_finish (struct dead_debug *debug, bitmap used) +{ + if (debug->used != used) + BITMAP_FREE (debug->used); + + dead_debug_reset_uses (debug, debug->head); + if (debug->to_rescan) { bitmap_iterator bi; @@ -3134,54 +3166,9 @@ dead_debug_finish (struct dead_debug *de } } -/* Reset DEBUG_INSNs with pending uses of DREGNO. */ -static void -dead_debug_reset (struct dead_debug *debug, unsigned int dregno) -{ - struct dead_debug_use **tailp = &debug->head; - struct dead_debug_use **insnp = &debug->head; - struct dead_debug_use *cur; - rtx insn; - - if (!debug->used || !bitmap_clear_bit (debug->used, dregno)) - return; - - while ((cur = *tailp)) - { - if (DF_REF_REGNO (cur->use) == dregno) - { - *tailp = cur->next; - insn = DF_REF_INSN (cur->use); - INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC (); - if (debug->to_rescan == NULL) - debug->to_rescan = BITMAP_ALLOC (NULL); - bitmap_set_bit (debug->to_rescan, INSN_UID (insn)); - XDELETE (cur); - /* If the current use isn't the first one attached to INSN, go back - to this first use. We assume that the uses attached to an insn - are adjacent. */ - if (tailp != insnp && DF_REF_INSN ((*insnp)->use) == insn) - tailp = insnp; - /* Then remove all the other uses attached to INSN. */ - while ((cur = *tailp) && DF_REF_INSN (cur->use) == insn) - { - *tailp = cur->next; - XDELETE (cur); - } - insnp = tailp; - } - else - { - if (DF_REF_INSN ((*insnp)->use) != DF_REF_INSN (cur->use)) - insnp = tailp; - tailp = &(*tailp)->next; - } - } -} - /* Add USE to DEBUG. It must be a dead reference to UREGNO in a debug insn. Create a bitmap for DEBUG as needed. */ -static inline void +void dead_debug_add (struct dead_debug *debug, df_ref use, unsigned int uregno) { struct dead_debug_use *newddu = XNEW (struct dead_debug_use); @@ -3197,23 +3184,27 @@ dead_debug_add (struct dead_debug *debug } /* If UREGNO is referenced by any entry in DEBUG, emit a debug insn - before INSN that binds the REG to a debug temp, and replace all - uses of UREGNO in DEBUG with uses of the debug temp. INSN must be - the insn where UREGNO dies. */ -static inline void -dead_debug_insert_before (struct dead_debug *debug, unsigned int uregno, - rtx insn) + before or after INSN (depending on WHERE), that binds a debug temp + to the widest-mode use of UREGNO, if WHERE is *_WITH_REG, or the + value stored in UREGNO by INSN otherwise, and replace all uses of + UREGNO in DEBUG with uses of the debug temp. INSN must be where + UREGNO dies, if WHERE is *_BEFORE_*, or where it is set otherwise. + Return the number of debug insns emitted. */ +int +dead_debug_insert_temp (struct dead_debug *debug, unsigned int uregno, + rtx insn, enum debug_temp_where where) { struct dead_debug_use **tailp = &debug->head; struct dead_debug_use *cur; struct dead_debug_use *uses = NULL; struct dead_debug_use **usesp = &uses; rtx reg = NULL; + rtx breg; rtx dval; rtx bind; if (!debug->used || !bitmap_clear_bit (debug->used, uregno)) - return; + return 0; /* Move all uses of uregno from debug->head to uses, setting mode to the widest referenced mode. */ @@ -3237,17 +3228,114 @@ dead_debug_insert_before (struct dead_de /* We may have dangling bits in debug->used for registers that were part of a multi-register use, one component of which has been reset. */ if (reg == NULL) - return; + { + gcc_checking_assert (!uses); + return 0; + } + + gcc_checking_assert (uses); + + breg = reg; + /* Recover the expression INSN stores in REG. */ + if (where == DEBUG_TEMP_BEFORE_WITH_VALUE) + { + rtx set = single_set (insn); + rtx dest, src; + + if (set) + { + dest = SET_DEST (set); + src = SET_SRC (set); + /* Lose if the REG-setting insn is a CALL. */ + if (GET_CODE (src) == CALL) + { + while (uses) + { + cur = uses->next; + XDELETE (uses); + uses = cur; + } + return 0; + } + } + + /* ??? Should we try to extract it from a PARALLEL? */ + if (!set) + breg = NULL; + /* Cool, it's the same REG, we can use SRC. */ + else if (dest == reg) + breg = copy_rtx (src); + else if (REG_P (dest)) + { + /* Hmm... Something's fishy, we should be setting REG here. */ + if (REGNO (dest) != REGNO (reg)) + breg = NULL; + /* Ok, it's the same (hardware) REG, but with a different + mode, so SUBREG it. */ + else + breg = lowpart_subreg (GET_MODE (reg), copy_rtx (src), + GET_MODE (dest)); + } + else if (GET_CODE (dest) == SUBREG) + { + /* We should be setting REG here. Lose. */ + if (REGNO (SUBREG_REG (dest)) != REGNO (reg)) + breg = NULL; + /* Lose if we're setting something other than the lowpart of + REG. */ + else if (!subreg_lowpart_p (dest)) + breg = NULL; + /* If we're not overwriting all the hardware registers that + setting REG in its mode would, we won't know what to bind + the debug temp to. */ + else if (REGNO (reg) < FIRST_PSEUDO_REGISTER + && (hard_regno_nregs[REGNO (reg)][GET_MODE (reg)] + != hard_regno_nregs[REGNO (reg)][GET_MODE (dest)])) + breg = NULL; + /* Yay, we can use SRC, just adjust its mode. */ + else + breg = lowpart_subreg (GET_MODE (reg), copy_rtx (src), + GET_MODE (dest)); + } + /* Oh well, we're out of luck. */ + else + breg = NULL; + + /* We couldn't figure out the value stored in REG, so reset all + of its pending debug uses. */ + if (!breg) + { + dead_debug_reset_uses (debug, uses); + return 0; + } + } + + /* If there's a single (debug) use of an otherwise unused REG, and + the debug use is not part of a larger expression, then it + probably doesn't make sense to introduce a new debug temp. */ + if (where == DEBUG_TEMP_AFTER_WITH_REG && !uses->next) + { + rtx next = DF_REF_INSN (uses->use); + + if (DEBUG_INSN_P (next) && reg == INSN_VAR_LOCATION_LOC (next)) + { + XDELETE (uses); + return 0; + } + } /* Create DEBUG_EXPR (and DEBUG_EXPR_DECL). */ dval = make_debug_expr_from_rtl (reg); /* Emit a debug bind insn before the insn in which reg dies. */ bind = gen_rtx_VAR_LOCATION (GET_MODE (reg), - DEBUG_EXPR_TREE_DECL (dval), reg, + DEBUG_EXPR_TREE_DECL (dval), breg, VAR_INIT_STATUS_INITIALIZED); - bind = emit_debug_insn_before (bind, insn); + if (where == DEBUG_TEMP_AFTER_WITH_REG) + bind = emit_debug_insn_after (bind, insn); + else + bind = emit_debug_insn_before (bind, insn); df_insn_rescan (bind); /* Adjust all uses. */ @@ -3265,6 +3353,8 @@ dead_debug_insert_before (struct dead_de uses = cur->next; XDELETE (cur); } + + return 1; } /* Recompute the REG_DEAD and REG_UNUSED notes and compute register @@ -3464,7 +3554,8 @@ df_note_bb_compute (unsigned int bb_inde break; } else - dead_debug_insert_before (&debug, uregno, insn); + dead_debug_insert_temp (&debug, uregno, insn, + DEBUG_TEMP_BEFORE_WITH_REG); if ( (!(DF_REF_FLAGS (use) & (DF_REF_MW_HARDREG | DF_REF_READ_WRITE))) Index: gcc/dce.c =================================================================== --- gcc/dce.c.orig 2012-04-13 05:18:28.604788011 -0300 +++ gcc/dce.c 2012-04-13 07:00:50.056647951 -0300 @@ -807,6 +807,7 @@ word_dce_process_block (basic_block bb, bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack); rtx insn; bool block_changed; + struct dead_debug debug; if (redo_out) { @@ -828,11 +829,24 @@ word_dce_process_block (basic_block bb, } bitmap_copy (local_live, DF_WORD_LR_OUT (bb)); + dead_debug_init (&debug, NULL); FOR_BB_INSNS_REVERSE (bb, insn) - if (NONDEBUG_INSN_P (insn)) + if (DEBUG_INSN_P (insn)) + { + df_ref *use_rec; + for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++) + if (DF_REF_REGNO (*use_rec) >= FIRST_PSEUDO_REGISTER + && (GET_MODE_SIZE (GET_MODE (DF_REF_REAL_REG (*use_rec))) + == 2 * UNITS_PER_WORD) + && !bitmap_bit_p (local_live, 2 * DF_REF_REGNO (*use_rec)) + && !bitmap_bit_p (local_live, 2 * DF_REF_REGNO (*use_rec) + 1)) + dead_debug_add (&debug, *use_rec, DF_REF_REGNO (*use_rec)); + } + else if (INSN_P (insn)) { bool any_changed; + /* No matter if the instruction is needed or not, we remove any regno in the defs from the live set. */ any_changed = df_word_lr_simulate_defs (insn, local_live); @@ -844,6 +858,15 @@ word_dce_process_block (basic_block bb, if (marked_insn_p (insn)) df_word_lr_simulate_uses (insn, local_live); + if (debug.used && !bitmap_empty_p (debug.used)) + { + df_ref *def_rec; + + for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) + dead_debug_insert_temp (&debug, DF_REF_REGNO (*def_rec), insn, + DEBUG_TEMP_BEFORE_WITH_VALUE); + } + if (dump_file) { fprintf (dump_file, "finished processing insn %d live out = ", @@ -856,6 +879,7 @@ word_dce_process_block (basic_block bb, if (block_changed) bitmap_copy (DF_WORD_LR_IN (bb), local_live); + dead_debug_finish (&debug, NULL); BITMAP_FREE (local_live); return block_changed; } @@ -873,6 +897,7 @@ dce_process_block (basic_block bb, bool rtx insn; bool block_changed; df_ref *def_rec; + struct dead_debug debug; if (redo_out) { @@ -896,22 +921,36 @@ dce_process_block (basic_block bb, bool bitmap_copy (local_live, DF_LR_OUT (bb)); df_simulate_initialize_backwards (bb, local_live); + dead_debug_init (&debug, NULL); FOR_BB_INSNS_REVERSE (bb, insn) - if (INSN_P (insn)) + if (DEBUG_INSN_P (insn)) + { + df_ref *use_rec; + for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++) + if (!bitmap_bit_p (local_live, DF_REF_REGNO (*use_rec)) + && !bitmap_bit_p (au, DF_REF_REGNO (*use_rec))) + dead_debug_add (&debug, *use_rec, DF_REF_REGNO (*use_rec)); + } + else if (INSN_P (insn)) { bool needed = marked_insn_p (insn); /* The insn is needed if there is someone who uses the output. */ if (!needed) for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) - if (bitmap_bit_p (local_live, DF_REF_REGNO (*def_rec)) - || bitmap_bit_p (au, DF_REF_REGNO (*def_rec))) - { - needed = true; - mark_insn (insn, true); - break; - } + { + dead_debug_insert_temp (&debug, DF_REF_REGNO (*def_rec), insn, + DEBUG_TEMP_BEFORE_WITH_VALUE); + + if (bitmap_bit_p (local_live, DF_REF_REGNO (*def_rec)) + || bitmap_bit_p (au, DF_REF_REGNO (*def_rec))) + { + needed = true; + mark_insn (insn, true); + break; + } + } /* No matter if the instruction is needed or not, we remove any regno in the defs from the live set. */ @@ -923,6 +962,7 @@ dce_process_block (basic_block bb, bool df_simulate_uses (insn, local_live); } + dead_debug_finish (&debug, NULL); df_simulate_finalize_backwards (bb, local_live); block_changed = !bitmap_equal_p (local_live, DF_LR_IN (bb));