From 0949f96dc6521be80ebb8ebc1e1c506165c22aac Mon Sep 17 00:00:00 2001 From: Teresa Johnson Date: Tue, 29 Sep 2020 15:53:41 -0700 Subject: [PATCH] [MemProf] Pass down memory profile name with optional path from clang Similar to -fprofile-generate=, add -fmemory-profile= which takes a directory path. This is passed down to LLVM via a new module flag metadata. LLVM in turn provides this name to the runtime via the new __memprof_profile_filename variable. Additionally, always pass a default filename (in $cwd if a directory name is not specified vi the = form of the option). This is also consistent with the behavior of the PGO instrumentation. Since the memory profiles will generally be fairly large, it doesn't make sense to dump them to stderr. Also, importantly, the memory profiles will eventually be dumped in a compact binary format, which is another reason why it does not make sense to send these to stderr by default. Change the existing memprof tests to specify log_path=stderr when that was being relied on. Depends on D89086. Differential Revision: https://reviews.llvm.org/D89087 --- clang/include/clang/Basic/CodeGenOptions.def | 1 - clang/include/clang/Basic/CodeGenOptions.h | 3 +++ clang/include/clang/Driver/Options.td | 3 +++ clang/lib/CodeGen/BackendUtil.cpp | 4 ++-- clang/lib/CodeGen/CodeGenModule.cpp | 7 +++++++ clang/lib/Driver/SanitizerArgs.cpp | 1 + clang/lib/Driver/ToolChains/Clang.cpp | 9 +++++--- clang/lib/Frontend/CompilerInvocation.cpp | 10 ++++++++- clang/test/CodeGen/memory-profile-filename.c | 12 +++++++++++ clang/test/Driver/fmemprof.cpp | 4 ++++ .../test/memprof/TestCases/atexit_stats.cpp | 4 ++-- .../test/memprof/TestCases/dump_process_map.cpp | 4 ++-- .../test/memprof/TestCases/log_path_test.cpp | 4 ++-- .../test/memprof/TestCases/malloc-size-too-big.cpp | 6 +++--- .../memprof/TestCases/mem_info_cache_entries.cpp | 2 +- .../test/memprof/TestCases/print_miss_rate.cpp | 4 ++-- compiler-rt/test/memprof/TestCases/stress_dtls.c | 6 +++--- .../memprof/TestCases/test_malloc_load_store.c | 4 ++-- .../test/memprof/TestCases/test_memintrin.cpp | 2 +- .../test/memprof/TestCases/test_new_load_store.cpp | 6 +++--- compiler-rt/test/memprof/TestCases/test_terse.cpp | 4 ++-- .../TestCases/unaligned_loads_and_stores.cpp | 2 +- .../lib/Transforms/Instrumentation/MemProfiler.cpp | 24 ++++++++++++++++++++++ llvm/test/Instrumentation/HeapProfiler/filename.ll | 15 ++++++++++++++ 24 files changed, 110 insertions(+), 31 deletions(-) create mode 100644 clang/test/CodeGen/memory-profile-filename.c create mode 100644 llvm/test/Instrumentation/HeapProfiler/filename.ll diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index f5222b5..7cd80aa 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -151,7 +151,6 @@ 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(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 diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 764d0a1..6452d2b 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -231,6 +231,9 @@ public: /// Name of the profile file to use with -fprofile-sample-use. std::string SampleProfileFile; + /// Name of the profile file to use as output for with -fmemory-profile. + std::string MemoryProfileOutput; + /// Name of the profile file to use as input for -fprofile-instr-use std::string ProfileInstrumentUsePath; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 0f74408..165baf0 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1017,6 +1017,9 @@ def fsymbol_partition_EQ : Joined<["-"], "fsymbol-partition=">, Group, Flags<[CC1Option]>; defm memory_profile : OptInFFlag<"memory-profile", "Enable", "Disable", " heap memory profiling">; +def fmemory_profile_EQ : Joined<["-"], "fmemory-profile=">, + Group, Flags<[CC1Option]>, MetaVarName<"">, + HelpText<"Enable heap memory profiling and dump results into ">; // Begin sanitizer flags. These should all be core options exposed in all driver // modes. diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index e693d6d..1c10681 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -687,7 +687,7 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM, if (LangOpts.Coroutines) addCoroutinePassesToExtensionPoints(PMBuilder); - if (CodeGenOpts.MemProf) { + if (!CodeGenOpts.MemoryProfileOutput.empty()) { PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, addMemProfilerPasses); PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, @@ -1421,7 +1421,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( if (CodeGenOpts.UniqueInternalLinkageNames) MPM.addPass(UniqueInternalLinkageNamesPass()); - if (CodeGenOpts.MemProf) { + if (!CodeGenOpts.MemoryProfileOutput.empty()) { MPM.addPass(createModuleToFunctionPassAdaptor(MemProfilerPass())); MPM.addPass(ModuleMemProfilerPass()); } diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 2a7fb4f..66a3c57 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -607,6 +607,13 @@ void CodeGenModule::Release() { !LangOpts.isSignReturnAddressWithAKey()); } + if (!CodeGenOpts.MemoryProfileOutput.empty()) { + llvm::LLVMContext &Ctx = TheModule.getContext(); + getModule().addModuleFlag( + llvm::Module::Error, "MemProfProfileFilename", + llvm::MDString::get(Ctx, CodeGenOpts.MemoryProfileOutput)); + } + if (LangOpts.CUDAIsDevice && getTriple().isNVPTX()) { // Indicate whether __nvvm_reflect should be configured to flush denormal // floating point values to 0. (This corresponds to its "__CUDA_FTZ" diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 68ae25e..5c27535 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -868,6 +868,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, D.CCCIsCXX(); NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile, + options::OPT_fmemory_profile_EQ, options::OPT_fno_memory_profile, false); // Finally, initialize the set of available and recoverable sanitizers. diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index a15067b..53d2709 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4309,9 +4309,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.getLastArg(options::OPT_save_temps_EQ)) Args.AddLastArg(CmdArgs, options::OPT_save_temps_EQ); - if (Args.hasFlag(options::OPT_fmemory_profile, - options::OPT_fno_memory_profile, false)) - Args.AddLastArg(CmdArgs, options::OPT_fmemory_profile); + auto *MemProfArg = Args.getLastArg(options::OPT_fmemory_profile, + options::OPT_fmemory_profile_EQ, + options::OPT_fno_memory_profile); + if (MemProfArg && + !MemProfArg->getOption().matches(options::OPT_fno_memory_profile)) + MemProfArg->render(Args, CmdArgs); // Embed-bitcode option. // Only white-listed flags below are allowed to be embedded. diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 2257916..3c0ba31 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1038,7 +1038,15 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.ThinLinkBitcodeFile = std::string(Args.getLastArgValue(OPT_fthin_link_bitcode_EQ)); - Opts.MemProf = Args.hasArg(OPT_fmemory_profile); + // The memory profile runtime appends the pid to make this name more unique. + const char *MemProfileBasename = "memprof.profraw"; + if (Args.hasArg(OPT_fmemory_profile_EQ)) { + SmallString<128> Path( + std::string(Args.getLastArgValue(OPT_fmemory_profile_EQ))); + llvm::sys::path::append(Path, MemProfileBasename); + Opts.MemoryProfileOutput = std::string(Path); + } else if (Args.hasArg(OPT_fmemory_profile)) + Opts.MemoryProfileOutput = MemProfileBasename; Opts.MSVolatile = Args.hasArg(OPT_fms_volatile); diff --git a/clang/test/CodeGen/memory-profile-filename.c b/clang/test/CodeGen/memory-profile-filename.c new file mode 100644 index 0000000..0041aca --- /dev/null +++ b/clang/test/CodeGen/memory-profile-filename.c @@ -0,0 +1,12 @@ +// Test that we get the expected module flag metadata for the memory profile +// filename. +// RUN: %clang -target x86_64-linux-gnu -S -emit-llvm -o - %s | FileCheck %s --check-prefix=NONE +// RUN: %clang -target x86_64-linux-gnu -fmemory-profile -S -emit-llvm -o - %s | FileCheck %s --check-prefix=DEFAULTNAME +// RUN: %clang -target x86_64-linux-gnu -fmemory-profile=/tmp -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CUSTOMNAME +int main(void) { + return 0; +} + +// NONE-NOT: MemProfProfileFilename +// DEFAULTNAME: !{i32 1, !"MemProfProfileFilename", !"memprof.profraw"} +// CUSTOMNAME: !{i32 1, !"MemProfProfileFilename", !"/tmp/memprof.profraw"} diff --git a/clang/test/Driver/fmemprof.cpp b/clang/test/Driver/fmemprof.cpp index 6968644..8879580 100644 --- a/clang/test/Driver/fmemprof.cpp +++ b/clang/test/Driver/fmemprof.cpp @@ -1,6 +1,10 @@ // RUN: %clangxx -target x86_64-linux-gnu -fmemory-profile %s -### 2>&1 | FileCheck %s +// RUN: %clangxx -target x86_64-linux-gnu -fmemory-profile=foo %s -### 2>&1 | FileCheck %s --check-prefix=DIR // RUN: %clangxx -target x86_64-linux-gnu -fmemory-profile -fno-memory-profile %s -### 2>&1 | FileCheck %s --check-prefix=OFF +// RUN: %clangxx -target x86_64-linux-gnu -fmemory-profile=foo -fno-memory-profile %s -### 2>&1 | FileCheck %s --check-prefix=OFF // CHECK: "-cc1" {{.*}} "-fmemory-profile" // CHECK: ld{{.*}}libclang_rt.memprof{{.*}}libclang_rt.memprof_cxx +// DIR: "-cc1" {{.*}} "-fmemory-profile=foo" +// DIR: ld{{.*}}libclang_rt.memprof{{.*}}libclang_rt.memprof_cxx // OFF-NOT: "-fmemory-profile" // OFF-NOT: libclang_rt.memprof diff --git a/compiler-rt/test/memprof/TestCases/atexit_stats.cpp b/compiler-rt/test/memprof/TestCases/atexit_stats.cpp index 0f21ae3..e5b271b 100644 --- a/compiler-rt/test/memprof/TestCases/atexit_stats.cpp +++ b/compiler-rt/test/memprof/TestCases/atexit_stats.cpp @@ -1,8 +1,8 @@ // Check atexit option. // RUN: %clangxx_memprof -O0 %s -o %t -// RUN: %env_memprof_opts=atexit=1 %run %t 2>&1 | FileCheck %s -// RUN: %env_memprof_opts=atexit=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOATEXIT +// RUN: %env_memprof_opts=log_path=stderr:atexit=1 %run %t 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr:atexit=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOATEXIT // CHECK: MemProfiler exit stats: // CHECK: Stats: {{[0-9]+}}M malloced ({{[0-9]+}}M for overhead) by {{[0-9]+}} calls diff --git a/compiler-rt/test/memprof/TestCases/dump_process_map.cpp b/compiler-rt/test/memprof/TestCases/dump_process_map.cpp index 2b9e98a..a6adb2f6 100644 --- a/compiler-rt/test/memprof/TestCases/dump_process_map.cpp +++ b/compiler-rt/test/memprof/TestCases/dump_process_map.cpp @@ -1,8 +1,8 @@ // Check print_module_map option. // RUN: %clangxx_memprof -O0 %s -o %t -// RUN: %env_memprof_opts=print_module_map=1 %run %t 2>&1 | FileCheck %s -// RUN: %env_memprof_opts=print_module_map=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOMAP +// RUN: %env_memprof_opts=log_path=stderr:print_module_map=1 %run %t 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr:print_module_map=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOMAP // CHECK: Process memory map follows: // CHECK: dump_process_map.cpp.tmp diff --git a/compiler-rt/test/memprof/TestCases/log_path_test.cpp b/compiler-rt/test/memprof/TestCases/log_path_test.cpp index 92d194be..298c182 100644 --- a/compiler-rt/test/memprof/TestCases/log_path_test.cpp +++ b/compiler-rt/test/memprof/TestCases/log_path_test.cpp @@ -3,8 +3,8 @@ // // RUN: %clangxx_memprof %s -o %t -// Regular run. -// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-GOOD --dump-input=always +// stderr log_path +// RUN: %env_memprof_opts=log_path=stderr %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-GOOD --dump-input=always // Good log_path. // RUN: rm -f %t.log.* diff --git a/compiler-rt/test/memprof/TestCases/malloc-size-too-big.cpp b/compiler-rt/test/memprof/TestCases/malloc-size-too-big.cpp index 3831d42..1bcde5a 100644 --- a/compiler-rt/test/memprof/TestCases/malloc-size-too-big.cpp +++ b/compiler-rt/test/memprof/TestCases/malloc-size-too-big.cpp @@ -1,8 +1,8 @@ // RUN: %clangxx_memprof -O0 %s -o %t -// RUN: %env_memprof_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-SUMMARY -// RUN: %env_memprof_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL +// RUN: %env_memprof_opts=log_path=stderr:allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-SUMMARY +// RUN: %env_memprof_opts=log_path=stderr:allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL // Test print_summary -// RUN: %env_memprof_opts=allocator_may_return_null=0:print_summary=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOSUMMARY +// RUN: %env_memprof_opts=log_path=stderr:allocator_may_return_null=0:print_summary=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOSUMMARY #include #include diff --git a/compiler-rt/test/memprof/TestCases/mem_info_cache_entries.cpp b/compiler-rt/test/memprof/TestCases/mem_info_cache_entries.cpp index 54c416b..c253855 100644 --- a/compiler-rt/test/memprof/TestCases/mem_info_cache_entries.cpp +++ b/compiler-rt/test/memprof/TestCases/mem_info_cache_entries.cpp @@ -1,6 +1,6 @@ // Check mem_info_cache_entries option. -// RUN: %clangxx_memprof -O0 %s -o %t && %env_memprof_opts=mem_info_cache_entries=15:print_mem_info_cache_miss_rate=1:print_mem_info_cache_miss_rate_details=1 %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_memprof -O0 %s -o %t && %env_memprof_opts=log_path=stderr:mem_info_cache_entries=15:print_mem_info_cache_miss_rate=1:print_mem_info_cache_miss_rate_details=1 %run %t 2>&1 | FileCheck %s // CHECK: Set 14 miss rate: 0 / {{.*}} = 0.00% // CHECK-NOT: Set diff --git a/compiler-rt/test/memprof/TestCases/print_miss_rate.cpp b/compiler-rt/test/memprof/TestCases/print_miss_rate.cpp index c319a48..e32a0de 100644 --- a/compiler-rt/test/memprof/TestCases/print_miss_rate.cpp +++ b/compiler-rt/test/memprof/TestCases/print_miss_rate.cpp @@ -2,8 +2,8 @@ // print_mem_info_cache_miss_rate_details options. // RUN: %clangxx_memprof -O0 %s -o %t -// RUN: %env_memprof_opts=print_mem_info_cache_miss_rate=1 %run %t 2>&1 | FileCheck %s -// RUN: %env_memprof_opts=print_mem_info_cache_miss_rate=1:print_mem_info_cache_miss_rate_details=1 %run %t 2>&1 | FileCheck %s --check-prefix=DETAILS +// RUN: %env_memprof_opts=log_path=stderr:print_mem_info_cache_miss_rate=1 %run %t 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr:print_mem_info_cache_miss_rate=1:print_mem_info_cache_miss_rate_details=1 %run %t 2>&1 | FileCheck %s --check-prefix=DETAILS // CHECK: Overall miss rate: 0 / {{.*}} = 0.00% // DETAILS: Set 0 miss rate: 0 / {{.*}} = 0.00% diff --git a/compiler-rt/test/memprof/TestCases/stress_dtls.c b/compiler-rt/test/memprof/TestCases/stress_dtls.c index c248ebe..bf5a858 100644 --- a/compiler-rt/test/memprof/TestCases/stress_dtls.c +++ b/compiler-rt/test/memprof/TestCases/stress_dtls.c @@ -7,9 +7,9 @@ // RUN: %clangxx_memprof %s -ldl -pthread -o %t // RUN: %run %t 0 3 // RUN: %run %t 2 3 -// RUN: %env_memprof_opts=verbosity=2 %run %t 10 2 2>&1 | FileCheck %s -// RUN: %env_memprof_opts=verbosity=2:intercept_tls_get_addr=1 %run %t 10 2 2>&1 | FileCheck %s -// RUN: %env_memprof_opts=verbosity=2:intercept_tls_get_addr=0 %run %t 10 2 2>&1 | FileCheck %s --check-prefix=CHECK0 +// RUN: %env_memprof_opts=log_path=stderr:verbosity=2 %run %t 10 2 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr:verbosity=2:intercept_tls_get_addr=1 %run %t 10 2 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr:verbosity=2:intercept_tls_get_addr=0 %run %t 10 2 2>&1 | FileCheck %s --check-prefix=CHECK0 // CHECK: __tls_get_addr // CHECK: Creating thread 0 // CHECK: __tls_get_addr diff --git a/compiler-rt/test/memprof/TestCases/test_malloc_load_store.c b/compiler-rt/test/memprof/TestCases/test_malloc_load_store.c index 61c2b42..7db1ad7 100644 --- a/compiler-rt/test/memprof/TestCases/test_malloc_load_store.c +++ b/compiler-rt/test/memprof/TestCases/test_malloc_load_store.c @@ -3,10 +3,10 @@ // before exit. // RUN: %clangxx_memprof -O0 %s -o %t -// RUN: %env_memprof_opts= %run %t 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr %run %t 2>&1 | FileCheck %s // RUN: %clangxx_memprof -DFREE -O0 %s -o %t -// RUN: %env_memprof_opts= %run %t 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr %run %t 2>&1 | FileCheck %s // This is actually: // Memory allocation stack id = STACKID diff --git a/compiler-rt/test/memprof/TestCases/test_memintrin.cpp b/compiler-rt/test/memprof/TestCases/test_memintrin.cpp index 199aa4a..005bc87 100644 --- a/compiler-rt/test/memprof/TestCases/test_memintrin.cpp +++ b/compiler-rt/test/memprof/TestCases/test_memintrin.cpp @@ -1,6 +1,6 @@ // Check profile with calls to memory intrinsics. -// RUN: %clangxx_memprof -O0 %s -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_memprof -O0 %s -o %t && %env_memprof_opts=log_path=stderr %run %t 2>&1 | FileCheck %s // This is actually: // Memory allocation stack id = STACKIDP diff --git a/compiler-rt/test/memprof/TestCases/test_new_load_store.cpp b/compiler-rt/test/memprof/TestCases/test_new_load_store.cpp index d3cb300..9ef3313 100644 --- a/compiler-rt/test/memprof/TestCases/test_new_load_store.cpp +++ b/compiler-rt/test/memprof/TestCases/test_new_load_store.cpp @@ -3,14 +3,14 @@ // before exit. // RUN: %clangxx_memprof -O0 %s -o %t -// RUN: %env_memprof_opts= %run %t 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr %run %t 2>&1 | FileCheck %s // RUN: %clangxx_memprof -DFREE -O0 %s -o %t -// RUN: %env_memprof_opts= %run %t 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr %run %t 2>&1 | FileCheck %s // Try again with callbacks instead of inline sequences // RUN: %clangxx_memprof -mllvm -memprof-use-callbacks -O0 %s -o %t -// RUN: %env_memprof_opts= %run %t 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr %run %t 2>&1 | FileCheck %s // This is actually: // Memory allocation stack id = STACKID diff --git a/compiler-rt/test/memprof/TestCases/test_terse.cpp b/compiler-rt/test/memprof/TestCases/test_terse.cpp index 750b49e..4ac0d5e 100644 --- a/compiler-rt/test/memprof/TestCases/test_terse.cpp +++ b/compiler-rt/test/memprof/TestCases/test_terse.cpp @@ -3,10 +3,10 @@ // deallocated before exit. // RUN: %clangxx_memprof -O0 %s -o %t -// RUN: %env_memprof_opts=print_terse=1 %run %t 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr:print_terse=1 %run %t 2>&1 | FileCheck %s // RUN: %clangxx_memprof -DFREE -O0 %s -o %t -// RUN: %env_memprof_opts=print_terse=1 %run %t 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr:print_terse=1 %run %t 2>&1 | FileCheck %s // CHECK: MIB:[[STACKID:[0-9]+]]/1/40.00/40/40/20.00/20/20/[[AVELIFETIME:[0-9]+]].00/[[AVELIFETIME]]/[[AVELIFETIME]]/0/0/0/0 // CHECK: Stack for id [[STACKID]]: diff --git a/compiler-rt/test/memprof/TestCases/unaligned_loads_and_stores.cpp b/compiler-rt/test/memprof/TestCases/unaligned_loads_and_stores.cpp index 1d25ddf..c007b43 100644 --- a/compiler-rt/test/memprof/TestCases/unaligned_loads_and_stores.cpp +++ b/compiler-rt/test/memprof/TestCases/unaligned_loads_and_stores.cpp @@ -1,4 +1,4 @@ -// RUN: %clangxx_memprof -O0 %s -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_memprof -O0 %s -o %t && %env_memprof_opts=log_path=stderr %run %t 2>&1 | FileCheck %s // This is actually: // Memory allocation stack id = STACKID diff --git a/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp b/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp index 7f2a5ae..32fd11a 100644 --- a/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp @@ -60,6 +60,8 @@ constexpr char MemProfVersionCheckNamePrefix[] = constexpr char MemProfShadowMemoryDynamicAddress[] = "__memprof_shadow_memory_dynamic_address"; +constexpr char MemProfFilenameVar[] = "__memprof_profile_filename"; + // Command-line flags. static cl::opt ClInsertVersionCheck( @@ -486,6 +488,26 @@ void MemProfiler::instrumentAddress(Instruction *OrigIns, IRB.CreateStore(ShadowValue, ShadowAddr); } +// Create the variable for the profile file name. +void createProfileFileNameVar(Module &M) { + const MDString *MemProfFilename = + dyn_cast_or_null(M.getModuleFlag("MemProfProfileFilename")); + if (!MemProfFilename) + return; + assert(!MemProfFilename->getString().empty() && + "Unexpected MemProfProfileFilename metadata with empty string"); + Constant *ProfileNameConst = ConstantDataArray::getString( + M.getContext(), MemProfFilename->getString(), true); + GlobalVariable *ProfileNameVar = new GlobalVariable( + M, ProfileNameConst->getType(), /*isConstant=*/true, + GlobalValue::WeakAnyLinkage, ProfileNameConst, MemProfFilenameVar); + Triple TT(M.getTargetTriple()); + if (TT.supportsCOMDAT()) { + ProfileNameVar->setLinkage(GlobalValue::ExternalLinkage); + ProfileNameVar->setComdat(M.getOrInsertComdat(MemProfFilenameVar)); + } +} + bool ModuleMemProfiler::instrumentModule(Module &M) { // Create a module constructor. std::string MemProfVersion = std::to_string(LLVM_MEM_PROFILER_VERSION); @@ -500,6 +522,8 @@ bool ModuleMemProfiler::instrumentModule(Module &M) { const uint64_t Priority = getCtorAndDtorPriority(TargetTriple); appendToGlobalCtors(M, MemProfCtorFunction, Priority); + createProfileFileNameVar(M); + return true; } diff --git a/llvm/test/Instrumentation/HeapProfiler/filename.ll b/llvm/test/Instrumentation/HeapProfiler/filename.ll new file mode 100644 index 0000000..f019a94 --- /dev/null +++ b/llvm/test/Instrumentation/HeapProfiler/filename.ll @@ -0,0 +1,15 @@ +; Test to ensure that the filename provided by clang in the module flags +; metadata results in the expected __memprof_profile_filename insertion. + +; RUN: opt < %s -mtriple=x86_64-unknown-linux -memprof -memprof-module -S | FileCheck --check-prefixes=CHECK %s + +define i32 @main() { +entry: + ret i32 0 +} + +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"MemProfProfileFilename", !"/tmp/memprof.profraw"} + +; CHECK: $__memprof_profile_filename = comdat any +; CHECK: @__memprof_profile_filename = constant [21 x i8] c"/tmp/memprof.profraw\00", comdat -- 2.7.4