+2020-05-11  Kelvin Nilsen  <kelvin@gcc.gnu.org>
+           Bill Schmidt  <wschmidt@linux.ibm.com>
+
+       * config/rs6000/altivec.h (vec_pdep): New macro implementing new
+       built-in function.
+       (vec_pext): Likewise.
+       * config/rs6000/altivec.md (UNSPEC_VPDEPD): New constant.
+       (UNSPEC_VPEXTD): Likewise.
+       (vpdepd): New insn.
+       (vpextd): Likewise.
+       * config/rs6000/rs6000-builtin.def (__builtin_altivec_vpdepd): New
+       built-in function.
+       (__builtin_altivec_vpextd): Likewise.
+       * config/rs6000/rs6000-call.c (builtin_function_type): Add
+       handling for FUTURE_BUILTIN_VPDEPD and FUTURE_BUILTIN_VPEXTD
+       cases.
+       * doc/extend.texi (PowerPC Altivec Built-in Functions Available
+       for a Future Architecture): Add description of vec_pdep and
+       vec_pext built-in functions.
+
 2020-05-11  Kelvin Nilsen  <kelvin@gcc.gnu.org>
            Bill Schmidt  <wschmidt@linux.ibm.com>
 
 
    with support for different vector argument and result types.  */
 #define vec_clzm(a, b) __builtin_altivec_vclzdm (a, b)
 #define vec_ctzm(a, b) __builtin_altivec_vctzdm (a, b)
+#define vec_pdep(a, b) __builtin_altivec_vpdepd (a, b)
+#define vec_pext(a, b) __builtin_altivec_vpextd (a, b)
+
 #endif
 
 #endif /* _ALTIVEC_H */
 
    UNSPEC_VRLNM
    UNSPEC_VCLZDM
    UNSPEC_VCTZDM
+   UNSPEC_VPDEPD
+   UNSPEC_VPEXTD
 ])
 
 (define_c_enum "unspecv"
    "vctzdm %0,%1,%2"
    [(set_attr "type" "vecsimple")])
 
