[compiler-rt] [llvm] [memprof] Use -memprof-default-options to set options during compile time (PR #118874)

Ellis Hoag via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 5 16:26:30 PST 2024


https://github.com/ellishg updated https://github.com/llvm/llvm-project/pull/118874

>From e6325694dad3cdc0a0659426fbf055105b1b1ae9 Mon Sep 17 00:00:00 2001
From: Ellis Hoag <ellis.sparky.hoag at gmail.com>
Date: Thu, 5 Dec 2024 13:18:39 -0800
Subject: [PATCH 1/3] [MemProf] Add __memprof_default_options_str to set
 options during compiletime

---
 .../include/sanitizer/memprof_interface.h     |  6 +++---
 compiler-rt/lib/memprof/memprof_flags.cpp     |  2 +-
 compiler-rt/lib/memprof/memprof_flags.h       | 16 +++++++-------
 .../lib/memprof/memprof_interface_internal.h  |  3 +++
 compiler-rt/lib/memprof/memprof_rtl.cpp       |  2 ++
 compiler-rt/lib/memprof/weak_symbols.txt      |  2 +-
 .../test/memprof/TestCases/set_options.cpp    | 16 ++++++++++++++
 .../Instrumentation/MemProfiler.cpp           | 21 +++++++++++++++++++
 .../HeapProfiler/memprof-options.ll           | 11 ++++++++++
 9 files changed, 67 insertions(+), 12 deletions(-)
 create mode 100644 compiler-rt/test/memprof/TestCases/set_options.cpp
 create mode 100644 llvm/test/Instrumentation/HeapProfiler/memprof-options.ll

diff --git a/compiler-rt/include/sanitizer/memprof_interface.h b/compiler-rt/include/sanitizer/memprof_interface.h
index 4660a7818c92b3..cdb65084b50200 100644
--- a/compiler-rt/include/sanitizer/memprof_interface.h
+++ b/compiler-rt/include/sanitizer/memprof_interface.h
@@ -47,9 +47,9 @@ void SANITIZER_CDECL __memprof_print_accumulated_stats(void);
 
 /// User-provided default option settings.
 ///
-/// You can provide your own implementation of this function to return a string
-/// containing MemProf runtime options (for example,
-/// <c>verbosity=1:print_stats=1</c>).
+/// You can set these options via the -memprof-default-options LLVM flag or
+/// you can provide your own implementation of this function. See
+/// memprof_flags.h for more info.
 ///
 /// \returns Default options string.
 const char *SANITIZER_CDECL __memprof_default_options(void);
diff --git a/compiler-rt/lib/memprof/memprof_flags.cpp b/compiler-rt/lib/memprof/memprof_flags.cpp
index b107ff8fa0a7ca..95fde9d9672d68 100644
--- a/compiler-rt/lib/memprof/memprof_flags.cpp
+++ b/compiler-rt/lib/memprof/memprof_flags.cpp
@@ -89,5 +89,5 @@ void InitializeFlags() {
 } // namespace __memprof
 
 SANITIZER_INTERFACE_WEAK_DEF(const char *, __memprof_default_options, void) {
-  return "";
+  return __memprof_default_options_str;
 }
diff --git a/compiler-rt/lib/memprof/memprof_flags.h b/compiler-rt/lib/memprof/memprof_flags.h
index 2f2b628653dc19..ee1b7b3bcad921 100644
--- a/compiler-rt/lib/memprof/memprof_flags.h
+++ b/compiler-rt/lib/memprof/memprof_flags.h
@@ -17,13 +17,15 @@
 #include "sanitizer_common/sanitizer_flag_parser.h"
 #include "sanitizer_common/sanitizer_internal_defs.h"
 
-// MemProf flag values can be defined in four ways:
-// 1) initialized with default values at startup.
-// 2) overriden during compilation of MemProf runtime by providing
-//    compile definition MEMPROF_DEFAULT_OPTIONS.
-// 3) overriden from string returned by user-specified function
-//    __memprof_default_options().
-// 4) overriden from env variable MEMPROF_OPTIONS.
+// Default MemProf flags are defined in memprof_flags.inc and sancov_flags.inc.
+// These values can be overridded in a number of ways, each option overrides the
+// prior one:
+//  1) by setting MEMPROF_DEFAULT_OPTIONS during the compilation of the MemProf
+//     runtime
+//  2) by setting the LLVM flag -memprof-default-options during the compilation
+//     of your binary
+//  3) by overriding the user-specified function __memprof_default_options()
+//  4) by setting the environment variable MEMPROF_OPTIONS during runtime
 
 namespace __memprof {
 
diff --git a/compiler-rt/lib/memprof/memprof_interface_internal.h b/compiler-rt/lib/memprof/memprof_interface_internal.h
index 318bc410440562..7d3a937814a34b 100644
--- a/compiler-rt/lib/memprof/memprof_interface_internal.h
+++ b/compiler-rt/lib/memprof/memprof_interface_internal.h
@@ -40,6 +40,9 @@ void __memprof_record_access_range(void const volatile *addr, uptr size);
 
 SANITIZER_INTERFACE_ATTRIBUTE void __memprof_print_accumulated_stats();
 
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE extern char
+    __memprof_default_options_str[1];
+
 SANITIZER_INTERFACE_ATTRIBUTE
 const char *__memprof_default_options();
 
diff --git a/compiler-rt/lib/memprof/memprof_rtl.cpp b/compiler-rt/lib/memprof/memprof_rtl.cpp
index 2cc6c2df5a6fe4..ef8884a7e56f40 100644
--- a/compiler-rt/lib/memprof/memprof_rtl.cpp
+++ b/compiler-rt/lib/memprof/memprof_rtl.cpp
@@ -27,6 +27,8 @@
 
 #include <time.h>
 
+SANITIZER_WEAK_ATTRIBUTE char __memprof_default_options_str[1];
+
 uptr __memprof_shadow_memory_dynamic_address; // Global interface symbol.
 
 // Allow the user to specify a profile output file via the binary.
diff --git a/compiler-rt/lib/memprof/weak_symbols.txt b/compiler-rt/lib/memprof/weak_symbols.txt
index 271813612ab604..bfece89e2e1579 100644
--- a/compiler-rt/lib/memprof/weak_symbols.txt
+++ b/compiler-rt/lib/memprof/weak_symbols.txt
@@ -1 +1 @@
-___memprof_default_options __memprof_profile_filename
+___memprof_default_options_str ___memprof_default_options __memprof_profile_filename
diff --git a/compiler-rt/test/memprof/TestCases/set_options.cpp b/compiler-rt/test/memprof/TestCases/set_options.cpp
new file mode 100644
index 00000000000000..00f3d606de911c
--- /dev/null
+++ b/compiler-rt/test/memprof/TestCases/set_options.cpp
@@ -0,0 +1,16 @@
+// RUN: %clangxx_memprof %s -o %t-default
+// RUN: %run %t-default | FileCheck %s --check-prefix=DEFAULT
+
+// RUN: %clangxx_memprof %s -mllvm -memprof-default-options="print_text=true,log_path=stdout,atexit=false" -o %t
+// RUN: %run %t | FileCheck %s
+
+#include <sanitizer/memprof_interface.h>
+#include <stdio.h>
+
+int main() {
+  printf("Options: \"%s\"\n", __memprof_default_options());
+  return 0;
+}
+
+// DEFAULT: Options: ""
+// CHECK: Options: "print_text=true,log_path=stdout,atexit=false"
diff --git a/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp b/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp
index 33a7a37fa28e65..6e17a16a46a9e9 100644
--- a/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp
@@ -166,6 +166,11 @@ static cl::opt<bool>
                                      "context in this module's profiles"),
                             cl::Hidden, cl::init(false));
 
