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

Reply via email to