[SimplifyLibCalls] New transformation: tan(atan(x)) -> x

This is enabled only under -ffast-math.
So, instead of emitting:
  4007b0:       50                      push   %rax
  4007b1:       e8 8a fd ff ff          callq  400540 <atanf@plt>
  4007b6:       58                      pop    %rax
  4007b7:       e9 94 fd ff ff          jmpq   400550 <tanf@plt>
  4007bc:       0f 1f 40 00             nopl   0x0(%rax)

for:
float mytan(float x) {
  return tanf(atanf(x));
}
we emit a single retq.

Differential Revision:	 http://reviews.llvm.org/D14302


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252098 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Davide Italiano 2015-11-04 23:36:56 +00:00
parent d022e94463
commit 9496ef1fef
4 changed files with 71 additions and 1 deletions

View File

@ -134,6 +134,7 @@ private:
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);

View File

@ -1359,6 +1359,40 @@ Value *LibCallSimplifier::optimizeSqrt(CallInst *CI, IRBuilder<> &B) {
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<CallInst>(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 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI) {
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 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI) {
case LibFunc::logb:
case LibFunc::sin:
case LibFunc::sinh:
case LibFunc::tan:
case LibFunc::tanh:
if (UnsafeFPShrink && hasFloatVersion(FuncName))
return optimizeUnaryDoubleFP(CI, Builder, true);

View File

@ -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)

View File

@ -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" }