diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 5b329e2f898f3..412a0e8979193 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -1642,6 +1642,8 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) { case Intrinsic::maxnum: case Intrinsic::minimum: case Intrinsic::maximum: + case Intrinsic::minimumnum: + case Intrinsic::maximumnum: case Intrinsic::log: case Intrinsic::log2: case Intrinsic::log10: @@ -2930,6 +2932,8 @@ static Constant *ConstantFoldIntrinsicCall2(Intrinsic::ID IntrinsicID, Type *Ty, case Intrinsic::minnum: case Intrinsic::maximum: case Intrinsic::minimum: + case Intrinsic::maximumnum: + case Intrinsic::minimumnum: case Intrinsic::nvvm_fmax_d: case Intrinsic::nvvm_fmin_d: // If one argument is undef, return the other argument. @@ -3030,6 +3034,10 @@ static Constant *ConstantFoldIntrinsicCall2(Intrinsic::ID IntrinsicID, Type *Ty, return ConstantFP::get(Ty->getContext(), minimum(Op1V, Op2V)); case Intrinsic::maximum: return ConstantFP::get(Ty->getContext(), maximum(Op1V, Op2V)); + case Intrinsic::minimumnum: + return ConstantFP::get(Ty->getContext(), minimumnum(Op1V, Op2V)); + case Intrinsic::maximumnum: + return ConstantFP::get(Ty->getContext(), maximumnum(Op1V, Op2V)); case Intrinsic::nvvm_fmax_d: case Intrinsic::nvvm_fmax_f: diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/fp-undef.ll b/llvm/test/Transforms/InstSimplify/ConstProp/fp-undef.ll index 6fa57a8a1467a..644fdf1daab01 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/fp-undef.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/fp-undef.ll @@ -5,6 +5,8 @@ declare <2 x double> @llvm.minnum.v2f64(<2 x double>, <2 x double>) declare <2 x double> @llvm.maxnum.v2f64(<2 x double>, <2 x double>) declare <2 x double> @llvm.minimum.v2f64(<2 x double>, <2 x double>) declare <2 x double> @llvm.maximum.v2f64(<2 x double>, <2 x double>) +declare <2 x double> @llvm.minimumnum.v2f64(<2 x double>, <2 x double>) +declare <2 x double> @llvm.maximumnum.v2f64(<2 x double>, <2 x double>) ; Constant folding - undef undef. @@ -538,6 +540,38 @@ define <2 x double> @frem_undef_op0_constant_vec(<2 x double> %x) { ret <2 x double> %r } +define <2 x double> @maximumnum_nan_op0_vec_partial_poison_op1_poison(<2 x double> %x) { +; CHECK-LABEL: @maximumnum_nan_op0_vec_partial_poison_op1_poison( +; CHECK-NEXT: ret <2 x double> +; + %r = call <2 x double> @llvm.maximumnum.v2f64(<2 x double> , <2 x double> poison) + ret <2 x double> %r +} + +define <2 x double> @maximumnum_nan_op1_vec_partial_poison_op0_poison(<2 x double> %x) { +; CHECK-LABEL: @maximumnum_nan_op1_vec_partial_poison_op0_poison( +; CHECK-NEXT: ret <2 x double> +; + %r = call <2 x double> @llvm.maximumnum.v2f64(<2 x double> poison, <2 x double> ) + ret <2 x double> %r +} + +define <2 x double> @minimumnum_nan_op0_vec_partial_poison_op1_poison(<2 x double> %x) { +; CHECK-LABEL: @minimumnum_nan_op0_vec_partial_poison_op1_poison( +; CHECK-NEXT: ret <2 x double> +; + %r = call <2 x double> @llvm.minimumnum.v2f64(<2 x double> , <2 x double> poison) + ret <2 x double> %r +} + +define <2 x double> @minimumnum_nan_op1_vec_partial_poison_op0_poison(<2 x double> %x) { +; CHECK-LABEL: @minimumnum_nan_op1_vec_partial_poison_op0_poison( +; CHECK-NEXT: ret <2 x double> +; + %r = call <2 x double> @llvm.minimumnum.v2f64(<2 x double> poison, <2 x double> ) + ret <2 x double> %r +} + define <2 x double> @maximum_nan_op0_vec_partial_undef_op1_undef(<2 x double> %x) { ; CHECK-LABEL: @maximum_nan_op0_vec_partial_undef_op1_undef( ; CHECK-NEXT: ret <2 x double> diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/min-max.ll b/llvm/test/Transforms/InstSimplify/ConstProp/min-max.ll index 9120649eb5c4f..a633d29179896 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/min-max.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/min-max.ll @@ -29,6 +29,20 @@ declare <4 x float> @llvm.maximum.v4f32(<4 x float>, <4 x float>) declare <4 x bfloat> @llvm.maximum.v4bf16(<4 x bfloat>, <4 x bfloat>) declare <4 x half> @llvm.maximum.v4f16(<4 x half>, <4 x half>) +declare float @llvm.minimumnum.f32(float, float) +declare bfloat @llvm.minimumnum.bf16(bfloat, bfloat) +declare half @llvm.minimumnum.f16(half, half) +declare <4 x float> @llvm.minimumnum.v4f32(<4 x float>, <4 x float>) +declare <4 x bfloat> @llvm.minimumnum.v4bf16(<4 x bfloat>, <4 x bfloat>) +declare <4 x half> @llvm.minimumnum.v4f16(<4 x half>, <4 x half>) + +declare float @llvm.maximumnum.f32(float, float) +declare bfloat @llvm.maximumnum.bf16(bfloat, bfloat) +declare half @llvm.maximumnum.f16(half, half) +declare <4 x float> @llvm.maximumnum.v4f32(<4 x float>, <4 x float>) +declare <4 x bfloat> @llvm.maximumnum.v4bf16(<4 x bfloat>, <4 x bfloat>) +declare <4 x half> @llvm.maximumnum.v4f16(<4 x half>, <4 x half>) + declare i8 @llvm.smax.i8(i8, i8) declare <5 x i8> @llvm.smax.v5i8(<5 x i8>, <5 x i8>) @@ -81,6 +95,22 @@ define float @minnum_float_qnan_p0() { ret float %min } +define float @minnum_float_p0_snan() { +; CHECK-LABEL: @minnum_float_p0_snan( +; CHECK-NEXT: ret float 0x7FFC000000000000 +; + %min = call float @llvm.minnum.f32(float 0.0, float 0x7FF4000000000000) + ret float %min +} + +define float @minnum_float_snan_p0() { +; CHECK-LABEL: @minnum_float_snan_p0( +; CHECK-NEXT: ret float 0x7FFC000000000000 +; + %min = call float @llvm.minnum.f32(float 0x7FF4000000000000, float 0.0) + ret float %min +} + define bfloat @minnum_bfloat() { ; CHECK-LABEL: @minnum_bfloat( ; CHECK-NEXT: ret bfloat 0xR40A0 @@ -173,6 +203,22 @@ define float @maxnum_float_qnan_p0() { ret float %max } +define float @maxnum_float_p0_snan() { +; CHECK-LABEL: @maxnum_float_p0_snan( +; CHECK-NEXT: ret float 0x7FFC000000000000 +; + %max = call float @llvm.maxnum.f32(float 0.0, float 0x7FF4000000000000) + ret float %max +} + +define float @maxnum_float_snan_p0() { +; CHECK-LABEL: @maxnum_float_snan_p0( +; CHECK-NEXT: ret float 0x7FFC000000000000 +; + %max = call float @llvm.maxnum.f32(float 0x7FF4000000000000, float 0.0) + ret float %max +} + define bfloat @maxnum_bfloat() { ; CHECK-LABEL: @maxnum_bfloat( ; CHECK-NEXT: ret bfloat 0xR4228 @@ -249,6 +295,38 @@ define half @minimum_half() { ret half %1 } +define float @minimum_float_p0_qnan() { +; CHECK-LABEL: @minimum_float_p0_qnan( +; CHECK-NEXT: ret float 0x7FF8000000000000 +; + %max = call float @llvm.minimum.f32(float 0.0, float 0x7FF8000000000000) + ret float %max +} + +define float @minimum_float_qnan_p0() { +; CHECK-LABEL: @minimum_float_qnan_p0( +; CHECK-NEXT: ret float 0x7FF8000000000000 +; + %max = call float @llvm.minimum.f32(float 0x7FF8000000000000, float 0.0) + ret float %max +} + +define float @minimum_float_p0_snan() { +; CHECK-LABEL: @minimum_float_p0_snan( +; CHECK-NEXT: ret float 0x7FFC000000000000 +; + %max = call float @llvm.minimum.f32(float 0.0, float 0x7FF4000000000000) + ret float %max +} + +define float @minimum_float_snan_p0() { +; CHECK-LABEL: @minimum_float_snan_p0( +; CHECK-NEXT: ret float 0x7FFC000000000000 +; + %max = call float @llvm.minimum.f32(float 0x7FF4000000000000, float 0.0) + ret float %max +} + ; Check that minimum propagates its NaN or smaller argument define <4 x float> @minimum_float_vec() { @@ -309,6 +387,38 @@ define half @maximum_half() { ret half %1 } +define float @maximum_float_p0_qnan() { +; CHECK-LABEL: @maximum_float_p0_qnan( +; CHECK-NEXT: ret float 0x7FF8000000000000 +; + %max = call float @llvm.maximum.f32(float 0.0, float 0x7FF8000000000000) + ret float %max +} + +define float @maximum_float_qnan_p0() { +; CHECK-LABEL: @maximum_float_qnan_p0( +; CHECK-NEXT: ret float 0x7FF8000000000000 +; + %max = call float @llvm.maximum.f32(float 0x7FF8000000000000, float 0.0) + ret float %max +} + +define float @maximum_float_p0_snan() { +; CHECK-LABEL: @maximum_float_p0_snan( +; CHECK-NEXT: ret float 0x7FFC000000000000 +; + %max = call float @llvm.maximum.f32(float 0.0, float 0x7FF4000000000000) + ret float %max +} + +define float @maximum_float_snan_p0() { +; CHECK-LABEL: @maximum_float_snan_p0( +; CHECK-NEXT: ret float 0x7FFC000000000000 +; + %max = call float @llvm.maximum.f32(float 0x7FF4000000000000, float 0.0) + ret float %max +} + ; Check that maximum propagates its NaN or greater argument define <4 x float> @maximum_float_vec() { @@ -345,6 +455,222 @@ define <4 x float> @maximum_float_zeros_vec() { ret <4 x float> %1 } +define float @minimumnum_float() { +; CHECK-LABEL: @minimumnum_float( +; CHECK-NEXT: ret float 5.000000e+00 +; + %1 = call float @llvm.minimumnum.f32(float 5.0, float 42.0) + ret float %1 +} + +define float @minimumnum_float_p0_n0() { +; CHECK-LABEL: @minimumnum_float_p0_n0( +; CHECK-NEXT: ret float -0.000000e+00 +; + %min = call float @llvm.minimumnum.f32(float 0.0, float -0.0) + ret float %min +} + +define float @minimumnum_float_n0_p0() { +; CHECK-LABEL: @minimumnum_float_n0_p0( +; CHECK-NEXT: ret float -0.000000e+00 +; + %min = call float @llvm.minimumnum.f32(float -0.0, float 0.0) + ret float %min +} + +define float @minimumnum_float_p0_qnan() { +; CHECK-LABEL: @minimumnum_float_p0_qnan( +; CHECK-NEXT: ret float 0.000000e+00 +; + %min = call float @llvm.minimumnum.f32(float 0.0, float 0x7FF8000000000000) + ret float %min +} + +define float @minimumnum_float_qnan_p0() { +; CHECK-LABEL: @minimumnum_float_qnan_p0( +; CHECK-NEXT: ret float 0.000000e+00 +; + %min = call float @llvm.minimumnum.f32(float 0x7FF8000000000000, float 0.0) + ret float %min +} + +define float @minimumnum_float_p0_snan() { +; CHECK-LABEL: @minimumnum_float_p0_snan( +; CHECK-NEXT: ret float 0.000000e+00 +; + %min = call float @llvm.minimumnum.f32(float 0.0, float 0x7FF4000000000000) + ret float %min +} + +define float @minimumnum_float_snan_p0() { +; CHECK-LABEL: @minimumnum_float_snan_p0( +; CHECK-NEXT: ret float 0.000000e+00 +; + %min = call float @llvm.minimumnum.f32(float 0x7FF4000000000000, float 0.0) + ret float %min +} + +define bfloat @minimumnum_bfloat() { +; CHECK-LABEL: @minimumnum_bfloat( +; CHECK-NEXT: ret bfloat 0xR40A0 +; + %1 = call bfloat @llvm.minimumnum.bf16(bfloat 5.0, bfloat 42.0) + ret bfloat %1 +} + +define half @minimumnum_half() { +; CHECK-LABEL: @minimumnum_half( +; CHECK-NEXT: ret half 0xH4500 +; + %1 = call half @llvm.minimumnum.f16(half 5.0, half 42.0) + ret half %1 +} + +; Check that minimumnum propagates its non-NaN or smaller argument + +define <4 x float> @minimumnum_float_vec() { +; CHECK-LABEL: @minimumnum_float_vec( +; CHECK-NEXT: ret <4 x float> +; + %1 = call <4 x float> @llvm.minimumnum.v4f32(<4 x float> , <4 x float> ) + ret <4 x float> %1 +} + +define <4 x bfloat> @minimumnum_bfloat_vec() { +; CHECK-LABEL: @minimumnum_bfloat_vec( +; CHECK-NEXT: ret <4 x bfloat> +; + %1 = call <4 x bfloat> @llvm.minimumnum.v4bf16(<4 x bfloat> , <4 x bfloat> ) + ret <4 x bfloat> %1 +} + +define <4 x half> @minimumnum_half_vec() { +; CHECK-LABEL: @minimumnum_half_vec( +; CHECK-NEXT: ret <4 x half> +; + %1 = call <4 x half> @llvm.minimumnum.v4f16(<4 x half> , <4 x half> ) + ret <4 x half> %1 +} + +; Check that minimumnum treats -0.0 as smaller than 0.0 while constant folding + +define <4 x float> @minimumnum_float_zeros_vec() { +; CHECK-LABEL: @minimumnum_float_zeros_vec( +; CHECK-NEXT: ret <4 x float> +; + %1 = call <4 x float> @llvm.minimumnum.v4f32(<4 x float> , <4 x float> ) + ret <4 x float> %1 +} + +define float @maximumnum_float() { +; CHECK-LABEL: @maximumnum_float( +; CHECK-NEXT: ret float 4.200000e+01 +; + %1 = call float @llvm.maximumnum.f32(float 5.0, float 42.0) + ret float %1 +} + +define bfloat @maximumnum_bfloat() { +; CHECK-LABEL: @maximumnum_bfloat( +; CHECK-NEXT: ret bfloat 0xR4228 +; + %1 = call bfloat @llvm.maximumnum.bf16(bfloat 5.0, bfloat 42.0) + ret bfloat %1 +} + +define half @maximumnum_half() { +; CHECK-LABEL: @maximumnum_half( +; CHECK-NEXT: ret half 0xH5140 +; + %1 = call half @llvm.maximumnum.f16(half 5.0, half 42.0) + ret half %1 +} + +define float @maximumnum_float_p0_n0() { +; CHECK-LABEL: @maximumnum_float_p0_n0( +; CHECK-NEXT: ret float 0.000000e+00 +; + %max = call float @llvm.maximumnum.f32(float 0.0, float -0.0) + ret float %max +} + +define float @maximumnum_float_n0_p0() { +; CHECK-LABEL: @maximumnum_float_n0_p0( +; CHECK-NEXT: ret float 0.000000e+00 +; + %max = call float @llvm.maximumnum.f32(float -0.0, float 0.0) + ret float %max +} + +define float @maximumnum_float_p0_qnan() { +; CHECK-LABEL: @maximumnum_float_p0_qnan( +; CHECK-NEXT: ret float 0.000000e+00 +; + %max = call float @llvm.maximumnum.f32(float 0.0, float 0x7FF8000000000000) + ret float %max +} + +define float @maximumnum_float_qnan_p0() { +; CHECK-LABEL: @maximumnum_float_qnan_p0( +; CHECK-NEXT: ret float 0.000000e+00 +; + %max = call float @llvm.maximumnum.f32(float 0x7FF8000000000000, float 0.0) + ret float %max +} + +define float @maximumnum_float_p0_snan() { +; CHECK-LABEL: @maximumnum_float_p0_snan( +; CHECK-NEXT: ret float 0.000000e+00 +; + %max = call float @llvm.maximumnum.f32(float 0.0, float 0x7FF4000000000000) + ret float %max +} + +define float @maximumnum_float_snan_p0() { +; CHECK-LABEL: @maximumnum_float_snan_p0( +; CHECK-NEXT: ret float 0.000000e+00 +; + %max = call float @llvm.maximumnum.f32(float 0x7FF4000000000000, float 0.0) + ret float %max +} + +; Check that maximumnum propagates its non-NaN or greater argument + +define <4 x float> @maximumnum_float_vec() { +; CHECK-LABEL: @maximumnum_float_vec( +; CHECK-NEXT: ret <4 x float> +; + %1 = call <4 x float> @llvm.maximumnum.v4f32(<4 x float> , <4 x float> ) + ret <4 x float> %1 +} + +define <4 x bfloat> @maximumnum_bfloat_vec() { +; CHECK-LABEL: @maximumnum_bfloat_vec( +; CHECK-NEXT: ret <4 x bfloat> +; + %1 = call <4 x bfloat> @llvm.maximumnum.v4bf16(<4 x bfloat> , <4 x bfloat> ) + ret <4 x bfloat> %1 +} + +define <4 x half> @maximumnum_half_vec() { +; CHECK-LABEL: @maximumnum_half_vec( +; CHECK-NEXT: ret <4 x half> +; + %1 = call <4 x half> @llvm.maximumnum.v4f16(<4 x half> , <4 x half> ) + ret <4 x half> %1 +} + +; Check that maximumnum treats -0.0 as smaller than 0.0 while constant folding + +define <4 x float> @maximumnum_float_zeros_vec() { +; CHECK-LABEL: @maximumnum_float_zeros_vec( +; CHECK-NEXT: ret <4 x float> +; + %1 = call <4 x float> @llvm.maximumnum.v4f32(<4 x float> , <4 x float> ) + ret <4 x float> %1 +} + define i8 @smax() { ; CHECK-LABEL: @smax( ; CHECK-NEXT: ret i8 -127