diff mbox series

[V2] rs6000: Add vec_extracth and vec_extractl

Message ID 20200513125050.60931-1-wschmidt@linux.ibm.com
State New
Headers show
Series [V2] rs6000: Add vec_extracth and vec_extractl | expand

Commit Message

Bill Schmidt May 13, 2020, 12:50 p.m. UTC
From: Kelvin Nilsen <kelvin@gcc.gnu.org>

Add new insns vextdu[bhw]vlx, vextddvlx, vextdu[bhw]vhx, and
vextddvhx, along with built-in access and overloaded built-in
access to these insns.

Changes from previous patch:
 * Removed the int iterators
 * Created separate expansions and insns
    vextractl<mode>
    vextractl<mode>_internal
    vextractr<mode>
    vextractr<mode>_internal
 * Adjusted rs6000-builtin.def entries to match the new expansion
   names

I didn't understand the comment about moving the decision making
part to the built-in handling code.  All the built-in handling
does is a table-driven call to the expansions; this logic *is*
the built-in handling code.  I don't see any way to simplify that.

Bootstrapped and tested on powerpc64le-unknown-linux-gnu with no
regressions, using a Power9 configuration.  Is this okay for
master?

Thanks,
Bill


[gcc]

2020-05-12  Kelvin Nilsen  <kelvin@gcc.gnu.org>

	* config/rs6000/altivec.h (vec_extractl): New #define.
	(vec_extracth): Likewise.
	* config/rs6000/altivec.md (UNSPEC_EXTRACTL): New constant.
	(UNSPEC_EXTRACTR): Likewise.
	(vextractl<mode>): New expansion.
	(vextractl<mode>_internal): New insn.
	(vextractr<mode>): New expansion.
	(vextractr<mode>_internal): New insn.
	* config/rs6000/rs6000-builtin.def (__builtin_altivec_vextdubvlx):
	New built-in function.
	(__builtin_altivec_vextduhvlx): Likewise.
	(__builtin_altivec_vextduwvlx): Likewise.
	(__builtin_altivec_vextddvlx): Likewise.
	(__builtin_altivec_vextdubvhx): Likewise.
	(__builtin_altivec_vextduhvhx): Likewise.
	(__builtin_altivec_vextduwvhx): Likewise.
	(__builtin_altivec_vextddvhx): Likewise.
	(__builtin_vec_extractl): New overloaded built-in function.
	(__builtin_vec_extracth): Likewise.
	* config/rs6000/rs6000-call.c (altivec_overloaded_builtins):
	Define overloaded forms of __builtin_vec_extractl and
	__builtin_vec_extracth.
	(builtin_function_type): Add cases to mark arguments of new
	built-in functions as unsigned.
	(rs6000_common_init_builtins): Add
	opaque_ftype_opaque_opaque_opaque_opaque.
	* config/rs6000/rs6000.md (du_or_d): New mode attribute.
	* doc/extend.texi (PowerPC AltiVec Built-in Functions Available
	for a Future Architecture): Add description of vec_extractl and
	vec_extractr built-in functions.

[gcc/testsuite]

2020-05-10  Kelvin Nilsen  <kelvin@gcc.gnu.org>

	* gcc.target/powerpc/vec-extracth-0.c: New.
	* gcc.target/powerpc/vec-extracth-1.c: New.
	* gcc.target/powerpc/vec-extracth-2.c: New.
	* gcc.target/powerpc/vec-extracth-3.c: New.
	* gcc.target/powerpc/vec-extracth-4.c: New.
	* gcc.target/powerpc/vec-extracth-5.c: New.
	* gcc.target/powerpc/vec-extracth-6.c: New.
	* gcc.target/powerpc/vec-extracth-7.c: New.
	* gcc.target/powerpc/vec-extracth-be-0.c: New.
	* gcc.target/powerpc/vec-extracth-be-1.c: New.
	* gcc.target/powerpc/vec-extracth-be-2.c: New.
	* gcc.target/powerpc/vec-extracth-be-3.c: New.
	* gcc.target/powerpc/vec-extractl-0.c: New.
	* gcc.target/powerpc/vec-extractl-1.c: New.
	* gcc.target/powerpc/vec-extractl-2.c: New.
	* gcc.target/powerpc/vec-extractl-3.c: New.
	* gcc.target/powerpc/vec-extractl-4.c: New.
	* gcc.target/powerpc/vec-extractl-5.c: New.
	* gcc.target/powerpc/vec-extractl-6.c: New.
	* gcc.target/powerpc/vec-extractl-7.c: New.
	* gcc.target/powerpc/vec-extractl-be-0.c: New.
	* gcc.target/powerpc/vec-extractl-be-1.c: New.
	* gcc.target/powerpc/vec-extractl-be-2.c: New.
	* gcc.target/powerpc/vec-extractl-be-3.c: New.
