I create a pr in https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/455, 
maybe we can discuss it there.

Zhijin,
Thanks.

> From: "Kito Cheng"<kito.ch...@gmail.com>
> Date:  Tue, Nov 26, 2024, 23:41
> Subject:  Re: [RFC][PATCH] RISC-V: Support 
> TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN
> To: "Zhijin Zeng"<zhijin.z...@spacemit.com>
> Cc: <gcc-patches@gcc.gnu.org>
> Do you mind creating a PR to

> https://github.com/riscv/riscv-elf-psabi-doc/pull/ to start the

> discussion? I believe this should be documented somewhere since it

> should be consistent between LLVM and GCC.

> 
> On Mon, Nov 4, 2024 at 2:26 PM Zhijin Zeng <zhijin.z...@spacemit.com> wrote:

> >

> > I can't find the vector function name mangling of risc-v, so in order to

> > support TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN,

> > TARGET_SIMD_CLONE_ADJUST and TARGET_SIMD_CLONE_USABLE, I add risc-v

> > vector function mangling rules as follow:

> >

> >      _ZGV<x>N<y>v<v...>_<func_name>

> >

> >      'x' is the LMUL, if the LMUL is 1/2/4/8 and 'x' is 1/2/4/8.

> >      'y' is the count of elements also 'simdlen' in gcc.

> >      'v...' depends on the number of parameter, there are as many 'v'

> > characters as there are parameters.

> >      'func_name' is the scalar function name.

> >

> > Maybe it's incorrect or incomplete, but I think it's worhting

> > discussing. And combined with the glibc patch, we can use libmvec in risc-v.

> >

> > glibc patch:

> > https://inbox.sourceware.org/libc-alpha/af3aceaa-dcf1-4fa6-ad7e-a7fd7444a...@spacemit.com/

> >

> >

> > Thanks,

> >

> > Zhijin

> >

> >

> > diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc

> > index 0b3b2c4cba9..d181aae4ac7 100644

> > --- a/gcc/config/riscv/riscv.cc

> > +++ b/gcc/config/riscv/riscv.cc

> > @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.  If not see

> >

> >   #define INCLUDE_MEMORY

> >   #define INCLUDE_STRING

> > +#include <cmath>

> >   #include "config.h"

> >   #include "system.h"

> >   #include "coretypes.h"

> > @@ -34,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see

> >   #include "insn-config.h"

> >   #include "insn-attr.h"

> >   #include "recog.h"

> > +#include "cgraph.h"

> >   #include "output.h"

> >   #include "alias.h"

> >   #include "tree.h"

> > @@ -5787,7 +5789,9 @@ riscv_vector_type_p (const_tree type)

> >   {

> >     /* Currently, only builtin scalable vector type is allowed, in the

> > future,

> >        more vector types may be allowed, such as GNU vector type, etc.  */

> > -  return riscv_vector::builtin_type_p (type);

> > +  if (!type)

> > +    return false;

> > +  return riscv_vector::builtin_type_p (type) || VECTOR_TYPE_P (type);

> >   }

> >

> >   static unsigned int

> > @@ -12695,6 +12699,231 @@

> > riscv_stack_clash_protection_alloca_probe_range (void)

> >     return STACK_CLASH_CALLER_GUARD;

> >   }

> >

> > +/* Return true for types that could be supported as SIMD return or

> > +   argument types.  */

> > +

> > +static bool

> > +supported_simd_type (tree t)

> > +{

> > +  if (SCALAR_FLOAT_TYPE_P (t) || INTEGRAL_TYPE_P (t))

> > +    {

> > +      HOST_WIDE_INT s = tree_to_shwi (TYPE_SIZE_UNIT (t));

> > +      return s == 1 || s == 2 || s == 4 || s == 8;

> > +    }

> > +  return false;

> > +}

> > +

> > +static unsigned

> > +lane_size (cgraph_simd_clone_arg_type clone_arg_type, tree type)

