Coverage Report

Created: 2017-10-03 07:32

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