[v2] RISC-V: More support of vx and vf for autovec comparison

Message ID 20240719085447.2640598-1-demin.han@starfivetech.com
State Changes Requested
Delegated to: Robin Dapp
Headers
Series [v2] RISC-V: More support of vx and vf for autovec comparison |

Checks

Context Check Description
rivoscibot/toolchain-ci-rivos-lint success Lint passed
rivoscibot/toolchain-ci-rivos-apply-patch success Patch applied
rivoscibot/toolchain-ci-rivos-build--newlib-rv64gcv-lp64d-multilib success Build passed
rivoscibot/toolchain-ci-rivos-build--linux-rv64gcv-lp64d-multilib success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
rivoscibot/toolchain-ci-rivos-build--newlib-rv32imc_zba_zbb_zbc_zbs-ilp32d-non-multilib success Build passed
rivoscibot/toolchain-ci-rivos-build--newlib-rv64gc-lp64d-multilib success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
rivoscibot/toolchain-ci-rivos-build--linux-rv64gc_zba_zbb_zbc_zbs-lp64d-non-multilib success Build passed
rivoscibot/toolchain-ci-rivos-build--linux-rv32gc_zba_zbb_zbc_zbs-ilp32d-non-multilib success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed
rivoscibot/toolchain-ci-rivos-test success Testing passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Test passed

Commit Message

Demin Han July 19, 2024, 8:54 a.m. UTC
  There are still some cases which can't utilize vx or vf after
last_combine pass.

1. integer comparison when imm isn't in range of [-16, 15]
2. float imm is 0.0
3. DI or DF mode under RV32

This patch fix above mentioned issues.

Tested on RV32 and RV64.

Signed-off-by: demin.han <demin.han@starfivetech.com>
gcc/ChangeLog:

	* config/riscv/autovec.md: register_operand to nonmemory_operand
	* config/riscv/riscv-v.cc (get_cmp_insn_code): Select code according
    * to scalar_p
	(expand_vec_cmp): Generate scalar_p and transform op1
	* config/riscv/riscv.cc (riscv_const_insns): Add !FLOAT_MODE_P
    * constrain

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/rvv/autovec/cmp/vcond-1.c: Fix and add test

Signed-off-by: demin.han <demin.han@starfivetech.com>
---
V2 changes:
  1. remove unnecessary add_integer_operand and related code
  2. fix one format issue
  3. split patch and make it only related to vec cmp

 gcc/config/riscv/autovec.md                   |  2 +-
 gcc/config/riscv/riscv-v.cc                   | 57 +++++++++++--------
 gcc/config/riscv/riscv.cc                     |  2 +-
 .../riscv/rvv/autovec/cmp/vcond-1.c           | 48 +++++++++++++++-
 4 files changed, 82 insertions(+), 27 deletions(-)
  

Comments

Li, Pan2 July 19, 2024, 10:33 a.m. UTC | #1
> +  TEST_COND_IMM_FLOAT (T, >, 0.0, _gt)					\
>  +  TEST_COND_IMM_FLOAT (T, <, 0.0, _lt)					\
>  +  TEST_COND_IMM_FLOAT (T, >=, 0.0, _ge)					\
>  +  TEST_COND_IMM_FLOAT (T, <=, 0.0, _le)					\
>  +  TEST_COND_IMM_FLOAT (T, ==, 0.0, _eq)					\
>  +  TEST_COND_IMM_FLOAT (T, !=, 0.0, _ne)					\

Just curious, does this patch covered float imm is -0.0 (notice only +0.0 is mentioned)?
If so we can have similar tests as +0.0 here.

It is totally Ok if -0.0f is not applicable here.

Pan

-----Original Message-----
From: demin.han <demin.han@starfivetech.com> 
Sent: Friday, July 19, 2024 4:55 PM
To: gcc-patches@gcc.gnu.org
Cc: juzhe.zhong@rivai.ai; kito.cheng@gmail.com; Li, Pan2 <pan2.li@intel.com>; jeffreyalaw@gmail.com; rdapp.gcc@gmail.com
Subject: [PATCH v2] RISC-V: More support of vx and vf for autovec comparison

There are still some cases which can't utilize vx or vf after
last_combine pass.

