summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2019-09-09 09:43:19 +0000
committerHans Wennborg <hans@hanshq.net>2019-09-09 09:43:19 +0000
commitb508b4ba06795704af6f05d4159fdf656e0185df (patch)
treefa4ed1618afe7929679832b60dffd614ceed8302
parent1c21c1972f9201c1f7d2a8f3ae27568b36d71efa (diff)
downloadllvm-b508b4ba06795704af6f05d4159fdf656e0185df.tar.gz
Merging r371221 and r371224:
------------------------------------------------------------------------ r371221 | spatel | 2019-09-06 18:10:18 +0200 (Fri, 06 Sep 2019) | 3 lines [SimplifyLibCalls] handle pow(x,-0.0) before it can assert (PR43233) https://bugs.llvm.org/show_bug.cgi?id=43233 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r371224 | jfb | 2019-09-06 18:26:59 +0200 (Fri, 06 Sep 2019) | 39 lines [InstCombine] pow(x, +/- 0.0) -> 1.0 Summary: This isn't an important optimization at all... We're already doing: pow(x, 0.0) -> 1.0 My patch merely teaches instcombine that -0.0 does the same. However, doing this fixes an AMAZING bug! Compile this program: extern "C" double pow(double, double); double boom(double base) { return pow(base, -0.0); } With: clang++ ~/Desktop/fast-math.cpp -ffast-math -O2 -S And clang will crash with a signal. Wow, fast math is so fast it ICEs the compiler! Arguably, the generated math is infinitely fast. What's actually happening is that we recurse infinitely in getPow. In debug we hit its assertion: assert(Exp != 0 && "Incorrect exponent 0 not handled"); We avoid this entire mess if we instead recognize that an exponent of positive and negative zero yield 1.0. A separate commit, r371221, fixed the same problem. This only contains the added tests. <rdar://problem/54598300> Reviewers: scanon Subscribers: hiraditya, jkorous, dexonsmith, ributzka, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D67248 ------------------------------------------------------------------------ llvm-svn: 371381
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp4
-rw-r--r--llvm/test/Transforms/InstCombine/pow-0.ll60
-rw-r--r--llvm/test/Transforms/InstCombine/pow-4.ll10
3 files changed, 72 insertions, 2 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index e0def81d5eee..e938ae6cb42f 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -1480,8 +1480,8 @@ Value *LibCallSimplifier::optimizePow(CallInst *Pow, IRBuilder<> &B) {
if (match(Expo, m_SpecificFP(-1.0)))
return B.CreateFDiv(ConstantFP::get(Ty, 1.0), Base, "reciprocal");
- // pow(x, 0.0) -> 1.0
- if (match(Expo, m_SpecificFP(0.0)))
+ // pow(x, +/-0.0) -> 1.0
+ if (match(Expo, m_AnyZeroFP()))
return ConstantFP::get(Ty, 1.0);
// pow(x, 1.0) -> x
diff --git a/llvm/test/Transforms/InstCombine/pow-0.ll b/llvm/test/Transforms/InstCombine/pow-0.ll
new file mode 100644
index 000000000000..8de8e12a2d10
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/pow-0.ll
@@ -0,0 +1,60 @@
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+; CHECK-LABEL: @zero(
+; CHECK-NEXT: ret double 1.000000e+00
+define double @zero(double %value) {
+ %res = call double @llvm.pow.f64(double %value, double 0.000000e+00)
+ ret double %res
+}
+
+; CHECK-LABEL: @minus_zero(
+; CHECK-NEXT: ret double 1.000000e+00
+define double @minus_zero(double %value) {
+ %res = call double @llvm.pow.f64(double %value, double -0.000000e+00)
+ ret double %res
+}
+
+; CHECK-LABEL: @fast_zero(
+; CHECK-NEXT: ret double 1.000000e+00
+define double @fast_zero(double %value) {
+ %res = call fast double @llvm.pow.f64(double %value, double 0.000000e+00)
+ ret double %res
+}
+
+; CHECK-LABEL: @fast_minus_zero(
+; CHECK-NEXT: ret double 1.000000e+00
+define double @fast_minus_zero(double %value) {
+ %res = call fast double @llvm.pow.f64(double %value, double -0.000000e+00)
+ ret double %res
+}
+
+; CHECK-LABEL: @vec_zero(
+; CHECK-NEXT: ret <2 x double> <double 1.000000e+00, double 1.000000e+00>
+define <2 x double> @vec_zero(<2 x double> %value) {
+ %res = call <2 x double> @llvm.pow.v2f64(<2 x double> %value, <2 x double> <double 0.000000e+00, double 0.000000e+00>)
+ ret <2 x double> %res
+}
+
+; CHECK-LABEL: @vec_minus_zero(
+; CHECK-NEXT: ret <2 x double> <double 1.000000e+00, double 1.000000e+00>
+define <2 x double> @vec_minus_zero(<2 x double> %value) {
+ %res = call <2 x double> @llvm.pow.v2f64(<2 x double> %value, <2 x double> <double -0.000000e+00, double -0.000000e+00>)
+ ret <2 x double> %res
+}
+
+; CHECK-LABEL: @vec_fast_zero(
+; CHECK-NEXT: ret <2 x double> <double 1.000000e+00, double 1.000000e+00>
+define <2 x double> @vec_fast_zero(<2 x double> %value) {
+ %res = call fast <2 x double> @llvm.pow.v2f64(<2 x double> %value, <2 x double> <double 0.000000e+00, double 0.000000e+00>)
+ ret <2 x double> %res
+}
+
+; CHECK-LABEL: @vec_fast_minus_zero(
+; CHECK-NEXT: ret <2 x double> <double 1.000000e+00, double 1.000000e+00>
+define <2 x double> @vec_fast_minus_zero(<2 x double> %value) {
+ %res = call fast <2 x double> @llvm.pow.v2f64(<2 x double> %value, <2 x double> <double -0.000000e+00, double -0.000000e+00>)
+ ret <2 x double> %res
+}
+
+declare double @llvm.pow.f64(double, double)
+declare <2 x double> @llvm.pow.v2f64(<2 x double>, <2 x double>)
diff --git a/llvm/test/Transforms/InstCombine/pow-4.ll b/llvm/test/Transforms/InstCombine/pow-4.ll
index e4352392e229..4aac27fe72f0 100644
--- a/llvm/test/Transforms/InstCombine/pow-4.ll
+++ b/llvm/test/Transforms/InstCombine/pow-4.ll
@@ -223,3 +223,13 @@ define <4 x float> @test_simplify_3_5(<4 x float> %x) {
ret <4 x float> %1
}
+; Make sure that -0.0 exponent is always simplified.
+
+define double @PR43233(double %x) {
+; CHECK-LABEL: @PR43233(
+; CHECK-NEXT: ret double 1.000000e+00
+;
+ %r = call fast double @llvm.pow.f64(double %x, double -0.0)
+ ret double %r
+}
+