This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: reload1: detect chained reloads


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]