367 lines
12 KiB
C++
367 lines
12 KiB
C++
//===- LLVMSPIRVOpts.h - Specify options for translation --------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
// Copyright (c) 2019 Intel Corporation. All rights reserved.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the "Software"),
|
|
// to deal with the Software without restriction, including without limitation
|
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
// and/or sell copies of the Software, and to permit persons to whom the
|
|
// Software is furnished to do so, subject to the following conditions:
|
|
//
|
|
// Redistributions of source code must retain the above copyright notice,
|
|
// this list of conditions and the following disclaimers.
|
|
// Redistributions in binary form must reproduce the above copyright notice,
|
|
// this list of conditions and the following disclaimers in the documentation
|
|
// and/or other materials provided with the distribution.
|
|
// Neither the names of Advanced Micro Devices, Inc., nor the names of its
|
|
// contributors may be used to endorse or promote products derived from this
|
|
// Software without specific prior written permission.
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
|
|
// THE SOFTWARE.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
/// \file LLVMSPIRVOpts.h
|
|
///
|
|
/// This files declares helper classes to handle SPIR-V versions and extensions.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
#ifndef SPIRV_LLVMSPIRVOPTS_H
|
|
#define SPIRV_LLVMSPIRVOPTS_H
|
|
|
|
#include <llvm/ADT/SmallVector.h>
|
|
#include <llvm/ADT/StringRef.h>
|
|
|
|
#include <cassert>
|
|
#include <cstdint>
|
|
#include <map>
|
|
#include <optional>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
namespace llvm {
|
|
class IntrinsicInst;
|
|
} // namespace llvm
|
|
|
|
namespace SPIRV {
|
|
|
|
/// SPIR-V versions known to translator.
|
|
enum class VersionNumber : uint32_t {
|
|
// See section 2.3 of SPIR-V spec: Physical Layout of a SPIR_V Module and
|
|
// Instruction
|
|
SPIRV_1_0 = 0x00010000,
|
|
SPIRV_1_1 = 0x00010100,
|
|
SPIRV_1_2 = 0x00010200,
|
|
SPIRV_1_3 = 0x00010300,
|
|
SPIRV_1_4 = 0x00010400,
|
|
SPIRV_1_5 = 0x00010500,
|
|
SPIRV_1_6 = 0x00010600,
|
|
MinimumVersion = SPIRV_1_0,
|
|
MaximumVersion = SPIRV_1_6
|
|
};
|
|
|
|
inline constexpr std::string_view formatVersionNumber(uint32_t Version) {
|
|
switch (Version) {
|
|
case static_cast<uint32_t>(VersionNumber::SPIRV_1_0):
|
|
return "1.0";
|
|
case static_cast<uint32_t>(VersionNumber::SPIRV_1_1):
|
|
return "1.1";
|
|
case static_cast<uint32_t>(VersionNumber::SPIRV_1_2):
|
|
return "1.2";
|
|
case static_cast<uint32_t>(VersionNumber::SPIRV_1_3):
|
|
return "1.3";
|
|
case static_cast<uint32_t>(VersionNumber::SPIRV_1_4):
|
|
return "1.4";
|
|
case static_cast<uint32_t>(VersionNumber::SPIRV_1_5):
|
|
return "1.5";
|
|
case static_cast<uint32_t>(VersionNumber::SPIRV_1_6):
|
|
return "1.6";
|
|
}
|
|
return "unknown";
|
|
}
|
|
|
|
inline bool isSPIRVVersionKnown(VersionNumber Ver) {
|
|
return Ver >= VersionNumber::MinimumVersion &&
|
|
Ver <= VersionNumber::MaximumVersion;
|
|
}
|
|
|
|
enum class ExtensionID : uint32_t {
|
|
First,
|
|
#define EXT(X) X,
|
|
#include "LLVMSPIRVExtensions.inc"
|
|
#undef EXT
|
|
Last,
|
|
};
|
|
|
|
enum class ExtInst : uint32_t { None, OpenCL };
|
|
|
|
enum class BIsRepresentation : uint32_t { OpenCL12, OpenCL20, SPIRVFriendlyIR };
|
|
|
|
enum class FPContractMode : uint32_t { On, Off, Fast };
|
|
|
|
enum class DebugInfoEIS : uint32_t {
|
|
SPIRV_Debug,
|
|
OpenCL_DebugInfo_100,
|
|
NonSemantic_Shader_DebugInfo_100,
|
|
NonSemantic_Shader_DebugInfo_200
|
|
};
|
|
|
|
enum class BuiltinFormat : uint32_t { Function, Global };
|
|
|
|
/// \brief Helper class to manage SPIR-V translation
|
|
class TranslatorOpts {
|
|
public:
|
|
// Unset optional means not directly specified by user
|
|
using ExtensionsStatusMap = std::map<ExtensionID, std::optional<bool>>;
|
|
|
|
using ArgList = llvm::SmallVector<llvm::StringRef, 4>;
|
|
|
|
TranslatorOpts() = default;
|
|
|
|
TranslatorOpts(VersionNumber Max, const ExtensionsStatusMap &Map = {})
|
|
: MaxVersion(Max), ExtStatusMap(Map) {}
|
|
|
|
bool isAllowedToUseVersion(VersionNumber RequestedVersion) const {
|
|
return RequestedVersion <= MaxVersion;
|
|
}
|
|
|
|
bool isAllowedToUseExtension(ExtensionID Extension) const {
|
|
auto I = ExtStatusMap.find(Extension);
|
|
if (ExtStatusMap.end() == I)
|
|
return false;
|
|
|
|
return I->second && *I->second;
|
|
}
|
|
|
|
void setAllowedToUseExtension(ExtensionID Extension, bool Allow = true) {
|
|
// Only allow using the extension if it has not already been disabled
|
|
auto I = ExtStatusMap.find(Extension);
|
|
if (I == ExtStatusMap.end() || !I->second || (*I->second) == true)
|
|
ExtStatusMap[Extension] = Allow;
|
|
}
|
|
|
|
std::vector<std::string>
|
|
getAllowedSPIRVExtensionNames(std::function<bool(ExtensionID)> &Filter) const;
|
|
|
|
VersionNumber getMaxVersion() const { return MaxVersion; }
|
|
|
|
bool isGenArgNameMDEnabled() const { return GenKernelArgNameMD; }
|
|
|
|
bool isSPIRVMemToRegEnabled() const { return SPIRVMemToReg; }
|
|
|
|
void setMemToRegEnabled(bool Mem2Reg) { SPIRVMemToReg = Mem2Reg; }
|
|
|
|
bool preserveAuxData() const { return PreserveAuxData; }
|
|
|
|
void setPreserveAuxData(bool ArgValue) { PreserveAuxData = ArgValue; }
|
|
|
|
void setGenKernelArgNameMDEnabled(bool ArgNameMD) {
|
|
GenKernelArgNameMD = ArgNameMD;
|
|
}
|
|
|
|
void enableAllExtensions();
|
|
|
|
void enableGenArgNameMD() { GenKernelArgNameMD = true; }
|
|
|
|
void setSpecConst(uint32_t SpecId, uint64_t SpecValue) {
|
|
ExternalSpecialization[SpecId] = SpecValue;
|
|
}
|
|
|
|
bool getSpecializationConstant(uint32_t SpecId, uint64_t &Value) const {
|
|
auto It = ExternalSpecialization.find(SpecId);
|
|
if (It == ExternalSpecialization.end())
|
|
return false;
|
|
Value = It->second;
|
|
return true;
|
|
}
|
|
|
|
void setExtInst(ExtInst Value) {
|
|
// --spirv-ext-inst supersedes --spirv-replace-fmuladd-with-ocl-mad
|
|
ReplaceLLVMFmulAddWithOpenCLMad = false;
|
|
ExtInstValue = Value;
|
|
}
|
|
|
|
ExtInst getExtInst() const { return ExtInstValue; }
|
|
|
|
void setDesiredBIsRepresentation(BIsRepresentation Value) {
|
|
DesiredRepresentationOfBIs = Value;
|
|
}
|
|
|
|
BIsRepresentation getDesiredBIsRepresentation() const {
|
|
return DesiredRepresentationOfBIs;
|
|
}
|
|
|
|
void setFPContractMode(FPContractMode Mode) { FPCMode = Mode; }
|
|
|
|
FPContractMode getFPContractMode() const { return FPCMode; }
|
|
|
|
bool isUnknownIntrinsicAllowed(llvm::IntrinsicInst *II) const noexcept;
|
|
bool isSPIRVAllowUnknownIntrinsicsEnabled() const noexcept;
|
|
void setSPIRVAllowUnknownIntrinsics(ArgList IntrinsicPrefixList) noexcept;
|
|
|
|
bool allowExtraDIExpressions() const noexcept {
|
|
return AllowExtraDIExpressions;
|
|
}
|
|
|
|
void setAllowExtraDIExpressionsEnabled(bool Allow) noexcept {
|
|
AllowExtraDIExpressions = Allow;
|
|
}
|
|
|
|
DebugInfoEIS getDebugInfoEIS() const { return DebugInfoVersion; }
|
|
|
|
void setDebugInfoEIS(DebugInfoEIS EIS) { DebugInfoVersion = EIS; }
|
|
|
|
bool shouldReplaceLLVMFmulAddWithOpenCLMad() const noexcept {
|
|
return ReplaceLLVMFmulAddWithOpenCLMad;
|
|
}
|
|
|
|
void setReplaceLLVMFmulAddWithOpenCLMad(bool Value) noexcept {
|
|
ReplaceLLVMFmulAddWithOpenCLMad = Value;
|
|
}
|
|
|
|
bool shouldPreserveOCLKernelArgTypeMetadataThroughString() const noexcept {
|
|
return PreserveOCLKernelArgTypeMetadataThroughString;
|
|
}
|
|
|
|
void setPreserveOCLKernelArgTypeMetadataThroughString(bool Value) noexcept {
|
|
PreserveOCLKernelArgTypeMetadataThroughString = Value;
|
|
}
|
|
|
|
bool shouldEmitFunctionPtrAddrSpace() const noexcept {
|
|
return EmitFunctionPtrAddrSpace;
|
|
}
|
|
|
|
void setEmitFunctionPtrAddrSpace(bool Value) noexcept {
|
|
EmitFunctionPtrAddrSpace = Value;
|
|
}
|
|
|
|
void setBuiltinFormat(BuiltinFormat Value) noexcept {
|
|
SPIRVBuiltinFormat = Value;
|
|
}
|
|
BuiltinFormat getBuiltinFormat() const noexcept { return SPIRVBuiltinFormat; }
|
|
|
|
void setUseLLVMTarget(bool Flag) noexcept { UseLLVMTarget = Flag; }
|
|
bool getUseLLVMTarget() const noexcept { return UseLLVMTarget; }
|
|
|
|
void setFnVarCategory(uint32_t Category) noexcept {
|
|
FnVarCategory = Category;
|
|
}
|
|
std::optional<uint32_t> getFnVarCategory() const noexcept {
|
|
return FnVarCategory;
|
|
}
|
|
|
|
void setFnVarFamily(uint32_t Family) noexcept { FnVarFamily = Family; }
|
|
std::optional<uint32_t> getFnVarFamily() const noexcept {
|
|
return FnVarFamily;
|
|
}
|
|
|
|
void setFnVarArch(uint32_t Arch) noexcept { FnVarArch = Arch; }
|
|
std::optional<uint32_t> getFnVarArch() const noexcept { return FnVarArch; }
|
|
|
|
void setFnVarTarget(uint32_t Target) noexcept { FnVarTarget = Target; }
|
|
std::optional<uint32_t> getFnVarTarget() const noexcept {
|
|
return FnVarTarget;
|
|
}
|
|
|
|
void setFnVarFeatures(std::vector<uint32_t> Features) noexcept {
|
|
FnVarFeatures = Features;
|
|
}
|
|
std::vector<uint32_t> getFnVarFeatures() const noexcept {
|
|
return FnVarFeatures;
|
|
}
|
|
|
|
void setFnVarCapabilities(std::vector<uint32_t> Capabilities) noexcept {
|
|
FnVarCapabilities = Capabilities;
|
|
}
|
|
std::vector<uint32_t> getFnVarCapabilities() const noexcept {
|
|
return FnVarCapabilities;
|
|
}
|
|
|
|
void setFnVarSpecEnable(bool Val) noexcept { FnVarSpecEnable = Val; }
|
|
bool getFnVarSpecEnable() const noexcept { return FnVarSpecEnable; }
|
|
|
|
void setFnVarSpvOut(std::string Val) noexcept { FnVarSpvOut = Val; }
|
|
std::string getFnVarSpvOut() const noexcept { return FnVarSpvOut; }
|
|
|
|
// Check that options passed to --fnvar-xxx flags make sense. Return true on
|
|
// success, false on failure.
|
|
bool validateFnVarOpts() const;
|
|
|
|
private:
|
|
// Common translation options
|
|
VersionNumber MaxVersion = VersionNumber::MaximumVersion;
|
|
ExtensionsStatusMap ExtStatusMap;
|
|
// SPIRVMemToReg option affects LLVM IR regularization phase
|
|
bool SPIRVMemToReg = false;
|
|
// SPIR-V to LLVM translation options
|
|
bool GenKernelArgNameMD = false;
|
|
std::unordered_map<uint32_t, uint64_t> ExternalSpecialization;
|
|
// Extended instruction set to use when translating from LLVM IR to SPIR-V
|
|
ExtInst ExtInstValue = ExtInst::None;
|
|
// Representation of built-ins, which should be used while translating from
|
|
// SPIR-V to back to LLVM IR
|
|
BIsRepresentation DesiredRepresentationOfBIs = BIsRepresentation::OpenCL12;
|
|
// Controls floating point contraction.
|
|
//
|
|
// - FPContractMode::On allows to choose a mode according to
|
|
// presence of fused LLVM intrinsics
|
|
//
|
|
// - FPContractMode::Off disables contratction for all entry points
|
|
//
|
|
// - FPContractMode::Fast allows *all* operations to be contracted
|
|
// for all entry points
|
|
FPContractMode FPCMode = FPContractMode::On;
|
|
|
|
// Unknown LLVM intrinsics will be translated as external function calls in
|
|
// SPIR-V
|
|
std::optional<ArgList> SPIRVAllowUnknownIntrinsics{};
|
|
|
|
// Enable support for extra DIExpression opcodes not listed in the SPIR-V
|
|
// DebugInfo specification.
|
|
bool AllowExtraDIExpressions = false;
|
|
|
|
DebugInfoEIS DebugInfoVersion = DebugInfoEIS::OpenCL_DebugInfo_100;
|
|
|
|
// Controls whether llvm.fmuladd.* should be replaced with mad from OpenCL
|
|
// extended instruction set or with a simple fmul + fadd
|
|
bool ReplaceLLVMFmulAddWithOpenCLMad = true;
|
|
|
|
// Add a workaround to preserve OpenCL kernel_arg_type and
|
|
// kernel_arg_type_qual metadata through OpString
|
|
bool PreserveOCLKernelArgTypeMetadataThroughString = false;
|
|
|
|
// Controls if CodeSectionINTEL can be emitted and consumed with a dedicated
|
|
// address space
|
|
bool EmitFunctionPtrAddrSpace = false;
|
|
|
|
bool PreserveAuxData = false;
|
|
|
|
std::optional<uint32_t> FnVarCategory = std::nullopt;
|
|
std::optional<uint32_t> FnVarFamily = std::nullopt;
|
|
std::optional<uint32_t> FnVarArch = std::nullopt;
|
|
std::optional<uint32_t> FnVarTarget = std::nullopt;
|
|
std::vector<uint32_t> FnVarFeatures = {};
|
|
std::vector<uint32_t> FnVarCapabilities = {};
|
|
std::string FnVarSpvOut = "";
|
|
bool FnVarSpecEnable = false;
|
|
|
|
BuiltinFormat SPIRVBuiltinFormat = BuiltinFormat::Function;
|
|
|
|
// Convert LLVM to SPIR-V using the LLVM SPIR-V Backend target
|
|
bool UseLLVMTarget = false;
|
|
};
|
|
|
|
} // namespace SPIRV
|
|
|
|
#endif // SPIRV_LLVMSPIRVOPTS_H
|