Hi!

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?

2017-09-07  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.

        * g++.dg/ext/altivec-18.C: New test.

--- gcc/config/rs6000/rs6000-c.c.jj     2017-09-01 09:26:55.000000000 +0200
+++ gcc/config/rs6000/rs6000-c.c        2017-09-06 15:43:11.719590365 +0200
@@ -6478,7 +6478,14 @@ 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)
+       {
+         /* Force array-to-pointer decay for C++.  */
+         gcc_assert (c_dialect_cxx ());
+         arg1 = default_conversion (arg1);
+         arg1_type = TREE_TYPE (arg1);
+       }
+      if (!POINTER_TYPE_P (arg1_type))
        goto bad;
 
       tree inner_type = TREE_TYPE (arg1_type);
@@ -6498,15 +6505,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,10 +6561,10 @@ altivec_resolve_overloaded_builtin (loca
          tree arg2_type = TREE_TYPE (arg2);
          if (TREE_CODE (arg2_type) == ARRAY_TYPE)
            {
-             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++.  */
+             gcc_assert (c_dialect_cxx ());
+             arg2 = default_conversion (arg2);
+             arg2_type = TREE_TYPE (arg2);
            }
 
          /* Find the built-in to make sure a compatible one exists; if not
--- gcc/testsuite/g++.dg/ext/altivec-18.C.jj    2017-09-06 15:45:00.673295858 
+0200
+++ gcc/testsuite/g++.dg/ext/altivec-18.C       2017-09-06 15:45:36.274872713 
+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

Reply via email to