Addressed the most of comments and tried to refactor the
riscv_expand_conditional_move() to some extent.
No regressions are found for "runtest --tool gcc
--target_board='riscv-sim/-mabi=lp64d/-mtune=mips-p8700/-O2 ' riscv.exp"
*config/riscv/riscv-cores.def(RISCV_CORE):Updated the supported march.
*config/riscv/riscv-ext-mips.def(DEFINE_RISCV_EXT):
New file added for mips conditional mov extension.
*config/riscv/riscv-ext.def: Likewise.
*config/riscv/t-riscv:Generates riscv-ext.opt
*config/riscv/riscv-ext.opt: Generated file.
*config/riscv/riscv.cc(riscv_expand_conditional_move):Updated for mips
cmov
and outlined some code that handle arch cond move.
*config/riscv/riscv.md(mov<mode>cc):updated expand for MIPS CCMOV.
*config/riscv/mips-insn.md:New file for mips-p8700 ccmov insn.
*testsuite/gcc.target/riscv/mipscondmov.c:Test file for mips.ccmov insn.
*gcc/doc/riscv-ext.texi:Updated for mips cmov.
---
gcc/config/riscv/mips-insn.md | 37 ++++++
gcc/config/riscv/riscv-cores.def | 3 +-
gcc/config/riscv/riscv-ext-mips.def | 35 +++++
gcc/config/riscv/riscv-ext.def | 1 +
gcc/config/riscv/riscv-ext.opt | 4 +
gcc/config/riscv/riscv.cc | 131 ++++++++++++-------
gcc/config/riscv/riscv.md | 3 +-
gcc/config/riscv/t-riscv | 3 +-
gcc/doc/riscv-ext.texi | 4 +
gcc/testsuite/gcc.target/riscv/mipscondmov.c | 30 +++++
10 files changed, 202 insertions(+), 49 deletions(-)
create mode 100644 gcc/config/riscv/mips-insn.md
create mode 100644 gcc/config/riscv/riscv-ext-mips.def
create mode 100644 gcc/testsuite/gcc.target/riscv/mipscondmov.c
diff --git a/gcc/config/riscv/mips-insn.md b/gcc/config/riscv/mips-insn.md
new file mode 100644
index 00000000000..e36b7d78796
--- /dev/null
+++ b/gcc/config/riscv/mips-insn.md
@@ -0,0 +1,37 @@
+;; Machine description for MIPS custom instructions.
+;; 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_insn "*mov<GPR:mode><X:mode>cc_bitmanip"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (if_then_else:GPR
+ (match_operator 5 "equality_operator"
+ [(match_operand:X 1 "register_operand" "r")
+ (match_operand:X 2 "const_0_operand" "J")])
+ (match_operand:GPR 3 "reg_or_0_operand" "rJ")
+ (match_operand:GPR 4 "reg_or_0_operand" "rJ")))]
+ "TARGET_XMIPSCMOV"
+{
+ enum rtx_code code = GET_CODE (operands[5]);
+ if (code == NE)
+ return "mips.ccmov\t%0,%1,%z3,%z4";
+ else
+ return "mips.ccmov\t%0,%1,%z4,%z3";
+}
+ [(set_attr "type" "condmove")
+ (set_attr "mode" "<GPR:MODE>")])
diff --git a/gcc/config/riscv/riscv-cores.def b/gcc/config/riscv/riscv-cores.def
index cff7c77a0bd..111ee02260e 100644
--- a/gcc/config/riscv/riscv-cores.def
+++ b/gcc/config/riscv/riscv-cores.def
@@ -168,7 +168,6 @@ RISCV_CORE("xiangshan-kunminghu",
"rv64imafdcbvh_sdtrig_sha_shcounterenw_"
"zvfhmin_zvkt_zvl128b_zvl32b_zvl64b",
"xiangshan-kunminghu")
-RISCV_CORE("mips-p8700", "rv64imafd_zicsr_zmmul_"
- "zaamo_zalrsc_zba_zbb",
+RISCV_CORE("mips-p8700", "rv64imafd_zaamo_zalrsc_zba_zbb",
"mips-p8700")
#undef RISCV_CORE
diff --git a/gcc/config/riscv/riscv-ext-mips.def
b/gcc/config/riscv/riscv-ext-mips.def
new file mode 100644
index 00000000000..f24507139f6
--- /dev/null
+++ b/gcc/config/riscv/riscv-ext-mips.def
@@ -0,0 +1,35 @@
+/* MIPS extension definition file for RISC-V.
+ 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/>.
+
+Please run `make riscv-regen` in build folder to make sure updated anything.
+
+Format of DEFINE_RISCV_EXT, please refer to riscv-ext.def. */
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xmipscmov,
+ /* UPPERCASE_NAME */ XMIPSCMOV,
+ /* FULL_NAME */ "Mips conditional move extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xmips,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
diff --git a/gcc/config/riscv/riscv-ext.def b/gcc/config/riscv/riscv-ext.def
index 816acaa34f4..6fc6d388635 100644
--- a/gcc/config/riscv/riscv-ext.def
+++ b/gcc/config/riscv/riscv-ext.def
@@ -2082,3 +2082,4 @@ DEFINE_RISCV_EXT(
#include "riscv-ext-sifive.def"
#include "riscv-ext-thead.def"
#include "riscv-ext-ventana.def"
+#include "riscv-ext-mips.def"
diff --git a/gcc/config/riscv/riscv-ext.opt b/gcc/config/riscv/riscv-ext.opt
index 9f8c5451d49..26d6e683acd 100644
--- a/gcc/config/riscv/riscv-ext.opt
+++ b/gcc/config/riscv/riscv-ext.opt
@@ -46,6 +46,9 @@ int riscv_sv_subext
TargetVariable
int riscv_xcv_subext
+TargetVariable
+int riscv_xmips_subext
+
TargetVariable
int riscv_xsf_subext
@@ -445,3 +448,4 @@ Mask(XTHEADVECTOR) Var(riscv_xthead_subext)
Mask(XVENTANACONDOPS) Var(riscv_xventana_subext)
+Mask(XMIPSCMOV) Var(riscv_xmips_subext)
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index f6608bd872b..d57f6d4cc53 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -87,6 +87,10 @@ along with GCC; see the file COPYING3. If not see
#include "riscv-vector-costs.h"
#include "riscv-subset.h"
+/* Target variants that support full conditional move. */
+#define TARGET_COND_MOV \
+ (TARGET_SFB_ALU || TARGET_XTHEADCONDMOV || TARGET_XMIPSCMOV)
+
/* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF. */
#define UNSPEC_ADDRESS_P(X) \
(GET_CODE (X) == UNSPEC \
@@ -4084,7 +4088,7 @@ riscv_rtx_costs (rtx x, machine_mode mode, int
outer_code, int opno ATTRIBUTE_UN
return false;
case IF_THEN_ELSE:
- if ((TARGET_SFB_ALU || TARGET_XTHEADCONDMOV)
+ if (TARGET_COND_MOV
&& reg_or_0_operand (XEXP (x, 1), mode)
&& sfb_alu_operand (XEXP (x, 2), mode)
&& comparison_operator (XEXP (x, 0), VOIDmode))
@@ -5402,6 +5406,68 @@ riscv_expand_conditional_branch (rtx label, rtx_code
code, rtx op0, rtx op1)
emit_jump_insn (gen_condjump (condition, label));
}
+/* canonicalization of the comparands. */
+void
+canonicalize_comparands (rtx_code code, rtx *op0, rtx *op1)
+{
+ /* An integer comparison must be comparing WORD_MODE objects.
+ Extend the comparison arguments as necessary. */
+ if ((INTEGRAL_MODE_P (GET_MODE (*op0)) && GET_MODE (*op0) != word_mode)
+ || (INTEGRAL_MODE_P (GET_MODE (*op1)) && GET_MODE (*op1) != word_mode))
+ riscv_extend_comparands (code, op0, op1);
+
+ /* We might have been handed back a SUBREG. Just to make things
+ easy, force it into a REG. */
+ if (!REG_P (*op0) && !CONST_INT_P (*op0))
+ *op0 = force_reg (word_mode, *op0);
+ if (!REG_P (*op1) && !CONST_INT_P (*op1))
+ *op1 = force_reg (word_mode, *op1);
+}
+
+/* Emit target specific conditional move like TARGET_XMIPSCMOV etc*/
+bool
+riscv_target_conditional_move (rtx dest, rtx op0, rtx op1, rtx_code code,
+ rtx cons, rtx alt)
+{
+ machine_mode dst_mode = GET_MODE (dest);
+ rtx target;
+
+ /* force the operands to the register*/
+ cons = force_reg (dst_mode, cons);
+ alt = force_reg (dst_mode, alt);
+
+ if (TARGET_XMIPSCMOV)
+ {
+ if (code == EQ || code == NE)
+ {
+ op0 = riscv_zero_if_equal (op0, op1);
+ op1 = const0_rtx;
+ }
+ else
+ {
+ target = gen_reg_rtx (GET_MODE (op0));
+ riscv_emit_int_order_test(code, 0, target, op0, op1);
+ op0 = target;
+ op1 = const0_rtx;
+ code = NE;
+ }
+ riscv_emit_int_compare (&code, &op0, &op1);
+ rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
+ emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (dst_mode,
+ cond, cons, alt)));
+ return true;
+ }
+ /* TARGET_SFB_ALU || TARGET_XTHEADCONDMOV */
+ else
+ {
+ riscv_emit_int_compare (&code, &op0, &op1, !TARGET_SFB_ALU);
+ rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
+ emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (dst_mode, cond,
+ cons, alt)));
+ return true;
+ }
+}
+
/* Emit a cond move: If OP holds, move CONS to DEST; else move ALT to DEST.
Return 0 if expansion failed. */
@@ -5454,34 +5520,22 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx
cons, rtx alt)
/* If we need more special cases, add them here. */
}
+
if (((TARGET_ZICOND_LIKE
|| (arith_operand (cons, dst_mode) && arith_operand (alt, dst_mode)))
&& GET_MODE_CLASS (dst_mode) == MODE_INT
&& GET_MODE_CLASS (cond_mode) == MODE_INT)
- || TARGET_SFB_ALU || TARGET_XTHEADCONDMOV)
+ || TARGET_COND_MOV)
{
machine_mode mode0 = GET_MODE (op0);
- machine_mode mode1 = GET_MODE (op1);
-
- /* An integer comparison must be comparing WORD_MODE objects.
- Extend the comparison arguments as necessary. */
- if ((INTEGRAL_MODE_P (mode0) && mode0 != word_mode)
- || (INTEGRAL_MODE_P (mode1) && mode1 != word_mode))
- riscv_extend_comparands (code, &op0, &op1);
- /* We might have been handed back a SUBREG. Just to make things
- easy, force it into a REG. */
- if (!REG_P (op0) && !CONST_INT_P (op0))
- op0 = force_reg (word_mode, op0);
- if (!REG_P (op1) && !CONST_INT_P (op1))
- op1 = force_reg (word_mode, op1);
+ canonicalize_comparands(code,&op0,&op1);
/* In the fallback generic case use DST_MODE rather than WORD_MODE
for the output of the SCC instruction, to match the mode of the NEG
operation below. The output of SCC is 0 or 1 boolean, so it is
valid for input in any scalar integer mode. */
- rtx tmp = gen_reg_rtx ((TARGET_ZICOND_LIKE
- || TARGET_SFB_ALU || TARGET_XTHEADCONDMOV)
+ rtx tmp = gen_reg_rtx ((TARGET_ZICOND_LIKE || TARGET_COND_MOV)
? word_mode : dst_mode);
bool invert = false;
@@ -5500,9 +5554,9 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx
cons, rtx alt)
if (code == LE || code == LEU || code == GE || code == GEU)
invert_ptr = &invert;
- /* Emit an SCC-like instruction into a temporary so that we can
- use an EQ/NE comparison. We can support both FP and integer
- conditional moves. */
+ /* Emit an SCC-like instruction into a temporary so that we can
+ use an EQ/NE comparison. We can support both FP and integer
+ conditional moves. */
if (INTEGRAL_MODE_P (mode0))
riscv_expand_int_scc (tmp, code, op0, op1, invert_ptr);
else if (FLOAT_MODE_P (mode0)
@@ -5518,25 +5572,12 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx
cons, rtx alt)
op0 = XEXP (op, 0);
op1 = XEXP (op, 1);
}
- else if (!TARGET_ZICOND_LIKE && !TARGET_SFB_ALU && !TARGET_XTHEADCONDMOV)
+ else if (!TARGET_ZICOND_LIKE && !TARGET_COND_MOV)
riscv_expand_int_scc (tmp, code, op0, op1, &invert);
- if (TARGET_SFB_ALU || TARGET_XTHEADCONDMOV)
- {
- riscv_emit_int_compare (&code, &op0, &op1, !TARGET_SFB_ALU);
- rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
+ if (TARGET_COND_MOV)
+ return riscv_target_conditional_move (dest, op0, op1, code, cons, alt);
- /* The expander is a bit loose in its specification of the true
- arm of the conditional move. That allows us to support more
- cases for extensions which are more general than SFB. But
- does mean we need to force CONS into a register at this point. */
- cons = force_reg (dst_mode, cons);
- /* With XTheadCondMov we need to force ALT into a register too. */
- alt = force_reg (dst_mode, alt);
- emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (dst_mode, cond,
- cons, alt)));
- return true;
- }
else if (!TARGET_ZICOND_LIKE)
{
if (invert)
@@ -5558,15 +5599,15 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx
cons, rtx alt)
else if (cons == CONST0_RTX (dst_mode)
&& ((REG_P (alt) || SUBREG_P (alt))
|| (CONST_INT_P (alt) && alt != CONST0_RTX (dst_mode))))
- {
- riscv_emit_int_compare (&code, &op0, &op1, true);
- rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
- alt = force_reg (dst_mode, alt);
- emit_insn (gen_rtx_SET (dest,
- gen_rtx_IF_THEN_ELSE (dst_mode, cond,
- cons, alt)));
- return true;
- }
+ {
+ riscv_emit_int_compare (&code, &op0, &op1, true);
+ rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
+ alt = force_reg (dst_mode, alt);
+ emit_insn (gen_rtx_SET (dest,
+ gen_rtx_IF_THEN_ELSE (dst_mode, cond,
+ cons, alt)));
+ return true;
+ }
/* imm, imm */
else if (CONST_INT_P (cons) && cons != CONST0_RTX (dst_mode)
&& CONST_INT_P (alt) && alt != CONST0_RTX (dst_mode))
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 3aed25c2588..eb6befe60c2 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -3298,7 +3298,7 @@
(match_operand:GPR 2 "movcc_operand")
(match_operand:GPR 3 "movcc_operand")))]
"TARGET_SFB_ALU || TARGET_XTHEADCONDMOV || TARGET_ZICOND_LIKE
- || TARGET_MOVCC"
+ || TARGET_MOVCC || TARGET_XMIPSCMOV"
{
if (riscv_expand_conditional_move (operands[0], operands[1],
operands[2], operands[3]))
@@ -4883,3 +4883,4 @@
(include "corev.md")
(include "xiangshan.md")
(include "mips-p8700.md")
+(include "mips-insn.md")
diff --git a/gcc/config/riscv/t-riscv b/gcc/config/riscv/t-riscv
index 32092d85687..7aac56ac86c 100644
--- a/gcc/config/riscv/t-riscv
+++ b/gcc/config/riscv/t-riscv
@@ -194,7 +194,8 @@ RISCV_EXT_DEFS = \
$(srcdir)/config/riscv/riscv-ext.def \
$(srcdir)/config/riscv/riscv-ext-sifive.def \
$(srcdir)/config/riscv/riscv-ext-thead.def \
- $(srcdir)/config/riscv/riscv-ext-ventana.def
+ $(srcdir)/config/riscv/riscv-ext-ventana.def \
+ $(srcdir)/config/riscv/riscv-ext-mips.def
$(srcdir)/config/riscv/riscv-ext.opt: $(RISCV_EXT_DEFS)
diff --git a/gcc/doc/riscv-ext.texi b/gcc/doc/riscv-ext.texi
index c3ed1bfb593..572b70e20fa 100644
--- a/gcc/doc/riscv-ext.texi
+++ b/gcc/doc/riscv-ext.texi
@@ -714,4 +714,8 @@
@tab 1.0
@tab Ventana integer conditional operations extension
+@item xmipscmov
+@tab 1.0
+@tab Mips conditional move extension
+
@end multitable
diff --git a/gcc/testsuite/gcc.target/riscv/mipscondmov.c
b/gcc/testsuite/gcc.target/riscv/mipscondmov.c
new file mode 100644
index 00000000000..144a6b718ef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/mipscondmov.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64imafd_xmipscmov -mabi=lp64d" { target { rv64 } } }
*/
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+#define MYTEST(name, mytype) \
+mytype test1_ ## name (mytype a, mytype b, mytype c, mytype d) { return (a ==
b) ? c : d; } \
+mytype test2_ ## name (mytype a, mytype b, mytype c, mytype d) { return (a !=
b) ? c : d; } \
+mytype test3_ ## name (mytype a, mytype b, mytype c, mytype d) { return (a >
b) ? c : d; } \
+mytype test4_ ## name (mytype a, mytype b, mytype c, mytype d) { return (a >=
b) ? c : d; } \
+mytype test5_ ## name (mytype a, mytype b, mytype c, mytype d) { return (a <
b) ? c : d; } \
+mytype test6_ ## name (mytype a, mytype b, mytype c, mytype d) { return (a <=
b) ? c : d; } \
+mytype test7_ ## name (mytype a, mytype b, mytype c, mytype d) { return (a ==
1) ? c : d; } \
+mytype test8_ ## name (mytype a, mytype b, mytype c, mytype d) { return (a !=
1) ? c : d; } \
+mytype test9_ ## name (mytype a, mytype b, mytype c, mytype d) { return (a >
1) ? c : d; } \
+mytype test10_ ## name (mytype a, mytype b, mytype c, mytype d) { return (a >=
1) ? c : d; } \
+mytype test11_ ## name (mytype a, mytype b, mytype c, mytype d) { return (a <
1) ? c : d; } \
+mytype test12_ ## name (mytype a, mytype b, mytype c, mytype d) { return (a <=
1) ? c : d; }
+
+MYTEST(1, long long);
+MYTEST(2, unsigned long long);
+MYTEST(3, long);
+MYTEST(4, unsigned long);
+MYTEST(5, int);
+MYTEST(6, unsigned int);
+MYTEST(7, short);
+MYTEST(8, unsigned short);
+MYTEST(9, signed char);
+MYTEST(10, unsigned char);
+
+/* { dg-final { scan-assembler-times "mips.ccmov" 120 } } */
--
2.43.0