1. integer comparison when imm isn't in range of [-16, 15]
2. float imm is 0.0
3. DI or DF mode under RV32

This patch fix above mentioned issues.

Tested on RV32 and RV64.

Signed-off-by: demin.han <demin.han@starfivetech.com>
gcc/ChangeLog:

	* config/riscv/autovec.md: register_operand to nonmemory_operand
	* config/riscv/riscv-v.cc (get_cmp_insn_code): Select code according
    * to scalar_p
	(expand_vec_cmp): Generate scalar_p and transform op1
	* config/riscv/riscv.cc (riscv_const_insns): Add !FLOAT_MODE_P
    * constrain

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/rvv/autovec/cmp/vcond-1.c: Fix and add test

Signed-off-by: demin.han <demin.han@starfivetech.com>
---
V2 changes:
  1. remove unnecessary add_integer_operand and related code
  2. fix one format issue
  3. split patch and make it only related to vec cmp

 gcc/config/riscv/autovec.md                   |  2 +-
 gcc/config/riscv/riscv-v.cc                   | 57 +++++++++++--------
 gcc/config/riscv/riscv.cc                     |  2 +-
 .../riscv/rvv/autovec/cmp/vcond-1.c           | 48 +++++++++++++++-
 4 files changed, 82 insertions(+), 27 deletions(-)

diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index d5793acc999..a7111172153 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -690,7 +690,7 @@ (define_expand "vec_cmp<mode><vm>"
   [(set (match_operand:<VM> 0 "register_operand")
 	(match_operator:<VM> 1 "comparison_operator"
 	  [(match_operand:V_VLSF 2 "register_operand")
-	   (match_operand:V_VLSF 3 "register_operand")]))]
+	   (match_operand:V_VLSF 3 "nonmemory_operand")]))]
   "TARGET_VECTOR"
   {
     riscv_vector::expand_vec_cmp_float (operands[0], GET_CODE (operands[1]),
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index e290675bbf0..56328075aeb 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -2624,32 +2624,27 @@ expand_vec_init (rtx target, rtx vals)
 /* Get insn code for corresponding comparison.  */
 
 static insn_code
-get_cmp_insn_code (rtx_code code, machine_mode mode)
+get_cmp_insn_code (rtx_code code, machine_mode mode, bool scalar_p)
 {
   insn_code icode;
-  switch (code)
+  if (FLOAT_MODE_P (mode))
     {
-    case EQ:
-    case NE:
-    case LE:
-    case LEU:
-    case GT:
-    case GTU:
-    case LTGT:
-      icode = code_for_pred_cmp (mode);
-      break;
-    case LT:
-    case LTU:
-    case GE:
-    case GEU:
-      if (FLOAT_MODE_P (mode))
-	icode = code_for_pred_cmp (mode);
+      icode = !scalar_p ? code_for_pred_cmp (mode)
+			: code_for_pred_cmp_scalar (mode);
+      return icode;
+    }
+  if (scalar_p)
+    {
+      if (code == GE || code == GEU)
+	icode = code_for_pred_ge_scalar (mode);
       else
-	icode = code_for_pred_ltge (mode);
-      break;
-    default:
-      gcc_unreachable ();
+	icode = code_for_pred_cmp_scalar (mode);
+      return icode;
     }
+  if (code == LT || code == LTU || code == GE || code == GEU)
+    icode = code_for_pred_ltge (mode);
+  else
+    icode = code_for_pred_cmp (mode);
   return icode;
 }
 
@@ -2771,7 +2766,6 @@ expand_vec_cmp (rtx target, rtx_code code, rtx op0, rtx op1, rtx mask,
 {
   machine_mode mask_mode = GET_MODE (target);
   machine_mode data_mode = GET_MODE (op0);
-  insn_code icode = get_cmp_insn_code (code, data_mode);
 
   if (code == LTGT)
     {
@@ -2779,12 +2773,29 @@ expand_vec_cmp (rtx target, rtx_code code, rtx op0, rtx op1, rtx mask,
       rtx gt = gen_reg_rtx (mask_mode);
       expand_vec_cmp (lt, LT, op0, op1, mask, maskoff);
       expand_vec_cmp (gt, GT, op0, op1, mask, maskoff);
-      icode = code_for_pred (IOR, mask_mode);
+      insn_code icode = code_for_pred (IOR, mask_mode);
       rtx ops[] = {target, lt, gt};
       emit_vlmax_insn (icode, BINARY_MASK_OP, ops);
       return;
     }
 
+  rtx elt;
+  bool scalar_p = false;
+  if (const_vec_duplicate_p (op1, &elt))
+    {
+      if (FLOAT_MODE_P (data_mode))
+	{
+	  scalar_p = true;
+	  op1 = force_reg (GET_MODE_INNER (GET_MODE (op1)), elt);
+	}
+      else if (!has_vi_variant_p (code, elt))
+	{
+	  scalar_p = true;
+	  op1 = elt;
+	}
+    }
+  insn_code icode = get_cmp_insn_code (code, data_mode, scalar_p);
+
   rtx cmp = gen_rtx_fmt_ee (code, mask_mode, op0, op1);
   if (!mask && !maskoff)
     {
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 19b9b2daa95..ad5668b2c5a 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -2140,7 +2140,7 @@ riscv_const_insns (rtx x)
 		   register vec_duplicate into vmv.v.x.  */
 		scalar_mode smode = GET_MODE_INNER (GET_MODE (x));
 		if (maybe_gt (GET_MODE_SIZE (smode), UNITS_PER_WORD)
-		    && !immediate_operand (elt, Pmode))
+		    && !FLOAT_MODE_P (smode) && !immediate_operand (elt, Pmode))
 		  return 0;
 		/* Constants from -16 to 15 can be loaded with vmv.v.i.
 		   The Wc0, Wc1 constraints are already covered by the
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cmp/vcond-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cmp/vcond-1.c
index 0faedacb2c7..6a072aab281 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cmp/vcond-1.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cmp/vcond-1.c
@@ -141,6 +141,34 @@
 TEST_VAR_ALL (DEF_VCOND_VAR)
 TEST_IMM_ALL (DEF_VCOND_IMM)
 
+#define TEST_COND_IMM_FLOAT(T, COND, IMM, SUFFIX)			\
+  T (float, float, COND, IMM, SUFFIX##_float_float)			\
+  T (double, double, COND, IMM, SUFFIX##_double_double)
+
+#define TEST_IMM_FLOAT_ALL(T)						\
+  TEST_COND_IMM_FLOAT (T, >, 0.0, _gt)					\
+  TEST_COND_IMM_FLOAT (T, <, 0.0, _lt)					\
+  TEST_COND_IMM_FLOAT (T, >=, 0.0, _ge)					\
+  TEST_COND_IMM_FLOAT (T, <=, 0.0, _le)					\
+  TEST_COND_IMM_FLOAT (T, ==, 0.0, _eq)					\
+  TEST_COND_IMM_FLOAT (T, !=, 0.0, _ne)					\
+									\
+  TEST_COND_IMM_FLOAT (T, >, 1.0, _gt1)					\
+  TEST_COND_IMM_FLOAT (T, <, 1.0, _lt1)					\
+  TEST_COND_IMM_FLOAT (T, >=, 1.0, _ge1)				\
+  TEST_COND_IMM_FLOAT (T, <=, 1.0, _le1)				\
+  TEST_COND_IMM_FLOAT (T, ==, 1.0, _eq1)				\
+  TEST_COND_IMM_FLOAT (T, !=, 1.0, _ne1)				\
+									\
+  TEST_COND_IMM_FLOAT (T, >, -1.0, _gt2)				\
+  TEST_COND_IMM_FLOAT (T, <, -1.0, _lt2)				\
+  TEST_COND_IMM_FLOAT (T, >=, -1.0, _ge2)				\
+  TEST_COND_IMM_FLOAT (T, <=, -1.0, _le2)				\
+  TEST_COND_IMM_FLOAT (T, ==, -1.0, _eq2)				\
+  TEST_COND_IMM_FLOAT (T, !=, -1.0, _ne2)
+
+TEST_IMM_FLOAT_ALL (DEF_VCOND_IMM)
+
 /* { dg-final { scan-assembler-times {\tvmseq\.vi} 42 } } */
 /* { dg-final { scan-assembler-times {\tvmsne\.vi} 42 } } */
 /* { dg-final { scan-assembler-times {\tvmsgt\.vi} 30 } } */
@@ -152,6 +180,22 @@ TEST_IMM_ALL (DEF_VCOND_IMM)
 /* { dg-final { scan-assembler-times {\tvmseq} 78 } } */
 /* { dg-final { scan-assembler-times {\tvmsne} 78 } } */
 /* { dg-final { scan-assembler-times {\tvmsgt} 82 } } */
-/* { dg-final { scan-assembler-times {\tvmslt} 38 } } */
-/* { dg-final { scan-assembler-times {\tvmsge} 38 } } */
+/* { dg-final { scan-assembler-times {\tvmslt} 56 } } */
+/* { dg-final { scan-assembler-times {\tvmsge} 20 } } */
 /* { dg-final { scan-assembler-times {\tvmsle} 82 } } */
+/* { dg-final { scan-assembler-times {\tvmseq\.vx} 24 } } */
+/* { dg-final { scan-assembler-times {\tvmsne\.vx} 24 } } */
+/* { dg-final { scan-assembler-times {\tvmsgt\.vx} 6 } } */
+/* { dg-final { scan-assembler-times {\tvmsgtu\.vx} 22 } } */
+/* { dg-final { scan-assembler-times {\tvmslt\.vx} 36 } } */
+/* { dg-final { scan-assembler-times {\tvmsltu\.vx} 0 } } */
+/* { dg-final { scan-assembler-times {\tvmsge\.vx} 0 } } */
+/* { dg-final { scan-assembler-times {\tvmsgeu\.vx} 0 } } */
+/* { dg-final { scan-assembler-times {\tvmsle\.vx} 6 } } */
+/* { dg-final { scan-assembler-times {\tvmsleu\.vx} 22 } } */
+/* { dg-final { scan-assembler-times {\tvmfgt.vf} 6 } } */
+/* { dg-final { scan-assembler-times {\tvmflt.vf} 6 } } */
+/* { dg-final { scan-assembler-times {\tvmfge.vf} 6 } } */
+/* { dg-final { scan-assembler-times {\tvmfle.vf} 6 } } */
+/* { dg-final { scan-assembler-times {\tvmfeq.vf} 6 } } */
+/* { dg-final { scan-assembler-times {\tvmfne.vf} 6 } } */
  
Demin Han July 19, 2024, 11:22 a.m. UTC | #2
> -----Original Message-----
> From: Li, Pan2 <pan2.li@intel.com>
> Sent: 2024年7月19日 18:33
> To: Demin Han <demin.han@starfivetech.com>; gcc-patches@gcc.gnu.org
> Cc: juzhe.zhong@rivai.ai; kito.cheng@gmail.com; jeffreyalaw@gmail.com;
> rdapp.gcc@gmail.com
> Subject: RE: [PATCH v2] RISC-V: More support of vx and vf for autovec
> comparison
> 
> > +  TEST_COND_IMM_FLOAT (T, >, 0.0, _gt)					\
> >  +  TEST_COND_IMM_FLOAT (T, <, 0.0, _lt)					\
> >  +  TEST_COND_IMM_FLOAT (T, >=, 0.0, _ge)					\
> >  +  TEST_COND_IMM_FLOAT (T, <=, 0.0, _le)					\
> >  +  TEST_COND_IMM_FLOAT (T, ==, 0.0, _eq)					\
> >  +  TEST_COND_IMM_FLOAT (T, !=, 0.0, _ne)					\
> 
> Just curious, does this patch covered float imm is -0.0 (notice only +0.0 is
> mentioned)?
> If so we can have similar tests as +0.0 here.
> 
> It is totally Ok if -0.0f is not applicable here.

I have a test. 
The backend can't see -0.0 and It becomes 0.0 when translate to gimple.

> Pan
> 
Regards,
Demin
  
Robin Dapp July 19, 2024, 8:36 p.m. UTC | #3
> -	   (match_operand:V_VLSF 3 "register_operand")]))]
> +	   (match_operand:V_VLSF 3 "nonmemory_operand")]))]

