[gcc r16-9293] rs6000: Add vector uncompress and unpack builtins for -mcpu=future [RFC02691]

kishan parmar via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:b4dd1de7c403142be3cb72c859f374e3507f8597

commit r16-9293-gb4dd1de7c403142be3cb72c859f374e3507f8597
Author: Kishan Parmar <[email protected]>
Date:   Tue Jul 7 16:55:09 2026 +0530

    rs6000: Add vector uncompress and unpack builtins for -mcpu=future [RFC02691]
    
    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.target/powerpc/future-vucmpr-altivec.c: New test.
            * gcc.target/powerpc/future-vucmpr-vsx.c: Likewise.
            * gcc.target/powerpc/future-vupk.c: Likewise.
    
    (cherry picked from commit 4790838765e8a4b0580b11ba0d8c6671d7c3fc95)

Diff:
---
 gcc/config/rs6000/altivec.md                       | 362 +++++++++++++++++++++
 gcc/config/rs6000/rs6000-builtins.def              |  37 +++
 gcc/config/rs6000/rs6000-overload.def              |  47 +++
 .../gcc.target/powerpc/future-vucmpr-altivec.c     |  49 +++
 .../gcc.target/powerpc/future-vucmpr-vsx.c         |  61 ++++
 gcc/testsuite/gcc.target/powerpc/future-vupk.c     |  51 +++
 6 files changed, 607 insertions(+)

diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index dbe24c450e14..a8f8d039ffc7 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"
@@ -4850,3 +4862,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 ebcbc500b8af..832aa1b2c45f 100644
--- a/gcc/config/rs6000/rs6000-builtins.def
+++ b/gcc/config/rs6000/rs6000-builtins.def
@@ -4059,3 +4059,40 @@
 
   const vuq __builtin_vsx_xsrebase3t3uqm (vuq, vuq, vuq);
     XSREBASE3T3UQM vsx_xsrebase3t3uqm {}
+
+  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 b1b1028867c6..215e1491837e 100644
--- a/gcc/config/rs6000/rs6000-overload.def
+++ b/gcc/config/rs6000/rs6000-overload.def
@@ -5027,6 +5027,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 000000000000..9f1438abf40d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/future-vucmpr-altivec.c
@@ -0,0 +1,49 @@
+/* { 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 000000000000..b8887f2a5e6b
--- /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 000000000000..7c642ed5c124
--- /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 } } */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.