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: 1664 Return-Path: Delivered-To: unknown Received: from imap.gmail.com (74.125.159.109) by localhost6.localdomain6 with IMAP4-SSL; 08 Jun 2011 14:54:05 -0000 Delivered-To: patches@linaro.org Received: by 10.52.110.9 with SMTP id hw9cs207527vdb; Sun, 29 May 2011 15:50:07 -0700 (PDT) Received: by 10.216.60.74 with SMTP id t52mr4596468wec.30.1306709407023; Sun, 29 May 2011 15:50:07 -0700 (PDT) Received: from mail-ww0-f42.google.com (mail-ww0-f42.google.com [74.125.82.42]) by mx.google.com with ESMTPS id t63si2213379weq.59.2011.05.29.15.50.05 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 29 May 2011 15:50:06 -0700 (PDT) Received-SPF: pass (google.com: domain of rdsandiford@googlemail.com designates 74.125.82.42 as permitted sender) client-ip=74.125.82.42; Authentication-Results: mx.google.com; spf=pass (google.com: domain of rdsandiford@googlemail.com designates 74.125.82.42 as permitted sender) smtp.mail=rdsandiford@googlemail.com; dkim=pass (test mode) header.i=@googlemail.com Received: by wwk4 with SMTP id 4so1133398wwk.1 for ; Sun, 29 May 2011 15:50:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=gamma; h=domainkey-signature:from:to:mail-followup-to:cc:subject:references :date:in-reply-to:message-id:user-agent:mime-version:content-type; bh=xmFsllPZaQCmntHbtbeAK/jETCYo11VMqELqkCGZ9LQ=; b=Nue8q9uN3PzMdFAO9S0Fcs6CcwjqcDXNtQCH0Zh2SmxjVK5CHFvmTEeGtsxMVrH6YB oD6mtoGSX9wxIUVQYsmcryNbIOB166VY92jSErtKoJYXKaLYiSS/Z3O5qNOXpHaBhiPD AAYVGqh5RPmGA4VLDK3pXbnmEMVRAcK/b2Hnc= DomainKey-Signature: a=rsa-sha1; c=nofws; d=googlemail.com; s=gamma; h=from:to:mail-followup-to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version:content-type; b=reqco+Bwi0UrRuzc9FKu3/H+89tI178znC186j6DYO9na8cuHZZ1D89HyzCRDHfkFM RtwLpszYGl7/9+NGlVlEyULoIn/tYx/z3UDmebec4Fqe/gaQoLRffkFMRitAQvdogP/8 itMIVus6hNH5VmS5C7SSemJJNY3NXxbHXVeWw= 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 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