Files
llvm-project/llvm/test/CodeGen/SystemZ/fminimumnum-fmaximumnum.ll
Nikita Popov d5378dafa2 [SystemZ] Mark fminimumnum/fmaximumnum as legal (#184595)
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.
2026-03-05 09:03:55 +01:00

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
}