Hello Surya,

Most of the requested changes in [Patch v3] have been incorporated.

Regarding the '*' prefix suggestion for the *_direct patterns,
I did not make that change since these patterns are emitted from the 
corresponding
define_expand patterns via gen_altivec_vupk<vu_hl>sntob_direct() and similar 
gen_altivec_vucmpr* calls.
Marking them with '*' would make them recognition-only and the generated calls 
would no longer work.

Thanks,
Kishan


On 23/06/26 4:14 pm, Kishan Parmar wrote:
> Hello,
>
> Below patch is bootstrapped and regtested on powerpc64*-linux-gnu with
> no regressions.
>
> This patch depends on:
> https://www.mail-archive.com/[email protected]/msg407092.html
> for future-vsx stanza support and should be committed after the patch
> is commited.
>
> Changes from v3:
>
>       - Tested on both little-endian and big-endian targets.
>       - Added documentation and explanatory comments.
>       - Reorganized builtins into future-vsx and future-altivec
>       stanzas.
>       - Fixed mode mismatches in builtin definitions and md patterns
>       of altivec_vupkint4tobf16 and altivec_vupkint8tobf16.
>       - Updated and corrected testcases as requested during review.
>
> Changes from v2:
>       - Add endian compensation sequence for LE so that the logical
>       vector element ordering matches BE semantics.
>
> Changes from v1:
>       - Add missing author line:
>       2025-03-11  Kishan Parmar  <[email protected]>
>
> Thank you,
> Kishan
>
> Add support for vector uncompress and unpack instructions
> proposed in RFC02691.  These instructions may or may not be added to a future
> Power processor, and the names of the builtins may change in the future.
>
> The instructions are exposed through new builtins and intrinsics
> interfaces and are enabled when compiling with -mcpu=future.
>
> This patch adds RTL patterns for vector uncompress (nibble, byte, and
> halfword) and unpack operations in altivec.md, along with the
> corresponding builtin definitions in rs6000-builtins.def and overload
> entries in rs6000-overload.def.
>
> The following new builtins are provided:
>
> vector unsigned short vec_uncompresshn (vector unsigned char,
>                                       vector unsigned int)
> vector unsigned int vec_uncompresshb (vector unsigned short,
>                                     vector unsigned short)
> vector unsigned long long vec_uncompresshh (vector unsigned int,
>                                           vector unsigned char)
> vector unsigned short vec_uncompressln (vector unsigned char,
>                                       vector unsigned int)
> vector unsigned int vec_uncompresslb (vector unsigned short,
>                                     vector unsigned short)
> vector unsigned long long vec_uncompresslh (vector unsigned int,
>                                           vector unsigned char)
> vector signed char vec_unpack_hsn_to_byte (vector unsigned long long)
> vector signed char vec_unpack_lsn_to_byte (vector unsigned long long)
> vector unsigned char vec_unpack_int4_to_bf16 (vector unsigned short,
>                                             const int<2>)
> vector unsigned char vec_unpack_int8_to_bf16 (vector unsigned short,
>                                             const int<1>)
> vector float vec_unpack_int4_to_fp32 (vector unsigned int, const int<3>)
> vector float vec_unpack_int8_to_fp32 (vector unsigned int, const int<2>)
>
> 2026-06-23  Kishan Parmar  <[email protected]>
>
> gcc/ChangeLog:
>       * config/rs6000/altivec.md (UNSPEC_VUCMPRHN): New unspec entry.
>       (UNSPEC_VUCMPRLN): Likewise.
>       (UNSPEC_VUCMPRHB): Likewise.
>       (UNSPEC_VUCMPRLB): Likewise.
>       (UNSPEC_VUCMPRHH): Likewise.
>       (UNSPEC_VUCMPRLH): Likewise.
>       (UNSPEC_VUPKHSNTOB): Likewise.
>       (UNSPEC_VUPKLSNTOB): Likewise.
>       (UNSPEC_VUPKINT4TOBF16): Likewise.
>       (UNSPEC_VUPKINT8TOBF16): Likewise.
>       (UNSPEC_VUPKINT4TOFP32): Likewise.
>       (UNSPEC_VUPKINT8TOFP32): Likewise.
>       (vu_hl): New attribute.
>       (vu_lh): Likewise.
>       (VUPKNTOB): New int iterator.
>       (altivec_vupkhsntob): New define_insn.
>       (altivec_vupklsntob): Likewise.
>       (altivec_vupkint4tobf16): Likewise.
>       (altivec_vupkint8tobf16): Likewise.
>       (altivec_vupkint4tofp32): Likewise.
>       (altivec_vupkint8tofp32): Likewise.
>       (vucmpr_splat): New attribute.
>       (vucmpr_pcv): Likewise.
>       (vucmpr_uim): Likewise.
>       (VUCMPR_N): New int iterator.
>       (VUCMPR_B): Likewise.
>       (VUCMPR_H): Likewise.
>       (altivec_vucmpr<vu_hl>n): New define_expand.
>       (altivec_vucmpr<vu_hl>n_direct): New define_insn for vucmpr<vu_hl>n.
>       (altivec_vucmpr<vu_hl>b): New define_expand.
>       (altivec_vucmpr<vu_hl>b_direct): New define_insn for vucmpr<vu_hl>b.
>       (altivec_vucmpr<vu_hl>h): New define_expand.
>       (altivec_vucmpr<vu_hl>h_direct): New define_insn for vucmpr<vu_hl>h.
>       * config/rs6000/rs6000-builtins.def: Add vector uncompress and unpack
>       builtins under [future].
>       * config/rs6000/rs6000-overload.def: Add vec_uncompress* and vec_unpack*
>       interfaces.
>
> gcc/testsuite/ChangeLog:
>       * gcc/testsuite/gcc.target/powerpc/future-vucmpr-altivec.c: New test.
>       * gcc/testsuite/gcc.target/powerpc/future-vucmpr-vsx.c: Likewise.
>       * gcc/testsuite/gcc.target/powerpc/future-vupk.c: Likewise.
> ---
>  gcc/config/rs6000/altivec.md                  | 362 ++++++++++++++++++
>  gcc/config/rs6000/rs6000-builtins.def         |  37 ++
>  gcc/config/rs6000/rs6000-overload.def         |  47 +++
>  .../powerpc/future-vucmpr-altivec.c           |  50 +++
>  .../gcc.target/powerpc/future-vucmpr-vsx.c    |  61 +++
>  .../gcc.target/powerpc/future-vupk.c          |  51 +++
>  6 files changed, 608 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.target/powerpc/future-vucmpr-altivec.c
>  create mode 100644 gcc/testsuite/gcc.target/powerpc/future-vucmpr-vsx.c
>  create mode 100644 gcc/testsuite/gcc.target/powerpc/future-vupk.c
>
> diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
> index 129f56245cd..32a6d3f3eb4 100644
> --- a/gcc/config/rs6000/altivec.md
> +++ b/gcc/config/rs6000/altivec.md
> @@ -171,6 +171,18 @@
>     UNSPEC_SLDB
>     UNSPEC_SRDB
>     UNSPEC_VECTOR_SHIFT
> +   UNSPEC_VUCMPRHN
> +   UNSPEC_VUCMPRLN
> +   UNSPEC_VUCMPRHB
> +   UNSPEC_VUCMPRLB
> +   UNSPEC_VUCMPRHH
> +   UNSPEC_VUCMPRLH
> +   UNSPEC_VUPKHSNTOB
> +   UNSPEC_VUPKLSNTOB
> +   UNSPEC_VUPKINT4TOBF16
> +   UNSPEC_VUPKINT8TOBF16
> +   UNSPEC_VUPKINT4TOFP32
> +   UNSPEC_VUPKINT8TOFP32
>  ])
>  
>  (define_c_enum "unspecv"
> @@ -4826,3 +4838,353 @@
>                                 (match_dup 3)]
>                                UNSPEC_BCD_ADD_SUB)
>                   (match_dup 4)))])])
> +
> +(define_int_attr vu_hl [(UNSPEC_VUPKHSNTOB "h") (UNSPEC_VUPKLSNTOB "l")
> +                     (UNSPEC_VUCMPRHN "h") (UNSPEC_VUCMPRLN "l")
> +                     (UNSPEC_VUCMPRHB "h") (UNSPEC_VUCMPRLB "l")
> +                     (UNSPEC_VUCMPRHH "h") (UNSPEC_VUCMPRLH "l")])
> +
> +(define_int_attr vu_lh [(UNSPEC_VUPKHSNTOB "l") (UNSPEC_VUPKLSNTOB "h")
> +                     (UNSPEC_VUCMPRHN "l") (UNSPEC_VUCMPRLN "h")
> +                     (UNSPEC_VUCMPRHB "l") (UNSPEC_VUCMPRLB "h")
> +                     (UNSPEC_VUCMPRHH "l") (UNSPEC_VUCMPRLH "h")])
> +
> +;; Vector unpack instructions for future.
> +
> +(define_int_iterator VUPKNTOB [UNSPEC_VUPKHSNTOB UNSPEC_VUPKLSNTOB])
> +
> +(define_insn "altivec_vupk<vu_hl>sntob_direct"
> +  [(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
> +     (unspec:V16QI [(match_operand:V2DI 1 "altivec_register_operand" "v")]
> +                   VUPKNTOB))]
> +  "TARGET_FUTURE && TARGET_VSX"
> +  "vupk<vu_hl>sntob %0, %1"
> +  [(set_attr "type" "vecperm")])
> +
> +;; Unpack signed nibbles to bytes.
> +;; For big-endian, generates:
> +;;   vupk<vu_hl>sntob operands[0], operands[1]
> +;; For little-endian, generates (requires VSX for xxbrq):
> +;;   vupk<vu_lh>sntob operands[0], operands[1]
> +;;   xxbrq operands[0], operands[0]
> +;; TARGET_VSX is required because the builtin operates on V2DI (vector
> +;; unsigned long long), which requires -mvsx. On little-endian systems,
> +;; the endian compensation also uses the VSX xxbrq instruction.
> +
> +(define_expand "altivec_vupk<vu_hl>sntob"
> +  [(set (match_operand:V16QI 0 "altivec_register_operand")
> +     (unspec:V16QI [(match_operand:V2DI 1 "altivec_register_operand")]
> +                   VUPKNTOB))]
> +  "TARGET_FUTURE && TARGET_VSX"
> +{
> +  if (BYTES_BIG_ENDIAN)
> +    emit_insn (gen_altivec_vupk<vu_hl>sntob_direct (operands[0],
> +                                                 operands[1]));
> +  else
> +    {
> +      emit_insn (gen_altivec_vupk<vu_lh>sntob_direct (operands[0],
> +                                                   operands[1]));
> +      emit_insn (gen_p9_xxbrq_v16qi (operands[0], operands[0]));
> +    }
> +  DONE;
> +})
> +
> +(define_insn "altivec_vupkint4tobf16"
> +  [(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
> +     (unspec:V16QI [(match_operand:V8HI 1 "altivec_register_operand" "v")
> +                    (match_operand:QI 2 "const_0_to_3_operand" "i")]
> +                   UNSPEC_VUPKINT4TOBF16))]
> +  "TARGET_FUTURE"
> +  "vupkint4tobf16 %0, %1, %2"
> +  [(set_attr "type" "vecperm")])
> +
> +(define_insn "altivec_vupkint8tobf16"
> +  [(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
> +     (unspec:V16QI [(match_operand:V8HI 1 "altivec_register_operand" "v")
> +                    (match_operand:QI 2 "const_0_to_1_operand" "i")]
> +                   UNSPEC_VUPKINT8TOBF16))]
> +  "TARGET_FUTURE"
> +  "vupkint8tobf16 %0, %1, %2"
> +  [(set_attr "type" "vecperm")])
> +
> +(define_insn "altivec_vupkint4tofp32"
> +  [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
> +        (unspec:V4SF [(match_operand:V4SI 1 "altivec_register_operand" "v")
> +                   (match_operand:QI 2 "const_0_to_7_operand" "i")]
> +                  UNSPEC_VUPKINT4TOFP32))]
> +  "TARGET_FUTURE"
> +  "vupkint4tofp32 %0, %1, %2"
> +  [(set_attr "type" "vecperm")])
> +
> +(define_insn "altivec_vupkint8tofp32"
> +  [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
> +     (unspec:V4SF [(match_operand:V4SI 1 "altivec_register_operand" "v")
> +                   (match_operand:QI 2 "const_0_to_3_operand" "i")]
> +                  UNSPEC_VUPKINT8TOFP32))]
> +  "TARGET_FUTURE"
> +  "vupkint8tofp32 %0, %1, %2"
> +  [(set_attr "type" "vecperm")])
> +
> +;; 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")
> +
> +;; Vector uncompress nibbles.
> +;; For big-endian, generates:
> +;;   vucmpr<vu_hl>n operands[0], operands[1], operands[2]
> +;; For little-endian with VSX, generates:
> +;;   vspltw splat, operands[2], <vucmpr_splat>
> +;;   xxbrw splat, splat
> +;;   vspltisb shift, 4
> +;;   vrlb rotated, bytes, shift
> +;;   vucmpr<vu_lh>n operands[0], operands[1], selector
> +;; For little-endian without VSX (Altivec-only), generates:
> +;;   pli mask, <vucmpr_pcv>
> +;;   vinsw pcv, mask, <vucmpr_uim>
> +;;   vperm operands[2], operands[2], operands[2], perm
> +;;   vspltisb shift, 4
> +;;   vrlb rotated, bytes, shift
> +;;   vucmpr<vu_lh>n operands[0], operands[1], selector
> +;;
> +;; Uncompress builtins require special handling on little-endian systems 
> because
> +;; the selector/mask layout does not match the architectural element ordering
> +;; used by the vector uncompress instructions. The selector must be byte-wise
> +;; reversed and the high/low nibbles swapped (via rotation) so that the
> +;; resulting vector matches big-endian semantics.
> +
> +(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);
> +      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_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));
> +      emit_insn (gen_altivec_vspltisb (shift, GEN_INT (4)));
> +      emit_move_insn (bytes, gen_lowpart (V16QImode, operands[2]));
> +      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));
> +    }
> +
> +  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")])
> +
> +;; Vector uncompress bytes.
> +;; For big-endian, generates:
> +;;   vucmpr<vu_hl>b operands[0], operands[1], operands[2]
> +;; For little-endian with VSX, generates:
> +;;   vsplth splat, operands[2], <vucmpr_splat>
> +;;   xxbrh splat, splat
> +;;   vspltisb shift, 4
> +;;   vrlb rotated, bytes, shift
> +;;   vucmpr<vu_lh>b operands[0], operands[1], selector
> +;; For little-endian without VSX (Altivec-only), generates:
> +;;   pli mask, <vucmpr_pcv>
> +;;   vinsw pcv, mask, <vucmpr_uim>
> +;;   vperm bytes, bytes, bytes, perm
> +;;   vspltisb shift, 4
> +;;   vrlb rotated, bytes, shift
> +;;   vucmpr<vu_lh>b operands[0], operands[1], selector
> +;;
> +;; Below builtins require special handling on little-endian systems similar
> +;; to nibbles, with selector byte-reversal and nibble swapping via rotation.
> +
> +(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 shift = gen_reg_rtx (V16QImode);
> +      rtx bytes = gen_reg_rtx (V16QImode);
> +      rtx rotated = gen_reg_rtx (V16QImode);
> +      rtx selector = gen_reg_rtx (V8HImode);
> +
> +      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 (bytes, gen_lowpart (V16QImode, operands[2]));
> +      emit_insn (gen_altivec_vperm_v16qi_direct (bytes, bytes, bytes, perm));
> +      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));
> +    }
> +
> +  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 && TARGET_VSX"
> +  "vucmpr<vu_hl>h %0, %1, %2"
> +  [(set_attr "type" "vecperm")])
> +
> +;; Vector uncompress halfwords.
> +;; For big-endian, generates:
> +;;   vucmpr<vu_hl>h operands[0], operands[1], operands[2]
> +;; For little-endian, generates:
> +;;   vspltb splat, operands[2], <vucmpr_splat>
> +;;   vspltisb shift, 4
> +;;   vrlb rotated, splat, shift
> +;;   vucmpr<vu_lh>h operands[0], operands[1], rotated
> +;;
> +;; TARGET_VSX is required because the builtin operates on V2DI (vector
> +;; unsigned long long), which requires -mvsx.
> +
> +(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 && 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 b5b6c98b69e..9222a76f0c4 100644
> --- a/gcc/config/rs6000/rs6000-builtins.def
> +++ b/gcc/config/rs6000/rs6000-builtins.def
> @@ -3977,3 +3977,40 @@
>  
>    const vss __builtin_vsx_xvmulhsh (vss, vss);
>      XVMULHSH smulv8hi3_highpart {}
> +
> +  const vull __builtin_altivec_uncompresshh (vui, vuc);
> +    VUCMPRHH altivec_vucmprhh {}
> +
> +  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 {}
> +
> +[future-altivec]
> +  const vus __builtin_altivec_uncompresshn (vuc, vui);
> +    VUCMPRHN altivec_vucmprhn {}
> +
> +  const vui __builtin_altivec_uncompresshb (vus, vus);
> +    VUCMPRHB altivec_vucmprhb {}
> +
> +  const vus __builtin_altivec_uncompressln (vuc, vui);
> +    VUCMPRLN altivec_vucmprln {}
> +
> +  const vui __builtin_altivec_uncompresslb (vus, vus);
> +    VUCMPRLB altivec_vucmprlb {}
> +
> +  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..62f48cc3c67
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/future-vucmpr-altivec.c
> @@ -0,0 +1,50 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -mdejagnu-cpu=future -mno-vsx" } */
> +/* { dg-require-effective-target powerpc_future_compile_ok } */
> +
> +#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 } } } } */
> +/* { dg-final { scan-assembler-times "vrlb" 4 { target { le } } } } */
> +/* { dg-final { scan-assembler-times "vspltisb" 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..b8887f2a5e6
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/future-vucmpr-vsx.c
> @@ -0,0 +1,61 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -mdejagnu-cpu=future -mvsx" } */
> +/* { dg-require-effective-target powerpc_future_compile_ok } */
> +
> +#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..7c642ed5c12
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/future-vupk.c
> @@ -0,0 +1,51 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -mdejagnu-cpu=future" } */
> +/* { dg-require-effective-target powerpc_future_compile_ok } */
> +
> +#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 && le } }  
> } } */
> +
> +/* { 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 } } */


Reply via email to