---
 gcc/config/rs6000/altivec.h                   |  3 +
 gcc/config/rs6000/altivec.md                  | 62 +++++++++++++++++++
 gcc/config/rs6000/rs6000-builtin.def          | 13 ++++
 gcc/config/rs6000/rs6000-call.c               | 39 +++++++++++-
 gcc/config/rs6000/rs6000.md                   | 10 +++
 gcc/doc/extend.texi                           | 56 +++++++++++++++++
 .../gcc.target/powerpc/vec-extracth-0.c       | 33 ++++++++++
 .../gcc.target/powerpc/vec-extracth-1.c       | 32 ++++++++++
 .../gcc.target/powerpc/vec-extracth-2.c       | 31 ++++++++++
 .../gcc.target/powerpc/vec-extracth-3.c       | 30 +++++++++
 .../gcc.target/powerpc/vec-extracth-4.c       | 31 ++++++++++
 .../gcc.target/powerpc/vec-extracth-5.c       | 29 +++++++++
 .../gcc.target/powerpc/vec-extracth-6.c       | 31 ++++++++++
 .../gcc.target/powerpc/vec-extracth-7.c       | 30 +++++++++
 .../gcc.target/powerpc/vec-extracth-be-0.c    | 32 ++++++++++
 .../gcc.target/powerpc/vec-extracth-be-1.c    | 30 +++++++++
 .../gcc.target/powerpc/vec-extracth-be-2.c    | 30 +++++++++
 .../gcc.target/powerpc/vec-extracth-be-3.c    | 30 +++++++++
 .../gcc.target/powerpc/vec-extractl-0.c       | 33 ++++++++++
 .../gcc.target/powerpc/vec-extractl-1.c       | 32 ++++++++++
 .../gcc.target/powerpc/vec-extractl-2.c       | 31 ++++++++++
 .../gcc.target/powerpc/vec-extractl-3.c       | 30 +++++++++
 .../gcc.target/powerpc/vec-extractl-4.c       | 31 ++++++++++
 .../gcc.target/powerpc/vec-extractl-5.c       | 29 +++++++++
 .../gcc.target/powerpc/vec-extractl-6.c       | 31 ++++++++++
 .../gcc.target/powerpc/vec-extractl-7.c       | 30 +++++++++
 .../gcc.target/powerpc/vec-extractl-be-0.c    | 32 ++++++++++
 .../gcc.target/powerpc/vec-extractl-be-1.c    | 30 +++++++++
 .../gcc.target/powerpc/vec-extractl-be-2.c    | 30 +++++++++
 .../gcc.target/powerpc/vec-extractl-be-3.c    | 30 +++++++++
 30 files changed, 919 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extracth-0.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extracth-1.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extracth-2.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extracth-3.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extracth-4.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extracth-5.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extracth-6.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extracth-7.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extracth-be-0.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extracth-be-1.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extracth-be-2.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extracth-be-3.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extractl-0.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extractl-1.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extractl-2.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extractl-3.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extractl-4.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extractl-5.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extractl-6.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extractl-7.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extractl-be-0.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extractl-be-1.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extractl-be-2.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-extractl-be-3.c

Comments

Segher Boessenkool May 13, 2020, 8:41 p.m. UTC | #1
Hi!

On Wed, May 13, 2020 at 07:50:50AM -0500, Bill Schmidt wrote:
> From: Kelvin Nilsen <kelvin@gcc.gnu.org>
> 
> Add new insns vextdu[bhw]vlx, vextddvlx, vextdu[bhw]vhx, and
> vextddvhx, along with built-in access and overloaded built-in
> access to these insns.
> 
> Changes from previous patch:
>  * Removed the int iterators
>  * Created separate expansions and insns
>     vextractl<mode>
>     vextractl<mode>_internal
>     vextractr<mode>
>     vextractr<mode>_internal
>  * Adjusted rs6000-builtin.def entries to match the new expansion
>    names
> 
> I didn't understand the comment about moving the decision making
> part to the built-in handling code.  All the built-in handling
> does is a table-driven call to the expansions; this logic *is*
> the built-in handling code.  I don't see any way to simplify that.

I'll try it myself :-)

> Bootstrapped and tested on powerpc64le-unknown-linux-gnu with no
> regressions, using a Power9 configuration.  Is this okay for
> master?

This is okay for trunk.  Thanks!


Segher


> 2020-05-12  Kelvin Nilsen  <kelvin@gcc.gnu.org>
> 
> 	* config/rs6000/altivec.h (vec_extractl): New #define.
> 	(vec_extracth): Likewise.
> 	* config/rs6000/altivec.md (UNSPEC_EXTRACTL): New constant.
> 	(UNSPEC_EXTRACTR): Likewise.
> 	(vextractl<mode>): New expansion.
> 	(vextractl<mode>_internal): New insn.
> 	(vextractr<mode>): New expansion.
> 	(vextractr<mode>_internal): New insn.
> 	* config/rs6000/rs6000-builtin.def (__builtin_altivec_vextdubvlx):
> 	New built-in function.
> 	(__builtin_altivec_vextduhvlx): Likewise.
> 	(__builtin_altivec_vextduwvlx): Likewise.
> 	(__builtin_altivec_vextddvlx): Likewise.
> 	(__builtin_altivec_vextdubvhx): Likewise.
> 	(__builtin_altivec_vextduhvhx): Likewise.
> 	(__builtin_altivec_vextduwvhx): Likewise.
> 	(__builtin_altivec_vextddvhx): Likewise.
> 	(__builtin_vec_extractl): New overloaded built-in function.
> 	(__builtin_vec_extracth): Likewise.
> 	* config/rs6000/rs6000-call.c (altivec_overloaded_builtins):
> 	Define overloaded forms of __builtin_vec_extractl and
> 	__builtin_vec_extracth.
> 	(builtin_function_type): Add cases to mark arguments of new
> 	built-in functions as unsigned.
> 	(rs6000_common_init_builtins): Add
> 	opaque_ftype_opaque_opaque_opaque_opaque.
> 	* config/rs6000/rs6000.md (du_or_d): New mode attribute.
> 	* doc/extend.texi (PowerPC AltiVec Built-in Functions Available
> 	for a Future Architecture): Add description of vec_extractl and
> 	vec_extractr built-in functions.
> 
> [gcc/testsuite]
> 
> 2020-05-10  Kelvin Nilsen  <kelvin@gcc.gnu.org>
> 
> 	* gcc.target/powerpc/vec-extracth-0.c: New.
> 	* gcc.target/powerpc/vec-extracth-1.c: New.
> 	* gcc.target/powerpc/vec-extracth-2.c: New.
> 	* gcc.target/powerpc/vec-extracth-3.c: New.
> 	* gcc.target/powerpc/vec-extracth-4.c: New.
> 	* gcc.target/powerpc/vec-extracth-5.c: New.
> 	* gcc.target/powerpc/vec-extracth-6.c: New.
> 	* gcc.target/powerpc/vec-extracth-7.c: New.
> 	* gcc.target/powerpc/vec-extracth-be-0.c: New.
> 	* gcc.target/powerpc/vec-extracth-be-1.c: New.
> 	* gcc.target/powerpc/vec-extracth-be-2.c: New.
> 	* gcc.target/powerpc/vec-extracth-be-3.c: New.
> 	* gcc.target/powerpc/vec-extractl-0.c: New.
> 	* gcc.target/powerpc/vec-extractl-1.c: New.
> 	* gcc.target/powerpc/vec-extractl-2.c: New.
> 	* gcc.target/powerpc/vec-extractl-3.c: New.
> 	* gcc.target/powerpc/vec-extractl-4.c: New.
> 	* gcc.target/powerpc/vec-extractl-5.c: New.
> 	* gcc.target/powerpc/vec-extractl-6.c: New.
> 	* gcc.target/powerpc/vec-extractl-7.c: New.
> 	* gcc.target/powerpc/vec-extractl-be-0.c: New.
> 	* gcc.target/powerpc/vec-extractl-be-1.c: New.
> 	* gcc.target/powerpc/vec-extractl-be-2.c: New.
> 	* gcc.target/powerpc/vec-extractl-be-3.c: New.
diff mbox series

