From 491af223e0edcf402724666d06f4ebebfade475d Mon Sep 17 00:00:00 2001 From: "Cai, Justin" Date: Fri, 14 Feb 2025 21:16:27 +0000 Subject: [PATCH 1/7] [SYCL] Add support AOT compilation support for Intel GPUs in clang-sycl-linker --- clang/test/Driver/clang-sycl-linker-test.cpp | 46 +++++-- .../clang-sycl-linker/ClangSYCLLinker.cpp | 130 +++++++++++++++++- clang/tools/clang-sycl-linker/SYCLLinkOpts.td | 19 ++- llvm/include/llvm/TargetParser/Triple.h | 9 ++ llvm/lib/TargetParser/Triple.cpp | 12 ++ 5 files changed, 202 insertions(+), 14 deletions(-) diff --git a/clang/test/Driver/clang-sycl-linker-test.cpp b/clang/test/Driver/clang-sycl-linker-test.cpp index f358900b4fbd8..d543fe6deadc9 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 --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 // // 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 --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 // // 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 --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 @@ -25,24 +25,54 @@ // 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 --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 -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 --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 -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 --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: 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: 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= +// +// RUN: clang-sycl-linker --dry-run --triple=spir64_gen -arch pvc %t_1.bc %t_2.bc -o a.out 2>&1 \ +// RUN: | FileCheck %s --check-prefix=AOT-INTEL-GPU +// AOT-INTEL-GPU: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[LLVMLINKOUT:.*]].bc --suppress-warnings +// AOT-INTEL-GPU-NEXT: "{{.*}}llvm-spirv{{.*}}" {{.*}}-o [[SPIRVTRANSLATIONOUT:.*]] [[LLVMLINKOUT]].bc +// AOT-INTEL-GPU-NEXT: "{{.*}}ocloc{{.*}}" {{.*}}-device pvc {{.*}}-output a.out -file [[SPIRVTRANSLATIONOUT]] +// +// RUN: clang-sycl-linker --dry-run --triple=spir64_gen -arch pvc %t_1.bc %t_2.bc -o a.out 2>&1 \ +// RUN: --sycl-backend-compile-options-from-image=-a \ +// RUN: --sycl-backend-link-options-from-image=-b \ +// RUN: --gpu-tool-arg=-c \ +// RUN: | FileCheck %s --check-prefix=AOT-INTEL-GPU-2 +// AOT-INTEL-GPU-2: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[LLVMLINKOUT:.*]].bc --suppress-warnings +// AOT-INTEL-GPU-2-NEXT: "{{.*}}llvm-spirv{{.*}}" {{.*}}-o [[SPIRVTRANSLATIONOUT:.*]] [[LLVMLINKOUT]].bc +// AOT-INTEL-GPU-2-NEXT: "{{.*}}ocloc{{.*}}" {{.*}}-device pvc -a -b -c {{.*}}-output a.out -file [[SPIRVTRANSLATIONOUT]] +// +// RUN: clang-sycl-linker --dry-run --triple=spir64_x86_64 %t_1.bc %t_2.bc -o a.out 2>&1 \ +// RUN: | FileCheck %s --check-prefix=AOT-INTEL-CPU +// AOT-INTEL-CPU: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[LLVMLINKOUT:.*]].bc --suppress-warnings +// AOT-INTEL-CPU-NEXT: "{{.*}}llvm-spirv{{.*}}" {{.*}}-o [[SPIRVTRANSLATIONOUT:.*]] [[LLVMLINKOUT]].bc +// AOT-INTEL-CPU-NEXT: "{{.*}}opencl-aot{{.*}}" {{.*}}--device=cpu {{.*}}-o a.out [[SPIRVTRANSLATIONOUT]] +// +// RUN: clang-sycl-linker --dry-run --triple=spir64_x86_64 %t_1.bc %t_2.bc -o a.out 2>&1 \ +// RUN: --sycl-backend-compile-options-from-image=-a \ +// RUN: --sycl-backend-link-options-from-image=-b \ +// RUN: --cpu-tool-arg=-c \ +// RUN: | FileCheck %s --check-prefix=AOT-INTEL-CPU-2 +// AOT-INTEL-CPU-2: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[LLVMLINKOUT:.*]].bc --suppress-warnings +// AOT-INTEL-CPU-2-NEXT: "{{.*}}llvm-spirv{{.*}}" {{.*}}-o [[SPIRVTRANSLATIONOUT:.*]] [[LLVMLINKOUT]].bc +// AOT-INTEL-CPU-2-NEXT: "{{.*}}opencl-aot{{.*}}" {{.*}}--device=cpu -a -b -c {{.*}}-o a.out [[SPIRVTRANSLATIONOUT]] diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index 2bcb3757d49d0..10caa882b19a9 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -66,6 +66,8 @@ static StringRef OutputFile; /// Directory to dump SPIR-V IR if requested by user. static SmallString<128> SPIRVDumpDir; +static bool IsAOTCompileNeeded = false; + static void printVersion(raw_ostream &OS) { OS << clang::getClangToolFullVersion("clang-sycl-linker") << '\n'; } @@ -385,14 +387,22 @@ static Expected runLLVMToSPIRVTranslation(StringRef File, SmallVector CmdArgs; CmdArgs.push_back(*LLVMToSPIRVProg); - const llvm::Triple Triple(Args.getLastArgValue(OPT_triple)); + const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ)); 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}); + + Expected OutFileOrErr = + IsAOTCompileNeeded + ? createTempFile(Args, sys::path::filename(OutputFile), "spv") + : OutputFile; + if (!OutFileOrErr) + return OutFileOrErr.takeError(); + + CmdArgs.append({"-o", *OutFileOrErr}); CmdArgs.push_back(File); if (Error Err = executeCommands(*LLVMToSPIRVProg, CmdArgs)) return std::move(Err); @@ -406,7 +416,7 @@ static Expected runLLVMToSPIRVTranslation(StringRef File, formatv("failed to create dump directory. path: {0}, error_code: {1}", SPIRVDumpDir, EC.value())); - StringRef Path = OutputFile; + StringRef Path = *OutFileOrErr; StringRef Filename = llvm::sys::path::filename(Path); SmallString<128> CopyPath = SPIRVDumpDir; CopyPath.append(Filename); @@ -419,9 +429,108 @@ static Expected runLLVMToSPIRVTranslation(StringRef File, Path, CopyPath, EC.value())); } + return *OutFileOrErr; +} + +/// Adds all AOT backend options required for SYCL AOT compilation step to +/// 'CmdArgs'. +/// 'Args' encompasses all arguments required for linking and wrapping device +/// code and will be parsed to generate backend options required to be passed +/// into the SYCL AOT compilation step. +/// IsCPU is a bool used to direct option generation. If IsCPU is false, then +/// options are generated for AOT compilation targeting Intel GPUs. +static void addBackendOptions(const ArgList &Args, + SmallVector &CmdArgs, bool IsCPU) { + StringRef OptC = + Args.getLastArgValue(OPT_sycl_backend_compile_options_from_image_EQ); + OptC.split(CmdArgs, " ", /*MaxSplit=*/-1, /*KeepEmpty=*/false); + StringRef OptL = + Args.getLastArgValue(OPT_sycl_backend_link_options_from_image_EQ); + OptL.split(CmdArgs, " ", /*MaxSplit=*/-1, /*KeepEmpty=*/false); + StringRef OptTool = (IsCPU) ? Args.getLastArgValue(OPT_cpu_tool_arg_EQ) + : Args.getLastArgValue(OPT_gpu_tool_arg_EQ); + OptTool.split(CmdArgs, " ", /*MaxSplit=*/-1, /*KeepEmpty=*/false); + return; +} + +/// Run AOT compilation for Intel CPU. +/// Calls opencl-aot tool to generate device code for Intel CPU backend. +/// 'InputFile' is the input SPIR-V file. +/// '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. +static Expected runAOTCompileIntelCPU(StringRef InputFile, + const ArgList &Args) { + const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ)); + SmallVector CmdArgs; + Expected OpenCLAOTPath = + findProgram(Args, "opencl-aot", {getMainExecutable("opencl-aot")}); + if (!OpenCLAOTPath) + return OpenCLAOTPath.takeError(); + + CmdArgs.push_back(*OpenCLAOTPath); + CmdArgs.push_back("--device=cpu"); + addBackendOptions(Args, CmdArgs, /* IsCPU */ true); + CmdArgs.push_back("-o"); + CmdArgs.push_back(OutputFile); + CmdArgs.push_back(InputFile); + if (Error Err = executeCommands(*OpenCLAOTPath, CmdArgs)) + return std::move(Err); + return OutputFile; +} + +/// Run AOT compilation for Intel GPU +/// Calls ocloc tool to generate device code for Intel GPU backend. +/// 'InputFile' is the input SPIR-V file. +/// '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. +static Expected runAOTCompileIntelGPU(StringRef InputFile, + const ArgList &Args) { + const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ)); + StringRef Arch(Args.getLastArgValue(OPT_arch)); + SmallVector CmdArgs; + Expected OclocPath = + findProgram(Args, "ocloc", {getMainExecutable("ocloc")}); + if (!OclocPath) + return OclocPath.takeError(); + + CmdArgs.push_back(*OclocPath); + // The next line prevents ocloc from modifying the image name + CmdArgs.push_back("-output_no_suffix"); + CmdArgs.push_back("-spirv_input"); + if (!Arch.empty()) { + CmdArgs.push_back("-device"); + CmdArgs.push_back(Arch); + } + addBackendOptions(Args, CmdArgs, /* IsCPU */ false); + CmdArgs.push_back("-output"); + CmdArgs.push_back(OutputFile); + CmdArgs.push_back("-file"); + CmdArgs.push_back(InputFile); + if (Error Err = executeCommands(*OclocPath, CmdArgs)) + return std::move(Err); return OutputFile; } +/// Run AOT compilation for Intel CPU/GPU. +/// 'InputFile' is the input SPIR-V file. +/// '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. +static Expected runAOTCompile(StringRef InputFile, + const ArgList &Args) { + const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ)); + if (Triple.isSPIRAOT()) { + if (Triple.getSubArch() == llvm::Triple::SPIRSubArch_gen) + return runAOTCompileIntelGPU(InputFile, Args); + if (Triple.getSubArch() == llvm::Triple::SPIRSubArch_x86_64) + return runAOTCompileIntelCPU(InputFile, Args); + } + return createStringError(inconvertibleErrorCode(), + "Unsupported SYCL Triple and Arch"); +} + Error runSYCLLink(ArrayRef Files, const ArgList &Args) { llvm::TimeTraceScope TimeScope("SYCLDeviceLink"); // First llvm-link step @@ -437,7 +546,13 @@ Error runSYCLLink(ArrayRef Files, const ArgList &Args) { // LLVM to SPIR-V translation step auto SPVFile = runLLVMToSPIRVTranslation(*DeviceLinkedFile, Args); if (!SPVFile) - return SPVFile.takeError(); + reportError(SPVFile.takeError()); + + Expected AOTFile = + (IsAOTCompileNeeded) ? runAOTCompile(*SPVFile, Args) : *SPVFile; + if (!AOTFile) + return AOTFile.takeError(); + return Error::success(); } @@ -474,7 +589,12 @@ int main(int argc, char **argv) { DryRun = Args.hasArg(OPT_dry_run); SaveTemps = Args.hasArg(OPT_save_temps); - OutputFile = "a.spv"; + const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ)); + IsAOTCompileNeeded = + (Triple.getSubArch() == llvm::Triple::SPIRSubArch_gen || + Triple.getSubArch() == llvm::Triple::SPIRSubArch_x86_64); + + OutputFile = IsAOTCompileNeeded ? "a.out" : "a.spv"; if (Args.hasArg(OPT_o)) OutputFile = Args.getLastArgValue(OPT_o); diff --git a/clang/tools/clang-sycl-linker/SYCLLinkOpts.td b/clang/tools/clang-sycl-linker/SYCLLinkOpts.td index 959fd6c3e867c..52544049f5988 100644 --- a/clang/tools/clang-sycl-linker/SYCLLinkOpts.td +++ b/clang/tools/clang-sycl-linker/SYCLLinkOpts.td @@ -24,7 +24,7 @@ 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">, +def triple_EQ : Joined<["--"], "triple=">, HelpText<"The device target triple">; def arch : Separate<["--", "-"], "arch">, HelpText<"Specify the name of the target architecture.">; @@ -50,3 +50,20 @@ def llvm_spirv_path_EQ : Joined<["--"], "llvm-spirv-path=">, def llvm_spirv_options_EQ : Joined<["--", "-"], "llvm-spirv-options=">, Flags<[LinkerOnlyOption]>, HelpText<"Options that will control llvm-spirv step">; + +def sycl_backend_compile_options_from_image_EQ : Joined<["--", "-"], "sycl-backend-compile-options-from-image=">, + Flags<[LinkerOnlyOption]>, + HelpText<"Compile options that will be transmitted to the SYCL backend compiler">; + +def sycl_backend_link_options_from_image_EQ : Joined<["--", "-"], "sycl-backend-link-options-from-image=">, + Flags<[LinkerOnlyOption]>, + HelpText<"Link options that will be transmitted to the SYCL backend compiler">; + +def gpu_tool_arg_EQ : + Joined<["--", "-"], "gpu-tool-arg=">, + Flags<[LinkerOnlyOption]>, + HelpText<"Options that are passed to the backend of target device compiler for Intel GPU during AOT compilation">; +def cpu_tool_arg_EQ : + Joined<["--", "-"], "cpu-tool-arg=">, + Flags<[LinkerOnlyOption]>, + HelpText<"Options that are passed to the backend of target device compiler for Intel CPU during AOT compilation">; diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h index 09c0d223d9b4d..b1c5cb9bb5214 100644 --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -176,6 +176,9 @@ class Triple { DXILSubArch_v1_7, DXILSubArch_v1_8, LatestDXILSubArch = DXILSubArch_v1_8, + + SPIRSubArch_gen, + SPIRSubArch_x86_64, }; enum VendorType { UnknownVendor, @@ -863,6 +866,12 @@ class Triple { return getArch() == Triple::spir || getArch() == Triple::spir64; } + /// Tests whether the target is SPIR and AOT related. + bool isSPIRAOT() const { + return isSPIR() && (getSubArch() == Triple::SPIRSubArch_gen || + getSubArch() == Triple::SPIRSubArch_x86_64); + } + /// Tests whether the target is SPIR-V (32/64-bit/Logical). bool isSPIRV() const { return getArch() == Triple::spirv32 || getArch() == Triple::spirv64 || diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index e9e6f130f757c..0aef18ff73cba 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -617,6 +617,8 @@ static Triple::ArchType parseArch(StringRef ArchName) { .Cases("spirv64", "spirv64v1.0", "spirv64v1.1", "spirv64v1.2", "spirv64v1.3", "spirv64v1.4", "spirv64v1.5", "spirv64v1.6", Triple::spirv64) + .StartsWith("spir64", Triple::spir64) + .StartsWith("spir", Triple::spir) .StartsWith("kalimba", Triple::kalimba) .Case("lanai", Triple::lanai) .Case("renderscript32", Triple::renderscript32) @@ -788,6 +790,16 @@ static Triple::SubArchType parseSubArch(StringRef SubArchName) { (SubArchName.ends_with("r6el") || SubArchName.ends_with("r6"))) return Triple::MipsSubArch_r6; + if (SubArchName.starts_with("spir")) { + StringRef SA(SubArchName); + if (SA.consume_front("spir64_") || SA.consume_front("spir_")) { + if (SA == "gen") + return Triple::SPIRSubArch_gen; + else if (SA == "x86_64") + return Triple::SPIRSubArch_x86_64; + } + } + if (SubArchName == "powerpcspe") return Triple::PPCSubArch_spe; From 52edf802fde28e33a7724d3bf390590362897112 Mon Sep 17 00:00:00 2001 From: "Cai, Justin" Date: Fri, 14 Mar 2025 15:46:11 +0000 Subject: [PATCH 2/7] Address review comments --- clang/test/Driver/clang-sycl-linker-test.cpp | 5 ++++ .../clang-sycl-linker/ClangSYCLLinker.cpp | 25 +++++++++---------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/clang/test/Driver/clang-sycl-linker-test.cpp b/clang/test/Driver/clang-sycl-linker-test.cpp index d543fe6deadc9..22dc5c220373c 100644 --- a/clang/test/Driver/clang-sycl-linker-test.cpp +++ b/clang/test/Driver/clang-sycl-linker-test.cpp @@ -76,3 +76,8 @@ // AOT-INTEL-CPU-2: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[LLVMLINKOUT:.*]].bc --suppress-warnings // AOT-INTEL-CPU-2-NEXT: "{{.*}}llvm-spirv{{.*}}" {{.*}}-o [[SPIRVTRANSLATIONOUT:.*]] [[LLVMLINKOUT]].bc // AOT-INTEL-CPU-2-NEXT: "{{.*}}opencl-aot{{.*}}" {{.*}}--device=cpu -a -b -c {{.*}}-o a.out [[SPIRVTRANSLATIONOUT]] +// +// RUN: not clang-sycl-linker --dry-run --triple=spir64_x86_64 %t_1.bc %t_2.bc 2>& 1 \ +// RUN: | FileCheck %s --check-prefix=NOOUTPUT +// NOOUTPUT: Output file is not specified +// diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index 10caa882b19a9..abecf3c98ca7b 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -461,7 +461,6 @@ static void addBackendOptions(const ArgList &Args, /// SYCL AOT compilation step. static Expected runAOTCompileIntelCPU(StringRef InputFile, const ArgList &Args) { - const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ)); SmallVector CmdArgs; Expected OpenCLAOTPath = findProgram(Args, "opencl-aot", {getMainExecutable("opencl-aot")}); @@ -487,8 +486,6 @@ static Expected runAOTCompileIntelCPU(StringRef InputFile, /// SYCL AOT compilation step. static Expected runAOTCompileIntelGPU(StringRef InputFile, const ArgList &Args) { - const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ)); - StringRef Arch(Args.getLastArgValue(OPT_arch)); SmallVector CmdArgs; Expected OclocPath = findProgram(Args, "ocloc", {getMainExecutable("ocloc")}); @@ -499,10 +496,12 @@ static Expected runAOTCompileIntelGPU(StringRef InputFile, // The next line prevents ocloc from modifying the image name CmdArgs.push_back("-output_no_suffix"); CmdArgs.push_back("-spirv_input"); - if (!Arch.empty()) { - CmdArgs.push_back("-device"); - CmdArgs.push_back(Arch); - } + + StringRef Arch(Args.getLastArgValue(OPT_arch)); + assert(!Arch.empty() && "Arch must be specified for AOT compilation"); + CmdArgs.push_back("-device"); + CmdArgs.push_back(Arch); + addBackendOptions(Args, CmdArgs, /* IsCPU */ false); CmdArgs.push_back("-output"); CmdArgs.push_back(OutputFile); @@ -536,17 +535,17 @@ Error runSYCLLink(ArrayRef Files, const ArgList &Args) { // First llvm-link step auto LinkedFile = linkDeviceInputFiles(Files, Args); if (!LinkedFile) - reportError(LinkedFile.takeError()); + return LinkedFile.takeError(); // second llvm-link step auto DeviceLinkedFile = linkDeviceLibFiles(*LinkedFile, Args); if (!DeviceLinkedFile) - reportError(DeviceLinkedFile.takeError()); + return DeviceLinkedFile.takeError(); // LLVM to SPIR-V translation step auto SPVFile = runLLVMToSPIRVTranslation(*DeviceLinkedFile, Args); if (!SPVFile) - reportError(SPVFile.takeError()); + return SPVFile.takeError(); Expected AOTFile = (IsAOTCompileNeeded) ? runAOTCompile(*SPVFile, Args) : *SPVFile; @@ -594,9 +593,9 @@ int main(int argc, char **argv) { (Triple.getSubArch() == llvm::Triple::SPIRSubArch_gen || Triple.getSubArch() == llvm::Triple::SPIRSubArch_x86_64); - OutputFile = IsAOTCompileNeeded ? "a.out" : "a.spv"; - if (Args.hasArg(OPT_o)) - OutputFile = Args.getLastArgValue(OPT_o); + if (!Args.hasArg(OPT_o)) + reportError(createStringError("Output file is not specified")); + OutputFile = Args.getLastArgValue(OPT_o); if (Args.hasArg(OPT_spirv_dump_device_code_EQ)) { Arg *A = Args.getLastArg(OPT_spirv_dump_device_code_EQ); From 5e13405491a40a573e66861cee88a57a9a3f9867 Mon Sep 17 00:00:00 2001 From: "Cai, Justin" Date: Mon, 17 Mar 2025 07:34:43 -0700 Subject: [PATCH 3/7] Address review comments --- clang/include/clang/Basic/SYCL.h | 131 ++++++++++ clang/lib/Basic/CMakeLists.txt | 1 + clang/lib/Basic/SYCL.cpp | 226 ++++++++++++++++++ clang/test/Driver/clang-sycl-linker-test.cpp | 34 +-- .../clang-sycl-linker/ClangSYCLLinker.cpp | 113 ++------- clang/tools/clang-sycl-linker/SYCLLinkOpts.td | 2 - 6 files changed, 390 insertions(+), 117 deletions(-) create mode 100644 clang/include/clang/Basic/SYCL.h create mode 100644 clang/lib/Basic/SYCL.cpp diff --git a/clang/include/clang/Basic/SYCL.h b/clang/include/clang/Basic/SYCL.h new file mode 100644 index 0000000000000..c7cad37639b91 --- /dev/null +++ b/clang/include/clang/Basic/SYCL.h @@ -0,0 +1,131 @@ +//===--- SYCL.h -------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_SYCL_H +#define LLVM_CLANG_BASIC_SYCL_H + +#include "clang/Basic/Cuda.h" + +namespace llvm { +class StringRef; +template class SmallString; +} // namespace llvm + +namespace clang { +// List of architectures (Intel CPUs and Intel GPUs) +// that support SYCL offloading. +enum class SYCLSupportedIntelArchs { + // Intel CPUs + UNKNOWN, + SKYLAKEAVX512, + COREAVX2, + COREI7AVX, + COREI7, + WESTMERE, + SANDYBRIDGE, + IVYBRIDGE, + BROADWELL, + COFFEELAKE, + ALDERLAKE, + SKYLAKE, + SKX, + CASCADELAKE, + ICELAKECLIENT, + ICELAKESERVER, + SAPPHIRERAPIDS, + GRANITERAPIDS, + // Intel GPUs + BDW, + SKL, + KBL, + CFL, + APL, + BXT, + GLK, + WHL, + AML, + CML, + ICLLP, + ICL, + EHL, + JSL, + TGLLP, + TGL, + RKL, + ADL_S, + RPL_S, + ADL_P, + ADL_N, + DG1, + ACM_G10, + DG2_G10, + ACM_G11, + DG2_G11, + ACM_G12, + DG2_G12, + PVC, + PVC_VG, + MTL_U, + MTL_S, + ARL_U, + ARL_S, + MTL_H, + ARL_H, + BMG_G21, + LNL_M, +}; + +// Check if the given Arch value is a Generic AMD GPU. +// Currently GFX*_GENERIC AMD GPUs do not support SYCL offloading. +// This list is used to filter out GFX*_GENERIC AMD GPUs in +// `IsSYCLSupportedAMDGPUArch`. +static inline bool IsAMDGenericGPUArch(OffloadArch Arch) { + return Arch == OffloadArch::GFX9_GENERIC || + Arch == OffloadArch::GFX10_1_GENERIC || + Arch == OffloadArch::GFX10_3_GENERIC || + Arch == OffloadArch::GFX11_GENERIC || + Arch == OffloadArch::GFX12_GENERIC; +} + +// Check if the given Arch value is a valid SYCL supported AMD GPU. +static inline bool IsSYCLSupportedAMDGPUArch(OffloadArch Arch) { + return Arch >= OffloadArch::GFX700 && Arch < OffloadArch::AMDGCNSPIRV && + !IsAMDGenericGPUArch(Arch); +} + +// Check if the given Arch value is a valid SYCL supported NVidia GPU. +static inline bool IsSYCLSupportedNVidiaGPUArch(OffloadArch Arch) { + return Arch >= OffloadArch::SM_50 && Arch <= OffloadArch::SM_90a; +} + +// Check if the given Arch value is a valid SYCL supported Intel CPU. +static inline bool IsSYCLSupportedIntelCPUArch(SYCLSupportedIntelArchs Arch) { + return Arch >= SYCLSupportedIntelArchs::SKYLAKEAVX512 && + Arch <= SYCLSupportedIntelArchs::GRANITERAPIDS; +} + +// Check if the given Arch value is a valid SYCL supported Intel GPU. +static inline bool IsSYCLSupportedIntelGPUArch(SYCLSupportedIntelArchs Arch) { + return Arch >= SYCLSupportedIntelArchs::BDW && + Arch <= SYCLSupportedIntelArchs::LNL_M; +} + +// Check if the user provided value for --offload-arch is a valid +// SYCL supported Intel AOT target. +SYCLSupportedIntelArchs +StringToOffloadArchSYCL(llvm::StringRef ArchNameAsString); + +// This is a mapping between the user provided --offload-arch value for Intel +// GPU targets and the spir64_gen device name accepted by OCLOC (the Intel GPU +// AOT compiler). +llvm::StringRef mapIntelGPUArchName(llvm::StringRef ArchName); +llvm::SmallString<64> getGenDeviceMacro(llvm::StringRef DeviceName); + +} // namespace clang + +#endif // LLVM_CLANG_BASIC_SYCL_H diff --git a/clang/lib/Basic/CMakeLists.txt b/clang/lib/Basic/CMakeLists.txt index 331dfbb3f4b67..be6d915e01b0a 100644 --- a/clang/lib/Basic/CMakeLists.txt +++ b/clang/lib/Basic/CMakeLists.txt @@ -90,6 +90,7 @@ add_clang_library(clangBasic SourceMgrAdapter.cpp Stack.cpp StackExhaustionHandler.cpp + SYCL.cpp TargetID.cpp TargetInfo.cpp Targets.cpp diff --git a/clang/lib/Basic/SYCL.cpp b/clang/lib/Basic/SYCL.cpp new file mode 100644 index 0000000000000..9ac5470cdbe5a --- /dev/null +++ b/clang/lib/Basic/SYCL.cpp @@ -0,0 +1,226 @@ +#include "clang/Basic/SYCL.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" + +using namespace llvm; + +namespace clang { + +// Struct that relates an AOT target value with +// Intel CPUs and Intel GPUs. +struct StringToOffloadArchSYCLMap { + const char *ArchName; + SYCLSupportedIntelArchs IntelArch; +}; + +// Mapping of supported SYCL offloading architectures. +static const StringToOffloadArchSYCLMap StringToArchNamesMap[] = { + // Intel CPU mapping. + {"skylake-avx512", SYCLSupportedIntelArchs::SKYLAKEAVX512}, + {"core-avx2", SYCLSupportedIntelArchs::COREAVX2}, + {"corei7-avx", SYCLSupportedIntelArchs::COREI7AVX}, + {"corei7", SYCLSupportedIntelArchs::COREI7}, + {"westmere", SYCLSupportedIntelArchs::WESTMERE}, + {"sandybridge", SYCLSupportedIntelArchs::SANDYBRIDGE}, + {"ivybridge", SYCLSupportedIntelArchs::IVYBRIDGE}, + {"broadwell", SYCLSupportedIntelArchs::BROADWELL}, + {"coffeelake", SYCLSupportedIntelArchs::COFFEELAKE}, + {"alderlake", SYCLSupportedIntelArchs::ALDERLAKE}, + {"skylake", SYCLSupportedIntelArchs::SKYLAKE}, + {"skx", SYCLSupportedIntelArchs::SKX}, + {"cascadelake", SYCLSupportedIntelArchs::CASCADELAKE}, + {"icelake-client", SYCLSupportedIntelArchs::ICELAKECLIENT}, + {"icelake-server", SYCLSupportedIntelArchs::ICELAKESERVER}, + {"sapphirerapids", SYCLSupportedIntelArchs::SAPPHIRERAPIDS}, + {"graniterapids", SYCLSupportedIntelArchs::GRANITERAPIDS}, + // Intel GPU mapping. + {"bdw", SYCLSupportedIntelArchs::BDW}, + {"skl", SYCLSupportedIntelArchs::SKL}, + {"kbl", SYCLSupportedIntelArchs::KBL}, + {"cfl", SYCLSupportedIntelArchs::CFL}, + {"apl", SYCLSupportedIntelArchs::APL}, + {"bxt", SYCLSupportedIntelArchs::BXT}, + {"glk", SYCLSupportedIntelArchs::GLK}, + {"whl", SYCLSupportedIntelArchs::WHL}, + {"aml", SYCLSupportedIntelArchs::AML}, + {"cml", SYCLSupportedIntelArchs::CML}, + {"icllp", SYCLSupportedIntelArchs::ICLLP}, + {"icl", SYCLSupportedIntelArchs::ICL}, + {"ehl", SYCLSupportedIntelArchs::EHL}, + {"jsl", SYCLSupportedIntelArchs::JSL}, + {"tgllp", SYCLSupportedIntelArchs::TGLLP}, + {"tgl", SYCLSupportedIntelArchs::TGL}, + {"rkl", SYCLSupportedIntelArchs::RKL}, + {"adl_s", SYCLSupportedIntelArchs::ADL_S}, + {"rpl_s", SYCLSupportedIntelArchs::RPL_S}, + {"adl_p", SYCLSupportedIntelArchs::ADL_P}, + {"adl_n", SYCLSupportedIntelArchs::ADL_N}, + {"dg1", SYCLSupportedIntelArchs::DG1}, + {"acm_g10", SYCLSupportedIntelArchs::ACM_G10}, + {"dg2_g10", SYCLSupportedIntelArchs::DG2_G10}, + {"acm_g11", SYCLSupportedIntelArchs::ACM_G11}, + {"dg2_g10", SYCLSupportedIntelArchs::DG2_G10}, + {"dg2_g11", SYCLSupportedIntelArchs::DG2_G11}, + {"acm_g12", SYCLSupportedIntelArchs::ACM_G12}, + {"dg2_g12", SYCLSupportedIntelArchs::DG2_G12}, + {"pvc", SYCLSupportedIntelArchs::PVC}, + {"pvc_vg", SYCLSupportedIntelArchs::PVC_VG}, + {"mtl_u", SYCLSupportedIntelArchs::MTL_U}, + {"mtl_s", SYCLSupportedIntelArchs::MTL_S}, + {"arl_u", SYCLSupportedIntelArchs::ARL_U}, + {"arl_s", SYCLSupportedIntelArchs::ARL_S}, + {"mtl_h", SYCLSupportedIntelArchs::MTL_H}, + {"arl_h", SYCLSupportedIntelArchs::ARL_H}, + {"bmg_g21", SYCLSupportedIntelArchs::BMG_G21}, + {"lnl_m", SYCLSupportedIntelArchs::LNL_M}}; + +// Check if the user provided value for --offload-arch is a valid +// SYCL supported Intel AOT target. +SYCLSupportedIntelArchs StringToOffloadArchSYCL(StringRef ArchNameAsString) { + auto result = + llvm::find_if(StringToArchNamesMap, + [ArchNameAsString](const StringToOffloadArchSYCLMap &map) { + return ArchNameAsString == map.ArchName; + }); + if (result == std::end(StringToArchNamesMap)) + return SYCLSupportedIntelArchs::UNKNOWN; + return result->IntelArch; +} + +// This is a mapping between the user provided --offload-arch value for Intel +// GPU targets and the spir64_gen device name accepted by OCLOC (the Intel GPU +// AOT compiler). +StringRef mapIntelGPUArchName(StringRef ArchName) { + StringRef Arch; + Arch = llvm::StringSwitch(ArchName) + .Case("bdw", "bdw") + .Case("skl", "skl") + .Case("kbl", "kbl") + .Case("cfl", "cfl") + .Cases("apl", "bxt", "apl") + .Case("glk", "glk") + .Case("whl", "whl") + .Case("aml", "aml") + .Case("cml", "cml") + .Cases("icllp", "icl", "icllp") + .Cases("ehl", "jsl", "ehl") + .Cases("tgllp", "tgl", "tgllp") + .Case("rkl", "rkl") + .Cases("adl_s", "rpl_s", "adl_s") + .Case("adl_p", "adl_p") + .Case("adl_n", "adl_n") + .Case("dg1", "dg1") + .Cases("acm_g10", "dg2_g10", "acm_g10") + .Cases("acm_g11", "dg2_g11", "acm_g11") + .Cases("acm_g12", "dg2_g12", "acm_g12") + .Case("pvc", "pvc") + .Case("pvc_vg", "pvc_vg") + .Cases("mtl_u", "mtl_s", "arl_u", "arl_s", "mtl_u") + .Case("mtl_h", "mtl_h") + .Case("arl_h", "arl_h") + .Case("bmg_g21", "bmg_g21") + .Case("lnl_m", "lnl_m") + .Default(""); + return Arch; +} + +SmallString<64> getGenDeviceMacro(StringRef DeviceName) { + SmallString<64> Macro; + StringRef Ext = llvm::StringSwitch(DeviceName) + .Case("bdw", "INTEL_GPU_BDW") + .Case("skl", "INTEL_GPU_SKL") + .Case("kbl", "INTEL_GPU_KBL") + .Case("cfl", "INTEL_GPU_CFL") + .Case("apl", "INTEL_GPU_APL") + .Case("glk", "INTEL_GPU_GLK") + .Case("whl", "INTEL_GPU_WHL") + .Case("aml", "INTEL_GPU_AML") + .Case("cml", "INTEL_GPU_CML") + .Case("icllp", "INTEL_GPU_ICLLP") + .Case("ehl", "INTEL_GPU_EHL") + .Case("tgllp", "INTEL_GPU_TGLLP") + .Case("rkl", "INTEL_GPU_RKL") + .Case("adl_s", "INTEL_GPU_ADL_S") + .Case("adl_p", "INTEL_GPU_ADL_P") + .Case("adl_n", "INTEL_GPU_ADL_N") + .Case("dg1", "INTEL_GPU_DG1") + .Case("acm_g10", "INTEL_GPU_ACM_G10") + .Case("acm_g11", "INTEL_GPU_ACM_G11") + .Case("acm_g12", "INTEL_GPU_ACM_G12") + .Case("pvc", "INTEL_GPU_PVC") + .Case("pvc_vg", "INTEL_GPU_PVC_VG") + .Case("mtl_u", "INTEL_GPU_MTL_U") + .Case("mtl_h", "INTEL_GPU_MTL_H") + .Case("arl_h", "INTEL_GPU_ARL_H") + .Case("bmg_g21", "INTEL_GPU_BMG_G21") + .Case("lnl_m", "INTEL_GPU_LNL_M") + .Case("ptl_h", "INTEL_GPU_PTL_H") + .Case("ptl_u", "INTEL_GPU_PTL_U") + .Case("sm_50", "NVIDIA_GPU_SM_50") + .Case("sm_52", "NVIDIA_GPU_SM_52") + .Case("sm_53", "NVIDIA_GPU_SM_53") + .Case("sm_60", "NVIDIA_GPU_SM_60") + .Case("sm_61", "NVIDIA_GPU_SM_61") + .Case("sm_62", "NVIDIA_GPU_SM_62") + .Case("sm_70", "NVIDIA_GPU_SM_70") + .Case("sm_72", "NVIDIA_GPU_SM_72") + .Case("sm_75", "NVIDIA_GPU_SM_75") + .Case("sm_80", "NVIDIA_GPU_SM_80") + .Case("sm_86", "NVIDIA_GPU_SM_86") + .Case("sm_87", "NVIDIA_GPU_SM_87") + .Case("sm_89", "NVIDIA_GPU_SM_89") + .Case("sm_90", "NVIDIA_GPU_SM_90") + .Case("sm_90a", "NVIDIA_GPU_SM_90A") + .Case("gfx700", "AMD_GPU_GFX700") + .Case("gfx701", "AMD_GPU_GFX701") + .Case("gfx702", "AMD_GPU_GFX702") + .Case("gfx703", "AMD_GPU_GFX703") + .Case("gfx704", "AMD_GPU_GFX704") + .Case("gfx705", "AMD_GPU_GFX705") + .Case("gfx801", "AMD_GPU_GFX801") + .Case("gfx802", "AMD_GPU_GFX802") + .Case("gfx803", "AMD_GPU_GFX803") + .Case("gfx805", "AMD_GPU_GFX805") + .Case("gfx810", "AMD_GPU_GFX810") + .Case("gfx900", "AMD_GPU_GFX900") + .Case("gfx902", "AMD_GPU_GFX902") + .Case("gfx904", "AMD_GPU_GFX904") + .Case("gfx906", "AMD_GPU_GFX906") + .Case("gfx908", "AMD_GPU_GFX908") + .Case("gfx909", "AMD_GPU_GFX909") + .Case("gfx90a", "AMD_GPU_GFX90A") + .Case("gfx90c", "AMD_GPU_GFX90C") + .Case("gfx940", "AMD_GPU_GFX940") + .Case("gfx941", "AMD_GPU_GFX941") + .Case("gfx942", "AMD_GPU_GFX942") + .Case("gfx1010", "AMD_GPU_GFX1010") + .Case("gfx1011", "AMD_GPU_GFX1011") + .Case("gfx1012", "AMD_GPU_GFX1012") + .Case("gfx1013", "AMD_GPU_GFX1013") + .Case("gfx1030", "AMD_GPU_GFX1030") + .Case("gfx1031", "AMD_GPU_GFX1031") + .Case("gfx1032", "AMD_GPU_GFX1032") + .Case("gfx1033", "AMD_GPU_GFX1033") + .Case("gfx1034", "AMD_GPU_GFX1034") + .Case("gfx1035", "AMD_GPU_GFX1035") + .Case("gfx1036", "AMD_GPU_GFX1036") + .Case("gfx1100", "AMD_GPU_GFX1100") + .Case("gfx1101", "AMD_GPU_GFX1101") + .Case("gfx1102", "AMD_GPU_GFX1102") + .Case("gfx1103", "AMD_GPU_GFX1103") + .Case("gfx1150", "AMD_GPU_GFX1150") + .Case("gfx1151", "AMD_GPU_GFX1151") + .Case("gfx1200", "AMD_GPU_GFX1200") + .Case("gfx1201", "AMD_GPU_GFX1201") + .Default(""); + if (!Ext.empty()) { + Macro = "__SYCL_TARGET_"; + Macro += Ext; + Macro += "__"; + } + return Macro; +} + +} // namespace clang diff --git a/clang/test/Driver/clang-sycl-linker-test.cpp b/clang/test/Driver/clang-sycl-linker-test.cpp index 22dc5c220373c..91c306663bdca 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{{.*}}" {{.*}}-o a.spv [[FIRSTLLVMLINKOUT]].bc // // 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{{.*}}" {{.*}}-o a.spv {{.*}}.bc // // 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,35 +25,25 @@ // 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 -// -// 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= -// -// RUN: clang-sycl-linker --dry-run --triple=spir64_gen -arch pvc %t_1.bc %t_2.bc -o a.out 2>&1 \ +// +// RUN: clang-sycl-linker --dry-run -arch pvc %t_1.bc %t_2.bc -o a.out 2>&1 \ // RUN: | FileCheck %s --check-prefix=AOT-INTEL-GPU // AOT-INTEL-GPU: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[LLVMLINKOUT:.*]].bc --suppress-warnings // AOT-INTEL-GPU-NEXT: "{{.*}}llvm-spirv{{.*}}" {{.*}}-o [[SPIRVTRANSLATIONOUT:.*]] [[LLVMLINKOUT]].bc // AOT-INTEL-GPU-NEXT: "{{.*}}ocloc{{.*}}" {{.*}}-device pvc {{.*}}-output a.out -file [[SPIRVTRANSLATIONOUT]] // -// RUN: clang-sycl-linker --dry-run --triple=spir64_gen -arch pvc %t_1.bc %t_2.bc -o a.out 2>&1 \ +// RUN: clang-sycl-linker --dry-run -arch pvc %t_1.bc %t_2.bc -o a.out 2>&1 \ // RUN: --sycl-backend-compile-options-from-image=-a \ // RUN: --sycl-backend-link-options-from-image=-b \ // RUN: --gpu-tool-arg=-c \ @@ -62,13 +52,13 @@ // AOT-INTEL-GPU-2-NEXT: "{{.*}}llvm-spirv{{.*}}" {{.*}}-o [[SPIRVTRANSLATIONOUT:.*]] [[LLVMLINKOUT]].bc // AOT-INTEL-GPU-2-NEXT: "{{.*}}ocloc{{.*}}" {{.*}}-device pvc -a -b -c {{.*}}-output a.out -file [[SPIRVTRANSLATIONOUT]] // -// RUN: clang-sycl-linker --dry-run --triple=spir64_x86_64 %t_1.bc %t_2.bc -o a.out 2>&1 \ +// RUN: clang-sycl-linker --dry-run -arch corei7 %t_1.bc %t_2.bc -o a.out 2>&1 \ // RUN: | FileCheck %s --check-prefix=AOT-INTEL-CPU // AOT-INTEL-CPU: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[LLVMLINKOUT:.*]].bc --suppress-warnings // AOT-INTEL-CPU-NEXT: "{{.*}}llvm-spirv{{.*}}" {{.*}}-o [[SPIRVTRANSLATIONOUT:.*]] [[LLVMLINKOUT]].bc // AOT-INTEL-CPU-NEXT: "{{.*}}opencl-aot{{.*}}" {{.*}}--device=cpu {{.*}}-o a.out [[SPIRVTRANSLATIONOUT]] // -// RUN: clang-sycl-linker --dry-run --triple=spir64_x86_64 %t_1.bc %t_2.bc -o a.out 2>&1 \ +// RUN: clang-sycl-linker --dry-run -arch corei7 %t_1.bc %t_2.bc -o a.out 2>&1 \ // RUN: --sycl-backend-compile-options-from-image=-a \ // RUN: --sycl-backend-link-options-from-image=-b \ // RUN: --cpu-tool-arg=-c \ @@ -77,7 +67,7 @@ // AOT-INTEL-CPU-2-NEXT: "{{.*}}llvm-spirv{{.*}}" {{.*}}-o [[SPIRVTRANSLATIONOUT:.*]] [[LLVMLINKOUT]].bc // AOT-INTEL-CPU-2-NEXT: "{{.*}}opencl-aot{{.*}}" {{.*}}--device=cpu -a -b -c {{.*}}-o a.out [[SPIRVTRANSLATIONOUT]] // -// RUN: not clang-sycl-linker --dry-run --triple=spir64_x86_64 %t_1.bc %t_2.bc 2>& 1 \ +// RUN: not clang-sycl-linker --dry-run %t_1.bc %t_2.bc 2>& 1 \ // RUN: | FileCheck %s --check-prefix=NOOUTPUT // NOOUTPUT: Output file is not specified // diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index abecf3c98ca7b..4fa68e0c5bafd 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -14,6 +14,7 @@ // target-specific device code. //===---------------------------------------------------------------------===// +#include "clang/Basic/SYCL.h" #include "clang/Basic/Version.h" #include "llvm/ADT/StringExtras.h" @@ -50,6 +51,7 @@ using namespace llvm; using namespace llvm::opt; using namespace llvm::object; +using namespace clang; /// Save intermediary results. static bool SaveTemps = false; @@ -306,72 +308,6 @@ 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. /// 'Args' encompasses all arguments required for linking device code and will @@ -387,8 +323,6 @@ static Expected runLLVMToSPIRVTranslation(StringRef File, SmallVector CmdArgs; CmdArgs.push_back(*LLVMToSPIRVProg); - const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ)); - getSPIRVTransOpts(Args, CmdArgs, Triple); StringRef LLVMToSPIRVOptions; if (Arg *A = Args.getLastArg(OPT_llvm_spirv_options_EQ)) LLVMToSPIRVOptions = A->getValue(); @@ -459,8 +393,7 @@ static void addBackendOptions(const ArgList &Args, /// '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. -static Expected runAOTCompileIntelCPU(StringRef InputFile, - const ArgList &Args) { +static Error runAOTCompileIntelCPU(StringRef InputFile, const ArgList &Args) { SmallVector CmdArgs; Expected OpenCLAOTPath = findProgram(Args, "opencl-aot", {getMainExecutable("opencl-aot")}); @@ -475,7 +408,7 @@ static Expected runAOTCompileIntelCPU(StringRef InputFile, CmdArgs.push_back(InputFile); if (Error Err = executeCommands(*OpenCLAOTPath, CmdArgs)) return std::move(Err); - return OutputFile; + return Error::success(); } /// Run AOT compilation for Intel GPU @@ -484,8 +417,7 @@ static Expected runAOTCompileIntelCPU(StringRef InputFile, /// '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. -static Expected runAOTCompileIntelGPU(StringRef InputFile, - const ArgList &Args) { +static Error runAOTCompileIntelGPU(StringRef InputFile, const ArgList &Args) { SmallVector CmdArgs; Expected OclocPath = findProgram(Args, "ocloc", {getMainExecutable("ocloc")}); @@ -509,7 +441,7 @@ static Expected runAOTCompileIntelGPU(StringRef InputFile, CmdArgs.push_back(InputFile); if (Error Err = executeCommands(*OclocPath, CmdArgs)) return std::move(Err); - return OutputFile; + return Error::success(); } /// Run AOT compilation for Intel CPU/GPU. @@ -517,17 +449,15 @@ static Expected runAOTCompileIntelGPU(StringRef InputFile, /// '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. -static Expected runAOTCompile(StringRef InputFile, - const ArgList &Args) { - const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ)); - if (Triple.isSPIRAOT()) { - if (Triple.getSubArch() == llvm::Triple::SPIRSubArch_gen) - return runAOTCompileIntelGPU(InputFile, Args); - if (Triple.getSubArch() == llvm::Triple::SPIRSubArch_x86_64) - return runAOTCompileIntelCPU(InputFile, Args); - } - return createStringError(inconvertibleErrorCode(), - "Unsupported SYCL Triple and Arch"); +static Error runAOTCompile(StringRef InputFile, const ArgList &Args) { + StringRef Arch = Args.getLastArgValue(OPT_arch); + SYCLSupportedIntelArchs OffloadArch = StringToOffloadArchSYCL(Arch); + if (IsSYCLSupportedIntelGPUArch(OffloadArch)) + return runAOTCompileIntelGPU(InputFile, Args); + if (IsSYCLSupportedIntelCPUArch(OffloadArch)) + return runAOTCompileIntelCPU(InputFile, Args); + + return createStringError(inconvertibleErrorCode(), "Unsupported arch"); } Error runSYCLLink(ArrayRef Files, const ArgList &Args) { @@ -547,10 +477,10 @@ Error runSYCLLink(ArrayRef Files, const ArgList &Args) { if (!SPVFile) return SPVFile.takeError(); - Expected AOTFile = - (IsAOTCompileNeeded) ? runAOTCompile(*SPVFile, Args) : *SPVFile; - if (!AOTFile) - return AOTFile.takeError(); + if (IsAOTCompileNeeded) { + if (Error Err = runAOTCompile(*SPVFile, Args)) + return Err; + } return Error::success(); } @@ -588,10 +518,7 @@ int main(int argc, char **argv) { DryRun = Args.hasArg(OPT_dry_run); SaveTemps = Args.hasArg(OPT_save_temps); - const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ)); - IsAOTCompileNeeded = - (Triple.getSubArch() == llvm::Triple::SPIRSubArch_gen || - Triple.getSubArch() == llvm::Triple::SPIRSubArch_x86_64); + IsAOTCompileNeeded = Args.hasArg(OPT_arch); if (!Args.hasArg(OPT_o)) reportError(createStringError("Output file is not specified")); diff --git a/clang/tools/clang-sycl-linker/SYCLLinkOpts.td b/clang/tools/clang-sycl-linker/SYCLLinkOpts.td index 52544049f5988..6631fff085286 100644 --- a/clang/tools/clang-sycl-linker/SYCLLinkOpts.td +++ b/clang/tools/clang-sycl-linker/SYCLLinkOpts.td @@ -24,8 +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_EQ : Joined<["--"], "triple=">, - HelpText<"The device target triple">; def arch : Separate<["--", "-"], "arch">, HelpText<"Specify the name of the target architecture.">; From 57fd7e40023e8f265de94fa1ba8348a7b2c68eec Mon Sep 17 00:00:00 2001 From: "Cai, Justin" Date: Mon, 17 Mar 2025 14:44:00 +0000 Subject: [PATCH 4/7] Remove triple changes --- llvm/include/llvm/TargetParser/Triple.h | 6 - llvm/lib/TargetParser/Triple.cpp | 167 +++++++++++------------- 2 files changed, 77 insertions(+), 96 deletions(-) diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h index 6108638bad40d..0f39997abf6d0 100644 --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -869,12 +869,6 @@ class Triple { return getArch() == Triple::spir || getArch() == Triple::spir64; } - /// Tests whether the target is SPIR and AOT related. - bool isSPIRAOT() const { - return isSPIR() && (getSubArch() == Triple::SPIRSubArch_gen || - getSubArch() == Triple::SPIRSubArch_x86_64); - } - /// Tests whether the target is SPIR-V (32/64-bit/Logical). bool isSPIRV() const { return getArch() == Triple::spirv32 || getArch() == Triple::spirv64 || diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index 0aef18ff73cba..2d7d51347d6b9 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -555,86 +555,83 @@ static Triple::ArchType parseARMArch(StringRef ArchName) { } static Triple::ArchType parseArch(StringRef ArchName) { - auto AT = - StringSwitch(ArchName) - .Cases("i386", "i486", "i586", "i686", Triple::x86) - // FIXME: Do we need to support these? - .Cases("i786", "i886", "i986", Triple::x86) - .Cases("amd64", "x86_64", "x86_64h", Triple::x86_64) - .Cases("powerpc", "powerpcspe", "ppc", "ppc32", Triple::ppc) - .Cases("powerpcle", "ppcle", "ppc32le", Triple::ppcle) - .Cases("powerpc64", "ppu", "ppc64", Triple::ppc64) - .Cases("powerpc64le", "ppc64le", Triple::ppc64le) - .Case("xscale", Triple::arm) - .Case("xscaleeb", Triple::armeb) - .Case("aarch64", Triple::aarch64) - .Case("aarch64_be", Triple::aarch64_be) - .Case("aarch64_32", Triple::aarch64_32) - .Case("arc", Triple::arc) - .Case("arm64", Triple::aarch64) - .Case("arm64_32", Triple::aarch64_32) - .Case("arm64e", Triple::aarch64) - .Case("arm64ec", Triple::aarch64) - .Case("arm", Triple::arm) - .Case("armeb", Triple::armeb) - .Case("thumb", Triple::thumb) - .Case("thumbeb", Triple::thumbeb) - .Case("avr", Triple::avr) - .Case("m68k", Triple::m68k) - .Case("msp430", Triple::msp430) - .Cases("mips", "mipseb", "mipsallegrex", "mipsisa32r6", "mipsr6", - Triple::mips) - .Cases("mipsel", "mipsallegrexel", "mipsisa32r6el", "mipsr6el", - Triple::mipsel) - .Cases("mips64", "mips64eb", "mipsn32", "mipsisa64r6", "mips64r6", - "mipsn32r6", Triple::mips64) - .Cases("mips64el", "mipsn32el", "mipsisa64r6el", "mips64r6el", - "mipsn32r6el", Triple::mips64el) - .Case("r600", Triple::r600) - .Case("amdgcn", Triple::amdgcn) - .Case("riscv32", Triple::riscv32) - .Case("riscv64", Triple::riscv64) - .Case("hexagon", Triple::hexagon) - .Cases("s390x", "systemz", Triple::systemz) - .Case("sparc", Triple::sparc) - .Case("sparcel", Triple::sparcel) - .Cases("sparcv9", "sparc64", Triple::sparcv9) - .Case("tce", Triple::tce) - .Case("tcele", Triple::tcele) - .Case("xcore", Triple::xcore) - .Case("nvptx", Triple::nvptx) - .Case("nvptx64", Triple::nvptx64) - .Case("amdil", Triple::amdil) - .Case("amdil64", Triple::amdil64) - .Case("hsail", Triple::hsail) - .Case("hsail64", Triple::hsail64) - .Case("spir", Triple::spir) - .Case("spir64", Triple::spir64) - .Cases("spirv", "spirv1.5", "spirv1.6", Triple::spirv) - .Cases("spirv32", "spirv32v1.0", "spirv32v1.1", "spirv32v1.2", - "spirv32v1.3", "spirv32v1.4", "spirv32v1.5", - "spirv32v1.6", Triple::spirv32) - .Cases("spirv64", "spirv64v1.0", "spirv64v1.1", "spirv64v1.2", - "spirv64v1.3", "spirv64v1.4", "spirv64v1.5", - "spirv64v1.6", Triple::spirv64) - .StartsWith("spir64", Triple::spir64) - .StartsWith("spir", Triple::spir) - .StartsWith("kalimba", Triple::kalimba) - .Case("lanai", Triple::lanai) - .Case("renderscript32", Triple::renderscript32) - .Case("renderscript64", Triple::renderscript64) - .Case("shave", Triple::shave) - .Case("ve", Triple::ve) - .Case("wasm32", Triple::wasm32) - .Case("wasm64", Triple::wasm64) - .Case("csky", Triple::csky) - .Case("loongarch32", Triple::loongarch32) - .Case("loongarch64", Triple::loongarch64) - .Cases("dxil", "dxilv1.0", "dxilv1.1", "dxilv1.2", "dxilv1.3", - "dxilv1.4", "dxilv1.5", "dxilv1.6", "dxilv1.7", "dxilv1.8", - Triple::dxil) - .Case("xtensa", Triple::xtensa) - .Default(Triple::UnknownArch); + auto AT = StringSwitch(ArchName) + .Cases("i386", "i486", "i586", "i686", Triple::x86) + // FIXME: Do we need to support these? + .Cases("i786", "i886", "i986", Triple::x86) + .Cases("amd64", "x86_64", "x86_64h", Triple::x86_64) + .Cases("powerpc", "powerpcspe", "ppc", "ppc32", Triple::ppc) + .Cases("powerpcle", "ppcle", "ppc32le", Triple::ppcle) + .Cases("powerpc64", "ppu", "ppc64", Triple::ppc64) + .Cases("powerpc64le", "ppc64le", Triple::ppc64le) + .Case("xscale", Triple::arm) + .Case("xscaleeb", Triple::armeb) + .Case("aarch64", Triple::aarch64) + .Case("aarch64_be", Triple::aarch64_be) + .Case("aarch64_32", Triple::aarch64_32) + .Case("arc", Triple::arc) + .Case("arm64", Triple::aarch64) + .Case("arm64_32", Triple::aarch64_32) + .Case("arm64e", Triple::aarch64) + .Case("arm64ec", Triple::aarch64) + .Case("arm", Triple::arm) + .Case("armeb", Triple::armeb) + .Case("thumb", Triple::thumb) + .Case("thumbeb", Triple::thumbeb) + .Case("avr", Triple::avr) + .Case("m68k", Triple::m68k) + .Case("msp430", Triple::msp430) + .Cases("mips", "mipseb", "mipsallegrex", "mipsisa32r6", + "mipsr6", Triple::mips) + .Cases("mipsel", "mipsallegrexel", "mipsisa32r6el", "mipsr6el", + Triple::mipsel) + .Cases("mips64", "mips64eb", "mipsn32", "mipsisa64r6", + "mips64r6", "mipsn32r6", Triple::mips64) + .Cases("mips64el", "mipsn32el", "mipsisa64r6el", "mips64r6el", + "mipsn32r6el", Triple::mips64el) + .Case("r600", Triple::r600) + .Case("amdgcn", Triple::amdgcn) + .Case("riscv32", Triple::riscv32) + .Case("riscv64", Triple::riscv64) + .Case("hexagon", Triple::hexagon) + .Cases("s390x", "systemz", Triple::systemz) + .Case("sparc", Triple::sparc) + .Case("sparcel", Triple::sparcel) + .Cases("sparcv9", "sparc64", Triple::sparcv9) + .Case("tce", Triple::tce) + .Case("tcele", Triple::tcele) + .Case("xcore", Triple::xcore) + .Case("nvptx", Triple::nvptx) + .Case("nvptx64", Triple::nvptx64) + .Case("amdil", Triple::amdil) + .Case("amdil64", Triple::amdil64) + .Case("hsail", Triple::hsail) + .Case("hsail64", Triple::hsail64) + .Case("spir", Triple::spir) + .Case("spir64", Triple::spir64) + .Cases("spirv", "spirv1.5", "spirv1.6", Triple::spirv) + .Cases("spirv32", "spirv32v1.0", "spirv32v1.1", "spirv32v1.2", + "spirv32v1.3", "spirv32v1.4", "spirv32v1.5", + "spirv32v1.6", Triple::spirv32) + .Cases("spirv64", "spirv64v1.0", "spirv64v1.1", "spirv64v1.2", + "spirv64v1.3", "spirv64v1.4", "spirv64v1.5", + "spirv64v1.6", Triple::spirv64) + .StartsWith("kalimba", Triple::kalimba) + .Case("lanai", Triple::lanai) + .Case("renderscript32", Triple::renderscript32) + .Case("renderscript64", Triple::renderscript64) + .Case("shave", Triple::shave) + .Case("ve", Triple::ve) + .Case("wasm32", Triple::wasm32) + .Case("wasm64", Triple::wasm64) + .Case("csky", Triple::csky) + .Case("loongarch32", Triple::loongarch32) + .Case("loongarch64", Triple::loongarch64) + .Cases("dxil", "dxilv1.0", "dxilv1.1", "dxilv1.2", "dxilv1.3", + "dxilv1.4", "dxilv1.5", "dxilv1.6", "dxilv1.7", + "dxilv1.8", Triple::dxil) + .Case("xtensa", Triple::xtensa) + .Default(Triple::UnknownArch); // Some architectures require special parsing logic just to compute the // ArchType result. @@ -790,16 +787,6 @@ static Triple::SubArchType parseSubArch(StringRef SubArchName) { (SubArchName.ends_with("r6el") || SubArchName.ends_with("r6"))) return Triple::MipsSubArch_r6; - if (SubArchName.starts_with("spir")) { - StringRef SA(SubArchName); - if (SA.consume_front("spir64_") || SA.consume_front("spir_")) { - if (SA == "gen") - return Triple::SPIRSubArch_gen; - else if (SA == "x86_64") - return Triple::SPIRSubArch_x86_64; - } - } - if (SubArchName == "powerpcspe") return Triple::PPCSubArch_spe; From f50b9a8226fc6f4d28d4f3d6dce728b4a6d7c7a4 Mon Sep 17 00:00:00 2001 From: "Cai, Justin" Date: Mon, 17 Mar 2025 14:46:30 +0000 Subject: [PATCH 5/7] Remove triple changes 2 --- llvm/include/llvm/TargetParser/Triple.h | 3 - llvm/lib/TargetParser/Triple.cpp | 155 ++++++++++++------------ 2 files changed, 78 insertions(+), 80 deletions(-) diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h index 0f39997abf6d0..390ed7fbab8c0 100644 --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -176,9 +176,6 @@ class Triple { DXILSubArch_v1_7, DXILSubArch_v1_8, LatestDXILSubArch = DXILSubArch_v1_8, - - SPIRSubArch_gen, - SPIRSubArch_x86_64, }; enum VendorType { UnknownVendor, diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index 2d7d51347d6b9..e9e6f130f757c 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -555,83 +555,84 @@ static Triple::ArchType parseARMArch(StringRef ArchName) { } static Triple::ArchType parseArch(StringRef ArchName) { - auto AT = StringSwitch(ArchName) - .Cases("i386", "i486", "i586", "i686", Triple::x86) - // FIXME: Do we need to support these? - .Cases("i786", "i886", "i986", Triple::x86) - .Cases("amd64", "x86_64", "x86_64h", Triple::x86_64) - .Cases("powerpc", "powerpcspe", "ppc", "ppc32", Triple::ppc) - .Cases("powerpcle", "ppcle", "ppc32le", Triple::ppcle) - .Cases("powerpc64", "ppu", "ppc64", Triple::ppc64) - .Cases("powerpc64le", "ppc64le", Triple::ppc64le) - .Case("xscale", Triple::arm) - .Case("xscaleeb", Triple::armeb) - .Case("aarch64", Triple::aarch64) - .Case("aarch64_be", Triple::aarch64_be) - .Case("aarch64_32", Triple::aarch64_32) - .Case("arc", Triple::arc) - .Case("arm64", Triple::aarch64) - .Case("arm64_32", Triple::aarch64_32) - .Case("arm64e", Triple::aarch64) - .Case("arm64ec", Triple::aarch64) - .Case("arm", Triple::arm) - .Case("armeb", Triple::armeb) - .Case("thumb", Triple::thumb) - .Case("thumbeb", Triple::thumbeb) - .Case("avr", Triple::avr) - .Case("m68k", Triple::m68k) - .Case("msp430", Triple::msp430) - .Cases("mips", "mipseb", "mipsallegrex", "mipsisa32r6", - "mipsr6", Triple::mips) - .Cases("mipsel", "mipsallegrexel", "mipsisa32r6el", "mipsr6el", - Triple::mipsel) - .Cases("mips64", "mips64eb", "mipsn32", "mipsisa64r6", - "mips64r6", "mipsn32r6", Triple::mips64) - .Cases("mips64el", "mipsn32el", "mipsisa64r6el", "mips64r6el", - "mipsn32r6el", Triple::mips64el) - .Case("r600", Triple::r600) - .Case("amdgcn", Triple::amdgcn) - .Case("riscv32", Triple::riscv32) - .Case("riscv64", Triple::riscv64) - .Case("hexagon", Triple::hexagon) - .Cases("s390x", "systemz", Triple::systemz) - .Case("sparc", Triple::sparc) - .Case("sparcel", Triple::sparcel) - .Cases("sparcv9", "sparc64", Triple::sparcv9) - .Case("tce", Triple::tce) - .Case("tcele", Triple::tcele) - .Case("xcore", Triple::xcore) - .Case("nvptx", Triple::nvptx) - .Case("nvptx64", Triple::nvptx64) - .Case("amdil", Triple::amdil) - .Case("amdil64", Triple::amdil64) - .Case("hsail", Triple::hsail) - .Case("hsail64", Triple::hsail64) - .Case("spir", Triple::spir) - .Case("spir64", Triple::spir64) - .Cases("spirv", "spirv1.5", "spirv1.6", Triple::spirv) - .Cases("spirv32", "spirv32v1.0", "spirv32v1.1", "spirv32v1.2", - "spirv32v1.3", "spirv32v1.4", "spirv32v1.5", - "spirv32v1.6", Triple::spirv32) - .Cases("spirv64", "spirv64v1.0", "spirv64v1.1", "spirv64v1.2", - "spirv64v1.3", "spirv64v1.4", "spirv64v1.5", - "spirv64v1.6", Triple::spirv64) - .StartsWith("kalimba", Triple::kalimba) - .Case("lanai", Triple::lanai) - .Case("renderscript32", Triple::renderscript32) - .Case("renderscript64", Triple::renderscript64) - .Case("shave", Triple::shave) - .Case("ve", Triple::ve) - .Case("wasm32", Triple::wasm32) - .Case("wasm64", Triple::wasm64) - .Case("csky", Triple::csky) - .Case("loongarch32", Triple::loongarch32) - .Case("loongarch64", Triple::loongarch64) - .Cases("dxil", "dxilv1.0", "dxilv1.1", "dxilv1.2", "dxilv1.3", - "dxilv1.4", "dxilv1.5", "dxilv1.6", "dxilv1.7", - "dxilv1.8", Triple::dxil) - .Case("xtensa", Triple::xtensa) - .Default(Triple::UnknownArch); + auto AT = + StringSwitch(ArchName) + .Cases("i386", "i486", "i586", "i686", Triple::x86) + // FIXME: Do we need to support these? + .Cases("i786", "i886", "i986", Triple::x86) + .Cases("amd64", "x86_64", "x86_64h", Triple::x86_64) + .Cases("powerpc", "powerpcspe", "ppc", "ppc32", Triple::ppc) + .Cases("powerpcle", "ppcle", "ppc32le", Triple::ppcle) + .Cases("powerpc64", "ppu", "ppc64", Triple::ppc64) + .Cases("powerpc64le", "ppc64le", Triple::ppc64le) + .Case("xscale", Triple::arm) + .Case("xscaleeb", Triple::armeb) + .Case("aarch64", Triple::aarch64) + .Case("aarch64_be", Triple::aarch64_be) + .Case("aarch64_32", Triple::aarch64_32) + .Case("arc", Triple::arc) + .Case("arm64", Triple::aarch64) + .Case("arm64_32", Triple::aarch64_32) + .Case("arm64e", Triple::aarch64) + .Case("arm64ec", Triple::aarch64) + .Case("arm", Triple::arm) + .Case("armeb", Triple::armeb) + .Case("thumb", Triple::thumb) + .Case("thumbeb", Triple::thumbeb) + .Case("avr", Triple::avr) + .Case("m68k", Triple::m68k) + .Case("msp430", Triple::msp430) + .Cases("mips", "mipseb", "mipsallegrex", "mipsisa32r6", "mipsr6", + Triple::mips) + .Cases("mipsel", "mipsallegrexel", "mipsisa32r6el", "mipsr6el", + Triple::mipsel) + .Cases("mips64", "mips64eb", "mipsn32", "mipsisa64r6", "mips64r6", + "mipsn32r6", Triple::mips64) + .Cases("mips64el", "mipsn32el", "mipsisa64r6el", "mips64r6el", + "mipsn32r6el", Triple::mips64el) + .Case("r600", Triple::r600) + .Case("amdgcn", Triple::amdgcn) + .Case("riscv32", Triple::riscv32) + .Case("riscv64", Triple::riscv64) + .Case("hexagon", Triple::hexagon) + .Cases("s390x", "systemz", Triple::systemz) + .Case("sparc", Triple::sparc) + .Case("sparcel", Triple::sparcel) + .Cases("sparcv9", "sparc64", Triple::sparcv9) + .Case("tce", Triple::tce) + .Case("tcele", Triple::tcele) + .Case("xcore", Triple::xcore) + .Case("nvptx", Triple::nvptx) + .Case("nvptx64", Triple::nvptx64) + .Case("amdil", Triple::amdil) + .Case("amdil64", Triple::amdil64) + .Case("hsail", Triple::hsail) + .Case("hsail64", Triple::hsail64) + .Case("spir", Triple::spir) + .Case("spir64", Triple::spir64) + .Cases("spirv", "spirv1.5", "spirv1.6", Triple::spirv) + .Cases("spirv32", "spirv32v1.0", "spirv32v1.1", "spirv32v1.2", + "spirv32v1.3", "spirv32v1.4", "spirv32v1.5", + "spirv32v1.6", Triple::spirv32) + .Cases("spirv64", "spirv64v1.0", "spirv64v1.1", "spirv64v1.2", + "spirv64v1.3", "spirv64v1.4", "spirv64v1.5", + "spirv64v1.6", Triple::spirv64) + .StartsWith("kalimba", Triple::kalimba) + .Case("lanai", Triple::lanai) + .Case("renderscript32", Triple::renderscript32) + .Case("renderscript64", Triple::renderscript64) + .Case("shave", Triple::shave) + .Case("ve", Triple::ve) + .Case("wasm32", Triple::wasm32) + .Case("wasm64", Triple::wasm64) + .Case("csky", Triple::csky) + .Case("loongarch32", Triple::loongarch32) + .Case("loongarch64", Triple::loongarch64) + .Cases("dxil", "dxilv1.0", "dxilv1.1", "dxilv1.2", "dxilv1.3", + "dxilv1.4", "dxilv1.5", "dxilv1.6", "dxilv1.7", "dxilv1.8", + Triple::dxil) + .Case("xtensa", Triple::xtensa) + .Default(Triple::UnknownArch); // Some architectures require special parsing logic just to compute the // ArchType result. From b3a03ef82c05f4b9a88ce0870ce9a73c3d854650 Mon Sep 17 00:00:00 2001 From: "Cai, Justin" Date: Wed, 19 Mar 2025 15:35:49 +0000 Subject: [PATCH 6/7] Update options --- clang/test/Driver/clang-sycl-linker-test.cpp | 12 +++----- .../clang-sycl-linker/ClangSYCLLinker.cpp | 28 ++++--------------- clang/tools/clang-sycl-linker/SYCLLinkOpts.td | 17 +++-------- 3 files changed, 13 insertions(+), 44 deletions(-) diff --git a/clang/test/Driver/clang-sycl-linker-test.cpp b/clang/test/Driver/clang-sycl-linker-test.cpp index 91c306663bdca..d341f069043d8 100644 --- a/clang/test/Driver/clang-sycl-linker-test.cpp +++ b/clang/test/Driver/clang-sycl-linker-test.cpp @@ -44,13 +44,11 @@ // AOT-INTEL-GPU-NEXT: "{{.*}}ocloc{{.*}}" {{.*}}-device pvc {{.*}}-output a.out -file [[SPIRVTRANSLATIONOUT]] // // RUN: clang-sycl-linker --dry-run -arch pvc %t_1.bc %t_2.bc -o a.out 2>&1 \ -// RUN: --sycl-backend-compile-options-from-image=-a \ -// RUN: --sycl-backend-link-options-from-image=-b \ -// RUN: --gpu-tool-arg=-c \ +// RUN: --ocloc-options="-a -b" \ // RUN: | FileCheck %s --check-prefix=AOT-INTEL-GPU-2 // AOT-INTEL-GPU-2: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[LLVMLINKOUT:.*]].bc --suppress-warnings // AOT-INTEL-GPU-2-NEXT: "{{.*}}llvm-spirv{{.*}}" {{.*}}-o [[SPIRVTRANSLATIONOUT:.*]] [[LLVMLINKOUT]].bc -// AOT-INTEL-GPU-2-NEXT: "{{.*}}ocloc{{.*}}" {{.*}}-device pvc -a -b -c {{.*}}-output a.out -file [[SPIRVTRANSLATIONOUT]] +// AOT-INTEL-GPU-2-NEXT: "{{.*}}ocloc{{.*}}" {{.*}}-device pvc -a -b {{.*}}-output a.out -file [[SPIRVTRANSLATIONOUT]] // // RUN: clang-sycl-linker --dry-run -arch corei7 %t_1.bc %t_2.bc -o a.out 2>&1 \ // RUN: | FileCheck %s --check-prefix=AOT-INTEL-CPU @@ -59,13 +57,11 @@ // AOT-INTEL-CPU-NEXT: "{{.*}}opencl-aot{{.*}}" {{.*}}--device=cpu {{.*}}-o a.out [[SPIRVTRANSLATIONOUT]] // // RUN: clang-sycl-linker --dry-run -arch corei7 %t_1.bc %t_2.bc -o a.out 2>&1 \ -// RUN: --sycl-backend-compile-options-from-image=-a \ -// RUN: --sycl-backend-link-options-from-image=-b \ -// RUN: --cpu-tool-arg=-c \ +// RUN: --opencl-aot-options="-a -b" \ // RUN: | FileCheck %s --check-prefix=AOT-INTEL-CPU-2 // AOT-INTEL-CPU-2: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[LLVMLINKOUT:.*]].bc --suppress-warnings // AOT-INTEL-CPU-2-NEXT: "{{.*}}llvm-spirv{{.*}}" {{.*}}-o [[SPIRVTRANSLATIONOUT:.*]] [[LLVMLINKOUT]].bc -// AOT-INTEL-CPU-2-NEXT: "{{.*}}opencl-aot{{.*}}" {{.*}}--device=cpu -a -b -c {{.*}}-o a.out [[SPIRVTRANSLATIONOUT]] +// AOT-INTEL-CPU-2-NEXT: "{{.*}}opencl-aot{{.*}}" {{.*}}--device=cpu -a -b {{.*}}-o a.out [[SPIRVTRANSLATIONOUT]] // // RUN: not clang-sycl-linker --dry-run %t_1.bc %t_2.bc 2>& 1 \ // RUN: | FileCheck %s --check-prefix=NOOUTPUT diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index 4fa68e0c5bafd..6c8f25108e03d 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -366,27 +366,6 @@ static Expected runLLVMToSPIRVTranslation(StringRef File, return *OutFileOrErr; } -/// Adds all AOT backend options required for SYCL AOT compilation step to -/// 'CmdArgs'. -/// 'Args' encompasses all arguments required for linking and wrapping device -/// code and will be parsed to generate backend options required to be passed -/// into the SYCL AOT compilation step. -/// IsCPU is a bool used to direct option generation. If IsCPU is false, then -/// options are generated for AOT compilation targeting Intel GPUs. -static void addBackendOptions(const ArgList &Args, - SmallVector &CmdArgs, bool IsCPU) { - StringRef OptC = - Args.getLastArgValue(OPT_sycl_backend_compile_options_from_image_EQ); - OptC.split(CmdArgs, " ", /*MaxSplit=*/-1, /*KeepEmpty=*/false); - StringRef OptL = - Args.getLastArgValue(OPT_sycl_backend_link_options_from_image_EQ); - OptL.split(CmdArgs, " ", /*MaxSplit=*/-1, /*KeepEmpty=*/false); - StringRef OptTool = (IsCPU) ? Args.getLastArgValue(OPT_cpu_tool_arg_EQ) - : Args.getLastArgValue(OPT_gpu_tool_arg_EQ); - OptTool.split(CmdArgs, " ", /*MaxSplit=*/-1, /*KeepEmpty=*/false); - return; -} - /// Run AOT compilation for Intel CPU. /// Calls opencl-aot tool to generate device code for Intel CPU backend. /// 'InputFile' is the input SPIR-V file. @@ -402,7 +381,8 @@ static Error runAOTCompileIntelCPU(StringRef InputFile, const ArgList &Args) { CmdArgs.push_back(*OpenCLAOTPath); CmdArgs.push_back("--device=cpu"); - addBackendOptions(Args, CmdArgs, /* IsCPU */ true); + StringRef ExtraArgs = Args.getLastArgValue(OPT_opencl_aot_options_EQ); + ExtraArgs.split(CmdArgs, " ", /*MaxSplit=*/-1, /*KeepEmpty=*/false); CmdArgs.push_back("-o"); CmdArgs.push_back(OutputFile); CmdArgs.push_back(InputFile); @@ -434,7 +414,9 @@ static Error runAOTCompileIntelGPU(StringRef InputFile, const ArgList &Args) { CmdArgs.push_back("-device"); CmdArgs.push_back(Arch); - addBackendOptions(Args, CmdArgs, /* IsCPU */ false); + StringRef ExtraArgs = Args.getLastArgValue(OPT_ocloc_options_EQ); + ExtraArgs.split(CmdArgs, " ", /*MaxSplit=*/-1, /*KeepEmpty=*/false); + CmdArgs.push_back("-output"); CmdArgs.push_back(OutputFile); CmdArgs.push_back("-file"); diff --git a/clang/tools/clang-sycl-linker/SYCLLinkOpts.td b/clang/tools/clang-sycl-linker/SYCLLinkOpts.td index 6631fff085286..4521ab17bef9e 100644 --- a/clang/tools/clang-sycl-linker/SYCLLinkOpts.td +++ b/clang/tools/clang-sycl-linker/SYCLLinkOpts.td @@ -49,19 +49,10 @@ def llvm_spirv_options_EQ : Joined<["--", "-"], "llvm-spirv-options=">, Flags<[LinkerOnlyOption]>, HelpText<"Options that will control llvm-spirv step">; -def sycl_backend_compile_options_from_image_EQ : Joined<["--", "-"], "sycl-backend-compile-options-from-image=">, +def ocloc_options_EQ : Joined<["--", "-"], "ocloc-options=">, Flags<[LinkerOnlyOption]>, - HelpText<"Compile options that will be transmitted to the SYCL backend compiler">; + HelpText<"Options passed to ocloc for Intel GPU AOT compilation">; -def sycl_backend_link_options_from_image_EQ : Joined<["--", "-"], "sycl-backend-link-options-from-image=">, +def opencl_aot_options_EQ : Joined<["--", "-"], "opencl-aot-options=">, Flags<[LinkerOnlyOption]>, - HelpText<"Link options that will be transmitted to the SYCL backend compiler">; - -def gpu_tool_arg_EQ : - Joined<["--", "-"], "gpu-tool-arg=">, - Flags<[LinkerOnlyOption]>, - HelpText<"Options that are passed to the backend of target device compiler for Intel GPU during AOT compilation">; -def cpu_tool_arg_EQ : - Joined<["--", "-"], "cpu-tool-arg=">, - Flags<[LinkerOnlyOption]>, - HelpText<"Options that are passed to the backend of target device compiler for Intel CPU during AOT compilation">; + HelpText<"Options passed to opencl-aot for CPU AOT compilation">; From c4e9f0f232b82e510d46ca098c2bf62d435f7335 Mon Sep 17 00:00:00 2001 From: "Cai, Justin" Date: Mon, 24 Mar 2025 07:41:21 -0700 Subject: [PATCH 7/7] Add comments in tests --- clang/test/Driver/clang-sycl-linker-test.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clang/test/Driver/clang-sycl-linker-test.cpp b/clang/test/Driver/clang-sycl-linker-test.cpp index d341f069043d8..c4bb7febdc1df 100644 --- a/clang/test/Driver/clang-sycl-linker-test.cpp +++ b/clang/test/Driver/clang-sycl-linker-test.cpp @@ -37,12 +37,14 @@ // RUN: | FileCheck %s --check-prefix=DEVLIBSERR2 // DEVLIBSERR2: '{{.*}}lib3.bc' SYCL device library file is not found // +// Test AOT compilation for an Intel GPU. // RUN: clang-sycl-linker --dry-run -arch pvc %t_1.bc %t_2.bc -o a.out 2>&1 \ // RUN: | FileCheck %s --check-prefix=AOT-INTEL-GPU // AOT-INTEL-GPU: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[LLVMLINKOUT:.*]].bc --suppress-warnings // AOT-INTEL-GPU-NEXT: "{{.*}}llvm-spirv{{.*}}" {{.*}}-o [[SPIRVTRANSLATIONOUT:.*]] [[LLVMLINKOUT]].bc // AOT-INTEL-GPU-NEXT: "{{.*}}ocloc{{.*}}" {{.*}}-device pvc {{.*}}-output a.out -file [[SPIRVTRANSLATIONOUT]] // +// Test AOT compilation for an Intel GPU with additional options. // RUN: clang-sycl-linker --dry-run -arch pvc %t_1.bc %t_2.bc -o a.out 2>&1 \ // RUN: --ocloc-options="-a -b" \ // RUN: | FileCheck %s --check-prefix=AOT-INTEL-GPU-2 @@ -50,12 +52,14 @@ // AOT-INTEL-GPU-2-NEXT: "{{.*}}llvm-spirv{{.*}}" {{.*}}-o [[SPIRVTRANSLATIONOUT:.*]] [[LLVMLINKOUT]].bc // AOT-INTEL-GPU-2-NEXT: "{{.*}}ocloc{{.*}}" {{.*}}-device pvc -a -b {{.*}}-output a.out -file [[SPIRVTRANSLATIONOUT]] // +// Test AOT compilation for an Intel CPU. // RUN: clang-sycl-linker --dry-run -arch corei7 %t_1.bc %t_2.bc -o a.out 2>&1 \ // RUN: | FileCheck %s --check-prefix=AOT-INTEL-CPU // AOT-INTEL-CPU: "{{.*}}llvm-link{{.*}}" {{.*}}.bc {{.*}}.bc -o [[LLVMLINKOUT:.*]].bc --suppress-warnings // AOT-INTEL-CPU-NEXT: "{{.*}}llvm-spirv{{.*}}" {{.*}}-o [[SPIRVTRANSLATIONOUT:.*]] [[LLVMLINKOUT]].bc // AOT-INTEL-CPU-NEXT: "{{.*}}opencl-aot{{.*}}" {{.*}}--device=cpu {{.*}}-o a.out [[SPIRVTRANSLATIONOUT]] // +// Test AOT compilation for an Intel CPU with additional options. // RUN: clang-sycl-linker --dry-run -arch corei7 %t_1.bc %t_2.bc -o a.out 2>&1 \ // RUN: --opencl-aot-options="-a -b" \ // RUN: | FileCheck %s --check-prefix=AOT-INTEL-CPU-2 @@ -63,6 +67,7 @@ // AOT-INTEL-CPU-2-NEXT: "{{.*}}llvm-spirv{{.*}}" {{.*}}-o [[SPIRVTRANSLATIONOUT:.*]] [[LLVMLINKOUT]].bc // AOT-INTEL-CPU-2-NEXT: "{{.*}}opencl-aot{{.*}}" {{.*}}--device=cpu -a -b {{.*}}-o a.out [[SPIRVTRANSLATIONOUT]] // +// Check that the output file must be specified. // RUN: not clang-sycl-linker --dry-run %t_1.bc %t_2.bc 2>& 1 \ // RUN: | FileCheck %s --check-prefix=NOOUTPUT // NOOUTPUT: Output file is not specified