https://github.com/wenju-he updated https://github.com/llvm/llvm-project/pull/224548
>From 1ce31dddedbe12c8cad2cfc32835c09b009d88a5 Mon Sep 17 00:00:00 2001 From: Wenju He <[email protected]> Date: Fri, 18 Sep 2026 09:49:21 +0200 Subject: [PATCH 1/5] [clang-sycl-linker] AOT-compile split modules concurrently AOT-compile all split modules in a thread pool instead of one at a time, cutting AOT wall time when there are multiple split modules. Co-Authored-By: Claude Sonnet 5 <[email protected]> --- .../clang-sycl-linker/ClangSYCLLinker.cpp | 59 +++++++++++++++++-- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index 70afc6d6c4cea0..c1b964d58c2040 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -52,6 +52,7 @@ #include "llvm/Support/Signals.h" #include "llvm/Support/StringSaver.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Support/ThreadPool.h" #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/WithColor.h" #include "llvm/Target/TargetMachine.h" @@ -924,6 +925,54 @@ static bool canSkipModuleSplit(IRSplitMode Mode, const Module &M, }); } +/// AOT-compiles every already-produced image in \p SplitModules concurrently +/// and swaps each module's path to point at the compiled object. +static Error aotCompileSplitModules(SmallVectorImpl<SplitModule> &SplitModules, + const ArgList &Args, StringRef OutputFile) { + // Each worker thread writes only its own index, so this is race-free. + SmallVector<std::string, 0> AOTFiles(SplitModules.size()); + // std::optional, not Error: pre-filled Error::success() move-assigned + // from a worker thread would abort on the unchecked-value assert. + SmallVector<std::optional<Error>, 0> AOTErrors(SplitModules.size()); + for (size_t I = 0, E = SplitModules.size(); I != E; ++I) { + SmallString<64> Prefix; + (sys::path::filename(OutputFile).rsplit('.').first + "_" + Twine(I)) + .toVector(Prefix); + Expected<StringRef> AOTFileOrErr = createTempFile(Args, Prefix, "out"); + if (!AOTFileOrErr) + return AOTFileOrErr.takeError(); + AOTFiles[I] = std::string(*AOTFileOrErr); + } + { + DefaultThreadPool AOTPool(llvm::heavyweight_hardware_concurrency()); + for (size_t I = 0, E = SplitModules.size(); I != E; ++I) + AOTPool.async( + [&](size_t I) { + AOTErrors[I].emplace(runAOTCompile(SplitModules[I].ModuleFilePath, + AOTFiles[I], Args)); + }, + I); + AOTPool.wait(); + } + // Every Error must be checked once, so visit all before returning + // instead of stopping at the first failure. + Error FirstErr = Error::success(); + for (std::optional<Error> &Err : AOTErrors) { + if (!*Err) + continue; + if (FirstErr) + consumeError(std::move(*Err)); + else + FirstErr = std::move(*Err); + } + if (FirstErr) + return FirstErr; + + for (size_t I = 0, E = AOTFiles.size(); I != E; ++I) + SplitModules[I].ModuleFilePath = AOTFiles[I]; + return Error::success(); +} + /// Performs the following steps: /// 1. Link all input bitcode files together with library files. /// 2. Optionally split the linked module according to the requested @@ -1000,14 +1049,12 @@ static Error runSYCLLink(ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs, } SplitModules[I].ModuleFilePath = CodeGenFile; - if (IsAOTCompileNeeded) { - std::string AOTFile = (Stem + "_" + Twine(I) + ".out").str(); - if (Error Err = runAOTCompile(CodeGenFile, AOTFile, Args)) - return Err; - SplitModules[I].ModuleFilePath = AOTFile; - } } + if (IsAOTCompileNeeded) + if (Error Err = aotCompileSplitModules(SplitModules, Args, OutputFile)) + return Err; + // Collect all images to be packed into a single OffloadBinary. SmallVector<OffloadingImage> Images; for (SplitModule &SI : SplitModules) { >From 96642b78e919c2613e608807f84529199499cbad Mon Sep 17 00:00:00 2001 From: Wenju He <[email protected]> Date: Fri, 18 Sep 2026 12:39:39 +0200 Subject: [PATCH 2/5] fix test: now is basename + hash --- clang/test/OffloadTools/clang-sycl-linker/basic.ll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/OffloadTools/clang-sycl-linker/basic.ll b/clang/test/OffloadTools/clang-sycl-linker/basic.ll index 00e3bba8d297e5..b7f88acc9814fa 100644 --- a/clang/test/OffloadTools/clang-sycl-linker/basic.ll +++ b/clang/test/OffloadTools/clang-sycl-linker/basic.ll @@ -114,7 +114,7 @@ ; RUN: | FileCheck %s --check-prefix=AOT-INTEL-GPU ; AOT-INTEL-GPU: link: inputs: {{.*}}.bc, {{.*}}.bc output: [[LLVMLINKOUT:.*]].bc ; AOT-INTEL-GPU-NEXT: LLVM backend: input: [[LLVMLINKOUT]].bc, output: [[SPIRVTRANSLATIONOUT:.*]]_0.spv -; AOT-INTEL-GPU-NEXT: "{{.*}}ocloc{{.*}}" {{.*}}-device bmg_g21 -a -b {{.*}}-output [[SPIRVTRANSLATIONOUT]]_0.out -file [[SPIRVTRANSLATIONOUT]]_0.spv +; AOT-INTEL-GPU-NEXT: "{{.*}}ocloc{{.*}}" {{.*}}-device bmg_g21 -a -b {{.*}}-output {{.*}}_0-{{.*}}.out -file [[SPIRVTRANSLATIONOUT]]_0.spv ; AOT-INTEL-GPU-NEXT: sycl-bundle: image kind: o, triple: spirv64, arch: bmg_g21 ; AOT-INTEL-GPU-NOT: {{.+}} ; @@ -131,7 +131,7 @@ ; RUN: | FileCheck %s --check-prefix=AOT-INTEL-CPU ; AOT-INTEL-CPU: link: inputs: {{.*}}.bc, {{.*}}.bc output: [[LLVMLINKOUT:.*]].bc ; AOT-INTEL-CPU-NEXT: LLVM backend: input: [[LLVMLINKOUT]].bc, output: [[SPIRVTRANSLATIONOUT:.*]]_0.spv -; AOT-INTEL-CPU-NEXT: "{{.*}}opencl-aot{{.*}}" {{.*}}--device=cpu -a -b {{.*}}-o [[SPIRVTRANSLATIONOUT]]_0.out [[SPIRVTRANSLATIONOUT]]_0.spv +; AOT-INTEL-CPU-NEXT: "{{.*}}opencl-aot{{.*}}" {{.*}}--device=cpu -a -b {{.*}}-o {{.*}}_0-{{.*}}.out [[SPIRVTRANSLATIONOUT]]_0.spv ; AOT-INTEL-CPU-NEXT: sycl-bundle: image kind: o, triple: spirv64, arch: graniterapids ; AOT-INTEL-CPU-NOT: {{.+}} ; >From 5dea9ce500f80ed47459f5d35504b36446b4cb3e Mon Sep 17 00:00:00 2001 From: Wenju He <[email protected]> Date: Sat, 19 Sep 2026 06:55:37 +0200 Subject: [PATCH 3/5] JIT image --- clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index c1b964d58c2040..e64cdb51f0ca44 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -925,8 +925,8 @@ static bool canSkipModuleSplit(IRSplitMode Mode, const Module &M, }); } -/// AOT-compiles every already-produced image in \p SplitModules concurrently -/// and swaps each module's path to point at the compiled object. +/// AOT-compiles every JIT image in \p SplitModules concurrently and swaps each +/// module's path to point at the compiled object. static Error aotCompileSplitModules(SmallVectorImpl<SplitModule> &SplitModules, const ArgList &Args, StringRef OutputFile) { // Each worker thread writes only its own index, so this is race-free. >From 55467baa1239ff88c8ded015e25d78eaf4db8a55 Mon Sep 17 00:00:00 2001 From: Wenju He <[email protected]> Date: Sat, 19 Sep 2026 07:10:17 +0200 Subject: [PATCH 4/5] [SYCL] Fix data race on llvm::errs() in concurrent AOT command printing aotCompileSplitModules dispatches runAOTCompile per split module onto a thread pool; each call can reach executeCommands's -v/--dry-run print of the command line, racing on the shared errs() stream. Co-Authored-By: Claude Sonnet 5 <[email protected]> --- clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index e64cdb51f0ca44..2cb41d7de1cff5 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -58,6 +58,8 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/Utils/SplitModuleByCategory.h" +#include <mutex> + using namespace llvm; using namespace llvm::opt; using namespace llvm::object; @@ -182,8 +184,11 @@ static void printCommands(ArrayRef<StringRef> CmdArgs) { /// Execute the command \p ExecutablePath with the arguments \p Args. static Error executeCommands(StringRef ExecutablePath, ArrayRef<StringRef> Args) { - if (Verbose || DryRun) + if (Verbose || DryRun) { + static std::mutex PrintMutex; + std::lock_guard<std::mutex> Lock(PrintMutex); printCommands(Args); + } if (DryRun) return Error::success(); >From b9ce5073a75c2c87100bad6f867ce1b718b84d53 Mon Sep 17 00:00:00 2001 From: Wenju He <[email protected]> Date: Tue, 22 Sep 2026 01:59:27 +0200 Subject: [PATCH 5/5] [clang-sycl-linker] Simplify AOT compile error handling with parallelForEachError Use parallelForEachError, matching clang-linker-wrapper's pattern, instead of manually managing a thread pool and a per-index optional-Error array. Co-Authored-By: Claude Sonnet 5 <[email protected]> --- .../clang-sycl-linker/ClangSYCLLinker.cpp | 36 +++++-------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index 2cb41d7de1cff5..7e876656ed62ec 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -47,12 +47,12 @@ #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/InitLLVM.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Parallel.h" #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" #include "llvm/Support/Signals.h" #include "llvm/Support/StringSaver.h" #include "llvm/Support/TargetSelect.h" -#include "llvm/Support/ThreadPool.h" #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/WithColor.h" #include "llvm/Target/TargetMachine.h" @@ -936,9 +936,6 @@ static Error aotCompileSplitModules(SmallVectorImpl<SplitModule> &SplitModules, const ArgList &Args, StringRef OutputFile) { // Each worker thread writes only its own index, so this is race-free. SmallVector<std::string, 0> AOTFiles(SplitModules.size()); - // std::optional, not Error: pre-filled Error::success() move-assigned - // from a worker thread would abort on the unchecked-value assert. - SmallVector<std::optional<Error>, 0> AOTErrors(SplitModules.size()); for (size_t I = 0, E = SplitModules.size(); I != E; ++I) { SmallString<64> Prefix; (sys::path::filename(OutputFile).rsplit('.').first + "_" + Twine(I)) @@ -948,30 +945,13 @@ static Error aotCompileSplitModules(SmallVectorImpl<SplitModule> &SplitModules, return AOTFileOrErr.takeError(); AOTFiles[I] = std::string(*AOTFileOrErr); } - { - DefaultThreadPool AOTPool(llvm::heavyweight_hardware_concurrency()); - for (size_t I = 0, E = SplitModules.size(); I != E; ++I) - AOTPool.async( - [&](size_t I) { - AOTErrors[I].emplace(runAOTCompile(SplitModules[I].ModuleFilePath, - AOTFiles[I], Args)); - }, - I); - AOTPool.wait(); - } - // Every Error must be checked once, so visit all before returning - // instead of stopping at the first failure. - Error FirstErr = Error::success(); - for (std::optional<Error> &Err : AOTErrors) { - if (!*Err) - continue; - if (FirstErr) - consumeError(std::move(*Err)); - else - FirstErr = std::move(*Err); - } - if (FirstErr) - return FirstErr; + + if (Error Err = parallelForEachError( + llvm::seq<size_t>(0, SplitModules.size()), [&](size_t I) -> Error { + return runAOTCompile(SplitModules[I].ModuleFilePath, AOTFiles[I], + Args); + })) + return Err; for (size_t I = 0, E = AOTFiles.size(); I != E; ++I) SplitModules[I].ModuleFilePath = AOTFiles[I]; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
