[PATCH] D67248: [InstCombine] pow(x, +/- 0.0) -> 1.0

JF Bastien via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 5 17:27:24 PDT 2019


jfb created this revision.
jfb added a reviewer: scanon.
Herald added subscribers: llvm-commits, ributzka, dexonsmith, jkorous, hiraditya.
Herald added a project: LLVM.

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.

rdar://problem/54598300


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D67248

Files:
  llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
  llvm/test/Transforms/InstCombine/pow-0.ll


Index: llvm/test/Transforms/InstCombine/pow-0.ll
===================================================================
--- /dev/null
+++ llvm/test/Transforms/InstCombine/pow-0.ll
@@ -0,0 +1,31 @@
+; 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
+}
+
+declare double @llvm.pow.f64(double, double)
Index: llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
===================================================================
--- llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -1562,8 +1562,9 @@
   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_SpecificFP(0.0)) ||
+      match(Expo, m_SpecificFP(-0.0)))
     return ConstantFP::get(Ty, 1.0);
 
   // pow(x, 1.0) -> x


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D67248.219010.patch
Type: text/x-patch
Size: 1731 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190906/93f96d64/attachment.bin>


More information about the llvm-commits mailing list