This patch introduces the pipeline description for the Synopsys RHX-100 series
processor to the RISC-V GCC backend. The RHX-100 features a 10-stage,
dual-issue, in-order execution pipeline architecture.
It has support for instruction fusion, which will be addressed by subsequent
patches. Due to fusion, up to four instructions can be issued in a single
cycle. It is modeled as four separate pipelines and the issue_rate is set to
four.
gcc/ChangeLog:
* config/riscv/riscv-cores.def (RISCV_TUNE): Add arc-v-rhx-100-series.
* config/riscv/riscv-opts.h (enum riscv_microarchitecture_type): Add
arcv_rhx100.
* config/riscv/riscv.cc (enum riscv_fusion_pairs): Add RISCV_FUSE_ARCV.
* config/riscv/riscv.md: Add arcv_rhx100 to tune attribute.
* doc/riscv-mtune.texi: Add RHX-100 documentation.
* config/riscv/arcv-rhx100.md: New file.
Co-authored-by: Artemiy Volkov <[email protected]>
Co-authored-by: Michiel Derhaeg <[email protected]>
Signed-off-by: Luis Silva <[email protected]>
---
gcc/config/riscv/arcv-rhx100.md | 96 ++++++++++++++++++++++++++++++++
gcc/config/riscv/riscv-cores.def | 1 +
gcc/config/riscv/riscv-opts.h | 1 +
gcc/config/riscv/riscv.cc | 26 +++++++++
gcc/config/riscv/riscv.md | 4 +-
gcc/doc/riscv-mtune.texi | 2 +
6 files changed, 129 insertions(+), 1 deletion(-)
create mode 100644 gcc/config/riscv/arcv-rhx100.md
diff --git a/gcc/config/riscv/arcv-rhx100.md b/gcc/config/riscv/arcv-rhx100.md
new file mode 100644
index 00000000000..c0631a17a28
--- /dev/null
+++ b/gcc/config/riscv/arcv-rhx100.md
@@ -0,0 +1,96 @@
+;; DFA scheduling description of the Synopsys RHX-100 cpu
+;; for GNU C compiler
+;; Copyright (C) 2025 Free Software Foundation, Inc.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+(define_automaton "arcv_rhx100")
+
+(define_cpu_unit "arcv_rhx100_ALU_A_fuse0_early" "arcv_rhx100")
+(define_cpu_unit "arcv_rhx100_ALU_A_fuse1_early" "arcv_rhx100")
+(define_cpu_unit "arcv_rhx100_ALU_B_fuse0_early" "arcv_rhx100")
+(define_cpu_unit "arcv_rhx100_ALU_B_fuse1_early" "arcv_rhx100")
+(define_cpu_unit "arcv_rhx100_MPY32" "arcv_rhx100")
+(define_cpu_unit "arcv_rhx100_DIV" "arcv_rhx100")
+(define_cpu_unit "arcv_rhx100_DMP_fuse0" "arcv_rhx100")
+(define_cpu_unit "arcv_rhx100_DMP_fuse1" "arcv_rhx100")
+(define_cpu_unit "arcv_rhx100_fdivsqrt" "arcv_rhx100")
+(define_cpu_unit "arcv_rhx100_issueA_fuse0" "arcv_rhx100")
+(define_cpu_unit "arcv_rhx100_issueA_fuse1" "arcv_rhx100")
+(define_cpu_unit "arcv_rhx100_issueB_fuse0" "arcv_rhx100")
+(define_cpu_unit "arcv_rhx100_issueB_fuse1" "arcv_rhx100")
+
+;; Instruction reservation for arithmetic instructions (pipe A, pipe B).
+(define_insn_reservation "arcv_rhx100_alu_early_arith" 1
+ (and (eq_attr "tune" "arcv_rhx100")
+ (eq_attr "type"
"unknown,move,const,arith,shift,slt,multi,auipc,nop,logical,\
+ bitmanip,min,max,minu,maxu,clz,ctz,atomic,\
+ condmove,mvpair,zicond,cpop,clmul"))
+ "((arcv_rhx100_issueA_fuse0 + arcv_rhx100_ALU_A_fuse0_early) |
(arcv_rhx100_issueA_fuse1 + arcv_rhx100_ALU_A_fuse1_early)) |
((arcv_rhx100_issueB_fuse0 + arcv_rhx100_ALU_B_fuse0_early) |
(arcv_rhx100_issueB_fuse1 + arcv_rhx100_ALU_B_fuse1_early))")
+
+(define_insn_reservation "arcv_rhx100_jmp_insn" 1
+ (and (eq_attr "tune" "arcv_rhx100")
+ (eq_attr "type" "branch,jump,call,jalr,ret,trap"))
+ "arcv_rhx100_issueA_fuse0 | arcv_rhx100_issueA_fuse1")
+
+(define_insn_reservation "arcv_rhx100_div_insn" 12
+ (and (eq_attr "tune" "arcv_rhx100")
+ (eq_attr "type" "idiv"))
+ "arcv_rhx100_issueA_fuse0 + arcv_rhx100_DIV, nothing*11")
+
+(define_insn_reservation "arcv_rhx100_mpy32_insn" 4
+ (and (eq_attr "tune" "arcv_rhx100")
+ (eq_attr "type" "imul"))
+ "arcv_rhx100_issueA_fuse0 + arcv_rhx100_MPY32, nothing*3")
+
+(define_insn_reservation "arcv_rhx100_load_insn" 3
+ (and (eq_attr "tune" "arcv_rhx100")
+ (eq_attr "type" "load,fpload"))
+ "(arcv_rhx100_issueB_fuse0 + arcv_rhx100_DMP_fuse0) |
(arcv_rhx100_issueB_fuse1 + arcv_rhx100_DMP_fuse1)")
+
+(define_insn_reservation "arcv_rhx100_store_insn" 1
+ (and (eq_attr "tune" "arcv_rhx100")
+ (eq_attr "type" "store,fpstore"))
+ "(arcv_rhx100_issueB_fuse0 + arcv_rhx100_DMP_fuse0) |
(arcv_rhx100_issueB_fuse1 + arcv_rhx100_DMP_fuse1)")
+
+;; (soft) floating points
+(define_insn_reservation "arcv_rhx100_xfer" 3
+ (and (eq_attr "tune" "arcv_rhx100")
+ (eq_attr "type" "mfc,mtc,fcvt,fcvt_i2f,fcvt_f2i,fmove,fcmp"))
+ "(arcv_rhx100_ALU_A_fuse0_early | arcv_rhx100_ALU_B_fuse0_early), nothing*2")
+
+(define_insn_reservation "arcv_rhx100_fmul" 5
+ (and (eq_attr "tune" "arcv_rhx100")
+ (eq_attr "type" "fadd,fmul,fmadd"))
+ "(arcv_rhx100_ALU_A_fuse0_early | arcv_rhx100_ALU_B_fuse0_early)")
+
+(define_insn_reservation "arcv_rhx100_fdiv" 20
+ (and (eq_attr "tune" "arcv_rhx100")
+ (eq_attr "type" "fdiv,fsqrt"))
+ "arcv_rhx100_fdivsqrt*20")
+
+;; Bypasses
+(define_bypass 1 "arcv_rhx100_alu_early_arith" "arcv_rhx100_store_insn"
"riscv_store_data_bypass_p")
+
+(define_bypass 1 "arcv_rhx100_load_insn" "arcv_rhx100_store_insn"
"riscv_store_data_bypass_p")
+(define_bypass 1 "arcv_rhx100_load_insn" "arcv_rhx100_alu_early_arith")
+(define_bypass 1 "arcv_rhx100_load_insn" "arcv_rhx100_mpy*_insn")
+(define_bypass 2 "arcv_rhx100_load_insn" "arcv_rhx100_load_insn")
+(define_bypass 1 "arcv_rhx100_load_insn" "arcv_rhx100_div_insn")
+
+(define_bypass 3 "arcv_rhx100_mpy32_insn" "arcv_rhx100_mpy*_insn")
+(define_bypass 3 "arcv_rhx100_mpy32_insn" "arcv_rhx100_div_insn")
diff --git a/gcc/config/riscv/riscv-cores.def b/gcc/config/riscv/riscv-cores.def
index 355b04466ed..4baedafd793 100644
--- a/gcc/config/riscv/riscv-cores.def
+++ b/gcc/config/riscv/riscv-cores.def
@@ -51,6 +51,7 @@ RISCV_TUNE("xt-c920v2", generic, generic_ooo_tune_info)
RISCV_TUNE("xiangshan-nanhu", xiangshan, xiangshan_nanhu_tune_info)
RISCV_TUNE("xiangshan-kunminghu", xiangshan, generic_ooo_tune_info)
RISCV_TUNE("spacemit-x60", spacemit_x60, spacemit_x60_tune_info)
+RISCV_TUNE("arc-v-rhx-100-series", arcv_rhx100, arcv_rhx100_tune_info)
RISCV_TUNE("generic-ooo", generic_ooo, generic_ooo_tune_info)
RISCV_TUNE("size", generic, optimize_size_tune_info)
RISCV_TUNE("mips-p8700", mips_p8700, mips_p8700_tune_info)
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index c8cfc4c5930..db2de28e392 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -65,6 +65,7 @@ enum riscv_microarchitecture_type {
andes_23_series,
andes_45_series,
spacemit_x60,
+ arcv_rhx100,
};
extern enum riscv_microarchitecture_type riscv_microarchitecture;
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 40705e079c7..8b9049f04b8 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -291,6 +291,7 @@ enum riscv_fusion_pairs
RISCV_FUSE_BFEXT = (1 << 11),
RISCV_FUSE_EXPANDED_LD = (1 << 12),
RISCV_FUSE_B_ALUI = (1 << 13),
+ RISCV_FUSE_ARCV = (1 << 14),
};
/* Costs of various operations on the different architectures. */
@@ -834,6 +835,31 @@ static const struct riscv_tune_param andes_45_tune_info = {
true, /* prefer-agnostic. */
};
+/* Costs to use when optimizing for Synopsys RHX-100. */
+static const struct riscv_tune_param arcv_rhx100_tune_info = {
+ {COSTS_N_INSNS (4), COSTS_N_INSNS (5)}, /* fp_add */
+ {COSTS_N_INSNS (4), COSTS_N_INSNS (5)}, /* fp_mul */
+ {COSTS_N_INSNS (20), COSTS_N_INSNS (20)}, /* fp_div */
+ {COSTS_N_INSNS (4), COSTS_N_INSNS (4)}, /* int_mul */
+ {COSTS_N_INSNS (27), COSTS_N_INSNS (43)}, /* int_div */
+ 4, /* issue_rate */
+ 9, /* branch_cost */
+ 2, /* memory_cost */
+ 8, /* fmv_cost */
+ false, /* slow_unaligned_access */
+ false, /* vector_unaligned_access */
+ false, /* use_divmod_expansion */
+ false, /* overlap_op_by_pieces */
+ true, /* use_zero_stride_load
*/
+ false, /* speculative_sched_vsetvl */
+ RISCV_FUSE_ARCV, /* fusible_ops */
+ NULL, /* vector cost */
+ NULL, /* function_align */
+ NULL, /* jump_align */
+ NULL, /* loop_align */
+ true, /* prefer-agnostic. */
+};
+
static bool riscv_avoid_shrink_wrapping_separate ();
static tree riscv_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
static tree riscv_handle_type_attribute (tree *, tree, tree, int, bool *);
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 3fe0ad0ccdf..58f30c4902b 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -674,7 +674,8 @@
;; Keep this in sync with enum riscv_microarchitecture.
(define_attr "tune"
"generic,sifive_7,sifive_p400,sifive_p600,xiangshan,generic_ooo,mips_p8700,
- tt_ascalon_d8,andes_25_series,andes_23_series,andes_45_series,spacemit_x60"
+ tt_ascalon_d8,andes_25_series,andes_23_series,andes_45_series,spacemit_x60,
+ arcv_rhx100"
(const (symbol_ref "((enum attr_tune) riscv_microarchitecture)")))
;; Describe a user's asm statement.
@@ -4993,3 +4994,4 @@
(include "andes-25-series.md")
(include "andes-45-series.md")
(include "spacemit-x60.md")
+(include "arcv-rhx100.md")
diff --git a/gcc/doc/riscv-mtune.texi b/gcc/doc/riscv-mtune.texi
index 6865bd6fbf7..6ceb9a93fac 100644
--- a/gcc/doc/riscv-mtune.texi
+++ b/gcc/doc/riscv-mtune.texi
@@ -52,6 +52,8 @@ particular CPU name. Permissible values for this option are:
@samp{spacemit-x60},
+@samp{arc-v-rhx-100-series},
+
@samp{generic-ooo},
@samp{size},
--
2.34.0