Skip to content

[SYCL] Add support AOT compilation for Intel GPUs in clang-sycl-linker #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 38 additions & 8 deletions clang/test/Driver/clang-sycl-linker-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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]]
130 changes: 125 additions & 5 deletions clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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';
}
Expand Down Expand Up @@ -385,14 +387,22 @@ static Expected<StringRef> runLLVMToSPIRVTranslation(StringRef File,

SmallVector<StringRef, 8> 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<StringRef> 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);
Expand All @@ -406,7 +416,7 @@ static Expected<StringRef> 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);
Expand All @@ -419,9 +429,108 @@ static Expected<StringRef> 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<StringRef, 8> &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<StringRef> runAOTCompileIntelCPU(StringRef InputFile,
const ArgList &Args) {
const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ));
SmallVector<StringRef, 8> CmdArgs;
Expected<std::string> 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<StringRef> runAOTCompileIntelGPU(StringRef InputFile,
const ArgList &Args) {
const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ));
StringRef Arch(Args.getLastArgValue(OPT_arch));
SmallVector<StringRef, 8> CmdArgs;
Expected<std::string> 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<StringRef> 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<std::string> Files, const ArgList &Args) {
llvm::TimeTraceScope TimeScope("SYCLDeviceLink");
// First llvm-link step
Expand All @@ -437,7 +546,13 @@ Error runSYCLLink(ArrayRef<std::string> Files, const ArgList &Args) {
// LLVM to SPIR-V translation step
auto SPVFile = runLLVMToSPIRVTranslation(*DeviceLinkedFile, Args);
if (!SPVFile)
return SPVFile.takeError();
reportError(SPVFile.takeError());

Expected<StringRef> AOTFile =
(IsAOTCompileNeeded) ? runAOTCompile(*SPVFile, Args) : *SPVFile;
if (!AOTFile)
return AOTFile.takeError();

return Error::success();
}

Expand Down Expand Up @@ -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);

Expand Down
19 changes: 18 additions & 1 deletion clang/tools/clang-sycl-linker/SYCLLinkOpts.td
Original file line number Diff line number Diff line change
Expand Up @@ -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.">;
Expand All @@ -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">;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Let's drop SYCL from these options. The tool is called clang-sycl-linker. The name implies that it works only with SYCL compilation flow*.
  2. Please, extend the help text to cover the meaning of "from-image" part.

* - @sarnex, this statement might be controversial if OpenMP offload is going to use this tool as well.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah at some point we will have to use this for OpenMP offloading as well


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">;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SYCL support non-Intel GPUs as well. Can this option be used to pass options to CUDA/HIP device compilers?

Copy link
Owner Author

@jzc jzc Mar 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CUDA/HIP step is not implemented but in theory this could easily pass to those device compilers. I took all these flags from the intel/llvm version of clang-linker-wrapper as is. However, to me, I don't see why gpu_tool_arg_EQ, cpu_tool_arg_EQ, OPT_sycl_backend_compile_options_from_image_EQ, and OPT_sycl_backend_link_options_from_image_EQ all need to be separate anyways; they are all used in the same way: just passing arguments down to the device compiler. Should we unify this flag into one? @asudarsa

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be we can call this gen-tool-arg?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gpu_tool_arg_EQ and cpu_tool_arg_EQ are options that are passed into clang-linker-wrapper by the driver based on command line options specified by user. OPT_sycl_backend_compile_options_from_image_EQ, and OPT_sycl_backend_link_options_from_image_EQ are options that are populated inside clang-linker-wrapper based on what is present inside the device image (in StringMap).
We will need these to be supported inside clang-sycl-linker in a similar fashion.

Thanks

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gpu_tool_arg_EQ and cpu_tool_arg_EQ are options that are passed into clang-linker-wrapper by the driver based on command line options specified by user. OPT_sycl_backend_compile_options_from_image_EQ, and OPT_sycl_backend_link_options_from_image_EQ are options that are populated inside clang-linker-wrapper based on what is present inside the device image (in StringMap). We will need these to be supported inside clang-sycl-linker in a similar fashion.

Thanks

@asudarsa, could you provide an example of commands leading to setting ocloc options via both the driver and device image metadata, please?

If it possible to set ocloc options through both options at the time, clang-linker-wrapper should merge options passed by the driver and extracted from the device code metadata to pass one set to the linker tool.

OPT_sycl_backend_compile_options_from_image_EQ and gpu_tool_arg_EQ are setting options for the same tool - ocloc. Having two separate options for that doesn't make much sense to me.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @bader

Here is the use case
`
clang++ -fsycl --offload-arch=pvc -Xsycl-target-backend -c1-opt --offload-new-driver test-sycl.cpp -c
(populates device image metadata)
AND
clang++ -fsycl --offload-arch=pvc -Xsycl-target-backend -c2-opt --offload-new-driver test-sycl.o
(Options from driver)

About combining the options, there is a problem. In the latest community version of clang-linker-wrapper, the input files are sent as is to clang driver for purpose of device code linking. So, we do not read the device image. Also, if multiple inputs are to be linked, then we might have different set of options in each device image metadata.

After I wrote this, I see another issue. If module 1 has '-opt1' backend option embedded in its metadata and module 2 has '-opt2' backend option, then we should not 'link' these two modules.

This needs further thought. Adding @mdtoguchi also for discussion here.

Thanks

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About combining the options, there is a problem. In the latest community version of clang-linker-wrapper, the input files are sent as is to clang driver for purpose of device code linking.

In this case, I think clang driver is expected to combine the flags. Anyway, whichever tool extracts device "code" from the device "image" should merge the flags from device image metadata to the flags passed via command line option.

I would expose tool specific flags in the clang-sycl-linker interface for clarity similar to -llvm-spirv-options=. E.g. --ocloc-options=.

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">;
9 changes: 9 additions & 0 deletions llvm/include/llvm/TargetParser/Triple.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ class Triple {
DXILSubArch_v1_7,
DXILSubArch_v1_8,
LatestDXILSubArch = DXILSubArch_v1_8,

SPIRSubArch_gen,
SPIRSubArch_x86_64,
};
enum VendorType {
UnknownVendor,
Expand Down Expand Up @@ -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 ||
Expand Down
12 changes: 12 additions & 0 deletions llvm/lib/TargetParser/Triple.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;

Expand Down