LLVM  12.0.0git
MemProfiler.cpp
Go to the documentation of this file.
1 //===- MemProfiler.cpp - memory allocation and access profiler ------------===//
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 file is a part of MemProfiler. Memory accesses are instrumented
10 // to increment the access count held in a shadow memory location, or
11 // alternatively to call into the runtime. Memory intrinsic calls (memmove,
12 // memcpy, memset) are changed to call the memory profiling runtime version
13 // instead.
14 //
15 //===----------------------------------------------------------------------===//
16 
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/Statistic.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/ADT/Triple.h"
22 #include "llvm/IR/Constant.h"
23 #include "llvm/IR/DataLayout.h"
24 #include "llvm/IR/Function.h"
25 #include "llvm/IR/GlobalValue.h"
26 #include "llvm/IR/IRBuilder.h"
27 #include "llvm/IR/Instruction.h"
28 #include "llvm/IR/LLVMContext.h"
29 #include "llvm/IR/Module.h"
30 #include "llvm/IR/Type.h"
31 #include "llvm/IR/Value.h"
32 #include "llvm/InitializePasses.h"
33 #include "llvm/Pass.h"
35 #include "llvm/Support/Debug.h"
39 
40 using namespace llvm;
41 
42 #define DEBUG_TYPE "memprof"
43 
44 constexpr int LLVM_MEM_PROFILER_VERSION = 1;
45 
46 // Size of memory mapped to a single shadow location.
47 constexpr uint64_t DefaultShadowGranularity = 64;
48 
49 // Scale from granularity down to shadow size.
50 constexpr uint64_t DefaultShadowScale = 3;
51 
52 constexpr char MemProfModuleCtorName[] = "memprof.module_ctor";
53 constexpr uint64_t MemProfCtorAndDtorPriority = 1;
54 // On Emscripten, the system needs more than one priorities for constructors.
55 constexpr uint64_t MemProfEmscriptenCtorAndDtorPriority = 50;
56 constexpr char MemProfInitName[] = "__memprof_init";
58  "__memprof_version_mismatch_check_v";
59 
61  "__memprof_shadow_memory_dynamic_address";
62 
63 constexpr char MemProfFilenameVar[] = "__memprof_profile_filename";
64 
65 // Command-line flags.
66 
68  "memprof-guard-against-version-mismatch",
69  cl::desc("Guard against compiler/runtime version mismatch."), cl::Hidden,
70  cl::init(true));
71 
72 // This flag may need to be replaced with -f[no-]memprof-reads.
73 static cl::opt<bool> ClInstrumentReads("memprof-instrument-reads",
74  cl::desc("instrument read instructions"),
75  cl::Hidden, cl::init(true));
76 
77 static cl::opt<bool>
78  ClInstrumentWrites("memprof-instrument-writes",
79  cl::desc("instrument write instructions"), cl::Hidden,
80  cl::init(true));
81 
83  "memprof-instrument-atomics",
84  cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden,
85  cl::init(true));
86 
88  "memprof-use-callbacks",
89  cl::desc("Use callbacks instead of inline instrumentation sequences."),
90  cl::Hidden, cl::init(false));
91 
93  ClMemoryAccessCallbackPrefix("memprof-memory-access-callback-prefix",
94  cl::desc("Prefix for memory access callbacks"),
95  cl::Hidden, cl::init("__memprof_"));
96 
97 // These flags allow to change the shadow mapping.
98 // The shadow mapping looks like
99 // Shadow = ((Mem & mask) >> scale) + offset
100 
101 static cl::opt<int> ClMappingScale("memprof-mapping-scale",
102  cl::desc("scale of memprof shadow mapping"),
104 
105 static cl::opt<int>
106  ClMappingGranularity("memprof-mapping-granularity",
107  cl::desc("granularity of memprof shadow mapping"),
109 
110 // Debug flags.
111 
112 static cl::opt<int> ClDebug("memprof-debug", cl::desc("debug"), cl::Hidden,
113  cl::init(0));
114 
115 static cl::opt<std::string> ClDebugFunc("memprof-debug-func", cl::Hidden,
116  cl::desc("Debug func"));
117 
118 static cl::opt<int> ClDebugMin("memprof-debug-min", cl::desc("Debug min inst"),
119  cl::Hidden, cl::init(-1));
120 
121 static cl::opt<int> ClDebugMax("memprof-debug-max", cl::desc("Debug max inst"),
122  cl::Hidden, cl::init(-1));
123 
124 STATISTIC(NumInstrumentedReads, "Number of instrumented reads");
125 STATISTIC(NumInstrumentedWrites, "Number of instrumented writes");
126 
127 namespace {
128 
129 /// This struct defines the shadow mapping using the rule:
130 /// shadow = ((mem & mask) >> Scale) ADD DynamicShadowOffset.
131 struct ShadowMapping {
132  ShadowMapping() {
133  Scale = ClMappingScale;
134  Granularity = ClMappingGranularity;
135  Mask = ~(Granularity - 1);
136  }
137 
138  int Scale;
139  int Granularity;
140  uint64_t Mask; // Computed as ~(Granularity-1)
141 };
142 
143 static uint64_t getCtorAndDtorPriority(Triple &TargetTriple) {
146 }
147 
148 struct InterestingMemoryAccess {
149  Value *Addr = nullptr;
150  bool IsWrite;
151  unsigned Alignment;
152  uint64_t TypeSize;
153  Value *MaybeMask = nullptr;
154 };
155 
156 /// Instrument the code in module to profile memory accesses.
157 class MemProfiler {
158 public:
159  MemProfiler(Module &M) {
160  C = &(M.getContext());
161  LongSize = M.getDataLayout().getPointerSizeInBits();
162  IntptrTy = Type::getIntNTy(*C, LongSize);
163  }
164 
165  /// If it is an interesting memory access, populate information
166  /// about the access and return a InterestingMemoryAccess struct.
167  /// Otherwise return None.
169  isInterestingMemoryAccess(Instruction *I) const;
170 
171  void instrumentMop(Instruction *I, const DataLayout &DL,
172  InterestingMemoryAccess &Access);
173  void instrumentAddress(Instruction *OrigIns, Instruction *InsertBefore,
174  Value *Addr, uint32_t TypeSize, bool IsWrite);
176  Instruction *I, Value *Addr,
177  unsigned Alignment, uint32_t TypeSize,
178  bool IsWrite);
179  void instrumentMemIntrinsic(MemIntrinsic *MI);
180  Value *memToShadow(Value *Shadow, IRBuilder<> &IRB);
181  bool instrumentFunction(Function &F);
182  bool maybeInsertMemProfInitAtFunctionEntry(Function &F);
183  bool insertDynamicShadowAtFunctionEntry(Function &F);
184 
185 private:
186  void initializeCallbacks(Module &M);
187 
188  LLVMContext *C;
189  int LongSize;
190  Type *IntptrTy;
191  ShadowMapping Mapping;
192 
193  // These arrays is indexed by AccessIsWrite
194  FunctionCallee MemProfMemoryAccessCallback[2];
195  FunctionCallee MemProfMemoryAccessCallbackSized[2];
196 
197  FunctionCallee MemProfMemmove, MemProfMemcpy, MemProfMemset;
198  Value *DynamicShadowOffset = nullptr;
199 };
200 
201 class MemProfilerLegacyPass : public FunctionPass {
202 public:
203  static char ID;
204 
205  explicit MemProfilerLegacyPass() : FunctionPass(ID) {
207  }
208 
209  StringRef getPassName() const override { return "MemProfilerFunctionPass"; }
210 
211  bool runOnFunction(Function &F) override {
212  MemProfiler Profiler(*F.getParent());
213  return Profiler.instrumentFunction(F);
214  }
215 };
216 
217 class ModuleMemProfiler {
218 public:
219  ModuleMemProfiler(Module &M) { TargetTriple = Triple(M.getTargetTriple()); }
220 
221  bool instrumentModule(Module &);
222 
223 private:
224  Triple TargetTriple;
225  ShadowMapping Mapping;
226  Function *MemProfCtorFunction = nullptr;
227 };
228 
229 class ModuleMemProfilerLegacyPass : public ModulePass {
230 public:
231  static char ID;
232 
233  explicit ModuleMemProfilerLegacyPass() : ModulePass(ID) {
235  }
236 
237  StringRef getPassName() const override { return "ModuleMemProfiler"; }
238 
239  void getAnalysisUsage(AnalysisUsage &AU) const override {}
240 
241  bool runOnModule(Module &M) override {
242  ModuleMemProfiler MemProfiler(M);
243  return MemProfiler.instrumentModule(M);
244  }
245 };
246 
247 } // end anonymous namespace
248 
250 
253  Module &M = *F.getParent();
254  MemProfiler Profiler(M);
255  if (Profiler.instrumentFunction(F))
256  return PreservedAnalyses::none();
257  return PreservedAnalyses::all();
258 
259  return PreservedAnalyses::all();
260 }
261 
263 
266  ModuleMemProfiler Profiler(M);
267  if (Profiler.instrumentModule(M))
268  return PreservedAnalyses::none();
269  return PreservedAnalyses::all();
270 }
271 
273 
274 INITIALIZE_PASS_BEGIN(MemProfilerLegacyPass, "memprof",
275  "MemProfiler: profile memory allocations and accesses.",
276  false, false)
277 INITIALIZE_PASS_END(MemProfilerLegacyPass, "memprof",
278  "MemProfiler: profile memory allocations and accesses.",
279  false, false)
280 
282  return new MemProfilerLegacyPass();
283 }
284 
286 
287 INITIALIZE_PASS(ModuleMemProfilerLegacyPass, "memprof-module",
288  "MemProfiler: profile memory allocations and accesses."
289  "ModulePass",
290  false, false)
291 
293  return new ModuleMemProfilerLegacyPass();
294 }
295 
296 Value *MemProfiler::memToShadow(Value *Shadow, IRBuilder<> &IRB) {
297  // (Shadow & mask) >> scale
298  Shadow = IRB.CreateAnd(Shadow, Mapping.Mask);
299  Shadow = IRB.CreateLShr(Shadow, Mapping.Scale);
300  // (Shadow >> scale) | offset
301  assert(DynamicShadowOffset);
302  return IRB.CreateAdd(Shadow, DynamicShadowOffset);
303 }
304 
305 // Instrument memset/memmove/memcpy
306 void MemProfiler::instrumentMemIntrinsic(MemIntrinsic *MI) {
307  IRBuilder<> IRB(MI);
308  if (isa<MemTransferInst>(MI)) {
309  IRB.CreateCall(
310  isa<MemMoveInst>(MI) ? MemProfMemmove : MemProfMemcpy,
311  {IRB.CreatePointerCast(MI->getOperand(0), IRB.getInt8PtrTy()),
312  IRB.CreatePointerCast(MI->getOperand(1), IRB.getInt8PtrTy()),
313  IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)});
314  } else if (isa<MemSetInst>(MI)) {
315  IRB.CreateCall(
316  MemProfMemset,
317  {IRB.CreatePointerCast(MI->getOperand(0), IRB.getInt8PtrTy()),
318  IRB.CreateIntCast(MI->getOperand(1), IRB.getInt32Ty(), false),
319  IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)});
320  }
321  MI->eraseFromParent();
322 }
323 
325 MemProfiler::isInterestingMemoryAccess(Instruction *I) const {
326  // Do not instrument the load fetching the dynamic shadow address.
327  if (DynamicShadowOffset == I)
328  return None;
329 
330  InterestingMemoryAccess Access;
331 
332  const DataLayout &DL = I->getModule()->getDataLayout();
333  if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
334  if (!ClInstrumentReads)
335  return None;
336  Access.IsWrite = false;
337  Access.TypeSize = DL.getTypeStoreSizeInBits(LI->getType());
338  Access.Alignment = LI->getAlignment();
339  Access.Addr = LI->getPointerOperand();
340  } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
341  if (!ClInstrumentWrites)
342  return None;
343  Access.IsWrite = true;
344  Access.TypeSize =
345  DL.getTypeStoreSizeInBits(SI->getValueOperand()->getType());
346  Access.Alignment = SI->getAlignment();
347  Access.Addr = SI->getPointerOperand();
348  } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) {
349  if (!ClInstrumentAtomics)
350  return None;
351  Access.IsWrite = true;
352  Access.TypeSize =
353  DL.getTypeStoreSizeInBits(RMW->getValOperand()->getType());
354  Access.Alignment = 0;
355  Access.Addr = RMW->getPointerOperand();
356  } else if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) {
357  if (!ClInstrumentAtomics)
358  return None;
359  Access.IsWrite = true;
360  Access.TypeSize =
361  DL.getTypeStoreSizeInBits(XCHG->getCompareOperand()->getType());
362  Access.Alignment = 0;
363  Access.Addr = XCHG->getPointerOperand();
364  } else if (auto *CI = dyn_cast<CallInst>(I)) {
365  auto *F = CI->getCalledFunction();
366  if (F && (F->getIntrinsicID() == Intrinsic::masked_load ||
367  F->getIntrinsicID() == Intrinsic::masked_store)) {
368  unsigned OpOffset = 0;
369  if (F->getIntrinsicID() == Intrinsic::masked_store) {
370  if (!ClInstrumentWrites)
371  return None;
372  // Masked store has an initial operand for the value.
373  OpOffset = 1;
374  Access.IsWrite = true;
375  } else {
376  if (!ClInstrumentReads)
377  return None;
378  Access.IsWrite = false;
379  }
380 
381  auto *BasePtr = CI->getOperand(0 + OpOffset);
382  auto *Ty = cast<PointerType>(BasePtr->getType())->getElementType();
383  Access.TypeSize = DL.getTypeStoreSizeInBits(Ty);
384  if (auto *AlignmentConstant =
385  dyn_cast<ConstantInt>(CI->getOperand(1 + OpOffset)))
386  Access.Alignment = (unsigned)AlignmentConstant->getZExtValue();
387  else
388  Access.Alignment = 1; // No alignment guarantees. We probably got Undef
389  Access.MaybeMask = CI->getOperand(2 + OpOffset);
390  Access.Addr = BasePtr;
391  }
392  }
393 
394  if (!Access.Addr)
395  return None;
396 
397  // Do not instrument acesses from different address spaces; we cannot deal
398  // with them.
399  Type *PtrTy = cast<PointerType>(Access.Addr->getType()->getScalarType());
400  if (PtrTy->getPointerAddressSpace() != 0)
401  return None;
402 
403  // Ignore swifterror addresses.
404  // swifterror memory addresses are mem2reg promoted by instruction
405  // selection. As such they cannot have regular uses like an instrumentation
406  // function and it makes no sense to track them as memory.
407  if (Access.Addr->isSwiftError())
408  return None;
409 
410  return Access;
411 }
412 
414  Instruction *I, Value *Addr,
415  unsigned Alignment,
416  uint32_t TypeSize, bool IsWrite) {
417  auto *VTy = cast<FixedVectorType>(
418  cast<PointerType>(Addr->getType())->getElementType());
419  uint64_t ElemTypeSize = DL.getTypeStoreSizeInBits(VTy->getScalarType());
420  unsigned Num = VTy->getNumElements();
421  auto *Zero = ConstantInt::get(IntptrTy, 0);
422  for (unsigned Idx = 0; Idx < Num; ++Idx) {
423  Value *InstrumentedAddress = nullptr;
424  Instruction *InsertBefore = I;
425  if (auto *Vector = dyn_cast<ConstantVector>(Mask)) {
426  // dyn_cast as we might get UndefValue
427  if (auto *Masked = dyn_cast<ConstantInt>(Vector->getOperand(Idx))) {
428  if (Masked->isZero())
429  // Mask is constant false, so no instrumentation needed.
430  continue;
431  // If we have a true or undef value, fall through to instrumentAddress.
432  // with InsertBefore == I
433  }
434  } else {
435  IRBuilder<> IRB(I);
436  Value *MaskElem = IRB.CreateExtractElement(Mask, Idx);
437  Instruction *ThenTerm = SplitBlockAndInsertIfThen(MaskElem, I, false);
438  InsertBefore = ThenTerm;
439  }
440 
441  IRBuilder<> IRB(InsertBefore);
442  InstrumentedAddress =
443  IRB.CreateGEP(VTy, Addr, {Zero, ConstantInt::get(IntptrTy, Idx)});
444  instrumentAddress(I, InsertBefore, InstrumentedAddress, ElemTypeSize,
445  IsWrite);
446  }
447 }
448 
449 void MemProfiler::instrumentMop(Instruction *I, const DataLayout &DL,
450  InterestingMemoryAccess &Access) {
451  if (Access.IsWrite)
452  NumInstrumentedWrites++;
453  else
454  NumInstrumentedReads++;
455 
456  if (Access.MaybeMask) {
457  instrumentMaskedLoadOrStore(DL, Access.MaybeMask, I, Access.Addr,
458  Access.Alignment, Access.TypeSize,
459  Access.IsWrite);
460  } else {
461  // Since the access counts will be accumulated across the entire allocation,
462  // we only update the shadow access count for the first location and thus
463  // don't need to worry about alignment and type size.
464  instrumentAddress(I, I, Access.Addr, Access.TypeSize, Access.IsWrite);
465  }
466 }
467 
468 void MemProfiler::instrumentAddress(Instruction *OrigIns,
469  Instruction *InsertBefore, Value *Addr,
470  uint32_t TypeSize, bool IsWrite) {
471  IRBuilder<> IRB(InsertBefore);
472  Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
473 
474  if (ClUseCalls) {
475  IRB.CreateCall(MemProfMemoryAccessCallback[IsWrite], AddrLong);
476  return;
477  }
478 
479  // Create an inline sequence to compute shadow location, and increment the
480  // value by one.
481  Type *ShadowTy = Type::getInt64Ty(*C);
482  Type *ShadowPtrTy = PointerType::get(ShadowTy, 0);
483  Value *ShadowPtr = memToShadow(AddrLong, IRB);
484  Value *ShadowAddr = IRB.CreateIntToPtr(ShadowPtr, ShadowPtrTy);
485  Value *ShadowValue = IRB.CreateLoad(ShadowTy, ShadowAddr);
487  ShadowValue = IRB.CreateAdd(ShadowValue, Inc);
488  IRB.CreateStore(ShadowValue, ShadowAddr);
489 }
490 
491 // Create the variable for the profile file name.
493  const MDString *MemProfFilename =
494  dyn_cast_or_null<MDString>(M.getModuleFlag("MemProfProfileFilename"));
495  if (!MemProfFilename)
496  return;
497  assert(!MemProfFilename->getString().empty() &&
498  "Unexpected MemProfProfileFilename metadata with empty string");
499  Constant *ProfileNameConst = ConstantDataArray::getString(
500  M.getContext(), MemProfFilename->getString(), true);
501  GlobalVariable *ProfileNameVar = new GlobalVariable(
502  M, ProfileNameConst->getType(), /*isConstant=*/true,
504  Triple TT(M.getTargetTriple());
505  if (TT.supportsCOMDAT()) {
506  ProfileNameVar->setLinkage(GlobalValue::ExternalLinkage);
507  ProfileNameVar->setComdat(M.getOrInsertComdat(MemProfFilenameVar));
508  }
509 }
510 
511 bool ModuleMemProfiler::instrumentModule(Module &M) {
512  // Create a module constructor.
513  std::string MemProfVersion = std::to_string(LLVM_MEM_PROFILER_VERSION);
514  std::string VersionCheckName =
516  : "";
517  std::tie(MemProfCtorFunction, std::ignore) =
519  MemProfInitName, /*InitArgTypes=*/{},
520  /*InitArgs=*/{}, VersionCheckName);
521 
522  const uint64_t Priority = getCtorAndDtorPriority(TargetTriple);
523  appendToGlobalCtors(M, MemProfCtorFunction, Priority);
524 
526 
527  return true;
528 }
529 
530 void MemProfiler::initializeCallbacks(Module &M) {
531  IRBuilder<> IRB(*C);
532 
533  for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
534  const std::string TypeStr = AccessIsWrite ? "store" : "load";
535 
536  SmallVector<Type *, 3> Args2 = {IntptrTy, IntptrTy};
537  SmallVector<Type *, 2> Args1{1, IntptrTy};
538  MemProfMemoryAccessCallbackSized[AccessIsWrite] =
539  M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + TypeStr + "N",
540  FunctionType::get(IRB.getVoidTy(), Args2, false));
541 
542  MemProfMemoryAccessCallback[AccessIsWrite] =
543  M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + TypeStr,
544  FunctionType::get(IRB.getVoidTy(), Args1, false));
545  }
546  MemProfMemmove = M.getOrInsertFunction(
547  ClMemoryAccessCallbackPrefix + "memmove", IRB.getInt8PtrTy(),
548  IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy);
549  MemProfMemcpy = M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + "memcpy",
550  IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
551  IRB.getInt8PtrTy(), IntptrTy);
552  MemProfMemset = M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + "memset",
553  IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
554  IRB.getInt32Ty(), IntptrTy);
555 }
556 
557 bool MemProfiler::maybeInsertMemProfInitAtFunctionEntry(Function &F) {
558  // For each NSObject descendant having a +load method, this method is invoked
559  // by the ObjC runtime before any of the static constructors is called.
560  // Therefore we need to instrument such methods with a call to __memprof_init
561  // at the beginning in order to initialize our runtime before any access to
562  // the shadow memory.
563  // We cannot just ignore these methods, because they may call other
564  // instrumented functions.
565  if (F.getName().find(" load]") != std::string::npos) {
566  FunctionCallee MemProfInitFunction =
568  IRBuilder<> IRB(&F.front(), F.front().begin());
569  IRB.CreateCall(MemProfInitFunction, {});
570  return true;
571  }
572  return false;
573 }
574 
575 bool MemProfiler::insertDynamicShadowAtFunctionEntry(Function &F) {
576  IRBuilder<> IRB(&F.front().front());
577  Value *GlobalDynamicAddress = F.getParent()->getOrInsertGlobal(
579  if (F.getParent()->getPICLevel() == PICLevel::NotPIC)
580  cast<GlobalVariable>(GlobalDynamicAddress)->setDSOLocal(true);
581  DynamicShadowOffset = IRB.CreateLoad(IntptrTy, GlobalDynamicAddress);
582  return true;
583 }
584 
585 bool MemProfiler::instrumentFunction(Function &F) {
586  if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage)
587  return false;
588  if (ClDebugFunc == F.getName())
589  return false;
590  if (F.getName().startswith("__memprof_"))
591  return false;
592 
593  bool FunctionModified = false;
594 
595  // If needed, insert __memprof_init.
596  // This function needs to be called even if the function body is not
597  // instrumented.
598  if (maybeInsertMemProfInitAtFunctionEntry(F))
599  FunctionModified = true;
600 
601  LLVM_DEBUG(dbgs() << "MEMPROF instrumenting:\n" << F << "\n");
602 
603  initializeCallbacks(*F.getParent());
604 
605  FunctionModified |= insertDynamicShadowAtFunctionEntry(F);
606 
607  SmallVector<Instruction *, 16> ToInstrument;
608 
609  // Fill the set of memory operations to instrument.
610  for (auto &BB : F) {
611  for (auto &Inst : BB) {
612  if (isInterestingMemoryAccess(&Inst) || isa<MemIntrinsic>(Inst))
613  ToInstrument.push_back(&Inst);
614  }
615  }
616 
617  int NumInstrumented = 0;
618  for (auto *Inst : ToInstrument) {
619  if (ClDebugMin < 0 || ClDebugMax < 0 ||
620  (NumInstrumented >= ClDebugMin && NumInstrumented <= ClDebugMax)) {
622  isInterestingMemoryAccess(Inst);
623  if (Access)
624  instrumentMop(Inst, F.getParent()->getDataLayout(), *Access);
625  else
626  instrumentMemIntrinsic(cast<MemIntrinsic>(Inst));
627  }
628  NumInstrumented++;
629  }
630 
631  if (NumInstrumented > 0)
632  FunctionModified = true;
633 
634  LLVM_DEBUG(dbgs() << "MEMPROF done instrumenting: " << FunctionModified << " "
635  << F << "\n");
636 
637  return FunctionModified;
638 }
static cl::opt< std::string > ClDebugFunc("memprof-debug-func", cl::Hidden, cl::desc("Debug func"))
const NoneType None
Definition: None.h:23
constexpr uint64_t DefaultShadowGranularity
Definition: MemProfiler.cpp:47
uint64_t CallInst * C
static cl::opt< bool > ClInstrumentWrites("memprof-instrument-writes", cl::desc("instrument write instructions"), cl::Hidden, cl::init(true))
bool isOSEmscripten() const
Tests whether the OS is Emscripten.
Definition: Triple.h:612
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:111
static Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true)
This method constructs a CDS and initializes it with a text string.
Definition: Constants.cpp:3006
constexpr int LLVM_MEM_PROFILER_VERSION
Definition: MemProfiler.cpp:44
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static cl::opt< int > ClDebugMax("memprof-debug-max", cl::desc("Debug max inst"), cl::Hidden, cl::init(-1))
This class represents lattice values for constants.
Definition: AllocatorList.h:23
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args=None, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition: IRBuilder.h:2427
std::pair< Function *, FunctionCallee > createSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type * > InitArgTypes, ArrayRef< Value * > InitArgs, StringRef VersionCheckName=StringRef())
Creates sanitizer constructor function, and calls sanitizer's init function from it.
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
An instruction that atomically checks whether a specified value is in a memory location,...
Definition: Instructions.h:522
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Definition: IRBuilder.h:1375
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
Definition: DerivedTypes.h:164
Available for inspection, not emission.
Definition: GlobalValue.h:49
static PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
Definition: Type.cpp:669
static void instrumentMaskedLoadOrStore(AddressSanitizer *Pass, const DataLayout &DL, Type *IntptrTy, Value *Mask, Instruction *I, Value *Addr, MaybeAlign Alignment, unsigned Granularity, uint32_t TypeSize, bool IsWrite, Value *SizeArgument, bool UseCalls, uint32_t Exp)
Externally visible function.
Definition: GlobalValue.h:48
STATISTIC(NumFunctions, "Total number of functions")
F(f)
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:2144
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
Definition: DerivedTypes.h:711
An instruction for reading from memory.
Definition: Instructions.h:174
static IntegerType * getInt64Ty(LLVMContext &C)
Definition: Type.cpp:198
an instruction that atomically reads a memory location, combines it with another value,...
Definition: Instructions.h:702
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:1415
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Definition: IRBuilder.h:518
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Definition: IRBuilder.h:1730
Instruction * SplitBlockAndInsertIfThen(Value *Cond, Instruction *SplitBefore, bool Unreachable, MDNode *BranchWeights, DominatorTree *DT, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
uint64_t Addr
std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
Definition: BitmaskEnum.h:80
FunctionCallee declareSanitizerInitFunction(Module &M, StringRef InitName, ArrayRef< Type * > InitArgTypes)
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:156
Type * getVoidTy()
Fetch the type representing void.
Definition: IRBuilder.h:556
INITIALIZE_PASS_BEGIN(MemProfilerLegacyPass, "memprof", "MemProfiler: profile memory allocations and accesses.", false, false) INITIALIZE_PASS_END(MemProfilerLegacyPass
constexpr uint64_t DefaultShadowScale
Definition: MemProfiler.cpp:50
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
Definition: IRBuilder.h:2218
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
Definition: Type.cpp:321
An instruction for storing to memory.
Definition: Instructions.h:303
static cl::opt< int > ClDebugMin("memprof-debug-min", cl::desc("Debug min inst"), cl::Hidden, cl::init(-1))
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Definition: IRBuilder.h:2474
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: PassManager.h:158
constexpr char MemProfInitName[]
Definition: MemProfiler.cpp:56
StringRef getString() const
Definition: Metadata.cpp:464
constexpr char MemProfModuleCtorName[]
Definition: MemProfiler.cpp:52
static bool runOnFunction(Function &F, bool PostInlining)
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:427
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:155
void createProfileFileNameVar(Module &M, StringRef InstrProfileOutput)
Definition: InstrProf.cpp:1138
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:46
static cl::opt< bool > ClInsertVersionCheck("memprof-guard-against-version-mismatch", cl::desc("Guard against compiler/runtime version mismatch."), cl::Hidden, cl::init(true))
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
static cl::opt< int > ClDebug("memprof-debug", cl::desc("debug"), cl::Hidden, cl::init(0))
This is an important base class in LLVM.
Definition: Constant.h:41
FunctionPass * createMemProfilerFunctionPass()
static cl::opt< bool > ClUseCalls("memprof-use-callbacks", cl::desc("Use callbacks instead of inline instrumentation sequences."), cl::Hidden, cl::init(false))
Represent the analysis usage information of a pass.
static cl::opt< bool > ClInstrumentReads("memprof-instrument-reads", cl::desc("instrument read instructions"), cl::Hidden, cl::init(true))
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition: IRBuilder.h:1265
constexpr char MemProfVersionCheckNamePrefix[]
Definition: MemProfiler.cpp:57
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Definition: IRBuilder.h:1701
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:161
PointerType * getInt8PtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer to an 8-bit integer value.
Definition: IRBuilder.h:561
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:45
This is the common base class for memset/memcpy/memmove.
void initializeModuleMemProfilerLegacyPassPass(PassRegistry &)
static cl::opt< int > ClMappingScale("memprof-mapping-scale", cl::desc("scale of memprof shadow mapping"), cl::Hidden, cl::init(DefaultShadowScale))
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1116
Module.h This file contains the declarations for the Module class.
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
Definition: Type.cpp:201
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:867
void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
Definition: ModuleUtils.cpp:66
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
constexpr uint64_t MemProfEmscriptenCtorAndDtorPriority
Definition: MemProfiler.cpp:55
constexpr char MemProfFilenameVar[]
Definition: MemProfiler.cpp:63
static cl::opt< bool > ClInstrumentAtomics("memprof-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true))
static cl::opt< std::string > ClMemoryAccessCallbackPrefix("memprof-memory-access-callback-prefix", cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__memprof_"))
pgo instr Read PGO instrumentation profile
void initializeMemProfilerLegacyPassPass(PassRegistry &)
Value * CreateGEP(Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")
Definition: IRBuilder.h:1852
#define I(x, y, z)
Definition: MD5.cpp:59
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:238
Keep one copy of named function when linking (weak)
Definition: GlobalValue.h:52
static cl::opt< int > ClMappingGranularity("memprof-mapping-granularity", cl::desc("granularity of memprof shadow mapping"), cl::Hidden, cl::init(DefaultShadowGranularity))
const std::string to_string(const T &Value)
Definition: ScopedPrinter.h:61
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:75
memprof
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:2195
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
A single uniqued string.
Definition: Metadata.h:602
A container for analyses that lazily runs them and caches their results.
INITIALIZE_PASS(ModuleMemProfilerLegacyPass, "memprof-module", "MemProfiler: profile memory allocations and accesses." "ModulePass", false, false) ModulePass *llvm
constexpr char MemProfShadowMemoryDynamicAddress[]
Definition: MemProfiler.cpp:60
#define LLVM_DEBUG(X)
Definition: Debug.h:122
constexpr uint64_t MemProfCtorAndDtorPriority
Definition: MemProfiler.cpp:53
ModulePass * createModuleMemProfilerLegacyPassPass()
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL