1*61ba2e39SJustin Bogner //===-- InstrProfiling.cpp - Frontend instrumentation based profiling -----===//
2*61ba2e39SJustin Bogner //
3*61ba2e39SJustin Bogner //                     The LLVM Compiler Infrastructure
4*61ba2e39SJustin Bogner //
5*61ba2e39SJustin Bogner // This file is distributed under the University of Illinois Open Source
6*61ba2e39SJustin Bogner // License. See LICENSE.TXT for details.
7*61ba2e39SJustin Bogner //
8*61ba2e39SJustin Bogner //===----------------------------------------------------------------------===//
9*61ba2e39SJustin Bogner //
10*61ba2e39SJustin Bogner // This pass lowers instrprof_increment intrinsics emitted by a frontend for
11*61ba2e39SJustin Bogner // profiling. It also builds the data structures and initialization code needed
12*61ba2e39SJustin Bogner // for updating execution counts and emitting the profile at runtime.
13*61ba2e39SJustin Bogner //
14*61ba2e39SJustin Bogner //===----------------------------------------------------------------------===//
15*61ba2e39SJustin Bogner 
16*61ba2e39SJustin Bogner #include "llvm/Transforms/Instrumentation.h"
17*61ba2e39SJustin Bogner 
18*61ba2e39SJustin Bogner #include "llvm/ADT/Triple.h"
19*61ba2e39SJustin Bogner #include "llvm/IR/IRBuilder.h"
20*61ba2e39SJustin Bogner #include "llvm/IR/IntrinsicInst.h"
21*61ba2e39SJustin Bogner #include "llvm/IR/Module.h"
22*61ba2e39SJustin Bogner #include "llvm/Transforms/Utils/ModuleUtils.h"
23*61ba2e39SJustin Bogner 
24*61ba2e39SJustin Bogner using namespace llvm;
25*61ba2e39SJustin Bogner 
26*61ba2e39SJustin Bogner #define DEBUG_TYPE "instrprof"
27*61ba2e39SJustin Bogner 
28*61ba2e39SJustin Bogner namespace {
29*61ba2e39SJustin Bogner 
30*61ba2e39SJustin Bogner class InstrProfiling : public ModulePass {
31*61ba2e39SJustin Bogner public:
32*61ba2e39SJustin Bogner   static char ID;
33*61ba2e39SJustin Bogner 
34*61ba2e39SJustin Bogner   InstrProfiling() : ModulePass(ID) {}
35*61ba2e39SJustin Bogner 
36*61ba2e39SJustin Bogner   InstrProfiling(const InstrProfOptions &Options)
37*61ba2e39SJustin Bogner       : ModulePass(ID), Options(Options) {}
38*61ba2e39SJustin Bogner 
39*61ba2e39SJustin Bogner   const char *getPassName() const override {
40*61ba2e39SJustin Bogner     return "Frontend instrumentation-based coverage lowering";
41*61ba2e39SJustin Bogner   }
42*61ba2e39SJustin Bogner 
43*61ba2e39SJustin Bogner   bool runOnModule(Module &M) override;
44*61ba2e39SJustin Bogner 
45*61ba2e39SJustin Bogner   void getAnalysisUsage(AnalysisUsage &AU) const override {
46*61ba2e39SJustin Bogner     AU.setPreservesCFG();
47*61ba2e39SJustin Bogner   }
48*61ba2e39SJustin Bogner 
49*61ba2e39SJustin Bogner private:
50*61ba2e39SJustin Bogner   InstrProfOptions Options;
51*61ba2e39SJustin Bogner   Module *M;
52*61ba2e39SJustin Bogner   DenseMap<GlobalVariable *, GlobalVariable *> RegionCounters;
53*61ba2e39SJustin Bogner   std::vector<Value *> UsedVars;
54*61ba2e39SJustin Bogner 
55*61ba2e39SJustin Bogner   bool isMachO() const {
56*61ba2e39SJustin Bogner     return Triple(M->getTargetTriple()).isOSBinFormatMachO();
57*61ba2e39SJustin Bogner   }
58*61ba2e39SJustin Bogner 
59*61ba2e39SJustin Bogner   /// Get the section name for the counter variables.
60*61ba2e39SJustin Bogner   StringRef getCountersSection() const {
61*61ba2e39SJustin Bogner     return isMachO() ? "__DATA,__llvm_prf_cnts" : "__llvm_prf_cnts";
62*61ba2e39SJustin Bogner   }
63*61ba2e39SJustin Bogner 
64*61ba2e39SJustin Bogner   /// Get the section name for the name variables.
65*61ba2e39SJustin Bogner   StringRef getNameSection() const {
66*61ba2e39SJustin Bogner     return isMachO() ? "__DATA,__llvm_prf_names" : "__llvm_prf_names";
67*61ba2e39SJustin Bogner   }
68*61ba2e39SJustin Bogner 
69*61ba2e39SJustin Bogner   /// Get the section name for the profile data variables.
70*61ba2e39SJustin Bogner   StringRef getDataSection() const {
71*61ba2e39SJustin Bogner     return isMachO() ? "__DATA,__llvm_prf_data" : "__llvm_prf_data";
72*61ba2e39SJustin Bogner   }
73*61ba2e39SJustin Bogner 
74*61ba2e39SJustin Bogner   /// Replace instrprof_increment with an increment of the appropriate value.
75*61ba2e39SJustin Bogner   void lowerIncrement(InstrProfIncrementInst *Inc);
76*61ba2e39SJustin Bogner 
77*61ba2e39SJustin Bogner   /// Get the region counters for an increment, creating them if necessary.
78*61ba2e39SJustin Bogner   ///
79*61ba2e39SJustin Bogner   /// If the counter array doesn't yet exist, the profile data variables
80*61ba2e39SJustin Bogner   /// referring to them will also be created.
81*61ba2e39SJustin Bogner   GlobalVariable *getOrCreateRegionCounters(InstrProfIncrementInst *Inc);
82*61ba2e39SJustin Bogner 
83*61ba2e39SJustin Bogner   /// Emit runtime registration functions for each profile data variable.
84*61ba2e39SJustin Bogner   void emitRegistration();
85*61ba2e39SJustin Bogner 
86*61ba2e39SJustin Bogner   /// Emit the necessary plumbing to pull in the runtime initialization.
87*61ba2e39SJustin Bogner   void emitRuntimeHook();
88*61ba2e39SJustin Bogner 
89*61ba2e39SJustin Bogner   /// Add uses of our data variables and runtime hook.
90*61ba2e39SJustin Bogner   void emitUses();
91*61ba2e39SJustin Bogner 
92*61ba2e39SJustin Bogner   /// Create a static initializer for our data, on platforms that need it.
93*61ba2e39SJustin Bogner   void emitInitialization();
94*61ba2e39SJustin Bogner };
95*61ba2e39SJustin Bogner 
96*61ba2e39SJustin Bogner } // anonymous namespace
97*61ba2e39SJustin Bogner 
98*61ba2e39SJustin Bogner char InstrProfiling::ID = 0;
99*61ba2e39SJustin Bogner INITIALIZE_PASS(InstrProfiling, "instrprof",
100*61ba2e39SJustin Bogner                 "Frontend instrumentation-based coverage lowering.", false,
101*61ba2e39SJustin Bogner                 false)
102*61ba2e39SJustin Bogner 
103*61ba2e39SJustin Bogner ModulePass *llvm::createInstrProfilingPass(const InstrProfOptions &Options) {
104*61ba2e39SJustin Bogner   return new InstrProfiling(Options);
105*61ba2e39SJustin Bogner }
106*61ba2e39SJustin Bogner 
107*61ba2e39SJustin Bogner bool InstrProfiling::runOnModule(Module &M) {
108*61ba2e39SJustin Bogner   bool MadeChange = false;
109*61ba2e39SJustin Bogner 
110*61ba2e39SJustin Bogner   this->M = &M;
111*61ba2e39SJustin Bogner   RegionCounters.clear();
112*61ba2e39SJustin Bogner   UsedVars.clear();
113*61ba2e39SJustin Bogner 
114*61ba2e39SJustin Bogner   for (Function &F : M)
115*61ba2e39SJustin Bogner     for (BasicBlock &BB : F)
116*61ba2e39SJustin Bogner       for (auto I = BB.begin(), E = BB.end(); I != E;)
117*61ba2e39SJustin Bogner         if (auto *Inc = dyn_cast<InstrProfIncrementInst>(I++)) {
118*61ba2e39SJustin Bogner           lowerIncrement(Inc);
119*61ba2e39SJustin Bogner           MadeChange = true;
120*61ba2e39SJustin Bogner         }
121*61ba2e39SJustin Bogner   if (!MadeChange)
122*61ba2e39SJustin Bogner     return false;
123*61ba2e39SJustin Bogner 
124*61ba2e39SJustin Bogner   emitRegistration();
125*61ba2e39SJustin Bogner   emitRuntimeHook();
126*61ba2e39SJustin Bogner   emitUses();
127*61ba2e39SJustin Bogner   emitInitialization();
128*61ba2e39SJustin Bogner   return true;
129*61ba2e39SJustin Bogner }
130*61ba2e39SJustin Bogner 
131*61ba2e39SJustin Bogner void InstrProfiling::lowerIncrement(InstrProfIncrementInst *Inc) {
132*61ba2e39SJustin Bogner   GlobalVariable *Counters = getOrCreateRegionCounters(Inc);
133*61ba2e39SJustin Bogner 
134*61ba2e39SJustin Bogner   IRBuilder<> Builder(Inc->getParent(), *Inc);
135*61ba2e39SJustin Bogner   uint64_t Index = Inc->getIndex()->getZExtValue();
136*61ba2e39SJustin Bogner   llvm::Value *Addr = Builder.CreateConstInBoundsGEP2_64(Counters, 0, Index);
137*61ba2e39SJustin Bogner   llvm::Value *Count = Builder.CreateLoad(Addr, "pgocount");
138*61ba2e39SJustin Bogner   Count = Builder.CreateAdd(Count, Builder.getInt64(1));
139*61ba2e39SJustin Bogner   Inc->replaceAllUsesWith(Builder.CreateStore(Count, Addr));
140*61ba2e39SJustin Bogner   Inc->eraseFromParent();
141*61ba2e39SJustin Bogner }
142*61ba2e39SJustin Bogner 
143*61ba2e39SJustin Bogner /// Get the name of a profiling variable for a particular function.
144*61ba2e39SJustin Bogner static std::string getVarName(InstrProfIncrementInst *Inc, StringRef VarName) {
145*61ba2e39SJustin Bogner   auto *Arr = cast<ConstantDataArray>(Inc->getName()->getInitializer());
146*61ba2e39SJustin Bogner   StringRef Name = Arr->isCString() ? Arr->getAsCString() : Arr->getAsString();
147*61ba2e39SJustin Bogner   return ("__llvm_profile_" + VarName + "_" + Name).str();
148*61ba2e39SJustin Bogner }
149*61ba2e39SJustin Bogner 
150*61ba2e39SJustin Bogner GlobalVariable *
151*61ba2e39SJustin Bogner InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
152*61ba2e39SJustin Bogner   GlobalVariable *Name = Inc->getName();
153*61ba2e39SJustin Bogner   auto It = RegionCounters.find(Name);
154*61ba2e39SJustin Bogner   if (It != RegionCounters.end())
155*61ba2e39SJustin Bogner     return It->second;
156*61ba2e39SJustin Bogner 
157*61ba2e39SJustin Bogner   // Move the name variable to the right section.
158*61ba2e39SJustin Bogner   Name->setSection(getNameSection());
159*61ba2e39SJustin Bogner   Name->setAlignment(1);
160*61ba2e39SJustin Bogner 
161*61ba2e39SJustin Bogner   uint64_t NumCounters = Inc->getNumCounters()->getZExtValue();
162*61ba2e39SJustin Bogner   LLVMContext &Ctx = M->getContext();
163*61ba2e39SJustin Bogner   ArrayType *CounterTy = ArrayType::get(Type::getInt64Ty(Ctx), NumCounters);
164*61ba2e39SJustin Bogner 
165*61ba2e39SJustin Bogner   // Create the counters variable.
166*61ba2e39SJustin Bogner   auto *Counters = new GlobalVariable(*M, CounterTy, false, Name->getLinkage(),
167*61ba2e39SJustin Bogner                                       Constant::getNullValue(CounterTy),
168*61ba2e39SJustin Bogner                                       getVarName(Inc, "counters"));
169*61ba2e39SJustin Bogner   Counters->setVisibility(Name->getVisibility());
170*61ba2e39SJustin Bogner   Counters->setSection(getCountersSection());
171*61ba2e39SJustin Bogner   Counters->setAlignment(8);
172*61ba2e39SJustin Bogner 
173*61ba2e39SJustin Bogner   RegionCounters[Inc->getName()] = Counters;
174*61ba2e39SJustin Bogner 
175*61ba2e39SJustin Bogner   // Create data variable.
176*61ba2e39SJustin Bogner   auto *NameArrayTy = Name->getType()->getPointerElementType();
177*61ba2e39SJustin Bogner   auto *Int32Ty = Type::getInt32Ty(Ctx);
178*61ba2e39SJustin Bogner   auto *Int64Ty = Type::getInt64Ty(Ctx);
179*61ba2e39SJustin Bogner   auto *Int8PtrTy = Type::getInt8PtrTy(Ctx);
180*61ba2e39SJustin Bogner   auto *Int64PtrTy = Type::getInt64PtrTy(Ctx);
181*61ba2e39SJustin Bogner 
182*61ba2e39SJustin Bogner   Type *DataTypes[] = {Int32Ty, Int32Ty, Int64Ty, Int8PtrTy, Int64PtrTy};
183*61ba2e39SJustin Bogner   auto *DataTy = StructType::get(Ctx, makeArrayRef(DataTypes));
184*61ba2e39SJustin Bogner   Constant *DataVals[] = {
185*61ba2e39SJustin Bogner       ConstantInt::get(Int32Ty, NameArrayTy->getArrayNumElements()),
186*61ba2e39SJustin Bogner       ConstantInt::get(Int32Ty, NumCounters),
187*61ba2e39SJustin Bogner       ConstantInt::get(Int64Ty, Inc->getHash()->getZExtValue()),
188*61ba2e39SJustin Bogner       ConstantExpr::getBitCast(Name, Int8PtrTy),
189*61ba2e39SJustin Bogner       ConstantExpr::getBitCast(Counters, Int64PtrTy)};
190*61ba2e39SJustin Bogner   auto *Data = new GlobalVariable(*M, DataTy, true, Name->getLinkage(),
191*61ba2e39SJustin Bogner                                   ConstantStruct::get(DataTy, DataVals),
192*61ba2e39SJustin Bogner                                   getVarName(Inc, "data"));
193*61ba2e39SJustin Bogner   Data->setVisibility(Name->getVisibility());
194*61ba2e39SJustin Bogner   Data->setSection(getDataSection());
195*61ba2e39SJustin Bogner   Data->setAlignment(8);
196*61ba2e39SJustin Bogner 
197*61ba2e39SJustin Bogner   // Mark the data variable as used so that it isn't stripped out.
198*61ba2e39SJustin Bogner   UsedVars.push_back(Data);
199*61ba2e39SJustin Bogner 
200*61ba2e39SJustin Bogner   return Counters;
201*61ba2e39SJustin Bogner }
202*61ba2e39SJustin Bogner 
203*61ba2e39SJustin Bogner void InstrProfiling::emitRegistration() {
204*61ba2e39SJustin Bogner   // Don't do this for Darwin.  compiler-rt uses linker magic.
205*61ba2e39SJustin Bogner   if (Triple(M->getTargetTriple()).isOSDarwin())
206*61ba2e39SJustin Bogner     return;
207*61ba2e39SJustin Bogner 
208*61ba2e39SJustin Bogner   // Construct the function.
209*61ba2e39SJustin Bogner   auto *VoidTy = Type::getVoidTy(M->getContext());
210*61ba2e39SJustin Bogner   auto *VoidPtrTy = Type::getInt8PtrTy(M->getContext());
211*61ba2e39SJustin Bogner   auto *RegisterFTy = FunctionType::get(VoidTy, false);
212*61ba2e39SJustin Bogner   auto *RegisterF = Function::Create(RegisterFTy, GlobalValue::InternalLinkage,
213*61ba2e39SJustin Bogner                                      "__llvm_profile_register_functions", M);
214*61ba2e39SJustin Bogner   RegisterF->setUnnamedAddr(true);
215*61ba2e39SJustin Bogner   if (Options.NoRedZone)
216*61ba2e39SJustin Bogner     RegisterF->addFnAttr(Attribute::NoRedZone);
217*61ba2e39SJustin Bogner 
218*61ba2e39SJustin Bogner   auto *RuntimeRegisterTy = llvm::FunctionType::get(VoidTy, VoidPtrTy, false);
219*61ba2e39SJustin Bogner   auto *RuntimeRegisterF =
220*61ba2e39SJustin Bogner       Function::Create(RuntimeRegisterTy, GlobalVariable::ExternalLinkage,
221*61ba2e39SJustin Bogner                        "__llvm_profile_register_function", M);
222*61ba2e39SJustin Bogner 
223*61ba2e39SJustin Bogner   IRBuilder<> IRB(BasicBlock::Create(M->getContext(), "", RegisterF));
224*61ba2e39SJustin Bogner   for (Value *Data : UsedVars)
225*61ba2e39SJustin Bogner     IRB.CreateCall(RuntimeRegisterF, IRB.CreateBitCast(Data, VoidPtrTy));
226*61ba2e39SJustin Bogner   IRB.CreateRetVoid();
227*61ba2e39SJustin Bogner }
228*61ba2e39SJustin Bogner 
229*61ba2e39SJustin Bogner void InstrProfiling::emitRuntimeHook() {
230*61ba2e39SJustin Bogner   const char *const RuntimeVarName = "__llvm_profile_runtime";
231*61ba2e39SJustin Bogner   const char *const RuntimeUserName = "__llvm_profile_runtime_user";
232*61ba2e39SJustin Bogner 
233*61ba2e39SJustin Bogner   // If the module's provided its own runtime, we don't need to do anything.
234*61ba2e39SJustin Bogner   if (M->getGlobalVariable(RuntimeVarName))
235*61ba2e39SJustin Bogner     return;
236*61ba2e39SJustin Bogner 
237*61ba2e39SJustin Bogner   // Declare an external variable that will pull in the runtime initialization.
238*61ba2e39SJustin Bogner   auto *Int32Ty = Type::getInt32Ty(M->getContext());
239*61ba2e39SJustin Bogner   auto *Var =
240*61ba2e39SJustin Bogner       new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
241*61ba2e39SJustin Bogner                          nullptr, RuntimeVarName);
242*61ba2e39SJustin Bogner 
243*61ba2e39SJustin Bogner   // Make a function that uses it.
244*61ba2e39SJustin Bogner   auto *User =
245*61ba2e39SJustin Bogner       Function::Create(FunctionType::get(Int32Ty, false),
246*61ba2e39SJustin Bogner                        GlobalValue::LinkOnceODRLinkage, RuntimeUserName, M);
247*61ba2e39SJustin Bogner   User->addFnAttr(Attribute::NoInline);
248*61ba2e39SJustin Bogner   if (Options.NoRedZone)
249*61ba2e39SJustin Bogner     User->addFnAttr(Attribute::NoRedZone);
250*61ba2e39SJustin Bogner 
251*61ba2e39SJustin Bogner   IRBuilder<> IRB(BasicBlock::Create(M->getContext(), "", User));
252*61ba2e39SJustin Bogner   auto *Load = IRB.CreateLoad(Var);
253*61ba2e39SJustin Bogner   IRB.CreateRet(Load);
254*61ba2e39SJustin Bogner 
255*61ba2e39SJustin Bogner   // Mark the user variable as used so that it isn't stripped out.
256*61ba2e39SJustin Bogner   UsedVars.push_back(User);
257*61ba2e39SJustin Bogner }
258*61ba2e39SJustin Bogner 
259*61ba2e39SJustin Bogner void InstrProfiling::emitUses() {
260*61ba2e39SJustin Bogner   if (UsedVars.empty())
261*61ba2e39SJustin Bogner     return;
262*61ba2e39SJustin Bogner 
263*61ba2e39SJustin Bogner   GlobalVariable *LLVMUsed = M->getGlobalVariable("llvm.used");
264*61ba2e39SJustin Bogner   std::vector<Constant*> MergedVars;
265*61ba2e39SJustin Bogner   if (LLVMUsed) {
266*61ba2e39SJustin Bogner     // Collect the existing members of llvm.used.
267*61ba2e39SJustin Bogner     ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());
268*61ba2e39SJustin Bogner     for (unsigned I = 0, E = Inits->getNumOperands(); I != E; ++I)
269*61ba2e39SJustin Bogner       MergedVars.push_back(Inits->getOperand(I));
270*61ba2e39SJustin Bogner     LLVMUsed->eraseFromParent();
271*61ba2e39SJustin Bogner   }
272*61ba2e39SJustin Bogner 
273*61ba2e39SJustin Bogner   Type *i8PTy = Type::getInt8PtrTy(M->getContext());
274*61ba2e39SJustin Bogner   // Add uses for our data.
275*61ba2e39SJustin Bogner   for (auto *Value : UsedVars)
276*61ba2e39SJustin Bogner     MergedVars.push_back(
277*61ba2e39SJustin Bogner         ConstantExpr::getBitCast(cast<llvm::Constant>(Value), i8PTy));
278*61ba2e39SJustin Bogner 
279*61ba2e39SJustin Bogner   // Recreate llvm.used.
280*61ba2e39SJustin Bogner   ArrayType *ATy = ArrayType::get(i8PTy, MergedVars.size());
281*61ba2e39SJustin Bogner   LLVMUsed = new llvm::GlobalVariable(
282*61ba2e39SJustin Bogner       *M, ATy, false, llvm::GlobalValue::AppendingLinkage,
283*61ba2e39SJustin Bogner       llvm::ConstantArray::get(ATy, MergedVars), "llvm.used");
284*61ba2e39SJustin Bogner 
285*61ba2e39SJustin Bogner   LLVMUsed->setSection("llvm.metadata");
286*61ba2e39SJustin Bogner }
287*61ba2e39SJustin Bogner 
288*61ba2e39SJustin Bogner void InstrProfiling::emitInitialization() {
289*61ba2e39SJustin Bogner   Constant *RegisterF = M->getFunction("__llvm_profile_register_functions");
290*61ba2e39SJustin Bogner   if (!RegisterF)
291*61ba2e39SJustin Bogner     return;
292*61ba2e39SJustin Bogner 
293*61ba2e39SJustin Bogner   // Create the initialization function.
294*61ba2e39SJustin Bogner   auto *VoidTy = Type::getVoidTy(M->getContext());
295*61ba2e39SJustin Bogner   auto *F =
296*61ba2e39SJustin Bogner       Function::Create(FunctionType::get(VoidTy, false),
297*61ba2e39SJustin Bogner                        GlobalValue::InternalLinkage, "__llvm_profile_init", M);
298*61ba2e39SJustin Bogner   F->setUnnamedAddr(true);
299*61ba2e39SJustin Bogner   F->addFnAttr(Attribute::NoInline);
300*61ba2e39SJustin Bogner   if (Options.NoRedZone)
301*61ba2e39SJustin Bogner     F->addFnAttr(Attribute::NoRedZone);
302*61ba2e39SJustin Bogner 
303*61ba2e39SJustin Bogner   // Add the basic block and the necessary calls.
304*61ba2e39SJustin Bogner   IRBuilder<> IRB(BasicBlock::Create(M->getContext(), "", F));
305*61ba2e39SJustin Bogner   IRB.CreateCall(RegisterF);
306*61ba2e39SJustin Bogner   IRB.CreateRetVoid();
307*61ba2e39SJustin Bogner 
308*61ba2e39SJustin Bogner   appendToGlobalCtors(*M, F, 0);
309*61ba2e39SJustin Bogner }
310