diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index 1da498a3152..f7f793cc326 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -1213,6 +1213,34 @@ wide_int_binop (wide_int &res,
   return true;
 }
 
+/* Returns true if we know who is smaller or equal, ARG1 or ARG2., and set the
+   min value to RES.  */
+bool
+can_min_p (const_tree arg1, const_tree arg2, poly_wide_int &res)
+{
+  if (tree_fits_poly_int64_p (arg1) && tree_fits_poly_int64_p (arg2))
+    {
+      if (known_le (tree_to_poly_int64 (arg1), tree_to_poly_int64 (arg2)))
+	res = wi::to_poly_wide (arg1);
+      else if (known_le (tree_to_poly_int64 (arg2), tree_to_poly_int64 (arg1)))
+	res = wi::to_poly_wide (arg2);
+      else
+	return false;
+    }
+  else if (tree_fits_poly_uint64_p (arg1) && tree_fits_poly_uint64_p (arg2))
+    {
+      if (known_le (tree_to_poly_uint64 (arg1), tree_to_poly_uint64 (arg2)))
+	res = wi::to_poly_wide (arg1);
+      else if (known_le (tree_to_poly_int64 (arg2), tree_to_poly_int64 (arg1)))
+	res = wi::to_poly_wide (arg2);
+      else
+	return false;
+    }
+  else
+    return false;
+  return true;
+}
+
 /* Combine two poly int's ARG1 and ARG2 under operation CODE to
    produce a new constant in RES.  Return FALSE if we don't know how
    to evaluate CODE at compile-time.  */
@@ -1261,6 +1289,11 @@ poly_int_binop (poly_wide_int &res, enum tree_code code,
 	return false;
       break;
 
+    case MIN_EXPR:
+      if (!can_min_p (arg1, arg2, res))
+	return false;
+      break;
+
     default:
       return false;
     }
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/fold-min-poly.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/fold-min-poly.c
new file mode 100644
index 00000000000..de4c472c76e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/fold-min-poly.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options " -march=rv64gcv_zvl128b -mabi=lp64d -O3 --param riscv-autovec-preference=scalable --param riscv-autovec-lmul=m1 -fno-vect-cost-model" } */
+
+void foo1 (int* restrict a, int* restrict b, int n)
+{
+    for (int i = 0; i < 4; i += 1)
+      a[i] += b[i];
+}
+
+void foo2 (int* restrict a, int* restrict b, int n)
+{
+    for (int i = 0; i < 3; i += 1)
+      a[i] += b[i];
+}
+
+void foo3 (int* restrict a, int* restrict b, int n)
+{
+    for (int i = 0; i < 5; i += 1)
+      a[i] += b[i];
+}
+
+/* { dg-final { scan-assembler-not {\tcsrr\t} } } */
+/* { dg-final { scan-assembler {\tvsetivli\tzero,4,e32,m1,t[au],m[au]} } } */
+/* { dg-final { scan-assembler {\tvsetivli\tzero,3,e32,m1,t[au],m[au]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/div-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/div-1.c
index f3388a86e38..40224c69458 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/div-1.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/div-1.c
@@ -55,4 +55,4 @@ DEF_OP_VV (div, 512, int64_t, /)
 
 /* { dg-final { scan-assembler-times {vdivu?\.vv\s+v[0-9]+,\s*v[0-9]+,\s*v[0-9]+} 42 } } */
 /* TODO: Ideally, we should make sure there is no "csrr vlenb". However, we still have 'csrr vlenb' for some cases since we don't support VLS mode conversion which are needed by division.  */
-/* { dg-final { scan-assembler-times {csrr} 19 } } */
+/* { dg-final { scan-assembler-not {csrr} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/shift-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/shift-3.c
index 98822b15657..b34a349949b 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/shift-3.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/shift-3.c
@@ -55,4 +55,4 @@ DEF_OP_VV (shift, 512, int64_t, <<)
 
 /* { dg-final { scan-assembler-times {vsll\.vv\s+v[0-9]+,\s*v[0-9]+,\s*v[0-9]+} 41 } } */
 /* TODO: Ideally, we should make sure there is no "csrr vlenb". However, we still have 'csrr vlenb' for some cases since we don't support VLS mode conversion which are needed by division.  */
-/* { dg-final { scan-assembler-times {csrr} 18 } } */
+/* { dg-final { scan-assembler-not {csrr} } } */
