i386-protos.h (ix86_expand_xorsign): New prototype.
authorUros Bizjak <ubizjak@gmail.com>
Wed, 9 Jan 2019 19:16:02 +0000 (20:16 +0100)
committerUros Bizjak <uros@gcc.gnu.org>
Wed, 9 Jan 2019 19:16:02 +0000 (20:16 +0100)
* config/i386/i386-protos.h (ix86_expand_xorsign): New prototype.
(ix86_split_xorsign): Ditto.
* config/i386/i386.c (ix86_expand_xorsign): New function.
(ix86_split_xorsign): Ditto.
* config/i386/i386.md (UNSPEC_XORSIGN): New unspec.
(xorsign<mode>3): New expander.
(xorsign<mode>3_1): New insn_and_split pattern.
* config/i386/sse.md (xorsign<mode>3): New expander.

testsuite/ChangeLog:

* lib/target-supports.exp
(check_effective_target_xorsign): Add i?86-*-* and x86_64-*-* targets.
* gcc.target/i386/xorsign.c: New test.

From-SVN: r267779

gcc/ChangeLog
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.md
gcc/config/i386/sse.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/xorsign.c [new file with mode: 0644]
gcc/testsuite/lib/target-supports.exp

index 09e176a9418e90c6bcce4fb694733fb1ce85eeba..c8fdce94c69792e6f9798e348dd699945513e706 100644 (file)
@@ -1,3 +1,14 @@
+2019-01-09  Uroš Bizjak  <ubizjak@gmail.com>
+
+       * config/i386/i386-protos.h (ix86_expand_xorsign): New prototype.
+       (ix86_split_xorsign): Ditto.
+       * config/i386/i386.c (ix86_expand_xorsign): New function.
+       (ix86_split_xorsign): Ditto.
+       * config/i386/i386.md (UNSPEC_XORSIGN): New unspec.
+       (xorsign<mode>3): New expander.
+       (xorsign<mode>3_1): New insn_and_split pattern.
+       * config/i386/sse.md (xorsign<mode>3): New expander.
+
 2019-01-09  Eric Botcazou  <ebotcazou@adacore.com>
 
        * config/sparc/sparc.md (*tablejump_sp32): Merge into...
index bf3637d06d6593abccb6e6c1f57429273f42602c..2d6001739176437c342a0f7980267953a5e54c31 100644 (file)
@@ -124,6 +124,8 @@ extern void ix86_expand_fp_absneg_operator (enum rtx_code, machine_mode,
 extern void ix86_expand_copysign (rtx []);
 extern void ix86_split_copysign_const (rtx []);
 extern void ix86_split_copysign_var (rtx []);
+extern void ix86_expand_xorsign (rtx []);
+extern void ix86_split_xorsign (rtx []);
 extern bool ix86_unary_operator_ok (enum rtx_code, machine_mode, rtx[]);
 extern bool ix86_match_ccmode (rtx, machine_mode);
 extern void ix86_expand_branch (enum rtx_code, rtx, rtx, rtx);
index bd48e080f465f6b0a97cab2d20110dd3f3c01b5a..628ec80123ee3fac5e645850b81149730f12e4d0 100644 (file)
@@ -21860,6 +21860,63 @@ ix86_split_copysign_var (rtx operands[])
   emit_insn (gen_rtx_SET (dest, x));
 }
 
