Home | History | Annotate | Download | only in Scalar
      1 //===--- PartiallyInlineLibCalls.cpp - Partially inline libcalls ----------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This pass tries to partially inline the fast path of well-known library
     11 // functions, such as using square-root instructions for cases where sqrt()
     12 // does not need to set errno.
     13 //
     14 //===----------------------------------------------------------------------===//
     15 
     16 #include "llvm/Transforms/Scalar/PartiallyInlineLibCalls.h"
     17 #include "llvm/Analysis/TargetLibraryInfo.h"
     18 #include "llvm/Analysis/TargetTransformInfo.h"
     19 #include "llvm/IR/IRBuilder.h"
     20 #include "llvm/Transforms/Scalar.h"
     21 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
     22 
     23 using namespace llvm;
     24 
     25 #define DEBUG_TYPE "partially-inline-libcalls"
     26 
     27 
     28 static bool optimizeSQRT(CallInst *Call, Function *CalledFunc,
     29                          BasicBlock &CurrBB, Function::iterator &BB) {
     30   // There is no need to change the IR, since backend will emit sqrt
     31   // instruction if the call has already been marked read-only.
     32   if (Call->onlyReadsMemory())
     33     return false;
     34 
     35   // The call must have the expected result type.
     36   if (!Call->getType()->isFloatingPointTy())
     37     return false;
     38 
     39   // Do the following transformation:
     40   //
     41   // (before)
     42   // dst = sqrt(src)
     43   //
     44   // (after)
     45   // v0 = sqrt_noreadmem(src) # native sqrt instruction.
     46   // if (v0 is a NaN)
     47   //   v1 = sqrt(src)         # library call.
     48   // dst = phi(v0, v1)
     49   //
     50 
     51   // Move all instructions following Call to newly created block JoinBB.
     52   // Create phi and replace all uses.
     53   BasicBlock *JoinBB = llvm::SplitBlock(&CurrBB, Call->getNextNode());
     54   IRBuilder<> Builder(JoinBB, JoinBB->begin());
     55   PHINode *Phi = Builder.CreatePHI(Call->getType(), 2);
     56   Call->replaceAllUsesWith(Phi);
     57 
     58   // Create basic block LibCallBB and insert a call to library function sqrt.
     59   BasicBlock *LibCallBB = BasicBlock::Create(CurrBB.getContext(), "call.sqrt",
     60                                              CurrBB.getParent(), JoinBB);
     61   Builder.SetInsertPoint(LibCallBB);
     62   Instruction *LibCall = Call->clone();
     63   Builder.Insert(LibCall);
     64   Builder.CreateBr(JoinBB);
     65 
     66   // Add attribute "readnone" so that backend can use a native sqrt instruction
     67   // for this call. Insert a FP compare instruction and a conditional branch
     68   // at the end of CurrBB.
     69   Call->addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone);
     70   CurrBB.getTerminator()->eraseFromParent();
     71   Builder.SetInsertPoint(&CurrBB);
     72   Value *FCmp = Builder.CreateFCmpOEQ(Call, Call);
     73   Builder.CreateCondBr(FCmp, JoinBB, LibCallBB);
     74 
     75   // Add phi operands.
     76   Phi->addIncoming(Call, &CurrBB);
     77   Phi->addIncoming(LibCall, LibCallBB);
     78 
     79   BB = JoinBB->getIterator();
     80   return true;
     81 }
     82 
     83 static bool runPartiallyInlineLibCalls(Function &F, TargetLibraryInfo *TLI,
     84                                        const TargetTransformInfo *TTI) {
     85   bool Changed = false;
     86 
     87   Function::iterator CurrBB;
     88   for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE;) {
     89     CurrBB = BB++;
     90 
     91     for (BasicBlock::iterator II = CurrBB->begin(), IE = CurrBB->end();
     92          II != IE; ++II) {
     93       CallInst *Call = dyn_cast<CallInst>(&*II);
     94       Function *CalledFunc;
     95 
     96       if (!Call || !(CalledFunc = Call->getCalledFunction()))
     97         continue;
     98 
     99       // Skip if function either has local linkage or is not a known library
    100       // function.
    101       LibFunc::Func LibFunc;
    102       if (CalledFunc->hasLocalLinkage() || !CalledFunc->hasName() ||
    103           !TLI->getLibFunc(CalledFunc->getName(), LibFunc))
    104         continue;
    105 
    106       switch (LibFunc) {
    107       case LibFunc::sqrtf:
    108       case LibFunc::sqrt:
    109         if (TTI->haveFastSqrt(Call->getType()) &&
    110             optimizeSQRT(Call, CalledFunc, *CurrBB, BB))
    111           break;
    112         continue;
    113       default:
    114         continue;
    115       }
    116 
    117       Changed = true;
    118       break;
    119     }
    120   }
    121 
    122   return Changed;
    123 }
    124 
    125 PreservedAnalyses
    126 PartiallyInlineLibCallsPass::run(Function &F, AnalysisManager<Function> &AM) {
    127   auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
    128   auto &TTI = AM.getResult<TargetIRAnalysis>(F);
    129   if (!runPartiallyInlineLibCalls(F, &TLI, &TTI))
    130     return PreservedAnalyses::all();
    131   return PreservedAnalyses::none();
    132 }
    133 
    134 namespace {
    135 class PartiallyInlineLibCallsLegacyPass : public FunctionPass {
    136 public:
    137   static char ID;
    138 
    139   PartiallyInlineLibCallsLegacyPass() : FunctionPass(ID) {
    140     initializePartiallyInlineLibCallsLegacyPassPass(
    141         *PassRegistry::getPassRegistry());
    142   }
    143 
    144   void getAnalysisUsage(AnalysisUsage &AU) const override {
    145     AU.addRequired<TargetLibraryInfoWrapperPass>();
    146     AU.addRequired<TargetTransformInfoWrapperPass>();
    147     FunctionPass::getAnalysisUsage(AU);
    148   }
    149 
    150   bool runOnFunction(Function &F) override {
    151     if (skipFunction(F))
    152       return false;
    153 
    154     TargetLibraryInfo *TLI =
    155         &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
    156     const TargetTransformInfo *TTI =
    157         &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
    158     return runPartiallyInlineLibCalls(F, TLI, TTI);
    159   }
    160 };
    161 }
    162 
    163 char PartiallyInlineLibCallsLegacyPass::ID = 0;
    164 INITIALIZE_PASS_BEGIN(PartiallyInlineLibCallsLegacyPass,
    165                       "partially-inline-libcalls",
    166                       "Partially inline calls to library functions", false,
    167                       false)
    168 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
    169 INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
    170 INITIALIZE_PASS_END(PartiallyInlineLibCallsLegacyPass,
    171                     "partially-inline-libcalls",
    172                     "Partially inline calls to library functions", false, false)
    173 
    174 FunctionPass *llvm::createPartiallyInlineLibCallsPass() {
    175   return new PartiallyInlineLibCallsLegacyPass();
    176 }
    177