Index: gcc/gcc/config/riscv/riscv.md
===================================================================
--- gcc.orig/gcc/config/riscv/riscv.md
+++ gcc/gcc/config/riscv/riscv.md
@@ -42,6 +42,8 @@
   UNSPEC_COPYSIGN
   UNSPEC_LRINT
   UNSPEC_LROUND
+  UNSPEC_FMIN
+  UNSPEC_FMAX
 
   ;; Stack tie
   UNSPEC_TIE
@@ -1216,6 +1218,26 @@
 ;;
 ;;  ....................
 
+(define_insn "fmin<mode>3"
+  [(set (match_operand:ANYF                    0 "register_operand" "=f")
+	(unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" " f"))
+		      (use (match_operand:ANYF 2 "register_operand" " f"))]
+		     UNSPEC_FMIN))]
+  "TARGET_HARD_FLOAT && !HONOR_SNANS (<MODE>mode)"
+  "fmin.<fmt>\t%0,%1,%2"
+  [(set_attr "type" "fmove")
+   (set_attr "mode" "<UNITMODE>")])
+
+(define_insn "fmax<mode>3"
+  [(set (match_operand:ANYF                    0 "register_operand" "=f")
+	(unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" " f"))
+		      (use (match_operand:ANYF 2 "register_operand" " f"))]
+		     UNSPEC_FMAX))]
+  "TARGET_HARD_FLOAT && !HONOR_SNANS (<MODE>mode)"
+  "fmax.<fmt>\t%0,%1,%2"
+  [(set_attr "type" "fmove")
+   (set_attr "mode" "<UNITMODE>")])
+
 (define_insn "smin<mode>3"
   [(set (match_operand:ANYF            0 "register_operand" "=f")
 	(smin:ANYF (match_operand:ANYF 1 "register_operand" " f")
Index: gcc/gcc/testsuite/gcc.target/riscv/fmax-snan.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.target/riscv/fmax-snan.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-finite-math-only -fsigned-zeros -fsignaling-nans -dp" } */
+
+double
+fmax (double x, double y)
+{
+  return __builtin_fmax (x, y);
+}
+
+/* { dg-final { scan-assembler-not "\tfmax\\.d\t" } } */
+/* { dg-final { scan-assembler-not "\tfge\\.d\t" } } */
+/* { dg-final { scan-assembler "\t(call|tail)\tfmax\t" } } */
Index: gcc/gcc/testsuite/gcc.target/riscv/fmax.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.target/riscv/fmax.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-finite-math-only -fsigned-zeros -fno-signaling-nans -dp" } */
+
+double
+fmax (double x, double y)
+{
+  return __builtin_fmax (x, y);
+}
+
+/* { dg-final { scan-assembler-not "\ttail\tfmax\t" } } */
+/* { dg-final { scan-assembler-not "\tfge\\.d\t" } } */
+/* { dg-final { scan-assembler "\tfmax\\.d\t\[^\n\]* fmaxdf3\n" } } */
Index: gcc/gcc/testsuite/gcc.target/riscv/fmaxf-snan.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.target/riscv/fmaxf-snan.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-finite-math-only -fsigned-zeros -fsignaling-nans -dp" } */
+
+float
+fmaxf (float x, float y)
+{
+  return __builtin_fmaxf (x, y);
+}
+
+/* { dg-final { scan-assembler-not "\tfmax\\.s\t" } } */
+/* { dg-final { scan-assembler-not "\tfge\\.s\t" } } */
+/* { dg-final { scan-assembler "\t(call|tail)\tfmaxf\t" } } */
Index: gcc/gcc/testsuite/gcc.target/riscv/fmaxf.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.target/riscv/fmaxf.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-finite-math-only -fsigned-zeros -fno-signaling-nans -dp" } */
+
+float
+fmaxf (float x, float y)
+{
+  return __builtin_fmaxf (x, y);
+}
+
+/* { dg-final { scan-assembler-not "\ttail\tfmaxf\t" } } */
+/* { dg-final { scan-assembler-not "\tfge\\.s\t" } } */
+/* { dg-final { scan-assembler "\tfmax\\.s\t\[^\n\]* fmaxsf3\n" } } */
Index: gcc/gcc/testsuite/gcc.target/riscv/fmin-snan.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.target/riscv/fmin-snan.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-finite-math-only -fsigned-zeros -fsignaling-nans -dp" } */
+
+double
+fmin (double x, double y)
+{
+  return __builtin_fmin (x, y);
+}
+
+/* { dg-final { scan-assembler-not "\tfmin\\.d\t" } } */
+/* { dg-final { scan-assembler-not "\tfle\\.d\t" } } */
+/* { dg-final { scan-assembler "\t(call|tail)\tfmin\t" } } */
Index: gcc/gcc/testsuite/gcc.target/riscv/fmin.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.target/riscv/fmin.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-finite-math-only -fsigned-zeros -fno-signaling-nans -dp" } */
+
+double
+fmin (double x, double y)
+{
+  return __builtin_fmin (x, y);
+}
+
+/* { dg-final { scan-assembler-not "\ttail\tfmin\t" } } */
+/* { dg-final { scan-assembler-not "\tfle\\.d\t" } } */
+/* { dg-final { scan-assembler "\tfmin\\.d\t\[^\n\]* fmindf3\n" } } */
Index: gcc/gcc/testsuite/gcc.target/riscv/fminf-snan.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.target/riscv/fminf-snan.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-finite-math-only -fsigned-zeros -fsignaling-nans -dp" } */
+
+float
+fminf (float x, float y)
+{
+  return __builtin_fminf (x, y);
+}
+
+/* { dg-final { scan-assembler-not "\tfmin\\.s\t" } } */
+/* { dg-final { scan-assembler-not "\tfle\\.s\t" } } */
+/* { dg-final { scan-assembler "\t(call|tail)\tfminf\t" } } */
Index: gcc/gcc/testsuite/gcc.target/riscv/fminf.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.target/riscv/fminf.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-finite-math-only -fsigned-zeros -fno-signaling-nans -dp" } */
+
+float
+fminf (float x, float y)
+{
+  return __builtin_fminf (x, y);
+}
+
+/* { dg-final { scan-assembler-not "\ttail\tfminf\t" } } */
+/* { dg-final { scan-assembler-not "\tfle\\.s\t" } } */
+/* { dg-final { scan-assembler "\tfmin\\.s\t\[^\n\]* fminsf3\n" } } */
Index: gcc/gcc/testsuite/gcc.target/riscv/smax-ieee.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.target/riscv/smax-ieee.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-ffinite-math-only -fsigned-zeros -dp" } */
+
+double
+smax (double x, double y)
+{
+  return x >= y ? x : y;
+}
+
+/* { dg-final { scan-assembler-not "\t(call|tail)\tfmax\t" } } */
+/* { dg-final { scan-assembler-not "\tfmax\\.d\t" } } */
+/* { dg-final { scan-assembler "\tfge\\.d\t" } } */
Index: gcc/gcc/testsuite/gcc.target/riscv/smax.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.target/riscv/smax.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-ffinite-math-only -fno-signed-zeros -dp" } */
+
+double
+smax (double x, double y)
+{
+  return x >= y ? x : y;
+}
+
+/* { dg-final { scan-assembler-not "\ttail\tfmax\t" } } */
+/* { dg-final { scan-assembler-not "\tfge\\.d\t" } } */
+/* { dg-final { scan-assembler "\tfmax\\.d\t\[^\n\]* smaxdf3\n" } } */
Index: gcc/gcc/testsuite/gcc.target/riscv/smaxf-ieee.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.target/riscv/smaxf-ieee.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-ffinite-math-only -fsigned-zeros -dp" } */
+
+float
+smaxf (float x, float y)
+{
+  return x >= y ? x : y;
+}
+
+/* { dg-final { scan-assembler-not "\t(call|tail)\tfmaxf\t" } } */
+/* { dg-final { scan-assembler-not "\tfmax\\.s\t" } } */
+/* { dg-final { scan-assembler "\tfge\\.s\t" } } */
Index: gcc/gcc/testsuite/gcc.target/riscv/smaxf.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.target/riscv/smaxf.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-ffinite-math-only -fno-signed-zeros -dp" } */
+
+float
+smaxf (float x, float y)
+{
+  return x >= y ? x : y;
+}
+
+/* { dg-final { scan-assembler-not "\ttail\tfmaxf\t" } } */
+/* { dg-final { scan-assembler-not "\tfge\\.s\t" } } */
+/* { dg-final { scan-assembler "\tfmax\\.s\t\[^\n\]* smaxsf3\n" } } */
Index: gcc/gcc/testsuite/gcc.target/riscv/smin-ieee.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.target/riscv/smin-ieee.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-ffinite-math-only -fsigned-zeros -dp" } */
+
+double
+smin (double x, double y)
+{
+  return x <= y ? x : y;
+}
+
+/* { dg-final { scan-assembler-not "\t(call|tail)\tfmin\t" } } */
+/* { dg-final { scan-assembler-not "\tfmin\\.d\t" } } */
+/* { dg-final { scan-assembler "\tfle\\.d\t" } } */
Index: gcc/gcc/testsuite/gcc.target/riscv/smin.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.target/riscv/smin.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-ffinite-math-only -fno-signed-zeros -dp" } */
+
+double
+smin (double x, double y)
+{
+  return x <= y ? x : y;
+}
+
+/* { dg-final { scan-assembler-not "\ttail\tfmin\t" } } */
+/* { dg-final { scan-assembler-not "\tfle\\.d\t" } } */
+/* { dg-final { scan-assembler "\tfmin\\.d\t\[^\n\]* smindf3\n" } } */
Index: gcc/gcc/testsuite/gcc.target/riscv/sminf-ieee.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.target/riscv/sminf-ieee.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-ffinite-math-only -fsigned-zeros -dp" } */
+
+float
+sminf (float x, float y)
+{
+  return x <= y ? x : y;
+}
+
+/* { dg-final { scan-assembler-not "\t(call|tail)\tfminf\t" } } */
+/* { dg-final { scan-assembler-not "\tfmin\\.s\t" } } */
+/* { dg-final { scan-assembler "\tfle\\.s\t" } } */
Index: gcc/gcc/testsuite/gcc.target/riscv/sminf.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.target/riscv/sminf.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-ffinite-math-only -fno-signed-zeros -dp" } */
+
+float
+sminf (float x, float y)
+{
+  return x <= y ? x : y;
+}
+
+/* { dg-final { scan-assembler-not "\ttail\tfminf\t" } } */
+/* { dg-final { scan-assembler-not "\tfle\\.s\t" } } */
+/* { dg-final { scan-assembler "\tfmin\\.s\t\[^\n\]* sminsf3\n" } } */
