RISC-V: Add RVV intrinsic basic framework.
gcc/ChangeLog: * config.gcc: Add gt files since function_instance is GTY ((user)). * config/riscv/riscv-builtins.cc (riscv_init_builtins): Add RVV intrinsic framework. (riscv_builtin_decl): Ditto. (riscv_expand_builtin): Ditto. * config/riscv/riscv-protos.h (builtin_decl): New function. (expand_builtin): Ditto. (enum riscv_builtin_class): New enum to classify RVV intrinsic and RISC-V general built-in. * config/riscv/riscv-vector-builtins.cc (class GTY): New declaration. (struct registered_function_hasher): New struct. (DEF_RVV_OP_TYPE): New macro. (DEF_RVV_TYPE): Ditto. (DEF_RVV_PRED_TYPE): Ditto. (GTY): New declaration. (add_attribute): New function. (check_required_extensions): Ditto. (rvv_arg_type_info::get_tree_type): Ditto. (function_instance::function_instance): Ditto. (function_instance::operator==): Ditto. (function_instance::any_type_float_p): Ditto. (function_instance::get_return_type): Ditto. (function_instance::get_arg_type): Ditto. (function_instance::hash): Ditto. (function_instance::call_properties): Ditto. (function_instance::reads_global_state_p): Ditto. (function_instance::modifies_global_state_p): Ditto. (function_instance::could_trap_p): Ditto. (function_builder::function_builder): Ditto. (function_builder::~function_builder): Ditto. (function_builder::allocate_argument_types): Ditto. (function_builder::register_function_group): Ditto. (function_builder::append_name): Ditto. (function_builder::finish_name): Ditto. (function_builder::get_attributes): Ditto. (function_builder::add_function): Ditto. (function_builder::add_unique_function): Ditto. (function_call_info::function_call_info): Ditto. (function_expander::function_expander): Ditto. (function_expander::add_input_operand): Ditto. (function_expander::generate_insn): Ditto. (registered_function_hasher::hash): Ditto. (registered_function_hasher::equal): Ditto. (builtin_decl): Ditto. (expand_builtin): Ditto. (gt_ggc_mx): Define for using GCC garbage collect. (gt_pch_nx): Define for using GCC garbage collect. * config/riscv/riscv-vector-builtins.def (DEF_RVV_OP_TYPE): New macro. (DEF_RVV_PRED_TYPE): Ditto. (vbool64_t): Add suffix. (vbool32_t): Ditto. (vbool16_t): Ditto. (vbool8_t): Ditto. (vbool4_t): Ditto. (vbool2_t): Ditto. (vbool1_t): Ditto. (vint8mf8_t): Ditto. (vuint8mf8_t): Ditto. (vint8mf4_t): Ditto. (vuint8mf4_t): Ditto. (vint8mf2_t): Ditto. (vuint8mf2_t): Ditto. (vint8m1_t): Ditto. (vuint8m1_t): Ditto. (vint8m2_t): Ditto. (vuint8m2_t): Ditto. (vint8m4_t): Ditto. (vuint8m4_t): Ditto. (vint8m8_t): Ditto. (vuint8m8_t): Ditto. (vint16mf4_t): Ditto. (vuint16mf4_t): Ditto. (vint16mf2_t): Ditto. (vuint16mf2_t): Ditto. (vint16m1_t): Ditto. (vuint16m1_t): Ditto. (vint16m2_t): Ditto. (vuint16m2_t): Ditto. (vint16m4_t): Ditto. (vuint16m4_t): Ditto. (vint16m8_t): Ditto. (vuint16m8_t): Ditto. (vint32mf2_t): Ditto. (vuint32mf2_t): Ditto. (vint32m1_t): Ditto. (vuint32m1_t): Ditto. (vint32m2_t): Ditto. (vuint32m2_t): Ditto. (vint32m4_t): Ditto. (vuint32m4_t): Ditto. (vint32m8_t): Ditto. (vuint32m8_t): Ditto. (vint64m1_t): Ditto. (vuint64m1_t): Ditto. (vint64m2_t): Ditto. (vuint64m2_t): Ditto. (vint64m4_t): Ditto. (vuint64m4_t): Ditto. (vint64m8_t): Ditto. (vuint64m8_t): Ditto. (vfloat32mf2_t): Ditto. (vfloat32m1_t): Ditto. (vfloat32m2_t): Ditto. (vfloat32m4_t): Ditto. (vfloat32m8_t): Ditto. (vfloat64m1_t): Ditto. (vfloat64m2_t): Ditto. (vfloat64m4_t): Ditto. (vfloat64m8_t): Ditto. (vv): Ditto. (vx): Ditto. (v): Ditto. (wv): Ditto. (wx): Ditto. (x_x_v): Ditto. (vf2): Ditto. (vf4): Ditto. (vf8): Ditto. (vvm): Ditto. (vxm): Ditto. (x_x_w): Ditto. (v_v): Ditto. (v_x): Ditto. (vs): Ditto. (mm): Ditto. (m): Ditto. (vf): Ditto. (vm): Ditto. (wf): Ditto. (vfm): Ditto. (v_f): Ditto. (ta): Ditto. (tu): Ditto. (ma): Ditto. (mu): Ditto. (tama): Ditto. (tamu): Ditto. (tuma): Ditto. (tumu): Ditto. (tam): Ditto. (tum): Ditto. * config/riscv/riscv-vector-builtins.h (GCC_RISCV_VECTOR_BUILTINS_H): New macro. (RVV_REQUIRE_RV64BIT): Ditto. (RVV_REQUIRE_ZVE64): Ditto. (RVV_REQUIRE_ELEN_FP_32): Ditto. (RVV_REQUIRE_ELEN_FP_64): Ditto. (enum operand_type_index): New enum. (DEF_RVV_OP_TYPE): New macro. (enum predication_type_index): New enum. (DEF_RVV_PRED_TYPE): New macro. (enum rvv_base_type): New enum. (struct rvv_builtin_suffixes): New struct. (struct rvv_arg_type_info): Ditto. (struct rvv_type_info): Ditto. (struct rvv_op_info): Ditto. (class registered_function): New class. (class function_base): Ditto. (class function_shape): Ditto. (struct function_group_info): New struct. (class GTY): New class. (class function_builder): Ditto. (class function_call_info): Ditto. (function_call_info::function_returns_void_p): New function. (class function_expander): New class. (function_instance::operator!=): New function. (function_expander::expand): Ditto. (function_expander::add_input_operand): Ditto. (function_base::call_properties): Ditto.
This commit is contained in:
parent
4e7ec7dbbb
commit
cbd505700e
6 changed files with 1064 additions and 80 deletions
|
@ -520,6 +520,8 @@ riscv*)
|
|||
extra_objs="${extra_objs} riscv-vector-builtins.o"
|
||||
d_target_objs="riscv-d.o"
|
||||
extra_headers="riscv_vector.h"
|
||||
target_gtfiles="$target_gtfiles \$(srcdir)/config/riscv/riscv-vector-builtins.cc"
|
||||
target_gtfiles="$target_gtfiles \$(srcdir)/config/riscv/riscv-vector-builtins.h"
|
||||
;;
|
||||
rs6000*-*-*)
|
||||
extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt"
|
||||
|
|
|
@ -223,7 +223,10 @@ riscv_init_builtins (void)
|
|||
{
|
||||
tree type = riscv_build_function_type (d->prototype);
|
||||
riscv_builtin_decls[i]
|
||||
= add_builtin_function (d->name, type, i, BUILT_IN_MD, NULL, NULL);
|
||||
= add_builtin_function (d->name, type,
|
||||
(i << RISCV_BUILTIN_SHIFT)
|
||||
+ RISCV_BUILTIN_GENERAL,
|
||||
BUILT_IN_MD, NULL, NULL);
|
||||
riscv_builtin_decl_index[d->icode] = i;
|
||||
}
|
||||
}
|
||||
|
@ -234,9 +237,18 @@ riscv_init_builtins (void)
|
|||
tree
|
||||
riscv_builtin_decl (unsigned int code, bool initialize_p ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (code >= ARRAY_SIZE (riscv_builtins))
|
||||
return error_mark_node;
|
||||
return riscv_builtin_decls[code];
|
||||
unsigned int subcode = code >> RISCV_BUILTIN_SHIFT;
|
||||
switch (code & RISCV_BUILTIN_CLASS)
|
||||
{
|
||||
case RISCV_BUILTIN_GENERAL:
|
||||
if (subcode >= ARRAY_SIZE (riscv_builtins))
|
||||
return error_mark_node;
|
||||
return riscv_builtin_decls[subcode];
|
||||
|
||||
case RISCV_BUILTIN_VECTOR:
|
||||
return riscv_vector::builtin_decl (subcode, initialize_p);
|
||||
}
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
/* Take argument ARGNO from EXP's argument list and convert it into
|
||||
|
@ -303,15 +315,23 @@ riscv_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
|
|||
{
|
||||
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
|
||||
unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
|
||||
const struct riscv_builtin_description *d = &riscv_builtins[fcode];
|
||||
|
||||
switch (d->builtin_type)
|
||||
unsigned int subcode = fcode >> RISCV_BUILTIN_SHIFT;
|
||||
switch (fcode & RISCV_BUILTIN_CLASS)
|
||||
{
|
||||
case RISCV_BUILTIN_DIRECT:
|
||||
return riscv_expand_builtin_direct (d->icode, target, exp, true);
|
||||
case RISCV_BUILTIN_VECTOR:
|
||||
return riscv_vector::expand_builtin (subcode, exp, target);
|
||||
case RISCV_BUILTIN_GENERAL: {
|
||||
const struct riscv_builtin_description *d = &riscv_builtins[subcode];
|
||||
|
||||
case RISCV_BUILTIN_DIRECT_NO_TARGET:
|
||||
return riscv_expand_builtin_direct (d->icode, target, exp, false);
|
||||
switch (d->builtin_type)
|
||||
{
|
||||
case RISCV_BUILTIN_DIRECT:
|
||||
return riscv_expand_builtin_direct (d->icode, target, exp, true);
|
||||
|
||||
case RISCV_BUILTIN_DIRECT_NO_TARGET:
|
||||
return riscv_expand_builtin_direct (d->icode, target, exp, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gcc_unreachable ();
|
||||
|
|
|
@ -124,6 +124,23 @@ extern const char *mangle_builtin_type (const_tree);
|
|||
extern bool verify_type_context (location_t, type_context_kind, const_tree, bool);
|
||||
#endif
|
||||
extern void handle_pragma_vector (void);
|
||||
extern tree builtin_decl (unsigned, bool);
|
||||
extern rtx expand_builtin (unsigned int, tree, rtx);
|
||||
}
|
||||
|
||||
/* We classify builtin types into two classes:
|
||||
1. General builtin class which is defined in riscv_builtins.
|
||||
2. Vector builtin class which is a special builtin architecture
|
||||
that implement intrinsic short into "pragma". */
|
||||
enum riscv_builtin_class
|
||||
{
|
||||
RISCV_BUILTIN_GENERAL,
|
||||
RISCV_BUILTIN_VECTOR
|
||||
};
|
||||
|
||||
const unsigned int RISCV_BUILTIN_SHIFT = 1;
|
||||
|
||||
/* Mask that selects the riscv_builtin_class part of a function code. */
|
||||
const unsigned int RISCV_BUILTIN_CLASS = (1 << RISCV_BUILTIN_SHIFT) - 1;
|
||||
|
||||
#endif /* ! GCC_RISCV_PROTOS_H */
|
||||
|
|
|
@ -66,13 +66,55 @@ struct vector_type_info
|
|||
const char *mangled_name;
|
||||
};
|
||||
|
||||
/* Information about each RVV type. */
|
||||
/* Describes a function decl. */
|
||||
class GTY (()) registered_function
|
||||
{
|
||||
public:
|
||||
function_instance GTY ((skip)) instance;
|
||||
|
||||
/* The decl itself. */
|
||||
tree GTY ((skip)) decl;
|
||||
};
|
||||
|
||||
/* Hash traits for registered_function. */
|
||||
struct registered_function_hasher : nofree_ptr_hash<registered_function>
|
||||
{
|
||||
typedef function_instance compare_type;
|
||||
|
||||
static hashval_t hash (value_type);
|
||||
static bool equal (value_type, const compare_type &);
|
||||
};
|
||||
|
||||
/* Static information about each RVV type. */
|
||||
static CONSTEXPR const vector_type_info vector_types[] = {
|
||||
#define DEF_RVV_TYPE(NAME, NCHARS, ABI_NAME, ARGS...) \
|
||||
{#NAME, #ABI_NAME, "u" #NCHARS #ABI_NAME},
|
||||
#include "riscv-vector-builtins.def"
|
||||
};
|
||||
|
||||
/* Static information about operand suffix for each RVV type. */
|
||||
const char *const operand_suffixes[NUM_OP_TYPES] = {
|
||||
"", /* OP_TYPE_none. */
|
||||
#define DEF_RVV_OP_TYPE(NAME) "_" # NAME,
|
||||
#include "riscv-vector-builtins.def"
|
||||
};
|
||||
|
||||
/* Static information about type suffix for each RVV type. */
|
||||
const rvv_builtin_suffixes type_suffixes[NUM_VECTOR_TYPES + 1] = {
|
||||
#define DEF_RVV_TYPE(NAME, NCHARS, ABI_NAME, SCALAR_TYPE, VECTOR_MODE, \
|
||||
VECTOR_MODE_MIN_VLEN_32, VECTOR_SUFFIX, SCALAR_SUFFIX, \
|
||||
VSETVL_SUFFIX) \
|
||||
{#VECTOR_SUFFIX, #SCALAR_SUFFIX, #VSETVL_SUFFIX},
|
||||
#include "riscv-vector-builtins.def"
|
||||
};
|
||||
|
||||
/* Static information about predication suffix for each RVV type. */
|
||||
const char *const predication_suffixes[NUM_PRED_TYPES] = {
|
||||
"", /* PRED_TYPE_none. */
|
||||
#define DEF_RVV_PRED_TYPE(NAME) "_" # NAME,
|
||||
#include "riscv-vector-builtins.def"
|
||||
};
|
||||
|
||||
/* The RVV types, with their built-in
|
||||
"__rvv..._t" name. Allow an index of NUM_VECTOR_TYPES, which always
|
||||
yields a null tree. */
|
||||
|
@ -82,6 +124,14 @@ static GTY (()) tree abi_vector_types[NUM_VECTOR_TYPES + 1];
|
|||
extern GTY (()) rvv_builtin_types_t builtin_types[NUM_VECTOR_TYPES + 1];
|
||||
rvv_builtin_types_t builtin_types[NUM_VECTOR_TYPES + 1];
|
||||
|
||||
/* The list of all registered function decls, indexed by code. */
|
||||
static GTY (()) vec<registered_function *, va_gc> *registered_functions;
|
||||
|
||||
/* All registered function decls, hashed on the function_instance
|
||||
that they implement. This is used for looking up implementations of
|
||||
overloaded functions. */
|
||||
static hash_table<registered_function_hasher> *function_table;
|
||||
|
||||
/* RAII class for enabling enough RVV features to define the built-in
|
||||
types and implement the riscv_vector.h pragma.
|
||||
|
||||
|
@ -118,6 +168,13 @@ rvv_switcher::~rvv_switcher ()
|
|||
sizeof (have_regs_of_mode));
|
||||
}
|
||||
|
||||
/* Add attribute NAME to ATTRS. */
|
||||
static tree
|
||||
add_attribute (const char *name, tree attrs)
|
||||
{
|
||||
return tree_cons (get_identifier (name), NULL_TREE, attrs);
|
||||
}
|
||||
|
||||
/* Add type attributes to builtin type tree, currently only the mangled name. */
|
||||
static void
|
||||
add_vector_type_attribute (tree type, const char *mangled_name)
|
||||
|
@ -215,6 +272,7 @@ static void
|
|||
register_vector_type (vector_type_index type)
|
||||
{
|
||||
tree vectype = abi_vector_types[type];
|
||||
|
||||
/* When vectype is NULL, the corresponding builtin type
|
||||
is disabled according to '-march'. */
|
||||
if (!vectype)
|
||||
|
@ -237,6 +295,386 @@ register_vector_type (vector_type_index type)
|
|||
builtin_types[type].vector_ptr = build_pointer_type (vectype);
|
||||
}
|
||||
|
||||
/* Check whether all the RVV_REQUIRE_* values in REQUIRED_EXTENSIONS are
|
||||
enabled. */
|
||||
static bool
|
||||
check_required_extensions (uint64_t required_extensions)
|
||||
{
|
||||
uint64_t riscv_isa_flags = 0;
|
||||
|
||||
if (TARGET_VECTOR_ELEN_FP_32)
|
||||
riscv_isa_flags |= RVV_REQUIRE_ELEN_FP_32;
|
||||
if (TARGET_VECTOR_ELEN_FP_64)
|
||||
riscv_isa_flags |= RVV_REQUIRE_ELEN_FP_64;
|
||||
if (TARGET_MIN_VLEN > 32)
|
||||
riscv_isa_flags |= RVV_REQUIRE_ZVE64;
|
||||
if (TARGET_64BIT)
|
||||
riscv_isa_flags |= RVV_REQUIRE_RV64BIT;
|
||||
|
||||
uint64_t missing_extensions = required_extensions & ~riscv_isa_flags;
|
||||
if (missing_extensions != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
tree
|
||||
rvv_arg_type_info::get_tree_type (vector_type_index type_idx) const
|
||||
{
|
||||
switch (base_type)
|
||||
{
|
||||
case RVV_BASE_vector:
|
||||
return builtin_types[type_idx].vector;
|
||||
case RVV_BASE_scalar:
|
||||
return builtin_types[type_idx].scalar;
|
||||
case RVV_BASE_vector_ptr:
|
||||
return builtin_types[type_idx].vector_ptr;
|
||||
case RVV_BASE_scalar_ptr:
|
||||
return builtin_types[type_idx].scalar_ptr;
|
||||
case RVV_BASE_scalar_const_ptr:
|
||||
return builtin_types[type_idx].scalar_const_ptr;
|
||||
case RVV_BASE_void:
|
||||
return void_type_node;
|
||||
case RVV_BASE_size:
|
||||
return size_type_node;
|
||||
case RVV_BASE_ptrdiff:
|
||||
return ptrdiff_type_node;
|
||||
case RVV_BASE_unsigned_long:
|
||||
return long_unsigned_type_node;
|
||||
case RVV_BASE_long:
|
||||
return long_integer_type_node;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
|
||||
function_instance::function_instance (const char *base_name_in,
|
||||
const function_base *base_in,
|
||||
const function_shape *shape_in,
|
||||
rvv_type_info type_in,
|
||||
predication_type_index pred_in,
|
||||
const rvv_op_info *op_info_in)
|
||||
: base_name (base_name_in), base (base_in), shape (shape_in), type (type_in),
|
||||
pred (pred_in), op_info (op_info_in)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
function_instance::operator== (const function_instance &other) const
|
||||
{
|
||||
for (unsigned int i = 0; op_info->args[i].base_type != NUM_BASE_TYPES; ++i)
|
||||
if (op_info->args[i].base_type != other.op_info->args[i].base_type)
|
||||
return false;
|
||||
return (base == other.base && shape == other.shape
|
||||
&& type.index == other.type.index && op_info->op == other.op_info->op
|
||||
&& pred == other.pred
|
||||
&& op_info->ret.base_type == other.op_info->ret.base_type);
|
||||
}
|
||||
|
||||
bool
|
||||
function_instance::any_type_float_p () const
|
||||
{
|
||||
if (FLOAT_MODE_P (TYPE_MODE (get_return_type ())))
|
||||
return true;
|
||||
|
||||
for (int i = 0; op_info->args[i].base_type != NUM_BASE_TYPES; ++i)
|
||||
if (FLOAT_MODE_P (TYPE_MODE (get_arg_type (i))))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
tree
|
||||
function_instance::get_return_type () const
|
||||
{
|
||||
return op_info->ret.get_tree_type (type.index);
|
||||
}
|
||||
|
||||
tree
|
||||
function_instance::get_arg_type (unsigned opno) const
|
||||
{
|
||||
return op_info->args[opno].get_tree_type (type.index);
|
||||
}
|
||||
|
||||
/* Return a hash code for a function_instance. */
|
||||
hashval_t
|
||||
function_instance::hash () const
|
||||
{
|
||||
inchash::hash h;
|
||||
/* BASE uniquely determines BASE_NAME, so we don't need to hash both. */
|
||||
h.add_ptr (base);
|
||||
h.add_ptr (shape);
|
||||
h.add_int (type.index);
|
||||
h.add_int (op_info->op);
|
||||
h.add_int (pred);
|
||||
h.add_int (op_info->ret.base_type);
|
||||
for (unsigned int i = 0; op_info->args[i].base_type != NUM_BASE_TYPES; ++i)
|
||||
h.add_int (op_info->args[i].base_type);
|
||||
return h.end ();
|
||||
}
|
||||
|
||||
/* Return a set of CP_* flags that describe what the function could do,
|
||||
taking the command-line flags into account. */
|
||||
unsigned int
|
||||
function_instance::call_properties () const
|
||||
{
|
||||
unsigned int flags = base->call_properties (*this);
|
||||
|
||||
/* -fno-trapping-math means that we can assume any FP exceptions
|
||||
are not user-visible. */
|
||||
if (!flag_trapping_math)
|
||||
flags &= ~CP_RAISE_FP_EXCEPTIONS;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/* Return true if calls to the function could read some form of
|
||||
global state. */
|
||||
bool
|
||||
function_instance::reads_global_state_p () const
|
||||
{
|
||||
unsigned int flags = call_properties ();
|
||||
|
||||
/* Preserve any dependence on rounding mode, flush to zero mode, etc.
|
||||
There is currently no way of turning this off; in particular,
|
||||
-fno-rounding-math (which is the default) means that we should make
|
||||
the usual assumptions about rounding mode, which for intrinsics means
|
||||
acting as the instructions do. */
|
||||
if (flags & CP_READ_FPCR)
|
||||
return true;
|
||||
|
||||
/* Handle direct reads of global state. */
|
||||
return flags & (CP_READ_MEMORY | CP_READ_CSR);
|
||||
}
|
||||
|
||||
/* Return true if calls to the function could modify some form of
|
||||
global state. */
|
||||
bool
|
||||
function_instance::modifies_global_state_p () const
|
||||
{
|
||||
unsigned int flags = call_properties ();
|
||||
|
||||
/* Preserve any exception state written back to the FPCR,
|
||||
unless -fno-trapping-math says this is unnecessary. */
|
||||
if (flags & CP_RAISE_FP_EXCEPTIONS)
|
||||
return true;
|
||||
|
||||
/* Handle direct modifications of global state. */
|
||||
return flags & (CP_WRITE_MEMORY | CP_WRITE_CSR);
|
||||
}
|
||||
|
||||
/* Return true if calls to the function could raise a signal. */
|
||||
bool
|
||||
function_instance::could_trap_p () const
|
||||
{
|
||||
unsigned int flags = call_properties ();
|
||||
|
||||
/* Handle functions that could raise SIGFPE. */
|
||||
if (flags & CP_RAISE_FP_EXCEPTIONS)
|
||||
return true;
|
||||
|
||||
/* Handle functions that could raise SIGBUS or SIGSEGV. */
|
||||
if (flags & (CP_READ_MEMORY | CP_WRITE_MEMORY))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function_builder::function_builder ()
|
||||
{
|
||||
m_direct_overloads = lang_GNU_CXX ();
|
||||
gcc_obstack_init (&m_string_obstack);
|
||||
}
|
||||
|
||||
function_builder::~function_builder ()
|
||||
{
|
||||
obstack_free (&m_string_obstack, NULL);
|
||||
}
|
||||
|
||||
/* Allocate arguments of the function. */
|
||||
void
|
||||
function_builder::allocate_argument_types (const function_instance &instance,
|
||||
vec<tree> &argument_types) const
|
||||
{
|
||||
for (unsigned int i = 0;
|
||||
instance.op_info->args[i].base_type != NUM_BASE_TYPES; ++i)
|
||||
argument_types.quick_push (
|
||||
instance.op_info->args[i].get_tree_type (instance.type.index));
|
||||
}
|
||||
|
||||
/* Register all the functions in GROUP. */
|
||||
void
|
||||
function_builder::register_function_group (const function_group_info &group)
|
||||
{
|
||||
(*group.shape)->build (*this, group);
|
||||
}
|
||||
|
||||
/* Add NAME to the end of the function name being built. */
|
||||
void
|
||||
function_builder::append_name (const char *name)
|
||||
{
|
||||
obstack_grow (&m_string_obstack, name, strlen (name));
|
||||
}
|
||||
|
||||
/* Zero-terminate and complete the function name being built. */
|
||||
char *
|
||||
function_builder::finish_name ()
|
||||
{
|
||||
obstack_1grow (&m_string_obstack, 0);
|
||||
return (char *) obstack_finish (&m_string_obstack);
|
||||
}
|
||||
|
||||
/* Return the appropriate function attributes for INSTANCE. */
|
||||
tree
|
||||
function_builder::get_attributes (const function_instance &instance)
|
||||
{
|
||||
tree attrs = NULL_TREE;
|
||||
|
||||
if (!instance.modifies_global_state_p ())
|
||||
{
|
||||
if (instance.reads_global_state_p ())
|
||||
attrs = add_attribute ("pure", attrs);
|
||||
else
|
||||
attrs = add_attribute ("const", attrs);
|
||||
}
|
||||
|
||||
if (!flag_non_call_exceptions || !instance.could_trap_p ())
|
||||
attrs = add_attribute ("nothrow", attrs);
|
||||
|
||||
return add_attribute ("leaf", attrs);
|
||||
}
|
||||
|
||||
/* Add a function called NAME with type FNTYPE and attributes ATTRS.
|
||||
INSTANCE describes what the function does. */
|
||||
registered_function &
|
||||
function_builder::add_function (const function_instance &instance,
|
||||
const char *name, tree fntype, tree attrs,
|
||||
bool placeholder_p)
|
||||
{
|
||||
unsigned int code = vec_safe_length (registered_functions);
|
||||
code = (code << RISCV_BUILTIN_SHIFT) + RISCV_BUILTIN_VECTOR;
|
||||
|
||||
/* We need to be able to generate placeholders to enusre that we have a
|
||||
consistent numbering scheme for function codes between the C and C++
|
||||
frontends, so that everything ties up in LTO.
|
||||
|
||||
Currently, tree-streamer-in.c:unpack_ts_function_decl_value_fields
|
||||
validates that tree nodes returned by TARGET_BUILTIN_DECL are non-NULL and
|
||||
some node other than error_mark_node. This is a holdover from when builtin
|
||||
decls were streamed by code rather than by value.
|
||||
|
||||
Ultimately, we should be able to remove this validation of BUILT_IN_MD
|
||||
nodes and remove the target hook. For now, however, we need to appease the
|
||||
validation and return a non-NULL, non-error_mark_node node, so we
|
||||
arbitrarily choose integer_zero_node. */
|
||||
tree decl = placeholder_p
|
||||
? integer_zero_node
|
||||
: simulate_builtin_function_decl (input_location, name, fntype,
|
||||
code, NULL, attrs);
|
||||
|
||||
registered_function &rfn = *ggc_alloc<registered_function> ();
|
||||
rfn.instance = instance;
|
||||
rfn.decl = decl;
|
||||
vec_safe_push (registered_functions, &rfn);
|
||||
|
||||
return rfn;
|
||||
}
|
||||
|
||||
/* Add a built-in function for INSTANCE, with the argument types given
|
||||
by ARGUMENT_TYPES and the return type given by RETURN_TYPE. NAME is
|
||||
the "full" name for C function. OVERLOAD_NAME is the "short" name for
|
||||
C++ overloaded function. OVERLOAD_NAME can be nullptr because some
|
||||
instance doesn't have C++ overloaded function. */
|
||||
void
|
||||
function_builder::add_unique_function (const function_instance &instance,
|
||||
const function_shape *shape,
|
||||
tree return_type,
|
||||
vec<tree> &argument_types)
|
||||
{
|
||||
/* Do not add this function if it is invalid. */
|
||||
if (!check_required_extensions (instance.type.required_extensions))
|
||||
return;
|
||||
|
||||
/* Add the function under its full (unique) name. */
|
||||
char *name = shape->get_name (*this, instance, false);
|
||||
tree fntype
|
||||
= build_function_type_array (return_type, argument_types.length (),
|
||||
argument_types.address ());
|
||||
tree attrs = get_attributes (instance);
|
||||
registered_function &rfn
|
||||
= add_function (instance, name, fntype, attrs, false);
|
||||
|
||||
/* Enter the function into the hash table. */
|
||||
hashval_t hash = instance.hash ();
|
||||
registered_function **rfn_slot
|
||||
= function_table->find_slot_with_hash (instance, hash, INSERT);
|
||||
gcc_assert (!*rfn_slot);
|
||||
*rfn_slot = &rfn;
|
||||
|
||||
/* Also add the function under its overloaded alias, if we want
|
||||
a separate decl for each instance of an overloaded function. */
|
||||
char *overload_name = shape->get_name (*this, instance, true);
|
||||
if (overload_name)
|
||||
{
|
||||
/* Attribute lists shouldn't be shared. */
|
||||
tree attrs = get_attributes (instance);
|
||||
bool placeholder_p = !m_direct_overloads;
|
||||
add_function (instance, overload_name, fntype, attrs, placeholder_p);
|
||||
}
|
||||
obstack_free (&m_string_obstack, name);
|
||||
}
|
||||
|
||||
function_call_info::function_call_info (location_t location_in,
|
||||
const function_instance &instance_in,
|
||||
tree fndecl_in)
|
||||
: function_instance (instance_in), location (location_in), fndecl (fndecl_in)
|
||||
{}
|
||||
|
||||
function_expander::function_expander (const function_instance &instance,
|
||||
tree fndecl_in, tree exp_in,
|
||||
rtx target_in)
|
||||
: function_call_info (EXPR_LOCATION (exp_in), instance, fndecl_in),
|
||||
exp (exp_in), target (target_in), opno (0)
|
||||
{
|
||||
if (!function_returns_void_p ())
|
||||
create_output_operand (&m_ops[opno++], target, TYPE_MODE (TREE_TYPE (exp)));
|
||||
}
|
||||
|
||||
/* Take argument ARGNO from EXP's argument list and convert it into
|
||||
an expand operand. Store the operand in *M_OPS. */
|
||||
void
|
||||
function_expander::add_input_operand (unsigned argno)
|
||||
{
|
||||
tree arg = CALL_EXPR_ARG (exp, argno);
|
||||
rtx x = expand_normal (arg);
|
||||
add_input_operand (TYPE_MODE (TREE_TYPE (arg)), x);
|
||||
}
|
||||
|
||||
/* Generate instruction ICODE, given that its operands have already
|
||||
been added to M_OPS. Return the value of the first operand. */
|
||||
rtx
|
||||
function_expander::generate_insn (insn_code icode)
|
||||
{
|
||||
gcc_assert (opno == insn_data[icode].n_generator_args);
|
||||
if (!maybe_expand_insn (icode, opno, m_ops))
|
||||
{
|
||||
error ("invalid argument to built-in function");
|
||||
return NULL_RTX;
|
||||
}
|
||||
return function_returns_void_p () ? const0_rtx : m_ops[0].value;
|
||||
}
|
||||
|
||||
inline hashval_t
|
||||
registered_function_hasher::hash (value_type value)
|
||||
{
|
||||
return value->instance.hash ();
|
||||
}
|
||||
|
||||
inline bool
|
||||
registered_function_hasher::equal (value_type value, const compare_type &key)
|
||||
{
|
||||
return value->instance == key;
|
||||
}
|
||||
|
||||
/* If TYPE is a built-in type defined by the RVV ABI, return the mangled name,
|
||||
otherwise return NULL. */
|
||||
const char *
|
||||
|
@ -356,4 +794,39 @@ handle_pragma_vector ()
|
|||
register_vector_type ((enum vector_type_index) type_i);
|
||||
}
|
||||
|
||||
/* Return the function decl with RVV function subcode CODE, or error_mark_node
|
||||
if no such function exists. */
|
||||
tree
|
||||
builtin_decl (unsigned int code, bool)
|
||||
{
|
||||
if (code >= vec_safe_length (registered_functions))
|
||||
return error_mark_node;
|
||||
|
||||
return (*registered_functions)[code]->decl;
|
||||
}
|
||||
|
||||
/* Expand a call to the RVV function with subcode CODE. EXP is the call
|
||||
expression and TARGET is the preferred location for the result.
|
||||
Return the value of the lhs. */
|
||||
rtx
|
||||
expand_builtin (unsigned int code, tree exp, rtx target)
|
||||
{
|
||||
registered_function &rfn = *(*registered_functions)[code];
|
||||
return function_expander (rfn.instance, rfn.decl, exp, target).expand ();
|
||||
}
|
||||
|
||||
} // end namespace riscv_vector
|
||||
|
||||
inline void
|
||||
gt_ggc_mx (function_instance *)
|
||||
{}
|
||||
|
||||
inline void
|
||||
gt_pch_nx (function_instance *)
|
||||
{}
|
||||
|
||||
inline void
|
||||
gt_pch_nx (function_instance *, gt_pointer_operator, void *)
|
||||
{}
|
||||
|
||||
#include "gt-riscv-vector-builtins.h"
|
||||
|
|
|
@ -19,181 +19,290 @@ along with GCC; see the file COPYING3. If not see
|
|||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Use "DEF_RVV_TYPE" macro to define RVV datatype builtins.
|
||||
1.The 1 argument is the name exposed to users.
|
||||
1.The 'NAME' argument is the name exposed to users.
|
||||
For example, "vint32m1_t".
|
||||
2.The 2 argument is the length of ABI-name.
|
||||
2.The 'NCHARS' argument is the length of ABI-name.
|
||||
For example, length of "__rvv_int32m1_t" is 15.
|
||||
3.The 3 argument is the ABI-name. For example, "__rvv_int32m1_t".
|
||||
4.The 4 argument is associated scalar type which is used in
|
||||
3.The 'ABI_NAME' argument is the ABI-name. For example, "__rvv_int32m1_t".
|
||||
4.The 'SCALAR_TYPE' argument is associated scalar type which is used in
|
||||
"build_vector_type_for_mode". For "vint32m1_t", we use "intSI_type_node" in
|
||||
RV64. Otherwise, we use "long_integer_type_node".
|
||||
5.The 5 and 6 argument are the machine modes of corresponding RVV type used
|
||||
in "build_vector_type_for_mode". For "vint32m1_t", we use VNx2SImode when
|
||||
TARGET_MIN_VLEN > 32. Otherwise the machine mode is VNx1SImode. */
|
||||
5.The 'VECTOR_MODE' is the machine modes of corresponding RVV type used
|
||||
in "build_vector_type_for_mode" when TARGET_MIN_VLEN > 32.
|
||||
For example: VECTOR_MODE = VNx2SI for "vint32m1_t".
|
||||
6.The 'VECTOR_MODE_MIN_VLEN_32' is the machine modes of corresponding RVV
|
||||
type used in "build_vector_type_for_mode" when TARGET_MIN_VLEN = 32. For
|
||||
example: VECTOR_MODE_MIN_VLEN_32 = VNx1SI for "vint32m1_t".
|
||||
7.The 'VECTOR_SUFFIX' define mode suffix for vector type.
|
||||
For example: type_suffixes[VECTOR_TYPE_vin32m1_t].vector = i32m1.
|
||||
8.The 'SCALAR_SUFFIX' define mode suffix for scalar type.
|
||||
For example: type_suffixes[VECTOR_TYPE_vin32m1_t].scalar = i32.
|
||||
9.The 'VSETVL_SUFFIX' define mode suffix for vsetvli instruction.
|
||||
For example: type_suffixes[VECTOR_TYPE_vin32m1_t].vsetvl = e32m1.
|
||||
*/
|
||||
|
||||
#ifndef DEF_RVV_TYPE
|
||||
#define DEF_RVV_TYPE(NAME, NCHARS, ABI_NAME, SCALAR_TYPE, VECTOR_MODE, \
|
||||
VECTOR_MODE_MIN_VLEN_32)
|
||||
VECTOR_MODE_MIN_VLEN_32, VECTOR_SUFFIX, SCALAR_SUFFIX, \
|
||||
VSETVL_SUFFIX)
|
||||
#endif
|
||||
|
||||
/* Use "DEF_RVV_OP_TYPE" macro to define RVV operand types.
|
||||
The 'NAME' will be concatenated into intrinsic function name. */
|
||||
#ifndef DEF_RVV_OP_TYPE
|
||||
#define DEF_RVV_OP_TYPE(NAME)
|
||||
#endif
|
||||
|
||||
/* Use "DEF_RVV_PRED_TYPE" macro to define RVV predication types.
|
||||
The 'NAME' will be concatenated into intrinsic function name. */
|
||||
#ifndef DEF_RVV_PRED_TYPE
|
||||
#define DEF_RVV_PRED_TYPE(NAME)
|
||||
#endif
|
||||
|
||||
/* SEW/LMUL = 64:
|
||||
Only enable when TARGET_MIN_VLEN > 32 and machine mode = VNx1BImode. */
|
||||
DEF_RVV_TYPE (vbool64_t, 14, __rvv_bool64_t, boolean, VNx1BI, VOID)
|
||||
DEF_RVV_TYPE (vbool64_t, 14, __rvv_bool64_t, boolean, VNx1BI, VOID, _b64, , )
|
||||
/* SEW/LMUL = 32:
|
||||
Machine mode = VNx2BImode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx1BImode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vbool32_t, 14, __rvv_bool32_t, boolean, VNx2BI, VNx1BI)
|
||||
DEF_RVV_TYPE (vbool32_t, 14, __rvv_bool32_t, boolean, VNx2BI, VNx1BI, _b32, , )
|
||||
/* SEW/LMUL = 16:
|
||||
Machine mode = VNx2BImode when TARGET_MIN_VLEN = 32.
|
||||
Machine mode = VNx4BImode when TARGET_MIN_VLEN > 32. */
|
||||
DEF_RVV_TYPE (vbool16_t, 14, __rvv_bool16_t, boolean, VNx4BI, VNx2BI)
|
||||
DEF_RVV_TYPE (vbool16_t, 14, __rvv_bool16_t, boolean, VNx4BI, VNx2BI, _b16, , )
|
||||
/* SEW/LMUL = 8:
|
||||
Machine mode = VNx8BImode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx4BImode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vbool8_t, 13, __rvv_bool8_t, boolean, VNx8BI, VNx4BI)
|
||||
DEF_RVV_TYPE (vbool8_t, 13, __rvv_bool8_t, boolean, VNx8BI, VNx4BI, _b8, , )
|
||||
/* SEW/LMUL = 4:
|
||||
Machine mode = VNx16BImode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx8BImode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vbool4_t, 13, __rvv_bool4_t, boolean, VNx16BI, VNx8BI)
|
||||
DEF_RVV_TYPE (vbool4_t, 13, __rvv_bool4_t, boolean, VNx16BI, VNx8BI, _b4, , )
|
||||
/* SEW/LMUL = 2:
|
||||
Machine mode = VNx32BImode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx16BImode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vbool2_t, 13, __rvv_bool2_t, boolean, VNx32BI, VNx16BI)
|
||||
DEF_RVV_TYPE (vbool2_t, 13, __rvv_bool2_t, boolean, VNx32BI, VNx16BI, _b2, , )
|
||||
/* SEW/LMUL = 1:
|
||||
Machine mode = VNx64BImode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx32BImode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vbool1_t, 13, __rvv_bool1_t, boolean, VNx64BI, VNx32BI)
|
||||
DEF_RVV_TYPE (vbool1_t, 13, __rvv_bool1_t, boolean, VNx64BI, VNx32BI, _b1, , )
|
||||
|
||||
/* LMUL = 1/8:
|
||||
Only enble when TARGET_MIN_VLEN > 32 and machine mode = VNx1QImode. */
|
||||
DEF_RVV_TYPE (vint8mf8_t, 15, __rvv_int8mf8_t, intQI, VNx1QI, VOID)
|
||||
DEF_RVV_TYPE (vuint8mf8_t, 16, __rvv_uint8mf8_t, unsigned_intQI, VNx1QI, VOID)
|
||||
DEF_RVV_TYPE (vint8mf8_t, 15, __rvv_int8mf8_t, intQI, VNx1QI, VOID, _i8mf8, _i8,
|
||||
_e8mf8)
|
||||
DEF_RVV_TYPE (vuint8mf8_t, 16, __rvv_uint8mf8_t, unsigned_intQI, VNx1QI, VOID,
|
||||
_u8mf8, _u8, _e8mf8)
|
||||
/* LMUL = 1/4:
|
||||
Machine mode = VNx2QImode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx1QImode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vint8mf4_t, 15, __rvv_int8mf4_t, intQI, VNx2QI, VNx1QI)
|
||||
DEF_RVV_TYPE (vuint8mf4_t, 16, __rvv_uint8mf4_t, unsigned_intQI, VNx2QI, VNx1QI)
|
||||
DEF_RVV_TYPE (vint8mf4_t, 15, __rvv_int8mf4_t, intQI, VNx2QI, VNx1QI, _i8mf4,
|
||||
_i8, _e8mf4)
|
||||
DEF_RVV_TYPE (vuint8mf4_t, 16, __rvv_uint8mf4_t, unsigned_intQI, VNx2QI, VNx1QI,
|
||||
_u8mf4, _u8, _e8mf4)
|
||||
/* LMUL = 1/2:
|
||||
Machine mode = VNx4QImode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx2QImode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vint8mf2_t, 15, __rvv_int8mf2_t, intQI, VNx4QI, VNx2QI)
|
||||
DEF_RVV_TYPE (vuint8mf2_t, 16, __rvv_uint8mf2_t, unsigned_intQI, VNx4QI, VNx2QI)
|
||||
DEF_RVV_TYPE (vint8mf2_t, 15, __rvv_int8mf2_t, intQI, VNx4QI, VNx2QI, _i8mf2,
|
||||
_i8, _e8mf2)
|
||||
DEF_RVV_TYPE (vuint8mf2_t, 16, __rvv_uint8mf2_t, unsigned_intQI, VNx4QI, VNx2QI,
|
||||
_u8mf2, _u8, _e8mf2)
|
||||
/* LMUL = 1:
|
||||
Machine mode = VNx8QImode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx4QImode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vint8m1_t, 14, __rvv_int8m1_t, intQI, VNx8QI, VNx4QI)
|
||||
DEF_RVV_TYPE (vuint8m1_t, 15, __rvv_uint8m1_t, unsigned_intQI, VNx8QI, VNx4QI)
|
||||
DEF_RVV_TYPE (vint8m1_t, 14, __rvv_int8m1_t, intQI, VNx8QI, VNx4QI, _i8m1, _i8,
|
||||
_e8m1)
|
||||
DEF_RVV_TYPE (vuint8m1_t, 15, __rvv_uint8m1_t, unsigned_intQI, VNx8QI, VNx4QI,
|
||||
_u8m1, _u8, _e8m1)
|
||||
/* LMUL = 2:
|
||||
Machine mode = VNx16QImode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx8QImode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vint8m2_t, 14, __rvv_int8m2_t, intQI, VNx16QI, VNx8QI)
|
||||
DEF_RVV_TYPE (vuint8m2_t, 15, __rvv_uint8m2_t, unsigned_intQI, VNx16QI, VNx8QI)
|
||||
DEF_RVV_TYPE (vint8m2_t, 14, __rvv_int8m2_t, intQI, VNx16QI, VNx8QI, _i8m2, _i8,
|
||||
_e8m2)
|
||||
DEF_RVV_TYPE (vuint8m2_t, 15, __rvv_uint8m2_t, unsigned_intQI, VNx16QI, VNx8QI,
|
||||
_u8m2, _u8, _e8m2)
|
||||
/* LMUL = 4:
|
||||
Machine mode = VNx32QImode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx16QImode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vint8m4_t, 14, __rvv_int8m4_t, intQI, VNx32QI, VNx16QI)
|
||||
DEF_RVV_TYPE (vuint8m4_t, 15, __rvv_uint8m4_t, unsigned_intQI, VNx32QI, VNx16QI)
|
||||
DEF_RVV_TYPE (vint8m4_t, 14, __rvv_int8m4_t, intQI, VNx32QI, VNx16QI, _i8m4,
|
||||
_i8, _e8m4)
|
||||
DEF_RVV_TYPE (vuint8m4_t, 15, __rvv_uint8m4_t, unsigned_intQI, VNx32QI, VNx16QI,
|
||||
_u8m4, _u8, _e8m4)
|
||||
/* LMUL = 8:
|
||||
Machine mode = VNx64QImode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx32QImode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vint8m8_t, 14, __rvv_int8m8_t, intQI, VNx64QI, VNx32QI)
|
||||
DEF_RVV_TYPE (vuint8m8_t, 15, __rvv_uint8m8_t, unsigned_intQI, VNx64QI, VNx32QI)
|
||||
DEF_RVV_TYPE (vint8m8_t, 14, __rvv_int8m8_t, intQI, VNx64QI, VNx32QI, _i8m8,
|
||||
_i8, _e8m8)
|
||||
DEF_RVV_TYPE (vuint8m8_t, 15, __rvv_uint8m8_t, unsigned_intQI, VNx64QI, VNx32QI,
|
||||
_u8m8, _u8, _e8m8)
|
||||
|
||||
/* LMUL = 1/4:
|
||||
Only enble when TARGET_MIN_VLEN > 32 and machine mode = VNx1HImode. */
|
||||
DEF_RVV_TYPE (vint16mf4_t, 16, __rvv_int16mf4_t, intHI, VNx1HI, VOID)
|
||||
DEF_RVV_TYPE (vuint16mf4_t, 17, __rvv_uint16mf4_t, unsigned_intHI, VNx1HI, VOID)
|
||||
DEF_RVV_TYPE (vint16mf4_t, 16, __rvv_int16mf4_t, intHI, VNx1HI, VOID, _i16mf4,
|
||||
_i16, _e16mf4)
|
||||
DEF_RVV_TYPE (vuint16mf4_t, 17, __rvv_uint16mf4_t, unsigned_intHI, VNx1HI, VOID,
|
||||
_u16mf4, _u16, _e16mf4)
|
||||
/* LMUL = 1/2:
|
||||
Machine mode = VNx2HImode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx1HImode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vint16mf2_t, 16, __rvv_int16mf2_t, intHI, VNx2HI, VNx1HI)
|
||||
DEF_RVV_TYPE (vint16mf2_t, 16, __rvv_int16mf2_t, intHI, VNx2HI, VNx1HI, _i16mf2,
|
||||
_i16, _e16mf2)
|
||||
DEF_RVV_TYPE (vuint16mf2_t, 17, __rvv_uint16mf2_t, unsigned_intHI, VNx2HI,
|
||||
VNx1HI)
|
||||
VNx1HI, _u16mf2, _u16, _e16mf2)
|
||||
/* LMUL = 1:
|
||||
Machine mode = VNx4HImode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx2HImode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vint16m1_t, 15, __rvv_int16m1_t, intHI, VNx4HI, VNx2HI)
|
||||
DEF_RVV_TYPE (vuint16m1_t, 16, __rvv_uint16m1_t, unsigned_intHI, VNx4HI, VNx2HI)
|
||||
DEF_RVV_TYPE (vint16m1_t, 15, __rvv_int16m1_t, intHI, VNx4HI, VNx2HI, _i16m1,
|
||||
_i16, _e16m1)
|
||||
DEF_RVV_TYPE (vuint16m1_t, 16, __rvv_uint16m1_t, unsigned_intHI, VNx4HI, VNx2HI,
|
||||
_u16m1, _u16, _e16m1)
|
||||
/* LMUL = 2:
|
||||
Machine mode = VNx8HImode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx4HImode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vint16m2_t, 15, __rvv_int16m2_t, intHI, VNx8HI, VNx4HI)
|
||||
DEF_RVV_TYPE (vuint16m2_t, 16, __rvv_uint16m2_t, unsigned_intHI, VNx8HI, VNx4HI)
|
||||
DEF_RVV_TYPE (vint16m2_t, 15, __rvv_int16m2_t, intHI, VNx8HI, VNx4HI, _i16m2,
|
||||
_i16, _e16m2)
|
||||
DEF_RVV_TYPE (vuint16m2_t, 16, __rvv_uint16m2_t, unsigned_intHI, VNx8HI, VNx4HI,
|
||||
_u16m2, _u16, _e16m2)
|
||||
/* LMUL = 4:
|
||||
Machine mode = VNx16HImode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx8HImode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vint16m4_t, 15, __rvv_int16m4_t, intHI, VNx16HI, VNx8HI)
|
||||
DEF_RVV_TYPE (vint16m4_t, 15, __rvv_int16m4_t, intHI, VNx16HI, VNx8HI, _i16m4,
|
||||
_i16, _e16m4)
|
||||
DEF_RVV_TYPE (vuint16m4_t, 16, __rvv_uint16m4_t, unsigned_intHI, VNx16HI,
|
||||
VNx8HI)
|
||||
VNx8HI, _u16m4, _u16, _e16m4)
|
||||
/* LMUL = 8:
|
||||
Machine mode = VNx32HImode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx16HImode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vint16m8_t, 15, __rvv_int16m8_t, intHI, VNx32HI, VNx16HI)
|
||||
DEF_RVV_TYPE (vint16m8_t, 15, __rvv_int16m8_t, intHI, VNx32HI, VNx16HI, _i16m8,
|
||||
_i16, _e16m8)
|
||||
DEF_RVV_TYPE (vuint16m8_t, 16, __rvv_uint16m8_t, unsigned_intHI, VNx32HI,
|
||||
VNx16HI)
|
||||
VNx16HI, _u16m8, _u16, _e16m8)
|
||||
|
||||
/* LMUL = 1/2:
|
||||
Only enble when TARGET_MIN_VLEN > 32 and machine mode = VNx1SImode. */
|
||||
DEF_RVV_TYPE (vint32mf2_t, 16, __rvv_int32mf2_t, int32, VNx1SI, VOID)
|
||||
DEF_RVV_TYPE (vuint32mf2_t, 17, __rvv_uint32mf2_t, unsigned_int32, VNx1SI, VOID)
|
||||
DEF_RVV_TYPE (vint32mf2_t, 16, __rvv_int32mf2_t, int32, VNx1SI, VOID, _i32mf2,
|
||||
_i32, _e32mf2)
|
||||
DEF_RVV_TYPE (vuint32mf2_t, 17, __rvv_uint32mf2_t, unsigned_int32, VNx1SI, VOID,
|
||||
_u32mf2, _u32, _e32mf2)
|
||||
/* LMUL = 1:
|
||||
Machine mode = VNx2SImode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx1SImode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vint32m1_t, 15, __rvv_int32m1_t, int32, VNx2SI, VNx1SI)
|
||||
DEF_RVV_TYPE (vuint32m1_t, 16, __rvv_uint32m1_t, unsigned_int32, VNx2SI, VNx1SI)
|
||||
DEF_RVV_TYPE (vint32m1_t, 15, __rvv_int32m1_t, int32, VNx2SI, VNx1SI, _i32m1,
|
||||
_i32, _e32m1)
|
||||
DEF_RVV_TYPE (vuint32m1_t, 16, __rvv_uint32m1_t, unsigned_int32, VNx2SI, VNx1SI,
|
||||
_u32m1, _u32, _e32m1)
|
||||
/* LMUL = 2:
|
||||
Machine mode = VNx4SImode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx2SImode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vint32m2_t, 15, __rvv_int32m2_t, int32, VNx4SI, VNx2SI)
|
||||
DEF_RVV_TYPE (vuint32m2_t, 16, __rvv_uint32m2_t, unsigned_int32, VNx4SI, VNx2SI)
|
||||
DEF_RVV_TYPE (vint32m2_t, 15, __rvv_int32m2_t, int32, VNx4SI, VNx2SI, _i32m2,
|
||||
_i32, _e32m2)
|
||||
DEF_RVV_TYPE (vuint32m2_t, 16, __rvv_uint32m2_t, unsigned_int32, VNx4SI, VNx2SI,
|
||||
_u32m2, _u32, _e32m2)
|
||||
/* LMUL = 4:
|
||||
Machine mode = VNx8SImode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx4SImode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vint32m4_t, 15, __rvv_int32m4_t, int32, VNx8SI, VNx4SI)
|
||||
DEF_RVV_TYPE (vuint32m4_t, 16, __rvv_uint32m4_t, unsigned_int32, VNx8SI, VNx4SI)
|
||||
DEF_RVV_TYPE (vint32m4_t, 15, __rvv_int32m4_t, int32, VNx8SI, VNx4SI, _i32m4,
|
||||
_i32, _e32m4)
|
||||
DEF_RVV_TYPE (vuint32m4_t, 16, __rvv_uint32m4_t, unsigned_int32, VNx8SI, VNx4SI,
|
||||
_u32m4, _u32, _e32m4)
|
||||
/* LMUL = 8:
|
||||
Machine mode = VNx16SImode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx8SImode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vint32m8_t, 15, __rvv_int32m8_t, int32, VNx16SI, VNx8SI)
|
||||
DEF_RVV_TYPE (vint32m8_t, 15, __rvv_int32m8_t, int32, VNx16SI, VNx8SI, _i32m8,
|
||||
_i32, _e32m8)
|
||||
DEF_RVV_TYPE (vuint32m8_t, 16, __rvv_uint32m8_t, unsigned_int32, VNx16SI,
|
||||
VNx8SI)
|
||||
VNx8SI, _u32m8, _u32, _e32m8)
|
||||
|
||||
/* SEW = 64:
|
||||
Disable when TARGET_MIN_VLEN > 32. */
|
||||
DEF_RVV_TYPE (vint64m1_t, 15, __rvv_int64m1_t, intDI, VNx1DI, VOID)
|
||||
DEF_RVV_TYPE (vuint64m1_t, 16, __rvv_uint64m1_t, unsigned_intDI, VNx1DI, VOID)
|
||||
DEF_RVV_TYPE (vint64m2_t, 15, __rvv_int64m2_t, intDI, VNx2DI, VOID)
|
||||
DEF_RVV_TYPE (vuint64m2_t, 16, __rvv_uint64m2_t, unsigned_intDI, VNx2DI, VOID)
|
||||
DEF_RVV_TYPE (vint64m4_t, 15, __rvv_int64m4_t, intDI, VNx4DI, VOID)
|
||||
DEF_RVV_TYPE (vuint64m4_t, 16, __rvv_uint64m4_t, unsigned_intDI, VNx4DI, VOID)
|
||||
DEF_RVV_TYPE (vint64m8_t, 15, __rvv_int64m8_t, intDI, VNx8DI, VOID)
|
||||
DEF_RVV_TYPE (vuint64m8_t, 16, __rvv_uint64m8_t, unsigned_intDI, VNx8DI, VOID)
|
||||
DEF_RVV_TYPE (vint64m1_t, 15, __rvv_int64m1_t, intDI, VNx1DI, VOID, _i64m1,
|
||||
_i64, _e64m1)
|
||||
DEF_RVV_TYPE (vuint64m1_t, 16, __rvv_uint64m1_t, unsigned_intDI, VNx1DI, VOID,
|
||||
_u64m1, _u64, _e64m1)
|
||||
DEF_RVV_TYPE (vint64m2_t, 15, __rvv_int64m2_t, intDI, VNx2DI, VOID, _i64m2,
|
||||
_i64, _e64m2)
|
||||
DEF_RVV_TYPE (vuint64m2_t, 16, __rvv_uint64m2_t, unsigned_intDI, VNx2DI, VOID,
|
||||
_u64m2, _u64, _e64m2)
|
||||
DEF_RVV_TYPE (vint64m4_t, 15, __rvv_int64m4_t, intDI, VNx4DI, VOID, _i64m4,
|
||||
_i64, _e64m4)
|
||||
DEF_RVV_TYPE (vuint64m4_t, 16, __rvv_uint64m4_t, unsigned_intDI, VNx4DI, VOID,
|
||||
_u64m4, _u64, _e64m4)
|
||||
DEF_RVV_TYPE (vint64m8_t, 15, __rvv_int64m8_t, intDI, VNx8DI, VOID, _i64m8,
|
||||
_i64, _e64m8)
|
||||
DEF_RVV_TYPE (vuint64m8_t, 16, __rvv_uint64m8_t, unsigned_intDI, VNx8DI, VOID,
|
||||
_u64m8, _u64, _e64m8)
|
||||
|
||||
/* LMUL = 1/2:
|
||||
Only enble when TARGET_MIN_VLEN > 32 and machine mode = VNx1SFmode. */
|
||||
DEF_RVV_TYPE (vfloat32mf2_t, 18, __rvv_float32mf2_t, float, VNx1SF, VOID)
|
||||
DEF_RVV_TYPE (vfloat32mf2_t, 18, __rvv_float32mf2_t, float, VNx1SF, VOID,
|
||||
_f32mf2, _f32, _e32mf2)
|
||||
/* LMUL = 1:
|
||||
Machine mode = VNx2SFmode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx1SFmode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vfloat32m1_t, 17, __rvv_float32m1_t, float, VNx2SF, VNx1SF)
|
||||
DEF_RVV_TYPE (vfloat32m1_t, 17, __rvv_float32m1_t, float, VNx2SF, VNx1SF,
|
||||
_f32m1, _f32, _e32m1)
|
||||
/* LMUL = 2:
|
||||
Machine mode = VNx4SFmode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx2SFmode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vfloat32m2_t, 17, __rvv_float32m2_t, float, VNx4SF, VNx2SF)
|
||||
DEF_RVV_TYPE (vfloat32m2_t, 17, __rvv_float32m2_t, float, VNx4SF, VNx2SF,
|
||||
_f32m2, _f32, _e32m2)
|
||||
/* LMUL = 4:
|
||||
Machine mode = VNx8SFmode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx4SFmode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vfloat32m4_t, 17, __rvv_float32m4_t, float, VNx8SF, VNx4SF)
|
||||
DEF_RVV_TYPE (vfloat32m4_t, 17, __rvv_float32m4_t, float, VNx8SF, VNx4SF,
|
||||
_f32m4, _f32, _e32m4)
|
||||
/* LMUL = 8:
|
||||
Machine mode = VNx16SFmode when TARGET_MIN_VLEN > 32.
|
||||
Machine mode = VNx8SFmode when TARGET_MIN_VLEN = 32. */
|
||||
DEF_RVV_TYPE (vfloat32m8_t, 17, __rvv_float32m8_t, float, VNx16SF, VNx8SF)
|
||||
DEF_RVV_TYPE (vfloat32m8_t, 17, __rvv_float32m8_t, float, VNx16SF, VNx8SF,
|
||||
_f32m8, _f32, _e32m8)
|
||||
|
||||
/* SEW = 64:
|
||||
Disable when TARGET_VECTOR_FP64. */
|
||||
DEF_RVV_TYPE (vfloat64m1_t, 17, __rvv_float64m1_t, double, VNx1DF, VOID)
|
||||
DEF_RVV_TYPE (vfloat64m2_t, 17, __rvv_float64m2_t, double, VNx2DF, VOID)
|
||||
DEF_RVV_TYPE (vfloat64m4_t, 17, __rvv_float64m4_t, double, VNx4DF, VOID)
|
||||
DEF_RVV_TYPE (vfloat64m8_t, 17, __rvv_float64m8_t, double, VNx8DF, VOID)
|
||||
DEF_RVV_TYPE (vfloat64m1_t, 17, __rvv_float64m1_t, double, VNx1DF, VOID, _f64m1,
|
||||
_f64, _e64m1)
|
||||
DEF_RVV_TYPE (vfloat64m2_t, 17, __rvv_float64m2_t, double, VNx2DF, VOID, _f64m2,
|
||||
_f64, _e64m2)
|
||||
DEF_RVV_TYPE (vfloat64m4_t, 17, __rvv_float64m4_t, double, VNx4DF, VOID, _f64m4,
|
||||
_f64, _e64m4)
|
||||
DEF_RVV_TYPE (vfloat64m8_t, 17, __rvv_float64m8_t, double, VNx8DF, VOID, _f64m8,
|
||||
_f64, _e64m8)
|
||||
|
||||
DEF_RVV_OP_TYPE (vv)
|
||||
DEF_RVV_OP_TYPE (vx)
|
||||
DEF_RVV_OP_TYPE (v)
|
||||
DEF_RVV_OP_TYPE (wv)
|
||||
DEF_RVV_OP_TYPE (wx)
|
||||
DEF_RVV_OP_TYPE (x_x_v)
|
||||
DEF_RVV_OP_TYPE (vf2)
|
||||
DEF_RVV_OP_TYPE (vf4)
|
||||
DEF_RVV_OP_TYPE (vf8)
|
||||
DEF_RVV_OP_TYPE (vvm)
|
||||
DEF_RVV_OP_TYPE (vxm)
|
||||
DEF_RVV_OP_TYPE (x_x_w)
|
||||
DEF_RVV_OP_TYPE (v_v)
|
||||
DEF_RVV_OP_TYPE (v_x)
|
||||
DEF_RVV_OP_TYPE (vs)
|
||||
DEF_RVV_OP_TYPE (mm)
|
||||
DEF_RVV_OP_TYPE (m)
|
||||
DEF_RVV_OP_TYPE (vf)
|
||||
DEF_RVV_OP_TYPE (vm)
|
||||
DEF_RVV_OP_TYPE (wf)
|
||||
DEF_RVV_OP_TYPE (vfm)
|
||||
DEF_RVV_OP_TYPE (v_f)
|
||||
|
||||
DEF_RVV_PRED_TYPE (ta)
|
||||
DEF_RVV_PRED_TYPE (tu)
|
||||
DEF_RVV_PRED_TYPE (ma)
|
||||
DEF_RVV_PRED_TYPE (mu)
|
||||
DEF_RVV_PRED_TYPE (tama)
|
||||
DEF_RVV_PRED_TYPE (tamu)
|
||||
DEF_RVV_PRED_TYPE (tuma)
|
||||
DEF_RVV_PRED_TYPE (tumu)
|
||||
DEF_RVV_PRED_TYPE (m)
|
||||
DEF_RVV_PRED_TYPE (tam)
|
||||
DEF_RVV_PRED_TYPE (tum)
|
||||
|
||||
#undef DEF_RVV_PRED_TYPE
|
||||
#undef DEF_RVV_OP_TYPE
|
||||
#undef DEF_RVV_TYPE
|
||||
|
|
|
@ -21,8 +21,101 @@
|
|||
#ifndef GCC_RISCV_VECTOR_BUILTINS_H
|
||||
#define GCC_RISCV_VECTOR_BUILTINS_H
|
||||
|
||||
/* The full name of an RVV intrinsic function is the concatenation of:
|
||||
|
||||
- the base name ("vadd", etc.)
|
||||
- the operand suffix ("_vv", "_vx", etc.)
|
||||
- the type suffix ("_i32m1", "_i32mf2", etc.)
|
||||
- the predication suffix ("_tamu", "_tumu", etc.)
|
||||
|
||||
Each piece of information is individually useful, so we retain this
|
||||
classification throughout:
|
||||
|
||||
- function_base represents the base name.
|
||||
|
||||
- operand_type_index can be used as an index to get operand suffix.
|
||||
|
||||
- rvv_op_info can be used as an index to get argument suffix.
|
||||
|
||||
- predication_type_index can be used as an index to get predication suffix.
|
||||
|
||||
In addition to its unique full name, a function may have a shorter
|
||||
overloaded alias. This alias removes pieces of the suffixes that
|
||||
can be inferred from the arguments, such as by shortening the mode
|
||||
suffix or dropping some of the type suffixes. The base name and the
|
||||
predication suffix stay the same.
|
||||
|
||||
- The function_instance class describes contains all properties of each
|
||||
individual function. Such these information will be used by
|
||||
function_builder, function_base, function_shape, gimple_folder,
|
||||
function_expander, etc.
|
||||
|
||||
- The function_builder class provides several helper function to add an
|
||||
intrinsic function.
|
||||
|
||||
- The function_shape class describes how that instruction has been presented
|
||||
at the language level:
|
||||
|
||||
1. Determine the function name for C and C++ overload function which can
|
||||
be recognized by compiler at language level for each instruction
|
||||
according to members of function_instance (base name, operand suffix,
|
||||
type suffix, predication suffix, etc.).
|
||||
|
||||
2. Specify the arguments type and return type of each function to
|
||||
describe how that instruction has presented at language level.
|
||||
|
||||
- The function_base describes how the underlying instruction behaves.
|
||||
|
||||
The static list of functions uses function_group to describe a group
|
||||
of related functions. The function_builder class is responsible for
|
||||
expanding this static description into a list of individual functions
|
||||
and registering the associated built-in functions. function_instance
|
||||
describes one of these individual functions in terms of the properties
|
||||
described above.
|
||||
|
||||
The classes involved in compiling a function call are:
|
||||
|
||||
- function_resolver, which resolves an overloaded function call to a
|
||||
specific function_instance and its associated function decl.
|
||||
|
||||
- function_checker, which checks whether the values of the arguments
|
||||
conform to the RVV ISA specification.
|
||||
|
||||
- gimple_folder, which tries to fold a function call at the gimple level
|
||||
|
||||
- function_expander, which expands a function call into rtl instructions
|
||||
|
||||
function_resolver and function_checker operate at the language level
|
||||
and so are associated with the function_shape. gimple_folder and
|
||||
function_expander are concerned with the behavior of the function
|
||||
and so are associated with the function_base. */
|
||||
|
||||
namespace riscv_vector {
|
||||
|
||||
/* Flags that describe what a function might do, in addition to reading
|
||||
its arguments and returning a result. */
|
||||
static const unsigned int CP_READ_FPCR = 1U << 0;
|
||||
static const unsigned int CP_RAISE_FP_EXCEPTIONS = 1U << 1;
|
||||
static const unsigned int CP_READ_MEMORY = 1U << 2;
|
||||
static const unsigned int CP_WRITE_MEMORY = 1U << 3;
|
||||
static const unsigned int CP_READ_CSR = 1U << 4;
|
||||
static const unsigned int CP_WRITE_CSR = 1U << 5;
|
||||
|
||||
/* Bit values used to identify required extensions for RVV intrinsics. */
|
||||
#define RVV_REQUIRE_RV64BIT (1 << 0) /* Require RV64. */
|
||||
#define RVV_REQUIRE_ZVE64 (1 << 1) /* Require TARGET_MIN_VLEN > 32. */
|
||||
#define RVV_REQUIRE_ELEN_FP_32 (1 << 2) /* Require FP ELEN >= 32. */
|
||||
#define RVV_REQUIRE_ELEN_FP_64 (1 << 3) /* Require FP ELEN >= 64. */
|
||||
|
||||
/* Enumerates the RVV operand types. */
|
||||
enum operand_type_index
|
||||
{
|
||||
OP_TYPE_none,
|
||||
#define DEF_RVV_OP_TYPE(NAME) OP_TYPE_##NAME,
|
||||
#include "riscv-vector-builtins.def"
|
||||
NUM_OP_TYPES
|
||||
};
|
||||
|
||||
/* Enumerates the RVV types, together called
|
||||
"vector types" for brevity. */
|
||||
enum vector_type_index
|
||||
|
@ -32,6 +125,31 @@ enum vector_type_index
|
|||
NUM_VECTOR_TYPES
|
||||
};
|
||||
|
||||
/* Enumerates the RVV governing predication types. */
|
||||
enum predication_type_index
|
||||
{
|
||||
PRED_TYPE_none,
|
||||
#define DEF_RVV_PRED_TYPE(NAME) PRED_TYPE_##NAME,
|
||||
#include "riscv-vector-builtins.def"
|
||||
NUM_PRED_TYPES
|
||||
};
|
||||
|
||||
/* Enumerates the RVV base types. */
|
||||
enum rvv_base_type
|
||||
{
|
||||
RVV_BASE_vector,
|
||||
RVV_BASE_scalar,
|
||||
RVV_BASE_vector_ptr,
|
||||
RVV_BASE_scalar_ptr,
|
||||
RVV_BASE_scalar_const_ptr,
|
||||
RVV_BASE_void,
|
||||
RVV_BASE_size,
|
||||
RVV_BASE_ptrdiff,
|
||||
RVV_BASE_unsigned_long,
|
||||
RVV_BASE_long,
|
||||
NUM_BASE_TYPES
|
||||
};
|
||||
|
||||
/* Builtin types that are used to register RVV intrinsics. */
|
||||
struct GTY (()) rvv_builtin_types_t
|
||||
{
|
||||
|
@ -42,6 +160,251 @@ struct GTY (()) rvv_builtin_types_t
|
|||
tree scalar_const_ptr;
|
||||
};
|
||||
|
||||
/* Builtin suffix that are used to register RVV intrinsics. */
|
||||
struct rvv_builtin_suffixes
|
||||
{
|
||||
const char *vector;
|
||||
const char *scalar;
|
||||
const char *vsetvl;
|
||||
};
|
||||
|
||||
/* RVV Builtin argument information. */
|
||||
struct rvv_arg_type_info
|
||||
{
|
||||
CONSTEXPR rvv_arg_type_info (rvv_base_type base_type_in)
|
||||
: base_type (base_type_in)
|
||||
{}
|
||||
enum rvv_base_type base_type;
|
||||
|
||||
tree get_tree_type (vector_type_index) const;
|
||||
};
|
||||
|
||||
/* Static information for each operand. */
|
||||
struct rvv_type_info
|
||||
{
|
||||
enum vector_type_index index;
|
||||
uint64_t required_extensions;
|
||||
};
|
||||
|
||||
/* RVV Builtin operands information. */
|
||||
struct rvv_op_info
|
||||
{
|
||||
const rvv_type_info *types;
|
||||
const operand_type_index op;
|
||||
rvv_arg_type_info ret;
|
||||
const rvv_arg_type_info *args;
|
||||
};
|
||||
|
||||
class registered_function;
|
||||
class function_base;
|
||||
class function_shape;
|
||||
|
||||
/* Static information about a set of functions. */
|
||||
struct function_group_info
|
||||
{
|
||||
/* The base name, as a string. */
|
||||
const char *base_name;
|
||||
|
||||
/* Describes the behavior associated with the function base name. */
|
||||
const function_base *const *base;
|
||||
|
||||
/* The shape of the functions, as described above the class definition.
|
||||
It's possible to have entries with the same base name but different
|
||||
shapes. */
|
||||
const function_shape *const *shape;
|
||||
|
||||
/* A list of the available operand types, predication types,
|
||||
and of the available operand datatype.
|
||||
The function supports every combination of the two.
|
||||
The list of predication is terminated by two NUM_PRED_TYPES,
|
||||
while the list of operand info is terminated by NUM_BASE_TYPES.
|
||||
The list of these type suffix is lexicographically ordered based
|
||||
on the index value. */
|
||||
const predication_type_index *preds;
|
||||
const rvv_op_info ops_infos;
|
||||
};
|
||||
|
||||
class GTY ((user)) function_instance
|
||||
{
|
||||
public:
|
||||
function_instance (const char *, const function_base *,
|
||||
const function_shape *, rvv_type_info,
|
||||
predication_type_index, const rvv_op_info *);
|
||||
|
||||
bool operator== (const function_instance &) const;
|
||||
bool operator!= (const function_instance &) const;
|
||||
hashval_t hash () const;
|
||||
|
||||
unsigned int call_properties () const;
|
||||
bool reads_global_state_p () const;
|
||||
bool modifies_global_state_p () const;
|
||||
bool could_trap_p () const;
|
||||
|
||||
/* Return true if return type or arguments are floating point type. */
|
||||
bool any_type_float_p () const;
|
||||
|
||||
tree get_return_type () const;
|
||||
tree get_arg_type (unsigned opno) const;
|
||||
|
||||
/* The properties of the function. (The explicit "enum"s are required
|
||||
for gengtype.) */
|
||||
const char *base_name;
|
||||
const function_base *base;
|
||||
const function_shape *shape;
|
||||
rvv_type_info type;
|
||||
enum predication_type_index pred;
|
||||
const rvv_op_info *op_info;
|
||||
};
|
||||
|
||||
/* A class for building and registering function decls. */
|
||||
class function_builder
|
||||
{
|
||||
public:
|
||||
function_builder ();
|
||||
~function_builder ();
|
||||
|
||||
void allocate_argument_types (const function_instance &, vec<tree> &) const;
|
||||
void add_unique_function (const function_instance &, const function_shape *,
|
||||
tree, vec<tree> &);
|
||||
void register_function_group (const function_group_info &);
|
||||
void append_name (const char *);
|
||||
char *finish_name ();
|
||||
|
||||
private:
|
||||
tree get_attributes (const function_instance &);
|
||||
|
||||
registered_function &add_function (const function_instance &, const char *,
|
||||
tree, tree, bool);
|
||||
|
||||
/* True if we should create a separate decl for each instance of an
|
||||
overloaded function, instead of using function_builder. */
|
||||
bool m_direct_overloads;
|
||||
|
||||
/* Used for building up function names. */
|
||||
obstack m_string_obstack;
|
||||
};
|
||||
|
||||
/* A base class for handling calls to built-in functions. */
|
||||
class function_call_info : public function_instance
|
||||
{
|
||||
public:
|
||||
function_call_info (location_t, const function_instance &, tree);
|
||||
|
||||
bool function_returns_void_p ();
|
||||
|
||||
/* The location of the call. */
|
||||
location_t location;
|
||||
|
||||
/* The FUNCTION_DECL that is being called. */
|
||||
tree fndecl;
|
||||
};
|
||||
|
||||
/* Return true if the function has no return value. */
|
||||
inline bool
|
||||
function_call_info::function_returns_void_p ()
|
||||
{
|
||||
return TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
|
||||
}
|
||||
|
||||
/* A class for expanding a function call into RTL. */
|
||||
class function_expander : public function_call_info
|
||||
{
|
||||
public:
|
||||
function_expander (const function_instance &, tree, tree, rtx);
|
||||
rtx expand ();
|
||||
|
||||
void add_input_operand (machine_mode, rtx);
|
||||
void add_input_operand (unsigned argno);
|
||||
rtx generate_insn (insn_code);
|
||||
|
||||
/* The function call expression. */
|
||||
tree exp;
|
||||
|
||||
/* For functions that return a value, this is the preferred location
|
||||
of that value. It could be null or could have a different mode
|
||||
from the function return type. */
|
||||
rtx target;
|
||||
|
||||
/* The number of the operands. */
|
||||
int opno;
|
||||
|
||||
private:
|
||||
/* Used to build up the operands to an instruction. */
|
||||
struct expand_operand m_ops[MAX_RECOG_OPERANDS];
|
||||
};
|
||||
|
||||
/* Provides information about a particular function base name, and handles
|
||||
tasks related to the base name. */
|
||||
class function_base
|
||||
{
|
||||
public:
|
||||
/* Return a set of CP_* flags that describe what the function might do,
|
||||
in addition to reading its arguments and returning a result. */
|
||||
virtual unsigned int call_properties (const function_instance &) const;
|
||||
|
||||
/* Expand the given call into rtl. Return the result of the function,
|
||||
or an arbitrary value if the function doesn't return a result. */
|
||||
virtual rtx expand (function_expander &) const = 0;
|
||||
};
|
||||
|
||||
/* Classifies functions into "shapes" base on:
|
||||
|
||||
- Base name of the intrinsic function.
|
||||
|
||||
- Operand types list.
|
||||
|
||||
- Argument type list.
|
||||
|
||||
- Predication type list. */
|
||||
class function_shape
|
||||
{
|
||||
public:
|
||||
/* Shape the function name according to function_instance. */
|
||||
virtual char *get_name (function_builder &, const function_instance &,
|
||||
bool) const
|
||||
= 0;
|
||||
|
||||
/* Define all functions associated with the given group. */
|
||||
virtual void build (function_builder &, const function_group_info &) const
|
||||
= 0;
|
||||
};
|
||||
|
||||
extern const char *const operand_suffixes[NUM_OP_TYPES];
|
||||
extern const rvv_builtin_suffixes type_suffixes[NUM_VECTOR_TYPES + 1];
|
||||
extern const char *const predication_suffixes[NUM_PRED_TYPES];
|
||||
extern rvv_builtin_types_t builtin_types[NUM_VECTOR_TYPES + 1];
|
||||
|
||||
inline bool
|
||||
function_instance::operator!= (const function_instance &other) const
|
||||
{
|
||||
return !operator== (other);
|
||||
}
|
||||
|
||||
/* Expand the call and return its lhs. */
|
||||
inline rtx
|
||||
function_expander::expand ()
|
||||
{
|
||||
return base->expand (*this);
|
||||
}
|
||||
|
||||
/* Create op and add it into M_OPS and increase OPNO. */
|
||||
inline void
|
||||
function_expander::add_input_operand (machine_mode mode, rtx op)
|
||||
{
|
||||
create_input_operand (&m_ops[opno++], op, mode);
|
||||
}
|
||||
|
||||
/* Default implementation of function_base::call_properties, with conservatively
|
||||
correct behavior for floating-point instructions. */
|
||||
inline unsigned int
|
||||
function_base::call_properties (const function_instance &instance) const
|
||||
{
|
||||
unsigned int flags = 0;
|
||||
if (instance.any_type_float_p ())
|
||||
return flags | CP_READ_FPCR | CP_RAISE_FP_EXCEPTIONS;
|
||||
return flags;
|
||||
}
|
||||
|
||||
} // end namespace riscv_vector
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue