diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -2457,6 +2457,22 @@ St)) return ConstantFP::get(Ty->getContext(), Res); return nullptr; + } else { + switch (IntrinsicID) { + default: + break; + case Intrinsic::copysign: + return ConstantFP::get(Ty->getContext(), + APFloat::copySign(Op1V, Op2V)); + case Intrinsic::minnum: + return ConstantFP::get(Ty->getContext(), minnum(Op1V, Op2V)); + case Intrinsic::maxnum: + return ConstantFP::get(Ty->getContext(), maxnum(Op1V, Op2V)); + case Intrinsic::minimum: + return ConstantFP::get(Ty->getContext(), minimum(Op1V, Op2V)); + case Intrinsic::maximum: + return ConstantFP::get(Ty->getContext(), maximum(Op1V, Op2V)); + } } if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy()) @@ -2467,16 +2483,6 @@ break; case Intrinsic::pow: return ConstantFoldBinaryFP(pow, Op1V, Op2V, Ty); - case Intrinsic::copysign: - return ConstantFP::get(Ty->getContext(), APFloat::copySign(Op1V, Op2V)); - case Intrinsic::minnum: - return ConstantFP::get(Ty->getContext(), minnum(Op1V, Op2V)); - case Intrinsic::maxnum: - return ConstantFP::get(Ty->getContext(), maxnum(Op1V, Op2V)); - case Intrinsic::minimum: - return ConstantFP::get(Ty->getContext(), minimum(Op1V, Op2V)); - case Intrinsic::maximum: - return ConstantFP::get(Ty->getContext(), maximum(Op1V, Op2V)); case Intrinsic::amdgcn_fmul_legacy: // The legacy behaviour is that multiplying +/- 0.0 by anything, even // NaN or infinity, gives +0.0. diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/copysign.ll b/llvm/test/Transforms/InstSimplify/ConstProp/copysign.ll --- a/llvm/test/Transforms/InstSimplify/ConstProp/copysign.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/copysign.ll @@ -57,8 +57,7 @@ define bfloat @bf16_01() { ; CHECK-LABEL: @bf16_01( -; CHECK-NEXT: [[X:%.*]] = call bfloat @llvm.copysign.bf16(bfloat 0xR3F80, bfloat 0xRC000) -; CHECK-NEXT: ret bfloat [[X]] +; CHECK-NEXT: ret bfloat 0xRBF80 ; %x = call bfloat @llvm.copysign.bf16(bfloat 1.0, bfloat -2.0) ret bfloat %x @@ -66,8 +65,7 @@ define bfloat @bf16_02() { ; CHECK-LABEL: @bf16_02( -; CHECK-NEXT: [[X:%.*]] = call bfloat @llvm.copysign.bf16(bfloat 0xRC000, bfloat 0xR3F80) -; CHECK-NEXT: ret bfloat [[X]] +; CHECK-NEXT: ret bfloat 0xR4000 ; %x = call bfloat @llvm.copysign.bf16(bfloat -2.0, bfloat 1.0) ret bfloat %x @@ -75,8 +73,7 @@ define bfloat @bf16_03() { ; CHECK-LABEL: @bf16_03( -; CHECK-NEXT: [[X:%.*]] = call bfloat @llvm.copysign.bf16(bfloat 0xRC000, bfloat 0xRBF80) -; CHECK-NEXT: ret bfloat [[X]] +; CHECK-NEXT: ret bfloat 0xRC000 ; %x = call bfloat @llvm.copysign.bf16(bfloat -2.0, bfloat -1.0) ret bfloat %x @@ -84,8 +81,7 @@ define fp128 @f128_01() { ; CHECK-LABEL: @f128_01( -; CHECK-NEXT: [[X:%.*]] = call fp128 @llvm.copysign.f128(fp128 0xL00000000000000000000000000000001, fp128 0xL00000000000000008000000000000002) -; CHECK-NEXT: ret fp128 [[X]] +; CHECK-NEXT: ret fp128 0xL00000000000000008000000000000001 ; %x = call fp128 @llvm.copysign.f128(fp128 0xL00000000000000000000000000000001, fp128 0xL00000000000000008000000000000002) ret fp128 %x @@ -93,8 +89,7 @@ define fp128 @f128_02() { ; CHECK-LABEL: @f128_02( -; CHECK-NEXT: [[X:%.*]] = call fp128 @llvm.copysign.f128(fp128 0xL00000000000000008000000000000003, fp128 0xL00000000000000000000000000000004) -; CHECK-NEXT: ret fp128 [[X]] +; CHECK-NEXT: ret fp128 0xL00000000000000000000000000000003 ; %x = call fp128 @llvm.copysign.f128(fp128 0xL00000000000000008000000000000003, fp128 0xL00000000000000000000000000000004) ret fp128 %x @@ -102,8 +97,7 @@ define fp128 @f128_03() { ; CHECK-LABEL: @f128_03( -; CHECK-NEXT: [[X:%.*]] = call fp128 @llvm.copysign.f128(fp128 0xL00000000000000008000000000000005, fp128 0xL00000000000000008000000000000006) -; CHECK-NEXT: ret fp128 [[X]] +; CHECK-NEXT: ret fp128 0xL00000000000000008000000000000005 ; %x = call fp128 @llvm.copysign.f128(fp128 0xL00000000000000008000000000000005, fp128 0xL00000000000000008000000000000006) ret fp128 %x @@ -111,8 +105,7 @@ define ppc_fp128 @ppc128_01() { ; CHECK-LABEL: @ppc128_01( -; CHECK-NEXT: [[X:%.*]] = call ppc_fp128 @llvm.copysign.ppcf128(ppc_fp128 0xM00000000000000000000000000000001, ppc_fp128 0xM80000000000000000000000000000002) -; CHECK-NEXT: ret ppc_fp128 [[X]] +; CHECK-NEXT: ret ppc_fp128 0xM80000000000000008000000000000001 ; %x = call ppc_fp128 @llvm.copysign.ppcf128(ppc_fp128 0xM00000000000000000000000000000001, ppc_fp128 0xM80000000000000000000000000000002) ret ppc_fp128 %x @@ -120,8 +113,7 @@ define ppc_fp128 @ppc128_02() { ; CHECK-LABEL: @ppc128_02( -; CHECK-NEXT: [[X:%.*]] = call ppc_fp128 @llvm.copysign.ppcf128(ppc_fp128 0xM80000000000000000000000000000003, ppc_fp128 0xM00000000000000000000000000000004) -; CHECK-NEXT: ret ppc_fp128 [[X]] +; CHECK-NEXT: ret ppc_fp128 0xM00000000000000008000000000000003 ; %x = call ppc_fp128 @llvm.copysign.ppcf128(ppc_fp128 0xM80000000000000000000000000000003, ppc_fp128 0xM00000000000000000000000000000004) ret ppc_fp128 %x @@ -129,8 +121,7 @@ define ppc_fp128 @ppc128_03() { ; CHECK-LABEL: @ppc128_03( -; CHECK-NEXT: [[X:%.*]] = call ppc_fp128 @llvm.copysign.ppcf128(ppc_fp128 0xM80000000000000000000000000000005, ppc_fp128 0xM80000000000000000000000000000006) -; CHECK-NEXT: ret ppc_fp128 [[X]] +; CHECK-NEXT: ret ppc_fp128 0xM80000000000000000000000000000005 ; %x = call ppc_fp128 @llvm.copysign.ppcf128(ppc_fp128 0xM80000000000000000000000000000005, ppc_fp128 0xM80000000000000000000000000000006) ret ppc_fp128 %x diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/min-max.ll b/llvm/test/Transforms/InstSimplify/ConstProp/min-max.ll --- a/llvm/test/Transforms/InstSimplify/ConstProp/min-max.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/min-max.ll @@ -2,16 +2,32 @@ ; RUN: opt -instsimplify -S < %s | FileCheck %s declare float @llvm.minnum.f32(float, float) +declare bfloat @llvm.minnum.bf16(bfloat, bfloat) +declare half @llvm.minnum.f16(half, half) declare <4 x float> @llvm.minnum.v4f32(<4 x float>, <4 x float>) +declare <4 x bfloat> @llvm.minnum.v4bf16(<4 x bfloat>, <4 x bfloat>) +declare <4 x half> @llvm.minnum.v4f16(<4 x half>, <4 x half>) declare float @llvm.maxnum.f32(float, float) +declare bfloat @llvm.maxnum.bf16(bfloat, bfloat) +declare half @llvm.maxnum.f16(half, half) declare <4 x float> @llvm.maxnum.v4f32(<4 x float>, <4 x float>) +declare <4 x bfloat> @llvm.maxnum.v4bf16(<4 x bfloat>, <4 x bfloat>) +declare <4 x half> @llvm.maxnum.v4f16(<4 x half>, <4 x half>) declare float @llvm.minimum.f32(float, float) +declare bfloat @llvm.minimum.bf16(bfloat, bfloat) +declare half @llvm.minimum.f16(half, half) declare <4 x float> @llvm.minimum.v4f32(<4 x float>, <4 x float>) +declare <4 x bfloat> @llvm.minimum.v4bf16(<4 x bfloat>, <4 x bfloat>) +declare <4 x half> @llvm.minimum.v4f16(<4 x half>, <4 x half>) declare float @llvm.maximum.f32(float, float) +declare bfloat @llvm.maximum.bf16(bfloat, bfloat) +declare half @llvm.maximum.f16(half, half) 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 i8 @llvm.smax.i8(i8, i8) declare <5 x i8> @llvm.smax.v5i8(<5 x i8>, <5 x i8>) @@ -33,6 +49,22 @@ ret float %1 } +define bfloat @minnum_bfloat() { +; CHECK-LABEL: @minnum_bfloat( +; CHECK-NEXT: ret bfloat 0xR40A0 +; + %1 = call bfloat @llvm.minnum.bf16(bfloat 5.0, bfloat 42.0) + ret bfloat %1 +} + +define half @minnum_half() { +; CHECK-LABEL: @minnum_half( +; CHECK-NEXT: ret half 0xH4500 +; + %1 = call half @llvm.minnum.f16(half 5.0, half 42.0) + ret half %1 +} + ; Check that minnum constant folds to propagate non-NaN or smaller argument define <4 x float> @minnum_float_vec() { @@ -43,6 +75,22 @@ ret <4 x float> %1 } +define <4 x bfloat> @minnum_bfloat_vec() { +; CHECK-LABEL: @minnum_bfloat_vec( +; CHECK-NEXT: ret <4 x bfloat> +; + %1 = call <4 x bfloat> @llvm.minnum.v4bf16(<4 x bfloat> , <4 x bfloat> ) + ret <4 x bfloat> %1 +} + +define <4 x half> @minnum_half_vec() { +; CHECK-LABEL: @minnum_half_vec( +; CHECK-NEXT: ret <4 x half> +; + %1 = call <4 x half> @llvm.minnum.v4f16(<4 x half> , <4 x half> ) + ret <4 x half> %1 +} + ; Check that minnum constant folds to propagate one of its argument zeros define <4 x float> @minnum_float_zeros_vec() { @@ -61,6 +109,22 @@ ret float %1 } +define bfloat @maxnum_bfloat() { +; CHECK-LABEL: @maxnum_bfloat( +; CHECK-NEXT: ret bfloat 0xR4228 +; + %1 = call bfloat @llvm.maxnum.bf16(bfloat 5.0, bfloat 42.0) + ret bfloat %1 +} + +define half @maxnum_half() { +; CHECK-LABEL: @maxnum_half( +; CHECK-NEXT: ret half 0xH5140 +; + %1 = call half @llvm.maxnum.f16(half 5.0, half 42.0) + ret half %1 +} + ; Check that maxnum constant folds to propagate non-NaN or greater argument define <4 x float> @maxnum_float_vec() { @@ -71,6 +135,22 @@ ret <4 x float> %1 } +define <4 x bfloat> @maxnum_bfloat_vec() { +; CHECK-LABEL: @maxnum_bfloat_vec( +; CHECK-NEXT: ret <4 x bfloat> +; + %1 = call <4 x bfloat> @llvm.maxnum.v4bf16(<4 x bfloat> , <4 x bfloat> ) + ret <4 x bfloat> %1 +} + +define <4 x half> @maxnum_half_vec() { +; CHECK-LABEL: @maxnum_half_vec( +; CHECK-NEXT: ret <4 x half> +; + %1 = call <4 x half> @llvm.maxnum.v4f16(<4 x half> , <4 x half> ) + ret <4 x half> %1 +} + ; Check that maxnum constant folds to propagate one of its argument zeros define <4 x float> @maxnum_float_zeros_vec() { @@ -89,6 +169,22 @@ ret float %1 } +define bfloat @minimum_bfloat() { +; CHECK-LABEL: @minimum_bfloat( +; CHECK-NEXT: ret bfloat 0xR40A0 +; + %1 = call bfloat @llvm.minimum.bf16(bfloat 5.0, bfloat 42.0) + ret bfloat %1 +} + +define half @minimum_half() { +; CHECK-LABEL: @minimum_half( +; CHECK-NEXT: ret half 0xH4500 +; + %1 = call half @llvm.minimum.f16(half 5.0, half 42.0) + ret half %1 +} + ; Check that minimum propagates its NaN or smaller argument define <4 x float> @minimum_float_vec() { @@ -99,6 +195,22 @@ ret <4 x float> %1 } +define <4 x bfloat> @minimum_bfloat_vec() { +; CHECK-LABEL: @minimum_bfloat_vec( +; CHECK-NEXT: ret <4 x bfloat> +; + %1 = call <4 x bfloat> @llvm.minimum.v4bf16(<4 x bfloat> , <4 x bfloat> ) + ret <4 x bfloat> %1 +} + +define <4 x half> @minimum_half_vec() { +; CHECK-LABEL: @minimum_half_vec( +; CHECK-NEXT: ret <4 x half> +; + %1 = call <4 x half> @llvm.minimum.v4f16(<4 x half> , <4 x half> ) + ret <4 x half> %1 +} + ; Check that minimum treats -0.0 as smaller than 0.0 while constant folding define <4 x float> @minimum_float_zeros_vec() { @@ -117,6 +229,22 @@ ret float %1 } +define bfloat @maximum_bfloat() { +; CHECK-LABEL: @maximum_bfloat( +; CHECK-NEXT: ret bfloat 0xR4228 +; + %1 = call bfloat @llvm.maximum.bf16(bfloat 5.0, bfloat 42.0) + ret bfloat %1 +} + +define half @maximum_half() { +; CHECK-LABEL: @maximum_half( +; CHECK-NEXT: ret half 0xH5140 +; + %1 = call half @llvm.maximum.f16(half 5.0, half 42.0) + ret half %1 +} + ; Check that maximum propagates its NaN or greater argument define <4 x float> @maximum_float_vec() { @@ -127,6 +255,22 @@ ret <4 x float> %1 } +define <4 x bfloat> @maximum_bfloat_vec() { +; CHECK-LABEL: @maximum_bfloat_vec( +; CHECK-NEXT: ret <4 x bfloat> +; + %1 = call <4 x bfloat> @llvm.maximum.v4bf16(<4 x bfloat> , <4 x bfloat> ) + ret <4 x bfloat> %1 +} + +define <4 x half> @maximum_half_vec() { +; CHECK-LABEL: @maximum_half_vec( +; CHECK-NEXT: ret <4 x half> +; + %1 = call <4 x half> @llvm.maximum.v4f16(<4 x half> , <4 x half> ) + ret <4 x half> %1 +} + ; Check that maximum treats -0.0 as smaller than 0.0 while constant folding define <4 x float> @maximum_float_zeros_vec() {