diff options
author | Marc Glisse <marc.glisse@inria.fr> | 2013-04-03 11:44:28 +0200 |
---|---|---|
committer | Marc Glisse <glisse@gcc.gnu.org> | 2013-04-03 09:44:28 +0000 |
commit | da694a7701bc6c2defe09cc590166de096dd26da (patch) | |
tree | ece4f79c1b1627fac4524994f1ce7a3179e31280 | |
parent | 4e7d7b3d5d5cefd5e19a736a83c3077f7c95baad (diff) | |
download | gcc-da694a7701bc6c2defe09cc590166de096dd26da.zip gcc-da694a7701bc6c2defe09cc590166de096dd26da.tar.gz gcc-da694a7701bc6c2defe09cc590166de096dd26da.tar.bz2 |
simplify-rtx.c (simplify_binary_operation_1): Handle VEC_MERGE.
2013-04-03 Marc Glisse <marc.glisse@inria.fr>
gcc/
* simplify-rtx.c (simplify_binary_operation_1) <VEC_SELECT>:
Handle VEC_MERGE.
(simplify_ternary_operation) <VEC_MERGE>: Use unsigned HOST_WIDE_INT
for masks. Test for side effects. Handle nested VEC_MERGE. Handle
equal arguments.
gcc/testsuite/
* gcc.target/i386/merge-1.c: New testcase.
* gcc.target/i386/avx2-vpblendd128-1.c: Make it non-trivial.
From-SVN: r197394
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/simplify-rtx.c | 94 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/avx2-vpblendd128-1.c | 3 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/merge-1.c | 22 |
5 files changed, 117 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1d14dd4..3377359 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2013-04-03 Marc Glisse <marc.glisse@inria.fr> + + * simplify-rtx.c (simplify_binary_operation_1) <VEC_SELECT>: + Handle VEC_MERGE. + (simplify_ternary_operation) <VEC_MERGE>: Use unsigned HOST_WIDE_INT + for masks. Test for side effects. Handle nested VEC_MERGE. Handle + equal arguments. + 2013-04-03 Jakub Jelinek <jakub@redhat.com> PR c/19449 diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index c320bcf..791f91a 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -3560,6 +3560,31 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, return vec; } + /* If we select elements in a vec_merge that all come from the same + operand, select from that operand directly. */ + if (GET_CODE (op0) == VEC_MERGE) + { + rtx trueop02 = avoid_constant_pool_reference (XEXP (op0, 2)); + if (CONST_INT_P (trueop02)) + { + unsigned HOST_WIDE_INT sel = UINTVAL (trueop02); + bool all_operand0 = true; + bool all_operand1 = true; + for (int i = 0; i < XVECLEN (trueop1, 0); i++) + { + rtx j = XVECEXP (trueop1, 0, i); + if (sel & (1 << UINTVAL (j))) + all_operand1 = false; + else + all_operand0 = false; + } + if (all_operand0 && !side_effects_p (XEXP (op0, 1))) + return simplify_gen_binary (VEC_SELECT, mode, XEXP (op0, 0), op1); + if (all_operand1 && !side_effects_p (XEXP (op0, 0))) + return simplify_gen_binary (VEC_SELECT, mode, XEXP (op0, 1), op1); + } + } + return 0; case VEC_CONCAT: { @@ -5224,7 +5249,7 @@ simplify_ternary_operation (enum rtx_code code, enum machine_mode mode, { unsigned int width = GET_MODE_PRECISION (mode); bool any_change = false; - rtx tem; + rtx tem, trueop2; /* VOIDmode means "infinite" precision. */ if (width == 0) @@ -5370,33 +5395,74 @@ simplify_ternary_operation (enum rtx_code code, enum machine_mode mode, gcc_assert (GET_MODE (op0) == mode); gcc_assert (GET_MODE (op1) == mode); gcc_assert (VECTOR_MODE_P (mode)); - op2 = avoid_constant_pool_reference (op2); - if (CONST_INT_P (op2)) + trueop2 = avoid_constant_pool_reference (op2); + if (CONST_INT_P (trueop2)) { - int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode)); + int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode)); unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size); - int mask = (1 << n_elts) - 1; + unsigned HOST_WIDE_INT sel = UINTVAL (trueop2); + unsigned HOST_WIDE_INT mask; + if (n_elts == HOST_BITS_PER_WIDE_INT) + mask = -1; + else + mask = ((unsigned HOST_WIDE_INT) 1 << n_elts) - 1; - if (!(INTVAL (op2) & mask)) + if (!(sel & mask) && !side_effects_p (op0)) return op1; - if ((INTVAL (op2) & mask) == mask) + if ((sel & mask) == mask && !side_effects_p (op1)) return op0; - op0 = avoid_constant_pool_reference (op0); - op1 = avoid_constant_pool_reference (op1); - if (GET_CODE (op0) == CONST_VECTOR - && GET_CODE (op1) == CONST_VECTOR) + rtx trueop0 = avoid_constant_pool_reference (op0); + rtx trueop1 = avoid_constant_pool_reference (op1); + if (GET_CODE (trueop0) == CONST_VECTOR + && GET_CODE (trueop1) == CONST_VECTOR) { rtvec v = rtvec_alloc (n_elts); unsigned int i; for (i = 0; i < n_elts; i++) - RTVEC_ELT (v, i) = (INTVAL (op2) & (1 << i) - ? CONST_VECTOR_ELT (op0, i) - : CONST_VECTOR_ELT (op1, i)); + RTVEC_ELT (v, i) = ((sel & ((unsigned HOST_WIDE_INT) 1 << i)) + ? CONST_VECTOR_ELT (trueop0, i) + : CONST_VECTOR_ELT (trueop1, i)); return gen_rtx_CONST_VECTOR (mode, v); } + + /* Replace (vec_merge (vec_merge a b m) c n) with (vec_merge b c n) + if no element from a appears in the result. */ + if (GET_CODE (op0) == VEC_MERGE) + { + tem = avoid_constant_pool_reference (XEXP (op0, 2)); + if (CONST_INT_P (tem)) + { + unsigned HOST_WIDE_INT sel0 = UINTVAL (tem); + if (!(sel & sel0 & mask) && !side_effects_p (XEXP (op0, 0))) + return simplify_gen_ternary (code, mode, mode, + XEXP (op0, 1), op1, op2); + if (!(sel & ~sel0 & mask) && !side_effects_p (XEXP (op0, 1))) + return simplify_gen_ternary (code, mode, mode, + XEXP (op0, 0), op1, op2); + } + } + if (GET_CODE (op1) == VEC_MERGE) + { + tem = avoid_constant_pool_reference (XEXP (op1, 2)); + if (CONST_INT_P (tem)) + { + unsigned HOST_WIDE_INT sel1 = UINTVAL (tem); + if (!(~sel & sel1 & mask) && !side_effects_p (XEXP (op1, 0))) + return simplify_gen_ternary (code, mode, mode, + op0, XEXP (op1, 1), op2); + if (!(~sel & ~sel1 & mask) && !side_effects_p (XEXP (op1, 1))) + return simplify_gen_ternary (code, mode, mode, + op0, XEXP (op1, 0), op2); + } + } } + + if (rtx_equal_p (op0, op1) + && !side_effects_p (op2) && !side_effects_p (op1)) + return op0; + break; default: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c726525..9ce315c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-04-03 Marc Glisse <marc.glisse@inria.fr> + + * gcc.target/i386/merge-1.c: New testcase. + * gcc.target/i386/avx2-vpblendd128-1.c: Make it non-trivial. + 2013-04-03 Jakub Jelinek <jakub@redhat.com> PR c/19449 diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpblendd128-1.c b/gcc/testsuite/gcc.target/i386/avx2-vpblendd128-1.c index 92f7e1b..a3fea95 100644 --- a/gcc/testsuite/gcc.target/i386/avx2-vpblendd128-1.c +++ b/gcc/testsuite/gcc.target/i386/avx2-vpblendd128-1.c @@ -5,9 +5,10 @@ #include <immintrin.h> __m128i x; +__m128i y; void extern avx2_test (void) { - x = _mm_blend_epi32 (x, x, 13); + x = _mm_blend_epi32 (x, y, 13); } diff --git a/gcc/testsuite/gcc.target/i386/merge-1.c b/gcc/testsuite/gcc.target/i386/merge-1.c new file mode 100644 index 0000000..d525685 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/merge-1.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -msse2" } */ + +#include <x86intrin.h> + +void +f (double *r, __m128d x, __m128d y, __m128d z) +{ + __m128d t=_mm_move_sd(x,y); + __m128d u=_mm_move_sd(t,z); + *r = u[0]; +} + +__m128d +g(__m128d x, __m128d y, __m128d z) +{ + __m128d t=_mm_move_sd(x,y); + __m128d u=_mm_move_sd(t,z); + return u; +} + +/* { dg-final { scan-assembler-times "movsd" 1 } } */ |