On Sat, 29 Sep 2012, Eric Botcazou wrote:
this patch lets the compiler try to rewrite:
(vec_concat (vec_select x [a]) (vec_select x [b]))
as:
vec_select x [a b]
or even just "x" if appropriate.
[...]
OK, but:
1) Always add a comment describing the simplification when you add one,
2) The condition:
+ if (GET_MODE (XEXP (trueop0, 0)) == mode
+ && INTVAL (XVECEXP (XEXP (trueop1, 1), 0, 0))
+ - INTVAL (XVECEXP (XEXP (trueop0, 1), 0, 0)) == 1)
+ return XEXP (trueop0, 0);
can be simplified: if GET_MODE (XEXP (trueop0, 0)) == mode, then XEXP
(trueop0, 0) is a 2-element vector so the only possible case is (0,1).
That would probably even be more correct since you don't test CONST_INT_P for
the indices, while the test is done in the VEC_SELECT case.
It looks like I was trying to be clever by replacing 2 understandable
tests with a single more obscure one, bad idea.
Why not generalizing to all kinds of VEC_SELECTs instead of just scalar ones?
Ok, I changed the patch a bit to handle arbitrary VEC_SELECTs, and moved
the identity recognition to VEC_SELECT handling (where it belonged).
Testing with non-scalar VEC_SELECTs was limited though, because they are
not that easy to generate. Also, the identity case is the only one where
it actually optimized. To handle more cases, I'd have to look through
several layers of VEC_SELECTs, which gets a bit complicated (for instance,
the permutation 0,1,3,2 will appear as a vec_concat of a
vec_select(v,[0,1]) and a vec_select(vec_select(v,[2,3]),[1,0]), or worse
with a vec_concat in the middle). It also didn't optimize 3,2,3,2,
possibly because that meant substituting the same rtx twice (I didn't go
that far in gdb). Then there is also the vec_duplicate case (I should try
to replace vec_duplicate with vec_concat in simplify-rtx to see what
happens...). Still, the identity case is nice to have.
Thanks for your comments.
bootstrap+testsuite on x86_64-linux-gnu with default languages.
2012-09-09 Marc Glisse <marc.gli...@inria.fr>
gcc/
* simplify-rtx.c (simplify_binary_operation_1) <VEC_SELECT>:
Detect the identity.
<VEC_CONCAT>: Handle VEC_SELECTs from the same vector.
gcc/testsuite/
* gcc.target/i386/vect-rebuild.c: New testcase.
--
Marc Glisse
Index: gcc/testsuite/gcc.target/i386/vect-rebuild.c
===================================================================
--- gcc/testsuite/gcc.target/i386/vect-rebuild.c (revision 0)
+++ gcc/testsuite/gcc.target/i386/vect-rebuild.c (revision 0)
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mavx -fno-tree-forwprop" } */
+
+typedef double v2df __attribute__ ((__vector_size__ (16)));
+typedef double v4df __attribute__ ((__vector_size__ (32)));
+
+v2df f1 (v2df x)
+{
+ v2df xx = { x[0], x[1] };
+ return xx;
+}
+
+v4df f2 (v4df x)
+{
+ v4df xx = { x[0], x[1], x[2], x[3] };
+ return xx;
+}
+
+v2df g (v2df x)
+{
+ v2df xx = { x[1], x[0] };
+ return xx;
+}
+
+v2df h (v4df x)
+{
+ v2df xx = { x[2], x[3] };
+ return xx;
+}
+
+/* { dg-final { scan-assembler-not "unpck" } } */
+/* { dg-final { scan-assembler-times "\tv?permilpd\[ \t\]" 1 } } */
+/* { dg-final { scan-assembler-times "\tv?extractf128\[ \t\]" 1 } } */
Property changes on: gcc/testsuite/gcc.target/i386/vect-rebuild.c
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision URL
Added: svn:eol-style
+ native
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c (revision 191865)
+++ gcc/simplify-rtx.c (working copy)
@@ -3239,20 +3239,37 @@ simplify_binary_operation_1 (enum rtx_co
rtx x = XVECEXP (trueop1, 0, i);
gcc_assert (CONST_INT_P (x));
RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop0,
INTVAL (x));
}
return gen_rtx_CONST_VECTOR (mode, v);
}
+ /* Recognize the identity. */
+ if (GET_MODE (trueop0) == mode)
+ {
+ bool maybe_ident = true;
+ for (int i = 0; i < XVECLEN (trueop1, 0); i++)
+ {
+ rtx j = XVECEXP (trueop1, 0, i);
+ if (!CONST_INT_P (j) || INTVAL (j) != i)
+ {
+ maybe_ident = false;
+ break;
+ }
+ }
+ if (maybe_ident)
+ return trueop0;
+ }
+
/* If we build {a,b} then permute it, build the result directly. */
if (XVECLEN (trueop1, 0) == 2
&& CONST_INT_P (XVECEXP (trueop1, 0, 0))
&& CONST_INT_P (XVECEXP (trueop1, 0, 1))
&& GET_CODE (trueop0) == VEC_CONCAT
&& GET_CODE (XEXP (trueop0, 0)) == VEC_CONCAT
&& GET_MODE (XEXP (trueop0, 0)) == mode
&& GET_CODE (XEXP (trueop0, 1)) == VEC_CONCAT
&& GET_MODE (XEXP (trueop0, 1)) == mode)
{
@@ -3364,20 +3381,38 @@ simplify_binary_operation_1 (enum rtx_co
if (!VECTOR_MODE_P (op1_mode))
RTVEC_ELT (v, i) = trueop1;
else
RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop1,
i - in_n_elts);
}
}
return gen_rtx_CONST_VECTOR (mode, v);
}
+
+ /* Try to merge 2 VEC_SELECTs from the same vector into a single one. */
+ if (GET_CODE (trueop0) == VEC_SELECT
+ && GET_CODE (trueop1) == VEC_SELECT
+ && rtx_equal_p (XEXP (trueop0, 0), XEXP (trueop1, 0)))
+ {
+ rtx par0 = XEXP (trueop0, 1);
+ rtx par1 = XEXP (trueop1, 1);
+ int len0 = XVECLEN (par0, 0);
+ int len1 = XVECLEN (par1, 0);
+ rtvec vec = rtvec_alloc (len0 + len1);
+ for (int i = 0; i < len0; i++)
+ RTVEC_ELT (vec, i) = XVECEXP (par0, 0, i);
+ for (int i = 0; i < len1; i++)
+ RTVEC_ELT (vec, len0 + i) = XVECEXP (par1, 0, i);
+ return simplify_gen_binary (VEC_SELECT, mode, XEXP (trueop0, 0),
+ gen_rtx_PARALLEL (VOIDmode, vec));
+ }
}
return 0;
default:
gcc_unreachable ();
}
return 0;
}