[llvm] [JIT] Respect `JITDUMP_USE_ARCH_TIMESTAMP` environment variable (PR #146085)

Cody Tapscott via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 27 07:22:21 PDT 2025


https://github.com/topolarity created https://github.com/llvm/llvm-project/pull/146085

This environment variable is set by `perf record -e intel_pt` to indicate that an arch-specific timestamp should be used when emitting the jitdump instead of CLOCK_MONOTONIC, which allows the dump to be correlated to the Intel PT recording data by `perf inject --jit`.

Without this change `perf inject` complains that the recording was taken improperly:
```console
$ perf inject --jit --input perf.data --output perf.jit.data                  
error, jitted code must be sampled with perf record -k 1
```

>From 62e0f161bff37a1cbd100ed13c1ed2a5174a741c Mon Sep 17 00:00:00 2001
From: Cody Tapscott <topolarity at tapscott.me>
Date: Fri, 27 Jun 2025 10:14:33 -0400
Subject: [PATCH] [JIT] Respect `JITDUMP_USE_ARCH_TIMESTAMP` environment
 variable

This environment variable is set by `perf record -e intel_pt` to indicate that an
arch-specific timestamp should be used when emitting the jitdump instead of
CLOCK_MONOTONIC, which allows the dump to be correlated to the Intel PT recording
data by `perf inject --jit`.
---
 .../PerfJITEvents/PerfJITEventListener.cpp    | 32 ++++++++++++++++---
 1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/ExecutionEngine/PerfJITEvents/PerfJITEventListener.cpp b/llvm/lib/ExecutionEngine/PerfJITEvents/PerfJITEventListener.cpp
index 4d14a606b98b0..e0cc72751394d 100644
--- a/llvm/lib/ExecutionEngine/PerfJITEvents/PerfJITEventListener.cpp
+++ b/llvm/lib/ExecutionEngine/PerfJITEvents/PerfJITEventListener.cpp
@@ -36,6 +36,10 @@
 #include <time.h>      // clock_gettime(), time(), localtime_r() */
 #include <unistd.h>    // for read(), close()
 
+#if defined(__x86_64__)
+#include <x86intrin.h> // for __rdtsc()
+#endif
+
 using namespace llvm;
 using namespace llvm::object;
 typedef DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind;
@@ -100,6 +104,9 @@ class PerfJITEventListener : public JITEventListener {
   // perf mmap marker
   void *MarkerAddr = NULL;
 
+  // use arch-specific timestamp instead of CLOCK_MONOTONIC
+  bool UseArchTimestamp = false;
+
   // perf support ready
   bool SuccessfullyInitialized = false;
 
@@ -168,10 +175,16 @@ static inline uint64_t timespec_to_ns(const struct timespec *ts) {
   return ((uint64_t)ts->tv_sec * NanoSecPerSec) + ts->tv_nsec;
 }
 
-static inline uint64_t perf_get_timestamp(void) {
+static inline uint64_t perf_get_timestamp(bool use_arch_timestamp) {
   struct timespec ts;
   int ret;
 
+  if (use_arch_timestamp) {
+#if defined(__x86_64__)
+    return __rdtsc();
+#endif
+  }
+
   ret = clock_gettime(CLOCK_MONOTONIC, &ts);
   if (ret)
     return 0;
@@ -181,8 +194,16 @@ static inline uint64_t perf_get_timestamp(void) {
 
 PerfJITEventListener::PerfJITEventListener()
     : Pid(sys::Process::getProcessId()) {
+
+  // check if arch-specific timestamp should be used
+#if defined(__x86_64__)
+  if (const char *UseArchTimestampEnv = getenv("JITDUMP_USE_ARCH_TIMESTAMP")) {
+    UseArchTimestamp = strcmp(UseArchTimestampEnv, "1") == 0;
+  }
+#endif
+
   // check if clock-source is supported
-  if (!perf_get_timestamp()) {
+  if (!UseArchTimestamp && !perf_get_timestamp(false)) {
     errs() << "kernel does not support CLOCK_MONOTONIC\n";
     return;
   }
@@ -221,7 +242,8 @@ PerfJITEventListener::PerfJITEventListener()
   Header.Version = LLVM_PERF_JIT_VERSION;
   Header.TotalSize = sizeof(Header);
   Header.Pid = Pid;
-  Header.Timestamp = perf_get_timestamp();
+  Header.Timestamp = perf_get_timestamp(UseArchTimestamp);
+  Header.Flags = UseArchTimestamp ? JITDUMP_FLAGS_ARCH_TIMESTAMP : 0;
   Dumpstream->write(reinterpret_cast<const char *>(&Header), sizeof(Header));
 
   // Everything initialized, can do profiling now.
@@ -417,7 +439,7 @@ void PerfJITEventListener::NotifyCode(Expected<llvm::StringRef> &Symbol,
   rec.Prefix.TotalSize = sizeof(rec) +        // debug record itself
                          Symbol->size() + 1 + // symbol name
                          CodeSize;            // and code
-  rec.Prefix.Timestamp = perf_get_timestamp();
+  rec.Prefix.Timestamp = perf_get_timestamp(UseArchTimestamp);
 
   rec.CodeSize = CodeSize;
   rec.Vma = CodeAddr;
@@ -446,7 +468,7 @@ void PerfJITEventListener::NotifyDebug(uint64_t CodeAddr,
   LLVMPerfJitRecordDebugInfo rec;
   rec.Prefix.Id = JIT_CODE_DEBUG_INFO;
   rec.Prefix.TotalSize = sizeof(rec); // will be increased further
-  rec.Prefix.Timestamp = perf_get_timestamp();
+  rec.Prefix.Timestamp = perf_get_timestamp(UseArchTimestamp);
   rec.CodeAddr = CodeAddr;
   rec.NrEntry = Lines.size();
 



More information about the llvm-commits mailing list