[rs6000] PR87532: Bad Results from vec_extract(unsigned char, foo) dependent upon function inline

Message ID c6da7343-92a2-d73d-d736-f8e952377b33@linux.ibm.com
State New
Headers show
Series
  • [rs6000] PR87532: Bad Results from vec_extract(unsigned char, foo) dependent upon function inline
Related show

Commit Message

Kelvin Nilsen March 8, 2019, 4:59 p.m.
This problem report, though initially motivated by differences in behavior between constant and non-constant selector arguments, uncovered a number of inconsistencies in the implementation of vec_extract.

This patch provides several fixes to make handling of constant selector expressions the same as the handling of non-constant selector expressions.  In the process of testing, it was observed that certain existing regression tests were looking for the wrong instructions to be emitted and those tests have been updated.

This has bootstrapped and tested without regressions on powerpc64le-unknown-linux (both P8 and P9) and on powerpc-linux (P7 big-endian, with both -m32 and -m64 target options).

Is this ok for trunk?

gcc/ChangeLog:

2019-03-08  Kelvin Nilsen  <kelvin@gcc.gnu.org>

	PR target/87532
	* config/rs6000/rs6000-c.c (altivec_resolve_overloaded_builtin):
	When handling vec-extract, use modular arithmetic to allow
	constant selectors greater than vector length.
	* config/rs6000/rs6000.c (rs6000_expand_vector_extract): Allow
	V1TImode vectors to have constant selector values greater than 0.
	Use modular arithmetic to compute vector index.
	(rs6000_split_vec_extract_var): Use modular arithmetic to compute
	index for in-memory vectors.  Correct code generation for
	in-register vectors.
	(altivec_expand_vec_ext_builtin): Use modular arithmetic to
	compute index.

gcc/testsuite/ChangeLog:

2019-03-08  Kelvin Nilsen  <kelvin@gcc.gnu.org>

	PR target/87532
	* gcc.target/powerpc/vsx-builtin-10a.c: New test.
	* gcc.target/powerpc/vsx-builtin-20a.c: New test.
	* gcc.target/powerpc/vsx-builtin-11b.c: New test.
	* gcc.target/powerpc/vsx-builtin-9b.c: New test.
	* gcc.target/powerpc/vsx-builtin-12a.c: New test.
	* gcc.target/powerpc/vsx-builtin-13b.c: New test.
	* gcc.target/powerpc/vsx-builtin-14a.c: New test.
	* gcc.target/powerpc/vec-extract-v16qiu-v2a.c: New test.
	* gcc.target/powerpc/vsx-builtin-15b.c: New test.
	* gcc.target/powerpc/vsx-builtin-16a.c: New test.
	* gcc.target/powerpc/vsx-builtin-17b.c: New test.
	* gcc.target/powerpc/vsx-builtin-18a.c: New test.
	* gcc.target/powerpc/pr87532-mc.c: New test.
	* gcc.target/powerpc/vsx-builtin-19b.c: New test.
	* gcc.target/powerpc/vsx-builtin-10b.c: New test.
	* gcc.target/powerpc/vsx-builtin-11a.c: New test.
	* gcc.target/powerpc/vsx-builtin-9a.c: New test.
	* gcc.target/powerpc/vsx-builtin-20b.c: New test.
	* gcc.target/powerpc/vsx-builtin-12b.c: New test.
	* gcc.target/powerpc/vsx-builtin-13a.c: New test.
	* gcc.target/powerpc/vsx-builtin-14b.c: New test.
	* gcc.target/powerpc/vsx-builtin-15a.c: New test.
	* gcc.target/powerpc/vec-extract-v16qiu-v2b.c: New test.
	* gcc.target/powerpc/pr87532.c: New test.
	* gcc.target/powerpc/vsx-builtin-16b.c: New test.
	* gcc.target/powerpc/vec-extract-v16qiu-v2.h: New test.
	* gcc.target/powerpc/vsx-builtin-17a.c: New test.
	* gcc.target/powerpc/vsx-builtin-18b.c: New test.
	* gcc.target/powerpc/vsx-builtin-19a.c: New test.
	* gcc.target/powerpc/fold-vec-extract-char.p8.c: Modify expected
	instruction selection.
	* gcc.target/powerpc/fold-vec-extract-short.p8.c: Likewise.
	* gcc.target/powerpc/fold-vec-extract-int.p8.c: Likewise.

Comments

Segher Boessenkool March 8, 2019, 6:47 p.m. | #1
Hi Kelvin,

On Fri, Mar 08, 2019 at 10:59:35AM -0600, Kelvin Nilsen wrote:
> This problem report, though initially motivated by differences in behavior between constant and non-constant selector arguments, uncovered a number of inconsistencies in the implementation of vec_extract.

> 

> This patch provides several fixes to make handling of constant selector expressions the same as the handling of non-constant selector expressions.  In the process of testing, it was observed that certain existing regression tests were looking for the wrong instructions to be emitted and those tests have been updated.

> 

> This has bootstrapped and tested without regressions on powerpc64le-unknown-linux (both P8 and P9) and on powerpc-linux (P7 big-endian, with both -m32 and -m64 target options).


Thanks for the patch.  I have lots of comments/questions, mostly about the
testcases.  Sorry :-/  The actual compiler code part looks good though.


> --- gcc/testsuite/gcc.target/powerpc/vsx-builtin-10a.c	(revision 0)

> +++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-10a.c	(revision 0)

> @@ -0,0 +1,157 @@

> +/* { dg-do run { target { powerpc*-*-* } } } */

> +/* { dg-skip-if "" { powerpc*-*-darwin* } } */


Is there any reason to think this testcase will fail on Darwin?  I mean, it
requires VSX, and that should skip the testcase already on Darwin?

> +/* { dg-require-effective-target dfp_hw } */


Why is that?  I don't see any dfp used here?

> +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */


You do not use -mcpu=, so why this dg-skip-if?  And please set
-mdejagnu-cpu= instead.

> --- gcc/testsuite/gcc.target/powerpc/fold-vec-extract-char.p8.c	(revision 269370)

> +++ gcc/testsuite/gcc.target/powerpc/fold-vec-extract-char.p8.c	(working copy)

> @@ -18,7 +18,7 @@

>  /* { dg-final { scan-assembler-times {\mxxpermdi\M} 3 { target lp64 } } } */

>  /* { dg-final { scan-assembler-times {\mvslo\M} 3 { target lp64 } } } */

>  /* { dg-final { scan-assembler-times {\mmfvsrd\M} 6 { target lp64 } } } */

> -/* { dg-final { scan-assembler-times {\msradi\M} 3 { target lp64 } } } */

> +/* { dg-final { scan-assembler-times {\msrdi\M} 3 { target lp64 } } } */


Maybe allow both?  So {\msra?di\M}?  Or does sradi make no sense here?

> --- gcc/testsuite/gcc.target/powerpc/vsx-builtin-14a.c	(revision 0)

> +++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-14a.c	(revision 0)

> @@ -0,0 +1,128 @@

> +/* { dg-do run { target { powerpc*-*-* } } } */

> +/* { dg-skip-if "" { powerpc*-*-darwin* } } */

> +/* { dg-require-effective-target dfp_hw } */

> +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */

> +/* { dg-options "-maltivec" } */

> +

> +/* This test should run the same on any target that supports altivec/dfp

> +   instructions.  Intentionally not specifying cpu in order to test

> +   all code generation paths.  */


I don't see where dfp comes in?  For server CPUs it is p6 and up, the same
as AltiVec, but that is coincidental.

> --- gcc/testsuite/gcc.target/powerpc/pr87532-mc.c	(revision 0)

> +++ gcc/testsuite/gcc.target/powerpc/pr87532-mc.c	(revision 0)

> @@ -0,0 +1,260 @@

> +/* { dg-do run { target { powerpc*-*-* && lp64 } } } */


Check for int128, instead?  Or is there another reason to want lp64?

> +  __asm__ (" # %x0" : "+wa" (a));


"wa" requires VSX.

> --- gcc/testsuite/gcc.target/powerpc/vsx-builtin-14b.c	(revision 0)

> +++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-14b.c	(revision 0)

> @@ -0,0 +1,128 @@

> +/* { dg-do run { target { powerpc*-*-* } } } */


Btw, you can just say { dg-do run }: everything in gcc.target/powerpc is
only run for powerpc*-*-* targets.

> --- gcc/testsuite/gcc.target/powerpc/vec-extract-v16qiu-v2b.c	(revision 0)

> +++ gcc/testsuite/gcc.target/powerpc/vec-extract-v16qiu-v2b.c	(revision 0)

> @@ -0,0 +1,16 @@

> +/* { dg-do run { target { powerpc*-*-linux* } } } */

> +/* { dg-skip-if "" { powerpc*-*-darwin* } } */

> +/* { dg-require-effective-target vsx_hw } */

> +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */

> +/* { dg-options "-O2 -mvsx -save-temps -dp -g" } */


I think that is debugging code left over?  -dp -g should be harmless, but
-save-temps is littering ;-)

> --- gcc/testsuite/gcc.target/powerpc/vec-extract-v16qiu-v2.h	(revision 0)

> +++ gcc/testsuite/gcc.target/powerpc/vec-extract-v16qiu-v2.h	(revision 0)


> +static vector TYPE

> +deoptimize (vector TYPE a)

> +{

> +  __asm__ (" # %x0" : "+wa" (a));

> +  return a;

> +}


Is this only ever compiled with VSX?  If not, use "v" instead?

> --- gcc/config/rs6000/rs6000-c.c	(revision 269370)

> +++ gcc/config/rs6000/rs6000-c.c	(working copy)

> @@ -6568,9 +6568,15 @@

>  	  /* If the second argument is an integer constant, if the value is in

>  	     the expected range, generate the built-in code if we can.  We need

>  	     64-bit and direct move to extract the small integer vectors.  */

> -	  if (TREE_CODE (arg2) == INTEGER_CST

> -	      && wi::ltu_p (wi::to_wide (arg2), nunits))

> +

> +	  if (TREE_CODE (arg2) == INTEGER_CST)

