https://gcc.gnu.org/g:a3b8e252101ada1777274faeebc29c3d4560e9b4
commit r17-1800-ga3b8e252101ada1777274faeebc29c3d4560e9b4 Author: Jeevitha <[email protected]> Date: Wed Jun 24 06:14:28 2026 -0500 rs6000: Add Future Vector Integer Arithmetic Instructions [RFC02680] 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-24 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: --- gcc/config/rs6000/altivec.md | 36 +++++++-- gcc/config/rs6000/rs6000-builtin.cc | 6 ++ gcc/config/rs6000/rs6000-builtins.def | 7 ++ gcc/config/rs6000/rs6000-gen-builtins.cc | 10 ++- gcc/config/rs6000/rs6000-overload.def | 4 + gcc/config/rs6000/rs6000.md | 6 +- gcc/config/rs6000/vsx.md | 74 +++++++++++++++--- gcc/doc/extend.texi | 18 +++++ .../gcc.target/powerpc/vsx_arith_builtin-1.c | 74 ++++++++++++++++++ .../gcc.target/powerpc/vsx_arith_builtin-2.c | 74 ++++++++++++++++++ .../gcc.target/powerpc/vsx_arith_builtin-3.c | 56 ++++++++++++++ .../gcc.target/powerpc/vsx_arith_builtin-4.c | 20 +++++ .../gcc.target/powerpc/vsx_arith_vect_1.c | 90 ++++++++++++++++++++++ .../gcc.target/powerpc/vsx_arith_vect_2.c | 43 +++++++++++ 14 files changed, 496 insertions(+), 22 deletions(-) diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md index 129f56245cd0..dbe24c450e14 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>" + "@ + 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>" + "@ + 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 df45e2d82ed9..541958d38c0d 100644 --- a/gcc/config/rs6000/rs6000-builtin.cc +++ b/gcc/config/rs6000/rs6000-builtin.cc @@ -146,6 +146,10 @@ rs6000_invalid_builtin (enum rs6000_gen_builtins fncode) error ("%qs requires the %qs and %qs options", name, "-mcpu=future", "-maltivec"); break; + case ENB_FUTURE_VSX: + error ("%qs requires the %qs and %qs options", name, "-mcpu=future", + "-mvsx"); + break; default: case ENB_ALWAYS: gcc_unreachable (); @@ -205,6 +209,8 @@ rs6000_builtin_is_supported (enum rs6000_gen_builtins fncode) return TARGET_FUTURE; case ENB_FUTURE_ALTIVEC: return TARGET_FUTURE && TARGET_ALTIVEC; + 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 0d1529b71d42..b5b6c98b69e9 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 32c1f4ef83d9..28ba90cea0f7 100644 --- a/gcc/config/rs6000/rs6000-gen-builtins.cc +++ b/gcc/config/rs6000/rs6000-gen-builtins.cc @@ -234,6 +234,7 @@ enum bif_stanza BSTZ_MMA, BSTZ_FUTURE, BSTZ_FUTURE_ALTIVEC, + BSTZ_FUTURE_VSX, NUMBIFSTANZAS }; @@ -269,7 +270,8 @@ static stanza_entry stanza_map[NUMBIFSTANZAS] = { "power10-64", BSTZ_P10_64 }, { "mma", BSTZ_MMA }, { "future", BSTZ_FUTURE }, - { "future-altivec", BSTZ_FUTURE_ALTIVEC } + { "future-altivec", BSTZ_FUTURE_ALTIVEC }, + { "future-vsx", BSTZ_FUTURE_VSX } }; static const char *enable_string[NUMBIFSTANZAS] = @@ -296,7 +298,8 @@ static const char *enable_string[NUMBIFSTANZAS] = "ENB_P10_64", "ENB_MMA", "ENB_FUTURE", - "ENB_FUTURE_ALTIVEC" + "ENB_FUTURE_ALTIVEC", + "ENB_FUTURE_VSX" }; /* Function modifiers provide special handling for const, pure, and fpmath @@ -2257,7 +2260,8 @@ write_decls (void) fprintf (header_file, " ENB_P10_64,\n"); fprintf (header_file, " ENB_MMA,\n"); fprintf (header_file, " ENB_FUTURE,\n"); - fprintf (header_file, " ENB_FUTURE_ALTIVEC\n"); + fprintf (header_file, " ENB_FUTURE_ALTIVEC,\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 ef7b59ed112a..09be9e7de71c 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 2ccbe178bb53..4ec3d3da8a99 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,10 @@ (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 1305eff8cddb..640d36790343 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" + "@ + 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" + "@ + 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 9b54348d18f0..2e8ec8a0af2c 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 000000000000..701c0028f955 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/vsx_arith_builtin-1.c @@ -0,0 +1,74 @@ +/* { 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) +{ + /* force x & y into FPRs to prefer xvadduwm over vadduwm. */ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return vec_add (x, y); /* xvadduwm */ +} + +v4si_t int_sub (v4si_t x, v4si_t y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return vec_sub (x, y); /* xvsubuwm */ +} + +v4si_t int_mul (v4si_t x, v4si_t y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return vec_mul (x, y); /* xvmuluwm */ +} + +v4si_t int_mulhi (v4si_t x, v4si_t y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return vec_mulh (x, y); /* xvmulhsw */ +} + +v8hi_t short_add (v8hi_t x, v8hi_t y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return vec_add (x, y); /* xvadduhm */ +} + +v8hi_t short_sub (v8hi_t x, v8hi_t y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return vec_sub (x, y); /* xvsubuhm */ +} + +v8hi_t short_mul (v8hi_t x, v8hi_t y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return vec_mul (x, y); /* xvmuluhm */ +} + +v8hi_t short_mulhi (v8hi_t x, v8hi_t y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return vec_mulh (x, y); /* xvmulhsh */ +} + +v2di_t longlong_mulhi (v2di_t x, v2di_t y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (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 000000000000..38f857ff0fe5 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/vsx_arith_builtin-2.c @@ -0,0 +1,74 @@ +/* { 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) +{ + /* force x & y into FPRs to prefer xvadduwm over vadduwm. */ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return vec_add (x, y); /* xvadduwm */ +} + +v4si_t uint_sub (v4si_t x, v4si_t y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return vec_sub (x, y); /* xvsubuwm */ +} + +v4si_t uint_mul (v4si_t x, v4si_t y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return vec_mul (x, y); /* xvmuluwm */ +} + +v4si_t uint_mulhi (v4si_t x, v4si_t y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return vec_mulh (x, y); /* xvmulhuw */ +} + +v8hi_t ushort_add (v8hi_t x, v8hi_t y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return vec_add (x, y); /* xvadduhm */ +} + +v8hi_t ushort_sub (v8hi_t x, v8hi_t y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return vec_sub (x, y); /* xvsubuhm */ +} + +v8hi_t ushort_mul (v8hi_t x, v8hi_t y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return vec_mul (x, y); /* xvmuluhm */ +} + +v8hi_t ushort_mulhi (v8hi_t x, v8hi_t y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return vec_mulh (x, y); /* xvmulhuh */ +} + +v2di_t ulonglong_mulhi (v2di_t x, v2di_t y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (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 000000000000..c0b28ad1b469 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/vsx_arith_builtin-3.c @@ -0,0 +1,56 @@ +/* { dg-do compile } */ +/* { dg-options "-mdejagnu-cpu=future -O2 -mno-vsx" } */ +/* { dg-require-effective-target powerpc_future_compile_ok } */ + +/* The -mno-vsx option turns off generation of VSX instructions (such as + xvadduwm) in favor of the traditional Altivec instructions (such as + vadduwm). */ + +#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 000000000000..56a3f2a97846 --- /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 000000000000..8596d562b0ff --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/vsx_arith_vect_1.c @@ -0,0 +1,90 @@ +/* { 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) +{ + /* force x & y into FPRs to prefer xvadduwm over vadduwm. */ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return x + y; /* xvadduwm */ +} + +vsi int_sub (vsi x, vsi y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return x - y; /* xvsubuwm */ +} + +vsi int_mul (vsi x, vsi y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return x * y; /* xvmuluwm */ +} + +vui uint_add (vui x, vui y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return x + y; /* xvadduwm */ +} + +vui uint_sub (vui x, vui y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return x - y; /* xvsubuwm */ +} + +vui uint_mul (vui x, vui y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return x * y; /* xvmuluwm */ +} + +vss short_add (vss x, vss y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return x + y; /* xvadduhm */ +} + +vss short_sub (vss x, vss y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return x - y; /* xvsubuhm */ +} + +vss short_mul (vss x, vss y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return x * y; /* xvmuluhm */ +} + +vus ushort_add (vus x, vus y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return x + y; /* xvadduhm */ +} + +vus ushort_sub (vus x, vus y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (y)); + return x - y; /* xvsubuhm */ +} + +vus ushort_mul (vus x, vus y) +{ + __asm__ (" # %x0,%x0" : "+f" (x), "+f" (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 000000000000..15f85803be59 --- /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 } } */
