[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