Skip to content

[SYCL] Add device config file consistency test #16369

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Jun 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
69e538a
[SYCL] Add device config file consistency test
jzc Dec 13, 2024
78a751a
Merge remote-tracking branch 'intel/sycl' into device-config-consistency
jzc Dec 19, 2024
3855884
Update cmake and CI
jzc Dec 19, 2024
3c062ef
Add backslash
jzc Dec 19, 2024
81431e7
Change install location
jzc Dec 19, 2024
07e599e
Fix typo
jzc Dec 19, 2024
215bf25
format
jzc Dec 19, 2024
d7264c9
Make style consistent
jzc Dec 20, 2024
b9e14c7
Move device config file feature detection
jzc Dec 20, 2024
7cd1109
Add SYCL_ prefix
jzc Dec 20, 2024
ef8481f
Fix syntax
jzc Dec 23, 2024
0b99853
Update HIP and CUDA aspects
jzc Jan 7, 2025
7b61e9e
Merge remote-tracking branch 'intel/sycl' into device-config-consistency
jzc Jan 7, 2025
9a893a0
Update HIP and CUDA aspects again
jzc Jan 9, 2025
96da39b
punctuation
jzc Jan 14, 2025
9a4f880
Merge remote-tracking branch 'intel/sycl' into device-config-consistency
jzc Jan 14, 2025
415a6be
Update CUDA usm aspects
jzc Jan 16, 2025
d9e0582
Revert "Update CUDA usm aspects"
jzc Jan 21, 2025
232357b
Update CUDA usm aspects
jzc Jan 21, 2025
fcb7c46
Merge remote-tracking branch 'intel/sycl' into device-config-consistency
jzc Jan 21, 2025
e359521
Merge remote-tracking branch 'upstream/sycl' into device-config-consi…
KornevNikita Jun 4, 2025
c278ad5
upd build_specific_features
KornevNikita Jun 4, 2025
c43cc7c
Apply review suggestions
KornevNikita Jun 5, 2025
8c2cfc4
Merge remote-tracking branch 'upstream/sycl' into device-config-consi…
KornevNikita Jun 5, 2025
2135b30
upd CudaMinAspects
KornevNikita Jun 5, 2025
fe49581
Merge remote-tracking branch 'upstream/sycl' into device-config-consi…
KornevNikita Jun 10, 2025
e098145
upd DeviceConfigFile.td
KornevNikita Jun 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions buildbot/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ def do_configure(args, passthrough_args):
xpti_enable_werror = "OFF"
llvm_enable_zstd = "ON"
spirv_enable_dis = "OFF"
sycl_install_device_config_file = "OFF"

if sys.platform != "darwin":
# For more info on the enablement of level_zero_v2 refer to this document:
Expand Down Expand Up @@ -160,6 +161,7 @@ def do_configure(args, passthrough_args):
libclc_targets_to_build += libclc_nvidia_target_names
libclc_gen_remangled_variants = "ON"
spirv_enable_dis = "ON"
sycl_install_device_config_file = "ON"

if args.enable_backends:
sycl_enabled_backends += args.enable_backends
Expand Down Expand Up @@ -208,6 +210,7 @@ def do_configure(args, passthrough_args):
"-DSYCL_ENABLE_EXTENSION_JIT={}".format(sycl_enable_jit),
"-DSYCL_ENABLE_MAJOR_RELEASE_PREVIEW_LIB={}".format(sycl_preview_lib),
"-DBUG_REPORT_URL=https://github.com/intel/llvm/issues",
"-DSYCL_INSTALL_DEVICE_CONFIG_FILE={}".format(sycl_install_device_config_file),
]

