[llvm] 3d6c10d - [SimplifyLibCalls] avoid converting pow() to powi() with no FMF

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 19 09:27:06 PDT 2022


Author: Sanjay Patel
Date: 2022-07-19T12:26:53-04:00
New Revision: 3d6c10dcf3b5d43708adb0c175e6ff382a4e9e4c

URL: https://github.com/llvm/llvm-project/commit/3d6c10dcf3b5d43708adb0c175e6ff382a4e9e4c
DIFF: https://github.com/llvm/llvm-project/commit/3d6c10dcf3b5d43708adb0c175e6ff382a4e9e4c.diff

LOG: [SimplifyLibCalls] avoid converting pow() to powi() with no FMF

powi() is not a standard math library function; it is specified
with non-strict semantics in the LangRef. We currently require
'afn' to do this transform when it needs a sqrt(), so I just
extended that requirement to the whole-number exponent too.

This bug was introduced with:
b17754bcaa14
...where we deferred expansion of pow() to later passes.

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index b359717424a6a..bca3b0538c5d8 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -1948,14 +1948,16 @@ Value *LibCallSimplifier::optimizePow(CallInst *Pow, IRBuilderBase &B) {
   if (Value *Sqrt = replacePowWithSqrt(Pow, B))
     return Sqrt;
 
+  // If we can approximate pow:
   // pow(x, n) -> powi(x, n) * sqrt(x) if n has exactly a 0.5 fraction
+  // pow(x, n) -> powi(x, n) if n is a constant signed integer value
   const APFloat *ExpoF;
-  if (match(Expo, m_APFloat(ExpoF)) && !ExpoF->isExactlyValue(0.5) &&
-      !ExpoF->isExactlyValue(-0.5)) {
+  if (AllowApprox && match(Expo, m_APFloat(ExpoF)) &&
+      !ExpoF->isExactlyValue(0.5) && !ExpoF->isExactlyValue(-0.5)) {
     APFloat ExpoA(abs(*ExpoF));
     APFloat ExpoI(*ExpoF);
     Value *Sqrt = nullptr;
-    if (AllowApprox && !ExpoA.isInteger()) {
+    if (!ExpoA.isInteger()) {
       APFloat Expo2 = ExpoA;
       // To check if ExpoA is an integer + 0.5, we add it to itself. If there
       // is no floating point exception and the result is an integer, then
@@ -1979,7 +1981,8 @@ Value *LibCallSimplifier::optimizePow(CallInst *Pow, IRBuilderBase &B) {
         return nullptr;
     }
 
-    // pow(x, n) -> powi(x, n) if n is a constant signed integer value
+    // 0.5 fraction is now optionally handled.
+    // Do pow -> powi for remaining integer exponent
     APSInt IntExpo(TLI->getIntSize(), /*isUnsigned=*/false);
     if (ExpoF->isInteger() &&
         ExpoF->convertToInteger(IntExpo, APFloat::rmTowardZero, &Ignored) ==

diff  --git a/llvm/test/Transforms/InstCombine/pow_fp_int.ll b/llvm/test/Transforms/InstCombine/pow_fp_int.ll
index 1c7771df251ac..d4d27c2e0201c 100644
--- a/llvm/test/Transforms/InstCombine/pow_fp_int.ll
+++ b/llvm/test/Transforms/InstCombine/pow_fp_int.ll
@@ -442,9 +442,11 @@ define double @pow_uitofp_double_base_no_fast(double %base, i32 %x) {
   ret double %pow
 }
 
+; negative test - pow with no FMF is not the same as the loosely-specified powi
+
 define double @powf_exp_const_int_no_fast(double %base) {
 ; CHECK-LABEL: @powf_exp_const_int_no_fast(
-; CHECK-NEXT:    [[RES:%.*]] = tail call double @llvm.powi.f64.i32(double [[BASE:%.*]], i32 40)
+; CHECK-NEXT:    [[RES:%.*]] = tail call double @llvm.pow.f64(double [[BASE:%.*]], double 4.000000e+01)
 ; CHECK-NEXT:    ret double [[RES]]
 ;
   %res = tail call double @llvm.pow.f64(double %base, double 4.000000e+01)
@@ -471,9 +473,11 @@ define double @powf_exp_const_not_int_no_fast(double %base) {
   ret double %res
 }
 
+; negative test - pow with no FMF is not the same as the loosely-specified powi
+
 define double @powf_exp_const2_int_no_fast(double %base) {
 ; CHECK-LABEL: @powf_exp_const2_int_no_fast(
-; CHECK-NEXT:    [[RES:%.*]] = tail call double @llvm.powi.f64.i32(double [[BASE:%.*]], i32 -40)
+; CHECK-NEXT:    [[RES:%.*]] = tail call double @llvm.pow.f64(double [[BASE:%.*]], double -4.000000e+01)
 ; CHECK-NEXT:    ret double [[RES]]
 ;
   %res = tail call double @llvm.pow.f64(double %base, double -4.000000e+01)

diff  --git a/llvm/test/Transforms/InstCombine/pow_fp_int16.ll b/llvm/test/Transforms/InstCombine/pow_fp_int16.ll
index 1c07c5d177615..90e81c99d91c8 100644
--- a/llvm/test/Transforms/InstCombine/pow_fp_int16.ll
+++ b/llvm/test/Transforms/InstCombine/pow_fp_int16.ll
@@ -412,9 +412,11 @@ define double @pow_uitofp_double_base_no_fast(double %base, i16 %x) {
   ret double %pow
 }
 
+; negative test - pow with no FMF is not the same as the loosely-specified powi
+
 define double @powf_exp_const_int_no_fast(double %base) {
 ; CHECK-LABEL: @powf_exp_const_int_no_fast(
-; CHECK-NEXT:    [[RES:%.*]] = tail call double @llvm.powi.f64.i16(double [[BASE:%.*]], i16 40)
+; CHECK-NEXT:    [[RES:%.*]] = tail call double @llvm.pow.f64(double [[BASE:%.*]], double 4.000000e+01)
 ; CHECK-NEXT:    ret double [[RES]]
 ;
   %res = tail call double @llvm.pow.f64(double %base, double 4.000000e+01)
@@ -441,9 +443,11 @@ define double @powf_exp_const_not_int_no_fast(double %base) {
   ret double %res
 }
 
+; negative test - pow with no FMF is not the same as the loosely-specified powi
+
 define double @powf_exp_const2_int_no_fast(double %base) {
 ; CHECK-LABEL: @powf_exp_const2_int_no_fast(
-; CHECK-NEXT:    [[RES:%.*]] = tail call double @llvm.powi.f64.i16(double [[BASE:%.*]], i16 -40)
+; CHECK-NEXT:    [[RES:%.*]] = tail call double @llvm.pow.f64(double [[BASE:%.*]], double -4.000000e+01)
 ; CHECK-NEXT:    ret double [[RES]]
 ;
   %res = tail call double @llvm.pow.f64(double %base, double -4.000000e+01)


        


More information about the llvm-commits mailing list