[llvm] 1946461 - [FPEnv] Strict versions of llvm.minimum/llvm.maximum

Ulrich Weigand via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 18 12:36:01 PST 2019


Author: Ulrich Weigand
Date: 2019-12-18T21:35:28+01:00
New Revision: 19464613440894f5906a83ea1b52999d9fa08882

URL: https://github.com/llvm/llvm-project/commit/19464613440894f5906a83ea1b52999d9fa08882
DIFF: https://github.com/llvm/llvm-project/commit/19464613440894f5906a83ea1b52999d9fa08882.diff

LOG: [FPEnv] Strict versions of llvm.minimum/llvm.maximum

Add new intrinsics
   llvm.experimental.constrained.minimum
   llvm.experimental.constrained.maximum
as strict versions of llvm.minimum and llvm.maximum.

Includes SystemZ back-end support.

Reviewed By: craig.topper

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

Added: 
    

Modified: 
    llvm/docs/LangRef.rst
    llvm/include/llvm/CodeGen/ISDOpcodes.h
    llvm/include/llvm/IR/ConstrainedOps.def
    llvm/include/llvm/IR/Intrinsics.td
    llvm/include/llvm/Target/TargetSelectionDAG.td
    llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
    llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
    llvm/lib/Target/SystemZ/SystemZInstrVector.td
    llvm/test/CodeGen/SystemZ/vec-strict-max-01.ll
    llvm/test/CodeGen/SystemZ/vec-strict-min-01.ll

Removed: 
    


################################################################################
diff  --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index e98cd3cdfd47..d227a9583263 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -16532,6 +16532,70 @@ Semantics:
 This function follows the IEEE-754 semantics for minNum.
 
 
+'``llvm.experimental.constrained.maximum``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+      declare <type>
+      @llvm.experimental.constrained.maximum(<type> <op1>, <type> <op2>
+                                             metadata <exception behavior>)
+
+Overview:
+"""""""""
+
+The '``llvm.experimental.constrained.maximum``' intrinsic returns the maximum
+of the two arguments, propagating NaNs and treating -0.0 as less than +0.0.
+
+Arguments:
+""""""""""
+
+The first two arguments and the return value are floating-point numbers
+of the same type.
+
+The third argument specifies the exception behavior as described above.
+
+Semantics:
+""""""""""
+
+This function follows semantics specified in the draft of IEEE 754-2018.
+
+
+'``llvm.experimental.constrained.minimum``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+      declare <type>
+      @llvm.experimental.constrained.minimum(<type> <op1>, <type> <op2>
+                                             metadata <exception behavior>)
+
+Overview:
+"""""""""
+
+The '``llvm.experimental.constrained.minimum``' intrinsic returns the minimum
+of the two arguments, propagating NaNs and treating -0.0 as less than +0.0.
+
+Arguments:
+""""""""""
+
+The first two arguments and the return value are floating-point numbers
+of the same type.
+
+The third argument specifies the exception behavior as described above.
+
+Semantics:
+""""""""""
+
+This function follows semantics specified in the draft of IEEE 754-2018.
+
+
 '``llvm.experimental.constrained.ceil``' Intrinsic
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 

