Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- PartiallyInlineLibCalls.cpp - Partially inline libcalls ----------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This pass tries to partially inline the fast path of well-known library
10
// functions, such as using square-root instructions for cases where sqrt()
11
// does not need to set errno.
12
//
13
//===----------------------------------------------------------------------===//
14
15
#include "llvm/Transforms/Scalar/PartiallyInlineLibCalls.h"
16
#include "llvm/Analysis/TargetLibraryInfo.h"
17
#include "llvm/Analysis/TargetTransformInfo.h"
18
#include "llvm/IR/IRBuilder.h"
19
#include "llvm/Support/DebugCounter.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
DEBUG_COUNTER(PILCounter, "partially-inline-libcalls-transform",
28
              "Controls transformations in partially-inline-libcalls");
29
30
static bool optimizeSQRT(CallInst *Call, Function *CalledFunc,
31
                         BasicBlock &CurrBB, Function::iterator &BB,
32
48
                         const TargetTransformInfo *TTI) {
33
48
  // There is no need to change the IR, since backend will emit sqrt
34
48
  // instruction if the call has already been marked read-only.
35
48
  if (Call->onlyReadsMemory())
36
21
    return false;
37
27
38
27
  if (!DebugCounter::shouldExecute(PILCounter))
39
0
    return false;
40
27
41
27
  // Do the following transformation:
42
27
  //
43
27
  // (before)
44
27
  // dst = sqrt(src)
45
27
  //
46
27
  // (after)
47
27
  // v0 = sqrt_noreadmem(src) # native sqrt instruction.
48
27
  // [if (v0 is a NaN) || if (src < 0)]
49
27
  //   v1 = sqrt(src)         # library call.
50
27
  // dst = phi(v0, v1)
51
27
  //
52
27
53
27
  // Move all instructions following Call to newly created block JoinBB.
54
27
  // Create phi and replace all uses.
55
27
  BasicBlock *JoinBB = llvm::SplitBlock(&CurrBB, Call->getNextNode());
56
27
  IRBuilder<> Builder(JoinBB, JoinBB->begin());
57
27
  Type *Ty = Call->getType();
58
27
  PHINode *Phi = Builder.CreatePHI(Ty, 2);
59
27
  Call->replaceAllUsesWith(Phi);
60
27
61
27
  // Create basic block LibCallBB and insert a call to library function sqrt.
62
27
  BasicBlock *LibCallBB = BasicBlock::Create(CurrBB.getContext(), "call.sqrt",
63
27
                                             CurrBB.getParent(), JoinBB);
64
27
  Builder.SetInsertPoint(LibCallBB);
65
27
  Instruction *LibCall = Call->clone();
66
27
  Builder.Insert(LibCall);
67
27
  Builder.CreateBr(JoinBB);
68
27
69
27
  // Add attribute "readnone" so that backend can use a native sqrt instruction
70
27
  // for this call. Insert a FP compare instruction and a conditional branch
71
27
  // at the end of CurrBB.
72
27
  Call->addAttribute(AttributeList::FunctionIndex, Attribute::ReadNone);
73
27
  CurrBB.getTerminator()->eraseFromParent();
74
27
  Builder.SetInsertPoint(&CurrBB);
75
27
  Value *FCmp = TTI->isFCmpOrdCheaperThanFCmpZero(Ty)
76
27
                    ? 
Builder.CreateFCmpORD(Call, Call)22
77
27
                    : Builder.CreateFCmpOGE(Call->getOperand(0),
78
5
                                            ConstantFP::get(Ty, 0.0));
79
27
  Builder.CreateCondBr(FCmp, JoinBB, LibCallBB);
80
27
81
27
  // Add phi operands.
82
27
  Phi->addIncoming(Call, &CurrBB);
83
27
  Phi->addIncoming(LibCall, LibCallBB);
84
27
85
27
  BB = JoinBB->getIterator();
86
27
  return true;
87
27
}
88
89
static bool runPartiallyInlineLibCalls(Function &F, TargetLibraryInfo *TLI,
90
489k
                                       const TargetTransformInfo *TTI) {
91
489k
  bool Changed = false;
92
489k
93
489k
  Function::iterator CurrBB;
94
3.18M
  for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE;) {
95
2.69M
    CurrBB = BB++;
96
2.69M
97
2.69M
    for (BasicBlock::iterator II = CurrBB->begin(), IE = CurrBB->end();
98
17.0M
         II != IE; 
++II14.3M
) {
99
14.3M
      CallInst *Call = dyn_cast<CallInst>(&*II);
100
14.3M
      Function *CalledFunc;
101
14.3M
102
14.3M
      if (!Call || 
!(CalledFunc = Call->getCalledFunction())1.83M
)
103
12.5M
        continue;
104
1.75M
105
1.75M
      if (Call->isNoBuiltin())
106
1.02M
        continue;
107
726k
108
726k
      // Skip if function either has local linkage or is not a known library
109
726k
      // function.
110
726k
      LibFunc LF;
111
726k
      if (CalledFunc->hasLocalLinkage() ||
112
726k
          
!TLI->getLibFunc(*CalledFunc, LF)705k
||
!TLI->has(LF)112k
)
113
618k
        continue;
114
107k
115
107k
      switch (LF) {
116
107k
      case LibFunc_sqrtf:
117
54
      case LibFunc_sqrt:
118
54
        if (TTI->haveFastSqrt(Call->getType()) &&
119
54
            
optimizeSQRT(Call, CalledFunc, *CurrBB, BB, TTI)48
)
120
27
          break;
121
27
        continue;
122
107k
      default:
123
107k
        continue;
124
27
      }
125
27
126
27
      Changed = true;
127
27
      break;
128
27
    }
129
2.69M
  }
