From: Yunze Zhu <yunze...@linux.alibaba.com> Currently when choosing multilib set for target like march=rv32imaf_zca/mabi=ilp32, gnu toolchain reports "Cannot find suitable multilib set". This is because in current dependent extension zca implies c when has combinations of extensions: Zca, F_Zca_Zcf or FD_Zca_Zcf_Zcd, and f_zca is not one of these combinations and therefore extension c can not be implied, and multilib set march=rv32imac/mabi=ilp32 cannot be selected. The most accurate method to fix this problem is changing multilib in MULTILIB_REQUIRED: march=rv32imac/mabi=ilp32 to an equivalent one: march=rv32ima_zca/mabi=ilp32. However, this method may cause compatibility issues with multilib path in previos toolchain. There is an alternative method that add an extra check in multilib selection functions, which checks whether c extension in multilibs is subset of zc* extensions in arch string. By this method not only totally matched multilib sets but equivalent multilib subsets could be selected.
gcc/ChangeLog: * common/config/riscv/riscv-common.cc (riscv_subset_list::match_score_inc_p): New Function. * config/riscv/riscv-subset.h: New Function. --- gcc/common/config/riscv/riscv-common.cc | 27 +++++++++++++++++++++++++ gcc/config/riscv/riscv-subset.h | 2 ++ 2 files changed, 29 insertions(+) diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc index a6d8763f032..f43899bb413 100644 --- a/gcc/common/config/riscv/riscv-common.cc +++ b/gcc/common/config/riscv/riscv-common.cc @@ -412,12 +412,39 @@ riscv_subset_list::match_score (riscv_subset_list *list) const for (s = list->m_head; s != NULL; s = s->next) if (this->lookup (s->name.c_str ()) != NULL) score++; + else if (this->match_score_inc_p (s->name.c_str (), list)) + score++; else return 0; return score; } +/* Check if given extension is equivalent to one or group of extensions +in given subset list. */ +bool +riscv_subset_list::match_score_inc_p (std::string name, + riscv_subset_list *multilib) const +{ + if (name.compare ("c") != 0 || this->lookup ("zca") == NULL) + return false; + + /* Check equivalent requirment when having d extension in multilib. */ + if (multilib->lookup ("d") != NULL) + { + if (multilib->xlen () == 32) + return this->lookup ("zcf") != NULL && this->lookup ("zcd") != NULL; + else + return this->lookup ("zcd") != NULL; + } + + /* Check equivalent requirment when having f extension in multilib. */ + if (multilib->lookup ("f") != NULL && multilib->xlen () == 32) + return this->lookup ("zcf") != NULL; + + return true; +} + /* Get the rank for single-letter subsets, lower value meaning higher priority. */ diff --git a/gcc/config/riscv/riscv-subset.h b/gcc/config/riscv/riscv-subset.h index c5d9fab4de9..f80210cd755 100644 --- a/gcc/config/riscv/riscv-subset.h +++ b/gcc/config/riscv/riscv-subset.h @@ -114,6 +114,8 @@ public: int match_score (riscv_subset_list *) const; + bool match_score_inc_p (std::string, riscv_subset_list *) const; + void set_loc (location_t); void set_allow_adding_dup (bool v) { m_allow_adding_dup = v; } -- 2.47.1