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 target/6753


Hi!

This following testcase was miscompiled when using SSE/SSE2.
The problem is that sse_mov?fcc_const0_? patterns lack of earlyclobber,
so if reload decided to:
%xmm0 = %xmm0 > something ? %xmm0 : 0.;
we are in big trouble, as the splitter splits this into:
%xmm0 = %xmm0 > something;
%xmm0 = %xmm0 & %xmm0;
which is 0 or NaN (0xffffffff resp. 0xffffffffffffffff).
While at it, I've noticed that there is a pasto, all sse_movdfcc_const0_
patterns were copied from sse_movsfcc_const0_ patterns with only sf->df
and TARGET_SSE->TARGET_SSE2 changes, using :SF all around, thus for -msse2
duplicates of sse_movsfcc_ patterns.
Also, I think it is clearer to use Y constaints than x in TARGET_SSE2
patterns.
I've added a check for op2 == op3 in the generic SSE sse_mov?fcc splitter,
so that in case GCC ever doesn't optimize it out, we ICE instead of silently
emitting incorrect code. Alternatively, we could optimize the comparison out
and just change it into movsf/movdf.

Bootstrap on i386 pending, ok to commit?
3.1.1 too?
Dunno what to do with the testcase, as it needs to be run on pentium3+.
Any ideas?

/* PR target/6753
   This testcase was miscompiled because sse_mov?fcc_const0*
   patterns were missing earlyclobber.  */
/* { dg-do run { target i686-*-* } } */
/* { dg-options "-march=pentium3 -msse -ffast-math -O2" } */

extern void abort (void);
extern void exit (int);

float one = 1.f;

void bar (float f)
{
  if (__builtin_memcmp (&one, &f, sizeof (float)))
    abort ();
}

float foo (void)
{
  return 1.f;
}

typedef struct
{
  float t;
} T;

int main (void)
{
  int i;
  T x[1];

  for (i = 0; i < 1; i++)
    {
      x[i].t = foo ();
      x[i].t = 0.f > x[i].t ? 0.f : x[i].t;
      bar (x[i].t);
    }

  exit (0);
}

2002-05-22  Jakub Jelinek  <jakub@redhat.com>

	PR target/6753
	* config/i386/i386.md (sse_movdfcc, sse_movdfcc_eq): Use Y instead
	of x in constraints for clarity.
	(sse_mov?fcc split): abort if op2 == op3.
	(sse_movsfcc_const0_1, sse_movsfcc_const0_2, sse_movsfcc_const0_3,
	sse_movsfcc_const0_4): Add earlyclobber.
	(sse_movdfcc_const0_1, sse_movdfcc_const0_2, sse_movdfcc_const0_3,
	sse_movdfcc_const0_4): Likewise.  Use DFmode, not SFmode.
	Use Y instead of x in constraints.

--- gcc/config/i386/i386.md.jj	Tue May 21 20:23:32 2002
+++ gcc/config/i386/i386.md	Wed May 22 16:53:14 2002
@@ -16576,12 +16576,12 @@
   "#")
 
 (define_insn "sse_movdfcc"
-  [(set (match_operand:DF 0 "register_operand" "=&x#rf,x#rf,?f#xr,?f#xr,?f#xr,?f#xr,?r#xf,?r#xf,?r#xf,?r#xf")
+  [(set (match_operand:DF 0 "register_operand" "=&Y#rf,Y#rf,?f#Yr,?f#Yr,?f#Yr,?f#Yr,?r#Yf,?r#Yf,?r#Yf,?r#Yf")
 	(if_then_else:DF (match_operator 1 "sse_comparison_operator"
-			[(match_operand:DF 4 "nonimmediate_operand" "0#fx,x#fx,f#x,f#x,xm#f,xm#f,f#x,f#x,xm#f,xm#f")
-			 (match_operand:DF 5 "nonimmediate_operand" "xm#f,xm#f,f#x,f#x,x#f,x#f,f#x,f#x,x#f,x#f")])
-		      (match_operand:DF 2 "nonimmediate_operand" "x#fr,0#fr,f#fx,0#fx,f#fx,0#fx,rm#rx,0#rx,rm#rx,0#rx")
-		      (match_operand:DF 3 "nonimmediate_operand" "x#fr,x#fr,0#fx,f#fx,0#fx,f#fx,0#fx,rm#rx,0#rx,rm#rx")))
+			[(match_operand:DF 4 "nonimmediate_operand" "0#fY,Y#fY,f#Y,f#Y,Ym#f,Ym#f,f#Y,f#Y,Ym#f,Ym#f")
+			 (match_operand:DF 5 "nonimmediate_operand" "Ym#f,Ym#f,f#Y,f#Y,Y#f,Y#f,f#Y,f#Y,Y#f,Y#f")])
+		      (match_operand:DF 2 "nonimmediate_operand" "Y#fr,0#fr,f#fY,0#fY,f#fY,0#fY,rm#rY,0#rY,rm#rY,0#rY")
+		      (match_operand:DF 3 "nonimmediate_operand" "Y#fr,Y#fr,0#fY,f#fY,0#fY,f#fY,0#fY,rm#rY,0#rY,rm#rY")))
    (clobber (match_scratch:DF 6 "=2,&4,X,X,X,X,X,X,X,X"))
    (clobber (reg:CC 17))]
   "TARGET_SSE2
