diff options
author | Richard Henderson <rth@redhat.com> | 2011-10-13 20:20:37 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2011-10-13 20:20:37 -0700 |
commit | 0772d476effe546701564ee9281fddfd189586f1 (patch) | |
tree | 705eec7815466c67d53b2837ca3cd560759f373e /gcc | |
parent | f6293442ba64f9225c4643438bb385eb0c34087a (diff) | |
download | gcc-0772d476effe546701564ee9281fddfd189586f1.zip gcc-0772d476effe546701564ee9281fddfd189586f1.tar.gz gcc-0772d476effe546701564ee9281fddfd189586f1.tar.bz2 |
i386: Implement vec_perm_const<mode>.
From-SVN: r179955
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/config/i386/i386-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 61 | ||||
-rw-r--r-- | gcc/config/i386/sse.md | 21 |
4 files changed, 88 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9e34eca..81d4f99 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -4,6 +4,11 @@ * config/rs6000/spu.md (vec_permv16qi): New pattern. + * config/i386/i386.c (ix86_expand_vec_perm_const): New. + * config/i386/i386-protos.h: Update. + * config/i386/sse.md (VEC_PERM_CONST): New mode iterator. + (vec_perm_const<VEC_PERM_CONST>): New expander. + 2011-10-13 Jakub Jelinek <jakub@redhat.com> * config/i386/sse.md (vec_set<mode>): Change V_128 iterator mode diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index eea038e..bdac6ff 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -124,6 +124,7 @@ extern bool ix86_expand_fp_movcc (rtx[]); extern bool ix86_expand_fp_vcond (rtx[]); extern bool ix86_expand_int_vcond (rtx[]); extern void ix86_expand_vec_perm (rtx[]); +extern bool ix86_expand_vec_perm_const (rtx[]); extern void ix86_expand_sse_unpack (rtx[], bool, bool); extern bool ix86_expand_int_addcc (rtx[]); extern rtx ix86_expand_call (rtx, rtx, rtx, rtx, rtx, bool); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index a81292b..df6267b 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -36132,6 +36132,67 @@ ix86_expand_vec_perm_builtin (tree exp) return CONST0_RTX (d.vmode); } +bool +ix86_expand_vec_perm_const (rtx operands[4]) +{ + struct expand_vec_perm_d d; + int i, nelt, which; + rtx sel; + + d.target = operands[0]; + d.op0 = operands[1]; + d.op1 = operands[2]; + sel = operands[3]; + + d.vmode = GET_MODE (d.target); + gcc_assert (VECTOR_MODE_P (d.vmode)); + d.nelt = nelt = GET_MODE_NUNITS (d.vmode); + d.testing_p = false; + + gcc_assert (GET_CODE (sel) == CONST_VECTOR); + gcc_assert (XVECLEN (sel, 0) == nelt); + + for (i = which = 0; i < nelt; ++i) + { + rtx e = XVECEXP (sel, 0, i); + int ei = INTVAL (e) & (2 * nelt - 1); + + which |= (ei < nelt ? 1 : 2); + d.perm[i] = ei; + } + + switch (which) + { + default: + gcc_unreachable(); + + case 3: + if (!rtx_equal_p (d.op0, d.op1)) + break; + + /* The elements of PERM do not suggest that only the first operand + is used, but both operands are identical. Allow easier matching + of the permutation by folding the permutation into the single + input vector. */ + for (i = 0; i < nelt; ++i) + if (d.perm[i] >= nelt) + d.perm[i] -= nelt; + /* FALLTHRU */ + + case 1: + d.op1 = d.op0; + break; + + case 2: + for (i = 0; i < nelt; ++i) + d.perm[i] -= nelt; + d.op0 = d.op1; + break; + } + + return ix86_expand_vec_perm_builtin_1 (&d); +} + /* Implement targetm.vectorize.builtin_vec_perm_ok. */ static bool diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 5bf30a8..d5e2de5 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -6236,6 +6236,27 @@ DONE; }) +(define_mode_iterator VEC_PERM_CONST + [(V4SF "TARGET_SSE") (V4SI "TARGET_SSE") + (V2DF "TARGET_SSE") (V2DI "TARGET_SSE") + (V16QI "TARGET_SSE2") (V8HI "TARGET_SSE2") + (V8SF "TARGET_AVX") (V4DF "TARGET_AVX") + (V8SI "TARGET_AVX") (V4DI "TARGET_AVX") + (V32QI "TARGET_AVX2") (V16HI "TARGET_AVX2")]) + +(define_expand "vec_perm_const<mode>" + [(match_operand:VEC_PERM_CONST 0 "register_operand" "") + (match_operand:VEC_PERM_CONST 1 "register_operand" "") + (match_operand:VEC_PERM_CONST 2 "register_operand" "") + (match_operand:<sseintvecmode> 3 "" "")] + "" +{ + if (ix86_expand_vec_perm_const (operands)) + DONE; + else + FAIL; +}) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Parallel bitwise logical operations |