Browse Source

gcc: support -march flag

Arguments like IMAFD or RV32I are supported.
pull/10/head
Andrew Waterman 11 years ago
parent
commit
068be3c3ff
  1. 81
      gcc/gcc/common/config/riscv/riscv-common.c
  2. 216
      gcc/gcc/config/riscv/riscv.c
  3. 33
      gcc/gcc/config/riscv/riscv.h
  4. 42
      gcc/gcc/config/riscv/riscv.md
  5. 10
      gcc/gcc/config/riscv/riscv.opt

81
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

216
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

33
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
<http://www.gnu.org/licenses/>. */
/* 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) \

42
gcc/gcc/config/riscv/riscv.md

@ -19,10 +19,6 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
(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<u>\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<u>\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 ? "div<u>w\t%0,%1,%2" : "div<u>\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<u>\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 ? "rem<u>w\t%0,%1,%2" : "rem<u>\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<u>\t%0,%1,%2"
[(set_attr "type" "idiv")
(set_attr "mode" "DI")])

10
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.

Loading…
Cancel
Save