diff --git a/gcc/gcc/common/config/riscv/riscv-common.c b/gcc/gcc/common/config/riscv/riscv-common.c
index e3cc55a9..9d1c220a 100644
--- a/gcc/gcc/common/config/riscv/riscv-common.c
+++ b/gcc/gcc/common/config/riscv/riscv-common.c
@@ -25,16 +25,85 @@ along with GCC; see the file COPYING3. If not see
#include "common/common-target-def.h"
#include "opts.h"
#include "flags.h"
+#include "errors.h"
+
+/* Parse a RISC-V ISA string into an option mask. */
+
+static void
+riscv_parse_arch_string (const char *isa, int *flags)
+{
+ const char *p = isa;
+
+ if (strncmp (p, "RV32", 4) == 0)
+ *flags |= MASK_32BIT, p += 4;
+ else if (strncmp (p, "RV64", 4) == 0)
+ *flags &= ~MASK_32BIT, p += 4;
+
+ if (*p++ != 'I')
+ {
+ error ("-march=%s: ISA strings must begin with I, RV32I, or RV64I", isa);
+ return;
+ }
+
+ *flags &= ~MASK_MULDIV;
+ if (*p == 'M')
+ *flags |= MASK_MULDIV, p++;
+
+ *flags &= ~MASK_ATOMIC;
+ if (*p == 'A')
+ *flags |= MASK_ATOMIC, p++;
+
+ *flags |= MASK_SOFT_FLOAT_ABI;
+ if (*p == 'F')
+ *flags &= ~MASK_SOFT_FLOAT_ABI, p++;
+
+ if (*p == 'D')
+ {
+ p++;
+ if (!TARGET_HARD_FLOAT)
+ {
+ error ("-march=%s: the D extension requires the F extension", isa);
+ return;
+ }
+ }
+ else if (TARGET_HARD_FLOAT)
+ {
+ error ("-march=%s: single-precision-only is not yet supported", isa);
+ return;
+ }
+
+ if (*p)
+ {
+ error ("-march=%s: unsupported ISA substring %s", isa, p);
+ return;
+ }
+}
+
+static int
+riscv_flags_from_arch_string (const char *isa)
+{
+ int flags = 0;
+ riscv_parse_arch_string (isa, &flags);
+ return flags;
+}
/* Implement TARGET_HANDLE_OPTION. */
static bool
-riscv_handle_option (struct gcc_options *opts ATTRIBUTE_UNUSED,
+riscv_handle_option (struct gcc_options *opts,
struct gcc_options *opts_set ATTRIBUTE_UNUSED,
- const struct cl_decoded_option *decoded ATTRIBUTE_UNUSED,
+ const struct cl_decoded_option *decoded,
location_t loc ATTRIBUTE_UNUSED)
{
- return true;
+ switch (decoded->opt_index)
+ {
+ case OPT_march_:
+ riscv_parse_arch_string (decoded->arg, &opts->x_target_flags);
+ return true;
+
+ default:
+ return true;
+ }
}
/* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */
@@ -49,10 +118,10 @@ static const struct default_options riscv_option_optimization_table[] =
#define TARGET_OPTION_OPTIMIZATION_TABLE riscv_option_optimization_table
#undef TARGET_DEFAULT_TARGET_FLAGS
-#define TARGET_DEFAULT_TARGET_FLAGS \
- (TARGET_DEFAULT \
- | TARGET_CPU_DEFAULT \
+#define TARGET_DEFAULT_TARGET_FLAGS \
+ (riscv_flags_from_arch_string (RISCV_ARCH_STRING_DEFAULT) \
| (TARGET_64BIT_DEFAULT ? 0 : MASK_32BIT))
+
#undef TARGET_HANDLE_OPTION
#define TARGET_HANDLE_OPTION riscv_handle_option
diff --git a/gcc/gcc/config/riscv/riscv.c b/gcc/gcc/config/riscv/riscv.c
index d50e9f62..457361c9 100644
--- a/gcc/gcc/config/riscv/riscv.c
+++ b/gcc/gcc/config/riscv/riscv.c
@@ -231,14 +231,13 @@ struct mips_integer_op {
};
/* The largest number of operations needed to load an integer constant.
- The worst accepted case for 64-bit constants is LUI,ORI,SLL,ORI,SLL,ORI.
- When the lowest bit is clear, we can try, but reject a sequence with
- an extra SLL at the end. */
+ The worst case is LUI, ADDI, SLLI, ADDI, SLLI, ADDI, SLLI, ADDI,
+ but we may attempt and reject even worse sequences. */
#define RISCV_MAX_INTEGER_OPS 32
/* Costs of various operations on the different architectures. */
-struct mips_rtx_cost_data
+struct riscv_tune_info
{
unsigned short fp_add;
unsigned short fp_mult_sf;
@@ -249,17 +248,27 @@ struct mips_rtx_cost_data
unsigned short int_mult_di;
unsigned short int_div_si;
unsigned short int_div_di;
+ unsigned short issue_rate;
unsigned short branch_cost;
unsigned short memory_latency;
};
-/* Global variables for machine-dependent things. */
+/* Information about one CPU we know about. */
+struct riscv_cpu_info {
+ /* This CPU's canonical name. */
+ const char *name;
+
+ /* The RISC-V ISA and extensions supported by this CPU. */
+ const char *isa;
+
+ /* Tuning parameters for this CPU. */
+ const struct riscv_tune_info *tune_info;
+};
-/* The processor that we should tune the code for. */
-enum processor riscv_tune;
+/* Global variables for machine-dependent things. */
-/* Which cost information to use. */
-static const struct mips_rtx_cost_data *mips_cost;
+/* Which tuning parameters to use. */
+static const struct riscv_tune_info *tune_info;
/* Index [M][R] is true if register R is allowed to hold a value of mode M. */
bool riscv_hard_regno_mode_ok[(int) MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER];
@@ -293,43 +302,24 @@ const enum reg_class riscv_regno_to_class[FIRST_PSEUDO_REGISTER] = {
FRAME_REGS, FRAME_REGS,
};
-/* A table describing all the processors GCC knows about. Names are
- matched in the order listed. The first mention of an ISA level is
- taken as the canonical name for that ISA.
-
- To ease comparison, please keep this table in the same order
- as GAS's riscv_cpu_info_table. Please also make sure that
- MIPS_ISA_LEVEL_SPEC and MIPS_ARCH_FLOAT_SPEC handle all -march
- options correctly. */
-static const struct riscv_cpu_info riscv_cpu_info_table[] = {
- /* Entries for generic ISAs. */
- { "rocket", PROCESSOR_ROCKET, 0 },
+/* Costs to use when optimizing for size. */
+static const struct riscv_tune_info rocket_tune_info = {
+ COSTS_N_INSNS (8), /* fp_add */
+ COSTS_N_INSNS (8), /* fp_mult_sf */
+ COSTS_N_INSNS (8), /* fp_mult_df */
+ COSTS_N_INSNS (20), /* fp_div_sf */
+ COSTS_N_INSNS (20), /* fp_div_df */
+ COSTS_N_INSNS (4), /* int_mult_si */
+ COSTS_N_INSNS (4), /* int_mult_di */
+ COSTS_N_INSNS (6), /* int_div_si */
+ COSTS_N_INSNS (6), /* int_div_di */
+ 1, /* issue_rate */
+ 2, /* branch_cost */
+ 7 /* memory_latency */
};
-/* Default costs. If these are used for a processor we should look
- up the actual costs. */
-#define DEFAULT_COSTS COSTS_N_INSNS (8), /* fp_add */ \
- COSTS_N_INSNS (8), /* fp_mult_sf */ \
- COSTS_N_INSNS (8), /* fp_mult_df */ \
- COSTS_N_INSNS (20), /* fp_div_sf */ \
- COSTS_N_INSNS (20), /* fp_div_df */ \
- COSTS_N_INSNS (4), /* int_mult_si */ \
- COSTS_N_INSNS (4), /* int_mult_di */ \
- COSTS_N_INSNS (6), /* int_div_si */ \
- COSTS_N_INSNS (6), /* int_div_di */ \
- 2, /* branch_cost */ \
- 7 /* memory_latency */
-
-/* Floating-point costs for processors without an FPU. Just assume that
- all floating-point libcalls are very expensive. */
-#define SOFT_FP_COSTS COSTS_N_INSNS (256), /* fp_add */ \
- COSTS_N_INSNS (256), /* fp_mult_sf */ \
- COSTS_N_INSNS (256), /* fp_mult_df */ \
- COSTS_N_INSNS (256), /* fp_div_sf */ \
- COSTS_N_INSNS (256) /* fp_div_df */
-
/* Costs to use when optimizing for size. */
-static const struct mips_rtx_cost_data mips_rtx_cost_optimize_size = {
+static const struct riscv_tune_info optimize_size_tune_info = {
COSTS_N_INSNS (1), /* fp_add */
COSTS_N_INSNS (1), /* fp_mult_sf */
COSTS_N_INSNS (1), /* fp_mult_df */
@@ -339,43 +329,30 @@ static const struct mips_rtx_cost_data mips_rtx_cost_optimize_size = {
COSTS_N_INSNS (1), /* int_mult_di */
COSTS_N_INSNS (1), /* int_div_si */
COSTS_N_INSNS (1), /* int_div_di */
+ 1, /* issue_rate */
1, /* branch_cost */
1 /* memory_latency */
};
-/* Costs to use when optimizing for speed, indexed by processor. */
-static const struct mips_rtx_cost_data
- mips_rtx_cost_data[NUM_PROCESSOR_VALUES] = {
- { /* Rocket */ DEFAULT_COSTS},
+/* A table describing all the processors GCC knows about. */
+static const struct riscv_cpu_info riscv_cpu_info_table[] = {
+ /* Entries for generic ISAs. */
+ { "rocket", "IMAFD", &rocket_tune_info },
};
-/* Predicates to test for presence of "near" and "far"/"long_call"
- attributes on the given TYPE. */
+/* Return the riscv_cpu_info entry for the given name string. */
-static bool
-mips_near_type_p (const_tree type)
-{
- return lookup_attribute ("near", TYPE_ATTRIBUTES (type)) != NULL;
-}
-
-static bool
-mips_far_type_p (const_tree type)
+static const struct riscv_cpu_info *
+riscv_parse_cpu (const char *cpu_string)
{
- return (lookup_attribute ("long_call", TYPE_ATTRIBUTES (type)) != NULL
- || lookup_attribute ("far", TYPE_ATTRIBUTES (type)) != NULL);
-}
+ unsigned int i;
-/* Implement TARGET_COMP_TYPE_ATTRIBUTES. */
+ for (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;
-static int
-mips_comp_type_attributes (const_tree type1, const_tree type2)
-{
- /* Disallow mixed near/far attributes. */
- if (mips_far_type_p (type1) && mips_near_type_p (type2))
- return 0;
- if (mips_near_type_p (type1) && mips_far_type_p (type2))
- return 0;
- return 1;
+ error ("unknown cpu `%s'", cpu_string);
+ return riscv_cpu_info_table;
}
/* Fill CODES with a sequence of rtl operations to load VALUE.
@@ -1435,7 +1412,7 @@ riscv_binary_cost (rtx x, int single_insns, int double_insns, bool speed)
static int
mips_fp_mult_cost (enum machine_mode mode)
{
- return mode == DFmode ? mips_cost->fp_mult_df : mips_cost->fp_mult_sf;
+ return mode == DFmode ? tune_info->fp_mult_df : tune_info->fp_mult_sf;
}
/* Return the cost of floating-point divisions of mode MODE. */
@@ -1443,7 +1420,7 @@ mips_fp_mult_cost (enum machine_mode mode)
static int
mips_fp_div_cost (enum machine_mode mode)
{
- return mode == DFmode ? mips_cost->fp_div_df : mips_cost->fp_div_sf;
+ return mode == DFmode ? tune_info->fp_div_df : tune_info->fp_div_sf;
}
/* Return the cost of sign-extending OP to mode MODE, not including the
@@ -1541,7 +1518,7 @@ riscv_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
cost = riscv_address_insns (addr, mode, true);
if (cost > 0)
{
- *total = COSTS_N_INSNS (cost + mips_cost->memory_latency);
+ *total = COSTS_N_INSNS (cost + tune_info->memory_latency);
return true;
}
/* Otherwise use the default handling. */
@@ -1565,7 +1542,7 @@ riscv_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
return true;
case ABS:
- *total = float_mode_p ? mips_cost->fp_add : COSTS_N_INSNS (3);
+ *total = float_mode_p ? tune_info->fp_add : COSTS_N_INSNS (3);
return false;
case LO_SUM:
@@ -1589,7 +1566,7 @@ riscv_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
mode = GET_MODE (XEXP (x, 0));
if (FLOAT_MODE_P (mode))
{
- *total = mips_cost->fp_add;
+ *total = tune_info->fp_add;
return false;
}
*total = riscv_binary_cost (x, 1, 3, speed);
@@ -1631,7 +1608,7 @@ riscv_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
if (GET_CODE (XEXP (x, 0)) == MULT)
*total = 0;
else
- *total = mips_cost->fp_add;
+ *total = tune_info->fp_add;
return false;
}
@@ -1659,7 +1636,7 @@ riscv_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
}
if (float_mode_p)
- *total = mips_cost->fp_add;
+ *total = tune_info->fp_add;
else
*total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 4 : 1);
return false;
@@ -1669,13 +1646,13 @@ riscv_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
*total = mips_fp_mult_cost (mode);
else if (mode == DImode && !TARGET_64BIT)
/* We use a MUL and a MULH[[S]U]. */
- *total = mips_cost->int_mult_si * 2;
+ *total = tune_info->int_mult_si * 2;
else if (!speed)
*total = 1;
else if (mode == DImode)
- *total = mips_cost->int_mult_di;
+ *total = tune_info->int_mult_di;
else
- *total = mips_cost->int_mult_si;
+ *total = tune_info->int_mult_si;
return false;
case DIV:
@@ -1693,9 +1670,9 @@ riscv_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
if (!speed)
*total = 1;
else if (mode == DImode)
- *total = mips_cost->int_div_di;
+ *total = tune_info->int_div_di;
else
- *total = mips_cost->int_div_si;
+ *total = tune_info->int_div_si;
return false;
case SIGN_EXTEND:
@@ -1711,7 +1688,7 @@ riscv_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
case FIX:
case FLOAT_EXTEND:
case FLOAT_TRUNCATE:
- *total = mips_cost->fp_add;
+ *total = tune_info->fp_add;
return false;
default:
@@ -3728,7 +3705,7 @@ mips_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
static int
mips_memory_move_cost (enum machine_mode mode, reg_class_t rclass, bool in)
{
- return (mips_cost->memory_latency
+ return (tune_info->memory_latency
+ memory_move_secondary_cost (mode, rclass, in));
}
@@ -3813,16 +3790,9 @@ mips_adjust_cost (rtx insn ATTRIBUTE_UNUSED, rtx link,
/* Return the number of instructions that can be issued per cycle. */
static int
-mips_issue_rate (void)
+riscv_issue_rate (void)
{
- switch (riscv_tune)
- {
- case PROCESSOR_ROCKET:
- return 1;
-
- default:
- return 1;
- }
+ return tune_info->issue_rate;
}
/* This structure describes a single built-in function. */
@@ -4200,60 +4170,21 @@ mips_init_machine_status (void)
return ggc_alloc_cleared_machine_function ();
}
-/* Return the riscv_cpu_info entry for the processor or ISA given
- by CPU_STRING. Return null if the string isn't recognized.
-
- A similar function exists in GAS. */
-
-static const struct riscv_cpu_info *
-mips_parse_cpu (const char *cpu_string)
-{
- unsigned int i;
-
- for (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;
-
- return NULL;
-}
-
/* Implement TARGET_OPTION_OVERRIDE. */
static void
mips_option_override (void)
{
int regno, mode;
- const struct riscv_cpu_info *info;
+ const struct riscv_cpu_info *cpu;
#ifdef SUBTARGET_OVERRIDE_OPTIONS
SUBTARGET_OVERRIDE_OPTIONS;
#endif
- info = mips_parse_cpu (RISCV_CPU_STRING_DEFAULT);
- gcc_assert (info);
- riscv_tune = info->cpu;
-
- if (riscv_tune_string != 0)
- {
- const struct riscv_cpu_info *tune = mips_parse_cpu (riscv_tune_string);
- if (tune)
- riscv_tune = tune->cpu;
- }
-
flag_pcc_struct_return = 0;
- /* Decide which rtx_costs structure to use. */
- if (optimize_size)
- mips_cost = &mips_rtx_cost_optimize_size;
- else
- mips_cost = &mips_rtx_cost_data[riscv_tune];
-
- /* If the user hasn't specified a branch cost, use the processor's
- default. */
- if (riscv_branch_cost == 0)
- riscv_branch_cost = mips_cost->branch_cost;
-
- if (!TARGET_USE_GP)
+ if (flag_pic)
g_switch_value = 0;
/* Prefer a call to memcpy over inline code when optimizing for size,
@@ -4261,9 +4192,15 @@ mips_option_override (void)
if (optimize_size && (target_flags_explicit & MASK_MEMCPY) == 0)
target_flags |= MASK_MEMCPY;
- /* Use atomic instructions, if user did not specify a preference */
- if ((target_flags_explicit & MASK_ATOMIC) == 0)
- target_flags |= MASK_ATOMIC;
+ /* Handle -mtune. */
+ cpu = riscv_parse_cpu (riscv_tune_string ? riscv_tune_string :
+ RISCV_TUNE_STRING_DEFAULT);
+ tune_info = optimize_size ? &optimize_size_tune_info : cpu->tune_info;
+
+ /* 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;
/* Set up riscv_hard_regno_mode_ok. */
for (mode = 0; mode < MAX_MACHINE_MODE; mode++)
@@ -4367,7 +4304,7 @@ mips_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
#undef TARGET_SCHED_ADJUST_COST
#define TARGET_SCHED_ADJUST_COST mips_adjust_cost
#undef TARGET_SCHED_ISSUE_RATE
-#define TARGET_SCHED_ISSUE_RATE mips_issue_rate
+#define TARGET_SCHED_ISSUE_RATE riscv_issue_rate
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
#define TARGET_FUNCTION_OK_FOR_SIBCALL hook_bool_tree_tree_true
@@ -4448,9 +4385,6 @@ mips_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
#undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
#define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_const_rtx_true
-#undef TARGET_COMP_TYPE_ATTRIBUTES
-#define TARGET_COMP_TYPE_ATTRIBUTES mips_comp_type_attributes
-
#ifdef HAVE_AS_DTPRELWORD
#undef TARGET_ASM_OUTPUT_DWARF_DTPREL
#define TARGET_ASM_OUTPUT_DWARF_DTPREL mips_output_dwarf_dtprel
diff --git a/gcc/gcc/config/riscv/riscv.h b/gcc/gcc/config/riscv/riscv.h
index d5612293..8fee145b 100644
--- a/gcc/gcc/config/riscv/riscv.h
+++ b/gcc/gcc/config/riscv/riscv.h
@@ -19,26 +19,6 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
. */
-/* Information about one recognized processor. Defined here for the
- benefit of TARGET_CPU_CPP_BUILTINS. */
-struct riscv_cpu_info {
- /* The 'canonical' name of the processor as far as GCC is concerned.
- It's typically a manufacturer's prefix followed by a numerical
- designation. It should be lowercase. */
- const char *name;
-
- /* The internal processor number that most closely matches this
- entry. Several processors can have the same value, if there's no
- difference between them from GCC's point of view. */
- enum processor cpu;
-
- /* A mask of PTF_* values. */
- unsigned int tune_flags;
-};
-
-/* True if a global pointer can be used to access small data. */
-#define TARGET_USE_GP (!flag_pic)
-
/* TARGET_HARD_FLOAT and TARGET_SOFT_FLOAT reflect whether the FPU is
directly accessible, while the command-line options select
TARGET_HARD_FLOAT_ABI and TARGET_SOFT_FLOAT_ABI to reflect the ABI
@@ -124,15 +104,15 @@ struct riscv_cpu_info {
/* Default target_flags if no switches are specified */
#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT 0
+#define TARGET_DEFAULT (TARGET_ATOMIC |
#endif
-#ifndef TARGET_CPU_DEFAULT
-#define TARGET_CPU_DEFAULT 0
+#ifndef RISCV_ARCH_STRING_DEFAULT
+#define RISCV_ARCH_STRING_DEFAULT "IMAFD"
#endif
-#ifndef RISCV_CPU_STRING_DEFAULT
-#define RISCV_CPU_STRING_DEFAULT "rocket"
+#ifndef RISCV_TUNE_STRING_DEFAULT
+#define RISCV_TUNE_STRING_DEFAULT "rocket"
#endif
#ifndef TARGET_64BIT_DEFAULT
@@ -898,7 +878,7 @@ typedef struct {
/* A C expression for the cost of a branch instruction. A value of
1 is the default; other values are interpreted relative to that. */
-#define BRANCH_COST(speed_p, predictable_p) riscv_branch_cost
+#define BRANCH_COST(speed_p, predictable_p) ((speed_p) ? riscv_branch_cost : 1)
#define LOGICAL_OP_NON_SHORT_CIRCUIT 0
/* Control the assembler format that we output. */
@@ -1147,7 +1127,6 @@ while (0)
extern const enum reg_class riscv_regno_to_class[];
extern bool riscv_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
extern const char* riscv_hi_relocs[];
-extern enum processor riscv_tune; /* which cpu to schedule for */
#endif
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
diff --git a/gcc/gcc/config/riscv/riscv.md b/gcc/gcc/config/riscv/riscv.md
index 6752e566..11d16474 100644
--- a/gcc/gcc/config/riscv/riscv.md
+++ b/gcc/gcc/config/riscv/riscv.md
@@ -19,10 +19,6 @@
;; along with GCC; see the file COPYING3. If not see
;; .
-(define_enum "processor" [
- rocket
-])
-
(define_c_enum "unspec" [
;; Floating-point moves.
UNSPEC_LOAD_LOW
@@ -240,10 +236,6 @@
(symbol_ref "mips_load_store_insns (operands[0], insn) * 4")
] (const_int 4)))
-;; Attribute describing the processor.
-(define_enum_attr "cpu" "processor"
- (const (symbol_ref "riscv_tune")))
-
;; Describe a user's asm statement.
(define_asm_attributes
[(set_attr "type" "multi")])
@@ -596,13 +588,13 @@
[(set (match_operand:GPR 0 "register_operand")
(mult:GPR (match_operand:GPR 1 "reg_or_0_operand")
(match_operand:GPR 2 "register_operand")))]
- "")
+ "TARGET_MULDIV")
(define_insn "*mulsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(mult:SI (match_operand:GPR 1 "register_operand" "r")
(match_operand:GPR2 2 "register_operand" "r")))]
- ""
+ "TARGET_MULDIV"
{ return TARGET_64BIT ? "mulw\t%0,%1,%2" : "mul\t%0,%1,%2"; }
[(set_attr "type" "imul")
(set_attr "mode" "SI")])
@@ -611,7 +603,7 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(mult:SI (truncate:SI (match_operand:DI 1 "register_operand" "r"))
(truncate:SI (match_operand:DI 2 "register_operand" "r"))))]
- "TARGET_64BIT"
+ "TARGET_MULDIV && TARGET_64BIT"
"mulw\t%0,%1,%2"
[(set_attr "type" "imul")
(set_attr "mode" "SI")])
@@ -621,7 +613,7 @@
(truncate:SI
(mult:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "register_operand" "r"))))]
- "TARGET_64BIT"
+ "TARGET_MULDIV && TARGET_64BIT"
"mulw\t%0,%1,%2"
[(set_attr "type" "imul")
(set_attr "mode" "SI")])
@@ -630,7 +622,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(mult:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "register_operand" "r")))]
- "TARGET_64BIT"
+ "TARGET_MULDIV && TARGET_64BIT"
"mul\t%0,%1,%2"
[(set_attr "type" "imul")
(set_attr "mode" "DI")])
@@ -652,7 +644,7 @@
(any_extend:TI
(match_operand:DI 2 "register_operand" "r"))))
(clobber (match_scratch:DI 3 "=r"))]
- "TARGET_64BIT"
+ "TARGET_MULDIV && TARGET_64BIT"
"#"
"reload_completed"
[
@@ -679,7 +671,7 @@
(any_extend:TI
(match_operand:DI 2 "register_operand" "r")))
(const_int 64))))]
- "TARGET_64BIT"
+ "TARGET_MULDIV && TARGET_64BIT"
"mulh\t%0,%1,%2"
[(set_attr "type" "imul")
(set_attr "mode" "DI")])
@@ -692,7 +684,7 @@
(sign_extend:TI
(match_operand:DI 2 "register_operand" "r"))))
(clobber (match_scratch:DI 3 "=r"))]
- "TARGET_64BIT"
+ "TARGET_MULDIV && TARGET_64BIT"
"#"
"reload_completed"
[
@@ -719,7 +711,7 @@
(sign_extend:TI
(match_operand:DI 2 "register_operand" "r")))
(const_int 64))))]
- "TARGET_64BIT"
+ "TARGET_MULDIV && TARGET_64BIT"
"mulhsu\t%0,%2,%1"
[(set_attr "type" "imul")
(set_attr "mode" "DI")])
@@ -731,7 +723,7 @@
(any_extend:DI
(match_operand:SI 2 "register_operand" "r"))))
(clobber (match_scratch:SI 3 "=r"))]
- "!TARGET_64BIT"
+ "TARGET_MULDIV && !TARGET_64BIT"
"#"
"reload_completed"
[
@@ -758,7 +750,7 @@
(any_extend:DI
(match_operand:SI 2 "register_operand" "r")))
(const_int 32))))]
- "!TARGET_64BIT"
+ "TARGET_MULDIV && !TARGET_64BIT"
"mulh\t%0,%1,%2"
[(set_attr "type" "imul")
(set_attr "mode" "SI")])
@@ -771,7 +763,7 @@
(sign_extend:DI
(match_operand:SI 2 "register_operand" "r"))))
(clobber (match_scratch:SI 3 "=r"))]
- "!TARGET_64BIT"
+ "TARGET_MULDIV && !TARGET_64BIT"
"#"
"reload_completed"
[
@@ -798,7 +790,7 @@
(sign_extend:DI
(match_operand:SI 2 "register_operand" "r")))
(const_int 32))))]
- "!TARGET_64BIT"
+ "TARGET_MULDIV && !TARGET_64BIT"
"mulhsu\t%0,%2,%1"
[(set_attr "type" "imul")
(set_attr "mode" "SI")])
@@ -815,7 +807,7 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(any_div:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "register_operand" "r")))]
- ""
+ "TARGET_MULDIV"
{ return TARGET_64BIT ? "divw\t%0,%1,%2" : "div\t%0,%1,%2"; }
[(set_attr "type" "idiv")
(set_attr "mode" "SI")])
@@ -824,7 +816,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(any_div:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "register_operand" "r")))]
- "TARGET_64BIT"
+ "TARGET_MULDIV && TARGET_64BIT"
"div\t%0,%1,%2"
[(set_attr "type" "idiv")
(set_attr "mode" "DI")])
@@ -833,7 +825,7 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(any_mod:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "register_operand" "r")))]
- ""
+ "TARGET_MULDIV"
{ return TARGET_64BIT ? "remw\t%0,%1,%2" : "rem\t%0,%1,%2"; }
[(set_attr "type" "idiv")
(set_attr "mode" "SI")])
@@ -842,7 +834,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(any_mod:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "register_operand" "r")))]
- "TARGET_64BIT"
+ "TARGET_MULDIV && TARGET_64BIT"
"rem\t%0,%1,%2"
[(set_attr "type" "idiv")
(set_attr "mode" "DI")])
diff --git a/gcc/gcc/config/riscv/riscv.opt b/gcc/gcc/config/riscv/riscv.opt
index 0fdcb735..b105277c 100644
--- a/gcc/gcc/config/riscv/riscv.opt
+++ b/gcc/gcc/config/riscv/riscv.opt
@@ -50,6 +50,10 @@ mfdiv
Target Report RejectNegative Mask(FDIV)
Use hardware floating-point divide and square root instructions
+march=
+Target RejectNegative Joined Var(riscv_arch_string)
+-march= Generate code for given RISC-V ISA (e.g. RV64IM)
+
mtune=
Target RejectNegative Joined Var(riscv_tune_string)
-mtune=PROCESSOR Optimize the output for PROCESSOR
@@ -60,4 +64,8 @@ Target Joined Separate UInteger Var(g_switch_value) Init(8)
matomic
Target Report Mask(ATOMIC)
-Use hardware atomic memory instructions. Enabled by default, use -mno-atomic to disable
+Use hardware atomic memory instructions.
+
+mmuldiv
+Target Report Mask(MULDIV)
+Use hardware instructions for integer multiplication and division.