diff mbox series

RISC-V: Scale RVV integer vector body costs by unit ratio

Message ID 20260902023225.3241-1-chen.zhongyao@zte.com.cn
State New
Headers show
Series RISC-V: Scale RVV integer vector body costs by unit ratio | expand

Commit Message

Zhongyao Chen Sept. 2, 2026, 2:32 a.m. UTC
This applies a scalar/vector unit ratio to integer vector body costs,
which helps the cost model better match the actual hardware throughput.

Take an int64 vadd at VLEN=128 for example: 4 scalar units and 2 vector
units can both process 4 elements per cycle. Without this ratio, both
vector and scalar stmts just get a cost of 1, which ends up making
vectorization look too cheap.

Skip applying this ratio for:
- reduction stmts
- gather/scatter stmts

Add scalar_units and vector_units fields to riscv_tune_param.  A zero
value for either field disables the scaling.

For generic-ooo, use a 4:2 scalar/vector unit ratio.
Other uarch are left unconfig since I dont know their unit number.
They can be tuned individually later.

BTW, this is still a rough cost model adjustment,
we’re trying to make progress one small piece at a time.

gcc/ChangeLog:

	* config/riscv/riscv-protos.h (get_vector_units): New.
	(get_scalar_units): New.
	* config/riscv/riscv-vector-costs.cc (costs::add_stmt_cost):
	Scale ordinary integer vector body costs using the current tune's
	scalar/vector unit ratio.
	* config/riscv/riscv.cc (riscv_tune_param): Add scalar_units and
	vector_units.
	(generic_ooo_tune_info): Set scalar_units to 4 and vector_units to 2.
	(get_vector_units): New.
	(get_scalar_units): New.

Signed-off-by: Zhongyao Chen <chen.zhongyao@zte.com.cn>
---
 gcc/config/riscv/riscv-protos.h        |  2 ++
 gcc/config/riscv/riscv-vector-costs.cc | 16 ++++++++++++++++
 gcc/config/riscv/riscv.cc              | 25 +++++++++++++++++++++++++
 3 files changed, 43 insertions(+)

Comments

Bohan Lei Sept. 2, 2026, 9 a.m. UTC | #1
Hi Zhongyao,

I am not sure about the downstream implementation of other vendors, but
currently in the tune parameters of our design, we are modeling that with our
`common_vector_cost` instance with int_stmt_cost and fp_stmt_cost
greater than 1.  I guess that can already suffice for many cases?  Also, we
can have designs whose FP vector unit number is different than the integer
vector unit number, and we may still need to bother with the
`common_vector_cost` struct.

Regards,
Bohan
Zhongyao Chen Sept. 5, 2026, 9:18 a.m. UTC | #2
Hi Bohan,

Yeah, common_vector_cost is another way to model this.

I’m just trying to make the cost-model rules clearer instead of hiding
them in magic numbers.
Otherwise, it may be hard to tell later whether a vector cost for a
given uarch already includes the unit-ratio scaling.

--
Regards,
Zhongyao

On Wed, Sep 2, 2026 at 5:01 PM Bohan Lei <garthlei@linux.alibaba.com> wrote:
>
> Hi Zhongyao,
>
> I am not sure about the downstream implementation of other vendors, but
> currently in the tune parameters of our design, we are modeling that with our
> `common_vector_cost` instance with int_stmt_cost and fp_stmt_cost
> greater than 1.  I guess that can already suffice for many cases?  Also, we
> can have designs whose FP vector unit number is different than the integer
> vector unit number, and we may still need to bother with the
> `common_vector_cost` struct.
>
> Regards,
> Bohan
Robin Dapp Sept. 7, 2026, 8:53 p.m. UTC | #3
> Yeah, common_vector_cost is another way to model this.
>
> I’m just trying to make the cost-model rules clearer instead of hiding
> them in magic numbers.
> Otherwise, it may be hard to tell later whether a vector cost for a
> given uarch already includes the unit-ratio scaling.

Originally, my idea was to have a target knob to enable this kind of 
costing but that might further complicate things, rather than 
simplify...  Bohan's approach is the basic one that we also used for a 
while but we want to do better than that in the future.