130
489k
131
489k
  return Changed;
132
489k
}
133
134
PreservedAnalyses
135
4
PartiallyInlineLibCallsPass::run(Function &F, FunctionAnalysisManager &AM) {
136
4
  auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
137
4
  auto &TTI = AM.getResult<TargetIRAnalysis>(F);
138
4
  if (!runPartiallyInlineLibCalls(F, &TLI, &TTI))
139
3
    return PreservedAnalyses::all();
140
1
  return PreservedAnalyses::none();
141
1
}
142
143
namespace {
144
class PartiallyInlineLibCallsLegacyPass : public FunctionPass {
145
public:
146
  static char ID;
147
148
34.5k
  PartiallyInlineLibCallsLegacyPass() : FunctionPass(ID) {
149
34.5k
    initializePartiallyInlineLibCallsLegacyPassPass(
150
34.5k
        *PassRegistry::getPassRegistry());
151
34.5k
  }
152
153
34.3k
  void getAnalysisUsage(AnalysisUsage &AU) const override {
154
34.3k
    AU.addRequired<TargetLibraryInfoWrapperPass>();
155
34.3k
    AU.addRequired<TargetTransformInfoWrapperPass>();
156
34.3k
    FunctionPass::getAnalysisUsage(AU);
157
34.3k
  }
158
159
490k
  bool runOnFunction(Function &F) override {
160
490k
    if (skipFunction(F))
161
272
      return false;
162
489k
163
489k
    TargetLibraryInfo *TLI =
164
489k
        &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
165
489k
    const TargetTransformInfo *TTI =
166
489k
        &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
167
489k
    return runPartiallyInlineLibCalls(F, TLI, TTI);
168
489k
  }
169
};
170
}
171
172
char PartiallyInlineLibCallsLegacyPass::ID = 0;
173
48.6k
INITIALIZE_PASS_BEGIN(PartiallyInlineLibCallsLegacyPass,
174
48.6k
                      "partially-inline-libcalls",
175
48.6k
                      "Partially inline calls to library functions", false,
176
48.6k
                      false)
177
48.6k
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
178
48.6k
INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
179
48.6k
INITIALIZE_PASS_END(PartiallyInlineLibCallsLegacyPass,
180
                    "partially-inline-libcalls",
181
                    "Partially inline calls to library functions", false, false)
182
183
34.5k
FunctionPass *llvm::createPartiallyInlineLibCallsPass() {
184
34.5k
  return new PartiallyInlineLibCallsLegacyPass();
185
34.5k
}