aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUmesh Kalappa <ukalappa.mips@gmail.com>2025-07-15 10:35:44 -0600
committerJeff Law <jlaw@ventanamicro.com>2025-07-15 10:37:19 -0600
commit3fbed69502770851c8a5bfece99e9ee8c6d9e4b0 (patch)
tree4b2a052b5e07316fb1fdbb84053a89ec1fb23a23
parentf307ab8b18c7b5623344b01f24af593594319196 (diff)
downloadgcc-3fbed69502770851c8a5bfece99e9ee8c6d9e4b0.zip
gcc-3fbed69502770851c8a5bfece99e9ee8c6d9e4b0.tar.gz
gcc-3fbed69502770851c8a5bfece99e9ee8c6d9e4b0.tar.bz2
[PATCH v5] RISC-V: Mips P8700 Conditional Move Support.
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.
-rw-r--r--gcc/config/riscv/mips-insn.md35
-rw-r--r--gcc/config/riscv/riscv-cores.def3
-rw-r--r--gcc/config/riscv/riscv-ext-mips.def35
-rw-r--r--gcc/config/riscv/riscv-ext.def1
-rw-r--r--gcc/config/riscv/riscv-ext.opt4
-rw-r--r--gcc/config/riscv/riscv.cc107
-rw-r--r--gcc/config/riscv/riscv.md3
-rw-r--r--gcc/config/riscv/t-riscv3
-rw-r--r--gcc/doc/riscv-ext.texi4
-rw-r--r--gcc/testsuite/gcc.target/riscv/mipscondmov.c29
10 files changed, 187 insertions, 37 deletions
diff --git a/gcc/config/riscv/mips-insn.md b/gcc/config/riscv/mips-insn.md
new file mode 100644
index 0000000..ad46026
--- /dev/null
+++ b/gcc/config/riscv/mips-insn.md
@@ -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>")])
diff --git a/gcc/config/riscv/riscv-cores.def b/gcc/config/riscv/riscv-cores.def
index 2096c00..98f3470 100644
--- a/gcc/config/riscv/riscv-cores.def
+++ b/gcc/config/riscv/riscv-cores.def
@@ -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
index 0000000..5d7836d
--- /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 816acaa..6fc6d38 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 9f8c545..26d6e68 100644
--- a/gcc/config/riscv/riscv-ext.opt
+++ b/gcc/config/riscv/riscv-ext.opt
@@ -47,6 +47,9 @@ TargetVariable
int riscv_xcv_subext
TargetVariable
+int riscv_xmips_subext
+
+TargetVariable
int riscv_xsf_subext
TargetVariable
@@ -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 a4428f0..1275b03 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 \
@@ -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)
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index c6661f5..c3b504d 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,6 +4883,7 @@
(include "vector-crypto.md")
(include "vector-bfloat16.md")
(include "zicond.md")
+(include "mips-insn.md")
(include "sfb.md")
(include "zc.md")
;; Vendor extensions
diff --git a/gcc/config/riscv/t-riscv b/gcc/config/riscv/t-riscv
index 32092d8..7aac56a 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 c3ed1bf..572b70e 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 0000000..5485133
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/mipscondmov.c
@@ -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 } } */