Therefore, I would suggest something similar to what I proposed in the 
original thread about this:  Let's introduce a function that (for now, 
crudely) estimates things.  If a uarch doesn't want or need the new 
scaling, it can still opt out by disabling the scaling (which already is 
the default).

I'll note that the insn scheduler for generic-ooo assumes one vector 
unit.  We might want to extend this.

I'd say this is good to go but for documentation purposes, let's 
introduce a function scale_vector_costs or something right away and
add a comment/TODO that we should try to estimate throughput as well
as the critical path.
diff mbox series

Patch

diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index e9612cca1a1..f879680f787 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -940,6 +940,8 @@  struct riscv_tune_info {
 const struct riscv_tune_info *
 riscv_parse_tune (const char *, bool);
 const cpu_vector_cost *get_vector_costs ();
+unsigned int get_vector_units ();
+unsigned int get_scalar_units ();
 int get_gr2vr_cost ();
 int get_vr2gr_cost ();
 int get_fr2vr_cost ();
diff --git a/gcc/config/riscv/riscv-vector-costs.cc b/gcc/config/riscv/riscv-vector-costs.cc
index bfb8a0ca63b..468d59230da 100644
--- a/gcc/config/riscv/riscv-vector-costs.cc
+++ b/gcc/config/riscv/riscv-vector-costs.cc
@@ -1617,6 +1617,22 @@  costs::add_stmt_cost (int count, vect_cost_for_stmt kind,
     stmt_cost = adjust_stmt_cost (kind, loop_vinfo, stmt_info, node, vectype,
 				  stmt_cost);
 
+  unsigned int scalar_units = get_scalar_units ();
+  unsigned int vector_units = get_vector_units ();
+
+  /* Scale integer vector body costs by the scalar/vector unit ratio.  */
+  if (!costing_for_scalar ()
+      && loop_vinfo
+      && where == vect_body
+      && kind == vector_stmt
+      && !is_reduction (stmt_info, node)
+      && !(stmt_info && STMT_VINFO_GATHER_SCATTER_P (stmt_info))
+      && !(node && mat_gather_scatter_p (SLP_TREE_MEMORY_ACCESS_TYPE (node)))
+      && vectype
+      && VECTOR_INTEGER_TYPE_P (vectype)
+      && scalar_units != 0 && vector_units != 0)
+    stmt_cost = CEIL (stmt_cost * scalar_units, vector_units);
+
   return record_stmt_cost (stmt_info, where, count * stmt_cost);
 }
 
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 62fa062cf58..798dc04770b 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -310,6 +310,10 @@  struct riscv_tune_param
     AUTOPREFETCHER_OFF,
     AUTOPREFETCHER_WEAK
   } autoprefetcher_model = AUTOPREFETCHER_OFF;
+  /* scalar and vector units used for vector costing.
+     A zero value disables the scaling.  */
+  unsigned short scalar_units;
+  unsigned short vector_units;
 };
 
 
@@ -726,6 +730,11 @@  static const struct riscv_tune_param generic_ooo_tune_info = {
   2,						/* int_reassoc_width.  */
   2,						/* fp_reassoc_width.  */
   1,						/* vec_reassoc_width.  */
+  4,						/* small_loop_unroll_ninsns.  */
+  2,						/* small_loop_unroll_factor.  */
+  riscv_tune_param::AUTOPREFETCHER_OFF,		/* autoprefetcher_model.  */
+  4,						/* scalar_units.  */
+  2,						/* vector_units.  */
 };
 
 static const common_vector_cost xt_c9501_vls_vector_cost = {
@@ -14165,6 +14174,22 @@  get_vector_costs ()
   return costs;
 }
 
+/* Return the number of vector units.  */
+
+unsigned int
+get_vector_units ()
+{
+  return tune_param->vector_units;
+}
+
+/* Return the number of scalar units.  */
+
+unsigned int
+get_scalar_units ()
+{
+  return tune_param->scalar_units;
+}
+
 /* Return the cost of operation that move from gpr to vr.
    It will take the value of --param=gpr2vr_cost if it is provided.
    Or the default regmove->GR2VR will be returned.  */