brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.5 KiB · ad6c9cd Raw
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