Index: lib/Transforms/Utils/SimplifyLibCalls.cpp =================================================================== --- lib/Transforms/Utils/SimplifyLibCalls.cpp +++ lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1091,6 +1091,20 @@ Callee->getAttributes()); } + + // pow(exp(x), y) -> exp(x*y) + if (CallInst *OpC = dyn_cast(Op1)) { + LibFunc::Func Func; + Function *Callee = OpC->getCalledFunction(); + StringRef FuncName = Callee->getName(); + + if (TLI->getLibFunc(FuncName, Func) && TLI->has(Func) && + Func == LibFunc::exp && Op2->getType()->isDoubleTy()) + return EmitUnaryFloatFnCall( + B.CreateFMul(OpC->getArgOperand(0), Op2, "mul"), + TLI->getName(LibFunc::exp), B, Callee->getAttributes()); + } + ConstantFP *Op2C = dyn_cast(Op2); if (!Op2C) return Ret; Index: test/Transforms/InstCombine/pow-exp.ll =================================================================== --- test/Transforms/InstCombine/pow-exp.ll +++ test/Transforms/InstCombine/pow-exp.ll @@ -0,0 +1,28 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-freebsd11.0" + +define double @mypow(double %x, double %y) #0 { +entry: + %x.addr = alloca double, align 8 + %y.addr = alloca double, align 8 + store double %x, double* %x.addr, align 8 + store double %y, double* %y.addr, align 8 + %0 = load double, double* %x.addr, align 8 + %call = call double @exp(double %0) #2 + %1 = load double, double* %y.addr, align 8 + %2 = call double @llvm.pow.f64(double %call, double %1) + ret double %2 +} + +declare double @exp(double) #1 +declare double @llvm.pow.f64(double, double) #2 + +; CHECK: define double @mypow(double %x, double %y) { +; CHECK: entry: +; CHECK: %call = call double @exp(double %x) +; CHECK: %mul = fmul double %x, %y +; CHECK: %exp = call double @exp(double %mul) +; CHECK: ret double %exp +; CHECK: }