C23 introduced new functions fminimum_num and fmaximum_num, and they follow the minimumNumber and maximumNumber of IEEE754-2019. Let's introduce new intrinsics to support them. This patch introduces support only support for scalar values. The support of vector (vp, vp.reduce, vector.reduce), experimental.constrained will be added in future patches. With this patch, MIPSr6 and LoongArch can work out of box with fcanonical and fmax/fmin. Aarch64/PowerPC64 can use the same login as MIPSr6 and LoongArch, while they have no fcanonical support yet. I will add it in future patches. The FMIN/FMAX of RISC-V instructions follows the minimumNumber/maximumNumber of IEEE754-2019. We can just add it in future patch. Background https://discourse.llvm.org/t/rfc-fix-llvm-min-f-and-llvm-max-f-intrinsics/79735 Currently we have fminnum/fmaxnum, which have different behavior on different platform for NUM vs sNaN: 1) Fallback to fmin(3)/fmax(3): return qNaN. 2) ARM64/ARM32+Neon: same as libc. 3) MIPSr6/LoongArch/RISC-V: return NUM. And the fix of fminnum/fmaxnum to follow minNUM/maxNUM of IEEE754-2008 will submit as separated patches.
133 lines
4.2 KiB
LLVM
133 lines
4.2 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc --mtriple=mipsisa32r6 < %s | FileCheck %s --check-prefix=MIPS32R6
|
|
|
|
declare float @llvm.maximumnum.f32(float, float)
|
|
declare double @llvm.maximumnum.f64(double, double)
|
|
declare float @llvm.minimumnum.f32(float, float)
|
|
declare double @llvm.minimumnum.f64(double, double)
|
|
|
|
define float @maximumnum_float(float %x, float %y) {
|
|
; MIPS32R6-LABEL: maximumnum_float:
|
|
; MIPS32R6: # %bb.0:
|
|
; MIPS32R6-NEXT: min.s $f0, $f14, $f14
|
|
; MIPS32R6-NEXT: min.s $f1, $f12, $f12
|
|
; MIPS32R6-NEXT: jr $ra
|
|
; MIPS32R6-NEXT: max.s $f0, $f1, $f0
|
|
%z = call float @llvm.maximumnum.f32(float %x, float %y)
|
|
ret float %z
|
|
}
|
|
|
|
define float @maximumnum_float_nsz(float %x, float %y) {
|
|
; MIPS32R6-LABEL: maximumnum_float_nsz:
|
|
; MIPS32R6: # %bb.0:
|
|
; MIPS32R6-NEXT: min.s $f0, $f14, $f14
|
|
; MIPS32R6-NEXT: min.s $f1, $f12, $f12
|
|
; MIPS32R6-NEXT: jr $ra
|
|
; MIPS32R6-NEXT: max.s $f0, $f1, $f0
|
|
%z = call nsz float @llvm.maximumnum.f32(float %x, float %y)
|
|
ret float %z
|
|
}
|
|
|
|
define float @maximumnum_float_nnan(float %x, float %y) {
|
|
; MIPS32R6-LABEL: maximumnum_float_nnan:
|
|
; MIPS32R6: # %bb.0:
|
|
; MIPS32R6-NEXT: jr $ra
|
|
; MIPS32R6-NEXT: max.s $f0, $f12, $f14
|
|
%z = call nnan float @llvm.maximumnum.f32(float %x, float %y)
|
|
ret float %z
|
|
}
|
|
|
|
|
|
define double @maximumnum_double(double %x, double %y) {
|
|
; MIPS32R6-LABEL: maximumnum_double:
|
|
; MIPS32R6: # %bb.0:
|
|
; MIPS32R6-NEXT: min.d $f0, $f14, $f14
|
|
; MIPS32R6-NEXT: min.d $f1, $f12, $f12
|
|
; MIPS32R6-NEXT: jr $ra
|
|
; MIPS32R6-NEXT: max.d $f0, $f1, $f0
|
|
%z = call double @llvm.maximumnum.f64(double %x, double %y)
|
|
ret double %z
|
|
}
|
|
|
|
define double @maximumnum_double_nsz(double %x, double %y) {
|
|
; MIPS32R6-LABEL: maximumnum_double_nsz:
|
|
; MIPS32R6: # %bb.0:
|
|
; MIPS32R6-NEXT: min.d $f0, $f14, $f14
|
|
; MIPS32R6-NEXT: min.d $f1, $f12, $f12
|
|
; MIPS32R6-NEXT: jr $ra
|
|
; MIPS32R6-NEXT: max.d $f0, $f1, $f0
|
|
%z = call nsz double @llvm.maximumnum.f64(double %x, double %y)
|
|
ret double %z
|
|
}
|
|
|
|
define double @maximumnum_double_nnan(double %x, double %y) {
|
|
; MIPS32R6-LABEL: maximumnum_double_nnan:
|
|
; MIPS32R6: # %bb.0:
|
|
; MIPS32R6-NEXT: jr $ra
|
|
; MIPS32R6-NEXT: max.d $f0, $f12, $f14
|
|
%z = call nnan double @llvm.maximumnum.f64(double %x, double %y)
|
|
ret double %z
|
|
}
|
|
|
|
define float @minimumnum_float(float %x, float %y) {
|
|
; MIPS32R6-LABEL: minimumnum_float:
|
|
; MIPS32R6: # %bb.0:
|
|
; MIPS32R6-NEXT: min.s $f0, $f14, $f14
|
|
; MIPS32R6-NEXT: min.s $f1, $f12, $f12
|
|
; MIPS32R6-NEXT: jr $ra
|
|
; MIPS32R6-NEXT: min.s $f0, $f1, $f0
|
|
%z = call float @llvm.minimumnum.f32(float %x, float %y)
|
|
ret float %z
|
|
}
|
|
|
|
define float @minimumnum_float_nsz(float %x, float %y) {
|
|
; MIPS32R6-LABEL: minimumnum_float_nsz:
|
|
; MIPS32R6: # %bb.0:
|
|
; MIPS32R6-NEXT: min.s $f0, $f14, $f14
|
|
; MIPS32R6-NEXT: min.s $f1, $f12, $f12
|
|
; MIPS32R6-NEXT: jr $ra
|
|
; MIPS32R6-NEXT: min.s $f0, $f1, $f0
|
|
%z = call nsz float @llvm.minimumnum.f32(float %x, float %y)
|
|
ret float %z
|
|
}
|
|
|
|
define float @minimumnum_float_nnan(float %x, float %y) {
|
|
; MIPS32R6-LABEL: minimumnum_float_nnan:
|
|
; MIPS32R6: # %bb.0:
|
|
; MIPS32R6-NEXT: jr $ra
|
|
; MIPS32R6-NEXT: min.s $f0, $f12, $f14
|
|
%z = call nnan float @llvm.minimumnum.f32(float %x, float %y)
|
|
ret float %z
|
|
}
|
|
|
|
define double @minimumnum_double(double %x, double %y) {
|
|
; MIPS32R6-LABEL: minimumnum_double:
|
|
; MIPS32R6: # %bb.0:
|
|
; MIPS32R6-NEXT: min.d $f0, $f14, $f14
|
|
; MIPS32R6-NEXT: min.d $f1, $f12, $f12
|
|
; MIPS32R6-NEXT: jr $ra
|
|
; MIPS32R6-NEXT: min.d $f0, $f1, $f0
|
|
%z = call double @llvm.minimumnum.f64(double %x, double %y)
|
|
ret double %z
|
|
}
|
|
|
|
define double @minimumnum_double_nsz(double %x, double %y) {
|
|
; MIPS32R6-LABEL: minimumnum_double_nsz:
|
|
; MIPS32R6: # %bb.0:
|
|
; MIPS32R6-NEXT: min.d $f0, $f14, $f14
|
|
; MIPS32R6-NEXT: min.d $f1, $f12, $f12
|
|
; MIPS32R6-NEXT: jr $ra
|
|
; MIPS32R6-NEXT: min.d $f0, $f1, $f0
|
|
%z = call nsz double @llvm.minimumnum.f64(double %x, double %y)
|
|
ret double %z
|
|
}
|
|
|
|
define double @minimumnum_double_nnan(double %x, double %y) {
|
|
; MIPS32R6-LABEL: minimumnum_double_nnan:
|
|
; MIPS32R6: # %bb.0:
|
|
; MIPS32R6-NEXT: jr $ra
|
|
; MIPS32R6-NEXT: min.d $f0, $f12, $f14
|
|
%z = call nnan double @llvm.minimumnum.f64(double %x, double %y)
|
|
ret double %z
|
|
}
|