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]

[PATCH] Fix PR optimization/10392


Hi,

This is the reload deficiency explained here:

   http://gcc.gnu.org/ml/gcc/2003-09/msg00460.html

which causes a regression on 3.3 branch and mainline for SH4.


As suggested by Jim, the patch modifies push_reload so that it tests the 
validity of the final optimization it wants to apply to input reloads, by 
emitting and trying to recognize the insn.

For the time being, it doesn't do any caching because I'm a bit concerned 
about the two calls to find_replacement in gen_reload: I think they rule out 
the caching of the entire insn, and possibly of the insn code. But I'd like 
to have the opinion of reload experts.

Bootstrapped/regtested on i586-redhat-linux-gnu (3.3 branch except Ada).


2003-09-17  Eric Botcazou  <ebotcazou@libertysurf.fr>

        PR optimization/10392
	* reload.h (gen_reload_plus_p): Declare.
	(gen_reload_plus_direct): Likewise.
	* reload1.c (gen_reload_plus_p): New function to test whether
	an expression is a PLUS that can be handled by gen_reload.
	(gen_reload_plus_direct): New function to attempt to reload a
	PLUS expression without using an auxilliary reload.
	(gen_reload): Use gen_reload_plus_p to recognize PLUS expressions.
	Use gen_reload_plus_direct to try to reload them directly.
	* reload.c (push_reload): When trying to optimize an input reload,
	check that a direct reload is sufficient if the operand is a PLUS.


2003-09-17  Eric Botcazou  <ebotcazou@libertysurf.fr>

	* gcc.dg/reload-1.c: New test.


The testcase is basically
http://www.kegel.com/crosstool/current/patches/gcc-3.3.1/pr10392-1-test.patch


--
Eric Botcazou
Index: reload1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload1.c,v
retrieving revision 1.366.2.6
diff -u -p -r1.366.2.6 reload1.c
--- reload1.c	7 Jun 2003 05:30:09 -0000	1.366.2.6
+++ reload1.c	16 Sep 2003 20:55:07 -0000
@@ -7367,6 +7367,67 @@ emit_reload_insns (chain)
   IOR_HARD_REG_SET (reg_reloaded_dead, reg_reloaded_died);
 }
 
+/* Return 1 if X is a PLUS expression that can be handled by gen_reload.  */
+
+bool
+gen_reload_plus_p (x)
+     rtx x;
+{
+  return (GET_CODE (x) == PLUS
+	  && (GET_CODE (XEXP (x, 0)) == REG
+	      || GET_CODE (XEXP (x, 0)) == SUBREG
+	      || GET_CODE (XEXP (x, 0)) == MEM)
+	  && (GET_CODE (XEXP (x, 1)) == REG
+	      || GET_CODE (XEXP (x, 1)) == SUBREG
+	      || CONSTANT_P (XEXP (x, 1))
+	      || GET_CODE (XEXP (x, 1)) == MEM));
+}
+
+/* Attempt to build an insn to perform a reload from IN0 PLUS IN1 in mode
+   IN_MODE (which must satisfy the gen_reload_plus_p predicate) to OUT
+   (which may be a reload register) using only the direct approach, i.e.
+   without separately reloading from INO or IN1 to OUT.
+
+   Returns the insn or zero if this is not possible.  */
+
+rtx
+gen_reload_plus_direct (out, in0, in1, in_mode)
+     rtx out;
+     rtx in0;
+     rtx in1;
+     enum machine_mode in_mode;
+{
+  rtx in, insn;
+  int code;
+
+  /* Since constraint checking is strict, commutativity won't be
+     checked, so we need to do that here to avoid spurious failure
+     if the add instruction is two-address and the second operand
+     of the add is the same as the reload reg, which is frequently
+     the case.  If the insn would be A = B + A, rearrange it so
+     it will be A = A + B as constrain_operands expects.  */
+
+  if (GET_CODE (in1) == REG && REGNO (out) == REGNO (in1))
+    in = gen_rtx_PLUS (in_mode, in1, in0);
+  else
+    in = gen_rtx_PLUS (in_mode, in0, in1);
+
+  insn = make_insn_raw (gen_rtx_SET (VOIDmode, out, in));
+  code = recog_memoized (insn);
+
+  if (code >= 0)
+    {
+      extract_insn (insn);
+      /* We want constrain operands to treat this insn strictly in
+	 its validity determination, i.e., the way it would after reload
+	 has completed.  */
+      if (constrain_operands (1))
+        return insn;
+    }
+
+  return NULL_RTX;
+}
+
 /* Emit code to perform a reload from IN (which may be a reload register) to
    OUT (which may also be a reload register).  IN or OUT is from operand
    OPNUM with reload type TYPE.
@@ -7422,14 +7483,7 @@ gen_reload (out, in, opnum, type)
 
      ??? At some point, this whole thing needs to be rethought.  */
 
-  if (GET_CODE (in) == PLUS
-      && (GET_CODE (XEXP (in, 0)) == REG
-	  || GET_CODE (XEXP (in, 0)) == SUBREG
-	  || GET_CODE (XEXP (in, 0)) == MEM)
-      && (GET_CODE (XEXP (in, 1)) == REG
-	  || GET_CODE (XEXP (in, 1)) == SUBREG
-	  || CONSTANT_P (XEXP (in, 1))
-	  || GET_CODE (XEXP (in, 1)) == MEM))
+  if (gen_reload_plus_p (in))
     {
       /* We need to compute the sum of a register or a MEM and another
 	 register, constant, or MEM, and put it into the reload
@@ -7450,34 +7504,12 @@ gen_reload (out, in, opnum, type)
       op0 = find_replacement (&XEXP (in, 0));
       op1 = find_replacement (&XEXP (in, 1));
 
-      /* Since constraint checking is strict, commutativity won't be
-	 checked, so we need to do that here to avoid spurious failure
-	 if the add instruction is two-address and the second operand
-	 of the add is the same as the reload reg, which is frequently
-	 the case.  If the insn would be A = B + A, rearrange it so
-	 it will be A = A + B as constrain_operands expects.  */
-
-      if (GET_CODE (XEXP (in, 1)) == REG
-	  && REGNO (out) == REGNO (XEXP (in, 1)))
-	tem = op0, op0 = op1, op1 = tem;
-
-      if (op0 != XEXP (in, 0) || op1 != XEXP (in, 1))
-	in = gen_rtx_PLUS (GET_MODE (in), op0, op1);
-
-      insn = emit_insn (gen_rtx_SET (VOIDmode, out, in));
-      code = recog_memoized (insn);
-
-      if (code >= 0)
+      insn = gen_reload_plus_direct (out, op0, op1, GET_MODE (in));
+      if (insn)
 	{
-	  extract_insn (insn);
-	  /* We want constrain operands to treat this insn strictly in
-	     its validity determination, i.e., the way it would after reload
-	     has completed.  */
-	  if (constrain_operands (1))
-	    return insn;
+	  add_insn (insn);
+	  return insn;
 	}
-
-      delete_insns_since (last);
 
       /* If that failed, we must use a conservative two-insn sequence.
 
Index: reload.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload.c,v
retrieving revision 1.199.2.8
diff -u -p -r1.199.2.8 reload.c
--- reload.c	28 Apr 2003 07:58:28 -0000	1.199.2.8
+++ reload.c	16 Sep 2003 20:56:18 -0000
@@ -1534,7 +1534,25 @@ push_reload (in, out, inloc, outloc, cla
 
 	    if (offs == nregs)
 	      {
-		rld[i].reg_rtx = gen_rtx_REG (rel_mode, regno);
+		rtx reg = gen_rtx_REG (rel_mode, regno);
+
+		/* In case the operand is a PLUS, we must also check that
+		   it is directly reloadable into the register, otherwise
+		   gen_reload will use an auxilliary reload from one of the
+		   operands of the PLUS to the register, which will cause
+		   the value currently in the register to be overwritten.  */
+
+		if (gen_reload_plus_p (in))
+		  {
+		    rtx insn = gen_reload_plus_direct (reg,
+						       XEXP (in, 0),
+						       XEXP (in, 1),
+						       GET_MODE (in));
+		    if (!insn)
+		      continue;
+		  }
+
+		rld[i].reg_rtx = reg;
 		break;
 	      }
 	  }
Index: reload.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload.h,v
retrieving revision 1.41
diff -u -p -r1.41 reload.h
--- reload.h	26 Sep 2002 22:25:13 -0000	1.41
+++ reload.h	16 Sep 2003 20:56:37 -0000
@@ -357,6 +357,15 @@ extern void mark_home_live PARAMS ((int)
    replacement (such as sp), plus an offset.  */
 extern rtx eliminate_regs PARAMS ((rtx, enum machine_mode, rtx));
 
+/* Return TRUE if X is a PLUS expression that can be handled by gen_reload.  */
+extern bool gen_reload_plus_p PARAMS ((rtx));
+
+/* Attempt to build an insn to perform a reload from IN0 PLUS IN1 in mode
+   IN_MODE (which must satisfy the gen_reload_plus_p predicate) to OUT
+   (which may be a reload register) using only the direct approach, i.e.
+   without separately reloading from INO or IN1 to OUT.  */
+extern rtx gen_reload_plus_direct PARAMS ((rtx, rtx, rtx, enum machine_mode));
+          
 /* Emit code to perform a reload from IN (which may be a reload register) to
    OUT (which may also be a reload register).  IN or OUT is from operand
    OPNUM with reload type TYPE.  */

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