/* This CPU's canonical name. */
const char *name;
+ /* Which automaton to use for tuning. */
+ enum riscv_microarchitecture_type microarchitecture;
+
/* Tuning parameters for this CPU. */
const struct riscv_tune_info *tune_info;
};
/* Which tuning parameters to use. */
static const struct riscv_tune_info *tune_info;
+/* Which automaton to use for tuning. */
+enum riscv_microarchitecture_type riscv_microarchitecture;
+
/* Index R is the smallest register class that contains register R. */
const enum reg_class riscv_regno_to_class[FIRST_PSEUDO_REGISTER] = {
GR_REGS, GR_REGS, GR_REGS, GR_REGS,
true, /* slow_unaligned_access */
};
+/* Costs to use when optimizing for Sifive 7 Series. */
+static const struct riscv_tune_info sifive_7_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 (6), COSTS_N_INSNS (6)}, /* int_div */
+ 2, /* issue_rate */
+ 4, /* branch_cost */
+ 3, /* memory_cost */
+ true, /* slow_unaligned_access */
+};
+
/* Costs to use when optimizing for size. */
static const struct riscv_tune_info optimize_size_tune_info = {
{COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* fp_add */
/* A table describing all the processors GCC knows about. */
static const struct riscv_cpu_info riscv_cpu_info_table[] = {
- { "rocket", &rocket_tune_info },
- { "size", &optimize_size_tune_info },
+ { "rocket", generic, &rocket_tune_info },
+ { "sifive-3-series", generic, &rocket_tune_info },
+ { "sifive-5-series", generic, &rocket_tune_info },
+ { "sifive-7-series", sifive_7, &sifive_7_tune_info },
+ { "size", generic, &optimize_size_tune_info },
};
/* Return the riscv_cpu_info entry for the given name string. */
&& ! cfun->machine->interrupt_handler_p);
}
+/* Given that there exists at least one variable that is set (produced)
+ by OUT_INSN and read (consumed) by IN_INSN, return true iff
+ IN_INSN represents one or more memory store operations and none of
+ the variables set by OUT_INSN is used by IN_INSN as the address of a
+ store operation. If either IN_INSN or OUT_INSN does not represent
+ a "single" RTL SET expression (as loosely defined by the
+ implementation of the single_set function) or a PARALLEL with only
+ SETs, CLOBBERs, and USEs inside, this function returns false.
+
+ Borrowed from rs6000, riscv_store_data_bypass_p checks for certain
+ conditions that result in assertion failures in the generic
+ store_data_bypass_p function and returns FALSE in such cases.
+
+ This is required to make -msave-restore work with the sifive-7
+ pipeline description. */
+
+bool
+riscv_store_data_bypass_p (rtx_insn *out_insn, rtx_insn *in_insn)
+{
+ rtx out_set, in_set;
+ rtx out_pat, in_pat;
+ rtx out_exp, in_exp;
+ int i, j;
+
+ in_set = single_set (in_insn);
+ if (in_set)
+ {
+ if (MEM_P (SET_DEST (in_set)))
+ {
+ out_set = single_set (out_insn);
+ if (!out_set)
+ {
+ out_pat = PATTERN (out_insn);
+ if (GET_CODE (out_pat) == PARALLEL)
+ {
+ for (i = 0; i < XVECLEN (out_pat, 0); i++)
+ {
+ out_exp = XVECEXP (out_pat, 0, i);
+ if ((GET_CODE (out_exp) == CLOBBER)
+ || (GET_CODE (out_exp) == USE))
+ continue;
+ else if (GET_CODE (out_exp) != SET)
+ return false;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ in_pat = PATTERN (in_insn);
+ if (GET_CODE (in_pat) != PARALLEL)
+ return false;
+
+ for (i = 0; i < XVECLEN (in_pat, 0); i++)
+ {
+ in_exp = XVECEXP (in_pat, 0, i);
+ if ((GET_CODE (in_exp) == CLOBBER) || (GET_CODE (in_exp) == USE))
+ continue;
+ else if (GET_CODE (in_exp) != SET)
+ return false;
+
+ if (MEM_P (SET_DEST (in_exp)))
+ {
+ out_set = single_set (out_insn);
+ if (!out_set)
+ {
+ out_pat = PATTERN (out_insn);
+ if (GET_CODE (out_pat) != PARALLEL)
+ return false;
+ for (j = 0; j < XVECLEN (out_pat, 0); j++)
+ {
+ out_exp = XVECEXP (out_pat, 0, j);
+ if ((GET_CODE (out_exp) == CLOBBER)
+ || (GET_CODE (out_exp) == USE))
+ continue;
+ else if (GET_CODE (out_exp) != SET)
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ return store_data_bypass_p (out_insn, in_insn);
+}
+
/* Implement TARGET_SECONDARY_MEMORY_NEEDED.
When floating-point registers are wider than integer ones, moves between
/* Handle -mtune. */
cpu = riscv_parse_cpu (riscv_tune_string ? riscv_tune_string :
RISCV_TUNE_STRING_DEFAULT);
+ riscv_microarchitecture = cpu->microarchitecture;
tune_info = optimize_size ? &optimize_size_tune_info : cpu->tune_info;
/* Use -mtune's setting for slow_unaligned_access, even when optimizing