aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorliuhongt <hongtao.liu@intel.com>2023-11-27 13:35:41 +0800
committerliuhongt <hongtao.liu@intel.com>2023-12-05 10:40:59 +0800
commitb1cb2d993cc1148281fb4922a7ae26a4ae9ecf6f (patch)
tree850b553431ec1942a20914c81e0ebfecbb09bf09 /gcc
parent48cf8d0773fee2f7acf2b9778c7af7e344de07e6 (diff)
downloadgcc-b1cb2d993cc1148281fb4922a7ae26a4ae9ecf6f.zip
gcc-b1cb2d993cc1148281fb4922a7ae26a4ae9ecf6f.tar.gz
gcc-b1cb2d993cc1148281fb4922a7ae26a4ae9ecf6f.tar.bz2
Take register pressure into account for vec_construct/scalar_to_vec when the components are not loaded from memory.
For vec_contruct, the components must be live at the same time if they're not loaded from memory, when the number of those components exceeds available registers, spill happens. Try to account that with a rough estimation. ??? Ideally, we should have an overall estimation of register pressure if we know the live range of all variables. gcc/ChangeLog: * config/i386/i386.cc (ix86_vector_costs::add_stmt_cost): Count sse_reg/gpr_regs for components not loaded from memory. (ix86_vector_costs:ix86_vector_costs): New constructor. (ix86_vector_costs::m_num_gpr_needed[3]): New private memeber. (ix86_vector_costs::m_num_sse_needed[3]): Ditto. (ix86_vector_costs::finish_cost): Estimate overall register pressure cost. (ix86_vector_costs::ix86_vect_estimate_reg_pressure): New function.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/i386/i386.cc54
1 files changed, 50 insertions, 4 deletions
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 93a9cb5..6ab3f61 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -24563,15 +24563,34 @@ ix86_noce_conversion_profitable_p (rtx_insn *seq, struct noce_if_info *if_info)
/* 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 *
@@ -24749,8 +24768,7 @@ ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind,
}
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;
@@ -24786,7 +24804,15 @@ ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind,
&& (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)
@@ -24823,6 +24849,24 @@ ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind,
}
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)
{
loop_vec_info loop_vinfo = dyn_cast<loop_vec_info> (m_vinfo);
@@ -24844,6 +24888,8 @@ 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);
}