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