Kyrylo Tkachov <[email protected]> writes: >> On 28 Aug 2026, at 11:41, Richard Sandiford >> <[email protected]> wrote: >> >> Richard Sandiford <[email protected]> writes: >>> <[email protected]> writes: >>>> From: Kyrylo Tkachov <[email protected]> >>>> >>>> REDUC_MAX, REDUC_MIN, REDUC_AND and REDUC_IOR are idempotent. A >>>> reduction of a nonempty duplicate vector with one of these operations is >>>> the duplicated element: >>>> >>>> v = [vec_duplicate_expr] x; >>>> res = .REDUC_MAX (v); >>>> >>>> becomes: >>>> >>>> res = x; >>>> >>>> For example, the new SVE test contains: >>>> >>>> int __GIMPLE () >>>> reduc_max (int x) >>>> { >>>> svint32_t v; >>>> int res; >>>> >>>> v = svdup_s32 (x); >>>> res = .REDUC_MAX (v); >>>> return res; >>>> } >>>> >>>> With -O2 -fgimple -march=armv8.2-a+sve, the code changes from: >>>> >>>> reduc_max: >>>> mov z31.s, w0 >>>> ptrue p7.b, all >>>> smaxv s31, p7, z31.s >>>> fmov w0, s31 >>>> ret >>>> >>>> to: >>>> >>>> reduc_max: >>>> ret >>>> >>>> An XOR reduction of a duplicate vector is zero when the number of lanes >>>> is even. GCC permits variable-length vectors whose lane count has >>>> unknown parity, such as [1, 1]. Fold REDUC_XOR only when multiple_p >>>> proves that every possible lane count has the required parity. >>>> >>>> Use the same two paths as IFN_VEC_EXTRACT and IFN_VEC_SHL_INSERT. Match >>>> a nonconstant VEC_DUPLICATE_EXPR directly in match.pd. Handle a >>>> VECTOR_CST in fold_const_reduction. >>>> >>>> Start constant folding with the explicitly encoded elements for both >>>> fixed-length and variable-length vectors. A non-stepped encoding can be >>>> used for an idempotent reduction when every encoded element is guaranteed >>>> to be present. For XOR, require the remaining encoded copies to cancel >>>> in pairs. Process two periods of a duplicate encoding, or the foreground >>>> and background of a two-element-per-pattern encoding. Use the exact >>>> element count as a fallback when it is known. >>>> >>>> Keep REDUC_MAX and REDUC_MIN when a shortened reduction could return a >>>> signaling NaN directly. The full reduction can quiet the NaN and raise an >>>> invalid-operation exception. >>>> >>>> These folds also let the constant reduction in the PR 127039 rule >>>> simplify for scalable constants. The scalar result cannot match the >>>> inverse reduction-pair rule, so the nontermination cycle stays blocked. >>>> >>>> Bootstrapped and tested on aarch64-none-linunx-gnu. >>>> Ok for trunk? >>>> Thanks, >>>> Kyrill >>>> >>>> gcc/ChangeLog: >>>> >>>> PR tree-optimization/127039 >>>> * fold-const-call.cc (fold_const_reduction): Fold non-stepped constants >>>> when the available lane-count information determines the result. >>>> * match.pd (reduction of a vector duplicate): New simplifications to >>>> the duplicated element or zero. >>>> >>>> gcc/testsuite/ChangeLog: >>>> >>>> PR tree-optimization/127039 >>>> * gcc.target/aarch64/sve/vec-reduc-dup-1.c: New test. >>>> * gcc.target/aarch64/sve/vec-reduc-pattern-1.c: New test. >>>> * gcc.target/aarch64/sve/vec-reduc-snan-1.c: New test. >>>> * gcc.target/aarch64/sve/vec-reduc-uniform-1.c: New test. >>>> * gcc.target/riscv/rvv/base/reduc-xor-uniform-1.c: New test. >>>> >>>> Signed-off-by: Kyrylo Tkachov <[email protected]> >>>> --- >>>> gcc/fold-const-call.cc | 36 +++- >>>> gcc/match.pd | 14 ++ >>>> .../gcc.target/aarch64/sve/vec-reduc-dup-1.c | 63 +++++++ >>>> .../aarch64/sve/vec-reduc-pattern-1.c | 156 ++++++++++++++++++ >>>> .../gcc.target/aarch64/sve/vec-reduc-snan-1.c | 65 ++++++++ >>>> .../aarch64/sve/vec-reduc-uniform-1.c | 71 ++++++++ >>>> .../riscv/rvv/base/reduc-xor-uniform-1.c | 47 ++++++ >>>> 7 files changed, 449 insertions(+), 3 deletions(-) >>>> create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/vec-reduc-dup-1.c >>>> create mode 100644 >>>> gcc/testsuite/gcc.target/aarch64/sve/vec-reduc-pattern-1.c >>>> create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/vec-reduc-snan-1.c >>>> create mode 100644 >>>> gcc/testsuite/gcc.target/aarch64/sve/vec-reduc-uniform-1.c >>>> create mode 100644 >>>> gcc/testsuite/gcc.target/riscv/rvv/base/reduc-xor-uniform-1.c >>>> >>>> diff --git a/gcc/fold-const-call.cc b/gcc/fold-const-call.cc >>>> index c483b80e704..342a65f4217 100644 >>>> --- a/gcc/fold-const-call.cc >>>> +++ b/gcc/fold-const-call.cc >>>> @@ -622,9 +622,39 @@ fold_const_builtin_nan (tree type, tree arg, bool >>>> quiet) >>>> static tree >>>> fold_const_reduction (tree type, tree arg, tree_code code) >>>> { >>>> - unsigned HOST_WIDE_INT nelts; >>>> - if (TREE_CODE (arg) != VECTOR_CST >>>> - || !VECTOR_CST_NELTS (arg).is_constant (&nelts)) >>>> + if (TREE_CODE (arg) != VECTOR_CST) >>>> + return NULL_TREE; >>>> + >>>> + bool idempotent_p = (code == MAX_EXPR >>>> + || code == MIN_EXPR >>>> + || code == BIT_AND_EXPR >>>> + || code == BIT_IOR_EXPR); >>>> + >>>> + unsigned HOST_WIDE_INT nelts = vector_cst_encoded_nelts (arg); >>>> + bool singleton_snan_p >>>> + = (nelts == 1 >>>> + && tree_expr_maybe_signaling_nan_p (VECTOR_CST_ELT (arg, 0))); >>>> + >>>> + if (idempotent_p >>>> + && !VECTOR_CST_STEPPED_P (arg) >>>> + && multiple_p (VECTOR_CST_NELTS (arg), nelts) >>>> + && !singleton_snan_p) >>> >>> I don't understand why the singleton_snan_p exception is needed. >>> Doesn't that imply that we mishandle that situation below? >>> >>> The condition seems to mean that a 128-bit SVE vector will be handled >>> differently for -msve-vector-bits=128 and -msve-vector-bits=scalable, >>> despite the behaviour being the same at runtime. >> >> Sorry, I get it now. Doubling nelts to force an operation would >> unnecessarily penalise folds of known single-element vectors, >> which really don't raise an exception. >> > > Yeah, that’s the idea. > >> So yeah, I suppose this is probably the best way to handle it. >> > > Thanks, can I take this as an ok for the patch?
Yeah, ok for the fold-const-call.cc part from my POV. Thanks, Richard
