https://gcc.gnu.org/g:d9b94a5efc0c427f1d2bf018a782475b1324ffcd
commit r16-5156-gd9b94a5efc0c427f1d2bf018a782475b1324ffcd Author: Lulu Cheng <[email protected]> Date: Wed Oct 15 16:53:16 2025 +0800 LoongArch: Add support for setting priority in fmv. 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. Diff: --- 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 db5eb0e69937..ffcfa97092a8 100644 --- a/gcc/config/loongarch/loongarch-protos.h +++ b/gcc/config/loongarch/loongarch-protos.h @@ -230,7 +230,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 834179fc6db5..c690d7aa821b 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 a700e177dc86..57767f6e2863 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -11470,9 +11470,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 ("..."))). */ @@ -11653,7 +11667,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)); @@ -12013,23 +12027,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"