diff  --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h b/llvm/include/llvm/CodeGen/ISDOpcodes.h
index d3494f552231..23918cb14d46 100644
--- a/llvm/include/llvm/CodeGen/ISDOpcodes.h
+++ b/llvm/include/llvm/CodeGen/ISDOpcodes.h
@@ -304,6 +304,7 @@ namespace ISD {
     STRICT_FRINT, STRICT_FNEARBYINT, STRICT_FMAXNUM, STRICT_FMINNUM,
     STRICT_FCEIL, STRICT_FFLOOR, STRICT_FROUND, STRICT_FTRUNC,
     STRICT_LROUND, STRICT_LLROUND, STRICT_LRINT, STRICT_LLRINT,
+    STRICT_FMAXIMUM, STRICT_FMINIMUM,
 
     /// STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or
     /// unsigned integer. These have the same semantics as fptosi and fptoui 

diff  --git a/llvm/include/llvm/IR/ConstrainedOps.def b/llvm/include/llvm/IR/ConstrainedOps.def
index 5bd1d60049d6..7e24684ca654 100644
--- a/llvm/include/llvm/IR/ConstrainedOps.def
+++ b/llvm/include/llvm/IR/ConstrainedOps.def
@@ -70,6 +70,8 @@ FUNCTION(lround,          1, 0, experimental_constrained_lround,     LROUND)
 FUNCTION(llround,         1, 0, experimental_constrained_llround,    LLROUND)
 FUNCTION(maxnum,          2, 0, experimental_constrained_maxnum,     FMAXNUM)
 FUNCTION(minnum,          2, 0, experimental_constrained_minnum,     FMINNUM)
+FUNCTION(maximum,         2, 0, experimental_constrained_maximum,    FMAXIMUM)
+FUNCTION(minimum,         2, 0, experimental_constrained_minimum,    FMINIMUM)
 FUNCTION(nearbyint,       1, 1, experimental_constrained_nearbyint,  FNEARBYINT)
 FUNCTION(pow,             2, 1, experimental_constrained_pow,        FPOW)
 FUNCTION(powi,            2, 1, experimental_constrained_powi,       FPOWI)

diff  --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index 100d1ba59479..914c605bada3 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -729,6 +729,14 @@ let IntrProperties = [IntrInaccessibleMemOnly, IntrWillReturn] in {
                                                       [ LLVMMatchType<0>,
                                                         LLVMMatchType<0>,
                                                         llvm_metadata_ty ]>;
+  def int_experimental_constrained_maximum : Intrinsic<[ llvm_anyfloat_ty ],
+                                                       [ LLVMMatchType<0>,
+                                                         LLVMMatchType<0>,
+                                                         llvm_metadata_ty ]>;
+  def int_experimental_constrained_minimum : Intrinsic<[ llvm_anyfloat_ty ],
+                                                       [ LLVMMatchType<0>,
+                                                         LLVMMatchType<0>,
+                                                         llvm_metadata_ty ]>;
   def int_experimental_constrained_ceil : Intrinsic<[ llvm_anyfloat_ty ],
                                                     [ LLVMMatchType<0>,
                                                       llvm_metadata_ty ]>;

diff  --git a/llvm/include/llvm/Target/TargetSelectionDAG.td b/llvm/include/llvm/Target/TargetSelectionDAG.td
index 6859e2fececd..84b73b4bbde1 100644
--- a/llvm/include/llvm/Target/TargetSelectionDAG.td
+++ b/llvm/include/llvm/Target/TargetSelectionDAG.td
@@ -530,6 +530,12 @@ def strict_fminnum    : SDNode<"ISD::STRICT_FMINNUM",
 def strict_fmaxnum    : SDNode<"ISD::STRICT_FMAXNUM",
                                SDTFPBinOp, [SDNPHasChain,
                                             SDNPCommutative, SDNPAssociative]>;
+def strict_fminimum   : SDNode<"ISD::STRICT_FMINIMUM",
+                               SDTFPBinOp, [SDNPHasChain,
+                                            SDNPCommutative, SDNPAssociative]>;
+def strict_fmaximum   : SDNode<"ISD::STRICT_FMAXIMUM",
+                               SDTFPBinOp, [SDNPHasChain,
+                                            SDNPCommutative, SDNPAssociative]>;
 def strict_fpround    : SDNode<"ISD::STRICT_FP_ROUND",
                                SDTFPRoundOp, [SDNPHasChain]>;
 def strict_fpextend   : SDNode<"ISD::STRICT_FP_EXTEND",
@@ -1384,6 +1390,12 @@ def any_fmaxnum    : PatFrags<(ops node:$lhs, node:$rhs),
 def any_fminnum    : PatFrags<(ops node:$lhs, node:$rhs),
                               [(strict_fminnum node:$lhs, node:$rhs),
                                (fminnum node:$lhs, node:$rhs)]>;
+def any_fmaximum   : PatFrags<(ops node:$lhs, node:$rhs),
+                              [(strict_fmaximum node:$lhs, node:$rhs),
+                               (fmaximum node:$lhs, node:$rhs)]>;
+def any_fminimum   : PatFrags<(ops node:$lhs, node:$rhs),
+                              [(strict_fminimum node:$lhs, node:$rhs),
+                               (fminimum node:$lhs, node:$rhs)]>;
 def any_fpround    : PatFrags<(ops node:$src),
                               [(strict_fpround node:$src),
                                (fpround node:$src)]>;

diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index b5f8a3bc934c..92e4160d69d5 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -186,7 +186,9 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
   case ISD::FMINNUM_IEEE:               return "fminnum_ieee";
   case ISD::FMAXNUM_IEEE:               return "fmaxnum_ieee";
   case ISD::FMINIMUM:                   return "fminimum";
+  case ISD::STRICT_FMINIMUM:            return "strict_fminimum";
   case ISD::FMAXIMUM:                   return "fmaximum";
+  case ISD::STRICT_FMAXIMUM:            return "strict_fmaximum";
   case ISD::FNEG:                       return "fneg";
   case ISD::FSQRT:                      return "fsqrt";
   case ISD::STRICT_FSQRT:               return "strict_fsqrt";

diff  --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index d20d4ddc76e3..14e15bad9330 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -583,6 +583,8 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM,
                      MVT::v4f32, MVT::v2f64 }) {
       setOperationAction(ISD::STRICT_FMAXNUM, VT, Legal);
       setOperationAction(ISD::STRICT_FMINNUM, VT, Legal);
+      setOperationAction(ISD::STRICT_FMAXIMUM, VT, Legal);
+      setOperationAction(ISD::STRICT_FMINIMUM, VT, Legal);
     }
   }
 

