Hi,
On 11/05/26 5:48 PM, jeevitha wrote:
> Hi All,
>
> This patch depends on the smul/umul pattern fix. This will be upstreamed
> after the above fix is upstreamed. These changes have been bootstrapped
> and regression tested on powerpc64le-linux. Is this okay for trunk?
>
> 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-11 Jeevitha Palanisamy <[email protected]>
>
> gcc/
> * config/rs6000/altivec.md (*vsx_add<mode>3): New pattern for VSX
> vector add for halfword and word.
> (*altivec_add<mode>3): Renamed from add<mode>3.
> (*vsx_sub<mode>3): New pattern for VSX vector subtract for halfword and
> word.
> (*altivec_sub<mode>3): Renamed from sub<mode>3.
> * config/rs6000/vector.md (VIMulH): New mode iterator for V4SI and V2DI.
> (add<mode>3): New expand pattern for integer vector add.
> (sub<mode>3): New expand pattern for integer vector subtract.
> (smul<mode>3_highpart): New expand pattern for signed vector
> multiply-high part on VIMulH modes.
> (umul<mode>3_highpart): New expand pattern for unsigned vector
'New expand pattern'.
> multiply-high part on VIMulH modes.
> * config/rs6000/vsx.md (VIArith): New mode iterator for V8HI and V4SI.
Just 'New mode iterator.'
> (vsx_mul<mode>3): New VSX vector multiply pattern for halfword and word.
> (vsx_smul<mode>3_highpart): New VSX signed multiply-high pattern for
> halfword and word.
> (vsx_umul<mode>3_highpart): New VSX unsigned multiply-high pattern for
> halfword and word.
> (*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 for VSX unsigned multiply-high halfword.
> (__builtin_vsx_xvmulhsh): New builtin for VSX signed multiply-high
> halfword.
Just 'New builtin.'
> * config/rs6000/rs6000-overload.def (__builtin_vec_mulh): Add
> overloads for vector multiply-high signed/unsigned halfword.
> * 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: New test.
>
> diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
> index 129f56245cd..ed04aebdba9 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"
We should also check for TARGET_VSX. So the check should be:
TARGET_FUTURE && TARGET_VSX
Also, let's place the define_expand and the define_insn's for
add<mode>3 in the same file for better readability.
> + "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"
Ditto.
> + "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-builtins.def
> b/gcc/config/rs6000/rs6000-builtins.def
> index 0d1529b71d4..8bac1133a6b 100644
> --- a/gcc/config/rs6000/rs6000-builtins.def
> +++ b/gcc/config/rs6000/rs6000-builtins.def
> @@ -3970,3 +3970,9 @@
>
> const vuc __builtin_galois_field_mult_xts (vuc, vuc);
> XXGFMUL128XTS xxgfmul128xts {}
> +
> + const vus __builtin_vsx_xvmulhuh (vus, vus);
> + XVMULHUH vsx_umulv8hi3_highpart {}
> +
> + const vss __builtin_vsx_xvmulhsh (vss, vss);
> + XVMULHSH vsx_smulv8hi3_highpart {}
Please add these adjacent to the exising *highpart entries.
> 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..6dbb95e8982 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,13 @@
> "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
> "")
>
> +(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 +205,13 @@
> "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
> "")
>
> +(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 +225,22 @@
> }
> })
>
> +(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"
> + "")
> +
> +(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"
> + "")
> +
Please keep all the 'highpart' patterns together.
We also need a few more tests to test the following:
1. Check that for -mcpu=future and a call to vec_mulh(vsll, vsll)
produces vmulhsd.
2. Check that for -mcpu=future -mnovsx, a call to vec_mulh(vui, vui)
produces vmulhuw.
3. Check that for -mcpu=future -mnovsx, a call to vec_add(vui, vui)
produces the expected instruction.
> (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 c99b6602135..9d1b5404095 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"
Check for TARGET_VSX needed here too.
Also pls add '*' prefix to vsx_mul<mode>3.
> + "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"
> + "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 here too?
-Surya
> + "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 42f83b98a05..7495a9df31d 100644
> --- a/gcc/doc/extend.texi
> +++ b/gcc/doc/extend.texi
> @@ -26737,6 +26737,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.
> +
> +@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..aca3ea67013
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/vsx_simd-1.c
> @@ -0,0 +1,64 @@
> +/* { dg-do compile } */
> +/* { dg-options "-mdejagnu-cpu=future -O2" } */
> +
> +#include <altivec.h>
> +
> +typedef vector signed int v4si_t;
> +typedef vector signed short v8hi_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 */
> +}
> +
> +/* { 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 } } */
> 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..31594255509
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/vsx_simd-2.c
> @@ -0,0 +1,64 @@
> +/* { dg-do compile } */
> +/* { dg-options "-mdejagnu-cpu=future -O2" } */
> +
> +#include <altivec.h>
> +
> +typedef vector unsigned int v4si_t;
> +typedef vector unsigned short v8hi_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 */
> +}
> +
> +/* { 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 } } */