[llvm] f62e5f4 - [MCJIT] Profile the code generated by MCJIT engine using Intel VTune profiler

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 16 01:04:11 PST 2020


Author: Lang Hames
Date: 2020-11-16T19:28:14+11:00
New Revision: f62e5f456917fabaa3c05442d343ea4fb4089a71

URL: https://github.com/llvm/llvm-project/commit/f62e5f456917fabaa3c05442d343ea4fb4089a71
DIFF: https://github.com/llvm/llvm-project/commit/f62e5f456917fabaa3c05442d343ea4fb4089a71.diff

LOG: [MCJIT] Profile the code generated by MCJIT engine using Intel VTune profiler

Patch by Elena Kovanova. Thanks Elena!

Problem:

LLVM already has a feature to profile the JIT-compiled code with VTune. This is
done using Intel JIT Profiling API (https://github.com/intel/ittapi). Function
information is captured by VTune as soon as the function is JIT-compiled. We
tried to use the same approach to report the function information generated by
the MCJIT engine – read parsing the debug information for in-memory ELF module
and report it using JIT API. As the results, we figured out that it did not work
properly for the following cases: inline functions, the functions located in
multiple source files, the functions having several bodies (address ranges).

Solution:

To overcome limitations described above, we have introduced new APIs as a part
of Intel ITT APIs to report the entire in-memory ELF module to be further
processed as regular ELF binaries with debug information.

This patch

1. Switches LLVM to open source version of Intel ITT/JIT APIs
(https://github.com/intel/ittapi) to keep it always up to date.

2. Adds support of profiling the code generated by MCJIT engine using Intel
VTune profiler

Another separate patch will get rid of obsolete Intel ITT APIs stuff, having
LLVM already switched to https://github.com/intel/ittapi.

Differential Revision: https://reviews.llvm.org/D86435

Added: 
    

Modified: 
    llvm/lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt
    llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp
    llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h
    llvm/test/JitListener/lit.local.cfg
    llvm/tools/llvm-jitlistener/llvm-jitlistener.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt b/llvm/lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt
index b56ec508b5a6..7f84b1505813 100644
--- a/llvm/lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt
@@ -1,5 +1,26 @@
 include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/.. )
 
+set(GIT_REPOSITORY https://github.com/intel/ittapi.git)
+set(GIT_TAG v3.18.8)
+
+if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/ittapi)
+    execute_process(COMMAND ${GIT_EXECUTABLE} clone ${GIT_REPOSITORY}
+                    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+                    RESULT_VARIABLE GIT_CLONE_RESULT)
+    if(NOT GIT_CLONE_RESULT EQUAL "0")
+        message(FATAL_ERROR "git clone ${GIT_REPOSITORY} failed with ${GIT_CLONE_RESULT}, please clone ${GIT_REPOSITORY}")
+    endif()
+endif()
+
+execute_process(COMMAND ${GIT_EXECUTABLE} checkout ${GIT_TAG}
+                WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ittapi
+                RESULT_VARIABLE GIT_CHECKOUT_RESULT)
+if(NOT GIT_CHECKOUT_RESULT EQUAL "0")
+    message(FATAL_ERROR "git checkout ${GIT_TAG} failed with ${GIT_CHECKOUT_RESULT}, please checkout ${GIT_TAG} at ${CMAKE_CURRENT_SOURCE_DIR}/ittapi")
+endif()
+
+include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/ittapi/include/ )
+
 if( HAVE_LIBDL )
     set(LLVM_INTEL_JIT_LIBS ${CMAKE_DL_LIBS})
 endif()
