From patchwork Sun May 29 22:50:01 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 97861 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 3A2C6B6F69 for ; Mon, 30 May 2011 08:50:25 +1000 (EST) Received: (qmail 31742 invoked by alias); 29 May 2011 22:50:23 -0000 Received: (qmail 31729 invoked by uid 22791); 29 May 2011 22:50:22 -0000 X-SWARE-Spam-Status: No, hits=-2.2 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, RFC_ABUSE_POST X-Spam-Check-By: sourceware.org Received: from mail-ww0-f51.google.com (HELO mail-ww0-f51.google.com) (74.125.82.51) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sun, 29 May 2011 22:50:06 +0000 Received: by wwf26 with SMTP id 26so3104844wwf.8 for ; Sun, 29 May 2011 15:50:05 -0700 (PDT) Received: by 10.227.206.135 with SMTP id fu7mr4202993wbb.64.1306709405469; Sun, 29 May 2011 15:50:05 -0700 (PDT) Received: from localhost (rsandifo.gotadsl.co.uk [82.133.89.107]) by mx.google.com with ESMTPS id ex2sm2659667wbb.65.2011.05.29.15.50.02 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 29 May 2011 15:50:04 -0700 (PDT) From: Richard Sandiford To: Eric Botcazou Mail-Followup-To: Eric Botcazou , gcc-patches@gcc.gnu.org, "Chung-Lin Tang" , Richard Earnshaw , patches@linaro.org, rdsandiford@googlemail.com Cc: gcc-patches@gcc.gnu.org, "Chung-Lin Tang" , Richard Earnshaw , patches@linaro.org Subject: Re: [patch, ARM] Fix PR48808, PR48792: More work on CANNOT_CHANGE_MODE_CLASS References: <4DE28F42.2070507@codesourcery.com> <87mxi5jlgv.fsf@firetop.home> <201105292328.45285.ebotcazou@adacore.com> Date: Sun, 29 May 2011 23:50:01 +0100 In-Reply-To: <201105292328.45285.ebotcazou@adacore.com> (Eric Botcazou's message of "Sun, 29 May 2011 23:28:44 +0200") Message-ID: <87ei3hjf52.fsf@firetop.home> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (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 Eric Botcazou writes: >> Something like the attached patch. Not tested yet, and I'm sure >> it'll break things in lots of fun and interesting ways... > > Mind posting a (temporarily) definitive version? I'll give it a whirl on the > SPARC and IA-64 to see how it would fare. Thanks. With the s/MODE/CODE/ fix (attached) it passes bootstrap & regression test on x86_64-linux-gnu. I'll also try to some assembly diffs over a range of targets. Richard gcc/ * reload.c (push_reload): Check contains_reg_of_mode. * reload1.c (strip_paradoxical_subreg): New function. (gen_reload_chain_without_interm_reg_p): Use it to handle paradoxical subregs. (emit_output_reload_insns, gen_reload): Likewise. Index: gcc/reload.c =================================================================== --- gcc/reload.c 2011-05-29 23:48:02.000000000 +0100 +++ gcc/reload.c 2011-05-29 23:48:02.000000000 +0100 @@ -1019,6 +1019,7 @@ push_reload (rtx in, rtx out, rtx *inloc #ifdef CANNOT_CHANGE_MODE_CLASS && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (in)), inmode, rclass) #endif + && contains_reg_of_mode[(int) rclass][(int) GET_MODE (SUBREG_REG (in))] && (CONSTANT_P (SUBREG_REG (in)) || GET_CODE (SUBREG_REG (in)) == PLUS || strict_low @@ -1125,6 +1126,7 @@ push_reload (rtx in, rtx out, rtx *inloc #ifdef CANNOT_CHANGE_MODE_CLASS && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)), outmode, rclass) #endif + && contains_reg_of_mode[(int) rclass][(int) GET_MODE (SUBREG_REG (out))] && (CONSTANT_P (SUBREG_REG (out)) || strict_low || (((REG_P (SUBREG_REG (out)) Index: gcc/reload1.c =================================================================== --- gcc/reload1.c 2011-05-29 23:48:02.000000000 +0100 +++ gcc/reload1.c 2011-05-29 23:48:02.000000000 +0100 @@ -4471,6 +4471,43 @@ scan_paradoxical_subregs (rtx x) } } } + +/* *FOCUS_PTR and *OTHER_PTR are two operands to a conceptual reload. + If *FOCUS_PTR is a paradoxical subreg, try to remove that subreg + and apply the corresponding narrowing subreg to *OTHER_PTR. + Return true if the operands were changed, false otherwise. */ + +static bool +strip_paradoxical_subreg (rtx *focus_ptr, rtx *other_ptr) +{ + rtx focus, inner, other, tem; + + focus = *focus_ptr; + if (GET_CODE (focus) != SUBREG) + return false; + + inner = SUBREG_REG (focus); + if (GET_MODE_SIZE (GET_MODE (focus)) <= GET_MODE_SIZE (GET_MODE (inner))) + return false; + + other = *other_ptr; + tem = gen_lowpart_common (GET_MODE (inner), other); + if (!tem) + return false; + + /* If the lowpart operation turned a hard register into a subreg, + rather than simplifying it to another hard register, then the + mode change cannot be properly represented. For example, OTHER + might be valid in its current mode, but not in the new one. */ + if (GET_CODE (tem) == SUBREG + && REG_P (other) + && HARD_REGISTER_P (other)) + return false; + + *focus_ptr = inner; + *other_ptr = tem; + return true; +} /* A subroutine of reload_as_needed. If INSN has a REG_EH_REGION note, examine all of the reload insns between PREV and NEXT exclusive, and @@ -5538,7 +5575,7 @@ gen_reload_chain_without_interm_reg_p (i chain reloads or do need an intermediate hard registers. */ bool result = true; int regno, n, code; - rtx out, in, tem, insn; + rtx out, in, insn; rtx last = get_last_insn (); /* Make r2 a component of r1. */ @@ -5557,11 +5594,7 @@ gen_reload_chain_without_interm_reg_p (i /* If IN is a paradoxical SUBREG, remove it and try to put the opposite SUBREG on OUT. Likewise for a paradoxical SUBREG on OUT. */ - if (GET_CODE (in) == SUBREG - && (GET_MODE_SIZE (GET_MODE (in)) - > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))) - && (tem = gen_lowpart_common (GET_MODE (SUBREG_REG (in)), out)) != 0) - in = SUBREG_REG (in), out = tem; + strip_paradoxical_subreg (&in, &out); if (GET_CODE (in) == PLUS && (REG_P (XEXP (in, 0)) @@ -7557,7 +7590,6 @@ emit_output_reload_insns (struct insn_ch if (tertiary_icode != CODE_FOR_nothing) { rtx third_reloadreg = rld[tertiary_reload].reg_rtx; - rtx tem; /* Copy primary reload reg to secondary reload reg. (Note that these have been swapped above, then @@ -7566,13 +7598,7 @@ emit_output_reload_insns (struct insn_ch /* If REAL_OLD is a paradoxical SUBREG, remove it and try to put the opposite SUBREG on RELOADREG. */ - if (GET_CODE (real_old) == SUBREG - && (GET_MODE_SIZE (GET_MODE (real_old)) - > GET_MODE_SIZE (GET_MODE (SUBREG_REG (real_old)))) - && 0 != (tem = gen_lowpart_common - (GET_MODE (SUBREG_REG (real_old)), - reloadreg))) - real_old = SUBREG_REG (real_old), reloadreg = tem; + strip_paradoxical_subreg (&real_old, &reloadreg); gen_reload (reloadreg, second_reloadreg, rl->opnum, rl->when_needed); @@ -8388,16 +8414,8 @@ gen_reload (rtx out, rtx in, int opnum, /* If IN is a paradoxical SUBREG, remove it and try to put the opposite SUBREG on OUT. Likewise for a paradoxical SUBREG on OUT. */ - if (GET_CODE (in) == SUBREG - && (GET_MODE_SIZE (GET_MODE (in)) - > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))) - && (tem = gen_lowpart_common (GET_MODE (SUBREG_REG (in)), out)) != 0) - in = SUBREG_REG (in), out = tem; - else if (GET_CODE (out) == SUBREG - && (GET_MODE_SIZE (GET_MODE (out)) - > GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))) - && (tem = gen_lowpart_common (GET_MODE (SUBREG_REG (out)), in)) != 0) - out = SUBREG_REG (out), in = tem; + if (!strip_paradoxical_subreg (&in, &out)) + strip_paradoxical_subreg (&out, &in); /* How to do this reload can get quite tricky. Normally, we are being asked to reload a simple operand, such as a MEM, a constant, or a pseudo