xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
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"
22*349cc55cSDimitry 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 
111*349cc55cSDimitry Andric static cl::opt<bool> ClStack("memprof-instrument-stack",
112*349cc55cSDimitry Andric                              cl::desc("Instrument scalar stack variables"),
113*349cc55cSDimitry Andric                              cl::Hidden, cl::init(false));
114*349cc55cSDimitry 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");
131*349cc55cSDimitry Andric STATISTIC(NumSkippedStackReads, "Number of non-instrumented stack reads");
132*349cc55cSDimitry 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;
159e8d8bef9SDimitry Andric   uint64_t TypeSize;
160e8d8bef9SDimitry Andric   Value *MaybeMask = nullptr;
161e8d8bef9SDimitry Andric };
162e8d8bef9SDimitry Andric 
163e8d8bef9SDimitry Andric /// Instrument the code in module to profile memory accesses.
164e8d8bef9SDimitry Andric class MemProfiler {
165e8d8bef9SDimitry Andric public:
166e8d8bef9SDimitry Andric   MemProfiler(Module &M) {
167e8d8bef9SDimitry Andric     C = &(M.getContext());
168e8d8bef9SDimitry Andric     LongSize = M.getDataLayout().getPointerSizeInBits();
169e8d8bef9SDimitry Andric     IntptrTy = Type::getIntNTy(*C, LongSize);
170e8d8bef9SDimitry Andric   }
171e8d8bef9SDimitry Andric 
172e8d8bef9SDimitry Andric   /// If it is an interesting memory access, populate information
173e8d8bef9SDimitry Andric   /// about the access and return a InterestingMemoryAccess struct.
174e8d8bef9SDimitry Andric   /// Otherwise return None.
175e8d8bef9SDimitry Andric   Optional<InterestingMemoryAccess>
176e8d8bef9SDimitry Andric   isInterestingMemoryAccess(Instruction *I) const;
177e8d8bef9SDimitry Andric 
178e8d8bef9SDimitry Andric   void instrumentMop(Instruction *I, const DataLayout &DL,
179e8d8bef9SDimitry Andric                      InterestingMemoryAccess &Access);
180e8d8bef9SDimitry Andric   void instrumentAddress(Instruction *OrigIns, Instruction *InsertBefore,
181e8d8bef9SDimitry Andric                          Value *Addr, uint32_t TypeSize, bool IsWrite);
182e8d8bef9SDimitry Andric   void instrumentMaskedLoadOrStore(const DataLayout &DL, Value *Mask,
183e8d8bef9SDimitry Andric                                    Instruction *I, Value *Addr,
184e8d8bef9SDimitry Andric                                    unsigned Alignment, uint32_t TypeSize,
185e8d8bef9SDimitry Andric                                    bool IsWrite);
186e8d8bef9SDimitry Andric   void instrumentMemIntrinsic(MemIntrinsic *MI);
187e8d8bef9SDimitry Andric   Value *memToShadow(Value *Shadow, IRBuilder<> &IRB);
188e8d8bef9SDimitry Andric   bool instrumentFunction(Function &F);
189e8d8bef9SDimitry Andric   bool maybeInsertMemProfInitAtFunctionEntry(Function &F);
190e8d8bef9SDimitry Andric   bool insertDynamicShadowAtFunctionEntry(Function &F);
191e8d8bef9SDimitry Andric 
192e8d8bef9SDimitry Andric private:
193e8d8bef9SDimitry Andric   void initializeCallbacks(Module &M);
194e8d8bef9SDimitry Andric 
195e8d8bef9SDimitry Andric   LLVMContext *C;
196e8d8bef9SDimitry Andric   int LongSize;
197e8d8bef9SDimitry Andric   Type *IntptrTy;
198e8d8bef9SDimitry Andric   ShadowMapping Mapping;
199e8d8bef9SDimitry Andric 
200e8d8bef9SDimitry Andric   // These arrays is indexed by AccessIsWrite
201e8d8bef9SDimitry Andric   FunctionCallee MemProfMemoryAccessCallback[2];
202e8d8bef9SDimitry Andric   FunctionCallee MemProfMemoryAccessCallbackSized[2];
203e8d8bef9SDimitry Andric 
204e8d8bef9SDimitry Andric   FunctionCallee MemProfMemmove, MemProfMemcpy, MemProfMemset;
205e8d8bef9SDimitry Andric   Value *DynamicShadowOffset = nullptr;
206e8d8bef9SDimitry Andric };
207e8d8bef9SDimitry Andric 
208e8d8bef9SDimitry Andric class MemProfilerLegacyPass : public FunctionPass {
209e8d8bef9SDimitry Andric public:
210e8d8bef9SDimitry Andric   static char ID;
211e8d8bef9SDimitry Andric 
212e8d8bef9SDimitry Andric   explicit MemProfilerLegacyPass() : FunctionPass(ID) {
213e8d8bef9SDimitry Andric     initializeMemProfilerLegacyPassPass(*PassRegistry::getPassRegistry());
214e8d8bef9SDimitry Andric   }
215e8d8bef9SDimitry Andric 
216e8d8bef9SDimitry Andric   StringRef getPassName() const override { return "MemProfilerFunctionPass"; }
217e8d8bef9SDimitry Andric 
218e8d8bef9SDimitry Andric   bool runOnFunction(Function &F) override {
219e8d8bef9SDimitry Andric     MemProfiler Profiler(*F.getParent());
220e8d8bef9SDimitry Andric     return Profiler.instrumentFunction(F);
221e8d8bef9SDimitry Andric   }
222e8d8bef9SDimitry Andric };
223e8d8bef9SDimitry Andric 
224e8d8bef9SDimitry Andric class ModuleMemProfiler {
225e8d8bef9SDimitry Andric public:
226e8d8bef9SDimitry Andric   ModuleMemProfiler(Module &M) { TargetTriple = Triple(M.getTargetTriple()); }
227e8d8bef9SDimitry Andric 
228e8d8bef9SDimitry Andric   bool instrumentModule(Module &);
229e8d8bef9SDimitry Andric 
230e8d8bef9SDimitry Andric private:
231e8d8bef9SDimitry Andric   Triple TargetTriple;
232e8d8bef9SDimitry Andric   ShadowMapping Mapping;
233e8d8bef9SDimitry Andric   Function *MemProfCtorFunction = nullptr;
234e8d8bef9SDimitry Andric };
235e8d8bef9SDimitry Andric 
236e8d8bef9SDimitry Andric class ModuleMemProfilerLegacyPass : public ModulePass {
237e8d8bef9SDimitry Andric public:
238e8d8bef9SDimitry Andric   static char ID;
239e8d8bef9SDimitry Andric 
240e8d8bef9SDimitry Andric   explicit ModuleMemProfilerLegacyPass() : ModulePass(ID) {
241e8d8bef9SDimitry Andric     initializeModuleMemProfilerLegacyPassPass(*PassRegistry::getPassRegistry());
242e8d8bef9SDimitry Andric   }
243e8d8bef9SDimitry Andric 
244e8d8bef9SDimitry Andric   StringRef getPassName() const override { return "ModuleMemProfiler"; }
245e8d8bef9SDimitry Andric 
246e8d8bef9SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {}
247e8d8bef9SDimitry Andric 
248e8d8bef9SDimitry Andric   bool runOnModule(Module &M) override {
249e8d8bef9SDimitry Andric     ModuleMemProfiler MemProfiler(M);
250e8d8bef9SDimitry Andric     return MemProfiler.instrumentModule(M);
251e8d8bef9SDimitry Andric   }
252e8d8bef9SDimitry Andric };
253e8d8bef9SDimitry Andric 
254e8d8bef9SDimitry Andric } // end anonymous namespace
255e8d8bef9SDimitry Andric 
256e8d8bef9SDimitry Andric MemProfilerPass::MemProfilerPass() {}
257e8d8bef9SDimitry Andric 
258e8d8bef9SDimitry Andric PreservedAnalyses MemProfilerPass::run(Function &F,
259e8d8bef9SDimitry Andric                                        AnalysisManager<Function> &AM) {
260e8d8bef9SDimitry Andric   Module &M = *F.getParent();
261e8d8bef9SDimitry Andric   MemProfiler Profiler(M);
262e8d8bef9SDimitry Andric   if (Profiler.instrumentFunction(F))
263e8d8bef9SDimitry Andric     return PreservedAnalyses::none();
264e8d8bef9SDimitry Andric   return PreservedAnalyses::all();
265e8d8bef9SDimitry Andric }
266e8d8bef9SDimitry Andric 
267e8d8bef9SDimitry Andric ModuleMemProfilerPass::ModuleMemProfilerPass() {}
268e8d8bef9SDimitry Andric 
269e8d8bef9SDimitry Andric PreservedAnalyses ModuleMemProfilerPass::run(Module &M,
270e8d8bef9SDimitry Andric                                              AnalysisManager<Module> &AM) {
271e8d8bef9SDimitry Andric   ModuleMemProfiler Profiler(M);
272e8d8bef9SDimitry Andric   if (Profiler.instrumentModule(M))
273e8d8bef9SDimitry Andric     return PreservedAnalyses::none();
274e8d8bef9SDimitry Andric   return PreservedAnalyses::all();
275e8d8bef9SDimitry Andric }
276e8d8bef9SDimitry Andric 
277e8d8bef9SDimitry Andric char MemProfilerLegacyPass::ID = 0;
278e8d8bef9SDimitry Andric 
279e8d8bef9SDimitry Andric INITIALIZE_PASS_BEGIN(MemProfilerLegacyPass, "memprof",
280e8d8bef9SDimitry Andric                       "MemProfiler: profile memory allocations and accesses.",
281e8d8bef9SDimitry Andric                       false, false)
282e8d8bef9SDimitry Andric INITIALIZE_PASS_END(MemProfilerLegacyPass, "memprof",
283e8d8bef9SDimitry Andric                     "MemProfiler: profile memory allocations and accesses.",
284e8d8bef9SDimitry Andric                     false, false)
285e8d8bef9SDimitry Andric 
286e8d8bef9SDimitry Andric FunctionPass *llvm::createMemProfilerFunctionPass() {
287e8d8bef9SDimitry Andric   return new MemProfilerLegacyPass();
288e8d8bef9SDimitry Andric }
289e8d8bef9SDimitry Andric 
290e8d8bef9SDimitry Andric char ModuleMemProfilerLegacyPass::ID = 0;
291e8d8bef9SDimitry Andric 
292e8d8bef9SDimitry Andric INITIALIZE_PASS(ModuleMemProfilerLegacyPass, "memprof-module",
293e8d8bef9SDimitry Andric                 "MemProfiler: profile memory allocations and accesses."
294e8d8bef9SDimitry Andric                 "ModulePass",
295e8d8bef9SDimitry Andric                 false, false)
296e8d8bef9SDimitry Andric 
297e8d8bef9SDimitry Andric ModulePass *llvm::createModuleMemProfilerLegacyPassPass() {
298e8d8bef9SDimitry Andric   return new ModuleMemProfilerLegacyPass();
299e8d8bef9SDimitry Andric }
300e8d8bef9SDimitry Andric 
301e8d8bef9SDimitry Andric Value *MemProfiler::memToShadow(Value *Shadow, IRBuilder<> &IRB) {
302e8d8bef9SDimitry Andric   // (Shadow & mask) >> scale
303e8d8bef9SDimitry Andric   Shadow = IRB.CreateAnd(Shadow, Mapping.Mask);
304e8d8bef9SDimitry Andric   Shadow = IRB.CreateLShr(Shadow, Mapping.Scale);
305e8d8bef9SDimitry Andric   // (Shadow >> scale) | offset
306e8d8bef9SDimitry Andric   assert(DynamicShadowOffset);
307e8d8bef9SDimitry Andric   return IRB.CreateAdd(Shadow, DynamicShadowOffset);
308e8d8bef9SDimitry Andric }
309e8d8bef9SDimitry Andric 
310e8d8bef9SDimitry Andric // Instrument memset/memmove/memcpy
311e8d8bef9SDimitry Andric void MemProfiler::instrumentMemIntrinsic(MemIntrinsic *MI) {
312e8d8bef9SDimitry Andric   IRBuilder<> IRB(MI);
313e8d8bef9SDimitry Andric   if (isa<MemTransferInst>(MI)) {
314e8d8bef9SDimitry Andric     IRB.CreateCall(
315e8d8bef9SDimitry Andric         isa<MemMoveInst>(MI) ? MemProfMemmove : MemProfMemcpy,
316e8d8bef9SDimitry Andric         {IRB.CreatePointerCast(MI->getOperand(0), IRB.getInt8PtrTy()),
317e8d8bef9SDimitry Andric          IRB.CreatePointerCast(MI->getOperand(1), IRB.getInt8PtrTy()),
318e8d8bef9SDimitry Andric          IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)});
319e8d8bef9SDimitry Andric   } else if (isa<MemSetInst>(MI)) {
320e8d8bef9SDimitry Andric     IRB.CreateCall(
321e8d8bef9SDimitry Andric         MemProfMemset,
322e8d8bef9SDimitry Andric         {IRB.CreatePointerCast(MI->getOperand(0), IRB.getInt8PtrTy()),
323e8d8bef9SDimitry Andric          IRB.CreateIntCast(MI->getOperand(1), IRB.getInt32Ty(), false),
324e8d8bef9SDimitry Andric          IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)});
325e8d8bef9SDimitry Andric   }
326e8d8bef9SDimitry Andric   MI->eraseFromParent();
327e8d8bef9SDimitry Andric }
328e8d8bef9SDimitry Andric 
329e8d8bef9SDimitry Andric Optional<InterestingMemoryAccess>
330e8d8bef9SDimitry Andric MemProfiler::isInterestingMemoryAccess(Instruction *I) const {
331e8d8bef9SDimitry Andric   // Do not instrument the load fetching the dynamic shadow address.
332e8d8bef9SDimitry Andric   if (DynamicShadowOffset == I)
333e8d8bef9SDimitry Andric     return None;
334e8d8bef9SDimitry Andric 
335e8d8bef9SDimitry Andric   InterestingMemoryAccess Access;
336e8d8bef9SDimitry Andric 
337e8d8bef9SDimitry Andric   const DataLayout &DL = I->getModule()->getDataLayout();
338e8d8bef9SDimitry Andric   if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
339e8d8bef9SDimitry Andric     if (!ClInstrumentReads)
340e8d8bef9SDimitry Andric       return None;
341e8d8bef9SDimitry Andric     Access.IsWrite = false;
342e8d8bef9SDimitry Andric     Access.TypeSize = DL.getTypeStoreSizeInBits(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;
349e8d8bef9SDimitry Andric     Access.TypeSize =
350e8d8bef9SDimitry Andric         DL.getTypeStoreSizeInBits(SI->getValueOperand()->getType());
351e8d8bef9SDimitry Andric     Access.Alignment = SI->getAlignment();
352e8d8bef9SDimitry Andric     Access.Addr = SI->getPointerOperand();
353e8d8bef9SDimitry Andric   } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) {
354e8d8bef9SDimitry Andric     if (!ClInstrumentAtomics)
355e8d8bef9SDimitry Andric       return None;
356e8d8bef9SDimitry Andric     Access.IsWrite = true;
357e8d8bef9SDimitry Andric     Access.TypeSize =
358e8d8bef9SDimitry Andric         DL.getTypeStoreSizeInBits(RMW->getValOperand()->getType());
359e8d8bef9SDimitry Andric     Access.Alignment = 0;
360e8d8bef9SDimitry Andric     Access.Addr = RMW->getPointerOperand();
361e8d8bef9SDimitry Andric   } else if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) {
362e8d8bef9SDimitry Andric     if (!ClInstrumentAtomics)
363e8d8bef9SDimitry Andric       return None;
364e8d8bef9SDimitry Andric     Access.IsWrite = true;
365e8d8bef9SDimitry Andric     Access.TypeSize =
366e8d8bef9SDimitry Andric         DL.getTypeStoreSizeInBits(XCHG->getCompareOperand()->getType());
367e8d8bef9SDimitry Andric     Access.Alignment = 0;
368e8d8bef9SDimitry Andric     Access.Addr = XCHG->getPointerOperand();
369e8d8bef9SDimitry Andric   } else if (auto *CI = dyn_cast<CallInst>(I)) {
370e8d8bef9SDimitry Andric     auto *F = CI->getCalledFunction();
371e8d8bef9SDimitry Andric     if (F && (F->getIntrinsicID() == Intrinsic::masked_load ||
372e8d8bef9SDimitry Andric               F->getIntrinsicID() == Intrinsic::masked_store)) {
373e8d8bef9SDimitry Andric       unsigned OpOffset = 0;
374e8d8bef9SDimitry Andric       if (F->getIntrinsicID() == Intrinsic::masked_store) {
375e8d8bef9SDimitry Andric         if (!ClInstrumentWrites)
376e8d8bef9SDimitry Andric           return None;
377e8d8bef9SDimitry Andric         // Masked store has an initial operand for the value.
378e8d8bef9SDimitry Andric         OpOffset = 1;
379e8d8bef9SDimitry Andric         Access.IsWrite = true;
380e8d8bef9SDimitry Andric       } else {
381e8d8bef9SDimitry Andric         if (!ClInstrumentReads)
382e8d8bef9SDimitry Andric           return None;
383e8d8bef9SDimitry Andric         Access.IsWrite = false;
384e8d8bef9SDimitry Andric       }
385e8d8bef9SDimitry Andric 
386e8d8bef9SDimitry Andric       auto *BasePtr = CI->getOperand(0 + OpOffset);
387e8d8bef9SDimitry Andric       auto *Ty = cast<PointerType>(BasePtr->getType())->getElementType();
388e8d8bef9SDimitry Andric       Access.TypeSize = DL.getTypeStoreSizeInBits(Ty);
389e8d8bef9SDimitry Andric       if (auto *AlignmentConstant =
390e8d8bef9SDimitry Andric               dyn_cast<ConstantInt>(CI->getOperand(1 + OpOffset)))
391e8d8bef9SDimitry Andric         Access.Alignment = (unsigned)AlignmentConstant->getZExtValue();
392e8d8bef9SDimitry Andric       else
393e8d8bef9SDimitry Andric         Access.Alignment = 1; // No alignment guarantees. We probably got Undef
394e8d8bef9SDimitry Andric       Access.MaybeMask = CI->getOperand(2 + OpOffset);
395e8d8bef9SDimitry Andric       Access.Addr = BasePtr;
396e8d8bef9SDimitry Andric     }
397e8d8bef9SDimitry Andric   }
398e8d8bef9SDimitry Andric 
399e8d8bef9SDimitry Andric   if (!Access.Addr)
400e8d8bef9SDimitry Andric     return None;
401e8d8bef9SDimitry Andric 
402e8d8bef9SDimitry Andric   // Do not instrument acesses from different address spaces; we cannot deal
403e8d8bef9SDimitry Andric   // with them.
404e8d8bef9SDimitry Andric   Type *PtrTy = cast<PointerType>(Access.Addr->getType()->getScalarType());
405e8d8bef9SDimitry Andric   if (PtrTy->getPointerAddressSpace() != 0)
406e8d8bef9SDimitry Andric     return None;
407e8d8bef9SDimitry Andric 
408e8d8bef9SDimitry Andric   // Ignore swifterror addresses.
409e8d8bef9SDimitry Andric   // swifterror memory addresses are mem2reg promoted by instruction
410e8d8bef9SDimitry Andric   // selection. As such they cannot have regular uses like an instrumentation
411e8d8bef9SDimitry Andric   // function and it makes no sense to track them as memory.
412e8d8bef9SDimitry Andric   if (Access.Addr->isSwiftError())
413e8d8bef9SDimitry Andric     return None;
414e8d8bef9SDimitry Andric 
415e8d8bef9SDimitry Andric   return Access;
416e8d8bef9SDimitry Andric }
417e8d8bef9SDimitry Andric 
418e8d8bef9SDimitry Andric void MemProfiler::instrumentMaskedLoadOrStore(const DataLayout &DL, Value *Mask,
419e8d8bef9SDimitry Andric                                               Instruction *I, Value *Addr,
420e8d8bef9SDimitry Andric                                               unsigned Alignment,
421e8d8bef9SDimitry Andric                                               uint32_t TypeSize, bool IsWrite) {
422e8d8bef9SDimitry Andric   auto *VTy = cast<FixedVectorType>(
423e8d8bef9SDimitry Andric       cast<PointerType>(Addr->getType())->getElementType());
424e8d8bef9SDimitry Andric   uint64_t ElemTypeSize = DL.getTypeStoreSizeInBits(VTy->getScalarType());
425e8d8bef9SDimitry Andric   unsigned Num = VTy->getNumElements();
426e8d8bef9SDimitry Andric   auto *Zero = ConstantInt::get(IntptrTy, 0);
427e8d8bef9SDimitry Andric   for (unsigned Idx = 0; Idx < Num; ++Idx) {
428e8d8bef9SDimitry Andric     Value *InstrumentedAddress = nullptr;
429e8d8bef9SDimitry Andric     Instruction *InsertBefore = I;
430e8d8bef9SDimitry Andric     if (auto *Vector = dyn_cast<ConstantVector>(Mask)) {
431e8d8bef9SDimitry Andric       // dyn_cast as we might get UndefValue
432e8d8bef9SDimitry Andric       if (auto *Masked = dyn_cast<ConstantInt>(Vector->getOperand(Idx))) {
433e8d8bef9SDimitry Andric         if (Masked->isZero())
434e8d8bef9SDimitry Andric           // Mask is constant false, so no instrumentation needed.
435e8d8bef9SDimitry Andric           continue;
436e8d8bef9SDimitry Andric         // If we have a true or undef value, fall through to instrumentAddress.
437e8d8bef9SDimitry Andric         // with InsertBefore == I
438e8d8bef9SDimitry Andric       }
439e8d8bef9SDimitry Andric     } else {
440e8d8bef9SDimitry Andric       IRBuilder<> IRB(I);
441e8d8bef9SDimitry Andric       Value *MaskElem = IRB.CreateExtractElement(Mask, Idx);
442e8d8bef9SDimitry Andric       Instruction *ThenTerm = SplitBlockAndInsertIfThen(MaskElem, I, false);
443e8d8bef9SDimitry Andric       InsertBefore = ThenTerm;
444e8d8bef9SDimitry Andric     }
445e8d8bef9SDimitry Andric 
446e8d8bef9SDimitry Andric     IRBuilder<> IRB(InsertBefore);
447e8d8bef9SDimitry Andric     InstrumentedAddress =
448e8d8bef9SDimitry Andric         IRB.CreateGEP(VTy, Addr, {Zero, ConstantInt::get(IntptrTy, Idx)});
449e8d8bef9SDimitry Andric     instrumentAddress(I, InsertBefore, InstrumentedAddress, ElemTypeSize,
450e8d8bef9SDimitry Andric                       IsWrite);
451e8d8bef9SDimitry Andric   }
452e8d8bef9SDimitry Andric }
453e8d8bef9SDimitry Andric 
454e8d8bef9SDimitry Andric void MemProfiler::instrumentMop(Instruction *I, const DataLayout &DL,
455e8d8bef9SDimitry Andric                                 InterestingMemoryAccess &Access) {
456*349cc55cSDimitry Andric   // Skip instrumentation of stack accesses unless requested.
457*349cc55cSDimitry Andric   if (!ClStack && isa<AllocaInst>(getUnderlyingObject(Access.Addr))) {
458*349cc55cSDimitry Andric     if (Access.IsWrite)
459*349cc55cSDimitry Andric       ++NumSkippedStackWrites;
460*349cc55cSDimitry Andric     else
461*349cc55cSDimitry Andric       ++NumSkippedStackReads;
462*349cc55cSDimitry Andric     return;
463*349cc55cSDimitry Andric   }
464*349cc55cSDimitry Andric 
465e8d8bef9SDimitry Andric   if (Access.IsWrite)
466e8d8bef9SDimitry Andric     NumInstrumentedWrites++;
467e8d8bef9SDimitry Andric   else
468e8d8bef9SDimitry Andric     NumInstrumentedReads++;
469e8d8bef9SDimitry Andric 
470e8d8bef9SDimitry Andric   if (Access.MaybeMask) {
471e8d8bef9SDimitry Andric     instrumentMaskedLoadOrStore(DL, Access.MaybeMask, I, Access.Addr,
472e8d8bef9SDimitry Andric                                 Access.Alignment, Access.TypeSize,
473e8d8bef9SDimitry Andric                                 Access.IsWrite);
474e8d8bef9SDimitry Andric   } else {
475e8d8bef9SDimitry Andric     // Since the access counts will be accumulated across the entire allocation,
476e8d8bef9SDimitry Andric     // we only update the shadow access count for the first location and thus
477e8d8bef9SDimitry Andric     // don't need to worry about alignment and type size.
478e8d8bef9SDimitry Andric     instrumentAddress(I, I, Access.Addr, Access.TypeSize, Access.IsWrite);
479e8d8bef9SDimitry Andric   }
480e8d8bef9SDimitry Andric }
481e8d8bef9SDimitry Andric 
482e8d8bef9SDimitry Andric void MemProfiler::instrumentAddress(Instruction *OrigIns,
483e8d8bef9SDimitry Andric                                     Instruction *InsertBefore, Value *Addr,
484e8d8bef9SDimitry Andric                                     uint32_t TypeSize, bool IsWrite) {
485e8d8bef9SDimitry Andric   IRBuilder<> IRB(InsertBefore);
486e8d8bef9SDimitry Andric   Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
487e8d8bef9SDimitry Andric 
488e8d8bef9SDimitry Andric   if (ClUseCalls) {
489e8d8bef9SDimitry Andric     IRB.CreateCall(MemProfMemoryAccessCallback[IsWrite], AddrLong);
490e8d8bef9SDimitry Andric     return;
491e8d8bef9SDimitry Andric   }
492e8d8bef9SDimitry Andric 
493e8d8bef9SDimitry Andric   // Create an inline sequence to compute shadow location, and increment the
494e8d8bef9SDimitry Andric   // value by one.
495e8d8bef9SDimitry Andric   Type *ShadowTy = Type::getInt64Ty(*C);
496e8d8bef9SDimitry Andric   Type *ShadowPtrTy = PointerType::get(ShadowTy, 0);
497e8d8bef9SDimitry Andric   Value *ShadowPtr = memToShadow(AddrLong, IRB);
498e8d8bef9SDimitry Andric   Value *ShadowAddr = IRB.CreateIntToPtr(ShadowPtr, ShadowPtrTy);
499e8d8bef9SDimitry Andric   Value *ShadowValue = IRB.CreateLoad(ShadowTy, ShadowAddr);
500e8d8bef9SDimitry Andric   Value *Inc = ConstantInt::get(Type::getInt64Ty(*C), 1);
501e8d8bef9SDimitry Andric   ShadowValue = IRB.CreateAdd(ShadowValue, Inc);
502e8d8bef9SDimitry Andric   IRB.CreateStore(ShadowValue, ShadowAddr);
503e8d8bef9SDimitry Andric }
504e8d8bef9SDimitry Andric 
505e8d8bef9SDimitry Andric // Create the variable for the profile file name.
506e8d8bef9SDimitry Andric void createProfileFileNameVar(Module &M) {
507e8d8bef9SDimitry Andric   const MDString *MemProfFilename =
508e8d8bef9SDimitry Andric       dyn_cast_or_null<MDString>(M.getModuleFlag("MemProfProfileFilename"));
509e8d8bef9SDimitry Andric   if (!MemProfFilename)
510e8d8bef9SDimitry Andric     return;
511e8d8bef9SDimitry Andric   assert(!MemProfFilename->getString().empty() &&
512e8d8bef9SDimitry Andric          "Unexpected MemProfProfileFilename metadata with empty string");
513e8d8bef9SDimitry Andric   Constant *ProfileNameConst = ConstantDataArray::getString(
514e8d8bef9SDimitry Andric       M.getContext(), MemProfFilename->getString(), true);
515e8d8bef9SDimitry Andric   GlobalVariable *ProfileNameVar = new GlobalVariable(
516e8d8bef9SDimitry Andric       M, ProfileNameConst->getType(), /*isConstant=*/true,
517e8d8bef9SDimitry Andric       GlobalValue::WeakAnyLinkage, ProfileNameConst, MemProfFilenameVar);
518e8d8bef9SDimitry Andric   Triple TT(M.getTargetTriple());
519e8d8bef9SDimitry Andric   if (TT.supportsCOMDAT()) {
520e8d8bef9SDimitry Andric     ProfileNameVar->setLinkage(GlobalValue::ExternalLinkage);
521e8d8bef9SDimitry Andric     ProfileNameVar->setComdat(M.getOrInsertComdat(MemProfFilenameVar));
522e8d8bef9SDimitry Andric   }
523e8d8bef9SDimitry Andric }
524e8d8bef9SDimitry Andric 
525e8d8bef9SDimitry Andric bool ModuleMemProfiler::instrumentModule(Module &M) {
526e8d8bef9SDimitry Andric   // Create a module constructor.
527e8d8bef9SDimitry Andric   std::string MemProfVersion = std::to_string(LLVM_MEM_PROFILER_VERSION);
528e8d8bef9SDimitry Andric   std::string VersionCheckName =
529e8d8bef9SDimitry Andric       ClInsertVersionCheck ? (MemProfVersionCheckNamePrefix + MemProfVersion)
530e8d8bef9SDimitry Andric                            : "";
531e8d8bef9SDimitry Andric   std::tie(MemProfCtorFunction, std::ignore) =
532e8d8bef9SDimitry Andric       createSanitizerCtorAndInitFunctions(M, MemProfModuleCtorName,
533e8d8bef9SDimitry Andric                                           MemProfInitName, /*InitArgTypes=*/{},
534e8d8bef9SDimitry Andric                                           /*InitArgs=*/{}, VersionCheckName);
535e8d8bef9SDimitry Andric 
536e8d8bef9SDimitry Andric   const uint64_t Priority = getCtorAndDtorPriority(TargetTriple);
537e8d8bef9SDimitry Andric   appendToGlobalCtors(M, MemProfCtorFunction, Priority);
538e8d8bef9SDimitry Andric 
539e8d8bef9SDimitry Andric   createProfileFileNameVar(M);
540e8d8bef9SDimitry Andric 
541e8d8bef9SDimitry Andric   return true;
542e8d8bef9SDimitry Andric }
543e8d8bef9SDimitry Andric 
544e8d8bef9SDimitry Andric void MemProfiler::initializeCallbacks(Module &M) {
545e8d8bef9SDimitry Andric   IRBuilder<> IRB(*C);
546e8d8bef9SDimitry Andric 
547e8d8bef9SDimitry Andric   for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
548e8d8bef9SDimitry Andric     const std::string TypeStr = AccessIsWrite ? "store" : "load";
549e8d8bef9SDimitry Andric 
550e8d8bef9SDimitry Andric     SmallVector<Type *, 3> Args2 = {IntptrTy, IntptrTy};
551e8d8bef9SDimitry Andric     SmallVector<Type *, 2> Args1{1, IntptrTy};
552e8d8bef9SDimitry Andric     MemProfMemoryAccessCallbackSized[AccessIsWrite] =
553e8d8bef9SDimitry Andric         M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + TypeStr + "N",
554e8d8bef9SDimitry Andric                               FunctionType::get(IRB.getVoidTy(), Args2, false));
555e8d8bef9SDimitry Andric 
556e8d8bef9SDimitry Andric     MemProfMemoryAccessCallback[AccessIsWrite] =
557e8d8bef9SDimitry Andric         M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + TypeStr,
558e8d8bef9SDimitry Andric                               FunctionType::get(IRB.getVoidTy(), Args1, false));
559e8d8bef9SDimitry Andric   }
560e8d8bef9SDimitry Andric   MemProfMemmove = M.getOrInsertFunction(
561e8d8bef9SDimitry Andric       ClMemoryAccessCallbackPrefix + "memmove", IRB.getInt8PtrTy(),
562e8d8bef9SDimitry Andric       IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy);
563e8d8bef9SDimitry Andric   MemProfMemcpy = M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + "memcpy",
564e8d8bef9SDimitry Andric                                         IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
565e8d8bef9SDimitry Andric                                         IRB.getInt8PtrTy(), IntptrTy);
566e8d8bef9SDimitry Andric   MemProfMemset = M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + "memset",
567e8d8bef9SDimitry Andric                                         IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
568e8d8bef9SDimitry Andric                                         IRB.getInt32Ty(), IntptrTy);
569e8d8bef9SDimitry Andric }
570e8d8bef9SDimitry Andric 
571e8d8bef9SDimitry Andric bool MemProfiler::maybeInsertMemProfInitAtFunctionEntry(Function &F) {
572e8d8bef9SDimitry Andric   // For each NSObject descendant having a +load method, this method is invoked
573e8d8bef9SDimitry Andric   // by the ObjC runtime before any of the static constructors is called.
574e8d8bef9SDimitry Andric   // Therefore we need to instrument such methods with a call to __memprof_init
575e8d8bef9SDimitry Andric   // at the beginning in order to initialize our runtime before any access to
576e8d8bef9SDimitry Andric   // the shadow memory.
577e8d8bef9SDimitry Andric   // We cannot just ignore these methods, because they may call other
578e8d8bef9SDimitry Andric   // instrumented functions.
579e8d8bef9SDimitry Andric   if (F.getName().find(" load]") != std::string::npos) {
580e8d8bef9SDimitry Andric     FunctionCallee MemProfInitFunction =
581e8d8bef9SDimitry Andric         declareSanitizerInitFunction(*F.getParent(), MemProfInitName, {});
582e8d8bef9SDimitry Andric     IRBuilder<> IRB(&F.front(), F.front().begin());
583e8d8bef9SDimitry Andric     IRB.CreateCall(MemProfInitFunction, {});
584e8d8bef9SDimitry Andric     return true;
585e8d8bef9SDimitry Andric   }
586e8d8bef9SDimitry Andric   return false;
587e8d8bef9SDimitry Andric }
588e8d8bef9SDimitry Andric 
589e8d8bef9SDimitry Andric bool MemProfiler::insertDynamicShadowAtFunctionEntry(Function &F) {
590e8d8bef9SDimitry Andric   IRBuilder<> IRB(&F.front().front());
591e8d8bef9SDimitry Andric   Value *GlobalDynamicAddress = F.getParent()->getOrInsertGlobal(
592e8d8bef9SDimitry Andric       MemProfShadowMemoryDynamicAddress, IntptrTy);
593e8d8bef9SDimitry Andric   if (F.getParent()->getPICLevel() == PICLevel::NotPIC)
594e8d8bef9SDimitry Andric     cast<GlobalVariable>(GlobalDynamicAddress)->setDSOLocal(true);
595e8d8bef9SDimitry Andric   DynamicShadowOffset = IRB.CreateLoad(IntptrTy, GlobalDynamicAddress);
596e8d8bef9SDimitry Andric   return true;
597e8d8bef9SDimitry Andric }
598e8d8bef9SDimitry Andric 
599e8d8bef9SDimitry Andric bool MemProfiler::instrumentFunction(Function &F) {
600e8d8bef9SDimitry Andric   if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage)
601e8d8bef9SDimitry Andric     return false;
602e8d8bef9SDimitry Andric   if (ClDebugFunc == F.getName())
603e8d8bef9SDimitry Andric     return false;
604e8d8bef9SDimitry Andric   if (F.getName().startswith("__memprof_"))
605e8d8bef9SDimitry Andric     return false;
606e8d8bef9SDimitry Andric 
607e8d8bef9SDimitry Andric   bool FunctionModified = false;
608e8d8bef9SDimitry Andric 
609e8d8bef9SDimitry Andric   // If needed, insert __memprof_init.
610e8d8bef9SDimitry Andric   // This function needs to be called even if the function body is not
611e8d8bef9SDimitry Andric   // instrumented.
612e8d8bef9SDimitry Andric   if (maybeInsertMemProfInitAtFunctionEntry(F))
613e8d8bef9SDimitry Andric     FunctionModified = true;
614e8d8bef9SDimitry Andric 
615e8d8bef9SDimitry Andric   LLVM_DEBUG(dbgs() << "MEMPROF instrumenting:\n" << F << "\n");
616e8d8bef9SDimitry Andric 
617e8d8bef9SDimitry Andric   initializeCallbacks(*F.getParent());
618e8d8bef9SDimitry Andric 
619e8d8bef9SDimitry Andric   FunctionModified |= insertDynamicShadowAtFunctionEntry(F);
620e8d8bef9SDimitry Andric 
621e8d8bef9SDimitry Andric   SmallVector<Instruction *, 16> ToInstrument;
622e8d8bef9SDimitry Andric 
623e8d8bef9SDimitry Andric   // Fill the set of memory operations to instrument.
624e8d8bef9SDimitry Andric   for (auto &BB : F) {
625e8d8bef9SDimitry Andric     for (auto &Inst : BB) {
626e8d8bef9SDimitry Andric       if (isInterestingMemoryAccess(&Inst) || isa<MemIntrinsic>(Inst))
627e8d8bef9SDimitry Andric         ToInstrument.push_back(&Inst);
628e8d8bef9SDimitry Andric     }
629e8d8bef9SDimitry Andric   }
630e8d8bef9SDimitry Andric 
631e8d8bef9SDimitry Andric   int NumInstrumented = 0;
632e8d8bef9SDimitry Andric   for (auto *Inst : ToInstrument) {
633e8d8bef9SDimitry Andric     if (ClDebugMin < 0 || ClDebugMax < 0 ||
634e8d8bef9SDimitry Andric         (NumInstrumented >= ClDebugMin && NumInstrumented <= ClDebugMax)) {
635e8d8bef9SDimitry Andric       Optional<InterestingMemoryAccess> Access =
636e8d8bef9SDimitry Andric           isInterestingMemoryAccess(Inst);
637e8d8bef9SDimitry Andric       if (Access)
638e8d8bef9SDimitry Andric         instrumentMop(Inst, F.getParent()->getDataLayout(), *Access);
639e8d8bef9SDimitry Andric       else
640e8d8bef9SDimitry Andric         instrumentMemIntrinsic(cast<MemIntrinsic>(Inst));
641e8d8bef9SDimitry Andric     }
642e8d8bef9SDimitry Andric     NumInstrumented++;
643e8d8bef9SDimitry Andric   }
644e8d8bef9SDimitry Andric 
645e8d8bef9SDimitry Andric   if (NumInstrumented > 0)
646e8d8bef9SDimitry Andric     FunctionModified = true;
647e8d8bef9SDimitry Andric 
648e8d8bef9SDimitry Andric   LLVM_DEBUG(dbgs() << "MEMPROF done instrumenting: " << FunctionModified << " "
649e8d8bef9SDimitry Andric                     << F << "\n");
650e8d8bef9SDimitry Andric 
651e8d8bef9SDimitry Andric   return FunctionModified;
652e8d8bef9SDimitry Andric }
653