From 84c3c7ce881a20095532baff121d38848efe2a0a Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 10 Sep 2012 18:23:02 +0200 Subject: [PATCH] tree-ssa-forwprop.c (simplify_permutation): Handle CONSTRUCTOR. 2012-09-10 Marc Glisse gcc/ * tree-ssa-forwprop.c (simplify_permutation): Handle CONSTRUCTOR. gcc/testsuite/ * gcc.dg/tree-ssa/forwprop-20.c: New testcase. From-SVN: r191151 --- gcc/ChangeLog | 4 ++ gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gcc.dg/tree-ssa/forwprop-20.c | 70 +++++++++++++++++++++ gcc/tree-ssa-forwprop.c | 95 +++++++++++++++++++++++------ 4 files changed, 155 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/forwprop-20.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f189aa9..c550f8b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2012-09-10 Marc Glisse + + * tree-ssa-forwprop.c (simplify_permutation): Handle CONSTRUCTOR. + 2012-09-10 Martin Jambor * params.def (PARAM_IPA_MAX_AGG_ITEMS): New parameter. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bd4b362..720e711 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2012-09-10 Marc Glisse + + * gcc.dg/tree-ssa/forwprop-20.c: New testcase. + 2012-09-10 Richard Guenther PR tree-optimization/54520 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-20.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-20.c new file mode 100644 index 0000000..5b0e8ee --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-20.c @@ -0,0 +1,70 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target double64 } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +#include + +/* 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" } } */ diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index 3f5b2f9..72217ec 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -2606,45 +2606,52 @@ is_combined_permutation_identity (tree mask1, tree mask2) 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; @@ -2660,7 +2667,59 @@ simplify_permutation (gimple_stmt_iterator *gsi) 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 -- 2.7.4