> > +{

> > +  gcc_assert (clone_arg_type != SIMD_CLONE_ARG_TYPE_MASK);

> > +

> > +  if (INTEGRAL_TYPE_P (type)

> > +      || SCALAR_FLOAT_TYPE_P (type))

> > +    switch (TYPE_PRECISION (type) / BITS_PER_UNIT)

> > +      {

> > +      default:

> > +       break;

> > +      case 1:

> > +      case 2:

> > +      case 4:

> > +      case 8:

> > +       return TYPE_PRECISION (type);

> > +      }

> > +  gcc_unreachable ();

> > +}

> > +

> > +/* Implement TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN.  */

> > +

> > +static int

> > +riscv_simd_clone_compute_vecsize_and_simdlen (struct cgraph_node *node,

> > +                                       struct cgraph_simd_clone *clonei,

> > +                                       tree base_type ATTRIBUTE_UNUSED,

> > +                                       int num, bool explicit_p)

> > +{

> > +  tree t, ret_type;

> > +  unsigned int elt_bit = 0;

> > +  unsigned HOST_WIDE_INT const_simdlen;

> > +

> > +  if (!TARGET_VECTOR)

> > +    return 0;

> > +

> > +  if (maybe_ne (clonei->simdlen, 0U)

> > +      && clonei->simdlen.is_constant (&const_simdlen)

> > +      && (const_simdlen < 2

> > +         || const_simdlen > 1024

> > +         || (const_simdlen & (const_simdlen - 1)) != 0))

> > +    {

> > +      if (explicit_p)

> > +       warning_at (DECL_SOURCE_LOCATION (node->decl), 0,

> > +                   "unsupported simdlen %wd", const_simdlen);

> > +      return 0;

> > +    }

> > +

> > +  ret_type = TREE_TYPE (TREE_TYPE (node->decl));

> > +  if (TREE_CODE (ret_type) != VOID_TYPE

> > +      && !supported_simd_type (ret_type))

> > +    {

> > +      if (!explicit_p)

> > +       ;

> > +      else if (COMPLEX_FLOAT_TYPE_P (ret_type))

> > +       warning_at (DECL_SOURCE_LOCATION (node->decl), 0,

> > +                   "GCC does not currently support return type %qT "

> > +                   "for simd", ret_type);

> > +      else

> > +       warning_at (DECL_SOURCE_LOCATION (node->decl), 0,

> > +                   "unsupported return type %qT for simd",

> > +                   ret_type);

> > +      return 0;

> > +    }

> > +

> > +  auto_vec<std::pair <tree, unsigned int>> vec_elts (clonei->nargs + 1);

> > +  if (TREE_CODE (ret_type) != VOID_TYPE)

> > +    {

> > +      elt_bit = lane_size (SIMD_CLONE_ARG_TYPE_VECTOR, ret_type);

> > +      vec_elts.safe_push (std::make_pair (ret_type, elt_bit));

> > +    }

> > +

> > +  int i;

> > +  tree type_arg_types = TYPE_ARG_TYPES (TREE_TYPE (node->decl));

> > +  bool decl_arg_p = (node->definition || type_arg_types == NULL_TREE);

> > +  for (t = (decl_arg_p ? DECL_ARGUMENTS (node->decl) : type_arg_types),

> > i = 0;

> > +       t && t != void_list_node; t = TREE_CHAIN (t), i++)

> > +    {

> > +      tree arg_type = decl_arg_p ? TREE_TYPE (t) : TREE_VALUE (t);

> > +      if (clonei->args[i].arg_type != SIMD_CLONE_ARG_TYPE_UNIFORM

> > +         && !supported_simd_type (arg_type))

> > +       {

> > +         if (!explicit_p)

> > +           ;

> > +         else if (COMPLEX_FLOAT_TYPE_P (ret_type))

> > +           warning_at (DECL_SOURCE_LOCATION (node->decl), 0,

> > +                       "GCC does not currently support argument type %qT "

> > +                       "for simd", arg_type);

> > +         else

> > +           warning_at (DECL_SOURCE_LOCATION (node->decl), 0,

> > +                       "unsupported argument type %qT for simd",

> > +                       arg_type);

> > +         return 0;

> > +       }

> > +      unsigned lane_bits = lane_size (clonei->args[i].arg_type, arg_type);

> > +      if (clonei->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)

> > +       vec_elts.safe_push (std::make_pair (arg_type, lane_bits));

> > +      if (!elt_bit)

> > +       elt_bit = lane_bits;

> > +      if (elt_bit != lane_bits)

> > +       return 0;

> > +    }

> > +

> > +  if (!elt_bit)

> > +    return 0;

> > +

> > +  clonei->vecsize_mangle = 'n';

> > +  clonei->mask_mode = VOIDmode;

> > +  poly_uint64 simdlen;

> > +  auto_vec<poly_uint64> simdlens (2);

> > +

> > +  clonei->vecsize_int = 0;

> > +  clonei->vecsize_float = 0;

> > +

> > +  if ((unsigned int)TARGET_MIN_VLEN <= elt_bit)

> > +    return 0;

> > +

> > +  /* Keep track of the possible simdlens the clones of this function

> > can have,

> > +     and check them later to see if we support them.  */

> > +  if (known_eq (clonei->simdlen, 0U))

> > +    {

> > +      if (TARGET_MAX_LMUL >= RVV_M1)

> > +       simdlens.safe_push (

> > +           exact_div (poly_uint64 (TARGET_MIN_VLEN * RVV_M1), elt_bit));

> > +      if (TARGET_MAX_LMUL >= RVV_M2)

> > +       simdlens.safe_push (

> > +           exact_div (poly_uint64 (TARGET_MIN_VLEN * RVV_M2), elt_bit));

> > +      if (TARGET_MAX_LMUL >= RVV_M4)

> > +       simdlens.safe_push (

> > +           exact_div (poly_uint64 (TARGET_MIN_VLEN * RVV_M4), elt_bit));

> > +      if (TARGET_MAX_LMUL >= RVV_M8)

> > +       simdlens.safe_push (

> > +           exact_div (poly_uint64 (TARGET_MIN_VLEN * RVV_M8), elt_bit));

> > +    }

> > +  else

> > +    simdlens.safe_push (clonei->simdlen);

> > +

> > +  unsigned j = 0;

> > +  while (j < simdlens.length ())

> > +    {

> > +      bool remove_simdlen = false;

> > +      for (auto elt : vec_elts)

> > +       if (known_gt (simdlens[j] * elt.second,

> > +           TARGET_MIN_VLEN * TARGET_MAX_LMUL))

> > +         {

> > +           /* Don't issue a warning for every simdclone when there is no

> > +              specific simdlen clause.  */

> > +           if (explicit_p && maybe_ne (clonei->simdlen, 0U))

> > +             warning_at (DECL_SOURCE_LOCATION (node->decl), 0,

> > +                         "GCC does not currently support simdlen %wd for "

> > +                         "type %qT",

> > +                         constant_lower_bound (simdlens[j]), elt.first);

> > +           remove_simdlen = true;

> > +           break;

> > +         }

> > +      if (remove_simdlen)

> > +       simdlens.ordered_remove (j);

> > +      else

> > +       j++;

> > +    }

> > +

> > +  int count = simdlens.length ();

> > +  if (count == 0)

> > +    {

> > +      if (explicit_p && known_eq (clonei->simdlen, 0U))

> > +       {

> > +         /* Warn the user if we can't generate any simdclone.  */

> > +         //simdlen = exact_div (TARGET_MIN_VLEN * LMUL, elt_bit);

> > +         warning_at (DECL_SOURCE_LOCATION (node->decl), 0,

> > +                     "GCC does not currently support a simdclone with

> > simdlens"

> > +                     " %wd and %wd for these types.",

> > +                     constant_lower_bound (simdlen),

> > +                     constant_lower_bound (simdlen*2));

> > +       }

> > +      return 0;

> > +    }

> > +

> > +  gcc_assert (num < count);

> > +  clonei->vecsize_mangle = std::exp2 (num) + '0';

> > +  clonei->simdlen = simdlens[num];

> > +  return count;

> > +}

