Hi @Jeff Law <jeffreya...@gmail.com>  and @ma...@orcam.me.uk
<ma...@orcam.me.uk> ,

Please have a look at the updated patch for conditional move support and
any comments or suggestions  please let us know ?

Thank you
~U

On Wed, Jul 2, 2025 at 12:46 PM Umesh Kalappa <ukalappa.m...@gmail.com>
wrote:

> Indentation are updated accordingly and no regress found.
>
> 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.
>         *gcc/doc/riscv-ext.texi: Updated for mips cmov.
>
> gcc/testsuite/ChangeLog:
>
>         *testsuite/gcc.target/riscv/mipscondmov.c: Test file for
> mips.ccmov insn.
> ---
>  gcc/config/riscv/mips-insn.md                |  36 +++++++
>  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                    | 107 +++++++++++++------
>  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, 189 insertions(+), 37 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..de53638d587
> --- /dev/null
> +++ b/gcc/config/riscv/mips-insn.md
> @@ -0,0 +1,36 @@
> +;; 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 2096c0095d4..98f347034fb 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 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 bbc7547d385..fa94bb2948a 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                                      \
> @@ -4150,7 +4154,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))
> @@ -5468,6 +5472,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.  */
>
> @@ -5520,34 +5586,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;
>
> @@ -5584,25 +5638,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 893c925b6b9..8500cac98d9 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]))
> @@ -4886,3 +4886,4 @@
>  (include "sifive-p600.md")
>  (include "generic-vector-ooo.md")
>  (include "generic-ooo.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 } } */
>
> base-commit: 2609a7a5971aa8a2ef1bafbf5581dcabd68a466e
> --
> 2.43.0
>
>

Reply via email to