1 //===- SPIRVModuleAnalysis.cpp - analysis of global instrs & regs - 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 // The analysis collects instructions that should be output at the module level 10 // and performs the global register numbering. 11 // 12 // The results of this analysis are used in AsmPrinter to rename registers 13 // globally and to output required instructions at the module level. 14 // 15 //===----------------------------------------------------------------------===// 16 17 #include "SPIRVModuleAnalysis.h" 18 #include "MCTargetDesc/SPIRVBaseInfo.h" 19 #include "MCTargetDesc/SPIRVMCTargetDesc.h" 20 #include "SPIRV.h" 21 #include "SPIRVSubtarget.h" 22 #include "SPIRVTargetMachine.h" 23 #include "SPIRVUtils.h" 24 #include "TargetInfo/SPIRVTargetInfo.h" 25 #include "llvm/ADT/STLExtras.h" 26 #include "llvm/CodeGen/MachineModuleInfo.h" 27 #include "llvm/CodeGen/TargetPassConfig.h" 28 29 using namespace llvm; 30 31 #define DEBUG_TYPE "spirv-module-analysis" 32 33 static cl::opt<bool> 34 SPVDumpDeps("spv-dump-deps", 35 cl::desc("Dump MIR with SPIR-V dependencies info"), 36 cl::Optional, cl::init(false)); 37 38 char llvm::SPIRVModuleAnalysis::ID = 0; 39 40 namespace llvm { 41 void initializeSPIRVModuleAnalysisPass(PassRegistry &); 42 } // namespace llvm 43 44 INITIALIZE_PASS(SPIRVModuleAnalysis, DEBUG_TYPE, "SPIRV module analysis", true, 45 true) 46 47 // Retrieve an unsigned from an MDNode with a list of them as operands. 48 static unsigned getMetadataUInt(MDNode *MdNode, unsigned OpIndex, 49 unsigned DefaultVal = 0) { 50 if (MdNode && OpIndex < MdNode->getNumOperands()) { 51 const auto &Op = MdNode->getOperand(OpIndex); 52 return mdconst::extract<ConstantInt>(Op)->getZExtValue(); 53 } 54 return DefaultVal; 55 } 56 57 static SPIRV::Requirements 58 getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category, 59 unsigned i, const SPIRVSubtarget &ST, 60 SPIRV::RequirementHandler &Reqs) { 61 unsigned ReqMinVer = getSymbolicOperandMinVersion(Category, i); 62 unsigned ReqMaxVer = getSymbolicOperandMaxVersion(Category, i); 63 unsigned TargetVer = ST.getSPIRVVersion(); 64 bool MinVerOK = !ReqMinVer || !TargetVer || TargetVer >= ReqMinVer; 65 bool MaxVerOK = !ReqMaxVer || !TargetVer || TargetVer <= ReqMaxVer; 66 CapabilityList ReqCaps = getSymbolicOperandCapabilities(Category, i); 67 ExtensionList ReqExts = getSymbolicOperandExtensions(Category, i); 68 if (ReqCaps.empty()) { 69 if (ReqExts.empty()) { 70 if (MinVerOK && MaxVerOK) 71 return {true, {}, {}, ReqMinVer, ReqMaxVer}; 72 return {false, {}, {}, 0, 0}; 73 } 74 } else if (MinVerOK && MaxVerOK) { 75 for (auto Cap : ReqCaps) { // Only need 1 of the capabilities to work. 76 if (Reqs.isCapabilityAvailable(Cap)) 77 return {true, {Cap}, {}, ReqMinVer, ReqMaxVer}; 78 } 79 } 80 // If there are no capabilities, or we can't satisfy the version or 81 // capability requirements, use the list of extensions (if the subtarget 82 // can handle them all). 83 if (llvm::all_of(ReqExts, [&ST](const SPIRV::Extension::Extension &Ext) { 84 return ST.canUseExtension(Ext); 85 })) { 86 return {true, {}, ReqExts, 0, 0}; // TODO: add versions to extensions. 87 } 88 return {false, {}, {}, 0, 0}; 89 } 90 91 void SPIRVModuleAnalysis::setBaseInfo(const Module &M) { 92 MAI.MaxID = 0; 93 for (int i = 0; i < SPIRV::NUM_MODULE_SECTIONS; i++) 94 MAI.MS[i].clear(); 95 MAI.RegisterAliasTable.clear(); 96 MAI.InstrsToDelete.clear(); 97 MAI.FuncMap.clear(); 98 MAI.GlobalVarList.clear(); 99 MAI.ExtInstSetMap.clear(); 100 MAI.Reqs.clear(); 101 MAI.Reqs.initAvailableCapabilities(*ST); 102 103 // TODO: determine memory model and source language from the configuratoin. 104 if (auto MemModel = M.getNamedMetadata("spirv.MemoryModel")) { 105 auto MemMD = MemModel->getOperand(0); 106 MAI.Addr = static_cast<SPIRV::AddressingModel::AddressingModel>( 107 getMetadataUInt(MemMD, 0)); 108 MAI.Mem = 109 static_cast<SPIRV::MemoryModel::MemoryModel>(getMetadataUInt(MemMD, 1)); 110 } else { 111 // TODO: Add support for VulkanMemoryModel. 112 MAI.Mem = ST->isOpenCLEnv() ? SPIRV::MemoryModel::OpenCL 113 : SPIRV::MemoryModel::GLSL450; 114 if (MAI.Mem == SPIRV::MemoryModel::OpenCL) { 115 unsigned PtrSize = ST->getPointerSize(); 116 MAI.Addr = PtrSize == 32 ? SPIRV::AddressingModel::Physical32 117 : PtrSize == 64 ? SPIRV::AddressingModel::Physical64 118 : SPIRV::AddressingModel::Logical; 119 } else { 120 // TODO: Add support for PhysicalStorageBufferAddress. 121 MAI.Addr = SPIRV::AddressingModel::Logical; 122 } 123 } 124 // Get the OpenCL version number from metadata. 125 // TODO: support other source languages. 126 if (auto VerNode = M.getNamedMetadata("opencl.ocl.version")) { 127 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_C; 128 // Construct version literal in accordance with SPIRV-LLVM-Translator. 129 // TODO: support multiple OCL version metadata. 130 assert(VerNode->getNumOperands() > 0 && "Invalid SPIR"); 131 auto VersionMD = VerNode->getOperand(0); 132 unsigned MajorNum = getMetadataUInt(VersionMD, 0, 2); 133 unsigned MinorNum = getMetadataUInt(VersionMD, 1); 134 unsigned RevNum = getMetadataUInt(VersionMD, 2); 135 MAI.SrcLangVersion = (MajorNum * 100 + MinorNum) * 1000 + RevNum; 136 } else { 137 MAI.SrcLang = SPIRV::SourceLanguage::Unknown; 138 MAI.SrcLangVersion = 0; 139 } 140 141 if (auto ExtNode = M.getNamedMetadata("opencl.used.extensions")) { 142 for (unsigned I = 0, E = ExtNode->getNumOperands(); I != E; ++I) { 143 MDNode *MD = ExtNode->getOperand(I); 144 if (!MD || MD->getNumOperands() == 0) 145 continue; 146 for (unsigned J = 0, N = MD->getNumOperands(); J != N; ++J) 147 MAI.SrcExt.insert(cast<MDString>(MD->getOperand(J))->getString()); 148 } 149 } 150 151 // Update required capabilities for this memory model, addressing model and 152 // source language. 153 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::MemoryModelOperand, 154 MAI.Mem, *ST); 155 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::SourceLanguageOperand, 156 MAI.SrcLang, *ST); 157 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::AddressingModelOperand, 158 MAI.Addr, *ST); 159 160 if (ST->isOpenCLEnv()) { 161 // TODO: check if it's required by default. 162 MAI.ExtInstSetMap[static_cast<unsigned>( 163 SPIRV::InstructionSet::OpenCL_std)] = 164 Register::index2VirtReg(MAI.getNextID()); 165 } 166 } 167 168 // Collect MI which defines the register in the given machine function. 169 static void collectDefInstr(Register Reg, const MachineFunction *MF, 170 SPIRV::ModuleAnalysisInfo *MAI, 171 SPIRV::ModuleSectionType MSType, 172 bool DoInsert = true) { 173 assert(MAI->hasRegisterAlias(MF, Reg) && "Cannot find register alias"); 174 MachineInstr *MI = MF->getRegInfo().getUniqueVRegDef(Reg); 175 assert(MI && "There should be an instruction that defines the register"); 176 MAI->setSkipEmission(MI); 177 if (DoInsert) 178 MAI->MS[MSType].push_back(MI); 179 } 180 181 void SPIRVModuleAnalysis::collectGlobalEntities( 182 const std::vector<SPIRV::DTSortableEntry *> &DepsGraph, 183 SPIRV::ModuleSectionType MSType, 184 std::function<bool(const SPIRV::DTSortableEntry *)> Pred, 185 bool UsePreOrder = false) { 186 DenseSet<const SPIRV::DTSortableEntry *> Visited; 187 for (const auto *E : DepsGraph) { 188 std::function<void(const SPIRV::DTSortableEntry *)> RecHoistUtil; 189 // NOTE: here we prefer recursive approach over iterative because 190 // we don't expect depchains long enough to cause SO. 191 RecHoistUtil = [MSType, UsePreOrder, &Visited, &Pred, 192 &RecHoistUtil](const SPIRV::DTSortableEntry *E) { 193 if (Visited.count(E) || !Pred(E)) 194 return; 195 Visited.insert(E); 196 197 // Traversing deps graph in post-order allows us to get rid of 198 // register aliases preprocessing. 199 // But pre-order is required for correct processing of function 200 // declaration and arguments processing. 201 if (!UsePreOrder) 202 for (auto *S : E->getDeps()) 203 RecHoistUtil(S); 204 205 Register GlobalReg = Register::index2VirtReg(MAI.getNextID()); 206 bool IsFirst = true; 207 for (auto &U : *E) { 208 const MachineFunction *MF = U.first; 209 Register Reg = U.second; 210 MAI.setRegisterAlias(MF, Reg, GlobalReg); 211 if (!MF->getRegInfo().getUniqueVRegDef(Reg)) 212 continue; 213 collectDefInstr(Reg, MF, &MAI, MSType, IsFirst); 214 IsFirst = false; 215 if (E->getIsGV()) 216 MAI.GlobalVarList.push_back(MF->getRegInfo().getUniqueVRegDef(Reg)); 217 } 218 219 if (UsePreOrder) 220 for (auto *S : E->getDeps()) 221 RecHoistUtil(S); 222 }; 223 RecHoistUtil(E); 224 } 225 } 226 227 // The function initializes global register alias table for types, consts, 228 // global vars and func decls and collects these instruction for output 229 // at module level. Also it collects explicit OpExtension/OpCapability 230 // instructions. 231 void SPIRVModuleAnalysis::processDefInstrs(const Module &M) { 232 std::vector<SPIRV::DTSortableEntry *> DepsGraph; 233 234 GR->buildDepsGraph(DepsGraph, SPVDumpDeps ? MMI : nullptr); 235 236 collectGlobalEntities( 237 DepsGraph, SPIRV::MB_TypeConstVars, 238 [](const SPIRV::DTSortableEntry *E) { return !E->getIsFunc(); }); 239 240 for (auto F = M.begin(), E = M.end(); F != E; ++F) { 241 MachineFunction *MF = MMI->getMachineFunction(*F); 242 if (!MF) 243 continue; 244 // Iterate through and collect OpExtension/OpCapability instructions. 245 for (MachineBasicBlock &MBB : *MF) { 246 for (MachineInstr &MI : MBB) { 247 if (MI.getOpcode() == SPIRV::OpExtension) { 248 // Here, OpExtension just has a single enum operand, not a string. 249 auto Ext = SPIRV::Extension::Extension(MI.getOperand(0).getImm()); 250 MAI.Reqs.addExtension(Ext); 251 MAI.setSkipEmission(&MI); 252 } else if (MI.getOpcode() == SPIRV::OpCapability) { 253 auto Cap = SPIRV::Capability::Capability(MI.getOperand(0).getImm()); 254 MAI.Reqs.addCapability(Cap); 255 MAI.setSkipEmission(&MI); 256 } 257 } 258 } 259 } 260 261 collectGlobalEntities( 262 DepsGraph, SPIRV::MB_ExtFuncDecls, 263 [](const SPIRV::DTSortableEntry *E) { return E->getIsFunc(); }, true); 264 } 265 266 // True if there is an instruction in the MS list with all the same operands as 267 // the given instruction has (after the given starting index). 268 // TODO: maybe it needs to check Opcodes too. 269 static bool findSameInstrInMS(const MachineInstr &A, 270 SPIRV::ModuleSectionType MSType, 271 SPIRV::ModuleAnalysisInfo &MAI, 272 unsigned StartOpIndex = 0) { 273 for (const auto *B : MAI.MS[MSType]) { 274 const unsigned NumAOps = A.getNumOperands(); 275 if (NumAOps != B->getNumOperands() || A.getNumDefs() != B->getNumDefs()) 276 continue; 277 bool AllOpsMatch = true; 278 for (unsigned i = StartOpIndex; i < NumAOps && AllOpsMatch; ++i) { 279 if (A.getOperand(i).isReg() && B->getOperand(i).isReg()) { 280 Register RegA = A.getOperand(i).getReg(); 281 Register RegB = B->getOperand(i).getReg(); 282 AllOpsMatch = MAI.getRegisterAlias(A.getMF(), RegA) == 283 MAI.getRegisterAlias(B->getMF(), RegB); 284 } else { 285 AllOpsMatch = A.getOperand(i).isIdenticalTo(B->getOperand(i)); 286 } 287 } 288 if (AllOpsMatch) 289 return true; 290 } 291 return false; 292 } 293 294 // Look for IDs declared with Import linkage, and map the corresponding function 295 // to the register defining that variable (which will usually be the result of 296 // an OpFunction). This lets us call externally imported functions using 297 // the correct ID registers. 298 void SPIRVModuleAnalysis::collectFuncNames(MachineInstr &MI, 299 const Function *F) { 300 if (MI.getOpcode() == SPIRV::OpDecorate) { 301 // If it's got Import linkage. 302 auto Dec = MI.getOperand(1).getImm(); 303 if (Dec == static_cast<unsigned>(SPIRV::Decoration::LinkageAttributes)) { 304 auto Lnk = MI.getOperand(MI.getNumOperands() - 1).getImm(); 305 if (Lnk == static_cast<unsigned>(SPIRV::LinkageType::Import)) { 306 // Map imported function name to function ID register. 307 const Function *ImportedFunc = 308 F->getParent()->getFunction(getStringImm(MI, 2)); 309 Register Target = MI.getOperand(0).getReg(); 310 MAI.FuncMap[ImportedFunc] = MAI.getRegisterAlias(MI.getMF(), Target); 311 } 312 } 313 } else if (MI.getOpcode() == SPIRV::OpFunction) { 314 // Record all internal OpFunction declarations. 315 Register Reg = MI.defs().begin()->getReg(); 316 Register GlobalReg = MAI.getRegisterAlias(MI.getMF(), Reg); 317 assert(GlobalReg.isValid()); 318 MAI.FuncMap[F] = GlobalReg; 319 } 320 } 321 322 // Collect the given instruction in the specified MS. We assume global register 323 // numbering has already occurred by this point. We can directly compare reg 324 // arguments when detecting duplicates. 325 static void collectOtherInstr(MachineInstr &MI, SPIRV::ModuleAnalysisInfo &MAI, 326 SPIRV::ModuleSectionType MSType, 327 bool Append = true) { 328 MAI.setSkipEmission(&MI); 329 if (findSameInstrInMS(MI, MSType, MAI)) 330 return; // Found a duplicate, so don't add it. 331 // No duplicates, so add it. 332 if (Append) 333 MAI.MS[MSType].push_back(&MI); 334 else 335 MAI.MS[MSType].insert(MAI.MS[MSType].begin(), &MI); 336 } 337 338 // Some global instructions make reference to function-local ID regs, so cannot 339 // be correctly collected until these registers are globally numbered. 340 void SPIRVModuleAnalysis::processOtherInstrs(const Module &M) { 341 for (auto F = M.begin(), E = M.end(); F != E; ++F) { 342 if ((*F).isDeclaration()) 343 continue; 344 MachineFunction *MF = MMI->getMachineFunction(*F); 345 assert(MF); 346 for (MachineBasicBlock &MBB : *MF) 347 for (MachineInstr &MI : MBB) { 348 if (MAI.getSkipEmission(&MI)) 349 continue; 350 const unsigned OpCode = MI.getOpcode(); 351 if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) { 352 collectOtherInstr(MI, MAI, SPIRV::MB_DebugNames); 353 } else if (OpCode == SPIRV::OpEntryPoint) { 354 collectOtherInstr(MI, MAI, SPIRV::MB_EntryPoints); 355 } else if (TII->isDecorationInstr(MI)) { 356 collectOtherInstr(MI, MAI, SPIRV::MB_Annotations); 357 collectFuncNames(MI, &*F); 358 } else if (TII->isConstantInstr(MI)) { 359 // Now OpSpecConstant*s are not in DT, 360 // but they need to be collected anyway. 361 collectOtherInstr(MI, MAI, SPIRV::MB_TypeConstVars); 362 } else if (OpCode == SPIRV::OpFunction) { 363 collectFuncNames(MI, &*F); 364 } else if (OpCode == SPIRV::OpTypeForwardPointer) { 365 collectOtherInstr(MI, MAI, SPIRV::MB_TypeConstVars, false); 366 } 367 } 368 } 369 } 370 371 // Number registers in all functions globally from 0 onwards and store 372 // the result in global register alias table. Some registers are already 373 // numbered in collectGlobalEntities. 374 void SPIRVModuleAnalysis::numberRegistersGlobally(const Module &M) { 375 for (auto F = M.begin(), E = M.end(); F != E; ++F) { 376 if ((*F).isDeclaration()) 377 continue; 378 MachineFunction *MF = MMI->getMachineFunction(*F); 379 assert(MF); 380 for (MachineBasicBlock &MBB : *MF) { 381 for (MachineInstr &MI : MBB) { 382 for (MachineOperand &Op : MI.operands()) { 383 if (!Op.isReg()) 384 continue; 385 Register Reg = Op.getReg(); 386 if (MAI.hasRegisterAlias(MF, Reg)) 387 continue; 388 Register NewReg = Register::index2VirtReg(MAI.getNextID()); 389 MAI.setRegisterAlias(MF, Reg, NewReg); 390 } 391 if (MI.getOpcode() != SPIRV::OpExtInst) 392 continue; 393 auto Set = MI.getOperand(2).getImm(); 394 if (!MAI.ExtInstSetMap.contains(Set)) 395 MAI.ExtInstSetMap[Set] = Register::index2VirtReg(MAI.getNextID()); 396 } 397 } 398 } 399 } 400 401 // RequirementHandler implementations. 402 void SPIRV::RequirementHandler::getAndAddRequirements( 403 SPIRV::OperandCategory::OperandCategory Category, uint32_t i, 404 const SPIRVSubtarget &ST) { 405 addRequirements(getSymbolicOperandRequirements(Category, i, ST, *this)); 406 } 407 408 void SPIRV::RequirementHandler::pruneCapabilities( 409 const CapabilityList &ToPrune) { 410 for (const auto &Cap : ToPrune) { 411 AllCaps.insert(Cap); 412 auto FoundIndex = std::find(MinimalCaps.begin(), MinimalCaps.end(), Cap); 413 if (FoundIndex != MinimalCaps.end()) 414 MinimalCaps.erase(FoundIndex); 415 CapabilityList ImplicitDecls = 416 getSymbolicOperandCapabilities(OperandCategory::CapabilityOperand, Cap); 417 pruneCapabilities(ImplicitDecls); 418 } 419 } 420 421 void SPIRV::RequirementHandler::addCapabilities(const CapabilityList &ToAdd) { 422 for (const auto &Cap : ToAdd) { 423 bool IsNewlyInserted = AllCaps.insert(Cap).second; 424 if (!IsNewlyInserted) // Don't re-add if it's already been declared. 425 continue; 426 CapabilityList ImplicitDecls = 427 getSymbolicOperandCapabilities(OperandCategory::CapabilityOperand, Cap); 428 pruneCapabilities(ImplicitDecls); 429 MinimalCaps.push_back(Cap); 430 } 431 } 432 433 void SPIRV::RequirementHandler::addRequirements( 434 const SPIRV::Requirements &Req) { 435 if (!Req.IsSatisfiable) 436 report_fatal_error("Adding SPIR-V requirements this target can't satisfy."); 437 438 if (Req.Cap.has_value()) 439 addCapabilities({Req.Cap.value()}); 440 441 addExtensions(Req.Exts); 442 443 if (Req.MinVer) { 444 if (MaxVersion && Req.MinVer > MaxVersion) { 445 LLVM_DEBUG(dbgs() << "Conflicting version requirements: >= " << Req.MinVer 446 << " and <= " << MaxVersion << "\n"); 447 report_fatal_error("Adding SPIR-V requirements that can't be satisfied."); 448 } 449 450 if (MinVersion == 0 || Req.MinVer > MinVersion) 451 MinVersion = Req.MinVer; 452 } 453 454 if (Req.MaxVer) { 455 if (MinVersion && Req.MaxVer < MinVersion) { 456 LLVM_DEBUG(dbgs() << "Conflicting version requirements: <= " << Req.MaxVer 457 << " and >= " << MinVersion << "\n"); 458 report_fatal_error("Adding SPIR-V requirements that can't be satisfied."); 459 } 460 461 if (MaxVersion == 0 || Req.MaxVer < MaxVersion) 462 MaxVersion = Req.MaxVer; 463 } 464 } 465 466 void SPIRV::RequirementHandler::checkSatisfiable( 467 const SPIRVSubtarget &ST) const { 468 // Report as many errors as possible before aborting the compilation. 469 bool IsSatisfiable = true; 470 auto TargetVer = ST.getSPIRVVersion(); 471 472 if (MaxVersion && TargetVer && MaxVersion < TargetVer) { 473 LLVM_DEBUG( 474 dbgs() << "Target SPIR-V version too high for required features\n" 475 << "Required max version: " << MaxVersion << " target version " 476 << TargetVer << "\n"); 477 IsSatisfiable = false; 478 } 479 480 if (MinVersion && TargetVer && MinVersion > TargetVer) { 481 LLVM_DEBUG(dbgs() << "Target SPIR-V version too low for required features\n" 482 << "Required min version: " << MinVersion 483 << " target version " << TargetVer << "\n"); 484 IsSatisfiable = false; 485 } 486 487 if (MinVersion && MaxVersion && MinVersion > MaxVersion) { 488 LLVM_DEBUG( 489 dbgs() 490 << "Version is too low for some features and too high for others.\n" 491 << "Required SPIR-V min version: " << MinVersion 492 << " required SPIR-V max version " << MaxVersion << "\n"); 493 IsSatisfiable = false; 494 } 495 496 for (auto Cap : MinimalCaps) { 497 if (AvailableCaps.contains(Cap)) 498 continue; 499 LLVM_DEBUG(dbgs() << "Capability not supported: " 500 << getSymbolicOperandMnemonic( 501 OperandCategory::CapabilityOperand, Cap) 502 << "\n"); 503 IsSatisfiable = false; 504 } 505 506 for (auto Ext : AllExtensions) { 507 if (ST.canUseExtension(Ext)) 508 continue; 509 LLVM_DEBUG(dbgs() << "Extension not supported: " 510 << getSymbolicOperandMnemonic( 511 OperandCategory::ExtensionOperand, Ext) 512 << "\n"); 513 IsSatisfiable = false; 514 } 515 516 if (!IsSatisfiable) 517 report_fatal_error("Unable to meet SPIR-V requirements for this target."); 518 } 519 520 // Add the given capabilities and all their implicitly defined capabilities too. 521 void SPIRV::RequirementHandler::addAvailableCaps(const CapabilityList &ToAdd) { 522 for (const auto Cap : ToAdd) 523 if (AvailableCaps.insert(Cap).second) 524 addAvailableCaps(getSymbolicOperandCapabilities( 525 SPIRV::OperandCategory::CapabilityOperand, Cap)); 526 } 527 528 void SPIRV::RequirementHandler::removeCapabilityIf( 529 const Capability::Capability ToRemove, 530 const Capability::Capability IfPresent) { 531 if (AllCaps.contains(IfPresent)) 532 AllCaps.erase(ToRemove); 533 } 534 535 namespace llvm { 536 namespace SPIRV { 537 void RequirementHandler::initAvailableCapabilities(const SPIRVSubtarget &ST) { 538 if (ST.isOpenCLEnv()) { 539 initAvailableCapabilitiesForOpenCL(ST); 540 return; 541 } 542 543 if (ST.isVulkanEnv()) { 544 initAvailableCapabilitiesForVulkan(ST); 545 return; 546 } 547 548 report_fatal_error("Unimplemented environment for SPIR-V generation."); 549 } 550 551 void RequirementHandler::initAvailableCapabilitiesForOpenCL( 552 const SPIRVSubtarget &ST) { 553 // Add the min requirements for different OpenCL and SPIR-V versions. 554 addAvailableCaps({Capability::Addresses, Capability::Float16Buffer, 555 Capability::Int16, Capability::Int8, Capability::Kernel, 556 Capability::Linkage, Capability::Vector16, 557 Capability::Groups, Capability::GenericPointer, 558 Capability::Shader}); 559 if (ST.hasOpenCLFullProfile()) 560 addAvailableCaps({Capability::Int64, Capability::Int64Atomics}); 561 if (ST.hasOpenCLImageSupport()) { 562 addAvailableCaps({Capability::ImageBasic, Capability::LiteralSampler, 563 Capability::Image1D, Capability::SampledBuffer, 564 Capability::ImageBuffer}); 565 if (ST.isAtLeastOpenCLVer(20)) 566 addAvailableCaps({Capability::ImageReadWrite}); 567 } 568 if (ST.isAtLeastSPIRVVer(11) && ST.isAtLeastOpenCLVer(22)) 569 addAvailableCaps({Capability::SubgroupDispatch, Capability::PipeStorage}); 570 if (ST.isAtLeastSPIRVVer(13)) 571 addAvailableCaps({Capability::GroupNonUniform, 572 Capability::GroupNonUniformVote, 573 Capability::GroupNonUniformArithmetic, 574 Capability::GroupNonUniformBallot, 575 Capability::GroupNonUniformClustered, 576 Capability::GroupNonUniformShuffle, 577 Capability::GroupNonUniformShuffleRelative}); 578 if (ST.isAtLeastSPIRVVer(14)) 579 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero, 580 Capability::SignedZeroInfNanPreserve, 581 Capability::RoundingModeRTE, 582 Capability::RoundingModeRTZ}); 583 // TODO: verify if this needs some checks. 584 addAvailableCaps({Capability::Float16, Capability::Float64}); 585 586 // Add capabilities enabled by extensions. 587 for (auto Extension : ST.getAllAvailableExtensions()) { 588 CapabilityList EnabledCapabilities = 589 getCapabilitiesEnabledByExtension(Extension); 590 addAvailableCaps(EnabledCapabilities); 591 } 592 593 // TODO: add OpenCL extensions. 594 } 595 596 void RequirementHandler::initAvailableCapabilitiesForVulkan( 597 const SPIRVSubtarget &ST) { 598 addAvailableCaps({Capability::Shader, Capability::Linkage}); 599 600 // Provided by Vulkan version 1.0. 601 addAvailableCaps({Capability::Int16, Capability::Int64, Capability::Float64}); 602 } 603 604 } // namespace SPIRV 605 } // namespace llvm 606 607 // Add the required capabilities from a decoration instruction (including 608 // BuiltIns). 609 static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex, 610 SPIRV::RequirementHandler &Reqs, 611 const SPIRVSubtarget &ST) { 612 int64_t DecOp = MI.getOperand(DecIndex).getImm(); 613 auto Dec = static_cast<SPIRV::Decoration::Decoration>(DecOp); 614 Reqs.addRequirements(getSymbolicOperandRequirements( 615 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs)); 616 617 if (Dec == SPIRV::Decoration::BuiltIn) { 618 int64_t BuiltInOp = MI.getOperand(DecIndex + 1).getImm(); 619 auto BuiltIn = static_cast<SPIRV::BuiltIn::BuiltIn>(BuiltInOp); 620 Reqs.addRequirements(getSymbolicOperandRequirements( 621 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs)); 622 } 623 } 624 625 // Add requirements for image handling. 626 static void addOpTypeImageReqs(const MachineInstr &MI, 627 SPIRV::RequirementHandler &Reqs, 628 const SPIRVSubtarget &ST) { 629 assert(MI.getNumOperands() >= 8 && "Insufficient operands for OpTypeImage"); 630 // The operand indices used here are based on the OpTypeImage layout, which 631 // the MachineInstr follows as well. 632 int64_t ImgFormatOp = MI.getOperand(7).getImm(); 633 auto ImgFormat = static_cast<SPIRV::ImageFormat::ImageFormat>(ImgFormatOp); 634 Reqs.getAndAddRequirements(SPIRV::OperandCategory::ImageFormatOperand, 635 ImgFormat, ST); 636 637 bool IsArrayed = MI.getOperand(4).getImm() == 1; 638 bool IsMultisampled = MI.getOperand(5).getImm() == 1; 639 bool NoSampler = MI.getOperand(6).getImm() == 2; 640 // Add dimension requirements. 641 assert(MI.getOperand(2).isImm()); 642 switch (MI.getOperand(2).getImm()) { 643 case SPIRV::Dim::DIM_1D: 644 Reqs.addRequirements(NoSampler ? SPIRV::Capability::Image1D 645 : SPIRV::Capability::Sampled1D); 646 break; 647 case SPIRV::Dim::DIM_2D: 648 if (IsMultisampled && NoSampler) 649 Reqs.addRequirements(SPIRV::Capability::ImageMSArray); 650 break; 651 case SPIRV::Dim::DIM_Cube: 652 Reqs.addRequirements(SPIRV::Capability::Shader); 653 if (IsArrayed) 654 Reqs.addRequirements(NoSampler ? SPIRV::Capability::ImageCubeArray 655 : SPIRV::Capability::SampledCubeArray); 656 break; 657 case SPIRV::Dim::DIM_Rect: 658 Reqs.addRequirements(NoSampler ? SPIRV::Capability::ImageRect 659 : SPIRV::Capability::SampledRect); 660 break; 661 case SPIRV::Dim::DIM_Buffer: 662 Reqs.addRequirements(NoSampler ? SPIRV::Capability::ImageBuffer 663 : SPIRV::Capability::SampledBuffer); 664 break; 665 case SPIRV::Dim::DIM_SubpassData: 666 Reqs.addRequirements(SPIRV::Capability::InputAttachment); 667 break; 668 } 669 670 // Has optional access qualifier. 671 // TODO: check if it's OpenCL's kernel. 672 if (MI.getNumOperands() > 8 && 673 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite) 674 Reqs.addRequirements(SPIRV::Capability::ImageReadWrite); 675 else 676 Reqs.addRequirements(SPIRV::Capability::ImageBasic); 677 } 678 679 void addInstrRequirements(const MachineInstr &MI, 680 SPIRV::RequirementHandler &Reqs, 681 const SPIRVSubtarget &ST) { 682 switch (MI.getOpcode()) { 683 case SPIRV::OpMemoryModel: { 684 int64_t Addr = MI.getOperand(0).getImm(); 685 Reqs.getAndAddRequirements(SPIRV::OperandCategory::AddressingModelOperand, 686 Addr, ST); 687 int64_t Mem = MI.getOperand(1).getImm(); 688 Reqs.getAndAddRequirements(SPIRV::OperandCategory::MemoryModelOperand, Mem, 689 ST); 690 break; 691 } 692 case SPIRV::OpEntryPoint: { 693 int64_t Exe = MI.getOperand(0).getImm(); 694 Reqs.getAndAddRequirements(SPIRV::OperandCategory::ExecutionModelOperand, 695 Exe, ST); 696 break; 697 } 698 case SPIRV::OpExecutionMode: 699 case SPIRV::OpExecutionModeId: { 700 int64_t Exe = MI.getOperand(1).getImm(); 701 Reqs.getAndAddRequirements(SPIRV::OperandCategory::ExecutionModeOperand, 702 Exe, ST); 703 break; 704 } 705 case SPIRV::OpTypeMatrix: 706 Reqs.addCapability(SPIRV::Capability::Matrix); 707 break; 708 case SPIRV::OpTypeInt: { 709 unsigned BitWidth = MI.getOperand(1).getImm(); 710 if (BitWidth == 64) 711 Reqs.addCapability(SPIRV::Capability::Int64); 712 else if (BitWidth == 16) 713 Reqs.addCapability(SPIRV::Capability::Int16); 714 else if (BitWidth == 8) 715 Reqs.addCapability(SPIRV::Capability::Int8); 716 break; 717 } 718 case SPIRV::OpTypeFloat: { 719 unsigned BitWidth = MI.getOperand(1).getImm(); 720 if (BitWidth == 64) 721 Reqs.addCapability(SPIRV::Capability::Float64); 722 else if (BitWidth == 16) 723 Reqs.addCapability(SPIRV::Capability::Float16); 724 break; 725 } 726 case SPIRV::OpTypeVector: { 727 unsigned NumComponents = MI.getOperand(2).getImm(); 728 if (NumComponents == 8 || NumComponents == 16) 729 Reqs.addCapability(SPIRV::Capability::Vector16); 730 break; 731 } 732 case SPIRV::OpTypePointer: { 733 auto SC = MI.getOperand(1).getImm(); 734 Reqs.getAndAddRequirements(SPIRV::OperandCategory::StorageClassOperand, SC, 735 ST); 736 // If it's a type of pointer to float16, add Float16Buffer capability. 737 assert(MI.getOperand(2).isReg()); 738 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo(); 739 SPIRVType *TypeDef = MRI.getVRegDef(MI.getOperand(2).getReg()); 740 if (TypeDef->getOpcode() == SPIRV::OpTypeFloat && 741 TypeDef->getOperand(1).getImm() == 16) 742 Reqs.addCapability(SPIRV::Capability::Float16Buffer); 743 break; 744 } 745 case SPIRV::OpBitReverse: 746 case SPIRV::OpBitFieldInsert: 747 case SPIRV::OpBitFieldSExtract: 748 case SPIRV::OpBitFieldUExtract: 749 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) { 750 Reqs.addCapability(SPIRV::Capability::Shader); 751 break; 752 } 753 Reqs.addExtension(SPIRV::Extension::SPV_KHR_bit_instructions); 754 Reqs.addCapability(SPIRV::Capability::BitInstructions); 755 break; 756 case SPIRV::OpTypeRuntimeArray: 757 Reqs.addCapability(SPIRV::Capability::Shader); 758 break; 759 case SPIRV::OpTypeOpaque: 760 case SPIRV::OpTypeEvent: 761 Reqs.addCapability(SPIRV::Capability::Kernel); 762 break; 763 case SPIRV::OpTypePipe: 764 case SPIRV::OpTypeReserveId: 765 Reqs.addCapability(SPIRV::Capability::Pipes); 766 break; 767 case SPIRV::OpTypeDeviceEvent: 768 case SPIRV::OpTypeQueue: 769 case SPIRV::OpBuildNDRange: 770 Reqs.addCapability(SPIRV::Capability::DeviceEnqueue); 771 break; 772 case SPIRV::OpDecorate: 773 case SPIRV::OpDecorateId: 774 case SPIRV::OpDecorateString: 775 addOpDecorateReqs(MI, 1, Reqs, ST); 776 break; 777 case SPIRV::OpMemberDecorate: 778 case SPIRV::OpMemberDecorateString: 779 addOpDecorateReqs(MI, 2, Reqs, ST); 780 break; 781 case SPIRV::OpInBoundsPtrAccessChain: 782 Reqs.addCapability(SPIRV::Capability::Addresses); 783 break; 784 case SPIRV::OpConstantSampler: 785 Reqs.addCapability(SPIRV::Capability::LiteralSampler); 786 break; 787 case SPIRV::OpTypeImage: 788 addOpTypeImageReqs(MI, Reqs, ST); 789 break; 790 case SPIRV::OpTypeSampler: 791 Reqs.addCapability(SPIRV::Capability::ImageBasic); 792 break; 793 case SPIRV::OpTypeForwardPointer: 794 // TODO: check if it's OpenCL's kernel. 795 Reqs.addCapability(SPIRV::Capability::Addresses); 796 break; 797 case SPIRV::OpAtomicFlagTestAndSet: 798 case SPIRV::OpAtomicLoad: 799 case SPIRV::OpAtomicStore: 800 case SPIRV::OpAtomicExchange: 801 case SPIRV::OpAtomicCompareExchange: 802 case SPIRV::OpAtomicIIncrement: 803 case SPIRV::OpAtomicIDecrement: 804 case SPIRV::OpAtomicIAdd: 805 case SPIRV::OpAtomicISub: 806 case SPIRV::OpAtomicUMin: 807 case SPIRV::OpAtomicUMax: 808 case SPIRV::OpAtomicSMin: 809 case SPIRV::OpAtomicSMax: 810 case SPIRV::OpAtomicAnd: 811 case SPIRV::OpAtomicOr: 812 case SPIRV::OpAtomicXor: { 813 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo(); 814 const MachineInstr *InstrPtr = &MI; 815 if (MI.getOpcode() == SPIRV::OpAtomicStore) { 816 assert(MI.getOperand(3).isReg()); 817 InstrPtr = MRI.getVRegDef(MI.getOperand(3).getReg()); 818 assert(InstrPtr && "Unexpected type instruction for OpAtomicStore"); 819 } 820 assert(InstrPtr->getOperand(1).isReg() && "Unexpected operand in atomic"); 821 Register TypeReg = InstrPtr->getOperand(1).getReg(); 822 SPIRVType *TypeDef = MRI.getVRegDef(TypeReg); 823 if (TypeDef->getOpcode() == SPIRV::OpTypeInt) { 824 unsigned BitWidth = TypeDef->getOperand(1).getImm(); 825 if (BitWidth == 64) 826 Reqs.addCapability(SPIRV::Capability::Int64Atomics); 827 } 828 break; 829 } 830 case SPIRV::OpGroupNonUniformIAdd: 831 case SPIRV::OpGroupNonUniformFAdd: 832 case SPIRV::OpGroupNonUniformIMul: 833 case SPIRV::OpGroupNonUniformFMul: 834 case SPIRV::OpGroupNonUniformSMin: 835 case SPIRV::OpGroupNonUniformUMin: 836 case SPIRV::OpGroupNonUniformFMin: 837 case SPIRV::OpGroupNonUniformSMax: 838 case SPIRV::OpGroupNonUniformUMax: 839 case SPIRV::OpGroupNonUniformFMax: 840 case SPIRV::OpGroupNonUniformBitwiseAnd: 841 case SPIRV::OpGroupNonUniformBitwiseOr: 842 case SPIRV::OpGroupNonUniformBitwiseXor: 843 case SPIRV::OpGroupNonUniformLogicalAnd: 844 case SPIRV::OpGroupNonUniformLogicalOr: 845 case SPIRV::OpGroupNonUniformLogicalXor: { 846 assert(MI.getOperand(3).isImm()); 847 int64_t GroupOp = MI.getOperand(3).getImm(); 848 switch (GroupOp) { 849 case SPIRV::GroupOperation::Reduce: 850 case SPIRV::GroupOperation::InclusiveScan: 851 case SPIRV::GroupOperation::ExclusiveScan: 852 Reqs.addCapability(SPIRV::Capability::Kernel); 853 Reqs.addCapability(SPIRV::Capability::GroupNonUniformArithmetic); 854 Reqs.addCapability(SPIRV::Capability::GroupNonUniformBallot); 855 break; 856 case SPIRV::GroupOperation::ClusteredReduce: 857 Reqs.addCapability(SPIRV::Capability::GroupNonUniformClustered); 858 break; 859 case SPIRV::GroupOperation::PartitionedReduceNV: 860 case SPIRV::GroupOperation::PartitionedInclusiveScanNV: 861 case SPIRV::GroupOperation::PartitionedExclusiveScanNV: 862 Reqs.addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV); 863 break; 864 } 865 break; 866 } 867 case SPIRV::OpGroupNonUniformShuffle: 868 case SPIRV::OpGroupNonUniformShuffleXor: 869 Reqs.addCapability(SPIRV::Capability::GroupNonUniformShuffle); 870 break; 871 case SPIRV::OpGroupNonUniformShuffleUp: 872 case SPIRV::OpGroupNonUniformShuffleDown: 873 Reqs.addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative); 874 break; 875 case SPIRV::OpGroupAll: 876 case SPIRV::OpGroupAny: 877 case SPIRV::OpGroupBroadcast: 878 case SPIRV::OpGroupIAdd: 879 case SPIRV::OpGroupFAdd: 880 case SPIRV::OpGroupFMin: 881 case SPIRV::OpGroupUMin: 882 case SPIRV::OpGroupSMin: 883 case SPIRV::OpGroupFMax: 884 case SPIRV::OpGroupUMax: 885 case SPIRV::OpGroupSMax: 886 Reqs.addCapability(SPIRV::Capability::Groups); 887 break; 888 case SPIRV::OpGroupNonUniformElect: 889 Reqs.addCapability(SPIRV::Capability::GroupNonUniform); 890 break; 891 case SPIRV::OpGroupNonUniformAll: 892 case SPIRV::OpGroupNonUniformAny: 893 case SPIRV::OpGroupNonUniformAllEqual: 894 Reqs.addCapability(SPIRV::Capability::GroupNonUniformVote); 895 break; 896 case SPIRV::OpGroupNonUniformBroadcast: 897 case SPIRV::OpGroupNonUniformBroadcastFirst: 898 case SPIRV::OpGroupNonUniformBallot: 899 case SPIRV::OpGroupNonUniformInverseBallot: 900 case SPIRV::OpGroupNonUniformBallotBitExtract: 901 case SPIRV::OpGroupNonUniformBallotBitCount: 902 case SPIRV::OpGroupNonUniformBallotFindLSB: 903 case SPIRV::OpGroupNonUniformBallotFindMSB: 904 Reqs.addCapability(SPIRV::Capability::GroupNonUniformBallot); 905 break; 906 case SPIRV::OpAssumeTrueKHR: 907 case SPIRV::OpExpectKHR: 908 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) { 909 Reqs.addExtension(SPIRV::Extension::SPV_KHR_expect_assume); 910 Reqs.addCapability(SPIRV::Capability::ExpectAssumeKHR); 911 } 912 break; 913 default: 914 break; 915 } 916 917 // If we require capability Shader, then we can remove the requirement for 918 // the BitInstructions capability, since Shader is a superset capability 919 // of BitInstructions. 920 Reqs.removeCapabilityIf(SPIRV::Capability::BitInstructions, 921 SPIRV::Capability::Shader); 922 } 923 924 static void collectReqs(const Module &M, SPIRV::ModuleAnalysisInfo &MAI, 925 MachineModuleInfo *MMI, const SPIRVSubtarget &ST) { 926 // Collect requirements for existing instructions. 927 for (auto F = M.begin(), E = M.end(); F != E; ++F) { 928 MachineFunction *MF = MMI->getMachineFunction(*F); 929 if (!MF) 930 continue; 931 for (const MachineBasicBlock &MBB : *MF) 932 for (const MachineInstr &MI : MBB) 933 addInstrRequirements(MI, MAI.Reqs, ST); 934 } 935 // Collect requirements for OpExecutionMode instructions. 936 auto Node = M.getNamedMetadata("spirv.ExecutionMode"); 937 if (Node) { 938 for (unsigned i = 0; i < Node->getNumOperands(); i++) { 939 MDNode *MDN = cast<MDNode>(Node->getOperand(i)); 940 const MDOperand &MDOp = MDN->getOperand(1); 941 if (auto *CMeta = dyn_cast<ConstantAsMetadata>(MDOp)) { 942 Constant *C = CMeta->getValue(); 943 if (ConstantInt *Const = dyn_cast<ConstantInt>(C)) { 944 auto EM = Const->getZExtValue(); 945 MAI.Reqs.getAndAddRequirements( 946 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST); 947 } 948 } 949 } 950 } 951 for (auto FI = M.begin(), E = M.end(); FI != E; ++FI) { 952 const Function &F = *FI; 953 if (F.isDeclaration()) 954 continue; 955 if (F.getMetadata("reqd_work_group_size")) 956 MAI.Reqs.getAndAddRequirements( 957 SPIRV::OperandCategory::ExecutionModeOperand, 958 SPIRV::ExecutionMode::LocalSize, ST); 959 if (F.getFnAttribute("hlsl.numthreads").isValid()) { 960 MAI.Reqs.getAndAddRequirements( 961 SPIRV::OperandCategory::ExecutionModeOperand, 962 SPIRV::ExecutionMode::LocalSize, ST); 963 } 964 if (F.getMetadata("work_group_size_hint")) 965 MAI.Reqs.getAndAddRequirements( 966 SPIRV::OperandCategory::ExecutionModeOperand, 967 SPIRV::ExecutionMode::LocalSizeHint, ST); 968 if (F.getMetadata("intel_reqd_sub_group_size")) 969 MAI.Reqs.getAndAddRequirements( 970 SPIRV::OperandCategory::ExecutionModeOperand, 971 SPIRV::ExecutionMode::SubgroupSize, ST); 972 if (F.getMetadata("vec_type_hint")) 973 MAI.Reqs.getAndAddRequirements( 974 SPIRV::OperandCategory::ExecutionModeOperand, 975 SPIRV::ExecutionMode::VecTypeHint, ST); 976 977 if (F.hasOptNone() && 978 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) { 979 // Output OpCapability OptNoneINTEL. 980 MAI.Reqs.addExtension(SPIRV::Extension::SPV_INTEL_optnone); 981 MAI.Reqs.addCapability(SPIRV::Capability::OptNoneINTEL); 982 } 983 } 984 } 985 986 static unsigned getFastMathFlags(const MachineInstr &I) { 987 unsigned Flags = SPIRV::FPFastMathMode::None; 988 if (I.getFlag(MachineInstr::MIFlag::FmNoNans)) 989 Flags |= SPIRV::FPFastMathMode::NotNaN; 990 if (I.getFlag(MachineInstr::MIFlag::FmNoInfs)) 991 Flags |= SPIRV::FPFastMathMode::NotInf; 992 if (I.getFlag(MachineInstr::MIFlag::FmNsz)) 993 Flags |= SPIRV::FPFastMathMode::NSZ; 994 if (I.getFlag(MachineInstr::MIFlag::FmArcp)) 995 Flags |= SPIRV::FPFastMathMode::AllowRecip; 996 if (I.getFlag(MachineInstr::MIFlag::FmReassoc)) 997 Flags |= SPIRV::FPFastMathMode::Fast; 998 return Flags; 999 } 1000 1001 static void handleMIFlagDecoration(MachineInstr &I, const SPIRVSubtarget &ST, 1002 const SPIRVInstrInfo &TII, 1003 SPIRV::RequirementHandler &Reqs) { 1004 if (I.getFlag(MachineInstr::MIFlag::NoSWrap) && TII.canUseNSW(I) && 1005 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand, 1006 SPIRV::Decoration::NoSignedWrap, ST, Reqs) 1007 .IsSatisfiable) { 1008 buildOpDecorate(I.getOperand(0).getReg(), I, TII, 1009 SPIRV::Decoration::NoSignedWrap, {}); 1010 } 1011 if (I.getFlag(MachineInstr::MIFlag::NoUWrap) && TII.canUseNUW(I) && 1012 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand, 1013 SPIRV::Decoration::NoUnsignedWrap, ST, 1014 Reqs) 1015 .IsSatisfiable) { 1016 buildOpDecorate(I.getOperand(0).getReg(), I, TII, 1017 SPIRV::Decoration::NoUnsignedWrap, {}); 1018 } 1019 if (!TII.canUseFastMathFlags(I)) 1020 return; 1021 unsigned FMFlags = getFastMathFlags(I); 1022 if (FMFlags == SPIRV::FPFastMathMode::None) 1023 return; 1024 Register DstReg = I.getOperand(0).getReg(); 1025 buildOpDecorate(DstReg, I, TII, SPIRV::Decoration::FPFastMathMode, {FMFlags}); 1026 } 1027 1028 // Walk all functions and add decorations related to MI flags. 1029 static void addDecorations(const Module &M, const SPIRVInstrInfo &TII, 1030 MachineModuleInfo *MMI, const SPIRVSubtarget &ST, 1031 SPIRV::ModuleAnalysisInfo &MAI) { 1032 for (auto F = M.begin(), E = M.end(); F != E; ++F) { 1033 MachineFunction *MF = MMI->getMachineFunction(*F); 1034 if (!MF) 1035 continue; 1036 for (auto &MBB : *MF) 1037 for (auto &MI : MBB) 1038 handleMIFlagDecoration(MI, ST, TII, MAI.Reqs); 1039 } 1040 } 1041 1042 struct SPIRV::ModuleAnalysisInfo SPIRVModuleAnalysis::MAI; 1043 1044 void SPIRVModuleAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { 1045 AU.addRequired<TargetPassConfig>(); 1046 AU.addRequired<MachineModuleInfoWrapperPass>(); 1047 } 1048 1049 bool SPIRVModuleAnalysis::runOnModule(Module &M) { 1050 SPIRVTargetMachine &TM = 1051 getAnalysis<TargetPassConfig>().getTM<SPIRVTargetMachine>(); 1052 ST = TM.getSubtargetImpl(); 1053 GR = ST->getSPIRVGlobalRegistry(); 1054 TII = ST->getInstrInfo(); 1055 1056 MMI = &getAnalysis<MachineModuleInfoWrapperPass>().getMMI(); 1057 1058 setBaseInfo(M); 1059 1060 addDecorations(M, *TII, MMI, *ST, MAI); 1061 1062 collectReqs(M, MAI, MMI, *ST); 1063 1064 // Process type/const/global var/func decl instructions, number their 1065 // destination registers from 0 to N, collect Extensions and Capabilities. 1066 processDefInstrs(M); 1067 1068 // Number rest of registers from N+1 onwards. 1069 numberRegistersGlobally(M); 1070 1071 // Collect OpName, OpEntryPoint, OpDecorate etc, process other instructions. 1072 processOtherInstrs(M); 1073 1074 // If there are no entry points, we need the Linkage capability. 1075 if (MAI.MS[SPIRV::MB_EntryPoints].empty()) 1076 MAI.Reqs.addCapability(SPIRV::Capability::Linkage); 1077 1078 return false; 1079 } 1080