@@ -16591,11 +16591,11 @@
   "#")
 
 (define_insn "sse_movdfcc_eq"
-  [(set (match_operand:DF 0 "register_operand" "=&x#rf,x#rf,?f#xr,?f#xr,?r#xf,?r#xf")
-	(if_then_else:DF (eq (match_operand:DF 3 "nonimmediate_operand" "%0#fx,x#fx,f#x,xm#f,f#x,xm#f")
-			     (match_operand:DF 4 "nonimmediate_operand" "xm#f,xm#f,f#x,x#f,f#x,x#f"))
-		      (match_operand:DF 1 "nonimmediate_operand" "x#fr,0#fr,0#fx,0#fx,0#rx,0#rx")
-		      (match_operand:DF 2 "nonimmediate_operand" "x#fr,x#fr,f#fx,f#fx,rm#rx,rm#rx")))
+  [(set (match_operand:DF 0 "register_operand" "=&Y#rf,Y#rf,?f#Yr,?f#Yr,?r#Yf,?r#Yf")
+	(if_then_else:DF (eq (match_operand:DF 3 "nonimmediate_operand" "%0#fY,Y#fY,f#Y,Ym#f,f#Y,Ym#f")
+			     (match_operand:DF 4 "nonimmediate_operand" "Ym#f,Ym#f,f#Y,Y#f,f#Y,Y#f"))
+		      (match_operand:DF 1 "nonimmediate_operand" "Y#fr,0#fr,0#fY,0#fY,0#rY,0#rY")
+		      (match_operand:DF 2 "nonimmediate_operand" "Y#fr,Y#fr,f#fY,f#fY,rm#rY,rm#rY")))
    (clobber (match_scratch:DF 5 "=1,&3,X,X,X,X"))
    (clobber (reg:CC 17))]
   "TARGET_SSE
@@ -16647,6 +16647,10 @@
    (set (subreg:TI (match_dup 0) 0) (ior:TI (subreg:TI (match_dup 6) 0)
 					    (subreg:TI (match_dup 7) 0)))]
 {
+  /* If op2 == op3, op3 will be clobbered before it is used.
+     This should be optimized out though.  */
+  if (operands_match_p (operands[2], operands[3]))
+    abort ();
   PUT_MODE (operands[1], GET_MODE (operands[0]));
   if (operands_match_p (operands[0], operands[4]))
     operands[6] = operands[4], operands[7] = operands[2];
@@ -16658,7 +16662,7 @@
 ;; Do not brother with the integer/floating point case, since these are
 ;; bot considerably slower, unlike in the generic case.
 (define_insn "*sse_movsfcc_const0_1"
-  [(set (match_operand:SF 0 "register_operand" "=x")
+  [(set (match_operand:SF 0 "register_operand" "=&x")
 	(if_then_else:SF (match_operator 1 "sse_comparison_operator"
 			[(match_operand:SF 4 "register_operand" "0")
 			 (match_operand:SF 5 "nonimmediate_operand" "xm")])
@@ -16668,7 +16672,7 @@
   "#")
 
 (define_insn "*sse_movsfcc_const0_2"
-  [(set (match_operand:SF 0 "register_operand" "=x")
+  [(set (match_operand:SF 0 "register_operand" "=&x")
 	(if_then_else:SF (match_operator 1 "sse_comparison_operator"
 			[(match_operand:SF 4 "register_operand" "0")
 			 (match_operand:SF 5 "nonimmediate_operand" "xm")])
@@ -16678,7 +16682,7 @@
   "#")
 
 (define_insn "*sse_movsfcc_const0_3"
-  [(set (match_operand:SF 0 "register_operand" "=x")
+  [(set (match_operand:SF 0 "register_operand" "=&x")
 	(if_then_else:SF (match_operator 1 "fcmov_comparison_operator"
 			[(match_operand:SF 4 "nonimmediate_operand" "xm")
 			 (match_operand:SF 5 "register_operand" "0")])
@@ -16688,7 +16692,7 @@
   "#")
 
 (define_insn "*sse_movsfcc_const0_4"
-  [(set (match_operand:SF 0 "register_operand" "=x")
+  [(set (match_operand:SF 0 "register_operand" "=&x")
 	(if_then_else:SF (match_operator 1 "fcmov_comparison_operator"
 			[(match_operand:SF 4 "nonimmediate_operand" "xm")
 			 (match_operand:SF 5 "register_operand" "0")])
@@ -16698,42 +16702,42 @@
   "#")
 
 (define_insn "*sse_movdfcc_const0_1"
-  [(set (match_operand:SF 0 "register_operand" "=x")
-	(if_then_else:SF (match_operator 1 "sse_comparison_operator"
-			[(match_operand:SF 4 "register_operand" "0")
-			 (match_operand:SF 5 "nonimmediate_operand" "xm")])
-		      (match_operand:SF 2 "register_operand" "x")
-		      (match_operand:SF 3 "const0_operand" "X")))]
+  [(set (match_operand:DF 0 "register_operand" "=&Y")
+	(if_then_else:DF (match_operator 1 "sse_comparison_operator"
+			[(match_operand:DF 4 "register_operand" "0")
+			 (match_operand:DF 5 "nonimmediate_operand" "Ym")])
+		      (match_operand:DF 2 "register_operand" "Y")
+		      (match_operand:DF 3 "const0_operand" "X")))]
   "TARGET_SSE2"
   "#")
 
 (define_insn "*sse_movdfcc_const0_2"
-  [(set (match_operand:SF 0 "register_operand" "=x")
-	(if_then_else:SF (match_operator 1 "sse_comparison_operator"
-			[(match_operand:SF 4 "register_operand" "0")
-			 (match_operand:SF 5 "nonimmediate_operand" "xm")])
-		      (match_operand:SF 2 "const0_operand" "X")
-		      (match_operand:SF 3 "register_operand" "x")))]
+  [(set (match_operand:DF 0 "register_operand" "=&Y")
+	(if_then_else:DF (match_operator 1 "sse_comparison_operator"
+			[(match_operand:DF 4 "register_operand" "0")
+			 (match_operand:DF 5 "nonimmediate_operand" "Ym")])
+		      (match_operand:DF 2 "const0_operand" "X")
+		      (match_operand:DF 3 "register_operand" "Y")))]
   "TARGET_SSE2"
   "#")
 
 (define_insn "*sse_movdfcc_const0_3"
-  [(set (match_operand:SF 0 "register_operand" "=x")
-	(if_then_else:SF (match_operator 1 "fcmov_comparison_operator"
-			[(match_operand:SF 4 "nonimmediate_operand" "xm")
-			 (match_operand:SF 5 "register_operand" "0")])
-		      (match_operand:SF 2 "register_operand" "x")
-		      (match_operand:SF 3 "const0_operand" "X")))]
+  [(set (match_operand:DF 0 "register_operand" "=&Y")
+	(if_then_else:DF (match_operator 1 "fcmov_comparison_operator"
+			[(match_operand:DF 4 "nonimmediate_operand" "Ym")
+			 (match_operand:DF 5 "register_operand" "0")])
+		      (match_operand:DF 2 "register_operand" "Y")
+		      (match_operand:DF 3 "const0_operand" "X")))]
   "TARGET_SSE2"
   "#")
 
 (define_insn "*sse_movdfcc_const0_4"
-  [(set (match_operand:SF 0 "register_operand" "=x")
-	(if_then_else:SF (match_operator 1 "fcmov_comparison_operator"
-			[(match_operand:SF 4 "nonimmediate_operand" "xm")
-			 (match_operand:SF 5 "register_operand" "0")])
-		      (match_operand:SF 2 "const0_operand" "X")
-		      (match_operand:SF 3 "register_operand" "x")))]
+  [(set (match_operand:DF 0 "register_operand" "=&Y")
+	(if_then_else:DF (match_operator 1 "fcmov_comparison_operator"
+			[(match_operand:DF 4 "nonimmediate_operand" "Ym")
+			 (match_operand:DF 5 "register_operand" "0")])
+		      (match_operand:DF 2 "const0_operand" "X")
+		      (match_operand:DF 3 "register_operand" "Y")))]
   "TARGET_SSE2"
   "#")
 

	Jakub


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