@@ -775,9 +775,9 @@ public:
tree pg = gimple_call_arg (f.call, 0);
if (!f.type_suffix (0).unsigned_p && integer_minus_onep (op2))
{
- function_instance instance ("svneg", functions::svneg,
- shapes::unary, MODE_none,
- f.type_suffix_ids, GROUP_none, f.pred);
+ function_instance instance ("svneg", functions::svneg, shapes::unary,
+ MODE_none, f.type_suffix_ids, GROUP_none,
+ f.pred, FPM_unused);
gcall *call = f.redirect_call (instance);
unsigned offset_index = 0;
if (f.pred == PRED_m)
@@ -805,7 +805,8 @@ public:
{
function_instance instance ("svlsr", functions::svlsr,
shapes::binary_uint_opt_n, MODE_n,
- f.type_suffix_ids, GROUP_none, f.pred);
+ f.type_suffix_ids, GROUP_none, f.pred,
+ FPM_unused);
call = f.redirect_call (instance);
tree d = INTEGRAL_TYPE_P (TREE_TYPE (op2)) ? op2 : op2_cst;
new_divisor = wide_int_to_tree (TREE_TYPE (d), tree_log2 (d));
@@ -818,7 +819,8 @@ public:
function_instance instance ("svasrd", functions::svasrd,
shapes::shift_right_imm, MODE_n,
- f.type_suffix_ids, GROUP_none, f.pred);
+ f.type_suffix_ids, GROUP_none, f.pred,
+ FPM_unused);
call = f.redirect_call (instance);
new_divisor = wide_int_to_tree (scalar_types[VECTOR_TYPE_svuint64_t],
tree_log2 (op2_cst));
@@ -2100,9 +2102,9 @@ public:
negated_op = op2;
if (!f.type_suffix (0).unsigned_p && negated_op)
{
- function_instance instance ("svneg", functions::svneg,
- shapes::unary, MODE_none,
- f.type_suffix_ids, GROUP_none, f.pred);
+ function_instance instance ("svneg", functions::svneg, shapes::unary,
+ MODE_none, f.type_suffix_ids, GROUP_none,
+ f.pred, FPM_unused);
gcall *call = f.redirect_call (instance);
unsigned offset_index = 0;
if (f.pred == PRED_m)
@@ -2143,7 +2145,8 @@ public:
tree_log2 (shift_op2));
function_instance instance ("svlsl", functions::svlsl,
shapes::binary_uint_opt_n, MODE_n,
- f.type_suffix_ids, GROUP_none, f.pred);
+ f.type_suffix_ids, GROUP_none, f.pred,
+ FPM_unused);
gcall *call = f.redirect_call (instance);
gimple_call_set_arg (call, 1, shift_op1);
gimple_call_set_arg (call, 2, shift_op2);
@@ -349,8 +349,8 @@ build_one (function_builder &b, const char *signature,
/* Byte forms of svdupq take 16 arguments. */
auto_vec<tree, 16> argument_types;
function_instance instance (group.base_name, *group.base, *group.shape,
- mode_suffix_id, group.types[ti],
- group.groups[gi], group.preds[pi]);
+ mode_suffix_id, group.types[ti], group.groups[gi],
+ group.preds[pi], group.fpm_mode);
tree return_type = parse_signature (instance, signature, argument_types);
apply_predication (instance, return_type, argument_types);
b.add_unique_function (instance, return_type, argument_types,
@@ -126,9 +126,9 @@ public:
tree op1 = gimple_call_arg (f.call, 0);
if (!integer_zerop (op1))
return NULL;
- function_instance instance ("svabd", functions::svabd,
- shapes::binary_opt_n, f.mode_suffix_id,
- f.type_suffix_ids, GROUP_none, PRED_x);
+ function_instance instance ("svabd", functions::svabd, shapes::binary_opt_n,
+ f.mode_suffix_id, f.type_suffix_ids, GROUP_none,
+ PRED_x, FPM_unused);
gcall *call = f.redirect_call (instance);
/* Add a ptrue as predicate, because unlike svaba, svabd is
predicated. */
@@ -512,7 +512,8 @@ public:
that we can use for sensible shift amounts. */
function_instance instance ("svqshl", functions::svqshl,
shapes::binary_int_opt_n, MODE_n,
- f.type_suffix_ids, GROUP_none, f.pred);
+ f.type_suffix_ids, GROUP_none, f.pred,
+ FPM_unused);
return f.redirect_call (instance);
}
else
@@ -520,9 +521,9 @@ public:
/* The saturation has no effect, and [SU]RSHL has immediate forms
that we can use for sensible shift amounts. */
function_instance instance ("svrshl", functions::svrshl,
- shapes::binary_int_opt_single_n,
- MODE_n, f.type_suffix_ids, GROUP_none,
- f.pred);
+ shapes::binary_int_opt_single_n, MODE_n,
+ f.type_suffix_ids, GROUP_none, f.pred,
+ FPM_unused);
return f.redirect_call (instance);
}
}
@@ -551,7 +552,8 @@ public:
-wi::to_wide (amount));
function_instance instance ("svasr", functions::svasr,
shapes::binary_uint_opt_n, MODE_n,
- f.type_suffix_ids, GROUP_none, f.pred);
+ f.type_suffix_ids, GROUP_none, f.pred,
+ FPM_unused);
if (f.type_suffix (0).unsigned_p)
{
instance.base_name = "svlsr";
@@ -586,7 +588,8 @@ public:
that we can use for sensible shift amounts. */
function_instance instance ("svlsl", functions::svlsl,
shapes::binary_uint_opt_n, MODE_n,
- f.type_suffix_ids, GROUP_none, f.pred);
+ f.type_suffix_ids, GROUP_none, f.pred,
+ FPM_unused);
gcall *call = f.redirect_call (instance);
gimple_call_set_arg (call, 2, amount);
return call;
@@ -599,7 +602,8 @@ public:
-wi::to_wide (amount));
function_instance instance ("svrshr", functions::svrshr,
shapes::shift_right_imm, MODE_n,
- f.type_suffix_ids, GROUP_none, f.pred);
+ f.type_suffix_ids, GROUP_none, f.pred,
+ FPM_unused);
gcall *call = f.redirect_call (instance);
gimple_call_set_arg (call, 2, amount);
return call;
@@ -635,7 +639,8 @@ public:
return NULL;
function_instance instance ("svlsr", functions::svlsr,
shapes::binary_uint_opt_n, MODE_n,
- f.type_suffix_ids, GROUP_none, PRED_x);
+ f.type_suffix_ids, GROUP_none, PRED_x,
+ FPM_unused);
if (!f.type_suffix (0).unsigned_p)
{
instance.base_name = "svasr";
@@ -933,9 +933,10 @@ static const predication_index preds_za_m[] = { PRED_za_m, NUM_PREDS };
/* A list of all arm_sve.h functions. */
static CONSTEXPR const function_group_info function_groups[] = {
-#define DEF_SVE_FUNCTION_GS(NAME, SHAPE, TYPES, GROUPS, PREDS) \
+#define DEF_SVE_FUNCTION_GS_FPM(NAME, SHAPE, TYPES, GROUPS, PREDS, FPM_MODE) \
{ #NAME, &functions::NAME, &shapes::SHAPE, types_##TYPES, groups_##GROUPS, \
- preds_##PREDS, aarch64_required_extensions::REQUIRED_EXTENSIONS },
+ preds_##PREDS, aarch64_required_extensions::REQUIRED_EXTENSIONS, \
+ FPM_##FPM_MODE },
#include "aarch64-sve-builtins.def"
};
@@ -943,7 +944,8 @@ static CONSTEXPR const function_group_info function_groups[] = {
static CONSTEXPR const function_group_info neon_sve_function_groups[] = {
#define DEF_NEON_SVE_FUNCTION(NAME, SHAPE, TYPES, GROUPS, PREDS) \
{ #NAME, &neon_sve_bridge_functions::NAME, &shapes::SHAPE, types_##TYPES, \
- groups_##GROUPS, preds_##PREDS, aarch64_required_extensions::ssve (0) },
+ groups_##GROUPS, preds_##PREDS, aarch64_required_extensions::ssve (0), \
+ FPM_unused },
#include "aarch64-neon-sve-bridge-builtins.def"
};
@@ -951,12 +953,13 @@ static CONSTEXPR const function_group_info neon_sve_function_groups[] = {
static CONSTEXPR const function_group_info sme_function_groups[] = {
#define DEF_SME_FUNCTION_GS(NAME, SHAPE, TYPES, GROUPS, PREDS) \
{ #NAME, &functions::NAME, &shapes::SHAPE, types_##TYPES, groups_##GROUPS, \
- preds_##PREDS, aarch64_required_extensions::REQUIRED_EXTENSIONS },
+ preds_##PREDS, aarch64_required_extensions::REQUIRED_EXTENSIONS, \
+ FPM_unused },
#define DEF_SME_ZA_FUNCTION_GS(NAME, SHAPE, TYPES, GROUPS, PREDS) \
{ #NAME, &functions::NAME##_za, &shapes::SHAPE, types_##TYPES, \
groups_##GROUPS, preds_##PREDS, \
aarch64_required_extensions::REQUIRED_EXTENSIONS \
- .and_also (AARCH64_FL_ZA_ON) },
+ .and_also (AARCH64_FL_ZA_ON), FPM_unused },
#include "aarch64-sve-builtins-sme.def"
};
@@ -1238,6 +1241,7 @@ function_instance::hash () const
h.add_int (type_suffix_ids[1]);
h.add_int (group_suffix_id);
h.add_int (pred);
+ h.add_int (fpm_mode);
return h.end ();
}
@@ -1668,7 +1672,8 @@ function_builder::add_overloaded_functions (const function_group_info &group,
{
function_instance instance (group.base_name, *group.base,
*group.shape, mode, types,
- group_suffix_id, group.preds[pi]);
+ group_suffix_id, group.preds[pi],
+ group.fpm_mode);
add_overloaded_function (instance, group.required_extensions);
};
@@ -1845,8 +1850,8 @@ function_resolver::lookup_form (mode_suffix_index mode,
group_suffix_index group)
{
type_suffix_pair types = { type0, type1 };
- function_instance instance (base_name, base, shape, mode, types,
- group, pred);
+ function_instance instance (base_name, base, shape, mode, types, group, pred,
+ fpm_mode);
registered_function *rfn
= function_table->find_with_hash (instance, instance.hash ());
return rfn ? rfn->decl : NULL_TREE;
@@ -37,8 +37,13 @@
#define DEF_SVE_GROUP_SUFFIX(A, B, C)
#endif
+#ifndef DEF_SVE_FUNCTION_GS_FPM
+#define DEF_SVE_FUNCTION_GS_FPM(A, B, C, D, E, F)
+#endif
+
#ifndef DEF_SVE_FUNCTION_GS
-#define DEF_SVE_FUNCTION_GS(A, B, C, D, E)
+#define DEF_SVE_FUNCTION_GS(A, B, C, D, E) \
+ DEF_SVE_FUNCTION_GS_FPM(A, B, C, D, E, unused)
#endif
#ifndef DEF_SVE_NEON_TYPE_SUFFIX
@@ -164,6 +169,7 @@ DEF_SVE_GROUP_SUFFIX (vg4x4, 4, 4)
#undef DEF_SVE_FUNCTION
#undef DEF_SVE_FUNCTION_GS
+#undef DEF_SVE_FUNCTION_GS_FPM
#undef DEF_SVE_GROUP_SUFFIX
#undef DEF_SME_ZA_SUFFIX
#undef DEF_SVE_NEON_TYPE_SUFFIX
@@ -28,6 +28,7 @@
- the "mode" suffix ("_n", "_index", etc.)
- the type suffixes ("_s32", "_b8", etc.)
- the predication suffix ("_x", "_z", etc.)
+ - the "_fpm" suffix when the floating point mode register is set
Each piece of information is individually useful, so we retain this
classification throughout:
@@ -42,6 +43,8 @@
- prediction_index extends the predication suffix with an additional
alternative: PRED_implicit for implicitly-predicated operations
+ - fpm_mode represents whether the fpm register is set or not
+
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
@@ -164,6 +167,14 @@ enum predication_index
NUM_PREDS
};
+/* Classifies intrinsics on whether they set the FPM register */
+enum fpm_mode_index
+{
+ FPM_unused,
+ FPM_set,
+ NUM_FPM_MODES
+};
+
/* Classifies element types, based on type suffixes with the bit count
removed. "count" isn't really an element type, but we pretend it is
for consistency. */
@@ -366,6 +377,9 @@ struct function_group_info
/* The architecture extensions that the functions require. */
aarch64_required_extensions required_extensions;
+
+ /* Whether the floating point register is set */
+ fpm_mode_index fpm_mode;
};
/* Describes a single fully-resolved function (i.e. one that has a
@@ -376,7 +390,7 @@ public:
function_instance (const char *, const function_base *,
const function_shape *, mode_suffix_index,
const type_suffix_pair &, group_suffix_index,
- predication_index);
+ predication_index, fpm_mode_index);
bool operator== (const function_instance &) const;
bool operator!= (const function_instance &) const;
@@ -420,6 +434,7 @@ public:
type_suffix_pair type_suffix_ids;
group_suffix_index group_suffix_id;
predication_index pred;
+ fpm_mode_index fpm_mode;
};
class registered_function;
@@ -876,16 +891,15 @@ tuple_type_field (tree type)
}
inline function_instance::
-function_instance (const char *base_name_in,
- const function_base *base_in,
+function_instance (const char *base_name_in, const function_base *base_in,
const function_shape *shape_in,
mode_suffix_index mode_suffix_id_in,
const type_suffix_pair &type_suffix_ids_in,
group_suffix_index group_suffix_id_in,
- predication_index pred_in)
+ predication_index pred_in, fpm_mode_index fpm_mode_in)
: base_name (base_name_in), base (base_in), shape (shape_in),
mode_suffix_id (mode_suffix_id_in), group_suffix_id (group_suffix_id_in),
- pred (pred_in)
+ pred (pred_in), fpm_mode (fpm_mode_in)
{
memcpy (type_suffix_ids, type_suffix_ids_in, sizeof (type_suffix_ids));
}
@@ -899,7 +913,8 @@ function_instance::operator== (const function_instance &other) const
&& type_suffix_ids[0] == other.type_suffix_ids[0]
&& type_suffix_ids[1] == other.type_suffix_ids[1]
&& group_suffix_id == other.group_suffix_id
- && pred == other.pred);
+ && pred == other.pred
+ && fpm_mode == other.fpm_mode);
}
inline bool