xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp (revision 04eeddc0aa8e0a417a16eaf9d7d095207f4a8623)
1e8d8bef9SDimitry Andric //===- MemProfiler.cpp - memory allocation and access profiler ------------===//
2e8d8bef9SDimitry Andric //
3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e8d8bef9SDimitry Andric //
7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
8e8d8bef9SDimitry Andric //
9e8d8bef9SDimitry Andric // This file is a part of MemProfiler. Memory accesses are instrumented
10e8d8bef9SDimitry Andric // to increment the access count held in a shadow memory location, or
11e8d8bef9SDimitry Andric // alternatively to call into the runtime. Memory intrinsic calls (memmove,
12e8d8bef9SDimitry Andric // memcpy, memset) are changed to call the memory profiling runtime version
13e8d8bef9SDimitry Andric // instead.
14e8d8bef9SDimitry Andric //
15e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
16e8d8bef9SDimitry Andric 
17e8d8bef9SDimitry Andric #include "llvm/Transforms/Instrumentation/MemProfiler.h"
18e8d8bef9SDimitry Andric #include "llvm/ADT/SmallVector.h"
19e8d8bef9SDimitry Andric #include "llvm/ADT/Statistic.h"
20e8d8bef9SDimitry Andric #include "llvm/ADT/StringRef.h"
21e8d8bef9SDimitry Andric #include "llvm/ADT/Triple.h"
22349cc55cSDimitry Andric #include "llvm/Analysis/ValueTracking.h"
23e8d8bef9SDimitry Andric #include "llvm/IR/Constant.h"
24e8d8bef9SDimitry Andric #include "llvm/IR/DataLayout.h"
25e8d8bef9SDimitry Andric #include "llvm/IR/Function.h"
26e8d8bef9SDimitry Andric #include "llvm/IR/GlobalValue.h"
27e8d8bef9SDimitry Andric #include "llvm/IR/IRBuilder.h"
28e8d8bef9SDimitry Andric #include "llvm/IR/Instruction.h"
29e8d8bef9SDimitry Andric #include "llvm/IR/LLVMContext.h"
30e8d8bef9SDimitry Andric #include "llvm/IR/Module.h"
31e8d8bef9SDimitry Andric #include "llvm/IR/Type.h"
32e8d8bef9SDimitry Andric #include "llvm/IR/Value.h"
33e8d8bef9SDimitry Andric #include "llvm/InitializePasses.h"
34e8d8bef9SDimitry Andric #include "llvm/Pass.h"
35e8d8bef9SDimitry Andric #include "llvm/Support/CommandLine.h"
36e8d8bef9SDimitry Andric #include "llvm/Support/Debug.h"
37e8d8bef9SDimitry Andric #include "llvm/Transforms/Instrumentation.h"
38e8d8bef9SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h"
39e8d8bef9SDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h"
40e8d8bef9SDimitry Andric 
41e8d8bef9SDimitry Andric using namespace llvm;
42e8d8bef9SDimitry Andric 
43e8d8bef9SDimitry Andric #define DEBUG_TYPE "memprof"
44e8d8bef9SDimitry Andric 
45e8d8bef9SDimitry Andric constexpr int LLVM_MEM_PROFILER_VERSION = 1;
46e8d8bef9SDimitry Andric 
47e8d8bef9SDimitry Andric // Size of memory mapped to a single shadow location.
48e8d8bef9SDimitry Andric constexpr uint64_t DefaultShadowGranularity = 64;
49e8d8bef9SDimitry Andric 
50e8d8bef9SDimitry Andric // Scale from granularity down to shadow size.
51e8d8bef9SDimitry Andric constexpr uint64_t DefaultShadowScale = 3;
52e8d8bef9SDimitry Andric 
53e8d8bef9SDimitry Andric constexpr char MemProfModuleCtorName[] = "memprof.module_ctor";
54e8d8bef9SDimitry Andric constexpr uint64_t MemProfCtorAndDtorPriority = 1;
55e8d8bef9SDimitry Andric // On Emscripten, the system needs more than one priorities for constructors.
56e8d8bef9SDimitry Andric constexpr uint64_t MemProfEmscriptenCtorAndDtorPriority = 50;
57e8d8bef9SDimitry Andric constexpr char MemProfInitName[] = "__memprof_init";
58e8d8bef9SDimitry Andric constexpr char MemProfVersionCheckNamePrefix[] =
59e8d8bef9SDimitry Andric     "__memprof_version_mismatch_check_v";
60e8d8bef9SDimitry Andric 
61e8d8bef9SDimitry Andric constexpr char MemProfShadowMemoryDynamicAddress[] =
62e8d8bef9SDimitry Andric     "__memprof_shadow_memory_dynamic_address";
63e8d8bef9SDimitry Andric 
64e8d8bef9SDimitry Andric constexpr char MemProfFilenameVar[] = "__memprof_profile_filename";
65e8d8bef9SDimitry Andric 
66e8d8bef9SDimitry Andric // Command-line flags.
67e8d8bef9SDimitry Andric 
68e8d8bef9SDimitry Andric static cl::opt<bool> ClInsertVersionCheck(
69e8d8bef9SDimitry Andric     "memprof-guard-against-version-mismatch",
70e8d8bef9SDimitry Andric     cl::desc("Guard against compiler/runtime version mismatch."), cl::Hidden,
71e8d8bef9SDimitry Andric     cl::init(true));
72e8d8bef9SDimitry Andric 
73e8d8bef9SDimitry Andric // This flag may need to be replaced with -f[no-]memprof-reads.
74e8d8bef9SDimitry Andric static cl::opt<bool> ClInstrumentReads("memprof-instrument-reads",
75e8d8bef9SDimitry Andric                                        cl::desc("instrument read instructions"),
76e8d8bef9SDimitry Andric                                        cl::Hidden, cl::init(true));
77e8d8bef9SDimitry Andric 
78e8d8bef9SDimitry Andric static cl::opt<bool>
79e8d8bef9SDimitry Andric     ClInstrumentWrites("memprof-instrument-writes",
80e8d8bef9SDimitry Andric                        cl::desc("instrument write instructions"), cl::Hidden,
81e8d8bef9SDimitry Andric                        cl::init(true));
82e8d8bef9SDimitry Andric 
83e8d8bef9SDimitry Andric static cl::opt<bool> ClInstrumentAtomics(
84e8d8bef9SDimitry Andric     "memprof-instrument-atomics",
85e8d8bef9SDimitry Andric     cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden,
86e8d8bef9SDimitry Andric     cl::init(true));
87e8d8bef9SDimitry Andric 
88e8d8bef9SDimitry Andric static cl::opt<bool> ClUseCalls(
89e8d8bef9SDimitry Andric     "memprof-use-callbacks",
90e8d8bef9SDimitry Andric     cl::desc("Use callbacks instead of inline instrumentation sequences."),
91e8d8bef9SDimitry Andric     cl::Hidden, cl::init(false));
92e8d8bef9SDimitry Andric 
93e8d8bef9SDimitry Andric static cl::opt<std::string>
94e8d8bef9SDimitry Andric     ClMemoryAccessCallbackPrefix("memprof-memory-access-callback-prefix",
95e8d8bef9SDimitry Andric                                  cl::desc("Prefix for memory access callbacks"),
96e8d8bef9SDimitry Andric                                  cl::Hidden, cl::init("__memprof_"));
97e8d8bef9SDimitry Andric 
98e8d8bef9SDimitry Andric // These flags allow to change the shadow mapping.
99e8d8bef9SDimitry Andric // The shadow mapping looks like
100e8d8bef9SDimitry Andric //    Shadow = ((Mem & mask) >> scale) + offset
101e8d8bef9SDimitry Andric 
102e8d8bef9SDimitry Andric static cl::opt<int> ClMappingScale("memprof-mapping-scale",
103e8d8bef9SDimitry Andric                                    cl::desc("scale of memprof shadow mapping"),
104e8d8bef9SDimitry Andric                                    cl::Hidden, cl::init(DefaultShadowScale));
105e8d8bef9SDimitry Andric 
106e8d8bef9SDimitry Andric static cl::opt<int>
107e8d8bef9SDimitry Andric     ClMappingGranularity("memprof-mapping-granularity",
108e8d8bef9SDimitry Andric                          cl::desc("granularity of memprof shadow mapping"),
109e8d8bef9SDimitry Andric                          cl::Hidden, cl::init(DefaultShadowGranularity));
110e8d8bef9SDimitry Andric 
111349cc55cSDimitry Andric static cl::opt<bool> ClStack("memprof-instrument-stack",
112349cc55cSDimitry Andric                              cl::desc("Instrument scalar stack variables"),
113349cc55cSDimitry Andric                              cl::Hidden, cl::init(false));
114349cc55cSDimitry Andric 
115e8d8bef9SDimitry Andric // Debug flags.
116e8d8bef9SDimitry Andric 
117e8d8bef9SDimitry Andric static cl::opt<int> ClDebug("memprof-debug", cl::desc("debug"), cl::Hidden,
118e8d8bef9SDimitry Andric                             cl::init(0));
119e8d8bef9SDimitry Andric 
120e8d8bef9SDimitry Andric static cl::opt<std::string> ClDebugFunc("memprof-debug-func", cl::Hidden,
121e8d8bef9SDimitry Andric                                         cl::desc("Debug func"));
122e8d8bef9SDimitry Andric 
123e8d8bef9SDimitry Andric static cl::opt<int> ClDebugMin("memprof-debug-min", cl::desc("Debug min inst"),
124e8d8bef9SDimitry Andric                                cl::Hidden, cl::init(-1));
125e8d8bef9SDimitry Andric 
126e8d8bef9SDimitry Andric static cl::opt<int> ClDebugMax("memprof-debug-max", cl::desc("Debug max inst"),
127e8d8bef9SDimitry Andric                                cl::Hidden, cl::init(-1));
128e8d8bef9SDimitry Andric 
129e8d8bef9SDimitry Andric STATISTIC(NumInstrumentedReads, "Number of instrumented reads");
130e8d8bef9SDimitry Andric STATISTIC(NumInstrumentedWrites, "Number of instrumented writes");
131349cc55cSDimitry Andric STATISTIC(NumSkippedStackReads, "Number of non-instrumented stack reads");
132349cc55cSDimitry Andric STATISTIC(NumSkippedStackWrites, "Number of non-instrumented stack writes");
133e8d8bef9SDimitry Andric 
134e8d8bef9SDimitry Andric namespace {
135e8d8bef9SDimitry Andric 
136e8d8bef9SDimitry Andric /// This struct defines the shadow mapping using the rule:
137e8d8bef9SDimitry Andric ///   shadow = ((mem & mask) >> Scale) ADD DynamicShadowOffset.
138e8d8bef9SDimitry Andric struct ShadowMapping {
139e8d8bef9SDimitry Andric   ShadowMapping() {
140e8d8bef9SDimitry Andric     Scale = ClMappingScale;
141e8d8bef9SDimitry Andric     Granularity = ClMappingGranularity;
142e8d8bef9SDimitry Andric     Mask = ~(Granularity - 1);
143e8d8bef9SDimitry Andric   }
144e8d8bef9SDimitry Andric 
145e8d8bef9SDimitry Andric   int Scale;
146e8d8bef9SDimitry Andric   int Granularity;
147e8d8bef9SDimitry Andric   uint64_t Mask; // Computed as ~(Granularity-1)
148e8d8bef9SDimitry Andric };
149e8d8bef9SDimitry Andric 
150e8d8bef9SDimitry Andric static uint64_t getCtorAndDtorPriority(Triple &TargetTriple) {
151e8d8bef9SDimitry Andric   return TargetTriple.isOSEmscripten() ? MemProfEmscriptenCtorAndDtorPriority
152e8d8bef9SDimitry Andric                                        : MemProfCtorAndDtorPriority;
153e8d8bef9SDimitry Andric }
154e8d8bef9SDimitry Andric 
155e8d8bef9SDimitry Andric struct InterestingMemoryAccess {
156e8d8bef9SDimitry Andric   Value *Addr = nullptr;
157e8d8bef9SDimitry Andric   bool IsWrite;
158e8d8bef9SDimitry Andric   unsigned Alignment;
159*04eeddc0SDimitry Andric   Type *AccessTy;
160e8d8bef9SDimitry Andric   uint64_t TypeSize;
161e8d8bef9SDimitry Andric   Value *MaybeMask = nullptr;
162e8d8bef9SDimitry Andric };
163e8d8bef9SDimitry Andric 
164e8d8bef9SDimitry Andric /// Instrument the code in module to profile memory accesses.
165e8d8bef9SDimitry Andric class MemProfiler {
166e8d8bef9SDimitry Andric public:
167e8d8bef9SDimitry Andric   MemProfiler(Module &M) {
168e8d8bef9SDimitry Andric     C = &(M.getContext());
169e8d8bef9SDimitry Andric     LongSize = M.getDataLayout().getPointerSizeInBits();
170e8d8bef9SDimitry Andric     IntptrTy = Type::getIntNTy(*C, LongSize);
171e8d8bef9SDimitry Andric   }
172e8d8bef9SDimitry Andric 
173e8d8bef9SDimitry Andric   /// If it is an interesting memory access, populate information
174e8d8bef9SDimitry Andric   /// about the access and return a InterestingMemoryAccess struct.
175e8d8bef9SDimitry Andric   /// Otherwise return None.
176e8d8bef9SDimitry Andric   Optional<InterestingMemoryAccess>
177e8d8bef9SDimitry Andric   isInterestingMemoryAccess(Instruction *I) const;
178e8d8bef9SDimitry Andric 
179e8d8bef9SDimitry Andric   void instrumentMop(Instruction *I, const DataLayout &DL,
180e8d8bef9SDimitry Andric                      InterestingMemoryAccess &Access);
181e8d8bef9SDimitry Andric   void instrumentAddress(Instruction *OrigIns, Instruction *InsertBefore,
182e8d8bef9SDimitry Andric                          Value *Addr, uint32_t TypeSize, bool IsWrite);
183e8d8bef9SDimitry Andric   void instrumentMaskedLoadOrStore(const DataLayout &DL, Value *Mask,
184e8d8bef9SDimitry Andric                                    Instruction *I, Value *Addr,
185*04eeddc0SDimitry Andric                                    unsigned Alignment, Type *AccessTy,
186e8d8bef9SDimitry Andric                                    bool IsWrite);
187e8d8bef9SDimitry Andric   void instrumentMemIntrinsic(MemIntrinsic *MI);
188e8d8bef9SDimitry Andric   Value *memToShadow(Value *Shadow, IRBuilder<> &IRB);
189e8d8bef9SDimitry Andric   bool instrumentFunction(Function &F);
190e8d8bef9SDimitry Andric   bool maybeInsertMemProfInitAtFunctionEntry(Function &F);
191e8d8bef9SDimitry Andric   bool insertDynamicShadowAtFunctionEntry(Function &F);
192e8d8bef9SDimitry Andric 
193e8d8bef9SDimitry Andric private:
194e8d8bef9SDimitry Andric   void initializeCallbacks(Module &M);
195e8d8bef9SDimitry Andric 
196e8d8bef9SDimitry Andric   LLVMContext *C;
197e8d8bef9SDimitry Andric   int LongSize;
198e8d8bef9SDimitry Andric   Type *IntptrTy;
199e8d8bef9SDimitry Andric   ShadowMapping Mapping;
200e8d8bef9SDimitry Andric 
201e8d8bef9SDimitry Andric   // These arrays is indexed by AccessIsWrite
202e8d8bef9SDimitry Andric   FunctionCallee MemProfMemoryAccessCallback[2];
203e8d8bef9SDimitry Andric   FunctionCallee MemProfMemoryAccessCallbackSized[2];
204e8d8bef9SDimitry Andric 
205e8d8bef9SDimitry Andric   FunctionCallee MemProfMemmove, MemProfMemcpy, MemProfMemset;
206e8d8bef9SDimitry Andric   Value *DynamicShadowOffset = nullptr;
207e8d8bef9SDimitry Andric };
208e8d8bef9SDimitry Andric 
209e8d8bef9SDimitry Andric class MemProfilerLegacyPass : public FunctionPass {
210e8d8bef9SDimitry Andric public:
211e8d8bef9SDimitry Andric   static char ID;
212e8d8bef9SDimitry Andric 
213e8d8bef9SDimitry Andric   explicit MemProfilerLegacyPass() : FunctionPass(ID) {
214e8d8bef9SDimitry Andric     initializeMemProfilerLegacyPassPass(*PassRegistry::getPassRegistry());
215e8d8bef9SDimitry Andric   }
216e8d8bef9SDimitry Andric 
217e8d8bef9SDimitry Andric   StringRef getPassName() const override { return "MemProfilerFunctionPass"; }
218e8d8bef9SDimitry Andric 
219e8d8bef9SDimitry Andric   bool runOnFunction(Function &F) override {
220e8d8bef9SDimitry Andric     MemProfiler Profiler(*F.getParent());
221e8d8bef9SDimitry Andric     return Profiler.instrumentFunction(F);
222e8d8bef9SDimitry Andric   }
223e8d8bef9SDimitry Andric };
224e8d8bef9SDimitry Andric 
225e8d8bef9SDimitry Andric class ModuleMemProfiler {
226e8d8bef9SDimitry Andric public:
227e8d8bef9SDimitry Andric   ModuleMemProfiler(Module &M) { TargetTriple = Triple(M.getTargetTriple()); }
228e8d8bef9SDimitry Andric 
229e8d8bef9SDimitry Andric   bool instrumentModule(Module &);
230e8d8bef9SDimitry Andric 
231e8d8bef9SDimitry Andric private:
232e8d8bef9SDimitry Andric   Triple TargetTriple;
233e8d8bef9SDimitry Andric   ShadowMapping Mapping;
234e8d8bef9SDimitry Andric   Function *MemProfCtorFunction = nullptr;
235e8d8bef9SDimitry Andric };
236e8d8bef9SDimitry Andric 
237e8d8bef9SDimitry Andric class ModuleMemProfilerLegacyPass : public ModulePass {
238e8d8bef9SDimitry Andric public:
239e8d8bef9SDimitry Andric   static char ID;
240e8d8bef9SDimitry Andric 
241e8d8bef9SDimitry Andric   explicit ModuleMemProfilerLegacyPass() : ModulePass(ID) {
242e8d8bef9SDimitry Andric     initializeModuleMemProfilerLegacyPassPass(*PassRegistry::getPassRegistry());
243e8d8bef9SDimitry Andric   }
244e8d8bef9SDimitry Andric 
245e8d8bef9SDimitry Andric   StringRef getPassName() const override { return "ModuleMemProfiler"; }
246e8d8bef9SDimitry Andric 
247e8d8bef9SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {}
248e8d8bef9SDimitry Andric 
249e8d8bef9SDimitry Andric   bool runOnModule(Module &M) override {
250e8d8bef9SDimitry Andric     ModuleMemProfiler MemProfiler(M);
251e8d8bef9SDimitry Andric     return MemProfiler.instrumentModule(M);
252e8d8bef9SDimitry Andric   }
253e8d8bef9SDimitry Andric };
254e8d8bef9SDimitry Andric 
255e8d8bef9SDimitry Andric } // end anonymous namespace
256e8d8bef9SDimitry Andric 
257e8d8bef9SDimitry Andric MemProfilerPass::MemProfilerPass() {}
258e8d8bef9SDimitry Andric 
259e8d8bef9SDimitry Andric PreservedAnalyses MemProfilerPass::run(Function &F,
260e8d8bef9SDimitry Andric                                        AnalysisManager<Function> &AM) {
261e8d8bef9SDimitry Andric   Module &M = *F.getParent();
262e8d8bef9SDimitry Andric   MemProfiler Profiler(M);
263e8d8bef9SDimitry Andric   if (Profiler.instrumentFunction(F))
264e8d8bef9SDimitry Andric     return PreservedAnalyses::none();
265e8d8bef9SDimitry Andric   return PreservedAnalyses::all();
266e8d8bef9SDimitry Andric }
267e8d8bef9SDimitry Andric 
268e8d8bef9SDimitry Andric ModuleMemProfilerPass::ModuleMemProfilerPass() {}
269e8d8bef9SDimitry Andric 
270e8d8bef9SDimitry Andric PreservedAnalyses ModuleMemProfilerPass::run(Module &M,
271e8d8bef9SDimitry Andric                                              AnalysisManager<Module> &AM) {
272e8d8bef9SDimitry Andric   ModuleMemProfiler Profiler(M);
273e8d8bef9SDimitry Andric   if (Profiler.instrumentModule(M))
274e8d8bef9SDimitry Andric     return PreservedAnalyses::none();
275e8d8bef9SDimitry Andric   return PreservedAnalyses::all();
276e8d8bef9SDimitry Andric }
277e8d8bef9SDimitry Andric 
278e8d8bef9SDimitry Andric char MemProfilerLegacyPass::ID = 0;
279e8d8bef9SDimitry Andric 
280e8d8bef9SDimitry Andric INITIALIZE_PASS_BEGIN(MemProfilerLegacyPass, "memprof",
281e8d8bef9SDimitry Andric                       "MemProfiler: profile memory allocations and accesses.",
282e8d8bef9SDimitry Andric                       false, false)
283e8d8bef9SDimitry Andric INITIALIZE_PASS_END(MemProfilerLegacyPass, "memprof",
284e8d8bef9SDimitry Andric                     "MemProfiler: profile memory allocations and accesses.",
285e8d8bef9SDimitry Andric                     false, false)
286e8d8bef9SDimitry Andric 
287e8d8bef9SDimitry Andric FunctionPass *llvm::createMemProfilerFunctionPass() {
288e8d8bef9SDimitry Andric   return new MemProfilerLegacyPass();
289e8d8bef9SDimitry Andric }
290e8d8bef9SDimitry Andric 
291e8d8bef9SDimitry Andric char ModuleMemProfilerLegacyPass::ID = 0;
292e8d8bef9SDimitry Andric 
293e8d8bef9SDimitry Andric INITIALIZE_PASS(ModuleMemProfilerLegacyPass, "memprof-module",
294e8d8bef9SDimitry Andric                 "MemProfiler: profile memory allocations and accesses."
295e8d8bef9SDimitry Andric                 "ModulePass",
296e8d8bef9SDimitry Andric                 false, false)
297e8d8bef9SDimitry Andric 
298e8d8bef9SDimitry Andric ModulePass *llvm::createModuleMemProfilerLegacyPassPass() {
299e8d8bef9SDimitry Andric   return new ModuleMemProfilerLegacyPass();
300e8d8bef9SDimitry Andric }
301e8d8bef9SDimitry Andric 
302e8d8bef9SDimitry Andric Value *MemProfiler::memToShadow(Value *Shadow, IRBuilder<> &IRB) {
303e8d8bef9SDimitry Andric   // (Shadow & mask) >> scale
304e8d8bef9SDimitry Andric   Shadow = IRB.CreateAnd(Shadow, Mapping.Mask);
305e8d8bef9SDimitry Andric   Shadow = IRB.CreateLShr(Shadow, Mapping.Scale);
306e8d8bef9SDimitry Andric   // (Shadow >> scale) | offset
307e8d8bef9SDimitry Andric   assert(DynamicShadowOffset);
308e8d8bef9SDimitry Andric   return IRB.CreateAdd(Shadow, DynamicShadowOffset);
309e8d8bef9SDimitry Andric }
310e8d8bef9SDimitry Andric 
311e8d8bef9SDimitry Andric // Instrument memset/memmove/memcpy
312e8d8bef9SDimitry Andric void MemProfiler::instrumentMemIntrinsic(MemIntrinsic *MI) {
313e8d8bef9SDimitry Andric   IRBuilder<> IRB(MI);
314e8d8bef9SDimitry Andric   if (isa<MemTransferInst>(MI)) {
315e8d8bef9SDimitry Andric     IRB.CreateCall(
316e8d8bef9SDimitry Andric         isa<MemMoveInst>(MI) ? MemProfMemmove : MemProfMemcpy,
317e8d8bef9SDimitry Andric         {IRB.CreatePointerCast(MI->getOperand(0), IRB.getInt8PtrTy()),
318e8d8bef9SDimitry Andric          IRB.CreatePointerCast(MI->getOperand(1), IRB.getInt8PtrTy()),
319e8d8bef9SDimitry Andric          IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)});
320e8d8bef9SDimitry Andric   } else if (isa<MemSetInst>(MI)) {
321e8d8bef9SDimitry Andric     IRB.CreateCall(
322e8d8bef9SDimitry Andric         MemProfMemset,
323e8d8bef9SDimitry Andric         {IRB.CreatePointerCast(MI->getOperand(0), IRB.getInt8PtrTy()),
324e8d8bef9SDimitry Andric          IRB.CreateIntCast(MI->getOperand(1), IRB.getInt32Ty(), false),
325e8d8bef9SDimitry Andric          IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)});
326e8d8bef9SDimitry Andric   }
327e8d8bef9SDimitry Andric   MI->eraseFromParent();
328e8d8bef9SDimitry Andric }
329e8d8bef9SDimitry Andric 
330e8d8bef9SDimitry Andric Optional<InterestingMemoryAccess>
331e8d8bef9SDimitry Andric MemProfiler::isInterestingMemoryAccess(Instruction *I) const {
332e8d8bef9SDimitry Andric   // Do not instrument the load fetching the dynamic shadow address.
333e8d8bef9SDimitry Andric   if (DynamicShadowOffset == I)
334e8d8bef9SDimitry Andric     return None;
335e8d8bef9SDimitry Andric 
336e8d8bef9SDimitry Andric   InterestingMemoryAccess Access;
337e8d8bef9SDimitry Andric 
338e8d8bef9SDimitry Andric   if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
339e8d8bef9SDimitry Andric     if (!ClInstrumentReads)
340e8d8bef9SDimitry Andric       return None;
341e8d8bef9SDimitry Andric     Access.IsWrite = false;
342*04eeddc0SDimitry Andric     Access.AccessTy = LI->getType();
343e8d8bef9SDimitry Andric     Access.Alignment = LI->getAlignment();
344e8d8bef9SDimitry Andric     Access.Addr = LI->getPointerOperand();
345e8d8bef9SDimitry Andric   } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
346e8d8bef9SDimitry Andric     if (!ClInstrumentWrites)
347e8d8bef9SDimitry Andric       return None;
348e8d8bef9SDimitry Andric     Access.IsWrite = true;
349*04eeddc0SDimitry Andric     Access.AccessTy = SI->getValueOperand()->getType();
350e8d8bef9SDimitry Andric     Access.Alignment = SI->getAlignment();
351e8d8bef9SDimitry Andric     Access.Addr = SI->getPointerOperand();
352e8d8bef9SDimitry Andric   } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) {
353e8d8bef9SDimitry Andric     if (!ClInstrumentAtomics)
354e8d8bef9SDimitry Andric       return None;
355e8d8bef9SDimitry Andric     Access.IsWrite = true;
356*04eeddc0SDimitry Andric     Access.AccessTy = RMW->getValOperand()->getType();
357e8d8bef9SDimitry Andric     Access.Alignment = 0;
358e8d8bef9SDimitry Andric     Access.Addr = RMW->getPointerOperand();
359e8d8bef9SDimitry Andric   } else if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) {
360e8d8bef9SDimitry Andric     if (!ClInstrumentAtomics)
361e8d8bef9SDimitry Andric       return None;
362e8d8bef9SDimitry Andric     Access.IsWrite = true;
363*04eeddc0SDimitry Andric     Access.AccessTy = XCHG->getCompareOperand()->getType();
364e8d8bef9SDimitry Andric     Access.Alignment = 0;
365e8d8bef9SDimitry Andric     Access.Addr = XCHG->getPointerOperand();
366e8d8bef9SDimitry Andric   } else if (auto *CI = dyn_cast<CallInst>(I)) {
367e8d8bef9SDimitry Andric     auto *F = CI->getCalledFunction();
368e8d8bef9SDimitry Andric     if (F && (F->getIntrinsicID() == Intrinsic::masked_load ||
369e8d8bef9SDimitry Andric               F->getIntrinsicID() == Intrinsic::masked_store)) {
370e8d8bef9SDimitry Andric       unsigned OpOffset = 0;
371e8d8bef9SDimitry Andric       if (F->getIntrinsicID() == Intrinsic::masked_store) {
372e8d8bef9SDimitry Andric         if (!ClInstrumentWrites)
373e8d8bef9SDimitry Andric           return None;
374e8d8bef9SDimitry Andric         // Masked store has an initial operand for the value.
375e8d8bef9SDimitry Andric         OpOffset = 1;
376*04eeddc0SDimitry Andric         Access.AccessTy = CI->getArgOperand(0)->getType();
377e8d8bef9SDimitry Andric         Access.IsWrite = true;
378e8d8bef9SDimitry Andric       } else {
379e8d8bef9SDimitry Andric         if (!ClInstrumentReads)
380e8d8bef9SDimitry Andric           return None;
381*04eeddc0SDimitry Andric         Access.AccessTy = CI->getType();
382e8d8bef9SDimitry Andric         Access.IsWrite = false;
383e8d8bef9SDimitry Andric       }
384e8d8bef9SDimitry Andric 
385e8d8bef9SDimitry Andric       auto *BasePtr = CI->getOperand(0 + OpOffset);
386e8d8bef9SDimitry Andric       if (auto *AlignmentConstant =
387e8d8bef9SDimitry Andric               dyn_cast<ConstantInt>(CI->getOperand(1 + OpOffset)))
388e8d8bef9SDimitry Andric         Access.Alignment = (unsigned)AlignmentConstant->getZExtValue();
389e8d8bef9SDimitry Andric       else
390e8d8bef9SDimitry Andric         Access.Alignment = 1; // No alignment guarantees. We probably got Undef
391e8d8bef9SDimitry Andric       Access.MaybeMask = CI->getOperand(2 + OpOffset);
392e8d8bef9SDimitry Andric       Access.Addr = BasePtr;
393e8d8bef9SDimitry Andric     }
394e8d8bef9SDimitry Andric   }
395e8d8bef9SDimitry Andric 
396e8d8bef9SDimitry Andric   if (!Access.Addr)
397e8d8bef9SDimitry Andric     return None;
398e8d8bef9SDimitry Andric 
399e8d8bef9SDimitry Andric   // Do not instrument acesses from different address spaces; we cannot deal
400e8d8bef9SDimitry Andric   // with them.
401e8d8bef9SDimitry Andric   Type *PtrTy = cast<PointerType>(Access.Addr->getType()->getScalarType());
402e8d8bef9SDimitry Andric   if (PtrTy->getPointerAddressSpace() != 0)
403e8d8bef9SDimitry Andric     return None;
404e8d8bef9SDimitry Andric 
405e8d8bef9SDimitry Andric   // Ignore swifterror addresses.
406e8d8bef9SDimitry Andric   // swifterror memory addresses are mem2reg promoted by instruction
407e8d8bef9SDimitry Andric   // selection. As such they cannot have regular uses like an instrumentation
408e8d8bef9SDimitry Andric   // function and it makes no sense to track them as memory.
409e8d8bef9SDimitry Andric   if (Access.Addr->isSwiftError())
410e8d8bef9SDimitry Andric     return None;
411e8d8bef9SDimitry Andric 
412*04eeddc0SDimitry Andric   const DataLayout &DL = I->getModule()->getDataLayout();
413*04eeddc0SDimitry Andric   Access.TypeSize = DL.getTypeStoreSizeInBits(Access.AccessTy);
414e8d8bef9SDimitry Andric   return Access;
415e8d8bef9SDimitry Andric }
416e8d8bef9SDimitry Andric 
417e8d8bef9SDimitry Andric void MemProfiler::instrumentMaskedLoadOrStore(const DataLayout &DL, Value *Mask,
418e8d8bef9SDimitry Andric                                               Instruction *I, Value *Addr,
419e8d8bef9SDimitry Andric                                               unsigned Alignment,
420*04eeddc0SDimitry Andric                                               Type *AccessTy, bool IsWrite) {
421*04eeddc0SDimitry Andric   auto *VTy = cast<FixedVectorType>(AccessTy);
422e8d8bef9SDimitry Andric   uint64_t ElemTypeSize = DL.getTypeStoreSizeInBits(VTy->getScalarType());
423e8d8bef9SDimitry Andric   unsigned Num = VTy->getNumElements();
424e8d8bef9SDimitry Andric   auto *Zero = ConstantInt::get(IntptrTy, 0);
425e8d8bef9SDimitry Andric   for (unsigned Idx = 0; Idx < Num; ++Idx) {
426e8d8bef9SDimitry Andric     Value *InstrumentedAddress = nullptr;
427e8d8bef9SDimitry Andric     Instruction *InsertBefore = I;
428e8d8bef9SDimitry Andric     if (auto *Vector = dyn_cast<ConstantVector>(Mask)) {
429e8d8bef9SDimitry Andric       // dyn_cast as we might get UndefValue
430e8d8bef9SDimitry Andric       if (auto *Masked = dyn_cast<ConstantInt>(Vector->getOperand(Idx))) {
431e8d8bef9SDimitry Andric         if (Masked->isZero())
432e8d8bef9SDimitry Andric           // Mask is constant false, so no instrumentation needed.
433e8d8bef9SDimitry Andric           continue;
434e8d8bef9SDimitry Andric         // If we have a true or undef value, fall through to instrumentAddress.
435e8d8bef9SDimitry Andric         // with InsertBefore == I
436e8d8bef9SDimitry Andric       }
437e8d8bef9SDimitry Andric     } else {
438e8d8bef9SDimitry Andric       IRBuilder<> IRB(I);
439e8d8bef9SDimitry Andric       Value *MaskElem = IRB.CreateExtractElement(Mask, Idx);
440e8d8bef9SDimitry Andric       Instruction *ThenTerm = SplitBlockAndInsertIfThen(MaskElem, I, false);
441e8d8bef9SDimitry Andric       InsertBefore = ThenTerm;
442e8d8bef9SDimitry Andric     }
443e8d8bef9SDimitry Andric 
444e8d8bef9SDimitry Andric     IRBuilder<> IRB(InsertBefore);
445e8d8bef9SDimitry Andric     InstrumentedAddress =
446e8d8bef9SDimitry Andric         IRB.CreateGEP(VTy, Addr, {Zero, ConstantInt::get(IntptrTy, Idx)});
447e8d8bef9SDimitry Andric     instrumentAddress(I, InsertBefore, InstrumentedAddress, ElemTypeSize,
448e8d8bef9SDimitry Andric                       IsWrite);
449e8d8bef9SDimitry Andric   }
450e8d8bef9SDimitry Andric }
451e8d8bef9SDimitry Andric 
452e8d8bef9SDimitry Andric void MemProfiler::instrumentMop(Instruction *I, const DataLayout &DL,
453e8d8bef9SDimitry Andric                                 InterestingMemoryAccess &Access) {
454349cc55cSDimitry Andric   // Skip instrumentation of stack accesses unless requested.
455349cc55cSDimitry Andric   if (!ClStack && isa<AllocaInst>(getUnderlyingObject(Access.Addr))) {
456349cc55cSDimitry Andric     if (Access.IsWrite)
457349cc55cSDimitry Andric       ++NumSkippedStackWrites;
458349cc55cSDimitry Andric     else
459349cc55cSDimitry Andric       ++NumSkippedStackReads;
460349cc55cSDimitry Andric     return;
461349cc55cSDimitry Andric   }
462349cc55cSDimitry Andric 
463e8d8bef9SDimitry Andric   if (Access.IsWrite)
464e8d8bef9SDimitry Andric     NumInstrumentedWrites++;
465e8d8bef9SDimitry Andric   else
466e8d8bef9SDimitry Andric     NumInstrumentedReads++;
467e8d8bef9SDimitry Andric 
468e8d8bef9SDimitry Andric   if (Access.MaybeMask) {
469e8d8bef9SDimitry Andric     instrumentMaskedLoadOrStore(DL, Access.MaybeMask, I, Access.Addr,
470*04eeddc0SDimitry Andric                                 Access.Alignment, Access.AccessTy,
471e8d8bef9SDimitry Andric                                 Access.IsWrite);
472e8d8bef9SDimitry Andric   } else {
473e8d8bef9SDimitry Andric     // Since the access counts will be accumulated across the entire allocation,
474e8d8bef9SDimitry Andric     // we only update the shadow access count for the first location and thus
475e8d8bef9SDimitry Andric     // don't need to worry about alignment and type size.
476e8d8bef9SDimitry Andric     instrumentAddress(I, I, Access.Addr, Access.TypeSize, Access.IsWrite);
477e8d8bef9SDimitry Andric   }
478e8d8bef9SDimitry Andric }
479e8d8bef9SDimitry Andric 
480e8d8bef9SDimitry Andric void MemProfiler::instrumentAddress(Instruction *OrigIns,
481e8d8bef9SDimitry Andric                                     Instruction *InsertBefore, Value *Addr,
482e8d8bef9SDimitry Andric                                     uint32_t TypeSize, bool IsWrite) {
483e8d8bef9SDimitry Andric   IRBuilder<> IRB(InsertBefore);
484e8d8bef9SDimitry Andric   Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
485e8d8bef9SDimitry Andric 
486e8d8bef9SDimitry Andric   if (ClUseCalls) {
487e8d8bef9SDimitry Andric     IRB.CreateCall(MemProfMemoryAccessCallback[IsWrite], AddrLong);
488e8d8bef9SDimitry Andric     return;
489e8d8bef9SDimitry Andric   }
490e8d8bef9SDimitry Andric 
491e8d8bef9SDimitry Andric   // Create an inline sequence to compute shadow location, and increment the
492e8d8bef9SDimitry Andric   // value by one.
493e8d8bef9SDimitry Andric   Type *ShadowTy = Type::getInt64Ty(*C);
494e8d8bef9SDimitry Andric   Type *ShadowPtrTy = PointerType::get(ShadowTy, 0);
495e8d8bef9SDimitry Andric   Value *ShadowPtr = memToShadow(AddrLong, IRB);
496e8d8bef9SDimitry Andric   Value *ShadowAddr = IRB.CreateIntToPtr(ShadowPtr, ShadowPtrTy);
497e8d8bef9SDimitry Andric   Value *ShadowValue = IRB.CreateLoad(ShadowTy, ShadowAddr);
498e8d8bef9SDimitry Andric   Value *Inc = ConstantInt::get(Type::getInt64Ty(*C), 1);
499e8d8bef9SDimitry Andric   ShadowValue = IRB.CreateAdd(ShadowValue, Inc);
500e8d8bef9SDimitry Andric   IRB.CreateStore(ShadowValue, ShadowAddr);
501e8d8bef9SDimitry Andric }
502e8d8bef9SDimitry Andric 
503e8d8bef9SDimitry Andric // Create the variable for the profile file name.
504e8d8bef9SDimitry Andric void createProfileFileNameVar(Module &M) {
505e8d8bef9SDimitry Andric   const MDString *MemProfFilename =
506e8d8bef9SDimitry Andric       dyn_cast_or_null<MDString>(M.getModuleFlag("MemProfProfileFilename"));
507e8d8bef9SDimitry Andric   if (!MemProfFilename)
508e8d8bef9SDimitry Andric     return;
509e8d8bef9SDimitry Andric   assert(!MemProfFilename->getString().empty() &&
510e8d8bef9SDimitry Andric          "Unexpected MemProfProfileFilename metadata with empty string");
511e8d8bef9SDimitry Andric   Constant *ProfileNameConst = ConstantDataArray::getString(
512e8d8bef9SDimitry Andric       M.getContext(), MemProfFilename->getString(), true);
513e8d8bef9SDimitry Andric   GlobalVariable *ProfileNameVar = new GlobalVariable(
514e8d8bef9SDimitry Andric       M, ProfileNameConst->getType(), /*isConstant=*/true,
515e8d8bef9SDimitry Andric       GlobalValue::WeakAnyLinkage, ProfileNameConst, MemProfFilenameVar);
516e8d8bef9SDimitry Andric   Triple TT(M.getTargetTriple());
517e8d8bef9SDimitry Andric   if (TT.supportsCOMDAT()) {
518e8d8bef9SDimitry Andric     ProfileNameVar->setLinkage(GlobalValue::ExternalLinkage);
519e8d8bef9SDimitry Andric     ProfileNameVar->setComdat(M.getOrInsertComdat(MemProfFilenameVar));
520e8d8bef9SDimitry Andric   }
521e8d8bef9SDimitry Andric }
522e8d8bef9SDimitry Andric 
523e8d8bef9SDimitry Andric bool ModuleMemProfiler::instrumentModule(Module &M) {
524e8d8bef9SDimitry Andric   // Create a module constructor.
525e8d8bef9SDimitry Andric   std::string MemProfVersion = std::to_string(LLVM_MEM_PROFILER_VERSION);
526e8d8bef9SDimitry Andric   std::string VersionCheckName =
527e8d8bef9SDimitry Andric       ClInsertVersionCheck ? (MemProfVersionCheckNamePrefix + MemProfVersion)
528e8d8bef9SDimitry Andric                            : "";
529e8d8bef9SDimitry Andric   std::tie(MemProfCtorFunction, std::ignore) =
530e8d8bef9SDimitry Andric       createSanitizerCtorAndInitFunctions(M, MemProfModuleCtorName,
531e8d8bef9SDimitry Andric                                           MemProfInitName, /*InitArgTypes=*/{},
532e8d8bef9SDimitry Andric                                           /*InitArgs=*/{}, VersionCheckName);
533e8d8bef9SDimitry Andric 
534e8d8bef9SDimitry Andric   const uint64_t Priority = getCtorAndDtorPriority(TargetTriple);
535e8d8bef9SDimitry Andric   appendToGlobalCtors(M, MemProfCtorFunction, Priority);
536e8d8bef9SDimitry Andric 
537e8d8bef9SDimitry Andric   createProfileFileNameVar(M);
538e8d8bef9SDimitry Andric 
539e8d8bef9SDimitry Andric   return true;
540e8d8bef9SDimitry Andric }
541e8d8bef9SDimitry Andric 
542e8d8bef9SDimitry Andric void MemProfiler::initializeCallbacks(Module &M) {
543e8d8bef9SDimitry Andric   IRBuilder<> IRB(*C);
544e8d8bef9SDimitry Andric 
545e8d8bef9SDimitry Andric   for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
546e8d8bef9SDimitry Andric     const std::string TypeStr = AccessIsWrite ? "store" : "load";
547e8d8bef9SDimitry Andric 
548e8d8bef9SDimitry Andric     SmallVector<Type *, 3> Args2 = {IntptrTy, IntptrTy};
549e8d8bef9SDimitry Andric     SmallVector<Type *, 2> Args1{1, IntptrTy};
550e8d8bef9SDimitry Andric     MemProfMemoryAccessCallbackSized[AccessIsWrite] =
551e8d8bef9SDimitry Andric         M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + TypeStr + "N",
552e8d8bef9SDimitry Andric                               FunctionType::get(IRB.getVoidTy(), Args2, false));
553e8d8bef9SDimitry Andric 
554e8d8bef9SDimitry Andric     MemProfMemoryAccessCallback[AccessIsWrite] =
555e8d8bef9SDimitry Andric         M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + TypeStr,
556e8d8bef9SDimitry Andric                               FunctionType::get(IRB.getVoidTy(), Args1, false));
557e8d8bef9SDimitry Andric   }
558e8d8bef9SDimitry Andric   MemProfMemmove = M.getOrInsertFunction(
559e8d8bef9SDimitry Andric       ClMemoryAccessCallbackPrefix + "memmove", IRB.getInt8PtrTy(),
560e8d8bef9SDimitry Andric       IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy);
561e8d8bef9SDimitry Andric   MemProfMemcpy = M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + "memcpy",
562e8d8bef9SDimitry Andric                                         IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
563e8d8bef9SDimitry Andric                                         IRB.getInt8PtrTy(), IntptrTy);
564e8d8bef9SDimitry Andric   MemProfMemset = M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + "memset",
565e8d8bef9SDimitry Andric                                         IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
566e8d8bef9SDimitry Andric                                         IRB.getInt32Ty(), IntptrTy);
567e8d8bef9SDimitry Andric }
568e8d8bef9SDimitry Andric 
569e8d8bef9SDimitry Andric bool MemProfiler::maybeInsertMemProfInitAtFunctionEntry(Function &F) {
570e8d8bef9SDimitry Andric   // For each NSObject descendant having a +load method, this method is invoked
571e8d8bef9SDimitry Andric   // by the ObjC runtime before any of the static constructors is called.
572e8d8bef9SDimitry Andric   // Therefore we need to instrument such methods with a call to __memprof_init
573e8d8bef9SDimitry Andric   // at the beginning in order to initialize our runtime before any access to
574e8d8bef9SDimitry Andric   // the shadow memory.
575e8d8bef9SDimitry Andric   // We cannot just ignore these methods, because they may call other
576e8d8bef9SDimitry Andric   // instrumented functions.
577e8d8bef9SDimitry Andric   if (F.getName().find(" load]") != std::string::npos) {
578e8d8bef9SDimitry Andric     FunctionCallee MemProfInitFunction =
579e8d8bef9SDimitry Andric         declareSanitizerInitFunction(*F.getParent(), MemProfInitName, {});
580e8d8bef9SDimitry Andric     IRBuilder<> IRB(&F.front(), F.front().begin());
581e8d8bef9SDimitry Andric     IRB.CreateCall(MemProfInitFunction, {});
582e8d8bef9SDimitry Andric     return true;
583e8d8bef9SDimitry Andric   }
584e8d8bef9SDimitry Andric   return false;
585e8d8bef9SDimitry Andric }
586e8d8bef9SDimitry Andric 
587e8d8bef9SDimitry Andric bool MemProfiler::insertDynamicShadowAtFunctionEntry(Function &F) {
588e8d8bef9SDimitry Andric   IRBuilder<> IRB(&F.front().front());
589e8d8bef9SDimitry Andric   Value *GlobalDynamicAddress = F.getParent()->getOrInsertGlobal(
590e8d8bef9SDimitry Andric       MemProfShadowMemoryDynamicAddress, IntptrTy);
591e8d8bef9SDimitry Andric   if (F.getParent()->getPICLevel() == PICLevel::NotPIC)
592e8d8bef9SDimitry Andric     cast<GlobalVariable>(GlobalDynamicAddress)->setDSOLocal(true);
593e8d8bef9SDimitry Andric   DynamicShadowOffset = IRB.CreateLoad(IntptrTy, GlobalDynamicAddress);
594e8d8bef9SDimitry Andric   return true;
595e8d8bef9SDimitry Andric }
596e8d8bef9SDimitry Andric 
597e8d8bef9SDimitry Andric bool MemProfiler::instrumentFunction(Function &F) {
598e8d8bef9SDimitry Andric   if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage)
599e8d8bef9SDimitry Andric     return false;
600e8d8bef9SDimitry Andric   if (ClDebugFunc == F.getName())
601e8d8bef9SDimitry Andric     return false;
602e8d8bef9SDimitry Andric   if (F.getName().startswith("__memprof_"))
603e8d8bef9SDimitry Andric     return false;
604e8d8bef9SDimitry Andric 
605e8d8bef9SDimitry Andric   bool FunctionModified = false;
606e8d8bef9SDimitry Andric 
607e8d8bef9SDimitry Andric   // If needed, insert __memprof_init.
608e8d8bef9SDimitry Andric   // This function needs to be called even if the function body is not
609e8d8bef9SDimitry Andric   // instrumented.
610e8d8bef9SDimitry Andric   if (maybeInsertMemProfInitAtFunctionEntry(F))
611e8d8bef9SDimitry Andric     FunctionModified = true;
612e8d8bef9SDimitry Andric 
613e8d8bef9SDimitry Andric   LLVM_DEBUG(dbgs() << "MEMPROF instrumenting:\n" << F << "\n");
614e8d8bef9SDimitry Andric 
615e8d8bef9SDimitry Andric   initializeCallbacks(*F.getParent());
616e8d8bef9SDimitry Andric 
617e8d8bef9SDimitry Andric   FunctionModified |= insertDynamicShadowAtFunctionEntry(F);
618e8d8bef9SDimitry Andric 
619e8d8bef9SDimitry Andric   SmallVector<Instruction *, 16> ToInstrument;
620e8d8bef9SDimitry Andric 
621e8d8bef9SDimitry Andric   // Fill the set of memory operations to instrument.
622e8d8bef9SDimitry Andric   for (auto &BB : F) {
623e8d8bef9SDimitry Andric     for (auto &Inst : BB) {
624e8d8bef9SDimitry Andric       if (isInterestingMemoryAccess(&Inst) || isa<MemIntrinsic>(Inst))
625e8d8bef9SDimitry Andric         ToInstrument.push_back(&Inst);
626e8d8bef9SDimitry Andric     }
627e8d8bef9SDimitry Andric   }
628e8d8bef9SDimitry Andric 
629e8d8bef9SDimitry Andric   int NumInstrumented = 0;
630e8d8bef9SDimitry Andric   for (auto *Inst : ToInstrument) {
631e8d8bef9SDimitry Andric     if (ClDebugMin < 0 || ClDebugMax < 0 ||
632e8d8bef9SDimitry Andric         (NumInstrumented >= ClDebugMin && NumInstrumented <= ClDebugMax)) {
633e8d8bef9SDimitry Andric       Optional<InterestingMemoryAccess> Access =
634e8d8bef9SDimitry Andric           isInterestingMemoryAccess(Inst);
635e8d8bef9SDimitry Andric       if (Access)
636e8d8bef9SDimitry Andric         instrumentMop(Inst, F.getParent()->getDataLayout(), *Access);
637e8d8bef9SDimitry Andric       else
638e8d8bef9SDimitry Andric         instrumentMemIntrinsic(cast<MemIntrinsic>(Inst));
639e8d8bef9SDimitry Andric     }
640e8d8bef9SDimitry Andric     NumInstrumented++;
641e8d8bef9SDimitry Andric   }
642e8d8bef9SDimitry Andric 
643e8d8bef9SDimitry Andric   if (NumInstrumented > 0)
644e8d8bef9SDimitry Andric     FunctionModified = true;
645e8d8bef9SDimitry Andric 
646e8d8bef9SDimitry Andric   LLVM_DEBUG(dbgs() << "MEMPROF done instrumenting: " << FunctionModified << " "
647e8d8bef9SDimitry Andric                     << F << "\n");
648e8d8bef9SDimitry Andric 
649e8d8bef9SDimitry Andric   return FunctionModified;
650e8d8bef9SDimitry Andric }
651