The fix for PR106329 needs a way of testing for a ptrue of a particular element size. We already had such a function for svlast, so this patch moves it to common code and generalises it to work with all kinds of vectors.
Tested on aarch64-linux-gnu & pushed. Richard gcc/ * config/aarch64/aarch64-sve-builtins.h (vector_cst_all_same): Declare. * config/aarch64/aarch64-sve-builtins.cc (vector_cst_all_same): New function, a generalized replacement of... * config/aarch64/aarch64-sve-builtins-base.cc (svlast_impl::vect_all_same): ...this. (svlast_impl::fold): Update accordingly. --- .../aarch64/aarch64-sve-builtins-base.cc | 17 ++-------------- gcc/config/aarch64/aarch64-sve-builtins.cc | 20 +++++++++++++++++++ gcc/config/aarch64/aarch64-sve-builtins.h | 2 ++ 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc b/gcc/config/aarch64/aarch64-sve-builtins-base.cc index 9010ecca6da..a6e527bedd1 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc +++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc @@ -1105,19 +1105,6 @@ public: bool is_lasta () const { return m_unspec == UNSPEC_LASTA; } bool is_lastb () const { return m_unspec == UNSPEC_LASTB; } - bool vect_all_same (tree v, int step) const - { - int i; - int nelts = vector_cst_encoded_nelts (v); - tree first_el = VECTOR_CST_ENCODED_ELT (v, 0); - - for (i = 0; i < nelts; i += step) - if (!operand_equal_p (VECTOR_CST_ENCODED_ELT (v, i), first_el, 0)) - return false; - - return true; - } - /* Fold a svlast{a/b} call with constant predicate to a BIT_FIELD_REF. BIT_FIELD_REF lowers to Advanced SIMD element extract, so we have to ensure the index of the element being accessed is in the range of a @@ -1142,7 +1129,7 @@ public: without a linear search of the predicate vector: 1. LASTA if predicate is all true, return element 0. 2. LASTA if predicate all false, return element 0. */ - if (is_lasta () && vect_all_same (pred, step_1)) + if (is_lasta () && vector_cst_all_same (pred, step_1)) { b = build3 (BIT_FIELD_REF, TREE_TYPE (f.lhs), val, bitsize_int (step * BITS_PER_UNIT), bitsize_int (0)); @@ -1152,7 +1139,7 @@ public: /* Handle the all-false case for LASTB where SVE VL == 128b - return the highest numbered element. */ if (is_lastb () && known_eq (BYTES_PER_SVE_VECTOR, 16) - && vect_all_same (pred, step_1) + && vector_cst_all_same (pred, step_1) && integer_zerop (VECTOR_CST_ENCODED_ELT (pred, 0))) { b = build3 (BIT_FIELD_REF, TREE_TYPE (f.lhs), val, diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc index 161a14edde7..b61156302cf 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins.cc +++ b/gcc/config/aarch64/aarch64-sve-builtins.cc @@ -2541,6 +2541,26 @@ function_checker::check () return shape->check (*this); } +/* Return true if V is a vector constant and if, for every in-range integer I, + element STEP*I is equal to element 0. */ +bool +vector_cst_all_same (tree v, unsigned int step) +{ + if (TREE_CODE (v) != VECTOR_CST) + return false; + + /* VECTOR_CST_NELTS_PER_PATTERN applies to any multiple of + VECTOR_CST_NPATTERNS. */ + unsigned int lcm = least_common_multiple (step, VECTOR_CST_NPATTERNS (v)); + unsigned int nelts = lcm * VECTOR_CST_NELTS_PER_PATTERN (v); + tree first_el = VECTOR_CST_ENCODED_ELT (v, 0); + for (unsigned int i = 0; i < nelts; i += step) + if (!operand_equal_p (VECTOR_CST_ENCODED_ELT (v, i), first_el, 0)) + return false; + + return true; +} + gimple_folder::gimple_folder (const function_instance &instance, tree fndecl, gimple_stmt_iterator *gsi_in, gcall *call_in) : function_call_info (gimple_location (call_in), instance, fndecl), diff --git a/gcc/config/aarch64/aarch64-sve-builtins.h b/gcc/config/aarch64/aarch64-sve-builtins.h index a301570b82e..d646df1c026 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins.h +++ b/gcc/config/aarch64/aarch64-sve-builtins.h @@ -672,6 +672,8 @@ extern tree acle_vector_types[MAX_TUPLE_SIZE][NUM_VECTOR_TYPES + 1]; extern tree acle_svpattern; extern tree acle_svprfop; +bool vector_cst_all_same (tree, unsigned int); + /* Return the ACLE type svbool_t. */ inline tree get_svbool_t (void) -- 2.25.1