Index: llvm/trunk/include/llvm/Transforms/Utils/SimplifyLibCalls.h =================================================================== --- llvm/trunk/include/llvm/Transforms/Utils/SimplifyLibCalls.h +++ llvm/trunk/include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -134,6 +134,7 @@ Value *optimizeFMinFMax(CallInst *CI, IRBuilder<> &B); Value *optimizeSqrt(CallInst *CI, IRBuilder<> &B); Value *optimizeSinCosPi(CallInst *CI, IRBuilder<> &B); + Value *optimizeTan(CallInst *CI, IRBuilder<> &B); // Integer Library Call Optimizations Value *optimizeFFS(CallInst *CI, IRBuilder<> &B); Index: llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1359,6 +1359,40 @@ return Ret; } +Value *LibCallSimplifier::optimizeTan(CallInst *CI, IRBuilder<> &B) { + Function *Callee = CI->getCalledFunction(); + Value *Ret = nullptr; + if (UnsafeFPShrink && Callee->getName() == "tan" && TLI->has(LibFunc::tanf)) + Ret = optimizeUnaryDoubleFP(CI, B, true); + FunctionType *FT = Callee->getFunctionType(); + + // Just make sure this has 1 argument of FP type, which matches the + // result type. + if (FT->getNumParams() != 1 || FT->getReturnType() != FT->getParamType(0) || + !FT->getParamType(0)->isFloatingPointTy()) + return Ret; + + if (!canUseUnsafeFPMath(CI->getParent()->getParent())) + return Ret; + Value *Op1 = CI->getArgOperand(0); + auto *OpC = dyn_cast(Op1); + if (!OpC) + return Ret; + + // tan(atan(x)) -> x + // tanf(atanf(x)) -> x + // tanl(atanl(x)) -> x + LibFunc::Func Func; + Function *F = OpC->getCalledFunction(); + StringRef FuncName = F->getName(); + if (TLI->getLibFunc(FuncName, Func) && TLI->has(Func) && + ((Func == LibFunc::atan && Callee->getName() == "tan") || + (Func == LibFunc::atanf && Callee->getName() == "tanf") || + (Func == LibFunc::atanl && Callee->getName() == "tanl"))) + Ret = OpC->getArgOperand(0); + return Ret; +} + static bool isTrigLibCall(CallInst *CI); static void insertSinCosCall(IRBuilder<> &B, Function *OrigCallee, Value *Arg, bool UseFloat, Value *&Sin, Value *&Cos, @@ -2146,6 +2180,10 @@ return optimizeFPuts(CI, Builder); case LibFunc::puts: return optimizePuts(CI, Builder); + case LibFunc::tan: + case LibFunc::tanf: + case LibFunc::tanl: + return optimizeTan(CI, Builder); case LibFunc::perror: return optimizeErrorReporting(CI, Builder); case LibFunc::vfprintf: @@ -2180,7 +2218,6 @@ case LibFunc::logb: case LibFunc::sin: case LibFunc::sinh: - case LibFunc::tan: case LibFunc::tanh: if (UnsafeFPShrink && hasFloatVersion(FuncName)) return optimizeUnaryDoubleFP(CI, Builder, true); Index: llvm/trunk/test/Transforms/InstCombine/tan-nofastmath.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/tan-nofastmath.ll +++ llvm/trunk/test/Transforms/InstCombine/tan-nofastmath.ll @@ -0,0 +1,17 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +define float @mytan(float %x) { +entry: + %call = call float @atanf(float %x) + %call1 = call float @tanf(float %call) + ret float %call1 +} + +; CHECK-LABEL: define float @mytan( +; CHECK: %call = call float @atanf(float %x) +; CHECK-NEXT: %call1 = call float @tanf(float %call) +; CHECK-NEXT: ret float %call1 +; CHECK-NEXT: } + +declare float @tanf(float) +declare float @atanf(float) Index: llvm/trunk/test/Transforms/InstCombine/tan.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/tan.ll +++ llvm/trunk/test/Transforms/InstCombine/tan.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +define float @mytan(float %x) #0 { +entry: + %call = call float @atanf(float %x) + %call1 = call float @tanf(float %call) + ret float %call1 +} + +; CHECK-LABEL: define float @mytan( +; CHECK: ret float %x + +declare float @tanf(float) #0 +declare float @atanf(float) #0 +attributes #0 = { "unsafe-fp-math"="true" }