+/* Expand an xorsign operation.  */
+
+void
+ix86_expand_xorsign (rtx operands[])
+{
+  rtx (*xorsign_insn)(rtx, rtx, rtx, rtx);
+  machine_mode mode, vmode;
+  rtx dest, op0, op1, mask;
+
+  dest = operands[0];
+  op0 = operands[1];
+  op1 = operands[2];
+
+  mode = GET_MODE (dest);
+
+  if (mode == SFmode)
+    {
+      xorsign_insn = gen_xorsignsf3_1;
+      vmode = V4SFmode;
+    }
+  else if (mode == DFmode)
+    {
+      xorsign_insn = gen_xorsigndf3_1;
+      vmode = V2DFmode;
+    }
+  else
+    gcc_unreachable ();
+
+  mask = ix86_build_signbit_mask (vmode, 0, 0);
+
+  emit_insn (xorsign_insn (dest, op0, op1, mask));
+}
+
+/* Deconstruct an xorsign operation into bit masks.  */
+
+void
+ix86_split_xorsign (rtx operands[])
+{
+  machine_mode mode, vmode;
+  rtx dest, op0, mask, x;
+
+  dest = operands[0];
+  op0 = operands[1];
+  mask = operands[3];
+
+  mode = GET_MODE (dest);
+  vmode = GET_MODE (mask);
+
+  dest = lowpart_subreg (vmode, dest, mode);
+  x = gen_rtx_AND (vmode, dest, mask);
+  emit_insn (gen_rtx_SET (dest, x));
+
+  op0 = lowpart_subreg (vmode, op0, mode);
+  x = gen_rtx_XOR (vmode, dest, op0);
+  emit_insn (gen_rtx_SET (dest, x));
+}
+
 /* Return TRUE or FALSE depending on whether the first SET in INSN
    has source and destination with matching CC modes, and that the
    CC mode is at least as constrained as REQ_MODE.  */
index 83124ccbeb3ace49a74e205dc11432b2a901f3a3..28e336044683585f608ba12249b15583b68586dd 100644 (file)
 
   ;; Generic math support
   UNSPEC_COPYSIGN
+  UNSPEC_XORSIGN
   UNSPEC_IEEE_MIN      ; not commutative
   UNSPEC_IEEE_MAX      ; not commutative
 
    && reload_completed"
   [(const_int 0)]
   "ix86_split_copysign_var (operands); DONE;")
+
+(define_expand "xorsign<mode>3"
+  [(match_operand:MODEF 0 "register_operand")
+   (match_operand:MODEF 1 "register_operand")
+   (match_operand:MODEF 2 "register_operand")]
+  "SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH"
+  "ix86_expand_xorsign (operands); DONE;")
+
+(define_insn_and_split "xorsign<mode>3_1"
+  [(set (match_operand:MODEF 0 "register_operand" "=Yv")
+       (unspec:MODEF
+         [(match_operand:MODEF 1 "register_operand" "Yv")
+          (match_operand:MODEF 2 "register_operand" "0")
+          (match_operand:<ssevecmode> 3 "nonimmediate_operand" "Yvm")]
+         UNSPEC_XORSIGN))]
+  "SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH"
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
+  "ix86_split_xorsign (operands); DONE;")
 \f
 ;; One complement instructions
 
index ec699d6f59cf6903619f48f3e769eb467cd00aee..b5e3cd82eea1303eb6c107082be4247b0f284d9b 100644 (file)
   operands[5] = gen_reg_rtx (<MODE>mode);
 })
 
+(define_expand "xorsign<mode>3"
+  [(set (match_dup 4)
+       (and:VF (match_dup 3)
+               (match_operand:VF 2 "vector_operand")))
+   (set (match_operand:VF 0 "register_operand")
+       (xor:VF (match_dup 4)
+               (match_operand:VF 1 "vector_operand")))]
+  "TARGET_SSE"
+{
+  operands[3] = ix86_build_signbit_mask (<MODE>mode, 1, 0);
+
+  operands[4] = gen_reg_rtx (<MODE>mode);
+})
+
 ;; Also define scalar versions.  These are used for abs, neg, and
 ;; conditional move.  Using subregs into vector modes causes register
 ;; allocation lossage.  These patterns do not allow memory operands
