[llvm] 00f4121 - [ORC][JITLink] Add Intel VTune support to JITLink (#83957)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 7 11:15:20 PST 2024
Author: Hongyu Chen
Date: 2024-03-07T11:15:16-08:00
New Revision: 00f412168cf6aee234615a11d1424fc58221eb78
URL: https://github.com/llvm/llvm-project/commit/00f412168cf6aee234615a11d1424fc58221eb78
DIFF: https://github.com/llvm/llvm-project/commit/00f412168cf6aee234615a11d1424fc58221eb78.diff
LOG: [ORC][JITLink] Add Intel VTune support to JITLink (#83957)
[ORC] Re-land https://github.com/llvm/llvm-project/pull/81826
This patch adds two plugins: VTuneSupportPlugin.cpp and
JITLoaderVTune.cpp. The testing is done in a manner similar to
llvm-jitlistener. Currently, we only support the old version of Intel
VTune API.
Added:
llvm/include/llvm/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.h
llvm/include/llvm/ExecutionEngine/Orc/Shared/VTuneSharedStructs.h
llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.h
llvm/lib/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.cpp
llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.cpp
llvm/test/ExecutionEngine/JITLink/x86-64/ELF_vtune.s
Modified:
llvm/lib/ExecutionEngine/Orc/Debugging/CMakeLists.txt
llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt
llvm/test/ExecutionEngine/JITLink/x86-64/lit.local.cfg
llvm/tools/llvm-jitlink/llvm-jitlink.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.h b/llvm/include/llvm/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.h
new file mode 100644
index 00000000000000..9deb38a1a71fb1
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.h
@@ -0,0 +1,66 @@
+//===--- VTuneSupportPlugin.h -- Support for VTune profiler ---*- C++ -*---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Handles support for registering code with VIntel Tune's Amplifier JIT API.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_DEBUGGING_VTUNESUPPORT_H
+#define LLVM_EXECUTIONENGINE_ORC_DEBUGGING_VTUNESUPPORT_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
+#include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h"
+#include "llvm/ExecutionEngine/Orc/Shared/VTuneSharedStructs.h"
+
+namespace llvm {
+
+namespace orc {
+
+class VTuneSupportPlugin : public ObjectLinkingLayer::Plugin {
+public:
+ VTuneSupportPlugin(ExecutorProcessControl &EPC, ExecutorAddr RegisterImplAddr,
+ ExecutorAddr UnregisterImplAddr, bool EmitDebugInfo)
+ : EPC(EPC), RegisterVTuneImplAddr(RegisterImplAddr),
+ UnregisterVTuneImplAddr(UnregisterImplAddr),
+ EmitDebugInfo(EmitDebugInfo) {}
+
+ void modifyPassConfig(MaterializationResponsibility &MR,
+ jitlink::LinkGraph &G,
+ jitlink::PassConfiguration &Config) override;
+
+ Error notifyEmitted(MaterializationResponsibility &MR) override;
+ Error notifyFailed(MaterializationResponsibility &MR) override;
+ Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override;
+ void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
+ ResourceKey SrcKey) override;
+
+ static Expected<std::unique_ptr<VTuneSupportPlugin>>
+ Create(ExecutorProcessControl &EPC, JITDylib &JD, bool EmitDebugInfo,
+ bool TestMode = false);
+
+private:
+ ExecutorProcessControl &EPC;
+ ExecutorAddr RegisterVTuneImplAddr;
+ ExecutorAddr UnregisterVTuneImplAddr;
+ std::mutex PluginMutex;
+ uint64_t NextMethodID = 0;
+ DenseMap<MaterializationResponsibility *, std::pair<uint64_t, uint64_t>>
+ PendingMethodIDs;
+ DenseMap<ResourceKey, SmallVector<std::pair<uint64_t, uint64_t>>>
+ LoadedMethodIDs;
+ bool EmitDebugInfo;
+};
+
+} // end namespace orc
+
+} // end namespace llvm
+
+#endif
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/VTuneSharedStructs.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/VTuneSharedStructs.h
new file mode 100644
index 00000000000000..667d3446faff74
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/VTuneSharedStructs.h
@@ -0,0 +1,102 @@
+//===-------------------- VTuneSharedStructs.h ------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Structs and serialization to share VTune-related information
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_VTUNESHAREDSTRUCTS_H
+#define LLVM_EXECUTIONENGINE_ORC_SHARED_VTUNESHAREDSTRUCTS_H
+
+namespace llvm {
+namespace orc {
+
+using VTuneLineTable = std::vector<std::pair<unsigned, unsigned>>;
+
+// SI = String Index, 1-indexed into the VTuneMethodBatch::Strings table.
+// SI == 0 means replace with nullptr.
+
+// MI = Method Index, 1-indexed into the VTuneMethodBatch::Methods table.
+// MI == 0 means this is a parent method and was not inlined.
+
+struct VTuneMethodInfo {
+ VTuneLineTable LineTable;
+ ExecutorAddr LoadAddr;
+ uint64_t LoadSize;
+ uint64_t MethodID;
+ uint32_t NameSI;
+ uint32_t ClassFileSI;
+ uint32_t SourceFileSI;
+ uint32_t ParentMI;
+};
+
+using VTuneMethodTable = std::vector<VTuneMethodInfo>;
+using VTuneStringTable = std::vector<std::string>;
+
+struct VTuneMethodBatch {
+ VTuneMethodTable Methods;
+ VTuneStringTable Strings;
+};
+
+using VTuneUnloadedMethodIDs = SmallVector<std::pair<uint64_t, uint64_t>>;
+
+namespace shared {
+
+using SPSVTuneLineTable = SPSSequence<SPSTuple<uint32_t, uint32_t>>;
+using SPSVTuneMethodInfo =
+ SPSTuple<SPSVTuneLineTable, SPSExecutorAddr, uint64_t, uint64_t, uint32_t,
+ uint32_t, uint32_t, uint32_t>;
+using SPSVTuneMethodTable = SPSSequence<SPSVTuneMethodInfo>;
+using SPSVTuneStringTable = SPSSequence<SPSString>;
+using SPSVTuneMethodBatch = SPSTuple<SPSVTuneMethodTable, SPSVTuneStringTable>;
+using SPSVTuneUnloadedMethodIDs = SPSSequence<SPSTuple<uint64_t, uint64_t>>;
+
+template <> class SPSSerializationTraits<SPSVTuneMethodInfo, VTuneMethodInfo> {
+public:
+ static size_t size(const VTuneMethodInfo &MI) {
+ return SPSVTuneMethodInfo::AsArgList::size(
+ MI.LineTable, MI.LoadAddr, MI.LoadSize, MI.MethodID, MI.NameSI,
+ MI.ClassFileSI, MI.SourceFileSI, MI.ParentMI);
+ }
+
+ static bool deserialize(SPSInputBuffer &IB, VTuneMethodInfo &MI) {
+ return SPSVTuneMethodInfo::AsArgList::deserialize(
+ IB, MI.LineTable, MI.LoadAddr, MI.LoadSize, MI.MethodID, MI.NameSI,
+ MI.ClassFileSI, MI.SourceFileSI, MI.ParentMI);
+ }
+
+ static bool serialize(SPSOutputBuffer &OB, const VTuneMethodInfo &MI) {
+ return SPSVTuneMethodInfo::AsArgList::serialize(
+ OB, MI.LineTable, MI.LoadAddr, MI.LoadSize, MI.MethodID, MI.NameSI,
+ MI.ClassFileSI, MI.SourceFileSI, MI.ParentMI);
+ }
+};
+
+template <>
+class SPSSerializationTraits<SPSVTuneMethodBatch, VTuneMethodBatch> {
+public:
+ static size_t size(const VTuneMethodBatch &MB) {
+ return SPSVTuneMethodBatch::AsArgList::size(MB.Methods, MB.Strings);
+ }
+
+ static bool deserialize(SPSInputBuffer &IB, VTuneMethodBatch &MB) {
+ return SPSVTuneMethodBatch::AsArgList::deserialize(IB, MB.Methods,
+ MB.Strings);
+ }
+
+ static bool serialize(SPSOutputBuffer &OB, const VTuneMethodBatch &MB) {
+ return SPSVTuneMethodBatch::AsArgList::serialize(OB, MB.Methods,
+ MB.Strings);
+ }
+};
+
+} // end namespace shared
+} // end namespace orc
+} // end namespace llvm
+
+#endif
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.h b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.h
new file mode 100644
index 00000000000000..afb7df592faf27
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.h
@@ -0,0 +1,31 @@
+
+//===------ JITLoaderVTune.h --- Register profiler objects ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Register objects for access by profilers via the perf JIT interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_JITLOADERVTUNE_H
+#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_JITLOADERVTUNE_H
+
+#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
+#include <cstdint>
+
+extern "C" llvm::orc::shared::CWrapperFunctionResult
+llvm_orc_registerVTuneImpl(const char *Data, uint64_t Size);
+
+extern "C" llvm::orc::shared::CWrapperFunctionResult
+llvm_orc_unregisterVTuneImpl(const char *Data, uint64_t Size);
+
+extern "C" llvm::orc::shared::CWrapperFunctionResult
+llvm_orc_test_registerVTuneImpl(const char *Data, uint64_t Size);
+
+#endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_JITLOADERVTUNE_H
+
+
diff --git a/llvm/lib/ExecutionEngine/Orc/Debugging/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/Debugging/CMakeLists.txt
index 5bf23a7ec0bc89..ed52692662a8a3 100644
--- a/llvm/lib/ExecutionEngine/Orc/Debugging/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/Orc/Debugging/CMakeLists.txt
@@ -8,6 +8,7 @@ add_llvm_component_library(LLVMOrcDebugging
DebuggerSupportPlugin.cpp
LLJITUtilsCBindings.cpp
PerfSupportPlugin.cpp
+ VTuneSupportPlugin.cpp
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/ExecutionEngine/Orc/Debugging/
diff --git a/llvm/lib/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.cpp b/llvm/lib/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.cpp
new file mode 100644
index 00000000000000..30a9728c8c20e3
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.cpp
@@ -0,0 +1,185 @@
+//===--- VTuneSupportPlugin.cpp -- Support for VTune profiler --*- C++ -*--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Handles support for registering code with VIntel Tune's Amplfiier JIT API.
+//
+//===----------------------------------------------------------------------===//
+#include "llvm/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/ExecutionEngine/Orc/Debugging/DebugInfoSupport.h"
+
+using namespace llvm;
+using namespace llvm::orc;
+using namespace llvm::jitlink;
+
+static constexpr StringRef RegisterVTuneImplName = "llvm_orc_registerVTuneImpl";
+static constexpr StringRef UnregisterVTuneImplName =
+ "llvm_orc_unregisterVTuneImpl";
+static constexpr StringRef RegisterTestVTuneImplName =
+ "llvm_orc_test_registerVTuneImpl";
+
+static VTuneMethodBatch getMethodBatch(LinkGraph &G, bool EmitDebugInfo) {
+ VTuneMethodBatch Batch;
+ std::unique_ptr<DWARFContext> DC;
+ StringMap<std::unique_ptr<MemoryBuffer>> DCBacking;
+ if (EmitDebugInfo) {
+ auto EDC = createDWARFContext(G);
+ if (!EDC) {
+ EmitDebugInfo = false;
+ } else {
+ DC = std::move(EDC->first);
+ DCBacking = std::move(EDC->second);
+ }
+ }
+
+ auto GetStringIdx = [Deduplicator = StringMap<uint32_t>(),
+ &Batch](StringRef S) mutable {
+ auto I = Deduplicator.find(S);
+ if (I != Deduplicator.end())
+ return I->second;
+
+ Batch.Strings.push_back(S.str());
+ return Deduplicator[S] = Batch.Strings.size();
+ };
+ for (auto Sym : G.defined_symbols()) {
+ if (!Sym->isCallable())
+ continue;
+
+ Batch.Methods.push_back(VTuneMethodInfo());
+ auto &Method = Batch.Methods.back();
+ Method.MethodID = 0;
+ Method.ParentMI = 0;
+ Method.LoadAddr = Sym->getAddress();
+ Method.LoadSize = Sym->getSize();
+ Method.NameSI = GetStringIdx(Sym->getName());
+ Method.ClassFileSI = 0;
+ Method.SourceFileSI = 0;
+
+ if (!EmitDebugInfo)
+ continue;
+
+ auto &Section = Sym->getBlock().getSection();
+ auto Addr = Sym->getAddress();
+ auto SAddr =
+ object::SectionedAddress{Addr.getValue(), Section.getOrdinal()};
+ DILineInfoTable LinesInfo = DC->getLineInfoForAddressRange(
+ SAddr, Sym->getSize(),
+ DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath);
+ Method.SourceFileSI = Batch.Strings.size();
+ Batch.Strings.push_back(DC->getLineInfoForAddress(SAddr).FileName);
+ for (auto &LInfo : LinesInfo) {
+ Method.LineTable.push_back(
+ std::pair<unsigned, unsigned>{/*unsigned*/ Sym->getOffset(),
+ /*DILineInfo*/ LInfo.second.Line});
+ }
+ }
+ return Batch;
+}
+
+void VTuneSupportPlugin::modifyPassConfig(MaterializationResponsibility &MR,
+ LinkGraph &G,
+ PassConfiguration &Config) {
+ Config.PostFixupPasses.push_back([this, MR = &MR](LinkGraph &G) {
+ // the object file is generated but not linked yet
+ auto Batch = getMethodBatch(G, EmitDebugInfo);
+ if (Batch.Methods.empty()) {
+ return Error::success();
+ }
+ {
+ std::lock_guard<std::mutex> Lock(PluginMutex);
+ uint64_t Allocated = Batch.Methods.size();
+ uint64_t Start = NextMethodID;
+ NextMethodID += Allocated;
+ for (size_t i = Start; i < NextMethodID; ++i) {
+ Batch.Methods[i - Start].MethodID = i;
+ }
+ this->PendingMethodIDs[MR] = {Start, Allocated};
+ }
+ G.allocActions().push_back(
+ {cantFail(shared::WrapperFunctionCall::Create<
+ shared::SPSArgList<shared::SPSVTuneMethodBatch>>(
+ RegisterVTuneImplAddr, Batch)),
+ {}});
+ return Error::success();
+ });
+}
+
+Error VTuneSupportPlugin::notifyEmitted(MaterializationResponsibility &MR) {
+ if (auto Err = MR.withResourceKeyDo([this, MR = &MR](ResourceKey K) {
+ std::lock_guard<std::mutex> Lock(PluginMutex);
+ auto I = PendingMethodIDs.find(MR);
+ if (I == PendingMethodIDs.end())
+ return;
+
+ LoadedMethodIDs[K].push_back(I->second);
+ PendingMethodIDs.erase(I);
+ })) {
+ return Err;
+ }
+ return Error::success();
+}
+
+Error VTuneSupportPlugin::notifyFailed(MaterializationResponsibility &MR) {
+ std::lock_guard<std::mutex> Lock(PluginMutex);
+ PendingMethodIDs.erase(&MR);
+ return Error::success();
+}
+
+Error VTuneSupportPlugin::notifyRemovingResources(JITDylib &JD, ResourceKey K) {
+ // Unregistration not required if not provided
+ if (!UnregisterVTuneImplAddr) {
+ return Error::success();
+ }
+ VTuneUnloadedMethodIDs UnloadedIDs;
+ {
+ std::lock_guard<std::mutex> Lock(PluginMutex);
+ auto I = LoadedMethodIDs.find(K);
+ if (I == LoadedMethodIDs.end())
+ return Error::success();
+
+ UnloadedIDs = std::move(I->second);
+ LoadedMethodIDs.erase(I);
+ }
+ if (auto Err = EPC.callSPSWrapper<void(shared::SPSVTuneUnloadedMethodIDs)>(
+ UnregisterVTuneImplAddr, UnloadedIDs))
+ return Err;
+
+ return Error::success();
+}
+
+void VTuneSupportPlugin::notifyTransferringResources(JITDylib &JD,
+ ResourceKey DstKey,
+ ResourceKey SrcKey) {
+ std::lock_guard<std::mutex> Lock(PluginMutex);
+ auto I = LoadedMethodIDs.find(SrcKey);
+ if (I == LoadedMethodIDs.end())
+ return;
+
+ auto &Dest = LoadedMethodIDs[DstKey];
+ Dest.insert(Dest.end(), I->second.begin(), I->second.end());
+ LoadedMethodIDs.erase(SrcKey);
+}
+
+Expected<std::unique_ptr<VTuneSupportPlugin>>
+VTuneSupportPlugin::Create(ExecutorProcessControl &EPC, JITDylib &JD,
+ bool EmitDebugInfo, bool TestMode) {
+ auto &ES = EPC.getExecutionSession();
+ auto RegisterImplName =
+ ES.intern(TestMode ? RegisterTestVTuneImplName : RegisterVTuneImplName);
+ auto UnregisterImplName = ES.intern(UnregisterVTuneImplName);
+ SymbolLookupSet SLS{RegisterImplName, UnregisterImplName};
+ auto Res = ES.lookup(makeJITDylibSearchOrder({&JD}), std::move(SLS));
+ if (!Res)
+ return Res.takeError();
+ ExecutorAddr RegisterImplAddr(
+ Res->find(RegisterImplName)->second.getAddress());
+ ExecutorAddr UnregisterImplAddr(
+ Res->find(UnregisterImplName)->second.getAddress());
+ return std::make_unique<VTuneSupportPlugin>(
+ EPC, RegisterImplAddr, UnregisterImplAddr, EmitDebugInfo);
+}
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt
index f2005dc1775e3c..3d1dfe758c79dd 100644
--- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt
@@ -2,10 +2,18 @@ if( CMAKE_HOST_UNIX AND HAVE_LIBRT )
set(rt_lib rt)
endif()
+set(intel_jit_profiling )
+if( LLVM_USE_INTEL_JITEVENTS )
+ set(intel_jit_profiling IntelJITProfiling)
+ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../IntelJITProfiling)
+ include_directories(${PROJECT_BINARY_DIR}/ittapi/include/ )
+endif()
+
add_llvm_component_library(LLVMOrcTargetProcess
ExecutorSharedMemoryMapperService.cpp
JITLoaderGDB.cpp
JITLoaderPerf.cpp
+ JITLoaderVTune.cpp
OrcRTBootstrap.cpp
RegisterEHFrames.cpp
SimpleExecutorDylibManager.cpp
@@ -21,6 +29,7 @@ add_llvm_component_library(LLVMOrcTargetProcess
${rt_lib}
LINK_COMPONENTS
+ ${intel_jit_profiling}
OrcShared
Support
TargetParser
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.cpp
new file mode 100644
index 00000000000000..d346214d3ae291
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.cpp
@@ -0,0 +1,224 @@
+//===------- JITLoaderVTune.cpp - Register profiler objects -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Register objects for access by profilers via the VTune JIT interface.
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.h"
+#include "llvm/ExecutionEngine/Orc/Shared/VTuneSharedStructs.h"
+#include <map>
+
+#if LLVM_USE_INTEL_JITEVENTS
+#include "IntelJITEventsWrapper.h"
+#include "ittnotify.h"
+
+using namespace llvm;
+using namespace llvm::orc;
+
+namespace {
+class JITEventWrapper {
+public:
+ static std::unique_ptr<IntelJITEventsWrapper> Wrapper;
+};
+std::unique_ptr<IntelJITEventsWrapper> JITEventWrapper::Wrapper;
+} // namespace
+
+static Error registerJITLoaderVTuneRegisterImpl(const VTuneMethodBatch &MB) {
+ const size_t StringsSize = MB.Strings.size();
+
+ for (const auto &MethodInfo : MB.Methods) {
+ iJIT_Method_Load MethodMessage;
+ memset(&MethodMessage, 0, sizeof(iJIT_Method_Load));
+
+ MethodMessage.method_id = MethodInfo.MethodID;
+ if (MethodInfo.NameSI != 0 && MethodInfo.NameSI < StringsSize) {
+ MethodMessage.method_name =
+ const_cast<char *>(MB.Strings.at(MethodInfo.NameSI).data());
+ } else {
+ MethodMessage.method_name = NULL;
+ }
+ if (MethodInfo.ClassFileSI != 0 && MethodInfo.ClassFileSI < StringsSize) {
+ MethodMessage.class_file_name =
+ const_cast<char *>(MB.Strings.at(MethodInfo.ClassFileSI).data());
+ } else {
+ MethodMessage.class_file_name = NULL;
+ }
+ if (MethodInfo.SourceFileSI != 0 && MethodInfo.SourceFileSI < StringsSize) {
+ MethodMessage.source_file_name =
+ const_cast<char *>(MB.Strings.at(MethodInfo.SourceFileSI).data());
+ } else {
+ MethodMessage.source_file_name = NULL;
+ }
+
+ MethodMessage.method_load_address = MethodInfo.LoadAddr.toPtr<void *>();
+ MethodMessage.method_size = MethodInfo.LoadSize;
+ MethodMessage.class_id = 0;
+
+ MethodMessage.user_data = NULL;
+ MethodMessage.user_data_size = 0;
+ MethodMessage.env = iJDE_JittingAPI;
+
+ std::vector<LineNumberInfo> LineInfo;
+ for (const auto &LInfo : MethodInfo.LineTable) {
+ LineInfo.push_back(LineNumberInfo{LInfo.first, LInfo.second});
+ }
+
+ if (LineInfo.size() == 0) {
+ MethodMessage.line_number_size = 0;
+ MethodMessage.line_number_table = 0;
+ } else {
+ MethodMessage.line_number_size = LineInfo.size();
+ MethodMessage.line_number_table = &*LineInfo.begin();
+ }
+ JITEventWrapper::Wrapper->iJIT_NotifyEvent(
+ iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &MethodMessage);
+ }
+
+ return Error::success();
+}
+
+static void registerJITLoaderVTuneUnregisterImpl(
+ const std::vector<std::pair<uint64_t, uint64_t>> &UM) {
+ for (auto &Method : UM) {
+ JITEventWrapper::Wrapper->iJIT_NotifyEvent(
+ iJVM_EVENT_TYPE_METHOD_UNLOAD_START,
+ const_cast<unsigned long *>(&Method.first));
+ }
+}
+
+extern "C" llvm::orc::shared::CWrapperFunctionResult
+llvm_orc_registerVTuneImpl(const char *Data, uint64_t Size) {
+ using namespace orc::shared;
+ if (!JITEventWrapper::Wrapper)
+ JITEventWrapper::Wrapper.reset(new IntelJITEventsWrapper);
+
+ return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle(
+ Data, Size, registerJITLoaderVTuneRegisterImpl)
+ .release();
+}
+
+extern "C" llvm::orc::shared::CWrapperFunctionResult
+llvm_orc_unregisterVTuneImpl(const char *Data, uint64_t Size) {
+ using namespace orc::shared;
+ return WrapperFunction<void(SPSVTuneUnloadedMethodIDs)>::handle(
+ Data, Size, registerJITLoaderVTuneUnregisterImpl)
+ .release();
+}
+
+// For Testing: following code comes from llvm-jitlistener.cpp in llvm tools
+namespace {
+using SourceLocations = std::vector<std::pair<std::string, unsigned int>>;
+using NativeCodeMap = std::map<uint64_t, SourceLocations>;
+NativeCodeMap ReportedDebugFuncs;
+} // namespace
+
+static int NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) {
+ switch (EventType) {
+ case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED: {
+ if (!EventSpecificData) {
+ errs() << "Error: The JIT event listener did not provide a event data.";
+ return -1;
+ }
+ iJIT_Method_Load *msg = static_cast<iJIT_Method_Load *>(EventSpecificData);
+
+ ReportedDebugFuncs[msg->method_id];
+
+ outs() << "Method load [" << msg->method_id << "]: " << msg->method_name
+ << ", Size = " << msg->method_size << "\n";
+
+ for (unsigned int i = 0; i < msg->line_number_size; ++i) {
+ if (!msg->line_number_table) {
+ errs() << "A function with a non-zero line count had no line table.";
+ return -1;
+ }
+ std::pair<std::string, unsigned int> loc(
+ std::string(msg->source_file_name),
+ msg->line_number_table[i].LineNumber);
+ ReportedDebugFuncs[msg->method_id].push_back(loc);
+ outs() << " Line info @ " << msg->line_number_table[i].Offset << ": "
+ << msg->source_file_name << ", line "
+ << msg->line_number_table[i].LineNumber << "\n";
+ }
+ outs() << "\n";
+ } break;
+ case iJVM_EVENT_TYPE_METHOD_UNLOAD_START: {
+ if (!EventSpecificData) {
+ errs() << "Error: The JIT event listener did not provide a event data.";
+ return -1;
+ }
+ unsigned int UnloadId =
+ *reinterpret_cast<unsigned int *>(EventSpecificData);
+ assert(1 == ReportedDebugFuncs.erase(UnloadId));
+ outs() << "Method unload [" << UnloadId << "]\n";
+ } break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static iJIT_IsProfilingActiveFlags IsProfilingActive(void) {
+ // for testing, pretend we have an Intel Parallel Amplifier XE 2011
+ // instance attached
+ return iJIT_SAMPLING_ON;
+}
+
+static unsigned int GetNewMethodID(void) {
+ static unsigned int id = 0;
+ return ++id;
+}
+
+extern "C" llvm::orc::shared::CWrapperFunctionResult
+llvm_orc_test_registerVTuneImpl(const char *Data, uint64_t Size) {
+ using namespace orc::shared;
+ JITEventWrapper::Wrapper.reset(new IntelJITEventsWrapper(
+ NotifyEvent, NULL, NULL, IsProfilingActive, 0, 0, GetNewMethodID));
+ return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle(
+ Data, Size, registerJITLoaderVTuneRegisterImpl)
+ .release();
+}
+
+#else
+
+using namespace llvm;
+using namespace llvm::orc;
+
+static Error unsupportedBatch(const VTuneMethodBatch &MB) {
+ return llvm::make_error<StringError>("unsupported for Intel VTune",
+ inconvertibleErrorCode());
+}
+
+static void unsuppported(const std::vector<std::pair<uint64_t, uint64_t>> &UM) {
+
+}
+
+extern "C" llvm::orc::shared::CWrapperFunctionResult
+llvm_orc_registerVTuneImpl(const char *Data, uint64_t Size) {
+ using namespace orc::shared;
+ return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle(
+ Data, Size, unsupportedBatch)
+ .release();
+}
+
+extern "C" llvm::orc::shared::CWrapperFunctionResult
+llvm_orc_unregisterVTuneImpl(const char *Data, uint64_t Size) {
+ using namespace orc::shared;
+ return WrapperFunction<void(SPSVTuneUnloadedMethodIDs)>::handle(Data, Size,
+ unsuppported)
+ .release();
+}
+
+extern "C" llvm::orc::shared::CWrapperFunctionResult
+llvm_orc_test_registerVTuneImpl(const char *Data, uint64_t Size) {
+ using namespace orc::shared;
+ return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle(
+ Data, Size, unsupportedBatch)
+ .release();
+}
+
+#endif
diff --git a/llvm/test/ExecutionEngine/JITLink/x86-64/ELF_vtune.s b/llvm/test/ExecutionEngine/JITLink/x86-64/ELF_vtune.s
new file mode 100644
index 00000000000000..1c95bde51e1211
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/x86-64/ELF_vtune.s
@@ -0,0 +1,52 @@
+# REQUIRES: native && x86_64-linux && intel-jitevents
+
+# RUN: rm -rf %t && mkdir %t
+# RUN: llvm-mc -triple=x86_64-unknown-linux \
+# RUN: -filetype=obj -o %t/ELF_x86-64_vtune.o %s
+# RUN: llvm-jitlink -vtune-support %t/ELF_x86-64_vtune.o | \
+# RUN: FileCheck %s
+
+# CHECK: Method load [0]: {{.*}}, Size = {{[0-9]+}}
+# CHECK: Method unload [0]
+ .file "test.c"
+ .text
+ .globl main
+ .type main, @function
+main:
+.LFB0:
+ .cfi_startproc
+ endbr64
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ movl %edi, -4(%rbp)
+ movq %rsi, -16(%rbp)
+ movl -4(%rbp), %ebx
+ addl $1, %ebx
+ movl $0, %eax
+ popq %rbp
+ .cfi_def_cfa 7, 8
+ ret
+ .cfi_endproc
+.LFE0:
+ .size main, .-main
+ .ident "GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0"
+ .section .note.GNU-stack,"", at progbits
+ .section .note.gnu.property,"a"
+ .align 8
+ .long 1f - 0f
+ .long 4f - 1f
+ .long 5
+0:
+ .string "GNU"
+1:
+ .align 8
+ .long 0xc0000002
+ .long 3f - 2f
+2:
+ .long 0x3
+3:
+ .align 8
+4:
diff --git a/llvm/test/ExecutionEngine/JITLink/x86-64/lit.local.cfg b/llvm/test/ExecutionEngine/JITLink/x86-64/lit.local.cfg
index 42bf50dcc13c35..d5a1ad626b657d 100644
--- a/llvm/test/ExecutionEngine/JITLink/x86-64/lit.local.cfg
+++ b/llvm/test/ExecutionEngine/JITLink/x86-64/lit.local.cfg
@@ -1,2 +1,5 @@
if not "X86" in config.root.targets:
config.unsupported = True
+
+if config.llvm_use_intel_jitevents:
+ config.available_features.add("intel-jitevents")
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
index f0b8310a32efd3..09b2a5900eb0b7 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
@@ -21,6 +21,7 @@
#include "llvm/ExecutionEngine/Orc/Debugging/DebugInfoSupport.h"
#include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupportPlugin.h"
#include "llvm/ExecutionEngine/Orc/Debugging/PerfSupportPlugin.h"
+#include "llvm/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.h"
#include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
#include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
@@ -34,6 +35,7 @@
#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.h"
#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
@@ -148,6 +150,10 @@ static cl::opt<bool> PerfSupport("perf-support",
cl::init(false), cl::Hidden,
cl::cat(JITLinkCategory));
+static cl::opt<bool> VTuneSupport("vtune-support",
+ cl::desc("Enable vtune profiling support"),
+ cl::init(false), cl::Hidden,
+ cl::cat(JITLinkCategory));
static cl::opt<bool>
NoProcessSymbols("no-process-syms",
cl::desc("Do not resolve to llvm-jitlink process symbols"),
@@ -264,7 +270,10 @@ static LLVM_ATTRIBUTE_USED void linkComponents() {
<< (void *)&llvm_orc_registerJITLoaderGDBAllocAction << '\n'
<< (void *)&llvm_orc_registerJITLoaderPerfStart << '\n'
<< (void *)&llvm_orc_registerJITLoaderPerfEnd << '\n'
- << (void *)&llvm_orc_registerJITLoaderPerfImpl << '\n';
+ << (void *)&llvm_orc_registerJITLoaderPerfImpl << '\n'
+ << (void *)&llvm_orc_registerVTuneImpl << '\n'
+ << (void *)&llvm_orc_unregisterVTuneImpl << '\n'
+ << (void *)&llvm_orc_test_registerVTuneImpl << '\n';
}
static bool UseTestResultOverride = false;
@@ -1004,6 +1013,14 @@ Session::Session(std::unique_ptr<ExecutorProcessControl> EPC, Error &Err)
this->ES.getExecutorProcessControl(), *ProcessSymsJD, true, true)));
}
+ if (VTuneSupport && TT.isOSBinFormatELF()) {
+ ObjLayer.addPlugin(ExitOnErr(DebugInfoPreservationPlugin::Create()));
+ ObjLayer.addPlugin(ExitOnErr(
+ VTuneSupportPlugin::Create(this->ES.getExecutorProcessControl(),
+ *ProcessSymsJD, /*EmitDebugInfo=*/true,
+ /*TestMode=*/true)));
+ }
+
// Set up the platform.
if (!OrcRuntime.empty()) {
assert(ProcessSymsJD && "ProcessSymsJD should have been set");
More information about the llvm-commits
mailing list