diff options
author | Jakub Jelinek <jakub@redhat.com> | 2011-09-16 21:14:36 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2011-09-16 21:14:36 +0200 |
commit | 6e2cb3913952ef1b7fd31f4f5b8754f55f689d9a (patch) | |
tree | 63520943d260db2da79353c5616960e263cdd8ba | |
parent | 6deb519753e07d167eda75bced5a7987a57f0a03 (diff) | |
download | gcc-6e2cb3913952ef1b7fd31f4f5b8754f55f689d9a.zip gcc-6e2cb3913952ef1b7fd31f4f5b8754f55f689d9a.tar.gz gcc-6e2cb3913952ef1b7fd31f4f5b8754f55f689d9a.tar.bz2 |
sse.md (vec_extract_hi_<mode>, [...]): Use vextracti128 instead of vextractf128 for -mavx2 and integer vectors.
* config/i386/sse.md (vec_extract_hi_<mode>,
vec_extract_hi_v16hi, vec_extract_hi_v32qi): Use
vextracti128 instead of vextractf128 for -mavx2 and
integer vectors. For V4DFmode fix up mode attribute.
(VEC_EXTRACT_MODE): For TARGET_AVX add 32-byte vectors.
(vec_set_lo_<mode>, vec_set_hi_<mode>): For VI8F_256 modes use V4DF
instead of V8SF mode attribute.
(avx2_extracti128): Change into define_expand.
* config/i386/i386.c (ix86_expand_vector_extract): Handle
32-byte vector modes if TARGET_AVX.
* gcc.target/i386/sse2-extract-1.c: New test.
* gcc.target/i386/avx-extract-1.c: New test.
From-SVN: r178915
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 78 | ||||
-rw-r--r-- | gcc/config/i386/sse.md | 93 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/avx-extract-1.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/sse2-extract-1.c | 102 |
6 files changed, 275 insertions, 21 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ce61c21..834ae64 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2011-09-16 Jakub Jelinek <jakub@redhat.com> + + * config/i386/sse.md (vec_extract_hi_<mode>, + vec_extract_hi_v16hi, vec_extract_hi_v32qi): Use + vextracti128 instead of vextractf128 for -mavx2 and + integer vectors. For V4DFmode fix up mode attribute. + (VEC_EXTRACT_MODE): For TARGET_AVX add 32-byte vectors. + (vec_set_lo_<mode>, vec_set_hi_<mode>): For VI8F_256 modes use V4DF + instead of V8SF mode attribute. + (avx2_extracti128): Change into define_expand. + * config/i386/i386.c (ix86_expand_vector_extract): Handle + 32-byte vector modes if TARGET_AVX. + 2011-09-16 Georg-Johann Lay <avr@gjlay.de> * config/avr/avr.md: (umulqihi3, mulqihi3): Write as one pattern. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 97580df..6e7bcd9 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -32587,6 +32587,84 @@ ix86_expand_vector_extract (bool mmx_ok, rtx target, rtx vec, int elt) use_vec_extr = TARGET_SSE4_1; break; + case V8SFmode: + if (TARGET_AVX) + { + tmp = gen_reg_rtx (V4SFmode); + if (elt < 4) + emit_insn (gen_vec_extract_lo_v8sf (tmp, vec)); + else + emit_insn (gen_vec_extract_hi_v8sf (tmp, vec)); + ix86_expand_vector_extract (false, target, tmp, elt & 3); + return; + } + break; + + case V4DFmode: + if (TARGET_AVX) + { + tmp = gen_reg_rtx (V2DFmode); + if (elt < 2) + emit_insn (gen_vec_extract_lo_v4df (tmp, vec)); + else + emit_insn (gen_vec_extract_hi_v4df (tmp, vec)); + ix86_expand_vector_extract (false, target, tmp, elt & 1); + return; + } + break; + + case V32QImode: + if (TARGET_AVX) + { + tmp = gen_reg_rtx (V16QImode); + if (elt < 16) + emit_insn (gen_vec_extract_lo_v32qi (tmp, vec)); + else + emit_insn (gen_vec_extract_hi_v32qi (tmp, vec)); + ix86_expand_vector_extract (false, target, tmp, elt & 15); + return; + } + break; + + case V16HImode: + if (TARGET_AVX) + { + tmp = gen_reg_rtx (V8HImode); + if (elt < 8) + emit_insn (gen_vec_extract_lo_v16hi (tmp, vec)); + else + emit_insn (gen_vec_extract_hi_v16hi (tmp, vec)); + ix86_expand_vector_extract (false, target, tmp, elt & 7); + return; + } + break; + + case V8SImode: + if (TARGET_AVX) + { + tmp = gen_reg_rtx (V4SImode); + if (elt < 4) + emit_insn (gen_vec_extract_lo_v8si (tmp, vec)); + else + emit_insn (gen_vec_extract_hi_v8si (tmp, vec)); + ix86_expand_vector_extract (false, target, tmp, elt & 3); + return; + } + break; + + case V4DImode: + if (TARGET_AVX) + { + tmp = gen_reg_rtx (V2DImode); + if (elt < 2) + emit_insn (gen_vec_extract_lo_v4di (tmp, vec)); + else + emit_insn (gen_vec_extract_hi_v4di (tmp, vec)); + ix86_expand_vector_extract (false, target, tmp, elt & 1); + return; + } + break; + case V8QImode: /* ??? Could extract the appropriate HImode element and shift. */ default: diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index e96fb7d..01edc4e 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -3827,13 +3827,23 @@ (match_operand:VI8F_256 1 "register_operand" "x,x") (parallel [(const_int 2) (const_int 3)])))] "TARGET_AVX" - "vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}" +{ + if (get_attr_mode (insn) == MODE_OI) + return "vextracti128\t{$0x1, %1, %0|%0, %1, 0x1}"; + else + return "vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}"; +} [(set_attr "type" "sselog") (set_attr "prefix_extra" "1") (set_attr "length_immediate" "1") (set_attr "memory" "none,store") (set_attr "prefix" "vex") - (set_attr "mode" "V8SF")]) + (set (attr "mode") + (if_then_else + (and (match_test "TARGET_AVX2") + (eq (const_string "<MODE>mode") (const_string "V4DImode"))) + (const_string "OI") + (const_string "V4DF")))]) (define_insn_and_split "vec_extract_lo_<mode>" [(set (match_operand:<ssehalfvecmode> 0 "nonimmediate_operand" "=x,m") @@ -3862,13 +3872,23 @@ (parallel [(const_int 4) (const_int 5) (const_int 6) (const_int 7)])))] "TARGET_AVX" - "vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}" +{ + if (get_attr_mode (insn) == MODE_OI) + return "vextracti128\t{$0x1, %1, %0|%0, %1, 0x1}"; + else + return "vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}"; +} [(set_attr "type" "sselog") (set_attr "prefix_extra" "1") (set_attr "length_immediate" "1") (set_attr "memory" "none,store") (set_attr "prefix" "vex") - (set_attr "mode" "V8SF")]) + (set (attr "mode") + (if_then_else + (and (match_test "TARGET_AVX2") + (eq (const_string "<MODE>mode") (const_string "V8SImode"))) + (const_string "OI") + (const_string "V8SF")))]) (define_insn_and_split "vec_extract_lo_v16hi" [(set (match_operand:V8HI 0 "nonimmediate_operand" "=x,m") @@ -3901,13 +3921,21 @@ (const_int 12) (const_int 13) (const_int 14) (const_int 15)])))] "TARGET_AVX" - "vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}" +{ + if (get_attr_mode (insn) == MODE_OI) + return "vextracti128\t{$0x1, %1, %0|%0, %1, 0x1}"; + else + return "vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}"; +} [(set_attr "type" "sselog") (set_attr "prefix_extra" "1") (set_attr "length_immediate" "1") (set_attr "memory" "none,store") (set_attr "prefix" "vex") - (set_attr "mode" "V8SF")]) + (set (attr "mode") + (if_then_else (match_test "TARGET_AVX2") + (const_string "OI") + (const_string "V8SF")))]) (define_insn_and_split "vec_extract_lo_v32qi" [(set (match_operand:V16QI 0 "nonimmediate_operand" "=x,m") @@ -3948,13 +3976,21 @@ (const_int 28) (const_int 29) (const_int 30) (const_int 31)])))] "TARGET_AVX" - "vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}" +{ + if (get_attr_mode (insn) == MODE_OI) + return "vextracti128\t{$0x1, %1, %0|%0, %1, 0x1}"; + else + return "vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}"; +} [(set_attr "type" "sselog") (set_attr "prefix_extra" "1") (set_attr "length_immediate" "1") (set_attr "memory" "none,store") (set_attr "prefix" "vex") - (set_attr "mode" "V8SF")]) + (set (attr "mode") + (if_then_else (match_test "TARGET_AVX2") + (const_string "OI") + (const_string "V8SF")))]) (define_insn "*sse4_1_extractps" [(set (match_operand:SF 0 "nonimmediate_operand" "=rm") @@ -3988,7 +4024,10 @@ ;; Modes handled by vec_extract patterns. (define_mode_iterator VEC_EXTRACT_MODE - [V16QI V8HI V4SI V2DI + [(V32QI "TARGET_AVX") V16QI + (V16HI "TARGET_AVX") V8HI + (V8SI "TARGET_AVX") V4SI + (V4DI "TARGET_AVX") V2DI (V8SF "TARGET_AVX") V4SF (V4DF "TARGET_AVX") V2DF]) @@ -11916,7 +11955,7 @@ (set_attr "prefix_extra" "1") (set_attr "length_immediate" "1") (set_attr "prefix" "vex") - (set_attr "mode" "V8SF")]) + (set_attr "mode" "V4DF")]) (define_insn "vec_set_hi_<mode>" [(set (match_operand:VI8F_256 0 "register_operand" "=x") @@ -11931,7 +11970,7 @@ (set_attr "prefix_extra" "1") (set_attr "length_immediate" "1") (set_attr "prefix" "vex") - (set_attr "mode" "V8SF")]) + (set_attr "mode" "V4DF")]) (define_insn "vec_set_lo_<mode>" [(set (match_operand:VI4F_256 0 "register_operand" "=x") @@ -12122,17 +12161,29 @@ DONE; }) -(define_insn "avx2_extracti128" - [(set (match_operand:V2DI 0 "register_operand" "=x") - (vec_select:V2DI - (match_operand:V4DI 1 "nonimmediate_operand" "xm") - (parallel [(match_operand:SI 2 "const_0_to_1_operand" "n")])))] +(define_expand "avx2_extracti128" + [(match_operand:V2DI 0 "nonimmediate_operand" "") + (match_operand:V4DI 1 "register_operand" "") + (match_operand:SI 2 "const_0_to_1_operand" "")] "TARGET_AVX2" - "vextracti128\t{%2, %1, %0|%0, %1, %2}" - [(set_attr "type" "ssemov") - (set_attr "prefix_extra" "1") - (set_attr "prefix" "vex") - (set_attr "mode" "OI")]) +{ + rtx (*insn)(rtx, rtx); + + switch (INTVAL (operands[2])) + { + case 0: + insn = gen_vec_extract_lo_v4di; + break; + case 1: + insn = gen_vec_extract_hi_v4di; + break; + default: + gcc_unreachable (); + } + + emit_insn (insn (operands[0], operands[1])); + DONE; +}) (define_expand "avx2_inserti128" [(match_operand:V4DI 0 "register_operand" "") diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f470918..b9d52b4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-09-16 Jakub Jelinek <jakub@redhat.com> + + * gcc.target/i386/sse2-extract-1.c: New test. + * gcc.target/i386/avx-extract-1.c: New test. + 2011-09-16 Terry Guo <terry.guo@arm.com> * gcc.dg/tree-ssa/foldconst-3.c: Don't use short enums. diff --git a/gcc/testsuite/gcc.target/i386/avx-extract-1.c b/gcc/testsuite/gcc.target/i386/avx-extract-1.c new file mode 100644 index 0000000..2684125 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx-extract-1.c @@ -0,0 +1,5 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -mavx" } */ +/* { dg-require-effective-target avx_runtime } */ + +#include "sse2-extract-1.c" diff --git a/gcc/testsuite/gcc.target/i386/sse2-extract-1.c b/gcc/testsuite/gcc.target/i386/sse2-extract-1.c new file mode 100644 index 0000000..f701cee --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sse2-extract-1.c @@ -0,0 +1,102 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -msse2" } */ +/* { dg-require-effective-target sse2_runtime } */ + +extern void abort (void); +typedef unsigned long long uint64_t; + +#define vector(elcount, type) \ +__attribute__((vector_size((elcount)*sizeof(type)))) type + +#define FN(elcount, type, idx) \ +__attribute__((noinline, noclone)) \ +type f##type##elcount##_##idx (vector (elcount, type) x) { return x[idx] + 1; } +#define T2(elcount, type) \ + H (elcount, type) \ + F (elcount, type, 0) \ + F (elcount, type, 1) +#define T4(elcount, type) \ + T2 (elcount, type) \ + F (elcount, type, 2) \ + F (elcount, type, 3) +#define T8(elcount, type) \ + T4 (elcount, type) \ + F (elcount, type, 4) \ + F (elcount, type, 5) \ + F (elcount, type, 6) \ + F (elcount, type, 7) +#define T16(elcount, type) \ + T8 (elcount, type) \ + F (elcount, type, 8) \ + F (elcount, type, 9) \ + F (elcount, type, 10) \ + F (elcount, type, 11) \ + F (elcount, type, 12) \ + F (elcount, type, 13) \ + F (elcount, type, 14) \ + F (elcount, type, 15) +#define T32(elcount, type) \ + T16 (elcount, type) \ + F (elcount, type, 16) \ + F (elcount, type, 17) \ + F (elcount, type, 18) \ + F (elcount, type, 19) \ + F (elcount, type, 20) \ + F (elcount, type, 21) \ + F (elcount, type, 22) \ + F (elcount, type, 23) \ + F (elcount, type, 24) \ + F (elcount, type, 25) \ + F (elcount, type, 26) \ + F (elcount, type, 27) \ + F (elcount, type, 28) \ + F (elcount, type, 29) \ + F (elcount, type, 30) \ + F (elcount, type, 31) +#define TESTS_SSE2 \ +T2 (2, double) E \ +T2 (2, uint64_t) E \ +T4 (4, float) E \ +T4 (4, int) E \ +T8 (8, short) E \ +T16 (16, char) E +#define TESTS_AVX \ +T4 (4, double) E \ +T4 (4, uint64_t) E \ +T8 (8, float) E \ +T8 (8, int) E \ +T16 (16, short) E \ +T32 (32, char) E +#ifdef __AVX__ +#define TESTS TESTS_SSE2 TESTS_AVX +#else +#define TESTS TESTS_SSE2 +#endif + +#define F FN +#define H(elcount, type) +#define E +TESTS + +int +main () +{ +#undef F +#undef H +#undef E +#define H(elcount, type) \ + vector (elcount, type) v##type##elcount = { +#define E }; +#define F(elcount, type, idx) idx + 1, + TESTS +#undef F +#undef H +#undef E +#define H(elcount, type) +#define E +#define F(elcount, type, idx) \ + if (f##type##elcount##_##idx (v##type##elcount) != idx + 2) \ + abort (); + TESTS + return 0; +} |