aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2018-05-08 14:16:19 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2018-05-08 14:16:19 +0200
commit4d4015db89b3e93dac9f8e08ce9127390d475f11 (patch)
tree58dcf1ac378e7ad6c3ef1d21a7f0fbb33c62e820 /gcc/config
parentac6818591810af25dc9f91d28230f30494e22a71 (diff)
downloadgcc-4d4015db89b3e93dac9f8e08ce9127390d475f11.zip
gcc-4d4015db89b3e93dac9f8e08ce9127390d475f11.tar.gz
gcc-4d4015db89b3e93dac9f8e08ce9127390d475f11.tar.bz2
re PR target/85572 (faster code for absolute value of __v2di)
PR target/85572 * config/i386/i386.c (ix86_expand_sse2_abs): Handle E_V2DImode and E_V4DImode. * config/i386/sse.md (abs<mode>2): Use VI_AVX2 iterator instead of VI1248_AVX512VL_AVX512BW. Handle V2DImode and V4DImode if not TARGET_AVX512VL using ix86_expand_sse2_abs. Formatting fixes. * g++.dg/other/sse2-pr85572-1.C: New test. * g++.dg/other/sse2-pr85572-2.C: New test. * g++.dg/other/sse4-pr85572-1.C: New test. * g++.dg/other/avx2-pr85572-1.C: New test. From-SVN: r260041
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/i386/i386.c73
-rw-r--r--gcc/config/i386/sse.md10
2 files changed, 58 insertions, 25 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index d99ff96..ab15ac3 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -49837,39 +49837,70 @@ ix86_expand_sse2_abs (rtx target, rtx input)
switch (mode)
{
+ case E_V2DImode:
+ case E_V4DImode:
+ /* For 64-bit signed integer X, with SSE4.2 use
+ pxor t0, t0; pcmpgtq X, t0; pxor t0, X; psubq t0, X.
+ Otherwise handle it similarly to V4SImode, except use 64 as W instead of
+ 32 and use logical instead of arithmetic right shift (which is
+ unimplemented) and subtract. */
+ if (TARGET_SSE4_2)
+ {
+ tmp0 = gen_reg_rtx (mode);
+ tmp1 = gen_reg_rtx (mode);
+ emit_move_insn (tmp1, CONST0_RTX (mode));
+ if (mode == E_V2DImode)
+ emit_insn (gen_sse4_2_gtv2di3 (tmp0, tmp1, input));
+ else
+ emit_insn (gen_avx2_gtv4di3 (tmp0, tmp1, input));
+ }
+ else
+ {
+ tmp0 = expand_simple_binop (mode, LSHIFTRT, input,
+ GEN_INT (GET_MODE_UNIT_BITSIZE (mode)
+ - 1), NULL, 0, OPTAB_DIRECT);
+ tmp0 = expand_simple_unop (mode, NEG, tmp0, NULL, false);
+ }
+
+ tmp1 = expand_simple_binop (mode, XOR, tmp0, input,
+ NULL, 0, OPTAB_DIRECT);
+ x = expand_simple_binop (mode, MINUS, tmp1, tmp0,
+ target, 0, OPTAB_DIRECT);
+ break;
+
+ case E_V4SImode:
/* For 32-bit signed integer X, the best way to calculate the absolute
value of X is (((signed) X >> (W-1)) ^ X) - ((signed) X >> (W-1)). */
- case E_V4SImode:
- tmp0 = expand_simple_binop (mode, ASHIFTRT, input,
- GEN_INT (GET_MODE_UNIT_BITSIZE (mode) - 1),
- NULL, 0, OPTAB_DIRECT);
- tmp1 = expand_simple_binop (mode, XOR, tmp0, input,
- NULL, 0, OPTAB_DIRECT);
- x = expand_simple_binop (mode, MINUS, tmp1, tmp0,
- target, 0, OPTAB_DIRECT);
- break;
+ tmp0 = expand_simple_binop (mode, ASHIFTRT, input,
+ GEN_INT (GET_MODE_UNIT_BITSIZE (mode) - 1),
+ NULL, 0, OPTAB_DIRECT);
+ tmp1 = expand_simple_binop (mode, XOR, tmp0, input,
+ NULL, 0, OPTAB_DIRECT);
+ x = expand_simple_binop (mode, MINUS, tmp1, tmp0,
+ target, 0, OPTAB_DIRECT);
+ break;
+ case E_V8HImode:
/* For 16-bit signed integer X, the best way to calculate the absolute
value of X is max (X, -X), as SSE2 provides the PMAXSW insn. */
- case E_V8HImode:
- tmp0 = expand_unop (mode, neg_optab, input, NULL_RTX, 0);
+ tmp0 = expand_unop (mode, neg_optab, input, NULL_RTX, 0);
- x = expand_simple_binop (mode, SMAX, tmp0, input,
- target, 0, OPTAB_DIRECT);
- break;
+ x = expand_simple_binop (mode, SMAX, tmp0, input,
+ target, 0, OPTAB_DIRECT);
+ break;
+ case E_V16QImode:
/* For 8-bit signed integer X, the best way to calculate the absolute
value of X is min ((unsigned char) X, (unsigned char) (-X)),
as SSE2 provides the PMINUB insn. */
- case E_V16QImode:
- tmp0 = expand_unop (mode, neg_optab, input, NULL_RTX, 0);
+ tmp0 = expand_unop (mode, neg_optab, input, NULL_RTX, 0);
- x = expand_simple_binop (V16QImode, UMIN, tmp0, input,
- target, 0, OPTAB_DIRECT);
- break;
+ x = expand_simple_binop (V16QImode, UMIN, tmp0, input,
+ target, 0, OPTAB_DIRECT);
+ break;
- default:
- gcc_unreachable ();
+ default:
+ gcc_unreachable ();
}
if (x != target)
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index aab4261..ae6294e 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -15211,12 +15211,14 @@
(set_attr "mode" "<sseinsnmode>")])
(define_expand "abs<mode>2"
- [(set (match_operand:VI1248_AVX512VL_AVX512BW 0 "register_operand")
- (abs:VI1248_AVX512VL_AVX512BW
- (match_operand:VI1248_AVX512VL_AVX512BW 1 "vector_operand")))]
+ [(set (match_operand:VI_AVX2 0 "register_operand")
+ (abs:VI_AVX2
+ (match_operand:VI_AVX2 1 "vector_operand")))]
"TARGET_SSE2"
{
- if (!TARGET_SSSE3)
+ if (!TARGET_SSSE3
+ || ((<MODE>mode == V2DImode || <MODE>mode == V4DImode)
+ && !TARGET_AVX512VL))
{
ix86_expand_sse2_abs (operands[0], operands[1]);
DONE;