https://github.com/YuriPlyakhin created https://github.com/llvm/llvm-project/pull/199777
The bitcode link phase has nothing SYCL-specific, as the removed TODO noted. Rename linkDeviceCode/getSYCLDeviceLibs and strip "SYCL"/"device" wording from the verbose output, error messages, and comments. Tests updated accordingly. >From 6793aed127007d6b1db8fe31d0cc5b77f35ee98e Mon Sep 17 00:00:00 2001 From: "Plyakhin, Yury" <[email protected]> Date: Tue, 26 May 2026 23:49:51 +0200 Subject: [PATCH] [clang-sycl-linker][NFC] Drop SYCL/device qualifiers from generic link step The bitcode link phase has nothing SYCL-specific, as the removed TODO noted. Rename linkDeviceCode/getSYCLDeviceLibs and strip "SYCL"/"device" wording from the verbose output, error messages, and comments. Tests updated accordingly. --- .../OffloadTools/clang-sycl-linker/basic.ll | 10 +-- .../clang-sycl-linker/split-mode.ll | 6 +- .../clang-sycl-linker/ClangSYCLLinker.cpp | 69 +++++++++---------- 3 files changed, 41 insertions(+), 44 deletions(-) diff --git a/clang/test/OffloadTools/clang-sycl-linker/basic.ll b/clang/test/OffloadTools/clang-sycl-linker/basic.ll index 5bb15b3ca9b4f..f0e1c9c010ee4 100644 --- a/clang/test/OffloadTools/clang-sycl-linker/basic.ll +++ b/clang/test/OffloadTools/clang-sycl-linker/basic.ll @@ -9,7 +9,7 @@ ; Test the dry run of a simple case to link two input files. ; RUN: clang-sycl-linker --dry-run -v --module-split-mode=none %t/input1.bc %t/input2.bc -o %t/spirv.out 2>&1 \ ; RUN: | FileCheck %s --check-prefix=SIMPLE-FO -; SIMPLE-FO: sycl-device-link: inputs: {{.*}}.bc, {{.*}}.bc libfiles: output: [[LLVMLINKOUT:.*]].bc +; SIMPLE-FO: link: inputs: {{.*}}.bc, {{.*}}.bc libfiles: output: [[LLVMLINKOUT:.*]].bc ; SIMPLE-FO-NEXT: LLVM backend: input: [[LLVMLINKOUT]].bc, output: {{.*}}_0.spv ; SIMPLE-FO-NOT: {{.+}} ; @@ -23,7 +23,7 @@ ; RUN: touch %t/libs/lib2.bc ; RUN: clang-sycl-linker --dry-run -v --module-split-mode=none %t/input1.bc %t/input2.bc --library-path=%t/libs --device-libs=lib1.bc,lib2.bc -o a.spv 2>&1 \ ; RUN: | FileCheck %s --check-prefix=DEVLIBS -; DEVLIBS: sycl-device-link: inputs: {{.*}}.bc libfiles: {{.*}}lib1.bc, {{.*}}lib2.bc output: [[LLVMLINKOUT:.*]].bc +; DEVLIBS: link: inputs: {{.*}}.bc libfiles: {{.*}}lib1.bc, {{.*}}lib2.bc output: [[LLVMLINKOUT:.*]].bc ; DEVLIBS-NEXT: LLVM backend: input: [[LLVMLINKOUT]].bc, output: a_0.spv ; ; Test a simple case with a random file (not bitcode) as input. @@ -38,13 +38,13 @@ ; DEVLIBSERR1: Number of device library files cannot be zero ; RUN: not clang-sycl-linker --dry-run %t/input1.bc %t/input2.bc --library-path=%t/libs --device-libs=lib1.bc,lib2.bc,lib3.bc -o a.spv 2>&1 \ ; RUN: | FileCheck %s --check-prefix=DEVLIBSERR2 -; DEVLIBSERR2: '{{.*}}lib3.bc' SYCL device library file is not found +; DEVLIBSERR2: '{{.*}}lib3.bc' device library file is not found ; ; Test AOT compilation for an Intel GPU. ; RUN: clang-sycl-linker --dry-run -v --module-split-mode=none -arch=bmg_g21 %t/input1.bc %t/input2.bc -o %t/aot-gpu.out 2>&1 \ ; RUN: --ocloc-options="-a -b" \ ; RUN: | FileCheck %s --check-prefix=AOT-INTEL-GPU -; AOT-INTEL-GPU: sycl-device-link: inputs: {{.*}}.bc, {{.*}}.bc libfiles: output: [[LLVMLINKOUT:.*]].bc +; AOT-INTEL-GPU: link: inputs: {{.*}}.bc, {{.*}}.bc libfiles: 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 ; @@ -56,7 +56,7 @@ ; RUN: clang-sycl-linker --dry-run -v --module-split-mode=none -arch=graniterapids %t/input1.bc %t/input2.bc -o %t/aot-cpu.out 2>&1 \ ; RUN: --opencl-aot-options="-a -b" \ ; RUN: | FileCheck %s --check-prefix=AOT-INTEL-CPU -; AOT-INTEL-CPU: sycl-device-link: inputs: {{.*}}.bc, {{.*}}.bc libfiles: output: [[LLVMLINKOUT:.*]].bc +; AOT-INTEL-CPU: link: inputs: {{.*}}.bc, {{.*}}.bc libfiles: 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 ; diff --git a/clang/test/OffloadTools/clang-sycl-linker/split-mode.ll b/clang/test/OffloadTools/clang-sycl-linker/split-mode.ll index ab6ccfaf64e70..56a6b3e082550 100644 --- a/clang/test/OffloadTools/clang-sycl-linker/split-mode.ll +++ b/clang/test/OffloadTools/clang-sycl-linker/split-mode.ll @@ -12,14 +12,14 @@ ; Test the split mode ("none"): kernels from different TUs are not split into separate images. ; RUN: clang-sycl-linker --dry-run -v --module-split-mode=none %t.bc -o %t-none.out 2>&1 \ ; RUN: | FileCheck %s --check-prefix=SPLIT-NONE -; SPLIT-NONE: sycl-device-link: inputs: {{.*}}.bc libfiles: output: [[LLVMLINKOUT:.*]].bc +; SPLIT-NONE: link: inputs: {{.*}}.bc libfiles: output: [[LLVMLINKOUT:.*]].bc ; SPLIT-NONE-NEXT: LLVM backend: input: [[LLVMLINKOUT]].bc, output: {{.*}}_0.spv ; SPLIT-NONE-NOT: {{.+}} ; ; Test the split mode ("kernel"): each SPIR_KERNEL function produces its own device image. ; RUN: clang-sycl-linker --dry-run -v --module-split-mode=kernel %t.bc -o %t-split-kernel.out 2>&1 \ ; RUN: | FileCheck %s --check-prefix=SPLIT-KERNEL -; SPLIT-KERNEL: sycl-device-link: inputs: {{.*}}.bc libfiles: output: [[LLVMLINKOUT:.*]].bc +; SPLIT-KERNEL: link: inputs: {{.*}}.bc libfiles: output: [[LLVMLINKOUT:.*]].bc ; SPLIT-KERNEL-NEXT: sycl-module-split: input: [[LLVMLINKOUT]].bc, mode: kernel ; SPLIT-KERNEL-NEXT: [[SPLIT0:.*]].bc [kernel_c ] ; SPLIT-KERNEL-NEXT: [[SPLIT1:.*]].bc [kernel_b ] @@ -39,7 +39,7 @@ ; Test per-TU split ('source' explicitly provided) ; RUN: clang-sycl-linker --dry-run -v --module-split-mode=source %t.bc -o %t-src.out 2>&1 \ ; RUN: | FileCheck %s --check-prefix=SPLIT-SRC -; SPLIT-SRC: sycl-device-link: inputs: {{.*}}.bc libfiles: output: [[LLVMLINKOUT:.*]].bc +; SPLIT-SRC: link: inputs: {{.*}}.bc libfiles: output: [[LLVMLINKOUT:.*]].bc ; SPLIT-SRC-NEXT: sycl-module-split: input: [[LLVMLINKOUT]].bc, mode: source ; SPLIT-SRC-NEXT: [[S0:.*]].bc [kernel_b kernel_c ] ; SPLIT-SRC-NEXT: [[S1:.*]].bc [kernel_a ] diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index 88a09d0a3ecc7..92e2cfdf8f4eb 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -217,10 +217,9 @@ Expected<std::unique_ptr<Module>> getBitcodeModule(StringRef File, return createStringError(Err.getMessage()); } -/// Gather all SYCL device library files that will be linked with input device -/// files. +/// Gather all device library files. /// The list of files and its location are passed from driver. -Expected<SmallVector<std::string>> getSYCLDeviceLibs(const ArgList &Args) { +Expected<SmallVector<std::string>> getDeviceLibs(const ArgList &Args) { SmallVector<std::string> DeviceLibFiles; StringRef LibraryPath; if (Arg *A = Args.getLastArg(OPT_library_path_EQ)) @@ -236,7 +235,7 @@ Expected<SmallVector<std::string>> getSYCLDeviceLibs(const ArgList &Args) { DeviceLibFiles.push_back(std::string(LibName)); else return createStringError("'" + LibName + - "' SYCL device library file is not found."); + "' device library file is not found."); } } return DeviceLibFiles; @@ -248,32 +247,26 @@ struct LinkResult { llvm::Triple TargetTriple; }; -/// TODO: There is nothing SYCL specific in linkDeviceCode function. Remove: -/// 1. Mentions of SYCL. -/// 2. "fat" file formats. This linker shouldn't refer to input files as -/// "device code"/"device libraries". - /// Following tasks are performed: /// 1. Resolve the target triple: use --triple= when given, otherwise take the /// first input that supplies a triple as canonical. Issue an error if any /// triple inputs disagree. -/// 2. Link all SYCL device bitcode images into one image. Device linking is -/// performed using the linkInModule API. -/// 3. Gather all SYCL device library bitcode images. +/// 2. Link all input bitcode images into one image using the linkInModule API. +/// 3. Gather all device library bitcode images. /// 4. Link all the images gathered in Step 3 with the output of Step 2 using /// linkInModule API. LinkOnlyNeeded flag is used. -Expected<LinkResult> linkDeviceCode(ArrayRef<std::string> InputFiles, - const ArgList &Args, LLVMContext &C) { - llvm::TimeTraceScope TimeScope("SYCL link device code"); +Expected<LinkResult> link(ArrayRef<std::string> InputFiles, const ArgList &Args, + LLVMContext &C) { + llvm::TimeTraceScope TimeScope("Link code"); assert(InputFiles.size() && "No inputs to link"); - // Get all SYCL device library files, if any. - auto SYCLDeviceLibFiles = getSYCLDeviceLibs(Args); - if (!SYCLDeviceLibFiles) - return SYCLDeviceLibFiles.takeError(); + // Get all device library files, if any. + Expected<SmallVector<std::string>> DeviceLibFiles = getDeviceLibs(Args); + if (!DeviceLibFiles) + return DeviceLibFiles.takeError(); - // Create a new file to write the linked device file to. + // Create a new file to write the linked file to. auto BitcodeOutput = createTempFile(Args, sys::path::filename(OutputFile), "bc"); if (!BitcodeOutput) @@ -281,17 +274,16 @@ Expected<LinkResult> linkDeviceCode(ArrayRef<std::string> InputFiles, if (Verbose || DryRun) { std::string Inputs = llvm::join(InputFiles.begin(), InputFiles.end(), ", "); - std::string LibInputs = llvm::join((*SYCLDeviceLibFiles).begin(), - (*SYCLDeviceLibFiles).end(), ", "); - errs() << formatv( - "sycl-device-link: inputs: {0} libfiles: {1} output: {2}\n", Inputs, - LibInputs, *BitcodeOutput); + std::string LibInputs = + llvm::join((*DeviceLibFiles).begin(), (*DeviceLibFiles).end(), ", "); + errs() << formatv("link: inputs: {0} libfiles: {1} output: {2}\n", Inputs, + LibInputs, *BitcodeOutput); } - // Link SYCL device input files. Resolve the target triple. + // Link input files. Resolve the target triple. llvm::Triple TargetTriple(Args.getLastArgValue(OPT_triple_EQ)); StringRef TripleSource = TargetTriple.empty() ? "" : "--triple="; - auto LinkerOutput = std::make_unique<Module>("sycl-device-link", C); + auto LinkerOutput = std::make_unique<Module>("linker-output", C); Linker L(*LinkerOutput); for (auto &File : InputFiles) { @@ -319,8 +311,8 @@ Expected<LinkResult> linkDeviceCode(ArrayRef<std::string> InputFiles, return createStringError( "Target triple must be specified or inferable from inputs"); - // Link in SYCL device library files. - for (auto &File : *SYCLDeviceLibFiles) { + // Link in device library files. + for (auto &File : *DeviceLibFiles) { auto LibMod = getBitcodeModule(File, C); if (!LibMod) return LibMod.takeError(); @@ -417,7 +409,7 @@ static Error runCodeGen(StringRef File, const llvm::Triple &TargetTriple, /// \param OutputFile The output file name. /// \param Args Encompasses all arguments required for linking and wrapping /// device code and will be parsed to generate options required to be passed -/// into the SYCL AOT compilation step. +/// into the AOT compilation step. static Error runAOTCompileIntelCPU(StringRef InputFile, StringRef OutputFile, const ArgList &Args) { SmallVector<StringRef, 8> CmdArgs; @@ -445,7 +437,7 @@ static Error runAOTCompileIntelCPU(StringRef InputFile, StringRef OutputFile, /// \param OutputFile The output file name. /// \param Args Encompasses all arguments required for linking and wrapping /// device code and will be parsed to generate options required to be passed -/// into the SYCL AOT compilation step. +/// into the AOT compilation step. static Error runAOTCompileIntelGPU(StringRef InputFile, StringRef OutputFile, const ArgList &Args) { SmallVector<StringRef, 8> CmdArgs; @@ -481,7 +473,7 @@ static Error runAOTCompileIntelGPU(StringRef InputFile, StringRef OutputFile, /// \param OutputFile The output file name. /// \param Args Encompasses all arguments required for linking and wrapping /// device code and will be parsed to generate options required to be passed -/// into the SYCL AOT compilation step. +/// into the AOT compilation step. static Error runAOTCompile(StringRef InputFile, StringRef OutputFile, const ArgList &Args) { StringRef Arch = Args.getLastArgValue(OPT_arch_EQ); @@ -653,15 +645,20 @@ static bool canSkipModuleSplit(IRSplitMode Mode, const Module &M, } /// Performs the following steps: -/// 1. Link input device code (user code and SYCL device library code). -/// 2. Run SPIR-V code generation. +/// 1. Link all input bitcode files together with device library files. +/// 2. Optionally split the linked module according to the requested +/// IRSplitMode. +/// 3. Run SPIR-V code generation on each (split) module. +/// 4. Optionally run AOT compilation when targeting an Intel offload arch. +/// 5. Pack the resulting images into a single OffloadBinary written to the +/// output file. Error runSYCLLink(ArrayRef<std::string> Files, const ArgList &Args) { llvm::TimeTraceScope TimeScope("SYCL device linking"); LLVMContext C; - // Link all input bitcode files and SYCL device library files, if any. - Expected<LinkResult> LinkedOrErr = linkDeviceCode(Files, Args, C); + // Link all input bitcode files and device library files, if any. + Expected<LinkResult> LinkedOrErr = link(Files, Args, C); if (!LinkedOrErr) return LinkedOrErr.takeError(); LinkResult &Result = *LinkedOrErr; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
