llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Alex Duran (adurang)

<details>
<summary>Changes</summary>



---
Full diff: https://github.com/llvm/llvm-project/pull/160570.diff


3 Files Affected:

- (modified) clang/tools/offload-arch/CMakeLists.txt (+9-1) 
- (added) clang/tools/offload-arch/LevelZeroArch.cpp (+133) 
- (modified) clang/tools/offload-arch/OffloadArch.cpp (+15-4) 


``````````diff
diff --git a/clang/tools/offload-arch/CMakeLists.txt 
b/clang/tools/offload-arch/CMakeLists.txt
index cb50b9c1d6dde..187c4d9517551 100644
--- a/clang/tools/offload-arch/CMakeLists.txt
+++ b/clang/tools/offload-arch/CMakeLists.txt
@@ -1,8 +1,16 @@
 set(LLVM_LINK_COMPONENTS Support)
 
-add_clang_tool(offload-arch OffloadArch.cpp NVPTXArch.cpp AMDGPUArchByKFD.cpp 
AMDGPUArchByHIP.cpp)
+add_clang_tool(offload-arch OffloadArch.cpp NVPTXArch.cpp AMDGPUArchByKFD.cpp
+               AMDGPUArchByHIP.cpp LevelZeroArch.cpp)
+
+find_path(OFFLOAD_ARCH_LEVEL_ZERO_INCLUDE_DIR NAMES level_zero/ze_api.h)
+if (OFFLOAD_ARCH_LEVEL_ZERO_INCLUDE_DIR)
+  target_include_directories(offload-arch PRIVATE 
${OFFLOAD_ARCH_LEVEL_ZERO_INCLUDE_DIR})
+  target_compile_definitions(offload-arch PRIVATE HAVE_LEVEL_ZERO_HEADERS)
+endif()
 
 add_clang_symlink(amdgpu-arch offload-arch)
 add_clang_symlink(nvptx-arch offload-arch)
+add_clang_symlink(intelgpu-arch offload-arch)
 
 target_link_libraries(offload-arch PRIVATE clangBasic)
diff --git a/clang/tools/offload-arch/LevelZeroArch.cpp 
b/clang/tools/offload-arch/LevelZeroArch.cpp
new file mode 100644
index 0000000000000..8b6b393f6f9f6
--- /dev/null
+++ b/clang/tools/offload-arch/LevelZeroArch.cpp
@@ -0,0 +1,133 @@
+//===- LevelZeroArch.cpp - list installed Level Zero devices ---*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a tool for detecting Level Zero devices installed in 
the
+// system
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef HAVE_LEVEL_ZERO_HEADERS
+
+int printGPUsByLevelZero() {
+   return 0;
+}
+
+#else
+
+#include "clang/Basic/Version.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
+#include <cstdio>
+#include <memory>
+#include <level_zero/ze_api.h>
+
+using namespace llvm;
+extern cl::opt<bool> Verbose;
+
+#define DEFINE_WRAPPER(NAME)                                                   
\
+  using NAME##_ty = decltype(NAME);                                            
\
+  void *NAME##Ptr = nullptr;                                                   
\
+  template <class... Ts> ze_result_t NAME##_wrap(Ts... args) {                 
\
+    if (!NAME##Ptr) {                                                          
\
+      return ZE_RESULT_ERROR_UNKNOWN;                                          
\
+    }                                                                          
\
+    return reinterpret_cast<NAME##_ty *>(NAME##Ptr)(args...);                  
\
+  };
+
+DEFINE_WRAPPER(zeInitDrivers)
+DEFINE_WRAPPER(zeDeviceGet)
+DEFINE_WRAPPER(zeDeviceGetProperties)
+
+static bool loadLevelZero() {
+  const char *L0Library = "libze_loader.so";
+  std::string ErrMsg;
+
+  auto DynlibHandle = std::make_unique<llvm::sys::DynamicLibrary>(
+      llvm::sys::DynamicLibrary::getPermanentLibrary(L0Library, &ErrMsg));
+  if (!DynlibHandle->isValid()) {
+    if (ErrMsg.empty())
+      ErrMsg = "unknown error";
+    if (Verbose)
+      llvm::errs() << "Unable to load library '" << L0Library << "': " << 
ErrMsg
+                   << "!\n";
+    return false;
+  }
+
+  constexpr struct {
+    const char *name;
+    void **fptr;
+  } dlwrap[] = {
+      {"zeInitDrivers", &zeInitDriversPtr},
+      {"zeDeviceGet", &zeDeviceGetPtr},
+      {"zeDeviceGetProperties", &zeDeviceGetPropertiesPtr},
+  };
+
+  for (auto entry : dlwrap) {
+    void *P = DynlibHandle->getAddressOfSymbol(entry.name);
+    if (P == nullptr) {
+      if (Verbose)
+        llvm::errs() << "Unable to find '" << entry.name << "' in '" << 
L0Library
+                     << "'!\n";
+      return false;
+    }
+    *(entry.fptr) = P;
+  }
+
+  return true;
+}
+
+#define CALL_ZE_AND_CHECK(Fn, ...)                                             
\
+  do {                                                                         
\
+    ze_result_t Rc = Fn##_wrap(__VA_ARGS__);                                   
\
+    if (Rc != ZE_RESULT_SUCCESS) {                                             
\
+      if (Verbose)                                                             
\
+        llvm::errs() << "Error: " << __func__ << ":" << #Fn                    
\
+                     << " failed with error code " << Rc << "\n";              
\
+      return 1;                                                                
\
+    }                                                                          
\
+  } while (0)
+
+int printGPUsByLevelZero() {
+  if (!loadLevelZero())
+    return 1;
+
+  ze_init_driver_type_desc_t driver_type = {};
+  driver_type.stype = ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC;
+  driver_type.flags = ZE_INIT_DRIVER_TYPE_FLAG_GPU;
+  driver_type.pNext = nullptr;
+  uint32_t driverCount{0};
+
+  // Initialize and find all drivers
+  CALL_ZE_AND_CHECK(zeInitDrivers, &driverCount, nullptr, &driver_type);
+
+  llvm::SmallVector<ze_driver_handle_t> drivers(driverCount);
+  CALL_ZE_AND_CHECK(zeInitDrivers, &driverCount, drivers.data(), &driver_type);
+
+  for (auto driver : drivers) {
+    // Discover all the devices for a given driver
+    uint32_t deviceCount = 0;
+    CALL_ZE_AND_CHECK(zeDeviceGet, driver, &deviceCount, nullptr);
+
+    llvm::SmallVector<ze_device_handle_t> devices(deviceCount);
+    CALL_ZE_AND_CHECK(zeDeviceGet, driver, &deviceCount, devices.data());
+
+    for (auto device : devices) {
+      // Get device properties
+      ze_device_properties_t deviceProperties;
+      CALL_ZE_AND_CHECK(zeDeviceGetProperties, device, &deviceProperties);
+      // Print device name
+      llvm::outs() << deviceProperties.name << '\n';
+    }
+  }
+
+  return 0;
+}
+
+#endif // HAVE_LEVEL_ZERO_HEADERS
diff --git a/clang/tools/offload-arch/OffloadArch.cpp 
b/clang/tools/offload-arch/OffloadArch.cpp
index 74be40214a0ec..5043c00986a9b 100644
--- a/clang/tools/offload-arch/OffloadArch.cpp
+++ b/clang/tools/offload-arch/OffloadArch.cpp
@@ -21,6 +21,7 @@ enum VendorName {
   all,
   amdgpu,
   nvptx,
+  intel,
 };
 
 static cl::opt<VendorName>
