181ad6265SDimitry Andric //===-- SPIRVSubtarget.cpp - SPIR-V Subtarget Information ------*- C++ -*--===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric // 981ad6265SDimitry Andric // This file implements the SPIR-V specific subclass of TargetSubtargetInfo. 1081ad6265SDimitry Andric // 1181ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1281ad6265SDimitry Andric 1381ad6265SDimitry Andric #include "SPIRVSubtarget.h" 1481ad6265SDimitry Andric #include "SPIRV.h" 15*0fca6ea1SDimitry Andric #include "SPIRVCommandLine.h" 1681ad6265SDimitry Andric #include "SPIRVGlobalRegistry.h" 1781ad6265SDimitry Andric #include "SPIRVLegalizerInfo.h" 1881ad6265SDimitry Andric #include "SPIRVRegisterBankInfo.h" 1981ad6265SDimitry Andric #include "SPIRVTargetMachine.h" 2081ad6265SDimitry Andric #include "llvm/MC/TargetRegistry.h" 2106c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h" 2281ad6265SDimitry Andric 2381ad6265SDimitry Andric using namespace llvm; 2481ad6265SDimitry Andric 2581ad6265SDimitry Andric #define DEBUG_TYPE "spirv-subtarget" 2681ad6265SDimitry Andric 2781ad6265SDimitry Andric #define GET_SUBTARGETINFO_TARGET_DESC 2881ad6265SDimitry Andric #define GET_SUBTARGETINFO_CTOR 2981ad6265SDimitry Andric #include "SPIRVGenSubtargetInfo.inc" 3081ad6265SDimitry Andric 31*0fca6ea1SDimitry Andric static cl::opt<bool> 32*0fca6ea1SDimitry Andric SPVTranslatorCompat("translator-compatibility-mode", 33*0fca6ea1SDimitry Andric cl::desc("SPIR-V Translator compatibility mode"), 34*0fca6ea1SDimitry Andric cl::Optional, cl::init(false)); 35*0fca6ea1SDimitry Andric 36*0fca6ea1SDimitry Andric static cl::opt<std::set<SPIRV::Extension::Extension>, false, 37*0fca6ea1SDimitry Andric SPIRVExtensionsParser> 38*0fca6ea1SDimitry Andric Extensions("spirv-ext", 39*0fca6ea1SDimitry Andric cl::desc("Specify list of enabled SPIR-V extensions")); 405f757f3fSDimitry Andric 4181ad6265SDimitry Andric // Compare version numbers, but allow 0 to mean unspecified. 42*0fca6ea1SDimitry Andric static bool isAtLeastVer(VersionTuple Target, VersionTuple VerToCompareTo) { 43*0fca6ea1SDimitry Andric return Target.empty() || Target >= VerToCompareTo; 4481ad6265SDimitry Andric } 4581ad6265SDimitry Andric 4681ad6265SDimitry Andric SPIRVSubtarget::SPIRVSubtarget(const Triple &TT, const std::string &CPU, 4781ad6265SDimitry Andric const std::string &FS, 4881ad6265SDimitry Andric const SPIRVTargetMachine &TM) 4981ad6265SDimitry Andric : SPIRVGenSubtargetInfo(TT, CPU, /*TuneCPU=*/CPU, FS), 50*0fca6ea1SDimitry Andric PointerSize(TM.getPointerSizeInBits(/* AS= */ 0)), InstrInfo(), 515f757f3fSDimitry Andric FrameLowering(initSubtargetDependencies(CPU, FS)), TLInfo(TM, *this), 525f757f3fSDimitry Andric TargetTriple(TT) { 53*0fca6ea1SDimitry Andric switch (TT.getSubArch()) { 54*0fca6ea1SDimitry Andric case Triple::SPIRVSubArch_v10: 55*0fca6ea1SDimitry Andric SPIRVVersion = VersionTuple(1, 0); 56*0fca6ea1SDimitry Andric break; 57*0fca6ea1SDimitry Andric case Triple::SPIRVSubArch_v11: 58*0fca6ea1SDimitry Andric SPIRVVersion = VersionTuple(1, 1); 59*0fca6ea1SDimitry Andric break; 60*0fca6ea1SDimitry Andric case Triple::SPIRVSubArch_v12: 61*0fca6ea1SDimitry Andric SPIRVVersion = VersionTuple(1, 2); 62*0fca6ea1SDimitry Andric break; 63*0fca6ea1SDimitry Andric case Triple::SPIRVSubArch_v13: 64*0fca6ea1SDimitry Andric SPIRVVersion = VersionTuple(1, 3); 65*0fca6ea1SDimitry Andric break; 66*0fca6ea1SDimitry Andric case Triple::SPIRVSubArch_v14: 67*0fca6ea1SDimitry Andric default: 68*0fca6ea1SDimitry Andric SPIRVVersion = VersionTuple(1, 4); 69*0fca6ea1SDimitry Andric break; 70*0fca6ea1SDimitry Andric case Triple::SPIRVSubArch_v15: 71*0fca6ea1SDimitry Andric SPIRVVersion = VersionTuple(1, 5); 72*0fca6ea1SDimitry Andric break; 73*0fca6ea1SDimitry Andric case Triple::SPIRVSubArch_v16: 74*0fca6ea1SDimitry Andric SPIRVVersion = VersionTuple(1, 6); 75*0fca6ea1SDimitry Andric break; 76*0fca6ea1SDimitry Andric } 77*0fca6ea1SDimitry Andric OpenCLVersion = VersionTuple(2, 2); 78*0fca6ea1SDimitry Andric 79bdd1243dSDimitry Andric // The order of initialization is important. 80bdd1243dSDimitry Andric initAvailableExtensions(); 81bdd1243dSDimitry Andric initAvailableExtInstSets(); 82bdd1243dSDimitry Andric 8381ad6265SDimitry Andric GR = std::make_unique<SPIRVGlobalRegistry>(PointerSize); 84fcaf7f86SDimitry Andric CallLoweringInfo = std::make_unique<SPIRVCallLowering>(TLInfo, GR.get()); 85*0fca6ea1SDimitry Andric InlineAsmInfo = std::make_unique<SPIRVInlineAsmLowering>(TLInfo); 8681ad6265SDimitry Andric Legalizer = std::make_unique<SPIRVLegalizerInfo>(*this); 8781ad6265SDimitry Andric RegBankInfo = std::make_unique<SPIRVRegisterBankInfo>(); 8881ad6265SDimitry Andric InstSelector.reset( 8981ad6265SDimitry Andric createSPIRVInstructionSelector(TM, *this, *RegBankInfo.get())); 9081ad6265SDimitry Andric } 9181ad6265SDimitry Andric 9281ad6265SDimitry Andric SPIRVSubtarget &SPIRVSubtarget::initSubtargetDependencies(StringRef CPU, 9381ad6265SDimitry Andric StringRef FS) { 9481ad6265SDimitry Andric ParseSubtargetFeatures(CPU, /*TuneCPU=*/CPU, FS); 9581ad6265SDimitry Andric return *this; 9681ad6265SDimitry Andric } 9781ad6265SDimitry Andric 98bdd1243dSDimitry Andric bool SPIRVSubtarget::canUseExtension(SPIRV::Extension::Extension E) const { 99bdd1243dSDimitry Andric return AvailableExtensions.contains(E); 100bdd1243dSDimitry Andric } 101bdd1243dSDimitry Andric 102bdd1243dSDimitry Andric bool SPIRVSubtarget::canUseExtInstSet( 103bdd1243dSDimitry Andric SPIRV::InstructionSet::InstructionSet E) const { 104bdd1243dSDimitry Andric return AvailableExtInstSets.contains(E); 105bdd1243dSDimitry Andric } 106bdd1243dSDimitry Andric 107*0fca6ea1SDimitry Andric bool SPIRVSubtarget::isAtLeastSPIRVVer(VersionTuple VerToCompareTo) const { 108bdd1243dSDimitry Andric return isAtLeastVer(SPIRVVersion, VerToCompareTo); 109bdd1243dSDimitry Andric } 110bdd1243dSDimitry Andric 111*0fca6ea1SDimitry Andric bool SPIRVSubtarget::isAtLeastOpenCLVer(VersionTuple VerToCompareTo) const { 1125f757f3fSDimitry Andric if (!isOpenCLEnv()) 1135f757f3fSDimitry Andric return false; 114bdd1243dSDimitry Andric return isAtLeastVer(OpenCLVersion, VerToCompareTo); 115bdd1243dSDimitry Andric } 116bdd1243dSDimitry Andric 11781ad6265SDimitry Andric // If the SPIR-V version is >= 1.4 we can call OpPtrEqual and OpPtrNotEqual. 118*0fca6ea1SDimitry Andric // In SPIR-V Translator compatibility mode this feature is not available. 11981ad6265SDimitry Andric bool SPIRVSubtarget::canDirectlyComparePointers() const { 120*0fca6ea1SDimitry Andric return !SPVTranslatorCompat && isAtLeastVer(SPIRVVersion, VersionTuple(1, 4)); 12181ad6265SDimitry Andric } 122bdd1243dSDimitry Andric 123bdd1243dSDimitry Andric void SPIRVSubtarget::initAvailableExtensions() { 124bdd1243dSDimitry Andric AvailableExtensions.clear(); 125bdd1243dSDimitry Andric if (!isOpenCLEnv()) 126bdd1243dSDimitry Andric return; 1275f757f3fSDimitry Andric 128*0fca6ea1SDimitry Andric AvailableExtensions.insert(Extensions.begin(), Extensions.end()); 129bdd1243dSDimitry Andric } 130bdd1243dSDimitry Andric 131bdd1243dSDimitry Andric // TODO: use command line args for this rather than just defaults. 132bdd1243dSDimitry Andric // Must have called initAvailableExtensions first. 133bdd1243dSDimitry Andric void SPIRVSubtarget::initAvailableExtInstSets() { 134bdd1243dSDimitry Andric AvailableExtInstSets.clear(); 135bdd1243dSDimitry Andric if (!isOpenCLEnv()) 136bdd1243dSDimitry Andric AvailableExtInstSets.insert(SPIRV::InstructionSet::GLSL_std_450); 137bdd1243dSDimitry Andric else 138bdd1243dSDimitry Andric AvailableExtInstSets.insert(SPIRV::InstructionSet::OpenCL_std); 139bdd1243dSDimitry Andric 140bdd1243dSDimitry Andric // Handle extended instruction sets from extensions. 141bdd1243dSDimitry Andric if (canUseExtension( 142bdd1243dSDimitry Andric SPIRV::Extension::SPV_AMD_shader_trinary_minmax_extension)) { 143bdd1243dSDimitry Andric AvailableExtInstSets.insert( 144bdd1243dSDimitry Andric SPIRV::InstructionSet::SPV_AMD_shader_trinary_minmax); 145bdd1243dSDimitry Andric } 146bdd1243dSDimitry Andric } 147