Hi Jeff and Marco,

Please pass your comments on the below changes and do needful.

Thank you
~U

On Sun, Jul 6, 2025 at 12:56 PM Umesh Kalappa <ukalappa.m...@gmail.com>
wrote:

> 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