[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