diff options
author | Jakub Jelinek <jakub@redhat.com> | 2018-05-08 14:16:19 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2018-05-08 14:16:19 +0200 |
commit | 4d4015db89b3e93dac9f8e08ce9127390d475f11 (patch) | |
tree | 58dcf1ac378e7ad6c3ef1d21a7f0fbb33c62e820 /gcc/config | |
parent | ac6818591810af25dc9f91d28230f30494e22a71 (diff) | |
download | gcc-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.c | 73 | ||||
-rw-r--r-- | gcc/config/i386/sse.md | 10 |
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; |