]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[PATCH v5] RISC-V: Mips P8700 Conditional Move Support.
authorUmesh Kalappa <ukalappa.mips@gmail.com>
Tue, 15 Jul 2025 16:35:44 +0000 (10:35 -0600)
committerJeff Law <jlaw@ventanamicro.com>
Tue, 15 Jul 2025 16:37:19 +0000 (10:37 -0600)
Updated the test for rv32 accordingly and no regress found for runs like
"runtest --tool gcc --target_board='riscv-sim/-march=rv32gc_zba_zbb_zbc_zbs/-mabi=ilp32d/-mcmodel=medlow' riscv.exp" and
"runtest --tool gcc --target_board='riscv-sim/-march=rv64gc_zba_zbb_zbc_zbs/-mabi=lp64d/-mcmodel=medlow' riscv.exp"

lint warnings can be ignored for riscv-cores.def and riscv-ext-mips.def

gcc/ChangeLog:

* 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.
* doc/riscv-ext.texi: Updated for mips cmov.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/mipscondmov.c: Test file for mips.ccmov insn.

gcc/config/riscv/mips-insn.md [new file with mode: 0644]
gcc/config/riscv/riscv-cores.def
gcc/config/riscv/riscv-ext-mips.def [new file with mode: 0644]
gcc/config/riscv/riscv-ext.def
gcc/config/riscv/riscv-ext.opt
gcc/config/riscv/riscv.cc
gcc/config/riscv/riscv.md
gcc/config/riscv/t-riscv
gcc/doc/riscv-ext.texi
gcc/testsuite/gcc.target/riscv/mipscondmov.c [new file with mode: 0644]

diff --git a/gcc/config/riscv/mips-insn.md b/gcc/config/riscv/mips-insn.md
new file mode 100644 (file)
index 0000000..ad46026
--- /dev/null
@@ -0,0 +1,35 @@
+;; 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 (any_eq:X (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 = <CODE>;
+  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>")])
index 2096c0095d4ec8d80af217a64cab4060f47e182a..98f347034fbb659ba2a593680922d0ce1be2c367 100644 (file)
@@ -169,7 +169,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",      "rv64imfd_zicsr_zifencei_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 (file)
index 0000000..5d7836d
--- /dev/null
@@ -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)
index 816acaa34f4aa6cc0bb0285b98dd21ef7c19fd33..6fc6d38863505f69b5582bac47f1cbefc1370650 100644 (file)
@@ -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"
index 9f8c5451d49775fde548b60e88ceafd4f7ed479d..26d6e683acd6d85a8aae043f9340b44f991a4f68 100644 (file)
@@ -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)
index a4428f0e96d2991158b56e6d27341a244bf371d6..1275b034cf834a2e5e0a28407e0e7151594060be 100644 (file)
@@ -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                                      \
@@ -4169,7 +4173,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))
@@ -5487,6 +5491,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.  */
 
@@ -5539,34 +5605,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;
 
@@ -5603,25 +5657,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)
index c6661f5646b3d5fdd566d706fb24d6b4ea314cb4..c3b504d088360f591837c4a0c64cdd10e78f553a 100644 (file)
                          (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]))
 (include "vector-crypto.md")
 (include "vector-bfloat16.md")
 (include "zicond.md")
+(include "mips-insn.md")
 (include "sfb.md")
 (include "zc.md")
 ;; Vendor extensions
index 32092d856878a2ec0283421706092235310ddac4..7aac56ac86ccbacc1b87e68629507d98b9434b25 100644 (file)
@@ -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)
 
index c3ed1bfb593671260bae4efe67e4a4dc5d97dd2b..572b70e20fa2985866412f6960198aebd5a20b27 100644 (file)
 @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 (file)
index 0000000..5485133
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32imafd_xmipscmov" { target { rv32 } } } */
+/* { 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)
+MYTEST(2, unsigned long)
+MYTEST(3, int)
+MYTEST(4, unsigned int)
+MYTEST(5, short)
+MYTEST(6, unsigned short)
+MYTEST(7, signed char)
+MYTEST(8, unsigned char)
+
+/* { dg-final { scan-assembler-times "mips.ccmov" 96 } } */