From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28781 invoked by alias); 18 Jan 2010 13:04:00 -0000 Received: (qmail 25250 invoked by uid 48); 18 Jan 2010 13:03:43 -0000 Date: Mon, 18 Jan 2010 13:04:00 -0000 Message-ID: <20100118130343.25246.qmail@sourceware.org> X-Bugzilla-Reason: CC References: Subject: [Bug tree-optimization/42728] "-fcompare-debug failure (length)" at -O1 In-Reply-To: Reply-To: gcc-bugzilla@gcc.gnu.org To: gcc-bugs@gcc.gnu.org From: "jakub at gcc dot gnu dot org" Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org X-SW-Source: 2010-01/txt/msg02194.txt.bz2 ------- Comment #2 from jakub at gcc dot gnu dot org 2010-01-18 13:03 ------- This is a fwprop.c bug. In particular, that the 797 /* If target_insn comes right after def_insn, which is very common 798 for addresses, we can use a quicker test. */ 799 if (NEXT_INSN (def_insn) == target_insn 800 && REG_P (SET_DEST (def_set))) shortcut in all_uses_available_at has different behavior depending from the following code. We have def_insn: (insn 15 14 18 4 pr42728.c:6 (parallel [ (set (reg/v/f:DI 60 [ b ]) (plus:DI (reg/v/f:DI 60 [ b ]) (const_int 1 [0x1]))) (clobber (reg:CC 17 flags)) ]) 252 {*adddi_1} (expr_list:REG_UNUSED (reg:CC 17 flags) (nil))) (as b is uninitialized, this is the only definition of b) and target_insn is (insn 21 19 22 4 pr42728.c:5 (set (reg:CCZ 17 flags) (compare:CCZ (mem:QI (reg/v/f:DI 60 [ b ]) [0 S1 A8]) (const_int 0 [0x0]))) 0 {*cmpqi_ccno_1} (nil)) (the only use of it besides debug_insns with -g). If def_insn and target_insn are adjacent (-g0), then this returns false, as one of the uses (the only one actually) in def_insn is the target of that insn. If there are any debug insns in between (or any other), it returns true, as /* Check if the reg in USE has only one definition. We already know that this definition reaches use, or we wouldn't be here. However, this is invalid for hard registers because if they are live at the beginning of the function it does not mean that we have an uninitialized access. */ regno = DF_REF_REGNO (use); def = DF_REG_DEF_CHAIN (regno); if (def && DF_REF_NEXT_REG (def) == NULL && regno >= FIRST_PSEUDO_REGISTER) return false; shortcut applies and thus local_ref_killed_between_p is not allowed to return true (because of the def in def_insn). To fix this, we could either ensure the shortcut is run regardless of any debug insns in between (next_nondebug_insn isn't probably usable, as target_insn may be a debug_insn): --- fwprop.c.jj 2009-12-10 19:19:08.000000000 +0100 +++ fwprop.c 2010-01-18 13:55:57.000000000 +0100 @@ -791,13 +791,16 @@ all_uses_available_at (rtx def_insn, rtx df_ref *use_rec; struct df_insn_info *insn_info = DF_INSN_INFO_GET (def_insn); rtx def_set = single_set (def_insn); + rtx next; gcc_assert (def_set); /* If target_insn comes right after def_insn, which is very common for addresses, we can use a quicker test. */ - if (NEXT_INSN (def_insn) == target_insn - && REG_P (SET_DEST (def_set))) + next = NEXT_INSN (def_insn); + while (next && next != target_insn && DEBUG_INSN_P (next)) + next = NEXT_INSN (next); + if (next == target_insn && REG_P (SET_DEST (def_set))) { rtx def_reg = SET_DEST (def_set); or we could do something like: --- fwprop.c.xx 2009-12-10 19:19:08.000000000 +0100 +++ fwprop.c 2010-01-18 14:02:32.000000000 +0100 @@ -818,17 +818,23 @@ all_uses_available_at (rtx def_insn, rtx } else { + rtx def_reg = REG_P (SET_DEST (def_set)) ? SET_DEST (def_set) : NULL_RTX; + /* Look at all the uses of DEF_INSN, and see if they are not killed between DEF_INSN and TARGET_INSN. */ for (use_rec = DF_INSN_INFO_USES (insn_info); *use_rec; use_rec++) { df_ref use = *use_rec; + if (def_reg && rtx_equal_p (DF_REF_REG (use), def_reg)) + return false; if (use_killed_between (use, def_insn, target_insn)) return false; } for (use_rec = DF_INSN_INFO_EQ_USES (insn_info); *use_rec; use_rec++) { df_ref use = *use_rec; + if (def_reg && rtx_equal_p (DF_REF_REG (use), def_reg)) + return false; if (use_killed_between (use, def_insn, target_insn)) return false; } -- jakub at gcc dot gnu dot org changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |bonzini at gnu dot org Status|UNCONFIRMED |NEW Ever Confirmed|0 |1 Last reconfirmed|0000-00-00 00:00:00 |2010-01-18 13:03:43 date| | http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42728