From 9f3379285af67cb6cdeee8f67a67b30974f90981 Mon Sep 17 00:00:00 2001 From: Arvind Sudarsanam Date: Tue, 11 Mar 2025 16:34:30 -0700 Subject: [PATCH 01/12] Add SPIR-V backend support inside clang-sycl-linker Signed-off-by: Arvind Sudarsanam --- clang/test/Driver/clang-sycl-linker-test.cpp | 16 +- clang/test/Driver/sycl-link-spirv-target.cpp | 6 +- .../clang-sycl-linker/ClangSYCLLinker.cpp | 165 ++++++------------ 3 files changed, 59 insertions(+), 128 deletions(-) diff --git a/clang/test/Driver/clang-sycl-linker-test.cpp b/clang/test/Driver/clang-sycl-linker-test.cpp index f358900b4fbd8..a96991020f854 100644 --- a/clang/test/Driver/clang-sycl-linker-test.cpp +++ b/clang/test/Driver/clang-sycl-linker-test.cpp @@ -6,12 +6,12 @@ // RUN: clang-sycl-linker --dry-run -triple spirv64 %t_1.bc %t_2.bc -o a.spv 2>&1 \ // RUN: | FileCheck %s --check-prefix=SIMPLE // SIMPLE: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[FIRSTLLVMLINKOUT:.*]].bc --suppress-warnings -// SIMPLE-NEXT: "{{.*}}llvm-spirv{{.*}}" {{.*}}-o a.spv [[FIRSTLLVMLINKOUT]].bc +// SIMPLE-NEXT: LLVM-SPIRV-Backend: input: {{.*}}.bc, output: a.spv // // Test that llvm-link is not called when only one input is present. // RUN: clang-sycl-linker --dry-run -triple spirv64 %t_1.bc -o a.spv 2>&1 \ // RUN: | FileCheck %s --check-prefix=SIMPLE-NO-LINK -// SIMPLE-NO-LINK: "{{.*}}llvm-spirv{{.*}}" {{.*}}-o a.spv {{.*}}.bc +// SIMPLE-NO-LINK: LLVM-SPIRV-Backend: input: {{.*}}.bc, output: a.spv // // Test a simple case with device library files specified. // RUN: touch %T/lib1.bc @@ -20,7 +20,7 @@ // RUN: | FileCheck %s --check-prefix=DEVLIBS // DEVLIBS: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[FIRSTLLVMLINKOUT:.*]].bc --suppress-warnings // DEVLIBS-NEXT: "{{.*}}llvm-link{{.*}}" -only-needed [[FIRSTLLVMLINKOUT]].bc {{.*}}lib1.bc {{.*}}lib2.bc -o [[SECONDLLVMLINKOUT:.*]].bc --suppress-warnings -// DEVLIBS-NEXT: "{{.*}}llvm-spirv{{.*}}" {{.*}}-o a.spv [[SECONDLLVMLINKOUT]].bc +// DEVLIBS-NEXT: LLVM-SPIRV-Backend: input: [[SECONDLLVMLINKOUT]].bc, output: a.spv // // Test a simple case with .o (fat object) as input. // TODO: Remove this test once fat object support is added. @@ -36,13 +36,3 @@ // RUN: not clang-sycl-linker --dry-run -triple spirv64 %t_1.bc %t_2.bc --library-path=%T --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 -// -// Test if correct set of llvm-spirv options are emitted for windows environment. -// RUN: clang-sycl-linker --dry-run -triple spirv64 --is-windows-msvc-env %t_1.bc %t_2.bc -o a.spv 2>&1 \ -// RUN: | FileCheck %s --check-prefix=LLVMOPTSWIN -// LLVMOPTSWIN: -spirv-debug-info-version=ocl-100 -spirv-allow-extra-diexpressions -spirv-allow-unknown-intrinsics=llvm.genx. -spirv-ext= -// -// Test if correct set of llvm-spirv options are emitted for linux environment. -// RUN: clang-sycl-linker --dry-run -triple spirv64 %t_1.bc %t_2.bc -o a.spv 2>&1 \ -// RUN: | FileCheck %s --check-prefix=LLVMOPTSLIN -// LLVMOPTSLIN: -spirv-debug-info-version=nonsemantic-shader-200 -spirv-allow-unknown-intrinsics=llvm.genx. -spirv-ext= diff --git a/clang/test/Driver/sycl-link-spirv-target.cpp b/clang/test/Driver/sycl-link-spirv-target.cpp index 85566c67ea92b..140a6438c7300 100644 --- a/clang/test/Driver/sycl-link-spirv-target.cpp +++ b/clang/test/Driver/sycl-link-spirv-target.cpp @@ -3,7 +3,7 @@ // // Test that -Xlinker options are being passed to clang-sycl-linker. // RUN: touch %t.bc -// RUN: %clangxx -### --target=spirv64 --sycl-link -Xlinker --llvm-spirv-path=/tmp \ -// RUN: -Xlinker --library-path=/tmp -Xlinker --device-libs=lib1.bc,lib2.bc %t.bc 2>&1 \ +// RUN: %clangxx -### --target=spirv64 --sycl-link -Xlinker --library-path=/tmp \ +// RUN: -Xlinker --device-libs=lib1.bc,lib2.bc %t.bc 2>&1 \ // RUN: | FileCheck %s -check-prefix=XLINKEROPTS -// XLINKEROPTS: "{{.*}}clang-sycl-linker{{.*}}" "--llvm-spirv-path=/tmp" "--library-path=/tmp" "--device-libs=lib1.bc,lib2.bc" "{{.*}}.bc" "-o" "a.out" +// XLINKEROPTS: "{{.*}}clang-sycl-linker{{.*}}" "--library-path=/tmp" "--device-libs=lib1.bc,lib2.bc" "{{.*}}.bc" "-o" "a.out" diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index 2bcb3757d49d0..e94c68bcb995b 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -16,6 +16,7 @@ #include "clang/Basic/Version.h" +#include "../../llvm/lib/Target/SPIRV/SPIRVAPI.h" #include "llvm/ADT/StringExtras.h" #include "llvm/BinaryFormat/Magic.h" #include "llvm/Bitcode/BitcodeWriter.h" @@ -304,121 +305,61 @@ static Expected linkDeviceLibFiles(StringRef InputFile, return *OutFileOrErr; } -/// Add any llvm-spirv option that relies on a specific Triple in addition -/// to user supplied options. -static void getSPIRVTransOpts(const ArgList &Args, - SmallVector &TranslatorArgs, - const llvm::Triple Triple) { - // Enable NonSemanticShaderDebugInfo.200 for non-Windows - const bool IsWindowsMSVC = - Triple.isWindowsMSVCEnvironment() || Args.hasArg(OPT_is_windows_msvc_env); - const bool EnableNonSemanticDebug = !IsWindowsMSVC; - if (EnableNonSemanticDebug) { - TranslatorArgs.push_back( - "-spirv-debug-info-version=nonsemantic-shader-200"); - } else { - TranslatorArgs.push_back("-spirv-debug-info-version=ocl-100"); - // Prevent crash in the translator if input IR contains DIExpression - // operations which don't have mapping to OpenCL.DebugInfo.100 spec. - TranslatorArgs.push_back("-spirv-allow-extra-diexpressions"); - } - std::string UnknownIntrinsics("-spirv-allow-unknown-intrinsics=llvm.genx."); - - TranslatorArgs.push_back(Args.MakeArgString(UnknownIntrinsics)); - - // Disable all the extensions by default - std::string ExtArg("-spirv-ext=-all"); - std::string DefaultExtArg = - ",+SPV_EXT_shader_atomic_float_add,+SPV_EXT_shader_atomic_float_min_max" - ",+SPV_KHR_no_integer_wrap_decoration,+SPV_KHR_float_controls" - ",+SPV_KHR_expect_assume,+SPV_KHR_linkonce_odr"; - std::string INTELExtArg = - ",+SPV_INTEL_subgroups,+SPV_INTEL_media_block_io" - ",+SPV_INTEL_device_side_avc_motion_estimation" - ",+SPV_INTEL_fpga_loop_controls,+SPV_INTEL_unstructured_loop_controls" - ",+SPV_INTEL_fpga_reg,+SPV_INTEL_blocking_pipes" - ",+SPV_INTEL_function_pointers,+SPV_INTEL_kernel_attributes" - ",+SPV_INTEL_io_pipes,+SPV_INTEL_inline_assembly" - ",+SPV_INTEL_arbitrary_precision_integers" - ",+SPV_INTEL_float_controls2,+SPV_INTEL_vector_compute" - ",+SPV_INTEL_fast_composite" - ",+SPV_INTEL_arbitrary_precision_fixed_point" - ",+SPV_INTEL_arbitrary_precision_floating_point" - ",+SPV_INTEL_variable_length_array,+SPV_INTEL_fp_fast_math_mode" - ",+SPV_INTEL_long_constant_composite" - ",+SPV_INTEL_arithmetic_fence" - ",+SPV_INTEL_global_variable_decorations" - ",+SPV_INTEL_cache_controls" - ",+SPV_INTEL_fpga_buffer_location" - ",+SPV_INTEL_fpga_argument_interfaces" - ",+SPV_INTEL_fpga_invocation_pipelining_attributes" - ",+SPV_INTEL_fpga_latency_control" - ",+SPV_INTEL_task_sequence" - ",+SPV_KHR_shader_clock" - ",+SPV_INTEL_bindless_images"; - ExtArg = ExtArg + DefaultExtArg + INTELExtArg; - ExtArg += ",+SPV_INTEL_token_type" - ",+SPV_INTEL_bfloat16_conversion" - ",+SPV_INTEL_joint_matrix" - ",+SPV_INTEL_hw_thread_queries" - ",+SPV_KHR_uniform_group_instructions" - ",+SPV_INTEL_masked_gather_scatter" - ",+SPV_INTEL_tensor_float32_conversion" - ",+SPV_INTEL_optnone" - ",+SPV_KHR_non_semantic_info" - ",+SPV_KHR_cooperative_matrix"; - TranslatorArgs.push_back(Args.MakeArgString(ExtArg)); -} - /// Run LLVM to SPIR-V translation. -/// Converts 'File' from LLVM bitcode to SPIR-V format using llvm-spirv tool. +/// Converts 'File' from LLVM bitcode to SPIR-V format using SPIR-V backend, /// 'Args' encompasses all arguments required for linking device code and will -/// be parsed to generate options required to be passed into llvm-spirv tool. -static Expected runLLVMToSPIRVTranslation(StringRef File, - const ArgList &Args) { - llvm::TimeTraceScope TimeScope("LLVMToSPIRVTranslation"); - StringRef LLVMSPIRVPath = Args.getLastArgValue(OPT_llvm_spirv_path_EQ); - Expected LLVMToSPIRVProg = - findProgram(Args, "llvm-spirv", {LLVMSPIRVPath}); - if (!LLVMToSPIRVProg) - return LLVMToSPIRVProg.takeError(); - - SmallVector CmdArgs; - CmdArgs.push_back(*LLVMToSPIRVProg); - const llvm::Triple Triple(Args.getLastArgValue(OPT_triple)); - getSPIRVTransOpts(Args, CmdArgs, Triple); - StringRef LLVMToSPIRVOptions; - if (Arg *A = Args.getLastArg(OPT_llvm_spirv_options_EQ)) - LLVMToSPIRVOptions = A->getValue(); - LLVMToSPIRVOptions.split(CmdArgs, " ", /* MaxSplit = */ -1, - /* KeepEmpty = */ false); - CmdArgs.append({"-o", OutputFile}); - CmdArgs.push_back(File); - if (Error Err = executeCommands(*LLVMToSPIRVProg, CmdArgs)) - return std::move(Err); - - if (!SPIRVDumpDir.empty()) { - std::error_code EC = - llvm::sys::fs::create_directory(SPIRVDumpDir, /*IgnoreExisting*/ true); - if (EC) - return createStringError( - EC, - formatv("failed to create dump directory. path: {0}, error_code: {1}", - SPIRVDumpDir, EC.value())); - - StringRef Path = OutputFile; - StringRef Filename = llvm::sys::path::filename(Path); - SmallString<128> CopyPath = SPIRVDumpDir; - CopyPath.append(Filename); - EC = llvm::sys::fs::copy_file(Path, CopyPath); - if (EC) - return createStringError( - EC, - formatv( - "failed to copy file. original: {0}, copy: {1}, error_code: {2}", - Path, CopyPath, EC.value())); +/// be parsed to generate options required to be passed into the backend. +static Expected runLLVMSPIRVBackend(StringRef File, + const ArgList &Args) { + llvm::TimeTraceScope TimeScope("LLVMToSPIRVTranslationViaSPIRVBackend"); + std::vector ExtNames, Opts; + if (Verbose || DryRun) { + errs() << formatv("LLVM-SPIRV-Backend: input: {0}, output: {1}\n", File, + OutputFile); + if (DryRun) + return OutputFile; } + SMDiagnostic Err; + LLVMContext C; + std::unique_ptr M = parseIRFile(File, Err, C); + if (!M) + return createStringError(inconvertibleErrorCode(), Err.getMessage()); + + static const std::string DefaultTriple = "spirv64v1.6-unknown-unknown"; + + // Correct the Triple value if needed + // TODO: Remove this correction once we start using spirv64/spirv32 triples + // everywhere. + Triple TargetTriple(M->getTargetTriple()); + if (TargetTriple.isSPIR()) { + TargetTriple.setArch(TargetTriple.getArch() == Triple::spir64 + ? Triple::spirv64 + : Triple::spirv32, + TargetTriple.getSubArch()); + M->setTargetTriple(TargetTriple); + // We need to reset Data Layout to conform with the TargetMachine + M->setDataLayout(""); + } + if (TargetTriple.getTriple().empty()) + TargetTriple.setTriple(DefaultTriple); + TargetTriple.setArch(TargetTriple.getArch(), Triple::SPIRVSubArch_v16); + M->setTargetTriple(TargetTriple); + + int FD = -1; + if (std::error_code EC = sys::fs::openFileForWrite(OutputFile, FD)) + return errorCodeToError(EC); + auto OS = std::make_unique(FD, true); + + std::string Result, ErrMsg; + // List of allowed extensions. Currently, all extensions are allowed. + // TODO: Update list of allowed extensions for SYCL compilation flow. + static const std::vector AllowExtNames{"all"}; + // Translate the Module into SPIR-V + if (!SPIRVTranslateModule(M.release(), Result, ErrMsg, AllowExtNames, {})) + return createStringError( + "SPIRVTranslation: SPIRV translation failed with " + ErrMsg); + *OS << Result; return OutputFile; } @@ -435,7 +376,7 @@ Error runSYCLLink(ArrayRef Files, const ArgList &Args) { reportError(DeviceLinkedFile.takeError()); // LLVM to SPIR-V translation step - auto SPVFile = runLLVMToSPIRVTranslation(*DeviceLinkedFile, Args); + auto SPVFile = runLLVMSPIRVBackend(*DeviceLinkedFile, Args); if (!SPVFile) return SPVFile.takeError(); return Error::success(); From e97d1d5989575891646e7990a0cb2fdf86e15184 Mon Sep 17 00:00:00 2001 From: Arvind Sudarsanam Date: Tue, 11 Mar 2025 16:38:39 -0700 Subject: [PATCH 02/12] Minor typo Signed-off-by: Arvind Sudarsanam --- clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index e94c68bcb995b..99e077db3b46b 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -306,7 +306,7 @@ static Expected linkDeviceLibFiles(StringRef InputFile, } /// Run LLVM to SPIR-V translation. -/// Converts 'File' from LLVM bitcode to SPIR-V format using SPIR-V backend, +/// Converts 'File' from LLVM bitcode to SPIR-V format using SPIR-V backend. /// 'Args' encompasses all arguments required for linking device code and will /// be parsed to generate options required to be passed into the backend. static Expected runLLVMSPIRVBackend(StringRef File, From b81a6dd9575627bd68d174c795c15b91af70faa1 Mon Sep 17 00:00:00 2001 From: Arvind Sudarsanam Date: Wed, 12 Mar 2025 08:05:44 -0700 Subject: [PATCH 03/12] Address review comments Signed-off-by: Arvind Sudarsanam --- .../tools/clang-sycl-linker/ClangSYCLLinker.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index 99e077db3b46b..b1d5e3fdfc20e 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -207,7 +207,7 @@ Expected> getInput(const ArgList &Args) { /// be parsed to generate options required to be passed into llvm-link. Expected linkDeviceInputFiles(ArrayRef InputFiles, const ArgList &Args) { - llvm::TimeTraceScope TimeScope("SYCL LinkDeviceInputFiles"); + llvm::TimeTraceScope TimeScope("Link device input files"); assert(InputFiles.size() && "No inputs to llvm-link"); // Early check to see if there is only one input. @@ -272,7 +272,7 @@ Expected> getSYCLDeviceLibs(const ArgList &Args) { /// be parsed to generate options required to be passed into llvm-link tool. static Expected linkDeviceLibFiles(StringRef InputFile, const ArgList &Args) { - llvm::TimeTraceScope TimeScope("LinkDeviceLibraryFiles"); + llvm::TimeTraceScope TimeScope("Link device library files"); auto SYCLDeviceLibFiles = getSYCLDeviceLibs(Args); if (!SYCLDeviceLibFiles) @@ -309,10 +309,9 @@ static Expected linkDeviceLibFiles(StringRef InputFile, /// Converts 'File' from LLVM bitcode to SPIR-V format using SPIR-V backend. /// 'Args' encompasses all arguments required for linking device code and will /// be parsed to generate options required to be passed into the backend. -static Expected runLLVMSPIRVBackend(StringRef File, - const ArgList &Args) { - llvm::TimeTraceScope TimeScope("LLVMToSPIRVTranslationViaSPIRVBackend"); - std::vector ExtNames, Opts; +static Expected runSPIRVCodeGen(StringRef File, + const ArgList &Args) { + llvm::TimeTraceScope TimeScope("SPIR-V code generation"); if (Verbose || DryRun) { errs() << formatv("LLVM-SPIRV-Backend: input: {0}, output: {1}\n", File, OutputFile); @@ -364,7 +363,7 @@ static Expected runLLVMSPIRVBackend(StringRef File, } Error runSYCLLink(ArrayRef Files, const ArgList &Args) { - llvm::TimeTraceScope TimeScope("SYCLDeviceLink"); + llvm::TimeTraceScope TimeScope("SYCL device linking"); // First llvm-link step auto LinkedFile = linkDeviceInputFiles(Files, Args); if (!LinkedFile) @@ -375,8 +374,8 @@ Error runSYCLLink(ArrayRef Files, const ArgList &Args) { if (!DeviceLinkedFile) reportError(DeviceLinkedFile.takeError()); - // LLVM to SPIR-V translation step - auto SPVFile = runLLVMSPIRVBackend(*DeviceLinkedFile, Args); + // SPIR-V code generation step + auto SPVFile = runSPIRVCodeGen(*DeviceLinkedFile, Args); if (!SPVFile) return SPVFile.takeError(); return Error::success(); From f446dcfbc4c747332dc7f04cacb37e8701692dca Mon Sep 17 00:00:00 2001 From: Arvind Sudarsanam Date: Wed, 12 Mar 2025 12:31:10 -0700 Subject: [PATCH 04/12] Use TargetMachine API for SPIR-V translation Signed-off-by: Arvind Sudarsanam --- clang/tools/clang-sycl-linker/CMakeLists.txt | 2 + .../clang-sycl-linker/ClangSYCLLinker.cpp | 47 +++++++++++++++---- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/clang/tools/clang-sycl-linker/CMakeLists.txt b/clang/tools/clang-sycl-linker/CMakeLists.txt index 5665ad7d7186e..c19ce2eac834e 100644 --- a/clang/tools/clang-sycl-linker/CMakeLists.txt +++ b/clang/tools/clang-sycl-linker/CMakeLists.txt @@ -1,8 +1,10 @@ set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} BinaryFormat + MC Option Object + Target TargetParser Support ) diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index b1d5e3fdfc20e..2b69772ab5723 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -16,7 +16,6 @@ #include "clang/Basic/Version.h" -#include "../../llvm/lib/Target/SPIRV/SPIRVAPI.h" #include "llvm/ADT/StringExtras.h" #include "llvm/BinaryFormat/Magic.h" #include "llvm/Bitcode/BitcodeWriter.h" @@ -24,6 +23,7 @@ #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IRReader/IRReader.h" #include "llvm/LTO/LTO.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ArchiveWriter.h" #include "llvm/Object/Binary.h" @@ -47,6 +47,7 @@ #include "llvm/Support/TargetSelect.h" #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/WithColor.h" +#include "llvm/Target/TargetMachine.h" using namespace llvm; using namespace llvm::opt; @@ -78,6 +79,17 @@ static const char *Executable; static SmallVector> TempFiles; namespace { + +std::once_flag InitOnceFlag; +void InitializeSPIRVTarget() { + std::call_once(InitOnceFlag, []() { + LLVMInitializeSPIRVTargetInfo(); + LLVMInitializeSPIRVTarget(); + LLVMInitializeSPIRVTargetMC(); + LLVMInitializeSPIRVAsmPrinter(); + }); +} + // Must not overlap with llvm::opt::DriverFlag. enum LinkerFlags { LinkerOnlyOption = (1 << 4) }; @@ -319,6 +331,9 @@ static Expected runSPIRVCodeGen(StringRef File, return OutputFile; } + // SPIR-V-specific target initialization. + InitializeSPIRVTarget(); + SMDiagnostic Err; LLVMContext C; std::unique_ptr M = parseIRFile(File, Err, C); @@ -345,20 +360,32 @@ static Expected runSPIRVCodeGen(StringRef File, TargetTriple.setArch(TargetTriple.getArch(), Triple::SPIRVSubArch_v16); M->setTargetTriple(TargetTriple); + std::string Msg; + const Target *T = TargetRegistry::lookupTarget(M->getTargetTriple(), Msg); + if (!T) + return createStringError(Msg + ": " + M->getTargetTriple().str()); + + TargetOptions Options; + std::optional RM; + std::optional CM; + std::unique_ptr TM( + T->createTargetMachine(M->getTargetTriple().str(), "", "", Options, RM, + CM)); + if (!TM) + return createStringError("Could not allocate target machine!"); + int FD = -1; if (std::error_code EC = sys::fs::openFileForWrite(OutputFile, FD)) return errorCodeToError(EC); auto OS = std::make_unique(FD, true); - std::string Result, ErrMsg; - // List of allowed extensions. Currently, all extensions are allowed. - // TODO: Update list of allowed extensions for SYCL compilation flow. - static const std::vector AllowExtNames{"all"}; - // Translate the Module into SPIR-V - if (!SPIRVTranslateModule(M.release(), Result, ErrMsg, AllowExtNames, {})) - return createStringError( - "SPIRVTranslation: SPIRV translation failed with " + ErrMsg); - *OS << Result; + legacy::PassManager CodeGenPasses; + TargetLibraryInfoImpl TLII(M->getTargetTriple()); + CodeGenPasses.add(new TargetLibraryInfoWrapperPass(TLII)); + if (TM->addPassesToEmitFile(CodeGenPasses, *OS, nullptr, + CodeGenFileType::ObjectFile)) + return createStringError("Failed to execute SPIR-V backend"); + CodeGenPasses.run(*M); return OutputFile; } From a3eb786ce57f80b93cd84586e43ead7de2f2bbcb Mon Sep 17 00:00:00 2001 From: Arvind Sudarsanam Date: Wed, 12 Mar 2025 12:35:55 -0700 Subject: [PATCH 05/12] Fix format Signed-off-by: Arvind Sudarsanam --- clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index 2b69772ab5723..4c88bcbf61824 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -368,9 +368,8 @@ static Expected runSPIRVCodeGen(StringRef File, TargetOptions Options; std::optional RM; std::optional CM; - std::unique_ptr TM( - T->createTargetMachine(M->getTargetTriple().str(), "", "", Options, RM, - CM)); + std::unique_ptr TM(T->createTargetMachine( + M->getTargetTriple().str(), "", "", Options, RM, CM)); if (!TM) return createStringError("Could not allocate target machine!"); From 9e19659c547a4fdc224e182be6f9d86f04ccc14b Mon Sep 17 00:00:00 2001 From: Arvind Sudarsanam Date: Wed, 12 Mar 2025 15:14:16 -0700 Subject: [PATCH 06/12] Removed unneeded update from spir to spirv triple. Remove -triple and -arch options to clang-sycl-linker Signed-off-by: Arvind Sudarsanam --- clang/test/Driver/clang-sycl-linker-test.cpp | 12 ++++++------ .../tools/clang-sycl-linker/ClangSYCLLinker.cpp | 17 ++++------------- clang/tools/clang-sycl-linker/SYCLLinkOpts.td | 5 ----- 3 files changed, 10 insertions(+), 24 deletions(-) diff --git a/clang/test/Driver/clang-sycl-linker-test.cpp b/clang/test/Driver/clang-sycl-linker-test.cpp index a96991020f854..b9c187f343464 100644 --- a/clang/test/Driver/clang-sycl-linker-test.cpp +++ b/clang/test/Driver/clang-sycl-linker-test.cpp @@ -3,20 +3,20 @@ // Test a simple case without arguments. // RUN: %clangxx -emit-llvm -c %s -o %t_1.bc // RUN: %clangxx -emit-llvm -c %s -o %t_2.bc -// RUN: clang-sycl-linker --dry-run -triple spirv64 %t_1.bc %t_2.bc -o a.spv 2>&1 \ +// RUN: clang-sycl-linker --dry-run %t_1.bc %t_2.bc -o a.spv 2>&1 \ // RUN: | FileCheck %s --check-prefix=SIMPLE // SIMPLE: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[FIRSTLLVMLINKOUT:.*]].bc --suppress-warnings // SIMPLE-NEXT: LLVM-SPIRV-Backend: input: {{.*}}.bc, output: a.spv // // Test that llvm-link is not called when only one input is present. -// RUN: clang-sycl-linker --dry-run -triple spirv64 %t_1.bc -o a.spv 2>&1 \ +// RUN: clang-sycl-linker --dry-run %t_1.bc -o a.spv 2>&1 \ // RUN: | FileCheck %s --check-prefix=SIMPLE-NO-LINK // SIMPLE-NO-LINK: LLVM-SPIRV-Backend: input: {{.*}}.bc, output: a.spv // // Test a simple case with device library files specified. // RUN: touch %T/lib1.bc // RUN: touch %T/lib2.bc -// RUN: clang-sycl-linker --dry-run -triple spirv64 %t_1.bc %t_2.bc --library-path=%T --device-libs=lib1.bc,lib2.bc -o a.spv 2>&1 \ +// RUN: clang-sycl-linker --dry-run %t_1.bc %t_2.bc --library-path=%T --device-libs=lib1.bc,lib2.bc -o a.spv 2>&1 \ // RUN: | FileCheck %s --check-prefix=DEVLIBS // DEVLIBS: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[FIRSTLLVMLINKOUT:.*]].bc --suppress-warnings // DEVLIBS-NEXT: "{{.*}}llvm-link{{.*}}" -only-needed [[FIRSTLLVMLINKOUT]].bc {{.*}}lib1.bc {{.*}}lib2.bc -o [[SECONDLLVMLINKOUT:.*]].bc --suppress-warnings @@ -25,14 +25,14 @@ // Test a simple case with .o (fat object) as input. // TODO: Remove this test once fat object support is added. // RUN: %clangxx -c %s -o %t.o -// RUN: not clang-sycl-linker --dry-run -triple spirv64 %t.o -o a.spv 2>&1 \ +// RUN: not clang-sycl-linker --dry-run %t.o -o a.spv 2>&1 \ // RUN: | FileCheck %s --check-prefix=FILETYPEERROR // FILETYPEERROR: Unsupported file type // // Test to see if device library related errors are emitted. -// RUN: not clang-sycl-linker --dry-run -triple spirv64 %t_1.bc %t_2.bc --library-path=%T --device-libs= -o a.spv 2>&1 \ +// RUN: not clang-sycl-linker --dry-run %t_1.bc %t_2.bc --library-path=%T --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 -triple spirv64 %t_1.bc %t_2.bc --library-path=%T --device-libs=lib1.bc,lib2.bc,lib3.bc -o a.spv 2>&1 \ +// RUN: not clang-sycl-linker --dry-run %t_1.bc %t_2.bc --library-path=%T --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 diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index 4c88bcbf61824..0a6bb26d3dae8 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -341,24 +341,12 @@ static Expected runSPIRVCodeGen(StringRef File, return createStringError(inconvertibleErrorCode(), Err.getMessage()); static const std::string DefaultTriple = "spirv64v1.6-unknown-unknown"; - - // Correct the Triple value if needed - // TODO: Remove this correction once we start using spirv64/spirv32 triples - // everywhere. Triple TargetTriple(M->getTargetTriple()); - if (TargetTriple.isSPIR()) { - TargetTriple.setArch(TargetTriple.getArch() == Triple::spir64 - ? Triple::spirv64 - : Triple::spirv32, - TargetTriple.getSubArch()); - M->setTargetTriple(TargetTriple); - // We need to reset Data Layout to conform with the TargetMachine - M->setDataLayout(""); - } if (TargetTriple.getTriple().empty()) TargetTriple.setTriple(DefaultTriple); TargetTriple.setArch(TargetTriple.getArch(), Triple::SPIRVSubArch_v16); M->setTargetTriple(TargetTriple); + assert(TargetTriple.isSPIROrSPIRV() && "Target triple is not SPIR or SPIR-V"); std::string Msg; const Target *T = TargetRegistry::lookupTarget(M->getTargetTriple(), Msg); @@ -373,6 +361,9 @@ static Expected runSPIRVCodeGen(StringRef File, if (!TM) return createStringError("Could not allocate target machine!"); + if (M->getDataLayout().isDefault()) + M->setDataLayout(TM->createDataLayout()); + int FD = -1; if (std::error_code EC = sys::fs::openFileForWrite(OutputFile, FD)) return errorCodeToError(EC); diff --git a/clang/tools/clang-sycl-linker/SYCLLinkOpts.td b/clang/tools/clang-sycl-linker/SYCLLinkOpts.td index 959fd6c3e867c..e3b3eb098efc4 100644 --- a/clang/tools/clang-sycl-linker/SYCLLinkOpts.td +++ b/clang/tools/clang-sycl-linker/SYCLLinkOpts.td @@ -24,11 +24,6 @@ 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 triple : Joined<["--"], "triple">, - HelpText<"The device target triple">; -def arch : Separate<["--", "-"], "arch">, - HelpText<"Specify the name of the target architecture.">; - def save_temps : Flag<["--", "-"], "save-temps">, Flags<[LinkerOnlyOption]>, HelpText<"Save intermediate results">; From be91b6bf3070c747c8a3988da89cb0071a08aba4 Mon Sep 17 00:00:00 2001 From: Arvind Sudarsanam Date: Thu, 13 Mar 2025 13:51:37 -0700 Subject: [PATCH 07/12] Address review comments Signed-off-by: Arvind Sudarsanam --- clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index 0a6bb26d3dae8..9f3e50820f4a6 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -325,7 +325,7 @@ static Expected runSPIRVCodeGen(StringRef File, const ArgList &Args) { llvm::TimeTraceScope TimeScope("SPIR-V code generation"); if (Verbose || DryRun) { - errs() << formatv("LLVM-SPIRV-Backend: input: {0}, output: {1}\n", File, + errs() << formatv("SPIR-V Backend: input: {0}, output: {1}\n", File, OutputFile); if (DryRun) return OutputFile; @@ -340,7 +340,7 @@ static Expected runSPIRVCodeGen(StringRef File, if (!M) return createStringError(inconvertibleErrorCode(), Err.getMessage()); - static const std::string DefaultTriple = "spirv64v1.6-unknown-unknown"; + static const std::string DefaultTriple = "spirv64-unknown-unknown"; Triple TargetTriple(M->getTargetTriple()); if (TargetTriple.getTriple().empty()) TargetTriple.setTriple(DefaultTriple); @@ -356,8 +356,9 @@ static Expected runSPIRVCodeGen(StringRef File, TargetOptions Options; std::optional RM; std::optional CM; - std::unique_ptr TM(T->createTargetMachine( - M->getTargetTriple().str(), "", "", Options, RM, CM)); + std::unique_ptr TM( + T->createTargetMachine(M->getTargetTriple().str(), /* CPU */ "", + /* Features */ "", Options, RM, CM)); if (!TM) return createStringError("Could not allocate target machine!"); @@ -374,7 +375,7 @@ static Expected runSPIRVCodeGen(StringRef File, CodeGenPasses.add(new TargetLibraryInfoWrapperPass(TLII)); if (TM->addPassesToEmitFile(CodeGenPasses, *OS, nullptr, CodeGenFileType::ObjectFile)) - return createStringError("Failed to execute SPIR-V backend"); + return createStringError("Failed to execute SPIR-V Backend"); CodeGenPasses.run(*M); return OutputFile; } From aca480fde9873c3270fe14ebad3172faccb7e963 Mon Sep 17 00:00:00 2001 From: Arvind Sudarsanam Date: Thu, 13 Mar 2025 14:15:10 -0700 Subject: [PATCH 08/12] Address review comments Signed-off-by: Arvind Sudarsanam --- clang/test/Driver/clang-sycl-linker-test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/test/Driver/clang-sycl-linker-test.cpp b/clang/test/Driver/clang-sycl-linker-test.cpp index b9c187f343464..ae55d16759c9e 100644 --- a/clang/test/Driver/clang-sycl-linker-test.cpp +++ b/clang/test/Driver/clang-sycl-linker-test.cpp @@ -6,12 +6,12 @@ // RUN: clang-sycl-linker --dry-run %t_1.bc %t_2.bc -o a.spv 2>&1 \ // RUN: | FileCheck %s --check-prefix=SIMPLE // SIMPLE: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[FIRSTLLVMLINKOUT:.*]].bc --suppress-warnings -// SIMPLE-NEXT: LLVM-SPIRV-Backend: input: {{.*}}.bc, output: a.spv +// SIMPLE-NEXT: SPIR-V Backend: input: {{.*}}.bc, output: a.spv // // Test that llvm-link is not called when only one input is present. // RUN: clang-sycl-linker --dry-run %t_1.bc -o a.spv 2>&1 \ // RUN: | FileCheck %s --check-prefix=SIMPLE-NO-LINK -// SIMPLE-NO-LINK: LLVM-SPIRV-Backend: input: {{.*}}.bc, output: a.spv +// SIMPLE-NO-LINK: SPIR-V Backend: input: {{.*}}.bc, output: a.spv // // Test a simple case with device library files specified. // RUN: touch %T/lib1.bc @@ -20,7 +20,7 @@ // RUN: | FileCheck %s --check-prefix=DEVLIBS // DEVLIBS: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[FIRSTLLVMLINKOUT:.*]].bc --suppress-warnings // DEVLIBS-NEXT: "{{.*}}llvm-link{{.*}}" -only-needed [[FIRSTLLVMLINKOUT]].bc {{.*}}lib1.bc {{.*}}lib2.bc -o [[SECONDLLVMLINKOUT:.*]].bc --suppress-warnings -// DEVLIBS-NEXT: LLVM-SPIRV-Backend: input: [[SECONDLLVMLINKOUT]].bc, output: a.spv +// DEVLIBS-NEXT: SPIR-V Backend: input: [[SECONDLLVMLINKOUT]].bc, output: a.spv // // Test a simple case with .o (fat object) as input. // TODO: Remove this test once fat object support is added. From 0cc442369d15c0d37193a9d608ca1250a077e9b4 Mon Sep 17 00:00:00 2001 From: Arvind Sudarsanam Date: Sat, 29 Mar 2025 07:45:45 -0700 Subject: [PATCH 09/12] Readd triple and arch options Signed-off-by: Arvind Sudarsanam --- clang/tools/clang-sycl-linker/SYCLLinkOpts.td | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clang/tools/clang-sycl-linker/SYCLLinkOpts.td b/clang/tools/clang-sycl-linker/SYCLLinkOpts.td index e3b3eb098efc4..1015fec1013b7 100644 --- a/clang/tools/clang-sycl-linker/SYCLLinkOpts.td +++ b/clang/tools/clang-sycl-linker/SYCLLinkOpts.td @@ -24,6 +24,11 @@ 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 triple : Separate<["--", "-"], "triple">, + HelpText<"The device target triple">; +def arch : Separate<["--", "-"], "arch">, + HelpText<"Specify the name of the target architecture.">; + def save_temps : Flag<["--", "-"], "save-temps">, Flags<[LinkerOnlyOption]>, HelpText<"Save intermediate results">; From 72e9f9570f96c078ae2fd4026d6a444d7b332c2e Mon Sep 17 00:00:00 2001 From: Arvind Sudarsanam Date: Sat, 29 Mar 2025 18:33:11 -0700 Subject: [PATCH 10/12] Add -spirv-version option to clang-sycl-linker Signed-off-by: Arvind Sudarsanam --- clang/test/Driver/clang-sycl-linker-test.cpp | 8 ++-- .../clang-sycl-linker/ClangSYCLLinker.cpp | 40 ++++++++++++------- clang/tools/clang-sycl-linker/SYCLLinkOpts.td | 4 ++ 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/clang/test/Driver/clang-sycl-linker-test.cpp b/clang/test/Driver/clang-sycl-linker-test.cpp index ae55d16759c9e..be3fa290e44ea 100644 --- a/clang/test/Driver/clang-sycl-linker-test.cpp +++ b/clang/test/Driver/clang-sycl-linker-test.cpp @@ -3,20 +3,20 @@ // Test a simple case without arguments. // RUN: %clangxx -emit-llvm -c %s -o %t_1.bc // RUN: %clangxx -emit-llvm -c %s -o %t_2.bc -// RUN: clang-sycl-linker --dry-run %t_1.bc %t_2.bc -o a.spv 2>&1 \ +// RUN: clang-sycl-linker --dry-run -v %t_1.bc %t_2.bc -o a.spv 2>&1 \ // RUN: | FileCheck %s --check-prefix=SIMPLE // SIMPLE: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[FIRSTLLVMLINKOUT:.*]].bc --suppress-warnings // SIMPLE-NEXT: SPIR-V Backend: input: {{.*}}.bc, output: a.spv // // Test that llvm-link is not called when only one input is present. -// RUN: clang-sycl-linker --dry-run %t_1.bc -o a.spv 2>&1 \ +// RUN: clang-sycl-linker --dry-run -v %t_1.bc -o a.spv 2>&1 \ // RUN: | FileCheck %s --check-prefix=SIMPLE-NO-LINK // SIMPLE-NO-LINK: SPIR-V Backend: input: {{.*}}.bc, output: a.spv // // Test a simple case with device library files specified. // RUN: touch %T/lib1.bc // RUN: touch %T/lib2.bc -// RUN: clang-sycl-linker --dry-run %t_1.bc %t_2.bc --library-path=%T --device-libs=lib1.bc,lib2.bc -o a.spv 2>&1 \ +// RUN: clang-sycl-linker --dry-run -v %t_1.bc %t_2.bc --library-path=%T --device-libs=lib1.bc,lib2.bc -o a.spv 2>&1 \ // RUN: | FileCheck %s --check-prefix=DEVLIBS // DEVLIBS: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[FIRSTLLVMLINKOUT:.*]].bc --suppress-warnings // DEVLIBS-NEXT: "{{.*}}llvm-link{{.*}}" -only-needed [[FIRSTLLVMLINKOUT]].bc {{.*}}lib1.bc {{.*}}lib2.bc -o [[SECONDLLVMLINKOUT:.*]].bc --suppress-warnings @@ -25,7 +25,7 @@ // Test a simple case with .o (fat object) as input. // TODO: Remove this test once fat object support is added. // RUN: %clangxx -c %s -o %t.o -// RUN: not clang-sycl-linker --dry-run %t.o -o a.spv 2>&1 \ +// RUN: not clang-sycl-linker --dry-run -v %t.o -o a.spv 2>&1 \ // RUN: | FileCheck %s --check-prefix=FILETYPEERROR // FILETYPEERROR: Unsupported file type // diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index 9f3e50820f4a6..f19ed9726a2ac 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -324,35 +324,38 @@ static Expected linkDeviceLibFiles(StringRef InputFile, static Expected runSPIRVCodeGen(StringRef File, const ArgList &Args) { llvm::TimeTraceScope TimeScope("SPIR-V code generation"); - if (Verbose || DryRun) { - errs() << formatv("SPIR-V Backend: input: {0}, output: {1}\n", File, - OutputFile); - if (DryRun) - return OutputFile; - } // SPIR-V-specific target initialization. InitializeSPIRVTarget(); + // Parse input module. SMDiagnostic Err; LLVMContext C; std::unique_ptr M = parseIRFile(File, Err, C); if (!M) return createStringError(inconvertibleErrorCode(), Err.getMessage()); - static const std::string DefaultTriple = "spirv64-unknown-unknown"; - Triple TargetTriple(M->getTargetTriple()); - if (TargetTriple.getTriple().empty()) - TargetTriple.setTriple(DefaultTriple); - TargetTriple.setArch(TargetTriple.getArch(), Triple::SPIRVSubArch_v16); - M->setTargetTriple(TargetTriple); - assert(TargetTriple.isSPIROrSPIRV() && "Target triple is not SPIR or SPIR-V"); - + // Update target triple for SPIR-V backend by incorporating SPIR-V version. + StringRef Version = Args.getLastArgValue(OPT_spirv_version_EQ); + static const std::string TargetTripleStr = + StringSwitch(Version) + .Case("1.0", "spirv64v1.0-unknown-unknown") + .Case("1.1", "spirv64v1.1-unknown-unknown") + .Case("1.2", "spirv64v1.2-unknown-unknown") + .Case("1.3", "spirv64v1.3-unknown-unknown") + .Case("1.4", "spirv64v1.4-unknown-unknown") + .Case("1.5", "spirv64v1.5-unknown-unknown") + .Case("1.6", "spirv64v1.6-unknown-unknown") + .Default("spirv64-unknown-unknown"); + M->setTargetTriple(llvm::Triple(TargetTripleStr)); + + // Get a handle to SPIR-V target backend. std::string Msg; const Target *T = TargetRegistry::lookupTarget(M->getTargetTriple(), Msg); if (!T) return createStringError(Msg + ": " + M->getTargetTriple().str()); + // Allocate SPIR-V target machine TargetOptions Options; std::optional RM; std::optional CM; @@ -362,14 +365,17 @@ static Expected runSPIRVCodeGen(StringRef File, if (!TM) return createStringError("Could not allocate target machine!"); + // Set data layout if needed. if (M->getDataLayout().isDefault()) M->setDataLayout(TM->createDataLayout()); + // Open output file for writing. int FD = -1; if (std::error_code EC = sys::fs::openFileForWrite(OutputFile, FD)) return errorCodeToError(EC); auto OS = std::make_unique(FD, true); + // Run SPIR-V codegen passes to generate SPIR-V file legacy::PassManager CodeGenPasses; TargetLibraryInfoImpl TLII(M->getTargetTriple()); CodeGenPasses.add(new TargetLibraryInfoWrapperPass(TLII)); @@ -377,6 +383,12 @@ static Expected runSPIRVCodeGen(StringRef File, CodeGenFileType::ObjectFile)) return createStringError("Failed to execute SPIR-V Backend"); CodeGenPasses.run(*M); + + if (Verbose) { + errs() << formatv("SPIR-V Backend: input: {0}, output: {1}\n", File, + OutputFile); + } + return OutputFile; } diff --git a/clang/tools/clang-sycl-linker/SYCLLinkOpts.td b/clang/tools/clang-sycl-linker/SYCLLinkOpts.td index 1015fec1013b7..bd71d6367b09f 100644 --- a/clang/tools/clang-sycl-linker/SYCLLinkOpts.td +++ b/clang/tools/clang-sycl-linker/SYCLLinkOpts.td @@ -46,6 +46,10 @@ def llvm_spirv_path_EQ : Joined<["--"], "llvm-spirv-path=">, Flags<[LinkerOnlyOption]>, MetaVarName<"">, HelpText<"Set the system llvm-spirv path">; +def spirv_version_EQ : Joined<["--"], "spirv-version=">, + Flags<[LinkerOnlyOption]>, + HelpText<"Set SPIR-V version">; + // Options to pass to llvm-spirv tool def llvm_spirv_options_EQ : Joined<["--", "-"], "llvm-spirv-options=">, Flags<[LinkerOnlyOption]>, From 1d0dfe37cd6bdb77f4f799cc2609620139fa31a7 Mon Sep 17 00:00:00 2001 From: Arvind Sudarsanam Date: Mon, 31 Mar 2025 10:19:21 -0700 Subject: [PATCH 11/12] Remove --spirv-version option. SPIR-V version will be part of device triple Signed-off-by: Arvind Sudarsanam --- .../clang-sycl-linker/ClangSYCLLinker.cpp | 18 ++---------------- clang/tools/clang-sycl-linker/SYCLLinkOpts.td | 4 ---- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index f19ed9726a2ac..3b552218faa42 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -335,27 +335,13 @@ static Expected runSPIRVCodeGen(StringRef File, if (!M) return createStringError(inconvertibleErrorCode(), Err.getMessage()); - // Update target triple for SPIR-V backend by incorporating SPIR-V version. - StringRef Version = Args.getLastArgValue(OPT_spirv_version_EQ); - static const std::string TargetTripleStr = - StringSwitch(Version) - .Case("1.0", "spirv64v1.0-unknown-unknown") - .Case("1.1", "spirv64v1.1-unknown-unknown") - .Case("1.2", "spirv64v1.2-unknown-unknown") - .Case("1.3", "spirv64v1.3-unknown-unknown") - .Case("1.4", "spirv64v1.4-unknown-unknown") - .Case("1.5", "spirv64v1.5-unknown-unknown") - .Case("1.6", "spirv64v1.6-unknown-unknown") - .Default("spirv64-unknown-unknown"); - M->setTargetTriple(llvm::Triple(TargetTripleStr)); - // Get a handle to SPIR-V target backend. std::string Msg; const Target *T = TargetRegistry::lookupTarget(M->getTargetTriple(), Msg); if (!T) return createStringError(Msg + ": " + M->getTargetTriple().str()); - // Allocate SPIR-V target machine + // Allocate SPIR-V target machine. TargetOptions Options; std::optional RM; std::optional CM; @@ -375,7 +361,7 @@ static Expected runSPIRVCodeGen(StringRef File, return errorCodeToError(EC); auto OS = std::make_unique(FD, true); - // Run SPIR-V codegen passes to generate SPIR-V file + // Run SPIR-V codegen passes to generate SPIR-V file. legacy::PassManager CodeGenPasses; TargetLibraryInfoImpl TLII(M->getTargetTriple()); CodeGenPasses.add(new TargetLibraryInfoWrapperPass(TLII)); diff --git a/clang/tools/clang-sycl-linker/SYCLLinkOpts.td b/clang/tools/clang-sycl-linker/SYCLLinkOpts.td index bd71d6367b09f..1015fec1013b7 100644 --- a/clang/tools/clang-sycl-linker/SYCLLinkOpts.td +++ b/clang/tools/clang-sycl-linker/SYCLLinkOpts.td @@ -46,10 +46,6 @@ def llvm_spirv_path_EQ : Joined<["--"], "llvm-spirv-path=">, Flags<[LinkerOnlyOption]>, MetaVarName<"">, HelpText<"Set the system llvm-spirv path">; -def spirv_version_EQ : Joined<["--"], "spirv-version=">, - Flags<[LinkerOnlyOption]>, - HelpText<"Set SPIR-V version">; - // Options to pass to llvm-spirv tool def llvm_spirv_options_EQ : Joined<["--", "-"], "llvm-spirv-options=">, Flags<[LinkerOnlyOption]>, From 3e9c850399965d6132de37bb0aa1ba09bd828832 Mon Sep 17 00:00:00 2001 From: Arvind Sudarsanam Date: Mon, 31 Mar 2025 11:41:12 -0700 Subject: [PATCH 12/12] Minor modifications Signed-off-by: Arvind Sudarsanam --- clang/test/Driver/clang-sycl-linker-test.cpp | 18 +++++++++--------- clang/test/Driver/sycl-link-spirv-target.cpp | 4 ++-- .../clang-sycl-linker/ClangSYCLLinker.cpp | 5 ++++- clang/tools/clang-sycl-linker/SYCLLinkOpts.td | 12 ++++++++---- 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/clang/test/Driver/clang-sycl-linker-test.cpp b/clang/test/Driver/clang-sycl-linker-test.cpp index be3fa290e44ea..d9f753a559e0c 100644 --- a/clang/test/Driver/clang-sycl-linker-test.cpp +++ b/clang/test/Driver/clang-sycl-linker-test.cpp @@ -1,22 +1,22 @@ // Tests the clang-sycl-linker tool. // // Test a simple case without arguments. -// RUN: %clangxx -emit-llvm -c %s -o %t_1.bc -// RUN: %clangxx -emit-llvm -c %s -o %t_2.bc -// RUN: clang-sycl-linker --dry-run -v %t_1.bc %t_2.bc -o a.spv 2>&1 \ +// RUN: %clangxx -emit-llvm -c -target spirv64 %s -o %t_1.bc +// RUN: %clangxx -emit-llvm -c -target spirv64 %s -o %t_2.bc +// RUN: clang-sycl-linker --dry-run -v -triple=spirv64 %t_1.bc %t_2.bc -o a.spv 2>&1 \ // RUN: | FileCheck %s --check-prefix=SIMPLE // SIMPLE: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[FIRSTLLVMLINKOUT:.*]].bc --suppress-warnings // SIMPLE-NEXT: SPIR-V Backend: input: {{.*}}.bc, output: a.spv // // Test that llvm-link is not called when only one input is present. -// RUN: clang-sycl-linker --dry-run -v %t_1.bc -o a.spv 2>&1 \ +// RUN: clang-sycl-linker --dry-run -v -triple=spirv64 %t_1.bc -o a.spv 2>&1 \ // RUN: | FileCheck %s --check-prefix=SIMPLE-NO-LINK // SIMPLE-NO-LINK: SPIR-V Backend: input: {{.*}}.bc, output: a.spv // // Test a simple case with device library files specified. // RUN: touch %T/lib1.bc // RUN: touch %T/lib2.bc -// RUN: clang-sycl-linker --dry-run -v %t_1.bc %t_2.bc --library-path=%T --device-libs=lib1.bc,lib2.bc -o a.spv 2>&1 \ +// RUN: clang-sycl-linker --dry-run -v -triple=spirv64 %t_1.bc %t_2.bc --library-path=%T --device-libs=lib1.bc,lib2.bc -o a.spv 2>&1 \ // RUN: | FileCheck %s --check-prefix=DEVLIBS // DEVLIBS: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[FIRSTLLVMLINKOUT:.*]].bc --suppress-warnings // DEVLIBS-NEXT: "{{.*}}llvm-link{{.*}}" -only-needed [[FIRSTLLVMLINKOUT]].bc {{.*}}lib1.bc {{.*}}lib2.bc -o [[SECONDLLVMLINKOUT:.*]].bc --suppress-warnings @@ -24,15 +24,15 @@ // // Test a simple case with .o (fat object) as input. // TODO: Remove this test once fat object support is added. -// RUN: %clangxx -c %s -o %t.o -// RUN: not clang-sycl-linker --dry-run -v %t.o -o a.spv 2>&1 \ +// RUN: %clangxx -c -target spirv64 %s -o %t.o +// RUN: not clang-sycl-linker --dry-run -v -triple=spirv64 %t.o -o a.spv 2>&1 \ // RUN: | FileCheck %s --check-prefix=FILETYPEERROR // FILETYPEERROR: Unsupported file type // // Test to see if device library related errors are emitted. -// RUN: not clang-sycl-linker --dry-run %t_1.bc %t_2.bc --library-path=%T --device-libs= -o a.spv 2>&1 \ +// RUN: not clang-sycl-linker --dry-run -triple=spirv64 %t_1.bc %t_2.bc --library-path=%T --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_1.bc %t_2.bc --library-path=%T --device-libs=lib1.bc,lib2.bc,lib3.bc -o a.spv 2>&1 \ +// RUN: not clang-sycl-linker --dry-run -triple=spirv64 %t_1.bc %t_2.bc --library-path=%T --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 diff --git a/clang/test/Driver/sycl-link-spirv-target.cpp b/clang/test/Driver/sycl-link-spirv-target.cpp index 140a6438c7300..586adae619165 100644 --- a/clang/test/Driver/sycl-link-spirv-target.cpp +++ b/clang/test/Driver/sycl-link-spirv-target.cpp @@ -3,7 +3,7 @@ // // Test that -Xlinker options are being passed to clang-sycl-linker. // RUN: touch %t.bc -// RUN: %clangxx -### --target=spirv64 --sycl-link -Xlinker --library-path=/tmp \ +// RUN: %clangxx -### --target=spirv64 --sycl-link -Xlinker -triple=spirv64 -Xlinker --library-path=/tmp \ // RUN: -Xlinker --device-libs=lib1.bc,lib2.bc %t.bc 2>&1 \ // RUN: | FileCheck %s -check-prefix=XLINKEROPTS -// XLINKEROPTS: "{{.*}}clang-sycl-linker{{.*}}" "--library-path=/tmp" "--device-libs=lib1.bc,lib2.bc" "{{.*}}.bc" "-o" "a.out" +// XLINKEROPTS: "{{.*}}clang-sycl-linker{{.*}}" "-triple=spirv64" "--library-path=/tmp" "--device-libs=lib1.bc,lib2.bc" "{{.*}}.bc" "-o" "a.out" diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index 3b552218faa42..fdc3c5e01d656 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -335,6 +335,9 @@ static Expected runSPIRVCodeGen(StringRef File, if (!M) return createStringError(inconvertibleErrorCode(), Err.getMessage()); + Triple TargetTriple(Args.getLastArgValue(OPT_triple_EQ)); + M->setTargetTriple(TargetTriple); + // Get a handle to SPIR-V target backend. std::string Msg; const Target *T = TargetRegistry::lookupTarget(M->getTargetTriple(), Msg); @@ -346,7 +349,7 @@ static Expected runSPIRVCodeGen(StringRef File, std::optional RM; std::optional CM; std::unique_ptr TM( - T->createTargetMachine(M->getTargetTriple().str(), /* CPU */ "", + T->createTargetMachine(M->getTargetTriple().getTriple(), /* CPU */ "", /* Features */ "", Options, RM, CM)); if (!TM) return createStringError("Could not allocate target machine!"); diff --git a/clang/tools/clang-sycl-linker/SYCLLinkOpts.td b/clang/tools/clang-sycl-linker/SYCLLinkOpts.td index 1015fec1013b7..1657b01b649de 100644 --- a/clang/tools/clang-sycl-linker/SYCLLinkOpts.td +++ b/clang/tools/clang-sycl-linker/SYCLLinkOpts.td @@ -24,10 +24,14 @@ 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 triple : Separate<["--", "-"], "triple">, - HelpText<"The device target triple">; -def arch : Separate<["--", "-"], "arch">, - HelpText<"Specify the name of the target architecture.">; +def arch_EQ : Joined<["--", "-"], "arch=">, + Flags<[LinkerOnlyOption]>, + MetaVarName<"">, + HelpText<"The device subarchitecture">; +def triple_EQ : Joined<["--", "-"], "triple=">, + Flags<[LinkerOnlyOption]>, + MetaVarName<"">, + HelpText<"The device target triple">; def save_temps : Flag<["--", "-"], "save-temps">, Flags<[LinkerOnlyOption]>, HelpText<"Save intermediate results">;