[llvm] d5378da - [SystemZ] Mark fminimumnum/fmaximumnum as legal (#184595)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 5 00:04:00 PST 2026
Author: Nikita Popov
Date: 2026-03-05T09:03:55+01:00
New Revision: d5378dafa2af38164c2577a36c7a6c6aa0249d9f
URL: https://github.com/llvm/llvm-project/commit/d5378dafa2af38164c2577a36c7a6c6aa0249d9f
DIFF: https://github.com/llvm/llvm-project/commit/d5378dafa2af38164c2577a36c7a6c6aa0249d9f.diff
LOG: [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.
Added:
llvm/test/CodeGen/SystemZ/fminimumnum-fmaximumnum.ll
Modified:
llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
llvm/lib/Target/SystemZ/SystemZInstrVector.td
Removed:
################################################################################
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index eacaaddc5e4d4..2a9cb903f3921 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -694,30 +694,14 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::FROUND, MVT::v4f32, Legal);
setOperationAction(ISD::FROUNDEVEN, MVT::v4f32, Legal);
- setOperationAction(ISD::FMAXNUM, MVT::f64, Legal);
- setOperationAction(ISD::FMAXIMUM, MVT::f64, Legal);
- setOperationAction(ISD::FMINNUM, MVT::f64, Legal);
- setOperationAction(ISD::FMINIMUM, MVT::f64, Legal);
-
- setOperationAction(ISD::FMAXNUM, MVT::v2f64, Legal);
- setOperationAction(ISD::FMAXIMUM, MVT::v2f64, Legal);
- setOperationAction(ISD::FMINNUM, MVT::v2f64, Legal);
- setOperationAction(ISD::FMINIMUM, MVT::v2f64, Legal);
-
- setOperationAction(ISD::FMAXNUM, MVT::f32, Legal);
- setOperationAction(ISD::FMAXIMUM, MVT::f32, Legal);
- setOperationAction(ISD::FMINNUM, MVT::f32, Legal);
- setOperationAction(ISD::FMINIMUM, MVT::f32, Legal);
-
- setOperationAction(ISD::FMAXNUM, MVT::v4f32, Legal);
- setOperationAction(ISD::FMAXIMUM, MVT::v4f32, Legal);
- setOperationAction(ISD::FMINNUM, MVT::v4f32, Legal);
- setOperationAction(ISD::FMINIMUM, MVT::v4f32, Legal);
-
- setOperationAction(ISD::FMAXNUM, MVT::f128, Legal);
- setOperationAction(ISD::FMAXIMUM, MVT::f128, Legal);
- setOperationAction(ISD::FMINNUM, MVT::f128, Legal);
- setOperationAction(ISD::FMINIMUM, MVT::f128, Legal);
+ for (MVT Type : {MVT::f64, MVT::v2f64, MVT::f32, MVT::v4f32, MVT::f128}) {
+ setOperationAction(ISD::FMAXNUM, Type, Legal);
+ setOperationAction(ISD::FMAXIMUM, Type, Legal);
+ setOperationAction(ISD::FMAXIMUMNUM, Type, Legal);
+ setOperationAction(ISD::FMINNUM, Type, Legal);
+ setOperationAction(ISD::FMINIMUM, Type, Legal);
+ setOperationAction(ISD::FMINIMUMNUM, Type, Legal);
+ }
// Handle constrained floating-point operations.
setOperationAction(ISD::STRICT_FADD, MVT::v4f32, Legal);
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrVector.td b/llvm/lib/Target/SystemZ/SystemZInstrVector.td
index 0bbca28ca7be0..fe26bdc72799b 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrVector.td
+++ b/llvm/lib/Target/SystemZ/SystemZInstrVector.td
@@ -1599,6 +1599,7 @@ let Predicates = [FeatureVector] in {
// Maximum.
multiclass VectorMax<Instruction insn, TypedReg tr> {
def : FPMinMax<insn, any_fmaxnum, tr, 4>;
+ def : FPMinMax<insn, fmaximumnum, tr, 4>;
def : FPMinMax<insn, any_fmaximum, tr, 1>;
}
let Predicates = [FeatureVectorEnhancements1] in {
@@ -1625,6 +1626,7 @@ let Predicates = [FeatureVector] in {
// Minimum.
multiclass VectorMin<Instruction insn, TypedReg tr> {
def : FPMinMax<insn, any_fminnum, tr, 4>;
+ def : FPMinMax<insn, fminimumnum, tr, 4>;
def : FPMinMax<insn, any_fminimum, tr, 1>;
}
let Predicates = [FeatureVectorEnhancements1] in {
diff --git a/llvm/test/CodeGen/SystemZ/fminimumnum-fmaximumnum.ll b/llvm/test/CodeGen/SystemZ/fminimumnum-fmaximumnum.ll
new file mode 100644
index 0000000000000..b447e9119086f
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/fminimumnum-fmaximumnum.ll
@@ -0,0 +1,164 @@
+; 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 at PLT
+; CHECK-NEXT: ldr %f9, %f0
+; CHECK-NEXT: ldr %f0, %f8
+; CHECK-NEXT: brasl %r14, __extendhfsf2 at PLT
+; CHECK-NEXT: wfminsb %f0, %f0, %f9, 4
+; CHECK-NEXT: brasl %r14, __truncsfhf2 at 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 at PLT
+; CHECK-NEXT: ldr %f9, %f0
+; CHECK-NEXT: ldr %f0, %f8
+; CHECK-NEXT: brasl %r14, __extendhfsf2 at PLT
+; CHECK-NEXT: wfmaxsb %f0, %f0, %f9, 4
+; CHECK-NEXT: brasl %r14, __truncsfhf2 at 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
+}
More information about the llvm-commits
mailing list