extern const riscv_cpu_info *riscv_find_cpu (const char *);
+/* Common vector costs in any kind of vectorization (e.g VLA and VLS). */
+struct common_vector_cost
+{
+ /* Cost of any integer vector operation, excluding the ones handled
+ specially below. */
+ const int int_stmt_cost;
+
+ /* Cost of any fp vector operation, excluding the ones handled
+ specially below. */
+ const int fp_stmt_cost;
+
+ /* Gather/scatter vectorization cost. */
+ const int gather_load_cost;
+ const int scatter_store_cost;
+
+ /* Cost of a vector-to-scalar operation. */
+ const int vec_to_scalar_cost;
+
+ /* Cost of a scalar-to-vector operation. */
+ const int scalar_to_vec_cost;
+
+ /* Cost of a permute operation. */
+ const int permute_cost;
+
+ /* Cost of an aligned vector load. */
+ const int align_load_cost;
+
+ /* Cost of an aligned vector store. */
+ const int align_store_cost;
+
+ /* Cost of an unaligned vector load. */
+ const int unalign_load_cost;
+
+ /* Cost of an unaligned vector store. */
+ const int unalign_store_cost;
+};
+
+/* scalable vectorization (VLA) specific cost. */
+struct scalable_vector_cost : common_vector_cost
+{
+ CONSTEXPR scalable_vector_cost (const common_vector_cost &base)
+ : common_vector_cost (base)
+ {}
+
+ /* TODO: We will need more other kinds of vector cost for VLA.
+ E.g. fold_left reduction cost, lanes load/store cost, ..., etc. */
+};
+
+/* Cost for vector insn classes. */
+struct cpu_vector_cost
+{
+ /* Cost of any integer scalar operation, excluding load and store. */
+ const int scalar_int_stmt_cost;
+
+ /* Cost of any fp scalar operation, excluding load and store. */
+ const int scalar_fp_stmt_cost;
+
+ /* Cost of a scalar load. */
+ const int scalar_load_cost;
+
+ /* Cost of a scalar store. */
+ const int scalar_store_cost;
+
+ /* Cost of a taken branch. */
+ const int cond_taken_branch_cost;
+
+ /* Cost of a not-taken branch. */
+ const int cond_not_taken_branch_cost;
+
+ /* Cost of an VLS modes operations. */
+ const common_vector_cost *vls;
+
+ /* Cost of an VLA modes operations. */
+ const scalable_vector_cost *vla;
+};
+
/* Routines implemented in riscv-selftests.cc. */
#if CHECKING_P
namespace selftest {
bool slow_unaligned_access;
bool use_divmod_expansion;
unsigned int fusible_ops;
+ const struct cpu_vector_cost *vec_costs;
};
VD_REGS, VD_REGS, VD_REGS, VD_REGS,
};
+/* Generic costs for VLS vector operations. */
+static const common_vector_cost generic_vls_vector_cost = {
+ 1, /* int_stmt_cost */
+ 1, /* fp_stmt_cost */
+ 1, /* gather_load_cost */
+ 1, /* scatter_store_cost */
+ 1, /* vec_to_scalar_cost */
+ 1, /* scalar_to_vec_cost */
+ 1, /* permute_cost */
+ 3, /* align_load_cost */
+ 3, /* align_store_cost */
+ 3, /* unalign_load_cost */
+ 3, /* unalign_store_cost */
+};
+
+/* Generic costs for VLA vector operations. */
+static const scalable_vector_cost generic_vla_vector_cost = {
+ {
+ 1, /* int_stmt_cost */
+ 1, /* fp_stmt_cost */
+ 1, /* gather_load_cost */
+ 1, /* scatter_store_cost */
+ 1, /* vec_to_scalar_cost */
+ 1, /* scalar_to_vec_cost */
+ 1, /* permute_cost */
+ 3, /* align_load_cost */
+ 3, /* align_store_cost */
+ 3, /* unalign_load_cost */
+ 3, /* unalign_store_cost */
+ },
+};
+
+/* Generic costs for vector insn classes. */
+static const struct cpu_vector_cost generic_vector_cost = {
+ 1, /* scalar_int_stmt_cost */
+ 1, /* scalar_fp_stmt_cost */
+ 1, /* scalar_load_cost */
+ 1, /* scalar_store_cost */
+ 3, /* cond_taken_branch_cost */
+ 1, /* cond_not_taken_branch_cost */
+ &generic_vls_vector_cost, /* vls */
+ &generic_vla_vector_cost, /* vla */
+};
+
/* 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 */
true, /* slow_unaligned_access */
false, /* use_divmod_expansion */
RISCV_FUSE_NOTHING, /* fusible_ops */
+ NULL, /* vector cost */
};
/* Costs to use when optimizing for Sifive 7 Series. */
true, /* slow_unaligned_access */
false, /* use_divmod_expansion */
RISCV_FUSE_NOTHING, /* fusible_ops */
+ NULL, /* vector cost */
};
/* Costs to use when optimizing for T-HEAD c906. */
false, /* slow_unaligned_access */
false, /* use_divmod_expansion */
RISCV_FUSE_NOTHING, /* fusible_ops */
+ NULL, /* vector cost */
};
/* Costs to use when optimizing for a generic ooo profile. */
false, /* slow_unaligned_access */
false, /* use_divmod_expansion */
RISCV_FUSE_NOTHING, /* fusible_ops */
+ &generic_vector_cost, /* vector cost */
};
/* Costs to use when optimizing for size. */
false, /* slow_unaligned_access */
false, /* use_divmod_expansion */
RISCV_FUSE_NOTHING, /* fusible_ops */
+ NULL, /* vector cost */
};
static bool riscv_avoid_shrink_wrapping_separate ();
return riscv_save_frame_pointer && !crtl->is_leaf;
}
+/* Return the appropriate common costs for vectors of type VECTYPE. */
+static const common_vector_cost *
+get_common_costs (tree vectype)
+{
+ const cpu_vector_cost *costs = tune_param->vec_costs;
+ gcc_assert (costs);
+
+ if (vectype && riscv_v_ext_vls_mode_p (TYPE_MODE (vectype)))
+ return costs->vls;
+ return costs->vla;
+}
+
+/* Implement targetm.vectorize.builtin_vectorization_cost. */
+
+static int
+riscv_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
+ tree vectype, int misalign ATTRIBUTE_UNUSED)
+{
+ unsigned elements;
+ const cpu_vector_cost *costs = tune_param->vec_costs;
+ bool fp = false;
+
+ if (vectype != NULL)
+ fp = FLOAT_TYPE_P (vectype);
+
+ if (costs != NULL)
+ {
+ const common_vector_cost *common_costs = get_common_costs (vectype);
+ gcc_assert (common_costs != NULL);
+ switch (type_of_cost)
+ {
+ case scalar_stmt:
+ return fp ? costs->scalar_fp_stmt_cost : costs->scalar_int_stmt_cost;
+
+ case scalar_load:
+ return costs->scalar_load_cost;
+
+ case scalar_store:
+ return costs->scalar_store_cost;
+
+ case vector_stmt:
+ return fp ? common_costs->fp_stmt_cost : common_costs->int_stmt_cost;
+
+ case vector_load:
+ return common_costs->align_load_cost;
+
+ case vector_store:
+ return common_costs->align_store_cost;
+
+ case vec_to_scalar:
+ return common_costs->vec_to_scalar_cost;
+
+ case scalar_to_vec:
+ return common_costs->scalar_to_vec_cost;
+
+ case unaligned_load:
+ return common_costs->unalign_load_cost;
+ case vector_gather_load:
+ return common_costs->gather_load_cost;
+
+ case unaligned_store:
+ return common_costs->unalign_store_cost;
+ case vector_scatter_store:
+ return common_costs->scatter_store_cost;
+
+ case cond_branch_taken:
+ return costs->cond_taken_branch_cost;
+
+ case cond_branch_not_taken:
+ return costs->cond_not_taken_branch_cost;
+
+ case vec_perm:
+ return common_costs->permute_cost;
+
+ case vec_promote_demote:
+ return fp ? common_costs->fp_stmt_cost : common_costs->int_stmt_cost;
+
+ case vec_construct:
+ elements = estimated_poly_value (TYPE_VECTOR_SUBPARTS (vectype));
+ return elements / 2 + 1;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ return default_builtin_vectorization_cost (type_of_cost, vectype, misalign);
+}
+
/* Implement targetm.vectorize.create_costs. */
static vector_costs *
#undef TARGET_FRAME_POINTER_REQUIRED
#define TARGET_FRAME_POINTER_REQUIRED riscv_frame_pointer_required
+#undef TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST
+#define TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST \
+ riscv_builtin_vectorization_cost
+
#undef TARGET_VECTORIZE_CREATE_COSTS
#define TARGET_VECTORIZE_CREATE_COSTS riscv_vectorize_create_costs