diff  --git a/llvm/lib/Target/SystemZ/SystemZInstrVector.td b/llvm/lib/Target/SystemZ/SystemZInstrVector.td
index 1f3817671d58..de6e473dd56b 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrVector.td
+++ b/llvm/lib/Target/SystemZ/SystemZInstrVector.td
@@ -1175,7 +1175,7 @@ let Predicates = [FeatureVector] in {
   // Maximum.
   multiclass VectorMax<Instruction insn, TypedReg tr> {
     def : FPMinMax<insn, any_fmaxnum, tr, 4>;
-    def : FPMinMax<insn, fmaximum, tr, 1>;
+    def : FPMinMax<insn, any_fmaximum, tr, 1>;
   }
   let Predicates = [FeatureVectorEnhancements1] in {
     let Uses = [FPC], mayRaiseFPException = 1 in {
@@ -1201,7 +1201,7 @@ let Predicates = [FeatureVector] in {
   // Minimum.
   multiclass VectorMin<Instruction insn, TypedReg tr> {
     def : FPMinMax<insn, any_fminnum, tr, 4>;
-    def : FPMinMax<insn, fminimum, tr, 1>;
+    def : FPMinMax<insn, any_fminimum, tr, 1>;
   }
   let Predicates = [FeatureVectorEnhancements1] in {
     let Uses = [FPC], mayRaiseFPException = 1 in {

diff  --git a/llvm/test/CodeGen/SystemZ/vec-strict-max-01.ll b/llvm/test/CodeGen/SystemZ/vec-strict-max-01.ll
index 161c75eeb52e..a5a312e809c7 100644
--- a/llvm/test/CodeGen/SystemZ/vec-strict-max-01.ll
+++ b/llvm/test/CodeGen/SystemZ/vec-strict-max-01.ll
@@ -4,11 +4,16 @@
 
 declare double @llvm.experimental.constrained.maxnum.f64(double, double, metadata)
 declare <2 x double> @llvm.experimental.constrained.maxnum.v2f64(<2 x double>, <2 x double>, metadata)
+declare double @llvm.experimental.constrained.maximum.f64(double, double, metadata)
+declare <2 x double> @llvm.experimental.constrained.maximum.v2f64(<2 x double>, <2 x double>, metadata)
 
 declare float @llvm.experimental.constrained.maxnum.f32(float, float, metadata)
 declare <4 x float> @llvm.experimental.constrained.maxnum.v4f32(<4 x float>, <4 x float>, metadata)
+declare float @llvm.experimental.constrained.maximum.f32(float, float, metadata)
+declare <4 x float> @llvm.experimental.constrained.maximum.v4f32(<4 x float>, <4 x float>, metadata)
 
 declare fp128 @llvm.experimental.constrained.maxnum.f128(fp128, fp128, metadata)
+declare fp128 @llvm.experimental.constrained.maximum.f128(fp128, fp128, metadata)
 
 ; Test the f64 maxnum intrinsic.
 define double @f1(double %dummy, double %val1, double %val2) #0 {
@@ -73,4 +78,67 @@ define void @f5(fp128 *%ptr1, fp128 *%ptr2, fp128 *%dst) #0 {
   ret void
 }
 
+; Test the f64 maximum intrinsic.
+define double @f11(double %dummy, double %val1, double %val2) #0 {
+; CHECK-LABEL: f11:
+; CHECK: wfmaxdb %f0, %f2, %f4, 1
+; CHECK: br %r14
+  %ret = call double @llvm.experimental.constrained.maximum.f64(
+                        double %val1, double %val2,
+                        metadata !"fpexcept.strict") #0
+  ret double %ret
+}
+
+; Test the v2f64 maximum intrinsic.
+define <2 x double> @f12(<2 x double> %dummy, <2 x double> %val1,
+                         <2 x double> %val2) #0 {
+; CHECK-LABEL: f12:
+; CHECK: vfmaxdb %v24, %v26, %v28, 1
+; CHECK: br %r14
+  %ret = call <2 x double> @llvm.experimental.constrained.maximum.v2f64(
+                        <2 x double> %val1, <2 x double> %val2,
+                        metadata !"fpexcept.strict") #0
+  ret <2 x double> %ret
+}
+
+; Test the f32 maximum intrinsic.
+define float @f13(float %dummy, float %val1, float %val2) #0 {
+; CHECK-LABEL: f13:
+; CHECK: wfmaxsb %f0, %f2, %f4, 1
+; CHECK: br %r14
+  %ret = call float @llvm.experimental.constrained.maximum.f32(
+                        float %val1, float %val2,
+                        metadata !"fpexcept.strict") #0
+  ret float %ret
+}
+
+; Test the v4f32 maximum intrinsic.
+define <4 x float> @f14(<4 x float> %dummy, <4 x float> %val1,
+                        <4 x float> %val2) #0 {
+; CHECK-LABEL: f14:
+; CHECK: vfmaxsb %v24, %v26, %v28, 1
+; CHECK: br %r14
+  %ret = call <4 x float> @llvm.experimental.constrained.maximum.v4f32(
+                        <4 x float> %val1, <4 x float> %val2,
+                        metadata !"fpexcept.strict") #0
+  ret <4 x float> %ret
+}
+
+; Test the f128 maximum intrinsic.
+define void @f15(fp128 *%ptr1, fp128 *%ptr2, fp128 *%dst) #0 {
+; CHECK-LABEL: f15:
+; CHECK-DAG: vl [[REG1:%v[0-9]+]], 0(%r2)
+; CHECK-DAG: vl [[REG2:%v[0-9]+]], 0(%r3)
+; CHECK: wfmaxxb [[RES:%v[0-9]+]], [[REG1]], [[REG2]], 1
+; CHECK: vst [[RES]], 0(%r4)
+; CHECK: br %r14
+  %val1 = load fp128, fp128* %ptr1
+  %val2 = load fp128, fp128* %ptr2
+  %res = call fp128 @llvm.experimental.constrained.maximum.f128(
+                        fp128 %val1, fp128 %val2,
+                        metadata !"fpexcept.strict") #0
+  store fp128 %res, fp128* %dst
+  ret void
+}
+
 attributes #0 = { strictfp }

