https://github.com/YuriPlyakhin updated 
https://github.com/llvm/llvm-project/pull/199777

>From 84ae86c7403516e22048145fdd2c9506673e8ea6 Mon Sep 17 00:00:00 2001
From: "Plyakhin, Yury" <[email protected]>
Date: Tue, 26 May 2026 23:49:51 +0200
Subject: [PATCH 1/8] [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;

>From 1e117e814f24de3dad2f219118235c17beb84c66 Mon Sep 17 00:00:00 2001
From: "Plyakhin, Yury" <[email protected]>
Date: Thu, 28 May 2026 02:12:34 +0200
Subject: [PATCH 2/8] addressed feedback

---
 clang/test/Driver/link-device-code.test       |  2 +-
 .../OffloadTools/clang-sycl-linker/basic.ll   |  9 +--
 .../clang-sycl-linker/ClangSYCLLinker.cpp     | 79 +++++++++++--------
 clang/tools/clang-sycl-linker/SYCLLinkOpts.td | 15 ++--
 4 files changed, 59 insertions(+), 46 deletions(-)

diff --git a/clang/test/Driver/link-device-code.test 
b/clang/test/Driver/link-device-code.test
index eb75eaf1fe5c2..e1c58beb0d02c 100644
--- a/clang/test/Driver/link-device-code.test
+++ b/clang/test/Driver/link-device-code.test
@@ -8,7 +8,7 @@
 
 # RUN: not clang-sycl-linker %t.bar.bc %t.baz.bc -triple=spirv64 --dry-run -o 
a.spv --print-linked-module 2>&1 | FileCheck %s 
--check-prefix=CHECK-MULTIPLE-DEFS
 
-# RUN: clang-sycl-linker %t.foo.bc %t.bar.bc -device-libs=%t.libLLVMSYCL.bc 
-library-path= -triple=spirv64 --dry-run -o a.spv --print-linked-module 2>&1 | 
FileCheck %s --check-prefix=CHECK-DEVICE-LIB
+# RUN: clang-sycl-linker %t.foo.bc %t.bar.bc --bc-library %t.libLLVMSYCL.bc -L 
"" -triple=spirv64 --dry-run -o a.spv --print-linked-module 2>&1 | FileCheck %s 
--check-prefix=CHECK-DEVICE-LIB
 
 ; CHECK-SIMPLE: define {{.*}}foo_func1{{.*}}
 ; CHECK-SIMPLE: define {{.*}}foo_func2{{.*}}
diff --git a/clang/test/OffloadTools/clang-sycl-linker/basic.ll 
b/clang/test/OffloadTools/clang-sycl-linker/basic.ll
index f0e1c9c010ee4..4ee3135904c56 100644
--- a/clang/test/OffloadTools/clang-sycl-linker/basic.ll
+++ b/clang/test/OffloadTools/clang-sycl-linker/basic.ll
@@ -21,7 +21,7 @@
 ; RUN: mkdir -p %t/libs
 ; RUN: touch %t/libs/lib1.bc
 ; 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: clang-sycl-linker --dry-run -v --module-split-mode=none %t/input1.bc 
%t/input2.bc --library-path=%t/libs --bc-library lib1.bc --bc-library lib2.bc 
-o a.spv 2>&1 \
 ; RUN:   | FileCheck %s --check-prefix=DEVLIBS
 ; DEVLIBS:      link: inputs: {{.*}}.bc  libfiles: {{.*}}lib1.bc, 
{{.*}}lib2.bc  output: [[LLVMLINKOUT:.*]].bc
 ; DEVLIBS-NEXT: LLVM backend: input: [[LLVMLINKOUT]].bc, output: a_0.spv
@@ -33,12 +33,9 @@
 ; FILETYPEERROR: Unsupported file type
 ;
 ; Test to see if device library related errors are emitted.
-; RUN: not clang-sycl-linker --dry-run %t/input1.bc %t/input2.bc 
--library-path=%t/libs --device-libs= -o a.spv 2>&1 \
-; RUN:   | FileCheck %s --check-prefix=DEVLIBSERR1
-; 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: not clang-sycl-linker --dry-run %t/input1.bc %t/input2.bc 
--library-path=%t/libs --bc-library lib1.bc --bc-library lib2.bc --bc-library 
lib3.bc -o a.spv 2>&1 \
 ; RUN:   | FileCheck %s --check-prefix=DEVLIBSERR2
-; DEVLIBSERR2: '{{.*}}lib3.bc' device library file is not found
+; DEVLIBSERR2: '{{.*}}lib3.bc' library file 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 \
diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp 
b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp
index 92e2cfdf8f4eb..9db3c7e3f83c6 100644
--- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp
+++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp
@@ -184,7 +184,7 @@ Error executeCommands(StringRef ExecutablePath, 
ArrayRef<StringRef> Args) {
 }
 
 Expected<SmallVector<std::string>> getInput(const ArgList &Args) {
-  // Collect all input bitcode files to be passed to the device linking stage.
+  // Collect all input bitcode files to be passed to the linking stage.
   SmallVector<std::string> BitcodeFiles;
   for (const opt::Arg *Arg : Args.filtered(OPT_INPUT)) {
     std::optional<std::string> Filename = std::string(Arg->getValue());
@@ -217,28 +217,39 @@ Expected<std::unique_ptr<Module>> 
getBitcodeModule(StringRef File,
   return createStringError(Err.getMessage());
 }
 
-/// Gather all device library files.
-/// The list of files and its location are passed from driver.
-Expected<SmallVector<std::string>> getDeviceLibs(const ArgList &Args) {
-  SmallVector<std::string> DeviceLibFiles;
-  StringRef LibraryPath;
-  if (Arg *A = Args.getLastArg(OPT_library_path_EQ))
-    LibraryPath = A->getValue();
-  if (Arg *A = Args.getLastArg(OPT_device_libs_EQ)) {
-    if (A->getValues().size() == 0)
-      return createStringError(
-          "Number of device library files cannot be zero.");
-    for (StringRef Val : A->getValues()) {
-      SmallString<128> LibName(LibraryPath);
-      llvm::sys::path::append(LibName, Val);
-      if (llvm::sys::fs::exists(LibName))
-        DeviceLibFiles.push_back(std::string(LibName));
-      else
-        return createStringError("'" + LibName +
-                                 "' device library file is not found.");
-    }
+std::optional<std::string> findFile(StringRef Dir, const Twine &Name) {
+  SmallString<128> Path(Dir);
+  llvm::sys::path::append(Path, Name);
+  if (sys::fs::exists(Path))
+    return static_cast<std::string>(Path);
+  return std::nullopt;
+}
+
+std::optional<std::string> searchLibrary(StringRef Name,
+                                         ArrayRef<StringRef> SearchPaths) {
+  for (StringRef Dir : SearchPaths)
+    if (std::optional<std::string> File = findFile(Dir, Name))
+      return File;
+  return std::nullopt;
+}
+
+/// Gather all library files. The list of files and its location are passed 
from
+/// driver.
+Expected<SmallVector<std::string>> getBCLibraryNames(const ArgList &Args) {
+  SmallVector<StringRef> LibraryPaths;
+  for (const opt::Arg *Arg : Args.filtered(OPT_library_path))
+    LibraryPaths.push_back(Arg->getValue());
+
+  SmallVector<std::string> LibraryFiles;
+  for (const opt::Arg *Arg : Args.filtered(OPT_bc_library_S)) {
+    std::optional<std::string> LibName =
+        searchLibrary(Arg->getValue(), LibraryPaths);
+    if (!LibName)
+      return createStringError("'%s' library file not found.", 
Arg->getValue());
+    LibraryFiles.push_back(std::move(*LibName));
   }
-  return DeviceLibFiles;
+
+  return LibraryFiles;
 }
 
 struct LinkResult {
@@ -252,7 +263,7 @@ struct LinkResult {
 /// first input that supplies a triple as canonical. Issue an error if any
 /// triple inputs disagree.
 /// 2. Link all input bitcode images into one image using the linkInModule API.
-/// 3. Gather all device library bitcode images.
+/// 3. Gather all 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> link(ArrayRef<std::string> InputFiles, const ArgList 
&Args,
@@ -261,10 +272,10 @@ Expected<LinkResult> link(ArrayRef<std::string> 
InputFiles, const ArgList &Args,
 
   assert(InputFiles.size() && "No inputs to link");
 
-  // Get all device library files, if any.
-  Expected<SmallVector<std::string>> DeviceLibFiles = getDeviceLibs(Args);
-  if (!DeviceLibFiles)
-    return DeviceLibFiles.takeError();
+  // Get all library files.
+  Expected<SmallVector<std::string>> BCLibFiles = getBCLibraryNames(Args);
+  if (!BCLibFiles)
+    return BCLibFiles.takeError();
 
   // Create a new file to write the linked file to.
   auto BitcodeOutput =
@@ -275,7 +286,7 @@ Expected<LinkResult> link(ArrayRef<std::string> InputFiles, 
const ArgList &Args,
   if (Verbose || DryRun) {
     std::string Inputs = llvm::join(InputFiles.begin(), InputFiles.end(), ", 
");
     std::string LibInputs =
-        llvm::join((*DeviceLibFiles).begin(), (*DeviceLibFiles).end(), ", ");
+        llvm::join((*BCLibFiles).begin(), (*BCLibFiles).end(), ", ");
     errs() << formatv("link: inputs: {0} libfiles: {1} output: {2}\n", Inputs,
                       LibInputs, *BitcodeOutput);
   }
@@ -311,8 +322,8 @@ Expected<LinkResult> link(ArrayRef<std::string> InputFiles, 
const ArgList &Args,
     return createStringError(
         "Target triple must be specified or inferable from inputs");
 
-  // Link in device library files.
-  for (auto &File : *DeviceLibFiles) {
+  // Link in library files.
+  for (auto &File : *BCLibFiles) {
     auto LibMod = getBitcodeModule(File, C);
     if (!LibMod)
       return LibMod.takeError();
@@ -645,19 +656,19 @@ static bool canSkipModuleSplit(IRSplitMode Mode, const 
Module &M,
 }
 
 /// Performs the following steps:
-/// 1. Link all input bitcode files together with device library files.
+/// 1. Link all input bitcode files together with 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.
+/// 4. Optionally run AOT compilation when targeting an Intel HW 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");
+  llvm::TimeTraceScope TimeScope("SYCL linking");
 
   LLVMContext C;
 
-  // Link all input bitcode files and device library files, if any.
+  // Link all input bitcode files and library files.
   Expected<LinkResult> LinkedOrErr = link(Files, Args, C);
   if (!LinkedOrErr)
     return LinkedOrErr.takeError();
diff --git a/clang/tools/clang-sycl-linker/SYCLLinkOpts.td 
b/clang/tools/clang-sycl-linker/SYCLLinkOpts.td
index 171915c29bd93..de8bd75f752a1 100644
--- a/clang/tools/clang-sycl-linker/SYCLLinkOpts.td
+++ b/clang/tools/clang-sycl-linker/SYCLLinkOpts.td
@@ -17,12 +17,17 @@ def o : JoinedOrSeparate<["-"], "o">, MetaVarName<"<path>">,
 def output : Separate<["--"], "output-file">, Alias<o>, Flags<[HelpHidden]>,
   HelpText<"Alias for -o">;
 
-def library_path_EQ : Joined<["--", "-"], "library-path=">,
-  Flags<[HelpHidden]>, HelpText<"Add <dir> to the library search path">;
+def library_path : JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">,
+  HelpText<"Add <dir> to the library search path">;
+def library_path_S : Separate<["--", "-"], "library-path">, 
Flags<[HelpHidden]>,
+  Alias<library_path>;
+def library_path_EQ : Joined<["--", "-"], "library-path=">, 
Flags<[HelpHidden]>,
+  Alias<library_path>;
 
-def device_libs_EQ : CommaJoined<["--", "-"], "device-libs=">,
-  Flags<[LinkerOnlyOption]>,
-  HelpText<"A comma separated list of device libraries that are linked during 
the device link.">;
+def bc_library_S : Separate<["--", "-"], "bc-library">, MetaVarName<"<name>">,
+  HelpText<"Search for LLVM bitcode library <name>. Library name is provided 
with extension, e.g. --bc-library foo.bc">;
+def bc_library_EQ : Joined<["--", "-"], "bc-library=">, Flags<[HelpHidden]>,
+  Alias<bc_library_S>;
 
 def arch_EQ : Joined<["--", "-"], "arch=">,
               Flags<[LinkerOnlyOption]>,

>From 8910f8307175ab3d1199bafb7b76c96dbe5db4da Mon Sep 17 00:00:00 2001
From: "Plyakhin, Yury" <[email protected]>
Date: Thu, 28 May 2026 02:28:38 +0200
Subject: [PATCH 3/8] fix lib search

---
 clang/test/Driver/link-device-code.test           | 2 +-
 clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/clang/test/Driver/link-device-code.test 
b/clang/test/Driver/link-device-code.test
index e1c58beb0d02c..8673e7fc487b8 100644
--- a/clang/test/Driver/link-device-code.test
+++ b/clang/test/Driver/link-device-code.test
@@ -8,7 +8,7 @@
 
 # RUN: not clang-sycl-linker %t.bar.bc %t.baz.bc -triple=spirv64 --dry-run -o 
a.spv --print-linked-module 2>&1 | FileCheck %s 
--check-prefix=CHECK-MULTIPLE-DEFS
 
-# RUN: clang-sycl-linker %t.foo.bc %t.bar.bc --bc-library %t.libLLVMSYCL.bc -L 
"" -triple=spirv64 --dry-run -o a.spv --print-linked-module 2>&1 | FileCheck %s 
--check-prefix=CHECK-DEVICE-LIB
+# RUN: clang-sycl-linker %t.foo.bc %t.bar.bc --bc-library %t.libLLVMSYCL.bc 
-triple=spirv64 --dry-run -o a.spv --print-linked-module 2>&1 | FileCheck %s 
--check-prefix=CHECK-DEVICE-LIB
 
 ; CHECK-SIMPLE: define {{.*}}foo_func1{{.*}}
 ; CHECK-SIMPLE: define {{.*}}foo_func2{{.*}}
diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp 
b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp
index 9db3c7e3f83c6..554fab4b7f827 100644
--- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp
+++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp
@@ -227,6 +227,8 @@ std::optional<std::string> findFile(StringRef Dir, const 
Twine &Name) {
 
 std::optional<std::string> searchLibrary(StringRef Name,
                                          ArrayRef<StringRef> SearchPaths) {
+  if (sys::fs::exists(Name))
+    return Name.str();
   for (StringRef Dir : SearchPaths)
     if (std::optional<std::string> File = findFile(Dir, Name))
       return File;

>From c5b897a11683ef0059b5530315e7f68992221a79 Mon Sep 17 00:00:00 2001
From: "Plyakhin, Yury" <[email protected]>
Date: Thu, 28 May 2026 02:33:25 +0200
Subject: [PATCH 4/8] test clean up

---
 clang/test/Driver/Inputs/SYCL/bar.ll          |  8 --
 clang/test/Driver/Inputs/SYCL/baz.ll          | 16 ---
 clang/test/Driver/Inputs/SYCL/foo.ll          | 20 ----
 clang/test/Driver/Inputs/SYCL/libLLVMSYCL.ll  | 14 ---
 clang/test/Driver/link-device-code.test       | 25 -----
 .../OffloadTools/clang-sycl-linker/link.ll    | 98 +++++++++++++++++++
 6 files changed, 98 insertions(+), 83 deletions(-)
 delete mode 100644 clang/test/Driver/Inputs/SYCL/bar.ll
 delete mode 100644 clang/test/Driver/Inputs/SYCL/baz.ll
 delete mode 100644 clang/test/Driver/Inputs/SYCL/foo.ll
 delete mode 100644 clang/test/Driver/Inputs/SYCL/libLLVMSYCL.ll
 delete mode 100644 clang/test/Driver/link-device-code.test
 create mode 100644 clang/test/OffloadTools/clang-sycl-linker/link.ll

diff --git a/clang/test/Driver/Inputs/SYCL/bar.ll 
b/clang/test/Driver/Inputs/SYCL/bar.ll
deleted file mode 100644
index 9f86b8aa54827..0000000000000
--- a/clang/test/Driver/Inputs/SYCL/bar.ll
+++ /dev/null
@@ -1,8 +0,0 @@
-target datalayout = 
"e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
-target triple = "spirv64"
-
-define spir_func i32 @bar_func1(i32 %a, i32 %b) {
-entry:
-  %res = add nsw i32 %b, %a
-  ret i32 %res
-}
diff --git a/clang/test/Driver/Inputs/SYCL/baz.ll 
b/clang/test/Driver/Inputs/SYCL/baz.ll
deleted file mode 100644
index 1fd7e44881981..0000000000000
--- a/clang/test/Driver/Inputs/SYCL/baz.ll
+++ /dev/null
@@ -1,16 +0,0 @@
-target datalayout = 
"e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
-target triple = "spirv64"
-
-define spir_func i32 @bar_func1(i32 %a, i32 %b) {
-entry:
-  %mul = shl nsw i32 %a, 1
-  %res = add nsw i32 %mul, %b
-  ret i32 %res
-}
-
-define spir_func i32 @baz_func1(i32 %a) {
-entry:
-  %add = add nsw i32 %a, 5
-  %res = tail call spir_func i32 @bar_func1(i32 %a, i32 %add)
-  ret i32 %res
-}
diff --git a/clang/test/Driver/Inputs/SYCL/foo.ll 
b/clang/test/Driver/Inputs/SYCL/foo.ll
deleted file mode 100644
index fbfd8c53bff9c..0000000000000
--- a/clang/test/Driver/Inputs/SYCL/foo.ll
+++ /dev/null
@@ -1,20 +0,0 @@
-target datalayout = 
"e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
-target triple = "spirv64"
-
-define spir_func i32 @foo_func1(i32 %a, i32 %b) {
-entry:
-  %call = tail call spir_func i32 @addFive(i32 %b)
-  %res = tail call spir_func i32 @bar_func1(i32 %a, i32 %call)
-  ret i32 %res
-}
-
-declare spir_func i32 @bar_func1(i32, i32)
-
-declare spir_func i32 @addFive(i32)
-
-define spir_func i32 @foo_func2(i32 %c, i32 %d, i32 %e) {
-entry:
-  %call = tail call spir_func i32 @foo_func1(i32 %c, i32 %d)
-  %res = mul nsw i32 %call, %e
-  ret i32 %res
-}
diff --git a/clang/test/Driver/Inputs/SYCL/libLLVMSYCL.ll 
b/clang/test/Driver/Inputs/SYCL/libLLVMSYCL.ll
deleted file mode 100644
index b161bde3b0c1e..0000000000000
--- a/clang/test/Driver/Inputs/SYCL/libLLVMSYCL.ll
+++ /dev/null
@@ -1,14 +0,0 @@
-target datalayout = 
"e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
-target triple = "spirv64"
-
-define spir_func i32 @addFive(i32 %a) {
-entry:
-  %res = add nsw i32 %a, 5
-  ret i32 %res
-}
-
-define spir_func i32 @unusedFunc(i32 %a) {
-entry:
-  %res = mul nsw i32 %a, 5
-  ret i32 %res
-}
diff --git a/clang/test/Driver/link-device-code.test 
b/clang/test/Driver/link-device-code.test
deleted file mode 100644
index 8673e7fc487b8..0000000000000
--- a/clang/test/Driver/link-device-code.test
+++ /dev/null
@@ -1,25 +0,0 @@
-# REQUIRES: spirv-registered-target
-
-# RUN: llvm-as %S/Inputs/SYCL/foo.ll -o %t.foo.bc
-# RUN: llvm-as %S/Inputs/SYCL/bar.ll -o %t.bar.bc
-# RUN: llvm-as %S/Inputs/SYCL/baz.ll -o %t.baz.bc
-# RUN: llvm-as %S/Inputs/SYCL/libLLVMSYCL.ll -o %t.libLLVMSYCL.bc
-# RUN: clang-sycl-linker %t.foo.bc %t.bar.bc -triple=spirv64 --dry-run -o 
a.spv --print-linked-module 2>&1 | FileCheck %s --check-prefix=CHECK-SIMPLE
-
-# RUN: not clang-sycl-linker %t.bar.bc %t.baz.bc -triple=spirv64 --dry-run -o 
a.spv --print-linked-module 2>&1 | FileCheck %s 
--check-prefix=CHECK-MULTIPLE-DEFS
-
-# RUN: clang-sycl-linker %t.foo.bc %t.bar.bc --bc-library %t.libLLVMSYCL.bc 
-triple=spirv64 --dry-run -o a.spv --print-linked-module 2>&1 | FileCheck %s 
--check-prefix=CHECK-DEVICE-LIB
-
-; CHECK-SIMPLE: define {{.*}}foo_func1{{.*}}
-; CHECK-SIMPLE: define {{.*}}foo_func2{{.*}}
-; CHECK-SIMPLE: define {{.*}}bar_func1{{.*}}
-; CHECK-SIMPLE-NOT: define {{.*}}addFive{{.*}}
-; CHECK-SIMPLE-NOT: define {{.*}}unusedFunc{{.*}}
-
-; CHECK-MULTIPLE-DEFS: error: Linking globals named {{.*}}bar_func1{{.*}} 
symbol multiply defined!
-
-; CHECK-DEVICE-LIB: define {{.*}}foo_func1{{.*}}
-; CHECK-DEVICE-LIB: define {{.*}}foo_func2{{.*}}
-; CHECK-DEVICE-LIB: define {{.*}}bar_func1{{.*}}
-; CHECK-DEVICE-LIB: define {{.*}}addFive{{.*}}
-; CHECK-DEVICE-LIB-NOT: define {{.*}}unusedFunc{{.*}}
diff --git a/clang/test/OffloadTools/clang-sycl-linker/link.ll 
b/clang/test/OffloadTools/clang-sycl-linker/link.ll
new file mode 100644
index 0000000000000..62c63e23828a7
--- /dev/null
+++ b/clang/test/OffloadTools/clang-sycl-linker/link.ll
@@ -0,0 +1,98 @@
+; Tests clang-sycl-linker linking behavior.
+;
+; REQUIRES: spirv-registered-target
+;
+; RUN: rm -rf %t && split-file %s %t
+; RUN: llvm-as %t/foo.ll -o %t/foo.bc
+; RUN: llvm-as %t/bar.ll -o %t/bar.bc
+; RUN: llvm-as %t/baz.ll -o %t/baz.bc
+; RUN: llvm-as %t/libLLVMSYCL.ll -o %t/libLLVMSYCL.bc
+;
+; Test linking two input files.
+; RUN: clang-sycl-linker %t/foo.bc %t/bar.bc -triple=spirv64 --dry-run -o 
a.spv --print-linked-module 2>&1 \
+; RUN:   | FileCheck %s --check-prefix=CHECK-SIMPLE
+; CHECK-SIMPLE: define {{.*}}foo_func1{{.*}}
+; CHECK-SIMPLE: define {{.*}}foo_func2{{.*}}
+; CHECK-SIMPLE: define {{.*}}bar_func1{{.*}}
+; CHECK-SIMPLE-NOT: define {{.*}}addFive{{.*}}
+; CHECK-SIMPLE-NOT: define {{.*}}unusedFunc{{.*}}
+;
+; Test that multiply defined symbols are reported as errors.
+; RUN: not clang-sycl-linker %t/bar.bc %t/baz.bc -triple=spirv64 --dry-run -o 
a.spv --print-linked-module 2>&1 \
+; RUN:   | FileCheck %s --check-prefix=CHECK-MULTIPLE-DEFS
+; CHECK-MULTIPLE-DEFS: error: Linking globals named {{.*}}bar_func1{{.*}} 
symbol multiply defined!
+;
+; Test linking with a device library file.
+; RUN: clang-sycl-linker %t/foo.bc %t/bar.bc --bc-library %t/libLLVMSYCL.bc 
-triple=spirv64 --dry-run -o a.spv --print-linked-module 2>&1 \
+; RUN:   | FileCheck %s --check-prefix=CHECK-DEVICE-LIB
+; CHECK-DEVICE-LIB: define {{.*}}foo_func1{{.*}}
+; CHECK-DEVICE-LIB: define {{.*}}foo_func2{{.*}}
+; CHECK-DEVICE-LIB: define {{.*}}bar_func1{{.*}}
+; CHECK-DEVICE-LIB: define {{.*}}addFive{{.*}}
+; CHECK-DEVICE-LIB-NOT: define {{.*}}unusedFunc{{.*}}
+
+;--- foo.ll
+target datalayout = 
"e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
+target triple = "spirv64"
+
+define spir_func i32 @foo_func1(i32 %a, i32 %b) {
+entry:
+  %call = tail call spir_func i32 @addFive(i32 %b)
+  %res = tail call spir_func i32 @bar_func1(i32 %a, i32 %call)
+  ret i32 %res
+}
+
+declare spir_func i32 @bar_func1(i32, i32)
+
+declare spir_func i32 @addFive(i32)
+
+define spir_func i32 @foo_func2(i32 %c, i32 %d, i32 %e) {
+entry:
+  %call = tail call spir_func i32 @foo_func1(i32 %c, i32 %d)
+  %res = mul nsw i32 %call, %e
+  ret i32 %res
+}
+
+;--- bar.ll
+target datalayout = 
"e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
+target triple = "spirv64"
+
+define spir_func i32 @bar_func1(i32 %a, i32 %b) {
+entry:
+  %res = add nsw i32 %b, %a
+  ret i32 %res
+}
+
+;--- baz.ll
+target datalayout = 
"e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
+target triple = "spirv64"
+
+define spir_func i32 @bar_func1(i32 %a, i32 %b) {
+entry:
+  %mul = shl nsw i32 %a, 1
+  %res = add nsw i32 %mul, %b
+  ret i32 %res
+}
+
+define spir_func i32 @baz_func1(i32 %a) {
+entry:
+  %add = add nsw i32 %a, 5
+  %res = tail call spir_func i32 @bar_func1(i32 %a, i32 %add)
+  ret i32 %res
+}
+
+;--- libLLVMSYCL.ll
+target datalayout = 
"e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
+target triple = "spirv64"
+
+define spir_func i32 @addFive(i32 %a) {
+entry:
+  %res = add nsw i32 %a, 5
+  ret i32 %res
+}
+
+define spir_func i32 @unusedFunc(i32 %a) {
+entry:
+  %res = mul nsw i32 %a, 5
+  ret i32 %res
+}

>From 10dd7229194c87a67b95231abf1415296e56bcd7 Mon Sep 17 00:00:00 2001
From: "Plyakhin, Yury" <[email protected]>
Date: Thu, 28 May 2026 02:42:35 +0200
Subject: [PATCH 5/8] updated test

---
 clang/test/OffloadTools/clang-sycl-linker/link.ll | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang/test/OffloadTools/clang-sycl-linker/link.ll 
b/clang/test/OffloadTools/clang-sycl-linker/link.ll
index 62c63e23828a7..d675f0400b182 100644
--- a/clang/test/OffloadTools/clang-sycl-linker/link.ll
+++ b/clang/test/OffloadTools/clang-sycl-linker/link.ll
@@ -6,7 +6,7 @@
 ; RUN: llvm-as %t/foo.ll -o %t/foo.bc
 ; RUN: llvm-as %t/bar.ll -o %t/bar.bc
 ; RUN: llvm-as %t/baz.ll -o %t/baz.bc
-; RUN: llvm-as %t/libLLVMSYCL.ll -o %t/libLLVMSYCL.bc
+; RUN: llvm-as %t/libfoo.ll -o %t/libfoo.bc
 ;
 ; Test linking two input files.
 ; RUN: clang-sycl-linker %t/foo.bc %t/bar.bc -triple=spirv64 --dry-run -o 
a.spv --print-linked-module 2>&1 \
@@ -22,8 +22,8 @@
 ; RUN:   | FileCheck %s --check-prefix=CHECK-MULTIPLE-DEFS
 ; CHECK-MULTIPLE-DEFS: error: Linking globals named {{.*}}bar_func1{{.*}} 
symbol multiply defined!
 ;
-; Test linking with a device library file.
-; RUN: clang-sycl-linker %t/foo.bc %t/bar.bc --bc-library %t/libLLVMSYCL.bc 
-triple=spirv64 --dry-run -o a.spv --print-linked-module 2>&1 \
+; Test linking with a BC library file.
+; RUN: clang-sycl-linker %t/foo.bc %t/bar.bc --bc-library %t/libfoo.bc 
-triple=spirv64 --dry-run -o a.spv --print-linked-module 2>&1 \
 ; RUN:   | FileCheck %s --check-prefix=CHECK-DEVICE-LIB
 ; CHECK-DEVICE-LIB: define {{.*}}foo_func1{{.*}}
 ; CHECK-DEVICE-LIB: define {{.*}}foo_func2{{.*}}
@@ -81,7 +81,7 @@ entry:
   ret i32 %res
 }
 
-;--- libLLVMSYCL.ll
+;--- libfoo.ll
 target datalayout = 
"e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
 target triple = "spirv64"
 

>From 9fbf0bf1c6eefd177876708e389e7cfa880ad8d9 Mon Sep 17 00:00:00 2001
From: "Plyakhin, Yury" <[email protected]>
Date: Thu, 28 May 2026 02:54:41 +0200
Subject: [PATCH 6/8] cleanup

---
 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 4ee3135904c56..da4d409d60f15 100644
--- a/clang/test/OffloadTools/clang-sycl-linker/basic.ll
+++ b/clang/test/OffloadTools/clang-sycl-linker/basic.ll
@@ -34,8 +34,8 @@
 ;
 ; Test to see if device library related errors are emitted.
 ; RUN: not clang-sycl-linker --dry-run %t/input1.bc %t/input2.bc 
--library-path=%t/libs --bc-library lib1.bc --bc-library lib2.bc --bc-library 
lib3.bc -o a.spv 2>&1 \
-; RUN:   | FileCheck %s --check-prefix=DEVLIBSERR2
-; DEVLIBSERR2: '{{.*}}lib3.bc' library file not found
+; RUN:   | FileCheck %s --check-prefix=DEVLIBSERR
+; DEVLIBSERR: '{{.*}}lib3.bc' library file 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 \

>From 8a8c692db4cf4ac80662e9d979973496c95c76d9 Mon Sep 17 00:00:00 2001
From: "Plyakhin, Yury" <[email protected]>
Date: Thu, 28 May 2026 03:01:12 +0200
Subject: [PATCH 7/8] simplified test

---
 .../OffloadTools/clang-sycl-linker/link.ll     | 18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/clang/test/OffloadTools/clang-sycl-linker/link.ll 
b/clang/test/OffloadTools/clang-sycl-linker/link.ll
index d675f0400b182..72473a6e0c34b 100644
--- a/clang/test/OffloadTools/clang-sycl-linker/link.ll
+++ b/clang/test/OffloadTools/clang-sycl-linker/link.ll
@@ -9,21 +9,20 @@
 ; RUN: llvm-as %t/libfoo.ll -o %t/libfoo.bc
 ;
 ; Test linking two input files.
-; RUN: clang-sycl-linker %t/foo.bc %t/bar.bc -triple=spirv64 --dry-run -o 
a.spv --print-linked-module 2>&1 \
+; RUN: clang-sycl-linker %t/foo.bc %t/bar.bc --dry-run -o a.spv 
--print-linked-module 2>&1 \
 ; RUN:   | FileCheck %s --check-prefix=CHECK-SIMPLE
 ; CHECK-SIMPLE: define {{.*}}foo_func1{{.*}}
 ; CHECK-SIMPLE: define {{.*}}foo_func2{{.*}}
 ; CHECK-SIMPLE: define {{.*}}bar_func1{{.*}}
 ; CHECK-SIMPLE-NOT: define {{.*}}addFive{{.*}}
-; CHECK-SIMPLE-NOT: define {{.*}}unusedFunc{{.*}}
 ;
 ; Test that multiply defined symbols are reported as errors.
-; RUN: not clang-sycl-linker %t/bar.bc %t/baz.bc -triple=spirv64 --dry-run -o 
a.spv --print-linked-module 2>&1 \
+; RUN: not clang-sycl-linker %t/bar.bc %t/baz.bc --dry-run -o a.spv 2>&1 \
 ; RUN:   | FileCheck %s --check-prefix=CHECK-MULTIPLE-DEFS
 ; CHECK-MULTIPLE-DEFS: error: Linking globals named {{.*}}bar_func1{{.*}} 
symbol multiply defined!
 ;
 ; Test linking with a BC library file.
-; RUN: clang-sycl-linker %t/foo.bc %t/bar.bc --bc-library %t/libfoo.bc 
-triple=spirv64 --dry-run -o a.spv --print-linked-module 2>&1 \
+; RUN: clang-sycl-linker %t/foo.bc %t/bar.bc --bc-library %t/libfoo.bc 
--dry-run -o a.spv --print-linked-module 2>&1 \
 ; RUN:   | FileCheck %s --check-prefix=CHECK-DEVICE-LIB
 ; CHECK-DEVICE-LIB: define {{.*}}foo_func1{{.*}}
 ; CHECK-DEVICE-LIB: define {{.*}}foo_func2{{.*}}
@@ -46,10 +45,9 @@ declare spir_func i32 @bar_func1(i32, i32)
 
 declare spir_func i32 @addFive(i32)
 
-define spir_func i32 @foo_func2(i32 %c, i32 %d, i32 %e) {
+define spir_func i32 @foo_func2(i32 %c, i32 %d) {
 entry:
-  %call = tail call spir_func i32 @foo_func1(i32 %c, i32 %d)
-  %res = mul nsw i32 %call, %e
+  %res = add nsw i32 %c, %d
   ret i32 %res
 }
 
@@ -74,12 +72,6 @@ entry:
   ret i32 %res
 }
 
-define spir_func i32 @baz_func1(i32 %a) {
-entry:
-  %add = add nsw i32 %a, 5
-  %res = tail call spir_func i32 @bar_func1(i32 %a, i32 %add)
-  ret i32 %res
-}
 
 ;--- libfoo.ll
 target datalayout = 
"e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"

>From 04483cb5c82b4b34cfaa7f79295fdec33b03b48d Mon Sep 17 00:00:00 2001
From: "Plyakhin, Yury" <[email protected]>
Date: Thu, 28 May 2026 03:20:46 +0200
Subject: [PATCH 8/8] improved coverage

---
 .../OffloadTools/clang-sycl-linker/basic.ll    | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/clang/test/OffloadTools/clang-sycl-linker/basic.ll 
b/clang/test/OffloadTools/clang-sycl-linker/basic.ll
index da4d409d60f15..2cadf725f576c 100644
--- a/clang/test/OffloadTools/clang-sycl-linker/basic.ll
+++ b/clang/test/OffloadTools/clang-sycl-linker/basic.ll
@@ -26,6 +26,24 @@
 ; DEVLIBS:      link: inputs: {{.*}}.bc  libfiles: {{.*}}lib1.bc, 
{{.*}}lib2.bc  output: [[LLVMLINKOUT:.*]].bc
 ; DEVLIBS-NEXT: LLVM backend: input: [[LLVMLINKOUT]].bc, output: a_0.spv
 ;
+; Test -L short form (joined) and --bc-library= joined form.
+; RUN: clang-sycl-linker --dry-run -v --module-split-mode=none %t/input1.bc 
-L%t/libs --bc-library=lib1.bc -o a.spv 2>&1 \
+; RUN:   | FileCheck %s --check-prefix=DEVLIBS-SHORT
+; DEVLIBS-SHORT: link: inputs: {{.*}}.bc  libfiles: {{.*}}libs/lib1.bc  
output: {{.*}}.bc
+;
+; Test that search continues past the first -L when the library is not found 
there. lib1.bc exists only in %t/libs (the second -L).
+; RUN: mkdir -p %t/empty
+; RUN: clang-sycl-linker --dry-run -v --module-split-mode=none %t/input1.bc -L 
%t/empty -L %t/libs --bc-library lib1.bc -o a.spv 2>&1 \
+; RUN:   | FileCheck %s --check-prefix=DEVLIBS-FALLTHROUGH
+; DEVLIBS-FALLTHROUGH: link: inputs: {{.*}}.bc  libfiles: {{.*}}libs/lib1.bc  
output: {{.*}}.bc
+;
+; Test that -L paths are searched in order: when the same name exists in 
multiple -L dirs, the first one wins.
+; RUN: mkdir -p %t/libs2
+; RUN: touch %t/libs/shadow.bc %t/libs2/shadow.bc
+; RUN: clang-sycl-linker --dry-run -v --module-split-mode=none %t/input1.bc -L 
%t/libs2 -L %t/libs --bc-library shadow.bc -o a.spv 2>&1 \
+; RUN:   | FileCheck %s --check-prefix=DEVLIBS-ORDER
+; DEVLIBS-ORDER: link: inputs: {{.*}}.bc  libfiles: {{.*}}libs2/shadow.bc  
output: {{.*}}.bc
+;
 ; Test a simple case with a random file (not bitcode) as input.
 ; RUN: touch %t/dummy.o
 ; RUN: not clang-sycl-linker %t/dummy.o -o a.spv 2>&1 \

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to