<div dir="rtl"><div dir="ltr">Hi Eli,</div><div dir="ltr"><br></div><div dir="ltr">The test is failing here</div><div dir="ltr"><br></div><div dir="ltr"><a href="http://bb.pgr.jp/builders/ninja-clang-x64-mingw64-RA/builds/13954/steps/test-llvm/logs/LLVM%20%3A%3A%20Transforms__DCE__calls-errno.ll">http://bb.pgr.jp/builders/ninja-clang-x64-mingw64-RA/builds/13954/steps/test-llvm/logs/LLVM%20%3A%3A%20Transforms__DCE__calls-errno.ll</a><br></div><div dir="ltr"><br></div><div dir="ltr">Yaron</div><div dir="ltr"><br></div></div><div class="gmail_extra"><br><div class="gmail_quote"><div dir="ltr">2016-11-02 22:48 GMT+02:00 Eli Friedman via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span>:</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: efriedma<br>
Date: Wed Nov  2 15:48:11 2016<br>
New Revision: 285857<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=285857&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=285857&view=rev</a><br>
Log:<br>
DCE math library calls with a constant operand.<br>
<br>
On platforms which use -fmath-errno, math libcalls without any uses<br>
require some extra checks to figure out if they are actually dead.<br>
<br>
Fixes <a href="https://llvm.org/bugs/show_bug.cgi?id=30464" rel="noreferrer" target="_blank">https://llvm.org/bugs/show_<wbr>bug.cgi?id=30464</a> .<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D25970" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D25970</a><br>
<br>
<br>
Added:<br>
    llvm/trunk/test/Transforms/<wbr>DCE/calls-errno.ll<br>
Modified:<br>
    llvm/trunk/include/llvm/<wbr>Analysis/ConstantFolding.h<br>
    llvm/trunk/lib/Analysis/<wbr>ConstantFolding.cpp<br>
    llvm/trunk/lib/Transforms/<wbr>Utils/Local.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/<wbr>Analysis/ConstantFolding.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ConstantFolding.h?rev=285857&r1=285856&r2=285857&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/include/<wbr>llvm/Analysis/ConstantFolding.<wbr>h?rev=285857&r1=285856&r2=<wbr>285857&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/<wbr>Analysis/ConstantFolding.h (original)<br>