Patch

diff --git a/gcc/config/rs6000/altivec.h b/gcc/config/rs6000/altivec.h
index 85c5626877d..0a7e8ab3647 100644
--- a/gcc/config/rs6000/altivec.h
+++ b/gcc/config/rs6000/altivec.h
@@ -697,6 +697,9 @@  __altivec_scalar_pred(vec_any_nle,
 #define vec_genpcvm(a, b)	__builtin_vec_xxgenpcvm (a, b)
 
 /* Overloaded built-in functions for future architecture.  */
+#define vec_extractl(a, b, c)	__builtin_vec_extractl (a, b, c)
+#define vec_extracth(a, b, c)	__builtin_vec_extracth (a, b, c)
+
 #define vec_gnb(a, b)	__builtin_vec_gnb (a, b)
 #define vec_clrl(a, b)	__builtin_vec_clrl (a, b)
 #define vec_clrr(a, b)	__builtin_vec_clrr (a, b)
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 1c0bbb7527a..792ca4f488e 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -171,6 +171,8 @@  (define_c_enum "unspec"
    UNSPEC_XXEVAL
    UNSPEC_VSTRIR
    UNSPEC_VSTRIL
+   UNSPEC_EXTRACTL
+   UNSPEC_EXTRACTR
 ])
 
 (define_c_enum "unspecv"
@@ -783,6 +785,66 @@  (define_expand "mulv8hi3"
   DONE;
 })
 
