Hi! On Thu, Sep 07, 2017 at 10:40:30AM +0200, Jakub Jelinek wrote: > The C and C++ FE handle resolve_overloaded_builtin differently, the C FE > calls it when e.g. array-to-pointer and function-to-pointer conversions > are already done on the arguments, while C++ FE does that only much later. > The c-common code e.g. for __sync/__atomic builtins deals with > that e.g. by: > if (TREE_CODE (type) == ARRAY_TYPE) > { > /* Force array-to-pointer decay for C++. */ > gcc_assert (c_dialect_cxx()); > (*params)[0] = default_conversion ((*params)[0]); > type = TREE_TYPE ((*params)[0]); > } > while the rs6000 md hook uses default_conversion only in one spot (the > generic handling), but for vec_ld and vec_st does something on its own. > What is even worse is that for vec_ld, it does that too late, there is > a fold_convert in between for the case where the element type is > qualified, and that only works if the argument is pointer, not array > (in which case it ICEs). > So, the following patch moves the vec_ld conversion earlier and for both > vec_ld and vec_st uses what c-common as well as later > altivec_resolve_overloaded_builtin uses. > > Bootstrapped/regtested on powerpc64-linux (regtest with {,-m32}), ok for > trunk?
Here is an updated version of that patch, fixed for the C90 non-lvalue arrays (which we want to reject as c-family rejects them for __atomic_* etc.). Bootstrapped/regtested on powerpc64-linux (regtest with {,-m32}), ok for trunk? 2017-09-12 Jakub Jelinek <ja...@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.jj 2017-09-08 09:13:59.863591547 +0200 +++ gcc/config/rs6000/rs6000-c.c 2017-09-08 09:16:36.354738183 +0200 @@ -6480,7 +6480,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); @@ -6500,15 +6506,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, @@ -6563,12 +6560,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.jj 2017-09-08 09:20:35.187912843 +0200 +++ gcc/testsuite/gcc.target/powerpc/pr82112.c 2017-09-08 09:24:21.362376676 +0200 @@ -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.jj 2017-09-08 09:15:20.593774717 +0200 +++ gcc/testsuite/g++.dg/ext/altivec-18.C 2017-09-08 09:15:20.593774717 +0200 @@ -0,0 +1,14 @@ +// PR target/82112 +// { dg-do compile { target powerpc*-*-* } } +// { dg-require-effective-target powerpc_altivec_ok } +// { dg-options "-save-temps -maltivec" } + +#include <altivec.h> + +__attribute__((aligned (16))) extern const unsigned char c[16]; + +void +foo (void) +{ + vec_ld (0, c); +} Jakub