Blob Blame History Raw
2017-09-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-09-12  Jakub Jelinek  <jakub@redhat.com>

	PR target/82112
	* config/rs6000/rs6000-c.c (altivec_resolve_overloaded_builtin): For
	ALTIVEC_BUILTIN_VEC_LD if arg1 has array type call default_conversion
	on it early, rather than manual conversion late.  For
	ALTIVEC_BUILTIN_VEC_ST if arg2 has array type call default_conversion
	instead of performing manual conversion.

	* gcc.target/powerpc/pr82112.c: New test.
	* g++.dg/ext/altivec-18.C: New test.

--- gcc/config/rs6000/rs6000-c.c	(revision 252027)
+++ gcc/config/rs6000/rs6000-c.c	(revision 252028)
@@ -6489,7 +6489,13 @@ altivec_resolve_overloaded_builtin (loca
 
       /* Strip qualifiers like "const" from the pointer arg.  */
       tree arg1_type = TREE_TYPE (arg1);
-      if (!POINTER_TYPE_P (arg1_type) && TREE_CODE (arg1_type) != ARRAY_TYPE)
+      if (TREE_CODE (arg1_type) == ARRAY_TYPE && c_dialect_cxx ())
+	{
+	  /* Force array-to-pointer decay for C++.  */
+	  arg1 = default_conversion (arg1);
+	  arg1_type = TREE_TYPE (arg1);
+	}
+      if (!POINTER_TYPE_P (arg1_type))
 	goto bad;
 
       tree inner_type = TREE_TYPE (arg1_type);
@@ -6509,15 +6515,6 @@ altivec_resolve_overloaded_builtin (loca
 	  if (!ptrofftype_p (TREE_TYPE (arg0)))
 	    arg0 = build1 (NOP_EXPR, sizetype, arg0);
 
-	  tree arg1_type = TREE_TYPE (arg1);
-	  if (TREE_CODE (arg1_type) == ARRAY_TYPE)
-	    {
-	      arg1_type = TYPE_POINTER_TO (TREE_TYPE (arg1_type));
-	      tree const0 = build_int_cstu (sizetype, 0);
-	      tree arg1_elt0 = build_array_ref (loc, arg1, const0);
-	      arg1 = build1 (ADDR_EXPR, arg1_type, arg1_elt0);
-	    }
-
 	  tree addr = fold_build2_loc (loc, POINTER_PLUS_EXPR, arg1_type,
 				       arg1, arg0);
 	  tree aligned = fold_build2_loc (loc, BIT_AND_EXPR, arg1_type, addr,
@@ -6572,12 +6569,11 @@ altivec_resolve_overloaded_builtin (loca
 	    arg1 = build1 (NOP_EXPR, sizetype, arg1);
 
 	  tree arg2_type = TREE_TYPE (arg2);
-	  if (TREE_CODE (arg2_type) == ARRAY_TYPE)
+	  if (TREE_CODE (arg2_type) == ARRAY_TYPE && c_dialect_cxx ())
 	    {
-	      arg2_type = TYPE_POINTER_TO (TREE_TYPE (arg2_type));
-	      tree const0 = build_int_cstu (sizetype, 0);
-	      tree arg2_elt0 = build_array_ref (loc, arg2, const0);
-	      arg2 = build1 (ADDR_EXPR, arg2_type, arg2_elt0);
+	      /* Force array-to-pointer decay for C++.  */
+	      arg2 = default_conversion (arg2);
+	      arg2_type = TREE_TYPE (arg2);
 	    }
 
 	  /* Find the built-in to make sure a compatible one exists; if not
--- gcc/testsuite/gcc.target/powerpc/pr82112.c	(nonexistent)
+++ gcc/testsuite/gcc.target/powerpc/pr82112.c	(revision 252028)
@@ -0,0 +1,16 @@
+/* PR target/82112 */
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-options "-maltivec -std=gnu90" } */
+
+#include <altivec.h>
+
+struct __attribute__((aligned (16))) S { unsigned char c[64]; } bar (void);
+vector unsigned char v;
+
+void
+foo (void)
+{
+  vec_ld (0, bar ().c);	/* { dg-error "invalid parameter combination for AltiVec intrinsic" } */
+  vec_st (v, 0, bar ().c);	/* { dg-error "invalid parameter combination for AltiVec intrinsic" } */
+}
--- gcc/testsuite/g++.dg/ext/altivec-18.C	(nonexistent)
+++ gcc/testsuite/g++.dg/ext/altivec-18.C	(revision 252028)
@@ -0,0 +1,14 @@
+// PR target/82112
+// { dg-do compile { target powerpc*-*-* } }
+// { dg-require-effective-target powerpc_altivec_ok }
+// { dg-options "-maltivec" }
+
+#include <altivec.h>
+
+__attribute__((aligned (16))) extern const unsigned char c[16];
+
+void
+foo (void)
+{
+  vec_ld (0, c);
+}