summaryrefslogtreecommitdiffstats
path: root/lld
diff options
context:
space:
mode:
Diffstat (limited to 'lld')
-rw-r--r--lld/CMakeLists.txt14
-rw-r--r--lld/cmake/modules/FindVTune.cmake31
-rw-r--r--lld/include/lld/Core/Instrumentation.h129
-rw-r--r--lld/lib/Core/PassManager.cpp2
-rw-r--r--lld/lib/Passes/LayoutPass.cpp7
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;
OpenPOWER on IntegriCloud