Add suggested_epilogue_mode to vector costs

The following enables targets to suggest the vector mode to be used
preferably for the epilogue of a vectorized loop.  The patch also
enables more than one vectorized epilogue in case the target suggests
a vector mode for the epilogue of a vector epilogue.

	* tree-vectorizer.h (vector_costs::suggested_epilogue_mode): New.
	(vector_costs::m_suggested_epilogue_mode): Likewise.
	(vector_costs::vector_costs): Initialize m_suggested_epilogue_mode.
	* tree-vect-loop.cc (vect_analyze_loop): Honor the target
	suggested prefered epilogue mode and support vector epilogues
	of vector epilogues if requested.
This commit is contained in:
Richard Biener 2024-11-08 11:12:06 +01:00 committed by Richard Biener
parent 61cd1c43b8
commit 82d955b0a8
2 changed files with 93 additions and 48 deletions

View File

@ -3714,6 +3714,14 @@ vect_analyze_loop (class loop *loop, gimple *loop_vectorized_call,
array may contain length-agnostic and length-specific modes. Their
ordering is not guaranteed, so we could end up picking a mode for the main
loop that is after the epilogue's optimal mode. */
if (!unlimited_cost_model (loop)
&& first_loop_vinfo->vector_costs->suggested_epilogue_mode () != VOIDmode)
{
vector_modes[0]
= first_loop_vinfo->vector_costs->suggested_epilogue_mode ();
cached_vf_per_mode[0] = 0;
}
else
vector_modes[0] = autodetected_vector_mode;
mode_i = 0;
@ -3721,11 +3729,14 @@ vect_analyze_loop (class loop *loop, gimple *loop_vectorized_call,
partial_vectors_supported_p () && param_vect_partial_vector_usage != 0;
poly_uint64 first_vinfo_vf = LOOP_VINFO_VECT_FACTOR (first_loop_vinfo);
loop_vec_info orig_loop_vinfo = first_loop_vinfo;
do
{
while (1)
{
/* If the target does not support partial vectors we can shorten the
number of modes to analyze for the epilogue as we know we can't pick a
mode that would lead to a VF at least as big as the
number of modes to analyze for the epilogue as we know we can't
pick a mode that would lead to a VF at least as big as the
FIRST_VINFO_VF. */
if (!supports_partial_vectors
&& maybe_ge (cached_vf_per_mode[mode_i], first_vinfo_vf))
@ -3744,7 +3755,7 @@ vect_analyze_loop (class loop *loop, gimple *loop_vectorized_call,
bool fatal;
opt_loop_vec_info loop_vinfo
= vect_analyze_loop_1 (loop, shared, &loop_form_info,
first_loop_vinfo,
orig_loop_vinfo,
vector_modes, mode_i,
autodetected_vector_mode, fatal);
if (fatal)
@ -3753,16 +3764,16 @@ vect_analyze_loop (class loop *loop, gimple *loop_vectorized_call,
if (loop_vinfo)
{
if (pick_lowest_cost_p
&& first_loop_vinfo->epilogue_vinfo
&& orig_loop_vinfo->epilogue_vinfo
&& vect_joust_loop_vinfos (loop_vinfo,
first_loop_vinfo->epilogue_vinfo))
orig_loop_vinfo->epilogue_vinfo))
{
gcc_assert (vect_epilogues);
delete first_loop_vinfo->epilogue_vinfo;
first_loop_vinfo->epilogue_vinfo = nullptr;
delete orig_loop_vinfo->epilogue_vinfo;
orig_loop_vinfo->epilogue_vinfo = nullptr;
}
if (!first_loop_vinfo->epilogue_vinfo)
first_loop_vinfo->epilogue_vinfo = loop_vinfo;
if (!orig_loop_vinfo->epilogue_vinfo)
orig_loop_vinfo->epilogue_vinfo = loop_vinfo;
else
{
delete loop_vinfo;
@ -3778,9 +3789,28 @@ vect_analyze_loop (class loop *loop, gimple *loop_vectorized_call,
if (mode_i == vector_modes.length ())
break;
}
orig_loop_vinfo = orig_loop_vinfo->epilogue_vinfo;
if (!orig_loop_vinfo)
break;
/* When we selected a first vectorized epilogue, see if the target
suggests to have another one. */
if (!unlimited_cost_model (loop)
&& (orig_loop_vinfo->vector_costs->suggested_epilogue_mode ()
!= VOIDmode))
{
vector_modes[0]
= orig_loop_vinfo->vector_costs->suggested_epilogue_mode ();
cached_vf_per_mode[0] = 0;
mode_i = 0;
}
else
break;
}
while (1);
if (first_loop_vinfo->epilogue_vinfo)
{
poly_uint64 lowest_th

View File

@ -1669,6 +1669,7 @@ public:
unsigned int outside_cost () const;
unsigned int total_cost () const;
unsigned int suggested_unroll_factor () const;
machine_mode suggested_epilogue_mode () const;
protected:
unsigned int record_stmt_cost (stmt_vec_info, vect_cost_model_location,
@ -1691,6 +1692,10 @@ protected:
/* The suggested unrolling factor determined at finish_cost. */
unsigned int m_suggested_unroll_factor;
/* The suggested mode to be used for a vectorized epilogue or VOIDmode,
determined at finish_cost. */
machine_mode m_suggested_epilogue_mode;
/* True if finish_cost has been called. */
bool m_finished;
};
@ -1704,6 +1709,7 @@ vector_costs::vector_costs (vec_info *vinfo, bool costing_for_scalar)
m_costing_for_scalar (costing_for_scalar),
m_costs (),
m_suggested_unroll_factor(1),
m_suggested_epilogue_mode(VOIDmode),
m_finished (false)
{
}
@ -1761,6 +1767,15 @@ vector_costs::suggested_unroll_factor () const
return m_suggested_unroll_factor;
}
/* Return the suggested epilogue mode. */
inline machine_mode
vector_costs::suggested_epilogue_mode () const
{
gcc_checking_assert (m_finished);
return m_suggested_epilogue_mode;
}
#define VECT_MAX_COST 1000
/* The maximum number of intermediate steps required in multi-step type