index 5caca46b5d5a0b4cfcf44674c6cb0d3fd4e76047..c4fa25493122631ffb7bd480aa2ed93fcc968cb5 100644 (file)
@@ -1,3 +1,9 @@
+2019-01-09  Uroš Bizjak  <ubizjak@gmail.com>
+
+       * lib/target-supports.exp
+       (check_effective_target_xorsign): Add i?86-*-* and x86_64-*-* targets.
+       * gcc.target/i386/xorsign.c: New test.
+
 2019-01-09  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gcc.target/sparc/tls-ld-int8.c: New test.
diff --git a/gcc/testsuite/gcc.target/i386/xorsign.c b/gcc/testsuite/gcc.target/i386/xorsign.c
new file mode 100644 (file)
index 0000000..ebed5ed
--- /dev/null
@@ -0,0 +1,57 @@
+/* { dg-do run { target sse2_runtime } } */
+/* { dg-options "-O2 -msse2 -mfpmath=sse -ftree-vectorize -fdump-tree-vect-details -save-temps" } */
+
+extern void abort ();
+
+#define N 16
+float a[N] = {-0.1f, -3.2f, -6.3f, -9.4f,
+             -12.5f, -15.6f, -18.7f, -21.8f,
+             24.9f, 27.1f, 30.2f, 33.3f,
+             36.4f, 39.5f, 42.6f, 45.7f};
+float b[N] = {-1.2f, 3.4f, -5.6f, 7.8f,
+             -9.0f, 1.0f, -2.0f, 3.0f,
+             -4.0f, -5.0f, 6.0f, 7.0f,
+             -8.0f, -9.0f, 10.0f, 11.0f};
+float r[N];
+
+double ad[N] = {-0.1d,  -3.2d,  -6.3d,  -9.4d,
+               -12.5d, -15.6d, -18.7d, -21.8d,
+                24.9d,  27.1d,  30.2d,  33.3d,
+                36.4d,  39.5d,  42.6d, 45.7d};
+double bd[N] = {-1.2d,  3.4d, -5.6d,  7.8d,
+               -9.0d,  1.0d, -2.0d,  3.0d,
+               -4.0d, -5.0d,  6.0d,  7.0d,
+               -8.0d, -9.0d, 10.0d, 11.0d};
+double rd[N];
+
+int
+main (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    r[i] = a[i] * __builtin_copysignf (1.0f, b[i]);
+
+  /* check results:  */
+  for (i = 0; i < N; i++)
+    if (r[i] != a[i] * __builtin_copysignf (1.0f, b[i]))
+      abort ();
+
+  for (i = 0; i < N; i++)
+    rd[i] = ad[i] * __builtin_copysign (1.0d, bd[i]);
+
+  /* check results:  */
+  for (i = 0; i < N; i++)
+    if (rd[i] != ad[i] * __builtin_copysign (1.0d, bd[i]))
+      abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" } } */
+/* { dg-final { scan-assembler "\[ \t\]xor" } } */
+/* { dg-final { scan-assembler "\[ \t\]and" } } */
+/* { dg-final { scan-assembler-not "copysign" } } */
+/* { dg-final { scan-assembler-not "\[ \t\]fxam" } } */
+/* { dg-final { scan-assembler-not "\[ \t\]or" } } */
+/* { dg-final { scan-assembler-not "\[ \t\]mul" } } */
index f0043d5dd4f90793f6b9ad563ee0911b635f934b..a3cf1c975f8e4b408c53bc2a6e084004a6b16198 100644 (file)
@@ -5730,7 +5730,8 @@ proc check_effective_target_vect_perm3_short { } {
 
 proc check_effective_target_xorsign { } {
     return [check_cached_effective_target_indexed xorsign {
-      expr { [istarget aarch64*-*-*] || [istarget arm*-*-*] }}]
+      expr { [istarget i?86-*-*] || [istarget x86_64-*-*]
+            || [istarget aarch64*-*-*] || [istarget arm*-*-*] }}]
 }
 
 # Return 1 if the target plus current options supports a vector