i386-protos.h (ix86_split_fp_absneg_operator): New prototype.
authorUros Bizjak <ubizjak@gmail.com>
Mon, 10 Jun 2019 19:17:57 +0000 (21:17 +0200)
committerUros Bizjak <uros@gcc.gnu.org>
Mon, 10 Jun 2019 19:17:57 +0000 (21:17 +0200)
* config/i386/i386-protos.h (ix86_split_fp_absneg_operator):
New prototype.
* config/i386/i386-expand.c (ix86_expand_fp_absneg_operator):
Emit clobber also for non-sse operations.
(ix86_split_fp_absneg_operator): New function.
* config/i386/i386.md (SSEMODEF): New mode iterator.
(ssevecmodef): New mode attribute.
(<code>tf2): Use absneg code iterator.
(*<code>tf2_1): Rename from *absnegtf3_sse. Use absneg code iterator.
Add three-operand AVX alternatives.
(*<code><mode>2_i387_1): Rename from *absnegxf2_i387.
Use absneg code iterator and X87MODEF mode iterator.
(absneg fp_reg non-sse splitter): Call absneg code iterator
and X87MODEF mode iterator.
(absneg general_reg non-sse splitter): Use absneg code iterator
and X87MODEF mode iterator.  Use ix86_split_fp_absneg_operator.
(*<code><mode>2_1): Rename from *absneg<mode>2.  Use absneg
code iterator.  Add three-operand AVX alternative.
(absneg sse_reg splitter): Use absneg code iterator
and SSEMODEF mode iterator.  Handle AVX operands.
(absneg fp_reg splitter): Use absneg code iterator
and MODEF mode iterator.
(absneg general_reg splitter): Merge splitters using MODEF mode
iterator.  Use absneg code iterator.  Call
ix86_split_fp_absneg_operator.
(*<code><mode>2_i387): Rename from *<code><mode>2_1.
Do not enable for non-sse modes before reload.
(CSGNMODE): Remove.
(CSGNVMODE): Ditto.
(copysing<mode>3): Use SSEMODEF instead of CSGNMODE and
ssevecmodef mode attribute instaed of CSGNVMODE.
(copysign<mode>3_const): Ditto.
(copysign<mode>3_var): Ditto.
* config/i386/i386.md (*<code><mode>2): Rename from *absneg<mode>2.
Use absneg code iterator.  Simplify code using std::swap.
* config/i386/predicates.md (absneg_operator): Remove.

From-SVN: r272123

gcc/ChangeLog
gcc/config/i386/i386-expand.c
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.md
gcc/config/i386/predicates.md
gcc/config/i386/sse.md

index 9327d97..a479644 100644 (file)
@@ -1,3 +1,42 @@
+2019-06-10  Uroš Bizjak  <ubizjak@gmail.com>
+
+       * config/i386/i386-protos.h (ix86_split_fp_absneg_operator):
+       New prototype.
+       * config/i386/i386-expand.c (ix86_expand_fp_absneg_operator):
+       Emit clobber also for non-sse operations.
+       (ix86_split_fp_absneg_operator): New function.
+       * config/i386/i386.md (SSEMODEF): New mode iterator.
+       (ssevecmodef): New mode attribute.
+       (<code>tf2): Use absneg code iterator.
+       (*<code>tf2_1): Rename from *absnegtf3_sse. Use absneg code iterator.
+       Add three-operand AVX alternatives.
+       (*<code><mode>2_i387_1): Rename from *absnegxf2_i387.
+       Use absneg code iterator and X87MODEF mode iterator.
+       (absneg fp_reg non-sse splitter): Call absneg code iterator
+       and X87MODEF mode iterator.
+       (absneg general_reg non-sse splitter): Use absneg code iterator
+       and X87MODEF mode iterator.  Use ix86_split_fp_absneg_operator.
+       (*<code><mode>2_1): Rename from *absneg<mode>2.  Use absneg
+       code iterator.  Add three-operand AVX alternative.
+       (absneg sse_reg splitter): Use absneg code iterator
+       and SSEMODEF mode iterator.  Handle AVX operands.
+       (absneg fp_reg splitter): Use absneg code iterator
+       and MODEF mode iterator.
+       (absneg general_reg splitter): Merge splitters using MODEF mode
+       iterator.  Use absneg code iterator.  Call
+       ix86_split_fp_absneg_operator.
+       (*<code><mode>2_i387): Rename from *<code><mode>2_1.
+       Do not enable for non-sse modes before reload.
+       (CSGNMODE): Remove.
+       (CSGNVMODE): Ditto.
+       (copysing<mode>3): Use SSEMODEF instead of CSGNMODE and
+       ssevecmodef mode attribute instaed of CSGNVMODE.
+       (copysign<mode>3_const): Ditto.
+       (copysign<mode>3_var): Ditto.
+       * config/i386/i386.md (*<code><mode>2): Rename from *absneg<mode>2.
+       Use absneg code iterator.  Simplify code using std::swap.
+       * config/i386/predicates.md (absneg_operator): Remove.
+
 2019-06-10  Martin Sebor  <msebor@redhat.com>
 
        * gimple-fold.c (get_range_strlen): Update comment that didn't
