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