diff --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst
new file mode 100644
--- /dev/null
+++ b/llvm/docs/SPIRVUsage.rst
@@ -0,0 +1,73 @@
+=============================
+User Guide for SPIR-V Target
+=============================
+
+.. contents::
+ :local:
+
+.. toctree::
+ :hidden:
+
+Introduction
+============
+
+The SPIR-V target provides code generation for the SPIR-V binary format described
+in `the official SPIR-V specification `_.
+
+.. _spirv-target-triples:
+
+Target Triples
+==============
+
+For cross-compilation into SPIR-V use option
+
+``-target ---``
+
+to specify the target triple:
+
+ .. table:: SPIR-V Architectures
+
+ ============ ==============================================================
+ Architecture Description
+ ============ ==============================================================
+ ``spirv32`` SPIR-V with 32-bit pointer width.
+ ``spirv64`` SPIR-V with 64-bit pointer width.
+ ============ ==============================================================
+
+ .. table:: SPIR-V Subarchitectures
+
+ ============ ==============================================================
+ Architecture Description
+ ============ ==============================================================
+ ** SPIR-V version deduced by tools based on the compiled input.
+ ``v1.0`` SPIR-V version 1.0.
+ ``v1.1`` SPIR-V version 1.1.
+ ``v1.2`` SPIR-V version 1.2.
+ ``v1.3`` SPIR-V version 1.3.
+ ``v1.4`` SPIR-V version 1.4.
+ ``v1.5`` SPIR-V version 1.5.
+ ============ ==============================================================
+
+ .. table:: SPIR-V Vendors
+
+ ===================== ==============================================================
+ Vendor Description
+ ===================== ==============================================================
+ **/``unknown`` Generic SPIR-V target without any vendor-specific settings.
+ ===================== ==============================================================
+
+ .. table:: Operating Systems
+
+ ===================== ============================================================
+ OS Description
+ ===================== ============================================================
+ **/``unknown`` Defaults to the OpenCL runtime.
+ ===================== ============================================================
+
+ .. table:: SPIR-V Environments
+
+ ===================== ==============================================================
+ Environment Description
+ ===================== ==============================================================
+ **/``unknown`` Defaults to the OpenCL environment.
+ ===================== ==============================================================
diff --git a/llvm/docs/UserGuides.rst b/llvm/docs/UserGuides.rst
--- a/llvm/docs/UserGuides.rst
+++ b/llvm/docs/UserGuides.rst
@@ -57,6 +57,7 @@
ResponseGuide
Remarks
SourceLevelDebugging
+ SPIRVUsage
StackSafetyAnalysis
SupportLibrary
TableGen/index
@@ -243,3 +244,6 @@
This document describes a DWARF extension to allow location descriptions on
the DWARF expression stack. It is part of
:doc:`AMDGPUDwarfExtensionsForHeterogeneousDebugging`.
+
+:doc:`SPIRVUsage`
+ This document describes using the SPIR-V target to compile GPU kernels.
diff --git a/llvm/include/llvm/ADT/Triple.h b/llvm/include/llvm/ADT/Triple.h
--- a/llvm/include/llvm/ADT/Triple.h
+++ b/llvm/include/llvm/ADT/Triple.h
@@ -149,7 +149,15 @@
MipsSubArch_r6,
- PPCSubArch_spe
+ PPCSubArch_spe,
+
+ // SPIR-V sub-arch corresponds to its version.
+ SPIRVSubArch_v10,
+ SPIRVSubArch_v11,
+ SPIRVSubArch_v12,
+ SPIRVSubArch_v13,
+ SPIRVSubArch_v14,
+ SPIRVSubArch_v15,
};
enum VendorType {
UnknownVendor,
diff --git a/llvm/lib/Support/Triple.cpp b/llvm/lib/Support/Triple.cpp
--- a/llvm/lib/Support/Triple.cpp
+++ b/llvm/lib/Support/Triple.cpp
@@ -495,8 +495,10 @@
.Case("hsail64", Triple::hsail64)
.Case("spir", Triple::spir)
.Case("spir64", Triple::spir64)
- .Case("spirv32", Triple::spirv32)
- .Case("spirv64", Triple::spirv64)
+ .Cases("spirv32", "spirv32v1.0", "spirv32v1.1", "spirv32v1.2",
+ "spirv32v1.3", "spirv32v1.4", "spirv32v1.5", Triple::spirv32)
+ .Cases("spirv64", "spirv64v1.0", "spirv64v1.1", "spirv64v1.2",
+ "spirv64v1.3", "spirv64v1.4", "spirv64v1.5", Triple::spirv64)
.StartsWith("kalimba", Triple::kalimba)
.Case("lanai", Triple::lanai)
.Case("renderscript32", Triple::renderscript32)
@@ -654,6 +656,16 @@
if (SubArchName == "arm64e")
return Triple::AArch64SubArch_arm64e;
+ if (SubArchName.startswith("spirv"))
+ return StringSwitch(SubArchName)
+ .EndsWith("v1.0", Triple::SPIRVSubArch_v10)
+ .EndsWith("v1.1", Triple::SPIRVSubArch_v11)
+ .EndsWith("v1.2", Triple::SPIRVSubArch_v12)
+ .EndsWith("v1.3", Triple::SPIRVSubArch_v13)
+ .EndsWith("v1.4", Triple::SPIRVSubArch_v14)
+ .EndsWith("v1.5", Triple::SPIRVSubArch_v15)
+ .Default(Triple::NoSubArch);
+
StringRef ARMSubArch = ARM::getCanonicalArchName(SubArchName);
// For now, this is the small part. Early return.
@@ -1511,7 +1523,9 @@
case Triple::riscv64: T.setArch(Triple::riscv32); break;
case Triple::sparcv9: T.setArch(Triple::sparc); break;
case Triple::spir64: T.setArch(Triple::spir); break;
- case Triple::spirv64: T.setArch(Triple::spirv32); break;
+ case Triple::spirv64:
+ T.setArch(Triple::spirv32, getSubArch());
+ break;
case Triple::wasm64: T.setArch(Triple::wasm32); break;
case Triple::x86_64: T.setArch(Triple::x86); break;
}
@@ -1586,7 +1600,9 @@
case Triple::riscv32: T.setArch(Triple::riscv64); break;
case Triple::sparc: T.setArch(Triple::sparcv9); break;
case Triple::spir: T.setArch(Triple::spir64); break;
- case Triple::spirv32: T.setArch(Triple::spirv64); break;
+ case Triple::spirv32:
+ T.setArch(Triple::spirv64, getSubArch());
+ break;
case Triple::thumb: T.setArch(Triple::aarch64); break;
case Triple::thumbeb: T.setArch(Triple::aarch64_be); break;
case Triple::wasm32: T.setArch(Triple::wasm64); break;
diff --git a/llvm/unittests/ADT/TripleTest.cpp b/llvm/unittests/ADT/TripleTest.cpp
--- a/llvm/unittests/ADT/TripleTest.cpp
+++ b/llvm/unittests/ADT/TripleTest.cpp
@@ -243,11 +243,85 @@
T = Triple("spirv32-unknown-unknown");
EXPECT_EQ(Triple::spirv32, T.getArch());
+ EXPECT_EQ(Triple::NoSubArch, T.getSubArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+
+ T = Triple("spirv32v1.0-unknown-unknown");
+ EXPECT_EQ(Triple::spirv32, T.getArch());
+ EXPECT_EQ(Triple::SPIRVSubArch_v10, T.getSubArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+
+ T = Triple("spirv32v1.1-unknown-unknown");
+ EXPECT_EQ(Triple::spirv32, T.getArch());
+ EXPECT_EQ(Triple::SPIRVSubArch_v11, T.getSubArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+
+ T = Triple("spirv32v1.2-unknown-unknown");
+ EXPECT_EQ(Triple::spirv32, T.getArch());
+ EXPECT_EQ(Triple::SPIRVSubArch_v12, T.getSubArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+
+ T = Triple("spirv32v1.3-unknown-unknown");
+ EXPECT_EQ(Triple::spirv32, T.getArch());
+ EXPECT_EQ(Triple::SPIRVSubArch_v13, T.getSubArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+
+ T = Triple("spirv32v1.4-unknown-unknown");
+ EXPECT_EQ(Triple::spirv32, T.getArch());
+ EXPECT_EQ(Triple::SPIRVSubArch_v14, T.getSubArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+
+ T = Triple("spirv32v1.5-unknown-unknown");
+ EXPECT_EQ(Triple::spirv32, T.getArch());
+ EXPECT_EQ(Triple::SPIRVSubArch_v15, T.getSubArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::UnknownOS, T.getOS());
T = Triple("spirv64-unknown-unknown");
EXPECT_EQ(Triple::spirv64, T.getArch());
+ EXPECT_EQ(Triple::NoSubArch, T.getSubArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+
+ T = Triple("spirv64v1.0-unknown-unknown");
+ EXPECT_EQ(Triple::spirv64, T.getArch());
+ EXPECT_EQ(Triple::SPIRVSubArch_v10, T.getSubArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+
+ T = Triple("spirv64v1.1-unknown-unknown");
+ EXPECT_EQ(Triple::spirv64, T.getArch());
+ EXPECT_EQ(Triple::SPIRVSubArch_v11, T.getSubArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+
+ T = Triple("spirv64v1.2-unknown-unknown");
+ EXPECT_EQ(Triple::spirv64, T.getArch());
+ EXPECT_EQ(Triple::SPIRVSubArch_v12, T.getSubArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+
+ T = Triple("spirv64v1.3-unknown-unknown");
+ EXPECT_EQ(Triple::spirv64, T.getArch());
+ EXPECT_EQ(Triple::SPIRVSubArch_v13, T.getSubArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+
+ T = Triple("spirv64v1.4-unknown-unknown");
+ EXPECT_EQ(Triple::spirv64, T.getArch());
+ EXPECT_EQ(Triple::SPIRVSubArch_v14, T.getSubArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+
+ T = Triple("spirv64v1.5-unknown-unknown");
+ EXPECT_EQ(Triple::spirv64, T.getArch());
+ EXPECT_EQ(Triple::SPIRVSubArch_v15, T.getSubArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::UnknownOS, T.getOS());