This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: reload1: detect chained reloads
- From: Rask Ingemann Lambertsen <rask at sygehus dot dk>
- To: DJ Delorie <dj at redhat dot com>
- Cc: iant at google dot com, gcc-patches at gcc dot gnu dot org
- Date: Sat, 14 Jul 2007 21:32:26 +0200
- Subject: Re: reload1: detect chained reloads
- References: <440F03E7.3050200@st.com> <200603081625.k28GPEuh031677@greed.delorie.com> <440F155F.4070402@st.com> <200603081835.k28IZ5GY004959@greed.delorie.com> <440F2E99.1010400@st.com> <200603082138.k28LchS0008311@greed.delorie.com> <200607311831.k6VIVlRe002018@greed.delorie.com> <m38xkobluy.fsf@localhost.localdomain> <200611172315.kAHNFcNf001253@greed.delorie.com>
On Fri, Nov 17, 2006 at 06:15:38PM -0500, DJ Delorie wrote:
> Index: reload1.c
[...]
> +static bool
> +reloads_unique_chain_p (int r1, int r2)
> +{
> + int i;
> +
> + /* We only check input reloads. */
> + if (! rld[r1].in || ! rld[r2].in)
> + return false;
> +
> + /* Avoid anything with output reloads. */
> + if (rld[r1].out || rld[r2].out)
> + return false;
> +
> + /* "chained" means one reload is a component of the other reload,
> + not the same as the other reload. */
> + if (rld[r1].opnum != rld[r2].opnum
> + || rtx_equal_p (rld[r1].in, rld[r2].in)
> + || rld[r1].optional || rld[r2].optional
> + || ! (reg_mentioned_p (rld[r1].in, rld[r2].in)
> + || reg_mentioned_p (rld[r2].in, rld[r1].in)))
> + return false;
> +
> + for (i = 0; i < n_reloads; i ++)
> + /* Look for input reloads that aren't our two */
> + if (i != r1 && i != r2 && rld[i].in)
> + {
> + /* If our reload is mentioned at all, it isn't a simple chain. */
> + if (reg_mentioned_p (rld[r1].in, rld[i].in))
> + return false;
> + }
> + return true;
> +}
I'm debugging a failure of testsuite/gcc.dg/20030225-1.c on my 16-bit x86
port. The problem arises when reload is given this insn:
(insn:HI 1187 1186 1544 5 .../20030225-1.c:75 (set (mem:HI (plus:HI (reg:HI 703 [ ivtmp.96 ])
(reg/v/f:HI 723 [ block ])) [2 S2 A16])
(reg:HI 1017)) 9 {*movhi} (expr_list:REG_DEAD (reg:HI 1017)
(nil)))
Both index and base register are on the stack. Additionally, the stack
pointer is not a valid base register, so that has to be reloaded as well.
The reloads produced are:
Reloads for insn # 1187
Reload order: 3 1 0 2 4
Reload 0: reload_in (HI) = (reg/f:HI 12 sp)
BASE_REGS, RELOAD_FOR_OPERAND_ADDRESS (opnum = 0)
reload_in_reg: (reg/f:HI 12 sp)
reload_reg_rtx: (reg:HI 10 bp)
Reload 1: reload_in (HI) = (mem/c:HI (plus:HI (reg/f:HI 12 sp)
(const_int 78 [0x4e])) [5 ivtmp.96+0 S2 A8])
BASE_W_INDEX_REGS, RELOAD_FOR_OPERAND_ADDRESS (opnum = 0), can't combine
reload_in_reg: (reg:HI 703 [ ivtmp.96 ])
reload_reg_rtx: (reg:HI 10 bp)
Reload 2: BASE_REGS, RELOAD_FOR_OPERAND_ADDRESS (opnum = 0)
reload_in_reg: (reg/f:HI 12 sp)
Reload 3: reload_in (HI) = (mem/f/c/i:HI (plus:HI (reg/f:HI 12 sp)
(const_int 94 [0x5e])) [3 block+0 S2 A16])
INDEX_REGS, RELOAD_FOR_OPERAND_ADDRESS (opnum = 0), can't combine
reload_in_reg: (reg/v/f:HI 723 [ block ])
reload_reg_rtx: (reg:HI 9 di)
Reload 4: reload_out (HI) = (mem:HI (plus:HI (reg:HI 703 [ ivtmp.96 ])
(reg/v/f:HI 723 [ block ])) [2 S2 A16])
GENERAL_REGS, RELOAD_FOR_OUTPUT (opnum = 0), optional
reload_out_reg: (mem:HI (plus:HI (reg:HI 703 [ ivtmp.96 ])
(reg/v/f:HI 723 [ block ])) [2 S2 A16])
Here, insn 2108 clobbers %bp which we need for insn 2109:
(insn 2107 1186 2108 5 .../20030225-1.c:75 (set (reg:HI 10 bp)
(reg/f:HI 12 sp)) 9 {*movhi} (nil))
(insn 2108 2107 2109 5 .../20030225-1.c:75 (set (reg:HI 10 bp)
(mem/c:HI (plus:HI (reg:HI 10 bp)
(const_int 78 [0x4e])) [5 ivtmp.96+0 S2 A8])) 9 {*movhi} (nil))
(insn 2109 2108 1187 5 .../20030225-1.c:75 (set (reg:HI 9 di)
(mem/f/c/i:HI (plus:HI (reg:HI 10 bp)
(const_int 94 [0x5e])) [3 block+0 S2 A16])) 9 {*movhi} (nil))
(insn:HI 1187 2109 2112 5 .../20030225-1.c:75 (set (mem:HI (plus:HI (reg:HI 10 bp)
(reg:HI 9 di)) [2 S2 A16])
(reg:HI 2 a [1017])) 9 {*movhi} (nil))
movw %sp, %bp ;# 2107 *movhi/1
movw 78(%bp),%bp ;# 2108 *movhi/1
movw 94(%bp),%di ;# 2109 *movhi/1
movw %ax, (%bp,%di) ;# 1187 *movhi/2
The interesting bits from the debugger:
Run till exit from #0 reloads_unique_chain_p (r1=3, r2=0) at ../../../cvssrc/gcc/gcc/reload1.c:4982
0x082c8ebb in reloads_conflict (r1=3, r2=0) at ../../../cvssrc/gcc/gcc/reload1.c:5032
Value returned is $29 = 1 '\001'
Run till exit from #0 reloads_unique_chain_p (r1=1, r2=0) at ../../../cvssrc/gcc/gcc/reload1.c:4982
0x082c8ebb in reloads_conflict (r1=1, r2=0) at ../../../cvssrc/gcc/gcc/reload1.c:5032
Value returned is $33 = 1 '\001'
Reloads 3 and 0 are not uniquely chained, and neither are 1 and 0. It
seems to me that we miss this conflict because the "reg" reload is r2, not
r1, and indeed, this patch fixes my problem:
Index: gcc/reload1.c
===================================================================
--- gcc/reload1.c (revision 125984)
+++ gcc/reload1.c (working copy)
@@ -4960,7 +4976,7 @@ reloads_unique_chain_p (int r1, int r2)
if (i != r1 && i != r2 && rld[i].in)
{
/* If our reload is mentioned at all, it isn't a simple chain. */
- if (reg_mentioned_p (rld[r1].in, rld[i].in))
+ if (reg_mentioned_p (rld[r2].in, rld[i].in))
return false;
}
return true;
movw %sp, %si ;# 2065 *movhi/1
movw 78(%si),%bp ;# 2066 *movhi/1
movw 94(%si),%di ;# 2067 *movhi/1
movw %ax, (%bp,%di) ;# 1187 *movhi/2
I just have a nasty feeling that the case which started all this (see
<URL:http://gcc.gnu.org/ml/gcc-patches/2006-03/msg00047.html> had the "reg"
reload in r1. Should I simply check it both ways?
--
Rask Ingemann Lambertsen