46#define DEBUG_TYPE "memprof"
65 "__memprof_version_mismatch_check_v";
68 "__memprof_shadow_memory_dynamic_address";
77 "memprof-guard-against-version-mismatch",
83 cl::desc(
"instrument read instructions"),
92 "memprof-instrument-atomics",
97 "memprof-use-callbacks",
98 cl::desc(
"Use callbacks instead of inline instrumentation sequences."),
103 cl::desc(
"Prefix for memory access callbacks"),
111 cl::desc(
"scale of memprof shadow mapping"),
116 cl::desc(
"granularity of memprof shadow mapping"),
120 cl::desc(
"Instrument scalar stack variables"),
138 cl::desc(
"Collect access count histograms"),
143 cl::desc(
"The default memprof options"),
147STATISTIC(NumInstrumentedReads,
"Number of instrumented reads");
148STATISTIC(NumInstrumentedWrites,
"Number of instrumented writes");
149STATISTIC(NumSkippedStackReads,
"Number of non-instrumented stack reads");
150STATISTIC(NumSkippedStackWrites,
"Number of non-instrumented stack writes");
156struct ShadowMapping {
160 Mask = ~(Granularity - 1);
173struct InterestingMemoryAccess {
177 Value *MaybeMask =
nullptr;
184 C = &(
M.getContext());
185 LongSize =
M.getDataLayout().getPointerSizeInBits();
187 PtrTy = PointerType::getUnqual(*C);
193 std::optional<InterestingMemoryAccess>
197 InterestingMemoryAccess &
Access);
206 bool maybeInsertMemProfInitAtFunctionEntry(
Function &
F);
207 bool insertDynamicShadowAtFunctionEntry(
Function &
F);
210 void initializeCallbacks(
Module &M);
216 ShadowMapping Mapping;
222 Value *DynamicShadowOffset =
nullptr;
225class ModuleMemProfiler {
227 ModuleMemProfiler(
Module &M) { TargetTriple =
M.getTargetTriple(); }
229 bool instrumentModule(
Module &);
233 ShadowMapping Mapping;
234 Function *MemProfCtorFunction =
nullptr;
244 "Memprof with histogram only supports default mapping granularity");
246 MemProfiler Profiler(M);
247 if (Profiler.instrumentFunction(
F))
257 ModuleMemProfiler Profiler(M);
258 if (Profiler.instrumentModule(M))
265 Shadow = IRB.
CreateAnd(Shadow, Mapping.Mask);
266 Shadow = IRB.
CreateLShr(Shadow, Mapping.Scale);
268 assert(DynamicShadowOffset);
269 return IRB.
CreateAdd(Shadow, DynamicShadowOffset);
275 if (isa<MemTransferInst>(
MI)) {
276 IRB.
CreateCall(isa<MemMoveInst>(
MI) ? MemProfMemmove : MemProfMemcpy,
277 {
MI->getOperand(0),
MI->getOperand(1),
279 }
else if (isa<MemSetInst>(
MI)) {
286 MI->eraseFromParent();
289std::optional<InterestingMemoryAccess>
290MemProfiler::isInterestingMemoryAccess(
Instruction *
I)
const {
292 if (DynamicShadowOffset ==
I)
295 InterestingMemoryAccess
Access;
297 if (
LoadInst *LI = dyn_cast<LoadInst>(
I)) {
301 Access.AccessTy = LI->getType();
302 Access.Addr = LI->getPointerOperand();
303 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(
I)) {
307 Access.AccessTy =
SI->getValueOperand()->getType();
308 Access.Addr =
SI->getPointerOperand();
313 Access.AccessTy = RMW->getValOperand()->getType();
314 Access.Addr = RMW->getPointerOperand();
319 Access.AccessTy = XCHG->getCompareOperand()->getType();
320 Access.Addr = XCHG->getPointerOperand();
321 }
else if (
auto *CI = dyn_cast<CallInst>(
I)) {
322 auto *
F = CI->getCalledFunction();
323 if (
F && (
F->getIntrinsicID() == Intrinsic::masked_load ||
324 F->getIntrinsicID() == Intrinsic::masked_store)) {
325 unsigned OpOffset = 0;
326 if (
F->getIntrinsicID() == Intrinsic::masked_store) {
331 Access.AccessTy = CI->getArgOperand(0)->getType();
336 Access.AccessTy = CI->getType();
340 auto *
BasePtr = CI->getOperand(0 + OpOffset);
341 Access.MaybeMask = CI->getOperand(2 + OpOffset);
351 Type *PtrTy = cast<PointerType>(
Access.Addr->getType()->getScalarType());
359 if (
Access.Addr->isSwiftError())
363 auto *
Addr =
Access.Addr->stripInBoundsOffsets();
367 if (GV->hasSection()) {
370 auto OF =
I->getModule()->getTargetTriple().getObjectFormat();
377 if (GV->getName().starts_with(
"__llvm"))
386 Type *AccessTy,
bool IsWrite) {
387 auto *VTy = cast<FixedVectorType>(AccessTy);
388 unsigned Num = VTy->getNumElements();
389 auto *
Zero = ConstantInt::get(IntptrTy, 0);
390 for (
unsigned Idx = 0;
Idx < Num; ++
Idx) {
391 Value *InstrumentedAddress =
nullptr;
393 if (
auto *
Vector = dyn_cast<ConstantVector>(Mask)) {
406 InsertBefore = ThenTerm;
410 InstrumentedAddress =
417 InterestingMemoryAccess &
Access) {
421 ++NumSkippedStackWrites;
423 ++NumSkippedStackReads;
428 NumInstrumentedWrites++;
430 NumInstrumentedReads++;
443void MemProfiler::instrumentAddress(
Instruction *OrigIns,
450 IRB.
CreateCall(MemProfMemoryAccessCallback[IsWrite], AddrLong);
457 Value *ShadowPtr = memToShadow(AddrLong, IRB);
468 Value *Inc = ConstantInt::get(ShadowTy, 1);
469 ShadowValue = IRB.
CreateAdd(ShadowValue, Inc);
476 dyn_cast_or_null<MDString>(M.getModuleFlag(
"MemProfProfileFilename"));
477 if (!MemProfFilename)
480 "Unexpected MemProfProfileFilename metadata with empty string");
482 M.getContext(), MemProfFilename->
getString(),
true);
484 M, ProfileNameConst->
getType(),
true,
486 const Triple &TT = M.getTargetTriple();
487 if (TT.supportsCOMDAT()) {
501 const Triple &TT = M.getTargetTriple();
502 if (TT.supportsCOMDAT()) {
504 MemprofHistogramFlag->setComdat(M.getOrInsertComdat(VarName));
516 const Triple &TT = M.getTargetTriple();
517 if (TT.supportsCOMDAT()) {
523bool ModuleMemProfiler::instrumentModule(
Module &M) {
527 std::string VersionCheckName =
530 std::tie(MemProfCtorFunction, std::ignore) =
533 {}, VersionCheckName);
535 const uint64_t Priority = getCtorAndDtorPriority(TargetTriple);
547void MemProfiler::initializeCallbacks(
Module &M) {
550 for (
size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
551 const std::string TypeStr = AccessIsWrite ?
"store" :
"load";
552 const std::string HistPrefix =
ClHistogram ?
"hist_" :
"";
555 MemProfMemoryAccessCallback[AccessIsWrite] =
M.getOrInsertFunction(
559 MemProfMemmove =
M.getOrInsertFunction(
562 PtrTy, PtrTy, PtrTy, IntptrTy);
568bool MemProfiler::maybeInsertMemProfInitAtFunctionEntry(
Function &
F) {
576 if (
F.getName().contains(
" load]")) {
586bool MemProfiler::insertDynamicShadowAtFunctionEntry(
Function &
F) {
588 Value *GlobalDynamicAddress =
F.getParent()->getOrInsertGlobal(
591 cast<GlobalVariable>(GlobalDynamicAddress)->setDSOLocal(
true);
592 DynamicShadowOffset = IRB.
CreateLoad(IntptrTy, GlobalDynamicAddress);
596bool MemProfiler::instrumentFunction(
Function &
F) {
601 if (
F.getName().starts_with(
"__memprof_"))
604 bool FunctionModified =
false;
609 if (maybeInsertMemProfInitAtFunctionEntry(
F))
610 FunctionModified =
true;
614 initializeCallbacks(*
F.getParent());
620 for (
auto &Inst : BB) {
621 if (isInterestingMemoryAccess(&Inst) || isa<MemIntrinsic>(Inst))
626 if (ToInstrument.
empty()) {
627 LLVM_DEBUG(
dbgs() <<
"MEMPROF done instrumenting: " << FunctionModified
628 <<
" " <<
F <<
"\n");
630 return FunctionModified;
633 FunctionModified |= insertDynamicShadowAtFunctionEntry(
F);
635 int NumInstrumented = 0;
636 for (
auto *Inst : ToInstrument) {
639 std::optional<InterestingMemoryAccess>
Access =
640 isInterestingMemoryAccess(Inst);
642 instrumentMop(Inst,
F.getDataLayout(), *
Access);
644 instrumentMemIntrinsic(cast<MemIntrinsic>(Inst));
649 if (NumInstrumented > 0)
650 FunctionModified =
true;
652 LLVM_DEBUG(
dbgs() <<
"MEMPROF done instrumenting: " << FunctionModified <<
" "
655 return FunctionModified;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< int > ClDebugMin("asan-debug-min", cl::desc("Debug min inst"), cl::Hidden, cl::init(-1))
static cl::opt< std::string > ClMemoryAccessCallbackPrefix("asan-memory-access-callback-prefix", cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__asan_"))
static cl::opt< bool > ClInsertVersionCheck("asan-guard-against-version-mismatch", cl::desc("Guard against compiler/runtime version mismatch."), cl::Hidden, cl::init(true))
static cl::opt< bool > ClInstrumentWrites("asan-instrument-writes", cl::desc("instrument write instructions"), cl::Hidden, cl::init(true))
static cl::opt< int > ClDebugMax("asan-debug-max", cl::desc("Debug max inst"), cl::Hidden, cl::init(-1))
static cl::opt< bool > ClStack("asan-stack", cl::desc("Handle stack memory"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClInstrumentAtomics("asan-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true))
static cl::opt< int > ClMappingScale("asan-mapping-scale", cl::desc("scale of asan shadow mapping"), cl::Hidden, cl::init(0))
static cl::opt< std::string > ClDebugFunc("asan-debug-func", cl::Hidden, cl::desc("Debug func"))
static cl::opt< bool > ClInstrumentReads("asan-instrument-reads", cl::desc("instrument read instructions"), cl::Hidden, cl::init(true))
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
Module.h This file contains the declarations for the Module class.
static cl::opt< int > ClMappingGranularity("memprof-mapping-granularity", cl::desc("granularity of memprof shadow mapping"), cl::Hidden, cl::init(DefaultMemGranularity))
constexpr char MemProfVersionCheckNamePrefix[]
static cl::opt< int > ClDebugMin("memprof-debug-min", cl::desc("Debug min inst"), cl::Hidden, cl::init(-1))
void createMemprofHistogramFlagVar(Module &M)
constexpr uint64_t MemProfEmscriptenCtorAndDtorPriority
static cl::opt< std::string > MemprofRuntimeDefaultOptions("memprof-runtime-default-options", cl::desc("The default memprof options"), cl::Hidden, cl::init(""))
static cl::opt< std::string > ClDebugFunc("memprof-debug-func", cl::Hidden, cl::desc("Debug func"))
constexpr char MemProfShadowMemoryDynamicAddress[]
constexpr uint64_t MemProfCtorAndDtorPriority
constexpr int LLVM_MEM_PROFILER_VERSION
static cl::opt< bool > ClUseCalls("memprof-use-callbacks", cl::desc("Use callbacks instead of inline instrumentation sequences."), cl::Hidden, cl::init(false))
static cl::opt< bool > ClInstrumentAtomics("memprof-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClInsertVersionCheck("memprof-guard-against-version-mismatch", cl::desc("Guard against compiler/runtime version mismatch."), cl::Hidden, cl::init(true))
constexpr char MemProfInitName[]
constexpr char MemProfFilenameVar[]
static cl::opt< bool > ClStack("memprof-instrument-stack", cl::desc("Instrument scalar stack variables"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClHistogram("memprof-histogram", cl::desc("Collect access count histograms"), cl::Hidden, cl::init(false))
constexpr uint64_t DefaultMemGranularity
void createMemprofDefaultOptionsVar(Module &M)
constexpr uint64_t HistogramGranularity
constexpr uint64_t DefaultShadowScale
static cl::opt< std::string > ClMemoryAccessCallbackPrefix("memprof-memory-access-callback-prefix", cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__memprof_"))
constexpr char MemProfModuleCtorName[]
static cl::opt< bool > ClInstrumentReads("memprof-instrument-reads", cl::desc("instrument read instructions"), cl::Hidden, cl::init(true))
static cl::opt< int > ClDebugMax("memprof-debug-max", cl::desc("Debug max inst"), cl::Hidden, cl::init(-1))
static cl::opt< bool > ClInstrumentWrites("memprof-instrument-writes", cl::desc("instrument write instructions"), cl::Hidden, cl::init(true))
static cl::opt< int > ClDebug("memprof-debug", cl::desc("debug"), cl::Hidden, cl::init(0))
static cl::opt< int > ClMappingScale("memprof-mapping-scale", cl::desc("scale of memprof shadow mapping"), cl::Hidden, cl::init(DefaultShadowScale))
constexpr char MemProfHistogramFlagVar[]
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Class for arbitrary precision integers.
A container for analyses that lazily runs them and caches their results.
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
static LLVM_ABI Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true)
This method constructs a CDS and initializes it with a text string.
This is an important base class in LLVM.
static LLVM_ABI Constant * getIntegerValue(Type *Ty, const APInt &V)
Return the value for an integer or pointer constant, or a vector thereof, with the given scalar value...
A parsed version of the target data layout string in and methods for querying it.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
LLVM_ABI void setComdat(Comdat *C)
void setLinkage(LinkageTypes LT)
@ ExternalLinkage
Externally visible function.
@ WeakAnyLinkage
Keep one copy of named function when linking (weak)
@ AvailableExternallyLinkage
Available for inspection, not emission.
Value * CreateICmpULT(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Type * getVoidTy()
Fetch the type representing void.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
LLVM_ABI StringRef getString() const
This is the common base class for memset/memcpy/memmove.
LLVM_ABI MemProfilerPass()
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
LLVM_ABI ModuleMemProfilerPass()
A Module instance is used to store all the information related to an LLVM module.
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
Triple - Helper class for working with autoconf configuration names.
bool isOSEmscripten() const
Tests whether the OS is Emscripten.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
void instrumentAddress(Module &M, IRBuilder<> &IRB, Instruction *OrigIns, Instruction *InsertBefore, Value *Addr, Align Alignment, TypeSize TypeStoreSize, bool IsWrite, Value *SizeArgument, bool UseCalls, bool Recover, int AsanScale, int AsanOffset)
Instrument the memory operand Addr.
constexpr 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.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
llvm::StringRef getMemprofOptionsSymbolName()
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::string getInstrProfSectionName(InstrProfSectKind IPSK, Triple::ObjectFormatType OF, bool AddSegmentInfo=true)
Return the name of the profile section corresponding to IPSK.
LLVM_ABI FunctionCallee declareSanitizerInitFunction(Module &M, StringRef InitName, ArrayRef< Type * > InitArgTypes, bool Weak=false)
LLVM_ABI std::pair< Function *, FunctionCallee > createSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type * > InitArgTypes, ArrayRef< Value * > InitArgs, StringRef VersionCheckName=StringRef(), bool Weak=false)
Creates sanitizer constructor function, and calls sanitizer's init function from it.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
LLVM_ABI void createProfileFileNameVar(Module &M, StringRef InstrProfileOutput)
LLVM_ABI 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.
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....