Skip to content

Commit

Permalink
[InstCombine] Expand the simplification of pow(x, 0.5) to sqrt(x)
Browse files Browse the repository at this point in the history
Expand the number of cases when `pow(x, 0.5)` is simplified into `sqrt(x)`
by considering the math semantics with more granularity.

Differential revision: https://reviews.llvm.org/D50036

llvm-svn: 339887
  • Loading branch information
Evandro Menezes committed Aug 16, 2018
1 parent 0a1e2f9 commit c05c7e1
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 97 deletions.
51 changes: 20 additions & 31 deletions llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
Expand Up @@ -1181,12 +1181,9 @@ static Value *getPow(Value *InnerChain[33], unsigned Exp, IRBuilder<> &B) {

/// Use square root in place of pow(x, +/-0.5).
Value *LibCallSimplifier::replacePowWithSqrt(CallInst *Pow, IRBuilder<> &B) {
// TODO: There is some subset of 'fast' under which these transforms should
// be allowed.
if (!Pow->isFast())
return nullptr;

Value *Sqrt, *Base = Pow->getArgOperand(0), *Expo = Pow->getArgOperand(1);
AttributeList Attrs = Pow->getCalledFunction()->getAttributes();
Module *Mod = Pow->getModule();
Type *Ty = Pow->getType();

const APFloat *ExpoF;
Expand All @@ -1198,18 +1195,32 @@ Value *LibCallSimplifier::replacePowWithSqrt(CallInst *Pow, IRBuilder<> &B) {
if (Pow->hasFnAttr(Attribute::ReadNone)) {
Function *SqrtFn = Intrinsic::getDeclaration(Pow->getModule(),
Intrinsic::sqrt, Ty);
Sqrt = B.CreateCall(SqrtFn, Base);
Sqrt = B.CreateCall(SqrtFn, Base, "sqrt");
}
// Otherwise, use the libcall for sqrt().
else if (hasUnaryFloatFn(TLI, Ty, LibFunc_sqrt, LibFunc_sqrtf, LibFunc_sqrtl))
// TODO: We also should check that the target can in fact lower the sqrt()
// libcall. We currently have no way to ask this question, so we ask if
// the target has a sqrt() libcall, which is not exactly the same.
Sqrt = emitUnaryFloatFnCall(Base, TLI->getName(LibFunc_sqrt), B,
Pow->getCalledFunction()->getAttributes());
Sqrt = emitUnaryFloatFnCall(Base, TLI->getName(LibFunc_sqrt), B, Attrs);
else
return nullptr;

// Handle signed zero base by expanding to fabs(sqrt(x)).
if (!Pow->hasNoSignedZeros()) {
Function *FAbsFn = Intrinsic::getDeclaration(Mod, Intrinsic::fabs, Ty);
Sqrt = B.CreateCall(FAbsFn, Sqrt, "abs");
}

// Handle non finite base by expanding to
// (x == -infinity ? +infinity : sqrt(x)).
if (!Pow->hasNoInfs()) {
Value *PosInf = ConstantFP::getInfinity(Ty),
*NegInf = ConstantFP::getInfinity(Ty, true);
Value *FCmp = B.CreateFCmpOEQ(Base, NegInf, "isinf");
Sqrt = B.CreateSelect(FCmp, PosInf, Sqrt);
}

// If the exponent is negative, then get the reciprocal.
if (ExpoF->isNegative())
Sqrt = B.CreateFDiv(ConstantFP::get(Ty, 1.0), Sqrt, "reciprocal");
Expand Down Expand Up @@ -1265,7 +1276,7 @@ Value *LibCallSimplifier::optimizePow(CallInst *Pow, IRBuilder<> &B) {
// We enable these only with fast-math. Besides rounding differences, the
// transformation changes overflow and underflow behavior quite dramatically.
// Example: x = 1000, y = 0.001.
// pow(exp(x), y) = pow(inf, 0.001) = inf, whereas exp(x*y) = exp(1).
// pow(exp(x), y) = pow(inf, 0.001) = inf, whereas exp(x * y) = exp(1).
auto *BaseFn = dyn_cast<CallInst>(Base);
if (BaseFn && BaseFn->isFast() && Pow->isFast()) {
LibFunc LibFn;
Expand Down Expand Up @@ -1299,28 +1310,6 @@ Value *LibCallSimplifier::optimizePow(CallInst *Pow, IRBuilder<> &B) {
if (Value *Sqrt = replacePowWithSqrt(Pow, B))
return Sqrt;

// FIXME: Correct the transforms and pull this into replacePowWithSqrt().
ConstantFP *ExpoC = dyn_cast<ConstantFP>(Expo);
if (ExpoC && ExpoC->isExactlyValue(0.5) &&
hasUnaryFloatFn(TLI, Ty, LibFunc_sqrt, LibFunc_sqrtf, LibFunc_sqrtl)) {
// Expand pow(x, 0.5) to (x == -infinity ? +infinity : fabs(sqrt(x))).
// This is faster than calling pow(), and still handles -0.0 and
// negative infinity correctly.
// TODO: In finite-only mode, this could be just fabs(sqrt(x)).
Value *PosInf = ConstantFP::getInfinity(Ty);
Value *NegInf = ConstantFP::getInfinity(Ty, true);

// TODO: As above, we should lower to the sqrt() intrinsic if the pow() is
// an intrinsic, to match errno semantics.
Value *Sqrt = emitUnaryFloatFnCall(Base, TLI->getName(LibFunc_sqrt),
B, Attrs);
Function *FAbsFn = Intrinsic::getDeclaration(Module, Intrinsic::fabs, Ty);
Value *FAbs = B.CreateCall(FAbsFn, Sqrt, "abs");
Value *FCmp = B.CreateFCmpOEQ(Base, NegInf, "isinf");
Sqrt = B.CreateSelect(FCmp, PosInf, FAbs);
return Sqrt;
}

// pow(x, n) -> x * x * x * ...
const APFloat *ExpoF;
if (Pow->isFast() && match(Expo, m_APFloat(ExpoF))) {
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Transforms/InstCombine/pow-1.ll
Expand Up @@ -293,7 +293,7 @@ define <2 x double> @pow_neg1_double_fastv(<2 x double> %x) {
declare double @llvm.pow.f64(double %Val, double %Power)
define double @test_simplify17(double %x) {
; ANY-LABEL: @test_simplify17(
; ANY-NEXT: [[SQRT:%.*]] = call double @sqrt(double [[X:%.*]]) #2
; ANY-NEXT: [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[X:%.*]])
; ANY-NEXT: [[ABS:%.*]] = call double @llvm.fabs.f64(double [[SQRT]])
; ANY-NEXT: [[ISINF:%.*]] = fcmp oeq double [[X]], 0xFFF0000000000000
; ANY-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], double 0x7FF0000000000000, double [[ABS]]
Expand Down

0 comments on commit c05c7e1

Please sign in to comment.