@@ -28,7 +29,8 @@ static cl::opt<VendorName>
          cl::init(all),
          cl::values(clEnumVal(all, "Print all GPUs (default)"),
                     clEnumVal(amdgpu, "Only print AMD GPUs"),
-                    clEnumVal(nvptx, "Only print NVIDIA GPUs")));
+                    clEnumVal(nvptx, "Only print NVIDIA GPUs"),
+                    clEnumVal(intel, "Only print Intel GPUs")));
 
 cl::opt<bool> Verbose("verbose", cl::desc("Enable verbose output"),
                       cl::init(false), cl::cat(OffloadArchCategory));
@@ -40,6 +42,7 @@ static void PrintVersion(raw_ostream &OS) {
 int printGPUsByKFD();
 int printGPUsByHIP();
 int printGPUsByCUDA();
+int printGPUsByLevelZero();
 
 static int printAMD() {
 #ifndef _WIN32
@@ -51,6 +54,7 @@ static int printAMD() {
 }
 
 static int printNVIDIA() { return printGPUsByCUDA(); }
+static int printIntel() { return printGPUsByLevelZero(); }
 
 int main(int argc, char *argv[]) {
   cl::HideUnrelatedOptions(OffloadArchCategory);
@@ -73,15 +77,22 @@ int main(int argc, char *argv[]) {
                     sys::path::stem(argv[0]).starts_with("amdgpu-arch");
   bool NVIDIAOnly = Only == VendorName::nvptx ||
                     sys::path::stem(argv[0]).starts_with("nvptx-arch");
+  bool IntelOnly = Only == VendorName::intel ||
+                   sys::path::stem(argv[0]).starts_with("intelgpu-arch");
+  bool All = !AMDGPUOnly && !NVIDIAOnly && !IntelOnly;
 
   int NVIDIAResult = 0;
-  if (!AMDGPUOnly)
+  if (NVIDIAOnly || All)
     NVIDIAResult = printNVIDIA();
 
   int AMDResult = 0;
-  if (!NVIDIAOnly)
+  if (AMDGPUOnly || All)
     AMDResult = printAMD();
 
+  int IntelResult = 0;
+  if (IntelOnly || All)
+    IntelResult = printIntel();
+
   // We only failed if all cases returned an error.
-  return AMDResult && NVIDIAResult;
+  return AMDResult && NVIDIAResult && IntelResult;
 }

``````````

</details>


https://github.com/llvm/llvm-project/pull/160570
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to