Browse Source

gcc: simplify and improve cost model

pull/94/head
Andrew Waterman 11 years ago
parent
commit
9b1c88aa2e
  1. 185
      gcc/gcc/config/riscv/riscv.c

185
gcc/gcc/config/riscv/riscv.c

@ -239,18 +239,14 @@ struct mips_integer_op {
struct riscv_tune_info
{
unsigned short fp_add;
unsigned short fp_mult_sf;
unsigned short fp_mult_df;
unsigned short fp_div_sf;
unsigned short fp_div_df;
unsigned short int_mult_si;
unsigned short int_mult_di;
unsigned short int_div_si;
unsigned short int_div_di;
unsigned short fp_add[2];
unsigned short fp_mul[2];
unsigned short fp_div[2];
unsigned short int_mul[2];
unsigned short int_div[2];
unsigned short issue_rate;
unsigned short branch_cost;
unsigned short memory_latency;
unsigned short memory_cost;
};
/* Information about one CPU we know about. */
@ -304,34 +300,26 @@ const enum reg_class riscv_regno_to_class[FIRST_PSEUDO_REGISTER] = {
/* 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 */
{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 (6), COSTS_N_INSNS (6)}, /* int_div */
1, /* issue_rate */
3, /* branch_cost */
5 /* memory_cost */
};
/* Costs to use when optimizing for 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 */
COSTS_N_INSNS (1), /* fp_div_sf */
COSTS_N_INSNS (1), /* fp_div_df */
COSTS_N_INSNS (1), /* int_mult_si */
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_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 */
{COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* int_mul */
{COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* int_div */
1, /* issue_rate */
1, /* branch_cost */
1 /* memory_cost */
};
/* A table describing all the processors GCC knows about. */
@ -1403,22 +1391,6 @@ riscv_binary_cost (rtx x, int single_insns, int double_insns, bool speed)
+ rtx_cost (XEXP (x, 1), GET_CODE (x), 1, speed));
}
/* Return the cost of floating-point multiplications of mode MODE. */
static int
mips_fp_mult_cost (enum machine_mode mode)
{
return mode == DFmode ? tune_info->fp_mult_df : tune_info->fp_mult_sf;
}
/* Return the cost of floating-point divisions of mode MODE. */
static int
mips_fp_div_cost (enum machine_mode mode)
{
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
cost of OP itself. */
@ -1514,7 +1486,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) + tune_info->memory_latency;
*total = COSTS_N_INSNS (cost + tune_info->memory_cost);
return true;
}
/* Otherwise use the default handling. */
@ -1538,7 +1510,7 @@ riscv_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
return true;
case ABS:
*total = float_mode_p ? tune_info->fp_add : COSTS_N_INSNS (3);
*total = COSTS_N_INSNS (float_mode_p ? 1 : 3);
return false;
case LO_SUM:
@ -1560,9 +1532,9 @@ riscv_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
/* Branch comparisons have VOIDmode, so use the first operand's
mode instead. */
mode = GET_MODE (XEXP (x, 0));
if (FLOAT_MODE_P (mode))
if (float_mode_p)
{
*total = tune_info->fp_add;
*total = tune_info->fp_add[mode == DFmode];
return false;
}
*total = riscv_binary_cost (x, 1, 3, speed);
@ -1579,7 +1551,7 @@ riscv_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
rtx op1 = XEXP (x, 1);
if (GET_CODE (op0) == MULT && GET_CODE (XEXP (op0, 0)) == NEG)
{
*total = (mips_fp_mult_cost (mode)
*total = (tune_info->fp_mul[mode == DFmode]
+ set_src_cost (XEXP (XEXP (op0, 0), 0), speed)
+ set_src_cost (XEXP (op0, 1), speed)
+ set_src_cost (op1, speed));
@ -1587,7 +1559,7 @@ riscv_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
}
if (GET_CODE (op1) == MULT)
{
*total = (mips_fp_mult_cost (mode)
*total = (tune_info->fp_mul[mode == DFmode]
+ set_src_cost (op0, speed)
+ set_src_cost (XEXP (op1, 0), speed)
+ set_src_cost (XEXP (op1, 1), speed));
@ -1599,12 +1571,7 @@ riscv_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
case PLUS:
if (float_mode_p)
{
/* If this is part of a MADD or MSUB, treat the PLUS as
being free. */
if (GET_CODE (XEXP (x, 0)) == MULT)
*total = 0;
else
*total = tune_info->fp_add;
*total = tune_info->fp_add[mode == DFmode];
return false;
}
@ -1623,7 +1590,7 @@ riscv_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
if ((GET_CODE (op) == PLUS || GET_CODE (op) == MINUS)
&& GET_CODE (XEXP (op, 0)) == MULT)
{
*total = (mips_fp_mult_cost (mode)
*total = (tune_info->fp_mul[mode == DFmode]
+ set_src_cost (XEXP (XEXP (op, 0), 0), speed)
+ set_src_cost (XEXP (XEXP (op, 0), 1), speed)
+ set_src_cost (XEXP (op, 1), speed));
@ -1632,23 +1599,20 @@ riscv_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
}
if (float_mode_p)
*total = tune_info->fp_add;
*total = tune_info->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 = mips_fp_mult_cost (mode);
else if (mode == DImode && !TARGET_64BIT)
/* We use a MUL and a MULH[[S]U]. */
*total = tune_info->int_mult_si * 2;
*total = tune_info->fp_mul[mode == DFmode];
else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
*total = 3 * tune_info->int_mul[0] + COSTS_N_INSNS (2);
else if (!speed)
*total = 1;
else if (mode == DImode)
*total = tune_info->int_mult_di;
*total = COSTS_N_INSNS (1);
else
*total = tune_info->int_mult_si;
*total = tune_info->int_mul[mode == DImode];
return false;
case DIV:
@ -1656,19 +1620,17 @@ riscv_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
case MOD:
if (float_mode_p)
{
*total = mips_fp_div_cost (mode);
*total = tune_info->fp_div[mode == DFmode];
return false;
}
/* Fall through. */
case UDIV:
case UMOD:
if (!speed)
*total = 1;
else if (mode == DImode)
*total = tune_info->int_div_di;
if (speed)
*total = tune_info->int_div[mode == DImode];
else
*total = tune_info->int_div_si;
*total = COSTS_N_INSNS (1);
return false;
case SIGN_EXTEND:
@ -1684,7 +1646,7 @@ riscv_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
case FIX:
case FLOAT_EXTEND:
case FLOAT_TRUNCATE:
*total = tune_info->fp_add;
*total = tune_info->fp_add[mode == DFmode];
return false;
default:
@ -3617,45 +3579,6 @@ mips_canonicalize_move_class (reg_class_t rclass)
return rclass;
}
/* Return the cost of moving a value of mode MODE from a register of
class FROM to a GPR. Return 0 for classes that are unions of other
classes handled by this function. */
static int
mips_move_to_gpr_cost (reg_class_t from)
{
switch (from)
{
case GENERAL_REGS:
return 1;
case FP_REGS:
/* FP->int moves can cause recoupling on decoupled implementations */
return 4;
default:
return 0;
}
}
/* Return the cost of moving a value of mode MODE from a GPR to a
register of class TO. Return 0 for classes that are unions of
other classes handled by this function. */
static int
mips_move_from_gpr_cost (reg_class_t to)
{
switch (to)
{
case GENERAL_REGS:
case FP_REGS:
return 1;
default:
return 0;
}
}
/* Implement TARGET_REGISTER_MOVE_COST. Return 0 for classes that are the
maximum of the move costs for subclasses; regclass will work out
the maximum for us. */
@ -3669,25 +3592,11 @@ mips_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
from = mips_canonicalize_move_class (from);
to = mips_canonicalize_move_class (to);
/* Handle moves that can be done without using general-purpose registers. */
if (from == FP_REGS && to == FP_REGS)
/* fmv.fmt. */
return 1;
/* Handle cases in which only one class deviates from the ideal. */
if (from == GENERAL_REGS)
return mips_move_from_gpr_cost (to);
if (to == GENERAL_REGS)
return mips_move_to_gpr_cost (from);
/* Handles cases that require a GPR temporary. */
cost1 = mips_move_to_gpr_cost (from);
if (cost1 != 0)
{
cost2 = mips_move_from_gpr_cost (to);
if (cost2 != 0)
return cost1 + cost2;
}
if ((from == GENERAL_REGS && to == GENERAL_REGS)
|| (from == GENERAL_REGS && to == FP_REGS)
|| (from == FP_REGS && to == GENERAL_REGS)
|| (from == FP_REGS && to == FP_REGS))
return COSTS_N_INSNS (1);
return 0;
}
@ -3697,7 +3606,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 (tune_info->memory_latency
return (tune_info->memory_cost
+ memory_move_secondary_cost (mode, rclass, in));
}

Loading…
Cancel
Save