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 const TargetTransformInfo *TTI) { 31 // There is no need to change the IR, since backend will emit sqrt 32 // instruction if the call has already been marked read-only. 33 if (Call->onlyReadsMemory()) 34 return false; 35 36 // Do the following transformation: 37 // 38 // (before) 39 // dst = sqrt(src) 40 // 41 // (after) 42 // v0 = sqrt_noreadmem(src) # native sqrt instruction. 43 // [if (v0 is a NaN) || if (src < 0)] 44 // v1 = sqrt(src) # library call. 45 // dst = phi(v0, v1) 46 // 47 48 // Move all instructions following Call to newly created block JoinBB. 49 // Create phi and replace all uses. 50 BasicBlock *JoinBB = llvm::SplitBlock(&CurrBB, Call->getNextNode()); 51 IRBuilder<> Builder(JoinBB, JoinBB->begin()); 52 Type *Ty = Call->getType(); 53 PHINode *Phi = Builder.CreatePHI(Ty, 2); 54 Call->replaceAllUsesWith(Phi); 55 56 // Create basic block LibCallBB and insert a call to library function sqrt. 57 BasicBlock *LibCallBB = BasicBlock::Create(CurrBB.getContext(), "call.sqrt", 58 CurrBB.getParent(), JoinBB); 59 Builder.SetInsertPoint(LibCallBB); 60 Instruction *LibCall = Call->clone(); 61 Builder.Insert(LibCall); 62 Builder.CreateBr(JoinBB); 63 64 // Add attribute "readnone" so that backend can use a native sqrt instruction 65 // for this call. Insert a FP compare instruction and a conditional branch 66 // at the end of CurrBB. 67 Call->addAttribute(AttributeList::FunctionIndex, Attribute::ReadNone); 68 CurrBB.getTerminator()->eraseFromParent(); 69 Builder.SetInsertPoint(&CurrBB); 70 Value *FCmp = TTI->isFCmpOrdCheaperThanFCmpZero(Ty) 71 ? Builder.CreateFCmpORD(Call, Call) 72 : Builder.CreateFCmpOGE(Call->getOperand(0), 73 ConstantFP::get(Ty, 0.0)); 74 Builder.CreateCondBr(FCmp, JoinBB, LibCallBB); 75 76 // Add phi operands. 77 Phi->addIncoming(Call, &CurrBB); 78 Phi->addIncoming(LibCall, LibCallBB); 79 80 BB = JoinBB->getIterator(); 81 return true; 82 } 83 84 static bool runPartiallyInlineLibCalls(Function &F, TargetLibraryInfo *TLI, 85 const TargetTransformInfo *TTI) { 86 bool Changed = false; 87 88 Function::iterator CurrBB; 89 for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE;) { 90 CurrBB = BB++; 91 92 for (BasicBlock::iterator II = CurrBB->begin(), IE = CurrBB->end(); 93 II != IE; ++II) { 94 CallInst *Call = dyn_cast<CallInst>(&*II); 95 Function *CalledFunc; 96 97 if (!Call || !(CalledFunc = Call->getCalledFunction())) 98 continue; 99 100 if (Call->isNoBuiltin()) 101 continue; 102 103 // Skip if function either has local linkage or is not a known library 104 // function. 105 LibFunc LF; 106 if (CalledFunc->hasLocalLinkage() || 107 !TLI->getLibFunc(*CalledFunc, LF) || !TLI->has(LF)) 108 continue; 109 110 switch (LF) { 111 case LibFunc_sqrtf: 112 case LibFunc_sqrt: 113 if (TTI->haveFastSqrt(Call->getType()) && 114 optimizeSQRT(Call, CalledFunc, *CurrBB, BB, TTI)) 115 break; 116 continue; 117 default: 118 continue; 119 } 120 121 Changed = true; 122 break; 123 } 124 } 125 126 return Changed; 127 } 128 129 PreservedAnalyses 130 PartiallyInlineLibCallsPass::run(Function &F, FunctionAnalysisManager &AM) { 131 auto &TLI = AM.getResult<TargetLibraryAnalysis>(F); 132 auto &TTI = AM.getResult<TargetIRAnalysis>(F); 133 if (!runPartiallyInlineLibCalls(F, &TLI, &TTI)) 134 return PreservedAnalyses::all(); 135 return PreservedAnalyses::none(); 136 } 137 138 namespace { 139 class PartiallyInlineLibCallsLegacyPass : public FunctionPass { 140 public: 141 static char ID; 142 143 PartiallyInlineLibCallsLegacyPass() : FunctionPass(ID) { 144 initializePartiallyInlineLibCallsLegacyPassPass( 145 *PassRegistry::getPassRegistry()); 146 } 147 148 void getAnalysisUsage(AnalysisUsage &AU) const override { 149 AU.addRequired<TargetLibraryInfoWrapperPass>(); 150 AU.addRequired<TargetTransformInfoWrapperPass>(); 151 FunctionPass::getAnalysisUsage(AU); 152 } 153 154 bool runOnFunction(Function &F) override { 155 if (skipFunction(F)) 156 return false; 157 158 TargetLibraryInfo *TLI = 159 &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(); 160 const TargetTransformInfo *TTI = 161 &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F); 162 return runPartiallyInlineLibCalls(F, TLI, TTI); 163 } 164 }; 165 } 166 167 char PartiallyInlineLibCallsLegacyPass::ID = 0; 168 INITIALIZE_PASS_BEGIN(PartiallyInlineLibCallsLegacyPass, 169 "partially-inline-libcalls", 170 "Partially inline calls to library functions", false, 171 false) 172 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) 173 INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) 174 INITIALIZE_PASS_END(PartiallyInlineLibCallsLegacyPass, 175 "partially-inline-libcalls", 176 "Partially inline calls to library functions", false, false) 177 178 FunctionPass *llvm::createPartiallyInlineLibCallsPass() { 179 return new PartiallyInlineLibCallsLegacyPass(); 180 } 181