diff --git a/openmp/libomptarget/plugins-nextgen/amdgpu/utils/UtilitiesRTL.h b/openmp/libomptarget/plugins-nextgen/amdgpu/utils/UtilitiesRTL.h new file mode 100644 --- /dev/null +++ b/openmp/libomptarget/plugins-nextgen/amdgpu/utils/UtilitiesRTL.h @@ -0,0 +1,134 @@ +//===----RTLs/amdgpu/utils/UtilitiesRTL.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 +// +//===----------------------------------------------------------------------===// +// +// RTL Utilities for AMDGPU plugins +// +//===----------------------------------------------------------------------===// + +#include + +#include "Debug.h" +#include "omptarget.h" + +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" + +namespace llvm { +namespace omp { +namespace target { +namespace plugin { +namespace utils { + +// The implicit arguments of AMDGPU kernels. +struct AMDGPUImplicitArgsTy { + uint64_t OffsetX; + uint64_t OffsetY; + uint64_t OffsetZ; + uint64_t HostcallPtr; + uint64_t Unused0; + uint64_t Unused1; + uint64_t Unused2; +}; + +static_assert(sizeof(AMDGPUImplicitArgsTy) == 56, + "Unexpected size of implicit arguments"); + +/// Parse a TargetID to get processor arch and feature map. +/// Returns processor subarch. +/// Returns TargetID features in \p FeatureMap argument. +/// If the \p TargetID contains feature+, FeatureMap it to true. +/// If the \p TargetID contains feature-, FeatureMap it to false. +/// If the \p TargetID does not contain a feature (default), do not map it. +StringRef parseTargetID(StringRef TargetID, StringMap &FeatureMap) { + if (TargetID.empty()) + return llvm::StringRef(); + + auto ArchFeature = TargetID.split(":"); + auto Arch = ArchFeature.first; + auto Features = ArchFeature.second; + if (Features.empty()) + return Arch; + + if (Features.contains("sramecc+")) { + FeatureMap.insert(std::pair("sramecc", true)); + } else if (Features.contains("sramecc-")) { + FeatureMap.insert(std::pair("sramecc", false)); + } + if (Features.contains("xnack+")) { + FeatureMap.insert(std::pair("xnack", true)); + } else if (Features.contains("xnack-")) { + FeatureMap.insert(std::pair("xnack", false)); + } + + return Arch; +} + +/// Check if an image is compatible with current system's environment. +bool isImageCompatibleWithEnv(const __tgt_image_info *Info, + StringRef EnvTargetID) { + llvm::StringRef ImageTargetID(Info->Arch); + + // Compatible in case of exact match. + if (ImageTargetID == EnvTargetID) { + DP("Compatible: Exact match \t[Image: %s]\t:\t[Env: %s]\n", + ImageTargetID.data(), EnvTargetID.data()); + return true; + } + + // Incompatible if Archs mismatch. + StringMap ImgMap, EnvMap; + StringRef ImgArch = utils::parseTargetID(ImageTargetID, ImgMap); + StringRef EnvArch = utils::parseTargetID(EnvTargetID, EnvMap); + + // Both EnvArch and ImgArch can't be empty here. + if (EnvArch.empty() || ImgArch.empty() || !ImgArch.contains(EnvArch)) { + DP("Incompatible: Processor mismatch \t[Image: %s]\t:\t[Env: %s]\n", + ImageTargetID.data(), EnvTargetID.data()); + return false; + } + + // Incompatible if image has more features than the environment, + // irrespective of type or sign of features. + if (ImgMap.size() > EnvMap.size()) { + DP("Incompatible: Image has more features than the Environment \t[Image: " + "%s]\t:\t[Env: %s]\n", + ImageTargetID.data(), EnvTargetID.data()); + return false; + } + + // Compatible if each target feature specified by the environment is + // compatible with target feature of the image. The target feature is + // compatible if the iamge does not specify it (meaning Any), or if it + // specifies it with the same value (meaning On or Off). + for (const auto &ImgFeature : ImgMap) { + auto EnvFeature = EnvMap.find(ImgFeature.first()); + if (EnvFeature == EnvMap.end() || + (EnvFeature->first() == ImgFeature.first() && + EnvFeature->second != ImgFeature.second)) { + DP("Incompatible: Value of Image's non-ANY feature is not matching with " + "the Environment's non-ANY feature \t[Image: %s]\t:\t[Env: %s]\n", + ImageTargetID.data(), EnvTargetID.data()); + return false; + } + } + + // Image is compatible if all features of Environment are: + // - either, present in the Image's features map with the same sign, + // - or, the feature is missing from Image's features map i.e. it is + // set to ANY + DP("Compatible: Target IDs are compatible \t[Image: %s]\t:\t[Env: %s]\n", + ImageTargetID.data(), EnvTargetID.data()); + + return true; +} + +} // namespace utils +} // namespace plugin +} // namespace target +} // namespace omp +} // namespace llvm diff --git a/openmp/libomptarget/plugins/amdgpu/CMakeLists.txt b/openmp/libomptarget/plugins/amdgpu/CMakeLists.txt --- a/openmp/libomptarget/plugins/amdgpu/CMakeLists.txt +++ b/openmp/libomptarget/plugins/amdgpu/CMakeLists.txt @@ -74,6 +74,7 @@ ADDITIONAL_HEADER_DIRS ${LIBOMPTARGET_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/impl + ${CMAKE_CURRENT_SOURCE_DIR}/../../plugins-nextgen/amdgpu/utils LINK_COMPONENTS Support @@ -96,6 +97,7 @@ PRIVATE ${LIBOMPTARGET_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/impl + ${CMAKE_CURRENT_SOURCE_DIR}/../../plugins-nextgen/amdgpu/utils ) diff --git a/openmp/libomptarget/plugins/amdgpu/impl/internal.h b/openmp/libomptarget/plugins/amdgpu/impl/internal.h --- a/openmp/libomptarget/plugins/amdgpu/impl/internal.h +++ b/openmp/libomptarget/plugins/amdgpu/impl/internal.h @@ -33,17 +33,6 @@ #define MAX_NUM_KERNELS (1024 * 16) -typedef struct impl_implicit_args_s { - uint64_t offset_x; - uint64_t offset_y; - uint64_t offset_z; - uint64_t hostcall_ptr; - uint64_t unused0; - uint64_t unused1; - uint64_t unused2; -} impl_implicit_args_t; -static_assert(sizeof(impl_implicit_args_t) == 56, ""); - // ---------------------- Kernel Start ------------- typedef struct atl_kernel_info_s { uint64_t kernel_object; diff --git a/openmp/libomptarget/plugins/amdgpu/src/rtl.cpp b/openmp/libomptarget/plugins/amdgpu/src/rtl.cpp --- a/openmp/libomptarget/plugins/amdgpu/src/rtl.cpp +++ b/openmp/libomptarget/plugins/amdgpu/src/rtl.cpp @@ -10,7 +10,6 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" #include "llvm/Frontend/OpenMP/OMPGridValues.h" @@ -34,6 +33,7 @@ #include "impl_runtime.h" #include "interop_hsa.h" +#include "UtilitiesRTL.h" #include "internal.h" #include "rt.h" @@ -45,6 +45,7 @@ using namespace llvm; using namespace llvm::object; using namespace llvm::ELF; +using namespace llvm::omp::target::plugin::utils; // hostrpc interface, FIXME: consider moving to its own include these are // statically linked into amdgpu/plugin if present from hostrpc_services.a, @@ -126,7 +127,7 @@ std::queue FreeKernargSegments; uint32_t kernargSizeIncludingImplicit() { - return KernargSegmentSize + sizeof(impl_implicit_args_t); + return KernargSegmentSize + sizeof(AMDGPUImplicitArgsTy); } ~KernelArgPool() { @@ -1487,13 +1488,13 @@ } // Initialize implicit arguments. TODO: Which of these can be dropped - impl_implicit_args_t *ImplArgs = reinterpret_cast( + AMDGPUImplicitArgsTy *ImplArgs = reinterpret_cast( static_cast(KernArg) + ArgPool->KernargSegmentSize); memset(ImplArgs, 0, - sizeof(impl_implicit_args_t)); // may not be necessary - ImplArgs->offset_x = 0; - ImplArgs->offset_y = 0; - ImplArgs->offset_z = 0; + sizeof(AMDGPUImplicitArgsTy)); // may not be necessary + ImplArgs->OffsetX = 0; + ImplArgs->OffsetY = 0; + ImplArgs->OffsetZ = 0; // assign a hostcall buffer for the selected Q if (__atomic_load_n(&DeviceInfo().HostcallRequired, __ATOMIC_ACQUIRE)) { @@ -1529,7 +1530,7 @@ } // initialise pointer for implicit_argument_count == 0 ABI - ImplArgs->hostcall_ptr = Buffer; + ImplArgs->HostcallPtr = Buffer; } Packet->kernarg_address = KernArg; @@ -1847,101 +1848,6 @@ return HSA_STATUS_SUCCESS; } -/// Parse a TargetID to get processor arch and feature map. -/// Returns processor subarch. -/// Returns TargetID features in \p FeatureMap argument. -/// If the \p TargetID contains feature+, FeatureMap it to true. -/// If the \p TargetID contains feature-, FeatureMap it to false. -/// If the \p TargetID does not contain a feature (default), do not map it. -StringRef parseTargetID(StringRef TargetID, StringMap &FeatureMap) { - if (TargetID.empty()) - return llvm::StringRef(); - - auto ArchFeature = TargetID.split(":"); - auto Arch = ArchFeature.first; - auto Features = ArchFeature.second; - if (Features.empty()) - return Arch; - - if (Features.contains("sramecc+")) { - FeatureMap.insert(std::pair("sramecc", true)); - } else if (Features.contains("sramecc-")) { - FeatureMap.insert(std::pair("sramecc", false)); - } - if (Features.contains("xnack+")) { - FeatureMap.insert(std::pair("xnack", true)); - } else if (Features.contains("xnack-")) { - FeatureMap.insert(std::pair("xnack", false)); - } - - return Arch; -} - -/// Checks if an image \p ImgInfo is compatible with current -/// system's environment \p EnvInfo -bool IsImageCompatibleWithEnv(const char *ImgInfo, std::string EnvInfo) { - llvm::StringRef ImgTID(ImgInfo), EnvTID(EnvInfo); - - // Compatible in case of exact match - if (ImgTID == EnvTID) { - DP("Compatible: Exact match \t[Image: %s]\t:\t[Environment: %s]\n", - ImgTID.data(), EnvTID.data()); - return true; - } - - // Incompatible if Archs mismatch. - StringMap ImgMap, EnvMap; - StringRef ImgArch = parseTargetID(ImgTID, ImgMap); - StringRef EnvArch = parseTargetID(EnvTID, EnvMap); - - // Both EnvArch and ImgArch can't be empty here. - if (EnvArch.empty() || ImgArch.empty() || !ImgArch.contains(EnvArch)) { - DP("Incompatible: Processor mismatch \t[Image: %s]\t:\t[Environment: %s]\n", - ImgTID.data(), EnvTID.data()); - return false; - } - - // Incompatible if image has more features than the environment, irrespective - // of type or sign of features. - if (ImgMap.size() > EnvMap.size()) { - DP("Incompatible: Image has more features than the environment \t[Image: " - "%s]\t:\t[Environment: %s]\n", - ImgTID.data(), EnvTID.data()); - return false; - } - - // Compatible if each target feature specified by the environment is - // compatible with target feature of the image. The target feature is - // compatible if the iamge does not specify it (meaning Any), or if it - // specifies it with the same value (meaning On or Off). - for (const auto &ImgFeature : ImgMap) { - auto EnvFeature = EnvMap.find(ImgFeature.first()); - if (EnvFeature == EnvMap.end()) { - DP("Incompatible: Value of Image's non-ANY feature is not matching with " - "the Environment feature's ANY value \t[Image: %s]\t:\t[Environment: " - "%s]\n", - ImgTID.data(), EnvTID.data()); - return false; - } else if (EnvFeature->first() == ImgFeature.first() && - EnvFeature->second != ImgFeature.second) { - DP("Incompatible: Value of Image's non-ANY feature is not matching with " - "the Environment feature's non-ANY value \t[Image: " - "%s]\t:\t[Environment: %s]\n", - ImgTID.data(), EnvTID.data()); - return false; - } - } - - // Image is compatible if all features of Environment are: - // - either, present in the Image's features map with the same sign, - // - or, the feature is missing from Image's features map i.e. it is - // set to ANY - DP("Compatible: Target IDs are compatible \t[Image: %s]\t:\t[Environment: " - "%s]\n", - ImgTID.data(), EnvTID.data()); - return true; -} - extern "C" { int32_t __tgt_rtl_is_valid_binary(__tgt_device_image *Image) { return elfMachineIdIsAmdgcn(Image); @@ -1966,7 +1872,7 @@ DP("Error iterating ISAs\n"); return false; } - if (!IsImageCompatibleWithEnv(info->Arch, DeviceInfo().TargetID[DeviceId])) + if (!isImageCompatibleWithEnv(info, DeviceInfo().TargetID[DeviceId])) return false; } DP("Image has Target ID compatible with the current environment: %s\n",