+(define_insn "vpdepd"
+  [(set (match_operand:V2DI 0 "altivec_register_operand" "=v")
+       (unspec:V2DI [(match_operand:V2DI 1 "altivec_register_operand" "v")
+                     (match_operand:V2DI 2 "altivec_register_operand" "v")]
+        UNSPEC_VPDEPD))]
+   "TARGET_FUTURE"
+   "vpdepd %0,%1,%2"
+   [(set_attr "type" "vecsimple")])
+
+(define_insn "vpextd"
+  [(set (match_operand:V2DI 0 "altivec_register_operand" "=v")
+       (unspec:V2DI [(match_operand:V2DI 1 "altivec_register_operand" "v")
+                     (match_operand:V2DI 2 "altivec_register_operand" "v")]
+        UNSPEC_VPEXTD))]
+   "TARGET_FUTURE"
+   "vpextd %0,%1,%2"
+   [(set_attr "type" "vecsimple")])
+
 
 (define_expand "bcd<bcd_add_sub>_<code>"
   [(parallel [(set (reg:CCFP CR6_REGNO)
 
 /* Future architecture vector built-ins.  */
 BU_FUTURE_V_2 (VCLZDM, "vclzdm", CONST, vclzdm)
 BU_FUTURE_V_2 (VCTZDM, "vctzdm", CONST, vctzdm)
+BU_FUTURE_V_2 (VPDEPD, "vpdepd", CONST, vpdepd)
+BU_FUTURE_V_2 (VPEXTD, "vpextd", CONST, vpextd)
 \f
 /* 1 argument crypto functions.  */
 BU_CRYPTO_1 (VSBOX,            "vsbox",          CONST, crypto_vsbox_v2di)
 
     case P8V_BUILTIN_ORC_V1TI_UNS:
     case FUTURE_BUILTIN_VCLZDM:
     case FUTURE_BUILTIN_VCTZDM:
+    case FUTURE_BUILTIN_VPDEPD:
+    case FUTURE_BUILTIN_VPEXTD:
       h.uns_p[0] = 1;
       h.uns_p[1] = 1;
       h.uns_p[2] = 1;
 
 implemented by the Future @code{vctzdm} instruction.
 @findex vec_ctzm
 
+@smallexample
+@exdent vector unsigned long long int
+@exdent vec_pdep (vector unsigned long long int, vector unsigned long long int)
+@end smallexample
+Perform a vector parallel bits deposit operation, as if implemented by
+the Future @code{vpdepd} instruction.
+@findex vec_pdep
+
+@smallexample
+@exdent vector unsigned long long int
+@exdent vec_pext (vector unsigned long long int, vector unsigned long long int)
+@end smallexample
+Perform a vector parallel bit extract operation, as if implemented by
+the Future @code{vpextd} instruction.
+@findex vec_pext
 
 @node PowerPC Hardware Transactional Memory Built-in Functions
 @subsection PowerPC Hardware Transactional Memory Built-in Functions
 
+2020-05-11  Kelvin Nilsen  <kelvin@gcc.gnu.org>
+
+       * gcc.target/powerpc/vec-pdep-0.c: New.
+       * gcc.target/powerpc/vec-pdep-1.c: New.
+       * gcc.target/powerpc/vec-pext-0.c: New.
+       * gcc.target/powerpc/vec-pext-1.c: New.
+
 2020-05-11  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/94988
 
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+vector unsigned long long int
+do_vec_pdep (vector unsigned long long int source,
+            vector unsigned long long int mask) {
+  return vec_pdep (source, mask);
+}
+
+int
+vectors_equal (vector unsigned long long int a,
+              vector unsigned long long int b)
+{
+  return (a[0] == b[0]) && (a[1] == b[1]);
+}
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned long long int source_a = { 0xa5f07e3cull, 0x7e3ca5f0ull };
+  vector unsigned long long int source_b = { 0x3ca5f07eull, 0x5a0fe7c3ull };
+
+  vector unsigned long long int mask_a = { 0xffff0000ull, 0x0000ffffull };
+  vector unsigned long long int mask_b = { 0x0f0f0f0full, 0xf0f0f0f0ull };
+
+  /* See pdepd-0.c for derivation of expected results.
+
+     result_aa [0] is compute (source [0], mask [0];
+     result_aa [1] is compute (source [1], mask [1].
+
+     result_ab [0] is compute (source [0], mask [2];
+     result_ab [1] is compute (source [1], mask [3].
+
+     result_ba [0] is compute (source [2], mask [0];
+     result_ba [1] is compute (source [3], mask [1].
+
+     result_bb [0] is compute (source [2], mask [2];
+     result_bb [1] is compute (source [3], mask [3].  */
+
+  vector unsigned long long int result_aa = { 0x7e3c0000ull, 0x0000a5f0ull };
+  vector unsigned long long int result_ab = { 0x070e030cull, 0xa050f000ull };
+  vector unsigned long long int result_ba = { 0xf07e0000ull, 0x0000e7c3ull };
+  vector unsigned long long int result_bb = { 0x0f00070eull, 0xe070c030ull };
+
+  if (!vec_all_eq (do_vec_pdep (source_a, mask_a), result_aa))
+    abort ();
+  if (!vec_all_eq (do_vec_pdep (source_a, mask_b), result_ab))
+    abort ();
+  if (!vec_all_eq (do_vec_pdep (source_b, mask_a), result_ba))
+    abort ();
+  if (!vec_all_eq (do_vec_pdep (source_b, mask_b), result_bb))
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvpdepd\M} } } */
 
--- /dev/null
+/* { dg-do run } */
+/* { dg-require-effective-target powerpc_future_hw } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+vector unsigned long long int
+do_vec_pdep (vector unsigned long long int source,
+            vector unsigned long long int mask) {
+  return vec_pdep (source, mask);
+}
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned long long int source_a = { 0xa5f07e3cull, 0x7e3ca5f0ull };
+  vector unsigned long long int source_b = { 0x3ca5f07eull, 0x5a0fe7c3ull };
+
+  vector unsigned long long int mask_a = { 0xffff0000ull, 0x0000ffffull };
+  vector unsigned long long int mask_b = { 0x0f0f0f0full, 0xf0f0f0f0ull };
+
+  /* See pdepd-0.c for derivation of expected results.
+
+     result_aa [0] is compute (source [0], mask [0];
+     result_aa [1] is compute (source [1], mask [1].
+
+     result_ab [0] is compute (source [0], mask [2];
+     result_ab [1] is compute (source [1], mask [3].
+
+     result_ba [0] is compute (source [2], mask [0];
+     result_ba [1] is compute (source [3], mask [1].
+
+     result_bb [0] is compute (source [2], mask [2];
+     result_bb [1] is compute (source [3], mask [3].  */
+
+  vector unsigned long long int result_aa = { 0x7e3c0000ull, 0x0000a5f0ull };
+  vector unsigned long long int result_ab = { 0x070e030cull, 0xa050f000ull };
+  vector unsigned long long int result_ba = { 0xf07e0000ull, 0x0000e7c3ull };
+  vector unsigned long long int result_bb = { 0x0f00070eull, 0xe070c030ull };
+
+  if (!vec_all_eq (do_vec_pdep (source_a, mask_a), result_aa))
+    abort ();
+  if (!vec_all_eq (do_vec_pdep (source_a, mask_b), result_ab))
+    abort ();
+  if (!vec_all_eq (do_vec_pdep (source_b, mask_a), result_ba))
+    abort ();
+  if (!vec_all_eq (do_vec_pdep (source_b, mask_b), result_bb))
+    abort ();
+
+  return 0;
+}
 
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+vector unsigned long long int
+do_vec_pext (vector unsigned long long int source,
+            vector unsigned long long int mask) {
+  return vec_pext (source, mask);
+}
+
+int main (int argc, char *argv [])
+{
+  vector unsigned long long int source_a = { 0xa5f07e3cull, 0x7e3ca5f0ull };
+  vector unsigned long long int source_b = { 0x3ca5f07eull, 0x5a0fe7c3ull };
+
+  vector unsigned long long int mask_a = { 0xffff0000ull, 0x0000ffffull };
+  vector unsigned long long int mask_b = { 0x0f0f0f0full, 0xf0f0f0f0ull };
+
+  /* See pextd-0.c for derivation of expected results.
+
+     result_aa [0] is compute (source [0], mask [0];
+     result_aa [1] is compute (source [1], mask [1].
+
+     result_ab [0] is compute (source [0], mask [2];
+     result_ab [1] is compute (source [1], mask [3].
+
+     result_ba [0] is compute (source [2], mask [0];
+     result_ba [1] is compute (source [3], mask [1].
+
+     result_bb [0] is compute (source [2], mask [2];
+     result_bb [1] is compute (source [3], mask [3].  */
+
+  vector unsigned long long int result_aa = { 0x0000a5f0ull, 0x0000a5f0ull };
+  vector unsigned long long int result_ab = { 0x000050ecull, 0x000073afull };
+  vector unsigned long long int result_ba = { 0x00003ca5ull, 0x0000e7c3ull };
+  vector unsigned long long int result_bb = { 0x0000c50eull, 0x000050ecull };
+
+  if (!vec_all_eq (do_vec_pext (source_a, mask_a), result_aa))
+    abort ();
+  if (!vec_all_eq (do_vec_pext (source_a, mask_b),result_ab))
+    abort ();
+  if (!vec_all_eq (do_vec_pext (source_b, mask_a), result_ba))
+    abort ();
+  if (!vec_all_eq (do_vec_pext (source_b, mask_b), result_bb))
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvpextd\M} } } */
 
