gcc/ChangeLog:
* config/loongarch/loongarch-protos.h
(loongarch_parse_fmv_features): Modify the type of parameter.
(loongarch_compare_version_priority): Function declaration.
* config/loongarch/loongarch-target-attr.cc
(enum features_prio): Define LA_PRIO_MAX to indicate the
highest priority of supported attributes.
(loongarch_parse_fmv_features): Added handling of setting
priority in attribute string.
(loongarch_compare_version_priority): Likewise.
* config/loongarch/loongarch.cc
(loongarch_process_target_version_attr): Likewise.
(get_feature_mask_for_version): Likewise.
(loongarch_compare_version_priority): Delete.
Change-Id: Id12dc67b781f77c03a110ac447bbe5f93c15ad24
---
gcc/config/loongarch/loongarch-protos.h | 5 +-
gcc/config/loongarch/loongarch-target-attr.cc | 141 ++++++++++++++++--
gcc/config/loongarch/loongarch.cc | 33 ++--
3 files changed, 147 insertions(+), 32 deletions(-)
diff --git a/gcc/config/loongarch/loongarch-protos.h
b/gcc/config/loongarch/loongarch-protos.h
index 9179cbd5e0c..cf0f93e3d14 100644
--- a/gcc/config/loongarch/loongarch-protos.h
+++ b/gcc/config/loongarch/loongarch-protos.h
@@ -227,7 +227,8 @@ extern bool loongarch_process_target_attr (tree args, tree
fndecl);
extern rtx loongarch_gen_stepped_int_parallel (unsigned int nelts, int base,
int step);
extern bool loongarch_parse_fmv_features (tree, string_slice,
loongarch_fmv_feature_mask *,
- unsigned int *);
+ auto_vec<unsigned int> *);
extern void get_feature_mask_for_version (tree, loongarch_fmv_feature_mask *,
- unsigned int *);
+ auto_vec<unsigned int> *);
+extern int loongarch_compare_version_priority (tree, tree);
#endif /* ! GCC_LOONGARCH_PROTOS_H */
diff --git a/gcc/config/loongarch/loongarch-target-attr.cc
b/gcc/config/loongarch/loongarch-target-attr.cc
index 5a4b0345bcb..f5ad147b3ba 100644
--- a/gcc/config/loongarch/loongarch-target-attr.cc
+++ b/gcc/config/loongarch/loongarch-target-attr.cc
@@ -63,7 +63,8 @@ enum features_prio
LA_PRIO_LSX,
LA_PRIO_LA64V1_0,
LA_PRIO_LA64V1_1,
- LA_PRIO_LASX
+ LA_PRIO_LASX,
+ LA_PRIO_MAX
};
/* All the information needed to handle a target attribute.
@@ -513,13 +514,19 @@ loongarch_option_valid_attribute_p (tree fndecl, tree,
tree args, int)
If FEATURE_MASK is nonnull, then assign to it a bitmask representing
the set of features explicitly specified in the feature string.
- If FEATURE_PRIORITY is nonnull, set an unsigned integer values
- presenting the priority of the feature string. */
+ If FEATURE_PRIORITY is nonnull, set one or two unsigned integer values
+ presenting the priority of the feature string. When the priority is
+ set explicitly in the attribute string, the number of members of
+ feature_priority is 2, feature_priority[0] is the priority set in the
+ code, and feature_priority[1] is the priority calculated from the
+ feature string. When the priority is not set in the attribute string,
+ the number of members of feature_priority is 1, and its value is the
+ priority calculated by the feature string. */
bool
loongarch_parse_fmv_features (tree decl, string_slice str,
loongarch_fmv_feature_mask *feature_mask,
- unsigned int *feature_priority)
+ auto_vec<unsigned int> *feature_priority)
{
location_t loc
= decl == NULL ? UNKNOWN_LOCATION : DECL_SOURCE_LOCATION (decl);
@@ -530,17 +537,82 @@ loongarch_parse_fmv_features (tree decl, string_slice str,
string_slice attr_str = string_slice::tokenize (&str, ";");
attr_str = attr_str.strip ();
- if (str.is_valid ())
+ if (attr_str == "default")
+ {
+ if (str.is_valid ())
+ {
+ error_at (loc, "\"default\" cannot be set together with other "
+ "features in %qs", attr_str.begin ());
+ return false;
+ }
+
+ if (feature_priority)
+ feature_priority->safe_push (LA_PRIO_NONE);
+ return true;
+ }
+
+ if (attr_str.empty ())
{
- error_at (loc, "attribute %qs is invalid", attr_str.begin ());
+ error_at (loc, "characher before %<;%> in attribute %qs cannot be empty",
+ attr_str.begin ());
return false;
}
- if (attr_str == "default")
+ /* At this time, str stores the string with the priority set in attribute.
+ If it does not exist, it is illegal. */
+ if (str.is_valid ())
{
- if (feature_priority)
- *feature_priority = LA_PRIO_NONE;
- return true;
+ if (str.empty ())
+ {
+ error_at (loc, "in attribute %qs priority cannot be empty",
+ attr_str.begin ());
+ return false;
+ }
+
+ string_slice prio_str = string_slice::tokenize (&str, ";");
+
+ if (str.is_valid ())
+ {
+ error_at (loc, "in attribute %qs the number of reatures "
+ "cannot exceed two", attr_str.begin ());
+ return false;
+ }
+
+ prio_str = prio_str.strip ();
+ string_slice name = string_slice::tokenize (&prio_str, "=");
+
+ if (name == "priority" && prio_str.is_valid ())
+ {
+ unsigned int tmp_prio = 0;
+ unsigned int len = 0;
+
+ for (char c : prio_str)
+ {
+ if (ISDIGIT (c))
+ len++;
+ else
+ break;
+ }
+
+ if (len != prio_str.size ()
+ || sscanf (prio_str.begin (), "%u", &tmp_prio) != 1)
+ {
+ error_at (loc, "Setting the priority value to %qs is "
+ "illegal in attribute %qs", prio_str.begin (),
+ attr_str.begin ());
+ return false;
+ }
+
+ if (feature_priority)
+ feature_priority->safe_push (tmp_prio + LA_PRIO_MAX);
+ }
+ else
+ {
+ error_at (loc, "in attribute %qs, the second feature should be "
+ "\"priority=%<num%>\" instead of %qs", attr_str.begin (),
+ name.begin ());
+ return false;
+ }
}
if (attr_str.is_valid ())
@@ -596,7 +668,7 @@ loongarch_parse_fmv_features (tree decl, string_slice str,
*feature_mask = tmp_mask;
if (feature_priority)
- *feature_priority = tmp_prio;
+ feature_priority->safe_push (tmp_prio);
}
else
{
@@ -619,7 +691,7 @@ loongarch_parse_fmv_features (tree decl, string_slice str,
*feature_mask = loongarch_attributes[i].feat_mask;
if (feature_priority)
- *feature_priority = loongarch_attributes[i].priority;
+ feature_priority->safe_push
(loongarch_attributes[i].priority);
break;
}
}
@@ -633,5 +705,50 @@ loongarch_parse_fmv_features (tree decl, string_slice str,
}
}
+ if (feature_priority)
+ gcc_assert (feature_priority->length () == 1
+ || feature_priority->length () == 2);
+
return true;
}
+
+/* Compare priorities of two version decls. Return:
+ 1: decl1 has a higher priority
+ -1: decl2 has a higher priority
+ 0: decl1 and decl2 have the same priority.
+*/
+
+int
+loongarch_compare_version_priority (tree decl1, tree decl2)
+{
+ auto_vec<unsigned int> prio1, prio2;
+
+ get_feature_mask_for_version (decl1, NULL, &prio1);
+ get_feature_mask_for_version (decl2, NULL, &prio2);
+
+ unsigned int max_prio1
+ = prio1.length () == 2 ? MAX (prio1[0], prio1[1]) : prio1[0];
+ unsigned int max_prio2
+ = prio2.length () == 2 ? MAX (prio2[0], prio2[1]) : prio2[0];
+
+ if (max_prio1 != max_prio2)
+ return max_prio1 > max_prio2 ? 1 : -1;
+
+ /* If max_prio1 == max_prio2, and max_prio1 >= LA_PRIO_MAX,
+ it means that the attribute strings of decl1 and decl2 are both
+ set with priorities, and the priority values are the same.
+ So next we use the priority calculated by the attribute string to
+ compare. */
+ if (max_prio1 >= LA_PRIO_MAX)
+ {
+ unsigned int min_prio1
+ = prio1.length () == 2 ? MIN (prio1[0], prio1[1]) : prio1[0];
+ unsigned int min_prio2
+ = prio2.length () == 2 ? MIN (prio2[0], prio2[1]) : prio2[0];
+
+ if (min_prio1 != min_prio2)
+ return min_prio1 > min_prio2 ? 1 : -1;
+ }
+
+ return 0;
+}
diff --git a/gcc/config/loongarch/loongarch.cc
b/gcc/config/loongarch/loongarch.cc
index 67197d4b5ee..5beb5cc6166 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -11342,9 +11342,23 @@ loongarch_process_target_version_attr (tree args, tree
fndecl)
if (str == "default")
return true;
+ if (loongarch_parse_fmv_features (fndecl, str, NULL, NULL) == false)
+ return false;
+
+ /* Get the attribute string and take out only the option part.
+ eg:
+ "arch=la64v1.0;priority=1"
+ The attr_string is "arch=la64v1.0".
+ */
+ string_slice attr_string = string_slice::tokenize (&str, ";");
+ attr_string = attr_string.strip ();
+
+ args = build_string (attr_string.size (), attr_string.begin ());
+
return loongarch_process_target_attr (args, fndecl);
}
+
/* Implement TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P. This is used to
process attribute ((target_version ("..."))). */
@@ -11525,7 +11539,7 @@ get_suffixed_assembler_name (tree default_decl, const
char *suffix)
void
get_feature_mask_for_version (tree decl,
loongarch_fmv_feature_mask *feature_mask,
- unsigned int *feature_priority)
+ auto_vec<unsigned int> *feature_priority)
{
tree version_attr = lookup_attribute ("target_version",
DECL_ATTRIBUTES (decl));
@@ -11885,23 +11899,6 @@ loongarch_generate_version_dispatcher_body (void
*node_p)
return resolver_decl;
}
-/* Compare priorities of two version decls. Return:
- 1: decl1 has a higher priority
- -1: decl2 has a higher priority
- 0: decl1 and decl2 have the same priority.
-*/
-
-int
-loongarch_compare_version_priority (tree decl1, tree decl2)
-{
- unsigned int prio1, prio2;
- get_feature_mask_for_version (decl1, NULL, &prio1);
- get_feature_mask_for_version (decl2, NULL, &prio2);
-
- return prio1 == prio2 ? 0
- : prio1 > prio2 ? 1 : -1;
-}
-
/* Initialize the GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
--
2.34.1