diff  --git a/llvm/test/CodeGen/SystemZ/vec-strict-min-01.ll b/llvm/test/CodeGen/SystemZ/vec-strict-min-01.ll
index d48a020f8805..5b66b1ec0591 100644
--- a/llvm/test/CodeGen/SystemZ/vec-strict-min-01.ll
+++ b/llvm/test/CodeGen/SystemZ/vec-strict-min-01.ll
@@ -4,11 +4,16 @@
 
 declare double @llvm.experimental.constrained.minnum.f64(double, double, metadata)
 declare <2 x double> @llvm.experimental.constrained.minnum.v2f64(<2 x double>, <2 x double>, metadata)
+declare double @llvm.experimental.constrained.minimum.f64(double, double, metadata)
+declare <2 x double> @llvm.experimental.constrained.minimum.v2f64(<2 x double>, <2 x double>, metadata)
 
 declare float @llvm.experimental.constrained.minnum.f32(float, float, metadata)
 declare <4 x float> @llvm.experimental.constrained.minnum.v4f32(<4 x float>, <4 x float>, metadata)
+declare float @llvm.experimental.constrained.minimum.f32(float, float, metadata)
+declare <4 x float> @llvm.experimental.constrained.minimum.v4f32(<4 x float>, <4 x float>, metadata)
 
 declare fp128 @llvm.experimental.constrained.minnum.f128(fp128, fp128, metadata)
