[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:
Teresa Johnson 2020-09-14 09:12:13 -07:00
parent becf155275
commit 226d80ebe2
20 changed files with 283 additions and 285 deletions

View File

@ -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

View File

@ -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);

View File

@ -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)) {

View File

@ -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;

View File

@ -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()) {

View File

@ -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);

View File

@ -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

View File

@ -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&);

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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_