In M=4 mode, the behavior matches IEEE 754-2019 minimumNumber, except that if both operands are sNaN, the result will be sNaN rather than qNaN. However, this is explicitly allowed for LLVM's minimumnum intrinsic, as canonicalization can be omitted for non-constrainted FP. As such, mark fminimumnum/fmaximumnum as legal, and lower them the same way as fminnum/fmaxnum. In the future, we may wish to switch those to use M=0 instead, to match IEEE 754-2008 maxNum/minNum instead.
165 lines
5.4 KiB
LLVM
165 lines
5.4 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
|
|
; RUN: llc -mtriple=s390x-unknown-linux-gnu -mcpu=z14 < %s | FileCheck %s
|
|
|
|
define half @fminimumnum_f16(half %a, half %b) nounwind {
|
|
; CHECK-LABEL: fminimumnum_f16:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: stmg %r14, %r15, 112(%r15)
|
|
; CHECK-NEXT: aghi %r15, -176
|
|
; CHECK-NEXT: std %f8, 168(%r15) # 8-byte Spill
|
|
; CHECK-NEXT: std %f9, 160(%r15) # 8-byte Spill
|
|
; CHECK-NEXT: ldr %f8, %f0
|
|
; CHECK-NEXT: ldr %f0, %f2
|
|
; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT
|
|
; CHECK-NEXT: ldr %f9, %f0
|
|
; CHECK-NEXT: ldr %f0, %f8
|
|
; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT
|
|
; CHECK-NEXT: wfminsb %f0, %f0, %f9, 4
|
|
; CHECK-NEXT: brasl %r14, __truncsfhf2@PLT
|
|
; CHECK-NEXT: ld %f8, 168(%r15) # 8-byte Reload
|
|
; CHECK-NEXT: ld %f9, 160(%r15) # 8-byte Reload
|
|
; CHECK-NEXT: lmg %r14, %r15, 288(%r15)
|
|
; CHECK-NEXT: br %r14
|
|
%res = call half @llvm.minimumnum(half %a, half %b)
|
|
ret half %res
|
|
}
|
|
|
|
define float @fminimumnum_f32(float %a, float %b) {
|
|
; CHECK-LABEL: fminimumnum_f32:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: wfminsb %f0, %f0, %f2, 4
|
|
; CHECK-NEXT: br %r14
|
|
%res = call float @llvm.minimumnum(float %a, float %b)
|
|
ret float %res
|
|
}
|
|
|
|
define double @fminimumnum_f64(double %a, double %b) {
|
|
; CHECK-LABEL: fminimumnum_f64:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: wfmindb %f0, %f0, %f2, 4
|
|
; CHECK-NEXT: br %r14
|
|
%res = call double @llvm.minimumnum(double %a, double %b)
|
|
ret double %res
|
|
}
|
|
|
|
define fp128 @fminimumnum_f128(fp128 %a, fp128 %b) {
|
|
; CHECK-LABEL: fminimumnum_f128:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vl %v0, 0(%r4), 3
|
|
; CHECK-NEXT: vl %v1, 0(%r3), 3
|
|
; CHECK-NEXT: wfminxb %v0, %v1, %v0, 4
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%res = call fp128 @llvm.minimumnum(fp128 %a, fp128 %b)
|
|
ret fp128 %res
|
|
}
|
|
|
|
define <4 x float> @fminimumnum_v4f32(<4 x float> %a, <4 x float> %b) {
|
|
; CHECK-LABEL: fminimumnum_v4f32:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vfminsb %v24, %v24, %v26, 4
|
|
; CHECK-NEXT: br %r14
|
|
%res = call <4 x float> @llvm.minimumnum(<4 x float> %a, <4 x float> %b)
|
|
ret <4 x float> %res
|
|
}
|
|
|
|
define <2 x double> @fminimumnum_v2f64(<2 x double> %a, <2 x double> %b) {
|
|
; CHECK-LABEL: fminimumnum_v2f64:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vfmindb %v24, %v24, %v26, 4
|
|
; CHECK-NEXT: br %r14
|
|
%res = call <2 x double> @llvm.minimumnum(<2 x double> %a, <2 x double> %b)
|
|
ret <2 x double> %res
|
|
}
|
|
|
|
define <4 x double> @fminimumnum_v4f64(<4 x double> %a, <4 x double> %b) {
|
|
; CHECK-LABEL: fminimumnum_v4f64:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vfmindb %v24, %v24, %v28, 4
|
|
; CHECK-NEXT: vfmindb %v26, %v26, %v30, 4
|
|
; CHECK-NEXT: br %r14
|
|
%res = call <4 x double> @llvm.minimumnum(<4 x double> %a, <4 x double> %b)
|
|
ret <4 x double> %res
|
|
}
|
|
|
|
define half @fmaximumnum_f16(half %a, half %b) nounwind {
|
|
; CHECK-LABEL: fmaximumnum_f16:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: stmg %r14, %r15, 112(%r15)
|
|
; CHECK-NEXT: aghi %r15, -176
|
|
; CHECK-NEXT: std %f8, 168(%r15) # 8-byte Spill
|
|
; CHECK-NEXT: std %f9, 160(%r15) # 8-byte Spill
|
|
; CHECK-NEXT: ldr %f8, %f0
|
|
; CHECK-NEXT: ldr %f0, %f2
|
|
; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT
|
|
; CHECK-NEXT: ldr %f9, %f0
|
|
; CHECK-NEXT: ldr %f0, %f8
|
|
; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT
|
|
; CHECK-NEXT: wfmaxsb %f0, %f0, %f9, 4
|
|
; CHECK-NEXT: brasl %r14, __truncsfhf2@PLT
|
|
; CHECK-NEXT: ld %f8, 168(%r15) # 8-byte Reload
|
|
; CHECK-NEXT: ld %f9, 160(%r15) # 8-byte Reload
|
|
; CHECK-NEXT: lmg %r14, %r15, 288(%r15)
|
|
; CHECK-NEXT: br %r14
|
|
%res = call half @llvm.maximumnum(half %a, half %b)
|
|
ret half %res
|
|
}
|
|
|
|
define float @fmaximumnum_f32(float %a, float %b) {
|
|
; CHECK-LABEL: fmaximumnum_f32:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: wfmaxsb %f0, %f0, %f2, 4
|
|
; CHECK-NEXT: br %r14
|
|
%res = call float @llvm.maximumnum(float %a, float %b)
|
|
ret float %res
|
|
}
|
|
|
|
define double @fmaximumnum_f64(double %a, double %b) {
|
|
; CHECK-LABEL: fmaximumnum_f64:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: wfmaxdb %f0, %f0, %f2, 4
|
|
; CHECK-NEXT: br %r14
|
|
%res = call double @llvm.maximumnum(double %a, double %b)
|
|
ret double %res
|
|
}
|
|
|
|
define fp128 @fmaximumnum_f128(fp128 %a, fp128 %b) {
|
|
; CHECK-LABEL: fmaximumnum_f128:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vl %v0, 0(%r4), 3
|
|
; CHECK-NEXT: vl %v1, 0(%r3), 3
|
|
; CHECK-NEXT: wfmaxxb %v0, %v1, %v0, 4
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%res = call fp128 @llvm.maximumnum(fp128 %a, fp128 %b)
|
|
ret fp128 %res
|
|
}
|
|
|
|
define <4 x float> @fmaximumnum_v4f32(<4 x float> %a, <4 x float> %b) {
|
|
; CHECK-LABEL: fmaximumnum_v4f32:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vfmaxsb %v24, %v24, %v26, 4
|
|
; CHECK-NEXT: br %r14
|
|
%res = call <4 x float> @llvm.maximumnum(<4 x float> %a, <4 x float> %b)
|
|
ret <4 x float> %res
|
|
}
|
|
|
|
define <2 x double> @fmaximumnum_v2f64(<2 x double> %a, <2 x double> %b) {
|
|
; CHECK-LABEL: fmaximumnum_v2f64:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vfmaxdb %v24, %v24, %v26, 4
|
|
; CHECK-NEXT: br %r14
|
|
%res = call <2 x double> @llvm.maximumnum(<2 x double> %a, <2 x double> %b)
|
|
ret <2 x double> %res
|
|
}
|
|
|
|
define <4 x double> @fmaximumnum_v4f64(<4 x double> %a, <4 x double> %b) {
|
|
; CHECK-LABEL: fmaximumnum_v4f64:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vfmaxdb %v24, %v24, %v28, 4
|
|
; CHECK-NEXT: vfmaxdb %v26, %v26, %v30, 4
|
|
; CHECK-NEXT: br %r14
|
|
%res = call <4 x double> @llvm.maximumnum(<4 x double> %a, <4 x double> %b)
|
|
ret <4 x double> %res
|
|
}
|