Even though the integer compares have nonmemory operand here their respective
insn patterns don't (but constrain properly).

I guess what's happening with register operand and a constant 0.0 is that we'd
broadcast (vec_duplicate) instead?  Can't we special-case the vector move
pattern to allow constant zero in two ways?  That would also allow to have a
uarch-specific choice regarding .vv vs .vf at the proper spot.
  
Robin Dapp July 19, 2024, 8:37 p.m. UTC | #4
> I have a test. 
> The backend can't see -0.0 and It becomes 0.0 when translate to gimple.

I don't think it should except when specifying -ffast-math or similar.
But we don't have a shortcut to load a negative zero, just the positive
one.
  
Jeff Law Aug. 25, 2024, 10:52 p.m. UTC | #5
On 7/19/24 2:54 AM, demin.han wrote:
> There are still some cases which can't utilize vx or vf after
> last_combine pass.
> 
> 1. integer comparison when imm isn't in range of [-16, 15]
> 2. float imm is 0.0
> 3. DI or DF mode under RV32
> 
> This patch fix above mentioned issues.
> 
> Tested on RV32 and RV64.
> 
> Signed-off-by: demin.han <demin.han@starfivetech.com>
> gcc/ChangeLog:
> 
> 	* config/riscv/autovec.md: register_operand to nonmemory_operand
> 	* config/riscv/riscv-v.cc (get_cmp_insn_code): Select code according
>      * to scalar_p
> 	(expand_vec_cmp): Generate scalar_p and transform op1
> 	* config/riscv/riscv.cc (riscv_const_insns): Add !FLOAT_MODE_P
>      * constrain
> 
> gcc/testsuite/ChangeLog:
> 
> 	* gcc.target/riscv/rvv/autovec/cmp/vcond-1.c: Fix and add test
> 
> Signed-off-by: demin.han <demin.han@starfivetech.com>
> ---
> V2 changes:
>    1. remove unnecessary add_integer_operand and related code
>    2. fix one format issue
>    3. split patch and make it only related to vec cmp
> 
>   gcc/config/riscv/autovec.md                   |  2 +-
>   gcc/config/riscv/riscv-v.cc                   | 57 +++++++++++--------
>   gcc/config/riscv/riscv.cc                     |  2 +-
>   .../riscv/rvv/autovec/cmp/vcond-1.c           | 48 +++++++++++++++-
>   4 files changed, 82 insertions(+), 27 deletions(-)
> 
> diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
> index d5793acc999..a7111172153 100644
> --- a/gcc/config/riscv/autovec.md
> +++ b/gcc/config/riscv/autovec.md
> @@ -690,7 +690,7 @@ (define_expand "vec_cmp<mode><vm>"
>     [(set (match_operand:<VM> 0 "register_operand")
>   	(match_operator:<VM> 1 "comparison_operator"
>   	  [(match_operand:V_VLSF 2 "register_operand")
> -	   (match_operand:V_VLSF 3 "register_operand")]))]
> +	   (match_operand:V_VLSF 3 "nonmemory_operand")]))]
>     "TARGET_VECTOR"
I'm still concerned about this.  We generally want the expander's 
predicate to match what the insn can do.  A "nonmemory_operand" is 
likely going to accept all kinds of things that we don't want.  A 
tighter predicate seems more appropriate.

