From: Loeka Rogge <[email protected]>
This patch implements instruction scheduling support for the dual-issue
ARC-V RHX-100 processor by adding scheduler hooks and state tracking for
the two execution pipes.
These hooks address microarchitectural details not covered by the
pipeline description.
The riscv_sched_variable_issue () and riscv_sched_reorder2 () hooks work
together to make sure that:
- the critical path and the instruction priorities are respected;
- both pipes are filled (taking advantage of parallel dispatch within
the microarchitectural constraints);
- there is as much fusion going on as possible;
- the existing fusion pairs are not broken up.
riscv_sched_adjust_priority () slightly bumps the priority of load/store
pairs. As a result it becomes easier for riscv_sched_reorder2 () to
schedule instructions in the memory pipe.
gcc/ChangeLog:
* config.gcc: Include arcv.cc.
* config/riscv/riscv-protos.h (arcv_sched_reorder2): Declare.
(arcv_sched_adjust_priority): Declare.
(arcv_sched_adjust_cost): Declare.
(arcv_can_issue_more_p): Declare.
(arcv_sched_variable_issue): Declare.
* config/riscv/riscv.cc (struct last_vconfig): Declare
riscv_cached_can_issue_more and riscv_last_scheduled_insn.
(riscv_sched_variable_issue): Handle RHX-100;
cache the returned issue count.
(riscv_sched_reorder2): New function. Return cached_can_issue_more
for non-RHX.
(riscv_sched_adjust_cost): Handle RHX-100.
(riscv_sched_adjust_priority): New function.
(TARGET_SCHED_ADJUST_PRIORITY): Define.
* config/riscv/riscv.h (TARGET_ARCV_RHX100): Define.
* config/riscv/t-riscv: Build arcv.o.
* config/riscv/arcv.cc: New file.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/fusion-ls-update-2.c: Remove XFAIL, and fix the
scan pattern.
* gcc.target/riscv/fusion-ls-update.c: Remove XFAIL.
Co-authored-by: Artemiy Volkov <[email protected]>
Co-authored-by: Michiel Derhaeg <[email protected]>
Co-authored-by: Alex Turjan <[email protected]>
Co-authored-by: Luis Silva <[email protected]>
Signed-off-by: Loeka Rogge <[email protected]>
---
gcc/config.gcc | 2 +-
gcc/config/riscv/arcv.cc | 279 ++++++++++++++++++
gcc/config/riscv/riscv-protos.h | 10 +
gcc/config/riscv/riscv.cc | 48 ++-
gcc/config/riscv/riscv.h | 4 +
gcc/config/riscv/t-riscv | 6 +
.../gcc.target/riscv/fusion-ls-update-2.c | 3 +-
.../gcc.target/riscv/fusion-ls-update.c | 3 +-
8 files changed, 343 insertions(+), 12 deletions(-)
create mode 100644 gcc/config/riscv/arcv.cc
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 13a0757c5a6..ba4a37c47e9 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -584,7 +584,7 @@ riscv*)
extra_objs="riscv-builtins.o riscv-c.o riscv-sr.o
riscv-shorten-memrefs.o riscv-selftests.o riscv-string.o"
extra_objs="${extra_objs} riscv-v.o riscv-vsetvl.o riscv-vector-costs.o
riscv-avlprop.o riscv-vect-permconst.o"
extra_objs="${extra_objs} riscv-vector-builtins.o
riscv-vector-builtins-shapes.o riscv-vector-builtins-bases.o
sifive-vector-builtins-bases.o andes-vector-builtins-bases.o"
- extra_objs="${extra_objs} thead.o riscv-target-attr.o riscv-zicfilp.o
riscv-bclr-lowest-set-bit.o riscv-opt-popretz.o riscv-fusion.o"
+ extra_objs="${extra_objs} thead.o riscv-target-attr.o riscv-zicfilp.o
riscv-bclr-lowest-set-bit.o riscv-opt-popretz.o riscv-fusion.o arcv.o"
d_target_objs="riscv-d.o"
extra_headers="riscv_vector.h riscv_crypto.h riscv_bitmanip.h
riscv_th_vector.h sifive_vector.h andes_vector.h"
target_gtfiles="$target_gtfiles
\$(srcdir)/config/riscv/riscv-vector-builtins.cc"
diff --git a/gcc/config/riscv/arcv.cc b/gcc/config/riscv/arcv.cc
new file mode 100644
index 00000000000..407f1dc9f1c
--- /dev/null
+++ b/gcc/config/riscv/arcv.cc
@@ -0,0 +1,279 @@
+/* Subroutines used for code generation for ARC-V processors.
+ Copyright (C) 2026 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 IN_TARGET_CODE 1
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "target.h"
+#include "rtl.h"
+#include "tree.h"
+#include "memmodel.h"
+#include "tm.h"
+#include "optabs.h"
+#include "regs.h"
+#include "emit-rtl.h"
+#include "recog.h"
+#include "diagnostic-core.h"
+#include "stor-layout.h"
+#include "alias.h"
+#include "fold-const.h"
+#include "output.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "explow.h"
+#include "calls.h"
+#include "varasm.h"
+#include "expr.h"
+#include "tm_p.h"
+#include "df.h"
+#include "reload.h"
+#include "sched-int.h"
+#include "tm-constrs.h"
+
+/* Scheduler state tracking for dual-pipe ARCV architectures. */
+
+struct arcv_sched_state {
+ /* True if the ALU pipe has been scheduled for the current cycle.
+ The ALU pipe handles arithmetic, logical, and other computational
+ instructions. */
+ int alu_pipe_scheduled_p;
+
+ /* True if pipe B has been scheduled for the current cycle.
+ Pipe B is the second execution pipe, typically used for memory
+ operations (loads/stores) but can also handle other instructions. */
+ int pipeB_scheduled_p;
+};
+
+static struct arcv_sched_state sched_state;
+
+/* Try to reorder ready queue to promote ARCV fusion opportunities.
+ Returns the number of instructions that can be issued this cycle. */
+
+int
+arcv_sched_reorder2 (rtx_insn **ready, int *n_readyp)
+{
+ if (sched_fusion)
+ return riscv_cached_can_issue_more;
+
+ if (!riscv_cached_can_issue_more)
+ return 0;
+
+ /* Fuse double load/store instances missed by sched_fusion. */
+ if (!sched_state.pipeB_scheduled_p && riscv_last_scheduled_insn
+ && ready && *n_readyp > 0
+ && !SCHED_GROUP_P (riscv_last_scheduled_insn)
+ && (get_attr_type (riscv_last_scheduled_insn) == TYPE_LOAD
+ || get_attr_type (riscv_last_scheduled_insn) == TYPE_STORE))
+ {
+ for (int i = 1; i <= *n_readyp; i++)
+ {
+ rtx_insn *next_insn
+ = next_nonnote_nondebug_insn_bb (ready[*n_readyp - i]);
+ /* Try to fuse the last_scheduled_insn with. */
+ /* Fuse only with nondebug insn. */
+ if (NONDEBUG_INSN_P (ready[*n_readyp - i])
+ /* Which have not been already fused. */
+ && !SCHED_GROUP_P (ready[*n_readyp - i])
+ && (!next_insn || !NONDEBUG_INSN_P (next_insn)
+ || !SCHED_GROUP_P (next_insn))
+ && riscv_macro_fusion_pair_p (riscv_last_scheduled_insn,
+ ready[*n_readyp - i]))
+ {
+ std::swap (ready[*n_readyp - 1], ready[*n_readyp - i]);
+ SCHED_GROUP_P (ready[*n_readyp - 1]) = 1;
+ sched_state.pipeB_scheduled_p = 1;
+ return riscv_cached_can_issue_more;
+ }
+ }
+ sched_state.pipeB_scheduled_p = 1;
+ }
+
+ /* Try to fuse a non-memory last_scheduled_insn. */
+ if ((!sched_state.alu_pipe_scheduled_p || !sched_state.pipeB_scheduled_p)
+ && riscv_last_scheduled_insn && ready && *n_readyp > 0
+ && !SCHED_GROUP_P (riscv_last_scheduled_insn)
+ && (get_attr_type (riscv_last_scheduled_insn) != TYPE_LOAD
+ && get_attr_type (riscv_last_scheduled_insn) != TYPE_STORE))
+ {
+ for (int i = 1; i <= *n_readyp; i++)
+ {
+ rtx_insn* next_insn
+ = next_nonnote_nondebug_insn_bb (ready[*n_readyp - i]);
+ if (NONDEBUG_INSN_P (ready[*n_readyp - i])
+ && !SCHED_GROUP_P (ready[*n_readyp - i])
+ && active_insn_p (ready[*n_readyp - i])
+ && (!next_insn || !NONDEBUG_INSN_P (next_insn)
+ || !SCHED_GROUP_P (next_insn))
+ && riscv_macro_fusion_pair_p (riscv_last_scheduled_insn,
+ ready[*n_readyp - i]))
+ {
+ if (get_attr_type (ready[*n_readyp - i]) == TYPE_LOAD
+ || get_attr_type (ready[*n_readyp - i]) == TYPE_STORE)
+ {
+ if (sched_state.pipeB_scheduled_p)
+ continue;
+ else
+ sched_state.pipeB_scheduled_p = 1;
+ }
+ else if (!sched_state.alu_pipe_scheduled_p)
+ sched_state.alu_pipe_scheduled_p = 1;
+ else
+ sched_state.pipeB_scheduled_p = 1;
+
+ std::swap (ready[*n_readyp - 1], ready[*n_readyp - i]);
+ SCHED_GROUP_P (ready[*n_readyp - 1]) = 1;
+ return riscv_cached_can_issue_more;
+ }
+ }
+ sched_state.alu_pipe_scheduled_p = 1;
+ }
+ /* When pipe B is scheduled, we can have no more memops this cycle. */
+ if (sched_state.pipeB_scheduled_p && *n_readyp > 0
+ && NONDEBUG_INSN_P (ready[*n_readyp - 1])
+ && recog_memoized (ready[*n_readyp - 1]) >= 0
+ && !SCHED_GROUP_P (ready[*n_readyp - 1]))
+ {
+ rtx_insn *head_next = next_nonnote_nondebug_insn_bb (ready[*n_readyp - 1]);
+ if (get_attr_type (ready[*n_readyp - 1]) == TYPE_LOAD
+ || get_attr_type (ready[*n_readyp - 1]) == TYPE_STORE
+ || (head_next && NONDEBUG_INSN_P (head_next)
+ && SCHED_GROUP_P (head_next) && recog_memoized (head_next) >= 0
+ && (get_attr_type (head_next) == TYPE_LOAD
+ || get_attr_type (head_next) == TYPE_STORE)))
+ {
+ if (sched_state.alu_pipe_scheduled_p)
+ return 0;
+
+ for (int i = 2; i <= *n_readyp; i++)
+ {
+ rtx_insn* next_insn
+ = next_nonnote_nondebug_insn_bb (ready[*n_readyp - i]);
+ if ((NONDEBUG_INSN_P (ready[*n_readyp - i])
+ && recog_memoized (ready[*n_readyp - i]) >= 0
+ && get_attr_type (ready[*n_readyp - i]) != TYPE_LOAD
+ && get_attr_type (ready[*n_readyp - i]) != TYPE_STORE
+ && !SCHED_GROUP_P (ready[*n_readyp - i])
+ && (!next_insn || !NONDEBUG_INSN_P (next_insn)
+ || !SCHED_GROUP_P (next_insn)))
+ || (next_insn && NONDEBUG_INSN_P (next_insn)
+ && recog_memoized (next_insn) >= 0
+ && get_attr_type (next_insn) != TYPE_LOAD
+ && get_attr_type (next_insn) != TYPE_STORE))
+ {
+ std::swap (ready[*n_readyp - 1], ready[*n_readyp - i]);
+ sched_state.alu_pipe_scheduled_p = 1;
+ riscv_cached_can_issue_more = 1;
+ return 1;
+ }
+ }
+ return 0;
+ }
+ }
+
+ /* If all else fails, schedule a single (fused) instruction. */
+ if (ready && *n_readyp > 0
+ && NONDEBUG_INSN_P (ready[*n_readyp - 1])
+ && recog_memoized (ready[*n_readyp - 1]) >= 0)
+ {
+ rtx_insn *next_insn = next_nonnote_nondebug_insn_bb (ready[*n_readyp - 1]);
+
+ riscv_cached_can_issue_more
+ = next_insn && NONDEBUG_INSN_P (next_insn) && SCHED_GROUP_P (next_insn)
+ ? 2 : 1;
+ }
+
+ return riscv_cached_can_issue_more;
+}
+
+int
+arcv_sched_adjust_priority (rtx_insn *insn, int priority)
+{
+ /* Bump the priority of fused load-store pairs for easier
+ scheduling of the memory pipe. The specific increase
+ value is determined empirically. */
+ rtx_insn *next = next_nonnote_nondebug_insn_bb (insn);
+ if (next && single_set (insn) && single_set (next)
+ && SCHED_GROUP_P (next)
+ && ((get_attr_type (insn) == TYPE_STORE
+ && get_attr_type (next) == TYPE_STORE)
+ || (get_attr_type (insn) == TYPE_LOAD
+ && get_attr_type (next) == TYPE_LOAD)))
+ return priority + 1;
+
+ return priority;
+}
+
+/* Adjust scheduling cost for ARCV fusion. */
+
+int
+arcv_sched_adjust_cost (rtx_insn *insn, int dep_type, int cost)
+{
+ if (dep_type == REG_DEP_ANTI && !SCHED_GROUP_P (insn))
+ return cost + 1;
+
+ return cost;
+}
+
+bool
+arcv_can_issue_more_p (int issue_rate, int more, rtx_insn *insn)
+{
+ /* Beginning of cycle - reset variables. */
+ if (more == issue_rate)
+ {
+ sched_state.alu_pipe_scheduled_p = 0;
+ sched_state.pipeB_scheduled_p = 0;
+ }
+
+ if (!(insn && NONDEBUG_INSN_P (insn) && SCHED_GROUP_P (insn))
+ && sched_state.alu_pipe_scheduled_p && sched_state.pipeB_scheduled_p)
+ {
+ riscv_cached_can_issue_more = 0;
+ return false;
+ }
+
+ riscv_cached_can_issue_more = more;
+
+ return true;
+}
+
+int
+arcv_sched_variable_issue (rtx_insn *insn, int more)
+{
+ rtx_insn *next = next_nonnote_nondebug_insn_bb (insn);
+ if (next && NONDEBUG_INSN_P (next) && SCHED_GROUP_P (next)
+ && single_set (insn) && single_set (next))
+ {
+ if (get_attr_type (insn) == TYPE_LOAD
+ || get_attr_type (insn) == TYPE_STORE
+ || get_attr_type (next) == TYPE_LOAD
+ || get_attr_type (next) == TYPE_STORE
+ || sched_state.alu_pipe_scheduled_p)
+ sched_state.pipeB_scheduled_p = 1;
+ else
+ sched_state.alu_pipe_scheduled_p = 1;
+ }
+
+ riscv_last_scheduled_insn = insn;
+ riscv_cached_can_issue_more = more - 1;
+
+ return riscv_cached_can_issue_more;
+}
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 5c0cd3dfedb..81e96e7dc52 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -937,10 +937,20 @@ extern const char *th_output_move (rtx, rtx);
extern bool th_print_operand_address (FILE *, machine_mode, rtx);
#endif
+extern int riscv_cached_can_issue_more;
+extern rtx_insn *riscv_last_scheduled_insn;
+
extern bool arcv_mpy_1c_bypass_p (rtx_insn *, rtx_insn *);
extern bool arcv_mpy_2c_bypass_p (rtx_insn *, rtx_insn *);
extern bool arcv_mpy_10c_bypass_p (rtx_insn *, rtx_insn *);
+/* Routines implemented in arcv.cc. */
+extern int arcv_sched_reorder2 (rtx_insn **, int *);
+extern int arcv_sched_adjust_priority (rtx_insn *, int);
+extern int arcv_sched_adjust_cost (rtx_insn *, int, int);
+extern bool arcv_can_issue_more_p (int, int, rtx_insn *);
+extern int arcv_sched_variable_issue (rtx_insn *, int);
+
extern bool strided_load_broadcast_p (void);
extern bool riscv_prefer_agnostic_p (void);
extern bool riscv_use_divmod_expander (void);
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index f3065e85276..15ede87d6c9 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -11796,8 +11796,8 @@ struct last_vconfig
/* Ready-list macro-fusion state for the current scheduling block. */
-static int riscv_cached_can_issue_more;
-static rtx_insn *riscv_last_scheduled_insn;
+int riscv_cached_can_issue_more;
+rtx_insn *riscv_last_scheduled_insn;
static bool riscv_last_fusion_insn_p;
/* Clear LAST_VCONFIG so we have no known state. */
@@ -11871,6 +11871,13 @@ riscv_sched_init (FILE *, int, int)
static int
riscv_sched_variable_issue (FILE *, int, rtx_insn *insn, int more)
{
+ if (TARGET_ARCV_RHX100
+ && !arcv_can_issue_more_p (riscv_issue_rate (), more, insn))
+ {
+ riscv_cached_can_issue_more = 0;
+ return 0;
+ }
+
if (DEBUG_INSN_P (insn))
{
riscv_cached_can_issue_more = more;
@@ -11937,6 +11944,13 @@ riscv_sched_variable_issue (FILE *, int, rtx_insn
*insn, int more)
last_vconfig.ma = mask_agnostic_p (insn);
}
}
+ if (TARGET_ARCV_RHX100)
+ {
+ more = arcv_sched_variable_issue (insn, more);
+ riscv_cached_can_issue_more = more;
+ return more;
+ }
+
riscv_cached_can_issue_more = more - 1;
return riscv_cached_can_issue_more;
}
@@ -12055,6 +12069,9 @@ static int
riscv_sched_reorder2 (FILE *file, int verbose, rtx_insn **ready,
int *nreadyp, int)
{
+ if (TARGET_ARCV_RHX100)
+ return arcv_sched_reorder2 (ready, nreadyp);
+
if (riscv_cached_can_issue_more > 0)
riscv_sched_reorder_fusion (file, verbose, ready, *nreadyp);
return riscv_cached_can_issue_more;
@@ -12076,9 +12093,12 @@ riscv_get_fusible_ops (void)
we currently only perform the adjustment when -madjust-lmul-cost is given.
*/
static int
-riscv_sched_adjust_cost (rtx_insn *, int, rtx_insn *insn, int cost,
- unsigned int)
+riscv_sched_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn,
+ int cost, unsigned int)
{
+ /* Use ARCV-specific cost adjustment for RHX-100. */
+ if (TARGET_ARCV_RHX100)
+ return arcv_sched_adjust_cost (insn, dep_type, cost);
/* Only do adjustments for the generic out-of-order and spacemit_x60
scheduling model. */
@@ -12087,10 +12107,10 @@ riscv_sched_adjust_cost (rtx_insn *, int, rtx_insn
*insn, int cost,
&& riscv_microarchitecture != spacemit_x60))
return cost;
- if (recog_memoized (insn) < 0)
+ if (recog_memoized (dep_insn) < 0)
return cost;
- enum attr_type type = get_attr_type (insn);
+ enum attr_type type = get_attr_type (dep_insn);
if (type == TYPE_VFREDO || type == TYPE_VFWREDO)
{
@@ -12108,7 +12128,7 @@ riscv_sched_adjust_cost (rtx_insn *, int, rtx_insn
*insn, int cost,
return cost;
enum riscv_vector::vlmul_type lmul =
- (riscv_vector::vlmul_type)get_attr_vlmul (insn);
+ (riscv_vector::vlmul_type)get_attr_vlmul (dep_insn);
double factor = 1;
switch (lmul)
@@ -12141,6 +12161,17 @@ riscv_sched_adjust_cost (rtx_insn *, int, rtx_insn
*insn, int cost,
return new_cost;
}
+/* Implement TARGET_SCHED_ADJUST_PRIORITY hook. */
+
+static int
+riscv_sched_adjust_priority (rtx_insn *insn, int priority)
+{
+ if (TARGET_ARCV_RHX100)
+ return arcv_sched_adjust_priority (insn, priority);
+
+ return priority;
+}
+
/* Implement TARGET_SCHED_CAN_SPECULATE_INSN hook. Return true if insn
can be scheduled for speculative execution. Reject vsetvl instructions to
prevent the scheduler from hoisting them out of basic blocks without
@@ -17142,6 +17173,9 @@ riscv_memtag_tag_bitsize ()
#undef TARGET_SCHED_ADJUST_COST
#define TARGET_SCHED_ADJUST_COST riscv_sched_adjust_cost
+#undef TARGET_SCHED_ADJUST_PRIORITY
+#define TARGET_SCHED_ADJUST_PRIORITY riscv_sched_adjust_priority
+
#undef TARGET_SCHED_REASSOCIATION_WIDTH
#define TARGET_SCHED_REASSOCIATION_WIDTH riscv_reassociation_width
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 7ba2a726ac4..64374560662 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -1002,6 +1002,10 @@ extern enum riscv_cc get_riscv_cc (const rtx use);
|| (riscv_microarchitecture == sifive_p600) \
|| (riscv_microarchitecture == andes_45_series))
+/* True if the target is ARC-V RHX100. */
+#define TARGET_ARCV_RHX100 \
+ (riscv_microarchitecture == arcv_rhx100)
+
/* True if the target supports misaligned vector loads and stores. */
#define TARGET_VECTOR_MISALIGN_SUPPORTED \
riscv_vector_unaligned_access_p
diff --git a/gcc/config/riscv/t-riscv b/gcc/config/riscv/t-riscv
index cdf2f87128a..24ec911585d 100644
--- a/gcc/config/riscv/t-riscv
+++ b/gcc/config/riscv/t-riscv
@@ -194,6 +194,12 @@ riscv-zicfilp.o: $(srcdir)/config/riscv/riscv-zicfilp.cc \
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/riscv/riscv-zicfilp.cc
+arcv.o: $(srcdir)/config/riscv/arcv.cc \
+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TARGET_H) $(BACKEND_H) $(RTL_H) \
+ memmodel.h $(EMIT_RTL_H) $(TM_H) output.h
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
PASSES_EXTRA += $(srcdir)/config/riscv/riscv-passes.def
$(common_out_file): $(srcdir)/config/riscv/riscv-cores.def \
diff --git a/gcc/testsuite/gcc.target/riscv/fusion-ls-update-2.c
b/gcc/testsuite/gcc.target/riscv/fusion-ls-update-2.c
index 57363b44fa8..8d3045cbf4d 100644
--- a/gcc/testsuite/gcc.target/riscv/fusion-ls-update-2.c
+++ b/gcc/testsuite/gcc.target/riscv/fusion-ls-update-2.c
@@ -13,5 +13,4 @@ fuse_ls_update_rev (int *p, int n, int val)
}
}
-/* XFAIL until scheduling support for RHX-100 series is implemented. */
-/* { dg-final { scan-rtl-dump "RISCV_FUSE_LS_UPDATE" "sched2" { xfail *-*-* }
} } */
+/* { dg-final { scan-rtl-dump "RISCV_FUSE_LS_UPDATE" "sched2" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/fusion-ls-update.c
b/gcc/testsuite/gcc.target/riscv/fusion-ls-update.c
index b71eab0fcd9..5939fdd0de9 100644
--- a/gcc/testsuite/gcc.target/riscv/fusion-ls-update.c
+++ b/gcc/testsuite/gcc.target/riscv/fusion-ls-update.c
@@ -12,5 +12,4 @@ fuse_ls_update (int *p, int n)
return sum;
}
-/* XFAIL until scheduling support for RHX-100 series is implemented. */
-/* { dg-final { scan-rtl-dump "RISCV_FUSE_LS_UPDATE" "sched2" { xfail *-*-* }
} } */
+/* { dg-final { scan-rtl-dump "RISCV_FUSE_LS_UPDATE" "sched2" } } */
--
2.47.3