From 72eb8335848be77649ac1c5229b8c26352ab8949 Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Tue, 13 Oct 2020 15:07:21 +0800 Subject: [PATCH] RISC-V: Add support for -mcpu option. - The behavior of -mcpu basically equal to -march plus -mtune, but it has lower priority than -march and -mtune. - The behavior and available options has sync with clang except we don't add few LLVM specific value, and add more sifive processor to the list. - -mtune also accept all available options of -mcpu, and use it setting. gcc/ChangeLog: * common/config/riscv/riscv-common.c (riscv_cpu_tables): New. (riscv_arch_str): Return empty string if current_subset_list is NULL. (riscv_find_cpu): New. (riscv_handle_option): Verify option value of -mcpu. (riscv_expand_arch): Using std::string. (riscv_default_mtune): New. (riscv_expand_arch_from_cpu): Ditto. * config/riscv/riscv-cores.def: New. * config/riscv/riscv-protos.h (riscv_find_cpu): New. (riscv_cpu_info): New. * config/riscv/riscv.c (riscv_tune_info): Rename ... (riscv_tune_param): ... to this. (riscv_cpu_info): Rename ... (riscv_tune_info): ... to this. (tune_info): Rename ... (tune_param): ... to this. (rocket_tune_info): Update data type name. (sifive_7_tune_info): Ditto. (optimize_size_tune_info): Ditto. (riscv_cpu_info_table): Rename ... (riscv_tune_info_table): ... to this. (riscv_parse_cpu): Rename ... (riscv_parse_tune): ... to this, and translate valid -mcpu option to -mtune option. (riscv_rtx_costs): Rename tune_info to tune_param. (riscv_class_max_nregs): Ditto. (riscv_memory_move_cost): Ditto. (riscv_init_machine_status): Use value of -mcpu if -mtune is not given, and rename tune_info to tune_param. * config/riscv/riscv.h (riscv_expand_arch_from_cpu): New. (riscv_default_mtune): Ditto. (EXTRA_SPEC_FUNCTIONS): Add riscv_expand_arch_from_cpu and riscv_default_mtune. (OPTION_DEFAULT_SPECS): Handle default value of -march/-mabi. (DRIVER_SELF_SPECS): Expand -march from -mcpu if -march is not given. * config/riscv/riscv.opt (-mcpu): New option. * config/riscv/t-riscv ($(common_out_file)): Add riscv-cores.def to dependency. * doc/invoke.texi (RISC-V Option): Add -mcpu, and update the description of default value for -mtune and -march. gcc/testsuite/ChangeLog: * gcc.target/riscv/mcpu-1.c: New. * gcc.target/riscv/mcpu-2.c: Ditto. * gcc.target/riscv/mcpu-3.c: Ditto. * gcc.target/riscv/mcpu-4.c: Ditto. * gcc.target/riscv/mcpu-5.c: Ditto. * gcc.target/riscv/mcpu-6.c: Ditto. * gcc.target/riscv/mcpu-7.c: Ditto. --- gcc/common/config/riscv/riscv-common.c | 91 +++++++++++++++++++++-- gcc/config/riscv/riscv-cores.def | 49 +++++++++++++ gcc/config/riscv/riscv-protos.h | 14 ++++ gcc/config/riscv/riscv.c | 97 +++++++++++++------------ gcc/config/riscv/riscv.h | 25 +++++-- gcc/config/riscv/riscv.opt | 4 + gcc/config/riscv/t-riscv | 2 + gcc/doc/invoke.texi | 24 +++++- gcc/testsuite/gcc.target/riscv/mcpu-1.c | 18 +++++ gcc/testsuite/gcc.target/riscv/mcpu-2.c | 18 +++++ gcc/testsuite/gcc.target/riscv/mcpu-3.c | 18 +++++ gcc/testsuite/gcc.target/riscv/mcpu-4.c | 18 +++++ gcc/testsuite/gcc.target/riscv/mcpu-5.c | 19 +++++ gcc/testsuite/gcc.target/riscv/mcpu-6.c | 10 +++ gcc/testsuite/gcc.target/riscv/mcpu-7.c | 10 +++ 15 files changed, 356 insertions(+), 61 deletions(-) create mode 100644 gcc/config/riscv/riscv-cores.def create mode 100644 gcc/testsuite/gcc.target/riscv/mcpu-1.c create mode 100644 gcc/testsuite/gcc.target/riscv/mcpu-2.c create mode 100644 gcc/testsuite/gcc.target/riscv/mcpu-3.c create mode 100644 gcc/testsuite/gcc.target/riscv/mcpu-4.c create mode 100644 gcc/testsuite/gcc.target/riscv/mcpu-5.c create mode 100644 gcc/testsuite/gcc.target/riscv/mcpu-6.c create mode 100644 gcc/testsuite/gcc.target/riscv/mcpu-7.c diff --git a/gcc/common/config/riscv/riscv-common.c b/gcc/common/config/riscv/riscv-common.c index 82c5154b611..4b6bdf8685d 100644 --- a/gcc/common/config/riscv/riscv-common.c +++ b/gcc/common/config/riscv/riscv-common.c @@ -60,6 +60,14 @@ riscv_implied_info_t riscv_implied_info[] = {NULL, NULL} }; +static const riscv_cpu_info riscv_cpu_tables[] = +{ +#define RISCV_CORE(CORE_NAME, ARCH, TUNE) \ + {CORE_NAME, ARCH, TUNE}, +#include "../../../config/riscv/riscv-cores.def" + {NULL, NULL, NULL} +}; + /* Subset list. */ class riscv_subset_list { @@ -604,8 +612,10 @@ fail: std::string riscv_arch_str (bool version_p) { - gcc_assert (current_subset_list); - return current_subset_list->to_string (version_p); + if (current_subset_list) + return current_subset_list->to_string (version_p); + else + return std::string(); } /* Parse a RISC-V ISA string into an option mask. Must clear or set all arch @@ -653,6 +663,21 @@ riscv_parse_arch_string (const char *isa, int *flags, location_t loc) current_subset_list = subset_list; } +/* Return the riscv_cpu_info entry for CPU, NULL if not found. */ + +const riscv_cpu_info * +riscv_find_cpu (const char *cpu) +{ + const riscv_cpu_info *cpu_info = &riscv_cpu_tables[0]; + for (;cpu_info->name != NULL; ++cpu_info) + { + const char *name = cpu_info->name; + if (strcmp (cpu, name) == 0) + return cpu_info; + } + return NULL; +} + /* Implement TARGET_HANDLE_OPTION. */ static bool @@ -667,6 +692,12 @@ riscv_handle_option (struct gcc_options *opts, riscv_parse_arch_string (decoded->arg, &opts->x_target_flags, loc); return true; + case OPT_mcpu_: + if (riscv_find_cpu (decoded->arg) == NULL) + error_at (loc, "%<-mcpu=%s%>: unknown CPU", + decoded->arg); + return true; + default: return true; } @@ -678,15 +709,65 @@ const char * riscv_expand_arch (int argc ATTRIBUTE_UNUSED, const char **argv) { - static char *_arch_buf; gcc_assert (argc == 1); int flags; location_t loc = UNKNOWN_LOCATION; riscv_parse_arch_string (argv[0], &flags, loc); - _arch_buf = xstrdup (riscv_arch_str (false).c_str ()); - return _arch_buf; + const std::string arch = riscv_arch_str (false); + if (arch.length()) + return xasprintf ("-march=%s", arch.c_str()); + else + return ""; } +/* Expand default -mtune option from -mcpu option, use default --with-tune value + if -mcpu don't have valid value. */ + +const char * +riscv_default_mtune (int argc, const char **argv) +{ + gcc_assert (argc == 2); + const riscv_cpu_info *cpu = riscv_find_cpu (argv[0]); + const char *default_mtune = argv[1]; + if (cpu) + return cpu->tune; + else + return default_mtune; +} + +/* Expand arch string with implied extensions from -mcpu option. */ + +const char * +riscv_expand_arch_from_cpu (int argc ATTRIBUTE_UNUSED, + const char **argv) +{ + gcc_assert (argc > 0 && argc <= 2); + const char *default_arch_str = NULL; + const char *arch_str = NULL; + if (argc >= 2) + default_arch_str = argv[1]; + + const riscv_cpu_info *cpu = riscv_find_cpu (argv[0]); + + if (cpu == NULL) + { + if (default_arch_str == NULL) + return ""; + else + arch_str = default_arch_str; + } + else + arch_str = cpu->arch; + + location_t loc = UNKNOWN_LOCATION; + int flags; + + riscv_parse_arch_string (arch_str, &flags, loc); + const std::string arch = riscv_arch_str (false); + return xasprintf ("-march=%s", arch.c_str()); +} + + /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */ static const struct default_options riscv_option_optimization_table[] = { diff --git a/gcc/config/riscv/riscv-cores.def b/gcc/config/riscv/riscv-cores.def new file mode 100644 index 00000000000..6a13f3e453c --- /dev/null +++ b/gcc/config/riscv/riscv-cores.def @@ -0,0 +1,49 @@ +/* List of supported core and tune info for RISC-V. + Copyright (C) 2020 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + . */ + +/* This is a list of cores that implement RISC-V. + + Before using #include to read this file, define a macro: + + RISCV_CORE(CORE_NAME, ARCH, MICRO_ARCH, TUNE_INFO) + + The CORE_NAME is the name of the core, represented as a string. + The ARCH is the default arch of the core, represented as a string, + can be NULL if no default arch. + The MICRO_ARCH is the name of the core for which scheduling decisions + will be made, represented as an identifier. + The TUNE_INFO is the detail cost model for this core, represented as an + identifier, reference to riscv-tunes.def. */ + +RISCV_CORE("sifive-e20", "rv32imc", "rocket") +RISCV_CORE("sifive-e21", "rv32imac", "rocket") +RISCV_CORE("sifive-e24", "rv32imafc", "rocket") +RISCV_CORE("sifive-e31", "rv32imac", "sifive-3-series") +RISCV_CORE("sifive-e34", "rv32imafc", "sifive-3-series") +RISCV_CORE("sifive-e76", "rv32imafc", "sifive-7-series") + +RISCV_CORE("sifive-s21", "rv64imac", "rocket") +RISCV_CORE("sifive-s51", "rv64imac", "sifive-5-series") +RISCV_CORE("sifive-s54", "rv64imafdc", "sifive-5-series") +RISCV_CORE("sifive-s76", "rv64imafdc", "sifive-7-series") + +RISCV_CORE("sifive-u54", "rv64imafdc", "sifive-5-series") +RISCV_CORE("sifive-u74", "rv64imafdc", "sifive-7-series") + +#undef RISCV_CORE diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 358224af898..256dab1d0cf 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -94,4 +94,18 @@ extern bool riscv_hard_regno_rename_ok (unsigned, unsigned); rtl_opt_pass * make_pass_shorten_memrefs (gcc::context *ctxt); +/* Information about one CPU we know about. */ +struct riscv_cpu_info { + /* This CPU's canonical name. */ + const char *name; + + /* Default arch for this CPU, could be NULL if no default arch. */ + const char *arch; + + /* Which automaton to use for tuning. */ + const char *tune; +}; + +extern const riscv_cpu_info *riscv_find_cpu (const char *); + #endif /* ! GCC_RISCV_PROTOS_H */ diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c index 63b0c3877b0..989a9f15250 100644 --- a/gcc/config/riscv/riscv.c +++ b/gcc/config/riscv/riscv.c @@ -209,7 +209,7 @@ struct riscv_integer_op { /* Costs of various operations on the different architectures. */ -struct riscv_tune_info +struct riscv_tune_param { unsigned short fp_add[2]; unsigned short fp_mul[2]; @@ -222,16 +222,16 @@ struct riscv_tune_info bool slow_unaligned_access; }; -/* Information about one CPU we know about. */ -struct riscv_cpu_info { - /* This CPU's canonical name. */ +/* Information about one micro-arch we know about. */ +struct riscv_tune_info { + /* This micro-arch canonical name. */ const char *name; /* Which automaton to use for tuning. */ enum riscv_microarchitecture_type microarchitecture; - /* Tuning parameters for this CPU. */ - const struct riscv_tune_info *tune_info; + /* Tuning parameters for this micro-arch. */ + const struct riscv_tune_param *tune_param; }; /* Global variables for machine-dependent things. */ @@ -248,7 +248,7 @@ unsigned riscv_stack_boundary; static int epilogue_cfa_sp_offset; /* Which tuning parameters to use. */ -static const struct riscv_tune_info *tune_info; +static const struct riscv_tune_param *tune_param; /* Which automaton to use for tuning. */ enum riscv_microarchitecture_type riscv_microarchitecture; @@ -275,7 +275,7 @@ const enum reg_class riscv_regno_to_class[FIRST_PSEUDO_REGISTER] = { }; /* Costs to use when optimizing for rocket. */ -static const struct riscv_tune_info rocket_tune_info = { +static const struct riscv_tune_param rocket_tune_info = { {COSTS_N_INSNS (4), COSTS_N_INSNS (5)}, /* fp_add */ {COSTS_N_INSNS (4), COSTS_N_INSNS (5)}, /* fp_mul */ {COSTS_N_INSNS (20), COSTS_N_INSNS (20)}, /* fp_div */ @@ -288,7 +288,7 @@ static const struct riscv_tune_info rocket_tune_info = { }; /* Costs to use when optimizing for Sifive 7 Series. */ -static const struct riscv_tune_info sifive_7_tune_info = { +static const struct riscv_tune_param sifive_7_tune_info = { {COSTS_N_INSNS (4), COSTS_N_INSNS (5)}, /* fp_add */ {COSTS_N_INSNS (4), COSTS_N_INSNS (5)}, /* fp_mul */ {COSTS_N_INSNS (20), COSTS_N_INSNS (20)}, /* fp_div */ @@ -301,7 +301,7 @@ static const struct riscv_tune_info sifive_7_tune_info = { }; /* Costs to use when optimizing for size. */ -static const struct riscv_tune_info optimize_size_tune_info = { +static const struct riscv_tune_param optimize_size_tune_info = { {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* fp_add */ {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* fp_mul */ {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* fp_div */ @@ -343,7 +343,7 @@ static const unsigned gpr_save_reg_order[] = { }; /* A table describing all the processors GCC knows about. */ -static const struct riscv_cpu_info riscv_cpu_info_table[] = { +static const struct riscv_tune_info riscv_tune_info_table[] = { { "rocket", generic, &rocket_tune_info }, { "sifive-3-series", generic, &rocket_tune_info }, { "sifive-5-series", generic, &rocket_tune_info }, @@ -351,17 +351,22 @@ static const struct riscv_cpu_info riscv_cpu_info_table[] = { { "size", generic, &optimize_size_tune_info }, }; -/* Return the riscv_cpu_info entry for the given name string. */ +/* Return the riscv_tune_info entry for the given name string. */ -static const struct riscv_cpu_info * -riscv_parse_cpu (const char *cpu_string) +static const struct riscv_tune_info * +riscv_parse_tune (const char *tune_string) { - for (unsigned i = 0; i < ARRAY_SIZE (riscv_cpu_info_table); i++) - if (strcmp (riscv_cpu_info_table[i].name, cpu_string) == 0) - return riscv_cpu_info_table + i; + const riscv_cpu_info *cpu = riscv_find_cpu (tune_string); - error ("unknown cpu %qs for %<-mtune%>", cpu_string); - return riscv_cpu_info_table; + if (cpu) + tune_string = cpu->tune; + + for (unsigned i = 0; i < ARRAY_SIZE (riscv_tune_info_table); i++) + if (strcmp (riscv_tune_info_table[i].name, tune_string) == 0) + return riscv_tune_info_table + i; + + error ("unknown cpu %qs for %<-mtune%>", tune_string); + return riscv_tune_info_table; } /* Helper function for riscv_build_integer; arguments are as for @@ -1703,7 +1708,7 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN instructions it needs. */ if ((cost = riscv_address_insns (XEXP (x, 0), mode, true)) > 0) { - *total = COSTS_N_INSNS (cost + tune_info->memory_cost); + *total = COSTS_N_INSNS (cost + tune_param->memory_cost); return true; } /* Otherwise use the default handling. */ @@ -1770,7 +1775,7 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN mode instead. */ mode = GET_MODE (XEXP (x, 0)); if (float_mode_p) - *total = tune_info->fp_add[mode == DFmode]; + *total = tune_param->fp_add[mode == DFmode]; else *total = riscv_binary_cost (x, 1, 3); return false; @@ -1779,19 +1784,19 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN case ORDERED: /* (FEQ(A, A) & FEQ(B, B)) compared against 0. */ mode = GET_MODE (XEXP (x, 0)); - *total = tune_info->fp_add[mode == DFmode] + COSTS_N_INSNS (2); + *total = tune_param->fp_add[mode == DFmode] + COSTS_N_INSNS (2); return false; case UNEQ: /* (FEQ(A, A) & FEQ(B, B)) compared against FEQ(A, B). */ mode = GET_MODE (XEXP (x, 0)); - *total = tune_info->fp_add[mode == DFmode] + COSTS_N_INSNS (3); + *total = tune_param->fp_add[mode == DFmode] + COSTS_N_INSNS (3); return false; case LTGT: /* (FLT(A, A) || FGT(B, B)). */ mode = GET_MODE (XEXP (x, 0)); - *total = tune_info->fp_add[mode == DFmode] + COSTS_N_INSNS (2); + *total = tune_param->fp_add[mode == DFmode] + COSTS_N_INSNS (2); return false; case UNGE: @@ -1800,13 +1805,13 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN case UNLT: /* FLT or FLE, but guarded by an FFLAGS read and write. */ mode = GET_MODE (XEXP (x, 0)); - *total = tune_info->fp_add[mode == DFmode] + COSTS_N_INSNS (4); + *total = tune_param->fp_add[mode == DFmode] + COSTS_N_INSNS (4); return false; case MINUS: case PLUS: if (float_mode_p) - *total = tune_info->fp_add[mode == DFmode]; + *total = tune_param->fp_add[mode == DFmode]; else *total = riscv_binary_cost (x, 1, 4); return false; @@ -1816,7 +1821,7 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN rtx op = XEXP (x, 0); if (GET_CODE (op) == FMA && !HONOR_SIGNED_ZEROS (mode)) { - *total = (tune_info->fp_mul[mode == DFmode] + *total = (tune_param->fp_mul[mode == DFmode] + set_src_cost (XEXP (op, 0), mode, speed) + set_src_cost (XEXP (op, 1), mode, speed) + set_src_cost (XEXP (op, 2), mode, speed)); @@ -1825,23 +1830,23 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN } if (float_mode_p) - *total = tune_info->fp_add[mode == DFmode]; + *total = tune_param->fp_add[mode == DFmode]; else *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 4 : 1); return false; case MULT: if (float_mode_p) - *total = tune_info->fp_mul[mode == DFmode]; + *total = tune_param->fp_mul[mode == DFmode]; else if (!TARGET_MUL) /* Estimate the cost of a library call. */ *total = COSTS_N_INSNS (speed ? 32 : 6); else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) - *total = 3 * tune_info->int_mul[0] + COSTS_N_INSNS (2); + *total = 3 * tune_param->int_mul[0] + COSTS_N_INSNS (2); else if (!speed) *total = COSTS_N_INSNS (1); else - *total = tune_info->int_mul[mode == DImode]; + *total = tune_param->int_mul[mode == DImode]; return false; case DIV: @@ -1849,7 +1854,7 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN case MOD: if (float_mode_p) { - *total = tune_info->fp_div[mode == DFmode]; + *total = tune_param->fp_div[mode == DFmode]; return false; } /* Fall through. */ @@ -1860,7 +1865,7 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN /* Estimate the cost of a library call. */ *total = COSTS_N_INSNS (speed ? 32 : 6); else if (speed) - *total = tune_info->int_div[mode == DImode]; + *total = tune_param->int_div[mode == DImode]; else *total = COSTS_N_INSNS (1); return false; @@ -1882,11 +1887,11 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN case FIX: case FLOAT_EXTEND: case FLOAT_TRUNCATE: - *total = tune_info->fp_add[mode == DFmode]; + *total = tune_param->fp_add[mode == DFmode]; return false; case FMA: - *total = (tune_info->fp_mul[mode == DFmode] + *total = (tune_param->fp_mul[mode == DFmode] + set_src_cost (XEXP (x, 0), mode, speed) + set_src_cost (XEXP (x, 1), mode, speed) + set_src_cost (XEXP (x, 2), mode, speed)); @@ -4546,7 +4551,7 @@ riscv_class_max_nregs (reg_class_t rclass, machine_mode mode) static int riscv_memory_move_cost (machine_mode mode, reg_class_t rclass, bool in) { - return (tune_info->memory_cost + return (tune_param->memory_cost + memory_move_secondary_cost (mode, rclass, in)); } @@ -4555,7 +4560,7 @@ riscv_memory_move_cost (machine_mode mode, reg_class_t rclass, bool in) static int riscv_issue_rate (void) { - return tune_info->issue_rate; + return tune_param->issue_rate; } /* Auxiliary function to emit RISC-V ELF attribute. */ @@ -4683,7 +4688,7 @@ riscv_init_machine_status (void) static void riscv_option_override (void) { - const struct riscv_cpu_info *cpu; + const struct riscv_tune_info *cpu; #ifdef SUBTARGET_OVERRIDE_OPTIONS SUBTARGET_OVERRIDE_OPTIONS; @@ -4705,26 +4710,28 @@ riscv_option_override (void) if (TARGET_HARD_FLOAT && (target_flags_explicit & MASK_FDIV) == 0) target_flags |= MASK_FDIV; - /* Handle -mtune. */ - cpu = riscv_parse_cpu (riscv_tune_string ? riscv_tune_string : - RISCV_TUNE_STRING_DEFAULT); + /* Handle -mtune, use -mcpu if -mtune is not given, and use default -mtune + if -mtune and -mcpu both not not given. */ + cpu = riscv_parse_tune (riscv_tune_string ? riscv_tune_string : + (riscv_cpu_string ? riscv_cpu_string : + RISCV_TUNE_STRING_DEFAULT)); riscv_microarchitecture = cpu->microarchitecture; - tune_info = optimize_size ? &optimize_size_tune_info : cpu->tune_info; + tune_param = optimize_size ? &optimize_size_tune_info : cpu->tune_param; /* Use -mtune's setting for slow_unaligned_access, even when optimizing for size. For architectures that trap and emulate unaligned accesses, the performance cost is too great, even for -Os. Similarly, if -m[no-]strict-align is left unspecified, heed -mtune's advice. */ - riscv_slow_unaligned_access_p = (cpu->tune_info->slow_unaligned_access + riscv_slow_unaligned_access_p = (cpu->tune_param->slow_unaligned_access || TARGET_STRICT_ALIGN); if ((target_flags_explicit & MASK_STRICT_ALIGN) == 0 - && cpu->tune_info->slow_unaligned_access) + && cpu->tune_param->slow_unaligned_access) target_flags |= MASK_STRICT_ALIGN; /* If the user hasn't specified a branch cost, use the processor's default. */ if (riscv_branch_cost == 0) - riscv_branch_cost = tune_info->branch_cost; + riscv_branch_cost = tune_param->branch_cost; /* Function to allocate machine-dependent function status. */ init_machine_status = &riscv_init_machine_status; diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index b7b4a1c88a5..172c7ca7c98 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -41,17 +41,27 @@ along with GCC; see the file COPYING3. If not see #endif extern const char *riscv_expand_arch (int argc, const char **argv); +extern const char *riscv_expand_arch_from_cpu (int argc, const char **argv); +extern const char *riscv_default_mtune (int argc, const char **argv); # define EXTRA_SPEC_FUNCTIONS \ - { "riscv_expand_arch", riscv_expand_arch }, + { "riscv_expand_arch", riscv_expand_arch }, \ + { "riscv_expand_arch_from_cpu", riscv_expand_arch_from_cpu }, \ + { "riscv_default_mtune", riscv_default_mtune }, /* Support for a compile-time default CPU, et cetera. The rules are: - --with-arch is ignored if -march is specified. + --with-arch is ignored if -march or -mcpu is specified. --with-abi is ignored if -mabi is specified. - --with-tune is ignored if -mtune is specified. */ + --with-tune is ignored if -mtune or -mcpu is specified. + + But using default -march/-mtune value if -mcpu don't have valid option. */ #define OPTION_DEFAULT_SPECS \ - {"tune", "%{!mtune=*:-mtune=%(VALUE)}" }, \ - {"arch", "%{!march=*:-march=%(VALUE)}" }, \ + {"tune", "%{!mtune=*:" \ + " %{!mcpu=*:-mtune=%(VALUE)}" \ + " %{mcpu=*:-mtune=%:riscv_default_mtune(%* %(VALUE))}}" }, \ + {"arch", "%{!march=*:" \ + " %{!mcpu=*:-march=%(VALUE)}" \ + " %{mcpu=*:%:riscv_expand_arch_from_cpu(%* %(VALUE))}}" }, \ {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \ #ifdef IN_LIBGCC2 @@ -69,8 +79,9 @@ extern const char *riscv_expand_arch (int argc, const char **argv); %(subtarget_asm_spec)" #undef DRIVER_SELF_SPECS -#define DRIVER_SELF_SPECS \ -"%{march=*:-march=%:riscv_expand_arch(%*)}" +#define DRIVER_SELF_SPECS \ +"%{march=*:%:riscv_expand_arch(%*)} " \ +"%{!march=*:%{mcpu=*:%:riscv_expand_arch_from_cpu(%*)}} " #define TARGET_DEFAULT_CMODEL CM_MEDLOW diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt index f01d3ab79c3..808b4a04405 100644 --- a/gcc/config/riscv/riscv.opt +++ b/gcc/config/riscv/riscv.opt @@ -79,6 +79,10 @@ mtune= Target RejectNegative Joined Var(riscv_tune_string) -mtune=PROCESSOR Optimize the output for PROCESSOR. +mcpu= +Target RejectNegative Joined Var(riscv_cpu_string) +-mcpu=PROCESSOR Use architecture of and optimize the output for PROCESSOR. + msmall-data-limit= Target Joined Separate UInteger Var(g_switch_value) Init(8) -msmall-data-limit=N Put global and static data smaller than bytes into a special section (on some targets). diff --git a/gcc/config/riscv/t-riscv b/gcc/config/riscv/t-riscv index 4820fb35d31..702767c1736 100644 --- a/gcc/config/riscv/t-riscv +++ b/gcc/config/riscv/t-riscv @@ -24,3 +24,5 @@ riscv-shorten-memrefs.o: $(srcdir)/config/riscv/riscv-shorten-memrefs.c $(POSTCOMPILE) PASSES_EXTRA += $(srcdir)/config/riscv/riscv-passes.def + +$(common_out_file): $(srcdir)/config/riscv/riscv-cores.def diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index b997c5123a7..289d81614b2 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -26001,14 +26001,30 @@ Generate code for given RISC-V ISA (e.g.@: @samp{rv64im}). ISA strings must be lower-case. Examples include @samp{rv64i}, @samp{rv32g}, @samp{rv32e}, and @samp{rv32imaf}. +When @option{-march=} is not specified, use the setting from @option{-mcpu}. + +If both @option{-march} and @option{-mcpu=} are not specified, the default for +this argument is system dependent, users who want a specific architecture +extensions should specify one explicitly. + +@item -mcpu=@var{processor-string} +@opindex mcpu +Use architecture of and optimize the output for the given processor, specified +by particular CPU name. +Permissible values for this option are: @samp{sifive-e20}, @samp{sifive-e21}, +@samp{sifive-e24}, @samp{sifive-e31}, @samp{sifive-e34}, @samp{sifive-e76}, +@samp{sifive-s21}, @samp{sifive-s51}, @samp{sifive-s54}, @samp{sifive-s76}, +@samp{sifive-u54}, and @samp{sifive-u74}. + @item -mtune=@var{processor-string} @opindex mtune -Optimize the output for the given processor, specified by microarchitecture -name. Permissible values for this option are: @samp{rocket}, +Optimize the output for the given processor, specified by microarchitecture or +particular CPU name. Permissible values for this option are: @samp{rocket}, @samp{sifive-3-series}, @samp{sifive-5-series}, @samp{sifive-7-series}, -and @samp{size}. +@samp{size}, and all valid options for @option{-mcpu=}. -When @option{-mtune=} is not specified, the default is @samp{rocket}. +When @option{-mtune=} is not specified, use the setting from @option{-mcpu}, +the default is @samp{rocket} if both are not specified. The @samp{size} choice is not intended for use by end-users. This is used when @option{-Os} is specified. It overrides the instruction cost info diff --git a/gcc/testsuite/gcc.target/riscv/mcpu-1.c b/gcc/testsuite/gcc.target/riscv/mcpu-1.c new file mode 100644 index 00000000000..6f6005c79eb --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/mcpu-1.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-skip-if "-march given" { *-*-* } { "-march=*" } } */ +/* { dg-options "-mcpu=sifive-e20 -mabi=ilp32" } */ +/* sifive-e20 = rv32imc */ + +#if !((__riscv_xlen == 32) \ + && !defined(__riscv_32e) \ + && defined(__riscv_mul) \ + && !defined(__riscv_atomic) \ + && !defined(__riscv_flen) \ + && defined(__riscv_compressed)) +#error "unexpected arch" +#endif + +int main() +{ + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/mcpu-2.c b/gcc/testsuite/gcc.target/riscv/mcpu-2.c new file mode 100644 index 00000000000..2992f4e1083 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/mcpu-2.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-skip-if "-march given" { *-*-* } { "-march=*" } } */ +/* { dg-options "-mcpu=sifive-e34 -mabi=ilp32" } */ +/* sifive-e34 = rv32imafc */ + +#if !((__riscv_xlen == 32) \ + && !defined(__riscv_32e) \ + && defined(__riscv_mul) \ + && defined(__riscv_atomic) \ + && (__riscv_flen == 32) \ + && defined(__riscv_compressed)) +#error "unexpected arch" +#endif + +int main() +{ + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/mcpu-3.c b/gcc/testsuite/gcc.target/riscv/mcpu-3.c new file mode 100644 index 00000000000..97b3f8190fa --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/mcpu-3.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-skip-if "-march given" { *-*-* } { "-march=*" } } */ +/* { dg-options "-mcpu=sifive-s51 -mabi=lp64" } */ +/* sifive-s51 = rv64imac */ + +#if !((__riscv_xlen == 64) \ + && !defined(__riscv_32e) \ + && defined(__riscv_mul) \ + && defined(__riscv_atomic) \ + && !defined(__riscv_flen) \ + && defined(__riscv_compressed)) +#error "unexpected arch" +#endif + +int main() +{ + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/mcpu-4.c b/gcc/testsuite/gcc.target/riscv/mcpu-4.c new file mode 100644 index 00000000000..52c59875422 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/mcpu-4.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-skip-if "-march given" { *-*-* } { "-march=*" } } */ +/* { dg-options "-mcpu=sifive-u74 -mabi=lp64" } */ +/* sifive-u74 = rv64imafdc */ + +#if !((__riscv_xlen == 64) \ + && !defined(__riscv_32e) \ + && defined(__riscv_mul) \ + && defined(__riscv_atomic) \ + && (__riscv_flen == 64) \ + && defined(__riscv_compressed)) +#error "unexpected arch" +#endif + +int main() +{ + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/mcpu-5.c b/gcc/testsuite/gcc.target/riscv/mcpu-5.c new file mode 100644 index 00000000000..c4ea7b5e41a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/mcpu-5.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-skip-if "-march given" { *-*-* } { "-march=*" } } */ +/* Verify -march will override arch option from -mcpu. */ +/* { dg-options "-mcpu=sifive-u74 -march=rv32ic -mabi=ilp32" } */ +/* sifive-s51 = rv64imafdc */ + +#if !((__riscv_xlen == 32) \ + && !defined(__riscv_32e) \ + && !defined(__riscv_mul) \ + && !defined(__riscv_atomic) \ + && !defined(__riscv_flen) \ + && defined(__riscv_compressed)) +#error "unexpected arch" +#endif + +int main() +{ + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/mcpu-6.c b/gcc/testsuite/gcc.target/riscv/mcpu-6.c new file mode 100644 index 00000000000..57e3345630c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/mcpu-6.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* Verify -mtune has higher priority than -mcpu for pipeline model . */ +/* { dg-options "-mcpu=sifive-u74 -mtune=rocket -fdump-rtl-sched2-details -O3 -march=rv32i -mabi=ilp32" } */ +/* { dg-final { scan-rtl-dump "simple_return\[ \]+:alu" "sched2" } } */ + +int main() +{ + return 0; +} + diff --git a/gcc/testsuite/gcc.target/riscv/mcpu-7.c b/gcc/testsuite/gcc.target/riscv/mcpu-7.c new file mode 100644 index 00000000000..fe3c04be4b6 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/mcpu-7.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* Verify -mtune has higher priority than -mcpu for pipeline model . */ +/* { dg-options "-mcpu=sifive-s21 -mtune=sifive-u74 -fdump-rtl-sched2-details -O3 -march=rv32i -mabi=ilp32" } */ +/* { dg-final { scan-rtl-dump "simple_return\[ \]+:sifive_7_B" "sched2" } } */ + +int main() +{ + return 0; +} + -- 2.30.2