Hi,
On 20/05/26 11:32 AM, Kishan Parmar wrote:
> +;; Vector uncompress instructions for future.
> +
> +;; VSX splat values for vector uncompress instructions for little endian.
> +(define_int_attr vucmpr_splat [(UNSPEC_VUCMPRHN "3")
> + (UNSPEC_VUCMPRLN "2")
> + (UNSPEC_VUCMPRHB "7")
> + (UNSPEC_VUCMPRLB "6")
> + (UNSPEC_VUCMPRHH "15")
> + (UNSPEC_VUCMPRLH "14")])
> +
> +;; Altivec PCV(Permute Control Vector) mask values for vperm used in
> +;; little endian.
> +(define_int_attr vucmpr_pcv [(UNSPEC_VUCMPRHN "0x0f0e0d0c")
> + (UNSPEC_VUCMPRLN "0x0b0a0908")
> + (UNSPEC_VUCMPRHB "0x0f0e0000")
> + (UNSPEC_VUCMPRLB "0x0d0c0000")])
> +
> +;; Values for UIM which are used in vinsw instruction which will be used in
> +;; little-endian, to know in vector.
> +(define_int_attr vucmpr_uim [(UNSPEC_VUCMPRHN "4") (UNSPEC_VUCMPRLN "0")
> + (UNSPEC_VUCMPRHB "2") (UNSPEC_VUCMPRLB "0")])
> +
> +/* On little-endian systems, the selector/mask layout does not match
> + the architectural element ordering used by the vector uncompress
> + instructions. Byte-wise reverse the selector layout and swap the high/low
> + nibbles so that the resulting vector matches big-endian semantics. */
> +
> +;; Vector Uncompress Nibbles
> +
> +(define_int_iterator VUCMPR_N [UNSPEC_VUCMPRHN UNSPEC_VUCMPRLN])
> +
> +(define_insn "altivec_vucmpr<vu_hl>n_direct"
> + [(set (match_operand:V8HI 0 "altivec_register_operand" "=v")
> + (unspec:V8HI [(match_operand:V16QI 1 "altivec_register_operand" "v")
> + (match_operand:V4SI 2 "altivec_register_operand" "v")]
> + VUCMPR_N))]
> + "TARGET_FUTURE"
> + "vucmpr<vu_hl>n %0, %1, %2")
> +
> +(define_expand "altivec_vucmpr<vu_hl>n"
> + [(set (match_operand:V8HI 0 "altivec_register_operand")
> + (unspec:V8HI [(match_operand:V16QI 1 "altivec_register_operand")
> + (match_operand:V4SI 2 "altivec_register_operand")]
> + VUCMPR_N))]
> + "TARGET_FUTURE"
> +{
> + if (BYTES_BIG_ENDIAN)
> + {
> + emit_insn (gen_altivec_vucmpr<vu_hl>n_direct(operands[0], operands[1],
> + operands[2]));
> + DONE;
> + }
> + if (TARGET_VSX)
> + {
> + rtx splat = gen_reg_rtx (V4SImode);
> + rtx shift = gen_reg_rtx (V16QImode);
> + rtx bytes = gen_reg_rtx (V16QImode);
> + rtx rotated = gen_reg_rtx (V16QImode);
> + rtx selector = gen_reg_rtx (V4SImode);
> +
> + emit_insn (gen_altivec_vspltw_direct (splat, operands[2],
> + GEN_INT (<vucmpr_splat>)));
> + emit_insn (gen_p9_xxbrw_v4si (splat, splat));
> + emit_move_insn (bytes, gen_lowpart (V16QImode, splat));
> + emit_insn (gen_altivec_vspltisb (shift, GEN_INT (4)));
> + emit_insn (gen_altivec_vrlb (rotated, bytes, shift));
> + emit_move_insn (selector, gen_lowpart (V4SImode, rotated));
> + emit_insn (gen_altivec_vucmpr<vu_lh>n_direct (operands[0], operands[1],
> + selector));
> + }
> + else
> + {
> + rtx pcv = gen_reg_rtx (V4SImode);
> + rtx perm = gen_reg_rtx (V16QImode);
> + rtx mask = gen_reg_rtx (SImode);
> +
> + emit_move_insn (mask, GEN_INT (<vucmpr_pcv>));
> + emit_insn (gen_vreplace_elt_v4si_inst (pcv, pcv, mask,
> + GEN_INT (<vucmpr_uim>)));
> + emit_move_insn (perm, gen_lowpart (V16QImode, pcv));
> + emit_insn (gen_altivec_vperm_v4si_direct (operands[2], operands[2],
> + operands[2], perm));
The bytes in operands[2] have been reversed, but the nibbles too should be
reversed.
A 'vrlb' is needed here.
> + emit_insn (gen_altivec_vucmpr<vu_lh>n_direct (operands[0], operands[1],
> + operands[2]));
> + }
> +
> + DONE;
> +})
> +
> +
> +;; Vector Uncompress Bytes
> +
> +(define_int_iterator VUCMPR_B [UNSPEC_VUCMPRHB UNSPEC_VUCMPRLB])
> +
> +(define_insn "altivec_vucmpr<vu_hl>b_direct"
> + [(set (match_operand:V4SI 0 "altivec_register_operand" "=v")
> + (unspec:V4SI [(match_operand:V8HI 1 "altivec_register_operand" "v")
> + (match_operand:V8HI 2 "altivec_register_operand" "v")]
> + VUCMPR_B))]
> + "TARGET_FUTURE"
> + "vucmpr<vu_hl>b %0, %1, %2"
> + [(set_attr "type" "vecperm")])
> +
> +(define_expand "altivec_vucmpr<vu_hl>b"
> + [(set (match_operand:V4SI 0 "altivec_register_operand")
> + (unspec:V4SI [(match_operand:V8HI 1 "altivec_register_operand")
> + (match_operand:V8HI 2 "altivec_register_operand")]
> + VUCMPR_B))]
> + "TARGET_FUTURE"
> +{
> + if (BYTES_BIG_ENDIAN)
> + {
> + emit_insn (gen_altivec_vucmpr<vu_hl>b_direct (operands[0], operands[1],
> + operands[2]));
> + DONE;
> + }
> + if (TARGET_VSX)
> + {
> + rtx splat = gen_reg_rtx (V8HImode);
> + rtx shift = gen_reg_rtx (V16QImode);
> + rtx bytes = gen_reg_rtx (V16QImode);
> + rtx rotated = gen_reg_rtx (V16QImode);
> + rtx selector = gen_reg_rtx (V8HImode);
> +
> + emit_insn (gen_altivec_vsplth_direct (splat, operands[2],
> + GEN_INT (<vucmpr_splat>)));
> + emit_insn (gen_p9_xxbrh_v8hi (splat, splat));
> + emit_move_insn (bytes, gen_lowpart (V16QImode, splat));
> + emit_insn (gen_altivec_vspltisb (shift, GEN_INT (4)));
> + emit_insn (gen_altivec_vrlb (rotated, bytes, shift));
> + emit_move_insn (selector, gen_lowpart (V8HImode, rotated));
> + emit_insn (gen_altivec_vucmpr<vu_lh>b_direct (operands[0], operands[1],
> + selector));
> + }
> + else
> + {
> + rtx pcv = gen_reg_rtx (V4SImode);
> + rtx perm = gen_reg_rtx (V16QImode);
> + rtx mask = gen_reg_rtx (SImode);
> + rtx selector = gen_reg_rtx (V4SImode);
> +
> + emit_move_insn (mask, GEN_INT (<vucmpr_pcv>));
> + emit_insn (gen_vreplace_elt_v4si_inst (pcv, pcv, mask,
> + GEN_INT (<vucmpr_uim>)));
> + emit_move_insn (perm, gen_lowpart (V16QImode, pcv));
> + emit_move_insn (selector, gen_lowpart (V4SImode, operands[2]));
> + emit_insn (gen_altivec_vperm_v4si_direct (selector, selector, selector,
> + perm));
Ditto.
-Surya
> + emit_insn (gen_altivec_vucmpr<vu_lh>b_direct (operands[0], operands[1],
> + gen_lowpart (V8HImode,
> + selector)));
> + }
> +
> + DONE;
> +})
> +
> +;; Vector Uncompress Halfwords
> +
> +(define_int_iterator VUCMPR_H [UNSPEC_VUCMPRHH UNSPEC_VUCMPRLH])
> +
> +(define_insn "altivec_vucmpr<vu_hl>h_direct"
> + [(set (match_operand:V2DI 0 "altivec_register_operand" "=v")
> + (unspec:V2DI [(match_operand:V4SI 1 "altivec_register_operand" "v")
> + (match_operand:V16QI 2 "altivec_register_operand" "v")]
> + VUCMPR_H))]
> + "TARGET_FUTURE"
> + "vucmpr<vu_hl>h %0, %1, %2"
> + [(set_attr "type" "vecperm")])
> +
> +(define_expand "altivec_vucmpr<vu_hl>h"
> + [(set (match_operand:V2DI 0 "altivec_register_operand")
> + (unspec:V2DI [(match_operand:V4SI 1 "altivec_register_operand")
> + (match_operand:V16QI 2 "altivec_register_operand")]
> + VUCMPR_H))]
> + "TARGET_FUTURE && (BYTES_BIG_ENDIAN || TARGET_VSX)"
> +{
> + if (BYTES_BIG_ENDIAN)
> + {
> + emit_insn (gen_altivec_vucmpr<vu_hl>h_direct (operands[0], operands[1],
> + operands[2]));
> + }
> + else
> + {
> + rtx splat = gen_reg_rtx (V16QImode);
> + rtx shift = gen_reg_rtx (V16QImode);
> + rtx rotated = gen_reg_rtx (V16QImode);
> +
> + emit_insn (gen_altivec_vspltb_direct (splat, operands[2],
> + GEN_INT (<vucmpr_splat>)));
> + emit_insn (gen_altivec_vspltisb (shift, GEN_INT (4)));
> + emit_insn (gen_altivec_vrlb (rotated, splat, shift));
> + emit_insn (gen_altivec_vucmpr<vu_lh>h_direct (operands[0], operands[1],
> + rotated));
> + }
> + DONE;
> +})
> diff --git a/gcc/config/rs6000/rs6000-builtins.def
> b/gcc/config/rs6000/rs6000-builtins.def
> index 0d1529b71d4..d4b3dab1b31 100644
> --- a/gcc/config/rs6000/rs6000-builtins.def
> +++ b/gcc/config/rs6000/rs6000-builtins.def
> @@ -3970,3 +3970,39 @@
>
> const vuc __builtin_galois_field_mult_xts (vuc, vuc);
> XXGFMUL128XTS xxgfmul128xts {}
> +
> + const vus __builtin_altivec_uncompresshn (vuc, vui);
> + VUCMPRHN altivec_vucmprhn {}
> +
> + const vui __builtin_altivec_uncompresshb (vus, vus);
> + VUCMPRHB altivec_vucmprhb {}
> +
> + const vull __builtin_altivec_uncompresshh (vui, vuc);
> + VUCMPRHH altivec_vucmprhh {}
> +
> + const vus __builtin_altivec_uncompressln (vuc, vui);
> + VUCMPRLN altivec_vucmprln {}
> +
> + const vui __builtin_altivec_uncompresslb (vus, vus);
> + VUCMPRLB altivec_vucmprlb {}
> +
> + const vull __builtin_altivec_uncompresslh (vui, vuc);
> + VUCMPRLH altivec_vucmprlh {}
> +
> + const vsc __builtin_altivec_unpack_hsn_to_byte (vull);
> + VUPKHSNTOB altivec_vupkhsntob {}
> +
> + const vsc __builtin_altivec_unpack_lsn_to_byte (vull);
> + VUPKLSNTOB altivec_vupklsntob {}
> +
> + const vuc __builtin_altivec_unpack_int4_to_bf16 (vus, const int<2>);
> + VUPKINT4TOBF16 altivec_vupkint4tobf16 {}
> +
> + const vuc __builtin_altivec_unpack_int8_to_bf16 (vus, const int<1>);
> + VUPKINT8TOBF16 altivec_vupkint8tobf16 {}
> +
> + const vf __builtin_altivec_unpack_int4_to_fp32 (vui, const int<3>);
> + VUPKINT4TOFP32 altivec_vupkint4tofp32 {}
> +
> + const vf __builtin_altivec_unpack_int8_to_fp32 (vui, const int<2>);
> + VUPKINT8TOFP32 altivec_vupkint8tofp32 {}
> diff --git a/gcc/config/rs6000/rs6000-overload.def
> b/gcc/config/rs6000/rs6000-overload.def
> index ef7b59ed112..11cd29f45c0 100644
> --- a/gcc/config/rs6000/rs6000-overload.def
> +++ b/gcc/config/rs6000/rs6000-overload.def
> @@ -5015,6 +5015,53 @@
> vd __builtin_vsx_xxsldwi (vd, vd, const int);
> XXSLDWI_2DF XXSLDWI_VD2
>
> +[VEC_UCMPRHN, vec_uncompresshn, __builtin_vec_uncompresshn]
> + vus __builtin_vec_uncompresshn (vuc, vui);
> + VUCMPRHN
> +
> +[VEC_UCMPRHB, vec_uncompresshb, __builtin_vec_uncomresshb]
> + vui __builtin_vec_uncomresshb (vus, vus);
> + VUCMPRHB
> +
> +[VEC_UCMPRHH, vec_uncompresshh, __builtin_vec_uncomresshh]
> + vull __builtin_vec_uncomresshh (vui, vuc);
> + VUCMPRHH
> +
> +[VEC_UCMPRLN, vec_uncompressln, __builtin_vec_uncomressln]
> + vus __builtin_vec_uncomressln (vuc, vui);
> + VUCMPRLN
> +
> +[VEC_UCMPRLB, vec_uncompresslb, __builtin_vec_uncomresslb]
> + vui __builtin_vec_uncomresslb (vus, vus);
> + VUCMPRLB
> +
> +[VEC_UCMPRLH, vec_uncompresslh, __builtin_vec_uncomresslh]
> + vull __builtin_vec_uncomresslh (vui, vuc);
> + VUCMPRLH
> +
> +[VEC_UNPACK_HSN_TO_BYTE, vec_unpack_hsn_to_byte,
> __builtin_vec_unpack_hsn_to_byte]
> + vsc __builtin_vec_unpack_hsn_to_byte (vull);
> + VUPKHSNTOB
> +
> +[VEC_UNPACK_LSN_TO_BYTE, vec_unpack_lsn_to_byte,
> __builtin_vec_unpack_lsn_to_byte]
> + vsc __builtin_vec_unpack_lsn_to_byte (vull);
> + VUPKLSNTOB
> +
> +[VEC_UNPACK_INT4_TO_BF16, vec_unpack_int4_to_bf16,
> __builtin_vec_unpack_int4_to_bf16]
> + vuc __builtin_vec_unpack_int4_to_bf16 (vus, const int<2>);
> + VUPKINT4TOBF16
> +
> +[VEC_UNPACK_INT8_TO_BF16, vec_unpack_int8_to_bf16,
> __builtin_vec_unpack_int8_to_bf16]
> + vuc __builtin_vec_unpack_int8_to_bf16 (vus, const int<1>);
> + VUPKINT8TOBF16
> +
> +[VEC_UNPACK_INT4_TO_FP32, vec_unpack_int4_to_fp32,
> __builtin_vec_unpack_int4_to_fp32]
> + vf __builtin_vec_unpack_int4_to_fp32 (vui, const int<3>);
> + VUPKINT4TOFP32
> +
> +[VEC_UNPACK_INT8_TO_FP32, vec_unpack_int8_to_fp32,
> __builtin_vec_unpack_int8_to_fp32]
> + vf __builtin_vec_unpack_int8_to_fp32 (vui, const int<2>);
> + VUPKINT8TOFP32
>
> ; **************************************************************************
> ; **************************************************************************
> diff --git a/gcc/testsuite/gcc.target/powerpc/future-vucmpr-altivec.c
> b/gcc/testsuite/gcc.target/powerpc/future-vucmpr-altivec.c
> new file mode 100644
> index 00000000000..0a1d489f9af
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/future-vucmpr-altivec.c
> @@ -0,0 +1,46 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -mdejagnu-cpu=future -mno-vsx" } */
> +
> +#include <altivec.h>
> +
> +vector unsigned short
> +test_uncompresshn (vector unsigned char a,
> + vector unsigned int b)
> +{
> + return vec_uncompresshn (a, b);
> +}
> +
> +vector unsigned int
> +test_uncompresshb (vector unsigned short a,
> + vector unsigned short b)
> +{
> + return vec_uncompresshb (a, b);
> +}
> +
> +vector unsigned short
> +test_uncompressln (vector unsigned char a,
> + vector unsigned int b)
> +{
> + return vec_uncompressln (a, b);
> +}
> +
> +vector unsigned int
> +test_uncompresslb (vector unsigned short a,
> + vector unsigned short b)
> +{
> + return vec_uncompresslb (a, b);
> +}
> +
> +/* { dg-final { scan-assembler-not "vxor" { target { be } } } } */
> +/* { dg-final { scan-assembler-not "vinsw" { target { be } } } } */
> +/* { dg-final { scan-assembler-not "vperm" { target { be } } } } */
> +
> +
> +/* { dg-final { scan-assembler-times "vxor" 4 { target { le } } } } */
> +/* { dg-final { scan-assembler-times "vinsw" 4 { target { le } } } } */
> +/* { dg-final { scan-assembler-times "vperm" 4 { target { le } } } } */
> +
> +/* Final uncompress instructions. */
> +
> +/* { dg-final { scan-assembler-times {vucmpr[lh][nb]} 4 } } */
> +
> diff --git a/gcc/testsuite/gcc.target/powerpc/future-vucmpr-vsx.c
> b/gcc/testsuite/gcc.target/powerpc/future-vucmpr-vsx.c
> new file mode 100644
> index 00000000000..9d783721091
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/future-vucmpr-vsx.c
> @@ -0,0 +1,60 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -mdejagnu-cpu=future -mvsx" } */
> +
> +#include <altivec.h>
> +
> +vector unsigned short test_uncompresshn(vector unsigned char a,
> + vector unsigned int b)
> +{
> + return vec_uncompresshn(a, b);
> +}
> +
> +vector unsigned int test_uncompresshb(vector unsigned short a,
> + vector unsigned short b)
> +{
> + return vec_uncompresshb(a, b);
> +}
> +
> +vector unsigned long long test_uncompresshh(vector unsigned int a,
> + vector unsigned char b)
> +{
> + return vec_uncompresshh(a, b);
> +}
> +
> +vector unsigned short test_uncompressln(vector unsigned char a,
> + vector unsigned int b)
> +{
> + return vec_uncompressln(a, b);
> +}
> +
> +vector unsigned int test_uncompresslb(vector unsigned short a,
> + vector unsigned short b)
> +{
> + return vec_uncompresslb(a, b);
> +}
> +
> +vector unsigned long long test_uncompresslh(vector unsigned int a,
> + vector unsigned char b)
> +{
> + return vec_uncompresslh(a, b);
> +}
> +
> +/* BE: direct instructions, no splats or reverse. */
> +
> +/* { dg-final { scan-assembler-not {vsplt[whb]} { target { be } } } } */
> +/* { dg-final { scan-assembler-not {xxspltib} { target { be } } } } */
> +/* { dg-final { scan-assembler-not {xxbr[wh]\M} { target { be } } } } */
> +/* { dg-final { scan-assembler-not {vrlb} { target { be } } } } */
> +
> +/* LE: splats and reverse-byte + rotate must appear. */
> +
> +/* { dg-final { scan-assembler-times {vsplt[whb]} 6 { target { le } } } } */
> +
> +/* { dg-final { scan-assembler-times "xxspltib" 6 { target { le } } } } */
> +
> +/* { dg-final { scan-assembler-times {xxbr[wh]} 4 { target { le } } } } */
> +
> +/* { dg-final { scan-assembler-times "vrlb" 6 { target { le } } } } */
> +
> +/* { dg-final { scan-assembler-times {vucmpr[lh][nbh]} 6 } } */
> +
> diff --git a/gcc/testsuite/gcc.target/powerpc/future-vupk.c
> b/gcc/testsuite/gcc.target/powerpc/future-vupk.c
> new file mode 100644
> index 00000000000..6031aaaa077
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/future-vupk.c
> @@ -0,0 +1,50 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -mdejagnu-cpu=future" } */
> +
> +#include <altivec.h>
> +
> +vector signed char
> +test_unpack_hsn_to_byte(vector unsigned long long a)
> +{
> + return vec_unpack_hsn_to_byte(a);
> +}
> +
> +vector signed char
> +test_unpack_lsn_to_byte(vector unsigned long long a)
> +{
> + return vec_unpack_lsn_to_byte(a);
> +}
> +
> +vector unsigned char
> +test_unpack_int4_to_bf16(vector unsigned short a)
> +{
> + return vec_unpack_int4_to_bf16(a, 0);
> +}
> +
> +vector unsigned char
> +test_unpack_int8_to_bf16(vector unsigned short a)
> +{
> + return vec_unpack_int8_to_bf16(a, 0);
> +}
> +
> +vector float
> +test_unpack_int4_to_fp32(vector unsigned int a)
> +{
> + return vec_unpack_int4_to_fp32(a, 0);
> +}
> +
> +vector float
> +test_unpack_int8_to_fp32(vector unsigned int a)
> +{
> + return vec_unpack_int8_to_fp32(a, 0);
> +}
> +
> +
> +/* { dg-final { scan-assembler-times "xxbrq" 2 { target { vsx_hw } } } } */
> +
> +/* { dg-final { scan-assembler-times "vupkhsntob" 1 } } */
> +/* { dg-final { scan-assembler-times "vupklsntob" 1 } } */
> +/* { dg-final { scan-assembler-times "vupkint4tobf16" 1 } } */
> +/* { dg-final { scan-assembler-times "vupkint8tobf16" 1 } } */
> +/* { dg-final { scan-assembler-times "vupkint4tofp32" 1 } } */
> +/* { dg-final { scan-assembler-times "vupkint8tofp32" 1 } } */