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 } } */