+static cl::opt<std::string>
+    MemprofDefaultOptions("memprof-default-options",
+                          cl::desc("The default memprof options"), cl::Hidden,
+                          cl::init(""));
+
 extern cl::opt<bool> MemProfReportHintedSizes;
 
 // Instrumentation statistics
@@ -547,6 +552,20 @@ void createMemprofHistogramFlagVar(Module &M) {
   appendToCompilerUsed(M, MemprofHistogramFlag);
 }
 
+void createMemprofDefaultOptionsVar(Module &M) {
+  Constant *OptionsConst = ConstantDataArray::getString(
+      M.getContext(), MemprofDefaultOptions, /*AddNull=*/true);
+  GlobalVariable *OptionsVar =
+      new GlobalVariable(M, OptionsConst->getType(), /*isConstant=*/true,
+                         GlobalValue::WeakAnyLinkage, OptionsConst,
+                         "__memprof_default_options_str");
+  Triple TT(M.getTargetTriple());
+  if (TT.supportsCOMDAT()) {
+    OptionsVar->setLinkage(GlobalValue::ExternalLinkage);
+    OptionsVar->setComdat(M.getOrInsertComdat(OptionsVar->getName()));
+  }
+}
+
 bool ModuleMemProfiler::instrumentModule(Module &M) {
 
   // Create a module constructor.
@@ -566,6 +585,8 @@ bool ModuleMemProfiler::instrumentModule(Module &M) {
 
   createMemprofHistogramFlagVar(M);
 
+  createMemprofDefaultOptionsVar(M);
+
   return true;
 }
 
diff --git a/llvm/test/Instrumentation/HeapProfiler/memprof-options.ll b/llvm/test/Instrumentation/HeapProfiler/memprof-options.ll
new file mode 100644
index 00000000000000..589e04bb403c6f
--- /dev/null
+++ b/llvm/test/Instrumentation/HeapProfiler/memprof-options.ll
@@ -0,0 +1,11 @@
+; RUN: opt < %s -mtriple=x86_64-unknown-linux -passes='function(memprof),memprof-module' -S | FileCheck %s --check-prefixes=CHECK,EMPTY
+; RUN: opt < %s -mtriple=x86_64-unknown-linux -passes='function(memprof),memprof-module' -S -memprof-default-options="verbose=1" | FileCheck %s --check-prefixes=CHECK,VERBOSE
+
+define i32 @main() {
+entry:
+  ret i32 0
+}
+
+; CHECK: $__memprof_default_options_str = comdat any
+; EMPTY: @__memprof_default_options_str = constant [1 x i8] zeroinitializer, comdat
+; VERBOSE: @__memprof_default_options_str = constant [10 x i8] c"verbose=1\00", comdat

>From 9ba0a77135ccd22ea74034dd65831cf31dd88b39 Mon Sep 17 00:00:00 2001
From: Ellis Hoag <ellis.sparky.hoag at gmail.com>
Date: Thu, 5 Dec 2024 16:21:50 -0800
Subject: [PATCH 2/3] rename to -memprof-runtime-default-options

---
 compiler-rt/include/sanitizer/memprof_interface.h         | 4 ++--
 compiler-rt/lib/memprof/memprof_flags.h                   | 4 ++--
 compiler-rt/test/memprof/TestCases/set_options.cpp        | 2 +-
 llvm/lib/Transforms/Instrumentation/MemProfiler.cpp       | 8 ++++----
 llvm/test/Instrumentation/HeapProfiler/memprof-options.ll | 2 +-
 5 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/compiler-rt/include/sanitizer/memprof_interface.h b/compiler-rt/include/sanitizer/memprof_interface.h
index cdb65084b50200..6d9b2a2394f41e 100644
--- a/compiler-rt/include/sanitizer/memprof_interface.h
+++ b/compiler-rt/include/sanitizer/memprof_interface.h
@@ -47,8 +47,8 @@ void SANITIZER_CDECL __memprof_print_accumulated_stats(void);
 
 /// User-provided default option settings.
 ///
-/// You can set these options via the -memprof-default-options LLVM flag or
-/// you can provide your own implementation of this function. See
+/// You can set these options via the -memprof-runtime-default-options LLVM flag
+/// or you can provide your own implementation of this function. See
 /// memprof_flags.h for more info.
 ///
 /// \returns Default options string.
diff --git a/compiler-rt/lib/memprof/memprof_flags.h b/compiler-rt/lib/memprof/memprof_flags.h
index ee1b7b3bcad921..4dd395a6be94a8 100644
--- a/compiler-rt/lib/memprof/memprof_flags.h
+++ b/compiler-rt/lib/memprof/memprof_flags.h
@@ -22,8 +22,8 @@
 // prior one:
 //  1) by setting MEMPROF_DEFAULT_OPTIONS during the compilation of the MemProf
 //     runtime
-//  2) by setting the LLVM flag -memprof-default-options during the compilation
-//     of your binary
+//  2) by setting the LLVM flag -memprof-runtime-default-options during the
+//     compilation of your binary
 //  3) by overriding the user-specified function __memprof_default_options()
 //  4) by setting the environment variable MEMPROF_OPTIONS during runtime
 
diff --git a/compiler-rt/test/memprof/TestCases/set_options.cpp b/compiler-rt/test/memprof/TestCases/set_options.cpp
index 00f3d606de911c..dddcfcf98c5c08 100644
--- a/compiler-rt/test/memprof/TestCases/set_options.cpp
+++ b/compiler-rt/test/memprof/TestCases/set_options.cpp
@@ -1,7 +1,7 @@
 // RUN: %clangxx_memprof %s -o %t-default
 // RUN: %run %t-default | FileCheck %s --check-prefix=DEFAULT
 
-// RUN: %clangxx_memprof %s -mllvm -memprof-default-options="print_text=true,log_path=stdout,atexit=false" -o %t
+// RUN: %clangxx_memprof %s -mllvm -memprof-runtime-default-options="print_text=true,log_path=stdout,atexit=false" -o %t
 // RUN: %run %t | FileCheck %s
 
 #include <sanitizer/memprof_interface.h>
diff --git a/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp b/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp
index 6e17a16a46a9e9..ab7d3c70029910 100644
--- a/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp
@@ -167,9 +167,9 @@ static cl::opt<bool>
                             cl::Hidden, cl::init(false));
 
 static cl::opt<std::string>
