re PR target/19700 (ICE in final_scan_insn with O1 -g -march=athlon-xp -mfpmath=sse)
authorRichard Henderson <rth@redhat.com>
Sun, 30 Jan 2005 17:48:01 +0000 (09:48 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Sun, 30 Jan 2005 17:48:01 +0000 (09:48 -0800)
        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.

From-SVN: r94442

gcc/ChangeLog
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.md

index ac4c2b1..ba3e1fb 100644 (file)
@@ -1,3 +1,18 @@
+2005-01-30  Richard Henderson  <rth@redhat.com>
+
+       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.
+
 2005-01-30  Kazu Hirata  <kazu@cs.umass.edu>
 
        * optabs.c, doc/c-tree.texi, doc/install.texi, doc/md.texi,
index fcbb822..feacd2d 100644 (file)
@@ -139,7 +139,9 @@ extern void ix86_expand_unary_operator (enum rtx_code, enum machine_mode,
 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 8508cd8..4b6b3f2 100644 (file)
@@ -8117,10 +8117,92 @@ ix86_expand_fp_absneg_operator (enum rtx_code code, enum machine_mode mode,
     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 21134d6..4f8d310 100644 (file)
   "#")
 
 (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;
 })
 
   "#")
 
 (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;
 })