LLVM API Documentation

PartiallyInlineLibCalls.cpp
Go to the documentation of this file.
00001 //===--- PartiallyInlineLibCalls.cpp - Partially inline libcalls ----------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This pass tries to partially inline the fast path of well-known library
00011 // functions, such as using square-root instructions for cases where sqrt()
00012 // does not need to set errno.
00013 //
00014 //===----------------------------------------------------------------------===//
00015 
00016 #include "llvm/Analysis/TargetTransformInfo.h"
00017 #include "llvm/IR/IRBuilder.h"
00018 #include "llvm/IR/Intrinsics.h"
00019 #include "llvm/Pass.h"
00020 #include "llvm/Support/CommandLine.h"
00021 #include "llvm/Target/TargetLibraryInfo.h"
00022 #include "llvm/Transforms/Scalar.h"
00023 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
00024 
00025 using namespace llvm;
00026 
00027 #define DEBUG_TYPE "partially-inline-libcalls"
00028 
00029 namespace {
00030   class PartiallyInlineLibCalls : public FunctionPass {
00031   public:
00032     static char ID;
00033 
00034     PartiallyInlineLibCalls() :
00035       FunctionPass(ID) {
00036       initializePartiallyInlineLibCallsPass(*PassRegistry::getPassRegistry());
00037     }
00038 
00039     void getAnalysisUsage(AnalysisUsage &AU) const override;
00040     bool runOnFunction(Function &F) override;
00041 
00042   private:
00043     /// Optimize calls to sqrt.
00044     bool optimizeSQRT(CallInst *Call, Function *CalledFunc,
00045                       BasicBlock &CurrBB, Function::iterator &BB);
00046   };
00047 
00048   char PartiallyInlineLibCalls::ID = 0;
00049 }
00050 
00051 INITIALIZE_PASS(PartiallyInlineLibCalls, "partially-inline-libcalls",
00052                 "Partially inline calls to library functions", false, false)
00053 
00054 void PartiallyInlineLibCalls::getAnalysisUsage(AnalysisUsage &AU) const {
00055   AU.addRequired<TargetLibraryInfo>();
00056   AU.addRequired<TargetTransformInfo>();
00057   FunctionPass::getAnalysisUsage(AU);
00058 }
00059 
00060 bool PartiallyInlineLibCalls::runOnFunction(Function &F) {
00061   bool Changed = false;
00062   Function::iterator CurrBB;
00063   TargetLibraryInfo *TLI = &getAnalysis<TargetLibraryInfo>();
00064   const TargetTransformInfo *TTI = &getAnalysis<TargetTransformInfo>();
00065   for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE;) {
00066     CurrBB = BB++;
00067 
00068     for (BasicBlock::iterator II = CurrBB->begin(), IE = CurrBB->end();
00069          II != IE; ++II) {
00070       CallInst *Call = dyn_cast<CallInst>(&*II);
00071       Function *CalledFunc;
00072 
00073       if (!Call || !(CalledFunc = Call->getCalledFunction()))
00074         continue;
00075 
00076       // Skip if function either has local linkage or is not a known library
00077       // function.
00078       LibFunc::Func LibFunc;
00079       if (CalledFunc->hasLocalLinkage() || !CalledFunc->hasName() ||
00080           !TLI->getLibFunc(CalledFunc->getName(), LibFunc))
00081         continue;
00082 
00083       switch (LibFunc) {
00084       case LibFunc::sqrtf:
00085       case LibFunc::sqrt:
00086         if (TTI->haveFastSqrt(Call->getType()) &&
00087             optimizeSQRT(Call, CalledFunc, *CurrBB, BB))
00088           break;
00089         continue;
00090       default:
00091         continue;
00092       }
00093 
00094       Changed = true;
00095       break;
00096     }
00097   }
00098 
00099   return Changed;
00100 }
00101 
00102 bool PartiallyInlineLibCalls::optimizeSQRT(CallInst *Call,
00103                                            Function *CalledFunc,
00104                                            BasicBlock &CurrBB,
00105                                            Function::iterator &BB) {
00106   // There is no need to change the IR, since backend will emit sqrt
00107   // instruction if the call has already been marked read-only.
00108   if (Call->onlyReadsMemory())
00109     return false;
00110 
00111   // The call must have the expected result type.
00112   if (!Call->getType()->isFloatingPointTy())
00113     return false;
00114 
00115   // Do the following transformation:
00116   //
00117   // (before)
00118   // dst = sqrt(src)
00119   //
00120   // (after)
00121   // v0 = sqrt_noreadmem(src) # native sqrt instruction.
00122   // if (v0 is a NaN)
00123   //   v1 = sqrt(src)         # library call.
00124   // dst = phi(v0, v1)
00125   //
00126 
00127   // Move all instructions following Call to newly created block JoinBB.
00128   // Create phi and replace all uses.
00129   BasicBlock *JoinBB = llvm::SplitBlock(&CurrBB, Call->getNextNode(), this);
00130   IRBuilder<> Builder(JoinBB, JoinBB->begin());
00131   PHINode *Phi = Builder.CreatePHI(Call->getType(), 2);
00132   Call->replaceAllUsesWith(Phi);
00133 
00134   // Create basic block LibCallBB and insert a call to library function sqrt.
00135   BasicBlock *LibCallBB = BasicBlock::Create(CurrBB.getContext(), "call.sqrt",
00136                                              CurrBB.getParent(), JoinBB);
00137   Builder.SetInsertPoint(LibCallBB);
00138   Instruction *LibCall = Call->clone();
00139   Builder.Insert(LibCall);
00140   Builder.CreateBr(JoinBB);
00141 
00142   // Add attribute "readnone" so that backend can use a native sqrt instruction
00143   // for this call. Insert a FP compare instruction and a conditional branch
00144   // at the end of CurrBB.
00145   Call->addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone);
00146   CurrBB.getTerminator()->eraseFromParent();
00147   Builder.SetInsertPoint(&CurrBB);
00148   Value *FCmp = Builder.CreateFCmpOEQ(Call, Call);
00149   Builder.CreateCondBr(FCmp, JoinBB, LibCallBB);
00150 
00151   // Add phi operands.
00152   Phi->addIncoming(Call, &CurrBB);
00153   Phi->addIncoming(LibCall, LibCallBB);
00154 
00155   BB = JoinBB;
00156   return true;
00157 }
00158 
00159 FunctionPass *llvm::createPartiallyInlineLibCallsPass() {
00160   return new PartiallyInlineLibCalls();
00161 }