forked from OSchip/llvm-project
[MemProf] Rename HeapProfiler to MemProfiler for consistency
This is consistent with the clang option added in
7ed8124d46
, and the comments on the
runtime patch in D87120.
Differential Revision: https://reviews.llvm.org/D87622
This commit is contained in:
parent
becf155275
commit
226d80ebe2
|
@ -145,7 +145,7 @@ CODEGENOPT(IncrementalLinkerCompatible, 1, 0) ///< Emit an object file which can
|
|||
///< linker.
|
||||
CODEGENOPT(MergeAllConstants , 1, 1) ///< Merge identical constants.
|
||||
CODEGENOPT(MergeFunctions , 1, 0) ///< Set when -fmerge-functions is enabled.
|
||||
CODEGENOPT(HeapProf , 1, 0) ///< Set when -fmemory-profile is enabled.
|
||||
CODEGENOPT(MemProf , 1, 0) ///< Set when -fmemory-profile is enabled.
|
||||
CODEGENOPT(MSVolatile , 1, 0) ///< Set when /volatile:ms is enabled.
|
||||
CODEGENOPT(NoCommon , 1, 0) ///< Set when -fno-common or C++ is enabled.
|
||||
CODEGENOPT(NoDwarfDirectoryAsm , 1, 0) ///< Set when -fno-dwarf-directory-asm is
|
||||
|
|
|
@ -55,7 +55,7 @@ class SanitizerArgs {
|
|||
bool MinimalRuntime = false;
|
||||
// True if cross-dso CFI support if provided by the system (i.e. Android).
|
||||
bool ImplicitCfiRuntime = false;
|
||||
bool NeedsHeapProfRt = false;
|
||||
bool NeedsMemProfRt = false;
|
||||
|
||||
public:
|
||||
/// Parses the sanitizer arguments from an argument list.
|
||||
|
@ -63,7 +63,7 @@ public:
|
|||
|
||||
bool needsSharedRt() const { return SharedRuntime; }
|
||||
|
||||
bool needsHeapProfRt() const { return NeedsHeapProfRt; }
|
||||
bool needsMemProfRt() const { return NeedsMemProfRt; }
|
||||
bool needsAsanRt() const { return Sanitizers.has(SanitizerKind::Address); }
|
||||
bool needsHwasanRt() const {
|
||||
return Sanitizers.has(SanitizerKind::HWAddress);
|
||||
|
|
|
@ -67,8 +67,8 @@
|
|||
#include "llvm/Transforms/Instrumentation/BoundsChecking.h"
|
||||
#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
|
||||
#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
|
||||
#include "llvm/Transforms/Instrumentation/HeapProfiler.h"
|
||||
#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
|
||||
#include "llvm/Transforms/Instrumentation/MemProfiler.h"
|
||||
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
|
||||
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
|
||||
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
|
||||
|
@ -268,10 +268,10 @@ static bool asanUseGlobalsGC(const Triple &T, const CodeGenOptions &CGOpts) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static void addHeapProfilerPasses(const PassManagerBuilder &Builder,
|
||||
legacy::PassManagerBase &PM) {
|
||||
PM.add(createHeapProfilerFunctionPass());
|
||||
PM.add(createModuleHeapProfilerLegacyPassPass());
|
||||
static void addMemProfilerPasses(const PassManagerBuilder &Builder,
|
||||
legacy::PassManagerBase &PM) {
|
||||
PM.add(createMemProfilerFunctionPass());
|
||||
PM.add(createModuleMemProfilerLegacyPassPass());
|
||||
}
|
||||
|
||||
static void addAddressSanitizerPasses(const PassManagerBuilder &Builder,
|
||||
|
@ -672,11 +672,11 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
|
|||
if (LangOpts.Coroutines)
|
||||
addCoroutinePassesToExtensionPoints(PMBuilder);
|
||||
|
||||
if (CodeGenOpts.HeapProf) {
|
||||
if (CodeGenOpts.MemProf) {
|
||||
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
||||
addHeapProfilerPasses);
|
||||
addMemProfilerPasses);
|
||||
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
||||
addHeapProfilerPasses);
|
||||
addMemProfilerPasses);
|
||||
}
|
||||
|
||||
if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds)) {
|
||||
|
@ -1384,9 +1384,9 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
|
|||
}
|
||||
}
|
||||
|
||||
if (CodeGenOpts.HeapProf) {
|
||||
MPM.addPass(createModuleToFunctionPassAdaptor(HeapProfilerPass()));
|
||||
MPM.addPass(ModuleHeapProfilerPass());
|
||||
if (CodeGenOpts.MemProf) {
|
||||
MPM.addPass(createModuleToFunctionPassAdaptor(MemProfilerPass()));
|
||||
MPM.addPass(ModuleMemProfilerPass());
|
||||
}
|
||||
|
||||
if (LangOpts.Sanitize.has(SanitizerKind::HWAddress)) {
|
||||
|
|
|
@ -866,8 +866,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
|
|||
LinkCXXRuntimes) ||
|
||||
D.CCCIsCXX();
|
||||
|
||||
NeedsHeapProfRt = Args.hasFlag(options::OPT_fmemory_profile,
|
||||
options::OPT_fno_memory_profile, false);
|
||||
NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,
|
||||
options::OPT_fno_memory_profile, false);
|
||||
|
||||
// Finally, initialize the set of available and recoverable sanitizers.
|
||||
Sanitizers.Mask |= Kinds;
|
||||
|
|
|
@ -706,10 +706,10 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
|
|||
if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid())
|
||||
HelperStaticRuntimes.push_back("asan-preinit");
|
||||
}
|
||||
if (SanArgs.needsHeapProfRt() && SanArgs.linkRuntimes()) {
|
||||
SharedRuntimes.push_back("heapprof");
|
||||
if (SanArgs.needsMemProfRt() && SanArgs.linkRuntimes()) {
|
||||
SharedRuntimes.push_back("memprof");
|
||||
if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid())
|
||||
HelperStaticRuntimes.push_back("heapprof-preinit");
|
||||
HelperStaticRuntimes.push_back("memprof-preinit");
|
||||
}
|
||||
if (SanArgs.needsUbsanRt() && SanArgs.linkRuntimes()) {
|
||||
if (SanArgs.requiresMinimalRuntime())
|
||||
|
@ -748,11 +748,11 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
|
|||
StaticRuntimes.push_back("asan_cxx");
|
||||
}
|
||||
|
||||
if (!SanArgs.needsSharedRt() && SanArgs.needsHeapProfRt() &&
|
||||
if (!SanArgs.needsSharedRt() && SanArgs.needsMemProfRt() &&
|
||||
SanArgs.linkRuntimes()) {
|
||||
StaticRuntimes.push_back("heapprof");
|
||||
StaticRuntimes.push_back("memprof");
|
||||
if (SanArgs.linkCXXRuntimes())
|
||||
StaticRuntimes.push_back("heapprof_cxx");
|
||||
StaticRuntimes.push_back("memprof_cxx");
|
||||
}
|
||||
|
||||
if (!SanArgs.needsSharedRt() && SanArgs.needsHwasanRt() && SanArgs.linkRuntimes()) {
|
||||
|
|
|
@ -1033,7 +1033,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
|
|||
Opts.ThinLinkBitcodeFile =
|
||||
std::string(Args.getLastArgValue(OPT_fthin_link_bitcode_EQ));
|
||||
|
||||
Opts.HeapProf = Args.hasArg(OPT_fmemory_profile);
|
||||
Opts.MemProf = Args.hasArg(OPT_fmemory_profile);
|
||||
|
||||
Opts.MSVolatile = Args.hasArg(OPT_fms_volatile);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: %clangxx -target x86_64-linux-gnu -fmemory-profile %s -### 2>&1 | FileCheck %s
|
||||
// RUN: %clangxx -target x86_64-linux-gnu -fmemory-profile -fno-memory-profile %s -### 2>&1 | FileCheck %s --check-prefix=OFF
|
||||
// CHECK: "-cc1" {{.*}} "-fmemory-profile"
|
||||
// CHECK: ld{{.*}}libclang_rt.heapprof{{.*}}libclang_rt.heapprof_cxx
|
||||
// CHECK: ld{{.*}}libclang_rt.memprof{{.*}}libclang_rt.memprof_cxx
|
||||
// OFF-NOT: "-fmemory-profile"
|
||||
// OFF-NOT: libclang_rt.heapprof
|
||||
// OFF-NOT: libclang_rt.memprof
|
||||
|
|
|
@ -176,7 +176,7 @@ void initializeGlobalSplitPass(PassRegistry&);
|
|||
void initializeGlobalsAAWrapperPassPass(PassRegistry&);
|
||||
void initializeGuardWideningLegacyPassPass(PassRegistry&);
|
||||
void initializeHardwareLoopsPass(PassRegistry&);
|
||||
void initializeHeapProfilerLegacyPassPass(PassRegistry &);
|
||||
void initializeMemProfilerLegacyPassPass(PassRegistry &);
|
||||
void initializeHotColdSplittingLegacyPassPass(PassRegistry&);
|
||||
void initializeHWAddressSanitizerLegacyPassPass(PassRegistry &);
|
||||
void initializeIPSCCPLegacyPassPass(PassRegistry&);
|
||||
|
@ -305,7 +305,7 @@ void initializeMergeICmpsLegacyPassPass(PassRegistry &);
|
|||
void initializeMergedLoadStoreMotionLegacyPassPass(PassRegistry&);
|
||||
void initializeMetaRenamerPass(PassRegistry&);
|
||||
void initializeModuleDebugInfoPrinterPass(PassRegistry&);
|
||||
void initializeModuleHeapProfilerLegacyPassPass(PassRegistry &);
|
||||
void initializeModuleMemProfilerLegacyPassPass(PassRegistry &);
|
||||
void initializeModuleSummaryIndexWrapperPassPass(PassRegistry&);
|
||||
void initializeModuloScheduleTestPass(PassRegistry&);
|
||||
void initializeMustExecutePrinterPass(PassRegistry&);
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
//===--------- Definition of the HeapProfiler class -------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares the HeapProfiler class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef LLVM_TRANSFORMS_INSTRUMENTATION_HEAPPROFILER_H
|
||||
#define LLVM_TRANSFORMS_INSTRUMENTATION_HEAPPROFILER_H
|
||||
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// Public interface to the heap profiler pass for instrumenting code to
|
||||
/// profile heap memory accesses.
|
||||
///
|
||||
/// The profiler itself is a function pass that works by inserting various
|
||||
/// calls to the HeapProfiler runtime library functions. The runtime library
|
||||
/// essentially replaces malloc() and free() with custom implementations that
|
||||
/// record data about the allocations.
|
||||
class HeapProfilerPass : public PassInfoMixin<HeapProfilerPass> {
|
||||
public:
|
||||
explicit HeapProfilerPass();
|
||||
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
|
||||
};
|
||||
|
||||
/// Public interface to the heap profiler module pass for instrumenting code
|
||||
/// to profile heap memory allocations and accesses.
|
||||
class ModuleHeapProfilerPass : public PassInfoMixin<ModuleHeapProfilerPass> {
|
||||
public:
|
||||
explicit ModuleHeapProfilerPass();
|
||||
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
|
||||
};
|
||||
|
||||
// Insert HeapProfiler instrumentation
|
||||
FunctionPass *createHeapProfilerFunctionPass();
|
||||
ModulePass *createModuleHeapProfilerLegacyPassPass();
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
|
@ -0,0 +1,49 @@
|
|||
//===--------- Definition of the MemProfiler class --------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares the MemProfiler class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef LLVM_TRANSFORMS_INSTRUMENTATION_MEMPROFILER_H
|
||||
#define LLVM_TRANSFORMS_INSTRUMENTATION_MEMPROFILER_H
|
||||
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// Public interface to the memory profiler pass for instrumenting code to
|
||||
/// profile memory accesses.
|
||||
///
|
||||
/// The profiler itself is a function pass that works by inserting various
|
||||
/// calls to the MemProfiler runtime library functions. The runtime library
|
||||
/// essentially replaces malloc() and free() with custom implementations that
|
||||
/// record data about the allocations.
|
||||
class MemProfilerPass : public PassInfoMixin<MemProfilerPass> {
|
||||
public:
|
||||
explicit MemProfilerPass();
|
||||
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
|
||||
};
|
||||
|
||||
/// Public interface to the memory profiler module pass for instrumenting code
|
||||
/// to profile memory allocations and accesses.
|
||||
class ModuleMemProfilerPass : public PassInfoMixin<ModuleMemProfilerPass> {
|
||||
public:
|
||||
explicit ModuleMemProfilerPass();
|
||||
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
|
||||
};
|
||||
|
||||
// Insert MemProfiler instrumentation
|
||||
FunctionPass *createMemProfilerFunctionPass();
|
||||
ModulePass *createModuleMemProfilerLegacyPassPass();
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
|
@ -111,9 +111,9 @@
|
|||
#include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"
|
||||
#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
|
||||
#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
|
||||
#include "llvm/Transforms/Instrumentation/HeapProfiler.h"
|
||||
#include "llvm/Transforms/Instrumentation/InstrOrderFile.h"
|
||||
#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
|
||||
#include "llvm/Transforms/Instrumentation/MemProfiler.h"
|
||||
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
|
||||
#include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
|
||||
#include "llvm/Transforms/Instrumentation/PoisonChecking.h"
|
||||
|
@ -261,9 +261,9 @@ static cl::opt<bool>
|
|||
cl::Hidden,
|
||||
cl::desc("Enable inline deferral during PGO"));
|
||||
|
||||
static cl::opt<bool> EnableHeapProfiler("enable-heap-prof", cl::init(false),
|
||||
cl::Hidden, cl::ZeroOrMore,
|
||||
cl::desc("Enable heap profiler"));
|
||||
static cl::opt<bool> EnableMemProfiler("enable-mem-prof", cl::init(false),
|
||||
cl::Hidden, cl::ZeroOrMore,
|
||||
cl::desc("Enable memory profiler"));
|
||||
|
||||
PipelineTuningOptions::PipelineTuningOptions() {
|
||||
LoopInterleaving = true;
|
||||
|
@ -1042,9 +1042,9 @@ ModulePassManager PassBuilder::buildModuleSimplificationPipeline(
|
|||
|
||||
MPM.addPass(buildInlinerPipeline(Level, Phase, DebugLogging));
|
||||
|
||||
if (EnableHeapProfiler && Phase != ThinLTOPhase::PreLink) {
|
||||
MPM.addPass(createModuleToFunctionPassAdaptor(HeapProfilerPass()));
|
||||
MPM.addPass(ModuleHeapProfilerPass());
|
||||
if (EnableMemProfiler && Phase != ThinLTOPhase::PreLink) {
|
||||
MPM.addPass(createModuleToFunctionPassAdaptor(MemProfilerPass()));
|
||||
MPM.addPass(ModuleMemProfilerPass());
|
||||
}
|
||||
|
||||
return MPM;
|
||||
|
|
|
@ -98,7 +98,7 @@ MODULE_PASS("msan-module", MemorySanitizerPass({}))
|
|||
MODULE_PASS("tsan-module", ThreadSanitizerPass())
|
||||
MODULE_PASS("kasan-module", ModuleAddressSanitizerPass(/*CompileKernel=*/true, false, true, false))
|
||||
MODULE_PASS("sancov-module", ModuleSanitizerCoveragePass())
|
||||
MODULE_PASS("heapprof-module", ModuleHeapProfilerPass())
|
||||
MODULE_PASS("memprof-module", ModuleMemProfilerPass())
|
||||
MODULE_PASS("poison-checking", PoisonCheckingPass())
|
||||
#undef MODULE_PASS
|
||||
|
||||
|
@ -279,7 +279,7 @@ FUNCTION_PASS("kasan", AddressSanitizerPass(true, false, false))
|
|||
FUNCTION_PASS("msan", MemorySanitizerPass({}))
|
||||
FUNCTION_PASS("kmsan", MemorySanitizerPass({0, false, /*Kernel=*/true}))
|
||||
FUNCTION_PASS("tsan", ThreadSanitizerPass())
|
||||
FUNCTION_PASS("heapprof", HeapProfilerPass())
|
||||
FUNCTION_PASS("memprof", MemProfilerPass())
|
||||
#undef FUNCTION_PASS
|
||||
|
||||
#ifndef FUNCTION_PASS_WITH_PARAMS
|
||||
|
|
|
@ -5,7 +5,7 @@ add_llvm_component_library(LLVMInstrumentation
|
|||
ControlHeightReduction.cpp
|
||||
DataFlowSanitizer.cpp
|
||||
GCOVProfiling.cpp
|
||||
HeapProfiler.cpp
|
||||
MemProfiler.cpp
|
||||
MemorySanitizer.cpp
|
||||
IndirectCallPromotion.cpp
|
||||
Instrumentation.cpp
|
||||
|
|
|
@ -105,8 +105,8 @@ Comdat *llvm::GetOrCreateFunctionComdat(Function &F, Triple &T,
|
|||
void llvm::initializeInstrumentation(PassRegistry &Registry) {
|
||||
initializeAddressSanitizerLegacyPassPass(Registry);
|
||||
initializeModuleAddressSanitizerLegacyPassPass(Registry);
|
||||
initializeHeapProfilerLegacyPassPass(Registry);
|
||||
initializeModuleHeapProfilerLegacyPassPass(Registry);
|
||||
initializeMemProfilerLegacyPassPass(Registry);
|
||||
initializeModuleMemProfilerLegacyPassPass(Registry);
|
||||
initializeBoundsCheckingLegacyPassPass(Registry);
|
||||
initializeControlHeightReductionLegacyPassPass(Registry);
|
||||
initializeGCOVProfilerLegacyPassPass(Registry);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//===- HeapProfiler.cpp - heap allocation and access profiler -------------===//
|
||||
//===- MemProfiler.cpp - memory allocation and access profiler ------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
|
@ -6,15 +6,15 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file is a part of HeapProfiler. Memory accesses are instrumented
|
||||
// This file is a part of MemProfiler. Memory accesses are instrumented
|
||||
// to increment the access count held in a shadow memory location, or
|
||||
// alternatively to call into the runtime. Memory intrinsic calls (memmove,
|
||||
// memcpy, memset) are changed to call the heap profiling runtime version
|
||||
// memcpy, memset) are changed to call the memory profiling runtime version
|
||||
// instead.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Transforms/Instrumentation/HeapProfiler.h"
|
||||
#include "llvm/Transforms/Instrumentation/MemProfiler.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
@ -39,9 +39,9 @@
|
|||
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "heapprof"
|
||||
#define DEBUG_TYPE "memprof"
|
||||
|
||||
constexpr int LLVM_HEAP_PROFILER_VERSION = 1;
|
||||
constexpr int LLVM_MEM_PROFILER_VERSION = 1;
|
||||
|
||||
// Size of memory mapped to a single shadow location.
|
||||
constexpr uint64_t DefaultShadowGranularity = 64;
|
||||
|
@ -49,74 +49,74 @@ constexpr uint64_t DefaultShadowGranularity = 64;
|
|||
// Scale from granularity down to shadow size.
|
||||
constexpr uint64_t DefaultShadowScale = 3;
|
||||
|
||||
constexpr char HeapProfModuleCtorName[] = "heapprof.module_ctor";
|
||||
constexpr uint64_t HeapProfCtorAndDtorPriority = 1;
|
||||
constexpr char MemProfModuleCtorName[] = "memprof.module_ctor";
|
||||
constexpr uint64_t MemProfCtorAndDtorPriority = 1;
|
||||
// On Emscripten, the system needs more than one priorities for constructors.
|
||||
constexpr uint64_t HeapProfEmscriptenCtorAndDtorPriority = 50;
|
||||
constexpr char HeapProfInitName[] = "__heapprof_init";
|
||||
constexpr char HeapProfVersionCheckNamePrefix[] =
|
||||
"__heapprof_version_mismatch_check_v";
|
||||
constexpr uint64_t MemProfEmscriptenCtorAndDtorPriority = 50;
|
||||
constexpr char MemProfInitName[] = "__memprof_init";
|
||||
constexpr char MemProfVersionCheckNamePrefix[] =
|
||||
"__memprof_version_mismatch_check_v";
|
||||
|
||||
constexpr char HeapProfShadowMemoryDynamicAddress[] =
|
||||
"__heapprof_shadow_memory_dynamic_address";
|
||||
constexpr char MemProfShadowMemoryDynamicAddress[] =
|
||||
"__memprof_shadow_memory_dynamic_address";
|
||||
|
||||
// Command-line flags.
|
||||
|
||||
static cl::opt<bool> ClInsertVersionCheck(
|
||||
"heapprof-guard-against-version-mismatch",
|
||||
"memprof-guard-against-version-mismatch",
|
||||
cl::desc("Guard against compiler/runtime version mismatch."), cl::Hidden,
|
||||
cl::init(true));
|
||||
|
||||
// This flag may need to be replaced with -f[no-]memprof-reads.
|
||||
static cl::opt<bool> ClInstrumentReads("heapprof-instrument-reads",
|
||||
static cl::opt<bool> ClInstrumentReads("memprof-instrument-reads",
|
||||
cl::desc("instrument read instructions"),
|
||||
cl::Hidden, cl::init(true));
|
||||
|
||||
static cl::opt<bool>
|
||||
ClInstrumentWrites("heapprof-instrument-writes",
|
||||
ClInstrumentWrites("memprof-instrument-writes",
|
||||
cl::desc("instrument write instructions"), cl::Hidden,
|
||||
cl::init(true));
|
||||
|
||||
static cl::opt<bool> ClInstrumentAtomics(
|
||||
"heapprof-instrument-atomics",
|
||||
"memprof-instrument-atomics",
|
||||
cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden,
|
||||
cl::init(true));
|
||||
|
||||
static cl::opt<bool> ClUseCalls(
|
||||
"heapprof-use-callbacks",
|
||||
"memprof-use-callbacks",
|
||||
cl::desc("Use callbacks instead of inline instrumentation sequences."),
|
||||
cl::Hidden, cl::init(false));
|
||||
|
||||
static cl::opt<std::string>
|
||||
ClMemoryAccessCallbackPrefix("heapprof-memory-access-callback-prefix",
|
||||
ClMemoryAccessCallbackPrefix("memprof-memory-access-callback-prefix",
|
||||
cl::desc("Prefix for memory access callbacks"),
|
||||
cl::Hidden, cl::init("__heapprof_"));
|
||||
cl::Hidden, cl::init("__memprof_"));
|
||||
|
||||
// These flags allow to change the shadow mapping.
|
||||
// The shadow mapping looks like
|
||||
// Shadow = ((Mem & mask) >> scale) + offset
|
||||
|
||||
static cl::opt<int> ClMappingScale("heapprof-mapping-scale",
|
||||
cl::desc("scale of heapprof shadow mapping"),
|
||||
static cl::opt<int> ClMappingScale("memprof-mapping-scale",
|
||||
cl::desc("scale of memprof shadow mapping"),
|
||||
cl::Hidden, cl::init(DefaultShadowScale));
|
||||
|
||||
static cl::opt<int>
|
||||
ClMappingGranularity("heapprof-mapping-granularity",
|
||||
cl::desc("granularity of heapprof shadow mapping"),
|
||||
ClMappingGranularity("memprof-mapping-granularity",
|
||||
cl::desc("granularity of memprof shadow mapping"),
|
||||
cl::Hidden, cl::init(DefaultShadowGranularity));
|
||||
|
||||
// Debug flags.
|
||||
|
||||
static cl::opt<int> ClDebug("heapprof-debug", cl::desc("debug"), cl::Hidden,
|
||||
static cl::opt<int> ClDebug("memprof-debug", cl::desc("debug"), cl::Hidden,
|
||||
cl::init(0));
|
||||
|
||||
static cl::opt<std::string> ClDebugFunc("heapprof-debug-func", cl::Hidden,
|
||||
static cl::opt<std::string> ClDebugFunc("memprof-debug-func", cl::Hidden,
|
||||
cl::desc("Debug func"));
|
||||
|
||||
static cl::opt<int> ClDebugMin("heapprof-debug-min", cl::desc("Debug min inst"),
|
||||
static cl::opt<int> ClDebugMin("memprof-debug-min", cl::desc("Debug min inst"),
|
||||
cl::Hidden, cl::init(-1));
|
||||
|
||||
static cl::opt<int> ClDebugMax("heapprof-debug-max", cl::desc("Debug max inst"),
|
||||
static cl::opt<int> ClDebugMax("memprof-debug-max", cl::desc("Debug max inst"),
|
||||
cl::Hidden, cl::init(-1));
|
||||
|
||||
STATISTIC(NumInstrumentedReads, "Number of instrumented reads");
|
||||
|
@ -139,8 +139,8 @@ struct ShadowMapping {
|
|||
};
|
||||
|
||||
static uint64_t getCtorAndDtorPriority(Triple &TargetTriple) {
|
||||
return TargetTriple.isOSEmscripten() ? HeapProfEmscriptenCtorAndDtorPriority
|
||||
: HeapProfCtorAndDtorPriority;
|
||||
return TargetTriple.isOSEmscripten() ? MemProfEmscriptenCtorAndDtorPriority
|
||||
: MemProfCtorAndDtorPriority;
|
||||
}
|
||||
|
||||
struct InterestingMemoryAccess {
|
||||
|
@ -151,10 +151,10 @@ struct InterestingMemoryAccess {
|
|||
Value *MaybeMask = nullptr;
|
||||
};
|
||||
|
||||
/// Instrument the code in module to profile heap accesses.
|
||||
class HeapProfiler {
|
||||
/// Instrument the code in module to profile memory accesses.
|
||||
class MemProfiler {
|
||||
public:
|
||||
HeapProfiler(Module &M) {
|
||||
MemProfiler(Module &M) {
|
||||
C = &(M.getContext());
|
||||
LongSize = M.getDataLayout().getPointerSizeInBits();
|
||||
IntptrTy = Type::getIntNTy(*C, LongSize);
|
||||
|
@ -177,7 +177,7 @@ public:
|
|||
void instrumentMemIntrinsic(MemIntrinsic *MI);
|
||||
Value *memToShadow(Value *Shadow, IRBuilder<> &IRB);
|
||||
bool instrumentFunction(Function &F);
|
||||
bool maybeInsertHeapProfInitAtFunctionEntry(Function &F);
|
||||
bool maybeInsertMemProfInitAtFunctionEntry(Function &F);
|
||||
bool insertDynamicShadowAtFunctionEntry(Function &F);
|
||||
|
||||
private:
|
||||
|
@ -189,68 +189,67 @@ private:
|
|||
ShadowMapping Mapping;
|
||||
|
||||
// These arrays is indexed by AccessIsWrite
|
||||
FunctionCallee HeapProfMemoryAccessCallback[2];
|
||||
FunctionCallee HeapProfMemoryAccessCallbackSized[2];
|
||||
FunctionCallee MemProfMemoryAccessCallback[2];
|
||||
FunctionCallee MemProfMemoryAccessCallbackSized[2];
|
||||
|
||||
FunctionCallee HeapProfMemmove, HeapProfMemcpy, HeapProfMemset;
|
||||
FunctionCallee MemProfMemmove, MemProfMemcpy, MemProfMemset;
|
||||
Value *DynamicShadowOffset = nullptr;
|
||||
};
|
||||
|
||||
class HeapProfilerLegacyPass : public FunctionPass {
|
||||
class MemProfilerLegacyPass : public FunctionPass {
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
explicit HeapProfilerLegacyPass() : FunctionPass(ID) {
|
||||
initializeHeapProfilerLegacyPassPass(*PassRegistry::getPassRegistry());
|
||||
explicit MemProfilerLegacyPass() : FunctionPass(ID) {
|
||||
initializeMemProfilerLegacyPassPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
StringRef getPassName() const override { return "HeapProfilerFunctionPass"; }
|
||||
StringRef getPassName() const override { return "MemProfilerFunctionPass"; }
|
||||
|
||||
bool runOnFunction(Function &F) override {
|
||||
HeapProfiler Profiler(*F.getParent());
|
||||
MemProfiler Profiler(*F.getParent());
|
||||
return Profiler.instrumentFunction(F);
|
||||
}
|
||||
};
|
||||
|
||||
class ModuleHeapProfiler {
|
||||
class ModuleMemProfiler {
|
||||
public:
|
||||
ModuleHeapProfiler(Module &M) { TargetTriple = Triple(M.getTargetTriple()); }
|
||||
ModuleMemProfiler(Module &M) { TargetTriple = Triple(M.getTargetTriple()); }
|
||||
|
||||
bool instrumentModule(Module &);
|
||||
|
||||
private:
|
||||
Triple TargetTriple;
|
||||
ShadowMapping Mapping;
|
||||
Function *HeapProfCtorFunction = nullptr;
|
||||
Function *MemProfCtorFunction = nullptr;
|
||||
};
|
||||
|
||||
class ModuleHeapProfilerLegacyPass : public ModulePass {
|
||||
class ModuleMemProfilerLegacyPass : public ModulePass {
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
explicit ModuleHeapProfilerLegacyPass() : ModulePass(ID) {
|
||||
initializeModuleHeapProfilerLegacyPassPass(
|
||||
*PassRegistry::getPassRegistry());
|
||||
explicit ModuleMemProfilerLegacyPass() : ModulePass(ID) {
|
||||
initializeModuleMemProfilerLegacyPassPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
StringRef getPassName() const override { return "ModuleHeapProfiler"; }
|
||||
StringRef getPassName() const override { return "ModuleMemProfiler"; }
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {}
|
||||
|
||||
bool runOnModule(Module &M) override {
|
||||
ModuleHeapProfiler HeapProfiler(M);
|
||||
return HeapProfiler.instrumentModule(M);
|
||||
ModuleMemProfiler MemProfiler(M);
|
||||
return MemProfiler.instrumentModule(M);
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
HeapProfilerPass::HeapProfilerPass() {}
|
||||
MemProfilerPass::MemProfilerPass() {}
|
||||
|
||||
PreservedAnalyses HeapProfilerPass::run(Function &F,
|
||||
AnalysisManager<Function> &AM) {
|
||||
PreservedAnalyses MemProfilerPass::run(Function &F,
|
||||
AnalysisManager<Function> &AM) {
|
||||
Module &M = *F.getParent();
|
||||
HeapProfiler Profiler(M);
|
||||
MemProfiler Profiler(M);
|
||||
if (Profiler.instrumentFunction(F))
|
||||
return PreservedAnalyses::none();
|
||||
return PreservedAnalyses::all();
|
||||
|
@ -258,41 +257,41 @@ PreservedAnalyses HeapProfilerPass::run(Function &F,
|
|||
return PreservedAnalyses::all();
|
||||
}
|
||||
|
||||
ModuleHeapProfilerPass::ModuleHeapProfilerPass() {}
|
||||
ModuleMemProfilerPass::ModuleMemProfilerPass() {}
|
||||
|
||||
PreservedAnalyses ModuleHeapProfilerPass::run(Module &M,
|
||||
AnalysisManager<Module> &AM) {
|
||||
ModuleHeapProfiler Profiler(M);
|
||||
PreservedAnalyses ModuleMemProfilerPass::run(Module &M,
|
||||
AnalysisManager<Module> &AM) {
|
||||
ModuleMemProfiler Profiler(M);
|
||||
if (Profiler.instrumentModule(M))
|
||||
return PreservedAnalyses::none();
|
||||
return PreservedAnalyses::all();
|
||||
}
|
||||
|
||||
char HeapProfilerLegacyPass::ID = 0;
|
||||
char MemProfilerLegacyPass::ID = 0;
|
||||
|
||||
INITIALIZE_PASS_BEGIN(HeapProfilerLegacyPass, "heapprof",
|
||||
"HeapProfiler: profile heap allocations and accesses.",
|
||||
INITIALIZE_PASS_BEGIN(MemProfilerLegacyPass, "memprof",
|
||||
"MemProfiler: profile memory allocations and accesses.",
|
||||
false, false)
|
||||
INITIALIZE_PASS_END(HeapProfilerLegacyPass, "heapprof",
|
||||
"HeapProfiler: profile heap allocations and accesses.",
|
||||
INITIALIZE_PASS_END(MemProfilerLegacyPass, "memprof",
|
||||
"MemProfiler: profile memory allocations and accesses.",
|
||||
false, false)
|
||||
|
||||
FunctionPass *llvm::createHeapProfilerFunctionPass() {
|
||||
return new HeapProfilerLegacyPass();
|
||||
FunctionPass *llvm::createMemProfilerFunctionPass() {
|
||||
return new MemProfilerLegacyPass();
|
||||
}
|
||||
|
||||
char ModuleHeapProfilerLegacyPass::ID = 0;
|
||||
char ModuleMemProfilerLegacyPass::ID = 0;
|
||||
|
||||
INITIALIZE_PASS(ModuleHeapProfilerLegacyPass, "heapprof-module",
|
||||
"HeapProfiler: profile heap allocations and accesses."
|
||||
INITIALIZE_PASS(ModuleMemProfilerLegacyPass, "memprof-module",
|
||||
"MemProfiler: profile memory allocations and accesses."
|
||||
"ModulePass",
|
||||
false, false)
|
||||
|
||||
ModulePass *llvm::createModuleHeapProfilerLegacyPassPass() {
|
||||
return new ModuleHeapProfilerLegacyPass();
|
||||
ModulePass *llvm::createModuleMemProfilerLegacyPassPass() {
|
||||
return new ModuleMemProfilerLegacyPass();
|
||||
}
|
||||
|
||||
Value *HeapProfiler::memToShadow(Value *Shadow, IRBuilder<> &IRB) {
|
||||
Value *MemProfiler::memToShadow(Value *Shadow, IRBuilder<> &IRB) {
|
||||
// (Shadow & mask) >> scale
|
||||
Shadow = IRB.CreateAnd(Shadow, Mapping.Mask);
|
||||
Shadow = IRB.CreateLShr(Shadow, Mapping.Scale);
|
||||
|
@ -302,17 +301,17 @@ Value *HeapProfiler::memToShadow(Value *Shadow, IRBuilder<> &IRB) {
|
|||
}
|
||||
|
||||
// Instrument memset/memmove/memcpy
|
||||
void HeapProfiler::instrumentMemIntrinsic(MemIntrinsic *MI) {
|
||||
void MemProfiler::instrumentMemIntrinsic(MemIntrinsic *MI) {
|
||||
IRBuilder<> IRB(MI);
|
||||
if (isa<MemTransferInst>(MI)) {
|
||||
IRB.CreateCall(
|
||||
isa<MemMoveInst>(MI) ? HeapProfMemmove : HeapProfMemcpy,
|
||||
isa<MemMoveInst>(MI) ? MemProfMemmove : MemProfMemcpy,
|
||||
{IRB.CreatePointerCast(MI->getOperand(0), IRB.getInt8PtrTy()),
|
||||
IRB.CreatePointerCast(MI->getOperand(1), IRB.getInt8PtrTy()),
|
||||
IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)});
|
||||
} else if (isa<MemSetInst>(MI)) {
|
||||
IRB.CreateCall(
|
||||
HeapProfMemset,
|
||||
MemProfMemset,
|
||||
{IRB.CreatePointerCast(MI->getOperand(0), IRB.getInt8PtrTy()),
|
||||
IRB.CreateIntCast(MI->getOperand(1), IRB.getInt32Ty(), false),
|
||||
IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)});
|
||||
|
@ -321,7 +320,7 @@ void HeapProfiler::instrumentMemIntrinsic(MemIntrinsic *MI) {
|
|||
}
|
||||
|
||||
Optional<InterestingMemoryAccess>
|
||||
HeapProfiler::isInterestingMemoryAccess(Instruction *I) const {
|
||||
MemProfiler::isInterestingMemoryAccess(Instruction *I) const {
|
||||
// Do not instrument the load fetching the dynamic shadow address.
|
||||
if (DynamicShadowOffset == I)
|
||||
return None;
|
||||
|
@ -409,11 +408,10 @@ HeapProfiler::isInterestingMemoryAccess(Instruction *I) const {
|
|||
return Access;
|
||||
}
|
||||
|
||||
void HeapProfiler::instrumentMaskedLoadOrStore(const DataLayout &DL,
|
||||
Value *Mask, Instruction *I,
|
||||
Value *Addr, unsigned Alignment,
|
||||
uint32_t TypeSize,
|
||||
bool IsWrite) {
|
||||
void MemProfiler::instrumentMaskedLoadOrStore(const DataLayout &DL, Value *Mask,
|
||||
Instruction *I, Value *Addr,
|
||||
unsigned Alignment,
|
||||
uint32_t TypeSize, bool IsWrite) {
|
||||
auto *VTy = cast<FixedVectorType>(
|
||||
cast<PointerType>(Addr->getType())->getElementType());
|
||||
uint64_t ElemTypeSize = DL.getTypeStoreSizeInBits(VTy->getScalarType());
|
||||
|
@ -446,8 +444,8 @@ void HeapProfiler::instrumentMaskedLoadOrStore(const DataLayout &DL,
|
|||
}
|
||||
}
|
||||
|
||||
void HeapProfiler::instrumentMop(Instruction *I, const DataLayout &DL,
|
||||
InterestingMemoryAccess &Access) {
|
||||
void MemProfiler::instrumentMop(Instruction *I, const DataLayout &DL,
|
||||
InterestingMemoryAccess &Access) {
|
||||
if (Access.IsWrite)
|
||||
NumInstrumentedWrites++;
|
||||
else
|
||||
|
@ -465,14 +463,14 @@ void HeapProfiler::instrumentMop(Instruction *I, const DataLayout &DL,
|
|||
}
|
||||
}
|
||||
|
||||
void HeapProfiler::instrumentAddress(Instruction *OrigIns,
|
||||
Instruction *InsertBefore, Value *Addr,
|
||||
uint32_t TypeSize, bool IsWrite) {
|
||||
void MemProfiler::instrumentAddress(Instruction *OrigIns,
|
||||
Instruction *InsertBefore, Value *Addr,
|
||||
uint32_t TypeSize, bool IsWrite) {
|
||||
IRBuilder<> IRB(InsertBefore);
|
||||
Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
|
||||
|
||||
if (ClUseCalls) {
|
||||
IRB.CreateCall(HeapProfMemoryAccessCallback[IsWrite], AddrLong);
|
||||
IRB.CreateCall(MemProfMemoryAccessCallback[IsWrite], AddrLong);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -488,24 +486,24 @@ void HeapProfiler::instrumentAddress(Instruction *OrigIns,
|
|||
IRB.CreateStore(ShadowValue, ShadowAddr);
|
||||
}
|
||||
|
||||
bool ModuleHeapProfiler::instrumentModule(Module &M) {
|
||||
bool ModuleMemProfiler::instrumentModule(Module &M) {
|
||||
// Create a module constructor.
|
||||
std::string HeapProfVersion = std::to_string(LLVM_HEAP_PROFILER_VERSION);
|
||||
std::string MemProfVersion = std::to_string(LLVM_MEM_PROFILER_VERSION);
|
||||
std::string VersionCheckName =
|
||||
ClInsertVersionCheck ? (HeapProfVersionCheckNamePrefix + HeapProfVersion)
|
||||
ClInsertVersionCheck ? (MemProfVersionCheckNamePrefix + MemProfVersion)
|
||||
: "";
|
||||
std::tie(HeapProfCtorFunction, std::ignore) =
|
||||
createSanitizerCtorAndInitFunctions(M, HeapProfModuleCtorName,
|
||||
HeapProfInitName, /*InitArgTypes=*/{},
|
||||
std::tie(MemProfCtorFunction, std::ignore) =
|
||||
createSanitizerCtorAndInitFunctions(M, MemProfModuleCtorName,
|
||||
MemProfInitName, /*InitArgTypes=*/{},
|
||||
/*InitArgs=*/{}, VersionCheckName);
|
||||
|
||||
const uint64_t Priority = getCtorAndDtorPriority(TargetTriple);
|
||||
appendToGlobalCtors(M, HeapProfCtorFunction, Priority);
|
||||
appendToGlobalCtors(M, MemProfCtorFunction, Priority);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HeapProfiler::initializeCallbacks(Module &M) {
|
||||
void MemProfiler::initializeCallbacks(Module &M) {
|
||||
IRBuilder<> IRB(*C);
|
||||
|
||||
for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
|
||||
|
@ -513,68 +511,68 @@ void HeapProfiler::initializeCallbacks(Module &M) {
|
|||
|
||||
SmallVector<Type *, 3> Args2 = {IntptrTy, IntptrTy};
|
||||
SmallVector<Type *, 2> Args1{1, IntptrTy};
|
||||
HeapProfMemoryAccessCallbackSized[AccessIsWrite] =
|
||||
MemProfMemoryAccessCallbackSized[AccessIsWrite] =
|
||||
M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + TypeStr + "N",
|
||||
FunctionType::get(IRB.getVoidTy(), Args2, false));
|
||||
|
||||
HeapProfMemoryAccessCallback[AccessIsWrite] =
|
||||
MemProfMemoryAccessCallback[AccessIsWrite] =
|
||||
M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + TypeStr,
|
||||
FunctionType::get(IRB.getVoidTy(), Args1, false));
|
||||
}
|
||||
HeapProfMemmove = M.getOrInsertFunction(
|
||||
MemProfMemmove = M.getOrInsertFunction(
|
||||
ClMemoryAccessCallbackPrefix + "memmove", IRB.getInt8PtrTy(),
|
||||
IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy);
|
||||
HeapProfMemcpy = M.getOrInsertFunction(
|
||||
ClMemoryAccessCallbackPrefix + "memcpy", IRB.getInt8PtrTy(),
|
||||
IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy);
|
||||
HeapProfMemset = M.getOrInsertFunction(
|
||||
ClMemoryAccessCallbackPrefix + "memset", IRB.getInt8PtrTy(),
|
||||
IRB.getInt8PtrTy(), IRB.getInt32Ty(), IntptrTy);
|
||||
MemProfMemcpy = M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + "memcpy",
|
||||
IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
|
||||
IRB.getInt8PtrTy(), IntptrTy);
|
||||
MemProfMemset = M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + "memset",
|
||||
IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
|
||||
IRB.getInt32Ty(), IntptrTy);
|
||||
}
|
||||
|
||||
bool HeapProfiler::maybeInsertHeapProfInitAtFunctionEntry(Function &F) {
|
||||
bool MemProfiler::maybeInsertMemProfInitAtFunctionEntry(Function &F) {
|
||||
// For each NSObject descendant having a +load method, this method is invoked
|
||||
// by the ObjC runtime before any of the static constructors is called.
|
||||
// Therefore we need to instrument such methods with a call to __heapprof_init
|
||||
// Therefore we need to instrument such methods with a call to __memprof_init
|
||||
// at the beginning in order to initialize our runtime before any access to
|
||||
// the shadow memory.
|
||||
// We cannot just ignore these methods, because they may call other
|
||||
// instrumented functions.
|
||||
if (F.getName().find(" load]") != std::string::npos) {
|
||||
FunctionCallee HeapProfInitFunction =
|
||||
declareSanitizerInitFunction(*F.getParent(), HeapProfInitName, {});
|
||||
FunctionCallee MemProfInitFunction =
|
||||
declareSanitizerInitFunction(*F.getParent(), MemProfInitName, {});
|
||||
IRBuilder<> IRB(&F.front(), F.front().begin());
|
||||
IRB.CreateCall(HeapProfInitFunction, {});
|
||||
IRB.CreateCall(MemProfInitFunction, {});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HeapProfiler::insertDynamicShadowAtFunctionEntry(Function &F) {
|
||||
bool MemProfiler::insertDynamicShadowAtFunctionEntry(Function &F) {
|
||||
IRBuilder<> IRB(&F.front().front());
|
||||
Value *GlobalDynamicAddress = F.getParent()->getOrInsertGlobal(
|
||||
HeapProfShadowMemoryDynamicAddress, IntptrTy);
|
||||
MemProfShadowMemoryDynamicAddress, IntptrTy);
|
||||
DynamicShadowOffset = IRB.CreateLoad(IntptrTy, GlobalDynamicAddress);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HeapProfiler::instrumentFunction(Function &F) {
|
||||
bool MemProfiler::instrumentFunction(Function &F) {
|
||||
if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage)
|
||||
return false;
|
||||
if (ClDebugFunc == F.getName())
|
||||
return false;
|
||||
if (F.getName().startswith("__heapprof_"))
|
||||
if (F.getName().startswith("__memprof_"))
|
||||
return false;
|
||||
|
||||
bool FunctionModified = false;
|
||||
|
||||
// If needed, insert __heapprof_init.
|
||||
// If needed, insert __memprof_init.
|
||||
// This function needs to be called even if the function body is not
|
||||
// instrumented.
|
||||
if (maybeInsertHeapProfInitAtFunctionEntry(F))
|
||||
if (maybeInsertMemProfInitAtFunctionEntry(F))
|
||||
FunctionModified = true;
|
||||
|
||||
LLVM_DEBUG(dbgs() << "HEAPPROF instrumenting:\n" << F << "\n");
|
||||
LLVM_DEBUG(dbgs() << "MEMPROF instrumenting:\n" << F << "\n");
|
||||
|
||||
initializeCallbacks(*F.getParent());
|
||||
|
||||
|
@ -607,8 +605,8 @@ bool HeapProfiler::instrumentFunction(Function &F) {
|
|||
if (NumInstrumented > 0)
|
||||
FunctionModified = true;
|
||||
|
||||
LLVM_DEBUG(dbgs() << "HEAPPROF done instrumenting: " << FunctionModified
|
||||
<< " " << F << "\n");
|
||||
LLVM_DEBUG(dbgs() << "MEMPROF done instrumenting: " << FunctionModified << " "
|
||||
<< F << "\n");
|
||||
|
||||
return FunctionModified;
|
||||
}
|
|
@ -1,15 +1,15 @@
|
|||
; Test basic address sanitizer instrumentation.
|
||||
;
|
||||
; RUN: opt < %s -heapprof -heapprof-module -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s
|
||||
; RUN: opt < %s -heapprof -heapprof-module -heapprof-mapping-scale=5 -S | FileCheck --check-prefixes=CHECK,CHECK-S5 %s
|
||||
; RUN: opt < %s -memprof -memprof-module -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s
|
||||
; RUN: opt < %s -memprof -memprof-module -memprof-mapping-scale=5 -S | FileCheck --check-prefixes=CHECK,CHECK-S5 %s
|
||||
|
||||
; We need the requires since both heapprof and heapprof-module require reading module level metadata which is done once by the heapprof-globals-md analysis
|
||||
; RUN: opt < %s -passes='function(heapprof),module(heapprof-module)' -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s
|
||||
; RUN: opt < %s -passes='function(heapprof),module(heapprof-module)' -heapprof-mapping-scale=5 -S | FileCheck --check-prefixes=CHECK,CHECK-S5 %s
|
||||
; We need the requires since both memprof and memprof-module require reading module level metadata which is done once by the memprof-globals-md analysis
|
||||
; RUN: opt < %s -passes='function(memprof),module(memprof-module)' -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s
|
||||
; RUN: opt < %s -passes='function(memprof),module(memprof-module)' -memprof-mapping-scale=5 -S | FileCheck --check-prefixes=CHECK,CHECK-S5 %s
|
||||
|
||||
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
; CHECK: @llvm.global_ctors = {{.*}}@heapprof.module_ctor
|
||||
; CHECK: @llvm.global_ctors = {{.*}}@memprof.module_ctor
|
||||
|
||||
define i32 @test_load(i32* %a) {
|
||||
entry:
|
||||
|
@ -17,7 +17,7 @@ entry:
|
|||
ret i32 %tmp1
|
||||
}
|
||||
; CHECK-LABEL: @test_load
|
||||
; CHECK: %[[SHADOW_OFFSET:[^ ]*]] = load i64, i64* @__heapprof_shadow_memory_dynamic_address
|
||||
; CHECK: %[[SHADOW_OFFSET:[^ ]*]] = load i64, i64* @__memprof_shadow_memory_dynamic_address
|
||||
; CHECK-NEXT: %[[LOAD_ADDR:[^ ]*]] = ptrtoint i32* %a to i64
|
||||
; CHECK-NEXT: %[[MASKED_ADDR:[^ ]*]] = and i64 %[[LOAD_ADDR]], -64
|
||||
; CHECK-S3-NEXT: %[[SHIFTED_ADDR:[^ ]*]] = lshr i64 %[[MASKED_ADDR]], 3
|
||||
|
@ -37,7 +37,7 @@ entry:
|
|||
ret void
|
||||
}
|
||||
; CHECK-LABEL: @test_store
|
||||
; CHECK: %[[SHADOW_OFFSET:[^ ]*]] = load i64, i64* @__heapprof_shadow_memory_dynamic_address
|
||||
; CHECK: %[[SHADOW_OFFSET:[^ ]*]] = load i64, i64* @__memprof_shadow_memory_dynamic_address
|
||||
; CHECK-NEXT: %[[STORE_ADDR:[^ ]*]] = ptrtoint i32* %a to i64
|
||||
; CHECK-NEXT: %[[MASKED_ADDR:[^ ]*]] = and i64 %[[STORE_ADDR]], -64
|
||||
; CHECK-S3-NEXT: %[[SHIFTED_ADDR:[^ ]*]] = lshr i64 %[[MASKED_ADDR]], 3
|
||||
|
@ -127,14 +127,14 @@ define void @i80test(i80* %a, i80* %b) nounwind uwtable {
|
|||
; CHECK: store i80 %t, i80* %b
|
||||
; CHECK: ret void
|
||||
|
||||
; heapprof should not instrument functions with available_externally linkage.
|
||||
; memprof should not instrument functions with available_externally linkage.
|
||||
define available_externally i32 @f_available_externally(i32* %a) {
|
||||
entry:
|
||||
%tmp1 = load i32, i32* %a
|
||||
ret i32 %tmp1
|
||||
}
|
||||
; CHECK-LABEL: @f_available_externally
|
||||
; CHECK-NOT: __heapprof_shadow_memory_dynamic_address
|
||||
; CHECK-NOT: __memprof_shadow_memory_dynamic_address
|
||||
; CHECK: ret i32
|
||||
|
||||
declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind
|
||||
|
@ -150,9 +150,9 @@ define void @memintr_test(i8* %a, i8* %b) nounwind uwtable {
|
|||
}
|
||||
|
||||
; CHECK-LABEL: memintr_test
|
||||
; CHECK: __heapprof_memset
|
||||
; CHECK: __heapprof_memmove
|
||||
; CHECK: __heapprof_memcpy
|
||||
; CHECK: __memprof_memset
|
||||
; CHECK: __memprof_memmove
|
||||
; CHECK: __memprof_memcpy
|
||||
; CHECK: ret void
|
||||
|
||||
declare void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* nocapture writeonly, i8, i64, i32) nounwind
|
||||
|
@ -161,7 +161,7 @@ declare void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* nocapture w
|
|||
|
||||
define void @memintr_element_atomic_test(i8* %a, i8* %b) nounwind uwtable {
|
||||
; This is a canary test to make sure that these don't get lowered into calls that don't
|
||||
; have the element-atomic property. Eventually, heapprof will have to be enhanced to lower
|
||||
; have the element-atomic property. Eventually, memprof will have to be enhanced to lower
|
||||
; these properly.
|
||||
; CHECK-LABEL: memintr_element_atomic_test
|
||||
; CHECK: tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 1 %a, i8 0, i64 100, i32 1)
|
||||
|
@ -175,5 +175,5 @@ define void @memintr_element_atomic_test(i8* %a, i8* %b) nounwind uwtable {
|
|||
}
|
||||
|
||||
|
||||
; CHECK: define internal void @heapprof.module_ctor()
|
||||
; CHECK: call void @__heapprof_init()
|
||||
; CHECK: define internal void @memprof.module_ctor()
|
||||
; CHECK: call void @__memprof_init()
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
; Test heapprof internal compiler flags:
|
||||
; -heapprof-use-callbacks
|
||||
; -heapprof-memory-access-callback-prefix
|
||||
; Test memprof internal compiler flags:
|
||||
; -memprof-use-callbacks
|
||||
; -memprof-memory-access-callback-prefix
|
||||
|
||||
; RUN: opt < %s -heapprof -heapprof-module -heapprof-use-callbacks -S | FileCheck %s --check-prefix=CHECK-CALL --check-prefix=CHECK-CALL-DEFAULT
|
||||
; RUN: opt < %s -heapprof -heapprof-module -heapprof-use-callbacks -heapprof-memory-access-callback-prefix=__foo_ -S | FileCheck %s --check-prefix=CHECK-CALL --check-prefix=CHECK-CALL-CUSTOM
|
||||
; RUN: opt < %s -heapprof -heapprof-module -heapprof-use-callbacks=false -S | FileCheck %s --check-prefix=CHECK-INLINE
|
||||
; RUN: opt < %s -heapprof -heapprof-module -S | FileCheck %s --check-prefix=CHECK-INLINE
|
||||
; RUN: opt < %s -memprof -memprof-module -memprof-use-callbacks -S | FileCheck %s --check-prefix=CHECK-CALL --check-prefix=CHECK-CALL-DEFAULT
|
||||
; RUN: opt < %s -memprof -memprof-module -memprof-use-callbacks -memprof-memory-access-callback-prefix=__foo_ -S | FileCheck %s --check-prefix=CHECK-CALL --check-prefix=CHECK-CALL-CUSTOM
|
||||
; RUN: opt < %s -memprof -memprof-module -memprof-use-callbacks=false -S | FileCheck %s --check-prefix=CHECK-INLINE
|
||||
; RUN: opt < %s -memprof -memprof-module -S | FileCheck %s --check-prefix=CHECK-INLINE
|
||||
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
define void @test_load(i32* %a, i64* %b, i512* %c, i80* %d) {
|
||||
entry:
|
||||
; CHECK-CALL: %[[LOAD_ADDR1:[^ ]*]] = ptrtoint i32* %a to i64
|
||||
; CHECK-CALL-DEFAULT: call void @__heapprof_load(i64 %[[LOAD_ADDR1]])
|
||||
; CHECK-CALL-DEFAULT: call void @__memprof_load(i64 %[[LOAD_ADDR1]])
|
||||
; CHECK-CALL-CUSTOM: call void @__foo_load(i64 %[[LOAD_ADDR1]])
|
||||
; CHECK-CALL: %[[LOAD_ADDR2:[^ ]*]] = ptrtoint i64* %b to i64
|
||||
; CHECK-CALL-DEFAULT: call void @__heapprof_load(i64 %[[LOAD_ADDR2]])
|
||||
; CHECK-CALL-DEFAULT: call void @__memprof_load(i64 %[[LOAD_ADDR2]])
|
||||
; CHECK-CALL-CUSTOM: call void @__foo_load(i64 %[[LOAD_ADDR2]])
|
||||
; CHECK-CALL: %[[LOAD_ADDR3:[^ ]*]] = ptrtoint i512* %c to i64
|
||||
; CHECK-CALL-DEFAULT: call void @__heapprof_load(i64 %[[LOAD_ADDR3]])
|
||||
; CHECK-CALL-DEFAULT: call void @__memprof_load(i64 %[[LOAD_ADDR3]])
|
||||
; CHECK-CALL-CUSTOM: call void @__foo_load(i64 %[[LOAD_ADDR3]])
|
||||
; CHECK-CALL: %[[LOAD_ADDR4:[^ ]*]] = ptrtoint i80* %d to i64
|
||||
; CHECK-CALL-DEFAULT: call void @__heapprof_load(i64 %[[LOAD_ADDR4]])
|
||||
; CHECK-CALL-DEFAULT: call void @__memprof_load(i64 %[[LOAD_ADDR4]])
|
||||
; CHECK-CALL-CUSTOM: call void @__foo_load(i64 %[[LOAD_ADDR4]])
|
||||
; CHECK-CALL-DEFAULT-NOT: call void @__heapprof_load
|
||||
; CHECK-CALL-DEFAULT-NOT: call void @__memprof_load
|
||||
; CHECK-CALL-CUSTOM-NOT: call void @__foo_load
|
||||
; CHECK-INLINE-NOT: call void @__heapprof_load
|
||||
; CHECK-INLINE-NOT: call void @__memprof_load
|
||||
%tmp1 = load i32, i32* %a, align 4
|
||||
%tmp2 = load i64, i64* %b, align 8
|
||||
%tmp3 = load i512, i512* %c, align 32
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
; RUN: opt < %s -heapprof -heapprof-use-callbacks -S \
|
||||
; RUN: opt < %s -memprof -memprof-use-callbacks -S \
|
||||
; RUN: | FileCheck %s -check-prefix=LOAD -check-prefix=STORE -check-prefix=ALL
|
||||
; RUN: opt < %s -heapprof -heapprof-use-callbacks -heapprof-instrument-reads=0 -S \
|
||||
; RUN: opt < %s -memprof -memprof-use-callbacks -memprof-instrument-reads=0 -S \
|
||||
; RUN: | FileCheck %s -check-prefix=NOLOAD -check-prefix=STORE -check-prefix=ALL
|
||||
; RUN: opt < %s -heapprof -heapprof-use-callbacks -heapprof-instrument-writes=0 -S \
|
||||
; RUN: opt < %s -memprof -memprof-use-callbacks -memprof-instrument-writes=0 -S \
|
||||
; RUN: | FileCheck %s -check-prefix=LOAD -check-prefix=NOSTORE -check-prefix=ALL
|
||||
; RUN: opt < %s -heapprof -heapprof-use-callbacks -heapprof-instrument-reads=0 -heapprof-instrument-writes=0 -S \
|
||||
; RUN: opt < %s -memprof -memprof-use-callbacks -memprof-instrument-reads=0 -memprof-instrument-writes=0 -S \
|
||||
; RUN: | FileCheck %s -check-prefix=NOLOAD -check-prefix=NOSTORE -check-prefix=ALL
|
||||
; Support heap profiling instrumentation for constant-mask llvm.masked.{load,store}
|
||||
; Support memory profiling instrumentation for constant-mask llvm.masked.{load,store}
|
||||
|
||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
|
||||
|
@ -22,16 +22,16 @@ declare void @llvm.masked.store.v4p0i32.p0v4p0i32(<4 x i32*>, <4 x i32*>*, i32,
|
|||
define void @store.v4f32.1110(<4 x float> %arg) {
|
||||
; ALL-LABEL: @store.v4f32.1110
|
||||
%p = load <4 x float>*, <4 x float>** @v4f32, align 8
|
||||
; NOSTORE-NOT: call void @__heapprof_store
|
||||
; NOSTORE-NOT: call void @__memprof_store
|
||||
; STORE: [[GEP0:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 0
|
||||
; STORE: [[PGEP0:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP0]] to i64
|
||||
; STORE: call void @__heapprof_store(i64 [[PGEP0]])
|
||||
; STORE: call void @__memprof_store(i64 [[PGEP0]])
|
||||
; STORE: [[GEP1:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 1
|
||||
; STORE: [[PGEP1:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP1]] to i64
|
||||
; STORE: call void @__heapprof_store(i64 [[PGEP1]])
|
||||
; STORE: call void @__memprof_store(i64 [[PGEP1]])
|
||||
; STORE: [[GEP2:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 2
|
||||
; STORE: [[PGEP2:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP2]] to i64
|
||||
; STORE: call void @__heapprof_store(i64 [[PGEP2]])
|
||||
; STORE: call void @__memprof_store(i64 [[PGEP2]])
|
||||
; STORE: tail call void @llvm.masked.store.v4f32.p0v4f32(<4 x float> %arg, <4 x float>* %p, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 false>)
|
||||
tail call void @llvm.masked.store.v4f32.p0v4f32(<4 x float> %arg, <4 x float>* %p, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 false>)
|
||||
ret void
|
||||
|
@ -40,19 +40,19 @@ define void @store.v4f32.1110(<4 x float> %arg) {
|
|||
define void @store.v8i32.10010110(<8 x i32> %arg) {
|
||||
; ALL-LABEL: @store.v8i32.10010110
|
||||
%p = load <8 x i32>*, <8 x i32>** @v8i32, align 8
|
||||
; NOSTORE-NOT: call void @__heapprof_store
|
||||
; NOSTORE-NOT: call void @__memprof_store
|
||||
; STORE: [[GEP0:%[0-9A-Za-z]+]] = getelementptr <8 x i32>, <8 x i32>* %p, i64 0, i64 0
|
||||
; STORE: [[PGEP0:%[0-9A-Za-z]+]] = ptrtoint i32* [[GEP0]] to i64
|
||||
; STORE: call void @__heapprof_store(i64 [[PGEP0]])
|
||||
; STORE: call void @__memprof_store(i64 [[PGEP0]])
|
||||
; STORE: [[GEP3:%[0-9A-Za-z]+]] = getelementptr <8 x i32>, <8 x i32>* %p, i64 0, i64 3
|
||||
; STORE: [[PGEP3:%[0-9A-Za-z]+]] = ptrtoint i32* [[GEP3]] to i64
|
||||
; STORE: call void @__heapprof_store(i64 [[PGEP3]])
|
||||
; STORE: call void @__memprof_store(i64 [[PGEP3]])
|
||||
; STORE: [[GEP5:%[0-9A-Za-z]+]] = getelementptr <8 x i32>, <8 x i32>* %p, i64 0, i64 5
|
||||
; STORE: [[PGEP5:%[0-9A-Za-z]+]] = ptrtoint i32* [[GEP5]] to i64
|
||||
; STORE: call void @__heapprof_store(i64 [[PGEP5]])
|
||||
; STORE: call void @__memprof_store(i64 [[PGEP5]])
|
||||
; STORE: [[GEP6:%[0-9A-Za-z]+]] = getelementptr <8 x i32>, <8 x i32>* %p, i64 0, i64 6
|
||||
; STORE: [[PGEP6:%[0-9A-Za-z]+]] = ptrtoint i32* [[GEP6]] to i64
|
||||
; STORE: call void @__heapprof_store(i64 [[PGEP6]])
|
||||
; STORE: call void @__memprof_store(i64 [[PGEP6]])
|
||||
; STORE: tail call void @llvm.masked.store.v8i32.p0v8i32(<8 x i32> %arg, <8 x i32>* %p, i32 8, <8 x i1> <i1 true, i1 false, i1 false, i1 true, i1 false, i1 true, i1 true, i1 false>)
|
||||
tail call void @llvm.masked.store.v8i32.p0v8i32(<8 x i32> %arg, <8 x i32>* %p, i32 8, <8 x i1> <i1 true, i1 false, i1 false, i1 true, i1 false, i1 true, i1 true, i1 false>)
|
||||
ret void
|
||||
|
@ -61,10 +61,10 @@ define void @store.v8i32.10010110(<8 x i32> %arg) {
|
|||
define void @store.v4i64.0001(<4 x i32*> %arg) {
|
||||
; ALL-LABEL: @store.v4i64.0001
|
||||
%p = load <4 x i32*>*, <4 x i32*>** @v4i64, align 8
|
||||
; NOSTORE-NOT: call void @__heapprof_store
|
||||
; NOSTORE-NOT: call void @__memprof_store
|
||||
; STORE: [[GEP3:%[0-9A-Za-z]+]] = getelementptr <4 x i32*>, <4 x i32*>* %p, i64 0, i64 3
|
||||
; STORE: [[PGEP3:%[0-9A-Za-z]+]] = ptrtoint i32** [[GEP3]] to i64
|
||||
; STORE: call void @__heapprof_store(i64 [[PGEP3]])
|
||||
; STORE: call void @__memprof_store(i64 [[PGEP3]])
|
||||
; STORE: tail call void @llvm.masked.store.v4p0i32.p0v4p0i32(<4 x i32*> %arg, <4 x i32*>* %p, i32 8, <4 x i1> <i1 false, i1 false, i1 false, i1 true>)
|
||||
tail call void @llvm.masked.store.v4p0i32.p0v4p0i32(<4 x i32*> %arg, <4 x i32*>* %p, i32 8, <4 x i1> <i1 false, i1 false, i1 false, i1 true>)
|
||||
ret void
|
||||
|
@ -78,7 +78,7 @@ define void @store.v4f32.variable(<4 x float> %arg, <4 x i1> %mask) {
|
|||
; STORE: [[THEN0]]:
|
||||
; STORE: [[GEP0:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 0
|
||||
; STORE: [[PGEP0:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP0]] to i64
|
||||
; STORE: call void @__heapprof_store(i64 [[PGEP0]])
|
||||
; STORE: call void @__memprof_store(i64 [[PGEP0]])
|
||||
; STORE: br label %[[AFTER0]]
|
||||
; STORE: [[AFTER0]]:
|
||||
|
||||
|
@ -87,7 +87,7 @@ define void @store.v4f32.variable(<4 x float> %arg, <4 x i1> %mask) {
|
|||
; STORE: [[THEN1]]:
|
||||
; STORE: [[GEP1:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 1
|
||||
; STORE: [[PGEP1:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP1]] to i64
|
||||
; STORE: call void @__heapprof_store(i64 [[PGEP1]])
|
||||
; STORE: call void @__memprof_store(i64 [[PGEP1]])
|
||||
; STORE: br label %[[AFTER1]]
|
||||
; STORE: [[AFTER1]]:
|
||||
|
||||
|
@ -96,7 +96,7 @@ define void @store.v4f32.variable(<4 x float> %arg, <4 x i1> %mask) {
|
|||
; STORE: [[THEN2]]:
|
||||
; STORE: [[GEP2:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 2
|
||||
; STORE: [[PGEP2:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP2]] to i64
|
||||
; STORE: call void @__heapprof_store(i64 [[PGEP2]])
|
||||
; STORE: call void @__memprof_store(i64 [[PGEP2]])
|
||||
; STORE: br label %[[AFTER2]]
|
||||
; STORE: [[AFTER2]]:
|
||||
|
||||
|
@ -105,7 +105,7 @@ define void @store.v4f32.variable(<4 x float> %arg, <4 x i1> %mask) {
|
|||
; STORE: [[THEN3]]:
|
||||
; STORE: [[GEP3:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 3
|
||||
; STORE: [[PGEP3:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP3]] to i64
|
||||
; STORE: call void @__heapprof_store(i64 [[PGEP3]])
|
||||
; STORE: call void @__memprof_store(i64 [[PGEP3]])
|
||||
; STORE: br label %[[AFTER3]]
|
||||
; STORE: [[AFTER3]]:
|
||||
|
||||
|
@ -120,12 +120,12 @@ define void @store.v4f32.1010.split(<4 x float> %arg) {
|
|||
%p = load <4 x float>*, <4 x float>** @v4f32, align 8
|
||||
; STORE: [[GEP0:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 0
|
||||
; STORE: [[PGEP0:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP0]] to i64
|
||||
; STORE: call void @__heapprof_store(i64 [[PGEP0]])
|
||||
; STORE: call void @__memprof_store(i64 [[PGEP0]])
|
||||
; STORE: tail call void @llvm.masked.store.v4f32.p0v4f32(<4 x float> %arg, <4 x float>* %p, i32 4, <4 x i1> <i1 true, i1 false, i1 false, i1 false>)
|
||||
tail call void @llvm.masked.store.v4f32.p0v4f32(<4 x float> %arg, <4 x float>* %p, i32 4, <4 x i1> <i1 true, i1 false, i1 false, i1 false>)
|
||||
; STORE: [[GEP1:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 2
|
||||
; STORE: [[PGEP1:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP1]] to i64
|
||||
; STORE: call void @__heapprof_store(i64 [[PGEP1]])
|
||||
; STORE: call void @__memprof_store(i64 [[PGEP1]])
|
||||
; STORE: tail call void @llvm.masked.store.v4f32.p0v4f32(<4 x float> %arg, <4 x float>* %p, i32 4, <4 x i1> <i1 false, i1 false, i1 true, i1 false>)
|
||||
tail call void @llvm.masked.store.v4f32.p0v4f32(<4 x float> %arg, <4 x float>* %p, i32 4, <4 x i1> <i1 false, i1 false, i1 true, i1 false>)
|
||||
ret void
|
||||
|
@ -139,19 +139,19 @@ declare <4 x i32*> @llvm.masked.load.v4p0i32.p0v4p0i32(<4 x i32*>*, i32, <4 x i1
|
|||
define <8 x i32> @load.v8i32.11100001(<8 x i32> %arg) {
|
||||
; ALL-LABEL: @load.v8i32.11100001
|
||||
%p = load <8 x i32>*, <8 x i32>** @v8i32, align 8
|
||||
; NOLOAD-NOT: call void @__heapprof_load
|
||||
; NOLOAD-NOT: call void @__memprof_load
|
||||
; LOAD: [[GEP0:%[0-9A-Za-z]+]] = getelementptr <8 x i32>, <8 x i32>* %p, i64 0, i64 0
|
||||
; LOAD: [[PGEP0:%[0-9A-Za-z]+]] = ptrtoint i32* [[GEP0]] to i64
|
||||
; LOAD: call void @__heapprof_load(i64 [[PGEP0]])
|
||||
; LOAD: call void @__memprof_load(i64 [[PGEP0]])
|
||||
; LOAD: [[GEP1:%[0-9A-Za-z]+]] = getelementptr <8 x i32>, <8 x i32>* %p, i64 0, i64 1
|
||||
; LOAD: [[PGEP1:%[0-9A-Za-z]+]] = ptrtoint i32* [[GEP1]] to i64
|
||||
; LOAD: call void @__heapprof_load(i64 [[PGEP1]])
|
||||
; LOAD: call void @__memprof_load(i64 [[PGEP1]])
|
||||
; LOAD: [[GEP2:%[0-9A-Za-z]+]] = getelementptr <8 x i32>, <8 x i32>* %p, i64 0, i64 2
|
||||
; LOAD: [[PGEP2:%[0-9A-Za-z]+]] = ptrtoint i32* [[GEP2]] to i64
|
||||
; LOAD: call void @__heapprof_load(i64 [[PGEP2]])
|
||||
; LOAD: call void @__memprof_load(i64 [[PGEP2]])
|
||||
; LOAD: [[GEP7:%[0-9A-Za-z]+]] = getelementptr <8 x i32>, <8 x i32>* %p, i64 0, i64 7
|
||||
; LOAD: [[PGEP7:%[0-9A-Za-z]+]] = ptrtoint i32* [[GEP7]] to i64
|
||||
; LOAD: call void @__heapprof_load(i64 [[PGEP7]])
|
||||
; LOAD: call void @__memprof_load(i64 [[PGEP7]])
|
||||
; LOAD: tail call <8 x i32> @llvm.masked.load.v8i32.p0v8i32(<8 x i32>* %p, i32 8, <8 x i1> <i1 true, i1 true, i1 true, i1 false, i1 false, i1 false, i1 false, i1 true>, <8 x i32> %arg)
|
||||
%res = tail call <8 x i32> @llvm.masked.load.v8i32.p0v8i32(<8 x i32>* %p, i32 8, <8 x i1> <i1 true, i1 true, i1 true, i1 false, i1 false, i1 false, i1 false, i1 true>, <8 x i32> %arg)
|
||||
ret <8 x i32> %res
|
||||
|
@ -160,13 +160,13 @@ define <8 x i32> @load.v8i32.11100001(<8 x i32> %arg) {
|
|||
define <4 x float> @load.v4f32.1001(<4 x float> %arg) {
|
||||
; ALL-LABEL: @load.v4f32.1001
|
||||
%p = load <4 x float>*, <4 x float>** @v4f32, align 8
|
||||
; NOLOAD-NOT: call void @__heapprof_load
|
||||
; NOLOAD-NOT: call void @__memprof_load
|
||||
; LOAD: [[GEP0:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 0
|
||||
; LOAD: [[PGEP0:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP0]] to i64
|
||||
; LOAD: call void @__heapprof_load(i64 [[PGEP0]])
|
||||
; LOAD: call void @__memprof_load(i64 [[PGEP0]])
|
||||
; LOAD: [[GEP3:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 3
|
||||
; LOAD: [[PGEP3:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP3]] to i64
|
||||
; LOAD: call void @__heapprof_load(i64 [[PGEP3]])
|
||||
; LOAD: call void @__memprof_load(i64 [[PGEP3]])
|
||||
; LOAD: tail call <4 x float> @llvm.masked.load.v4f32.p0v4f32(<4 x float>* %p, i32 4, <4 x i1> <i1 true, i1 false, i1 false, i1 true>, <4 x float> %arg)
|
||||
%res = tail call <4 x float> @llvm.masked.load.v4f32.p0v4f32(<4 x float>* %p, i32 4, <4 x i1> <i1 true, i1 false, i1 false, i1 true>, <4 x float> %arg)
|
||||
ret <4 x float> %res
|
||||
|
@ -175,10 +175,10 @@ define <4 x float> @load.v4f32.1001(<4 x float> %arg) {
|
|||
define <4 x i32*> @load.v4i64.0001(<4 x i32*> %arg) {
|
||||
; ALL-LABEL: @load.v4i64.0001
|
||||
%p = load <4 x i32*>*, <4 x i32*>** @v4i64, align 8
|
||||
; NOLOAD-NOT: call void @__heapprof_load
|
||||
; NOLOAD-NOT: call void @__memprof_load
|
||||
; LOAD: [[GEP3:%[0-9A-Za-z]+]] = getelementptr <4 x i32*>, <4 x i32*>* %p, i64 0, i64 3
|
||||
; LOAD: [[PGEP3:%[0-9A-Za-z]+]] = ptrtoint i32** [[GEP3]] to i64
|
||||
; LOAD: call void @__heapprof_load(i64 [[PGEP3]])
|
||||
; LOAD: call void @__memprof_load(i64 [[PGEP3]])
|
||||
; LOAD: tail call <4 x i32*> @llvm.masked.load.v4p0i32.p0v4p0i32(<4 x i32*>* %p, i32 8, <4 x i1> <i1 false, i1 false, i1 false, i1 true>, <4 x i32*> %arg)
|
||||
%res = tail call <4 x i32*> @llvm.masked.load.v4p0i32.p0v4p0i32(<4 x i32*>* %p, i32 8, <4 x i1> <i1 false, i1 false, i1 false, i1 true>, <4 x i32*> %arg)
|
||||
ret <4 x i32*> %res
|
||||
|
@ -192,7 +192,7 @@ define <4 x float> @load.v4f32.variable(<4 x float> %arg, <4 x i1> %mask) {
|
|||
; LOAD: [[THEN0]]:
|
||||
; LOAD: [[GEP0:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 0
|
||||
; LOAD: [[PGEP0:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP0]] to i64
|
||||
; LOAD: call void @__heapprof_load(i64 [[PGEP0]])
|
||||
; LOAD: call void @__memprof_load(i64 [[PGEP0]])
|
||||
; LOAD: br label %[[AFTER0]]
|
||||
; LOAD: [[AFTER0]]:
|
||||
|
||||
|
@ -201,7 +201,7 @@ define <4 x float> @load.v4f32.variable(<4 x float> %arg, <4 x i1> %mask) {
|
|||
; LOAD: [[THEN1]]:
|
||||
; LOAD: [[GEP1:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 1
|
||||
; LOAD: [[PGEP1:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP1]] to i64
|
||||
; LOAD: call void @__heapprof_load(i64 [[PGEP1]])
|
||||
; LOAD: call void @__memprof_load(i64 [[PGEP1]])
|
||||
; LOAD: br label %[[AFTER1]]
|
||||
; LOAD: [[AFTER1]]:
|
||||
|
||||
|
@ -210,7 +210,7 @@ define <4 x float> @load.v4f32.variable(<4 x float> %arg, <4 x i1> %mask) {
|
|||
; LOAD: [[THEN2]]:
|
||||
; LOAD: [[GEP2:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 2
|
||||
; LOAD: [[PGEP2:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP2]] to i64
|
||||
; LOAD: call void @__heapprof_load(i64 [[PGEP2]])
|
||||
; LOAD: call void @__memprof_load(i64 [[PGEP2]])
|
||||
; LOAD: br label %[[AFTER2]]
|
||||
; LOAD: [[AFTER2]]:
|
||||
|
||||
|
@ -219,7 +219,7 @@ define <4 x float> @load.v4f32.variable(<4 x float> %arg, <4 x i1> %mask) {
|
|||
; LOAD: [[THEN3]]:
|
||||
; LOAD: [[GEP3:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 3
|
||||
; LOAD: [[PGEP3:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP3]] to i64
|
||||
; LOAD: call void @__heapprof_load(i64 [[PGEP3]])
|
||||
; LOAD: call void @__memprof_load(i64 [[PGEP3]])
|
||||
; LOAD: br label %[[AFTER3]]
|
||||
; LOAD: [[AFTER3]]:
|
||||
|
||||
|
@ -234,12 +234,12 @@ define <4 x float> @load.v4f32.1001.split(<4 x float> %arg) {
|
|||
%p = load <4 x float>*, <4 x float>** @v4f32, align 8
|
||||
; LOAD: [[GEP0:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 0
|
||||
; LOAD: [[PGEP0:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP0]] to i64
|
||||
; LOAD: call void @__heapprof_load(i64 [[PGEP0]])
|
||||
; LOAD: call void @__memprof_load(i64 [[PGEP0]])
|
||||
; LOAD: %res = tail call <4 x float> @llvm.masked.load.v4f32.p0v4f32(<4 x float>* %p, i32 4, <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x float> %arg)
|
||||
%res = tail call <4 x float> @llvm.masked.load.v4f32.p0v4f32(<4 x float>* %p, i32 4, <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x float> %arg)
|
||||
; LOAD: [[GEP3:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 3
|
||||
; LOAD: [[PGEP3:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP3]] to i64
|
||||
; LOAD: call void @__heapprof_load(i64 [[PGEP3]])
|
||||
; LOAD: call void @__memprof_load(i64 [[PGEP3]])
|
||||
; LOAD: tail call <4 x float> @llvm.masked.load.v4f32.p0v4f32(<4 x float>* %p, i32 4, <4 x i1> <i1 false, i1 false, i1 false, i1 true>, <4 x float> %res)
|
||||
%res2 = tail call <4 x float> @llvm.masked.load.v4f32.p0v4f32(<4 x float>* %p, i32 4, <4 x i1> <i1 false, i1 false, i1 false, i1 true>, <4 x float> %res)
|
||||
ret <4 x float> %res2
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
; Test that the scale (-heapprof-mapping-scale) and granularity (-heapprof-mapping-granularity) command-line options work as expected
|
||||
; Test that the scale (-memprof-mapping-scale) and granularity (-memprof-mapping-granularity) command-line options work as expected
|
||||
;
|
||||
; RUN: opt < %s -heapprof -heapprof-module -heapprof-mapping-granularity 32 -S | FileCheck --check-prefix=CHECK-GRAN %s
|
||||
; RUN: opt < %s -heapprof -heapprof-module -heapprof-mapping-scale 1 -S | FileCheck --check-prefix=CHECK-SCALE %s
|
||||
; RUN: opt < %s -heapprof -heapprof-module -heapprof-mapping-granularity 16 -heapprof-mapping-scale 0 -S | FileCheck --check-prefix=CHECK-BOTH %s
|
||||
; RUN: opt < %s -memprof -memprof-module -memprof-mapping-granularity 32 -S | FileCheck --check-prefix=CHECK-GRAN %s
|
||||
; RUN: opt < %s -memprof -memprof-module -memprof-mapping-scale 1 -S | FileCheck --check-prefix=CHECK-SCALE %s
|
||||
; RUN: opt < %s -memprof -memprof-module -memprof-mapping-granularity 16 -memprof-mapping-scale 0 -S | FileCheck --check-prefix=CHECK-BOTH %s
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
define i32 @read(i32* %a) {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
; Check that the HeapProf module constructor guards against compiler/runtime version
|
||||
; Check that the MemProf module constructor guards against compiler/runtime version
|
||||
; mismatch.
|
||||
|
||||
; RUN: opt < %s -heapprof-module -S | FileCheck %s
|
||||
; RUN: opt < %s -heapprof-module -heapprof-guard-against-version-mismatch=0 -S | FileCheck %s --check-prefix=NOGUARD
|
||||
; RUN: opt < %s -memprof-module -S | FileCheck %s
|
||||
; RUN: opt < %s -memprof-module -memprof-guard-against-version-mismatch=0 -S | FileCheck %s --check-prefix=NOGUARD
|
||||
|
||||
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
; CHECK-LABEL: define internal void @heapprof.module_ctor()
|
||||
; CHECK: call void @__heapprof_version_mismatch_check_v1
|
||||
; NOGUARD-NOT: call void @__heapprof_version_mismatch_check_
|
||||
; CHECK-LABEL: define internal void @memprof.module_ctor()
|
||||
; CHECK: call void @__memprof_version_mismatch_check_v1
|
||||
; NOGUARD-NOT: call void @__memprof_version_mismatch_check_
|
||||
|
|
Loading…
Reference in New Issue