Skip to content

Commit 95bba24

Browse files
Introduce support of the LLVM SPIR-V Backend to translate LLVM IR to SPIR-V (#3229)
This PR is to introduce support of the LLVM SPIR-V Backend to translate LLVM IR to SPIR-V. The backend will be preferred over Khronos Translator only when both conditions are satisfied: * the SPIR-V Backend is present in the deployment of LLVM, * there is an environmental variable `TRITON_USE_SPIRV_BACKEND` present and set to a non-zero integer value. Khronos Translator remains the default tool to translate LLVM IR to SPIR-V.
1 parent 7784cf0 commit 95bba24

File tree

3 files changed

+120
-10
lines changed

3 files changed

+120
-10
lines changed

scripts/compile-triton.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ build_llvm() {
138138
-DCMAKE_BUILD_TYPE=Release \
139139
-DLLVM_ENABLE_ASSERTIONS=true \
140140
-DLLVM_ENABLE_PROJECTS="mlir" \
141-
-DLLVM_TARGETS_TO_BUILD="X86;NVPTX;AMDGPU" \
141+
-DLLVM_TARGETS_TO_BUILD="X86;NVPTX;AMDGPU;SPIRV" \
142142
-DLLVM_INSTALL_UTILS=true \
143143
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
144144
-DCMAKE_INSTALL_PREFIX=$PACKAGES_DIR/llvm \

third_party/intel/lib/Target/SPIRV/CMakeLists.txt

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,38 @@
11
# SPIRV-LLVM-Translator is required.
22
find_package(SPIRVToLLVMTranslator)
33

4-
add_mlir_translation_library(TritonSPIRV
5-
SPIRVTranslation.cpp
4+
# Check if there is the LLVM SPIR-V backend.
5+
is_llvm_target_library("SPIRV" spirv_present_result INCLUDED_TARGETS)
66

7-
LINK_COMPONENTS
8-
Core
7+
if(spirv_present_result)
8+
message(STATUS "Found SPIR-V Backend")
9+
add_compile_definitions(LLVM_SPIRV_BACKEND_TARGET_PRESENT)
10+
add_mlir_translation_library(TritonSPIRV
11+
SPIRVTranslation.cpp
912

10-
LINK_LIBS PUBLIC
11-
TritonLLVMIR
12-
# spirv tools
13-
LLVMSPIRVLib
14-
)
13+
LINK_COMPONENTS
14+
Core
15+
# spirv backend
16+
SPIRVCodeGen
17+
18+
LINK_LIBS PUBLIC
19+
TritonLLVMIR
20+
# spirv tools
21+
LLVMSPIRVLib
22+
)
23+
else()
24+
add_mlir_translation_library(TritonSPIRV
25+
SPIRVTranslation.cpp
26+
27+
LINK_COMPONENTS
28+
Core
29+
30+
LINK_LIBS PUBLIC
31+
TritonLLVMIR
32+
# spirv tools
33+
LLVMSPIRVLib
34+
)
35+
endif()
1536

1637
# Add SPIRV-LLVM-Translator include directory.
1738
target_include_directories(TritonSPIRV PRIVATE ${SPIRVToLLVMTranslator_INCLUDE_DIR})

third_party/intel/lib/Target/SPIRV/SPIRVTranslation.cpp

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,85 @@
1111
#include "llvm/Support/CommandLine.h"
1212
#include "llvm/Support/TargetSelect.h"
1313
#include "llvm/Target/TargetMachine.h"
14+
#include "llvm/TargetParser/Triple.h"
15+
16+
#if defined(LLVM_SPIRV_BACKEND_TARGET_PRESENT)
17+
namespace llvm {
18+
19+
using namespace llvm;
20+
using namespace SPIRV;
21+
22+
// The LLVM SPIR-V backend exposes an API call that translates LLVM module to
23+
// SPIR-V and writes results into a string as binary SPIR-V output, providing
24+
// diagnostics on fail and means of configuring translation.
25+
extern "C" bool SPIRVTranslate(Module *M, std::string &SpirvObj,
26+
std::string &ErrMsg,
27+
const std::vector<std::string> &AllowExtNames,
28+
llvm::CodeGenOptLevel OLevel,
29+
Triple TargetTriple);
30+
31+
static inline Triple::SubArchType
32+
spirvVersionToSubArch(SPIRV::VersionNumber VN) {
33+
switch (VN) {
34+
case SPIRV::VersionNumber::SPIRV_1_0:
35+
return Triple::SPIRVSubArch_v10;
36+
case VersionNumber::SPIRV_1_1:
37+
return Triple::SPIRVSubArch_v11;
38+
case VersionNumber::SPIRV_1_2:
39+
return Triple::SPIRVSubArch_v12;
40+
case VersionNumber::SPIRV_1_3:
41+
return Triple::SPIRVSubArch_v13;
42+
case VersionNumber::SPIRV_1_4:
43+
return Triple::SPIRVSubArch_v14;
44+
case VersionNumber::SPIRV_1_5:
45+
return Triple::SPIRVSubArch_v15;
46+
case VersionNumber::SPIRV_1_6:
47+
return Triple::SPIRVSubArch_v16;
48+
}
49+
return Triple::NoSubArch;
50+
}
51+
52+
bool runSpirvBackend(Module *M, std::string &Result, std::string &ErrMsg,
53+
const SPIRV::TranslatorOpts &TranslatorOpts) {
54+
static const std::string DefaultTriple = "spirv64v1.6-unknown-unknown";
55+
static const std::vector<std::string> AllowExtNames{"all"};
56+
57+
// Correct the Triple value if needed
58+
Triple TargetTriple(M->getTargetTriple());
59+
if (TargetTriple.isSPIR()) {
60+
TargetTriple.setArch(TargetTriple.getArch() == Triple::spir64
61+
? Triple::spirv64
62+
: Triple::spirv32,
63+
TargetTriple.getSubArch());
64+
M->setTargetTriple(TargetTriple.str());
65+
// We need to reset Data Layout to conform with the TargetMachine
66+
M->setDataLayout("");
67+
}
68+
if (TargetTriple.getTriple().empty())
69+
TargetTriple.setTriple(DefaultTriple);
70+
if (TranslatorOpts.getMaxVersion() != VersionNumber::MaximumVersion) {
71+
TargetTriple.setArch(TargetTriple.getArch(),
72+
spirvVersionToSubArch(TranslatorOpts.getMaxVersion()));
73+
M->setTargetTriple(TargetTriple.str());
74+
}
75+
76+
// Translate the Module into SPIR-V
77+
return SPIRVTranslate(M, Result, ErrMsg, AllowExtNames,
78+
CodeGenOptLevel::Aggressive, TargetTriple);
79+
}
80+
81+
bool runSpirvBackend(Module *M, std::ostream &OS, std::string &ErrMsg,
82+
const SPIRV::TranslatorOpts &TranslatorOpts) {
83+
std::string Result;
84+
bool Status = runSpirvBackend(M, Result, ErrMsg, TranslatorOpts);
85+
if (Status)
86+
OS << Result;
87+
return Status;
88+
}
89+
90+
} // namespace llvm
91+
92+
#endif // LLVM_SPIRV_BACKEND_TARGET_PRESENT
1493

1594
namespace triton {
1695

@@ -63,7 +142,17 @@ std::string translateLLVMIRToSPIRV(llvm::Module &module) {
63142
SPIRVOpts.setPreserveOCLKernelArgTypeMetadataThroughString(true);
64143
SPIRVOpts.setPreserveAuxData(false);
65144
SPIRVOpts.setSPIRVAllowUnknownIntrinsics({"llvm.genx.GenISA."});
145+
146+
#if defined(LLVM_SPIRV_BACKEND_TARGET_PRESENT)
147+
int SpvTranslateMode = 0;
148+
if (const char *EnvIsBackend = std::getenv("TRITON_USE_SPIRV_BACKEND"))
149+
llvm::StringRef(EnvIsBackend).getAsInteger(10, SpvTranslateMode);
150+
auto success = SpvTranslateMode
151+
? llvm::runSpirvBackend(&module, OS, Err, SPIRVOpts)
152+
: llvm::writeSpirv(&module, SPIRVOpts, OS, Err);
153+
#else
66154
auto success = llvm::writeSpirv(&module, SPIRVOpts, OS, Err);
155+
#endif // LLVM_SPIRV_BACKEND_TARGET_PRESENT
67156

68157
if (!success) {
69158
llvm::errs() << "SPIRVTranslation: SPIRV translation failed with"

0 commit comments

Comments
 (0)