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-exception 6 // 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 "SPIRVGlobalRegistry.h" 16 #include "SPIRVLegalizerInfo.h" 17 #include "SPIRVRegisterBankInfo.h" 18 #include "SPIRVTargetMachine.h" 19 #include "llvm/MC/TargetRegistry.h" 20 #include "llvm/TargetParser/Host.h" 21 22 using namespace llvm; 23 24 #define DEBUG_TYPE "spirv-subtarget" 25 26 #define GET_SUBTARGETINFO_TARGET_DESC 27 #define GET_SUBTARGETINFO_CTOR 28 #include "SPIRVGenSubtargetInfo.inc" 29 30 // Compare version numbers, but allow 0 to mean unspecified. 31 static bool isAtLeastVer(uint32_t Target, uint32_t VerToCompareTo) { 32 return Target == 0 || Target >= VerToCompareTo; 33 } 34 35 static unsigned computePointerSize(const Triple &TT) { 36 const auto Arch = TT.getArch(); 37 // TODO: unify this with pointers legalization. 38 assert(TT.isSPIRV()); 39 return Arch == Triple::spirv32 ? 32 : 64; 40 } 41 42 SPIRVSubtarget::SPIRVSubtarget(const Triple &TT, const std::string &CPU, 43 const std::string &FS, 44 const SPIRVTargetMachine &TM) 45 : SPIRVGenSubtargetInfo(TT, CPU, /*TuneCPU=*/CPU, FS), 46 PointerSize(computePointerSize(TT)), SPIRVVersion(0), OpenCLVersion(0), 47 InstrInfo(), FrameLowering(initSubtargetDependencies(CPU, FS)), 48 TLInfo(TM, *this) { 49 // The order of initialization is important. 50 initAvailableExtensions(); 51 initAvailableExtInstSets(); 52 53 GR = std::make_unique<SPIRVGlobalRegistry>(PointerSize); 54 CallLoweringInfo = std::make_unique<SPIRVCallLowering>(TLInfo, GR.get()); 55 Legalizer = std::make_unique<SPIRVLegalizerInfo>(*this); 56 RegBankInfo = std::make_unique<SPIRVRegisterBankInfo>(); 57 InstSelector.reset( 58 createSPIRVInstructionSelector(TM, *this, *RegBankInfo.get())); 59 } 60 61 SPIRVSubtarget &SPIRVSubtarget::initSubtargetDependencies(StringRef CPU, 62 StringRef FS) { 63 ParseSubtargetFeatures(CPU, /*TuneCPU=*/CPU, FS); 64 if (SPIRVVersion == 0) 65 SPIRVVersion = 14; 66 if (OpenCLVersion == 0) 67 OpenCLVersion = 22; 68 return *this; 69 } 70 71 bool SPIRVSubtarget::canUseExtension(SPIRV::Extension::Extension E) const { 72 return AvailableExtensions.contains(E); 73 } 74 75 bool SPIRVSubtarget::canUseExtInstSet( 76 SPIRV::InstructionSet::InstructionSet E) const { 77 return AvailableExtInstSets.contains(E); 78 } 79 80 bool SPIRVSubtarget::isAtLeastSPIRVVer(uint32_t VerToCompareTo) const { 81 return isAtLeastVer(SPIRVVersion, VerToCompareTo); 82 } 83 84 bool SPIRVSubtarget::isAtLeastOpenCLVer(uint32_t VerToCompareTo) const { 85 return isAtLeastVer(OpenCLVersion, VerToCompareTo); 86 } 87 88 // If the SPIR-V version is >= 1.4 we can call OpPtrEqual and OpPtrNotEqual. 89 bool SPIRVSubtarget::canDirectlyComparePointers() const { 90 return isAtLeastVer(SPIRVVersion, 14); 91 } 92 93 // TODO: use command line args for this rather than defaults. 94 void SPIRVSubtarget::initAvailableExtensions() { 95 AvailableExtensions.clear(); 96 if (!isOpenCLEnv()) 97 return; 98 // A default extension for testing. 99 AvailableExtensions.insert( 100 SPIRV::Extension::SPV_KHR_no_integer_wrap_decoration); 101 } 102 103 // TODO: use command line args for this rather than just defaults. 104 // Must have called initAvailableExtensions first. 105 void SPIRVSubtarget::initAvailableExtInstSets() { 106 AvailableExtInstSets.clear(); 107 if (!isOpenCLEnv()) 108 AvailableExtInstSets.insert(SPIRV::InstructionSet::GLSL_std_450); 109 else 110 AvailableExtInstSets.insert(SPIRV::InstructionSet::OpenCL_std); 111 112 // Handle extended instruction sets from extensions. 113 if (canUseExtension( 114 SPIRV::Extension::SPV_AMD_shader_trinary_minmax_extension)) { 115 AvailableExtInstSets.insert( 116 SPIRV::InstructionSet::SPV_AMD_shader_trinary_minmax); 117 } 118 } 119