diff options
Diffstat (limited to 'lld')
-rw-r--r-- | lld/CMakeLists.txt | 14 | ||||
-rw-r--r-- | lld/cmake/modules/FindVTune.cmake | 31 | ||||
-rw-r--r-- | lld/include/lld/Core/Instrumentation.h | 129 | ||||
-rw-r--r-- | lld/lib/Core/PassManager.cpp | 2 | ||||
-rw-r--r-- | lld/lib/Passes/LayoutPass.cpp | 7 |
5 files changed, 182 insertions, 1 deletions
diff --git a/lld/CMakeLists.txt b/lld/CMakeLists.txt index e2b09620be5..21a0bed8179 100644 --- a/lld/CMakeLists.txt +++ b/lld/CMakeLists.txt @@ -68,6 +68,20 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) "`CMakeFiles'. Please delete them.") endif() +list (APPEND CMAKE_MODULE_PATH "${LLD_SOURCE_DIR}/cmake/modules") + +option(LLD_USE_VTUNE + "Enable VTune user task tracking." + OFF) +if (LLD_USE_VTUNE) + find_package(VTune) + if (VTUNE_FOUND) + include_directories(${VTune_INCLUDE_DIRS}) + list(APPEND LLVM_COMMON_LIBS ${VTune_LIBRARIES}) + add_definitions(-DLLD_HAS_VTUNE) + endif() +endif() + # lld requires c++11 to build. Make sure that we have a compiler and standard # library combination that can do that. if (MSVC11) diff --git a/lld/cmake/modules/FindVTune.cmake b/lld/cmake/modules/FindVTune.cmake new file mode 100644 index 00000000000..bd0cbe9a38c --- /dev/null +++ b/lld/cmake/modules/FindVTune.cmake @@ -0,0 +1,31 @@ +# - Find VTune ittnotify. +# Defines: +# VTune_FOUND +# VTune_INCLUDE_DIRS +# VTune_LIBRARIES + +set(dirs + "$ENV{VTUNE_AMPLIFIER_XE_2013_DIR}/" + "C:/Program Files (x86)/Intel/VTune Amplifier XE 2013/" + "$ENV{VTUNE_AMPLIFIER_XE_2011_DIR}/" + "C:/Program Files (x86)/Intel/VTune Amplifier XE 2011/" + ) + +find_path(VTune_INCLUDE_DIRS ittnotify.h + PATHS ${dirs} + PATH_SUFFIXES include) + +if (CMAKE_SIZEOF_VOID_P MATCHES "8") + set(vtune_lib_dir lib64) +else() + set(vtune_lib_dir lib32) +endif() + +find_library(VTune_LIBRARIES libittnotify + HINTS "${VTune_INCLUDE_DIRS}/.." + PATHS ${dirs} + PATH_SUFFIXES ${vtune_lib_dir}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + VTune DEFAULT_MSG VTune_LIBRARIES VTune_INCLUDE_DIRS) diff --git a/lld/include/lld/Core/Instrumentation.h b/lld/include/lld/Core/Instrumentation.h new file mode 100644 index 00000000000..9d2dc02bc41 --- /dev/null +++ b/lld/include/lld/Core/Instrumentation.h @@ -0,0 +1,129 @@ +//===- include/Core/Instrumentation.h - Instrumentation API ---------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Provide an Instrumentation API that optionally uses VTune interfaces. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLD_CORE_INSTRUMENTATION_H +#define LLD_CORE_INSTRUMENTATION_H + +#ifdef LLD_HAS_VTUNE +# include <ittnotify.h> +#endif + +namespace lld { +#ifdef LLD_HAS_VTUNE +/// \brief A unique global scope for instrumentation data. +/// +/// Domains last for the lifetime of the application and cannot be destroyed. +/// Multiple Domains created with the same name represent the same domain. +class Domain { + __itt_domain *_domain; + +public: + Domain(const char *name) : _domain(__itt_domain_createA(name)) {} + + operator __itt_domain *() const { return _domain; } + __itt_domain *operator->() const { return _domain; } +}; + +/// \brief A global reference to a string constant. +/// +/// These are uniqued by the ITT runtime and cannot be deleted. They are not +/// specific to a domain. +/// +/// Prefer reusing a single StringHandle over passing a ntbs when the same +/// string will be used often. +class StringHandle { + __itt_string_handle *_handle; + +public: + StringHandle(const char *name) : _handle(__itt_string_handle_createA(name)) {} + + operator __itt_string_handle *() const { return _handle; } +}; + +/// \brief A task on a single thread. Nests within other tasks. +/// +/// Each thread has its own task stack and tasks nest recursively on that stack. +/// A task cannot transfer threads. +/// +/// SBRM is used to ensure task starts and ends are ballanced. The lifetime of +/// a task is either the liftime of this object, or until end is called. +class ScopedTask { + __itt_domain *_domain; + + ScopedTask(const ScopedTask &) LLVM_DELETED_FUNCTION; + ScopedTask &operator=(const ScopedTask &) LLVM_DELETED_FUNCTION; + +public: + /// \brief Create a task in Domain \p d named \p s. + ScopedTask(const Domain &d, const StringHandle &s) : _domain(d) { + __itt_task_begin(d, __itt_null, __itt_null, s); + } + + ScopedTask(ScopedTask &&other) { + *this = std::move(other); + } + + ScopedTask &operator=(ScopedTask &&other) { + _domain = other._domain; + other._domain = nullptr; + return *this; + } + + /// \brief Prematurely end this task. + void end() { + if (_domain) + __itt_task_end(_domain); + _domain = nullptr; + } + + ~ScopedTask() { end(); } +}; + +/// \brief A specific point in time. Allows metadata to be associated. +class Marker { +public: + Marker(const Domain &d, const StringHandle &s) { + __itt_marker(d, __itt_null, s, __itt_scope_global); + } +}; +#else +class Domain { +public: + Domain(const char *name) {} +}; + +class StringHandle { +public: + StringHandle(const char *name) {} +}; + +class ScopedTask { +public: + ScopedTask(const Domain &d, const StringHandle &s) {} + void end() {} +}; + +class Marker { +public: + Marker(const Domain &d, const StringHandle &s) {} +}; +#endif + +inline const Domain &getDefaultDomain() { + static Domain domain("org.llvm.lld"); + return domain; +} +} // end namespace lld. + +#endif diff --git a/lld/lib/Core/PassManager.cpp b/lld/lib/Core/PassManager.cpp index 2dee5ee51ef..f5d998d5be0 100644 --- a/lld/lib/Core/PassManager.cpp +++ b/lld/lib/Core/PassManager.cpp @@ -9,6 +9,7 @@ #include "lld/Core/PassManager.h" +#include "lld/Core/Instrumentation.h" #include "lld/Core/Pass.h" #include "llvm/Support/ErrorOr.h" @@ -16,6 +17,7 @@ namespace lld { ErrorOr<void> PassManager::runOnFile(MutableFile &mf) { for (auto &pass : _passes) { + ScopedTask task(getDefaultDomain(), "Pass"); pass->perform(mf); } return llvm::error_code::success(); diff --git a/lld/lib/Passes/LayoutPass.cpp b/lld/lib/Passes/LayoutPass.cpp index dd9fe7c979d..639527bbe35 100644 --- a/lld/lib/Passes/LayoutPass.cpp +++ b/lld/lib/Passes/LayoutPass.cpp @@ -11,7 +11,8 @@ #define DEBUG_TYPE "LayoutPass" #include "lld/Passes/LayoutPass.h" -#include "llvm/Support/Debug.h" + +#include "lld/Core/Instrumentation.h" #include "llvm/Support/Debug.h" @@ -133,6 +134,7 @@ bool LayoutPass::CompareAtoms::operator()(const DefinedAtom *left, /// targetAtom until the targetAtom has all atoms of size 0, then chain the /// targetAtoms and its tree to the current chain void LayoutPass::buildFollowOnTable(MutableFile::DefinedAtomRange &range) { + ScopedTask task(getDefaultDomain(), "LayoutPass::buildFollowOnTable"); for (auto ai : range) { for (const Reference *r : *ai) { if (r->kind() == lld::Reference::kindLayoutAfter) { @@ -250,6 +252,7 @@ void LayoutPass::buildFollowOnTable(MutableFile::DefinedAtomRange &range) { /// if not add the atom to the chain, so that the current atom is part of the /// the chain where the rootAtom is in void LayoutPass::buildInGroupTable(MutableFile::DefinedAtomRange &range) { + ScopedTask task(getDefaultDomain(), "LayoutPass::buildInGroupTable"); // This table would convert precededby references to follow on // references so that we have only one table for (auto ai : range) { @@ -336,6 +339,7 @@ void LayoutPass::buildInGroupTable(MutableFile::DefinedAtomRange &range) { /// same chain), chain all the atoms that are lead by the targetAtom into /// the current chain void LayoutPass::buildPrecededByTable(MutableFile::DefinedAtomRange &range) { + ScopedTask task(getDefaultDomain(), "LayoutPass::buildPrecededByTable"); // This table would convert precededby references to follow on // references so that we have only one table for (auto ai : range) { @@ -400,6 +404,7 @@ void LayoutPass::buildPrecededByTable(MutableFile::DefinedAtomRange &range) { /// already assigned skip the atom and move to the next. This is the /// main map thats used to sort the atoms while comparing two atoms together void LayoutPass::buildOrdinalOverrideMap(MutableFile::DefinedAtomRange &range) { + ScopedTask task(getDefaultDomain(), "LayoutPass::buildOrdinalOverrideMap"); uint64_t index = 0; for (auto ai : range) { const DefinedAtom *atom = ai; |