From: Artem Shinkarov <artyom.shinkaroff@gmail.com>
To: Richard Henderson <rth@redhat.com>
Cc: Nathan Froyd <froydnj@codesourcery.com>,
Richard Guenther <richard.guenther@gmail.com>,
gcc-patches@gcc.gnu.org,
"Joseph S. Myers" <joseph@codesourcery.com>
Subject: Re: Fold vector to scalar optimization
Date: Wed, 03 Nov 2010 18:20:00 -0000 [thread overview]
Message-ID: <AANLkTikABMEBRuOfMpPCPAJ783BfLJEJnyYxKy_O304J@mail.gmail.com> (raw)
In-Reply-To: <4CD18D05.2040707@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 1170 bytes --]
ChangeLog:
2010-11-01 Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
gcc/
* passes.c (init_optimization_passes): Move veclower after SSA.
* tree-vect-generic.c (expand_vector_operations_1): Handle conversion.
gcc/testsuite/
* gcc.dg/vec-scal-opt.c: New testcase.
* gcc.dg/vec-scal-opt1.c: New testcase.
* gcc.dg/vec-scal-opt2.c: New testcase.
On Wed, Nov 3, 2010 at 4:25 PM, Richard Henderson <rth@redhat.com> wrote:
>> + if (vector_scalar_shift
>> + && ((TREE_CODE (rhs2) == VECTOR_CST && (var = rhs2))
>> + ||
>> + (TREE_CODE (rhs2) == SSA_NAME
>> + && (def_stmt = SSA_NAME_DEF_STMT (rhs2))
>> + && gimple_assign_single_p (def_stmt)
>> + && (var = gimple_assign_rhs1 (def_stmt))))
>> + && uniform_vector_p (var, &first))
>> + {
>> + gimple_assign_set_rhs2 (stmt, first);
>> + update_stmt (stmt);
>> + rhs2 = first;
>> + }
>
> Fix the indentation on the { } block and the patch is ok.
>
>
> r~
>
[-- Attachment #2: vec-scal-opt.c.v5.diff --]
[-- Type: text/x-diff, Size: 7583 bytes --]
Index: gcc/testsuite/gcc.dg/vec-scal-opt2.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt2.c (revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt2.c (revision 0)
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-veclower" } */
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define vector(elcount, type) \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[]) {
+ vector(8, short) v0 = {argc,1,2,3,4,5,6,7};
+ vector(8, short) v1 = {2,2,2,2,2,2,2,2};
+ vector(8, short) r1;
+
+ r1 = v0 >> v1;
+
+ return vidx(short, r1, 0);
+}
+
+/* { dg-final { scan-tree-dump-times ">> 2" 1 "veclower" } } */
+/* { dg-final { cleanup-tree-dump "veclower" } } */
Index: gcc/testsuite/gcc.dg/vec-scal-opt.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt.c (revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt.c (revision 0)
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-veclower" } */
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define vector(elcount, type) \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+short k;
+
+int main (int argc, char *argv[]) {
+ k = argc;
+ vector(8, short) v0 = {argc,1,2,3,4,5,6,7};
+ vector(8, short) v2 = {k, k,k,k,k,k,k,k};
+ vector(8, short) r1;
+
+ r1 = v0 >> v2;
+
+ return vidx(short, r1, 0);
+}
+
+/* { dg-final { scan-tree-dump-times ">> k.\[0-9_\]*" 1 "veclower" } } */
+/* { dg-final { cleanup-tree-dump "veclower" } } */
Index: gcc/testsuite/gcc.dg/vec-scal-opt1.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt1.c (revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt1.c (revision 0)
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-veclower" } */
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define vector(elcount, type) \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+short k;
+
+int main (int argc, char *argv[]) {
+ vector(8, short) v0 = {argc,1,2,3,4,5,6,7};
+ vector(8, short) r1;
+
+ r1 = v0 >> (vector(8, short)){2,2,2,2,2,2,2,2};
+
+ return vidx(short, r1, 0);
+}
+
+/* { dg-final { scan-tree-dump-times ">> 2" 1 "veclower" } } */
+/* { dg-final { cleanup-tree-dump "veclower" } } */
Index: gcc/tree-vect-generic.c
===================================================================
--- gcc/tree-vect-generic.c (revision 166249)
+++ gcc/tree-vect-generic.c (working copy)
@@ -284,6 +284,62 @@ expand_vector_addition (gimple_stmt_iter
a, b, code);
}
+/* Check if vector VEC consists of all the equal elements and
+ that the number of elements corresponds to the type of VEC.
+ Function sets ELEMENT with the first element of the vector
+ or NULL_TREE if comparison failed. */
+static bool uniform_vector_p (tree vec, tree *element)
+{
+ tree first, t, els;
+ bool eq = true;
+ unsigned HOST_WIDE_INT i;
+
+ *element = NULL_TREE;
+
+ if (vec == NULL_TREE)
+ return false;
+
+ if (TREE_CODE (vec) == VECTOR_CST)
+ {
+ els = TREE_VECTOR_CST_ELTS (vec);
+ first = TREE_VALUE (els);
+ els = TREE_CHAIN (els);
+
+ for (t = els, i = 0; t; t = TREE_CHAIN (t), i++)
+ {
+ eq = operand_equal_p (first, TREE_VALUE(t), 0);
+ if (!eq)
+ break;
+ }
+
+ *element = first;
+ return eq && (i == TYPE_VECTOR_SUBPARTS (TREE_TYPE (vec))-1);
+ }
+
+ else if (TREE_CODE (vec) == CONSTRUCTOR)
+ {
+ first = error_mark_node;
+
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (vec), i, t)
+ {
+ if (i == 0)
+ {
+ first = t;
+ continue;
+ }
+ eq = (first == t);
+ if (!eq)
+ break;
+ }
+
+ *element = first;
+ return eq && (i == TYPE_VECTOR_SUBPARTS (TREE_TYPE (vec)));
+
+ }
+
+ return false;
+}
+
static tree
expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
gimple assign, enum tree_code code)
@@ -392,7 +448,7 @@ expand_vector_operations_1 (gimple_stmt_
tree lhs, rhs1, rhs2 = NULL, type, compute_type;
enum tree_code code;
enum machine_mode compute_mode;
- optab op;
+ optab op = NULL;
enum gimple_rhs_class rhs_class;
tree new_rhs;
@@ -434,18 +490,45 @@ expand_vector_operations_1 (gimple_stmt_
|| code == LROTATE_EXPR
|| code == RROTATE_EXPR)
{
- /* If the 2nd argument is vector, we need a vector/vector shift */
+ bool vector_scalar_shift;
+ op = optab_for_tree_code (code, type, optab_scalar);
+
+ /* Vector/Scalar shift is supported. */
+ vector_scalar_shift = !(!op
+ || optab_handler (op, TYPE_MODE (type))
+ == CODE_FOR_nothing);
+
+ /* If the 2nd argument is vector, we need a vector/vector shift.
+ Except all the elements in the second vector are the same. */
if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs2))))
- op = optab_for_tree_code (code, type, optab_vector);
- else
- {
- /* Try for a vector/scalar shift, and if we don't have one, see if we
- have a vector/vector shift */
- op = optab_for_tree_code (code, type, optab_scalar);
- if (!op
- || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
- op = optab_for_tree_code (code, type, optab_vector);
- }
+ {
+ tree first, var = NULL_TREE;
+ gimple def_stmt;
+
+ /* Check whether we have vector <op> {x,x,x,x} where x
+ could be a scalar variable or a constant. Transform
+ vector <op> {x,x,x,x} ==> vector <op> scalar. */
+ if (vector_scalar_shift
+ && ((TREE_CODE (rhs2) == VECTOR_CST && (var = rhs2))
+ ||
+ (TREE_CODE (rhs2) == SSA_NAME
+ && (def_stmt = SSA_NAME_DEF_STMT (rhs2))
+ && gimple_assign_single_p (def_stmt)
+ && (var = gimple_assign_rhs1 (def_stmt))))
+ && uniform_vector_p (var, &first))
+ {
+ gimple_assign_set_rhs2 (stmt, first);
+ update_stmt (stmt);
+ rhs2 = first;
+ }
+ else
+ op = optab_for_tree_code (code, type, optab_vector);
+ }
+
+ /* Try for a vector/scalar shift, and if we don't have one, see if we
+ have a vector/vector shift */
+ else if (!vector_scalar_shift)
+ op = optab_for_tree_code (code, type, optab_vector);
}
else
op = optab_for_tree_code (code, type, optab_default);
Index: gcc/passes.c
===================================================================
--- gcc/passes.c (revision 166249)
+++ gcc/passes.c (working copy)
@@ -736,7 +736,6 @@ init_optimization_passes (void)
NEXT_PASS (pass_refactor_eh);
NEXT_PASS (pass_lower_eh);
NEXT_PASS (pass_build_cfg);
- NEXT_PASS (pass_lower_vector);
NEXT_PASS (pass_warn_function_return);
NEXT_PASS (pass_build_cgraph_edges);
NEXT_PASS (pass_inline_parameters);
@@ -755,6 +754,7 @@ init_optimization_passes (void)
NEXT_PASS (pass_referenced_vars);
NEXT_PASS (pass_build_ssa);
+ NEXT_PASS (pass_lower_vector);
NEXT_PASS (pass_early_warn_uninitialized);
/* Note that it is not strictly necessary to schedule an early
inline pass here. However, some test cases (e.g.,
next prev parent reply other threads:[~2010-11-03 18:12 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-11-01 20:21 Artem Shinkarov
2010-11-02 11:04 ` Richard Guenther
2010-11-02 16:20 ` Artem Shinkarov
2010-11-02 18:58 ` Richard Henderson
2010-11-03 11:47 ` Artem Shinkarov
2010-11-03 12:18 ` Nathan Froyd
2010-11-03 13:23 ` Artem Shinkarov
2010-11-03 16:26 ` Richard Henderson
2010-11-03 18:20 ` Artem Shinkarov [this message]
2010-11-03 21:09 ` Richard Guenther
2010-11-05 11:34 ` Ramana Radhakrishnan
-- strict thread matches above, loose matches on Subject: below --
2010-06-18 16:25 Artem Shinkarov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=AANLkTikABMEBRuOfMpPCPAJ783BfLJEJnyYxKy_O304J@mail.gmail.com \
--to=artyom.shinkaroff@gmail.com \
--cc=froydnj@codesourcery.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=joseph@codesourcery.com \
--cc=richard.guenther@gmail.com \
--cc=rth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).