+++ llvm/trunk/include/llvm/<wbr>Analysis/ConstantFolding.h Wed Nov  2 15:48:11 2016<br>
@@ -23,6 +23,7 @@<br>
 namespace llvm {<br>
 class APInt;<br>
 template <typename T> class ArrayRef;<br>
+class CallSite;<br>
 class Constant;<br>
 class ConstantExpr;<br>
 class ConstantVector;<br>
@@ -125,6 +126,10 @@ bool canConstantFoldCallTo(const Functio<br>
 /// with the specified arguments, returning null if unsuccessful.<br>
 Constant *ConstantFoldCall(Function *F, ArrayRef<Constant *> Operands,<br>
                            const TargetLibraryInfo *TLI = nullptr);<br>
+<br>
+/// \brief Check whether the given call has no side-effects.<br>
+/// Specifically checks for math routimes which sometimes set errno.<br>
+bool isMathLibCallNoop(CallSite CS, const TargetLibraryInfo *TLI);<br>
 }<br>
<br>
 #endif<br>
<br>
Modified: llvm/trunk/lib/Analysis/<wbr>ConstantFolding.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ConstantFolding.cpp?rev=285857&r1=285856&r2=285857&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/<wbr>Analysis/ConstantFolding.cpp?<wbr>rev=285857&r1=285856&r2=<wbr>285857&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Analysis/<wbr>ConstantFolding.cpp (original)<br>
+++ llvm/trunk/lib/Analysis/<wbr>ConstantFolding.cpp Wed Nov  2 15:48:11 2016<br>
@@ -1967,3 +1967,152 @@ llvm::ConstantFoldCall(<wbr>Function *F, Arra<br>
<br>
   return ConstantFoldScalarCall(Name, F->getIntrinsicID(), Ty, Operands, TLI);<br>
 }<br>
+<br>
+bool llvm::isMathLibCallNoop(<wbr>CallSite CS, const TargetLibraryInfo *TLI) {<br>
+  // FIXME: Refactor this code; this duplicates logic in LibCallsShrinkWrap<br>
+  // (and to some extent ConstantFoldScalarCall).<br>
+  Function *F = CS.getCalledFunction();<br>
+  if (!F)<br>
+    return false;<br>
+<br>
+  LibFunc::Func Func;<br>
+  if (!TLI || !TLI->getLibFunc(*F, Func))<br>
+    return false;<br>
+<br>
+  if (CS.getNumArgOperands() == 1) {<br>
+    if (ConstantFP *OpC = dyn_cast<ConstantFP>(CS.<wbr>getArgOperand(0))) {<br>
+      const APFloat &Op = OpC->getValueAPF();<br>
+      switch (Func) {<br>
+      case LibFunc::logl:<br>
+      case LibFunc::log:<br>
+      case LibFunc::logf:<br>
+      case LibFunc::log2l:<br>
+      case LibFunc::log2:<br>
+      case LibFunc::log2f:<br>
+      case LibFunc::log10l:<br>
+      case LibFunc::log10:<br>
+      case LibFunc::log10f:<br>
+        return Op.isNaN() || (!Op.isZero() && !Op.isNegative());<br>
+<br>
+      case LibFunc::expl:<br>
+      case LibFunc::exp:<br>
+      case LibFunc::expf:<br>
+        // FIXME: These boundaries are slightly conservative.<br>
+        if (OpC->getType()->isDoubleTy())<br>
+          return Op.compare(APFloat(-745.0)) != APFloat::cmpLessThan &&<br>
+                 Op.compare(APFloat(709.0)) != APFloat::cmpGreaterThan;<br>
+        if (OpC->getType()->isFloatTy())<br>
+          return Op.compare(APFloat(-103.0f)) != APFloat::cmpLessThan &&<br>
+                 Op.compare(APFloat(88.0f)) != APFloat::cmpGreaterThan;<br>
+        break;<br>
+<br>
+      case LibFunc::exp2l:<br>
+      case LibFunc::exp2:<br>
+      case LibFunc::exp2f:<br>
+        // FIXME: These boundaries are slightly conservative.<br>
+        if (OpC->getType()->isDoubleTy())<br>
+          return Op.compare(APFloat(-1074.0)) != APFloat::cmpLessThan &&<br>
+                 Op.compare(APFloat(1023.0)) != APFloat::cmpGreaterThan;<br>
+        if (OpC->getType()->isFloatTy())<br>
+          return Op.compare(APFloat(-149.0f)) != APFloat::cmpLessThan &&<br>
+                 Op.compare(APFloat(127.0f)) != APFloat::cmpGreaterThan;<br>
+        break;<br>
+<br>
+      case LibFunc::sinl:<br>
+      case LibFunc::sin:<br>
+      case LibFunc::sinf:<br>
+      case LibFunc::cosl:<br>
+      case LibFunc::cos:<br>
+      case LibFunc::cosf:<br>
+        return !Op.isInfinity();<br>
+<br>
+      case LibFunc::tanl:<br>
+      case LibFunc::tan:<br>
+      case LibFunc::tanf: {<br>
+        // FIXME: Stop using the host math library.<br>
+        // FIXME: The computation isn't done in the right precision.<br>
+        Type *Ty = OpC->getType();<br>
+        if (Ty->isDoubleTy() || Ty->isFloatTy() || Ty->isHalfTy()) {<br>
+          double OpV = getValueAsDouble(OpC);<br>
+          return ConstantFoldFP(tan, OpV, Ty) != nullptr;<br>
+        }<br>
+        break;<br>
+      }<br>
+<br>
+      case LibFunc::asinl:<br>
+      case LibFunc::asin:<br>
+      case LibFunc::asinf:<br>
+      case LibFunc::acosl:<br>
+      case LibFunc::acos:<br>
+      case LibFunc::acosf:<br>
+        return Op.compare(APFloat(Op.<wbr>getSemantics(), "-1")) !=<br>
+                   APFloat::cmpLessThan &&<br>
+               Op.compare(APFloat(Op.<wbr>getSemantics(), "1")) !=<br>
+                   APFloat::cmpGreaterThan;<br>
+<br>
+      case LibFunc::sinh:<br>
+      case LibFunc::cosh:<br>
+      case LibFunc::sinhf:<br>
+      case LibFunc::coshf:<br>
+      case LibFunc::sinhl:<br>
+      case LibFunc::coshl:<br>
+        // FIXME: These boundaries are slightly conservative.<br>
+        if (OpC->getType()->isDoubleTy())<br>
+          return Op.compare(APFloat(-710.0)) != APFloat::cmpLessThan &&<br>
+                 Op.compare(APFloat(710.0)) != APFloat::cmpGreaterThan;<br>
+        if (OpC->getType()->isFloatTy())<br>
+          return Op.compare(APFloat(-89.0f)) != APFloat::cmpLessThan &&<br>
+                 Op.compare(APFloat(89.0f)) != APFloat::cmpGreaterThan;<br>
+        break;<br>
+<br>
+      case LibFunc::sqrtl:<br>
+      case LibFunc::sqrt:<br>
+      case LibFunc::sqrtf:<br>
+        return Op.isNaN() || Op.isZero() || !Op.isNegative();<br>
+<br>
+      // FIXME: Add more functions: sqrt_finite, atanh, expm1, log1p,<br>
+      // maybe others?<br>
+      default:<br>
+        break;<br>
+      }<br>
+    }<br>
+  }<br>
+<br>
+  if (CS.getNumArgOperands() == 2) {<br>
+    ConstantFP *Op0C = dyn_cast<ConstantFP>(CS.<wbr>getArgOperand(0));<br>
+    ConstantFP *Op1C = dyn_cast<ConstantFP>(CS.<wbr>getArgOperand(1));<br>
+    if (Op0C && Op1C) {<br>
+      const APFloat &Op0 = Op0C->getValueAPF();<br>
+      const APFloat &Op1 = Op1C->getValueAPF();<br>
+<br>
+      switch (Func) {<br>
+      case LibFunc::powl:<br>
+      case LibFunc::pow:<br>
+      case LibFunc::powf: {<br>
+        // FIXME: Stop using the host math library.<br>
+        // FIXME: The computation isn't done in the right precision.<br>
+        Type *Ty = Op0C->getType();<br>
+        if (Ty->isDoubleTy() || Ty->isFloatTy() || Ty->isHalfTy()) {<br>
+          if (Ty == Op1C->getType()) {<br>
+            double Op0V = getValueAsDouble(Op0C);<br>
+            double Op1V = getValueAsDouble(Op1C);<br>
+            return ConstantFoldBinaryFP(pow, Op0V, Op1V, Ty) != nullptr;<br>
+          }<br>
+        }<br>
+        break;<br>
+      }<br>
+<br>
+      case LibFunc::fmodl:<br>
+      case LibFunc::fmod:<br>
+      case LibFunc::fmodf:<br>
+        return Op0.isNaN() || Op1.isNaN() ||<br>
+               (!Op0.isInfinity() && !Op1.isZero());<br>
+<br>
+      default:<br>
+        break;<br>
+      }<br>
+    }<br>
+  }<br>
+<br>
+  return false;<br>
+}<br>
<br>
Modified: llvm/trunk/lib/Transforms/<wbr>Utils/Local.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/Local.cpp?rev=285857&r1=285856&r2=285857&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/<wbr>Transforms/Utils/Local.cpp?<wbr>rev=285857&r1=285856&r2=<wbr>285857&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Transforms/<wbr>Utils/Local.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/<wbr>Utils/Local.cpp Wed Nov  2 15:48:11 2016<br>
@@ -340,6 +340,10 @@ bool llvm::<wbr>isInstructionTriviallyDead(In<br>
     if (Constant *C = dyn_cast<Constant>(CI-><wbr>getArgOperand(0)))<br>
       return C->isNullValue() || isa<UndefValue>(C);<br>
<br>
+  if (CallSite CS = CallSite(I))<br>
+    if (isMathLibCallNoop(CS, TLI))<br>
+      return true;<br>
+<br>
   return false;<br>
 }<br>
<br>
<br>
Added: llvm/trunk/test/Transforms/<wbr>DCE/calls-errno.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DCE/calls-errno.ll?rev=285857&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>Transforms/DCE/calls-errno.ll?<wbr>rev=285857&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/Transforms/<wbr>DCE/calls-errno.ll (added)<br>
+++ llvm/trunk/test/Transforms/<wbr>DCE/calls-errno.ll Wed Nov  2 15:48:11 2016<br>
@@ -0,0 +1,91 @@<br>
+; RUN: opt < %s -dce -S | FileCheck %s<br>
+<br>
+declare double @acos(double) nounwind<br>
+declare double @asin(double) nounwind<br>
+declare double @atan(double) nounwind<br>
+declare double @atan2(double, double) nounwind<br>
+declare double @ceil(double) nounwind<br>
+declare double @cos(double) nounwind<br>
+declare double @cosh(double) nounwind<br>
+declare double @exp(double) nounwind<br>
+declare double @exp2(double) nounwind<br>
+declare double @fabs(double) nounwind<br>
+declare double @floor(double) nounwind<br>
+declare double @fmod(double, double) nounwind<br>
+declare double @log(double) nounwind<br>
+declare double @log10(double) nounwind<br>
+declare double @pow(double, double) nounwind<br>
+declare double @sin(double) nounwind<br>
+declare double @sinh(double) nounwind<br>
+declare double @sqrt(double) nounwind<br>
+declare double @tan(double) nounwind<br>
+declare double @tanh(double) nounwind<br>
+<br>
+declare float @acosf(float) nounwind<br>
+declare float @asinf(float) nounwind<br>
+declare float @atanf(float) nounwind<br>
+declare float @atan2f(float, float) nounwind<br>
+declare float @ceilf(float) nounwind<br>
+declare float @cosf(float) nounwind<br>
+declare float @coshf(float) nounwind<br>
+declare float @expf(float) nounwind<br>
+declare float @exp2f(float) nounwind<br>
+declare float @fabsf(float) nounwind<br>
+declare float @floorf(float) nounwind<br>
+declare float @fmodf(float, float) nounwind<br>
+declare float @logf(float) nounwind<br>
+declare float @log10f(float) nounwind<br>
+declare float @powf(float, float) nounwind<br>
+declare float @sinf(float) nounwind<br>
+declare float @sinhf(float) nounwind<br>
+declare float @sqrtf(float) nounwind<br>
+declare float @tanf(float) nounwind<br>
+declare float @tanhf(float) nounwind<br>
+<br>
+define void @T() {<br>
+entry:<br>
+; CHECK-LABEL: @T(<br>
+; CHECK-NEXT: entry:<br>
+<br>
+; log(0) produces a pole error<br>
+; CHECK-NEXT: %log1 = call double @log(double 0.000000e+00)<br>
+  %log1 = call double @log(double 0.000000e+00)<br>
+<br>
+; log(-1) produces a domain error<br>
+; CHECK-NEXT: %log2 = call double @log(double -1.000000e+00)<br>
+  %log2 = call double @log(double -1.000000e+00)<br>
+<br>
+; log(1) is 0<br>
+  %log3 = call double @log(double 1.000000e+00)<br>
+<br>
+; exp(100) is roughly 2.6e+43<br>
+  %exp1 = call double @exp(double 1.000000e+02)<br>
+<br>
+; exp(1000) is a range error<br>
+; CHECK-NEXT: %exp2 = call double @exp(double 1.000000e+03)<br>
+  %exp2 = call double @exp(double 1.000000e+03)<br>
+<br>
+; cos(0) is 1<br>
+  %cos1 = call double @cos(double 0.000000e+00)<br>
+<br>
+; cos(inf) is a domain error<br>
+; CHECK-NEXT: %cos2 = call double @cos(double 0x7FF0000000000000)<br>
+  %cos2 = call double @cos(double 0x7FF0000000000000)<br>
+<br>
+; pow(0, 1) is 0<br>
+  %pow1 = call double @pow(double 0x7FF0000000000000, double 1.000000e+00)<br>
+<br>
+; pow(0, -1) is a pole error<br>
+; CHECK-NEXT: %pow2 = call double @pow(double 0.000000e+00, double -1.000000e+00)<br>
+  %pow2 = call double @pow(double 0.000000e+00, double -1.000000e+00)<br>
+<br>
+; fmod(inf, nan) is nan<br>
+  %fmod1 = call double @fmod(double 0x7FF0000000000000, double 0x7FF0000000000001)<br>
+<br>
+; fmod(inf, 1) is a domain error<br>
+; CHECK-NEXT: %fmod2 = call double @fmod(double 0x7FF0000000000000, double 1.000000e+00)<br>
+  %fmod2 = call double @fmod(double 0x7FF0000000000000, double 1.000000e+00)<br>
+<br>
+; CHECK-NEXT: ret void<br>
+  ret void<br>
+}<br>
<br>
<br>
______________________________<wbr>_________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>