aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Glisse <marc.glisse@inria.fr>2013-04-03 11:44:28 +0200
committerMarc Glisse <glisse@gcc.gnu.org>2013-04-03 09:44:28 +0000
commitda694a7701bc6c2defe09cc590166de096dd26da (patch)
treeece4f79c1b1627fac4524994f1ce7a3179e31280
parent4e7d7b3d5d5cefd5e19a736a83c3077f7c95baad (diff)
downloadgcc-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/ChangeLog8
-rw-r--r--gcc/simplify-rtx.c94
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpblendd128-1.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/merge-1.c22
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 } } */