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/generic-ooo.md: Update comments for vector issue width.
* config/riscv/generic-vector-ooo.md (vxu_ooo_issue): Change to
reservation over 2 units.
(vxu_ooo_alu): Likewise.
(vxu_ooo_multicycle): Likewise.
* config/riscv/riscv-vector-costs.cc (costs::scale_vector_cost): New.
(costs::add_stmt_cost): Call it.
* config/riscv/riscv-vector-costs.h (costs::scale_vector_cost): New.
* 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.
Signed-off-by: Zhongyao Chen <[email protected]>
---
gcc/config/riscv/generic-ooo.md | 6 ++---
gcc/config/riscv/generic-vector-ooo.md | 9 +++++---
gcc/config/riscv/riscv-protos.h | 2 ++
gcc/config/riscv/riscv-vector-costs.cc | 31 ++++++++++++++++++++++++++
gcc/config/riscv/riscv-vector-costs.h | 6 +++++
gcc/config/riscv/riscv.cc | 25 +++++++++++++++++++++
6 files changed, 73 insertions(+), 6 deletions(-)
diff --git a/gcc/config/riscv/generic-ooo.md b/gcc/config/riscv/generic-ooo.md
index 601f9a989c26..7ff05b7accfa 100644
--- a/gcc/config/riscv/generic-ooo.md
+++ b/gcc/config/riscv/generic-ooo.md
@@ -22,11 +22,11 @@
;; Regarding functional units we assume a three-way split:
;; - Integer ALU (IXU) - 4 symmetric units.
;; - Floating-point (FXU) - 2 symmetric units.
-;; - Vector Unit (VXU) - 1 unit.
+;; - Vector Unit (VXU) - 2 units.
-;; We assume 6-wide issue:
+;; We assume 7-wide issue:
;; - 5-wide generic/integer issue.
-;; - 1-wide vector issue.
+;; - 2-wide vector issue.
;; For now, the only subunits are for non-pipelined integer division and
;; vector div/mult/sqrt.
diff --git a/gcc/config/riscv/generic-vector-ooo.md
b/gcc/config/riscv/generic-vector-ooo.md
index af8c0026d861..e0d9a9f972ea 100644
--- a/gcc/config/riscv/generic-vector-ooo.md
+++ b/gcc/config/riscv/generic-vector-ooo.md
@@ -23,13 +23,16 @@
(define_automaton "vector_ooo")
;; Separate issue queue for vector instructions.
-(define_cpu_unit "vxu_ooo_issue" "vector_ooo")
+(define_cpu_unit "vxu_issue0,vxu_issue1" "vector_ooo")
+(define_reservation "vxu_ooo_issue" "vxu_issue0|vxu_issue1")
;; Vector execution unit.
-(define_cpu_unit "vxu_ooo_alu" "vector_ooo")
+(define_cpu_unit "vxu_alu0,vxu_alu1" "vector_ooo")
+(define_reservation "vxu_ooo_alu" "vxu_alu0|vxu_alu1")
;; Vector subunit that does mult/div/sqrt.
-(define_cpu_unit "vxu_ooo_multicycle" "vector_ooo")
+(define_cpu_unit "vxu_multicycle0,vxu_multicycle1" "vector_ooo")
+(define_reservation "vxu_ooo_multicycle" "vxu_multicycle0|vxu_multicycle1")
(define_insn_reservation "vec_load" 6
(and (eq_attr "tune" "generic_ooo,generic")
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index b0c1d8d4d05c..a97d2fcf46c2 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -941,6 +941,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 41a15ae220ac..8e5e55dde8a5 100644
--- a/gcc/config/riscv/riscv-vector-costs.cc
+++ b/gcc/config/riscv/riscv-vector-costs.cc
@@ -1626,9 +1626,40 @@ 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);
+ stmt_cost = scale_vector_cost (kind, loop_vinfo, stmt_info, node,
+ vectype, where, stmt_cost);
+
return record_stmt_cost (stmt_info, where, count * stmt_cost);
}
+unsigned
+costs::scale_vector_cost (enum vect_cost_for_stmt kind,
+ loop_vec_info loop_vinfo,
+ stmt_vec_info stmt_info, slp_tree node,
+ tree vectype, vect_cost_model_location where,
+ unsigned stmt_cost)
+{
+ unsigned int scalar_units = get_scalar_units ();
+ unsigned int vector_units = get_vector_units ();
+
+ /* TODO: we should try to estimate throughput as well
+ as the critical path. */
+ /* 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 stmt_cost;
+}
+
/* For some target specific vectorization cost which can't be handled per stmt,
we check the requisite conditions and adjust the vectorization cost
accordingly if satisfied. One typical example is to model and adjust
diff --git a/gcc/config/riscv/riscv-vector-costs.h
b/gcc/config/riscv/riscv-vector-costs.h
index 74f1eab40012..ab506106fcae 100644
--- a/gcc/config/riscv/riscv-vector-costs.h
+++ b/gcc/config/riscv/riscv-vector-costs.h
@@ -137,6 +137,12 @@ private:
loop_vec_info,
stmt_vec_info stmt_info, slp_tree,
tree vectype, int stmt_cost);
+ unsigned scale_vector_cost (enum vect_cost_for_stmt kind,
+ loop_vec_info,
+ stmt_vec_info stmt_info, slp_tree,
+ tree vectype,
+ vect_cost_model_location where,
+ unsigned stmt_cost);
};
} // namespace riscv_vector
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index f8b54fc4ae68..126370755565 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 = 0;
+ unsigned short vector_units = 0;
};
@@ -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 = {
@@ -14296,6 +14305,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. */
--
2.43.0