From patchwork Thu Sep 9 15:22:30 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Makarov X-Patchwork-Id: 64308 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 8A910B6F06 for ; Fri, 10 Sep 2010 01:22:47 +1000 (EST) Received: (qmail 20992 invoked by alias); 9 Sep 2010 15:22:45 -0000 Received: (qmail 20891 invoked by uid 22791); 9 Sep 2010 15:22:42 -0000 X-SWARE-Spam-Status: No, hits=-6.1 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, T_RP_MATCHES_RCVD 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; Thu, 09 Sep 2010 15:22:33 +0000 Received: from int-mx03.intmail.prod.int.phx2.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o89FMVD9031052 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 9 Sep 2010 11:22:31 -0400 Received: from toll.yyz.redhat.com (toll.yyz.redhat.com [10.15.16.165]) by int-mx03.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o89FMUMe015326; Thu, 9 Sep 2010 11:22:30 -0400 Message-ID: <4C88FBB6.3080309@redhat.com> Date: Thu, 09 Sep 2010 11:22:30 -0400 From: Vladimir Makarov User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.7) Gecko/20100720 Fedora/3.1.1-1.fc13 Thunderbird/3.1.1 MIME-Version: 1.0 To: gcc-patches CC: uweigand@gcc.gnu.org Subject: [patch] a fix for PR45312 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 The following patch fixes PR45312. The details are on http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45312 I'd like to add that this bug is probably 15 years old and removing merge_assigned_reloads does not affect the code at least for SPEC2000 and many other benchmarks I tried on x86/x86_64 because subsequent optimizations can do the same as this function (mainly removing reload in the same hard register from the same source). Ok to commit into the trunk, gcc 4.4 and gcc 4.5 branch? 2010-09-09 Vladimir Makarov PR middle-end/45312 * reload1.c (merge_assigned_reloads): Remove. (reload_as_needed): Don't call it. Index: reload1.c =================================================================== --- reload1.c (revision 164108) +++ reload1.c (working copy) @@ -435,7 +435,6 @@ static void failed_reload (rtx, int); static int set_reload_reg (int, int); static void choose_reload_regs_init (struct insn_chain *, rtx *); static void choose_reload_regs (struct insn_chain *); -static void merge_assigned_reloads (rtx); static void emit_input_reload_insns (struct insn_chain *, struct reload *, rtx, int); static void emit_output_reload_insns (struct insn_chain *, struct reload *, @@ -4596,12 +4595,6 @@ reload_as_needed (int live_known) Record the choices of reload reg in reload_reg_rtx. */ choose_reload_regs (chain); - /* Merge any reloads that we didn't combine for fear of - increasing the number of spill registers needed but now - discover can be safely merged. */ - if (targetm.small_register_classes_for_mode_p (VOIDmode)) - merge_assigned_reloads (insn); - /* Generate the insns to reload operands into or out of their reload regs. */ emit_reload_insns (chain); @@ -6994,153 +6987,6 @@ deallocate_reload_reg (int r) reload_spill_index[r] = -1; } -/* If the small_register_classes_for_mode_p target hook returns true for - some machine modes, we may not have merged two reloads of the same item - for fear that we might not have enough reload registers. However, - normally they will get the same reload register and hence actually need - not be loaded twice. - - Here we check for the most common case of this phenomenon: when we have - a number of reloads for the same object, each of which were allocated - the same reload_reg_rtx, that reload_reg_rtx is not used for any other - reload, and is not modified in the insn itself. If we find such, - merge all the reloads and set the resulting reload to RELOAD_OTHER. - This will not increase the number of spill registers needed and will - prevent redundant code. */ - -static void -merge_assigned_reloads (rtx insn) -{ - int i, j; - - /* Scan all the reloads looking for ones that only load values and - are not already RELOAD_OTHER and ones whose reload_reg_rtx are - assigned and not modified by INSN. */ - - for (i = 0; i < n_reloads; i++) - { - int conflicting_input = 0; - int max_input_address_opnum = -1; - int min_conflicting_input_opnum = MAX_RECOG_OPERANDS; - - if (rld[i].in == 0 || rld[i].when_needed == RELOAD_OTHER - || rld[i].out != 0 || rld[i].reg_rtx == 0 - || reg_set_p (rld[i].reg_rtx, insn)) - continue; - - /* Look at all other reloads. Ensure that the only use of this - reload_reg_rtx is in a reload that just loads the same value - as we do. Note that any secondary reloads must be of the identical - class since the values, modes, and result registers are the - same, so we need not do anything with any secondary reloads. */ - - for (j = 0; j < n_reloads; j++) - { - if (i == j || rld[j].reg_rtx == 0 - || ! reg_overlap_mentioned_p (rld[j].reg_rtx, - rld[i].reg_rtx)) - continue; - - if (rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS - && rld[j].opnum > max_input_address_opnum) - max_input_address_opnum = rld[j].opnum; - - /* If the reload regs aren't exactly the same (e.g, different modes) - or if the values are different, we can't merge this reload. - But if it is an input reload, we might still merge - RELOAD_FOR_INPUT_ADDRESS and RELOAD_FOR_OTHER_ADDRESS reloads. */ - - if (! rtx_equal_p (rld[i].reg_rtx, rld[j].reg_rtx) - || rld[j].out != 0 || rld[j].in == 0 - || ! rtx_equal_p (rld[i].in, rld[j].in)) - { - if (rld[j].when_needed != RELOAD_FOR_INPUT - || ((rld[i].when_needed != RELOAD_FOR_INPUT_ADDRESS - || rld[i].opnum > rld[j].opnum) - && rld[i].when_needed != RELOAD_FOR_OTHER_ADDRESS)) - break; - conflicting_input = 1; - if (min_conflicting_input_opnum > rld[j].opnum) - min_conflicting_input_opnum = rld[j].opnum; - } - } - - /* If all is OK, merge the reloads. Only set this to RELOAD_OTHER if - we, in fact, found any matching reloads. */ - - if (j == n_reloads - && max_input_address_opnum <= min_conflicting_input_opnum) - { - gcc_assert (rld[i].when_needed != RELOAD_FOR_OUTPUT); - - for (j = 0; j < n_reloads; j++) - if (i != j && rld[j].reg_rtx != 0 - && rtx_equal_p (rld[i].reg_rtx, rld[j].reg_rtx) - && (! conflicting_input - || rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS - || rld[j].when_needed == RELOAD_FOR_OTHER_ADDRESS)) - { - rld[i].when_needed = RELOAD_OTHER; - rld[j].in = 0; - reload_spill_index[j] = -1; - transfer_replacements (i, j); - } - - /* If this is now RELOAD_OTHER, look for any reloads that - load parts of this operand and set them to - RELOAD_FOR_OTHER_ADDRESS if they were for inputs, - RELOAD_OTHER for outputs. Note that this test is - equivalent to looking for reloads for this operand - number. - - We must take special care with RELOAD_FOR_OUTPUT_ADDRESS; - it may share registers with a RELOAD_FOR_INPUT, so we can - not change it to RELOAD_FOR_OTHER_ADDRESS. We should - never need to, since we do not modify RELOAD_FOR_OUTPUT. - - It is possible that the RELOAD_FOR_OPERAND_ADDRESS - instruction is assigned the same register as the earlier - RELOAD_FOR_OTHER_ADDRESS instruction. Merging these two - instructions will cause the RELOAD_FOR_OTHER_ADDRESS - instruction to be deleted later on. */ - - if (rld[i].when_needed == RELOAD_OTHER) - for (j = 0; j < n_reloads; j++) - if (rld[j].in != 0 - && rld[j].when_needed != RELOAD_OTHER - && rld[j].when_needed != RELOAD_FOR_OTHER_ADDRESS - && rld[j].when_needed != RELOAD_FOR_OUTPUT_ADDRESS - && rld[j].when_needed != RELOAD_FOR_OPERAND_ADDRESS - && (! conflicting_input - || rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS - || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS) - && reg_overlap_mentioned_for_reload_p (rld[j].in, - rld[i].in)) - { - int k; - - rld[j].when_needed - = ((rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS - || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS) - ? RELOAD_FOR_OTHER_ADDRESS : RELOAD_OTHER); - - /* Check to see if we accidentally converted two - reloads that use the same reload register with - different inputs to the same type. If so, the - resulting code won't work. */ - if (rld[j].reg_rtx) - for (k = 0; k < j; k++) - gcc_assert (rld[k].in == 0 || rld[k].reg_rtx == 0 - || rld[k].when_needed != rld[j].when_needed - || !rtx_equal_p (rld[k].reg_rtx, - rld[j].reg_rtx) - || rtx_equal_p (rld[k].in, - rld[j].in)); - } - } - } -} - /* These arrays are filled by emit_reload_insns and its subroutines. */ static rtx input_reload_insns[MAX_RECOG_OPERANDS]; static rtx other_input_address_reload_insns = 0;