if libclc_enabled:
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/SYCLLowerIR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ set(LLVM_TABLEGEN_PROJECT LLVM)
set(LLVM_TARGET_DEFINITIONS DeviceConfigFile.td)
tablegen(LLVM DeviceConfigFile.inc -gen-dynamic-tables)
add_public_tablegen_target(DeviceConfigFile)
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/DeviceConfigFile.hpp"
"${CMAKE_CURRENT_BINARY_DIR}/DeviceConfigFile.inc"
DESTINATION include/llvm/SYCLLowerIR
COMPONENT DeviceConfigFile)
7 changes: 2 additions & 5 deletions llvm/include/llvm/SYCLLowerIR/DeviceConfigFile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,9 @@

#include <map>
#include <string>
#include <string_view>
#include <vector>

namespace llvm {
class StringRef;
}

namespace DeviceConfigFile {

// This struct is used in DeviceConfigFile.td. Both the fields and the name of
Expand All @@ -22,7 +19,7 @@ namespace DeviceConfigFile {
// DeviceConfigFile.td.
struct TargetInfo {
bool maySupportOtherAspects;
std::vector<llvm::StringRef> aspects;
std::vector<std::string_view> aspects;
std::vector<unsigned> subGroupSizes;
std::string aotToolchain;
std::string aotToolchainOptions;
Expand Down
22 changes: 14 additions & 8 deletions llvm/include/llvm/SYCLLowerIR/DeviceConfigFile.td
Original file line number Diff line number Diff line change
Expand Up @@ -177,14 +177,18 @@ defvar IntelCpuAspects = [
AspectExt_oneapi_srgb, AspectExt_oneapi_native_assert,
AspectExt_intel_legacy_image, AspectExt_oneapi_ballot_group,
AspectExt_oneapi_fixed_size_group, AspectExt_oneapi_opportunistic_group,
AspectExt_oneapi_tangle_group, AspectExt_oneapi_private_alloca
AspectExt_oneapi_tangle_group, AspectExt_oneapi_private_alloca,
AspectOnline_compiler, AspectOnline_linker, AspectExt_intel_gpu_slices,
AspectExt_intel_gpu_subslices_per_slice, AspectExt_intel_gpu_eu_count_per_subslice,
AspectExt_intel_gpu_hw_threads_per_eu, AspectExt_intel_device_id,
AspectExt_oneapi_virtual_functions
] # AllUSMAspects;

def : TargetInfo<"spir64", [], [], "", "", 1>;
def : TargetInfo<"spir64_gen", [], [], "", "", 1>;
def : TargetInfo<"spir64_x86_64", IntelCpuAspects, [4, 8, 16, 32, 64], "", "", 1>;
def : TargetInfo<"spir64_fpga", [], [], "", "", 1>;
def : TargetInfo<"x86_64", [], [], "", "", 1>;
def : TargetInfo<"x86_64", IntelCpuAspects, [4, 8, 16, 32, 64], "", "", 1>;
// Examples of how to use a combination of explicitly specified values + predefined lists
//defvar AspectList = [AspectCpu] # AllUSMAspects;
//def : TargetInfo<"Test", AspectList, []>;
Expand All @@ -196,9 +200,11 @@ defvar Fp16Fp64Atomic64 = [AspectFp16, AspectFp64, AspectAtomic64];
defvar Fp16Atomic64 = [AspectFp16, AspectAtomic64];
defvar Sg8_16_32 = [8, 16, 32];
defvar Sg16_32 = [16, 32];
defvar IntelBaseAspects = [AspectExt_intel_esimd];
defvar IntelGPUBaseAspects = [AspectExt_intel_esimd, AspectExt_oneapi_ballot_group,
AspectExt_oneapi_fixed_size_group, AspectExt_oneapi_opportunistic_group,
AspectExt_oneapi_tangle_group];
class IntelTargetInfo<string Name, list<Aspect> Aspects, list<int> subGroupSizesList>
: TargetInfo<Name, IntelBaseAspects # Aspects, subGroupSizesList>;
: TargetInfo<Name, IntelGPUBaseAspects # Aspects, subGroupSizesList>;
// Note: only the "canonical" target names are listed here - see
// SYCL::gen::resolveGenDevice().
//
Expand Down Expand Up @@ -266,7 +272,7 @@ defvar CudaMinUSMAspects = [AspectUsm_device_allocations, AspectUsm_host_allocat
defvar CudaSM90USMAspects = [AspectUsm_system_allocations, AspectUsm_atomic_host_allocations, AspectUsm_atomic_shared_allocations];

defvar CudaMinAspects = !listconcat(CudaMinUSMAspects, [AspectGpu, AspectFp64, AspectOnline_compiler, AspectOnline_linker,
AspectQueue_profiling, AspectExt_intel_pci_address, AspectExt_intel_max_mem_bandwidth, AspectExt_intel_memory_bus_width,
AspectQueue_profiling, AspectExt_intel_pci_address, AspectExt_intel_memory_bus_width,
AspectExt_intel_device_info_uuid, AspectExt_oneapi_native_assert, AspectExt_intel_free_memory, AspectExt_intel_device_id,
AspectExt_intel_memory_clock_rate, AspectExt_oneapi_ballot_group, AspectExt_oneapi_fixed_size_group,
AspectExt_oneapi_opportunistic_group, AspectExt_oneapi_graph, AspectExt_oneapi_limited_graph]);
Expand Down Expand Up @@ -323,9 +329,9 @@ defvar HipSubgroupSizesCDNA = [64]; // gfx908, gfx90a (encapsulates CDNA1..2

defvar HipMinAspects = [AspectGpu, AspectFp16, AspectFp64,
AspectOnline_compiler, AspectOnline_linker, AspectQueue_profiling,
AspectExt_intel_pci_address, AspectExt_intel_max_mem_bandwidth,
AspectExt_intel_device_id, AspectExt_intel_memory_clock_rate,
AspectExt_intel_memory_bus_width, AspectExt_intel_free_memory];
AspectExt_intel_pci_address, AspectExt_intel_device_id,
AspectExt_intel_memory_clock_rate, AspectExt_intel_memory_bus_width,
AspectExt_intel_free_memory];

defvar HipUSMAspects = !listremove(AllUSMAspects, [AspectUsm_system_allocations]);
defvar HipGraphAspects = [AspectExt_oneapi_graph, AspectExt_oneapi_limited_graph];
Expand Down
5 changes: 5 additions & 0 deletions sycl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,11 @@ if("hip" IN_LIST SYCL_ENABLE_BACKENDS)
list(APPEND SYCL_TOOLCHAIN_DEPLOY_COMPONENTS ur_adapter_hip)
endif()

if(SYCL_INSTALL_DEVICE_CONFIG_FILE)
add_dependencies(sycl-toolchain DeviceConfigFile)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you give some background on why we need to install this? thx

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still testing things, so I might change some things, but I want to support the new device_config_file_consistency test. It uses the DeviceConfigFile.hpp, and that file includes DeviceConfigFile.inc, which is generated by tablegen. On CI from what I understand the e2e tests are invoked by using the packed install files from the build step and only runs CMake on the sycl/test-e2e subfolder. So since we probably don't want to build tablegen and invoke other LLVM cmake files when running the e2e tests, I install the DeviceConfigFile.inc it in the build step to pass it to the e2e tests. Also note that this test must be an e2e test as it queries the device it is running the test on, so it can't be moved to sycl/test.

Copy link
Contributor

@sarnex sarnex Dec 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry so what tools/files are required to generate that hpp file? Is it just llvm-tablegen and DeviceConfigFile.inc?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea just tablegen and DeviceConfigFile.td are needed for the hpp file

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also just for some more background I was aiming so that DeviceConfigFile.hpp is not installed by default because outside of testing, this file is not needed for a SYCL distribution, it is only used in the compiler.

list(APPEND SYCL_TOOLCHAIN_DEPLOY_COMPONENTS DeviceConfigFile)
endif()

# Use it as fake dependency in order to force another command(s) to execute.
add_custom_command(OUTPUT __force_it
COMMAND "${CMAKE_COMMAND}" -E echo
Expand Down
136 changes: 136 additions & 0 deletions sycl/test-e2e/Basic/device_config_file_consistency.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// This test checks to see if every aspect and sub-group size declared in the
// device config file is supported by the device. Note this does not mean
// check that the device config file is exhaustive, only that the device
// supports everything it declares. However, this test does print out any
// aspects that are supported by the device but not declared in the device
// config file.

// REQUIRES: device-config-file
// RUN: %{build} -o %t.out %device_config_file_include_flag
// RUN: %{run} %t.out
#include <map>

#include <llvm/SYCLLowerIR/DeviceConfigFile.hpp>
#include <sycl/detail/core.hpp>

#define __SYCL_ASPECT_DEPRECATED_ALIAS(ASPECT, ID, MESSAGE) \
__SYCL_ASPECT_DEPRECATED(ASPECT, ID, MESSAGE)

using namespace sycl;

const char *getArchName(const device &Device) {
namespace syclex = sycl::ext::oneapi::experimental;
auto Arch = Device.get_info<syclex::info::device::architecture>();
switch (Arch) {
#define __SYCL_ARCHITECTURE(ARCH, VAL) \
case syclex::architecture::ARCH: \
return #ARCH;
#define __SYCL_ARCHITECTURE_ALIAS(ARCH, VAL)
#include <sycl/ext/oneapi/experimental/device_architecture.def>
#undef __SYCL_ARCHITECTURE
#undef __SYCL_ARCHITECTURE_ALIAS
}
return "unknown";
}

// Checks if a container contains a specific element.
template <typename Container, typename T>
bool contains(const Container &C, const T &Elem) {
return std::find(C.begin(), C.end(), Elem) != C.end();
}

std::string_view getAspectName(aspect Asp) {
switch (Asp) {
#define __SYCL_ASPECT(ASPECT, ID) \
case aspect::ASPECT: \
return #ASPECT;
#include <sycl/info/aspects.def>
#undef __SYCL_ASPECT
}
return "unknown";
}

aspect getAspectByName(std::string_view Name) {
#define __SYCL_ASPECT(ASPECT, ID) \
if (Name == #ASPECT) \
return aspect::ASPECT;
#include <sycl/info/aspects.def>
throw std::invalid_argument("Unknown aspect name");
}

int main() {
// Get the device arch.
queue Q;
auto Dev = Q.get_device();
auto DeviceName = getArchName(Dev);

auto TargetInfo = DeviceConfigFile::TargetTable.find(DeviceName);
if (TargetInfo == DeviceConfigFile::TargetTable.end()) {
std::cout << "No aspects found for device " << DeviceName << "\n";
return 1;
}

// Check aspects consistency.
int NAspectInconsistencies = 0;

auto SupportedAspects = Dev.get_info<info::device::aspects>();
auto DeviceConfigAspectNames = TargetInfo->second.aspects;
std::vector<aspect> DeviceConfigAspects;
for (auto AspectName : DeviceConfigAspectNames) {
DeviceConfigAspects.push_back(getAspectByName(AspectName));
}

for (auto Asp : DeviceConfigAspects) {
if (!contains(SupportedAspects, Asp)) {
std::cout << "error: " << DeviceName << " does not support aspect "
<< getAspectName(Asp)
<< " but it is declared in the device config file\n";
++NAspectInconsistencies;
}
}
for (auto Asp : SupportedAspects) {
if (!contains(DeviceConfigAspects, Asp)) {
std::cout << "note: the device " << DeviceName << " supports aspect "
<< getAspectName(Asp)
<< " but it is not declared in the device config file\n";
// Not necessarily an error, so we won't increment n_fail.
}
}

if (NAspectInconsistencies != 0) {
std::cout << "Aspects are inconsistent\n";
return 1;
}

// Check sub-group sizes consistency.
int NSubGroupSizeInconsistencies = 0;

auto SupportedSubGroupSizes = Dev.get_info<info::device::sub_group_sizes>();
auto DeviceConfigSubGroupSizes = TargetInfo->second.subGroupSizes;

for (auto Size : DeviceConfigSubGroupSizes) {
if (!contains(SupportedSubGroupSizes, Size)) {
std::cout << "error: " << DeviceName
<< " does not support sub-group size " << Size
<< " but it is declared in the device config file\n";
++NSubGroupSizeInconsistencies;
}
}
for (auto Size : SupportedSubGroupSizes) {
if (!contains(DeviceConfigSubGroupSizes, Size)) {
std::cout << "note: the device " << DeviceName
<< " supports sub-group size " << Size
<< " but it is not declared in the device config file\n";
// Not necessarily an error, so we won't increment n_fail.
}
}

if (NSubGroupSizeInconsistencies != 0) {
std::cout << "Sub-group sizes are inconsistent\n";
return 1;
}

return 0;
}

#undef __SYCL_ASPECT_DEPRECATED_ALIAS
1 change: 1 addition & 0 deletions sycl/test-e2e/E2EExpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class E2EExpr(BooleanExpression):
"false",
"pdtracker",
"ze_debug",
"device-config-file",
}

def __init__(self, string, variables, build_only_mode, final_unknown_value):
Expand Down
12 changes: 12 additions & 0 deletions sycl/test-e2e/lit.cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,18 @@ def get_sycl_ls_verbose(sycl_device, env):

for target in config.sycl_build_targets:
config.available_features.add("any-target-is-" + target.replace("target-", ""))

if config.llvm_main_include_dir:
lit_config.note("Using device config file built from LLVM")
config.available_features.add("device-config-file")
config.substitutions.append(
("%device_config_file_include_flag", f"-I {config.llvm_main_include_dir}")
)
elif os.path.exists(f"{config.sycl_include}/llvm/SYCLLowerIR/DeviceConfigFile.hpp"):
lit_config.note("Using installed device config file")
config.available_features.add("device-config-file")
config.substitutions.append(("%device_config_file_include_flag", ""))

# That has to be executed last so that all device-independent features have been
# discovered already.
config.sycl_dev_features = {}
Expand Down
1 change: 1 addition & 0 deletions sycl/test-e2e/lit.site.cfg.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def get_dpcpp_tool_path(name):
except subprocess.CalledProcessError:
return os.path.join(config.dpcpp_bin_dir, name)

config.llvm_main_include_dir = "@LLVM_MAIN_INCLUDE_DIR@"
config.llvm_tools_dir = os.path.dirname(get_dpcpp_tool_path("llvm-config"))
config.lit_tools_dir = os.path.dirname("@TEST_SUITE_LIT@")
config.dump_ir_supported = lit_config.params.get("dump_ir", ("@DUMP_IR_SUPPORTED@" if "@DUMP_IR_SUPPORTED@" else False))
Expand Down
5 changes: 2 additions & 3 deletions sycl/test/basic_tests/device_config_file_aspects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
//
#include <map>

#include <llvm/ADT/StringRef.h>
#include <llvm/SYCLLowerIR/DeviceConfigFile.hpp>
#include <sycl/sycl.hpp>

Expand All @@ -16,7 +15,7 @@ int main() {
auto aspectsList = testAspects->second.aspects;

#define __SYCL_ASPECT(ASPECT, ASPECT_VAL) \
llvm::StringRef s##ASPECT(#ASPECT); \
std::string_view s##ASPECT(#ASPECT); \
assert(std::find(aspectsList.begin(), aspectsList.end(), s##ASPECT) != \
aspectsList.end());

Expand All @@ -29,7 +28,7 @@ int main() {
assert(testDeprecatedAspects != DeviceConfigFile::TargetTable.end());
auto deprecatedAspectsList = testDeprecatedAspects->second.aspects;
#define __SYCL_ASPECT_DEPRECATED(ASPECT, ASPECT_VAL, MSG) \
llvm::StringRef s##ASPECT(#ASPECT); \
std::string_view s##ASPECT(#ASPECT); \
assert(std::find(deprecatedAspectsList.begin(), deprecatedAspectsList.end(), \
s##ASPECT) != deprecatedAspectsList.end());

Expand Down