> > +

> > +/* Implement TARGET_SIMD_CLONE_ADJUST.  */

> > +

> > +static void

> > +riscv_simd_clone_adjust (struct cgraph_node *node)

> > +{

> > +  tree t = TREE_TYPE (node->decl);

> > +  TYPE_ATTRIBUTES (t) = make_attribute ("riscv_vector_cc", "default",

> > +                                       TYPE_ATTRIBUTES (t));

> > +}

> > +

> > +/* Implement TARGET_SIMD_CLONE_USABLE.  */

> > +

> > +static int

> > +riscv_simd_clone_usable (struct cgraph_node *node)

> > +{

> > +  switch (node->simdclone->vecsize_mangle)

> > +    {

> > +    case '1':

> > +    case '2':

> > +    case '4':

> > +    case '8':

> > +      if (!TARGET_VECTOR)

> > +       return -1;

> > +      return 0;

> > +    default:

> > +      gcc_unreachable ();

> > +    }

> > +}

> > +

> >   /* Initialize the GCC target structure.  */

> >   #undef TARGET_ASM_ALIGNED_HI_OP

> >   #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"

> > @@ -13060,6 +13289,16 @@ riscv_stack_clash_protection_alloca_probe_range

> > (void)

> >   #undef TARGET_C_MODE_FOR_FLOATING_TYPE

