[llvm] 048458f - [RISCV] Add no NaN support to lowerFMAXIMUM_FMINIMUM.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 1 09:51:30 PDT 2023


Author: Craig Topper
Date: 2023-08-01T09:51:24-07:00
New Revision: 048458f94c60fc9c200c9dcbcccd4a54ed84b8f9

URL: https://github.com/llvm/llvm-project/commit/048458f94c60fc9c200c9dcbcccd4a54ed84b8f9
DIFF: https://github.com/llvm/llvm-project/commit/048458f94c60fc9c200c9dcbcccd4a54ed84b8f9.diff

LOG: [RISCV] Add no NaN support to lowerFMAXIMUM_FMINIMUM.

Using the nonans FMF and the DAG.isKnownNeverNaN on the inputs.

Reviewed By: fakepaper56

Differential Revision: https://reviews.llvm.org/D156748

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVISelLowering.cpp
    llvm/test/CodeGen/RISCV/double-maximum-minimum.ll
    llvm/test/CodeGen/RISCV/float-maximum-minimum.ll
    llvm/test/CodeGen/RISCV/half-maximum-minimum.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 34932c5df2200b..f5f72b36afa372 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -4670,12 +4670,18 @@ static SDValue lowerFMAXIMUM_FMINIMUM(SDValue Op, SelectionDAG &DAG,
   // ensures that when one input is a nan, the other will also be a nan allowing
   // the nan to propagate. If both inputs are nan, this will swap the inputs
   // which is harmless.
-  // FIXME: Handle nonans FMF and use isKnownNeverNaN.
-  SDValue XIsNonNan = DAG.getSetCC(DL, XLenVT, X, X, ISD::SETOEQ);
-  SDValue NewY = DAG.getSelect(DL, VT, XIsNonNan, Y, X);
 
-  SDValue YIsNonNan = DAG.getSetCC(DL, XLenVT, Y, Y, ISD::SETOEQ);
-  SDValue NewX = DAG.getSelect(DL, VT, YIsNonNan, X, Y);
+  SDValue NewY = Y;;
+  if (!Op->getFlags().hasNoNaNs() && !DAG.isKnownNeverNaN(X)) {
+    SDValue XIsNonNan = DAG.getSetCC(DL, XLenVT, X, X, ISD::SETOEQ);
+    NewY = DAG.getSelect(DL, VT, XIsNonNan, Y, X);
+  }
+
+  SDValue NewX = X;
+  if (!Op->getFlags().hasNoNaNs() && !DAG.isKnownNeverNaN(Y)) {
+    SDValue YIsNonNan = DAG.getSetCC(DL, XLenVT, Y, Y, ISD::SETOEQ);
+    NewX = DAG.getSelect(DL, VT, YIsNonNan, X, Y);
+  }
 
   unsigned Opc =
       Op.getOpcode() == ISD::FMAXIMUM ? RISCVISD::FMAX : RISCVISD::FMIN;

diff  --git a/llvm/test/CodeGen/RISCV/double-maximum-minimum.ll b/llvm/test/CodeGen/RISCV/double-maximum-minimum.ll
index 873f2c068f636f..45a31ab709922c 100644
--- a/llvm/test/CodeGen/RISCV/double-maximum-minimum.ll
+++ b/llvm/test/CodeGen/RISCV/double-maximum-minimum.ll
@@ -159,6 +159,209 @@ define double @fmaximum_f64(double %a, double %b) nounwind {
   %1 = call double @llvm.maximum.f64(double %a, double %b)
   ret double %1
 }
+
+define double @fminimum_nnan_f64(double %a, double %b) nounwind {
+; CHECKIFD-LABEL: fminimum_nnan_f64:
+; CHECKIFD:       # %bb.0:
+; CHECKIFD-NEXT:    fmin.d fa0, fa0, fa1
+; CHECKIFD-NEXT:    ret
+;
+; RV32IZFINXZDINX-LABEL: fminimum_nnan_f64:
+; RV32IZFINXZDINX:       # %bb.0:
+; RV32IZFINXZDINX-NEXT:    addi sp, sp, -16
+; RV32IZFINXZDINX-NEXT:    sw a2, 8(sp)
+; RV32IZFINXZDINX-NEXT:    sw a3, 12(sp)
+; RV32IZFINXZDINX-NEXT:    lw a2, 8(sp)
+; RV32IZFINXZDINX-NEXT:    lw a3, 12(sp)
+; RV32IZFINXZDINX-NEXT:    sw a0, 8(sp)
+; RV32IZFINXZDINX-NEXT:    sw a1, 12(sp)
+; RV32IZFINXZDINX-NEXT:    lw a0, 8(sp)
+; RV32IZFINXZDINX-NEXT:    lw a1, 12(sp)
+; RV32IZFINXZDINX-NEXT:    fmin.d a0, a0, a2
+; RV32IZFINXZDINX-NEXT:    sw a0, 8(sp)
+; RV32IZFINXZDINX-NEXT:    sw a1, 12(sp)
+; RV32IZFINXZDINX-NEXT:    lw a0, 8(sp)
+; RV32IZFINXZDINX-NEXT:    lw a1, 12(sp)
+; RV32IZFINXZDINX-NEXT:    addi sp, sp, 16
+; RV32IZFINXZDINX-NEXT:    ret
+;
+; RV64IZFINXZDINX-LABEL: fminimum_nnan_f64:
+; RV64IZFINXZDINX:       # %bb.0:
+; RV64IZFINXZDINX-NEXT:    fmin.d a0, a0, a1
+; RV64IZFINXZDINX-NEXT:    ret
+  %1 = call nnan double @llvm.minimum.f64(double %a, double %b)
+  ret double %1
+}
+
+define double @fmaximum_nnan_f64(double %a, double %b) nounwind {
+; CHECKIFD-LABEL: fmaximum_nnan_f64:
+; CHECKIFD:       # %bb.0:
+; CHECKIFD-NEXT:    feq.d a0, fa0, fa0
+; CHECKIFD-NEXT:    fmv.d fa5, fa1
+; CHECKIFD-NEXT:    beqz a0, .LBB3_3
+; CHECKIFD-NEXT:  # %bb.1:
+; CHECKIFD-NEXT:    feq.d a0, fa1, fa1
+; CHECKIFD-NEXT:    beqz a0, .LBB3_4
+; CHECKIFD-NEXT:  .LBB3_2:
+; CHECKIFD-NEXT:    fmin.d fa0, fa0, fa5
+; CHECKIFD-NEXT:    ret
+; CHECKIFD-NEXT:  .LBB3_3:
+; CHECKIFD-NEXT:    fmv.d fa5, fa0
+; CHECKIFD-NEXT:    feq.d a0, fa1, fa1
+; CHECKIFD-NEXT:    bnez a0, .LBB3_2
+; CHECKIFD-NEXT:  .LBB3_4:
+; CHECKIFD-NEXT:    fmin.d fa0, fa1, fa5
+; CHECKIFD-NEXT:    ret
+;
+; RV32IZFINXZDINX-LABEL: fmaximum_nnan_f64:
+; RV32IZFINXZDINX:       # %bb.0:
+; RV32IZFINXZDINX-NEXT:    addi sp, sp, -16
+; RV32IZFINXZDINX-NEXT:    sw a2, 8(sp)
+; RV32IZFINXZDINX-NEXT:    sw a3, 12(sp)
+; RV32IZFINXZDINX-NEXT:    lw a2, 8(sp)
+; RV32IZFINXZDINX-NEXT:    lw a3, 12(sp)
+; RV32IZFINXZDINX-NEXT:    sw a0, 8(sp)
+; RV32IZFINXZDINX-NEXT:    sw a1, 12(sp)
+; RV32IZFINXZDINX-NEXT:    lw a0, 8(sp)
+; RV32IZFINXZDINX-NEXT:    lw a1, 12(sp)
+; RV32IZFINXZDINX-NEXT:    feq.d a6, a0, a0
+; RV32IZFINXZDINX-NEXT:    mv a4, a2
+; RV32IZFINXZDINX-NEXT:    bnez a6, .LBB3_2
+; RV32IZFINXZDINX-NEXT:  # %bb.1:
+; RV32IZFINXZDINX-NEXT:    mv a4, a0
+; RV32IZFINXZDINX-NEXT:  .LBB3_2:
+; RV32IZFINXZDINX-NEXT:    feq.d a6, a2, a2
+; RV32IZFINXZDINX-NEXT:    bnez a6, .LBB3_4
+; RV32IZFINXZDINX-NEXT:  # %bb.3:
+; RV32IZFINXZDINX-NEXT:    mv a0, a2
+; RV32IZFINXZDINX-NEXT:  .LBB3_4:
+; RV32IZFINXZDINX-NEXT:    fmin.d a0, a0, a4
+; RV32IZFINXZDINX-NEXT:    sw a0, 8(sp)
+; RV32IZFINXZDINX-NEXT:    sw a1, 12(sp)
+; RV32IZFINXZDINX-NEXT:    lw a0, 8(sp)
+; RV32IZFINXZDINX-NEXT:    lw a1, 12(sp)
+; RV32IZFINXZDINX-NEXT:    addi sp, sp, 16
+; RV32IZFINXZDINX-NEXT:    ret
+;
+; RV64IZFINXZDINX-LABEL: fmaximum_nnan_f64:
+; RV64IZFINXZDINX:       # %bb.0:
+; RV64IZFINXZDINX-NEXT:    feq.d a3, a0, a0
+; RV64IZFINXZDINX-NEXT:    mv a2, a1
+; RV64IZFINXZDINX-NEXT:    beqz a3, .LBB3_3
+; RV64IZFINXZDINX-NEXT:  # %bb.1:
+; RV64IZFINXZDINX-NEXT:    feq.d a3, a1, a1
+; RV64IZFINXZDINX-NEXT:    beqz a3, .LBB3_4
+; RV64IZFINXZDINX-NEXT:  .LBB3_2:
+; RV64IZFINXZDINX-NEXT:    fmin.d a0, a0, a2
+; RV64IZFINXZDINX-NEXT:    ret
+; RV64IZFINXZDINX-NEXT:  .LBB3_3:
+; RV64IZFINXZDINX-NEXT:    mv a2, a0
+; RV64IZFINXZDINX-NEXT:    feq.d a3, a1, a1
+; RV64IZFINXZDINX-NEXT:    bnez a3, .LBB3_2
+; RV64IZFINXZDINX-NEXT:  .LBB3_4:
+; RV64IZFINXZDINX-NEXT:    fmin.d a0, a1, a2
+; RV64IZFINXZDINX-NEXT:    ret
+  %1 = call double @llvm.minimum.f64(double %a, double %b)
+  ret double %1
+}
+
+define double @fminimum_nnan_op_f64(double %a, double %b) nounwind {
+; CHECKIFD-LABEL: fminimum_nnan_op_f64:
+; CHECKIFD:       # %bb.0:
+; CHECKIFD-NEXT:    feq.d a0, fa1, fa1
+; CHECKIFD-NEXT:    bnez a0, .LBB4_2
+; CHECKIFD-NEXT:  # %bb.1:
+; CHECKIFD-NEXT:    fmin.d fa0, fa1, fa1
+; CHECKIFD-NEXT:    ret
+; CHECKIFD-NEXT:  .LBB4_2:
+; CHECKIFD-NEXT:    fadd.d fa5, fa0, fa0
+; CHECKIFD-NEXT:    fmin.d fa0, fa5, fa1
+; CHECKIFD-NEXT:    ret
+;
+; RV32IZFINXZDINX-LABEL: fminimum_nnan_op_f64:
+; RV32IZFINXZDINX:       # %bb.0:
+; RV32IZFINXZDINX-NEXT:    addi sp, sp, -16
+; RV32IZFINXZDINX-NEXT:    sw a2, 8(sp)
+; RV32IZFINXZDINX-NEXT:    sw a3, 12(sp)
+; RV32IZFINXZDINX-NEXT:    lw a2, 8(sp)
+; RV32IZFINXZDINX-NEXT:    lw a3, 12(sp)
+; RV32IZFINXZDINX-NEXT:    sw a0, 8(sp)
+; RV32IZFINXZDINX-NEXT:    feq.d a0, a2, a2
+; RV32IZFINXZDINX-NEXT:    sw a1, 12(sp)
+; RV32IZFINXZDINX-NEXT:    bnez a0, .LBB4_2
+; RV32IZFINXZDINX-NEXT:  # %bb.1:
+; RV32IZFINXZDINX-NEXT:    mv a0, a2
+; RV32IZFINXZDINX-NEXT:    j .LBB4_3
+; RV32IZFINXZDINX-NEXT:  .LBB4_2:
+; RV32IZFINXZDINX-NEXT:    lw a0, 8(sp)
+; RV32IZFINXZDINX-NEXT:    lw a1, 12(sp)
+; RV32IZFINXZDINX-NEXT:    fadd.d a0, a0, a0
+; RV32IZFINXZDINX-NEXT:  .LBB4_3:
+; RV32IZFINXZDINX-NEXT:    fmin.d a0, a0, a2
+; RV32IZFINXZDINX-NEXT:    sw a0, 8(sp)
+; RV32IZFINXZDINX-NEXT:    sw a1, 12(sp)
+; RV32IZFINXZDINX-NEXT:    lw a0, 8(sp)
+; RV32IZFINXZDINX-NEXT:    lw a1, 12(sp)
+; RV32IZFINXZDINX-NEXT:    addi sp, sp, 16
+; RV32IZFINXZDINX-NEXT:    ret
+;
+; RV64IZFINXZDINX-LABEL: fminimum_nnan_op_f64:
+; RV64IZFINXZDINX:       # %bb.0:
+; RV64IZFINXZDINX-NEXT:    feq.d a2, a1, a1
+; RV64IZFINXZDINX-NEXT:    bnez a2, .LBB4_2
+; RV64IZFINXZDINX-NEXT:  # %bb.1:
+; RV64IZFINXZDINX-NEXT:    fmin.d a0, a1, a1
+; RV64IZFINXZDINX-NEXT:    ret
+; RV64IZFINXZDINX-NEXT:  .LBB4_2:
+; RV64IZFINXZDINX-NEXT:    fadd.d a0, a0, a0
+; RV64IZFINXZDINX-NEXT:    fmin.d a0, a0, a1
+; RV64IZFINXZDINX-NEXT:    ret
+  %c = fadd nnan double %a, %a
+  %1 = call double @llvm.minimum.f64(double %c, double %b)
+  ret double %1
+}
+
+define double @fmaximum_nnan_op_f64(double %a, double %b) nounwind {
+; CHECKIFD-LABEL: fmaximum_nnan_op_f64:
+; CHECKIFD:       # %bb.0:
+; CHECKIFD-NEXT:    fadd.d fa5, fa0, fa1
+; CHECKIFD-NEXT:    fsub.d fa4, fa0, fa1
+; CHECKIFD-NEXT:    fmax.d fa0, fa5, fa4
+; CHECKIFD-NEXT:    ret
+;
+; RV32IZFINXZDINX-LABEL: fmaximum_nnan_op_f64:
+; RV32IZFINXZDINX:       # %bb.0:
+; RV32IZFINXZDINX-NEXT:    addi sp, sp, -16
+; RV32IZFINXZDINX-NEXT:    sw a2, 8(sp)
+; RV32IZFINXZDINX-NEXT:    sw a3, 12(sp)
+; RV32IZFINXZDINX-NEXT:    lw a2, 8(sp)
+; RV32IZFINXZDINX-NEXT:    lw a3, 12(sp)
+; RV32IZFINXZDINX-NEXT:    sw a0, 8(sp)
+; RV32IZFINXZDINX-NEXT:    sw a1, 12(sp)
+; RV32IZFINXZDINX-NEXT:    lw a0, 8(sp)
+; RV32IZFINXZDINX-NEXT:    lw a1, 12(sp)
+; RV32IZFINXZDINX-NEXT:    fadd.d a4, a0, a2
+; RV32IZFINXZDINX-NEXT:    fsub.d a0, a0, a2
+; RV32IZFINXZDINX-NEXT:    fmax.d a0, a4, a0
+; RV32IZFINXZDINX-NEXT:    sw a0, 8(sp)
+; RV32IZFINXZDINX-NEXT:    sw a1, 12(sp)
+; RV32IZFINXZDINX-NEXT:    lw a0, 8(sp)
+; RV32IZFINXZDINX-NEXT:    lw a1, 12(sp)
+; RV32IZFINXZDINX-NEXT:    addi sp, sp, 16
+; RV32IZFINXZDINX-NEXT:    ret
+;
+; RV64IZFINXZDINX-LABEL: fmaximum_nnan_op_f64:
+; RV64IZFINXZDINX:       # %bb.0:
+; RV64IZFINXZDINX-NEXT:    fadd.d a2, a0, a1
+; RV64IZFINXZDINX-NEXT:    fsub.d a0, a0, a1
+; RV64IZFINXZDINX-NEXT:    fmax.d a0, a2, a0
+; RV64IZFINXZDINX-NEXT:    ret
+  %c = fadd nnan double %a, %b
+  %d = fsub nnan double %a, %b
+  %1 = call double @llvm.maximum.f64(double %c, double %d)
+  ret double %1
+}
+
 ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
 ; RV32IFD: {{.*}}
 ; RV64IFD: {{.*}}

diff  --git a/llvm/test/CodeGen/RISCV/float-maximum-minimum.ll b/llvm/test/CodeGen/RISCV/float-maximum-minimum.ll
index 48a58ea111585a..0e00dff0b64245 100644
--- a/llvm/test/CodeGen/RISCV/float-maximum-minimum.ll
+++ b/llvm/test/CodeGen/RISCV/float-maximum-minimum.ll
@@ -181,3 +181,162 @@ define float @fmaximum_f32(float %a, float %b) nounwind {
   %1 = call float @llvm.maximum.f32(float %a, float %b)
   ret float %1
 }
+
+define float @fminimum_nnan_f32(float %a, float %b) nounwind {
+; RV32IF-LABEL: fminimum_nnan_f32:
+; RV32IF:       # %bb.0:
+; RV32IF-NEXT:    fmin.s fa0, fa0, fa1
+; RV32IF-NEXT:    ret
+;
+; RV32IZFINX-LABEL: fminimum_nnan_f32:
+; RV32IZFINX:       # %bb.0:
+; RV32IZFINX-NEXT:    fmin.s a0, a0, a1
+; RV32IZFINX-NEXT:    ret
+;
+; RV64IF-LABEL: fminimum_nnan_f32:
+; RV64IF:       # %bb.0:
+; RV64IF-NEXT:    fmin.s fa0, fa0, fa1
+; RV64IF-NEXT:    ret
+;
+; RV64IZFINX-LABEL: fminimum_nnan_f32:
+; RV64IZFINX:       # %bb.0:
+; RV64IZFINX-NEXT:    fmin.s a0, a0, a1
+; RV64IZFINX-NEXT:    ret
+  %1 = call nnan float @llvm.minimum.f32(float %a, float %b)
+  ret float %1
+}
+
+define float @fmaximum_nnan_f32(float %a, float %b) nounwind {
+; RV32IF-LABEL: fmaximum_nnan_f32:
+; RV32IF:       # %bb.0:
+; RV32IF-NEXT:    fmax.s fa0, fa0, fa1
+; RV32IF-NEXT:    ret
+;
+; RV32IZFINX-LABEL: fmaximum_nnan_f32:
+; RV32IZFINX:       # %bb.0:
+; RV32IZFINX-NEXT:    fmax.s a0, a0, a1
+; RV32IZFINX-NEXT:    ret
+;
+; RV64IF-LABEL: fmaximum_nnan_f32:
+; RV64IF:       # %bb.0:
+; RV64IF-NEXT:    fmax.s fa0, fa0, fa1
+; RV64IF-NEXT:    ret
+;
+; RV64IZFINX-LABEL: fmaximum_nnan_f32:
+; RV64IZFINX:       # %bb.0:
+; RV64IZFINX-NEXT:    fmax.s a0, a0, a1
+; RV64IZFINX-NEXT:    ret
+  %1 = call nnan float @llvm.maximum.f32(float %a, float %b)
+  ret float %1
+}
+
+define float @fminimum_nnan_attr_f32(float %a, float %b) nounwind "no-nans-fp-math"="true" {
+; RV32IF-LABEL: fminimum_nnan_attr_f32:
+; RV32IF:       # %bb.0:
+; RV32IF-NEXT:    fmin.s fa0, fa0, fa1
+; RV32IF-NEXT:    ret
+;
+; RV32IZFINX-LABEL: fminimum_nnan_attr_f32:
+; RV32IZFINX:       # %bb.0:
+; RV32IZFINX-NEXT:    fmin.s a0, a0, a1
+; RV32IZFINX-NEXT:    ret
+;
+; RV64IF-LABEL: fminimum_nnan_attr_f32:
+; RV64IF:       # %bb.0:
+; RV64IF-NEXT:    fmin.s fa0, fa0, fa1
+; RV64IF-NEXT:    ret
+;
+; RV64IZFINX-LABEL: fminimum_nnan_attr_f32:
+; RV64IZFINX:       # %bb.0:
+; RV64IZFINX-NEXT:    fmin.s a0, a0, a1
+; RV64IZFINX-NEXT:    ret
+  %1 = call float @llvm.minimum.f32(float %a, float %b)
+  ret float %1
+}
+
+define float @fminimum_nnan_op_f32(float %a, float %b) nounwind {
+; RV32IF-LABEL: fminimum_nnan_op_f32:
+; RV32IF:       # %bb.0:
+; RV32IF-NEXT:    feq.s a0, fa0, fa0
+; RV32IF-NEXT:    bnez a0, .LBB5_2
+; RV32IF-NEXT:  # %bb.1:
+; RV32IF-NEXT:    fmin.s fa0, fa0, fa0
+; RV32IF-NEXT:    ret
+; RV32IF-NEXT:  .LBB5_2:
+; RV32IF-NEXT:    fadd.s fa5, fa0, fa0
+; RV32IF-NEXT:    fmin.s fa0, fa0, fa5
+; RV32IF-NEXT:    ret
+;
+; RV32IZFINX-LABEL: fminimum_nnan_op_f32:
+; RV32IZFINX:       # %bb.0:
+; RV32IZFINX-NEXT:    feq.s a1, a0, a0
+; RV32IZFINX-NEXT:    bnez a1, .LBB5_2
+; RV32IZFINX-NEXT:  # %bb.1:
+; RV32IZFINX-NEXT:    fmin.s a0, a0, a0
+; RV32IZFINX-NEXT:    ret
+; RV32IZFINX-NEXT:  .LBB5_2:
+; RV32IZFINX-NEXT:    fadd.s a1, a0, a0
+; RV32IZFINX-NEXT:    fmin.s a0, a0, a1
+; RV32IZFINX-NEXT:    ret
+;
+; RV64IF-LABEL: fminimum_nnan_op_f32:
+; RV64IF:       # %bb.0:
+; RV64IF-NEXT:    feq.s a0, fa0, fa0
+; RV64IF-NEXT:    bnez a0, .LBB5_2
+; RV64IF-NEXT:  # %bb.1:
+; RV64IF-NEXT:    fmin.s fa0, fa0, fa0
+; RV64IF-NEXT:    ret
+; RV64IF-NEXT:  .LBB5_2:
+; RV64IF-NEXT:    fadd.s fa5, fa0, fa0
+; RV64IF-NEXT:    fmin.s fa0, fa0, fa5
+; RV64IF-NEXT:    ret
+;
+; RV64IZFINX-LABEL: fminimum_nnan_op_f32:
+; RV64IZFINX:       # %bb.0:
+; RV64IZFINX-NEXT:    feq.s a1, a0, a0
+; RV64IZFINX-NEXT:    bnez a1, .LBB5_2
+; RV64IZFINX-NEXT:  # %bb.1:
+; RV64IZFINX-NEXT:    fmin.s a0, a0, a0
+; RV64IZFINX-NEXT:    ret
+; RV64IZFINX-NEXT:  .LBB5_2:
+; RV64IZFINX-NEXT:    fadd.s a1, a0, a0
+; RV64IZFINX-NEXT:    fmin.s a0, a0, a1
+; RV64IZFINX-NEXT:    ret
+  %c = fadd nnan float %a, %a
+  %1 = call float @llvm.minimum.f32(float %a, float %c)
+  ret float %1
+}
+
+define float @fmaximum_nnan_op_f32(float %a, float %b) nounwind {
+; RV32IF-LABEL: fmaximum_nnan_op_f32:
+; RV32IF:       # %bb.0:
+; RV32IF-NEXT:    fadd.s fa5, fa0, fa1
+; RV32IF-NEXT:    fsub.s fa4, fa0, fa1
+; RV32IF-NEXT:    fmax.s fa0, fa5, fa4
+; RV32IF-NEXT:    ret
+;
+; RV32IZFINX-LABEL: fmaximum_nnan_op_f32:
+; RV32IZFINX:       # %bb.0:
+; RV32IZFINX-NEXT:    fadd.s a2, a0, a1
+; RV32IZFINX-NEXT:    fsub.s a0, a0, a1
+; RV32IZFINX-NEXT:    fmax.s a0, a2, a0
+; RV32IZFINX-NEXT:    ret
+;
+; RV64IF-LABEL: fmaximum_nnan_op_f32:
+; RV64IF:       # %bb.0:
+; RV64IF-NEXT:    fadd.s fa5, fa0, fa1
+; RV64IF-NEXT:    fsub.s fa4, fa0, fa1
+; RV64IF-NEXT:    fmax.s fa0, fa5, fa4
+; RV64IF-NEXT:    ret
+;
+; RV64IZFINX-LABEL: fmaximum_nnan_op_f32:
+; RV64IZFINX:       # %bb.0:
+; RV64IZFINX-NEXT:    fadd.s a2, a0, a1
+; RV64IZFINX-NEXT:    fsub.s a0, a0, a1
+; RV64IZFINX-NEXT:    fmax.s a0, a2, a0
+; RV64IZFINX-NEXT:    ret
+  %c = fadd nnan float %a, %b
+  %d = fsub nnan float %a, %b
+  %1 = call float @llvm.maximum.f32(float %c, float %d)
+  ret float %1
+}

diff  --git a/llvm/test/CodeGen/RISCV/half-maximum-minimum.ll b/llvm/test/CodeGen/RISCV/half-maximum-minimum.ll
index 267a2083c80f6a..bc3f44363fb955 100644
--- a/llvm/test/CodeGen/RISCV/half-maximum-minimum.ll
+++ b/llvm/test/CodeGen/RISCV/half-maximum-minimum.ll
@@ -99,3 +99,94 @@ define half @fmaximum_f16(half %a, half %b) nounwind {
   %1 = call half @llvm.maximum.f16(half %a, half %b)
   ret half %1
 }
+
+define half @fminimum_nnan_f16(half %a, half %b) nounwind {
+; CHECKIZFH-LABEL: fminimum_nnan_f16:
+; CHECKIZFH:       # %bb.0:
+; CHECKIZFH-NEXT:    fmin.h fa0, fa0, fa1
+; CHECKIZFH-NEXT:    ret
+;
+; CHECKIZHINX-LABEL: fminimum_nnan_f16:
+; CHECKIZHINX:       # %bb.0:
+; CHECKIZHINX-NEXT:    fmin.h a0, a0, a1
+; CHECKIZHINX-NEXT:    ret
+  %1 = call nnan half @llvm.minimum.f16(half %a, half %b)
+  ret half %1
+}
+
+define half @fmaximum_nnan_f16(half %a, half %b) nounwind {
+; CHECKIZFH-LABEL: fmaximum_nnan_f16:
+; CHECKIZFH:       # %bb.0:
+; CHECKIZFH-NEXT:    fmax.h fa0, fa0, fa1
+; CHECKIZFH-NEXT:    ret
+;
+; CHECKIZHINX-LABEL: fmaximum_nnan_f16:
+; CHECKIZHINX:       # %bb.0:
+; CHECKIZHINX-NEXT:    fmax.h a0, a0, a1
+; CHECKIZHINX-NEXT:    ret
+  %1 = call nnan half @llvm.maximum.f16(half %a, half %b)
+  ret half %1
+}
+
+define half @fminimum_nnan_attr_f16(half %a, half %b) nounwind "no-nans-fp-math"="true" {
+; CHECKIZFH-LABEL: fminimum_nnan_attr_f16:
+; CHECKIZFH:       # %bb.0:
+; CHECKIZFH-NEXT:    fmin.h fa0, fa0, fa1
+; CHECKIZFH-NEXT:    ret
+;
+; CHECKIZHINX-LABEL: fminimum_nnan_attr_f16:
+; CHECKIZHINX:       # %bb.0:
+; CHECKIZHINX-NEXT:    fmin.h a0, a0, a1
+; CHECKIZHINX-NEXT:    ret
+  %1 = call half @llvm.minimum.f16(half %a, half %b)
+  ret half %1
+}
+
+define half @fminimum_nnan_op_f16(half %a, half %b) nounwind {
+; CHECKIZFH-LABEL: fminimum_nnan_op_f16:
+; CHECKIZFH:       # %bb.0:
+; CHECKIZFH-NEXT:    feq.h a0, fa0, fa0
+; CHECKIZFH-NEXT:    bnez a0, .LBB5_2
+; CHECKIZFH-NEXT:  # %bb.1:
+; CHECKIZFH-NEXT:    fmin.h fa0, fa0, fa0
+; CHECKIZFH-NEXT:    ret
+; CHECKIZFH-NEXT:  .LBB5_2:
+; CHECKIZFH-NEXT:    fadd.h fa5, fa0, fa0
+; CHECKIZFH-NEXT:    fmin.h fa0, fa0, fa5
+; CHECKIZFH-NEXT:    ret
+;
+; CHECKIZHINX-LABEL: fminimum_nnan_op_f16:
+; CHECKIZHINX:       # %bb.0:
+; CHECKIZHINX-NEXT:    feq.h a1, a0, a0
+; CHECKIZHINX-NEXT:    bnez a1, .LBB5_2
+; CHECKIZHINX-NEXT:  # %bb.1:
+; CHECKIZHINX-NEXT:    fmin.h a0, a0, a0
+; CHECKIZHINX-NEXT:    ret
+; CHECKIZHINX-NEXT:  .LBB5_2:
+; CHECKIZHINX-NEXT:    fadd.h a1, a0, a0
+; CHECKIZHINX-NEXT:    fmin.h a0, a0, a1
+; CHECKIZHINX-NEXT:    ret
+  %c = fadd nnan half %a, %a
+  %1 = call half @llvm.minimum.f16(half %a, half %c)
+  ret half %1
+}
+
+define half @fmaximum_nnan_op_f16(half %a, half %b) nounwind {
+; CHECKIZFH-LABEL: fmaximum_nnan_op_f16:
+; CHECKIZFH:       # %bb.0:
+; CHECKIZFH-NEXT:    fadd.h fa5, fa0, fa1
+; CHECKIZFH-NEXT:    fsub.h fa4, fa0, fa1
+; CHECKIZFH-NEXT:    fmax.h fa0, fa5, fa4
+; CHECKIZFH-NEXT:    ret
+;
+; CHECKIZHINX-LABEL: fmaximum_nnan_op_f16:
+; CHECKIZHINX:       # %bb.0:
+; CHECKIZHINX-NEXT:    fadd.h a2, a0, a1
+; CHECKIZHINX-NEXT:    fsub.h a0, a0, a1
+; CHECKIZHINX-NEXT:    fmax.h a0, a2, a0
+; CHECKIZHINX-NEXT:    ret
+  %c = fadd nnan half %a, %b
+  %d = fsub nnan half %a, %b
+  %1 = call half @llvm.maximum.f16(half %c, half %d)
+  ret half %1
+}


        


More information about the llvm-commits mailing list