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" 20*06c3fb27SDimitry 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 3081ad6265SDimitry Andric // Compare version numbers, but allow 0 to mean unspecified. 3181ad6265SDimitry Andric static bool isAtLeastVer(uint32_t Target, uint32_t VerToCompareTo) { 3281ad6265SDimitry Andric return Target == 0 || Target >= VerToCompareTo; 3381ad6265SDimitry Andric } 3481ad6265SDimitry Andric 3581ad6265SDimitry Andric static unsigned computePointerSize(const Triple &TT) { 3681ad6265SDimitry Andric const auto Arch = TT.getArch(); 3781ad6265SDimitry Andric // TODO: unify this with pointers legalization. 3881ad6265SDimitry Andric assert(TT.isSPIRV()); 3981ad6265SDimitry Andric return Arch == Triple::spirv32 ? 32 : 64; 4081ad6265SDimitry Andric } 4181ad6265SDimitry Andric 4281ad6265SDimitry Andric SPIRVSubtarget::SPIRVSubtarget(const Triple &TT, const std::string &CPU, 4381ad6265SDimitry Andric const std::string &FS, 4481ad6265SDimitry Andric const SPIRVTargetMachine &TM) 4581ad6265SDimitry Andric : SPIRVGenSubtargetInfo(TT, CPU, /*TuneCPU=*/CPU, FS), 46bdd1243dSDimitry Andric PointerSize(computePointerSize(TT)), SPIRVVersion(0), OpenCLVersion(0), 47bdd1243dSDimitry Andric InstrInfo(), FrameLowering(initSubtargetDependencies(CPU, FS)), 48bdd1243dSDimitry Andric TLInfo(TM, *this) { 49bdd1243dSDimitry Andric // The order of initialization is important. 50bdd1243dSDimitry Andric initAvailableExtensions(); 51bdd1243dSDimitry Andric initAvailableExtInstSets(); 52bdd1243dSDimitry Andric 5381ad6265SDimitry Andric GR = std::make_unique<SPIRVGlobalRegistry>(PointerSize); 54fcaf7f86SDimitry Andric CallLoweringInfo = std::make_unique<SPIRVCallLowering>(TLInfo, GR.get()); 5581ad6265SDimitry Andric Legalizer = std::make_unique<SPIRVLegalizerInfo>(*this); 5681ad6265SDimitry Andric RegBankInfo = std::make_unique<SPIRVRegisterBankInfo>(); 5781ad6265SDimitry Andric InstSelector.reset( 5881ad6265SDimitry Andric createSPIRVInstructionSelector(TM, *this, *RegBankInfo.get())); 5981ad6265SDimitry Andric } 6081ad6265SDimitry Andric 6181ad6265SDimitry Andric SPIRVSubtarget &SPIRVSubtarget::initSubtargetDependencies(StringRef CPU, 6281ad6265SDimitry Andric StringRef FS) { 6381ad6265SDimitry Andric ParseSubtargetFeatures(CPU, /*TuneCPU=*/CPU, FS); 6481ad6265SDimitry Andric if (SPIRVVersion == 0) 6581ad6265SDimitry Andric SPIRVVersion = 14; 66bdd1243dSDimitry Andric if (OpenCLVersion == 0) 67bdd1243dSDimitry Andric OpenCLVersion = 22; 6881ad6265SDimitry Andric return *this; 6981ad6265SDimitry Andric } 7081ad6265SDimitry Andric 71bdd1243dSDimitry Andric bool SPIRVSubtarget::canUseExtension(SPIRV::Extension::Extension E) const { 72bdd1243dSDimitry Andric return AvailableExtensions.contains(E); 73bdd1243dSDimitry Andric } 74bdd1243dSDimitry Andric 75bdd1243dSDimitry Andric bool SPIRVSubtarget::canUseExtInstSet( 76bdd1243dSDimitry Andric SPIRV::InstructionSet::InstructionSet E) const { 77bdd1243dSDimitry Andric return AvailableExtInstSets.contains(E); 78bdd1243dSDimitry Andric } 79bdd1243dSDimitry Andric 80bdd1243dSDimitry Andric bool SPIRVSubtarget::isAtLeastSPIRVVer(uint32_t VerToCompareTo) const { 81bdd1243dSDimitry Andric return isAtLeastVer(SPIRVVersion, VerToCompareTo); 82bdd1243dSDimitry Andric } 83bdd1243dSDimitry Andric 84bdd1243dSDimitry Andric bool SPIRVSubtarget::isAtLeastOpenCLVer(uint32_t VerToCompareTo) const { 85bdd1243dSDimitry Andric return isAtLeastVer(OpenCLVersion, VerToCompareTo); 86bdd1243dSDimitry Andric } 87bdd1243dSDimitry Andric 8881ad6265SDimitry Andric // If the SPIR-V version is >= 1.4 we can call OpPtrEqual and OpPtrNotEqual. 8981ad6265SDimitry Andric bool SPIRVSubtarget::canDirectlyComparePointers() const { 9081ad6265SDimitry Andric return isAtLeastVer(SPIRVVersion, 14); 9181ad6265SDimitry Andric } 92bdd1243dSDimitry Andric 93bdd1243dSDimitry Andric // TODO: use command line args for this rather than defaults. 94bdd1243dSDimitry Andric void SPIRVSubtarget::initAvailableExtensions() { 95bdd1243dSDimitry Andric AvailableExtensions.clear(); 96bdd1243dSDimitry Andric if (!isOpenCLEnv()) 97bdd1243dSDimitry Andric return; 98bdd1243dSDimitry Andric // A default extension for testing. 99bdd1243dSDimitry Andric AvailableExtensions.insert( 100bdd1243dSDimitry Andric SPIRV::Extension::SPV_KHR_no_integer_wrap_decoration); 101bdd1243dSDimitry Andric } 102bdd1243dSDimitry Andric 103bdd1243dSDimitry Andric // TODO: use command line args for this rather than just defaults. 104bdd1243dSDimitry Andric // Must have called initAvailableExtensions first. 105bdd1243dSDimitry Andric void SPIRVSubtarget::initAvailableExtInstSets() { 106bdd1243dSDimitry Andric AvailableExtInstSets.clear(); 107bdd1243dSDimitry Andric if (!isOpenCLEnv()) 108bdd1243dSDimitry Andric AvailableExtInstSets.insert(SPIRV::InstructionSet::GLSL_std_450); 109bdd1243dSDimitry Andric else 110bdd1243dSDimitry Andric AvailableExtInstSets.insert(SPIRV::InstructionSet::OpenCL_std); 111bdd1243dSDimitry Andric 112bdd1243dSDimitry Andric // Handle extended instruction sets from extensions. 113bdd1243dSDimitry Andric if (canUseExtension( 114bdd1243dSDimitry Andric SPIRV::Extension::SPV_AMD_shader_trinary_minmax_extension)) { 115bdd1243dSDimitry Andric AvailableExtInstSets.insert( 116bdd1243dSDimitry Andric SPIRV::InstructionSet::SPV_AMD_shader_trinary_minmax); 117bdd1243dSDimitry Andric } 118bdd1243dSDimitry Andric } 119