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" 1581ad6265SDimitry Andric #include "SPIRVGlobalRegistry.h" 1681ad6265SDimitry Andric #include "SPIRVLegalizerInfo.h" 1781ad6265SDimitry Andric #include "SPIRVRegisterBankInfo.h" 1881ad6265SDimitry Andric #include "SPIRVTargetMachine.h" 1981ad6265SDimitry Andric #include "llvm/MC/TargetRegistry.h" 2006c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h" 2181ad6265SDimitry Andric 2281ad6265SDimitry Andric using namespace llvm; 2381ad6265SDimitry Andric 2481ad6265SDimitry Andric #define DEBUG_TYPE "spirv-subtarget" 2581ad6265SDimitry Andric 2681ad6265SDimitry Andric #define GET_SUBTARGETINFO_TARGET_DESC 2781ad6265SDimitry Andric #define GET_SUBTARGETINFO_CTOR 2881ad6265SDimitry Andric #include "SPIRVGenSubtargetInfo.inc" 2981ad6265SDimitry Andric 30*5f757f3fSDimitry Andric cl::list<SPIRV::Extension::Extension> Extensions( 31*5f757f3fSDimitry Andric "spirv-extensions", cl::desc("SPIR-V extensions"), cl::ZeroOrMore, 32*5f757f3fSDimitry Andric cl::Hidden, 33*5f757f3fSDimitry Andric cl::values( 34*5f757f3fSDimitry Andric clEnumValN(SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers, 35*5f757f3fSDimitry Andric "SPV_INTEL_arbitrary_precision_integers", 36*5f757f3fSDimitry Andric "Allows generating arbitrary width integer types"), 37*5f757f3fSDimitry Andric clEnumValN(SPIRV::Extension::SPV_INTEL_optnone, "SPV_INTEL_optnone", 38*5f757f3fSDimitry Andric "Adds OptNoneINTEL value for Function Control mask that " 39*5f757f3fSDimitry Andric "indicates a request to not optimize the function"), 40*5f757f3fSDimitry Andric clEnumValN(SPIRV::Extension::SPV_KHR_no_integer_wrap_decoration, 41*5f757f3fSDimitry Andric "SPV_KHR_no_integer_wrap_decoration", 42*5f757f3fSDimitry Andric "Adds decorations to indicate that a given instruction does " 43*5f757f3fSDimitry Andric "not cause integer wrapping"), 44*5f757f3fSDimitry Andric clEnumValN(SPIRV::Extension::SPV_KHR_expect_assume, 45*5f757f3fSDimitry Andric "SPV_KHR_expect_assume", 46*5f757f3fSDimitry Andric "Provides additional information to a compiler, similar to " 47*5f757f3fSDimitry Andric "the llvm.assume and llvm.expect intrinsics."), 48*5f757f3fSDimitry Andric clEnumValN(SPIRV::Extension::SPV_KHR_bit_instructions, 49*5f757f3fSDimitry Andric "SPV_KHR_bit_instructions", 50*5f757f3fSDimitry Andric "This enables bit instructions to be used by SPIR-V modules " 51*5f757f3fSDimitry Andric "without requiring the Shader capability"))); 52*5f757f3fSDimitry Andric 5381ad6265SDimitry Andric // Compare version numbers, but allow 0 to mean unspecified. 5481ad6265SDimitry Andric static bool isAtLeastVer(uint32_t Target, uint32_t VerToCompareTo) { 5581ad6265SDimitry Andric return Target == 0 || Target >= VerToCompareTo; 5681ad6265SDimitry Andric } 5781ad6265SDimitry Andric 5881ad6265SDimitry Andric SPIRVSubtarget::SPIRVSubtarget(const Triple &TT, const std::string &CPU, 5981ad6265SDimitry Andric const std::string &FS, 6081ad6265SDimitry Andric const SPIRVTargetMachine &TM) 6181ad6265SDimitry Andric : SPIRVGenSubtargetInfo(TT, CPU, /*TuneCPU=*/CPU, FS), 62*5f757f3fSDimitry Andric PointerSize(TM.getPointerSizeInBits(/* AS= */ 0)), SPIRVVersion(0), 63*5f757f3fSDimitry Andric OpenCLVersion(0), InstrInfo(), 64*5f757f3fSDimitry Andric FrameLowering(initSubtargetDependencies(CPU, FS)), TLInfo(TM, *this), 65*5f757f3fSDimitry Andric TargetTriple(TT) { 66bdd1243dSDimitry Andric // The order of initialization is important. 67bdd1243dSDimitry Andric initAvailableExtensions(); 68bdd1243dSDimitry Andric initAvailableExtInstSets(); 69bdd1243dSDimitry Andric 7081ad6265SDimitry Andric GR = std::make_unique<SPIRVGlobalRegistry>(PointerSize); 71fcaf7f86SDimitry Andric CallLoweringInfo = std::make_unique<SPIRVCallLowering>(TLInfo, GR.get()); 7281ad6265SDimitry Andric Legalizer = std::make_unique<SPIRVLegalizerInfo>(*this); 7381ad6265SDimitry Andric RegBankInfo = std::make_unique<SPIRVRegisterBankInfo>(); 7481ad6265SDimitry Andric InstSelector.reset( 7581ad6265SDimitry Andric createSPIRVInstructionSelector(TM, *this, *RegBankInfo.get())); 7681ad6265SDimitry Andric } 7781ad6265SDimitry Andric 7881ad6265SDimitry Andric SPIRVSubtarget &SPIRVSubtarget::initSubtargetDependencies(StringRef CPU, 7981ad6265SDimitry Andric StringRef FS) { 8081ad6265SDimitry Andric ParseSubtargetFeatures(CPU, /*TuneCPU=*/CPU, FS); 8181ad6265SDimitry Andric if (SPIRVVersion == 0) 8281ad6265SDimitry Andric SPIRVVersion = 14; 83bdd1243dSDimitry Andric if (OpenCLVersion == 0) 84bdd1243dSDimitry Andric OpenCLVersion = 22; 8581ad6265SDimitry Andric return *this; 8681ad6265SDimitry Andric } 8781ad6265SDimitry Andric 88bdd1243dSDimitry Andric bool SPIRVSubtarget::canUseExtension(SPIRV::Extension::Extension E) const { 89bdd1243dSDimitry Andric return AvailableExtensions.contains(E); 90bdd1243dSDimitry Andric } 91bdd1243dSDimitry Andric 92bdd1243dSDimitry Andric bool SPIRVSubtarget::canUseExtInstSet( 93bdd1243dSDimitry Andric SPIRV::InstructionSet::InstructionSet E) const { 94bdd1243dSDimitry Andric return AvailableExtInstSets.contains(E); 95bdd1243dSDimitry Andric } 96bdd1243dSDimitry Andric 97bdd1243dSDimitry Andric bool SPIRVSubtarget::isAtLeastSPIRVVer(uint32_t VerToCompareTo) const { 98bdd1243dSDimitry Andric return isAtLeastVer(SPIRVVersion, VerToCompareTo); 99bdd1243dSDimitry Andric } 100bdd1243dSDimitry Andric 101bdd1243dSDimitry Andric bool SPIRVSubtarget::isAtLeastOpenCLVer(uint32_t VerToCompareTo) const { 102*5f757f3fSDimitry Andric if (!isOpenCLEnv()) 103*5f757f3fSDimitry Andric return false; 104bdd1243dSDimitry Andric return isAtLeastVer(OpenCLVersion, VerToCompareTo); 105bdd1243dSDimitry Andric } 106bdd1243dSDimitry Andric 10781ad6265SDimitry Andric // If the SPIR-V version is >= 1.4 we can call OpPtrEqual and OpPtrNotEqual. 10881ad6265SDimitry Andric bool SPIRVSubtarget::canDirectlyComparePointers() const { 10981ad6265SDimitry Andric return isAtLeastVer(SPIRVVersion, 14); 11081ad6265SDimitry Andric } 111bdd1243dSDimitry Andric 112bdd1243dSDimitry Andric void SPIRVSubtarget::initAvailableExtensions() { 113bdd1243dSDimitry Andric AvailableExtensions.clear(); 114bdd1243dSDimitry Andric if (!isOpenCLEnv()) 115bdd1243dSDimitry Andric return; 116*5f757f3fSDimitry Andric 117*5f757f3fSDimitry Andric for (auto Extension : Extensions) 118*5f757f3fSDimitry Andric AvailableExtensions.insert(Extension); 119bdd1243dSDimitry Andric } 120bdd1243dSDimitry Andric 121bdd1243dSDimitry Andric // TODO: use command line args for this rather than just defaults. 122bdd1243dSDimitry Andric // Must have called initAvailableExtensions first. 123bdd1243dSDimitry Andric void SPIRVSubtarget::initAvailableExtInstSets() { 124bdd1243dSDimitry Andric AvailableExtInstSets.clear(); 125bdd1243dSDimitry Andric if (!isOpenCLEnv()) 126bdd1243dSDimitry Andric AvailableExtInstSets.insert(SPIRV::InstructionSet::GLSL_std_450); 127bdd1243dSDimitry Andric else 128bdd1243dSDimitry Andric AvailableExtInstSets.insert(SPIRV::InstructionSet::OpenCL_std); 129bdd1243dSDimitry Andric 130bdd1243dSDimitry Andric // Handle extended instruction sets from extensions. 131bdd1243dSDimitry Andric if (canUseExtension( 132bdd1243dSDimitry Andric SPIRV::Extension::SPV_AMD_shader_trinary_minmax_extension)) { 133bdd1243dSDimitry Andric AvailableExtInstSets.insert( 134bdd1243dSDimitry Andric SPIRV::InstructionSet::SPV_AMD_shader_trinary_minmax); 135bdd1243dSDimitry Andric } 136bdd1243dSDimitry Andric } 137