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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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
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)
[ 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 ]>;
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",
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)]>;
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";
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);
}
}
// 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 {
// 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 {
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 {
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 }
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 {
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 }