From 03cb2b25026f060149eb94c85b228e5b3a780588 Mon Sep 17 00:00:00 2001 From: Chris Perkins Date: Wed, 8 Jan 2025 16:32:04 -0800 Subject: [PATCH] [SYCL] kernel_compiler remove GCC < 8 workarounds. (#16550) We can use experimental filesystem when compiling SYCL with GCC 7, which means we can remove the #ifdef hacks from the kernel_compiler. --- .../kernel_compiler/kernel_compiler_sycl.cpp | 138 +++++++----------- .../KernelCompiler/kernel_compiler_sycl.cpp | 15 +- 2 files changed, 55 insertions(+), 98 deletions(-) diff --git a/sycl/source/detail/kernel_compiler/kernel_compiler_sycl.cpp b/sycl/source/detail/kernel_compiler/kernel_compiler_sycl.cpp index 6362bf355cfc5..4590a17ecf67b 100644 --- a/sycl/source/detail/kernel_compiler/kernel_compiler_sycl.cpp +++ b/sycl/source/detail/kernel_compiler/kernel_compiler_sycl.cpp @@ -9,59 +9,26 @@ #include "kernel_compiler_sycl.hpp" #include // make_error_code -#if __GNUC__ && __GNUC__ < 8 - -// std::filesystem is not availalbe for GCC < 8 -// and much of the cross-platform file handling code depends upon it. -// Given that this extension is experimental and that the file -// handling aspects are most likely temporary, it makes sense to -// simply not support GCC<8. - -namespace sycl { -inline namespace _V1 { -namespace ext::oneapi::experimental { -namespace detail { - -bool SYCL_Compilation_Available() { return false; } - -spirv_vec_t -SYCL_to_SPIRV(const std::string &SYCLSource, include_pairs_t IncludePairs, - const std::vector &UserArgs, std::string *LogPtr, - const std::vector &RegisteredKernelNames) { - (void)SYCLSource; - (void)IncludePairs; - (void)UserArgs; - (void)LogPtr; - (void)RegisteredKernelNames; - throw sycl::exception(sycl::errc::build, - "kernel_compiler does not support GCC<8"); -} - -std::string userArgsAsString(const std::vector &UserArguments) { - return std::accumulate(UserArguments.begin(), UserArguments.end(), - std::string(""), - [](const std::string &A, const std::string &B) { - return A.empty() ? B : A + " " + B; - }); -} - -} // namespace detail -} // namespace ext::oneapi::experimental -} // namespace _V1 -} // namespace sycl - -#else - #include #include -#include #include #include #include #include #include +// For GCC versions less than 8, use experimental/filesystem. +#if defined(__has_include) && __has_include() +#include +namespace fs = std::filesystem; +#elif defined(__has_include) && __has_include() +#include +namespace fs = std::experimental::filesystem; +#else +#error "kernel_compiler sycl requires C++ filesystem support" +#endif + namespace sycl { inline namespace _V1 { namespace ext::oneapi::experimental { @@ -80,14 +47,12 @@ std::string generateSemiUniqueId() { // Combine time and random number into a string. std::stringstream Ss; - Ss << Milliseconds.count() << "_" << std::setfill('0') << std::setw(5) - << RandomNumber; + Ss << Milliseconds.count() << "_" << RandomNumber; return Ss.str(); } -std::filesystem::path prepareWS(const std::string &Id) { - namespace fs = std::filesystem; +fs::path prepareWS(const std::string &Id) { const fs::path TmpDirectoryPath = fs::temp_directory_path(); fs::path NewDirectoryPath = TmpDirectoryPath / Id; @@ -104,10 +69,10 @@ std::filesystem::path prepareWS(const std::string &Id) { return NewDirectoryPath; } -void deleteWS(const std::filesystem::path &ParentDir) { +void deleteWS(const fs::path &ParentDir) { try { - std::filesystem::remove_all(ParentDir); - } catch (const std::filesystem::filesystem_error &E) { + fs::remove_all(ParentDir); + } catch (const fs::filesystem_error &E) { // We could simply suppress this, since deleting the directory afterwards // is not critical. But if there are problems, seems good to know. throw sycl::exception(sycl::errc::build, E.what()); @@ -122,8 +87,7 @@ std::string userArgsAsString(const std::vector &UserArguments) { }); } -void outputPreamble(std::ofstream &Os, const std::filesystem::path &FilePath, - const std::string &Id, +void outputPreamble(std::ofstream &Os, const std::string &Id, const std::vector &UserArgs) { Os << "/*\n"; @@ -133,15 +97,15 @@ void outputPreamble(std::ofstream &Os, const std::filesystem::path &FilePath, Os << ".cpp \n */" << std::endl; } -std::filesystem::path -outputCpp(const std::filesystem::path &ParentDir, const std::string &Id, - std::string RawCodeString, const std::vector &UserArgs, - const std::vector &RegisteredKernelNames) { - std::filesystem::path FilePath = ParentDir / (Id + ".cpp"); +fs::path outputCpp(const fs::path &ParentDir, const std::string &Id, + std::string RawCodeString, + const std::vector &UserArgs, + const std::vector &RegisteredKernelNames) { + fs::path FilePath = ParentDir / (Id + ".cpp"); std::ofstream Outfile(FilePath, std::ios::out | std::ios::trunc); if (Outfile.is_open()) { - outputPreamble(Outfile, FilePath, Id, UserArgs); + outputPreamble(Outfile, Id, UserArgs); Outfile << RawCodeString << std::endl; // Temporarily needed until -c works with -fsycl-dump-spirv. @@ -161,12 +125,11 @@ outputCpp(const std::filesystem::path &ParentDir, const std::string &Id, return FilePath; } -void outputIncludeFiles(const std::filesystem::path &Dirpath, - include_pairs_t IncludePairs) { +void outputIncludeFiles(const fs::path &Dirpath, include_pairs_t IncludePairs) { using pairStrings = std::pair; for (pairStrings p : IncludePairs) { - std::filesystem::path FilePath = Dirpath / p.first; - std::filesystem::create_directories(FilePath.parent_path()); + fs::path FilePath = Dirpath / p.first; + fs::create_directories(FilePath.parent_path()); std::ofstream outfile(FilePath, std::ios::out | std::ios::trunc); if (outfile.is_open()) { outfile << p.second << std::endl; @@ -191,11 +154,10 @@ std::string getCompilerName() { // We are assuming that the compiler is in /bin and the shared lib in // the adjacent /lib. -std::filesystem::path getCompilerPath() { +fs::path getCompilerPath() { std::string Compiler = getCompilerName(); const std::string LibSYCLDir = sycl::detail::OSUtil::getCurrentDSODir(); - std::filesystem::path CompilerPath = - std::filesystem::path(LibSYCLDir) / ".." / "bin" / Compiler; + fs::path CompilerPath = fs::path(LibSYCLDir) / ".." / "bin" / Compiler; return CompilerPath; } @@ -225,16 +187,15 @@ int invokeCommand(const std::string &command, std::string &output) { return 0; } -std::string invokeCompiler(const std::filesystem::path &FPath, - const std::filesystem::path &DPath, +std::string invokeCompiler(const fs::path &FPath, const fs::path &DPath, const std::string &Id, const std::vector &UserArgs, std::string *LogPtr) { - std::filesystem::path FilePath(FPath); - std::filesystem::path ParentDir(DPath); - std::filesystem::path TargetPath = ParentDir / (Id + ".bin"); - std::filesystem::path LogPath = ParentDir / "compilation_log.txt"; + fs::path FilePath(FPath); + fs::path ParentDir(DPath); + fs::path TargetPath = ParentDir / (Id + ".bin"); + fs::path LogPath = ParentDir / "compilation_log.txt"; std::string Compiler = getCompilerPath().make_preferred().string(); std::string Command = @@ -262,13 +223,13 @@ std::string invokeCompiler(const std::filesystem::path &FPath, return CompileLog; } -std::filesystem::path findSpv(const std::filesystem::path &ParentDir, - const std::string &Id, std::string &CompileLog) { +fs::path findSpv(const fs::path &ParentDir, const std::string &Id, + std::string &CompileLog) { std::regex PatternRegex(Id + R"(.*\.spv)"); // Iterate through all files in the directory matching the pattern. - for (const auto &Entry : std::filesystem::directory_iterator(ParentDir)) { - if (Entry.is_regular_file() && + for (const auto &Entry : fs::directory_iterator(ParentDir)) { + if (fs::is_regular_file(Entry.path()) && std::regex_match(Entry.path().filename().string(), PatternRegex)) { return Entry.path(); // Return the path if it matches the SPV pattern. } @@ -278,7 +239,7 @@ std::filesystem::path findSpv(const std::filesystem::path &ParentDir, throw sycl::exception(sycl::errc::build, "Compile failure: " + CompileLog); } -spirv_vec_t loadSpvFromFile(const std::filesystem::path &FileName) { +spirv_vec_t loadSpvFromFile(const fs::path &FileName) { std::ifstream SpvStream(FileName, std::ios::binary); SpvStream.seekg(0, std::ios::end); size_t Size = SpvStream.tellg(); @@ -294,23 +255,23 @@ SYCL_to_SPIRV(const std::string &SYCLSource, include_pairs_t IncludePairs, const std::vector &UserArgs, std::string *LogPtr, const std::vector &RegisteredKernelNames) { // clang-format off - const std::string id = generateSemiUniqueId(); - const std::filesystem::path ParentDir = prepareWS(id); - std::filesystem::path FilePath = outputCpp(ParentDir, id, SYCLSource, UserArgs, RegisteredKernelNames); - outputIncludeFiles(ParentDir, IncludePairs); - std::string CompileLog = invokeCompiler(FilePath, ParentDir, id, UserArgs, LogPtr); - std::filesystem::path SpvPath = findSpv(ParentDir, id, CompileLog); - spirv_vec_t Spv = loadSpvFromFile(SpvPath); - deleteWS(ParentDir); - return Spv; + const std::string id = generateSemiUniqueId(); + const fs::path ParentDir = prepareWS(id); + fs::path FilePath = outputCpp(ParentDir, id, SYCLSource, UserArgs, RegisteredKernelNames); + outputIncludeFiles(ParentDir, IncludePairs); + std::string CompileLog = invokeCompiler(FilePath, ParentDir, id, UserArgs, LogPtr); + fs::path SpvPath = findSpv(ParentDir, id, CompileLog); + spirv_vec_t Spv = loadSpvFromFile(SpvPath); + deleteWS(ParentDir); + return Spv; // clang-format on } bool SYCL_Compilation_Available() { // Is compiler on $PATH ? We try to invoke it. std::string id = generateSemiUniqueId(); - const std::filesystem::path tmp = std::filesystem::temp_directory_path(); - std::filesystem::path DumpPath = tmp / (id + "_version.txt"); + const fs::path tmp = fs::temp_directory_path(); + fs::path DumpPath = tmp / (id + "_version.txt"); std::string Compiler = getCompilerPath().make_preferred().string(); std::string TestCommand = Compiler + " --version > " + DumpPath.make_preferred().string(); @@ -323,7 +284,6 @@ bool SYCL_Compilation_Available() { } // namespace ext::oneapi::experimental } // namespace _V1 } // namespace sycl -#endif #if SYCL_EXT_JIT_ENABLE #include "../jit_compiler.hpp" diff --git a/sycl/test-e2e/KernelCompiler/kernel_compiler_sycl.cpp b/sycl/test-e2e/KernelCompiler/kernel_compiler_sycl.cpp index 27ab3401d4426..d8b020e971d4a 100644 --- a/sycl/test-e2e/KernelCompiler/kernel_compiler_sycl.cpp +++ b/sycl/test-e2e/KernelCompiler/kernel_compiler_sycl.cpp @@ -12,14 +12,11 @@ // -- Test the kernel_compiler with SYCL source. // RUN: %{build} -o %t.out -// If clang++ is not on the PATH, or if sycl was compiled with GCC < 8, then -// the kernel_compiler is not available for SYCL language. // Note: this 'invoking clang++' version for SYCL language support is temporary, // and will be replaced by the SYCL_JIT version soon. -// DEFINE: %{available} = %t.out available -// RUN: %if available %{ %{run} %t.out %} -// RUN: %if available %{ %{l0_leak_check} %{run} %t.out %} +// RUN: %{run} %t.out +// RUN: %{l0_leak_check} %{run} %t.out // -- Test again, with caching. // 'reading-from-cache' is just a string we pass to differentiate between the @@ -27,13 +24,13 @@ // DEFINE: %{cache_vars} = %{l0_leak_check} env SYCL_CACHE_PERSISTENT=1 SYCL_CACHE_TRACE=5 SYCL_CACHE_DIR=%t/cache_dir // RUN: rm -rf %t/cache_dir -// RUN: %if available %{ %{cache_vars} %t.out 2>&1 | FileCheck %s --check-prefixes=CHECK-WRITTEN-TO-CACHE %} -// RUN: %if available %{ %{cache_vars} %t.out reading-from-cache 2>&1 | FileCheck %s --check-prefixes=CHECK-READ-FROM-CACHE %} +// RUN: %{cache_vars} %t.out 2>&1 | FileCheck %s --check-prefixes=CHECK-WRITTEN-TO-CACHE +// RUN: %{cache_vars} %t.out reading-from-cache 2>&1 | FileCheck %s --check-prefixes=CHECK-READ-FROM-CACHE // -- Add leak check. // RUN: rm -rf %t/cache_dir -// RUN: %if available %{ %{l0_leak_check} %{cache_vars} %t.out 2>&1 | FileCheck %s --check-prefixes=CHECK-WRITTEN-TO-CACHE %} -// RUN: %if available %{ %{l0_leak_check} %{cache_vars} %t.out reading-from-cache 2>&1 | FileCheck %s --check-prefixes=CHECK-READ-FROM-CACHE %} +// RUN: %{l0_leak_check} %{cache_vars} %t.out 2>&1 | FileCheck %s --check-prefixes=CHECK-WRITTEN-TO-CACHE +// RUN: %{l0_leak_check} %{cache_vars} %t.out reading-from-cache 2>&1 | FileCheck %s --check-prefixes=CHECK-READ-FROM-CACHE // CHECK-WRITTEN-TO-CACHE: [Persistent Cache]: enabled // CHECK-WRITTEN-TO-CACHE-NOT: [kernel_compiler Persistent Cache]: using cached binary