+declare fp128 @llvm.experimental.constrained.minimum.f128(fp128, fp128, metadata)
 
 ; Test the f64 minnum intrinsic.
 define double @f1(double %dummy, double %val1, double %val2) #0 {
@@ -73,4 +78,67 @@ define void @f5(fp128 *%ptr1, fp128 *%ptr2, fp128 *%dst) #0 {
   ret void
 }
 
+; Test the f64 minimum intrinsic.
+define double @f11(double %dummy, double %val1, double %val2) #0 {
+; CHECK-LABEL: f11:
+; CHECK: wfmindb %f0, %f2, %f4, 1
+; CHECK: br %r14
+  %ret = call double @llvm.experimental.constrained.minimum.f64(
+                        double %val1, double %val2,
+                        metadata !"fpexcept.strict") #0
+  ret double %ret
+}
+
+; Test the v2f64 minimum intrinsic.
+define <2 x double> @f12(<2 x double> %dummy, <2 x double> %val1,
+                         <2 x double> %val2) #0 {
+; CHECK-LABEL: f12:
+; CHECK: vfmindb %v24, %v26, %v28, 1
+; CHECK: br %r14
+  %ret = call <2 x double> @llvm.experimental.constrained.minimum.v2f64(
+                        <2 x double> %val1, <2 x double> %val2,
+                        metadata !"fpexcept.strict") #0
+  ret <2 x double> %ret
+}
+
+; Test the f32 minimum intrinsic.
+define float @f13(float %dummy, float %val1, float %val2) #0 {
+; CHECK-LABEL: f13:
+; CHECK: wfminsb %f0, %f2, %f4, 1
+; CHECK: br %r14
+  %ret = call float @llvm.experimental.constrained.minimum.f32(
+                        float %val1, float %val2,
+                        metadata !"fpexcept.strict") #0
+  ret float %ret
+}
+
+; Test the v4f32 minimum intrinsic.
+define <4 x float> @f14(<4 x float> %dummy, <4 x float> %val1,
+                        <4 x float> %val2) #0 {
+; CHECK-LABEL: f14:
+; CHECK: vfminsb %v24, %v26, %v28, 1
+; CHECK: br %r14
+  %ret = call <4 x float> @llvm.experimental.constrained.minimum.v4f32(
+                        <4 x float> %val1, <4 x float> %val2,
+                        metadata !"fpexcept.strict") #0
+  ret <4 x float> %ret
+}
+
+; Test the f128 minimum intrinsic.
+define void @f15(fp128 *%ptr1, fp128 *%ptr2, fp128 *%dst) #0 {
+; CHECK-LABEL: f15:
+; CHECK-DAG: vl [[REG1:%v[0-9]+]], 0(%r2)
+; CHECK-DAG: vl [[REG2:%v[0-9]+]], 0(%r3)
+; CHECK: wfminxb [[RES:%v[0-9]+]], [[REG1]], [[REG2]], 1
+; CHECK: vst [[RES]], 0(%r4)
+; CHECK: br %r14
+  %val1 = load fp128, fp128* %ptr1
+  %val2 = load fp128, fp128* %ptr2
+  %res = call fp128 @llvm.experimental.constrained.minimum.f128(
+                        fp128 %val1, fp128 %val2,
+                        metadata !"fpexcept.strict") #0
+  store fp128 %res, fp128* %dst
+  ret void
+}
+
 attributes #0 = { strictfp }


        


More information about the llvm-commits mailing list