#define builtin_define(TXT) cpp_define (pfile, TXT)
-struct pragma_intrinsic_flags
-{
- int intrinsic_riscv_isa_flags;
-
- int intrinsic_riscv_vector_elen_flags;
- int intrinsic_riscv_zvl_subext;
- int intrinsic_riscv_zvb_subext;
- int intrinsic_riscv_zvk_subext;
-};
-
-static void
-riscv_pragma_intrinsic_flags_pollute (struct pragma_intrinsic_flags *flags)
-{
- flags->intrinsic_riscv_isa_flags = riscv_isa_flags;
- flags->intrinsic_riscv_vector_elen_flags = riscv_vector_elen_flags;
- flags->intrinsic_riscv_zvl_subext = riscv_zvl_subext;
- flags->intrinsic_riscv_zvb_subext = riscv_zvb_subext;
- flags->intrinsic_riscv_zvk_subext = riscv_zvk_subext;
-
- riscv_isa_flags = riscv_isa_flags
- | MASK_VECTOR;
-
- riscv_zvl_subext = riscv_zvl_subext
- | MASK_ZVL32B
- | MASK_ZVL64B
- | MASK_ZVL128B
- | MASK_ZVL256B
- | MASK_ZVL512B
- | MASK_ZVL1024B
- | MASK_ZVL2048B
- | MASK_ZVL4096B;
-
- riscv_vector_elen_flags = riscv_vector_elen_flags
- | MASK_VECTOR_ELEN_32
- | MASK_VECTOR_ELEN_64
- | MASK_VECTOR_ELEN_FP_16
- | MASK_VECTOR_ELEN_FP_32
- | MASK_VECTOR_ELEN_FP_64;
-
- riscv_zvb_subext = riscv_zvb_subext
- | MASK_ZVBB
- | MASK_ZVBC
- | MASK_ZVKB;
-
- riscv_zvk_subext = riscv_zvk_subext
- | MASK_ZVKG
- | MASK_ZVKNED
- | MASK_ZVKNHA
- | MASK_ZVKNHB
- | MASK_ZVKSED
- | MASK_ZVKSH
- | MASK_ZVKN
- | MASK_ZVKNC
- | MASK_ZVKNG
- | MASK_ZVKS
- | MASK_ZVKSC
- | MASK_ZVKSG
- | MASK_ZVKT;
-}
-
-static void
-riscv_pragma_intrinsic_flags_restore (struct pragma_intrinsic_flags *flags)
-{
- riscv_isa_flags = flags->intrinsic_riscv_isa_flags;
-
- riscv_vector_elen_flags = flags->intrinsic_riscv_vector_elen_flags;
- riscv_zvl_subext = flags->intrinsic_riscv_zvl_subext;
- riscv_zvb_subext = flags->intrinsic_riscv_zvb_subext;
- riscv_zvk_subext = flags->intrinsic_riscv_zvk_subext;
-}
-
static int
riscv_ext_version_value (unsigned major, unsigned minor)
{
|| strcmp (name, "xtheadvector") == 0
|| strcmp (name, "xsfvcp") == 0)
{
- struct pragma_intrinsic_flags backup_flags;
-
- riscv_pragma_intrinsic_flags_pollute (&backup_flags);
-
- riscv_option_override ();
- init_adjust_machine_modes ();
- riscv_vector::reinit_builtins ();
riscv_vector::handle_pragma_vector ();
-
- riscv_pragma_intrinsic_flags_restore (&backup_flags);
-
- /* Re-initialize after the flags are restored. */
- riscv_option_override ();
- init_adjust_machine_modes ();
}
else
error ("unknown %<#pragma riscv intrinsic%> option %qs", name);
static hash_table<non_overloaded_registered_function_hasher>
*non_overloaded_function_table;
+struct pragma_intrinsic_flags
+{
+ int intrinsic_riscv_isa_flags;
+ int intrinsic_riscv_base_subext;
+
+ int intrinsic_riscv_vector_elen_flags;
+ int intrinsic_riscv_zvl_subext;
+ int intrinsic_riscv_zvf_subext;
+};
+
+static void
+riscv_pragma_intrinsic_flags_pollute (struct pragma_intrinsic_flags *flags)
+{
+ /* We already defer the required extension checking to expantion time, so we
+ only need to pollute those flags that might affect the type registration.
+
+ e.g. zvfbmin and zvfhmin are required to define the vector bf16 and f16,
+ and VECTOR_ELEN* also required for vector interger and floating
+ type. */
+ flags->intrinsic_riscv_isa_flags = riscv_isa_flags;
+ flags->intrinsic_riscv_base_subext = riscv_base_subext;
+ flags->intrinsic_riscv_vector_elen_flags = riscv_vector_elen_flags;
+ flags->intrinsic_riscv_zvl_subext = riscv_zvl_subext;
+ flags->intrinsic_riscv_zvf_subext = riscv_zvf_subext;
+
+ riscv_zvf_subext = riscv_zvf_subext
+ | MASK_ZVFBFMIN
+ | MASK_ZVFHMIN;
+
+ riscv_isa_flags = riscv_isa_flags
+ | MASK_VECTOR;
+
+ riscv_base_subext = riscv_base_subext
+ | MASK_MUL;
+
+ riscv_zvl_subext = riscv_zvl_subext
+ | MASK_ZVL32B
+ | MASK_ZVL64B
+ | MASK_ZVL128B
+ | MASK_ZVL256B
+ | MASK_ZVL512B
+ | MASK_ZVL1024B
+ | MASK_ZVL2048B
+ | MASK_ZVL4096B;
+
+ riscv_vector_elen_flags = riscv_vector_elen_flags
+ | MASK_VECTOR_ELEN_32
+ | MASK_VECTOR_ELEN_64
+ | MASK_VECTOR_ELEN_FP_16
+ | MASK_VECTOR_ELEN_FP_32
+ | MASK_VECTOR_ELEN_FP_64
+ | MASK_VECTOR_ELEN_BF_16;
+}
+
+static void
+riscv_pragma_intrinsic_flags_restore (struct pragma_intrinsic_flags *flags)
+{
+ riscv_isa_flags = flags->intrinsic_riscv_isa_flags;
+ riscv_base_subext = flags->intrinsic_riscv_base_subext;
+
+ riscv_vector_elen_flags = flags->intrinsic_riscv_vector_elen_flags;
+ riscv_zvl_subext = flags->intrinsic_riscv_zvl_subext;
+ riscv_zvf_subext = flags->intrinsic_riscv_zvf_subext;
+}
+
/* RAII class for enabling enough RVV features to define the built-in
types and implement the riscv_vector.h pragma.
class rvv_switcher
{
public:
- rvv_switcher ();
+ rvv_switcher (bool pollute_flags = true);
~rvv_switcher ();
private:
bool m_old_have_regs_of_mode[MAX_MACHINE_MODE];
+ struct pragma_intrinsic_flags backup_flags;
+ bool m_pollute_flags;
};
-rvv_switcher::rvv_switcher ()
+static void
+register_builtin_types_on_null ();
+
+rvv_switcher::rvv_switcher (bool pollute_flags)
+ : m_pollute_flags (pollute_flags)
{
+ if (m_pollute_flags)
+ {
+ riscv_pragma_intrinsic_flags_pollute (&backup_flags);
+ riscv_option_override ();
+ }
+
/* Set have_regs_of_mode before targetm.init_builtins (). */
memcpy (m_old_have_regs_of_mode, have_regs_of_mode,
sizeof (have_regs_of_mode));
for (int i = 0; i < NUM_MACHINE_MODES; ++i)
if (riscv_v_ext_vector_mode_p ((machine_mode) i))
have_regs_of_mode[i] = true;
+
+ /* Not necessary to adjust mode and register type if we don't pollute
+ flags. */
+ if (m_pollute_flags)
+ {
+ init_adjust_machine_modes ();
+
+ register_builtin_types_on_null ();
+ }
}
rvv_switcher::~rvv_switcher ()
/* Recover back have_regs_of_mode. */
memcpy (have_regs_of_mode, m_old_have_regs_of_mode,
sizeof (have_regs_of_mode));
+
+ if (m_pollute_flags)
+ {
+ riscv_pragma_intrinsic_flags_restore (&backup_flags);
+
+ /* Re-initialize after the flags are restored. */
+ riscv_option_override ();
+ init_adjust_machine_modes ();
+ }
}
/* Add attribute NAME to ATTRS. */
static void
register_builtin_types ()
{
- /* Get type node from get_typenode_from_name to prevent we have different type
- node define in different target libraries, e.g. int32_t defined as
- `long` in RV32/newlib-stdint, but `int` for RV32/glibc-stdint.h.
- NOTE: uint[16|32|64]_type_node already defined in tree.h. */
- tree int8_type_node = get_typenode_from_name (INT8_TYPE);
- tree uint8_type_node = get_typenode_from_name (UINT8_TYPE);
- tree int16_type_node = get_typenode_from_name (INT16_TYPE);
- tree int32_type_node = get_typenode_from_name (INT32_TYPE);
- tree int64_type_node = get_typenode_from_name (INT64_TYPE);
-
- machine_mode mode;
-#define DEF_RVV_TYPE(NAME, NCHARS, ABI_NAME, SCALAR_TYPE, VECTOR_MODE, \
- ARGS...) \
- mode = VECTOR_MODE##mode; \
- register_builtin_type (VECTOR_TYPE_##NAME, SCALAR_TYPE##_type_node, mode);
-#define DEF_RVV_TUPLE_TYPE(NAME, NCHARS, ABI_NAME, SUBPART_TYPE, SCALAR_TYPE, \
- NF, VECTOR_SUFFIX) \
- register_tuple_type (VECTOR_TYPE_##NAME, VECTOR_TYPE_##SUBPART_TYPE, \
- SCALAR_TYPE##_type_node, NF);
-#include "riscv-vector-builtins.def"
+ /* Don't pollute flags at this stage to make sure we only register type with
+ what we want so far, we will register all type if necessary later. */
+ rvv_switcher rvv (/* pollute_flags */ false);
+ register_builtin_types_on_null ();
}
/* Similar as register_builtin_types but perform the registration if and
gcc_unreachable ();
}
-static uint64_t
-get_required_extensions (vector_type_index type_idx)
-{
- for (unsigned int i = 0; all_ops[i].index != NUM_VECTOR_TYPES; i++)
- if (type_idx == all_ops[i].index)
- return all_ops[i].required_extensions;
- for (unsigned int i = 0; b_ops[i].index != NUM_VECTOR_TYPES; i++)
- if (type_idx == b_ops[i].index)
- return b_ops[i].required_extensions;
- gcc_unreachable ();
-}
-
/* Check whether all the RVV_REQUIRE_* values in REQUIRED_EXTENSIONS are
- enabled. */
+ enabled.
+ TODO: We defer the required extensions to expantion time, this function is
+ only doing the legality now, and we may rename this function and moving
+ to another layer. */
static bool
check_required_extensions (const function_instance &instance)
{
rvv_type_info type_info = instance.type;
- uint64_t required_extensions = type_info.required_extensions;
const rvv_op_info *op_info = instance.op_info;
if (required_extensions_p (op_info->ret.base_type))
= op_info->ret.get_function_type_index (type_info.index);
if (ret_type_idx == NUM_VECTOR_TYPES)
return false;
- required_extensions |= get_required_extensions (ret_type_idx);
}
for (unsigned i = 0; op_info->args[i].base_type != NUM_BASE_TYPES; ++i)
{
if (!required_extensions_p (op_info->args[i].base_type))
continue;
-
enum vector_type_index vector_type
= op_info->args[i].get_function_type_index (type_info.index);
if (vector_type == NUM_VECTOR_TYPES)
return false;
- required_extensions |= get_required_extensions (vector_type);
-
- /* According to RVV ISA, EEW=64 index of indexed loads/stores require
- XLEN = 64. */
- if (op_info->args[i].base_type == RVV_BASE_eew64_index)
- required_extensions |= RVV_REQUIRE_RV64BIT;
}
- uint64_t isa_flags = 0;
-
- if (TARGET_VECTOR_ELEN_BF_16)
- isa_flags |= RVV_REQUIRE_ELEN_BF_16;
- if (TARGET_VECTOR_ELEN_FP_16)
- isa_flags |= RVV_REQUIRE_ELEN_FP_16;
- if (TARGET_VECTOR_ELEN_FP_32)
- isa_flags |= RVV_REQUIRE_ELEN_FP_32;
- if (TARGET_VECTOR_ELEN_FP_64)
- isa_flags |= RVV_REQUIRE_ELEN_FP_64;
- if (TARGET_VECTOR_ELEN_64)
- isa_flags |= RVV_REQUIRE_ELEN_64;
- if (TARGET_64BIT)
- isa_flags |= RVV_REQUIRE_RV64BIT;
- if (TARGET_FULL_V)
- isa_flags |= RVV_REQUIRE_FULL_V;
- if (TARGET_MIN_VLEN > 32)
- isa_flags |= RVV_REQUIRE_MIN_VLEN_64;
-
- uint64_t missing_extensions = required_extensions & ~isa_flags;
- if (missing_extensions != 0)
- return false;
return true;
}
return op_info->ret.get_tree_type (type.index);
}
+bool
+function_instance::function_returns_void_p () const
+{
+ return get_return_type () == void_type_node;
+}
+
tree
function_instance::get_arg_type (unsigned opno) const
{
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
+ tree decl = placeholder_p || in_lto_p
? integer_zero_node
: simulate_builtin_function_decl (input_location, name, fntype,
code, NULL, attrs);
void
init_builtins ()
{
- rvv_switcher rvv;
- if (!TARGET_VECTOR)
- return;
- register_builtin_types ();
- if (in_lto_p)
- handle_pragma_vector ();
-}
-
-/* Reinitialize builtins similar to init_builtins, but only the null
- builtin types will be registered. */
-void
-reinit_builtins ()
-{
- rvv_switcher rvv;
-
- if (!TARGET_VECTOR)
- return;
-
- register_builtin_types_on_null ();
-
if (in_lto_p)
+ /* "pragma vector" will register type during the process. */
handle_pragma_vector ();
+ else
+ {
+ if (!TARGET_VECTOR)
+ return;
+ register_builtin_types ();
+ }
}
/* Implement TARGET_VERIFY_TYPE_CONTEXT for RVV types. */
function_table = new hash_table<registered_function_hasher> (1023);
function_builder builder;
for (unsigned int i = 0; i < ARRAY_SIZE (function_groups); ++i)
- {
- if (function_groups[i].match (function_groups[i].required_extensions))
- builder.register_function_group (function_groups[i]);
- }
+ builder.register_function_group (function_groups[i]);
}
/* Return the function decl with RVV function subcode CODE, or error_mark_node