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/10876


Hi,

This is a regression from GCC 3.2.3 on 32-bit Sparc, present on mainline and 
3.3 branch, which triggers when compiling aRts/KDE 3.1.2 at -O2.

The compiler segfaults in unroll.c:calculate_giv_inc() after a series of 
events, which can be traced back to an assumption made by the function: 
general induction variables are incremented with a PLUS (after strength 
reduction).

Now, on Sparc, the addsi3 expander may emit a MINUS under certain 
circumstances, which confuses calculate_giv_inc().

Bootstrapped/regtested on sparc-sun-solaris2.9 (c,c++,objc,f77 3.3 branch).
Ok for 3.3 branch and mainline?

-- 
Eric Botcazou


2003-05-20  Eric Botcazou  <ebotcazou@libertysurf.fr>

	PR optimization/10876
	* unroll.c (calculate_giv_inc): Handle givs that are
	incremented with a MINUS.


2003-05-20  Eric Botcazou  <ebotcazou@libertysurf.fr>

	* gcc.c-torture/compile/20030520-1.c: New test.
Index: gcc/unroll.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/unroll.c,v
retrieving revision 1.184.2.2
diff -u -r1.184.2.2 unroll.c
--- gcc/unroll.c	25 Mar 2003 20:23:07 -0000	1.184.2.2
+++ gcc/unroll.c	20 May 2003 10:27:31 -0000
@@ -1588,14 +1588,16 @@
 
  retry:
   /* Verify that we have an increment insn here.  First check for a plus
-     as the set source.  */
-  if (GET_CODE (SET_SRC (pattern)) != PLUS)
+     or a minus as the set source.  */
+  if (GET_CODE (SET_SRC (pattern)) != PLUS
+      && GET_CODE (SET_SRC (pattern)) != MINUS)
     {
       /* SR sometimes computes the new giv value in a temp, then copies it
 	 to the new_reg.  */
       src_insn = PREV_INSN (src_insn);
       pattern = single_set (src_insn);
-      if (GET_CODE (SET_SRC (pattern)) != PLUS)
+      if (GET_CODE (SET_SRC (pattern)) != PLUS
+          && GET_CODE (SET_SRC (pattern)) != MINUS)
 	abort ();
 
       /* The last insn emitted is not needed, so delete it to avoid confusing
@@ -1603,10 +1605,21 @@
       delete_related_insns (get_last_insn ());
     }
 
-  /* Verify that we have a constant as the second operand of the plus.  */
+  /* Verify that we have a constant as the second operand.  */
   increment = XEXP (SET_SRC (pattern), 1);
-  if (GET_CODE (increment) != CONST_INT)
+  if (GET_CODE (increment) == CONST_INT)
     {
+      /* The Sparc port may emit a minus under certain circumstances when
+	 the addsi3 pattern is invoked.  */
+      if (GET_CODE (SET_SRC (pattern)) == MINUS)
+         increment = GEN_INT (-INTVAL (increment));
+    }
+  else
+    {
+      /* We don't handle minus in this branch.  */
+      if (GET_CODE (SET_SRC (pattern)) == MINUS)
+	abort();
+
       /* SR sometimes puts the constant in a register, especially if it is
 	 too big to be an add immed operand.  */
       increment = find_last_value (increment, &src_insn, NULL_RTX, 0);
/* PR optimization/10876 */
/* Contributed by Christian Ehrhardt */

/* Verify that the loop optimizer takes into
   account an oddity of the Sparc port.  */

void f(void)
{
  unsigned int butterfly, block, offset;
  double *Z;

  for (block = 0; block < 512; block += 512) {
    double T1re, T2re;
    offset = butterfly + block;
    T1re += T2re;
    T2re = Z[offset] + T1re;
  }
}

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