aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorUros Bizjak <ubizjak@gmail.com>2019-01-09 20:16:02 +0100
committerUros Bizjak <uros@gcc.gnu.org>2019-01-09 20:16:02 +0100
commit33142cf9cf82aa1f1be6b8c77f903818c101b9dd (patch)
tree10fd20099e2a8a5a9291613f0afc9c891a75c841 /gcc
parentf3ed896c5535cdcab09698b7b7f37c84825d9d7d (diff)
downloadgcc-33142cf9cf82aa1f1be6b8c77f903818c101b9dd.zip
gcc-33142cf9cf82aa1f1be6b8c77f903818c101b9dd.tar.gz
gcc-33142cf9cf82aa1f1be6b8c77f903818c101b9dd.tar.bz2
i386-protos.h (ix86_expand_xorsign): New prototype.
* 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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/config/i386/i386-protos.h2
-rw-r--r--gcc/config/i386/i386.c57
-rw-r--r--gcc/config/i386/i386.md21
-rw-r--r--gcc/config/i386/sse.md14
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.target/i386/xorsign.c57
-rw-r--r--gcc/testsuite/lib/target-supports.exp3
8 files changed, 170 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 09e176a..c8fdce9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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...
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index bf3637d..2d60017 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -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);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index bd48e08..628ec80 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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. */
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 83124cc..28e3360 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -124,6 +124,7 @@
;; Generic math support
UNSPEC_COPYSIGN
+ UNSPEC_XORSIGN
UNSPEC_IEEE_MIN ; not commutative
UNSPEC_IEEE_MAX ; not commutative
@@ -9784,6 +9785,26 @@
&& 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;")
;; One complement instructions
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index ec699d6..b5e3cd8 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -3423,6 +3423,20 @@
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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5caca46..c4fa254 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..ebed5ed
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/xorsign.c
@@ -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" } } */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index f0043d5..a3cf1c9 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -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