Hi,
On 19/05/26 5:25 PM, jeevitha wrote:
> Hi All,
>
> The following changes have been bootstrapped and regression tested on
> powerpc64le-linux. Is this okay for trunk?
>
> 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. Existing Altivec
> patterns are renamed to altivec_* to avoid name conflicts.
>
> 2026-05-19 Jeevitha Palanisamy <[email protected]>
>
> gcc/
> * config/rs6000/altivec.md (*vsx_add<mode>3): New insn pattern.
> (*altivec_add<mode>3): Renamed from add<mode>3.
> (*vsx_sub<mode>3): New insn pattern.
> (*altivec_sub<mode>3): Renamed from sub<mode>3.
> * config/rs6000/vector.md (VIMulH): New mode iterator.
> (add<mode>3): New expand pattern.
> (sub<mode>3): Likewise.
> (smul<mode>3_highpart): Likewise.
> (umul<mode>3_highpart): Likewise.
> * config/rs6000/vsx.md (VIArith): New mode iterator.
> (*vsx_mul<mode>3): New insn pattern.
> (vsx_smul<mode>3_highpart): Likewise.
> (vsx_umul<mode>3_highpart): Likewise.
> (*altivec_smul<mode>3_highpart): Renamed from smul<mode>3_highpart.
> (*altivec_umul<mode>3_highpart): Renamed from umul<mode>3_highpart.
> * 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_FUTUREV.
s/BSTZ_FUTUREV/BSTZ_FUTURE_VSX
> (stanza_map): Add future-vsx stanza mapping.
> (enable_string): Add ENB_FUTUREV.
Let's rename as ENB_FUTURE_VSX. 'V' has been used to denote 'vector' in other
stanzas, but here we want to represent VSX.
> (write_decls): Add ENB_FUTUREV to the bif_enable enum in the generated
> header file.
> * config/rs6000/rs6000-builtin.cc (rs6000_invalid_builtin): Handle
> ENB_FUTUREV and issue a diagnostic requiring -mcpu=future and -mvsx.
> (rs6000_builtin_is_supported): Return TARGET_FUTURE && TARGET_VSX for
> ENB_FUTUREV built-ins.
> * doc/extend.texi (PowerPC AltiVec/VSX Built-in Functions Available
> on Future ISA): Document new functions.
>
> gcc/testsuite/
> * gcc.target/powerpc/vsx_simd-1.c: New test.
> * gcc.target/powerpc/vsx_simd-2.c: Likewise.
> * gcc.target/powerpc/vsx_simd-3.c: Likewise.
> * gcc.target/powerpc/vsx_simd-4.c: Likewise.
>
> diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
> index 129f56245cd..3bdc22d5f9e 100644
> --- a/gcc/config/rs6000/altivec.md
> +++ b/gcc/config/rs6000/altivec.md
> @@ -503,11 +503,18 @@
>
> ;; Simple binary operations.
>
> +(define_insn "*vsx_add<mode>3"
> + [(set (match_operand:VIArith 0 "vsx_register_operand" "=wa")
> + (plus:VIArith (match_operand:VIArith 1 "vsx_register_operand" "wa")
> + (match_operand:VIArith 2 "vsx_register_operand"
> "wa")))]
> + "TARGET_FUTURE && TARGET_VSX"
> + "xvaddu<VI_char>m %x0,%x1,%x2")
> +
> ;; 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")))]
> +(define_insn "*altivec_add<mode>3"
> + [(set (match_operand:VEC_I 0 "register_operand" "=v")
> + (plus:VEC_I (match_operand:VEC_I 1 "register_operand" "v")
> + (match_operand:VEC_I 2 "register_operand" "v")))]
> "<VI_unit>"
> "vaddu<VI_char>m %0,%1,%2"
> [(set_attr "type" "vecsimple")])
> @@ -547,11 +554,18 @@
> "vadds<VI_char>s %0,%1,%2"
> [(set_attr "type" "vecsimple")])
>
> +(define_insn "*vsx_sub<mode>3"
> + [(set (match_operand:VIArith 0 "vsx_register_operand" "=wa")
> + (minus:VIArith (match_operand:VIArith 1 "vsx_register_operand" "wa")
> + (match_operand:VIArith 2 "vsx_register_operand"
> "wa")))]
> + "TARGET_FUTURE && TARGET_VSX"
> + "xvsubu<VI_char>m %x0,%x1,%x2")
> +
> ;; 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")))]
> +(define_insn "*altivec_sub<mode>3"
> + [(set (match_operand:VEC_I 0 "register_operand" "=v")
> + (minus:VEC_I (match_operand:VEC_I 1 "register_operand" "v")
> + (match_operand:VEC_I 2 "register_operand" "v")))]
> "<VI_unit>"
> "vsubu<VI_char>m %0,%1,%2"
> [(set_attr "type" "vecsimple")])
> diff --git a/gcc/config/rs6000/rs6000-builtin.cc
> b/gcc/config/rs6000/rs6000-builtin.cc
> index 4d0e541351f..94f0c9d8ab8 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_FUTUREV:
> + 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_FUTUREV:
> + 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..0e7553eb196 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 vsx_umulv8hi3_highpart {}
> +
> + const vss __builtin_vsx_xvmulhsh (vss, vss);
> + XVMULHSH vsx_smulv8hi3_highpart {}
> diff --git a/gcc/config/rs6000/rs6000-gen-builtins.cc
> b/gcc/config/rs6000/rs6000-gen-builtins.cc
> index 7436404cff5..035b63f08a0 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_FUTUREV,
> 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_FUTUREV }
> };
>
> 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_FUTUREV"
> };
>
> /* 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_FUTUREV\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/vector.md b/gcc/config/rs6000/vector.md
> index e6adf91002e..80fb46c8f00 100644
> --- a/gcc/config/rs6000/vector.md
> +++ b/gcc/config/rs6000/vector.md
> @@ -71,6 +71,9 @@
> ;; Vector integer modes
> (define_mode_iterator VI [V4SI V8HI V16QI])
>
> +;; Vector integer multiply high modes
> +(define_mode_iterator VIMulH [V4SI V2DI])
> +
> ;; Base type from vector mode
> (define_mode_attr VEC_base [(V16QI "QI")
> (V8HI "HI")
> @@ -188,6 +191,14 @@
> "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
> "")
>
> +;; This expander will be mapped to *vsx_add<mode>3 / *altivec_add<mode>3
> +(define_expand "add<mode>3"
> + [(set (match_operand:VEC_I 0 "register_operand")
> + (plus:VEC_I (match_operand:VEC_I 1 "register_operand")
> + (match_operand:VEC_I 2 "register_operand")))]
> + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
> + "")
> +
> (define_expand "sub<mode>3"
> [(set (match_operand:VEC_F 0 "vfloat_operand")
> (minus:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
> @@ -195,6 +206,14 @@
> "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
> "")
>
> +;; This expander will be mapped to *vsx_sub<mode>3 / *altivec_sub<mode>3
> +(define_expand "sub<mode>3"
> + [(set (match_operand:VEC_I 0 "register_operand")
> + (minus:VEC_I (match_operand:VEC_I 1 "register_operand")
> + (match_operand:VEC_I 2 "register_operand")))]
> + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
> + "")
> +
> (define_expand "mul<mode>3"
> [(set (match_operand:VEC_F 0 "vfloat_operand")
> (mult:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
> @@ -208,6 +227,28 @@
> }
> })
>
> +;; This expander will be mapped to
> +;; *altivec_smul<mode>3_highpart /
> +;; vsx_smul<mode>3_highpart.
> +(define_expand "smul<mode>3_highpart"
> + [(set (match_operand:VIMulH 0 "register_operand")
> + (smul_highpart:VIMulH
> + (match_operand:VIMulH 1 "register_operand")
> + (match_operand:VIMulH 2 "register_operand")))]
> + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode) && TARGET_POWER10"
> + "")
> +
> +;; This expander will be mapped to
> +;; *altivec_umul<mode>3_highpart /
> +;; vsx_umul<mode>3_highpart.
> +(define_expand "umul<mode>3_highpart"
> + [(set (match_operand:VIMulH 0 "register_operand")
> + (umul_highpart:VIMulH
> + (match_operand:VIMulH 1 "register_operand")
> + (match_operand:VIMulH 2 "register_operand")))]
> + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode) && TARGET_POWER10"
> + "")
> +
> (define_expand "div<mode>3"
> [(set (match_operand:VEC_F 0 "vfloat_operand")
> (div:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
> diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
> index f5ace28ea93..10064e3e9b1 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,20 +6556,36 @@
> [(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 "vsx_smul<mode>3_highpart"
> + [(set (match_operand:VIArith 0 "vsx_register_operand" "=wa")
> + (smul_highpart:VIArith
> + (match_operand:VIArith 1 "vsx_register_operand" "wa")
> + (match_operand:VIArith 2 "vsx_register_operand" "wa")))]
> + "TARGET_FUTURE && TARGET_VSX"
> + "xvmulhs<wd> %x0,%x1,%x2")
> +
> +(define_insn "vsx_umul<mode>3_highpart"
> + [(set (match_operand:VIArith 0 "vsx_register_operand" "=wa")
> + (umul_highpart:VIArith
> + (match_operand:VIArith 1 "vsx_register_operand" "wa")
> + (match_operand:VIArith 2 "vsx_register_operand" "wa")))]
> + "TARGET_FUTURE && TARGET_VSX"
> + "xvmulhu<wd> %x0,%x1,%x2")
> +
> +(define_insn "*altivec_smul<mode>3_highpart"
> + [(set (match_operand:VIMulH 0 "altivec_register_operand" "=v")
> + (smul_highpart:VIMulH
> + (match_operand:VIMulH 1 "altivec_register_operand" "v")
> + (match_operand:VIMulH 2 "altivec_register_operand" "v")))]
> "TARGET_POWER10"
> "vmulhs<wd> %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 "*altivec_umul<mode>3_highpart"
> + [(set (match_operand:VIMulH 0 "altivec_register_operand" "=v")
> + (umul_highpart:VIMulH
> + (match_operand:VIMulH 1 "altivec_register_operand" "v")
> + (match_operand:VIMulH 2 "altivec_register_operand" "v")))]
> "TARGET_POWER10"
> "vmulhu<wd> %0,%1,%2"
> [(set_attr "type" "veccomplex")])
> diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
> index 01ffe30c441..5a5f9ce28c0 100644
> --- a/gcc/doc/extend.texi
> +++ b/gcc/doc/extend.texi
> @@ -26761,6 +26761,22 @@ vec_t __builtin_galois_field_mult_gcm (vec_t, vec_t);
> vec_t __builtin_galois_field_mult_xts (vec_t, vec_t);
> @end smallexample
>
> +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.
It would be good to have a subheading here, denoting what is being added.
A similar thing is being done in the ECC builtins patch. I understand that
a subheading was not added for the AES builtins, but we will need to add one
for that too. That would be a separate patch though.
-Surya
> +
> +@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_simd-1.c
> b/gcc/testsuite/gcc.target/powerpc/vsx_simd-1.c
> new file mode 100644
> index 00000000000..486fef38dae
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/vsx_simd-1.c
> @@ -0,0 +1,72 @@
> +/* { dg-do compile } */
> +/* { dg-options "-mdejagnu-cpu=future -O2" } */
> +
> +#include <altivec.h>
> +
> +typedef vector signed int v4si_t;
> +typedef vector signed short v8hi_t;
> +typedef vector signed long long v2di_t;
> +
> +__attribute__((noinline))
> +v4si_t int_add (v4si_t x, v4si_t y)
> +{
> + return vec_add (x, y); /* xvadduwm */
> +}
> +
> +__attribute__((noinline))
> +v4si_t int_sub (v4si_t x, v4si_t y)
> +{
> + return vec_sub (x, y); /* xvsubuwm */
> +}
> +
> +__attribute__((noinline))
> +v4si_t int_mul (v4si_t x, v4si_t y)
> +{
> + return vec_mul (x, y); /* xvmuluwm */
> +}
> +
> +__attribute__((noinline))
> +v4si_t int_mulhi (v4si_t x, v4si_t y)
> +{
> + return vec_mulh (x, y); /* xvmulhsw */
> +}
> +
> +__attribute__((noinline))
> +v8hi_t short_add (v8hi_t x, v8hi_t y)
> +{
> + return vec_add (x, y); /* xvadduhm */
> +}
> +
> +__attribute__((noinline))
> +v8hi_t short_sub (v8hi_t x, v8hi_t y)
> +{
> + return vec_sub (x, y); /* xvsubuhm */
> +}
> +
> +__attribute__((noinline))
> +v8hi_t short_mul (v8hi_t x, v8hi_t y)
> +{
> + return vec_mul (x, y); /* xvmuluhm */
> +}
> +
> +__attribute__((noinline))
> +v8hi_t short_mulhi (v8hi_t x, v8hi_t y)
> +{
> + return vec_mulh (x, y); /* xvmulhsh */
> +}
> +
> +__attribute__((noinline))
> +v2di_t longlong_mul (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_simd-2.c
> b/gcc/testsuite/gcc.target/powerpc/vsx_simd-2.c
> new file mode 100644
> index 00000000000..04e1997d66f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/vsx_simd-2.c
> @@ -0,0 +1,72 @@
> +/* { dg-do compile } */
> +/* { dg-options "-mdejagnu-cpu=future -O2" } */
> +
> +#include <altivec.h>
> +
> +typedef vector unsigned int v4si_t;
> +typedef vector unsigned short v8hi_t;
> +typedef vector unsigned long long v2di_t;
> +
> +__attribute__((noinline))
> +v4si_t int_add (v4si_t x, v4si_t y)
> +{
> + return vec_add (x, y); /* xvadduwm */
> +}
> +
> +__attribute__((noinline))
> +v4si_t int_sub (v4si_t x, v4si_t y)
> +{
> + return vec_sub (x, y); /* xvsubuwm */
> +}
> +
> +__attribute__((noinline))
> +v4si_t int_mul (v4si_t x, v4si_t y)
> +{
> + return vec_mul (x, y); /* xvmuluwm */
> +}
> +
> +__attribute__((noinline))
> +v4si_t int_mulhi (v4si_t x, v4si_t y)
> +{
> + return vec_mulh (x, y); /* xvmulhuw */
> +}
> +
> +__attribute__((noinline))
> +v8hi_t short_add (v8hi_t x, v8hi_t y)
> +{
> + return vec_add (x, y); /* xvadduhm */
> +}
> +
> +__attribute__((noinline))
> +v8hi_t short_sub (v8hi_t x, v8hi_t y)
> +{
> + return vec_sub (x, y); /* xvsubuhm */
> +}
> +
> +__attribute__((noinline))
> +v8hi_t short_mul (v8hi_t x, v8hi_t y)
> +{
> + return vec_mul (x, y); /* xvmuluhm */
> +}
> +
> +__attribute__((noinline))
> +v8hi_t short_mulhi (v8hi_t x, v8hi_t y)
> +{
> + return vec_mulh (x, y); /* xvmulhuh */
> +}
> +
> +__attribute__((noinline))
> +v2di_t longlong_mul (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_simd-3.c
> b/gcc/testsuite/gcc.target/powerpc/vsx_simd-3.c
> new file mode 100644
> index 00000000000..e58db04714d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/vsx_simd-3.c
> @@ -0,0 +1,58 @@
> +/* { dg-do compile } */
> +/* { dg-options "-mdejagnu-cpu=future -O2 -mno-vsx" } */
> +
> +#include <altivec.h>
> +
> +typedef vector signed int vsi;
> +typedef vector signed short vss;
> +typedef vector unsigned int vui;
> +
> +__attribute__((noinline))
> +vsi int_add (vsi x, vsi y)
> +{
> + return vec_add (x, y); /* vadduwm */
> +}
> +
> +__attribute__((noinline))
> +vsi int_sub (vsi x, vsi y)
> +{
> + return vec_sub (x, y); /* vsubuwm */
> +}
> +
> +__attribute__((noinline))
> +vsi int_mulhi (vsi x, vsi y)
> +{
> + return vec_mulh (x, y); /* vmulhsw */
> +}
> +
> +__attribute__((noinline))
> +vui uint_mulh (vui x, vui y)
> +{
> + return vec_mulh (x, y); /* vmulhuw */
> +}
> +
> +__attribute__((noinline))
> +vss short_add (vss x, vss y)
> +{
> + return vec_add (x, y); /* vadduhm */
> +}
> +
> +__attribute__((noinline))
> +vss short_sub (vss x, vss y)
> +{
> + return vec_sub (x, y); /* vsubuhm */
> +}
> +
> +__attribute__((noinline))
> +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_simd-4.c
> b/gcc/testsuite/gcc.target/powerpc/vsx_simd-4.c
> new file mode 100644
> index 00000000000..be6ab3c91a6
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/vsx_simd-4.c
> @@ -0,0 +1,19 @@
> +/* { dg-do compile } */
> +/* { dg-options "-mdejagnu-cpu=future -O2 -mno-vsx" } */
> +
> +#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" } */
> +}