match.pd: fold reductions of vector duplicates and repeats [PR127039]

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.

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 <ktkachov@nvidia.com>
7 files changed