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 "SPIRVCommandLine.h" 16 #include "SPIRVGlobalRegistry.h" 17 #include "SPIRVLegalizerInfo.h" 18 #include "SPIRVRegisterBankInfo.h" 19 #include "SPIRVTargetMachine.h" 20 #include "llvm/MC/TargetRegistry.h" 21 #include "llvm/TargetParser/Host.h" 22 23 using namespace llvm; 24 25 #define DEBUG_TYPE "spirv-subtarget" 26 27 #define GET_SUBTARGETINFO_TARGET_DESC 28 #define GET_SUBTARGETINFO_CTOR 29 #include "SPIRVGenSubtargetInfo.inc" 30 31 static cl::opt<bool> 32 SPVTranslatorCompat("translator-compatibility-mode", 33 cl::desc("SPIR-V Translator compatibility mode"), 34 cl::Optional, cl::init(false)); 35 36 static cl::opt<std::set<SPIRV::Extension::Extension>, false, 37 SPIRVExtensionsParser> 38 Extensions("spirv-ext", 39 cl::desc("Specify list of enabled SPIR-V extensions")); 40 41 // Compare version numbers, but allow 0 to mean unspecified. 42 static bool isAtLeastVer(VersionTuple Target, VersionTuple VerToCompareTo) { 43 return Target.empty() || Target >= VerToCompareTo; 44 } 45 46 SPIRVSubtarget::SPIRVSubtarget(const Triple &TT, const std::string &CPU, 47 const std::string &FS, 48 const SPIRVTargetMachine &TM) 49 : SPIRVGenSubtargetInfo(TT, CPU, /*TuneCPU=*/CPU, FS), 50 PointerSize(TM.getPointerSizeInBits(/* AS= */ 0)), InstrInfo(), 51 FrameLowering(initSubtargetDependencies(CPU, FS)), TLInfo(TM, *this), 52 TargetTriple(TT) { 53 switch (TT.getSubArch()) { 54 case Triple::SPIRVSubArch_v10: 55 SPIRVVersion = VersionTuple(1, 0); 56 break; 57 case Triple::SPIRVSubArch_v11: 58 SPIRVVersion = VersionTuple(1, 1); 59 break; 60 case Triple::SPIRVSubArch_v12: 61 SPIRVVersion = VersionTuple(1, 2); 62 break; 63 case Triple::SPIRVSubArch_v13: 64 SPIRVVersion = VersionTuple(1, 3); 65 break; 66 case Triple::SPIRVSubArch_v14: 67 default: 68 SPIRVVersion = VersionTuple(1, 4); 69 break; 70 case Triple::SPIRVSubArch_v15: 71 SPIRVVersion = VersionTuple(1, 5); 72 break; 73 case Triple::SPIRVSubArch_v16: 74 SPIRVVersion = VersionTuple(1, 6); 75 break; 76 } 77 OpenCLVersion = VersionTuple(2, 2); 78 79 // The order of initialization is important. 80 initAvailableExtensions(); 81 initAvailableExtInstSets(); 82 83 GR = std::make_unique<SPIRVGlobalRegistry>(PointerSize); 84 CallLoweringInfo = std::make_unique<SPIRVCallLowering>(TLInfo, GR.get()); 85 InlineAsmInfo = std::make_unique<SPIRVInlineAsmLowering>(TLInfo); 86 Legalizer = std::make_unique<SPIRVLegalizerInfo>(*this); 87 RegBankInfo = std::make_unique<SPIRVRegisterBankInfo>(); 88 InstSelector.reset( 89 createSPIRVInstructionSelector(TM, *this, *RegBankInfo.get())); 90 } 91 92 SPIRVSubtarget &SPIRVSubtarget::initSubtargetDependencies(StringRef CPU, 93 StringRef FS) { 94 ParseSubtargetFeatures(CPU, /*TuneCPU=*/CPU, FS); 95 return *this; 96 } 97 98 bool SPIRVSubtarget::canUseExtension(SPIRV::Extension::Extension E) const { 99 return AvailableExtensions.contains(E); 100 } 101 102 bool SPIRVSubtarget::canUseExtInstSet( 103 SPIRV::InstructionSet::InstructionSet E) const { 104 return AvailableExtInstSets.contains(E); 105 } 106 107 bool SPIRVSubtarget::isAtLeastSPIRVVer(VersionTuple VerToCompareTo) const { 108 return isAtLeastVer(SPIRVVersion, VerToCompareTo); 109 } 110 111 bool SPIRVSubtarget::isAtLeastOpenCLVer(VersionTuple VerToCompareTo) const { 112 if (!isOpenCLEnv()) 113 return false; 114 return isAtLeastVer(OpenCLVersion, VerToCompareTo); 115 } 116 117 // If the SPIR-V version is >= 1.4 we can call OpPtrEqual and OpPtrNotEqual. 118 // In SPIR-V Translator compatibility mode this feature is not available. 119 bool SPIRVSubtarget::canDirectlyComparePointers() const { 120 return !SPVTranslatorCompat && isAtLeastVer(SPIRVVersion, VersionTuple(1, 4)); 121 } 122 123 void SPIRVSubtarget::initAvailableExtensions() { 124 AvailableExtensions.clear(); 125 if (!isOpenCLEnv()) 126 return; 127 128 AvailableExtensions.insert(Extensions.begin(), Extensions.end()); 129 } 130 131 // TODO: use command line args for this rather than just defaults. 132 // Must have called initAvailableExtensions first. 133 void SPIRVSubtarget::initAvailableExtInstSets() { 134 AvailableExtInstSets.clear(); 135 if (!isOpenCLEnv()) 136 AvailableExtInstSets.insert(SPIRV::InstructionSet::GLSL_std_450); 137 else 138 AvailableExtInstSets.insert(SPIRV::InstructionSet::OpenCL_std); 139 140 // Handle extended instruction sets from extensions. 141 if (canUseExtension( 142 SPIRV::Extension::SPV_AMD_shader_trinary_minmax_extension)) { 143 AvailableExtInstSets.insert( 144 SPIRV::InstructionSet::SPV_AMD_shader_trinary_minmax); 145 } 146 } 147