2017-09-15 Jakub Jelinek Backported from mainline 2017-09-12 Jakub Jelinek 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 + +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 + +__attribute__((aligned (16))) extern const unsigned char c[16]; + +void +foo (void) +{ + vec_ld (0, c); +}