On 11/06/26 2:33 PM, jeevitha wrote:
> Hi All,
>
> The following changes have been bootstrapped and regression tested on
> powerpc64le-linux. Is this okay for trunk?
>
> Changes from V4:
> * Modified the existing patterns for add, sub, and mulh.
> * Added new test cases.
> * Added the future ISA attribute.
>
> Changes from V3:
> * Renamed ENB_FUTUREV and BSTZ_FUTUREV.
> * Added subheading in extend.texi.
>
> Changes from V2:
> * Added TARGET_VSX check to all new insn patterns.
> * Added * prefix to vsx_mul pattern.
> * Added new test cases vsx_simd-3.c and vsx_simd-4.c.
> * Created new future-vsx stanza to map builtins.
>
> Changes from V1:
> * Incorporated wording suggestions.
> * Renamed mode iterators to VIMulH and VIArith for better clarity.
> * Removed extra blank line in vsx_simd-*.c test case.
> * Replaced unspec with proper smul_highpart and umul_highpart RTL
> codes for multiply-high patterns.
> * Added * prefix to internal patterns for vsx_add, vsx_sub, altivec_add,
> altivec_sub, altivec_smul and altivec_umul.
> * Updated extend.texi.
>
> This patch adds support for VSX vector arithmetic instructions that may
> be added to future PowerPC processors. Note that the names of these
> builtins may change in the future.
>
> New VSX patterns are added for vector add, subtract, multiply, and
> multiply-high instructions guarded by TARGET_FUTURE. A new builtin
> enablement stanza future-vsx is added for builtins requiring
> both -mcpu=future and -mvsx.
>
> 2026-06-11 Jeevitha Palanisamy <[email protected]>
>
> gcc/
> * config/rs6000/altivec.md (V16QI_V2DI): New mode iterator.
> (add<mode>3): Split into two patterns to support future ISA
> alternatives.
> (sub<mode>3): Likewise.
> * config/rs6000/vsx.md (VIArith): New mode iterator.
> (vsx_mul<mode>3): New insn pattern.
> (smul<mode>3_highpart): Split into mode-specific patterns.
> (umul<mode>3_highpart): Likewise.
> (smulv8hi3_highpart): New insn pattern.
> (smulv4si3_highpart): Likewise.
> (smulv2di3_highpart): Likewise.
> (umulv8hi3_highpart): Likewise.
> (umulv4si3_highpart): Likewise.
> (umulv2di3_highpart): Likewise.
> * config/rs6000/rs6000-builtins.def (__builtin_vsx_xvmulhuh): New
> builtin.
> (__builtin_vsx_xvmulhsh): Likewise.
> * config/rs6000/rs6000-overload.def (__builtin_vec_mulh): Add
> overloads for vector multiply-high signed/unsigned halfword.
> * config/rs6000/rs6000-gen-builtins.cc (enum bif_stanza): Add entry for
> BSTZ_FUTURE_VSX.
> (stanza_map): Add future-vsx stanza mapping.
> (enable_string): Add ENB_FUTURE_VSX.
> (write_decls): Add ENB_FUTURE_VSX to the bif_enable enum in the
> generated header file.
> * config/rs6000/rs6000.md (define_attr "isa"): Add future to the list
> of ISA values.
> (define_attr "enabled"): Add check for future ISA.
> * config/rs6000/rs6000-builtin.cc (rs6000_invalid_builtin): Handle
> ENB_FUTURE_VSX and issue a diagnostic requiring -mcpu=future and -mvsx.
> (rs6000_builtin_is_supported): Return TARGET_FUTURE && TARGET_VSX
> for ENB_FUTURE_VSX built-ins.
> * doc/extend.texi (PowerPC AltiVec/VSX Built-in Functions Available
> on Future ISA): Document new functions.
>
> gcc/testsuite/
> * gcc.target/powerpc/vsx_arith_builtin-1.c: New test.
> * gcc.target/powerpc/vsx_arith_builtin-2.c: Likewise.
> * gcc.target/powerpc/vsx_arith_builtin-3.c: Likewise.
> * gcc.target/powerpc/vsx_arith_builtin-4.c: Likewise.
> * gcc.target/powerpc/vsx_arith_vect_1.c: Likewise.
> * gcc.target/powerpc/vsx_arith_vect_2.c: Likewise.
>
> diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
> index 129f56245cd..dbe24c450e1 100644
> --- a/gcc/config/rs6000/altivec.md
> +++ b/gcc/config/rs6000/altivec.md
> @@ -238,6 +238,8 @@
> ;; Vector negate
> (define_mode_iterator VNEG [V4SI V2DI])
>
> +(define_mode_iterator V16QI_V2DI [V16QI V2DI])
> +
> ;; Vector move instructions.
> (define_insn "*altivec_mov<mode>"
> [(set (match_operand:VM2 0 "nonimmediate_operand"
> "=Z,v,v,?Y,?*r,?*r,v,v,?*r")
> @@ -505,13 +507,24 @@
>
> ;; add
> (define_insn "add<mode>3"
> - [(set (match_operand:VI2 0 "register_operand" "=v")
> - (plus:VI2 (match_operand:VI2 1 "register_operand" "v")
> - (match_operand:VI2 2 "register_operand" "v")))]
> + [(set (match_operand:V16QI_V2DI 0 "register_operand" "=v")
> + (plus:V16QI_V2DI (match_operand:V16QI_V2DI 1 "register_operand" "v")
> + (match_operand:V16QI_V2DI 2 "register_operand"
> "v")))]
> "<VI_unit>"
> "vaddu<VI_char>m %0,%1,%2"
> [(set_attr "type" "vecsimple")])
>
> +(define_insn "add<mode>3"
> + [(set (match_operand:VIArith 0 "register_operand" "=wa,v")
> + (plus:VIArith (match_operand:VIArith 1 "register_operand" "wa,v")
> + (match_operand:VIArith 2 "register_operand" "wa,v")))]
> + "<VI_unit>"
<VI_unit> checks for ALTIVEC mode for V8HI & V4SI. But the xvaddu*m
instructions should be
generated only if VSX is true.
> + "@
> + xvaddu<VI_char>m %x0,%x1,%x2
> + vaddu<VI_char>m %0,%1,%2"
> + [(set_attr "type" "vecsimple")
> + (set_attr "isa" "future,*")])
> +
> (define_insn "*altivec_addv4sf3"
> [(set (match_operand:V4SF 0 "register_operand" "=v")
> (plus:V4SF (match_operand:V4SF 1 "register_operand" "v")
> @@ -549,13 +562,24 @@
>
> ;; sub
> (define_insn "sub<mode>3"
> - [(set (match_operand:VI2 0 "register_operand" "=v")
> - (minus:VI2 (match_operand:VI2 1 "register_operand" "v")
> - (match_operand:VI2 2 "register_operand" "v")))]
> + [(set (match_operand:V16QI_V2DI 0 "register_operand" "=v")
> + (minus:V16QI_V2DI (match_operand:V16QI_V2DI 1 "register_operand" "v")
> + (match_operand:V16QI_V2DI 2 "register_operand"
> "v")))]
> "<VI_unit>"
> "vsubu<VI_char>m %0,%1,%2"
> [(set_attr "type" "vecsimple")])
>
> +(define_insn "sub<mode>3"
> + [(set (match_operand:VIArith 0 "register_operand" "=wa,v")
> + (minus:VIArith (match_operand:VIArith 1 "register_operand" "wa,v")
> + (match_operand:VIArith 2 "register_operand" "wa,v")))]
> + "<VI_unit>"
Ditto.
> + "@
> + xvsubu<VI_char>m %x0,%x1,%x2
> + vsubu<VI_char>m %0,%1,%2"
> + [(set_attr "type" "vecsimple")
> + (set_attr "isa" "future,*")])
> +
> (define_insn "*altivec_subv4sf3"
> [(set (match_operand:V4SF 0 "register_operand" "=v")
> (minus:V4SF (match_operand:V4SF 1 "register_operand" "v")
> diff --git a/gcc/config/rs6000/rs6000-builtin.cc
> b/gcc/config/rs6000/rs6000-builtin.cc
> index f4f3772d6cc..3d8b5acf45b 100644
> --- a/gcc/config/rs6000/rs6000-builtin.cc
> +++ b/gcc/config/rs6000/rs6000-builtin.cc
> @@ -142,6 +142,10 @@ rs6000_invalid_builtin (enum rs6000_gen_builtins fncode)
> case ENB_FUTURE:
> error ("%qs requires the %qs option", name, "-mcpu=future");
> break;
> + case ENB_FUTURE_VSX:
> + error ("%qs requires the %qs and %qs options", name, "-mcpu=future",
> + "-mvsx");
> + break;
> default:
> case ENB_ALWAYS:
> gcc_unreachable ();
> @@ -199,6 +203,8 @@ rs6000_builtin_is_supported (enum rs6000_gen_builtins
> fncode)
> return TARGET_MMA;
> case ENB_FUTURE:
> return TARGET_FUTURE;
> + case ENB_FUTURE_VSX:
> + return TARGET_FUTURE && TARGET_VSX;
> default:
> gcc_unreachable ();
> }
> diff --git a/gcc/config/rs6000/rs6000-builtins.def
> b/gcc/config/rs6000/rs6000-builtins.def
> index 0d1529b71d4..b5b6c98b69e 100644
> --- a/gcc/config/rs6000/rs6000-builtins.def
> +++ b/gcc/config/rs6000/rs6000-builtins.def
> @@ -3970,3 +3970,10 @@
>
> const vuc __builtin_galois_field_mult_xts (vuc, vuc);
> XXGFMUL128XTS xxgfmul128xts {}
> +
> +[future-vsx]
> + const vus __builtin_vsx_xvmulhuh (vus, vus);
> + XVMULHUH umulv8hi3_highpart {}
> +
> + const vss __builtin_vsx_xvmulhsh (vss, vss);
> + XVMULHSH smulv8hi3_highpart {}
> diff --git a/gcc/config/rs6000/rs6000-gen-builtins.cc
> b/gcc/config/rs6000/rs6000-gen-builtins.cc
> index 7436404cff5..dd60d20eaaf 100644
> --- a/gcc/config/rs6000/rs6000-gen-builtins.cc
> +++ b/gcc/config/rs6000/rs6000-gen-builtins.cc
> @@ -233,6 +233,7 @@ enum bif_stanza
> BSTZ_P10_64,
> BSTZ_MMA,
> BSTZ_FUTURE,
> + BSTZ_FUTURE_VSX,
> NUMBIFSTANZAS
> };
>
> @@ -267,7 +268,8 @@ static stanza_entry stanza_map[NUMBIFSTANZAS] =
> { "power10", BSTZ_P10 },
> { "power10-64", BSTZ_P10_64 },
> { "mma", BSTZ_MMA },
> - { "future", BSTZ_FUTURE }
> + { "future", BSTZ_FUTURE },
> + { "future-vsx", BSTZ_FUTURE_VSX }
> };
>
> static const char *enable_string[NUMBIFSTANZAS] =
> @@ -293,7 +295,8 @@ static const char *enable_string[NUMBIFSTANZAS] =
> "ENB_P10",
> "ENB_P10_64",
> "ENB_MMA",
> - "ENB_FUTURE"
> + "ENB_FUTURE",
> + "ENB_FUTURE_VSX"
> };
>
> /* Function modifiers provide special handling for const, pure, and fpmath
> @@ -2253,7 +2256,8 @@ write_decls (void)
> fprintf (header_file, " ENB_P10,\n");
> fprintf (header_file, " ENB_P10_64,\n");
> fprintf (header_file, " ENB_MMA,\n");
> - fprintf (header_file, " ENB_FUTURE\n");
> + fprintf (header_file, " ENB_FUTURE,\n");
> + fprintf (header_file, " ENB_FUTURE_VSX\n");
> fprintf (header_file, "};\n\n");
>
> fprintf (header_file, "#define PPC_MAXRESTROPNDS 3\n");
> diff --git a/gcc/config/rs6000/rs6000-overload.def
> b/gcc/config/rs6000/rs6000-overload.def
> index ef7b59ed112..09be9e7de71 100644
> --- a/gcc/config/rs6000/rs6000-overload.def
> +++ b/gcc/config/rs6000/rs6000-overload.def
> @@ -2530,6 +2530,10 @@
> VMULEUD
>
> [VEC_MULH, vec_mulh, __builtin_vec_mulh]
> + vss __builtin_vec_mulh (vss, vss);
> + XVMULHSH
> + vus __builtin_vec_mulh (vus, vus);
> + XVMULHUH
> vsi __builtin_vec_mulh (vsi, vsi);
> VMULHSW
> vui __builtin_vec_mulh (vui, vui);
> diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
> index 2ccbe178bb5..536ea2c9d76 100644
> --- a/gcc/config/rs6000/rs6000.md
> +++ b/gcc/config/rs6000/rs6000.md
> @@ -369,7 +369,7 @@
> (const (symbol_ref "(enum attr_cpu) rs6000_tune")))
>
> ;; The ISA we implement.
> -(define_attr "isa" "any,p5,p6,p7,p7v,p8,p8v,p9,p9v,p9kf,p9tf,p10"
> +(define_attr "isa" "any,p5,p6,p7,p7v,p8,p8v,p9,p9v,p9kf,p9tf,p10,future"
> (const_string "any"))
>
> ;; Is this alternative enabled for the current CPU/ISA/etc.?
> @@ -421,6 +421,9 @@
> (and (eq_attr "isa" "p10")
> (match_test "TARGET_POWER10"))
> (const_int 1)
> + (and (eq_attr "isa" "future")
> + (match_test "TARGET_FUTURE"))
> + (const_int 1)
> ] (const_int 0)))
>
> ;; If this instruction is microcoded on the CELL processor
> diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
> index 1305eff8cdd..640d3679034 100644
> --- a/gcc/config/rs6000/vsx.md
> +++ b/gcc/config/rs6000/vsx.md
> @@ -418,6 +418,9 @@
> (define_int_attr vczlsbb_char [(UNSPEC_VCLZLSBB "l")
> (UNSPEC_VCTZLSBB "t")])
>
> +;; Vector integer arithmetic modes
> +(define_mode_iterator VIArith [V8HI V4SI])
> +
> ;; VSX moves
>
> ;; TImode memory to memory move optimization on LE with p8vector
> @@ -1711,6 +1714,13 @@
> "xvsub<sd>p %x0,%x1,%x2"
> [(set_attr "type" "<VStype_simple>")])
>
> +(define_insn "vsx_mul<mode>3"
> + [(set (match_operand:VIArith 0 "vsx_register_operand" "=wa")
> + (mult:VIArith (match_operand:VIArith 1 "vsx_register_operand" "wa")
> + (match_operand:VIArith 2 "vsx_register_operand"
> "wa")))]
> + "TARGET_FUTURE && TARGET_VSX"
> + "xvmulu<wd>m %x0,%x1,%x2")
> +
> (define_insn "*vsx_mul<mode>3"
> [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
> (mult:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "wa")
> @@ -6546,22 +6556,62 @@
> [(set_attr "type" "vecdiv")
> (set_attr "size" "<bits>")])
>
> -(define_insn "smul<mode>3_highpart"
> - [(set (match_operand:VIlong 0 "altivec_register_operand" "=v")
> - (smul_highpart:VIlong
> - (match_operand:VIlong 1 "altivec_register_operand" "v")
> - (match_operand:VIlong 2 "altivec_register_operand" "v")))]
> +(define_insn "smulv8hi3_highpart"
> + [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
> + (smul_highpart:V8HI
> + (match_operand:V8HI 1 "vsx_register_operand" "wa")
> + (match_operand:V8HI 2 "vsx_register_operand" "wa")))]
> + "TARGET_FUTURE && TARGET_VSX"
> + "xvmulhsh %x0,%x1,%x2")
> +
> +(define_insn "smulv4si3_highpart"
> + [(set (match_operand:V4SI 0 "register_operand" "=wa,v")
> + (smul_highpart:V4SI
> + (match_operand:V4SI 1 "register_operand" "wa,v")
> + (match_operand:V4SI 2 "register_operand" "wa,v")))]
> + "TARGET_POWER10"
Here too, xvmulhsw should be emitted only if VSX is true.
> + "@
> + xvmulhsw %x0,%x1,%x2
> + vmulhsw %0,%1,%2"
> + [(set_attr "type" "veccomplex")
> + (set_attr "isa" "future,p10")])
> +
> +(define_insn "smulv2di3_highpart"
> + [(set (match_operand:V2DI 0 "altivec_register_operand" "=v")
> + (smul_highpart:V2DI
> + (match_operand:V2DI 1 "altivec_register_operand" "v")
> + (match_operand:V2DI 2 "altivec_register_operand" "v")))]
> "TARGET_POWER10"
> - "vmulhs<wd> %0,%1,%2"
> + "vmulhsd %0,%1,%2"
> [(set_attr "type" "veccomplex")])
>
> -(define_insn "umul<mode>3_highpart"
> - [(set (match_operand:VIlong 0 "altivec_register_operand" "=v")
> - (umul_highpart:VIlong
> - (match_operand:VIlong 1 "altivec_register_operand" "v")
> - (match_operand:VIlong 2 "altivec_register_operand" "v")))]
> +(define_insn "umulv8hi3_highpart"
> + [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
> + (umul_highpart:V8HI
> + (match_operand:V8HI 1 "vsx_register_operand" "wa")
> + (match_operand:V8HI 2 "vsx_register_operand" "wa")))]
> + "TARGET_FUTURE && TARGET_VSX"
> + "xvmulhuh %x0,%x1,%x2")
> +
> +(define_insn "umulv4si3_highpart"
> + [(set (match_operand:V4SI 0 "register_operand" "=wa,v")
> + (umul_highpart:V4SI
> + (match_operand:V4SI 1 "register_operand" "wa,v")
> + (match_operand:V4SI 2 "register_operand" "wa,v")))]
> + "TARGET_POWER10"
Ditto.
-Surya
> + "@
> + xvmulhuw %x0,%x1,%x2
> + vmulhuw %0,%1,%2"
> + [(set_attr "type" "veccomplex")
> + (set_attr "isa" "future,p10")])
> +
> +(define_insn "umulv2di3_highpart"
> + [(set (match_operand:V2DI 0 "altivec_register_operand" "=v")
> + (umul_highpart:V2DI
> + (match_operand:V2DI 1 "altivec_register_operand" "v")
> + (match_operand:V2DI 2 "altivec_register_operand" "v")))]
> "TARGET_POWER10"
> - "vmulhu<wd> %0,%1,%2"
> + "vmulhud %0,%1,%2"
> [(set_attr "type" "veccomplex")])
>
> ;; Vector multiply low double word
> diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
> index 4fbdc87f17c..494c0f69832 100644
> --- a/gcc/doc/extend.texi
> +++ b/gcc/doc/extend.texi
> @@ -26846,6 +26846,24 @@ vec_t __builtin_galois_field_mult_gcm (vec_t, vec_t);
> vec_t __builtin_galois_field_mult_xts (vec_t, vec_t);
> @end smallexample
>
> +@subsubheading PowerPC Vector Integer Multiply High Built-in Functions
> +
> +Future PowerPC processors may add new instructions for vector integer
> +multiply high for halfword. GCC provides support for these instructions
> through
> +the following built-in functions.
> +
> +@findex vec_mulh
> +@smallexample
> +@exdent vector signed short
> +@exdent vec_mulh (vector signed short @var{a}, vector signed short @var{b});
> +@exdent vector unsigned short
> +@exdent vec_mulh (vector unsigned short @var{a}, vector unsigned short
> @var{b});
> +@end smallexample
> +
> +For each integer value @code{i} from 0 to 7, do the following. The integer
> +value in halfword element @code{i} of @var{a} is multiplied by the integer
> +value in halfword element @code{i} of @var{b}. The high-order 16 bits of the
> +32-bit product are placed into halfword element @code{i} of the vector
> returned.
>
> @node PowerPC Hardware Transactional Memory Built-in Functions
> @subsection PowerPC Hardware Transactional Memory Built-in Functions
> diff --git a/gcc/testsuite/gcc.target/powerpc/vsx_arith_builtin-1.c
> b/gcc/testsuite/gcc.target/powerpc/vsx_arith_builtin-1.c
> new file mode 100644
> index 00000000000..0421a71980e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/vsx_arith_builtin-1.c
> @@ -0,0 +1,64 @@
> +/* { dg-do compile } */
> +/* { dg-options "-mdejagnu-cpu=future -O2" } */
> +/* { dg-require-effective-target powerpc_future_compile_ok } */
> +
> +#include <altivec.h>
> +
> +typedef vector signed int v4si_t;
> +typedef vector signed short v8hi_t;
> +typedef vector signed long long v2di_t;
> +
> +v4si_t int_add (v4si_t x, v4si_t y)
> +{
> + return vec_add (x, y); /* xvadduwm */
> +}
> +
> +v4si_t int_sub (v4si_t x, v4si_t y)
> +{
> + return vec_sub (x, y); /* xvsubuwm */
> +}
> +
> +v4si_t int_mul (v4si_t x, v4si_t y)
> +{
> + return vec_mul (x, y); /* xvmuluwm */
> +}
> +
> +v4si_t int_mulhi (v4si_t x, v4si_t y)
> +{
> + return vec_mulh (x, y); /* xvmulhsw */
> +}
> +
> +v8hi_t short_add (v8hi_t x, v8hi_t y)
> +{
> + return vec_add (x, y); /* xvadduhm */
> +}
> +
> +v8hi_t short_sub (v8hi_t x, v8hi_t y)
> +{
> + return vec_sub (x, y); /* xvsubuhm */
> +}
> +
> +v8hi_t short_mul (v8hi_t x, v8hi_t y)
> +{
> + return vec_mul (x, y); /* xvmuluhm */
> +}
> +
> +v8hi_t short_mulhi (v8hi_t x, v8hi_t y)
> +{
> + return vec_mulh (x, y); /* xvmulhsh */
> +}
> +
> +v2di_t longlong_mulhi (v2di_t x, v2di_t y)
> +{
> + return vec_mulh (x, y); /* vmulhsd */
> +}
> +
> +/* { dg-final { scan-assembler-times "xvadduwm" 1 } } */
> +/* { dg-final { scan-assembler-times "xvsubuwm" 1 } } */
> +/* { dg-final { scan-assembler-times "xvmuluwm" 1 } } */
> +/* { dg-final { scan-assembler-times "xvmulhsw" 1 } } */
> +/* { dg-final { scan-assembler-times "xvadduhm" 1 } } */
> +/* { dg-final { scan-assembler-times "xvsubuhm" 1 } } */
> +/* { dg-final { scan-assembler-times "xvmuluhm" 1 } } */
> +/* { dg-final { scan-assembler-times "xvmulhsh" 1 } } */
> +/* { dg-final { scan-assembler-times "vmulhsd" 1 } } */
> diff --git a/gcc/testsuite/gcc.target/powerpc/vsx_arith_builtin-2.c
> b/gcc/testsuite/gcc.target/powerpc/vsx_arith_builtin-2.c
> new file mode 100644
> index 00000000000..c44304041b3
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/vsx_arith_builtin-2.c
> @@ -0,0 +1,64 @@
> +/* { dg-do compile } */
> +/* { dg-options "-mdejagnu-cpu=future -O2" } */
> +/* { dg-require-effective-target powerpc_future_compile_ok } */
> +
> +#include <altivec.h>
> +
> +typedef vector unsigned int v4si_t;
> +typedef vector unsigned short v8hi_t;
> +typedef vector unsigned long long v2di_t;
> +
> +v4si_t uint_add (v4si_t x, v4si_t y)
> +{
> + return vec_add (x, y); /* xvadduwm */
> +}
> +
> +v4si_t uint_sub (v4si_t x, v4si_t y)
> +{
> + return vec_sub (x, y); /* xvsubuwm */
> +}
> +
> +v4si_t uint_mul (v4si_t x, v4si_t y)
> +{
> + return vec_mul (x, y); /* xvmuluwm */
> +}
> +
> +v4si_t uint_mulhi (v4si_t x, v4si_t y)
> +{
> + return vec_mulh (x, y); /* xvmulhuw */
> +}
> +
> +v8hi_t ushort_add (v8hi_t x, v8hi_t y)
> +{
> + return vec_add (x, y); /* xvadduhm */
> +}
> +
> +v8hi_t ushort_sub (v8hi_t x, v8hi_t y)
> +{
> + return vec_sub (x, y); /* xvsubuhm */
> +}
> +
> +v8hi_t ushort_mul (v8hi_t x, v8hi_t y)
> +{
> + return vec_mul (x, y); /* xvmuluhm */
> +}
> +
> +v8hi_t ushort_mulhi (v8hi_t x, v8hi_t y)
> +{
> + return vec_mulh (x, y); /* xvmulhuh */
> +}
> +
> +v2di_t ulonglong_mulhi (v2di_t x, v2di_t y)
> +{
> + return vec_mulh (x, y); /* vmulhud */
> +}
> +
> +/* { dg-final { scan-assembler-times "xvadduwm" 1 } } */
> +/* { dg-final { scan-assembler-times "xvsubuwm" 1 } } */
> +/* { dg-final { scan-assembler-times "xvmuluwm" 1 } } */
> +/* { dg-final { scan-assembler-times "xvmulhuw" 1 } } */
> +/* { dg-final { scan-assembler-times "xvadduhm" 1 } } */
> +/* { dg-final { scan-assembler-times "xvsubuhm" 1 } } */
> +/* { dg-final { scan-assembler-times "xvmuluhm" 1 } } */
> +/* { dg-final { scan-assembler-times "xvmulhuh" 1 } } */
> +/* { dg-final { scan-assembler-times "vmulhud" 1 } } */
> diff --git a/gcc/testsuite/gcc.target/powerpc/vsx_arith_builtin-3.c
> b/gcc/testsuite/gcc.target/powerpc/vsx_arith_builtin-3.c
> new file mode 100644
> index 00000000000..675d6b07445
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/vsx_arith_builtin-3.c
> @@ -0,0 +1,52 @@
> +/* { dg-do compile } */
> +/* { dg-options "-mdejagnu-cpu=future -O2 -mno-vsx" } */
> +/* { dg-require-effective-target powerpc_future_compile_ok } */
> +
> +#include <altivec.h>
> +
> +typedef vector signed int vsi;
> +typedef vector signed short vss;
> +typedef vector unsigned int vui;
> +
> +vsi int_add (vsi x, vsi y)
> +{
> + return vec_add (x, y); /* vadduwm */
> +}
> +
> +vsi int_sub (vsi x, vsi y)
> +{
> + return vec_sub (x, y); /* vsubuwm */
> +}
> +
> +vsi int_mulhi (vsi x, vsi y)
> +{
> + return vec_mulh (x, y); /* vmulhsw */
> +}
> +
> +vui uint_mulh (vui x, vui y)
> +{
> + return vec_mulh (x, y); /* vmulhuw */
> +}
> +
> +vss short_add (vss x, vss y)
> +{
> + return vec_add (x, y); /* vadduhm */
> +}
> +
> +vss short_sub (vss x, vss y)
> +{
> + return vec_sub (x, y); /* vsubuhm */
> +}
> +
> +vss short_mul (vss x, vss y)
> +{
> + return vec_mul (x, y); /* vmladduhm */
> +}
> +
> +/* { dg-final { scan-assembler-times "vadduwm" 1 } } */
> +/* { dg-final { scan-assembler-times "vsubuwm" 1 } } */
> +/* { dg-final { scan-assembler-times "vmulhsw" 1 } } */
> +/* { dg-final { scan-assembler-times "vmulhuw" 1 } } */
> +/* { dg-final { scan-assembler-times "vadduhm" 1 } } */
> +/* { dg-final { scan-assembler-times "vsubuhm" 1 } } */
> +/* { dg-final { scan-assembler-times "vmladduhm" 1 } } */
> diff --git a/gcc/testsuite/gcc.target/powerpc/vsx_arith_builtin-4.c
> b/gcc/testsuite/gcc.target/powerpc/vsx_arith_builtin-4.c
> new file mode 100644
> index 00000000000..56a3f2a9784
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/vsx_arith_builtin-4.c
> @@ -0,0 +1,20 @@
> +/* { dg-do compile } */
> +/* { dg-options "-mdejagnu-cpu=future -O2 -mno-vsx" } */
> +/* { dg-require-effective-target powerpc_future_compile_ok } */
> +
> +#include <altivec.h>
> +
> +typedef vector signed short vss;
> +typedef vector unsigned short vus;
> +
> +__attribute__((noinline))
> +vss short_mulhi (vss x, vss y)
> +{
> + return vec_mulh (x, y); /* { dg-error "'__builtin_vsx_xvmulhsh' requires
> the '-mcpu=future' and '-mvsx' options" } */
> +}
> +
> +__attribute__((noinline))
> +vus ushort_mulhi (vus x, vus y)
> +{
> + return vec_mulh (x, y); /* { dg-error "'__builtin_vsx_xvmulhuh' requires
> the '-mcpu=future' and '-mvsx' options" } */
> +}
> diff --git a/gcc/testsuite/gcc.target/powerpc/vsx_arith_vect_1.c
> b/gcc/testsuite/gcc.target/powerpc/vsx_arith_vect_1.c
> new file mode 100644
> index 00000000000..fce087689f6
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/vsx_arith_vect_1.c
> @@ -0,0 +1,77 @@
> +/* { dg-do compile } */
> +/* { dg-options "-mdejagnu-cpu=future -O2" } */
> +/* { dg-require-effective-target powerpc_future_compile_ok } */
> +
> +#include <altivec.h>
> +
> +typedef vector signed int vsi;
> +typedef vector unsigned int vui;
> +typedef vector signed short vss;
> +typedef vector unsigned short vus;
> +
> +vsi int_add (vsi x, vsi y)
> +{
> + return x + y; /* xvadduwm */
> +}
> +
> +vsi int_sub (vsi x, vsi y)
> +{
> + return x - y; /* xvsubuwm */
> +}
> +
> +vsi int_mul (vsi x, vsi y)
> +{
> + return x * y; /* xvmuluwm */
> +}
> +
> +vui uint_add (vui x, vui y)
> +{
> + return x + y; /* xvadduwm */
> +}
> +
> +vui uint_sub (vui x, vui y)
> +{
> + return x - y; /* xvsubuwm */
> +}
> +
> +vui uint_mul (vui x, vui y)
> +{
> + return x * y; /* xvmuluwm */
> +}
> +
> +vss short_add (vss x, vss y)
> +{
> + return x + y; /* xvadduhm */
> +}
> +
> +vss short_sub (vss x, vss y)
> +{
> + return x - y; /* xvsubuhm */
> +}
> +
> +vss short_mul (vss x, vss y)
> +{
> + return x * y; /* xvmuluhm */
> +}
> +
> +vus ushort_add (vus x, vus y)
> +{
> + return x + y; /* xvadduhm */
> +}
> +
> +vus ushort_sub (vus x, vus y)
> +{
> + return x - y; /* xvsubuhm */
> +}
> +
> +vus ushort_mul (vus x, vus y)
> +{
> + return x * y; /* xvmuluhm */
> +}
> +
> +/* { dg-final { scan-assembler-times "xvadduwm" 2 } } */
> +/* { dg-final { scan-assembler-times "xvsubuwm" 2 } } */
> +/* { dg-final { scan-assembler-times "xvmuluwm" 2 } } */
> +/* { dg-final { scan-assembler-times "xvadduhm" 2 } } */
> +/* { dg-final { scan-assembler-times "xvsubuhm" 2 } } */
> +/* { dg-final { scan-assembler-times "xvmuluhm" 2 } } */
> diff --git a/gcc/testsuite/gcc.target/powerpc/vsx_arith_vect_2.c
> b/gcc/testsuite/gcc.target/powerpc/vsx_arith_vect_2.c
> new file mode 100644
> index 00000000000..15f85803be5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/vsx_arith_vect_2.c
> @@ -0,0 +1,43 @@
> +/* { dg-do compile } */
> +/* { dg-options "-mdejagnu-cpu=future -O2 -ftree-vectorize
> -fno-unroll-loops" } */
> +/* { dg-require-effective-target powerpc_future_compile_ok } */
> +
> +#define N 128
> +
> +extern signed int si_a[N], si_b[N], si_c[N];
> +extern unsigned int ui_a[N], ui_b[N], ui_c[N];
> +extern signed short ss_a[N], ss_b[N], ss_c[N];
> +extern unsigned short us_a[N], us_b[N], us_c[N];
> +
> +void int_mulhi ()
> +{
> + for (int i = 0; i < N; i++)
> + si_c[i] = ((signed long long) si_a[i] *
> + (signed long long) si_b[i]) >> 32;
> +}
> +
> +void uint_mulhi ()
> +{
> + for (int i = 0; i < N; i++)
> + ui_c[i] = ((unsigned long long) ui_a[i] *
> + (unsigned long long) ui_b[i]) >> 32;
> +}
> +
> +void short_mulhi ()
> +{
> + for (int i = 0; i < N; i++)
> + ss_c[i] = ((signed int) ss_a[i] *
> + (signed int) ss_b[i]) >> 16;
> +}
> +
> +void ushort_mulhi ()
> +{
> + for (int i = 0; i < N; i++)
> + us_c[i] = ((unsigned int) us_a[i] *
> + (unsigned int) us_b[i]) >> 16;
> +}
> +
> +/* { dg-final { scan-assembler-times {\mxvmulhsw\M} 1 } } */
> +/* { dg-final { scan-assembler-times {\mxvmulhuw\M} 1 } } */
> +/* { dg-final { scan-assembler-times {\mxvmulhsh\M} 1 } } */
> +/* { dg-final { scan-assembler-times {\mxvmulhuh\M} 1 } } */
>
>