xref: /llvm-project/bolt/include/bolt/Passes/Instrumentation.h (revision a5f3d1a803020167bd9d494a8a3921e7dcc1550a)
1 //===- bolt/Passes/Instrumentation.h ----------------------------*- C++ -*-===//
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 is an instrumentation pass that modifies the input binary to generate
10 // a profile after execution finishes. It can modify branches and calls to
11 // increment counters stored in the process memory. A runtime library is linked
12 // into the final binary to handle writing these counters to an fdata file. See
13 // runtime/instr.cpp
14 //
15 //===----------------------------------------------------------------------===//
16 
17 #ifndef BOLT_PASSES_INSTRUMENTATION_H
18 #define BOLT_PASSES_INSTRUMENTATION_H
19 
20 #include "bolt/Passes/BinaryPasses.h"
21 #include "bolt/Passes/InstrumentationSummary.h"
22 #include "llvm/Support/RWMutex.h"
23 
24 namespace llvm {
25 namespace bolt {
26 
27 class Instrumentation : public BinaryFunctionPass {
28 public:
Instrumentation(const cl::opt<bool> & PrintPass)29   Instrumentation(const cl::opt<bool> &PrintPass)
30       : BinaryFunctionPass(PrintPass),
31         Summary(std::make_unique<InstrumentationSummary>()) {}
32 
33   /// Modifies all functions by inserting instrumentation code (first step)
34   Error runOnFunctions(BinaryContext &BC) override;
35 
getName()36   const char *getName() const override { return "instrumentation"; }
37 
38 private:
39   void instrumentFunction(BinaryFunction &Function,
40                           MCPlusBuilder::AllocatorIdTy = 0);
41 
42   /// Retrieve the string table index for the name of \p Function. We encode
43   /// instrumented locations descriptions with the aid of a string table to
44   /// manage memory of the instrumentation runtime in a more efficient way.
45   /// If this function name is not represented in the string table yet, it will
46   /// be inserted and its index returned.
47   uint32_t getFunctionNameIndex(const BinaryFunction &Function);
48 
49   /// Metadata creation methods
50   void createIndCallDescription(const BinaryFunction &FromFunction,
51                                 uint32_t From);
52   void createIndCallTargetDescription(const BinaryFunction &ToFunction,
53                                       uint32_t To);
54   bool createCallDescription(FunctionDescription &FuncDesc,
55                              const BinaryFunction &FromFunction, uint32_t From,
56                              uint32_t FromNodeID,
57                              const BinaryFunction &ToFunction, uint32_t To,
58                              bool IsInvoke);
59   bool createEdgeDescription(FunctionDescription &FuncDesc,
60                              const BinaryFunction &FromFunction, uint32_t From,
61                              uint32_t FromNodeID,
62                              const BinaryFunction &ToFunction, uint32_t To,
63                              uint32_t ToNodeID, bool Instrumented);
64   void createLeafNodeDescription(FunctionDescription &FuncDesc, uint32_t Node);
65 
66   /// Create the sequence of instructions to increment a counter
67   InstructionListType createInstrumentationSnippet(BinaryContext &BC,
68                                                    bool IsLeaf);
69 
70   // Critical edges worklist
71   // This worklist keeps track of CFG edges <From-To> that needs to be split.
72   // This task is deferred until we finish processing all BBs because we can't
73   // modify the CFG while iterating over it. For each edge, \p SplitInstrsTy
74   // stores the list of instrumentation instructions as a vector of MCInsts.
75   // instrumentOneTarget() populates this, instrumentFunction() consumes.
76   using SplitWorklistTy =
77       std::vector<std::pair<BinaryBasicBlock *, BinaryBasicBlock *>>;
78   using SplitInstrsTy = std::vector<InstructionListType>;
79 
80   /// Instrument the branch or call in \p Iter. \p TargetBB should be non-null
81   /// if this is a local branch and null if it is a call. Return true if the
82   /// location was instrumented with an explicit counter or false if it just
83   /// created the description, but no explicit counters were necessary.
84   bool instrumentOneTarget(SplitWorklistTy &SplitWorklist,
85                            SplitInstrsTy &SplitInstrs,
86                            BinaryBasicBlock::iterator &Iter,
87                            BinaryFunction &FromFunction,
88                            BinaryBasicBlock &FromBB, uint32_t From,
89                            BinaryFunction &ToFunc, BinaryBasicBlock *TargetBB,
90                            uint32_t ToOffset, bool IsLeaf, bool IsInvoke,
91                            FunctionDescription *FuncDesc, uint32_t FromNodeID,
92                            uint32_t ToNodeID = 0);
93 
94   void instrumentLeafNode(BinaryBasicBlock &BB, BinaryBasicBlock::iterator Iter,
95                           bool IsLeaf, FunctionDescription &FuncDesc,
96                           uint32_t Node);
97 
98   void instrumentIndirectTarget(BinaryBasicBlock &BB,
99                                 BinaryBasicBlock::iterator &Iter,
100                                 BinaryFunction &FromFunction, uint32_t From);
101 
102   void createAuxiliaryFunctions(BinaryContext &BC);
103 
104   uint32_t getFDSize() const;
105 
106   /// Create a runtime library, pass the BinData over, and register it
107   /// under \p BC.
108   void setupRuntimeLibrary(BinaryContext &BC);
109 
110   /// strtab indices in StringTable for each function name
111   std::unordered_map<const BinaryFunction *, uint32_t> FuncToStringIdx;
112 
113   mutable llvm::sys::RWMutex FDMutex;
114 
115   /// The data generated during Instrumentation pass that needs to
116   /// be passed to the Instrument runtime library.
117   std::unique_ptr<InstrumentationSummary> Summary;
118 
119   /// Statistics on counters
120   uint32_t DirectCallCounters{0};
121   uint32_t BranchCounters{0};
122   uint32_t LeafNodeCounters{0};
123 
124   /// Indirect call instrumentation functions
125   BinaryFunction *IndCallHandlerExitBBFunction;
126   BinaryFunction *IndTailCallHandlerExitBBFunction;
127 };
128 } // namespace bolt
129 } // namespace llvm
130 
131 #endif
132