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]

Fix PR target/17245


This is an ICE at -O -mcpu=v9 on SPARC 32-bit, a regression present on the 
3.4 branch.  The reload pass generates an invalid insn:

ultrasp11.c: In function `f':
ultrasp11.c:25: error: insn does not satisfy its constraints:
(insn 169 9 11 0 (set (reg:TF 10 %o2)
        (mem/u/f:TF (lo_sum:SI (reg/f:SI 1 %g1 [111])
                (symbol_ref/u:SI ("*.LLC0") [flags 0x2])) [0 S16 A64])) 98 
{*movtf_insn_sp32} (nil)
    (nil))
ultrasp11.c:25: internal compiler error: in reload_cse_simplify_operands, at 
postreload.c:391

It is invalid because the address is not offsettable (with the Sun assembler)
and the pattern wants it to be offsettable for subsequent splitting.

This insn is emitted as part of reload #1 for:

(insn 11 9 13 0 (set (reg/v:TF 109 [ W ])
        (mem/u/f:TF (lo_sum:SI (reg/f:SI 111)
                (symbol_ref/u:SI ("*.LLC0") [flags 0x2])) [0 S16 A64])) 98 
{*movtf_insn_sp32} (insn_list 9 (nil))
    (expr_list:REG_DEAD (reg/f:SI 111)
        (nil)))

(reg/v:TF 109 [ W ]) doesn't get a hard-reg so reload needs to fix up a move 
between two MEMs with TFmode.  %o2 is selected as the reload register and 
the insn loading the register is emitted without further ado since the 
address is generically valid.


This appears to be a limitation of the reload pass, as the SPARC back-end 
already has provisions to dealt with it in a very similar case, the REG+REG 
address form which is not offsettable either:

	  /* We prohibit REG + REG for TFmode when there are no instructions
	     which accept REG+REG instructions.  We do this because REG+REG
 	     is not an offsetable address.  If we get the situation in reload
 	     where source and destination of a movtf pattern are both MEMs with
 	     REG+REG address, then only one of them gets converted to an
 	     offsetable address.  */

So I think it is reasonable to prohibit LO_SUM for TFmode too, when LO_SUM is 
not offsettable.  Note that the testcase doesn't ICE with -mcpu=v8 because 
LO_SUM is already rejected in this case, and actually doubly rejected since 
input_operand and legitimate_address_p contain redundant code.

Bootstrapped/regtested on sparc64-sun-solaris2.9 and sparc-sun-solaris2.8, 
applied to mainline and 3.4 branch.


2004-10-08  Eric Botcazou  <ebotcazou@libertysurf.fr>

	PR target/17245
	* config/sparc/sparc.c (input_operand): Remove redundant code
	for handling LO_SUM.
	(legitimate_address_p) <REG+REG>: Do not recheck TARGET_V9.
	<LO_SUM>: If LO_SUM is offsettable, accept it for TFmode on V9.
	Otherwise only accept it for TFmode if quad move insns are available.


2004-10-08  Christian Ehrhardt  <ehrhardt@mathematik.uni-ulm.de>

	* gcc.dg/ultrasp11.c: New test.


-- 
Eric Botcazou
Index: config/sparc/sparc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.c,v
retrieving revision 1.271.4.20
diff -u -p -r1.271.4.20 sparc.c
--- config/sparc/sparc.c	17 Jul 2004 21:18:57 -0000	1.271.4.20
+++ config/sparc/sparc.c	8 Oct 2004 13:16:02 -0000
@@ -1315,23 +1315,7 @@ input_operand (rtx op, enum machine_mode
 
   /* Check for valid MEM forms.  */
   if (GET_CODE (op) == MEM)
-    {
-      rtx inside = XEXP (op, 0);
-
-      if (GET_CODE (inside) == LO_SUM)
-	{
-	  /* We can't allow these because all of the splits
-	     (eventually as they trickle down into DFmode
-	     splits) require offsettable memory references.  */
-	  if (! TARGET_V9
-	      && GET_MODE (op) == TFmode)
-	    return 0;
-
-	  return (register_operand (XEXP (inside, 0), Pmode)
-		  && CONSTANT_P (XEXP (inside, 1)));
-	}
-      return memory_address_p (mode, inside);
-    }
+    return memory_address_p (mode, XEXP (op, 0));
 
   return 0;
 }
@@ -3374,15 +3358,14 @@ legitimate_address_p (enum machine_mode 
       else if ((REG_P (rs1) || GET_CODE (rs1) == SUBREG)
 	       && (REG_P (rs2) || GET_CODE (rs2) == SUBREG))
 	{
-	  /* We prohibit REG + REG for TFmode when there are no instructions
-	     which accept REG+REG instructions.  We do this because REG+REG
-	     is not an offsetable address.  If we get the situation in reload
+	  /* We prohibit REG + REG for TFmode when there are no quad move insns
+	     and we consequently need to split.  We do this because REG+REG
+	     is not an offsettable address.  If we get the situation in reload
 	     where source and destination of a movtf pattern are both MEMs with
 	     REG+REG address, then only one of them gets converted to an
-	     offsetable address.  */
+	     offsettable address.  */
 	  if (mode == TFmode
-	      && !(TARGET_FPU && TARGET_ARCH64 && TARGET_V9
-		   && TARGET_HARD_QUAD))
+	      && ! (TARGET_FPU && TARGET_ARCH64 && TARGET_HARD_QUAD))
 	    return 0;
 
 	  /* We prohibit REG + REG on ARCH32 if not optimizing for
@@ -3415,10 +3398,25 @@ legitimate_address_p (enum machine_mode 
       if (! CONSTANT_P (imm1) || tls_symbolic_operand (rs1))
 	return 0;
 
-      /* We can't allow TFmode, because an offset greater than or equal to the
-         alignment (8) may cause the LO_SUM to overflow if !v9.  */
-      if (mode == TFmode && !TARGET_V9)
-	return 0;
+      if (USE_AS_OFFSETABLE_LO10)
+	{
+	  /* We can't allow TFmode, because an offset greater than or equal to
+	     the alignment (8) may cause the LO_SUM to overflow if !v9.  */
+	  if (mode == TFmode && ! TARGET_V9)
+	    return 0;
+	}
+      else
+        {
+	  /* We prohibit LO_SUM for TFmode when there are no quad move insns
+	     and we consequently need to split.  We do this because LO_SUM
+	     is not an offsettable address.  If we get the situation in reload
+	     where source and destination of a movtf pattern are both MEMs with
+	     LO_SUM address, then only one of them gets converted to an
+	     offsettable address.  */
+	  if (mode == TFmode
+	      && ! (TARGET_FPU && TARGET_ARCH64 && TARGET_HARD_QUAD))
+	    return 0;
+	}
     }
   else if (GET_CODE (addr) == CONST_INT && SMALL_INT (addr))
     return 1;
/* PR target/17245 */
/* Origin: <aaronw@net.com> */
/* Testcase by Christian Ehrhardt <ehrhardt@mathematik.uni-ulm.de> */
/* { dg-do compile { target sparc*-*-* } } */
/* { dg-options "-O -mcpu=v9" } */

/* This used to fail on 32-bit Ultrasparc because reload was emitting
   a move insn that doesn't satisfy its constraints.  */

int n; 
double range ;
double bin ;
double wmean;

double f ()
{
  int i ;
  long double W = 0 ;
  for ( i = 0 ; i < n ; i ++) {
    double xi = range;
    double wi = bin;
    W += wi ;
    wmean += ( xi - wmean) * ( wi / W);
  }
}

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