> >   #define TARGET_C_MODE_FOR_FLOATING_TYPE riscv_c_mode_for_floating_type

> >

> > +#undef TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN

> > +#define TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN \

> > +  riscv_simd_clone_compute_vecsize_and_simdlen

> > +

> > +#undef TARGET_SIMD_CLONE_ADJUST

> > +#define TARGET_SIMD_CLONE_ADJUST riscv_simd_clone_adjust

> > +

> > +#undef TARGET_SIMD_CLONE_USABLE

> > +#define TARGET_SIMD_CLONE_USABLE riscv_simd_clone_usable

> > +

> >   struct gcc_target targetm = TARGET_INITIALIZER;

> >

> >   #include "gt-riscv.h"

> > --

> > 2.25.1

> >

> > This message and any attachment are confidential and may be privileged or 
> > otherwise protected from disclosure. If you are not an intended recipient 
> > of this message, please delete it and any attachment from your system and 
> > notify the sender immediately by reply e-mail. Unintended recipients should 
> > not use, copy, disclose or take any action based on this message or any 
> > information contained in this message. Emails cannot be guaranteed to be 
> > secure or error free as they can be intercepted, amended, lost or 
> > destroyed, and you should take full responsibility for security checking.

> >

> > 本邮件及其任何附件具有保密性质,并可能受其他保护或不允许被披露给第三方。如阁下误收到本邮件,敬请立即以回复电子邮件的方式通知发件人,并将本邮件及其任何附件从阁下系统中予以删除。如阁下并非本邮件写明之收件人,敬请切勿使用、复制、披露本邮件或其任何内容,亦请切勿依本邮件或其任何内容而采取任何行动。电子邮件无法保证是一种安全和不会出现任何差错的通信方式,可能会被拦截、修改、丢失或损坏,收件人需自行负责做好安全检查。
> 


This message and any attachment are confidential and may be privileged or 
otherwise protected from disclosure. If you are not an intended recipient of 
this message, please delete it and any attachment from your system and notify 
the sender immediately by reply e-mail. Unintended recipients should not use, 
copy, disclose or take any action based on this message or any information 
contained in this message. Emails cannot be guaranteed to be secure or error 
free as they can be intercepted, amended, lost or destroyed, and you should 
take full responsibility for security checking. 
 
本邮件及其任何附件具有保密性质,并可能受其他保护或不允许被披露给第三方。如阁下误收到本邮件,敬请立即以回复电子邮件的方式通知发件人,并将本邮件及其任何附件从阁下系统中予以删除。如阁下并非本邮件写明之收件人,敬请切勿使用、复制、披露本邮件或其任何内容,亦请切勿依本邮件或其任何内容而采取任何行动。电子邮件无法保证是一种安全和不会出现任何差错的通信方式,可能会被拦截、修改、丢失或损坏,收件人需自行负责做好安全检查。

Reply via email to