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