From patchwork Wed Jul 21 22:48:31 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bernd Schmidt X-Patchwork-Id: 59515 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 96EAB1007D5 for ; Thu, 22 Jul 2010 08:49:39 +1000 (EST) Received: (qmail 7298 invoked by alias); 21 Jul 2010 22:49:37 -0000 Received: (qmail 7286 invoked by uid 22791); 21 Jul 2010 22:49:35 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 21 Jul 2010 22:49:29 +0000 Received: (qmail 15797 invoked from network); 21 Jul 2010 22:49:27 -0000 Received: from unknown (HELO ?84.152.249.159?) (bernds@127.0.0.2) by mail.codesourcery.com with ESMTPA; 21 Jul 2010 22:49:27 -0000 Message-ID: <4C47793F.8040500@codesourcery.com> Date: Thu, 22 Jul 2010 00:48:31 +0200 From: Bernd Schmidt User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.10) Gecko/20100625 Thunderbird/3.0.5 MIME-Version: 1.0 To: GCC Patches Subject: Fix postreload problems 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 There are still some reports of bootstrap failures and other problems after my postreload patch last week. The patch below should fix these. IainS has been very helpful in providing a testcase. While I didn't have a testcase I stared the code for a long time; this also produced some fixes, even in the old code. The main problem was that the new code could mess up lifetime information by rescanning a previously encountered insn with reload_combine_note_use. This could add uses for registers that are set between the current point and the old use. In the old optimization, reload_combine_recognize_pattern, we can sometimes allocate a new register. This code wasn't checking whether it's actually safe to do so; I've copied a range of typical checks from elsewhere. Some of them are likely already covered by the life information we compute, others (like the df_regs_ever_live_p check and the call to hard_regno_scratch_ok) seem necessary. Some remnants of my first attempt to fix the DEBUG_INSN problem remained; I've removed those. Bootstrapped, tested on x86_64-linux and i686-linux (where I only saw the failure from PR45005), and committed. Bernd PR bootstrap/44970 PR middle-end/45009 * postreload.c: Include "target.h". (reload_combine_closest_single_use): Don't take DEBUG_INSNs into account. (fixup_debug_insns): Don't copy the rtx. (reload_combine_recognize_const_pattern): DEBUG_INSNs can't have uses. Don't copy when replacing. Call fixup_debug_insns in the case where we merged one add with another. (reload_combine_recognize_pattern): Fail if there aren't any uses. Try harder to determine whether we're picking a valid index register. Don't set store_ruid for an insn we're going to scan in the next iteration. (reload_combine): Remove unused code. (reload_combine_note_use): When updating use information for an old insn, ignore a use that occurs after store_ruid. * Makefile.in (postreload.o): Update dependencies. Index: gcc/postreload.c =================================================================== --- gcc/postreload.c (revision 162372) +++ gcc/postreload.c (working copy) @@ -44,6 +44,7 @@ along with GCC; see the file COPYING3. #include "toplev.h" #include "except.h" #include "tree.h" +#include "target.h" #include "timevar.h" #include "tree-pass.h" #include "df.h" @@ -816,8 +817,7 @@ reload_combine_purge_reg_uses_after_ruid /* Find the use of REGNO with the ruid that is highest among those lower than RUID_LIMIT, and return it if it is the only use of this - reg in the insn (or if the insn is a debug insn). Return NULL - otherwise. */ + reg in the insn. Return NULL otherwise. */ static struct reg_use * reload_combine_closest_single_use (unsigned regno, int ruid_limit) @@ -838,9 +838,9 @@ reload_combine_closest_single_use (unsig if (this_ruid > best_ruid) { best_ruid = this_ruid; - retval = reg_state[regno].reg_use + i; + retval = use; } - else if (this_ruid == best_ruid && !DEBUG_INSN_P (use->insn)) + else if (this_ruid == best_ruid) retval = NULL; } if (last_label_ruid >= best_ruid) @@ -866,7 +866,7 @@ fixup_debug_insns (rtx reg, rtx replacem continue; t = INSN_VAR_LOCATION_LOC (insn); - t = simplify_replace_rtx (t, reg, copy_rtx (replacement)); + t = simplify_replace_rtx (t, reg, replacement); validate_change (insn, &INSN_VAR_LOCATION_LOC (insn), t, 0); } } @@ -938,10 +938,6 @@ reload_combine_recognize_const_pattern ( /* Start the search for the next use from here. */ from_ruid = use->ruid; - /* We'll fix up DEBUG_INSNs after we're done. */ - if (use && DEBUG_INSN_P (use->insn)) - continue; - if (use && GET_MODE (*use->usep) == Pmode) { rtx use_insn = use->insn; @@ -972,7 +968,7 @@ reload_combine_recognize_const_pattern ( int old_cost = address_cost (oldaddr, GET_MODE (mem), as, speed); int new_cost; - newaddr = simplify_replace_rtx (oldaddr, reg, copy_rtx (src)); + newaddr = simplify_replace_rtx (oldaddr, reg, src); if (memory_address_addr_space_p (GET_MODE (mem), newaddr, as)) { XEXP (mem, 0) = newaddr; @@ -1008,8 +1004,7 @@ reload_combine_recognize_const_pattern ( int old_cost = rtx_cost (SET_SRC (new_set), SET, speed); gcc_assert (rtx_equal_p (XEXP (SET_SRC (new_set), 0), reg)); - new_src = simplify_replace_rtx (SET_SRC (new_set), reg, - copy_rtx (src)); + new_src = simplify_replace_rtx (SET_SRC (new_set), reg, src); if (rtx_cost (new_src, SET, speed) <= old_cost && validate_change (use_insn, &SET_SRC (new_set), @@ -1024,6 +1019,7 @@ reload_combine_recognize_const_pattern ( /* See if that took care of the add insn. */ if (rtx_equal_p (SET_DEST (new_set), reg)) { + fixup_debug_insns (reg, src, insn, use_insn); delete_insn (insn); return true; } @@ -1102,6 +1098,8 @@ reload_combine_recognize_pattern (rtx in && REG_P (XEXP (src, 1)) && rtx_equal_p (XEXP (src, 0), reg) && !rtx_equal_p (XEXP (src, 1), reg) + && reg_state[regno].use_index >= 0 + && reg_state[regno].use_index < RELOAD_COMBINE_MAX_USES && last_label_ruid < reg_state[regno].use_ruid) { rtx base = XEXP (src, 1); @@ -1134,7 +1132,11 @@ reload_combine_recognize_pattern (rtx in if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], i) && reg_state[i].use_index == RELOAD_COMBINE_MAX_USES && reg_state[i].store_ruid <= reg_state[regno].use_ruid - && hard_regno_nregs[i][GET_MODE (reg)] == 1) + && (call_used_regs[i] || df_regs_ever_live_p (i)) + && (!frame_pointer_needed || i != HARD_FRAME_POINTER_REGNUM) + && !fixed_regs[i] && !global_regs[i] + && hard_regno_nregs[i][GET_MODE (reg)] == 1 + && targetm.hard_regno_scratch_ok (regno)) { index_reg = gen_rtx_REG (GET_MODE (reg), i); reg_sum = gen_rtx_PLUS (GET_MODE (reg), index_reg, base); @@ -1150,7 +1152,6 @@ reload_combine_recognize_pattern (rtx in && prev_set && CONST_INT_P (SET_SRC (prev_set)) && rtx_equal_p (SET_DEST (prev_set), reg) - && reg_state[regno].use_index >= 0 && (reg_state[REGNO (base)].store_ruid <= reg_state[regno].use_ruid)) { @@ -1201,8 +1202,6 @@ reload_combine_recognize_pattern (rtx in remove_reg_equal_equiv_notes (prev); reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES; - reg_state[REGNO (index_reg)].store_ruid - = reload_combine_ruid; return true; } } @@ -1244,14 +1243,6 @@ reload_combine (void) } } -#if 0 - /* If reg+reg can be used in offsetable memory addresses, the main chunk of - reload has already used it where appropriate, so there is no use in - trying to generate it now. */ - if (double_reg_address_ok || last_index_reg == -1) - return; -#endif - /* Set up LABEL_LIVE and EVER_LIVE_AT_START. The register lifetime information is a bit fuzzy immediately after reload, but it's still good enough to determine which registers are live at a jump @@ -1511,6 +1502,11 @@ reload_combine_note_use (rtx *xp, rtx in return; } + /* We may be called to update uses in previously seen insns. + Don't add uses beyond the last store we saw. */ + if (ruid < reg_state[regno].store_ruid) + return; + /* If this register is already used in some unknown fashion, we can't do anything. If we decrement the index from zero to -1, we can't store more Index: Makefile.in =================================================================== --- Makefile.in (revision 162372) +++ Makefile.in (working copy) @@ -3288,7 +3288,7 @@ postreload.o : postreload.c $(CONFIG_H) $(RTL_H) $(FLAGS_H) $(EXPR_H) $(OPTABS_H) reload.h $(REGS_H) \ hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) $(RECOG_H) output.h \ $(FUNCTION_H) $(TOPLEV_H) $(DIAGNOSTIC_CORE_H) cselib.h $(TM_P_H) $(EXCEPT_H) $(TREE_H) $(MACHMODE_H) \ - $(OBSTACK_H) $(TIMEVAR_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H) + $(OBSTACK_H) $(TARGET_H) $(TIMEVAR_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H) postreload-gcse.o : postreload-gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \ $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h $(TOPLEV_H) $(DIAGNOSTIC_CORE_H) \