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