index 9791453..0585c7d 100644 (file)
@@ -1704,10 +1704,11 @@ void
 ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode,
                                rtx operands[])
 {
-  rtx mask, set, dst, src;
+  rtx set, dst, src;
   bool use_sse = false;
   bool vector_mode = VECTOR_MODE_P (mode);
   machine_mode vmode = mode;
+  rtvec par;
 
   if (vector_mode)
     use_sse = true;
@@ -1722,24 +1723,19 @@ ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode,
        vmode = V2DFmode;
     }
 
-  /* NEG and ABS performed with SSE use bitwise mask operations.
-     Create the appropriate mask now.  */
-  if (use_sse)
-    mask = ix86_build_signbit_mask (vmode, vector_mode, code == ABS);
-  else
-    mask = NULL_RTX;
-
   dst = operands[0];
   src = operands[1];
 
   set = gen_rtx_fmt_e (code, mode, src);
   set = gen_rtx_SET (dst, set);
 
-  if (mask)
+  if (use_sse)
     {
-      rtx use, clob;
-      rtvec par;
+      rtx mask, use, clob;
 
+      /* NEG and ABS performed with SSE use bitwise mask operations.
+        Create the appropriate mask now.  */
+      mask = ix86_build_signbit_mask (vmode, vector_mode, code == ABS);
       use = gen_rtx_USE (VOIDmode, mask);
       if (vector_mode)
        par = gen_rtvec (2, set, use);
@@ -1748,10 +1744,104 @@ ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode,
           clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
          par = gen_rtvec (3, set, use, clob);
         }
-      emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
     }
   else