@@ -10,6 +31,7 @@ set(LLVM_INTEL_JIT_LIBS ${LLVM_PTHREAD_LIB} ${LLVM_INTEL_JIT_LIBS})
 add_llvm_component_library(LLVMIntelJITEvents
   IntelJITEventListener.cpp
   jitprofiling.c
+  ittapi/src/ittnotify/ittnotify_static.c
 
   LINK_LIBS ${LLVM_INTEL_JIT_LIBS}
 

diff  --git a/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp b/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp
index 1ebc820a8b49..3f75012f5cf9 100644
--- a/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp
+++ b/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "IntelJITEventsWrapper.h"
+#include "ittnotify.h"
 #include "llvm-c/ExecutionEngine.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/CodeGen/MachineFunction.h"
@@ -36,6 +37,86 @@ using namespace llvm::object;
 
 namespace {
 
+class IntelIttnotifyInfo {
+  std::string ModuleName;
+  std::vector<std::string> SectionNamesVector;
+  std::vector<__itt_section_info> SectionInfoVector;
+  __itt_module_object *ModuleObject;
+  IntelJITEventsWrapper &WrapperRef;
+
+public:
+  IntelIttnotifyInfo(IntelJITEventsWrapper &Wrapper)
+      : ModuleObject(NULL), WrapperRef(Wrapper){};
+  ~IntelIttnotifyInfo() { delete ModuleObject; };
+
+  void setModuleName(const char *Name) { ModuleName = std::string(Name); }
+
+  const char *getModuleName() { return ModuleName.c_str(); }
+
+  void setModuleObject(__itt_module_object *ModuleObj) {
+    ModuleObject = ModuleObj;
+  }
+
+  __itt_module_object *getModuleObject() { return ModuleObject; }
+
+  __itt_section_info *getSectionInfoVectorBegin() {
+    if (SectionInfoVector.size())
+      return &SectionInfoVector[0];
+    return NULL;
+  }
+
+  void reportSection(llvm::IttEventType EventType, const char *SectionName,
+                     unsigned int SectionSize) {
+    WrapperRef.iJitIttNotifyInfo(EventType, SectionName, SectionSize);
+  }
+
+  int fillSectionInformation(const ObjectFile &Obj,
+                             const RuntimeDyld::LoadedObjectInfo &L) {
+
+    int SectionCounter = 0;
+
+    for (auto &Section : Obj.sections()) {
+      uint64_t SectionLoadAddr = L.getSectionLoadAddress(Section);
+      if (SectionLoadAddr) {
+        object::ELFSectionRef ElfSection(Section);
+
+        __itt_section_info SectionInfo;
+        memset(&SectionInfo, 0, sizeof(SectionInfo));
+        SectionInfo.start_addr = reinterpret_cast<void *>(SectionLoadAddr);
+        SectionInfo.file_offset = ElfSection.getOffset();
+        SectionInfo.flags = ElfSection.getFlags();
+
+        StringRef SectionName("");
+        auto SectionNameOrError = ElfSection.getName();
+        if (SectionNameOrError)
+          SectionName = *SectionNameOrError;
+
+        SectionNamesVector.push_back(SectionName.str());
+        SectionInfo.size = ElfSection.getSize();
+        reportSection(llvm::LoadBinarySection, SectionName.str().c_str(),
+                      SectionInfo.size);
+
+        if (ElfSection.isBSS()) {
+          SectionInfo.type = itt_section_type_bss;
+        } else if (ElfSection.isData()) {
+          SectionInfo.type = itt_section_type_data;
+        } else if (ElfSection.isText()) {
+          SectionInfo.type = itt_section_type_text;
+        }
+        SectionInfoVector.push_back(SectionInfo);
+        ++SectionCounter;
+      }
+    }
+    // Hereinafter: don't change SectionNamesVector content to avoid vector
+    // reallocation - reallocation invalidates all the references, pointers, and
+    // iterators referring to the elements in the sequence.
+    for (int I = 0; I < SectionCounter; ++I) {
+      SectionInfoVector[I].name = SectionNamesVector[I].c_str();
+    }
+    return SectionCounter;
+  }
+};
+
 class IntelJITEventListener : public JITEventListener {
   typedef DenseMap<void*, unsigned int> MethodIDMap;
 
@@ -48,6 +129,8 @@ class IntelJITEventListener : public JITEventListener {
   ObjectMap  LoadedObjectMap;
   std::map<ObjectKey, OwningBinary<ObjectFile>> DebugObjects;
 
+  std::map<ObjectKey, std::unique_ptr<IntelIttnotifyInfo>> KeyToIttnotify;
+
 public:
   IntelJITEventListener(IntelJITEventsWrapper* libraryWrapper) {
       Wrapper.reset(libraryWrapper);
@@ -95,146 +178,205 @@ static iJIT_Method_Load FunctionDescToIntelJITFormat(
   return Result;
 }
 
+int getBackwardCompatibilityMode() {
+
+  char *BackwardCompatibilityEnv = getenv("INTEL_JIT_BACKWARD_COMPATIBILITY");
+  int BackwardCompatibilityMode = 0;
+  if (BackwardCompatibilityEnv) {
+    StringRef(BackwardCompatibilityEnv)
+        .getAsInteger(10, BackwardCompatibilityMode);
+  }
+  return BackwardCompatibilityMode;
+}
+
 void IntelJITEventListener::notifyObjectLoaded(
     ObjectKey Key, const ObjectFile &Obj,
     const RuntimeDyld::LoadedObjectInfo &L) {
 
-  OwningBinary<ObjectFile> DebugObjOwner = L.getObjectForDebug(Obj);
-  const ObjectFile *DebugObj = DebugObjOwner.getBinary();
-  if (!DebugObj)
-    return;
-
-  // Get the address of the object image for use as a unique identifier
-  const void* ObjData = DebugObj->getData().data();
-  std::unique_ptr<DIContext> Context = DWARFContext::create(*DebugObj);
-  MethodAddressVector Functions;
-
-  // Use symbol info to iterate functions in the object.
-  for (const std::pair<SymbolRef, uint64_t> &P : computeSymbolSizes(*DebugObj)) {
-    SymbolRef Sym = P.first;
-    std::vector<LineNumberInfo> LineInfo;
-    std::string SourceFileName;
-
-    Expected<SymbolRef::Type> SymTypeOrErr = Sym.getType();
-    if (!SymTypeOrErr) {
-      // TODO: Actually report errors helpfully.
-      consumeError(SymTypeOrErr.takeError());
-      continue;
+  int BackwardCompatibilityMode = getBackwardCompatibilityMode();
+  if (BackwardCompatibilityMode == 0) {
+    if (Obj.isELF()) {
+      std::unique_ptr<IntelIttnotifyInfo> ModuleIttnotify =
+          std::make_unique<IntelIttnotifyInfo>(*Wrapper);
+      ModuleIttnotify->setModuleName(
+          StringRef(llvm::utohexstr(
+                        MD5Hash(Obj.getMemoryBufferRef().getBuffer()), true))
+              .str()
+              .c_str());
+
+      __itt_module_object *ModuleObject = new __itt_module_object();
+      ModuleObject->module_name = ModuleIttnotify->getModuleName();
+      ModuleObject->module_size = Obj.getMemoryBufferRef().getBufferSize();
+      Wrapper->iJitIttNotifyInfo(llvm::LoadBinaryModule,
+                                 ModuleObject->module_name,
+                                 ModuleObject->module_size);
+      ModuleObject->module_type = __itt_module_type_elf;
+      ModuleObject->section_number =
+          ModuleIttnotify->fillSectionInformation(Obj, L);
+      ModuleObject->module_buffer =
+          (void *)const_cast<char *>(Obj.getMemoryBufferRef().getBufferStart());
+      ModuleObject->module_id =
+          __itt_id_make((void *)&(*ModuleObject), ModuleObject->module_size);
+      ModuleObject->section_array =
+          ModuleIttnotify->getSectionInfoVectorBegin();
+      ModuleIttnotify->setModuleObject(ModuleObject);
+
+      __itt_module_load_with_sections(ModuleObject);
+
+      KeyToIttnotify[Key] = std::move(ModuleIttnotify);
     }
-    SymbolRef::Type SymType = *SymTypeOrErr;
-    if (SymType != SymbolRef::ST_Function)
-      continue;
-
-    Expected<StringRef> Name = Sym.getName();
-    if (!Name) {
-      // TODO: Actually report errors helpfully.
-      consumeError(Name.takeError());
-      continue;
+  } else if (BackwardCompatibilityMode == 1) {
+
+    OwningBinary<ObjectFile> DebugObjOwner = L.getObjectForDebug(Obj);
+    const ObjectFile *DebugObj = DebugObjOwner.getBinary();
+    if (!DebugObj)
+      return;
+
+    // Get the address of the object image for use as a unique identifier
+    const void *ObjData = DebugObj->getData().data();
+    std::unique_ptr<DIContext> Context = DWARFContext::create(*DebugObj);
+    MethodAddressVector Functions;
+
+    // Use symbol info to iterate functions in the object.
+    for (const std::pair<SymbolRef, uint64_t> &P :
+         computeSymbolSizes(*DebugObj)) {
+      SymbolRef Sym = P.first;
+      std::vector<LineNumberInfo> LineInfo;
+      std::string SourceFileName;
+
+      Expected<SymbolRef::Type> SymTypeOrErr = Sym.getType();
+      if (!SymTypeOrErr) {
+        // TODO: Actually report errors helpfully.
+        consumeError(SymTypeOrErr.takeError());
+        continue;
+      }
+      SymbolRef::Type SymType = *SymTypeOrErr;
+      if (SymType != SymbolRef::ST_Function)
+        continue;
+
+      Expected<StringRef> Name = Sym.getName();
+      if (!Name) {
+        // TODO: Actually report errors helpfully.
+        consumeError(Name.takeError());
+        continue;
+      }
+
+      Expected<uint64_t> AddrOrErr = Sym.getAddress();
+      if (!AddrOrErr) {
+        // TODO: Actually report errors helpfully.
+        consumeError(AddrOrErr.takeError());
+        continue;
+      }
+      uint64_t Addr = *AddrOrErr;
+      uint64_t Size = P.second;
+
+      auto SecOrErr = Sym.getSection();
+      if (!SecOrErr) {
+        // TODO: Actually report errors helpfully.
+        consumeError(SecOrErr.takeError());
+        continue;
+      }
+      object::section_iterator Sec = *SecOrErr;
+      if (Sec == Obj.section_end())
+        continue;
+      uint64_t Index = Sec->getIndex();
+
+      // Record this address in a local vector
+      Functions.push_back((void *)Addr);
+
+      // Build the function loaded notification message
+      iJIT_Method_Load FunctionMessage =
+          FunctionDescToIntelJITFormat(*Wrapper, Name->data(), Addr, Size);
+      DILineInfoTable Lines =
+          Context->getLineInfoForAddressRange({Addr, Index}, Size);
+      DILineInfoTable::iterator Begin = Lines.begin();
+      DILineInfoTable::iterator End = Lines.end();
+      for (DILineInfoTable::iterator It = Begin; It != End; ++It) {
+        LineInfo.push_back(
+            DILineInfoToIntelJITFormat((uintptr_t)Addr, It->first, It->second));
+      }
+      if (LineInfo.size() == 0) {
+        FunctionMessage.source_file_name = 0;
+        FunctionMessage.line_number_size = 0;
+        FunctionMessage.line_number_table = 0;
+      } else {
+        // Source line information for the address range is provided as
+        // a code offset for the start of the corresponding sub-range and
+        // a source line. JIT API treats offsets in LineNumberInfo structures
+        // as the end of the corresponding code region. The start of the code
+        // is taken from the previous element. Need to shift the elements.
+
+        LineNumberInfo last = LineInfo.back();
+        last.Offset = FunctionMessage.method_size;
+        LineInfo.push_back(last);
+        for (size_t i = LineInfo.size() - 2; i > 0; --i)
+          LineInfo[i].LineNumber = LineInfo[i - 1].LineNumber;
+
+        SourceFileName = Lines.front().second.FileName;
+        FunctionMessage.source_file_name =
+            const_cast<char *>(SourceFileName.c_str());
+        FunctionMessage.line_number_size = LineInfo.size();
+        FunctionMessage.line_number_table = &*LineInfo.begin();
+      }
+
+      Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED,
+                                &FunctionMessage);
+      MethodIDs[(void *)Addr] = FunctionMessage.method_id;
     }
 
-    Expected<uint64_t> AddrOrErr = Sym.getAddress();
-    if (!AddrOrErr) {
-      // TODO: Actually report errors helpfully.
-      consumeError(AddrOrErr.takeError());
-      continue;
-    }
-    uint64_t Addr = *AddrOrErr;
-    uint64_t Size = P.second;
-
-    auto SecOrErr = Sym.getSection();
-    if (!SecOrErr) {
-      // TODO: Actually report errors helpfully.
-      consumeError(SecOrErr.takeError());
-      continue;
-    }
-    object::section_iterator Sec = *SecOrErr;
-    if (Sec == Obj.section_end())
-      continue;
-    uint64_t Index = Sec->getIndex();
-
-    // Record this address in a local vector
-    Functions.push_back((void*)Addr);
-
-    // Build the function loaded notification message
-    iJIT_Method_Load FunctionMessage =
-      FunctionDescToIntelJITFormat(*Wrapper, Name->data(), Addr, Size);
-    DILineInfoTable Lines =
-      Context->getLineInfoForAddressRange({Addr, Index}, Size);
-    DILineInfoTable::iterator Begin = Lines.begin();
-    DILineInfoTable::iterator End = Lines.end();
-    for (DILineInfoTable::iterator It = Begin; It != End; ++It) {
-      LineInfo.push_back(
-          DILineInfoToIntelJITFormat((uintptr_t)Addr, It->first, It->second));
-    }
-    if (LineInfo.size() == 0) {
-      FunctionMessage.source_file_name = 0;
-      FunctionMessage.line_number_size = 0;
-      FunctionMessage.line_number_table = 0;
-    } else {
-      // Source line information for the address range is provided as
-      // a code offset for the start of the corresponding sub-range and
-      // a source line. JIT API treats offsets in LineNumberInfo structures
-      // as the end of the corresponding code region. The start of the code
-      // is taken from the previous element. Need to shift the elements.
-
-      LineNumberInfo last = LineInfo.back();
-      last.Offset = FunctionMessage.method_size;
-      LineInfo.push_back(last);
-      for (size_t i = LineInfo.size() - 2; i > 0; --i)
-        LineInfo[i].LineNumber = LineInfo[i - 1].LineNumber;
-
-      SourceFileName = Lines.front().second.FileName;
-      FunctionMessage.source_file_name =
-        const_cast<char *>(SourceFileName.c_str());
-      FunctionMessage.line_number_size = LineInfo.size();
-      FunctionMessage.line_number_table = &*LineInfo.begin();
-    }
-
-    Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED,
-                              &FunctionMessage);
-    MethodIDs[(void*)Addr] = FunctionMessage.method_id;
+    // To support object unload notification, we need to keep a list of
+    // registered function addresses for each loaded object.  We will
+    // use the MethodIDs map to get the registered ID for each function.
+    LoadedObjectMap[ObjData] = Functions;
+    DebugObjects[Key] = std::move(DebugObjOwner);
   }
-
-  // To support object unload notification, we need to keep a list of
-  // registered function addresses for each loaded object.  We will
-  // use the MethodIDs map to get the registered ID for each function.
-  LoadedObjectMap[ObjData] = Functions;
-  DebugObjects[Key] = std::move(DebugObjOwner);
 }
 
 void IntelJITEventListener::notifyFreeingObject(ObjectKey Key) {
-  // This object may not have been registered with the listener. If it wasn't,
-  // bail out.
-  if (DebugObjects.find(Key) == DebugObjects.end())
-    return;
-
-  // Get the address of the object image for use as a unique identifier
-  const ObjectFile &DebugObj = *DebugObjects[Key].getBinary();
-  const void* ObjData = DebugObj.getData().data();
-
-  // Get the object's function list from LoadedObjectMap
-  ObjectMap::iterator OI = LoadedObjectMap.find(ObjData);
-  if (OI == LoadedObjectMap.end())
-    return;
-  MethodAddressVector& Functions = OI->second;
-
-  // Walk the function list, unregistering each function
-  for (MethodAddressVector::iterator FI = Functions.begin(),
-                                     FE = Functions.end();
-       FI != FE;
-       ++FI) {
-    void* FnStart = const_cast<void*>(*FI);
-    MethodIDMap::iterator MI = MethodIDs.find(FnStart);
-    if (MI != MethodIDs.end()) {
-      Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_UNLOAD_START,
-                                &MI->second);
-      MethodIDs.erase(MI);
+
+  int BackwardCompatibilityMode = getBackwardCompatibilityMode();
+  if (BackwardCompatibilityMode == 0) {
+    if (KeyToIttnotify.find(Key) == KeyToIttnotify.end())
+      return;
+    __itt_module_unload_with_sections(KeyToIttnotify[Key]->getModuleObject());
+    Wrapper->iJitIttNotifyInfo(
+        llvm::UnloadBinaryModule,
+        KeyToIttnotify[Key]->getModuleObject()->module_name,
+        KeyToIttnotify[Key]->getModuleObject()->module_size);
+    KeyToIttnotify.erase(Key);
+  } else if (BackwardCompatibilityMode == 1) {
+    // This object may not have been registered with the listener. If it wasn't,
+    // bail out.
+    if (DebugObjects.find(Key) == DebugObjects.end())
+      return;
+
+    // Get the address of the object image for use as a unique identifier
+    const ObjectFile &DebugObj = *DebugObjects[Key].getBinary();
+    const void *ObjData = DebugObj.getData().data();
+
+    // Get the object's function list from LoadedObjectMap
+    ObjectMap::iterator OI = LoadedObjectMap.find(ObjData);
+    if (OI == LoadedObjectMap.end())
+      return;
+    MethodAddressVector &Functions = OI->second;
+
+    // Walk the function list, unregistering each function
+    for (MethodAddressVector::iterator FI = Functions.begin(),
+                                       FE = Functions.end();
+         FI != FE; ++FI) {
+      void *FnStart = const_cast<void *>(*FI);
+      MethodIDMap::iterator MI = MethodIDs.find(FnStart);
+      if (MI != MethodIDs.end()) {
+        Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_UNLOAD_START,
+                                  &MI->second);
+        MethodIDs.erase(MI);
+      }
     }
-  }
 
-  // Erase the object from LoadedObjectMap
-  LoadedObjectMap.erase(OI);
-  DebugObjects.erase(Key);
+    // Erase the object from LoadedObjectMap
+    LoadedObjectMap.erase(OI);
+    DebugObjects.erase(Key);
+  }
 }
 
 }  // anonymous namespace.

diff  --git a/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h b/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h
index 68699c6a2200..088b33b798a3 100644
--- a/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h
+++ b/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h
@@ -21,10 +21,18 @@
 
 namespace llvm {
 
+typedef enum {
+  LoadBinaryModule,
+  LoadBinarySection,
+  UnloadBinaryModule,
+  UnloadBinarySection
+} IttEventType;
+
 class IntelJITEventsWrapper {
   // Function pointer types for testing implementation of Intel jitprofiling
   // library
   typedef int (*NotifyEventPtr)(iJIT_JVM_EVENT, void*);
+  typedef int (*IttnotifyInfoPtr)(IttEventType, const char *, unsigned int);
   typedef void (*RegisterCallbackExPtr)(void *, iJIT_ModeChangedEx );
   typedef iJIT_IsProfilingActiveFlags (*IsProfilingActivePtr)(void);
   typedef void (*FinalizeThreadPtr)(void);
@@ -32,6 +40,7 @@ class IntelJITEventsWrapper {
   typedef unsigned int (*GetNewMethodIDPtr)(void);
 
   NotifyEventPtr NotifyEventFunc;
+  IttnotifyInfoPtr IttnotifyInfoFunc;
   RegisterCallbackExPtr RegisterCallbackExFunc;
   IsProfilingActivePtr IsProfilingActiveFunc;
   GetNewMethodIDPtr GetNewMethodIDFunc;
@@ -42,23 +51,22 @@ class IntelJITEventsWrapper {
   }
 
   IntelJITEventsWrapper()
-  : NotifyEventFunc(::iJIT_NotifyEvent),
-    RegisterCallbackExFunc(::iJIT_RegisterCallbackEx),
-    IsProfilingActiveFunc(::iJIT_IsProfilingActive),
-    GetNewMethodIDFunc(::iJIT_GetNewMethodID) {
-  }
+      : NotifyEventFunc(::iJIT_NotifyEvent), IttnotifyInfoFunc(0),
+        RegisterCallbackExFunc(::iJIT_RegisterCallbackEx),
+        IsProfilingActiveFunc(::iJIT_IsProfilingActive),
+        GetNewMethodIDFunc(::iJIT_GetNewMethodID) {}
 
   IntelJITEventsWrapper(NotifyEventPtr NotifyEventImpl,
-                   RegisterCallbackExPtr RegisterCallbackExImpl,
-                   IsProfilingActivePtr IsProfilingActiveImpl,
-                   FinalizeThreadPtr FinalizeThreadImpl,
-                   FinalizeProcessPtr FinalizeProcessImpl,
-                   GetNewMethodIDPtr GetNewMethodIDImpl)
-  : NotifyEventFunc(NotifyEventImpl),
-    RegisterCallbackExFunc(RegisterCallbackExImpl),
-    IsProfilingActiveFunc(IsProfilingActiveImpl),
-    GetNewMethodIDFunc(GetNewMethodIDImpl) {
-  }
+                        IttnotifyInfoPtr IttnotifyInfoImpl,
+                        RegisterCallbackExPtr RegisterCallbackExImpl,
+                        IsProfilingActivePtr IsProfilingActiveImpl,
+                        FinalizeThreadPtr FinalizeThreadImpl,
+                        FinalizeProcessPtr FinalizeProcessImpl,
+                        GetNewMethodIDPtr GetNewMethodIDImpl)
+      : NotifyEventFunc(NotifyEventImpl), IttnotifyInfoFunc(IttnotifyInfoImpl),
+        RegisterCallbackExFunc(RegisterCallbackExImpl),
+        IsProfilingActiveFunc(IsProfilingActiveImpl),
+        GetNewMethodIDFunc(GetNewMethodIDImpl) {}
 
   // Sends an event announcing that a function has been emitted
   //   return values are event-specific.  See Intel documentation for details.
@@ -68,6 +76,13 @@ class IntelJITEventsWrapper {
     return NotifyEventFunc(EventType, EventSpecificData);
   }
 
+  int iJitIttNotifyInfo(IttEventType EventType, const char *Name,
+                        unsigned int Size) {
+    if (!IttnotifyInfoFunc)
+      return -1;
+    return IttnotifyInfoFunc(EventType, Name, Size);
+  }
+
   // Registers a callback function to receive notice of profiling state changes
   void iJIT_RegisterCallbackEx(void *UserData,
                                iJIT_ModeChangedEx NewModeCallBackFuncEx) {

diff  --git a/llvm/test/JitListener/lit.local.cfg b/llvm/test/JitListener/lit.local.cfg
index 50a54ebe7ea8..1576fbe9edd2 100644
--- a/llvm/test/JitListener/lit.local.cfg
+++ b/llvm/test/JitListener/lit.local.cfg
@@ -1,2 +1,3 @@
 if not config.root.llvm_use_intel_jitevents:
     config.unsupported = True
+config.environment['INTEL_JIT_BACKWARD_COMPATIBILITY'] = '1'

diff  --git a/llvm/tools/llvm-jitlistener/llvm-jitlistener.cpp b/llvm/tools/llvm-jitlistener/llvm-jitlistener.cpp
index 82a798d3f74d..52428dc758e1 100644
--- a/llvm/tools/llvm-jitlistener/llvm-jitlistener.cpp
+++ b/llvm/tools/llvm-jitlistener/llvm-jitlistener.cpp
@@ -88,6 +88,46 @@ int NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) {
   return 0;
 }
 
+int ittNotifyInfo(IttEventType EventType, const char *Name, unsigned int Size) {
+  switch (EventType) {
+  case LoadBinaryModule: {
+    if (!Name) {
+      errs() << "Error: The IttNotify event listener did not provide a module "
+                "name.";
+      return -1;
+    }
+    outs() << "Module loaded : Name = " << Name << ", Size = " << Size << "\n";
+  } break;
+  case LoadBinarySection: {
+    if (!Name) {
+      errs() << "Error: The IttNotify event listener did not provide a section "
+                "name.";
+      return -1;
+    }
+    outs() << "Loaded section : Name = " << Name << ", Size = " << Size << "\n";
+  } break;
+  case UnloadBinaryModule: {
+    if (!Name) {
+      errs() << "Error: The IttNotify event listener did not provide a module "
+                "name.";
+      return -1;
+    }
+    outs() << "Module unloaded : Name = " << Name << ", Size = " << Size
+           << "\n";
+  } break;
+  case UnloadBinarySection: {
+    if (!Name) {
+      errs() << "Error: The IttNotify event listener did not provide a section "
+                "name.";
+      return -1;
+    }
+    outs() << "Unloaded section : Name = " << Name << ", Size = " << Size
+           << "\n";
+  } break;
+  }
+  return 0;
+}
+
 iJIT_IsProfilingActiveFlags IsProfilingActive(void) {
   // for testing, pretend we have an Intel Parallel Amplifier XE 2011
   // instance attached
@@ -155,7 +195,8 @@ class JitEventListenerTest {
 
     std::unique_ptr<llvm::JITEventListener> Listener(
         JITEventListener::createIntelJITEventListener(new IntelJITEventsWrapper(
-            NotifyEvent, 0, IsProfilingActive, 0, 0, GetNewMethodID)));
+            NotifyEvent, ittNotifyInfo, 0, IsProfilingActive, 0, 0,
+            GetNewMethodID)));
 
     TheJIT->RegisterJITEventListener(Listener.get());
 


        


More information about the llvm-commits mailing list