This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: combine vec_perm_expr with constructor
On Sat, Sep 8, 2012 at 9:14 AM, Marc Glisse <marc.glisse@inria.fr> wrote:
> On Mon, 3 Sep 2012, Richard Guenther wrote:
>
>> You do work above and then bail late here. Always do early exists early
>> to reduce useless compile-time.
>
> [...]
>
>> You need to verify that fold_ternary returns something that is valid
>> GIMPLE.
>> fold () in general happily returns trees that are in the need of
>> re-gimplification.
>> You expect a CONSTRUCTOR or VECTOR_CST here, so you should check
>> for that.
>
>
> Hello,
>
> here is a new version of the patch, again tested on x86_64-linux-gnu.
Ok.
Thanks,
Richard.
> 2012-09-08 Marc Glisse <marc.glisse@inria.fr>
>
>
> gcc/
> * tree-ssa-forwprop.c (simplify_permutation): Handle CONSTRUCTOR.
>
> gcc/testsuite/
> * gcc.dg/tree-ssa/forwprop-20.c: New testcase.
>
>
> --
> Marc Glisse
>
> Index: gcc/testsuite/gcc.dg/tree-ssa/forwprop-20.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/tree-ssa/forwprop-20.c (revision 0)
> +++ gcc/testsuite/gcc.dg/tree-ssa/forwprop-20.c (revision 0)
> @@ -0,0 +1,70 @@
> +/* { dg-do compile } */
> +/* { dg-require-effective-target double64 } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +
> +#include <stdint.h>
> +
> +/* All of these optimizations happen for unsupported vector modes as a
> + consequence of the lowering pass. We need to test with a vector mode
> + that is supported by default on at least some architectures, or make
> + the test target specific so we can pass a flag like -mavx. */
> +
> +typedef double vecf __attribute__ ((vector_size (2 * sizeof (double))));
> +typedef int64_t veci __attribute__ ((vector_size (2 * sizeof (int64_t))));
> +
> +void f (double d, vecf* r)
> +{
> + vecf x = { -d, 5 };
> + vecf y = { 1, 4 };
> + veci m = { 2, 0 };
> + *r = __builtin_shuffle (x, y, m); // { 1, -d }
> +}
> +
> +void g (float d, vecf* r)
> +{
> + vecf x = { d, 5 };
> + vecf y = { 1, 4 };
> + veci m = { 2, 1 };
> + *r = __builtin_shuffle (x, y, m); // { 1, 5 }
> +}
> +
> +void h (double d, vecf* r)
> +{
> + vecf x = { d + 1, 5 };
> + vecf y = { 1 , 4 };
> + veci m = { 2 , 0 };
> + *r = __builtin_shuffle (y, x, m); // { d + 1, 1 }
> +}
> +
> +void i (float d, vecf* r)
> +{
> + vecf x = { d, 5 };
> + veci m = { 1, 0 };
> + *r = __builtin_shuffle (x, m); // { 5, d }
> +}
> +
> +void j (vecf* r)
> +{
> + vecf y = { 1, 2 };
> + veci m = { 0, 0 };
> + *r = __builtin_shuffle (y, m); // { 1, 1 }
> +}
> +
> +void k (vecf* r)
> +{
> + vecf x = { 3, 4 };
> + vecf y = { 1, 2 };
> + veci m = { 3, 0 };
> + *r = __builtin_shuffle (x, y, m); // { 2, 3 }
> +}
> +
> +void l (double d, vecf* r)
> +{
> + vecf x = { -d, 5 };
> + vecf y = { d, 4 };
> + veci m = { 2, 0 };
> + *r = __builtin_shuffle (x, y, m); // { d, -d }
> +}
> +
> +/* { dg-final { scan-tree-dump-not "VEC_PERM_EXPR" "optimized" } } */
> +/* { dg-final { cleanup-tree-dump "optimized" } } */
>
> Property changes on: gcc/testsuite/gcc.dg/tree-ssa/forwprop-20.c
> ___________________________________________________________________
> Added: svn:eol-style
> + native
> Added: svn:keywords
> + Author Date Id Revision URL
>
> Index: gcc/tree-ssa-forwprop.c
> ===================================================================
> --- gcc/tree-ssa-forwprop.c (revision 191082)
> +++ gcc/tree-ssa-forwprop.c (working copy)
> @@ -2599,75 +2599,134 @@ is_combined_permutation_identity (tree m
> if (j == i)
> maybe_identity2 = false;
> else if (j == i + nelts)
> maybe_identity1 = false;
> else
> return 0;
> }
> return maybe_identity1 ? 1 : maybe_identity2 ? 2 : 0;
> }
>
> -/* Combine two shuffles in a row. Returns 1 if there were any changes
> - made, 2 if cfg-cleanup needs to run. Else it returns 0. */
> +/* Combine a shuffle with its arguments. Returns 1 if there were any
> + changes made, 2 if cfg-cleanup needs to run. Else it returns 0. */
>
> static int
> simplify_permutation (gimple_stmt_iterator *gsi)
> {
> gimple stmt = gsi_stmt (*gsi);
> gimple def_stmt;
> - tree op0, op1, op2, op3;
> - enum tree_code code = gimple_assign_rhs_code (stmt);
> - enum tree_code code2;
> + tree op0, op1, op2, op3, arg0, arg1;
> + enum tree_code code;
>
> - gcc_checking_assert (code == VEC_PERM_EXPR);
> + gcc_checking_assert (gimple_assign_rhs_code (stmt) == VEC_PERM_EXPR);
>
> op0 = gimple_assign_rhs1 (stmt);
> op1 = gimple_assign_rhs2 (stmt);
> op2 = gimple_assign_rhs3 (stmt);
>
> - if (TREE_CODE (op0) != SSA_NAME)
> - return 0;
> -
> if (TREE_CODE (op2) != VECTOR_CST)
> return 0;
>
> - if (op0 != op1)
> - return 0;
> + if (TREE_CODE (op0) == VECTOR_CST)
> + {
> + code = VECTOR_CST;
> + arg0 = op0;
> + }
> + else if (TREE_CODE (op0) == SSA_NAME)
> + {
> + def_stmt = SSA_NAME_DEF_STMT (op0);
> + if (!def_stmt || !is_gimple_assign (def_stmt)
> + || !can_propagate_from (def_stmt))
> + return 0;
>
> - def_stmt = SSA_NAME_DEF_STMT (op0);
> - if (!def_stmt || !is_gimple_assign (def_stmt)
> - || !can_propagate_from (def_stmt))
> + code = gimple_assign_rhs_code (def_stmt);
> + arg0 = gimple_assign_rhs1 (def_stmt);
> + }
> + else
> return 0;
>
> - code2 = gimple_assign_rhs_code (def_stmt);
> -
> /* Two consecutive shuffles. */
> - if (code2 == VEC_PERM_EXPR)
> + if (code == VEC_PERM_EXPR)
> {
> tree orig;
> int ident;
> +
> + if (op0 != op1)
> + return 0;
> op3 = gimple_assign_rhs3 (def_stmt);
> if (TREE_CODE (op3) != VECTOR_CST)
> return 0;
> ident = is_combined_permutation_identity (op3, op2);
> if (!ident)
> return 0;
> orig = (ident == 1) ? gimple_assign_rhs1 (def_stmt)
> : gimple_assign_rhs2 (def_stmt);
> gimple_assign_set_rhs1 (stmt, unshare_expr (orig));
> gimple_assign_set_rhs_code (stmt, TREE_CODE (orig));
> gimple_set_num_ops (stmt, 2);
> update_stmt (stmt);
> return remove_prop_source_from_use (op0) ? 2 : 1;
> }
>
> - return false;
> + /* Shuffle of a constructor. */
> + else if (code == CONSTRUCTOR || code == VECTOR_CST)
> + {
> + tree opt;
> + bool ret = false;
> + if (op0 != op1)
> + {
> + if (TREE_CODE (op0) == SSA_NAME && !has_single_use (op0))
> + return 0;
> +
> + if (TREE_CODE (op1) == VECTOR_CST)
> + arg1 = op1;
> + else if (TREE_CODE (op1) == SSA_NAME)
> + {
> + enum tree_code code2;
> +
> + if (!has_single_use (op1))
> + return 0;
> +
> + gimple def_stmt2 = SSA_NAME_DEF_STMT (op1);
> + if (!def_stmt2 || !is_gimple_assign (def_stmt2)
> + || !can_propagate_from (def_stmt2))
> + return 0;
> +
> + code2 = gimple_assign_rhs_code (def_stmt2);
> + if (code2 != CONSTRUCTOR && code2 != VECTOR_CST)
> + return 0;
> + arg1 = gimple_assign_rhs1 (def_stmt2);
> + }
> + else
> + return 0;
> + }
> + else
> + {
> + /* Already used twice in this statement. */
> + if (TREE_CODE (op0) == SSA_NAME && num_imm_uses (op0) > 2)
> + return 0;
> + arg1 = arg0;
> + }
> + opt = fold_ternary (VEC_PERM_EXPR, TREE_TYPE(op0), arg0, arg1, op2);
> + if (!opt
> + || (TREE_CODE (opt) != CONSTRUCTOR && TREE_CODE(opt) !=
> VECTOR_CST))
> + return 0;
> + gimple_assign_set_rhs_from_tree (gsi, opt);
> + update_stmt (gsi_stmt (*gsi));
> + if (TREE_CODE (op0) == SSA_NAME)
> + ret = remove_prop_source_from_use (op0);
> + if (op0 != op1 && TREE_CODE (op1) == SSA_NAME)
> + ret |= remove_prop_source_from_use (op1);
> + return ret ? 2 : 1;
> + }
> +
> + return 0;
> }
>
> /* Main entry point for the forward propagation and statement combine
> optimizer. */
>
> static unsigned int
> ssa_forward_propagate_and_combine (void)
> {
> basic_block bb;
> unsigned int todoflags = 0;
>