# [PATCH] D22104: [SimplifyLibCalls] pow(x, 0.5) -> fabs(sqrt(x)) (finite-only-mode)

Davide Italiano via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 7 11:48:47 PDT 2016

```davide created this revision.
davide added reviewers: majnemer, spatel, scanon.

This is a new version of http://reviews.llvm.org/D16833 as mgrang has no more time to work on the feature.
This patch substantially differ from the previous version. The original patch applied the transformation if:
` if (Op1C->getValueAPF().isFinite())`

I don't think this is the correct way of checking we're in finite-mode only. Instead, checked that the function has the attributes `no-nans-fp-math` and `no-infs-fp-math` both set to true. I hope I wasn't entirely wrong in my analysis. In any case, comments welcome.

Also, this adds a test (which wasn't included in the original revision).

cc:ing Steve Canon so that he can confirm/deny if this makes sense from a mathematical point of view.

http://reviews.llvm.org/D22104

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

Index: test/Transforms/InstCombine/pow-sqrt.ll
===================================================================
--- test/Transforms/InstCombine/pow-sqrt.ll
+++ test/Transforms/InstCombine/pow-sqrt.ll
@@ -11,3 +11,16 @@

declare double @llvm.pow.f64(double, double)

+; In finite-only mode, we can transform pow(x, 0.5) -> fabs(sqrt(x))
+
+define double @pow_finite(double %x) #0 {
+  %pow = call double @llvm.pow.f64(double %x, double 5.000000e-01)
+  ret double %pow
+}
+
+attributes #0 = { "no-infs-fp-math"="true" "no-nans-fp-math"="true" }
+
+; CHECK-LABEL: define double @pow_finite(
+; CHECK-NEXT:  %sqrt = call double @sqrt(double %x)
+; CHECK-NEXT:  %fabs = call double @fabs(double %sqrt)
+; CHECK-NEXT:  ret double %fabs
Index: lib/Transforms/Utils/SimplifyLibCalls.cpp
===================================================================
--- lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -985,6 +985,17 @@
return InnerChain[Exp];
}

+static bool isFiniteMathMode(Function &F) {
+  bool HasFunNoNaNAttr = false, HasFunNoInfAttr = false;
+  if (F.hasFnAttribute("no-nans-fp-math"))
+    HasFunNoNaNAttr =
+        F.getFnAttribute("no-nans-fp-math").getValueAsString() == "true";
+  if (F.hasFnAttribute("no-infs-fp-math"))
+    HasFunNoInfAttr =
+        F.getFnAttribute("no-infs-fp-math").getValueAsString() == "true";
+  return HasFunNoNaNAttr && HasFunNoInfAttr;
+}
+
Value *LibCallSimplifier::optimizePow(CallInst *CI, IRBuilder<> &B) {
Function *Callee = CI->getCalledFunction();
Value *Ret = nullptr;
@@ -1052,15 +1063,20 @@
Callee->getAttributes());
}

-    // Expand pow(x, 0.5) to (x == -infinity ? +infinity : fabs(sqrt(x))).
+    // In finite-only mode, pow(x, 0.5) -> fabs(sqrt(x))
+    Function &F = *B.GetInsertBlock()->getParent();
+    Value *Sqrt = emitUnaryFloatFnCall(Op1, "sqrt", B, Callee->getAttributes());
+    Value *FAbs =
+        emitUnaryFloatFnCall(Sqrt, "fabs", B, Callee->getAttributes());
+    if (isFiniteMathMode(F))
+      return FAbs;
+
+    // Otherwise, expand pow(x, 0.5) to
+    //   (x == -infinity ? +infinity : fabs(sqrt(x))).
// This is faster than calling pow, and still handles negative zero
// and negative infinity correctly.
-    // TODO: In finite-only mode, this could be just fabs(sqrt(x)).
Value *Inf = ConstantFP::getInfinity(CI->getType());
Value *NegInf = ConstantFP::getInfinity(CI->getType(), true);
-    Value *Sqrt = emitUnaryFloatFnCall(Op1, "sqrt", B, Callee->getAttributes());
-    Value *FAbs =
-        emitUnaryFloatFnCall(Sqrt, "fabs", B, Callee->getAttributes());
Value *FCmp = B.CreateFCmpOEQ(Op1, NegInf);
Value *Sel = B.CreateSelect(FCmp, Inf, FAbs);
return Sel;

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D22104.63107.patch
Type: text/x-patch
Size: 2783 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160707/27ee02fc/attachment.bin>
```