diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -231,6 +231,9 @@ /// 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/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -151,7 +151,6 @@ ///< 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/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1017,6 +1017,9 @@ 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 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -687,7 +687,7 @@ 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 @@ 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 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -607,6 +607,13 @@ !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 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -868,6 +868,7 @@ 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 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4309,9 +4309,12 @@ 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 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1038,7 +1038,15 @@ 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 --- /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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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 --- a/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp @@ -60,6 +60,8 @@ 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 @@ 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 @@ 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 --- /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