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


Disconnecting the splitter from the insn is the primary fix for this bug,
since with an X constraint, the operand will no longer match the insn.

But I also noticed that almost all of the copysign uses in the given 
Fortran sample used constant first operands, and we can do a bit better
by special casing that.

Tested on i686-linux (and a build of LAPACK with -mfpmath=sse), and
on x86_64-linux (without a build of LAPACK).


r~


        PR target/19700
        * config/i386/i386.c (ix86_expand_copysign): New.
        (ix86_split_copysign_const): New.
        (ix86_split_copysign_var): Rename from ix86_split_copysign,
        rearrange op1/nmask operands.
        * config/i386/i386-protos.h: Update.
        * config/i386/i386.md (copysignsf3): Use ix86_expand_copysign.
        (copysigndf3): Likewise.
        (copysignsf3_const, copysigndf3_const): New.
        (copysignsf3_var): Rename from copysignsf3, split out splitter
        and fix split predicate for X constraint.
        (copysigndf3_var): Similarly.

Index: config/i386/i386-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386-protos.h,v
retrieving revision 1.129
diff -u -p -d -r1.129 i386-protos.h
--- config/i386/i386-protos.h	28 Jan 2005 00:55:00 -0000	1.129
+++ config/i386/i386-protos.h	30 Jan 2005 17:41:33 -0000
@@ -139,7 +139,9 @@ extern void ix86_expand_unary_operator (
 extern rtx ix86_build_signbit_mask (enum machine_mode, bool, bool);
 extern void ix86_expand_fp_absneg_operator (enum rtx_code, enum machine_mode,
 					    rtx[]);
-extern void ix86_split_copysign (rtx []);
+extern void ix86_expand_copysign (rtx []);
+extern void ix86_split_copysign_const (rtx []);
+extern void ix86_split_copysign_var (rtx []);
 extern int ix86_unary_operator_ok (enum rtx_code, enum machine_mode, rtx[]);
 extern int ix86_match_ccmode (rtx, enum machine_mode);
 extern rtx ix86_expand_compare (enum rtx_code, rtx *, rtx *);
Index: config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.792
diff -u -p -d -r1.792 i386.c
--- config/i386/i386.c	28 Jan 2005 09:16:50 -0000	1.792
+++ config/i386/i386.c	30 Jan 2005 17:41:36 -0000
@@ -8117,10 +8117,92 @@ ix86_expand_fp_absneg_operator (enum rtx
     emit_move_insn (operands[0], dst);
 }
 
-/* Deconstruct a copysign operation into bit masks.  */
+/* Expand a copysign operation.  Special case operand 0 being a constant.  */
 
 void
-ix86_split_copysign (rtx operands[])
+ix86_expand_copysign (rtx operands[])
+{
+  enum machine_mode mode, vmode;
+  rtx dest, op0, op1, mask, nmask;
+
+  dest = operands[0];
+  op0 = operands[1];
+  op1 = operands[2];
+
+  mode = GET_MODE (dest);
+  vmode = mode == SFmode ? V4SFmode : V2DFmode;
+
+  if (GET_CODE (op0) == CONST_DOUBLE)
+    {
+      rtvec v;
+
+      if (real_isneg (CONST_DOUBLE_REAL_VALUE (op0)))
+	op0 = simplify_unary_operation (ABS, mode, op0, mode);
+
+      if (op0 == CONST0_RTX (mode))
+	op0 = CONST0_RTX (vmode);
+      else
+        {
+	  if (mode == SFmode)
+	    v = gen_rtvec (4, op0, CONST0_RTX (SFmode),
+                           CONST0_RTX (SFmode), CONST0_RTX (SFmode));
+	  else
+	    v = gen_rtvec (2, op0, CONST0_RTX (DFmode));
+          op0 = force_reg (vmode, gen_rtx_CONST_VECTOR (vmode, v));
+	}
+
+      mask = ix86_build_signbit_mask (mode, 0, 0);
+
+      if (mode == SFmode)
+	emit_insn (gen_copysignsf3_const (dest, op0, op1, mask));
+      else
+	emit_insn (gen_copysigndf3_const (dest, op0, op1, mask));
+    }
+  else
+    {
+      nmask = ix86_build_signbit_mask (mode, 0, 1);
+      mask = ix86_build_signbit_mask (mode, 0, 0);
+
+      if (mode == SFmode)
+	emit_insn (gen_copysignsf3_var (dest, NULL, op0, op1, nmask, mask));
+      else
+	emit_insn (gen_copysigndf3_var (dest, NULL, op0, op1, nmask, mask));
+    }
+}
+
+/* Deconstruct a copysign operation into bit masks.  Operand 0 is known to
+   be a constant, and so has already been expanded into a vector constant.  */
+
+void
+ix86_split_copysign_const (rtx operands[])
+{
+  enum machine_mode mode, vmode;
+  rtx dest, op0, op1, mask, x;
+
+  dest = operands[0];
+  op0 = operands[1];
+  op1 = operands[2];
+  mask = operands[3];
+
+  mode = GET_MODE (dest);
+  vmode = GET_MODE (mask);
+
+  dest = simplify_gen_subreg (vmode, dest, mode, 0);
+  x = gen_rtx_AND (vmode, dest, mask);
+  emit_insn (gen_rtx_SET (VOIDmode, dest, x));
+
+  if (op0 != CONST0_RTX (vmode))
+    {
+      x = gen_rtx_IOR (vmode, dest, op0);
+      emit_insn (gen_rtx_SET (VOIDmode, dest, x));
+    }
+}
+
+/* Deconstruct a copysign operation into bit masks.  Operand 0 is variable,
+   so we have to do two masks.  */
+
+void
+ix86_split_copysign_var (rtx operands[])
 {
   enum machine_mode mode, vmode;
   rtx dest, scratch, op0, op1, mask, nmask, x;
@@ -8128,8 +8210,8 @@ ix86_split_copysign (rtx operands[])
   dest = operands[0];
   scratch = operands[1];
   op0 = operands[2];
-  nmask = operands[3];
-  op1 = operands[4];
+  op1 = operands[3];
+  nmask = operands[4];
   mask = operands[5];
 
   mode = GET_MODE (dest);
Index: config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.615
diff -u -p -d -r1.615 i386.md
--- config/i386/i386.md	30 Jan 2005 03:14:44 -0000	1.615
+++ config/i386/i386.md	30 Jan 2005 17:41:39 -0000
@@ -9452,34 +9452,56 @@
   "#")
 
 (define_expand "copysignsf3"
-  [(parallel [(set (match_operand:SF 0 "register_operand" "")
-		   (unspec:SF [(match_operand:SF 1 "register_operand" "")
-			       (match_dup 4)
-			       (match_operand:SF 2 "register_operand" "")
-			       (match_dup 5)]
-			      UNSPEC_COPYSIGN))
-	      (clobber (match_scratch:V4SF 3 ""))])]
+  [(match_operand:SF 0 "register_operand" "")
+   (match_operand:SF 1 "nonmemory_operand" "")
+   (match_operand:SF 2 "register_operand" "")]
   "TARGET_SSE_MATH"
 {
-  operands[4] = ix86_build_signbit_mask (SFmode, 0, 1);
-  operands[5] = ix86_build_signbit_mask (SFmode, 0, 0);
+  ix86_expand_copysign (operands);
+  DONE;
 })
 
-(define_insn_and_split "*copysignsf3"
+(define_insn_and_split "copysignsf3_const"
+  [(set (match_operand:SF 0 "register_operand"          "=x")
+	(unspec:SF
+	  [(match_operand:V4SF 1 "vector_move_operand"  "xmC")
+	   (match_operand:SF 2 "register_operand"       "0")
+	   (match_operand:V4SF 3 "nonimmediate_operand" "xm")]
+	  UNSPEC_COPYSIGN))]
+  "TARGET_SSE_MATH"
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
+{
+  ix86_split_copysign_const (operands);
+  DONE;
+})
+
+(define_insn "copysignsf3_var"
   [(set (match_operand:SF 0 "register_operand"          "=x, x, x, x,x")
 	(unspec:SF
 	  [(match_operand:SF 2 "register_operand"       " x, 0, 0, x,x")
-	   (match_operand:V4SF 3 "nonimmediate_operand" " X,xm,xm, 0,0")
-	   (match_operand:SF 4 "register_operand"       " 1, 1, x, 1,x")
+	   (match_operand:SF 3 "register_operand"       " 1, 1, x, 1,x")
+	   (match_operand:V4SF 4 "nonimmediate_operand" " X,xm,xm, 0,0")
 	   (match_operand:V4SF 5 "nonimmediate_operand" " 0,xm, 1,xm,1")]
 	  UNSPEC_COPYSIGN))
    (clobber (match_scratch:V4SF 1			"=x, x, x, x,x"))]
   "TARGET_SSE_MATH"
-  "#"
-  "&& reload_completed"
+  "#")
+
+(define_split
+  [(set (match_operand:SF 0 "register_operand" "")
+	(unspec:SF
+	  [(match_operand:SF 2 "register_operand" "")
+	   (match_operand:SF 3 "register_operand" "")
+	   (match_operand:V4SF 4 "" "")
+	   (match_operand:V4SF 5 "" "")]
+	  UNSPEC_COPYSIGN))
+   (clobber (match_scratch:V4SF 1 ""))]
+  "TARGET_SSE_MATH && reload_completed"
   [(const_int 0)]
 {
-  ix86_split_copysign (operands);
+  ix86_split_copysign_var (operands);
   DONE;
 })
 
@@ -9526,34 +9548,56 @@
   "#")
 
 (define_expand "copysigndf3"
-  [(parallel [(set (match_operand:DF 0 "register_operand" "")
-		   (unspec:DF [(match_operand:DF 1 "register_operand" "")
-			       (match_dup 4)
-			       (match_operand:DF 2 "register_operand" "")
-			       (match_dup 5)]
-			      UNSPEC_COPYSIGN))
-	      (clobber (match_scratch:V2DF 3 ""))])]
+  [(match_operand:DF 0 "register_operand" "")
+   (match_operand:DF 1 "nonmemory_operand" "")
+   (match_operand:DF 2 "register_operand" "")]
   "TARGET_SSE2 && TARGET_SSE_MATH"
 {
-  operands[4] = ix86_build_signbit_mask (DFmode, 0, 1);
-  operands[5] = ix86_build_signbit_mask (DFmode, 0, 0);
+  ix86_expand_copysign (operands);
+  DONE;
 })
 
-(define_insn_and_split "*copysigndf3"
+(define_insn_and_split "copysigndf3_const"
+  [(set (match_operand:DF 0 "register_operand"          "=x")
+	(unspec:DF
+	  [(match_operand:V2DF 1 "vector_move_operand"  "xmC")
+	   (match_operand:DF 2 "register_operand"       "0")
+	   (match_operand:V2DF 3 "nonimmediate_operand" "xm")]
+	  UNSPEC_COPYSIGN))]
+  "TARGET_SSE2 && TARGET_SSE_MATH"
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
+{
+  ix86_split_copysign_const (operands);
+  DONE;
+})
+
+(define_insn "copysigndf3_var"
   [(set (match_operand:DF 0 "register_operand"          "=x, x, x, x,x")
 	(unspec:DF
 	  [(match_operand:DF 2 "register_operand"       " x, 0, 0, x,x")
-	   (match_operand:V2DF 3 "nonimmediate_operand" " X,xm,xm, 0,0")
-	   (match_operand:DF 4 "register_operand"       " 1, 1, x, 1,x")
+	   (match_operand:DF 3 "register_operand"       " 1, 1, x, 1,x")
+	   (match_operand:V2DF 4 "nonimmediate_operand" " X,xm,xm, 0,0")
 	   (match_operand:V2DF 5 "nonimmediate_operand" " 0,xm, 1,xm,1")]
 	  UNSPEC_COPYSIGN))
    (clobber (match_scratch:V2DF 1			"=x, x, x, x,x"))]
   "TARGET_SSE2 && TARGET_SSE_MATH"
-  "#"
-  "&& reload_completed"
+  "#")
+
+(define_split
+  [(set (match_operand:DF 0 "register_operand" "")
+	(unspec:DF
+	  [(match_operand:DF 2 "register_operand" "")
+	   (match_operand:DF 3 "register_operand" "")
+	   (match_operand:V2DF 4 "" "")
+	   (match_operand:V2DF 5 "" "")]
+	  UNSPEC_COPYSIGN))
+   (clobber (match_scratch:V2DF 1 ""))]
+  "TARGET_SSE2 && TARGET_SSE_MATH && reload_completed"
   [(const_int 0)]
 {
-  ix86_split_copysign (operands);
+  ix86_split_copysign_var (operands);
   DONE;
 })
 


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