Commit b8c317c1 by Kito Cheng Committed by Kito Cheng

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.
parent 6377653f
...@@ -60,6 +60,14 @@ riscv_implied_info_t riscv_implied_info[] = ...@@ -60,6 +60,14 @@ riscv_implied_info_t riscv_implied_info[] =
{NULL, NULL} {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. */ /* Subset list. */
class riscv_subset_list class riscv_subset_list
{ {
...@@ -604,8 +612,10 @@ fail: ...@@ -604,8 +612,10 @@ fail:
std::string std::string
riscv_arch_str (bool version_p) riscv_arch_str (bool version_p)
{ {
gcc_assert (current_subset_list); if (current_subset_list)
return current_subset_list->to_string (version_p); 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 /* 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) ...@@ -653,6 +663,21 @@ riscv_parse_arch_string (const char *isa, int *flags, location_t loc)
current_subset_list = subset_list; 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. */ /* Implement TARGET_HANDLE_OPTION. */
static bool static bool
...@@ -667,6 +692,12 @@ riscv_handle_option (struct gcc_options *opts, ...@@ -667,6 +692,12 @@ riscv_handle_option (struct gcc_options *opts,
riscv_parse_arch_string (decoded->arg, &opts->x_target_flags, loc); riscv_parse_arch_string (decoded->arg, &opts->x_target_flags, loc);
return true; return true;
case OPT_mcpu_:
if (riscv_find_cpu (decoded->arg) == NULL)
error_at (loc, "%<-mcpu=%s%>: unknown CPU",
decoded->arg);
return true;
default: default:
return true; return true;
} }
...@@ -678,15 +709,65 @@ const char * ...@@ -678,15 +709,65 @@ const char *
riscv_expand_arch (int argc ATTRIBUTE_UNUSED, riscv_expand_arch (int argc ATTRIBUTE_UNUSED,
const char **argv) const char **argv)
{ {
static char *_arch_buf;
gcc_assert (argc == 1); gcc_assert (argc == 1);
int flags; int flags;
location_t loc = UNKNOWN_LOCATION; location_t loc = UNKNOWN_LOCATION;
riscv_parse_arch_string (argv[0], &flags, loc); riscv_parse_arch_string (argv[0], &flags, loc);
_arch_buf = xstrdup (riscv_arch_str (false).c_str ()); const std::string arch = riscv_arch_str (false);
return _arch_buf; 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. */ /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */
static const struct default_options riscv_option_optimization_table[] = static const struct default_options riscv_option_optimization_table[] =
{ {
......
/* 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
...@@ -94,4 +94,18 @@ extern bool riscv_hard_regno_rename_ok (unsigned, unsigned); ...@@ -94,4 +94,18 @@ extern bool riscv_hard_regno_rename_ok (unsigned, unsigned);
rtl_opt_pass * make_pass_shorten_memrefs (gcc::context *ctxt); 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 */ #endif /* ! GCC_RISCV_PROTOS_H */
...@@ -41,17 +41,27 @@ along with GCC; see the file COPYING3. If not see ...@@ -41,17 +41,27 @@ along with GCC; see the file COPYING3. If not see
#endif #endif
extern const char *riscv_expand_arch (int argc, const char **argv); 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 \ # 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: /* 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-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 \ #define OPTION_DEFAULT_SPECS \
{"tune", "%{!mtune=*:-mtune=%(VALUE)}" }, \ {"tune", "%{!mtune=*:" \
{"arch", "%{!march=*:-march=%(VALUE)}" }, \ " %{!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)}" }, \ {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
#ifdef IN_LIBGCC2 #ifdef IN_LIBGCC2
...@@ -69,8 +79,9 @@ extern const char *riscv_expand_arch (int argc, const char **argv); ...@@ -69,8 +79,9 @@ extern const char *riscv_expand_arch (int argc, const char **argv);
%(subtarget_asm_spec)" %(subtarget_asm_spec)"
#undef DRIVER_SELF_SPECS #undef DRIVER_SELF_SPECS
#define DRIVER_SELF_SPECS \ #define DRIVER_SELF_SPECS \
"%{march=*:-march=%:riscv_expand_arch(%*)}" "%{march=*:%:riscv_expand_arch(%*)} " \
"%{!march=*:%{mcpu=*:%:riscv_expand_arch_from_cpu(%*)}} "
#define TARGET_DEFAULT_CMODEL CM_MEDLOW #define TARGET_DEFAULT_CMODEL CM_MEDLOW
......
...@@ -79,6 +79,10 @@ mtune= ...@@ -79,6 +79,10 @@ mtune=
Target RejectNegative Joined Var(riscv_tune_string) Target RejectNegative Joined Var(riscv_tune_string)
-mtune=PROCESSOR Optimize the output for PROCESSOR. -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= msmall-data-limit=
Target Joined Separate UInteger Var(g_switch_value) Init(8) 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). -msmall-data-limit=N Put global and static data smaller than <number> bytes into a special section (on some targets).
......
...@@ -24,3 +24,5 @@ riscv-shorten-memrefs.o: $(srcdir)/config/riscv/riscv-shorten-memrefs.c ...@@ -24,3 +24,5 @@ riscv-shorten-memrefs.o: $(srcdir)/config/riscv/riscv-shorten-memrefs.c
$(POSTCOMPILE) $(POSTCOMPILE)
PASSES_EXTRA += $(srcdir)/config/riscv/riscv-passes.def PASSES_EXTRA += $(srcdir)/config/riscv/riscv-passes.def
$(common_out_file): $(srcdir)/config/riscv/riscv-cores.def
...@@ -25314,14 +25314,30 @@ Generate code for given RISC-V ISA (e.g.@: @samp{rv64im}). ISA strings must be ...@@ -25314,14 +25314,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 lower-case. Examples include @samp{rv64i}, @samp{rv32g}, @samp{rv32e}, and
@samp{rv32imaf}. @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} @item -mtune=@var{processor-string}
@opindex mtune @opindex mtune
Optimize the output for the given processor, specified by microarchitecture Optimize the output for the given processor, specified by microarchitecture or
name. Permissible values for this option are: @samp{rocket}, particular CPU name. Permissible values for this option are: @samp{rocket},
@samp{sifive-3-series}, @samp{sifive-5-series}, @samp{sifive-7-series}, @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 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 when @option{-Os} is specified. It overrides the instruction cost info
/* { 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;
}
/* { 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;
}
/* { 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;
}
/* { 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;
}
/* { 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;
}
/* { 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;
}
/* { 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment