https://gcc.gnu.org/g:f4f72f9b6bcdec8b2ba20a58a241c8d9d631480c

commit r15-3388-gf4f72f9b6bcdec8b2ba20a58a241c8d9d631480c
Author: YunQiang Su <s...@gcc.gnu.org>
Date:   Mon Aug 26 08:45:36 2024 +0800

    MIPS: Support vector reduc for MSA
    
    We have SHF.fmt and HADD_S/U.fmt with MSA, which can be used for
    vector reduc.
    
    For min/max for U8/S8, we can
            SHF.B W1, W0, 0xb1  # swap byte inner every half
            MIN.B W1, W1, W0
            SHF.H W2, W1, 0xb1  # swap half inner every word
            MIN.B W2, W2, W1
            SHF.W W3, W2, 0xb1  # swap word inner every doubleword
            MIN.B W4, W3, W2
            SHF.W W4, W4, 0x4e  # swap the two doubleword
            MIN.B W4, W4, W3
    
    For plus of S8/U8, we can use HADD
            HADD.H  W0, W0, W0
            HADD.W  W0, W0, W0
            HADD.D  W0, W0, W0
            SHF.W   W1, W0, 0x4e  # swap the two doubleword
            ADDV.D  W1, W1, W0
            COPY_S.B  T0, W1      # COPY_U.B for U8
    
    We can do similar for S16/U16/S32/U32/S64/U64/FLOAT/DOUBLE.
    
    gcc
    
            * config/mips/mips-msa.md: (MSA_NO_HADD): we have HADD for
            S8/U8/S16/U16/S32/U32 only.
            (reduc_smin_scal_<mode>): New define pattern.
            (reduc_smax_scal_<mode>): Ditto.
            (reduc_umin_scal_<mode>): Ditto.
            (reduc_umax_scal_<mode>): Ditto.
            (reduc_plus_scal_<mode>): Ditto.
            (reduc_plus_scal_v4si): Ditto.
            (reduc_plus_scal_v8hi): Ditto.
            (reduc_plus_scal_v16qi): Ditto.
            (reduc_<optab>_scal_<mode>): Ditto.
            * config/mips/mips-protos.h: New function mips_expand_msa_reduc.
            * config/mips/mips.cc: New function mips_expand_msa_reduc.
            * config/mips/mips.md: Define any_bitwise iterator.
    
    gcc/testsuite:
    
            * gcc.target/mips/msa-reduc.c: New tests.

Diff:
---
 gcc/config/mips/mips-msa.md               | 128 ++++++++++++++++++++++++++++++
 gcc/config/mips/mips-protos.h             |   1 +
 gcc/config/mips/mips.cc                   |  41 ++++++++++
 gcc/config/mips/mips.md                   |   4 +
 gcc/testsuite/gcc.target/mips/msa-reduc.c | 119 +++++++++++++++++++++++++++
 5 files changed, 293 insertions(+)

diff --git a/gcc/config/mips/mips-msa.md b/gcc/config/mips/mips-msa.md
index 377c63f0d357..976f296402ee 100644
--- a/gcc/config/mips/mips-msa.md
+++ b/gcc/config/mips/mips-msa.md
@@ -125,6 +125,9 @@
 ;; Only floating-point modes.
 (define_mode_iterator FMSA     [V2DF V4SF])
 
+;; Only used for reduce_plus_scal: V4SI, V8HI, V16QI have HADD.
+(define_mode_iterator MSA_NO_HADD [V2DF V4SF V2DI])
+
 ;; The attribute gives the integer vector mode with same size.
 (define_mode_attr VIMODE
   [(V2DF "V2DI")
@@ -2802,3 +2805,128 @@
   (set_attr "mode" "TI")
   (set_attr "compact_form" "never")
   (set_attr "branch_likely" "no")])