+(define_expand "vextractl<mode>"
+  [(set (match_operand:V2DI 0 "altivec_register_operand")
+	(unspec:V2DI [(match_operand:VI2 1 "altivec_register_operand")
+		      (match_operand:VI2 2 "altivec_register_operand")
+		      (match_operand:SI 3 "register_operand")]
+		     UNSPEC_EXTRACTL))]
+  "TARGET_FUTURE"
+{
+  if (BYTES_BIG_ENDIAN)
+    {
+      emit_insn (gen_vextractl<mode>_internal (operands[0], operands[1],
+					       operands[2], operands[3]));
+      emit_insn (gen_xxswapd_v2di (operands[0], operands[0]));
+    }
+  else
+    emit_insn (gen_vextractr<mode>_internal (operands[0], operands[2],
+					     operands[1], operands[3]));
+  DONE;
+})
+
+(define_insn "vextractl<mode>_internal"
+  [(set (match_operand:V2DI 0 "altivec_register_operand" "=v")
+	(unspec:V2DI [(match_operand:VEC_I 1 "altivec_register_operand" "v")
+		      (match_operand:VEC_I 2 "altivec_register_operand" "v")
+		      (match_operand:SI 3 "register_operand" "r")]
+		     UNSPEC_EXTRACTL))]
+  "TARGET_FUTURE"
+  "vext<du_or_d><wd>vlx %0,%1,%2,%3"
+  [(set_attr "type" "vecsimple")])
+
+(define_expand "vextractr<mode>"
+  [(set (match_operand:V2DI 0 "altivec_register_operand")
+	(unspec:V2DI [(match_operand:VI2 1 "altivec_register_operand")
+		      (match_operand:VI2 2 "altivec_register_operand")
+		      (match_operand:SI 3 "register_operand")]
+		     UNSPEC_EXTRACTR))]
+  "TARGET_FUTURE"
+{
+  if (BYTES_BIG_ENDIAN)
+    {
+      emit_insn (gen_vextractr<mode>_internal (operands[0], operands[1],
+					       operands[2], operands[3]));
+      emit_insn (gen_xxswapd_v2di (operands[0], operands[0]));
+    }
+  else
+    emit_insn (gen_vextractl<mode>_internal (operands[0], operands[2],
+    					     operands[1], operands[3]));
+  DONE;
+})
+
+(define_insn "vextractr<mode>_internal"
+  [(set (match_operand:V2DI 0 "altivec_register_operand" "=v")
+	(unspec:V2DI [(match_operand:VEC_I 1 "altivec_register_operand" "v")
+		      (match_operand:VEC_I 2 "altivec_register_operand" "v")
+		      (match_operand:SI 3 "register_operand" "r")]
+		     UNSPEC_EXTRACTR))]
+  "TARGET_FUTURE"
+  "vext<du_or_d><wd>vrx %0,%1,%2,%3"
+  [(set_attr "type" "vecsimple")])
+
 (define_expand "vstrir_<mode>"
   [(set (match_operand:VIshort 0 "altivec_register_operand")
 	(unspec:VIshort [(match_operand:VIshort 1 "altivec_register_operand")]
diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def
index 9acb448b8e4..e58edec47da 100644
--- a/gcc/config/rs6000/rs6000-builtin.def
+++ b/gcc/config/rs6000/rs6000-builtin.def
@@ -2616,6 +2616,16 @@  BU_FUTURE_V_2 (XXGENPCVM_V8HI, "xxgenpcvm_v8hi", CONST, xxgenpcvm_v8hi)
 BU_FUTURE_V_2 (XXGENPCVM_V4SI, "xxgenpcvm_v4si", CONST, xxgenpcvm_v4si)
 BU_FUTURE_V_2 (XXGENPCVM_V2DI, "xxgenpcvm_v2di", CONST, xxgenpcvm_v2di)
 
+BU_FUTURE_V_3 (VEXTRACTBL, "vextdubvlx", CONST, vextractlv16qi)
+BU_FUTURE_V_3 (VEXTRACTHL, "vextduhvlx", CONST, vextractlv8hi)
+BU_FUTURE_V_3 (VEXTRACTWL, "vextduwvlx", CONST, vextractlv4si)
+BU_FUTURE_V_3 (VEXTRACTDL, "vextddvlx", CONST, vextractlv2di)
+
+BU_FUTURE_V_3 (VEXTRACTBR, "vextdubvhx", CONST, vextractrv16qi)
+BU_FUTURE_V_3 (VEXTRACTHR, "vextduhvhx", CONST, vextractrv8hi)
+BU_FUTURE_V_3 (VEXTRACTWR, "vextduwvhx", CONST, vextractrv4si)
+BU_FUTURE_V_3 (VEXTRACTDR, "vextddvhx", CONST, vextractrv2di)
+
 BU_FUTURE_V_1 (VSTRIBR, "vstribr", CONST, vstrir_v16qi)
 BU_FUTURE_V_1 (VSTRIHR, "vstrihr", CONST, vstrir_v8hi)
 BU_FUTURE_V_1 (VSTRIBL, "vstribl", CONST, vstril_v16qi)
@@ -2633,6 +2643,9 @@  BU_FUTURE_OVERLOAD_2 (GNB, "gnb")
 BU_FUTURE_OVERLOAD_4 (XXEVAL, "xxeval")
 BU_FUTURE_OVERLOAD_2 (XXGENPCVM, "xxgenpcvm")
 
+BU_FUTURE_OVERLOAD_3 (EXTRACTL, "extractl")
+BU_FUTURE_OVERLOAD_3 (EXTRACTH, "extracth")
+
 BU_FUTURE_OVERLOAD_1 (VSTRIR, "strir")
 BU_FUTURE_OVERLOAD_1 (VSTRIL, "stril")
 
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index 04189eaaa53..0ac8054d030 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -5552,6 +5552,32 @@  const struct altivec_builtin_types altivec_overloaded_builtins[] = {
     RS6000_BTI_unsigned_V1TI, RS6000_BTI_unsigned_V1TI,
     RS6000_BTI_unsigned_V1TI, RS6000_BTI_unsigned_V1TI },
 
+  { FUTURE_BUILTIN_VEC_EXTRACTL, FUTURE_BUILTIN_VEXTRACTBL,
+    RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V16QI,
+    RS6000_BTI_unsigned_V16QI, RS6000_BTI_UINTQI },
+  { FUTURE_BUILTIN_VEC_EXTRACTL, FUTURE_BUILTIN_VEXTRACTHL,
+    RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V8HI,
+    RS6000_BTI_unsigned_V8HI, RS6000_BTI_UINTQI },
+  { FUTURE_BUILTIN_VEC_EXTRACTL, FUTURE_BUILTIN_VEXTRACTWL,
+    RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V4SI,
+    RS6000_BTI_unsigned_V4SI, RS6000_BTI_UINTQI },
+  { FUTURE_BUILTIN_VEC_EXTRACTL, FUTURE_BUILTIN_VEXTRACTDL,
+    RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI,
+    RS6000_BTI_unsigned_V2DI, RS6000_BTI_UINTQI },
+
+  { FUTURE_BUILTIN_VEC_EXTRACTH, FUTURE_BUILTIN_VEXTRACTBR,
+    RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V16QI,
+    RS6000_BTI_unsigned_V16QI, RS6000_BTI_UINTQI },
+  { FUTURE_BUILTIN_VEC_EXTRACTH, FUTURE_BUILTIN_VEXTRACTHR,
+    RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V8HI,
+    RS6000_BTI_unsigned_V8HI, RS6000_BTI_UINTQI },
+  { FUTURE_BUILTIN_VEC_EXTRACTH, FUTURE_BUILTIN_VEXTRACTWR,
+    RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V4SI,
+    RS6000_BTI_unsigned_V4SI, RS6000_BTI_UINTQI },
+  { FUTURE_BUILTIN_VEC_EXTRACTH, FUTURE_BUILTIN_VEXTRACTDR,
+    RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI,
+    RS6000_BTI_unsigned_V2DI, RS6000_BTI_UINTQI },
+
   { FUTURE_BUILTIN_VEC_VSTRIL, FUTURE_BUILTIN_VSTRIBL,
     RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0, 0 },
   { FUTURE_BUILTIN_VEC_VSTRIL, FUTURE_BUILTIN_VSTRIBL,
@@ -13255,6 +13281,14 @@  builtin_function_type (machine_mode mode_ret, machine_mode mode_arg0,
     case CRYPTO_BUILTIN_VSHASIGMAW:
     case CRYPTO_BUILTIN_VSHASIGMAD:
     case CRYPTO_BUILTIN_VSHASIGMA:
+    case FUTURE_BUILTIN_VEXTRACTBL:
+    case FUTURE_BUILTIN_VEXTRACTHL:
+    case FUTURE_BUILTIN_VEXTRACTWL:
+    case FUTURE_BUILTIN_VEXTRACTDL:
+    case FUTURE_BUILTIN_VEXTRACTBR:
+    case FUTURE_BUILTIN_VEXTRACTHR:
+    case FUTURE_BUILTIN_VEXTRACTWR:
+    case FUTURE_BUILTIN_VEXTRACTDR:
       h.uns_p[0] = 1;
       h.uns_p[1] = 1;
       h.uns_p[2] = 1;
@@ -13393,6 +13427,7 @@  rs6000_common_init_builtins (void)
   tree opaque_ftype_opaque = NULL_TREE;
   tree opaque_ftype_opaque_opaque = NULL_TREE;
   tree opaque_ftype_opaque_opaque_opaque = NULL_TREE;
+  tree opaque_ftype_opaque_opaque_opaque_opaque = NULL_TREE;
   HOST_WIDE_INT builtin_mask = rs6000_builtin_mask;
 
   /* Create Altivec and VSX builtins on machines with at least the
@@ -13418,9 +13453,9 @@  rs6000_common_init_builtins (void)
 
       if (rs6000_overloaded_builtin_p (d->code))
 	{
-	  type = opaque_ftype_opaque_opaque_opaque;
+	  type = opaque_ftype_opaque_opaque_opaque_opaque;
 	  if (!type)
-	    type = opaque_ftype_opaque_opaque_opaque
+	    type = opaque_ftype_opaque_opaque_opaque_opaque
 	      = build_function_type_list (opaque_V4SI_type_node,
 					  opaque_V4SI_type_node,
 					  opaque_V4SI_type_node,
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 4fcd6a94022..0aa5265d199 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -653,6 +653,16 @@  (define_mode_attr wd [(QI    "b")
 		      (V1TI  "q")
 		      (TI    "q")])
 
+; For double extract from different origin types
+(define_mode_attr du_or_d [(QI    "du")
+			   (HI    "du")
+			   (SI    "du")
+			   (DI    "d")
+			   (V16QI "du")
+			   (V8HI  "du")
+			   (V4SI  "du")
+			   (V2DI  "d")])
+
 ;; How many bits in this mode?
 (define_mode_attr bits [(QI "8") (HI "16") (SI "32") (DI "64")
 					   (SF "32") (DF "64")])
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 4c5ed3f3bac..55dd477ffb8 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -20809,6 +20809,62 @@  Perform a 128-bit vector gather  operation, as if implemented by the Future
 integer value between 2 and 7 inclusive.
 @findex vec_gnb
 
+@smallexample
+@exdent vector unsigned long long int
+@exdent vec_extractl (vector unsigned char, vector unsigned char, unsigned int)
+@exdent vector unsigned long long int
+@exdent vec_extractl (vector unsigned short, vector unsigned short, unsigned int)
+@exdent vector unsigned long long int
+@exdent vec_extractl (vector unsigned int, vector unsigned int, unsigned int)
+@exdent vector unsigned long long int
+@exdent vec_extractl (vector unsigned long long, vector unsigned long long, unsigned int)
+@end smallexample
+Extract a single element from the vector formed by catenating this function's
+first two arguments at the byte offset specified by this function's
+third argument.  On big-endian targets, this function behaves as if
+implemented by the Future @code{vextdubvlx}, @code{vextduhvlx},
+@code{vextduwvlx}, or @code{vextddvlx} instructions, depending on the
+types of the function's first two arguments.  On little-endian
+targets, this function behaves as if implemented by the Future
+@code{vextdubvrx}, @code{vextduhvrx},
+@code{vextduwvrx}, or @code{vextddvrx} instructions.
+The byte offset of the element to be extracted is calculated
+by computing the remainder of dividing the third argument by 32.
+If this reminader value is not a multiple of the vector element size,
+or if its value added to the vector element size exceeds 32, the
+result is undefined.
+@findex vec_extractl
+
+@smallexample
+@exdent vector unsigned long long int
+@exdent vec_extractr (vector unsigned char, vector unsigned char, unsigned int)
+@exdent vector unsigned long long int
+@exdent vec_extractr (vector unsigned short, vector unsigned short, unsigned int)
+@exdent vector unsigned long long int
+@exdent vec_extractr (vector unsigned int, vector unsigned int, unsigned int)
+@exdent vector unsigned long long int
+@exdent vec_extractr (vector unsigned long long, vector unsigned long long, unsigned int)
+@end smallexample
+Extract a single element from the vector formed by catenating this function's
+first two arguments at the byte offset calculated by subtracting this
+function's third argument from 31.  On big-endian targets, this
+function behaves as if
+implemented by the Future
+@code{vextdubvrx}, @code{vextduhvrx},
+@code{vextduwvrx}, or @code{vextddvrx} instructions, depending on the
+types of the function's first two arguments.
+On little-endian
+targets, this function behaves as if implemented by the Future
+@code{vextdubvlx}, @code{vextduhvlx},
+@code{vextduwvlx}, or @code{vextddvlx} instructions.
+The byte offset of the element to be extracted, measured from the
+right end of the catenation of the two vector arguments, is calculated
+by computing the remainder of dividing the third argument by 32.
+If this reminader value is not a multiple of the vector element size,
+or if its value added to the vector element size exceeds 32, the
+result is undefined.
+@findex vec_extractr
+
 @smallexample
 @exdent vector unsigned long long int
 @exdent vec_pdep (vector unsigned long long int, vector unsigned long long int)
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extracth-0.c b/gcc/testsuite/gcc.target/powerpc/vec-extracth-0.c
new file mode 100644
index 00000000000..953b148d8e8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extracth-0.c
@@ -0,0 +1,33 @@ 
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned char source_a = {
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+  vector unsigned char source_b = {
+    16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
+
+  vector unsigned long long int result_1 = { 0, 16 };
+  vector unsigned long long int result_2 = { 0, 15 };
+  vector unsigned long long int result_3 = { 0, 11 };
+  vector unsigned long long int result_4 = { 0, 23 };
+
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 15), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 4), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 24), result_4))
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvextdubvlx\M} { target le } } } */
+/* { dg-final { scan-assembler {\mvextdubvrx\M} { target be } } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extracth-1.c b/gcc/testsuite/gcc.target/powerpc/vec-extracth-1.c
new file mode 100644
index 00000000000..ec55f0ed8e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extracth-1.c
@@ -0,0 +1,32 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target powerpc_future_hw } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned char source_a = {
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+  vector unsigned char source_b = {
+    16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
+
+  vector unsigned long long int result_1 = { 0, 16 };
+  vector unsigned long long int result_2 = { 0, 15 };
+  vector unsigned long long int result_3 = { 0, 11 };
+  vector unsigned long long int result_4 = { 0, 23 };
+
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 15), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 4), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 24), result_4))
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extracth-2.c b/gcc/testsuite/gcc.target/powerpc/vec-extracth-2.c
new file mode 100644
index 00000000000..0520546ba39
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extracth-2.c
@@ -0,0 +1,31 @@ 
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned short source_a = { 0, 2, 4, 6, 8, 10, 12, 14 };
+  vector unsigned short source_b = { 16, 18, 20, 22, 24, 26, 28, 30 };
+
+  vector unsigned long long int result_1 = { 0, 16 };
+  vector unsigned long long int result_2 = { 0, 14 };
+  vector unsigned long long int result_3 = { 0, 6 };
+  vector unsigned long long int result_4 = { 0, 18 };
+
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 14), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 8), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 28), result_4))
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvextduhvlx\M} { target le } } } */
+/* { dg-final { scan-assembler {\mvextduhvrx\M} { target be } } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extracth-3.c b/gcc/testsuite/gcc.target/powerpc/vec-extracth-3.c
new file mode 100644
index 00000000000..962b2fd3035
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extracth-3.c
@@ -0,0 +1,30 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target powerpc_future_hw } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned short source_a = { 0, 2, 4, 6, 8, 10, 12, 14 };
+  vector unsigned short source_b = { 16, 18, 20, 22, 24, 26, 28, 30 };
+
+  vector unsigned long long int result_1 = { 0, 16 };
+  vector unsigned long long int result_2 = { 0, 14 };
+  vector unsigned long long int result_3 = { 0, 6 };
+  vector unsigned long long int result_4 = { 0, 18 };
+
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 14), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 8), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 28), result_4))
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extracth-4.c b/gcc/testsuite/gcc.target/powerpc/vec-extracth-4.c
new file mode 100644
index 00000000000..0f6d1bf9a9d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extracth-4.c
@@ -0,0 +1,31 @@ 
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned int source_a = { 0, 4, 8, 12 };
+  vector unsigned int source_b = { 16, 20, 24, 28 };
+
+  vector unsigned long long int result_1 = { 0, 16 };
+  vector unsigned long long int result_2 = { 0, 12 };
+  vector unsigned long long int result_3 = { 0, 4 };
+  vector unsigned long long int result_4 = { 0, 16 };
+
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 12), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 8), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 28), result_4))
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvextduwvlx\M} { target le } } } */
+/* { dg-final { scan-assembler {\mvextduwvrx\M} { target be } } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extracth-5.c b/gcc/testsuite/gcc.target/powerpc/vec-extracth-5.c
new file mode 100644
index 00000000000..94ed061725f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extracth-5.c
@@ -0,0 +1,29 @@ 
+/* { dg-require-effective-target powerpc_future_hw } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned int source_a = { 0, 4, 8, 12 };
+  vector unsigned int source_b = { 16, 20, 24, 28 };
+
+  vector unsigned long long int result_1 = { 0, 16 };
+  vector unsigned long long int result_2 = { 0, 12 };
+  vector unsigned long long int result_3 = { 0, 4 };
+  vector unsigned long long int result_4 = { 0, 16 };
+
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 12), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 8), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 28), result_4))
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extracth-6.c b/gcc/testsuite/gcc.target/powerpc/vec-extracth-6.c
new file mode 100644
index 00000000000..27acaa192cc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extracth-6.c
@@ -0,0 +1,31 @@ 
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned long long source_a = { 0, 14 };
+  vector unsigned long long source_b = { 16, 30 };
+
+  vector unsigned long long int result_1 = { 0, 16 };
+  vector unsigned long long int result_2 = { 0, 14 };
+  vector unsigned long long int result_3 = { 0, 0 };
+  vector unsigned long long int result_4 = { 0, 30 };
+
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 8), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 8), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 16), result_4))
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvextddvlx\M} { target le } } } */
+/* { dg-final { scan-assembler {\mvextddvrx\M} { target be } } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extracth-7.c b/gcc/testsuite/gcc.target/powerpc/vec-extracth-7.c
new file mode 100644
index 00000000000..30c4d3a5cf0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extracth-7.c
@@ -0,0 +1,30 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target powerpc_future_hw } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned long long source_a = { 0, 14 };
+  vector unsigned long long source_b = { 16, 30 };
+
+  vector unsigned long long int result_1 = { 0, 16 };
+  vector unsigned long long int result_2 = { 0, 14 };
+  vector unsigned long long int result_3 = { 0, 0 };
+  vector unsigned long long int result_4 = { 0, 30 };
+
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 8), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 8), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 16), result_4))
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extracth-be-0.c b/gcc/testsuite/gcc.target/powerpc/vec-extracth-be-0.c
new file mode 100644
index 00000000000..93181033693
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extracth-be-0.c
@@ -0,0 +1,32 @@ 
+/* { dg-options "-mdejagnu-cpu=future -mbig-endian" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned char source_a = {
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+  vector unsigned char source_b = {
+    16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
+
+  vector unsigned long long int result_1 = { 0, 16 };
+  vector unsigned long long int result_2 = { 0, 15 };
+  vector unsigned long long int result_3 = { 0, 11 };
+  vector unsigned long long int result_4 = { 0, 23 };
+
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 15), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 4), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 24), result_4))
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvextdubvrx\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extracth-be-1.c b/gcc/testsuite/gcc.target/powerpc/vec-extracth-be-1.c
new file mode 100644
index 00000000000..48cf3ac8628
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extracth-be-1.c
@@ -0,0 +1,30 @@ 
+/* { dg-options "-mdejagnu-cpu=future -mbig-endian" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned short source_a = { 0, 2, 4, 6, 8, 10, 12, 14 };
+  vector unsigned short source_b = { 16, 18, 20, 22, 24, 26, 28, 30 };
+
+  vector unsigned long long int result_1 = { 0, 16 };
+  vector unsigned long long int result_2 = { 0, 14 };
+  vector unsigned long long int result_3 = { 0, 6 };
+  vector unsigned long long int result_4 = { 0, 18 };
+
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 14), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 8), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 28), result_4))
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvextduhvrx\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extracth-be-2.c b/gcc/testsuite/gcc.target/powerpc/vec-extracth-be-2.c
new file mode 100644
index 00000000000..cb2b1c84127
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extracth-be-2.c
@@ -0,0 +1,30 @@ 
+/* { dg-options "-mdejagnu-cpu=future -mbig-endian" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned int source_a = { 0, 4, 8, 12 };
+  vector unsigned int source_b = { 16, 20, 24, 28 };
+
+  vector unsigned long long int result_1 = { 0, 16 };
+  vector unsigned long long int result_2 = { 0, 12 };
+  vector unsigned long long int result_3 = { 0, 4 };
+  vector unsigned long long int result_4 = { 0, 16 };
+
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 12), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 8), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 28), result_4))
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvextduwvrx\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extracth-be-3.c b/gcc/testsuite/gcc.target/powerpc/vec-extracth-be-3.c
new file mode 100644
index 00000000000..292c8fea571
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extracth-be-3.c
@@ -0,0 +1,30 @@ 
+/* { dg-options "-mdejagnu-cpu=future -mbig-endian" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned long long source_a = { 0, 14 };
+  vector unsigned long long source_b = { 16, 30 };
+
+  vector unsigned long long int result_1 = { 0, 16 };
+  vector unsigned long long int result_2 = { 0, 14 };
+  vector unsigned long long int result_3 = { 0, 0 };
+  vector unsigned long long int result_4 = { 0, 30 };
+
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 8), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 8), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extracth (source_b, source_a, 16), result_4))
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvextddvrx\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extractl-0.c b/gcc/testsuite/gcc.target/powerpc/vec-extractl-0.c
new file mode 100644
index 00000000000..7cbd79ca384
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extractl-0.c
@@ -0,0 +1,33 @@ 
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned char source_a = {
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+  vector unsigned char source_b = {
+    16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
+
+  vector unsigned long long int result_1 = { 0, 15 };
+  vector unsigned long long int result_2 = { 0, 16 };
+  vector unsigned long long int result_3 = { 0, 20 };
+  vector unsigned long long int result_4 = { 0, 8 };
+
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 15), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 4), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 24), result_4))
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvextdubvrx\M} { target le } } } */
+/* { dg-final { scan-assembler {\mvextdubvlx\M} { target be } } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extractl-1.c b/gcc/testsuite/gcc.target/powerpc/vec-extractl-1.c
new file mode 100644
index 00000000000..3a8329abea6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extractl-1.c
@@ -0,0 +1,32 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target powerpc_future_hw } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned char source_a = {
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+  vector unsigned char source_b = {
+    16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
+
+  vector unsigned long long int result_1 = { 0, 15 };
+  vector unsigned long long int result_2 = { 0, 16 };
+  vector unsigned long long int result_3 = { 0, 20 };
+  vector unsigned long long int result_4 = { 0, 8 };
+
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 15), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 4), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 24), result_4))
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extractl-2.c b/gcc/testsuite/gcc.target/powerpc/vec-extractl-2.c
new file mode 100644
index 00000000000..3912b9427bc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extractl-2.c
@@ -0,0 +1,31 @@ 
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned short source_a = { 0, 2, 4, 6, 8, 10, 12, 14 };
+  vector unsigned short source_b = { 16, 18, 20, 22, 24, 26, 28, 30 };
+
+  vector unsigned long long int result_1 = { 0, 14 };
+  vector unsigned long long int result_2 = { 0, 16 };
+  vector unsigned long long int result_3 = { 0, 24 };
+  vector unsigned long long int result_4 = { 0, 12 };
+
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 14), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 8), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 28), result_4))
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvextduhvrx\M} { target le } } } */
+/* { dg-final { scan-assembler {\mvextduhvlx\M} { target be } } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extractl-3.c b/gcc/testsuite/gcc.target/powerpc/vec-extractl-3.c
new file mode 100644
index 00000000000..fd61fdfd077
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extractl-3.c
@@ -0,0 +1,30 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target powerpc_future_hw } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned short source_a = { 0, 2, 4, 6, 8, 10, 12, 14 };
+  vector unsigned short source_b = { 16, 18, 20, 22, 24, 26, 28, 30 };
+
+  vector unsigned long long int result_1 = { 0, 14 };
+  vector unsigned long long int result_2 = { 0, 16 };
+  vector unsigned long long int result_3 = { 0, 24 };
+  vector unsigned long long int result_4 = { 0, 12 };
+
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 14), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 8), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 28), result_4))
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extractl-4.c b/gcc/testsuite/gcc.target/powerpc/vec-extractl-4.c
new file mode 100644
index 00000000000..df06570449b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extractl-4.c
@@ -0,0 +1,31 @@ 
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned int source_a = { 0, 4, 8, 12 };
+  vector unsigned int source_b = { 16, 20, 24, 28 };
+
+  vector unsigned long long int result_1 = { 0, 12 };
+  vector unsigned long long int result_2 = { 0, 16 };
+  vector unsigned long long int result_3 = { 0, 24 };
+  vector unsigned long long int result_4 = { 0, 4 };
+
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 12), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 8), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 20), result_4))
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvextduwvrx\M} { target le } } } */
+/* { dg-final { scan-assembler {\mvextduwvlx\M} { target be } } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extractl-5.c b/gcc/testsuite/gcc.target/powerpc/vec-extractl-5.c
new file mode 100644
index 00000000000..dc9b9cce8e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extractl-5.c
@@ -0,0 +1,29 @@ 
+/* { dg-require-effective-target powerpc_future_hw } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned int source_a = { 0, 4, 8, 12 };
+  vector unsigned int source_b = { 16, 20, 24, 28 };
+
+  vector unsigned long long int result_1 = { 0, 12 };
+  vector unsigned long long int result_2 = { 0, 16 };
+  vector unsigned long long int result_3 = { 0, 24 };
+  vector unsigned long long int result_4 = { 0, 4 };
+
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 12), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 8), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 20), result_4))
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extractl-6.c b/gcc/testsuite/gcc.target/powerpc/vec-extractl-6.c
new file mode 100644
index 00000000000..925073b874c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extractl-6.c
@@ -0,0 +1,31 @@ 
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned long long source_a = { 0, 14 };
+  vector unsigned long long source_b = { 16, 30 };
+
+  vector unsigned long long int result_1 = { 0, 14 };
+  vector unsigned long long int result_2 = { 0, 16 };
+  vector unsigned long long int result_3 = { 0, 30 };
+  vector unsigned long long int result_4 = { 0, 0 };
+
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 8), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 8), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 16), result_4))
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvextddvrx\M} { target le } } } */
+/* { dg-final { scan-assembler {\mvextddvlx\M} { target be } } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extractl-7.c b/gcc/testsuite/gcc.target/powerpc/vec-extractl-7.c
new file mode 100644
index 00000000000..9d212d28e74
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extractl-7.c
@@ -0,0 +1,30 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target powerpc_future_hw } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned long long source_a = { 0, 14 };
+  vector unsigned long long source_b = { 16, 30 };
+
+  vector unsigned long long int result_1 = { 0, 14 };
+  vector unsigned long long int result_2 = { 0, 16 };
+  vector unsigned long long int result_3 = { 0, 30 };
+  vector unsigned long long int result_4 = { 0, 0 };
+
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 8), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 8), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 16), result_4))
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extractl-be-0.c b/gcc/testsuite/gcc.target/powerpc/vec-extractl-be-0.c
new file mode 100644
index 00000000000..743d90a382f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extractl-be-0.c
@@ -0,0 +1,32 @@ 
+/* { dg-options "-mdejagnu-cpu=future -mbig-endian" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned char source_a = {
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+  vector unsigned char source_b = {
+    16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
+
+  vector unsigned long long int result_1 = { 0, 15 };
+  vector unsigned long long int result_2 = { 0, 16 };
+  vector unsigned long long int result_3 = { 0, 20 };
+  vector unsigned long long int result_4 = { 0, 8 };
+
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 15), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 4), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 24), result_4))
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvextdubvlx\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extractl-be-1.c b/gcc/testsuite/gcc.target/powerpc/vec-extractl-be-1.c
new file mode 100644
index 00000000000..0dd223b7920
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extractl-be-1.c
@@ -0,0 +1,30 @@ 
+/* { dg-options "-mdejagnu-cpu=future -mbig-endian" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned short source_a = { 0, 2, 4, 6, 8, 10, 12, 14 };
+  vector unsigned short source_b = { 16, 18, 20, 22, 24, 26, 28, 30 };
+
+  vector unsigned long long int result_1 = { 0, 14 };
+  vector unsigned long long int result_2 = { 0, 16 };
+  vector unsigned long long int result_3 = { 0, 24 };
+  vector unsigned long long int result_4 = { 0, 12 };
+
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 14), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 8), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 28), result_4))
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvextduhvlx\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extractl-be-2.c b/gcc/testsuite/gcc.target/powerpc/vec-extractl-be-2.c
new file mode 100644
index 00000000000..d9d4396e5d9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extractl-be-2.c
@@ -0,0 +1,30 @@ 
+/* { dg-options "-mdejagnu-cpu=future -mbig-endian" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned int source_a = { 0, 4, 8, 12 };
+  vector unsigned int source_b = { 16, 20, 24, 28 };
+
+  vector unsigned long long int result_1 = { 0, 12 };
+  vector unsigned long long int result_2 = { 0, 16 };
+  vector unsigned long long int result_3 = { 0, 24 };
+  vector unsigned long long int result_4 = { 0, 4 };
+
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 12), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 8), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 20), result_4))
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvextduwvlx\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extractl-be-3.c b/gcc/testsuite/gcc.target/powerpc/vec-extractl-be-3.c
new file mode 100644
index 00000000000..95f9ddda747
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extractl-be-3.c
@@ -0,0 +1,30 @@ 
+/* { dg-options "-mdejagnu-cpu=future -mbig-endian" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+int
+main (int argc, char *argv [])
+{
+  vector unsigned long long source_a = { 0, 14 };
+  vector unsigned long long source_b = { 16, 30 };
+
+  vector unsigned long long int result_1 = { 0, 14 };
+  vector unsigned long long int result_2 = { 0, 16 };
+  vector unsigned long long int result_3 = { 0, 30 };
+  vector unsigned long long int result_4 = { 0, 0 };
+
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 8), result_1))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_a, source_b, 16), result_2))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 8), result_3))
+    abort ();
+  if (!vec_all_eq (vec_extractl (source_b, source_a, 16), result_4))
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvextddvlx\M} } } */