-    MemprofDefaultOptions("memprof-default-options",
-                          cl::desc("The default memprof options"), cl::Hidden,
-                          cl::init(""));
+    MemprofRuntimeDefaultOptions("memprof-runtime-default-options",
+                                 cl::desc("The default memprof options"),
+                                 cl::Hidden, cl::init(""));
 
 extern cl::opt<bool> MemProfReportHintedSizes;
 
@@ -554,7 +554,7 @@ void createMemprofHistogramFlagVar(Module &M) {
 
 void createMemprofDefaultOptionsVar(Module &M) {
   Constant *OptionsConst = ConstantDataArray::getString(
-      M.getContext(), MemprofDefaultOptions, /*AddNull=*/true);
+      M.getContext(), MemprofRuntimeDefaultOptions, /*AddNull=*/true);
   GlobalVariable *OptionsVar =
       new GlobalVariable(M, OptionsConst->getType(), /*isConstant=*/true,
                          GlobalValue::WeakAnyLinkage, OptionsConst,
diff --git a/llvm/test/Instrumentation/HeapProfiler/memprof-options.ll b/llvm/test/Instrumentation/HeapProfiler/memprof-options.ll
index 589e04bb403c6f..8e82d524952dd4 100644
--- a/llvm/test/Instrumentation/HeapProfiler/memprof-options.ll
+++ b/llvm/test/Instrumentation/HeapProfiler/memprof-options.ll
@@ -1,5 +1,5 @@
 ; RUN: opt < %s -mtriple=x86_64-unknown-linux -passes='function(memprof),memprof-module' -S | FileCheck %s --check-prefixes=CHECK,EMPTY
-; RUN: opt < %s -mtriple=x86_64-unknown-linux -passes='function(memprof),memprof-module' -S -memprof-default-options="verbose=1" | FileCheck %s --check-prefixes=CHECK,VERBOSE
+; RUN: opt < %s -mtriple=x86_64-unknown-linux -passes='function(memprof),memprof-module' -S -memprof-runtime-default-options="verbose=1" | FileCheck %s --check-prefixes=CHECK,VERBOSE
 
 define i32 @main() {
 entry:

>From 88ab7fa228d45b7e2a6087ddc7e1341052fe6b08 Mon Sep 17 00:00:00 2001
From: Ellis Hoag <ellis.sparky.hoag at gmail.com>
Date: Thu, 5 Dec 2024 16:26:15 -0800
Subject: [PATCH 3/3] add test

---
 compiler-rt/test/memprof/TestCases/default_options.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/compiler-rt/test/memprof/TestCases/default_options.cpp b/compiler-rt/test/memprof/TestCases/default_options.cpp
index 1b6b61fc048b6d..4042a7df588b08 100644
--- a/compiler-rt/test/memprof/TestCases/default_options.cpp
+++ b/compiler-rt/test/memprof/TestCases/default_options.cpp
@@ -1,5 +1,8 @@
 // RUN: %clangxx_memprof -O2 %s -o %t && %run %t 2>&1 | FileCheck %s
 
+// Check that overriding __memprof_default_options() takes precedence over the LLVM flag
+// RUN: %clangxx_memprof -O2 %s -o %t-flag -mllvm -memprof-runtime-default-options="verbosity=0 help=0" && %run %t-flag 2>&1 | FileCheck %s
+
 const char *kMemProfDefaultOptions = "verbosity=1 help=1";
 
 extern "C" const char *__memprof_default_options() {



More information about the llvm-commits mailing list