190 lines · cpp
1//===-- SPIRVSubtarget.cpp - SPIR-V Subtarget Information ------*- C++ -*--===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the SPIR-V specific subclass of TargetSubtargetInfo.10//11//===----------------------------------------------------------------------===//12 13#include "SPIRVSubtarget.h"14#include "SPIRV.h"15#include "SPIRVCommandLine.h"16#include "SPIRVGlobalRegistry.h"17#include "SPIRVLegalizerInfo.h"18#include "SPIRVRegisterBankInfo.h"19#include "SPIRVTargetMachine.h"20#include "llvm/TargetParser/Host.h"21 22using namespace llvm;23 24#define DEBUG_TYPE "spirv-subtarget"25 26#define GET_SUBTARGETINFO_TARGET_DESC27#define GET_SUBTARGETINFO_CTOR28#include "SPIRVGenSubtargetInfo.inc"29 30static cl::opt<bool>31 SPVTranslatorCompat("translator-compatibility-mode",32 cl::desc("SPIR-V Translator compatibility mode"),33 cl::Optional, cl::init(false));34 35static cl::opt<std::set<SPIRV::Extension::Extension>, false,36 SPIRVExtensionsParser>37 Extensions("spirv-ext",38 cl::desc("Specify list of enabled SPIR-V extensions"));39 40// Provides access to the cl::opt<...> `Extensions` variable from outside of the41// module.42void SPIRVSubtarget::addExtensionsToClOpt(43 const std::set<SPIRV::Extension::Extension> &AllowList) {44 Extensions.insert(AllowList.begin(), AllowList.end());45}46 47// Compare version numbers, but allow 0 to mean unspecified.48static bool isAtLeastVer(VersionTuple Target, VersionTuple VerToCompareTo) {49 return Target.empty() || Target >= VerToCompareTo;50}51 52SPIRVSubtarget::SPIRVSubtarget(const Triple &TT, const std::string &CPU,53 const std::string &FS,54 const SPIRVTargetMachine &TM)55 : SPIRVGenSubtargetInfo(TT, CPU, /*TuneCPU=*/CPU, FS),56 PointerSize(TM.getPointerSizeInBits(/* AS= */ 0)),57 InstrInfo(initSubtargetDependencies(CPU, FS)), FrameLowering(*this),58 TLInfo(TM, *this), TargetTriple(TT) {59 switch (TT.getSubArch()) {60 case Triple::SPIRVSubArch_v10:61 SPIRVVersion = VersionTuple(1, 0);62 break;63 case Triple::SPIRVSubArch_v11:64 SPIRVVersion = VersionTuple(1, 1);65 break;66 case Triple::SPIRVSubArch_v12:67 SPIRVVersion = VersionTuple(1, 2);68 break;69 case Triple::SPIRVSubArch_v13:70 SPIRVVersion = VersionTuple(1, 3);71 break;72 case Triple::SPIRVSubArch_v14:73 SPIRVVersion = VersionTuple(1, 4);74 break;75 case Triple::SPIRVSubArch_v15:76 SPIRVVersion = VersionTuple(1, 5);77 break;78 case Triple::SPIRVSubArch_v16:79 SPIRVVersion = VersionTuple(1, 6);80 break;81 default:82 if (TT.getVendor() == Triple::AMD)83 SPIRVVersion = VersionTuple(1, 6);84 else85 SPIRVVersion = VersionTuple(1, 4);86 }87 OpenCLVersion = VersionTuple(2, 2);88 89 // Set the environment based on the target triple.90 if (TargetTriple.getOS() == Triple::Vulkan)91 Env = Shader;92 else if (TargetTriple.getEnvironment() == Triple::OpenCL ||93 TargetTriple.getVendor() == Triple::AMD)94 Env = Kernel;95 else96 Env = Unknown;97 98 // Set the default extensions based on the target triple.99 if (TargetTriple.getVendor() == Triple::Intel)100 Extensions.insert(SPIRV::Extension::SPV_INTEL_function_pointers);101 if (TargetTriple.getVendor() == Triple::AMD)102 Extensions = SPIRVExtensionsParser::getValidExtensions(TargetTriple);103 104 // The order of initialization is important.105 initAvailableExtensions(Extensions);106 initAvailableExtInstSets();107 108 GR = std::make_unique<SPIRVGlobalRegistry>(PointerSize);109 CallLoweringInfo = std::make_unique<SPIRVCallLowering>(TLInfo, GR.get());110 InlineAsmInfo = std::make_unique<SPIRVInlineAsmLowering>(TLInfo);111 Legalizer = std::make_unique<SPIRVLegalizerInfo>(*this);112 RegBankInfo = std::make_unique<SPIRVRegisterBankInfo>();113 InstSelector.reset(createSPIRVInstructionSelector(TM, *this, *RegBankInfo));114}115 116SPIRVSubtarget &SPIRVSubtarget::initSubtargetDependencies(StringRef CPU,117 StringRef FS) {118 ParseSubtargetFeatures(CPU, /*TuneCPU=*/CPU, FS);119 return *this;120}121 122bool SPIRVSubtarget::canUseExtension(SPIRV::Extension::Extension E) const {123 return AvailableExtensions.contains(E);124}125 126bool SPIRVSubtarget::canUseExtInstSet(127 SPIRV::InstructionSet::InstructionSet E) const {128 return AvailableExtInstSets.contains(E);129}130 131SPIRV::InstructionSet::InstructionSet132SPIRVSubtarget::getPreferredInstructionSet() const {133 if (isShader())134 return SPIRV::InstructionSet::GLSL_std_450;135 else136 return SPIRV::InstructionSet::OpenCL_std;137}138 139bool SPIRVSubtarget::isAtLeastSPIRVVer(VersionTuple VerToCompareTo) const {140 return isAtLeastVer(SPIRVVersion, VerToCompareTo);141}142 143bool SPIRVSubtarget::isAtLeastOpenCLVer(VersionTuple VerToCompareTo) const {144 if (isShader())145 return false;146 return isAtLeastVer(OpenCLVersion, VerToCompareTo);147}148 149// If the SPIR-V version is >= 1.4 we can call OpPtrEqual and OpPtrNotEqual.150// In SPIR-V Translator compatibility mode this feature is not available.151bool SPIRVSubtarget::canDirectlyComparePointers() const {152 return !SPVTranslatorCompat && isAtLeastVer(SPIRVVersion, VersionTuple(1, 4));153}154 155void SPIRVSubtarget::accountForAMDShaderTrinaryMinmax() {156 if (canUseExtension(157 SPIRV::Extension::SPV_AMD_shader_trinary_minmax_extension)) {158 AvailableExtInstSets.insert(159 SPIRV::InstructionSet::SPV_AMD_shader_trinary_minmax);160 }161}162 163// TODO: use command line args for this rather than just defaults.164// Must have called initAvailableExtensions first.165void SPIRVSubtarget::initAvailableExtInstSets() {166 AvailableExtInstSets.clear();167 if (isShader())168 AvailableExtInstSets.insert(SPIRV::InstructionSet::GLSL_std_450);169 else170 AvailableExtInstSets.insert(SPIRV::InstructionSet::OpenCL_std);171 172 // Handle extended instruction sets from extensions.173 accountForAMDShaderTrinaryMinmax();174}175 176// Set available extensions after SPIRVSubtarget is created.177void SPIRVSubtarget::initAvailableExtensions(178 const std::set<SPIRV::Extension::Extension> &AllowedExtIds) {179 AvailableExtensions.clear();180 const std::set<SPIRV::Extension::Extension> &ValidExtensions =181 SPIRVExtensionsParser::getValidExtensions(TargetTriple);182 183 for (const auto &Ext : AllowedExtIds) {184 if (ValidExtensions.count(Ext))185 AvailableExtensions.insert(Ext);186 }187 188 accountForAMDShaderTrinaryMinmax();189}190