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; 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