RISC-V: Add support for -mcpu option.
authorKito Cheng <kito.cheng@sifive.com>
Tue, 13 Oct 2020 07:07:21 +0000 (15:07 +0800)
committerKito Cheng <kito.cheng@sifive.com>
Thu, 15 Oct 2020 03:12:39 +0000 (11:12 +0800)
 - 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.

15 files changed:
gcc/common/config/riscv/riscv-common.c
gcc/config/riscv/riscv-cores.def [new file with mode: 0644]
gcc/config/riscv/riscv-protos.h
gcc/config/riscv/riscv.c
gcc/config/riscv/riscv.h
gcc/config/riscv/riscv.opt
gcc/config/riscv/t-riscv
gcc/doc/invoke.texi
gcc/testsuite/gcc.target/riscv/mcpu-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/mcpu-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/mcpu-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/mcpu-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/mcpu-5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/mcpu-6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/mcpu-7.c [new file with mode: 0644]

index 82c5154b61183499afc43535845ef0d9a8efb71f..4b6bdf8685d7ed4a32aef074a5ade4fbc7b92efb 100644 (file)
@@ -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 (file)
index 0000000..6a13f3e
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+/* 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
index 358224af898856839cfe7824e6a448198f27bfbd..256dab1d0cff57f5d578d49e3b3b69984d3db062 100644 (file)
@@ -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 */
index 63b0c3877b0d3e5da2cfcd82c7b1e28985b4186d..989a9f15250c2fc1decb4f7e2ea0c2b2618f6892 100644 (file)
@@ -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;
index b7b4a1c88a522ad19cff176a2d087c2dc0180f63..172c7ca7c98bdcbe63440d1035871977136dd87f 100644 (file)
@@ -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
 
index f01d3ab79c3b47e952a5effd81e1f55969152082..808b4a04405487db49aeaf91cb442772db36e102 100644 (file)
@@ -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 <number> bytes into a special section (on some targets).
index 4820fb35d317d463bd389a218350bd54e50a0ed5..702767c17362a6d55691a2248c69989f573e42d4 100644 (file)
@@ -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
index b997c5123a7d96c0b42e28807a4e48fe689c470c..289d81614b2f540c6a19f7ace395767850ffc111 100644 (file)
@@ -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 (file)
index 0000000..6f6005c
--- /dev/null
@@ -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 (file)
index 0000000..2992f4e
--- /dev/null
@@ -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 (file)
index 0000000..97b3f81
--- /dev/null
@@ -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 (file)
index 0000000..52c5987
--- /dev/null
@@ -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 (file)
index 0000000..c4ea7b5
--- /dev/null
@@ -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 (file)
index 0000000..57e3345
--- /dev/null
@@ -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 (file)
index 0000000..fe3c04b
--- /dev/null
@@ -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;
+}
+