| 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 |
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
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
> 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 --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. */
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(+)