Hello,

Please ignore this patch as, v3 of the patch has been sent.
https://patchwork.sourceware.org/project/gcc/patch/[email protected]/
This patch was also missing the correct patch version in the subject header. it 
should have been marked as v2.


Thanks.
Kishan

On 30/09/26 7:27 pm, Kishan Parmar wrote:
> Hello All,
>
> Changes from V1:
>       - Dropped rs6000-c.cc change. Resolver needs no modification
>         since v2 does not have opaque instance entries.
>       - Dropped isopaque field on typeinfo and the corresponding
>         complete_vector_type() change; opaque string is now built in
>         a self-contained helper make_opaque_fndecl().
>       - Dropped parse_first_ovld_entry() and
>         maybe_generate_opaque_variant(). v2 does not insert synthetic
>         ovlddata entries into the ovlds[] array.
>       - Removed the _VOP / __VOP enum entries and the wrong bifids
>         they introduced.
>
> Thank You,
> Kishan
>
> Before r12-5752 (gd08236359eb229), the public overload declaration for
> overloaded PowerPC built-in functions used opaque_V4SI_type_node for all
> vector argument and return types.  The C front end's compatibility check
> (vector_types_convertible_p in c-family/c-common.cc) has an early-exit
> for TYPE_VECTOR_OPAQUE types, so mis-typed vector arguments were passed
> silently at that stage and left for altivec_resolve_overloaded_builtin()
> to diagnose properly.
>
> r12-5752 switched the new built-in generator to register each overload's
> public declaration using the concrete vector type of the first instance
> prototype.  This reactivated the front end's early vector-type
> check, causing a spurious "use -flax-vector-conversions to permit
> conversions between vectors with differing element types"
> note before the overload resolver ran, obscuring the real diagnostic
> such as "too few arguments".
>
> Fix this in rs6000-gen-builtins.cc by restoring the opaque prototype for
> the public overload declaration whenever the overload has by-value
> vector arguments or a by-value vector return type.  A new "vop4si"
> entry is added to type_map[], mapping to opaque_V4SI_type_node, and a
> new helper make_opaque_fndecl() builds the function-type identifier
> string with every by-value vector position replaced by "vop4si".
> Vector-pointer arguments (e.g. vsc *) remain as it was, because
> front-end's pointer-type check does not emit the 
> -flax-vector-conversions note anyway.
>
> 2026-09-30  Kishan Parmar  <[email protected]>
>
> gcc/ChangeLog:
>       * config/rs6000/rs6000-gen-builtins.cc (type_map): Add "vop4si"
>       entry mapping to opaque_V4SI.
>       (make_opaque_fndecl): New function.  Build a function-type
>       identifier string like construct_fntype_id() but with every
>       by-value vector position replaced by "vop4si".
>       (proto_has_vector_arg): New function.  Return true if a
>       prototype has at least one vector argument.
>       (write_init_ovld_table): Introduce reg_fndecl. Use
>       make_opaque_fndecl() for the public overload declaration when
>       the stanza has vector arguments, otherwise use the first
>       instance's concrete fndecl as before.  Update the generated
>       comment in the output file.  Free reg_fndecl after use when
>       it was malloc'd by make_opaque_fndecl().
>       (write_init_file): Add pre-pass loop to call
>       make_opaque_fndecl() for every stanza with vector arguments
>       before the fntype_rbt inorder walk, so that the opaque type
>       strings are declared before they are used.
>
> gcc/testsuite/ChangeLog:
>       * gcc.target/powerpc/pr104930.c: New test.
> ---
>  gcc/config/rs6000/rs6000-gen-builtins.cc | 179 ++++++++++++++++++++++-
>  1 file changed, 171 insertions(+), 8 deletions(-)
>
> diff --git a/gcc/config/rs6000/rs6000-gen-builtins.cc 
> b/gcc/config/rs6000/rs6000-gen-builtins.cc
> index 08068ba78fd..76dd33bbb90 100644
> --- a/gcc/config/rs6000/rs6000-gen-builtins.cc
> +++ b/gcc/config/rs6000/rs6000-gen-builtins.cc
> @@ -600,6 +600,7 @@ static typemap type_map[] =
>      { "v4sf",                "V4SF" },
>      { "v4si",                "V4SI" },
>      { "v8hi",                "V8HI" },
> +    { "vop4si",              "opaque_V4SI" },
>      { "vp8hi",               "pixel_V8HI" },
>    };
>  
> @@ -2772,15 +2773,145 @@ write_init_bif_table (void)
>      }
>  }
>  
> +/* Build a function-type identifier string like construct_fntype_id() does,
> +   but replace every by-value vector position with "vop4si" (opaque_V4SI).
> +   This string is used as the public overload declaration so the C front end
> +   does not complain about vector type mismatches before the overload 
> resolver
> +   runs (PR target/104930).
> +
> +   Rules for each position:
> +     - by-value vector (isvector=1, ispointer=0): use "vop4si".
> +     - vector pointer (isvector=1, ispointer=1): As it was, e.g. "pv16qi".
> +       Pointer arguments never trigger the -flax-vector-conversions note 
> anyway.
> +     - everything else: same as construct_fntype_id(), no change.  */
> +
> +static char *
> +make_opaque_fndecl (prototype *protoptr)
> +{
> +  /* Use the same size estimate as construct_fntype_id.  "vop4si" is 6 chars,
> +     same worst-case length as "bv16qi", within the 9-char per-type budget.  
> */
> +  int len = protoptr->nargs ? (protoptr->nargs + 1) * 9 + 6 : 17;
> +  char *buf = (char *) malloc (len);
> +  int bufi = 0;
> +
> +  //  Return type
> +  if (protoptr->rettype.ispointer)
> +    buf[bufi++] = 'p';
> +
> +  if (protoptr->rettype.isvoid)
> +    buf[bufi++] = 'v';
> +  else if (protoptr->rettype.isvector && !protoptr->rettype.ispointer)
> +    {
> +      memcpy (&buf[bufi], "vop4si", 6);
> +      bufi += 6;
> +    }
> +  else
> +    {
> +      /* Scalar return, or vector-pointer return (e.g. vsc *): emit
> +      the concrete type, identical to construct_fntype_id().  */
> +      if (protoptr->rettype.isunsigned)
> +     buf[bufi++] = 'u';
> +      if (protoptr->rettype.isvector)
> +     complete_vector_type (&protoptr->rettype, buf, &bufi);
> +      else
> +     complete_base_type (&protoptr->rettype, buf, &bufi);
> +    }
> +
> +  memcpy (&buf[bufi], "_ftype", 6);
> +  bufi += 6;
> +
> +  // Argument types
> +  if (!protoptr->nargs)
> +    {
> +      memcpy (&buf[bufi], "_v", 2);
> +      bufi += 2;
> +    }
> +  else
> +    {
> +      typelist *argptr = protoptr->args;
> +      for (int i = 0; i < protoptr->nargs; i++, argptr = argptr->next)
> +     {
> +       assert (argptr);
> +       buf[bufi++] = '_';
> +
> +       if (argptr->info.isvector && !argptr->info.ispointer)
> +         {
> +           memcpy (&buf[bufi], "vop4si", 6);
> +           bufi += 6;
> +         }
> +       else
> +         {
> +           /* Non-vector argument, or vector-pointer argument (e.g. vsc *,
> +              const vbc *): emit the concrete type, identical to
> +              construct_fntype_id().  */
> +           if (argptr->info.isconst
> +               && argptr->info.base == BT_INT
> +               && !argptr->info.ispointer)
> +             {
> +               buf[bufi++] = 'c';
> +               buf[bufi++] = 'i';
> +               continue;
> +             }
> +           if (argptr->info.ispointer)
> +             {
> +               if (argptr->info.isvoid)
> +                 {
> +                   if (argptr->info.isconst)
> +                     {
> +                       memcpy (&buf[bufi], "pcvoid", 6);
> +                       bufi += 6;
> +                       continue;
> +                     }
> +                   else
> +                     {
> +                       buf[bufi++] = 'p';
> +                       buf[bufi++] = 'v';
> +                       continue;
> +                     }
> +                 }
> +               else
> +                 buf[bufi++] = 'p';
> +             }
> +           if (argptr->info.isunsigned)
> +             buf[bufi++] = 'u';
> +           if (argptr->info.isvector)
> +             complete_vector_type (&argptr->info, buf, &bufi);
> +           else
> +             complete_base_type (&argptr->info, buf, &bufi);
> +         }
> +     }
> +      assert (!argptr);
> +    }
> +
> +  buf[bufi] = '\0';
> +
> +  rbt_insert (&fntype_rbt, buf);
> +
> +  return buf;
> +}
> +
> +/* Return true if PROTOPTR has at least one vector argument.  */
> +static bool
> +proto_has_vector_arg (prototype *protoptr)
> +{
> +  for (typelist *arg = protoptr->args; arg; arg = arg->next)
> +    if (arg->info.isvector)
> +      return true;
> +  return false;
> +}
> +
>  /* Write code to initialize the overload table.  */
>  static void
>  write_init_ovld_table (void)
>  {
>    fprintf (init_file, "  int base = RS6000_OVLD_NONE;\n\n");
>    fprintf (init_file,
> -        "  /* The fndecl for an overload is arbitrarily the first one\n"
> -        "     for the overload.  We sort out the real types when\n"
> -        "     processing the overload in the gcc front end.  */\n");
> +        "  /* The fndecl for the public overload declaration is an opaque-\n"
> +        "     typed prototype when the overload has vector arguments.  
> This\n"
> +        "     avoids a spurious -flax-vector-conversions note in the C/C++\n"
> +        "     front end before altivec_resolve_overloaded_builtin() runs.\n"
> +        "     See PR target/104930.  For overloads without vector 
> arguments\n"
> +        "     the first instance's concrete type is used, as before.  */\n");
>  
>    for (int i = 0; i <= curr_ovld; i++)
>      {
> @@ -2794,16 +2925,33 @@ write_init_ovld_table (void)
>         ovld_stanza *stanza = &ovld_stanzas[ovlds[i].stanza];
>         fprintf (init_file, "\n");
>  
> +       /* If this stanza has vector arguments, register its public
> +          declaration with an opaque prototype so that the front end's
> +          early argument-type check does not fire before the overload
> +          resolver can inspect the actual argument types.  Otherwise
> +          use the first instance's concrete fndecl, as before.
> +          make_opaque_fndecl() returns a malloc'd buffer, on duplicate
> +          the RBT did not take ownership so we must free it after use.  */
> +       char *reg_fndecl;
> +       bool free_reg_fndecl = false;
> +       if (proto_has_vector_arg (&ovlds[i].proto))
> +         {
> +           reg_fndecl = make_opaque_fndecl (&ovlds[i].proto);
> +           free_reg_fndecl = true;
> +         }
> +       else
> +         reg_fndecl = ovlds[i].fndecl;
> +
>         /* Check whether we have a "tf" token in this string, representing
>            a float128_type_node.  It's possible that float128_type_node is
>            undefined (occurs for -maltivec -mno-vsx, for example), so we
>            must guard against that.  */
> -       int tf_found = strstr (ovlds[i].fndecl, "tf") != NULL;
> +       int tf_found = strstr (reg_fndecl, "tf") != NULL;
>  
>         /* Similarly, look for decimal float tokens.  */
> -       int dfp_found = (strstr (ovlds[i].fndecl, "sd") != NULL
> -                        || strstr (ovlds[i].fndecl, "dd") != NULL
> -                        || strstr (ovlds[i].fndecl, "td") != NULL);
> +       int dfp_found = (strstr (reg_fndecl, "sd") != NULL
> +                        || strstr (reg_fndecl, "dd") != NULL
> +                        || strstr (reg_fndecl, "td") != NULL);
>  
>         if (tf_found)
>           {
> @@ -2824,7 +2972,7 @@ write_init_ovld_table (void)
>                  stanza->intern_name);
>         fprintf (init_file,
>                  "                            %s,\n",
> -                ovlds[i].fndecl);
> +                reg_fndecl);
>         fprintf (init_file,
>                  "                            (int)RS6000_OVLD_%s,"
>                  " BUILT_IN_MD,\n",
> @@ -2844,6 +2992,9 @@ write_init_ovld_table (void)
>         fprintf (init_file,
>                  "    = RS6000_INST_%s;\n\n",
>                  ovlds[i].ovld_id_name);
> +
> +       if (free_reg_fndecl)
> +         free (reg_fndecl);
>       }
>      }
>  }
> @@ -2871,6 +3022,18 @@ write_init_file (void)
>    write_bif_static_init ();
>    write_ovld_static_init ();
>  
> +  /*   We call make_opaque_fndecl() here first (before the RBT walk below)
> +     so that the opaque type strings land in fntype_rbt in time for
> +     write_fntype_init() to emit their tree-variable declarations.
> +     write_init_ovld_table() calls make_opaque_fndecl() a second time to
> +     get the string for fprintf,that second rbt_insert() is a no-op
> +     since the string is already in the tree.  Two calls, but the second
> +     one is cheap and avoids storing extra pointers in ovld_stanzas.  */
> +  for (int i = 0; i <= curr_ovld; i++)
> +    if (i == 0 || ovlds[i].stanza != ovlds[i-1].stanza)
> +      if (proto_has_vector_arg (&ovlds[i].proto))
> +     make_opaque_fndecl (&ovlds[i].proto);
> +
>    /* The reason to pass pointers to the function instead of accessing
>       the rs6000_{{builtin,instance}_info_fntype,overload_info,builtin_decls}
>       arrays directly is to decrease size of the already large function and

Reply via email to