-    emit_insn (set);
+    {
+      rtx clob;
+
+      /* Changing of sign for FP values is doable using integer unit too.  */
+      clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
+      par = gen_rtvec (2, set, clob);
+    }
+
+  emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
+}
+
+/* Deconstruct a floating point ABS or NEG operation
+   with integer registers into integer operations.  */
+
+void
+ix86_split_fp_absneg_operator (enum rtx_code code, machine_mode mode,
+                              rtx operands[])
+{
+  enum rtx_code absneg_op;
+  rtx dst, set;
+
+  gcc_assert (operands_match_p (operands[0], operands[1]));
+
+  switch (mode)
+    {
+    case E_SFmode:
+      dst = gen_lowpart (SImode, operands[0]);
+
+      if (code == ABS)
+       {
+         set = gen_int_mode (0x7fffffff, SImode);
+         absneg_op = AND;
+       }
+      else
+       {
+         set = gen_int_mode (0x80000000, SImode);
+         absneg_op = XOR;
+       }
+      set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
+      break;
+
+    case E_DFmode:
+      if (TARGET_64BIT)
+       {
+         dst = gen_lowpart (DImode, operands[0]);
+         dst = gen_rtx_ZERO_EXTRACT (DImode, dst, const1_rtx, GEN_INT (63));
+
+         if (code == ABS)
+           set = const0_rtx;
+         else
+           set = gen_rtx_NOT (DImode, dst);
+       }
+      else
+       {
+         dst = gen_highpart (SImode, operands[0]);
+
+         if (code == ABS)
+           {
+             set = gen_int_mode (0x7fffffff, SImode);
+             absneg_op = AND;
+           }
+         else
+           {
+             set = gen_int_mode (0x80000000, SImode);
+             absneg_op = XOR;
+           }
+         set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
+       }
+      break;
+
+    case E_XFmode:
+      dst = gen_rtx_REG (SImode,
+                        REGNO (operands[0]) + (TARGET_64BIT ? 1 : 2));
+      if (code == ABS)
+       {
+         set = GEN_INT (0x7fff);
+         absneg_op = AND;
+       }
+      else
+       {
+         set = GEN_INT (0x8000);
+         absneg_op = XOR;
+       }
+      set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  set = gen_rtx_SET (dst, set);
+
+  rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
+  rtvec par = gen_rtvec (2, set, clob);
+
+  emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
 }
 
 /* Expand a copysign operation.  Special case operand 0 being a constant.  */
index b9de1e7..80b6ee7 100644 (file)
@@ -121,6 +121,8 @@ extern rtx ix86_expand_adjust_ufix_to_sfix_si (rtx, rtx *);
 extern enum ix86_fpcmp_strategy ix86_fp_comparison_strategy (enum rtx_code);
 extern void ix86_expand_fp_absneg_operator (enum rtx_code, machine_mode,
                                            rtx[]);
+extern void ix86_split_fp_absneg_operator (enum rtx_code, machine_mode,
+                                          rtx[]);
 extern void ix86_expand_copysign (rtx []);
 extern void ix86_split_copysign_const (rtx []);
 extern void ix86_split_copysign_var (rtx []);
index 977fbc6..9f8194b 100644 (file)
 ;; All x87 floating point modes
 (define_mode_iterator X87MODEF [SF DF XF])
 
+;; All SSE floating point modes
+(define_mode_iterator SSEMODEF [SF DF TF])
+(define_mode_attr ssevecmodef [(SF "V4SF") (DF "V2DF") (TF "TF")])
+
 ;; SSE instruction suffix for various modes
 (define_mode_attr ssemodesuffix
   [(SF "ss") (DF "sd")
   [(set_attr "type" "negnot")
    (set_attr "mode" "<MODE>")])
 
-;; Changing of sign for FP values is doable using integer unit too.
+(define_expand "<code>tf2"
+  [(set (match_operand:TF 0 "register_operand")
+       (absneg:TF (match_operand:TF 1 "register_operand")))]
+  "TARGET_SSE"
+  "ix86_expand_fp_absneg_operator (<CODE>, TFmode, operands); DONE;")
+
+(define_insn "*<code>tf2_1"
+  [(set (match_operand:TF 0 "register_operand" "=x,x,Yv,Yv")
+       (absneg:TF
+         (match_operand:TF 1 "vector_operand" "0,xBm,Yv,m")))
+   (use (match_operand:TF 2 "vector_operand" "xBm,0,Yvm,Yv"))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_SSE"
+  "#"
+  [(set_attr "isa" "noavx,noavx,avx,avx")])
 
 (define_expand "<code><mode>2"
   [(set (match_operand:X87MODEF 0 "register_operand")
   "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)"
   "ix86_expand_fp_absneg_operator (<CODE>, <MODE>mode, operands); DONE;")
 
-(define_insn "*absneg<mode>2"
-  [(set (match_operand:MODEF 0 "register_operand" "=Yv,Yv,f,!r")
-       (match_operator:MODEF 3 "absneg_operator"
-         [(match_operand:MODEF 1 "register_operand" "0,Yv,0,0")]))
-   (use (match_operand:<ssevecmode> 2 "nonimmediate_operand" "Yvm,0,X,X"))
+;; Changing of sign for FP values is doable using integer unit too.
+(define_insn "*<code><mode>2_i387_1"
+  [(set (match_operand:X87MODEF 0 "register_operand" "=f,!r")
+       (absneg:X87MODEF
+         (match_operand:X87MODEF 1 "register_operand" "0,0")))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_80387"
+  "#")
+
+(define_split
+  [(set (match_operand:X87MODEF 0 "fp_register_operand")
+       (absneg:X87MODEF (match_operand:X87MODEF 1 "fp_register_operand")))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_80387 && reload_completed"
+  [(set (match_dup 0) (absneg:X87MODEF (match_dup 1)))])
+
+(define_split
+  [(set (match_operand:X87MODEF 0 "general_reg_operand")
+       (absneg:X87MODEF (match_operand:X87MODEF 1 "general_reg_operand")))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_80387 && reload_completed"
+  [(const_int 0)]
+  "ix86_split_fp_absneg_operator (<CODE>, <MODE>mode, operands); DONE;")
+
+(define_insn "*<code><mode>2_1"
+  [(set (match_operand:MODEF 0 "register_operand" "=x,x,Yv,f,!r")
+       (absneg:MODEF
+         (match_operand:MODEF 1 "register_operand" "0,x,Yv,0,0")))
+   (use (match_operand:<ssevecmode> 2 "vector_operand" "xBm,0,Yvm,X,X"))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)"
   "#"
-  [(set (attr "enabled")
+  [(set_attr "isa" "noavx,noavx,avx,*,*")
+   (set (attr "enabled")
      (if_then_else
        (match_test ("SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH"))
        (if_then_else
-        (eq_attr "alternative" "2")
+        (eq_attr "alternative" "3,4")
         (symbol_ref "TARGET_MIX_SSE_I387")
-        (symbol_ref "true"))
+        (const_string "*"))
        (if_then_else
-        (eq_attr "alternative" "2,3")
+        (eq_attr "alternative" "3,4")
         (symbol_ref "true")
         (symbol_ref "false"))))])
 
-(define_insn "*absnegxf2_i387"
-  [(set (match_operand:XF 0 "register_operand" "=f,!r")
-       (match_operator:XF 3 "absneg_operator"
-         [(match_operand:XF 1 "register_operand" "0,0")]))
-   (use (match_operand 2))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_80387"
-  "#")
-
-(define_expand "<code>tf2"
-  [(set (match_operand:TF 0 "register_operand")
-       (absneg:TF (match_operand:TF 1 "register_operand")))]
-  "TARGET_SSE"
-  "ix86_expand_fp_absneg_operator (<CODE>, TFmode, operands); DONE;")
-
-(define_insn "*absnegtf2_sse"
-  [(set (match_operand:TF 0 "register_operand" "=Yv,Yv")
-       (match_operator:TF 3 "absneg_operator"
-         [(match_operand:TF 1 "register_operand" "0,Yv")]))
-   (use (match_operand:TF 2 "nonimmediate_operand" "Yvm,0"))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_SSE"
-  "#")
-
-;; Splitters for fp abs and neg.
-
 (define_split
-  [(set (match_operand 0 "fp_register_operand")
-       (match_operator 1 "absneg_operator" [(match_dup 0)]))
-   (use (match_operand 2))
+  [(set (match_operand:SSEMODEF 0 "sse_reg_operand")
+       (absneg:SSEMODEF
+         (match_operand:SSEMODEF 1 "vector_operand")))
+   (use (match_operand:<ssevecmodef> 2 "vector_operand"))
    (clobber (reg:CC FLAGS_REG))]
-  "reload_completed"
-  [(set (match_dup 0) (match_op_dup 1 [(match_dup 0)]))])
-
-(define_split
-  [(set (match_operand 0 "sse_reg_operand")
-       (match_operator 3 "absneg_operator"
-         [(match_operand 1 "register_operand")]))
-   (use (match_operand 2 "nonimmediate_operand"))
-   (clobber (reg:CC FLAGS_REG))]
-  "reload_completed"
+  "((SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
+    || (TARGET_SSE && (<MODE>mode == TFmode)))
+   && reload_completed"
   [(set (match_dup 0) (match_dup 3))]
 {
-  machine_mode mode = GET_MODE (operands[0]);
-  machine_mode vmode = GET_MODE (operands[2]);
-  rtx tmp;
+  machine_mode mode = <MODE>mode;
+  machine_mode vmode = <ssevecmodef>mode;
+  enum rtx_code absneg_op = <CODE> == ABS ? AND : XOR;
 
   operands[0] = lowpart_subreg (vmode, operands[0], mode);
   operands[1] = lowpart_subreg (vmode, operands[1], mode);
-  if (operands_match_p (operands[0], operands[2]))
-    std::swap (operands[1], operands[2]);
-  if (GET_CODE (operands[3]) == ABS)
-    tmp = gen_rtx_AND (vmode, operands[1], operands[2]);
-  else
-    tmp = gen_rtx_XOR (vmode, operands[1], operands[2]);
-  operands[3] = tmp;
-})
 
-(define_split
-  [(set (match_operand:SF 0 "general_reg_operand")
-       (match_operator:SF 1 "absneg_operator" [(match_dup 0)]))
-   (use (match_operand:V4SF 2))
-   (clobber (reg:CC FLAGS_REG))]
-  "reload_completed"
-  [(parallel [(set (match_dup 0) (match_dup 1))
-             (clobber (reg:CC FLAGS_REG))])]
-{
-  rtx tmp;
-  operands[0] = gen_lowpart (SImode, operands[0]);
-  if (GET_CODE (operands[1]) == ABS)
+  if (TARGET_AVX)
     {
-      tmp = gen_int_mode (0x7fffffff, SImode);
-      tmp = gen_rtx_AND (SImode, operands[0], tmp);
+      if (MEM_P (operands[1]))
+        std::swap (operands[1], operands[2]);
     }
   else
-    {
-      tmp = gen_int_mode (0x80000000, SImode);
-      tmp = gen_rtx_XOR (SImode, operands[0], tmp);
-    }
-  operands[1] = tmp;
+   {
+     if (operands_match_p (operands[0], operands[2]))
+       std::swap (operands[1], operands[2]);
+   }
+
+  operands[3]
+    = gen_rtx_fmt_ee (absneg_op, vmode, operands[1], operands[2]);
 })
 
 (define_split
-  [(set (match_operand:DF 0 "general_reg_operand")
-       (match_operator:DF 1 "absneg_operator" [(match_dup 0)]))
+  [(set (match_operand:MODEF 0 "fp_register_operand")
+       (absneg:MODEF (match_operand:MODEF 1 "fp_register_operand")))
    (use (match_operand 2))
    (clobber (reg:CC FLAGS_REG))]
-  "reload_completed"
-  [(parallel [(set (match_dup 0) (match_dup 1))
-             (clobber (reg:CC FLAGS_REG))])]
-{
-  rtx tmp;
-  if (TARGET_64BIT)
-    {
-      tmp = gen_lowpart (DImode, operands[0]);
-      tmp = gen_rtx_ZERO_EXTRACT (DImode, tmp, const1_rtx, GEN_INT (63));
-      operands[0] = tmp;
-
-      if (GET_CODE (operands[1]) == ABS)
-       tmp = const0_rtx;
-      else
-       tmp = gen_rtx_NOT (DImode, tmp);
-    }
-  else
-    {
-      operands[0] = gen_highpart (SImode, operands[0]);
-      if (GET_CODE (operands[1]) == ABS)
-       {
-         tmp = gen_int_mode (0x7fffffff, SImode);
-         tmp = gen_rtx_AND (SImode, operands[0], tmp);
-       }
-      else
-       {
-         tmp = gen_int_mode (0x80000000, SImode);
-         tmp = gen_rtx_XOR (SImode, operands[0], tmp);
-       }
-    }
-  operands[1] = tmp;
-})
+  "TARGET_80387 && reload_completed"
+  [(set (match_dup 0) (absneg:X87MODEF (match_dup 1)))])
 
 (define_split
-  [(set (match_operand:XF 0 "general_reg_operand")
-       (match_operator:XF 1 "absneg_operator" [(match_dup 0)]))
+  [(set (match_operand:MODEF 0 "general_reg_operand")
+       (absneg:MODEF (match_operand:MODEF 1 "general_reg_operand")))
    (use (match_operand 2))
    (clobber (reg:CC FLAGS_REG))]
-  "reload_completed"
-  [(parallel [(set (match_dup 0) (match_dup 1))
-             (clobber (reg:CC FLAGS_REG))])]
-{
-  rtx tmp;
-  operands[0] = gen_rtx_REG (SImode,
-                            REGNO (operands[0]) + (TARGET_64BIT ? 1 : 2));
-  if (GET_CODE (operands[1]) == ABS)
-    {
-      tmp = GEN_INT (0x7fff);
-      tmp = gen_rtx_AND (SImode, operands[0], tmp);
-    }
-  else
-    {
-      tmp = GEN_INT (0x8000);
-      tmp = gen_rtx_XOR (SImode, operands[0], tmp);
-    }
-  operands[1] = tmp;
-})
+  "TARGET_80387 && reload_completed"
+  [(const_int 0)]
+  "ix86_split_fp_absneg_operator (<CODE>, <MODE>mode, operands); DONE;")
 
 ;; Conditionalize these after reload. If they match before reload, we
 ;; lose the clobber and ability to use integer instructions.
 
-(define_insn "*<code><mode>2_1"
+(define_insn "*<code><mode>2_i387"
   [(set (match_operand:X87MODEF 0 "register_operand" "=f")
        (absneg:X87MODEF (match_operand:X87MODEF 1 "register_operand" "0")))]
-  "TARGET_80387
-   && (reload_completed
-       || !(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH))"
+  "TARGET_80387 && reload_completed"
   "<absneg_mnemonic>"
   [(set_attr "type" "fsgn")
    (set_attr "mode" "<MODE>")])
 
 ;; Copysign instructions
 
-(define_mode_iterator CSGNMODE [SF DF TF])
-(define_mode_attr CSGNVMODE [(SF "V4SF") (DF "V2DF") (TF "TF")])
-
 (define_expand "copysign<mode>3"
-  [(match_operand:CSGNMODE 0 "register_operand")
-   (match_operand:CSGNMODE 1 "nonmemory_operand")
-   (match_operand:CSGNMODE 2 "register_operand")]
+  [(match_operand:SSEMODEF 0 "register_operand")
+   (match_operand:SSEMODEF 1 "nonmemory_operand")
+   (match_operand:SSEMODEF 2 "register_operand")]
   "(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
    || (TARGET_SSE && (<MODE>mode == TFmode))"
   "ix86_expand_copysign (operands); DONE;")
 
 (define_insn_and_split "copysign<mode>3_const"
-  [(set (match_operand:CSGNMODE 0 "register_operand" "=Yv")
-       (unspec:CSGNMODE
-         [(match_operand:<CSGNVMODE> 1 "nonimm_or_0_operand" "YvmC")
-          (match_operand:CSGNMODE 2 "register_operand" "0")
-          (match_operand:<CSGNVMODE> 3 "nonimmediate_operand" "Yvm")]
+  [(set (match_operand:SSEMODEF 0 "register_operand" "=Yv")
+       (unspec:SSEMODEF
+         [(match_operand:<ssevecmodef> 1 "nonimm_or_0_operand" "YvmC")
+          (match_operand:SSEMODEF 2 "register_operand" "0")
+          (match_operand:<ssevecmodef> 3 "nonimmediate_operand" "Yvm")]
          UNSPEC_COPYSIGN))]
   "(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
    || (TARGET_SSE && (<MODE>mode == TFmode))"
   "ix86_split_copysign_const (operands); DONE;")
 
 (define_insn "copysign<mode>3_var"
-  [(set (match_operand:CSGNMODE 0 "register_operand" "=Yv,Yv,Yv,Yv,Yv")
-       (unspec:CSGNMODE
-         [(match_operand:CSGNMODE 2 "register_operand" "Yv,0,0,Yv,Yv")
-          (match_operand:CSGNMODE 3 "register_operand" "1,1,Yv,1,Yv")
-          (match_operand:<CSGNVMODE> 4
+  [(set (match_operand:SSEMODEF 0 "register_operand" "=Yv,Yv,Yv,Yv,Yv")
+       (unspec:SSEMODEF
+         [(match_operand:SSEMODEF 2 "register_operand" "Yv,0,0,Yv,Yv")
+          (match_operand:SSEMODEF 3 "register_operand" "1,1,Yv,1,Yv")
+          (match_operand:<ssevecmodef> 4
             "nonimmediate_operand" "X,Yvm,Yvm,0,0")
-          (match_operand:<CSGNVMODE> 5
+          (match_operand:<ssevecmodef> 5
             "nonimmediate_operand" "0,Yvm,1,Yvm,1")]
          UNSPEC_COPYSIGN))
-   (clobber (match_scratch:<CSGNVMODE> 1 "=Yv,Yv,Yv,Yv,Yv"))]
+   (clobber (match_scratch:<ssevecmodef> 1 "=Yv,Yv,Yv,Yv,Yv"))]
   "(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
    || (TARGET_SSE && (<MODE>mode == TFmode))"
   "#")
 
 (define_split
-  [(set (match_operand:CSGNMODE 0 "register_operand")
-       (unspec:CSGNMODE
-         [(match_operand:CSGNMODE 2 "register_operand")
-          (match_operand:CSGNMODE 3 "register_operand")
-          (match_operand:<CSGNVMODE> 4)
-          (match_operand:<CSGNVMODE> 5)]
+  [(set (match_operand:SSEMODEF 0 "register_operand")
+       (unspec:SSEMODEF
+         [(match_operand:SSEMODEF 2 "register_operand")
+          (match_operand:SSEMODEF 3 "register_operand")
+          (match_operand:<ssevecmodef> 4)
+          (match_operand:<ssevecmodef> 5)]
          UNSPEC_COPYSIGN))
-   (clobber (match_scratch:<CSGNVMODE> 1))]
+   (clobber (match_scratch:<ssevecmodef> 1))]
   "((SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
     || (TARGET_SSE && (<MODE>mode == TFmode)))
    && reload_completed"
index 29867fb..5e8f671 100644 (file)
 (define_predicate "compare_operator"
   (match_code "compare"))
 
-(define_predicate "absneg_operator"
-  (match_code "abs,neg"))
-
 ;; Return true if OP is a memory operand, aligned to
 ;; less than its natural alignment.
 (define_predicate "misaligned_operand"
index 0997f43..d7d5425 100644 (file)
   "TARGET_SSE"
   "ix86_expand_fp_absneg_operator (<CODE>, <MODE>mode, operands); DONE;")
 
-(define_insn_and_split "*absneg<mode>2"
+(define_insn_and_split "*<code><mode>2"
   [(set (match_operand:VF 0 "register_operand" "=x,x,v,v")
-       (match_operator:VF 3 "absneg_operator"
-         [(match_operand:VF 1 "vector_operand" "0,  xBm,v, m")]))
+       (absneg:VF
+         (match_operand:VF 1 "vector_operand" "0,  xBm,v, m")))
    (use (match_operand:VF 2 "vector_operand"    "xBm,0,  vm,v"))]
   "TARGET_SSE"
   "#"
   "&& reload_completed"
-  [(const_int 0)]
+  [(set (match_dup 0) (match_dup 3))]
 {
-  enum rtx_code absneg_op;
-  rtx op1, op2;
-  rtx t;
+  enum rtx_code absneg_op = <CODE> == ABS ? AND : XOR;
 
   if (TARGET_AVX)
     {
       if (MEM_P (operands[1]))
-       op1 = operands[2], op2 = operands[1];
-      else
-       op1 = operands[1], op2 = operands[2];
+        std::swap (operands[1], operands[2]);
     }
   else
-    {
-      op1 = operands[0];
-      if (rtx_equal_p (operands[0], operands[1]))
-       op2 = operands[2];
-      else
-       op2 = operands[1];
-    }
+   {
+     if (operands_match_p (operands[0], operands[2]))
+       std::swap (operands[1], operands[2]);
+   }
 
-  absneg_op = GET_CODE (operands[3]) == NEG ? XOR : AND;
-  t = gen_rtx_fmt_ee (absneg_op, <MODE>mode, op1, op2);
-  t = gen_rtx_SET (operands[0], t);
-  emit_insn (t);
-  DONE;
+  operands[3]
+    = gen_rtx_fmt_ee (absneg_op, <MODE>mode, operands[1], operands[2]);
 }
   [(set_attr "isa" "noavx,noavx,avx,avx")])