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 c/8281 (Sparc)


Hi,

This is an ICE during compilation of Mozilla 1.0 on Ultrasparc, which 
triggers on the 3.2 branch at -O2 -fPIC, a regression from gcc 2.95.3.

The ICE was first reported as PR middle-end/7151 and fixed by David on 1st 
October but, about two weeks later, another problem (a segfault) was 
reported on the exact same line of code (it appears that no testcase was 
checked in alongside the first fix). Current 3.2.3pre ICEs again:

ultrasp7.c: In function `__ieee754_pow':
ultrasp7.c:49: insn does not satisfy its constraints:
(insn 302 300 61 (set (reg:SI 65 %f33 [110])
        (reg:SI 37 %f5 [36])) 51 {*movsi_insn} (insn_list:REG_DEP_ANTI 59 
(insn_list:REG_DEP_OUTPUT 298 (insn_list 294 (nil))))
    (nil))

ultrasp7.c:49: Internal compiler error in extract_constrain_insn_cached, at 
recog.c:2063


David's core modification was to enable DImode moves using FP registers on 
32-bit Sparc v9, which is ok since 32-bit v9 has 64-bit 'fmovd'.

@@ -2062,9 +2062,9 @@
 
 (define_insn "*movdi_insn_sp32_v9"
   [(set (match_operand:DI 0 "nonimmediate_operand"
-					"=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?f")
+					"=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?f,?e,?e,?W")
         (match_operand:DI 1 "input_operand"
-					" J,J,U,T,r,o,i,r, f, T, o, f, f"))]
+					" J,J,U,T,r,o,i,r, f, T, o, f, f, e, W, e"))]
   "! TARGET_ARCH64 && TARGET_V9
    && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
   "@

The problem is that we can now end up with DImode moves using FP registers 
after reload, which are caught by four 32-bit DImode splitters:

(define_split
  [(set (match_operand:DI 0 "register_operand" "")
        (match_operand:DI 1 "const_double_operand" ""))]

(define_split
  [(set (match_operand:DI 0 "register_operand" "")
        (match_operand:DI 1 "register_operand" ""))]

(define_split
  [(set (match_operand:DI 0 "register_operand" "")
        (match_operand:DI 1 "memory_operand" ""))]

(define_split
  [(set (match_operand:DI 0 "memory_operand" "")
        (match_operand:DI 1 "register_operand" ""))]

Now v9 doesn't support SFmode operations for the upper FP registers 
(%fp32-%fp63, REGs 64-95) so we need to disable the splitters for these 
registers.

David disabled the first splitter in his patch:

@@ -2388,7 +2392,14 @@
 (define_split
   [(set (match_operand:DI 0 "register_operand" "")
         (match_operand:DI 1 "const_double_operand" ""))]
-  "! TARGET_ARCH64 && reload_completed"
+  "reload_completed
+   && (! TARGET_V9
+       || (! TARGET_ARCH64
+           && ((GET_CODE (operands[0]) == REG
+                && REGNO (operands[0]) < 32)
+               || (GET_CODE (operands[0]) == SUBREG
+                   && GET_CODE (SUBREG_REG (operands[0])) == REG
+                   && REGNO (SUBREG_REG (operands[0])) < 32))))"
   [(clobber (const_int 0))]
 {
   emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),


The second splitter is responsible for the ICE on the testcase: it splits 

(insn 276 282 61 (set (reg/v:DI 64 %f32 [110])
        (reg:DI 36 %f4)) 58 {*movdi_insn_sp32_v9} (nil)
    (nil))

into

(insn 300 282 302 (set (reg:SI 64 %f32 [110])
        (reg:SI 36 %f4)) 51 {*movsi_insn} (insn_list 282 (nil))
    (expr_list:REG_DEAD (reg:SI 36 %f4)
        (nil)))

(insn 302 300 61 (set (reg:SI 65 %f33 [110])
        (reg:SI 37 %f5 [36])) 51 {*movsi_insn} (nil)
    (expr_list:REG_DEAD (reg:SI 37 %f5 [36])
        (nil)))

which are both invalid.


So the first part of the fix is to disable the second splitter the same way 
David disabled the first one. Then there is a new problem: the 
"movdi_insn_sp32_v9" pattern above contains a "f-f" alternative which 
expects a splitter, which we have just disabled because we use < 32 instead 
of < 64. But this "f-f" alternative is actually unnecessary since it is 
superseded by the "e-e" alternative (the 64 FP registers are equivalent in 
DFmode), so we can remove it. This is sufficient to let the testcase pass.

I think the two remaining 32-bit DI splitters can wrongly trigger for the 
odd-numbered upper FP regs too, but this would need to be confirmed.

Bootstrapped/regtested by Kaveh for sparcv9-sun-solaris2.7 on 3.2 and 3.3 
branches.

-- 
Eric Botcazou


2003-03-26  Eric Botcazou  <ebotcazou at libertysurf dot fr>

	PR c/8281
	* config/sparc/sparc.md (movdi_insn_sp32_v9): Remove 'f-f' alternative.
	(movdi reg/reg split): Match only on sparc32, and v9 when int regs.


2003-03-26  Eric Botcazou  <ebotcazou at libertysurf dot fr>

        * gcc.dg/ultrasp7.c: New test.
Index: config/sparc/sparc.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.md,v
retrieving revision 1.148.2.15.4.1
diff -u -r1.148.2.15.4.1 sparc.md
--- config/sparc/sparc.md	2 Oct 2002 03:47:05 -0000	1.148.2.15.4.1
+++ config/sparc/sparc.md	23 Mar 2003 18:40:41 -0000
@@ -2531,9 +2531,9 @@
 
 (define_insn "*movdi_insn_sp32_v9"
   [(set (match_operand:DI 0 "nonimmediate_operand"
-					"=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?f,?e,?e,?W")
+					"=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?e,?e,?W")
         (match_operand:DI 1 "input_operand"
-					" J,J,U,T,r,o,i,r, f, T, o, f, f, e, W, e"))]
+					" J,J,U,T,r,o,i,r, f, T, o, f, e, W, e"))]
   "! TARGET_ARCH64 && TARGET_V9
    && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
   "@
@@ -2549,13 +2549,12 @@
    ldd\\t%1, %0
    #
    #
-   #
    fmovd\\t%1, %0
    ldd\\t%1, %0
    std\\t%1, %0"
-  [(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,*,fpmove,fpload,fpstore")
-   (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,2,*,*,*")
-   (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,*,double,*,*")])
+  [(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,fpmove,fpload,fpstore")
+   (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,*,*,*")
+   (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,double,*,*")])
 
 (define_insn "*movdi_insn_sp32"
   [(set (match_operand:DI 0 "nonimmediate_operand"
@@ -2899,7 +2898,14 @@
 (define_split
   [(set (match_operand:DI 0 "register_operand" "")
         (match_operand:DI 1 "register_operand" ""))]
-  "! TARGET_ARCH64 && reload_completed"
+  "reload_completed
+   && (! TARGET_V9
+       || (! TARGET_ARCH64
+           && ((GET_CODE (operands[0]) == REG
+                && REGNO (operands[0]) < 32)
+               || (GET_CODE (operands[0]) == SUBREG
+                   && GET_CODE (SUBREG_REG (operands[0])) == REG
+                   && REGNO (SUBREG_REG (operands[0])) < 32))))"
   [(clobber (const_int 0))]
   "
 {
/* PR c/8281 */
/* Originator: TANIGUCHI Yasuaki <yasuaki at k8 dot dion dot ne dot jp> */
/* { dg-do compile { target sparc-*-* } } */
/* { dg-options "-O2 -mcpu=ultrasparc -fPIC" } */

static const double bp = 1.0, dp_l[] = { 0.0};

double __ieee754_pow(double x, double y)
{
  union {
    int lo;
    double d;
  }uz;

  double y1,t1,p_h,t,z;
  double z_h,z_l,p_l;
  double t2,r,s,u,v,w;
  int i = 0;
 
  double s_h,t_h;
  double s2,s_l,t_l;
 
 
  v = 1.0/(v+bp);
  uz.d = s_h = s = u*v;
  uz.lo = 0;
  s_h = uz.d;
  uz.d = t_h;
  uz.lo = 3;
  t_h = uz.d;
  s_l = v*((u-s_h*t_h)-s_h*t_l);
  s2 = s*s;
  r = s2* s2* (1.1+s2*(1.2+s2*(1.3+s2*(1.4+s2*(1.5+s2*1.6)))));
  s2 = s_h*s_h;
  uz.lo = 0;
  t_h = uz.d;
  t_l = r-((t_h-3.0)-s2);
  v = s_l*t_h+t_l*s;
  p_l = v-(p_h-u);
  z_h = bp *p_h;
  z_l = bp*p_h+p_l*1.0+dp_l[i];
  t = (double)i;
  t1 = (((bp+z_l)+bp)+t);
  t2 = z_l-(((t1-t)-bp)-z_h);
  p_l = (y-y1)*t1+y*t2;
  z = p_l+p_h;

  return s*z;
}

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