--- /dev/null
+/* { dg-do run } */
+/* { dg-require-effective-target powerpc_future_hw } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+vector unsigned long long int
+do_vec_pext (vector unsigned long long int source,
+            vector unsigned long long int mask) {
+  return vec_pext (source, mask);
+}
+
+int main (int argc, char *argv [])
+{
+  vector unsigned long long int source_a = { 0xa5f07e3cull, 0x7e3ca5f0ull };
+  vector unsigned long long int source_b = { 0x3ca5f07eull, 0x5a0fe7c3ull };
+
+  vector unsigned long long int mask_a = { 0xffff0000ull, 0x0000ffffull };
+  vector unsigned long long int mask_b = { 0x0f0f0f0full, 0xf0f0f0f0ull };
+
+  /* See pextd-0.c for derivation of expected results.
+
+     result_aa [0] is compute (source [0], mask [0];
+     result_aa [1] is compute (source [1], mask [1].
+
+     result_ab [0] is compute (source [0], mask [2];
+     result_ab [1] is compute (source [1], mask [3].
+
+     result_ba [0] is compute (source [2], mask [0];
+     result_ba [1] is compute (source [3], mask [1].
+
+     result_bb [0] is compute (source [2], mask [2];
+     result_bb [1] is compute (source [3], mask [3].  */
+
+  vector unsigned long long int result_aa = { 0x0000a5f0ull, 0x0000a5f0ull };
+  vector unsigned long long int result_ab = { 0x000050ecull, 0x000073afull };
+  vector unsigned long long int result_ba = { 0x00003ca5ull, 0x0000e7c3ull };
+  vector unsigned long long int result_bb = { 0x0000c50eull, 0x000050ecull };
+
+  if (!vec_all_eq (do_vec_pext (source_a, mask_a), result_aa))
+    abort ();
+  if (!vec_all_eq (do_vec_pext (source_a, mask_b),result_ab))
+    abort ();
+  if (!vec_all_eq (do_vec_pext (source_b, mask_a), result_ba))
+    abort ();
+  if (!vec_all_eq (do_vec_pext (source_b, mask_b), result_bb))
+    abort ();
+
+  return 0;
+}