On Mon, 2020-10-05 at 11:51 -0700, Carl Love wrote: > Will, Segher: > > Patch 1, adds the 128-bit sign extension instruction support and > corresponding builtin support.
> > I updated the change log per the comments from Will. > > Patch has been retested on Power 9 LE. > > Pet me know if it is ready to commit to mainline. > > Carl > > ----------------------------------------------------------- > > > gcc/ChangeLog > > 2020-10-05 Carl Love <c...@us.ibm.com> > * config/rs6000/altivec.h (vec_signextll, vec_signexti): Add define > for new builtins. > * config/rs6000/rs6000-builtin.def (VSIGNEXTI, VSIGNEXTLL): Add > overloaded builtin definitions. > (VSIGNEXTSB2W, VSIGNEXTSH2W, VSIGNEXTSB2D, VSIGNEXTSH2D,VSIGNEXTSW2D): > Add builtin expansions. > * config/rs6000-call.c (P9V_BUILTIN_VEC_VSIGNEXTI, > P9V_BUILTIN_VEC_VSIGNEXTLL): Add overloaded argument definitions. > * config/rs6000/vsx.md: Make define_insn vsx_sign_extend_si_v2di > visible. > * doc/extend.texi: Add documentation for the vec_signexti and > vec_signextll builtins. > > gcc/testsuite/ChangeLog > > 2020-10-05 Carl Love <c...@us.ibm.com> > * gcc.target/powerpc/p9-sign_extend-runnable.c: New test case. > --- > gcc/config/rs6000/altivec.h | 3 + > gcc/config/rs6000/rs6000-builtin.def | 9 ++ > gcc/config/rs6000/rs6000-call.c | 13 ++ > gcc/config/rs6000/vsx.md | 2 +- > gcc/doc/extend.texi | 15 ++ > .../powerpc/p9-sign_extend-runnable.c | 128 ++++++++++++++++++ > 6 files changed, 169 insertions(+), 1 deletion(-) > create mode 100644 gcc/testsuite/gcc.target/powerpc/p9-sign_extend-runnable.c > > diff --git a/gcc/config/rs6000/altivec.h b/gcc/config/rs6000/altivec.h > index f7720d136c9..cfa5eda4cd5 100644 > --- a/gcc/config/rs6000/altivec.h > +++ b/gcc/config/rs6000/altivec.h > @@ -494,6 +494,9 @@ > > #define vec_xlx __builtin_vec_vextulx > #define vec_xrx __builtin_vec_vexturx > +#define vec_signexti __builtin_vec_vsignexti > +#define vec_signextll __builtin_vec_vsignextll > + > #endif Can probably drop that blank line. > > /* Predicates. > diff --git a/gcc/config/rs6000/rs6000-builtin.def > b/gcc/config/rs6000/rs6000-builtin.def > index e91a48ddf5f..4c2e9460949 100644 > --- a/gcc/config/rs6000/rs6000-builtin.def > +++ b/gcc/config/rs6000/rs6000-builtin.def > @@ -2715,6 +2715,8 @@ BU_P9V_OVERLOAD_1 (VPRTYBD, "vprtybd") > BU_P9V_OVERLOAD_1 (VPRTYBQ, "vprtybq") > BU_P9V_OVERLOAD_1 (VPRTYBW, "vprtybw") > BU_P9V_OVERLOAD_1 (VPARITY_LSBB, "vparity_lsbb") > +BU_P9V_OVERLOAD_1 (VSIGNEXTI, "vsignexti") > +BU_P9V_OVERLOAD_1 (VSIGNEXTLL, "vsignextll") > > /* 2 argument functions added in ISA 3.0 (power9). */ > BU_P9_2 (CMPRB, "byte_in_range", CONST, cmprb) > @@ -2726,6 +2728,13 @@ BU_P9_OVERLOAD_2 (CMPRB, "byte_in_range") > BU_P9_OVERLOAD_2 (CMPRB2, "byte_in_either_range") > BU_P9_OVERLOAD_2 (CMPEQB, "byte_in_set") > > +/* Sign extend builtins that work on ISA 3.0, but not defined until ISA 3.1. > */ I have mixed feelings about straddling the ISA 3.0 and 3.1 ; but not sure how to properly improve. (I defer). The rest LGTM, Thanks -Will > +BU_P9V_AV_1 (VSIGNEXTSB2W, "vsignextsb2w", CONST, > vsx_sign_extend_qi_v4si) > +BU_P9V_AV_1 (VSIGNEXTSH2W, "vsignextsh2w", CONST, > vsx_sign_extend_hi_v4si) > +BU_P9V_AV_1 (VSIGNEXTSB2D, "vsignextsb2d", CONST, > vsx_sign_extend_qi_v2di) > +BU_P9V_AV_1 (VSIGNEXTSH2D, "vsignextsh2d", CONST, > vsx_sign_extend_hi_v2di) > +BU_P9V_AV_1 (VSIGNEXTSW2D, "vsignextsw2d", CONST, > vsx_sign_extend_si_v2di) > + > /* Builtins for scalar instructions added in ISA 3.1 (power10). */ > BU_P10_MISC_2 (CFUGED, "cfuged", CONST, cfuged) > BU_P10_MISC_2 (CNTLZDM, "cntlzdm", CONST, cntlzdm) > diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c > index a8b520834c7..9e514a01012 100644 > --- a/gcc/config/rs6000/rs6000-call.c > +++ b/gcc/config/rs6000/rs6000-call.c > @@ -5527,6 +5527,19 @@ const struct altivec_builtin_types > altivec_overloaded_builtins[] = { > RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, > RS6000_BTI_INTSI, RS6000_BTI_INTSI }, > > + /* Sign extend builtins that work work on ISA 3.0, not added until ISA 3.1 > */ > + { P9V_BUILTIN_VEC_VSIGNEXTI, P9V_BUILTIN_VSIGNEXTSB2W, > + RS6000_BTI_V4SI, RS6000_BTI_V16QI, 0, 0 }, > + { P9V_BUILTIN_VEC_VSIGNEXTI, P9V_BUILTIN_VSIGNEXTSH2W, > + RS6000_BTI_V4SI, RS6000_BTI_V8HI, 0, 0 }, > + > + { P9V_BUILTIN_VEC_VSIGNEXTLL, P9V_BUILTIN_VSIGNEXTSB2D, > + RS6000_BTI_V2DI, RS6000_BTI_V16QI, 0, 0 }, > + { P9V_BUILTIN_VEC_VSIGNEXTLL, P9V_BUILTIN_VSIGNEXTSH2D, > + RS6000_BTI_V2DI, RS6000_BTI_V8HI, 0, 0 }, > + { P9V_BUILTIN_VEC_VSIGNEXTLL, P9V_BUILTIN_VSIGNEXTSW2D, > + RS6000_BTI_V2DI, RS6000_BTI_V4SI, 0, 0 }, > + > /* Overloaded built-in functions for ISA3.1 (power10). */ > { P10_BUILTIN_VEC_CLRL, P10V_BUILTIN_VCLRLB, > RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_UINTSI, 0 }, > diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md > index 4ff52455fd3..31fcffe8f33 100644 > --- a/gcc/config/rs6000/vsx.md > +++ b/gcc/config/rs6000/vsx.md > @@ -4787,7 +4787,7 @@ > "vextsh2<wd> %0,%1" > [(set_attr "type" "vecexts")]) > > -(define_insn "*vsx_sign_extend_si_v2di" > +(define_insn "vsx_sign_extend_si_v2di" > [(set (match_operand:V2DI 0 "vsx_register_operand" "=v") > (unspec:V2DI [(match_operand:V4SI 1 "vsx_register_operand" "v")] > UNSPEC_VSX_SIGN_EXTEND))] > diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi > index 5571c4f2ff2..c1c2c9f9bf7 100644 > --- a/gcc/doc/extend.texi > +++ b/gcc/doc/extend.texi > @@ -20800,6 +20800,21 @@ void vec_xst (vector unsigned char, int, vector > unsigned char *); > void vec_xst (vector unsigned char, int, unsigned char *); > @end smallexample > > +uThe following sign extension builtins are provided. > + > +@smallexample > +vector signed int vec_signexti (vector signed char a) > +vector signed long long vec_signextll (vector signed char a) > +vector signed int vec_signexti (vector signed short a) > +vector signed long long vec_signextll (vector signed short a) > +vector signed long long vec_signextll (vector signed int a) > +@end smallexample > + > +Each element of the result is produced by sign-extending the element of the > +input vector that would fall in the least significant portion of the result > +element. For example, a sign-extension of a vector signed char to a vector > +signed long long will sign extend the rightmost byte of each doubleword. > + > @node PowerPC AltiVec Built-in Functions Available on ISA 3.1 > @subsubsection PowerPC AltiVec Built-in Functions Available on ISA 3.1 > > diff --git a/gcc/testsuite/gcc.target/powerpc/p9-sign_extend-runnable.c > b/gcc/testsuite/gcc.target/powerpc/p9-sign_extend-runnable.c > new file mode 100644 > index 00000000000..7bf979c6fd4 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/powerpc/p9-sign_extend-runnable.c > @@ -0,0 +1,128 @@ > +/* { dg-do run { target { powerpc*-*-linux* && { lp64 && p9vector_hw } } } } > */ > +/* { dg-require-effective-target powerpc_p9vector_ok } */ > +/* { dg-options "-O2 -mdejagnu-cpu=power9 -save-temps" } */ > + > +/* These builtins were not defined until ISA 3.1 but only require ISA 3.0 > + support. */ > + > +/* { dg-final { scan-assembler-times {\mvextsb2w\M} 1 } } */ > +/* { dg-final { scan-assembler-times {\mvextsb2d\M} 1 } } */ > +/* { dg-final { scan-assembler-times {\mvextsh2w\M} 1 } } */ > +/* { dg-final { scan-assembler-times {\mvextsh2d\M} 1 } } */ > +/* { dg-final { scan-assembler-times {\mvextsw2d\M} 1 } } */ > + > +#include <altivec.h> > + > +#define DEBUG 0 > + > +#if DEBUG > +#include <stdio.h> > +#include <stdlib.h> > +#endif > + > +void abort (void); > + > +int main () > +{ > + int i; > + > + vector signed char vec_arg_qi, vec_result_qi; > + vector signed short int vec_arg_hi, vec_result_hi, vec_expected_hi; > + vector signed int vec_arg_wi, vec_result_wi, vec_expected_wi; > + vector signed long long vec_result_di, vec_expected_di; > + > + /* test sign extend byte to word */ > + vec_arg_qi = (vector signed char) {1, 2, 3, 4, 5, 6, 7, 8, > + -1, -2, -3, -4, -5, -6, -7, -8}; > + vec_expected_wi = (vector signed int) {1, 5, -1, -5}; > + > + vec_result_wi = vec_signexti (vec_arg_qi); > + > + for (i = 0; i < 4; i++) > + if (vec_result_wi[i] != vec_expected_wi[i]) { > +#if DEBUG > + printf("ERROR: vec_signexti(char, int): "); > + printf("vec_result_wi[%d] != vec_expected_wi[%d]\n", > + i, i); > + printf("vec_result_wi[%d] = %d\n", i, vec_result_wi[i]); > + printf("vec_expected_wi[%d] = %d\n", i, vec_expected_wi[i]); > +#else > + abort(); > +#endif > + } > + > + /* test sign extend byte to double */ > + vec_arg_qi = (vector signed char){1, 2, 3, 4, 5, 6, 7, 8, > + -1, -2, -3, -4, -5, -6, -7, -8}; > + vec_expected_di = (vector signed long long int){1, -1}; > + > + vec_result_di = vec_signextll(vec_arg_qi); > + > + for (i = 0; i < 2; i++) > + if (vec_result_di[i] != vec_expected_di[i]) { > +#if DEBUG > + printf("ERROR: vec_signextll(byte, long long int): "); > + printf("vec_result_di[%d] != vec_expected_di[%d]\n", i, i); > + printf("vec_result_di[%d] = %lld\n", i, vec_result_di[i]); > + printf("vec_expected_di[%d] = %lld\n", i, vec_expected_di[i]); > +#else > + abort(); > +#endif > + } > + > + /* test sign extend short to word */ > + vec_arg_hi = (vector signed short int){1, 2, 3, 4, -1, -2, -3, -4}; > + vec_expected_wi = (vector signed int){1, 3, -1, -3}; > + > + vec_result_wi = vec_signexti(vec_arg_hi); > + > + for (i = 0; i < 4; i++) > + if (vec_result_wi[i] != vec_expected_wi[i]) { > +#if DEBUG > + printf("ERROR: vec_signexti(short, int): "); > + printf("vec_result_wi[%d] != vec_expected_wi[%d]\n", i, i); > + printf("vec_result_wi[%d] = %d\n", i, vec_result_wi[i]); > + printf("vec_expected_wi[%d] = %d\n", i, vec_expected_wi[i]); > +#else > + abort(); > +#endif > + } > + > + /* test sign extend short to double word */ > + vec_arg_hi = (vector signed short int ){1, 3, 5, 7, -1, -3, -5, -7}; > + vec_expected_di = (vector signed long long int){1, -1}; > + > + vec_result_di = vec_signextll(vec_arg_hi); > + > + for (i = 0; i < 2; i++) > + if (vec_result_di[i] != vec_expected_di[i]) { > +#if DEBUG > + printf("ERROR: vec_signextll(short, double): "); > + printf("vec_result_di[%d] != vec_expected_di[%d]\n", i, i); > + printf("vec_result_di[%d] = %lld\n", i, vec_result_di[i]); > + printf("vec_expected_di[%d] = %lld\n", i, vec_expected_di[i]); > +#else > + abort(); > +#endif > + } > + > + /* test sign extend word to double word */ > + vec_arg_wi = (vector signed int ){1, 3, -1, -3}; > + vec_expected_di = (vector signed long long int){1, -1}; > + > + vec_result_di = vec_signextll(vec_arg_wi); > + > + for (i = 0; i < 2; i++) > + if (vec_result_di[i] != vec_expected_di[i]) { > +#if DEBUG > + printf("ERROR: vec_signextll(word, double): "); > + printf("vec_result_di[%d] != vec_expected_di[%d]\n", i, i); > + printf("vec_result_di[%d] = %lld\n", i, vec_result_di[i]); > + printf("vec_expected_di[%d] = %lld\n", i, vec_expected_di[i]); > +#else > + abort(); > +#endif > + } > + > + return 0; > +}