Also note that a define_expand is primarily used during initial RTL 
generation.  What's more important from a code optimization standpoint 
is the define_insn patterns since that's what passes will test against 
for recognition.]

Jeff
  

Patch

diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index d5793acc999..a7111172153 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -690,7 +690,7 @@  (define_expand "vec_cmp<mode><vm>"
   [(set (match_operand:<VM> 0 "register_operand")
 	(match_operator:<VM> 1 "comparison_operator"
 	  [(match_operand:V_VLSF 2 "register_operand")
-	   (match_operand:V_VLSF 3 "register_operand")]))]
+	   (match_operand:V_VLSF 3 "nonmemory_operand")]))]
   "TARGET_VECTOR"
   {
     riscv_vector::expand_vec_cmp_float (operands[0], GET_CODE (operands[1]),
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index e290675bbf0..56328075aeb 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -2624,32 +2624,27 @@  expand_vec_init (rtx target, rtx vals)
 /* Get insn code for corresponding comparison.  */
 
 static insn_code
-get_cmp_insn_code (rtx_code code, machine_mode mode)
+get_cmp_insn_code (rtx_code code, machine_mode mode, bool scalar_p)
 {
   insn_code icode;
-  switch (code)
+  if (FLOAT_MODE_P (mode))
     {
-    case EQ:
-    case NE:
-    case LE:
-    case LEU:
-    case GT:
-    case GTU:
-    case LTGT:
-      icode = code_for_pred_cmp (mode);
-      break;
-    case LT:
-    case LTU:
-    case GE:
-    case GEU:
-      if (FLOAT_MODE_P (mode))
-	icode = code_for_pred_cmp (mode);
+      icode = !scalar_p ? code_for_pred_cmp (mode)
+			: code_for_pred_cmp_scalar (mode);
+      return icode;
+    }
+  if (scalar_p)
+    {
+      if (code == GE || code == GEU)
+	icode = code_for_pred_ge_scalar (mode);
       else
-	icode = code_for_pred_ltge (mode);
-      break;
-    default:
-      gcc_unreachable ();
+	icode = code_for_pred_cmp_scalar (mode);
+      return icode;
     }
+  if (code == LT || code == LTU || code == GE || code == GEU)
+    icode = code_for_pred_ltge (mode);
+  else
+    icode = code_for_pred_cmp (mode);
   return icode;
 }
 
@@ -2771,7 +2766,6 @@  expand_vec_cmp (rtx target, rtx_code code, rtx op0, rtx op1, rtx mask,
 {
   machine_mode mask_mode = GET_MODE (target);
   machine_mode data_mode = GET_MODE (op0);
-  insn_code icode = get_cmp_insn_code (code, data_mode);
 
   if (code == LTGT)
     {
@@ -2779,12 +2773,29 @@  expand_vec_cmp (rtx target, rtx_code code, rtx op0, rtx op1, rtx mask,
       rtx gt = gen_reg_rtx (mask_mode);
       expand_vec_cmp (lt, LT, op0, op1, mask, maskoff);
       expand_vec_cmp (gt, GT, op0, op1, mask, maskoff);
-      icode = code_for_pred (IOR, mask_mode);
+      insn_code icode = code_for_pred (IOR, mask_mode);
       rtx ops[] = {target, lt, gt};
       emit_vlmax_insn (icode, BINARY_MASK_OP, ops);
       return;
     }
 
+  rtx elt;
+  bool scalar_p = false;
+  if (const_vec_duplicate_p (op1, &elt))
+    {
+      if (FLOAT_MODE_P (data_mode))
+	{
+	  scalar_p = true;
+	  op1 = force_reg (GET_MODE_INNER (GET_MODE (op1)), elt);
+	}
+      else if (!has_vi_variant_p (code, elt))
+	{
+	  scalar_p = true;
+	  op1 = elt;
+	}
+    }
+  insn_code icode = get_cmp_insn_code (code, data_mode, scalar_p);
+
   rtx cmp = gen_rtx_fmt_ee (code, mask_mode, op0, op1);
   if (!mask && !maskoff)
     {
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 19b9b2daa95..ad5668b2c5a 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -2140,7 +2140,7 @@  riscv_const_insns (rtx x)
 		   register vec_duplicate into vmv.v.x.  */
 		scalar_mode smode = GET_MODE_INNER (GET_MODE (x));
 		if (maybe_gt (GET_MODE_SIZE (smode), UNITS_PER_WORD)
-		    && !immediate_operand (elt, Pmode))
+		    && !FLOAT_MODE_P (smode) && !immediate_operand (elt, Pmode))
 		  return 0;
 		/* Constants from -16 to 15 can be loaded with vmv.v.i.
 		   The Wc0, Wc1 constraints are already covered by the
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cmp/vcond-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cmp/vcond-1.c
index 0faedacb2c7..6a072aab281 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cmp/vcond-1.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cmp/vcond-1.c
@@ -141,6 +141,34 @@ 
 TEST_VAR_ALL (DEF_VCOND_VAR)
 TEST_IMM_ALL (DEF_VCOND_IMM)
 
+#define TEST_COND_IMM_FLOAT(T, COND, IMM, SUFFIX)			\
+  T (float, float, COND, IMM, SUFFIX##_float_float)			\
+  T (double, double, COND, IMM, SUFFIX##_double_double)
+
+#define TEST_IMM_FLOAT_ALL(T)						\
+  TEST_COND_IMM_FLOAT (T, >, 0.0, _gt)					\
+  TEST_COND_IMM_FLOAT (T, <, 0.0, _lt)					\
+  TEST_COND_IMM_FLOAT (T, >=, 0.0, _ge)					\
+  TEST_COND_IMM_FLOAT (T, <=, 0.0, _le)					\
+  TEST_COND_IMM_FLOAT (T, ==, 0.0, _eq)					\
+  TEST_COND_IMM_FLOAT (T, !=, 0.0, _ne)					\
+									\
+  TEST_COND_IMM_FLOAT (T, >, 1.0, _gt1)					\
+  TEST_COND_IMM_FLOAT (T, <, 1.0, _lt1)					\
+  TEST_COND_IMM_FLOAT (T, >=, 1.0, _ge1)				\
+  TEST_COND_IMM_FLOAT (T, <=, 1.0, _le1)				\
+  TEST_COND_IMM_FLOAT (T, ==, 1.0, _eq1)				\
+  TEST_COND_IMM_FLOAT (T, !=, 1.0, _ne1)				\
+									\
+  TEST_COND_IMM_FLOAT (T, >, -1.0, _gt2)				\
+  TEST_COND_IMM_FLOAT (T, <, -1.0, _lt2)				\
+  TEST_COND_IMM_FLOAT (T, >=, -1.0, _ge2)				\
+  TEST_COND_IMM_FLOAT (T, <=, -1.0, _le2)				\
+  TEST_COND_IMM_FLOAT (T, ==, -1.0, _eq2)				\
+  TEST_COND_IMM_FLOAT (T, !=, -1.0, _ne2)
+
+TEST_IMM_FLOAT_ALL (DEF_VCOND_IMM)
+
 /* { dg-final { scan-assembler-times {\tvmseq\.vi} 42 } } */
 /* { dg-final { scan-assembler-times {\tvmsne\.vi} 42 } } */
 /* { dg-final { scan-assembler-times {\tvmsgt\.vi} 30 } } */
@@ -152,6 +180,22 @@  TEST_IMM_ALL (DEF_VCOND_IMM)
 /* { dg-final { scan-assembler-times {\tvmseq} 78 } } */
 /* { dg-final { scan-assembler-times {\tvmsne} 78 } } */
 /* { dg-final { scan-assembler-times {\tvmsgt} 82 } } */
-/* { dg-final { scan-assembler-times {\tvmslt} 38 } } */
-/* { dg-final { scan-assembler-times {\tvmsge} 38 } } */
+/* { dg-final { scan-assembler-times {\tvmslt} 56 } } */
+/* { dg-final { scan-assembler-times {\tvmsge} 20 } } */
 /* { dg-final { scan-assembler-times {\tvmsle} 82 } } */
+/* { dg-final { scan-assembler-times {\tvmseq\.vx} 24 } } */
+/* { dg-final { scan-assembler-times {\tvmsne\.vx} 24 } } */
+/* { dg-final { scan-assembler-times {\tvmsgt\.vx} 6 } } */
+/* { dg-final { scan-assembler-times {\tvmsgtu\.vx} 22 } } */
+/* { dg-final { scan-assembler-times {\tvmslt\.vx} 36 } } */
+/* { dg-final { scan-assembler-times {\tvmsltu\.vx} 0 } } */
+/* { dg-final { scan-assembler-times {\tvmsge\.vx} 0 } } */
+/* { dg-final { scan-assembler-times {\tvmsgeu\.vx} 0 } } */
+/* { dg-final { scan-assembler-times {\tvmsle\.vx} 6 } } */
+/* { dg-final { scan-assembler-times {\tvmsleu\.vx} 22 } } */
+/* { dg-final { scan-assembler-times {\tvmfgt.vf} 6 } } */
+/* { dg-final { scan-assembler-times {\tvmflt.vf} 6 } } */
+/* { dg-final { scan-assembler-times {\tvmfge.vf} 6 } } */
+/* { dg-final { scan-assembler-times {\tvmfle.vf} 6 } } */
+/* { dg-final { scan-assembler-times {\tvmfeq.vf} 6 } } */
+/* { dg-final { scan-assembler-times {\tvmfne.vf} 6 } } */