[ConstantFolding] Enable folding of min/max/copysign for all floats
authorSerge Pavlov <sepavloff@gmail.com>
Wed, 9 Jun 2021 03:49:17 +0000 (10:49 +0700)
committerSerge Pavlov <sepavloff@gmail.com>
Thu, 10 Jun 2021 04:57:51 +0000 (11:57 +0700)
Previously such folding was enabled for half, float and double values
only. With this change it is allowed for other floating point values
also.

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

llvm/lib/Analysis/ConstantFolding.cpp
llvm/test/Transforms/InstSimplify/ConstProp/copysign.ll
llvm/test/Transforms/InstSimplify/ConstProp/min-max.ll

index 85aab19..3508e3c 100644 (file)
@@ -2362,7 +2362,7 @@ static Constant *ConstantFoldScalarCall2(StringRef Name,
   }
 
   if (auto *Op1 = dyn_cast<ConstantFP>(Operands[0])) {
-    if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy())
+    if (!Ty->isFloatingPointTy())
       return nullptr;
     APFloat Op1V = Op1->getValueAPF();
 
@@ -2374,8 +2374,6 @@ static Constant *ConstantFoldScalarCall2(StringRef Name,
       switch (IntrinsicID) {
       default:
         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:
@@ -2386,6 +2384,16 @@ static Constant *ConstantFoldScalarCall2(StringRef Name,
         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())
+        return nullptr;
+
+      switch (IntrinsicID) {
+      default:
+        break;
+      case Intrinsic::pow:
+        return ConstantFoldBinaryFP(pow, Op1V, Op2V, Ty);
       case Intrinsic::amdgcn_fmul_legacy:
         // The legacy behaviour is that multiplying +/- 0.0 by anything, even
         // NaN or infinity, gives +0.0.
index 6c0dfbb..35bc599 100644 (file)
@@ -57,8 +57,7 @@ define double @f64_03() {
 
 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_01() {
 
 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_02() {
 
 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 bfloat @bf16_03() {
 
 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_01() {
 
 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_02() {
 
 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 fp128 @f128_03() {
 
 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_01() {
 
 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_02() {
 
 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
index 4ef2fbf..975ff36 100644 (file)
@@ -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 @@ define float @minnum_float() {
   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 @@ define <4 x float> @minnum_float_vec() {
   ret <4 x float> %1
 }
 
+define <4 x bfloat> @minnum_bfloat_vec() {
+; CHECK-LABEL: @minnum_bfloat_vec(
+; CHECK-NEXT:    ret <4 x bfloat> <bfloat 0xR7FC0, bfloat 0xR40A0, bfloat 0xR4228, bfloat 0xR40A0>
+;
+  %1 = call <4 x bfloat> @llvm.minnum.v4bf16(<4 x bfloat> <bfloat 0x7FF8000000000000, bfloat 0x7FF8000000000000, bfloat 42., bfloat 42.>, <4 x bfloat> <bfloat 0x7FF8000000000000, bfloat 5., bfloat 0x7FF8000000000000, bfloat 5.>)
+  ret <4 x bfloat> %1
+}
+
+define <4 x half> @minnum_half_vec() {
+; CHECK-LABEL: @minnum_half_vec(
+; CHECK-NEXT:    ret <4 x half> <half 0xH7E00, half 0xH4500, half 0xH5140, half 0xH4500>
+;
+  %1 = call <4 x half> @llvm.minnum.v4f16(<4 x half> <half 0x7FF8000000000000, half 0x7FF8000000000000, half 42., half 42.>, <4 x half> <half 0x7FF8000000000000, half 5., half 0x7FF8000000000000, half 5.>)
+  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 @@ define float @maxnum_float() {
   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 @@ define <4 x float> @maxnum_float_vec() {
   ret <4 x float> %1
 }
 
+define <4 x bfloat> @maxnum_bfloat_vec() {
+; CHECK-LABEL: @maxnum_bfloat_vec(
+; CHECK-NEXT:    ret <4 x bfloat> <bfloat 0xR7FC0, bfloat 0xR40A0, bfloat 0xR4228, bfloat 0xR4228>
+;
+  %1 = call <4 x bfloat> @llvm.maxnum.v4bf16(<4 x bfloat> <bfloat 0x7FF8000000000000, bfloat 0x7FF8000000000000, bfloat 42., bfloat 42.>, <4 x bfloat> <bfloat 0x7FF8000000000000, bfloat 5., bfloat 0x7FF8000000000000, bfloat 5.>)
+  ret <4 x bfloat> %1
+}
+
+define <4 x half> @maxnum_half_vec() {
+; CHECK-LABEL: @maxnum_half_vec(
+; CHECK-NEXT:    ret <4 x half> <half 0xH7E00, half 0xH4500, half 0xH5140, half 0xH5140>
+;
+  %1 = call <4 x half> @llvm.maxnum.v4f16(<4 x half> <half 0x7FF8000000000000, half 0x7FF8000000000000, half 42., half 42.>, <4 x half> <half 0x7FF8000000000000, half 5., half 0x7FF8000000000000, half 5.>)
+  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 @@ define float @minimum_float() {
   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 @@ define <4 x float> @minimum_float_vec() {
   ret <4 x float> %1
 }
 
+define <4 x bfloat> @minimum_bfloat_vec() {
+; CHECK-LABEL: @minimum_bfloat_vec(
+; CHECK-NEXT:    ret <4 x bfloat> <bfloat 0xR7FC0, bfloat 0xR7FC0, bfloat 0xR7FC0, bfloat 0xR40A0>
+;
+  %1 = call <4 x bfloat> @llvm.minimum.v4bf16(<4 x bfloat> <bfloat 0x7FF8000000000000, bfloat 0x7FF8000000000000, bfloat 42., bfloat 42.>, <4 x bfloat> <bfloat 0x7FF8000000000000, bfloat 5., bfloat 0x7FF8000000000000, bfloat 5.>)
+  ret <4 x bfloat> %1
+}
+
+define <4 x half> @minimum_half_vec() {
+; CHECK-LABEL: @minimum_half_vec(
+; CHECK-NEXT:    ret <4 x half> <half 0xH7E00, half 0xH7E00, half 0xH7E00, half 0xH4500>
+;
+  %1 = call <4 x half> @llvm.minimum.v4f16(<4 x half> <half 0x7FF8000000000000, half 0x7FF8000000000000, half 42., half 42.>, <4 x half> <half 0x7FF8000000000000, half 5., half 0x7FF8000000000000, half 5.>)
+  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 @@ define float @maximum_float() {
   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 @@ define <4 x float> @maximum_float_vec() {
   ret <4 x float> %1
 }
 
+define <4 x bfloat> @maximum_bfloat_vec() {
+; CHECK-LABEL: @maximum_bfloat_vec(
+; CHECK-NEXT:    ret <4 x bfloat> <bfloat 0xR7FC0, bfloat 0xR7FC0, bfloat 0xR7FC0, bfloat 0xR4228>
+;
+  %1 = call <4 x bfloat> @llvm.maximum.v4bf16(<4 x bfloat> <bfloat 0x7FF8000000000000, bfloat 0x7FF8000000000000, bfloat 42., bfloat 42.>, <4 x bfloat> <bfloat 0x7FF8000000000000, bfloat 5., bfloat 0x7FF8000000000000, bfloat 5.>)
+  ret <4 x bfloat> %1
+}
+
+define <4 x half> @maximum_half_vec() {
+; CHECK-LABEL: @maximum_half_vec(
+; CHECK-NEXT:    ret <4 x half> <half 0xH7E00, half 0xH7E00, half 0xH7E00, half 0xH5140>
+;
+  %1 = call <4 x half> @llvm.maximum.v4f16(<4 x half> <half 0x7FF8000000000000, half 0x7FF8000000000000, half 42., half 42.>, <4 x half> <half 0x7FF8000000000000, half 5., half 0x7FF8000000000000, half 5.>)
+  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() {