Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
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
3 changes: 3 additions & 0 deletions include/LLVMSPIRVExtensions.inc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#endif

EXT(SPV_KHR_no_integer_wrap_decoration)
EXT(SPV_KHR_float_controls)
EXT(SPV_INTEL_subgroups)
EXT(SPV_INTEL_media_block_io)
EXT(SPV_INTEL_device_side_avc_motion_estimation)
Expand All @@ -15,3 +16,5 @@ EXT(SPV_INTEL_blocking_pipes)
EXT(SPV_INTEL_function_pointers)
EXT(SPV_INTEL_kernel_attributes)
EXT(SPV_INTEL_inline_assembly)
EXT(SPV_INTEL_float_controls2)
EXT(SPV_INTEL_vector_compute)
13 changes: 10 additions & 3 deletions include/LLVMSPIRVLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,13 @@ bool getSpecConstInfo(std::istream &IS,
std::unique_ptr<Module>
convertSpirvToLLVM(LLVMContext &C, SPIRV::SPIRVModule &BM, std::string &ErrMsg);

/// \brief Convert a SPIRVModule into LLVM IR using specified options
/// \returns null on failure.
std::unique_ptr<Module> convertSpirvToLLVM(LLVMContext &C,
SPIRV::SPIRVModule &BM,
const SPIRV::TranslatorOpts &Opts,
std::string &ErrMsg);

/// \brief Regularize LLVM module by removing entities not representable by
/// SPIRV.
bool regularizeLlvmForSpirv(Module *M, std::string &ErrMsg);
Expand Down Expand Up @@ -184,9 +191,9 @@ ModulePass *createSPIRVLowerMemmove();
/// Create a pass for regularize LLVM module to be translated to SPIR-V.
ModulePass *createSPIRVRegularizeLLVM();

/// Create a pass for translating SPIR-V builtin functions to OCL builtin
/// functions.
ModulePass *createSPIRVToOCL(Module &M);
/// Create a pass for translating SPIR-V Instructions to desired
/// representation in LLVM IR (OpenCL built-ins, SPIR-V Friendly IR, etc.)
ModulePass *createSPIRVBIsLoweringPass(Module &, SPIRV::BIsRepresentation);

/// Create a pass for translating SPIR-V builtin functions to OCL 1.2 builtin
/// functions.
Expand Down
14 changes: 14 additions & 0 deletions include/LLVMSPIRVOpts.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ enum class ExtensionID : uint32_t {

enum class FPContractMode : uint32_t { On, Off, Fast };

enum class BIsRepresentation : uint32_t { OpenCL12, OpenCL20, SPIRVFriendlyIR };

/// \brief Helper class to manage SPIR-V translation
class TranslatorOpts {
public:
Expand Down Expand Up @@ -127,6 +129,14 @@ class TranslatorOpts {

FPContractMode getFPContractMode() const { return FPCMode; }

void setDesiredBIsRepresentation(BIsRepresentation Value) {
DesiredRepresentationOfBIs = Value;
}

BIsRepresentation getDesiredBIsRepresentation() const {
return DesiredRepresentationOfBIs;
}

private:
// Common translation options
VersionNumber MaxVersion = VersionNumber::MaximumVersion;
Expand All @@ -146,6 +156,10 @@ class TranslatorOpts {
// - FPContractMode::Fast allows *all* operations to be contracted
// for all entry points
FPContractMode FPCMode = FPContractMode::On;

// Representation of built-ins, which should be used while translating from
// SPIR-V to back to LLVM IR
BIsRepresentation DesiredRepresentationOfBIs = BIsRepresentation::OpenCL12;
};

} // namespace SPIRV
Expand Down
1 change: 1 addition & 0 deletions lib/SPIRV/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ add_llvm_library(LLVMSPIRVLib
OCL21ToSPIRV.cpp
OCLTypeToSPIRV.cpp
OCLUtil.cpp
VectorComputeUtil.cpp
SPIRVLowerBool.cpp
SPIRVLowerConstExpr.cpp
SPIRVLowerMemmove.cpp
Expand Down
142 changes: 100 additions & 42 deletions lib/SPIRV/PreprocessMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "SPIRVInternal.h"
#include "SPIRVMDBuilder.h"
#include "SPIRVMDWalker.h"
#include "VectorComputeUtil.h"

#include "llvm/ADT/Triple.h"
#include "llvm/IR/IRBuilder.h"
Expand Down Expand Up @@ -69,6 +70,9 @@ class PreprocessMetadata : public ModulePass {

bool runOnModule(Module &M) override;
void visit(Module *M);
void preprocessOCLMetadata(Module *M, SPIRVMDBuilder *B, SPIRVMDWalker *W);
void preprocessVectorComputeMetadata(Module *M, SPIRVMDBuilder *B,
SPIRVMDWalker *W);

static char ID;

Expand Down Expand Up @@ -99,48 +103,8 @@ void PreprocessMetadata::visit(Module *M) {
SPIRVMDBuilder B(*M);
SPIRVMDWalker W(*M);

unsigned CLVer = getOCLVersion(M, true);
if (CLVer != 0) { // Preprocess OpenCL-specific metadata
// !spirv.Source = !{!x}
// !{x} = !{i32 3, i32 102000}
B.addNamedMD(kSPIRVMD::Source)
.addOp()
.add(CLVer < kOCLVer::CL21 ? spv::SourceLanguageOpenCL_C
: spv::SourceLanguageOpenCL_CPP)
.add(CLVer)
.done();
if (EraseOCLMD)
B.eraseNamedMD(kSPIR2MD::OCLVer).eraseNamedMD(kSPIR2MD::SPIRVer);

// !spirv.MemoryModel = !{!x}
// !{x} = !{i32 1, i32 2}
Triple TT(M->getTargetTriple());
assert(isSupportedTriple(TT) && "Invalid triple");
B.addNamedMD(kSPIRVMD::MemoryModel)
.addOp()
.add(TT.isArch32Bit() ? spv::AddressingModelPhysical32
: spv::AddressingModelPhysical64)
.add(spv::MemoryModelOpenCL)
.done();

// Add source extensions
// !spirv.SourceExtension = !{!x, !y, ...}
// !x = {!"cl_khr_..."}
// !y = {!"cl_khr_..."}
auto Exts = getNamedMDAsStringSet(M, kSPIR2MD::Extensions);
if (!Exts.empty()) {
auto N = B.addNamedMD(kSPIRVMD::SourceExtension);
for (auto &I : Exts)
N.addOp().add(I).done();
}
if (EraseOCLMD)
B.eraseNamedMD(kSPIR2MD::Extensions).eraseNamedMD(kSPIR2MD::OptFeatures);

if (EraseOCLMD)
B.eraseNamedMD(kSPIR2MD::FPContract);
}

// The rest of metadata might come not only from OpenCL
preprocessOCLMetadata(M, &B, &W);
preprocessVectorComputeMetadata(M, &B, &W);

// Create metadata representing (empty so far) list
// of OpExecutionMode instructions
Expand Down Expand Up @@ -234,6 +198,100 @@ void PreprocessMetadata::visit(Module *M) {
}
}

void PreprocessMetadata::preprocessOCLMetadata(Module *M, SPIRVMDBuilder *B,
SPIRVMDWalker *W) {
unsigned CLVer = getOCLVersion(M, true);
if (CLVer == 0)
return;
// Preprocess OpenCL-specific metadata
// !spirv.Source = !{!x}
// !{x} = !{i32 3, i32 102000}
B->addNamedMD(kSPIRVMD::Source)
.addOp()
.add(CLVer < kOCLVer::CL21 ? spv::SourceLanguageOpenCL_C
: spv::SourceLanguageOpenCL_CPP)
.add(CLVer)
.done();
if (EraseOCLMD)
B->eraseNamedMD(kSPIR2MD::OCLVer).eraseNamedMD(kSPIR2MD::SPIRVer);

// !spirv.MemoryModel = !{!x}
// !{x} = !{i32 1, i32 2}
Triple TT(M->getTargetTriple());
assert(isSupportedTriple(TT) && "Invalid triple");
B->addNamedMD(kSPIRVMD::MemoryModel)
.addOp()
.add(TT.isArch32Bit() ? spv::AddressingModelPhysical32
: spv::AddressingModelPhysical64)
.add(spv::MemoryModelOpenCL)
.done();

// Add source extensions
// !spirv.SourceExtension = !{!x, !y, ...}
// !x = {!"cl_khr_..."}
// !y = {!"cl_khr_..."}
auto Exts = getNamedMDAsStringSet(M, kSPIR2MD::Extensions);
if (!Exts.empty()) {
auto N = B->addNamedMD(kSPIRVMD::SourceExtension);
for (auto &I : Exts)
N.addOp().add(I).done();
}
if (EraseOCLMD)
B->eraseNamedMD(kSPIR2MD::Extensions).eraseNamedMD(kSPIR2MD::OptFeatures);

if (EraseOCLMD)
B->eraseNamedMD(kSPIR2MD::FPContract);
}

void PreprocessMetadata::preprocessVectorComputeMetadata(Module *M,
SPIRVMDBuilder *B,
SPIRVMDWalker *W) {
using namespace VectorComputeUtil;

auto EM = B->addNamedMD(kSPIRVMD::ExecutionMode);

for (auto &F : *M) {
// Add VC float control execution modes
// RoundMode and FloatMode are always same for all types in VC
// While Denorm could be different for double, float and half
auto Attrs = F.getAttributes();
if (Attrs.hasFnAttribute(kVCMetadata::VCFloatControl)) {
SPIRVWord Mode = 0;
Attrs
.getAttribute(AttributeList::FunctionIndex,
kVCMetadata::VCFloatControl)
.getValueAsString()
.getAsInteger(0, Mode);
spv::ExecutionMode ExecRoundMode =
VCRoundModeExecModeMap::map(getVCRoundMode(Mode));
spv::ExecutionMode ExecFloatMode =
VCFloatModeExecModeMap::map(getVCFloatMode(Mode));
VCFloatTypeSizeMap::foreach (
[&](VCFloatType FloatType, unsigned TargetWidth) {
EM.addOp().add(&F).add(ExecRoundMode).add(TargetWidth).done();
EM.addOp().add(&F).add(ExecFloatMode).add(TargetWidth).done();
EM.addOp()
.add(&F)
.add(VCDenormModeExecModeMap::map(
getVCDenormPreserve(Mode, FloatType)))
.add(TargetWidth)
.done();
});
}
if (Attrs.hasFnAttribute(kVCMetadata::VCSLMSize)) {
SPIRVWord SLMSize = 0;
Attrs.getAttribute(AttributeList::FunctionIndex, kVCMetadata::VCSLMSize)
.getValueAsString()
.getAsInteger(0, SLMSize);
EM.addOp()
.add(&F)
.add(spv::ExecutionModeSharedLocalMemorySizeINTEL)
.add(SLMSize)
.done();
}
}
}

} // namespace SPIRV

INITIALIZE_PASS(PreprocessMetadata, "preprocess-metadata",
Expand Down
4 changes: 4 additions & 0 deletions lib/SPIRV/SPIRVLowerOCLBlocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ class SPIRVLowerOCLBlocks : public ModulePass {
public:
SPIRVLowerOCLBlocks() : ModulePass(ID) {}

StringRef getPassName() const override {
return "Lower OpenCL Blocks For SPIR-V";
}

bool runOnModule(Module &M) {
bool Changed = false;
for (Function &F : M) {
Expand Down
Loading