From patchwork Mon Nov 1 20:11:31 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Artem Shinkarov X-Patchwork-Id: 69833 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id DE6FB1007D2 for ; Tue, 2 Nov 2010 07:12:05 +1100 (EST) Received: (qmail 5608 invoked by alias); 1 Nov 2010 20:12:02 -0000 Received: (qmail 5592 invoked by uid 22791); 1 Nov 2010 20:11:58 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, TW_TM, T_TO_NO_BRKTS_FREEMAIL X-Spam-Check-By: sourceware.org Received: from mail-vw0-f47.google.com (HELO mail-vw0-f47.google.com) (209.85.212.47) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 01 Nov 2010 20:11:53 +0000 Received: by vws17 with SMTP id 17so4298515vws.20 for ; Mon, 01 Nov 2010 13:11:51 -0700 (PDT) Received: by 10.224.28.207 with SMTP id n15mr8446378qac.139.1288642311310; Mon, 01 Nov 2010 13:11:51 -0700 (PDT) MIME-Version: 1.0 Received: by 10.229.4.25 with HTTP; Mon, 1 Nov 2010 13:11:31 -0700 (PDT) From: Artem Shinkarov Date: Mon, 1 Nov 2010 20:11:31 +0000 Message-ID: Subject: Fold vector to scalar optimization To: gcc-patches@gcc.gnu.org Cc: "Joseph S. Myers" , Richard Guenther X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org This patch folds a vector of equal values to the scalar in vector-shift operation. ChangeLog: 2010-11-01 Artjoms Sinkarovs 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. bootstrapped and tested on x86_64_unknown-linux OK? 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,2,3,4,5,6,7}; + vector(8, short) v1 = {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,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,2,3,4,5,6,7}; + vector(8, short) r1; + + r1 = v0 >> (vector(8, short)){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 166126) +++ gcc/tree-vect-generic.c (working copy) @@ -392,7 +392,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; @@ -436,8 +436,72 @@ expand_vector_operations_1 (gimple_stmt_ { /* If the 2nd argument is vector, we need a vector/vector shift */ if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs2)))) - op = optab_for_tree_code (code, type, optab_vector); - else + { + /* Chack whether we have vector {x,x,x,x} where x + could be a scalar variable or a constant. Transform + vector {x,x,x,x} ==> vector scalar. */ + if (TREE_CODE (rhs2) == SSA_NAME + && TREE_CODE (TREE_TYPE (rhs2)) == VECTOR_TYPE) + { + gimple def_stmt; + def_stmt = SSA_NAME_DEF_STMT (rhs2); + + if (gimple_assign_single_p (def_stmt)) + { + tree var = gimple_assign_rhs1 (def_stmt); + + /* Check for {cst,cst,cst,...} case. */ + if (TREE_CODE (var) == VECTOR_CST) + { + tree first, t, els = TREE_VECTOR_CST_ELTS (var); + bool eq = true; + + first = TREE_VALUE (els); + els = TREE_CHAIN (els); + + for (t = els; t; t = TREE_CHAIN (t)) + if (!(eq = operand_equal_p (first, TREE_VALUE(t), 0))) + break; + + if (eq) /* All the elements are the same. */ + { + gimple_assign_set_rhs2 (stmt, first); + update_stmt (stmt); + rhs2 = first; + } + } + /* Check for {x,x,x,...} case. */ + else if (TREE_CODE (var) == CONSTRUCTOR) + { + tree t, first = error_mark_node; + bool eq = true; + unsigned HOST_WIDE_INT i; + + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (var), i, t) + { + if (i == 0) + { + first = t; + continue; + } + if (!(eq = (first == t))) + break; + } + + if (eq) /* All the elements are the same. */ + { + gimple_assign_set_rhs2 (stmt, first); + update_stmt (stmt); + rhs2 = first; + } + } + } + } + else + op = optab_for_tree_code (code, type, optab_vector); + } + + if (!VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs2)))) { /* Try for a vector/scalar shift, and if we don't have one, see if we have a vector/vector shift */ Index: gcc/passes.c =================================================================== --- gcc/passes.c (revision 166126) +++ 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.,