[llvm] r369120 - [InstCombine] Simplify pow(2.0, itofp(y)) to ldexp(1.0, y)

Evandro Menezes via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 16 08:33:41 PDT 2019


Author: evandro
Date: Fri Aug 16 08:33:41 2019
New Revision: 369120

URL: http://llvm.org/viewvc/llvm-project?rev=369120&view=rev
Log:
[InstCombine] Simplify pow(2.0, itofp(y)) to ldexp(1.0, y)

Simplify `pow(2.0, itofp(y))` to `ldexp(1.0, y)`.

Differential revision: https://reviews.llvm.org/D65979

Modified:
    llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp
    llvm/trunk/test/Transforms/InstCombine/pow_fp_int.ll

Modified: llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp?rev=369120&r1=369119&r2=369120&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp Fri Aug 16 08:33:41 2019
@@ -1284,9 +1284,25 @@ static Value *getPow(Value *InnerChain[3
   return InnerChain[Exp];
 }
 
+// Return a properly extended 32-bit integer if the operation is an itofp.
+static Value *getIntToFPVal(Value *I2F, IRBuilder<> &B) {
+  if (isa<SIToFPInst>(I2F) || isa<UIToFPInst>(I2F)) {
+    Value *Op = cast<Instruction>(I2F)->getOperand(0);
+    // Make sure that the exponent fits inside an int32_t,
+    // thus avoiding any range issues that FP has not.
+    unsigned BitWidth = Op->getType()->getPrimitiveSizeInBits();
+    if (BitWidth < 32 ||
+        (BitWidth == 32 && isa<SIToFPInst>(I2F)))
+      return isa<SIToFPInst>(I2F) ? B.CreateSExt(Op, B.getInt32Ty())
+                                  : B.CreateZExt(Op, B.getInt32Ty());
+  }
+
+  return nullptr;
+}
+
 /// Use exp{,2}(x * y) for pow(exp{,2}(x), y);
-/// exp2(n * x) for pow(2.0 ** n, x); exp10(x) for pow(10.0, x);
-/// exp2(log2(n) * x) for pow(n, x).
+/// ldexp(1.0, x) for pow(2.0, itofp(x)); exp2(n * x) for pow(2.0 ** n, x);
+/// exp10(x) for pow(10.0, x); exp2(log2(n) * x) for pow(n, x).
 Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilder<> &B) {
   Value *Base = Pow->getArgOperand(0), *Expo = Pow->getArgOperand(1);
   AttributeList Attrs = Pow->getCalledFunction()->getAttributes();
@@ -1368,6 +1384,16 @@ Value *LibCallSimplifier::replacePowWith
   if (!match(Pow->getArgOperand(0), m_APFloat(BaseF)))
     return nullptr;
 
+  // pow(2.0, itofp(x)) -> ldexp(1.0, x)
+  if (match(Base, m_SpecificFP(2.0)) &&
+      (isa<SIToFPInst>(Expo) || isa<UIToFPInst>(Expo)) &&
+      hasFloatFn(TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl)) {
+    if (Value *ExpoI = getIntToFPVal(Expo, B))
+      return emitBinaryFloatFnCall(ConstantFP::get(Ty, 1.0), ExpoI, TLI,
+                                   LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl,
+                                   B, Attrs);
+  }
+
   // pow(2.0 ** n, x) -> exp2(n * x)
   if (hasFloatFn(TLI, Ty, LibFunc_exp2, LibFunc_exp2f, LibFunc_exp2l)) {
     APFloat BaseR = APFloat(1.0);
@@ -1605,16 +1631,8 @@ Value *LibCallSimplifier::optimizePow(Ca
 
   // powf(x, itofp(y)) -> powi(x, y)
   if (AllowApprox && (isa<SIToFPInst>(Expo) || isa<UIToFPInst>(Expo))) {
-    Value *IntExpo = cast<Instruction>(Expo)->getOperand(0);
-    Value *NewExpo = nullptr;
-    unsigned BitWidth = IntExpo->getType()->getPrimitiveSizeInBits();
-    if (isa<SIToFPInst>(Expo) && BitWidth == 32)
-      NewExpo = IntExpo;
-    else if (BitWidth < 32)
-      NewExpo = isa<SIToFPInst>(Expo) ? B.CreateSExt(IntExpo, B.getInt32Ty())
-                                      : B.CreateZExt(IntExpo, B.getInt32Ty());
-    if (NewExpo)
-      return createPowWithIntegerExponent(Base, NewExpo, M, B);
+    if (Value *ExpoI = getIntToFPVal(Expo, B))
+      return createPowWithIntegerExponent(Base, ExpoI, M, B);
   }
 
   return Shrunk;
@@ -1635,20 +1653,12 @@ Value *LibCallSimplifier::optimizeExp2(C
   // Turn exp2(uitofp(x)) -> ldexp(1.0, zext(x))  if sizeof(x) < 32
   if ((isa<SIToFPInst>(Op) || isa<UIToFPInst>(Op)) &&
       hasFloatFn(TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl)) {
-    Instruction *OpC = cast<Instruction>(Op);
-    Value *Exp = OpC->getOperand(0);
-    unsigned BitWidth = Exp->getType()->getPrimitiveSizeInBits();
-
-    if (BitWidth < 32 ||
-        (BitWidth == 32 && isa<SIToFPInst>(Op))) {
-      Exp = isa<SIToFPInst>(Op) ? B.CreateSExt(Exp, B.getInt32Ty())
-                                : B.CreateZExt(Exp, B.getInt32Ty());
-
+    if (Value *Exp = getIntToFPVal(Op, B))
       return emitBinaryFloatFnCall(ConstantFP::get(Ty, 1.0), Exp, TLI,
                                    LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl,
                                    B, CI->getCalledFunction()->getAttributes());
-    }
   }
+
   return Ret;
 }
 

Modified: llvm/trunk/test/Transforms/InstCombine/pow_fp_int.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/pow_fp_int.ll?rev=369120&r1=369119&r2=369120&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/pow_fp_int.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/pow_fp_int.ll Fri Aug 16 08:33:41 2019
@@ -49,6 +49,18 @@ define double @pow_uitofp_double_const_b
   ret double %pow
 }
 
+define double @pow_sitofp_double_const_base_2_fast(i32 %x) {
+; CHECK-LABEL: @pow_sitofp_double_const_base_2_fast(
+; CHECK-NEXT:    [[LDEXPF:%.*]] = call afn float @ldexpf(float 1.000000e+00, i32 [[X:%.*]]) #1
+; CHECK-NEXT:    [[RES:%.*]] = fpext float [[LDEXPF]] to double
+; CHECK-NEXT:    ret double [[RES]]
+;
+  %subfp = sitofp i32 %x to float
+  %pow = tail call afn float @llvm.pow.f32(float 2.000000e+00, float %subfp)
+  %res = fpext float %pow to double
+  ret double %res
+}
+
 define double @pow_sitofp_double_const_base_power_of_2_fast(i32 %x) {
 ; CHECK-LABEL: @pow_sitofp_double_const_base_power_of_2_fast(
 ; CHECK-NEXT:    [[SUBFP:%.*]] = sitofp i32 [[X:%.*]] to float
@@ -63,6 +75,19 @@ define double @pow_sitofp_double_const_b
   ret double %res
 }
 
+define double @pow_uitofp_const_base_2_fast(i31 %x) {
+; CHECK-LABEL: @pow_uitofp_const_base_2_fast(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i31 [[X:%.*]] to i32
+; CHECK-NEXT:    [[LDEXPF:%.*]] = call afn float @ldexpf(float 1.000000e+00, i32 [[TMP1]]) #1
+; CHECK-NEXT:    [[RES:%.*]] = fpext float [[LDEXPF]] to double
+; CHECK-NEXT:    ret double [[RES]]
+;
+  %subfp = uitofp i31 %x to float
+  %pow = tail call afn float @llvm.pow.f32(float 2.000000e+00, float %subfp)
+  %res = fpext float %pow to double
+  ret double %res
+}
+
 define double @pow_uitofp_const_base_power_of_2_fast(i31 %x) {
 ; CHECK-LABEL: @pow_uitofp_const_base_power_of_2_fast(
 ; CHECK-NEXT:    [[SUBFP:%.*]] = uitofp i31 [[X:%.*]] to float
@@ -210,6 +235,19 @@ define double @pow_uitofp_const_base_fas
   ret double %res
 }
 
+define double @pow_uitofp_const_base_2_fast_i32(i32 %x) {
+; CHECK-LABEL: @pow_uitofp_const_base_2_fast_i32(
+; CHECK-NEXT:    [[SUBFP:%.*]] = uitofp i32 [[X:%.*]] to float
+; CHECK-NEXT:    [[EXP2:%.*]] = call fast float @llvm.exp2.f32(float [[SUBFP]])
+; CHECK-NEXT:    [[RES:%.*]] = fpext float [[EXP2]] to double
+; CHECK-NEXT:    ret double [[RES]]
+;
+  %subfp = uitofp i32 %x to float
+  %pow = tail call fast float @llvm.pow.f32(float 2.000000e+00, float %subfp)
+  %res = fpext float %pow to double
+  ret double %res
+}
+
 define double @pow_uitofp_const_base_power_of_2_fast_i32(i32 %x) {
 ; CHECK-LABEL: @pow_uitofp_const_base_power_of_2_fast_i32(
 ; CHECK-NEXT:    [[SUBFP:%.*]] = uitofp i32 [[X:%.*]] to float
@@ -303,6 +341,18 @@ define double @pow_uitofp_const_base_no_
   ret double %res
 }
 
+define double @pow_sitofp_const_base_2_no_fast(i32 %x) {
+; CHECK-LABEL: @pow_sitofp_const_base_2_no_fast(
+; CHECK-NEXT:    [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i32 [[X:%.*]]) #1
+; CHECK-NEXT:    [[RES:%.*]] = fpext float [[LDEXPF]] to double
+; CHECK-NEXT:    ret double [[RES]]
+;
+  %subfp = sitofp i32 %x to float
+  %pow = tail call float @llvm.pow.f32(float 2.000000e+00, float %subfp)
+  %res = fpext float %pow to double
+  ret double %res
+}
+
 define double @pow_sitofp_const_base_power_of_2_no_fast(i32 %x) {
 ; CHECK-LABEL: @pow_sitofp_const_base_power_of_2_no_fast(
 ; CHECK-NEXT:    [[SUBFP:%.*]] = sitofp i32 [[X:%.*]] to float
@@ -316,6 +366,19 @@ define double @pow_sitofp_const_base_pow
   %res = fpext float %pow to double
   ret double %res
 }
+
+define double @pow_uitofp_const_base_2_no_fast(i32 %x) {
+; CHECK-LABEL: @pow_uitofp_const_base_2_no_fast(
+; CHECK-NEXT:    [[SUBFP:%.*]] = uitofp i32 [[X:%.*]] to float
+; CHECK-NEXT:    [[EXP2:%.*]] = call float @llvm.exp2.f32(float [[SUBFP]])
+; CHECK-NEXT:    [[RES:%.*]] = fpext float [[EXP2]] to double
+; CHECK-NEXT:    ret double [[RES]]
+;
+  %subfp = uitofp i32 %x to float
+  %pow = tail call float @llvm.pow.f32(float 2.000000e+00, float %subfp)
+  %res = fpext float %pow to double
+  ret double %res
+}
 
 define double @pow_uitofp_const_base_power_of_2_no_fast(i32 %x) {
 ; CHECK-LABEL: @pow_uitofp_const_base_power_of_2_no_fast(




More information about the llvm-commits mailing list