/* x86-specific vector costs. */
class ix86_vector_costs : public vector_costs
{
- using vector_costs::vector_costs;
+public:
+ ix86_vector_costs (vec_info *, bool);
unsigned int add_stmt_cost (int count, vect_cost_for_stmt kind,
stmt_vec_info stmt_info, slp_tree node,
tree vectype, int misalign,
vect_cost_model_location where) override;
void finish_cost (const vector_costs *) override;
+
+private:
+
+ /* Estimate register pressure of the vectorized code. */
+ void ix86_vect_estimate_reg_pressure ();
+ /* Number of GENERAL_REGS/SSE_REGS used in the vectorizer, it's used for
+ estimation of register pressure.
+ ??? Currently it's only used by vec_construct/scalar_to_vec
+ where we know it's not loaded from memory. */
+ unsigned m_num_gpr_needed[3];
+ unsigned m_num_sse_needed[3];
};
+ix86_vector_costs::ix86_vector_costs (vec_info* vinfo, bool costing_for_scalar)
+ : vector_costs (vinfo, costing_for_scalar),
+ m_num_gpr_needed (),
+ m_num_sse_needed ()
+{
+}
+
/* Implement targetm.vectorize.create_costs. */
static vector_costs *
}
else if ((kind == vec_construct || kind == scalar_to_vec)
&& node
- && SLP_TREE_DEF_TYPE (node) == vect_external_def
- && INTEGRAL_TYPE_P (TREE_TYPE (vectype)))
+ && SLP_TREE_DEF_TYPE (node) == vect_external_def)
{
stmt_cost = ix86_builtin_vectorization_cost (kind, vectype, misalign);
unsigned i;
&& (gimple_assign_rhs_code (def) != BIT_FIELD_REF
|| !VECTOR_TYPE_P (TREE_TYPE
(TREE_OPERAND (gimple_assign_rhs1 (def), 0))))))
- stmt_cost += ix86_cost->sse_to_integer;
+ {
+ if (fp)
+ m_num_sse_needed[where]++;
+ else
+ {
+ m_num_gpr_needed[where]++;
+ stmt_cost += ix86_cost->sse_to_integer;
+ }
+ }
}
FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_OPS (node), i, op)
if (TREE_CODE (op) == SSA_NAME)
return retval;
}
+void
+ix86_vector_costs::ix86_vect_estimate_reg_pressure ()
+{
+ unsigned gpr_spill_cost = COSTS_N_INSNS (ix86_cost->int_store [2]) / 2;
+ unsigned sse_spill_cost = COSTS_N_INSNS (ix86_cost->sse_store[0]) / 2;
+
+ /* Any better way to have target available fp registers, currently use SSE_REGS. */
+ unsigned target_avail_sse = TARGET_64BIT ? (TARGET_AVX512F ? 32 : 16) : 8;
+ for (unsigned i = 0; i != 3; i++)
+ {
+ if (m_num_gpr_needed[i] > target_avail_regs)
+ m_costs[i] += gpr_spill_cost * (m_num_gpr_needed[i] - target_avail_regs);
+ /* Only measure sse registers pressure. */
+ if (TARGET_SSE && (m_num_sse_needed[i] > target_avail_sse))
+ m_costs[i] += sse_spill_cost * (m_num_sse_needed[i] - target_avail_sse);
+ }
+}
+
void
ix86_vector_costs::finish_cost (const vector_costs *scalar_costs)
{
m_costs[vect_body] = INT_MAX;
}
+ ix86_vect_estimate_reg_pressure ();
+
vector_costs::finish_cost (scalar_costs);
}