diff options
Diffstat (limited to 'gcc/config/riscv/riscv.cc')
-rw-r--r-- | gcc/config/riscv/riscv.cc | 78 |
1 files changed, 70 insertions, 8 deletions
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 74462cc..3c1bb74 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -450,6 +450,29 @@ static const struct cpu_vector_cost generic_vector_cost = { &rvv_regmove_vector_cost, /* regmove */ }; +/* Costs to use when optimizing for generic. */ +static const struct riscv_tune_param generic_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 */ + {COSTS_N_INSNS (4), COSTS_N_INSNS (4)}, /* int_mul */ + {COSTS_N_INSNS (33), COSTS_N_INSNS (65)}, /* int_div */ + 1, /* issue_rate */ + 4, /* branch_cost */ + 5, /* memory_cost */ + 8, /* fmv_cost */ + true, /* slow_unaligned_access */ + false, /* vector_unaligned_access */ + false, /* use_divmod_expansion */ + false, /* overlap_op_by_pieces */ + false, /* speculative_sched_vsetvl */ + RISCV_FUSE_NOTHING, /* fusible_ops */ + NULL, /* vector cost */ + NULL, /* function_align */ + NULL, /* jump_align */ + NULL, /* loop_align */ +}; + /* Costs to use when optimizing for rocket. */ static const struct riscv_tune_param rocket_tune_info = { {COSTS_N_INSNS (4), COSTS_N_INSNS (5)}, /* fp_add */ @@ -814,6 +837,16 @@ void riscv_frame_info::reset(void) arg_pointer_offset = 0; } +/* Check if the mode is twice the size of the XLEN mode. */ + +static bool +riscv_2x_xlen_mode_p (machine_mode mode) +{ + poly_int64 mode_size = GET_MODE_SIZE (mode); + return mode_size.is_constant () + && (mode_size.to_constant () == UNITS_PER_WORD * 2); +} + /* Implement TARGET_MIN_ARITHMETIC_PRECISION. */ static unsigned int @@ -3778,10 +3811,8 @@ riscv_legitimize_move (machine_mode mode, rtx dest, rtx src) return true; } - if (TARGET_ZILSD - && (GET_MODE_UNIT_SIZE (mode) == (UNITS_PER_WORD * 2)) - && ((REG_P (dest) && MEM_P (src)) - || (MEM_P (dest) && REG_P (src))) + if (TARGET_ZILSD && riscv_2x_xlen_mode_p (mode) + && ((REG_P (dest) && MEM_P (src)) || (MEM_P (dest) && REG_P (src))) && can_create_pseudo_p ()) { rtx reg = REG_P (dest) ? dest : src; @@ -3868,7 +3899,7 @@ static int riscv_binary_cost (rtx x, int single_insns, int double_insns) { if (!riscv_v_ext_mode_p (GET_MODE (x)) - && GET_MODE_SIZE (GET_MODE (x)).to_constant () == UNITS_PER_WORD * 2) + && riscv_2x_xlen_mode_p (GET_MODE (x))) return COSTS_N_INSNS (double_insns); return COSTS_N_INSNS (single_insns); } @@ -3980,6 +4011,8 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN case MULT: case SMAX: case UMAX: + case SMIN: + case UMIN: { rtx op; rtx op_0 = XEXP (x, 0); @@ -4022,10 +4055,41 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN *total = COSTS_N_INSNS (1); return true; } + + /* Register move for XLEN * 2. */ + if (TARGET_ZILSD + && register_operand (SET_SRC (x), GET_MODE (SET_SRC (x))) + && riscv_2x_xlen_mode_p (mode)) + { + /* We still need two instruction for move with ZILSD, + but let minus one cost to let subreg split don't. + TODO: Add riscv_tune_param for this. */ + *total = COSTS_N_INSNS (2) - 1; + return true; + } + + /* Load for XLEN * 2. */ + if (TARGET_ZILSD && MEM_P (SET_SRC (x)) + && riscv_2x_xlen_mode_p (mode)) + { + /* TODO: Add riscv_tune_param for this. */ + *total = COSTS_N_INSNS (1); + return true; + } + riscv_rtx_costs (SET_SRC (x), mode, SET, opno, total, speed); return true; } + /* Store for XLEN * 2. */ + if (TARGET_ZILSD && MEM_P (SET_DEST (x)) && REG_P (SET_SRC (x)) + && riscv_2x_xlen_mode_p (mode)) + { + /* TODO: Add riscv_tune_param for this. */ + *total = COSTS_N_INSNS (1); + return true; + } + /* Otherwise return FALSE indicating we should recurse into both the SET_DEST and SET_SRC combining the cost of both. */ return false; @@ -9973,9 +10037,7 @@ riscv_hard_regno_mode_ok (unsigned int regno, machine_mode mode) return false; /* Zilsd require load/store with even-odd reg pair. */ - if (TARGET_ZILSD - && (GET_MODE_UNIT_SIZE (mode) == (UNITS_PER_WORD * 2)) - && ((regno % 2) != 0)) + if (TARGET_ZILSD && riscv_2x_xlen_mode_p (mode) && ((regno % 2) != 0)) return false; if (!GP_REG_P (regno + nregs - 1)) |