>  	    {

> +	      if (!wi::ltu_p (wi::to_wide (arg2), nunits))

> +		{

> +		  wide_int selector = wi::to_wide (arg2);

> +		  selector = wi::umod_trunc (selector, nunits);

> +		  arg2 = wide_int_to_tree (TREE_TYPE (arg2), selector);

> +		}


You can just always do this, no need for the condition?  Makes it easier
to read.

> --- gcc/config/rs6000/rs6000.c	(revision 269370)

> +++ gcc/config/rs6000/rs6000.c	(working copy)

> @@ -6894,7 +6894,6 @@

>  	default:

>  	  break;

>  	case E_V1TImode:

> -	  gcc_assert (INTVAL (elt) == 0 && inner_mode == TImode);


You could leave the inner_mode part?  Or is the assert here pretty
useless anyway?

> @@ -7173,7 +7190,9 @@

>  

>    else if (REG_P (src) || SUBREG_P (src))

>      {

> -      int bit_shift = byte_shift + 3;

> +      int num_elements = GET_MODE_NUNITS (mode);

> +      int bits_in_element = 128 / num_elements;


Use GET_MODE_INNER?  Or will that not help here.

> @@ -14724,8 +14743,18 @@

>    op1 = expand_normal (arg1);

>  

>    /* Call get_element_number to validate arg1 if it is a constant.  */

> +

>    if (TREE_CODE (arg1) == INTEGER_CST)

> -    (void) get_element_number (TREE_TYPE (arg0), arg1);

> +    {

> +      unsigned HOST_WIDE_INT elt;

> +      unsigned HOST_WIDE_INT size = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));

> +      unsigned int truncated_selector;

> +      if (!tree_fits_uhwi_p (arg1))

> +	error ("selector must fit in HOST_WIDE_INT");


"error" is a user-visible error, and HOST_WIDE_INT is not something a user
knows.


Segher

Patch

Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-10a.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-10a.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-10a.c	(revision 0)
@@ -0,0 +1,157 @@ 
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target dfp_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-maltivec" } */
+
+/* This test should run the same on any target that supports altivec/dfp
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define CONST0		(0)
+#define CONST1		(1)
+#define CONST2		(2)
+#define CONST3		(3)
+#define CONST4		(4)
+#define CONST5		(5)
+#define CONST6		(6)
+#define CONST7		(7)
+
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+short s3 (vector short v)
+{
+  return __builtin_vec_ext_v8hi (v, 3);
+}
+
+short s7 (vector short v)
+{
+  return __builtin_vec_ext_v8hi (v, 7);
+}
+
+short s21 (vector short v)
+{
+  return __builtin_vec_ext_v8hi (v, 21);
+}
+
+short s30 (vector short v)
+{
+  return __builtin_vec_ext_v8hi (v, 30);
+}
+
+/* Test for vector residing in memory.  */
+short ms3 (vector short *vp)
+{
+  return __builtin_vec_ext_v8hi (*vp, 3);
+}
+
+short ms7 (vector short *vp)
+{
+  return __builtin_vec_ext_v8hi (*vp, 7);
+}
+
+short ms21 (vector short *vp)
+{
+  return __builtin_vec_ext_v8hi (*vp, 21);
+}
+
+short ms30 (vector short *vp)
+{
+  return __builtin_vec_ext_v8hi (*vp, 30);
+}
+
+/* Test the same with variable indices.  */
+
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+short ci (vector short v, int i)
+{
+  return __builtin_vec_ext_v8hi (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+__attribute__((noinline))
+short mci (vector short *vp, int i)
+{
+  return __builtin_vec_ext_v8hi (*vp, i);
+}
+
+
+int main (int argc, short *argv[]) {
+  vector short sv = {
+    CONST0, CONST1, CONST2, CONST3, CONST4, CONST5, CONST6, CONST7 };
+  short s;
+
+  s = s3 (sv);
+  if (s != CONST3)
+    abort ();
+
+  s = s7 (sv);
+  if (s != CONST7)
+    abort ();
+
+  s = s21 (sv);
+  if (s != CONST5)
+    abort ();
+
+  s = s30 (sv);
+  if (s != CONST6)
+    abort ();
+
+  s = ms3 (&sv);
+  if (s != CONST3)
+    abort ();
+
+  s = ms7 (&sv);
+  if (s != CONST7)
+    abort ();
+
+  s = ms21 (&sv);
+  if (s != CONST5)
+    abort ();
+
+  s = ms30 (&sv);
+  if (s != CONST6)
+    abort ();
+
+  s = ci (sv, 5);
+  if (s != CONST5)
+    abort ();
+
+  s = ci (sv, 2);
+  if (s != CONST2)
+    abort ();
+
+  s = ci (sv, 15);
+  if (s != CONST7)
+    abort ();
+
+  s = ci (sv, 28);
+  if (s != CONST4)
+    abort ();
+
+  s = mci (&sv, 5);
+  if (s != CONST5)
+    abort ();
+
+  s = mci (&sv, 12);
+  if (s != CONST4)
+    abort ();
+
+  s = mci (&sv, 25);
+  if (s != CONST1)
+    abort ();
+
+  s = mci (&sv, 16);
+  if (s != CONST0)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-20a.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-20a.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-20a.c	(revision 0)
@@ -0,0 +1,117 @@ 
+/* { dg-do run { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-mvsx" } */
+
+/* This test should run the same on any target that supports vsx
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+/* Define this after PR89424 is addressed.  */
+#undef PR89424
+
+extern void abort (void);
+
+#define CONST0		(((unsigned __int128) 31415926539) << 60)
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+unsigned __int128 e0 (vector unsigned __int128 v)
+{
+  return __builtin_vec_extract (v, 0);
+}
+
+unsigned __int128 e3 (vector unsigned __int128 v)
+{
+  return __builtin_vec_extract (v, 3);
+}
+
+/* Test for vector residing in memory.  */
+unsigned __int128 me0 (vector unsigned __int128 *vp)
+{
+  return __builtin_vec_extract (*vp, 0);
+}
+
+unsigned __int128 me3 (vector unsigned __int128 *vp)
+{
+  return __builtin_vec_extract (*vp, 3);
+}
+
+/* Test the same with variable indices.  */
+
+#ifdef PR89424
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+unsigned __int128 ei (vector unsigned __int128 v, int i)
+{
+  return __builtin_vec_extract (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+unsigned __int128 mei (vector unsigned __int128 *vp, int i)
+{
+  return __builtin_vec_extract (*vp, i);
+}
+#endif
+
+int main (int argc, char *argv[]) {
+  vector unsigned __int128 dv = { CONST0 };
+  unsigned __int128 d;
+
+  d = e0 (dv);
+  if (d != CONST0)
+    abort ();
+
+  d = e3 (dv);
+  if (d != CONST0)
+    abort ();
+
+  d = me0 (&dv);
+  if (d != CONST0)
+    abort ();
+
+  d = me3 (&dv);
+  if (d != CONST0)
+    abort ();
+
+#ifdef PR89424
+  d = ei (dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 1);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 2);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 3);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 1);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 2);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 3);
+  if (d != CONST0)
+    abort ();
+#endif
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-11b.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-11b.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-11b.c	(revision 0)
@@ -0,0 +1,151 @@ 
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target dfp_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-maltivec -O3" } */
+
+/* This test should run the same on any target that supports altivec/dfp
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define CONST0		(0)
+#define CONST1		(1)
+#define CONST2		(2)
+#define CONST3		(3)
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+int s3 (vector int v)
+{
+  return __builtin_vec_ext_v4si (v, 3);
+}
+
+int s1 (vector int v)
+{
+  return __builtin_vec_ext_v4si (v, 1);
+}
+
+int s21 (vector int v)
+{
+  return __builtin_vec_ext_v4si (v, 21);
+}
+
+int s30 (vector int v)
+{
+  return __builtin_vec_ext_v4si (v, 30);
+}
+
+/* Test for vector residing in memory.  */
+int ms3 (vector int *vp)
+{
+  return __builtin_vec_ext_v4si (*vp, 3);
+}
+
+int ms1(vector int *vp)
+{
+  return __builtin_vec_ext_v4si (*vp, 1);
+}
+
+int ms21(vector int *vp)
+{
+  return __builtin_vec_ext_v4si (*vp, 21);
+}
+
+int ms30(vector int *vp)
+{
+  return __builtin_vec_ext_v4si (*vp, 30);
+}
+
+/* Test the same with variable indices.  */
+
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+int ci (vector int v, int i)
+{
+  return __builtin_vec_ext_v4si (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+__attribute__((noinline))
+int mci(vector int *vp, int i)
+{
+  return __builtin_vec_ext_v4si (*vp, i);
+}
+
+
+int main (int argc, int *argv[]) {
+  vector int sv = { CONST0, CONST1, CONST2, CONST3 };
+  int s;
+
+  s = s3 (sv);
+  if (s != CONST3)
+    abort ();
+
+  s = s1 (sv);
+  if (s != CONST1)
+    abort ();
+
+  s = s21 (sv);
+  if (s != CONST1)
+    abort ();
+
+  s = s30 (sv);
+  if (s != CONST2)
+    abort ();
+
+  s = ms3 (&sv);
+  if (s != CONST3)
+    abort ();
+
+  s = ms1 (&sv);
+  if (s != CONST1)
+    abort ();
+
+  s = ms21 (&sv);
+  if (s != CONST1)
+    abort ();
+
+  s = ms30 (&sv);
+  if (s != CONST2)
+    abort ();
+
+  s = ci (sv, 5);
+  if (s != CONST1)
+    abort ();
+
+  s = ci (sv, 2);
+  if (s != CONST2)
+    abort ();
+
+  s = ci (sv, 15);
+  if (s != CONST3)
+    abort ();
+
+  s = ci (sv, 28);
+  if (s != CONST0)
+    abort ();
+
+  s = mci (&sv, 5);
+  if (s != CONST1)
+    abort ();
+
+  s = mci (&sv, 12);
+  if (s != CONST0)
+    abort ();
+
+  s = mci (&sv, 25);
+  if (s != CONST1)
+    abort ();
+
+  s = mci (&sv, 16);
+  if (s != CONST0)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-9b.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-9b.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-9b.c	(revision 0)
@@ -0,0 +1,166 @@ 
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target dfp_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-maltivec -O3" } */
+
+/* This test should run the same on any target that supports altivec/dfp
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define CONST0		(0)
+#define CONST1		(1)
+#define CONST2		(2)
+#define CONST3		(3)
+#define CONST4		(4)
+#define CONST5		(5)
+#define CONST6		(6)
+#define CONST7		(7)
+#define CONST8		(8)
+#define CONST9		(9)
+#define CONSTA		(10)
+#define CONSTB		(11)
+#define CONSTC		(12)
+#define CONSTD		(13)
+#define CONSTE		(14)
+#define CONSTF		(15)
+
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+signed char c0 (vector signed char v)
+{
+  return __builtin_vec_ext_v16qi (v, 0);
+}
+
+signed char c9 (vector signed char v)
+{
+  return __builtin_vec_ext_v16qi (v, 9);
+}
+
+signed char c21 (vector signed char v)
+{
+  return __builtin_vec_ext_v16qi (v, 21);
+}
+
+signed char c30 (vector signed char v)
+{
+  return __builtin_vec_ext_v16qi (v, 30);
+}
+
+/* Test for vector residing in memory.  */
+signed char mc0 (vector signed char *vp)
+{
+  return __builtin_vec_ext_v16qi (*vp, 0);
+}
+
+signed char mc9 (vector signed char *vp)
+{
+  return __builtin_vec_ext_v16qi (*vp, 9);
+}
+
+signed char mc21 (vector signed char *vp)
+{
+  return __builtin_vec_ext_v16qi (*vp, 21);
+}
+
+signed char mc30 (vector signed char *vp)
+{
+  return __builtin_vec_ext_v16qi (*vp, 30);
+}
+
+/* Test the same with variable indices.  */
+
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+signed char ci (vector signed char v, int i)
+{
+  return __builtin_vec_ext_v16qi (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+__attribute__((noinline))
+signed char mci(vector signed char *vp, int i) {
+  return __builtin_vec_ext_v16qi (*vp, i);
+}
+
+
+int main (int argc, char *argv[]) {
+  vector signed char cv = { CONST0, CONST1, CONST2, CONST3,
+			    CONST4, CONST5, CONST6, CONST7,
+			    CONST8, CONST9, CONSTA, CONSTB,
+			    CONSTC, CONSTD, CONSTE, CONSTF };
+  signed char c;
+
+  c = c0 (cv);
+  if (c != CONST0)
+    abort ();
+
+  c = c9 (cv);
+  if (c != CONST9)
+    abort ();
+
+  c = c21 (cv);
+  if (c != CONST5)
+    abort ();
+
+  c = c30 (cv);
+  if (c != CONSTE)
+    abort ();
+
+  c = mc0 (&cv);
+  if (c != CONST0)
+    abort ();
+
+  c = mc9 (&cv);
+  if (c != CONST9)
+    abort ();
+
+  c = mc21 (&cv);
+  if (c != CONST5)
+    abort ();
+
+  c = mc30 (&cv);
+  if (c != CONSTE)
+    abort ();
+
+  c = ci (cv, 8);
+  if (c != CONST8)
+    abort ();
+
+  c = ci (cv, 13);
+  if (c != CONSTD)
+    abort ();
+
+  c = ci (cv, 23);
+  if (c != CONST7)
+    abort ();
+
+  c = ci (cv, 31);
+  if (c != CONSTF)
+    abort ();
+
+  c = mci (&cv, 5);
+  if (c != CONST5)
+    abort ();
+
+  c = mci (&cv, 12);
+  if (c != CONSTC)
+    abort ();
+
+  c = mci (&cv, 25);
+  if (c != CONST9)
+    abort ();
+
+  c = mci (&cv, 16);
+  if (c != CONST0)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-12a.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-12a.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-12a.c	(revision 0)
@@ -0,0 +1,111 @@ 
+/* { dg-do run { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-mvsx" } */
+
+/* This test should run the same on any target that supports vsx
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define CONST0		(31415926539LL)
+#define CONST1		(2 * 31415926539LL)
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+long long int e0 (vector long long int v)
+{
+  return __builtin_vec_ext_v2di (v, 0);
+}
+
+long long int e3 (vector long long int v)
+{
+  return __builtin_vec_ext_v2di (v, 3);
+}
+
+/* Test for vector residing in memory.  */
+long long int me0 (vector long long int *vp)
+{
+  return __builtin_vec_ext_v2di (*vp, 0);
+}
+
+long long int me3 (vector long long int *vp)
+{
+  return __builtin_vec_ext_v2di (*vp, 3);
+}
+
+/* Test the same with variable indices.  */
+
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+long long int ei (vector long long int v, int i)
+{
+  return __builtin_vec_ext_v2di (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+long long int mei (vector long long int *vp, int i)
+{
+  return __builtin_vec_ext_v2di (*vp, i);
+}
+
+int main (int argc, char *argv[]) {
+  vector long long int dv = { CONST0, CONST1 };
+  long long int d;
+
+  d = e0 (dv);
+  if (d != CONST0)
+    abort ();
+
+  d = e3 (dv);
+  if (d != CONST1)
+    abort ();
+
+  d = me0 (&dv);
+  if (d != CONST0)
+    abort ();
+
+  d = me3 (&dv);
+  if (d != CONST1)
+    abort ();
+
+  d = ei (dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 1);
+  if (d != CONST1)
+    abort ();
+
+  d = ei (dv, 2);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 3);
+  if (d != CONST1)
+    abort ();
+
+  d = mei (&dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 1);
+  if (d != CONST1)
+    abort ();
+
+  d = mei (&dv, 2);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 3);
+  if (d != CONST1)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/fold-vec-extract-char.p8.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/fold-vec-extract-char.p8.c	(revision 269370)
+++ gcc/testsuite/gcc.target/powerpc/fold-vec-extract-char.p8.c	(working copy)
@@ -18,7 +18,7 @@ 
 /* { dg-final { scan-assembler-times {\mxxpermdi\M} 3 { target lp64 } } } */
 /* { dg-final { scan-assembler-times {\mvslo\M} 3 { target lp64 } } } */
 /* { dg-final { scan-assembler-times {\mmfvsrd\M} 6 { target lp64 } } } */
-/* { dg-final { scan-assembler-times {\msradi\M} 3 { target lp64 } } } */
+/* { dg-final { scan-assembler-times {\msrdi\M} 3 { target lp64 } } } */
 /* { dg-final { scan-assembler-times "extsb" 2 } } */
 /* { dg-final { scan-assembler-times {\mvspltb\M} 3 { target lp64 } } } */
 /* { dg-final { scan-assembler-times {\mrlwinm\M} 2 { target lp64} } } */
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-13b.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-13b.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-13b.c	(revision 0)
@@ -0,0 +1,126 @@ 
+/* { dg-do run { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-mvsx -O3" } */
+
+/* This test should run the same on any target that supports vsx
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+/* Define this after PR89424 is addressed.  */
+#undef PR89424
+
+/* Define this after PR89626 is addressed.  */
+#undef PR89626
+
+#ifdef PR89626
+#define SIGNED
+#else
+#define SIGNED signed
+#endif
+
+extern void abort (void);
+
+#define CONST0		(((SIGNED __int128) 31415926539) << 60)
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+SIGNED __int128 e0 (vector SIGNED __int128 v)
+{
+  return __builtin_vec_ext_v1ti (v, 0);
+}
+
+SIGNED __int128 e3 (vector SIGNED __int128 v)
+{
+  return __builtin_vec_ext_v1ti (v, 3);
+}
+
+/* Test for vector residing in memory.  */
+SIGNED __int128 me0 (vector SIGNED __int128 *vp)
+{
+  return __builtin_vec_ext_v1ti (*vp, 0);
+}
+
+SIGNED __int128 me3 (vector SIGNED __int128 *vp)
+{
+  return __builtin_vec_ext_v1ti (*vp, 3);
+}
+
+/* Test the same with variable indices.  */
+
+#ifdef PR89424
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+SIGNED __int128 ei (vector SIGNED __int128 v, int i)
+{
+  return __builtin_vec_ext_v1ti (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+SIGNED __int128 mei (vector SIGNED __int128 *vp, int i)
+{
+  return __builtin_vec_ext_v1ti (*vp, i);
+}
+#endif
+
+int main (int argc, char *argv[]) {
+  vector SIGNED __int128 dv = { CONST0 };
+  SIGNED __int128 d;
+
+  d = e0 (dv);
+  if (d != CONST0)
+    abort ();
+
+  d = e3 (dv);
+  if (d != CONST0)
+    abort ();
+
+  d = me0 (&dv);
+  if (d != CONST0)
+    abort ();
+
+  d = me3 (&dv);
+  if (d != CONST0)
+    abort ();
+
+#ifdef PR89424
+  d = ei (dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 1);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 2);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 3);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 1);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 2);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 3);
+  if (d != CONST0)
+    abort ();
+#endif
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-14a.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-14a.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-14a.c	(revision 0)
@@ -0,0 +1,128 @@ 
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target dfp_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-maltivec" } */
+
+/* This test should run the same on any target that supports altivec/dfp
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define CONST0		((float) (3.1415926539))
+#define CONST1		((float) (3.1415926539 * 2))
+#define CONST2		((float) (3.1415926539 * 3))
+#define CONST3		((float) (3.1415926539 * 4))
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+float e0(vector float v){ return __builtin_vec_ext_v4sf (v, 0); }
+float e1(vector float v){ return __builtin_vec_ext_v4sf (v, 1); }
+float e7(vector float v){ return __builtin_vec_ext_v4sf (v, 7); }
+float e8(vector float v){ return __builtin_vec_ext_v4sf (v, 8); }
+
+/* Test for vector residing in memory.  */
+float me0(vector float *vp){ return __builtin_vec_ext_v4sf (*vp, 0); }
+float me1(vector float *vp){ return __builtin_vec_ext_v4sf (*vp, 1); }
+
+float me13(vector float *vp)
+{
+  return __builtin_vec_ext_v4sf (*vp, 13);
+}
+
+float me15(vector float *vp)
+{
+  return __builtin_vec_ext_v4sf (*vp, 15);
+}
+
+/* Test the same with variable indices.  */
+
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+float ei(vector float v, int i)
+{
+  return __builtin_vec_ext_v4sf (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+float mei(vector float *vp, int i)
+{
+  return __builtin_vec_ext_v4sf (*vp, i);
+}
+
+
+int main (int argc, char *argv[]) {
+  vector float dv = { CONST0, CONST1, CONST2, CONST3 };
+  float d;
+
+  d = e0 (dv);
+  if (d != CONST0)
+    abort ();
+
+  d = e1 (dv);
+  if (d != CONST1)
+    abort ();
+
+  d = e7 (dv);
+  if (d != CONST3)
+    abort ();
+
+  d = e8 (dv);
+  if (d != CONST0)
+    abort ();
+
+  d = me0 (&dv);
+  if (d != CONST0)
+    abort ();
+
+  d = me1 (&dv);
+  if (d != CONST1)
+    abort ();
+
+  d = me13 (&dv);
+  if (d != CONST1)
+    abort ();
+
+  d = me15 (&dv);
+  if (d != CONST3)
+    abort ();
+
+  d = ei (dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 2);
+  if (d != CONST2)
+    abort ();
+
+  d = ei (dv, 11);
+  if (d != CONST3)
+    abort ();
+
+  d = ei (dv, 17);
+  if (d != CONST1)
+    abort ();
+
+  d = mei (&dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 1);
+  if (d != CONST1)
+    abort ();
+
+  d = mei (&dv, 15);
+  if (d != CONST3)
+    abort ();
+
+  d = mei (&dv, 6);
+  if (d != CONST2)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vec-extract-v16qiu-v2a.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vec-extract-v16qiu-v2a.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vec-extract-v16qiu-v2a.c	(revision 0)
@@ -0,0 +1,16 @@ 
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-O2 -mvsx -save-temps -dp -g" } */
+
+#define TYPE unsigned char
+/* ELEMENTS is number of elements in a vector of TYPE.  */
+#define ELEMENTS 16
+#define INITIAL \
+  {  3, 2, 3, 4, 5, 6, 7, 8, 240, 241, 242, 243, 244, 245, 246, 247 }
+
+#define DO_TRACE
+#define DISABLE_INLINE_OF_GET_AUTO_N
+
+#include "vec-extract-v16qiu-v2.h"
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-15b.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-15b.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-15b.c	(revision 0)
@@ -0,0 +1,115 @@ 
+/* { dg-do run { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-mvsx -O3" } */
+
+/* This test should run the same on any target that supports vsx
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define CONST0		(3.1415926539)
+#define CONST1		(3.1415926539 * 2)
+
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+double e0(vector double v){ return __builtin_vec_ext_v2df (v, 0); }
+double e1(vector double v){ return __builtin_vec_ext_v2df (v, 1); }
+double e2(vector double v){ return __builtin_vec_ext_v2df (v, 2); }
+double e3(vector double v){ return __builtin_vec_ext_v2df (v, 3); }
+
+/* Test for vector residing in memory.  */
+double me0(vector double *vp){ return __builtin_vec_ext_v2df (*vp, 0); }
+double me1(vector double *vp){ return __builtin_vec_ext_v2df (*vp, 1); }
+double me2(vector double *vp){ return __builtin_vec_ext_v2df (*vp, 2); }
+double me3(vector double *vp){ return __builtin_vec_ext_v2df (*vp, 3); }
+
+/* Test the same with variable indices.  */
+
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+double ei(vector double v, int i){ return __builtin_vec_ext_v2df (v, i); }
+
+/* Test for variable selector and vector residing in memory.  */
+double mei(vector double *vp, int i){ return __builtin_vec_ext_v2df (*vp, i); }
+
+
+int main (int argc, char *argv[]) {
+  vector double dv;
+  double d;
+  dv[0] = CONST0;
+  dv[1] = CONST1;
+
+  d = e0 (dv);
+  if (d != CONST0)
+    abort ();
+
+  d = e1 (dv);
+  if (d != CONST1)
+    abort ();
+
+  d = e2 (dv);
+  if (d != CONST0)
+    abort ();
+
+  d = e3 (dv);
+  if (d != CONST1)
+    abort ();
+
+  d = me0 (&dv);
+  if (d != CONST0)
+    abort ();
+
+  d = me1 (&dv);
+  if (d != CONST1)
+    abort ();
+
+  d = me2 (&dv);
+  if (d != CONST0)
+    abort ();
+
+  d = me3 (&dv);
+  if (d != CONST1)
+    abort ();
+
+  d = ei (dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 1);
+  if (d != CONST1)
+    abort ();
+
+  d = ei (dv, 2);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 3);
+  if (d != CONST1)
+    abort ();
+
+  d = mei (&dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 1);
+  if (d != CONST1)
+    abort ();
+
+  d = mei (&dv, 2);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 3);
+  if (d != CONST1)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-16a.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-16a.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-16a.c	(revision 0)
@@ -0,0 +1,167 @@ 
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target dfp_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-maltivec" } */
+
+/* This test should run the same on any target that supports altivec/dfp
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define CONST0		(0)
+#define CONST1		(1)
+#define CONST2		(2)
+#define CONST3		(3)
+#define CONST4		(4)
+#define CONST5		(5)
+#define CONST6		(6)
+#define CONST7		(7)
+#define CONST8		(8)
+#define CONST9		(9)
+#define CONSTA		(10)
+#define CONSTB		(11)
+#define CONSTC		(12)
+#define CONSTD		(13)
+#define CONSTE		(14)
+#define CONSTF		(15)
+
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+unsigned char c0 (vector unsigned char v)
+{
+  return __builtin_vec_extract (v, 0);
+}
+
+unsigned char c9 (vector unsigned char v)
+{
+  return __builtin_vec_extract (v, 9);
+}
+
+unsigned char c21 (vector unsigned char v)
+{
+  return __builtin_vec_extract (v, 21);
+}
+
+unsigned char c30 (vector unsigned char v)
+{
+  return __builtin_vec_extract (v, 30);
+}
+
+/* Test for vector residing in memory.  */
+unsigned char mc0 (vector unsigned char *vp)
+{
+  return __builtin_vec_extract (*vp, 0);
+}
+
+unsigned char mc9 (vector unsigned char *vp)
+{
+  return __builtin_vec_extract (*vp, 9);
+}
+
+unsigned char mc21 (vector unsigned char *vp)
+{
+  return __builtin_vec_extract (*vp, 21);
+}
+
+unsigned char mc30 (vector unsigned char *vp)
+{
+  return __builtin_vec_extract (*vp, 30);
+}
+
+/* Test the same with variable indices.  */
+
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+unsigned char ci (vector unsigned char v, int i)
+{
+  return __builtin_vec_extract (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+__attribute__((noinline))
+unsigned char mci (vector unsigned char *vp, int i)
+{
+  return __builtin_vec_extract (*vp, i);
+}
+
+
+int main (int argc, char *argv[]) {
+  vector unsigned char cv = { CONST0, CONST1, CONST2, CONST3,
+			    CONST4, CONST5, CONST6, CONST7,
+			    CONST8, CONST9, CONSTA, CONSTB,
+			    CONSTC, CONSTD, CONSTE, CONSTF };
+  unsigned char c;
+
+  c = c0 (cv);
+  if (c != CONST0)
+    abort ();
+
+  c = c9 (cv);
+  if (c != CONST9)
+    abort ();
+
+  c = c21 (cv);
+  if (c != CONST5)
+    abort ();
+
+  c = c30 (cv);
+  if (c != CONSTE)
+    abort ();
+
+  c = mc0 (&cv);
+  if (c != CONST0)
+    abort ();
+
+  c = mc9 (&cv);
+  if (c != CONST9)
+    abort ();
+
+  c = mc21 (&cv);
+  if (c != CONST5)
+    abort ();
+
+  c = mc30 (&cv);
+  if (c != CONSTE)
+    abort ();
+
+  c = ci (cv, 8);
+  if (c != CONST8)
+    abort ();
+
+  c = ci (cv, 13);
+  if (c != CONSTD)
+    abort ();
+
+  c = ci (cv, 23);
+  if (c != CONST7)
+    abort ();
+
+  c = ci (cv, 31);
+  if (c != CONSTF)
+    abort ();
+
+  c = mci (&cv, 5);
+  if (c != CONST5)
+    abort ();
+
+  c = mci (&cv, 12);
+  if (c != CONSTC)
+    abort ();
+
+  c = mci (&cv, 25);
+  if (c != CONST9)
+    abort ();
+
+  c = mci (&cv, 16);
+  if (c != CONST0)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-17b.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-17b.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-17b.c	(revision 0)
@@ -0,0 +1,157 @@ 
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target dfp_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-maltivec -O3" } */
+
+/* This test should run the same on any target that supports altivec/dfp
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define CONST0		(0)
+#define CONST1		(1)
+#define CONST2		(2)
+#define CONST3		(3)
+#define CONST4		(4)
+#define CONST5		(5)
+#define CONST6		(6)
+#define CONST7		(7)
+
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+unsigned short s3 (vector unsigned short v)
+{
+  return __builtin_vec_extract (v, 3);
+}
+
+unsigned short s7 (vector unsigned short v)
+{
+  return __builtin_vec_extract (v, 7);
+}
+
+unsigned short s21 (vector unsigned short v)
+{
+  return __builtin_vec_extract (v, 21);
+}
+
+unsigned short s30 (vector unsigned short v)
+{
+  return __builtin_vec_extract (v, 30);
+}
+
+/* Test for vector residing in memory.  */
+unsigned short ms3 (vector unsigned short *vp)
+{
+  return __builtin_vec_extract (*vp, 3);
+}
+
+unsigned short ms7 (vector unsigned short *vp)
+{
+  return __builtin_vec_extract (*vp, 7);
+}
+
+unsigned short ms21 (vector unsigned short *vp)
+{
+  return __builtin_vec_extract (*vp, 21);
+}
+
+unsigned short ms30 (vector unsigned short *vp)
+{
+  return __builtin_vec_extract (*vp, 30);
+}
+
+/* Test the same with variable indices.  */
+
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+unsigned short ci (vector unsigned short v, int i)
+{
+  return __builtin_vec_extract (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+__attribute__((noinline))
+unsigned short mci (vector unsigned short *vp, int i)
+{
+  return __builtin_vec_extract (*vp, i);
+}
+
+
+int main (int argc, unsigned short *argv[]) {
+  vector unsigned short sv = {
+    CONST0, CONST1, CONST2, CONST3, CONST4, CONST5, CONST6, CONST7 };
+  unsigned short s;
+
+  s = s3 (sv);
+  if (s != CONST3)
+    abort ();
+
+  s = s7 (sv);
+  if (s != CONST7)
+    abort ();
+
+  s = s21 (sv);
+  if (s != CONST5)
+    abort ();
+
+  s = s30 (sv);
+  if (s != CONST6)
+    abort ();
+
+  s = ms3 (&sv);
+  if (s != CONST3)
+    abort ();
+
+  s = ms7 (&sv);
+  if (s != CONST7)
+    abort ();
+
+  s = ms21 (&sv);
+  if (s != CONST5)
+    abort ();
+
+  s = ms30 (&sv);
+  if (s != CONST6)
+    abort ();
+
+  s = ci (sv, 5);
+  if (s != CONST5)
+    abort ();
+
+  s = ci (sv, 2);
+  if (s != CONST2)
+    abort ();
+
+  s = ci (sv, 15);
+  if (s != CONST7)
+    abort ();
+
+  s = ci (sv, 28);
+  if (s != CONST4)
+    abort ();
+
+  s = mci (&sv, 5);
+  if (s != CONST5)
+    abort ();
+
+  s = mci (&sv, 12);
+  if (s != CONST4)
+    abort ();
+
+  s = mci (&sv, 25);
+  if (s != CONST1)
+    abort ();
+
+  s = mci (&sv, 16);
+  if (s != CONST0)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-18a.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-18a.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-18a.c	(revision 0)
@@ -0,0 +1,151 @@ 
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target dfp_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-maltivec" } */
+
+/* This test should run the same on any target that supports altivec/dfp
+   instructions.  Unsigned Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define CONST0		(0)
+#define CONST1		(1)
+#define CONST2		(2)
+#define CONST3		(3)
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+unsigned int s3 (vector unsigned int v)
+{
+  return __builtin_vec_extract (v, 3);
+}
+
+unsigned int s1 (vector unsigned int v)
+{
+  return __builtin_vec_extract (v, 1);
+}
+
+unsigned int s21 (vector unsigned int v)
+{
+  return __builtin_vec_extract (v, 21);
+}
+
+unsigned int s30 (vector unsigned int v)
+{
+  return __builtin_vec_extract (v, 30);
+}
+
+/* Test for vector residing in memory.  */
+unsigned int ms3 (vector unsigned int *vp)
+{
+  return __builtin_vec_extract (*vp, 3);
+}
+
+unsigned int ms1(vector unsigned int *vp)
+{
+  return __builtin_vec_extract (*vp, 1);
+}
+
+unsigned int ms21(vector unsigned int *vp)
+{
+  return __builtin_vec_extract (*vp, 21);
+}
+
+unsigned int ms30(vector unsigned int *vp)
+{
+  return __builtin_vec_extract (*vp, 30);
+}
+
+/* Test the same with variable indices.  */
+
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+unsigned int ci (vector unsigned int v, int i)
+{
+  return __builtin_vec_extract (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+__attribute__((noinline))
+unsigned int mci(vector unsigned int *vp, int i)
+{
+  return __builtin_vec_extract (*vp, i);
+}
+
+
+unsigned int main (int argc, unsigned char *argv[]) {
+  vector unsigned int sv = { CONST0, CONST1, CONST2, CONST3 };
+  unsigned int s;
+
+  s = s3 (sv);
+  if (s != CONST3)
+    abort ();
+
+  s = s1 (sv);
+  if (s != CONST1)
+    abort ();
+
+  s = s21 (sv);
+  if (s != CONST1)
+    abort ();
+
+  s = s30 (sv);
+  if (s != CONST2)
+    abort ();
+
+  s = ms3 (&sv);
+  if (s != CONST3)
+    abort ();
+
+  s = ms1 (&sv);
+  if (s != CONST1)
+    abort ();
+
+  s = ms21 (&sv);
+  if (s != CONST1)
+    abort ();
+
+  s = ms30 (&sv);
+  if (s != CONST2)
+    abort ();
+
+  s = ci (sv, 5);
+  if (s != CONST1)
+    abort ();
+
+  s = ci (sv, 2);
+  if (s != CONST2)
+    abort ();
+
+  s = ci (sv, 15);
+  if (s != CONST3)
+    abort ();
+
+  s = ci (sv, 28);
+  if (s != CONST0)
+    abort ();
+
+  s = mci (&sv, 5);
+  if (s != CONST1)
+    abort ();
+
+  s = mci (&sv, 12);
+  if (s != CONST0)
+    abort ();
+
+  s = mci (&sv, 25);
+  if (s != CONST1)
+    abort ();
+
+  s = mci (&sv, 16);
+  if (s != CONST0)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/pr87532-mc.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr87532-mc.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/pr87532-mc.c	(revision 0)
@@ -0,0 +1,260 @@ 
+/* { dg-do run { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target dfp_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-maltivec -O2" } */
+
+/* This test should run the same on any target that supports altivec/dfp
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <altivec.h>
+
+#include <stdio.h>
+
+static vector unsigned __int128
+deoptimize_uint128 (vector unsigned __int128  a)
+{
+  __asm__ (" # %x0" : "+wa" (a));
+  return a;
+}
+
+static vector unsigned long long int
+deoptimize_ulong (vector unsigned long long int a)
+{
+  __asm__ (" # %x0" : "+wa" (a));
+  return a;
+}
+
+static vector unsigned int
+deoptimize_uint (vector unsigned int a)
+{
+  __asm__ (" # %x0" : "+wa" (a));
+  return a;
+}
+
+static vector unsigned char
+deoptimize_uchar (vector unsigned char a)
+{
+  __asm__ (" # %x0" : "+wa" (a));
+  return a;
+}
+
+static vector unsigned short
+deoptimize_ushort (vector unsigned short a)
+{
+  __asm__ (" # %x0" : "+wa" (a));
+  return a;
+}
+
+__attribute ((noinline)) unsigned __int128
+get_auto_n_uint128 (vector unsigned __int128 a, int n)
+{
+  return __builtin_vec_extract (a, n);
+}
+
+__attribute ((noinline)) unsigned long long int
+get_auto_n_ulong (vector unsigned long long int a, int n)
+{
+  return __builtin_vec_extract (a, n);
+}
+
+__attribute ((noinline))
+unsigned int get_auto_n_uint (vector unsigned int a, int n)
+{
+  return __builtin_vec_extract (a, n);
+}
+
+__attribute ((noinline))
+unsigned char get_auto_n_uchar (vector unsigned char a, int n)
+{
+  return __builtin_vec_extract (a, n);
+}
+
+__attribute ((noinline))
+unsigned short get_auto_n_ushort (vector unsigned short a, int n)
+{
+  return __builtin_vec_extract (a, n);
+}
+
+
+int check_uint128_element (int i, unsigned __int128 entry)
+{
+  printf ("checking uint128 entry at index %d\n", i);
+
+  return (entry == ((((unsigned __int128) 0xffeeddccbbaa9988ULL) << 64)
+		    | 0x0706050403020100ULL));
+}
+
+int check_ulong_element (int i, unsigned long long int entry)
+{
+  printf ("checking ulong entry 0x%llx at index %d\n", entry, i);
+
+  switch (i % 2)
+    {
+      case 0: return (entry == 0x9999901010ULL);
+      case 1: return (entry == 0x7777733333ULL);
+      default:
+	return 0;
+    }
+}
+
+int check_uint_element (int i, unsigned int entry)
+{
+  printf ("checking uint entry 0x%x at index %d\n", entry, i);
+
+  switch (i % 4)
+    {
+    case 0: return (entry == 0x99999);
+    case 1: return (entry == 0x01010);
+    case 2: return (entry == 0x77777);
+    case 3: return (entry == 0x33333);
+    default:
+      return 0;
+    }
+}
+
+int check_uchar_element (int i, unsigned char entry)
+{
+  printf ("checking uchar entry 0x%x at index %d\n", entry, i);
+  switch (i % 16)
+    {
+    case 0: return (entry == 0x90);
+    case 1: return (entry == 0x80);
+    case 2: return (entry == 0x70);
+    case 3: return (entry == 0x60);
+    case 4: return (entry == 0x50);
+    case 5: return (entry == 0x40);
+    case 6: return (entry == 0x30);
+    case 7: return (entry == 0x20);
+    case 8: return (entry == 0x10);
+    case 9: return (entry == 0xf0);
+    case 10: return (entry == 0xe0);
+    case 11: return (entry == 0xd0);
+    case 12: return (entry == 0xc0);
+    case 13: return (entry == 0xb0);
+    case 14: return (entry == 0xa0);
+    case 15: return (entry == 0xff);
+    default:
+      return 0;
+    }
+}
+
+int check_ushort_element (int i, unsigned short entry)
+{
+  printf ("checking ushort entry 0x%x at index %d\n", entry, i);
+  switch (i % 8)
+    {
+    case 0: return (entry == 0x9988);
+    case 1: return (entry == 0x8877);
+    case 2: return (entry == 0x7766);
+    case 3: return (entry == 0x6655);
+    case 4: return (entry == 0x5544);
+    case 5: return (entry == 0x4433);
+    case 6: return (entry == 0x3322);
+    case 7: return (entry == 0x2211);
+    default:
+      return 0;
+    }
+}
+
+void do_auto_uint128 ( vector unsigned __int128 a )
+{
+  int i;
+  unsigned __int128 c;
+  for (i = 0; i < 32; i += 3)
+    {
+      c = get_auto_n_uint128 (a,i);
+      if (!check_uint128_element (i, c)) abort ();
+    }
+ }
+
+void do_auto_ulong ( vector unsigned long long int a )
+{
+  int i;
+  unsigned long long int c;
+  for (i = 0; i < 32; i += 3)
+    {
+      c = get_auto_n_ulong (a,i);
+      if (!check_ulong_element (i, c)) abort ();
+    }
+ }
+
+void do_auto_uint ( vector unsigned int a )
+{
+  int i;
+  unsigned int c;
+  for (i = 0; i < 32; i += 3)
+    {
+      c = get_auto_n_uint (a,i);
+      if (!check_uint_element (i, c)) abort ();
+    }
+ }
+
+void do_auto_ushort ( vector unsigned short a )
+{
+  int i;
+  unsigned short c;
+  for (i = 0; i < 32; i += 3)
+    {
+      c = get_auto_n_ushort (a,i);
+      if (!check_ushort_element (i, c)) abort ();
+    }
+}
+
+void do_auto_uchar ( vector unsigned char a )
+{
+  int i;
+  unsigned char c;
+  for (i = 0; i < 32; i += 3)
+    {
+      c = get_auto_n_uchar (a,i);
+      if (!check_uchar_element (i, c)) abort ();
+    }
+}
+
+int
+main (void)
+{
+  size_t i;
+
+  vector unsigned __int128 u = {
+    ((((unsigned __int128) 0xffeeddccbbaa9988ULL) << 64)
+     | 0x0706050403020100ULL) };
+  vector unsigned __int128 du;
+
+  vector unsigned long long int v = { 0x9999901010ULL, 0x7777733333ULL };
+  vector unsigned long long int dv;
+
+  vector unsigned int x = { 0x99999, 0x01010, 0x77777, 0x33333 };
+  vector unsigned int dx;
+
+  vector unsigned char y = { 0x90, 0x80, 0x70, 0x60, 0x50, 0x40, 0x30, 0x20,
+			     0x10, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0xff };
+  vector unsigned char dy;
+
+  vector unsigned short z = { 0x9988, 0x8877, 0x7766, 0x6655,
+			      0x5544, 0x4433, 0x3322, 0x2211 };
+  vector unsigned short dz;
+
+  do_auto_uint128 (u);
+  do_auto_ulong (v);
+  do_auto_uint (x);
+  do_auto_uchar (y);
+  do_auto_ushort (z);
+
+  du = deoptimize_uint128 (u);
+  dv = deoptimize_ulong (v);
+  dx = deoptimize_uint (x);
+  dy = deoptimize_uchar (y);
+  dz = deoptimize_ushort (z);
+
+  do_auto_uint128 (du);
+  do_auto_ulong (dv);
+  do_auto_uint (dx);
+  do_auto_uchar (dy);
+  do_auto_ushort (dz);
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-19b.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-19b.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-19b.c	(revision 0)
@@ -0,0 +1,111 @@ 
+/* { dg-do run { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-mvsx -O3" } */
+
+/* This test should run the same on any target that supports vsx
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define CONST0		(31415926539LL)
+#define CONST1		(2 * 31415926539LL)
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+unsigned long long int e0 (vector unsigned long long int v)
+{
+  return __builtin_vec_extract (v, 0);
+}
+
+unsigned long long int e3 (vector unsigned long long int v)
+{
+  return __builtin_vec_extract (v, 3);
+}
+
+/* Test for vector residing in memory.  */
+unsigned long long int me0 (vector unsigned long long int *vp)
+{
+  return __builtin_vec_extract (*vp, 0);
+}
+
+unsigned long long int me3 (vector unsigned long long int *vp)
+{
+  return __builtin_vec_extract (*vp, 3);
+}
+
+/* Test the same with variable indices.  */
+
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+unsigned long long int ei (vector unsigned long long int v, int i)
+{
+  return __builtin_vec_extract (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+unsigned long long int mei (vector unsigned long long int *vp, int i)
+{
+  return __builtin_vec_extract (*vp, i);
+}
+
+int main (int argc, char *argv[]) {
+  vector unsigned long long int dv = { CONST0, CONST1 };
+  unsigned long long int d;
+
+  d = e0 (dv);
+  if (d != CONST0)
+    abort ();
+
+  d = e3 (dv);
+  if (d != CONST1)
+    abort ();
+
+  d = me0 (&dv);
+  if (d != CONST0)
+    abort ();
+
+  d = me3 (&dv);
+  if (d != CONST1)
+    abort ();
+
+  d = ei (dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 1);
+  if (d != CONST1)
+    abort ();
+
+  d = ei (dv, 2);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 3);
+  if (d != CONST1)
+    abort ();
+
+  d = mei (&dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 1);
+  if (d != CONST1)
+    abort ();
+
+  d = mei (&dv, 2);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 3);
+  if (d != CONST1)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-10b.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-10b.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-10b.c	(revision 0)
@@ -0,0 +1,157 @@ 
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target dfp_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-maltivec -O3" } */
+
+/* This test should run the same on any target that supports altivec/dfp
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define CONST0		(0)
+#define CONST1		(1)
+#define CONST2		(2)
+#define CONST3		(3)
+#define CONST4		(4)
+#define CONST5		(5)
+#define CONST6		(6)
+#define CONST7		(7)
+
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+short s3 (vector short v)
+{
+  return __builtin_vec_ext_v8hi (v, 3);
+}
+
+short s7 (vector short v)
+{
+  return __builtin_vec_ext_v8hi (v, 7);
+}
+
+short s21 (vector short v)
+{
+  return __builtin_vec_ext_v8hi (v, 21);
+}
+
+short s30 (vector short v)
+{
+  return __builtin_vec_ext_v8hi (v, 30);
+}
+
+/* Test for vector residing in memory.  */
+short ms3 (vector short *vp)
+{
+  return __builtin_vec_ext_v8hi (*vp, 3);
+}
+
+short ms7 (vector short *vp)
+{
+  return __builtin_vec_ext_v8hi (*vp, 7);
+}
+
+short ms21 (vector short *vp)
+{
+  return __builtin_vec_ext_v8hi (*vp, 21);
+}
+
+short ms30 (vector short *vp)
+{
+  return __builtin_vec_ext_v8hi (*vp, 30);
+}
+
+/* Test the same with variable indices.  */
+
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+short ci (vector short v, int i)
+{
+  return __builtin_vec_ext_v8hi (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+__attribute__((noinline))
+short mci (vector short *vp, int i)
+{
+  return __builtin_vec_ext_v8hi (*vp, i);
+}
+
+
+int main (int argc, short *argv[]) {
+  vector short sv = {
+    CONST0, CONST1, CONST2, CONST3, CONST4, CONST5, CONST6, CONST7 };
+  short s;
+
+  s = s3 (sv);
+  if (s != CONST3)
+    abort ();
+
+  s = s7 (sv);
+  if (s != CONST7)
+    abort ();
+
+  s = s21 (sv);
+  if (s != CONST5)
+    abort ();
+
+  s = s30 (sv);
+  if (s != CONST6)
+    abort ();
+
+  s = ms3 (&sv);
+  if (s != CONST3)
+    abort ();
+
+  s = ms7 (&sv);
+  if (s != CONST7)
+    abort ();
+
+  s = ms21 (&sv);
+  if (s != CONST5)
+    abort ();
+
+  s = ms30 (&sv);
+  if (s != CONST6)
+    abort ();
+
+  s = ci (sv, 5);
+  if (s != CONST5)
+    abort ();
+
+  s = ci (sv, 2);
+  if (s != CONST2)
+    abort ();
+
+  s = ci (sv, 15);
+  if (s != CONST7)
+    abort ();
+
+  s = ci (sv, 28);
+  if (s != CONST4)
+    abort ();
+
+  s = mci (&sv, 5);
+  if (s != CONST5)
+    abort ();
+
+  s = mci (&sv, 12);
+  if (s != CONST4)
+    abort ();
+
+  s = mci (&sv, 25);
+  if (s != CONST1)
+    abort ();
+
+  s = mci (&sv, 16);
+  if (s != CONST0)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-11a.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-11a.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-11a.c	(revision 0)
@@ -0,0 +1,151 @@ 
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target dfp_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-maltivec" } */
+
+/* This test should run the same on any target that supports altivec/dfp
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define CONST0		(0)
+#define CONST1		(1)
+#define CONST2		(2)
+#define CONST3		(3)
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+int s3 (vector int v)
+{
+  return __builtin_vec_ext_v4si (v, 3);
+}
+
+int s1 (vector int v)
+{
+  return __builtin_vec_ext_v4si (v, 1);
+}
+
+int s21 (vector int v)
+{
+  return __builtin_vec_ext_v4si (v, 21);
+}
+
+int s30 (vector int v)
+{
+  return __builtin_vec_ext_v4si (v, 30);
+}
+
+/* Test for vector residing in memory.  */
+int ms3 (vector int *vp)
+{
+  return __builtin_vec_ext_v4si (*vp, 3);
+}
+
+int ms1(vector int *vp)
+{
+  return __builtin_vec_ext_v4si (*vp, 1);
+}
+
+int ms21(vector int *vp)
+{
+  return __builtin_vec_ext_v4si (*vp, 21);
+}
+
+int ms30(vector int *vp)
+{
+  return __builtin_vec_ext_v4si (*vp, 30);
+}
+
+/* Test the same with variable indices.  */
+
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+int ci (vector int v, int i)
+{
+  return __builtin_vec_ext_v4si (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+__attribute__((noinline))
+int mci(vector int *vp, int i)
+{
+  return __builtin_vec_ext_v4si (*vp, i);
+}
+
+
+int main (int argc, int *argv[]) {
+  vector int sv = { CONST0, CONST1, CONST2, CONST3 };
+  int s;
+
+  s = s3 (sv);
+  if (s != CONST3)
+    abort ();
+
+  s = s1 (sv);
+  if (s != CONST1)
+    abort ();
+
+  s = s21 (sv);
+  if (s != CONST1)
+    abort ();
+
+  s = s30 (sv);
+  if (s != CONST2)
+    abort ();
+
+  s = ms3 (&sv);
+  if (s != CONST3)
+    abort ();
+
+  s = ms1 (&sv);
+  if (s != CONST1)
+    abort ();
+
+  s = ms21 (&sv);
+  if (s != CONST1)
+    abort ();
+
+  s = ms30 (&sv);
+  if (s != CONST2)
+    abort ();
+
+  s = ci (sv, 5);
+  if (s != CONST1)
+    abort ();
+
+  s = ci (sv, 2);
+  if (s != CONST2)
+    abort ();
+
+  s = ci (sv, 15);
+  if (s != CONST3)
+    abort ();
+
+  s = ci (sv, 28);
+  if (s != CONST0)
+    abort ();
+
+  s = mci (&sv, 5);
+  if (s != CONST1)
+    abort ();
+
+  s = mci (&sv, 12);
+  if (s != CONST0)
+    abort ();
+
+  s = mci (&sv, 25);
+  if (s != CONST1)
+    abort ();
+
+  s = mci (&sv, 16);
+  if (s != CONST0)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-9a.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-9a.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-9a.c	(revision 0)
@@ -0,0 +1,166 @@ 
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target dfp_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-maltivec" } */
+
+/* This test should run the same on any target that supports altivec/dfp
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define CONST0		(0)
+#define CONST1		(1)
+#define CONST2		(2)
+#define CONST3		(3)
+#define CONST4		(4)
+#define CONST5		(5)
+#define CONST6		(6)
+#define CONST7		(7)
+#define CONST8		(8)
+#define CONST9		(9)
+#define CONSTA		(10)
+#define CONSTB		(11)
+#define CONSTC		(12)
+#define CONSTD		(13)
+#define CONSTE		(14)
+#define CONSTF		(15)
+
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+signed char c0 (vector signed char v)
+{
+  return __builtin_vec_ext_v16qi (v, 0);
+}
+
+signed char c9 (vector signed char v)
+{
+  return __builtin_vec_ext_v16qi (v, 9);
+}
+
+signed char c21 (vector signed char v)
+{
+  return __builtin_vec_ext_v16qi (v, 21);
+}
+
+signed char c30 (vector signed char v)
+{
+  return __builtin_vec_ext_v16qi (v, 30);
+}
+
+/* Test for vector residing in memory.  */
+signed char mc0 (vector signed char *vp)
+{
+  return __builtin_vec_ext_v16qi (*vp, 0);
+}
+
+signed char mc9 (vector signed char *vp)
+{
+  return __builtin_vec_ext_v16qi (*vp, 9);
+}
+
+signed char mc21 (vector signed char *vp)
+{
+  return __builtin_vec_ext_v16qi (*vp, 21);
+}
+
+signed char mc30 (vector signed char *vp)
+{
+  return __builtin_vec_ext_v16qi (*vp, 30);
+}
+
+/* Test the same with variable indices.  */
+
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+signed char ci (vector signed char v, int i)
+{
+  return __builtin_vec_ext_v16qi (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+__attribute__((noinline))
+signed char mci(vector signed char *vp, int i) {
+  return __builtin_vec_ext_v16qi (*vp, i);
+}
+
+
+int main (int argc, char *argv[]) {
+  vector signed char cv = { CONST0, CONST1, CONST2, CONST3,
+			    CONST4, CONST5, CONST6, CONST7,
+			    CONST8, CONST9, CONSTA, CONSTB,
+			    CONSTC, CONSTD, CONSTE, CONSTF };
+  signed char c;
+
+  c = c0 (cv);
+  if (c != CONST0)
+    abort ();
+
+  c = c9 (cv);
+  if (c != CONST9)
+    abort ();
+
+  c = c21 (cv);
+  if (c != CONST5)
+    abort ();
+
+  c = c30 (cv);
+  if (c != CONSTE)
+    abort ();
+
+  c = mc0 (&cv);
+  if (c != CONST0)
+    abort ();
+
+  c = mc9 (&cv);
+  if (c != CONST9)
+    abort ();
+
+  c = mc21 (&cv);
+  if (c != CONST5)
+    abort ();
+
+  c = mc30 (&cv);
+  if (c != CONSTE)
+    abort ();
+
+  c = ci (cv, 8);
+  if (c != CONST8)
+    abort ();
+
+  c = ci (cv, 13);
+  if (c != CONSTD)
+    abort ();
+
+  c = ci (cv, 23);
+  if (c != CONST7)
+    abort ();
+
+  c = ci (cv, 31);
+  if (c != CONSTF)
+    abort ();
+
+  c = mci (&cv, 5);
+  if (c != CONST5)
+    abort ();
+
+  c = mci (&cv, 12);
+  if (c != CONSTC)
+    abort ();
+
+  c = mci (&cv, 25);
+  if (c != CONST9)
+    abort ();
+
+  c = mci (&cv, 16);
+  if (c != CONST0)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/fold-vec-extract-short.p8.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/fold-vec-extract-short.p8.c	(revision 269370)
+++ gcc/testsuite/gcc.target/powerpc/fold-vec-extract-short.p8.c	(working copy)
@@ -6,9 +6,9 @@ 
 /* { dg-options "-mdejagnu-cpu=power8 -O2" } */
 
 // six tests total. Targeting P8, both LE and BE.
-// p8 (le) variable offset: rldicl, subfic, sldi, mtvsrd, xxpermdi, vslo, mfvsrd, sradi, *extsh
+// p8 (le) variable offset: rldicl, subfic, sldi, mtvsrd, xxpermdi, vslo, mfvsrd, srdi, *extsh
 // p8 (le) const offset:                          mtvsrd,                                *extsh/rlwinm
-// p8 (be) var offset:                      sldi, mtvsrd, xxpermdi, vslo, mfvsrd, sradi, *extsh
+// p8 (be) var offset:                      sldi, mtvsrd, xxpermdi, vslo, mfvsrd, srdi, *extsh
 // p8 (be) const offset:    vsplth,               mfvsrd,                                *extsh/rlwinm
 
 // * - each of the above will have an extsh if the argument is signed.
@@ -22,7 +22,7 @@ 
 /* { dg-final { scan-assembler-times "xxpermdi" 3 { target lp64 } } } */
 /* { dg-final { scan-assembler-times "vslo" 3 { target lp64 } } } */
 /* { dg-final { scan-assembler-times "mfvsrd" 6 { target lp64 } } } */
-/* { dg-final { scan-assembler-times "sradi" 3 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "srdi" 3 { target lp64 } } } */
 /* { dg-final { scan-assembler-times "extsh" 2 { target lp64 } } } */
 /* { dg-final { scan-assembler-times "rlwinm" 2 { target lp64 } } } */
 
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-20b.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-20b.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-20b.c	(revision 0)
@@ -0,0 +1,117 @@ 
+/* { dg-do run { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-mvsx -O3" } */
+
+/* This test should run the same on any target that supports vsx
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+/* Define this after PR89424 is addressed.  */
+#undef PR89424
+
+extern void abort (void);
+
+#define CONST0		(((unsigned __int128) 31415926539) << 60)
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+unsigned __int128 e0 (vector unsigned __int128 v)
+{
+  return __builtin_vec_extract (v, 0);
+}
+
+unsigned __int128 e3 (vector unsigned __int128 v)
+{
+  return __builtin_vec_extract (v, 3);
+}
+
+/* Test for vector residing in memory.  */
+unsigned __int128 me0 (vector unsigned __int128 *vp)
+{
+  return __builtin_vec_extract (*vp, 0);
+}
+
+unsigned __int128 me3 (vector unsigned __int128 *vp)
+{
+  return __builtin_vec_extract (*vp, 3);
+}
+
+/* Test the same with variable indices.  */
+
+#ifdef PR89424
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+unsigned __int128 ei (vector unsigned __int128 v, int i)
+{
+  return __builtin_vec_extract (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+unsigned __int128 mei (vector unsigned __int128 *vp, int i)
+{
+  return __builtin_vec_extract (*vp, i);
+}
+#endif
+
+int main (int argc, char *argv[]) {
+  vector unsigned __int128 dv = { CONST0 };
+  unsigned __int128 d;
+
+  d = e0 (dv);
+  if (d != CONST0)
+    abort ();
+
+  d = e3 (dv);
+  if (d != CONST0)
+    abort ();
+
+  d = me0 (&dv);
+  if (d != CONST0)
+    abort ();
+
+  d = me3 (&dv);
+  if (d != CONST0)
+    abort ();
+
+#ifdef PR89424
+  d = ei (dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 1);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 2);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 3);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 1);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 2);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 3);
+  if (d != CONST0)
+    abort ();
+#endif
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/fold-vec-extract-int.p8.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/fold-vec-extract-int.p8.c	(revision 269370)
+++ gcc/testsuite/gcc.target/powerpc/fold-vec-extract-int.p8.c	(working copy)
@@ -21,7 +21,7 @@ 
 /* { dg-final { scan-assembler-times {\mxxpermdi\M} 3 { target lp64 } } } */
 /* { dg-final { scan-assembler-times {\mvslo\M} 3 { target lp64 } } } */
 /* { dg-final { scan-assembler-times {\mmfvsrd\M} 3 { target lp64 } } } */
-/* { dg-final { scan-assembler-times {\msradi\M} 3 { target lp64 } } } */
+/* { dg-final { scan-assembler-times {\msrdi\M} 3 { target lp64 } } } */
 /* { dg-final { scan-assembler-times {\mextsw\M} 2 { target lp64 } } } */
 
 
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-12b.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-12b.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-12b.c	(revision 0)
@@ -0,0 +1,111 @@ 
+/* { dg-do run { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-mvsx -O3" } */
+
+/* This test should run the same on any target that supports vsx
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define CONST0		(31415926539LL)
+#define CONST1		(2 * 31415926539LL)
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+long long int e0 (vector long long int v)
+{
+  return __builtin_vec_ext_v2di (v, 0);
+}
+
+long long int e3 (vector long long int v)
+{
+  return __builtin_vec_ext_v2di (v, 3);
+}
+
+/* Test for vector residing in memory.  */
+long long int me0 (vector long long int *vp)
+{
+  return __builtin_vec_ext_v2di (*vp, 0);
+}
+
+long long int me3 (vector long long int *vp)
+{
+  return __builtin_vec_ext_v2di (*vp, 3);
+}
+
+/* Test the same with variable indices.  */
+
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+long long int ei (vector long long int v, int i)
+{
+  return __builtin_vec_ext_v2di (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+long long int mei (vector long long int *vp, int i)
+{
+  return __builtin_vec_ext_v2di (*vp, i);
+}
+
+int main (int argc, char *argv[]) {
+  vector long long int dv = { CONST0, CONST1 };
+  long long int d;
+
+  d = e0 (dv);
+  if (d != CONST0)
+    abort ();
+
+  d = e3 (dv);
+  if (d != CONST1)
+    abort ();
+
+  d = me0 (&dv);
+  if (d != CONST0)
+    abort ();
+
+  d = me3 (&dv);
+  if (d != CONST1)
+    abort ();
+
+  d = ei (dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 1);
+  if (d != CONST1)
+    abort ();
+
+  d = ei (dv, 2);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 3);
+  if (d != CONST1)
+    abort ();
+
+  d = mei (&dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 1);
+  if (d != CONST1)
+    abort ();
+
+  d = mei (&dv, 2);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 3);
+  if (d != CONST1)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-13a.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-13a.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-13a.c	(revision 0)
@@ -0,0 +1,126 @@ 
+/* { dg-do run { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-mvsx" } */
+
+/* This test should run the same on any target that supports vsx
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+/* Define this after PR89424 is addressed.  */
+#undef PR89424
+
+/* Define this after PR89626 is addressed.  */
+#undef PR89626
+
+#ifdef PR89626
+#define SIGNED
+#else
+#define SIGNED signed
+#endif
+
+extern void abort (void);
+
+#define CONST0		(((SIGNED __int128) 31415926539) << 60)
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+SIGNED __int128 e0 (vector SIGNED __int128 v)
+{
+  return __builtin_vec_ext_v1ti (v, 0);
+}
+
+SIGNED __int128 e3 (vector SIGNED __int128 v)
+{
+  return __builtin_vec_ext_v1ti (v, 3);
+}
+
+/* Test for vector residing in memory.  */
+SIGNED __int128 me0 (vector SIGNED __int128 *vp)
+{
+  return __builtin_vec_ext_v1ti (*vp, 0);
+}
+
+SIGNED __int128 me3 (vector SIGNED __int128 *vp)
+{
+  return __builtin_vec_ext_v1ti (*vp, 3);
+}
+
+/* Test the same with variable indices.  */
+
+#ifdef PR89424
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+SIGNED __int128 ei (vector SIGNED __int128 v, int i)
+{
+  return __builtin_vec_ext_v1ti (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+SIGNED __int128 mei (vector SIGNED __int128 *vp, int i)
+{
+  return __builtin_vec_ext_v1ti (*vp, i);
+}
+#endif
+
+int main (int argc, char *argv[]) {
+  vector SIGNED __int128 dv = { CONST0 };
+  SIGNED __int128 d;
+
+  d = e0 (dv);
+  if (d != CONST0)
+    abort ();
+
+  d = e3 (dv);
+  if (d != CONST0)
+    abort ();
+
+  d = me0 (&dv);
+  if (d != CONST0)
+    abort ();
+
+  d = me3 (&dv);
+  if (d != CONST0)
+    abort ();
+
+#ifdef PR89424
+  d = ei (dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 1);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 2);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 3);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 1);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 2);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 3);
+  if (d != CONST0)
+    abort ();
+#endif
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-14b.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-14b.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-14b.c	(revision 0)
@@ -0,0 +1,128 @@ 
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target dfp_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-maltivec -O3" } */
+
+/* This test should run the same on any target that supports altivec/dfp
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define CONST0		((float) (3.1415926539))
+#define CONST1		((float) (3.1415926539 * 2))
+#define CONST2		((float) (3.1415926539 * 3))
+#define CONST3		((float) (3.1415926539 * 4))
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+float e0(vector float v){ return __builtin_vec_ext_v4sf (v, 0); }
+float e1(vector float v){ return __builtin_vec_ext_v4sf (v, 1); }
+float e7(vector float v){ return __builtin_vec_ext_v4sf (v, 7); }
+float e8(vector float v){ return __builtin_vec_ext_v4sf (v, 8); }
+
+/* Test for vector residing in memory.  */
+float me0(vector float *vp){ return __builtin_vec_ext_v4sf (*vp, 0); }
+float me1(vector float *vp){ return __builtin_vec_ext_v4sf (*vp, 1); }
+
+float me13(vector float *vp)
+{
+  return __builtin_vec_ext_v4sf (*vp, 13);
+}
+
+float me15(vector float *vp)
+{
+  return __builtin_vec_ext_v4sf (*vp, 15);
+}
+
+/* Test the same with variable indices.  */
+
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+float ei(vector float v, int i)
+{
+  return __builtin_vec_ext_v4sf (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+float mei(vector float *vp, int i)
+{
+  return __builtin_vec_ext_v4sf (*vp, i);
+}
+
+
+int main (int argc, char *argv[]) {
+  vector float dv = { CONST0, CONST1, CONST2, CONST3 };
+  float d;
+
+  d = e0 (dv);
+  if (d != CONST0)
+    abort ();
+
+  d = e1 (dv);
+  if (d != CONST1)
+    abort ();
+
+  d = e7 (dv);
+  if (d != CONST3)
+    abort ();
+
+  d = e8 (dv);
+  if (d != CONST0)
+    abort ();
+
+  d = me0 (&dv);
+  if (d != CONST0)
+    abort ();
+
+  d = me1 (&dv);
+  if (d != CONST1)
+    abort ();
+
+  d = me13 (&dv);
+  if (d != CONST1)
+    abort ();
+
+  d = me15 (&dv);
+  if (d != CONST3)
+    abort ();
+
+  d = ei (dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 2);
+  if (d != CONST2)
+    abort ();
+
+  d = ei (dv, 11);
+  if (d != CONST3)
+    abort ();
+
+  d = ei (dv, 17);
+  if (d != CONST1)
+    abort ();
+
+  d = mei (&dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 1);
+  if (d != CONST1)
+    abort ();
+
+  d = mei (&dv, 15);
+  if (d != CONST3)
+    abort ();
+
+  d = mei (&dv, 6);
+  if (d != CONST2)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-15a.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-15a.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-15a.c	(revision 0)
@@ -0,0 +1,115 @@ 
+/* { dg-do run { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-mvsx" } */
+
+/* This test should run the same on any target that supports vsx
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define CONST0		(3.1415926539)
+#define CONST1		(3.1415926539 * 2)
+
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+double e0(vector double v){ return __builtin_vec_ext_v2df (v, 0); }
+double e1(vector double v){ return __builtin_vec_ext_v2df (v, 1); }
+double e2(vector double v){ return __builtin_vec_ext_v2df (v, 2); }
+double e3(vector double v){ return __builtin_vec_ext_v2df (v, 3); }
+
+/* Test for vector residing in memory.  */
+double me0(vector double *vp){ return __builtin_vec_ext_v2df (*vp, 0); }
+double me1(vector double *vp){ return __builtin_vec_ext_v2df (*vp, 1); }
+double me2(vector double *vp){ return __builtin_vec_ext_v2df (*vp, 2); }
+double me3(vector double *vp){ return __builtin_vec_ext_v2df (*vp, 3); }
+
+/* Test the same with variable indices.  */
+
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+double ei(vector double v, int i){ return __builtin_vec_ext_v2df (v, i); }
+
+/* Test for variable selector and vector residing in memory.  */
+double mei(vector double *vp, int i){ return __builtin_vec_ext_v2df (*vp, i); }
+
+
+int main (int argc, char *argv[]) {
+  vector double dv;
+  double d;
+  dv[0] = CONST0;
+  dv[1] = CONST1;
+
+  d = e0 (dv);
+  if (d != CONST0)
+    abort ();
+
+  d = e1 (dv);
+  if (d != CONST1)
+    abort ();
+
+  d = e2 (dv);
+  if (d != CONST0)
+    abort ();
+
+  d = e3 (dv);
+  if (d != CONST1)
+    abort ();
+
+  d = me0 (&dv);
+  if (d != CONST0)
+    abort ();
+
+  d = me1 (&dv);
+  if (d != CONST1)
+    abort ();
+
+  d = me2 (&dv);
+  if (d != CONST0)
+    abort ();
+
+  d = me3 (&dv);
+  if (d != CONST1)
+    abort ();
+
+  d = ei (dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 1);
+  if (d != CONST1)
+    abort ();
+
+  d = ei (dv, 2);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 3);
+  if (d != CONST1)
+    abort ();
+
+  d = mei (&dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 1);
+  if (d != CONST1)
+    abort ();
+
+  d = mei (&dv, 2);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 3);
+  if (d != CONST1)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vec-extract-v16qiu-v2b.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vec-extract-v16qiu-v2b.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vec-extract-v16qiu-v2b.c	(revision 0)
@@ -0,0 +1,16 @@ 
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-O2 -mvsx -save-temps -dp -g" } */
+
+#define TYPE unsigned char
+/* ELEMENTS is number of elements in a vector of TYPE.  */
+#define ELEMENTS 16
+#define INITIAL \
+  {  3, 2, 3, 4, 5, 6, 7, 8, 240, 241, 242, 243, 244, 245, 246, 247 }
+
+#define DO_TRACE
+#undef DISABLE_INLINE_OF_GET_AUTO_N
+
+#include "vec-extract-v16qiu-v2.h"
Index: gcc/testsuite/gcc.target/powerpc/pr87532.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr87532.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/pr87532.c	(revision 0)
@@ -0,0 +1,74 @@ 
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target dfp_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-maltivec" } */
+
+/* This test should run the same on any target that supports altivec/dfp
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <altivec.h>
+#include <stdio.h>
+
+static void
+check (unsigned char, unsigned char) __attribute__((__noinline__));
+
+static __attribute__((altivec(vector__))) unsigned char
+deoptimize (__attribute__((altivec(vector__))) unsigned char)
+__attribute__((__noinline__));
+
+static __attribute__((altivec(vector__))) unsigned char
+deoptimize (__attribute__((altivec(vector__))) unsigned char a)
+{
+  __asm__ (" # %x0" : "+wa" (a));
+  return a;
+}
+
+// Toggle this attribute inline/noinline to see pass/fail.
+// fails with the noinline attribute applied.
+__attribute__ ((__noinline__))
+unsigned char
+get_auto_n (__attribute__((altivec(vector__))) unsigned char a, size_t n)
+{
+  return (unsigned char) __builtin_vec_extract (a, n);
+}
+
+void
+do_auto (__attribute__((altivec(vector__))) unsigned char a)
+{
+  size_t i;
+  for (i = 1; i < 3 ; i++)
+  {
+    do
+      {
+	printf ("get_auto_n (a, %d) produces 0x0%x\n",
+		i, (int) get_auto_n (a, i));
+
+	if ((int) get_auto_n (a,i) > 250) abort();
+      } while (0);
+  }
+}
+
+int
+main (void)
+{
+  size_t i;
+  __attribute__((altivec(vector__))) unsigned char x =
+    { 3, 2, 3, 8, 5, 6, 7, 8, 240, 241, 242, 243, 244, 245, 246, 247 };
+  __attribute__((altivec(vector__))) unsigned char a;
+
+  printf (" first elements of x are: %d %d %d %d %d\n",
+	  x[0], x[1], x[2], x[3], x[4]);
+
+  a = deoptimize (x);
+
+  printf (" after deoptimization, first elements of a are: %d %d %d %d %d\n",
+	  a[0], a[1], a[2], a[3], a[4]);
+
+  do_auto (a);
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-16b.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-16b.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-16b.c	(revision 0)
@@ -0,0 +1,167 @@ 
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target dfp_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-maltivec -O3" } */
+
+/* This test should run the same on any target that supports altivec/dfp
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define CONST0		(0)
+#define CONST1		(1)
+#define CONST2		(2)
+#define CONST3		(3)
+#define CONST4		(4)
+#define CONST5		(5)
+#define CONST6		(6)
+#define CONST7		(7)
+#define CONST8		(8)
+#define CONST9		(9)
+#define CONSTA		(10)
+#define CONSTB		(11)
+#define CONSTC		(12)
+#define CONSTD		(13)
+#define CONSTE		(14)
+#define CONSTF		(15)
+
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+unsigned char c0 (vector unsigned char v)
+{
+  return __builtin_vec_extract (v, 0);
+}
+
+unsigned char c9 (vector unsigned char v)
+{
+  return __builtin_vec_extract (v, 9);
+}
+
+unsigned char c21 (vector unsigned char v)
+{
+  return __builtin_vec_extract (v, 21);
+}
+
+unsigned char c30 (vector unsigned char v)
+{
+  return __builtin_vec_extract (v, 30);
+}
+
+/* Test for vector residing in memory.  */
+unsigned char mc0 (vector unsigned char *vp)
+{
+  return __builtin_vec_extract (*vp, 0);
+}
+
+unsigned char mc9 (vector unsigned char *vp)
+{
+  return __builtin_vec_extract (*vp, 9);
+}
+
+unsigned char mc21 (vector unsigned char *vp)
+{
+  return __builtin_vec_extract (*vp, 21);
+}
+
+unsigned char mc30 (vector unsigned char *vp)
+{
+  return __builtin_vec_extract (*vp, 30);
+}
+
+/* Test the same with variable indices.  */
+
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+unsigned char ci (vector unsigned char v, int i)
+{
+  return __builtin_vec_extract (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+__attribute__((noinline))
+unsigned char mci (vector unsigned char *vp, int i)
+{
+  return __builtin_vec_extract (*vp, i);
+}
+
+
+int main (int argc, char *argv[]) {
+  vector unsigned char cv = { CONST0, CONST1, CONST2, CONST3,
+			    CONST4, CONST5, CONST6, CONST7,
+			    CONST8, CONST9, CONSTA, CONSTB,
+			    CONSTC, CONSTD, CONSTE, CONSTF };
+  unsigned char c;
+
+  c = c0 (cv);
+  if (c != CONST0)
+    abort ();
+
+  c = c9 (cv);
+  if (c != CONST9)
+    abort ();
+
+  c = c21 (cv);
+  if (c != CONST5)
+    abort ();
+
+  c = c30 (cv);
+  if (c != CONSTE)
+    abort ();
+
+  c = mc0 (&cv);
+  if (c != CONST0)
+    abort ();
+
+  c = mc9 (&cv);
+  if (c != CONST9)
+    abort ();
+
+  c = mc21 (&cv);
+  if (c != CONST5)
+    abort ();
+
+  c = mc30 (&cv);
+  if (c != CONSTE)
+    abort ();
+
+  c = ci (cv, 8);
+  if (c != CONST8)
+    abort ();
+
+  c = ci (cv, 13);
+  if (c != CONSTD)
+    abort ();
+
+  c = ci (cv, 23);
+  if (c != CONST7)
+    abort ();
+
+  c = ci (cv, 31);
+  if (c != CONSTF)
+    abort ();
+
+  c = mci (&cv, 5);
+  if (c != CONST5)
+    abort ();
+
+  c = mci (&cv, 12);
+  if (c != CONSTC)
+    abort ();
+
+  c = mci (&cv, 25);
+  if (c != CONST9)
+    abort ();
+
+  c = mci (&cv, 16);
+  if (c != CONST0)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vec-extract-v16qiu-v2.h
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vec-extract-v16qiu-v2.h	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vec-extract-v16qiu-v2.h	(revision 0)
@@ -0,0 +1,253 @@ 
+#include <stdlib.h>
+#include <stddef.h>
+#include <altivec.h>
+
+#ifndef RTYPE
+#define RTYPE TYPE
+#endif
+
+#ifdef DO_TRACE
+#include <stdio.h>
+
+#define TRACE(STRING, NUM)						\
+do									\
+  {									\
+    fprintf (stderr, "%s: %2d\n", STRING, (int) NUM);			\
+    fflush (stderr);							\
+  }									\
+while (0)
+
+#ifndef FAIL_FORMAT
+#define FAIL_FORMAT "%ld"
+#define FAIL_CAST(X) ((long)(X))
+#endif
+
+#define FAIL(EXP, GOT)							 \
+do									 \
+  {									 \
+    fprintf (stderr, "Expected: " FAIL_FORMAT ", got " FAIL_FORMAT "\n", \
+	     FAIL_CAST (EXP), FAIL_CAST (GOT));				 \
+    fflush (stderr);							 \
+    abort ();								 \
+  }									 \
+while (0)
+
+#else
+#define TRACE(STRING, NUM)
+#define FAIL(EXP, GOT) abort ()
+#endif
+
+static void
+check (RTYPE, RTYPE) __attribute__((__noinline__));
+
+static vector TYPE
+deoptimize (vector TYPE) __attribute__((__noinline__));
+
+static vector TYPE
+*deoptimize_ptr (vector TYPE *)	__attribute__((__noinline__));
+
+static void
+check (RTYPE expected, RTYPE got)
+{
+  if (expected != got)
+    FAIL (expected, got);
+}
+
+static vector TYPE
+deoptimize (vector TYPE a)
+{
+  __asm__ (" # %x0" : "+wa" (a));
+  return a;
+}
+
+static vector TYPE *
+deoptimize_ptr (vector TYPE *p)
+{
+  __asm__ (" # %0" : "+r" (p));
+  return p;
+}
+
+
+RTYPE
+get_auto_0 (vector TYPE a)
+{
+  TRACE ("get_auto_", 0);
+  return (RTYPE) vec_extract (a, 0);
+}
+
+RTYPE
+get_auto_1 (vector TYPE a)
+{
+  TRACE ("get_auto_", 1);
+  return (RTYPE) vec_extract (a, 1);
+}
+
+#if ELEMENTS >= 4
+RTYPE
+get_auto_2 (vector TYPE a)
+{
+  return (RTYPE) vec_extract (a, 2);
+}
+
+RTYPE
+get_auto_3 (vector TYPE a)
+{
+  return (RTYPE) vec_extract (a, 3);
+}
+
+#if ELEMENTS >= 8
+RTYPE
+get_auto_4 (vector TYPE a)
+{
+  return (RTYPE) vec_extract (a, 4);
+}
+
+RTYPE
+get_auto_5 (vector TYPE a)
+{
+  return (RTYPE) vec_extract (a, 5);
+}
+
+RTYPE
+get_auto_6 (vector TYPE a)
+{
+  return (RTYPE) vec_extract (a, 6);
+}
+
+RTYPE
+get_auto_7 (vector TYPE a)
+{
+  return (RTYPE) vec_extract (a, 7);
+}
+
+#if ELEMENTS >= 16
+RTYPE
+get_auto_8 (vector TYPE a)
+{
+  return (RTYPE) vec_extract (a, 8);
+}
+
+RTYPE
+get_auto_9 (vector TYPE a)
+{
+  return (RTYPE) vec_extract (a, 9);
+}
+
+RTYPE
+get_auto_10 (vector TYPE a)
+{
+  return (RTYPE) vec_extract (a, 10);
+}
+
+RTYPE
+get_auto_11 (vector TYPE a)
+{
+  return (RTYPE) vec_extract (a, 11);
+}
+
+RTYPE
+get_auto_12 (vector TYPE a)
+{
+  return (RTYPE) vec_extract (a, 12);
+}
+
+RTYPE
+get_auto_13 (vector TYPE a)
+{
+  return (RTYPE) vec_extract (a, 13);
+}
+
+RTYPE
+get_auto_14 (vector TYPE a)
+{
+  return (RTYPE) vec_extract (a, 14);
+}
+
+RTYPE
+get_auto_15 (vector TYPE a)
+{
+  return (RTYPE) vec_extract (a, 15);
+}
+
+#endif
+#endif
+#endif
+
+
+/* Tests for the normal case of vec_extract where the vector is in a register
+   and returning the result in a register as a return value.  */
+#ifdef DISABLE_INLINE_OF_GET_AUTO_N
+__attribute__ ((__noinline__))
+#else
+/* gcc issues warning: always_inline function might not be inlinable
+
+   __attribute__ ((__always_inline__))
+*/
+#endif
+RTYPE
+get_auto_n (vector TYPE a, ssize_t n)
+{
+  return (RTYPE) vec_extract (a, n);
+}
+
+typedef RTYPE (*auto_func_type) (vector TYPE);
+
+static auto_func_type get_auto_const[] = {
+  get_auto_0,
+  get_auto_1,
+#if ELEMENTS >= 4
+  get_auto_2,
+  get_auto_3,
+#if ELEMENTS >= 8
+  get_auto_4,
+  get_auto_5,
+  get_auto_6,
+  get_auto_7,
+#if ELEMENTS >= 16
+  get_auto_8,
+  get_auto_9,
+  get_auto_10,
+  get_auto_11,
+  get_auto_12,
+  get_auto_13,
+  get_auto_14,
+  get_auto_15,
+#endif
+#endif
+#endif
+};
+
+extern void do_auto (vector TYPE a) __attribute__((__noinline__));
+
+void
+do_auto (vector TYPE a)
+{
+  size_t i;
+
+  for (i = 1; i < 40; i += 3)
+    {
+      TRACE ("do_auto, i: ", i);
+      TRACE ("  get_auto_const[i] returns: ",
+	     (*get_auto_const [i % ELEMENTS]) (a));
+      TRACE ("  get_auto_n returns", get_auto_n (a, i));
+      check (get_auto_n (a, i), (*get_auto_const [i % ELEMENTS]) (a));
+    }
+}
+
+
+
+/* Main program to test all of the possibilities.  */
+int
+main (void)
+{
+  size_t i;
+  vector TYPE x = INITIAL;
+  vector TYPE *p, *p2, a, y;
+  vector TYPE z[2];
+
+  a = deoptimize (x);
+
+  do_auto (a);
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-17a.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-17a.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-17a.c	(revision 0)
@@ -0,0 +1,157 @@ 
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target dfp_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-maltivec" } */
+
+/* This test should run the same on any target that supports altivec/dfp
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define CONST0		(0)
+#define CONST1		(1)
+#define CONST2		(2)
+#define CONST3		(3)
+#define CONST4		(4)
+#define CONST5		(5)
+#define CONST6		(6)
+#define CONST7		(7)
+
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+unsigned short s3 (vector unsigned short v)
+{
+  return __builtin_vec_extract (v, 3);
+}
+
+unsigned short s7 (vector unsigned short v)
+{
+  return __builtin_vec_extract (v, 7);
+}
+
+unsigned short s21 (vector unsigned short v)
+{
+  return __builtin_vec_extract (v, 21);
+}
+
+unsigned short s30 (vector unsigned short v)
+{
+  return __builtin_vec_extract (v, 30);
+}
+
+/* Test for vector residing in memory.  */
+unsigned short ms3 (vector unsigned short *vp)
+{
+  return __builtin_vec_extract (*vp, 3);
+}
+
+unsigned short ms7 (vector unsigned short *vp)
+{
+  return __builtin_vec_extract (*vp, 7);
+}
+
+unsigned short ms21 (vector unsigned short *vp)
+{
+  return __builtin_vec_extract (*vp, 21);
+}
+
+unsigned short ms30 (vector unsigned short *vp)
+{
+  return __builtin_vec_extract (*vp, 30);
+}
+
+/* Test the same with variable indices.  */
+
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+unsigned short ci (vector unsigned short v, int i)
+{
+  return __builtin_vec_extract (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+__attribute__((noinline))
+unsigned short mci (vector unsigned short *vp, int i)
+{
+  return __builtin_vec_extract (*vp, i);
+}
+
+
+int main (int argc, unsigned short *argv[]) {
+  vector unsigned short sv = {
+    CONST0, CONST1, CONST2, CONST3, CONST4, CONST5, CONST6, CONST7 };
+  unsigned short s;
+
+  s = s3 (sv);
+  if (s != CONST3)
+    abort ();
+
+  s = s7 (sv);
+  if (s != CONST7)
+    abort ();
+
+  s = s21 (sv);
+  if (s != CONST5)
+    abort ();
+
+  s = s30 (sv);
+  if (s != CONST6)
+    abort ();
+
+  s = ms3 (&sv);
+  if (s != CONST3)
+    abort ();
+
+  s = ms7 (&sv);
+  if (s != CONST7)
+    abort ();
+
+  s = ms21 (&sv);
+  if (s != CONST5)
+    abort ();
+
+  s = ms30 (&sv);
+  if (s != CONST6)
+    abort ();
+
+  s = ci (sv, 5);
+  if (s != CONST5)
+    abort ();
+
+  s = ci (sv, 2);
+  if (s != CONST2)
+    abort ();
+
+  s = ci (sv, 15);
+  if (s != CONST7)
+    abort ();
+
+  s = ci (sv, 28);
+  if (s != CONST4)
+    abort ();
+
+  s = mci (&sv, 5);
+  if (s != CONST5)
+    abort ();
+
+  s = mci (&sv, 12);
+  if (s != CONST4)
+    abort ();
+
+  s = mci (&sv, 25);
+  if (s != CONST1)
+    abort ();
+
+  s = mci (&sv, 16);
+  if (s != CONST0)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-18b.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-18b.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-18b.c	(revision 0)
@@ -0,0 +1,151 @@ 
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target dfp_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-maltivec -O3" } */
+
+/* This test should run the same on any target that supports altivec/dfp
+   instructions.  Unsigned Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define CONST0		(0)
+#define CONST1		(1)
+#define CONST2		(2)
+#define CONST3		(3)
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+unsigned int s3 (vector unsigned int v)
+{
+  return __builtin_vec_extract (v, 3);
+}
+
+unsigned int s1 (vector unsigned int v)
+{
+  return __builtin_vec_extract (v, 1);
+}
+
+unsigned int s21 (vector unsigned int v)
+{
+  return __builtin_vec_extract (v, 21);
+}
+
+unsigned int s30 (vector unsigned int v)
+{
+  return __builtin_vec_extract (v, 30);
+}
+
+/* Test for vector residing in memory.  */
+unsigned int ms3 (vector unsigned int *vp)
+{
+  return __builtin_vec_extract (*vp, 3);
+}
+
+unsigned int ms1(vector unsigned int *vp)
+{
+  return __builtin_vec_extract (*vp, 1);
+}
+
+unsigned int ms21(vector unsigned int *vp)
+{
+  return __builtin_vec_extract (*vp, 21);
+}
+
+unsigned int ms30(vector unsigned int *vp)
+{
+  return __builtin_vec_extract (*vp, 30);
+}
+
+/* Test the same with variable indices.  */
+
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+unsigned int ci (vector unsigned int v, int i)
+{
+  return __builtin_vec_extract (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+__attribute__((noinline))
+unsigned int mci(vector unsigned int *vp, int i)
+{
+  return __builtin_vec_extract (*vp, i);
+}
+
+
+unsigned int main (int argc, unsigned char *argv[]) {
+  vector unsigned int sv = { CONST0, CONST1, CONST2, CONST3 };
+  unsigned int s;
+
+  s = s3 (sv);
+  if (s != CONST3)
+    abort ();
+
+  s = s1 (sv);
+  if (s != CONST1)
+    abort ();
+
+  s = s21 (sv);
+  if (s != CONST1)
+    abort ();
+
+  s = s30 (sv);
+  if (s != CONST2)
+    abort ();
+
+  s = ms3 (&sv);
+  if (s != CONST3)
+    abort ();
+
+  s = ms1 (&sv);
+  if (s != CONST1)
+    abort ();
+
+  s = ms21 (&sv);
+  if (s != CONST1)
+    abort ();
+
+  s = ms30 (&sv);
+  if (s != CONST2)
+    abort ();
+
+  s = ci (sv, 5);
+  if (s != CONST1)
+    abort ();
+
+  s = ci (sv, 2);
+  if (s != CONST2)
+    abort ();
+
+  s = ci (sv, 15);
+  if (s != CONST3)
+    abort ();
+
+  s = ci (sv, 28);
+  if (s != CONST0)
+    abort ();
+
+  s = mci (&sv, 5);
+  if (s != CONST1)
+    abort ();
+
+  s = mci (&sv, 12);
+  if (s != CONST0)
+    abort ();
+
+  s = mci (&sv, 25);
+  if (s != CONST1)
+    abort ();
+
+  s = mci (&sv, 16);
+  if (s != CONST0)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-19a.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-19a.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-19a.c	(revision 0)
@@ -0,0 +1,111 @@ 
+/* { dg-do run { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { } } */
+/* { dg-options "-mvsx" } */
+
+/* This test should run the same on any target that supports vsx
+   instructions.  Intentionally not specifying cpu in order to test
+   all code generation paths.  */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define CONST0		(31415926539LL)
+#define CONST1		(2 * 31415926539LL)
+
+/* Test that indices > length of vector are applied modulo the vector
+   length.  */
+
+/* Test for vector residing in register.  */
+unsigned long long int e0 (vector unsigned long long int v)
+{
+  return __builtin_vec_extract (v, 0);
+}
+
+unsigned long long int e3 (vector unsigned long long int v)
+{
+  return __builtin_vec_extract (v, 3);
+}
+
+/* Test for vector residing in memory.  */
+unsigned long long int me0 (vector unsigned long long int *vp)
+{
+  return __builtin_vec_extract (*vp, 0);
+}
+
+unsigned long long int me3 (vector unsigned long long int *vp)
+{
+  return __builtin_vec_extract (*vp, 3);
+}
+
+/* Test the same with variable indices.  */
+
+/* Test for variable selector and vector residing in register.  */
+__attribute__((noinline))
+unsigned long long int ei (vector unsigned long long int v, int i)
+{
+  return __builtin_vec_extract (v, i);
+}
+
+/* Test for variable selector and vector residing in memory.  */
+unsigned long long int mei (vector unsigned long long int *vp, int i)
+{
+  return __builtin_vec_extract (*vp, i);
+}
+
+int main (int argc, char *argv[]) {
+  vector unsigned long long int dv = { CONST0, CONST1 };
+  unsigned long long int d;
+
+  d = e0 (dv);
+  if (d != CONST0)
+    abort ();
+
+  d = e3 (dv);
+  if (d != CONST1)
+    abort ();
+
+  d = me0 (&dv);
+  if (d != CONST0)
+    abort ();
+
+  d = me3 (&dv);
+  if (d != CONST1)
+    abort ();
+
+  d = ei (dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 1);
+  if (d != CONST1)
+    abort ();
+
+  d = ei (dv, 2);
+  if (d != CONST0)
+    abort ();
+
+  d = ei (dv, 3);
+  if (d != CONST1)
+    abort ();
+
+  d = mei (&dv, 0);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 1);
+  if (d != CONST1)
+    abort ();
+
+  d = mei (&dv, 2);
+  if (d != CONST0)
+    abort ();
+
+  d = mei (&dv, 3);
+  if (d != CONST1)
+    abort ();
+
+  return 0;
+}
Index: gcc/config/rs6000/rs6000-c.c
===================================================================
--- gcc/config/rs6000/rs6000-c.c	(revision 269370)
+++ gcc/config/rs6000/rs6000-c.c	(working copy)
@@ -6568,9 +6568,15 @@ 
 	  /* If the second argument is an integer constant, if the value is in
 	     the expected range, generate the built-in code if we can.  We need
 	     64-bit and direct move to extract the small integer vectors.  */
-	  if (TREE_CODE (arg2) == INTEGER_CST
-	      && wi::ltu_p (wi::to_wide (arg2), nunits))
+
+	  if (TREE_CODE (arg2) == INTEGER_CST)
 	    {
+	      if (!wi::ltu_p (wi::to_wide (arg2), nunits))
+		{
+		  wide_int selector = wi::to_wide (arg2);
+		  selector = wi::umod_trunc (selector, nunits);
+		  arg2 = wide_int_to_tree (TREE_TYPE (arg2), selector);
+		}
 	      switch (mode)
 		{
 		default:
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 269370)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -6894,7 +6894,6 @@ 
 	default:
 	  break;
 	case E_V1TImode:
-	  gcc_assert (INTVAL (elt) == 0 && inner_mode == TImode);
 	  emit_move_insn (target, gen_lowpart (TImode, vec));
 	  break;
 	case E_V2DFmode:
@@ -6974,18 +6973,32 @@ 
 	}
     }
 
-  gcc_assert (CONST_INT_P (elt));
-
   /* Allocate mode-sized buffer.  */
   mem = assign_stack_temp (mode, GET_MODE_SIZE (mode));
 
   emit_move_insn (mem, vec);
+  if (CONST_INT_P (elt))
+    {
+      int modulo_elt = INTVAL (elt) % GET_MODE_NUNITS (mode);
 
-  /* Add offset to field within buffer matching vector element.  */
-  mem = adjust_address_nv (mem, inner_mode,
-			   INTVAL (elt) * GET_MODE_SIZE (inner_mode));
+      /* Add offset to field within buffer matching vector element.  */
+      mem = adjust_address_nv (mem, inner_mode,
+			       modulo_elt * GET_MODE_SIZE (inner_mode));
+      emit_move_insn (target, adjust_address_nv (mem, inner_mode, 0));
+    }
+  else
+    {
+      unsigned int ele_size = GET_MODE_SIZE (inner_mode);
+      rtx num_ele_m1 = GEN_INT (GET_MODE_NUNITS (mode) - 1);
+      rtx new_addr = gen_reg_rtx (Pmode);
 
-  emit_move_insn (target, adjust_address_nv (mem, inner_mode, 0));
+      elt = gen_rtx_AND (Pmode, elt, num_ele_m1);
+      if (ele_size > 1)
+	elt = gen_rtx_MULT (Pmode, elt, GEN_INT (ele_size));
+      new_addr = gen_rtx_PLUS (Pmode, XEXP (mem, 0), elt);
+      new_addr = change_address (mem, inner_mode, new_addr);
+      emit_move_insn (target, new_addr);
+    }
 }
 
 /* Adjust a memory address (MEM) of a vector type to point to a scalar field
@@ -7165,6 +7178,10 @@ 
      systems.  */
   if (MEM_P (src))
     {
+      int num_elements = GET_MODE_NUNITS (mode);
+      rtx num_ele_m1 = GEN_INT (num_elements - 1);
+
+      emit_insn (gen_anddi3 (element, element, num_ele_m1));
       gcc_assert (REG_P (tmp_gpr));
       emit_move_insn (dest, rs6000_adjust_vec_address (dest, src, element,
 						       tmp_gpr, scalar_mode));
@@ -7173,7 +7190,9 @@ 
 
   else if (REG_P (src) || SUBREG_P (src))
     {
-      int bit_shift = byte_shift + 3;
+      int num_elements = GET_MODE_NUNITS (mode);
+      int bits_in_element = 128 / num_elements;
+      int bit_shift = 7 - exact_log2 (num_elements);
       rtx element2;
       unsigned int dest_regno = reg_or_subregno (dest);
       unsigned int src_regno = reg_or_subregno (src);
@@ -7249,7 +7268,7 @@ 
 	{
 	  if (!BYTES_BIG_ENDIAN)
 	    {
-	      rtx num_ele_m1 = GEN_INT (GET_MODE_NUNITS (mode) - 1);
+	      rtx num_ele_m1 = GEN_INT (num_elements - 1);
 
 	      emit_insn (gen_anddi3 (tmp_gpr, element, num_ele_m1));
 	      emit_insn (gen_subdi3 (tmp_gpr, num_ele_m1, tmp_gpr));
@@ -7307,8 +7326,8 @@ 
 	    emit_insn (gen_vsx_vslo_v2di (tmp_altivec_di, src_v2di,
 					  tmp_altivec));
 	    emit_move_insn (tmp_gpr_di, tmp_altivec_di);
-	    emit_insn (gen_ashrdi3 (tmp_gpr_di, tmp_gpr_di,
-				    GEN_INT (64 - (8 * scalar_size))));
+	    emit_insn (gen_lshrdi3 (tmp_gpr_di, tmp_gpr_di,
+				    GEN_INT (64 - bits_in_element)));
 	    return;
 	  }
 
@@ -14724,8 +14743,18 @@ 
   op1 = expand_normal (arg1);
 
   /* Call get_element_number to validate arg1 if it is a constant.  */
+
   if (TREE_CODE (arg1) == INTEGER_CST)
-    (void) get_element_number (TREE_TYPE (arg0), arg1);
+    {
+      unsigned HOST_WIDE_INT elt;
+      unsigned HOST_WIDE_INT size = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
+      unsigned int truncated_selector;
+      if (!tree_fits_uhwi_p (arg1))
+	error ("selector must fit in HOST_WIDE_INT");
+      elt = tree_to_uhwi (arg1);
+      truncated_selector = elt % size;
+      op1 = GEN_INT (truncated_selector);
+    }
 
   tmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
   mode0 = TYPE_MODE (TREE_TYPE (arg0));