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