This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR c/8281 (Sparc)
- From: Eric Botcazou <ebotcazou at libertysurf dot fr>
- To: gcc-patches at gcc dot gnu dot org
- Cc: "David S. Miller" <davem at redhat dot com>
- Date: Wed, 26 Mar 2003 01:05:59 +0100
- Subject: [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;
}