From ebd733a78ccf5792067e94852c6c81a5f9aa0020 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Mon, 20 May 2019 10:33:54 +0000 Subject: [PATCH] gimple-match-head.c: Include vec-perm-indices.h. 2019-05-20 Richard Biener * gimple-match-head.c: Include vec-perm-indices.h. * generic-match-head.c: Likewise. * fold-const.h (fold_vec_perm): Declare when vec-perm-indices.h is included. * fold-const.c (fold_vec_perm): Export. (fold_ternary_loc): Move non-constant folding of VEC_PERM_EXPR... (match.pd): ...here. From-SVN: r271404 --- gcc/ChangeLog | 10 +++++ gcc/fold-const.c | 63 +++--------------------------- gcc/fold-const.h | 3 ++ gcc/generic-match-head.c | 1 + gcc/gimple-match-head.c | 1 + gcc/match.pd | 83 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 104 insertions(+), 57 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 682d5f75e6c..920ea6ffa65 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2019-05-20 Richard Biener + + * gimple-match-head.c: Include vec-perm-indices.h. + * generic-match-head.c: Likewise. + * fold-const.h (fold_vec_perm): Declare when vec-perm-indices.h + is included. + * fold-const.c (fold_vec_perm): Export. + (fold_ternary_loc): Move non-constant folding of VEC_PERM_EXPR... + (match.pd): ...here. + 2019-05-20 Jakub Jelinek * cfgloop.h (struct loop): Add simdlen member. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index c4257721cfe..34448524050 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -9015,7 +9015,7 @@ vec_cst_ctor_to_array (tree arg, unsigned int nelts, tree *elts) selector. Return the folded VECTOR_CST or CONSTRUCTOR if successful, NULL_TREE otherwise. */ -static tree +tree fold_vec_perm (tree type, tree arg0, tree arg1, const vec_perm_indices &sel) { unsigned int i; @@ -11763,7 +11763,10 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type, return NULL_TREE; case VEC_PERM_EXPR: - if (TREE_CODE (arg2) == VECTOR_CST) + /* Perform constant folding of BIT_INSERT_EXPR. */ + if (TREE_CODE (arg2) == VECTOR_CST + && TREE_CODE (op0) == VECTOR_CST + && TREE_CODE (op1) == VECTOR_CST) { /* Build a vector of integers from the tree mask. */ vec_perm_builder builder; @@ -11774,61 +11777,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type, poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (type); bool single_arg = (op0 == op1); vec_perm_indices sel (builder, single_arg ? 1 : 2, nelts); - - /* Check for cases that fold to OP0 or OP1 in their original - element order. */ - if (sel.series_p (0, 1, 0, 1)) - return op0; - if (sel.series_p (0, 1, nelts, 1)) - return op1; - - if (!single_arg) - { - if (sel.all_from_input_p (0)) - op1 = op0; - else if (sel.all_from_input_p (1)) - { - op0 = op1; - sel.rotate_inputs (1); - } - } - - if ((TREE_CODE (op0) == VECTOR_CST - || TREE_CODE (op0) == CONSTRUCTOR) - && (TREE_CODE (op1) == VECTOR_CST - || TREE_CODE (op1) == CONSTRUCTOR)) - { - tree t = fold_vec_perm (type, op0, op1, sel); - if (t != NULL_TREE) - return t; - } - - bool changed = (op0 == op1 && !single_arg); - - /* Generate a canonical form of the selector. */ - if (arg2 == op2 && sel.encoding () != builder) - { - /* Some targets are deficient and fail to expand a single - argument permutation while still allowing an equivalent - 2-argument version. */ - if (sel.ninputs () == 2 - || can_vec_perm_const_p (TYPE_MODE (type), sel, false)) - op2 = vec_perm_indices_to_tree (TREE_TYPE (arg2), sel); - else - { - vec_perm_indices sel2 (builder, 2, nelts); - if (can_vec_perm_const_p (TYPE_MODE (type), sel2, false)) - op2 = vec_perm_indices_to_tree (TREE_TYPE (arg2), sel2); - else - /* Not directly supported with either encoding, - so use the preferred form. */ - op2 = vec_perm_indices_to_tree (TREE_TYPE (arg2), sel); - } - changed = true; - } - - if (changed) - return build3_loc (loc, VEC_PERM_EXPR, type, op0, op1, op2); + return fold_vec_perm (type, op0, op1, sel); } return NULL_TREE; diff --git a/gcc/fold-const.h b/gcc/fold-const.h index 049fee91876..c4b7cbfbdba 100644 --- a/gcc/fold-const.h +++ b/gcc/fold-const.h @@ -100,6 +100,9 @@ extern tree fold_bit_and_mask (tree, tree, enum tree_code, tree, enum tree_code, tree, tree, tree, enum tree_code, tree, tree, tree *); extern tree fold_read_from_constant_string (tree); +#if GCC_VEC_PERN_INDICES_H +extern tree fold_vec_perm (tree, tree, tree, const vec_perm_indices &); +#endif extern bool wide_int_binop (wide_int &res, enum tree_code, const wide_int &arg1, const wide_int &arg2, signop, wi::overflow_type *); diff --git a/gcc/generic-match-head.c b/gcc/generic-match-head.c index a46f375017b..76fc9993481 100644 --- a/gcc/generic-match-head.c +++ b/gcc/generic-match-head.c @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple.h" #include "ssa.h" #include "cgraph.h" +#include "vec-perm-indices.h" #include "fold-const.h" #include "stor-layout.h" #include "tree-dfa.h" diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c index bbbc0f2c28b..f83f2256178 100644 --- a/gcc/gimple-match-head.c +++ b/gcc/gimple-match-head.c @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple.h" #include "ssa.h" #include "cgraph.h" +#include "vec-perm-indices.h" #include "fold-const.h" #include "fold-const-call.h" #include "stor-layout.h" diff --git a/gcc/match.pd b/gcc/match.pd index 29c94e01f7d..9ff52123cd9 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -5374,3 +5374,86 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (bit_and:elt_type (BIT_FIELD_REF:elt_type @0 { size; } { pos; }) { elt; }))))))) + +(simplify + (vec_perm @0 @1 VECTOR_CST@2) + (with + { + tree op0 = @0, op1 = @1, op2 = @2; + + /* Build a vector of integers from the tree mask. */ + vec_perm_builder builder; + if (!tree_to_vec_perm_builder (&builder, op2)) + return NULL_TREE; + + /* Create a vec_perm_indices for the integer vector. */ + poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (type); + bool single_arg = (op0 == op1); + vec_perm_indices sel (builder, single_arg ? 1 : 2, nelts); + } + (if (sel.series_p (0, 1, 0, 1)) + { op0; } + (if (sel.series_p (0, 1, nelts, 1)) + { op1; } + (with + { + if (!single_arg) + { + if (sel.all_from_input_p (0)) + op1 = op0; + else if (sel.all_from_input_p (1)) + { + op0 = op1; + sel.rotate_inputs (1); + } + } + gassign *def; + tree cop0 = op0, cop1 = op1; + if (TREE_CODE (op0) == SSA_NAME + && (def = dyn_cast (SSA_NAME_DEF_STMT (op0))) + && gimple_assign_rhs_code (def) == CONSTRUCTOR) + cop0 = gimple_assign_rhs1 (def); + if (TREE_CODE (op1) == SSA_NAME + && (def = dyn_cast (SSA_NAME_DEF_STMT (op1))) + && gimple_assign_rhs_code (def) == CONSTRUCTOR) + cop1 = gimple_assign_rhs1 (def); + + tree t; + } + (if ((TREE_CODE (cop0) == VECTOR_CST + || TREE_CODE (cop0) == CONSTRUCTOR) + && (TREE_CODE (cop1) == VECTOR_CST + || TREE_CODE (cop1) == CONSTRUCTOR) + && (t = fold_vec_perm (type, cop0, cop1, sel))) + { t; } + (with + { + bool changed = (op0 == op1 && !single_arg); + + /* Generate a canonical form of the selector. */ + if (sel.encoding () != builder) + { + /* Some targets are deficient and fail to expand a single + argument permutation while still allowing an equivalent + 2-argument version. */ + tree oldop2 = op2; + if (sel.ninputs () == 2 + || can_vec_perm_const_p (TYPE_MODE (type), sel, false)) + op2 = vec_perm_indices_to_tree (TREE_TYPE (op2), sel); + else + { + vec_perm_indices sel2 (builder, 2, nelts); + if (can_vec_perm_const_p (TYPE_MODE (type), sel2, false)) + op2 = vec_perm_indices_to_tree (TREE_TYPE (op2), sel2); + else + /* Not directly supported with either encoding, + so use the preferred form. */ + op2 = vec_perm_indices_to_tree (TREE_TYPE (op2), sel); + } + /* Differences in the encoder do not necessarily mean + differences in the resulting vector. */ + changed = !operand_equal_p (op2, oldop2, 0); + } + } + (if (changed) + (vec_perm { op0; } { op1; } { op2; }))))))))) -- 2.30.2