+
+
+;; Vector reduction operation
+(define_expand "reduc_smin_scal_<mode>"
+  [(match_operand:<UNITMODE> 0 "register_operand")
+   (match_operand:MSA 1 "register_operand")]
+  "ISA_HAS_MSA"
+{
+  rtx tmp = gen_reg_rtx (<MODE>mode);
+  mips_expand_msa_reduc (gen_smin<mode>3, tmp, operands[1]);
+  emit_insn (gen_vec_extract<mode><unitmode> (operands[0], tmp,
+                                             const0_rtx));
+  DONE;
+})
+
+(define_expand "reduc_smax_scal_<mode>"
+  [(match_operand:<UNITMODE> 0 "register_operand")
+   (match_operand:MSA 1 "register_operand")]
+  "ISA_HAS_MSA"
+{
+  rtx tmp = gen_reg_rtx (<MODE>mode);
+  mips_expand_msa_reduc (gen_smax<mode>3, tmp, operands[1]);
+  emit_insn (gen_vec_extract<mode><unitmode> (operands[0], tmp,
+                                             const0_rtx));
+  DONE;
+})
+
+(define_expand "reduc_umin_scal_<mode>"
+  [(match_operand:<UNITMODE> 0 "register_operand")
+   (match_operand:IMSA 1 "register_operand")]
+  "ISA_HAS_MSA"
+{
+  rtx tmp = gen_reg_rtx (<MODE>mode);
+  mips_expand_msa_reduc (gen_umin<mode>3, tmp, operands[1]);
+  emit_insn (gen_vec_extract<mode><unitmode> (operands[0], tmp,
+                                             const0_rtx));
+  DONE;
+})
+
+(define_expand "reduc_umax_scal_<mode>"
+  [(match_operand:<UNITMODE> 0 "register_operand")
+   (match_operand:IMSA 1 "register_operand")]
+  "ISA_HAS_MSA"
+{
+  rtx tmp = gen_reg_rtx (<MODE>mode);
+  mips_expand_msa_reduc (gen_umax<mode>3, tmp, operands[1]);
+  emit_insn (gen_vec_extract<mode><unitmode> (operands[0], tmp,
+                                             const0_rtx));
+  DONE;
+})
+
+(define_expand "reduc_plus_scal_<mode>"
+  [(match_operand:<UNITMODE> 0 "register_operand")
+   (match_operand:MSA_NO_HADD 1 "register_operand")]
+  "ISA_HAS_MSA"
+{
+  rtx tmp = gen_reg_rtx (<MODE>mode);
+  mips_expand_msa_reduc (gen_add<mode>3, tmp, operands[1]);
+  emit_insn (gen_vec_extract<mode><unitmode> (operands[0], tmp,
+                                             const0_rtx));
+  DONE;
+})
+
+(define_expand "reduc_plus_scal_v4si"
+  [(match_operand:SI 0 "register_operand")
+   (match_operand:V4SI 1 "register_operand")]
+  "ISA_HAS_MSA"
+{
+  rtx tmp = gen_reg_rtx (SImode);
+  rtx tmp1 = gen_reg_rtx (V2DImode);
+  emit_insn (gen_msa_hadd_s_d (tmp1, operands[1], operands[1]));
+  emit_insn (gen_vec_extractv4sisi (operands[0], gen_lowpart (V4SImode, tmp1),
+                                   const0_rtx));
+  emit_insn (gen_vec_extractv4sisi (tmp, gen_lowpart (V4SImode, tmp1),
+                                   GEN_INT (2)));
+  emit_insn (gen_addsi3 (operands[0], operands[0], tmp));
+  DONE;
+})
+
+(define_expand "reduc_plus_scal_v8hi"
+  [(match_operand:HI 0 "register_operand")
+   (match_operand:V8HI 1 "register_operand")]
+  "ISA_HAS_MSA"
+{
+  rtx tmp1 = gen_reg_rtx (V4SImode);
+  rtx tmp2 = gen_reg_rtx (V2DImode);
+  rtx tmp3 = gen_reg_rtx (V2DImode);
+  emit_insn (gen_msa_hadd_s_w (tmp1, operands[1], operands[1]));
+  emit_insn (gen_msa_hadd_s_d (tmp2, tmp1, tmp1));
+  mips_expand_msa_reduc (gen_addv2di3, tmp3, tmp2);
+  emit_insn (gen_vec_extractv8hihi (operands[0], gen_lowpart (V8HImode, tmp3),
+                                   const0_rtx));
+  DONE;
+})
+
+(define_expand "reduc_plus_scal_v16qi"
+  [(match_operand:QI 0 "register_operand")
+   (match_operand:V16QI 1 "register_operand")]
+  "ISA_HAS_MSA"
+{
+  rtx tmp1 = gen_reg_rtx (V8HImode);
+  rtx tmp2 = gen_reg_rtx (V4SImode);
+  rtx tmp3 = gen_reg_rtx (V2DImode);
+  rtx tmp4 = gen_reg_rtx (V2DImode);
+  emit_insn (gen_msa_hadd_s_h (tmp1, operands[1], operands[1]));
+  emit_insn (gen_msa_hadd_s_w (tmp2, tmp1, tmp1));
+  emit_insn (gen_msa_hadd_s_d (tmp3, tmp2, tmp2));
+  mips_expand_msa_reduc (gen_addv2di3, tmp4, tmp3);
+  emit_insn (gen_vec_extractv16qiqi (operands[0], gen_lowpart (V16QImode, 
tmp4),
+                                   const0_rtx));
+  DONE;
+})
+
+(define_expand "reduc_<optab>_scal_<mode>"
+  [(any_bitwise:<UNITMODE>
+      (match_operand:<UNITMODE> 0 "register_operand")
+      (match_operand:IMSA 1 "register_operand"))]
+  "ISA_HAS_MSA"
+{
+  rtx tmp = gen_reg_rtx (<MODE>mode);
+  mips_expand_msa_reduc (gen_<optab><mode>3, tmp, operands[1]);
+  emit_insn (gen_vec_extract<mode><unitmode> (operands[0], tmp,
+                                             const0_rtx));
+  DONE;
+})
diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h
index 90b4c87fdea1..96e084e6e641 100644
--- a/gcc/config/mips/mips-protos.h
+++ b/gcc/config/mips/mips-protos.h
@@ -352,6 +352,7 @@ extern void mips_expand_atomic_qihi (union mips_gen_fn_ptrs,
 extern void mips_expand_vector_init (rtx, rtx);
 extern void mips_expand_vec_unpack (rtx op[2], bool, bool);
 extern void mips_expand_vec_reduc (rtx, rtx, rtx (*)(rtx, rtx, rtx));
+extern void mips_expand_msa_reduc (rtx (*)(rtx, rtx, rtx), rtx, rtx);
 extern void mips_expand_vec_minmax (rtx, rtx, rtx,
                                    rtx (*) (rtx, rtx, rtx), bool);
 
diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
index 6c797b621643..173f792bf55a 100644
--- a/gcc/config/mips/mips.cc
+++ b/gcc/config/mips/mips.cc
@@ -22239,6 +22239,47 @@ mips_vectorize_vec_perm_const (machine_mode vmode, 
machine_mode op_mode,
   return ok;
 }
 
+/* Expand a vector reduction.  FN is the binary pattern to reduce;
+   DEST is the destination; IN is the input vector.  */
+
+void
+mips_expand_msa_reduc (rtx (*fn) (rtx, rtx, rtx), rtx dest, rtx in)
+{
+  rtx swap, vec = in;
+  machine_mode mode = GET_MODE (in);
+  unsigned int i, gelt;
+  const unsigned nelt = GET_MODE_BITSIZE (mode) / GET_MODE_UNIT_BITSIZE (mode);
+  unsigned char perm[MAX_VECT_LEN];
+
+  /* We have no SHF.d.  */
+  if (nelt == 2)
+    {
+      perm[0] = 2;
+      perm[1] = 3;
+      perm[2] = 0;
+      perm[3] = 1;
+      rtx rsi = simplify_gen_subreg (V4SImode, in, mode, 0);
+      swap = gen_reg_rtx (V4SImode);
+      mips_expand_vselect (swap, rsi, perm, 4);
+      emit_move_insn (dest, gen_rtx_SUBREG (mode, swap, 0));
+      emit_insn (fn (dest, dest, vec));
+      return;
+    }
+
+  for (gelt=1; gelt<=nelt/2; gelt *= 2)
+    {
+      for (i = 0; i<nelt; i++)
+       perm[i] = ((i/gelt)%2) ? (i-gelt) : (i+gelt);
+      if (gelt == nelt/2)
+       swap = dest;
+      else
+       swap = gen_reg_rtx (mode);
+      mips_expand_vselect (swap, vec, perm, nelt);
+      emit_insn (fn (swap, swap, vec));
+      vec = swap;
+    }
+}
+
 /* Implement TARGET_SCHED_REASSOCIATION_WIDTH.  */
 
 static int
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 737d2566ec80..f147667d63a8 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -993,6 +993,10 @@
 ;; from the same template.
 (define_code_iterator any_shift [ashift ashiftrt lshiftrt])
 
+;; This code iterator allows the three bitwise instructions to be generated
+;; from the same template.
+(define_code_iterator any_bitwise [and ior xor])
+
 ;; This code iterator allows unsigned and signed division to be generated
 ;; from the same template.
 (define_code_iterator any_div [div udiv])
diff --git a/gcc/testsuite/gcc.target/mips/msa-reduc.c 
b/gcc/testsuite/gcc.target/mips/msa-reduc.c
new file mode 100644
index 000000000000..27cc28ed255b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/msa-reduc.c
@@ -0,0 +1,119 @@
+/* Test reduc support for MIPS MSA ASE with shf.FMT */
+/* { dg-do compile } */
+/* { dg-skip-if "auto-vectorization test" { *-*-* } { "-O0" "-O1" "-O2" "-Os"} 
{ "-O3" } } */
+/* { dg-options "-mfp64 -mhard-float -mmsa -ffast-math" } */
+
+/* { dg-final { scan-assembler-times 
"min_int8_t:.*shf\\.b.*0xb1.*min_s\\.b.*shf\\.h.*0xb1.*min_s\\.b.*shf\\.w.*0xb1.*min_s\\.b.*shf\\.w.*0x4e.*min_s\\.b.*copy_s\\.b.*min_int8_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"max_int8_t:.*shf\\.b.*0xb1.*max_s\\.b.*shf\\.h.*0xb1.*max_s\\.b.*shf\\.w.*0xb1.*max_s\\.b.*shf\\.w.*0x4e.*max_s\\.b.*copy_s\\.b.*max_int8_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"min_uint8_t:.*shf\\.b.*0xb1.*min_u\\.b.*shf\\.h.*0xb1.*min_u\\.b.*shf\\.w.*0xb1.*min_u\\.b.*shf\\.w.*0x4e.*min_u\\.b.*copy_.\\.b.*min_uint8_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"max_uint8_t:.*shf\\.b.*0xb1.*max_u\\.b.*shf\\.h.*0xb1.*max_u\\.b.*shf\\.w.*0xb1.*max_u\\.b.*shf\\.w.*0x4e.*max_u\\.b.*copy_.\\.b.*max_uint8_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"min_int16_t:.*shf\\.h.*0xb1.*min_s\\.h.*shf\\.w.*0xb1.*min_s\\.h.*shf\\.w.*0x4e.*min_s\\.h.*copy_s\\.h.*min_int16_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"max_int16_t:.*shf\\.h.*0xb1.*max_s\\.h.*shf\\.w.*0xb1.*max_s\\.h.*shf\\.w.*0x4e.*max_s\\.h.*copy_s\\.h.*max_int16_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"min_uint16_t:.*shf\\.h.*0xb1.*min_u\\.h.*shf\\.w.*0xb1.*min_u\\.h.*shf\\.w.*0x4e.*min_u\\.h.*copy_.\\.h.*min_uint16_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"max_uint16_t:.*shf\\.h.*0xb1.*max_u\\.h.*shf\\.w.*0xb1.*max_u\\.h.*shf\\.w.*0x4e.*max_u\\.h.*copy_.\\.h.*max_uint16_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"min_int32_t:.*shf\\.w.*0xb1.*min_s\\.w.*shf\\.w.*0x4e.*min_s\\.w.*copy_s\\.w.*min_int32_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"max_int32_t:.*shf\\.w.*0xb1.*max_s\\.w.*shf\\.w.*0x4e.*max_s\\.w.*copy_s\\.w.*max_int32_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"min_uint32_t:.*shf\\.w.*0xb1.*min_u\\.w.*shf\\.w.*0x4e.*min_u\\.w.*copy_.\\.w.*min_uint32_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"max_uint32_t:.*shf\\.w.*0xb1.*max_u\\.w.*shf\\.w.*0x4e.*max_u\\.w.*copy_.\\.w.*max_uint32_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"min_int64_t:.*shf\\.w.*0x4e.*min_s\\.d.*copy_s\\.?.*min_int64_t" 1 } } */
+/* { dg-final { scan-assembler-times 
"max_int64_t:.*shf\\.w.*0x4e.*max_s\\.d.*copy_s\\.?.*max_int64_t" 1 } } */
+/* { dg-final { scan-assembler-times 
"min_uint64_t:.*shf\\.w.*0x4e.*min_u\\.d.*copy_.\\.?.*min_uint64_t" 1 } } */
+/* { dg-final { scan-assembler-times 
"max_uint64_t:.*shf\\.w.*0x4e.*max_u\\.d.*copy_.\\.?.*max_uint64_t" 1 } } */
+/* { dg-final { scan-assembler-times 
"min_float:.*shf\\.w.*0xb1.*fmin\\.w.*shf\\.w.*0x4e.*fmin\\.w.*min_float" 1 } } 
*/
+/* { dg-final { scan-assembler-times 
"max_float:.*shf\\.w.*0xb1.*fmax\\.w.*shf\\.w.*0x4e.*fmax\\.w.*max_float" 1 } } 
*/
+/* { dg-final { scan-assembler-times 
"min_double:.*shf\\.w.*0x4e.*fmin\\.d.*min_double" 1 } } */
+/* { dg-final { scan-assembler-times 
"max_double:.*shf\\.w.*0x4e.*fmax\\.d.*max_double" 1 } } */
+
+/* { dg-final { scan-assembler-times 
"plus_int8_t:.*hadd_s\\.h.*hadd_s\\.w.*hadd_s\\.d.*shf\\.w.*0x4e.*addv\\.d.*copy_s\\.b.*plus_int8_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"plus_uint8_t:.*hadd_s\\.h.*hadd_s\\.w.*hadd_s\\.d.*shf\\.w.*0x4e.*addv\\.d.*copy_.\\.b.*plus_uint8_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"plus_int16_t:.*hadd_s\\.w.*hadd_s\\.d.*shf\\.w.*0x4e.*addv\\.d.*copy_s\\.h.*plus_int16_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"plus_uint16_t:.*hadd_s\\.w.*hadd_s\\.d.*shf\\.w.*0x4e.*addv\\.d.*copy_.\\.h.*plus_uint16_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"plus_int32_t:.*hadd_s\\.d.*copy_s\\.w.*copy_s\\.w.*addu.*plus_int32_t" 1 } } */
+/* { dg-final { scan-assembler-times 
"plus_uint32_t:.*hadd_s\\.d.*copy_s\\.w.*copy_s\\.w.*addu.*plus_uint32_t" 1 } } 
*/
+/* { dg-final { scan-assembler-times 
"plus_int64_t:.*shf\\.w.*0x4e.*addv\\.d.*copy_s\\.?.*plus_int64_t" 1 } } */
+/* { dg-final { scan-assembler-times 
"plus_uint64_t:.*shf\\.w.*0x4e.*addv\\.d.*copy_.\\.?.*plus_uint64_t" 1 } } */
+/* { dg-final { scan-assembler-times 
"plus_float:.*shf\\.w.*0xb1.*fadd\\.w.*shf\\.w.*0x4e.*fadd\\.w.*plus_float" 1 } 
} */
+/* { dg-final { scan-assembler-times 
"plus_double:.*shf\\.w.*0x4e.*fadd\\.d.*plus_double" 1 } } */
+
+/* { dg-final { scan-assembler-times 
"or_int8_t:.*shf\\.b.*0xb1.*or\\.v.*shf\\.h.*0xb1.*or\\.v.*shf\\.w.*0xb1.*or\\.v.*shf\\.w.*0x4e.*or\\.v.*copy_s\\.b.*or_int8_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"xor_int8_t:.*shf\\.b.*0xb1.*xor\\.v.*shf\\.h.*0xb1.*xor\\.v.*shf\\.w.*0xb1.*xor\\.v.*shf\\.w.*0x4e.*xor\\.v.*copy_s\\.b.*xor_int8_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"and_int8_t:.*shf\\.b.*0xb1.*and\\.v.*shf\\.h.*0xb1.*and\\.v.*shf\\.w.*0xb1.*and\\.v.*shf\\.w.*0x4e.*and\\.v.*copy_s\\.b.*and_int8_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"or_uint8_t:.*shf\\.b.*0xb1.*or\\.v.*shf\\.h.*0xb1.*or\\.v.*shf\\.w.*0xb1.*or\\.v.*shf\\.w.*0x4e.*or\\.v.*copy_.\\.b.*or_uint8_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"xor_uint8_t:.*shf\\.b.*0xb1.*xor\\.v.*shf\\.h.*0xb1.*xor\\.v.*shf\\.w.*0xb1.*xor\\.v.*shf\\.w.*0x4e.*xor\\.v.*copy_.\\.b.*xor_uint8_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"and_uint8_t:.*shf\\.b.*0xb1.*and\\.v.*shf\\.h.*0xb1.*and\\.v.*shf\\.w.*0xb1.*and\\.v.*shf\\.w.*0x4e.*and\\.v.*copy_.\\.b.*and_uint8_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"or_int16_t:.*shf\\.h.*0xb1.*or\\.v.*shf\\.w.*0xb1.*or\\.v.*shf\\.w.*0x4e.*or\\.v.*copy_s\\.h.*or_int16_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"xor_int16_t:.*shf\\.h.*0xb1.*xor\\.v.*shf\\.w.*0xb1.*xor\\.v.*shf\\.w.*0x4e.*xor\\.v.*copy_s\\.h.*xor_int16_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"and_int16_t:.*shf\\.h.*0xb1.*and\\.v.*shf\\.w.*0xb1.*and\\.v.*shf\\.w.*0x4e.*and\\.v.*copy_s\\.h.*and_int16_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"or_uint16_t:.*shf\\.h.*0xb1.*or\\.v.*shf\\.w.*0xb1.*or\\.v.*shf\\.w.*0x4e.*or\\.v.*copy_.\\.h.*or_uint16_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"xor_uint16_t:.*shf\\.h.*0xb1.*xor\\.v.*shf\\.w.*0xb1.*xor\\.v.*shf\\.w.*0x4e.*xor\\.v.*copy_.\\.h.*xor_uint16_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"and_uint16_t:.*shf\\.h.*0xb1.*and\\.v.*shf\\.w.*0xb1.*and\\.v.*shf\\.w.*0x4e.*and\\.v.*copy_.\\.h.*and_uint16_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"or_int32_t:.*shf\\.w.*0xb1.*or\\.v.*shf\\.w.*0x4e.*or\\.v.*copy_s\\.w.*or_int32_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"xor_int32_t:.*shf\\.w.*0xb1.*xor\\.v.*shf\\.w.*0x4e.*xor\\.v.*copy_s\\.w.*xor_int32_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"and_int32_t:.*shf\\.w.*0xb1.*and\\.v.*shf\\.w.*0x4e.*and\\.v.*copy_s\\.w.*and_int32_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"or_uint32_t:.*shf\\.w.*0xb1.*or\\.v.*shf\\.w.*0x4e.*or\\.v.*copy_.\\.w.*or_uint32_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"xor_uint32_t:.*shf\\.w.*0xb1.*xor\\.v.*shf\\.w.*0x4e.*xor\\.v.*copy_.\\.w.*xor_uint32_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"and_uint32_t:.*shf\\.w.*0xb1.*and\\.v.*shf\\.w.*0x4e.*and\\.v.*copy_.\\.w.*and_uint32_t"
 1 } } */
+/* { dg-final { scan-assembler-times 
"or_int64_t:.*shf\\.w.*0x4e.*or\\.v.*copy_s\\.?.*or_int64_t" 1 } } */
+/* { dg-final { scan-assembler-times 
"xor_int64_t:.*shf\\.w.*0x4e.*xor\\.v.*copy_s\\.?.*xor_int64_t" 1 } } */
+/* { dg-final { scan-assembler-times 
"and_int64_t:.*shf\\.w.*0x4e.*and\\.v.*copy_s\\.?.*and_int64_t" 1 } } */
+/* { dg-final { scan-assembler-times 
"or_uint64_t:.*shf\\.w.*0x4e.*or\\.v.*copy_.\\.?.*or_uint64_t" 1 } } */
+/* { dg-final { scan-assembler-times 
"xor_uint64_t:.*shf\\.w.*0x4e.*xor\\.v.*copy_.\\.?.*xor_uint64_t" 1 } } */
+/* { dg-final { scan-assembler-times 
"and_uint64_t:.*shf\\.w.*0x4e.*and\\.v.*copy_.\\.?.*and_uint64_t" 1 } } */
+
+#include <stdint.h>
+
+#define D_TY_CALC(type) \
+       type a_##type[32] __attribute__ ((aligned (16))); \
+       type min_##type () { \
+               type ret = a_##type[0]; \
+               for (int i=0; i<32; i++) \
+                       ret = (ret < a_##type[i]) ? ret : a_##type[i]; \
+               return ret;     \
+       }       \
+       type max_##type () { \
+               type ret = a_##type[0]; \
+               for (int i=0; i<32; i++) \
+                       ret = (ret > a_##type[i]) ? ret : a_##type[i]; \
+               return ret;     \
+       }       \
+       type plus_##type () { \
+               type ret = 0;   \
+               for (int i=0; i<32; i++) \
+                       ret += a_##type[i]; \
+               return ret;     \
+       }
+
+#define D_TY_BIT(type) \
+       type or_##type () {     \
+               type ret = 0;   \
+               for (int i=0; i<32; i++) \
+                       ret |= a_##type[i]; \
+               return ret;     \
+       }       \
+       type and_##type () {    \
+               type ret = (type)(long long)~0LL;       \
+               for (int i=0; i<32; i++) \
+                       ret &= a_##type[i]; \
+               return ret;     \
+       }       \
+       type xor_##type () {    \
+               type ret = (type)(long long)~0LL;       \
+               for (int i=0; i<32; i++) \
+                       ret ^= a_##type[i]; \
+               return ret;     \
+       }
+
+#define D_TY(type) D_TY_CALC(type) D_TY_BIT(type)
+
+D_TY (int8_t)
+D_TY (uint8_t)
+D_TY (int16_t)
+D_TY (uint16_t)
+D_TY (int32_t)
+D_TY (uint32_t)
+D_TY (int64_t)
+D_TY (uint64_t)
+D_TY_CALC (float)
+D_TY_CALC (double)
+
+

Reply via email to