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 cl::list<SPIRV::Extension::Extension> Extensions( 31 "spirv-extensions", cl::desc("SPIR-V extensions"), cl::ZeroOrMore, 32 cl::Hidden, 33 cl::values( 34 clEnumValN(SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers, 35 "SPV_INTEL_arbitrary_precision_integers", 36 "Allows generating arbitrary width integer types"), 37 clEnumValN(SPIRV::Extension::SPV_INTEL_optnone, "SPV_INTEL_optnone", 38 "Adds OptNoneINTEL value for Function Control mask that " 39 "indicates a request to not optimize the function"), 40 clEnumValN(SPIRV::Extension::SPV_KHR_no_integer_wrap_decoration, 41 "SPV_KHR_no_integer_wrap_decoration", 42 "Adds decorations to indicate that a given instruction does " 43 "not cause integer wrapping"), 44 clEnumValN(SPIRV::Extension::SPV_KHR_expect_assume, 45 "SPV_KHR_expect_assume", 46 "Provides additional information to a compiler, similar to " 47 "the llvm.assume and llvm.expect intrinsics."), 48 clEnumValN(SPIRV::Extension::SPV_KHR_bit_instructions, 49 "SPV_KHR_bit_instructions", 50 "This enables bit instructions to be used by SPIR-V modules " 51 "without requiring the Shader capability"))); 52 53 // Compare version numbers, but allow 0 to mean unspecified. 54 static bool isAtLeastVer(uint32_t Target, uint32_t VerToCompareTo) { 55 return Target == 0 || Target >= VerToCompareTo; 56 } 57 58 SPIRVSubtarget::SPIRVSubtarget(const Triple &TT, const std::string &CPU, 59 const std::string &FS, 60 const SPIRVTargetMachine &TM) 61 : SPIRVGenSubtargetInfo(TT, CPU, /*TuneCPU=*/CPU, FS), 62 PointerSize(TM.getPointerSizeInBits(/* AS= */ 0)), SPIRVVersion(0), 63 OpenCLVersion(0), InstrInfo(), 64 FrameLowering(initSubtargetDependencies(CPU, FS)), TLInfo(TM, *this), 65 TargetTriple(TT) { 66 // The order of initialization is important. 67 initAvailableExtensions(); 68 initAvailableExtInstSets(); 69 70 GR = std::make_unique<SPIRVGlobalRegistry>(PointerSize); 71 CallLoweringInfo = std::make_unique<SPIRVCallLowering>(TLInfo, GR.get()); 72 Legalizer = std::make_unique<SPIRVLegalizerInfo>(*this); 73 RegBankInfo = std::make_unique<SPIRVRegisterBankInfo>(); 74 InstSelector.reset( 75 createSPIRVInstructionSelector(TM, *this, *RegBankInfo.get())); 76 } 77 78 SPIRVSubtarget &SPIRVSubtarget::initSubtargetDependencies(StringRef CPU, 79 StringRef FS) { 80 ParseSubtargetFeatures(CPU, /*TuneCPU=*/CPU, FS); 81 if (SPIRVVersion == 0) 82 SPIRVVersion = 14; 83 if (OpenCLVersion == 0) 84 OpenCLVersion = 22; 85 return *this; 86 } 87 88 bool SPIRVSubtarget::canUseExtension(SPIRV::Extension::Extension E) const { 89 return AvailableExtensions.contains(E); 90 } 91 92 bool SPIRVSubtarget::canUseExtInstSet( 93 SPIRV::InstructionSet::InstructionSet E) const { 94 return AvailableExtInstSets.contains(E); 95 } 96 97 bool SPIRVSubtarget::isAtLeastSPIRVVer(uint32_t VerToCompareTo) const { 98 return isAtLeastVer(SPIRVVersion, VerToCompareTo); 99 } 100 101 bool SPIRVSubtarget::isAtLeastOpenCLVer(uint32_t VerToCompareTo) const { 102 if (!isOpenCLEnv()) 103 return false; 104 return isAtLeastVer(OpenCLVersion, VerToCompareTo); 105 } 106 107 // If the SPIR-V version is >= 1.4 we can call OpPtrEqual and OpPtrNotEqual. 108 bool SPIRVSubtarget::canDirectlyComparePointers() const { 109 return isAtLeastVer(SPIRVVersion, 14); 110 } 111 112 void SPIRVSubtarget::initAvailableExtensions() { 113 AvailableExtensions.clear(); 114 if (!isOpenCLEnv()) 115 return; 116 117 for (auto Extension : Extensions) 118 AvailableExtensions.insert(Extension); 119 } 120 121 // TODO: use command line args for this rather than just defaults. 122 // Must have called initAvailableExtensions first. 123 void SPIRVSubtarget::initAvailableExtInstSets() { 124 AvailableExtInstSets.clear(); 125 if (!isOpenCLEnv()) 126 AvailableExtInstSets.insert(SPIRV::InstructionSet::GLSL_std_450); 127 else 128 AvailableExtInstSets.insert(SPIRV::InstructionSet::OpenCL_std); 129 130 // Handle extended instruction sets from extensions. 131 if (canUseExtension( 132 SPIRV::Extension::SPV_AMD_shader_trinary_minmax_extension)) { 133 AvailableExtInstSets.insert( 134 SPIRV::InstructionSet::SPV_AMD_shader_trinary_minmax); 135 } 136 } 137