LLVM: lib/Target/SPIRV/SPIRVModuleAnalysis.cpp Source File (original) (raw)

63 const auto &Op = MdNode->getOperand(OpIndex);

65 }

67}

68

70getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category,

73

75 if (ST.isShader())

76 AvoidCaps.S.insert(SPIRV::Capability::Shader);

77 else

78 AvoidCaps.S.insert(SPIRV::Capability::Kernel);

79

83 bool MinVerOK = SPIRVVersion.empty() || SPIRVVersion >= ReqMinVer;

84 bool MaxVerOK =

85 ReqMaxVer.empty() || SPIRVVersion.empty() || SPIRVVersion <= ReqMaxVer;

88 if (ReqCaps.empty()) {

89 if (ReqExts.empty()) {

90 if (MinVerOK && MaxVerOK)

91 return {true, {}, {}, ReqMinVer, ReqMaxVer};

93 }

94 } else if (MinVerOK && MaxVerOK) {

95 if (ReqCaps.size() == 1) {

96 auto Cap = ReqCaps[0];

99 SPIRV::OperandCategory::CapabilityOperand, Cap));

100 return {true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};

101 }

102 } else {

103

104

105

106

107

108

110 for (auto Cap : ReqCaps)

113 for (size_t i = 0, Sz = UseCaps.size(); i < Sz; ++i) {

114 auto Cap = UseCaps[i];

115 if (i == Sz - 1 || !AvoidCaps.S.contains(Cap)) {

117 SPIRV::OperandCategory::CapabilityOperand, Cap));

118 return {true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};

119 }

120 }

121 }

122 }

123

124

125

126 if (llvm::all_of(ReqExts, [&ST](const SPIRV::Extension::Extension &Ext) {

127 return ST.canUseExtension(Ext);

128 })) {

129 return {true,

130 {},

131 std::move(ReqExts),

133 VersionTuple()};

134 }

136}

137

138void SPIRVModuleAnalysis::setBaseInfo(const Module &M) {

139 MAI.MaxID = 0;

141 MAI.MS[i].clear();

142 MAI.RegisterAliasTable.clear();

143 MAI.InstrsToDelete.clear();

144 MAI.FuncMap.clear();

145 MAI.GlobalVarList.clear();

146 MAI.ExtInstSetMap.clear();

147 MAI.Reqs.clear();

148 MAI.Reqs.initAvailableCapabilities(*ST);

149

150

151 if (auto MemModel = M.getNamedMetadata("spirv.MemoryModel")) {

152 auto MemMD = MemModel->getOperand(0);

153 MAI.Addr = static_castSPIRV::AddressingModel::AddressingModel\(

154 getMetadataUInt(MemMD, 0));

155 MAI.Mem =

156 static_castSPIRV::MemoryModel::MemoryModel\(getMetadataUInt(MemMD, 1));

157 } else {

158

159 MAI.Mem = ST->isShader() ? SPIRV::MemoryModel::GLSL450

160 : SPIRV::MemoryModel::OpenCL;

161 if (MAI.Mem == SPIRV::MemoryModel::OpenCL) {

162 unsigned PtrSize = ST->getPointerSize();

163 MAI.Addr = PtrSize == 32 ? SPIRV::AddressingModel::Physical32

164 : PtrSize == 64 ? SPIRV::AddressingModel::Physical64

165 : SPIRV::AddressingModel::Logical;

166 } else {

167

168 MAI.Addr = SPIRV::AddressingModel::Logical;

169 }

170 }

171

172

173 if (auto VerNode = M.getNamedMetadata("opencl.ocl.version")) {

174 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_C;

175

176

177 assert(VerNode->getNumOperands() > 0 && "Invalid SPIR");

178 auto VersionMD = VerNode->getOperand(0);

179 unsigned MajorNum = getMetadataUInt(VersionMD, 0, 2);

180 unsigned MinorNum = getMetadataUInt(VersionMD, 1);

181 unsigned RevNum = getMetadataUInt(VersionMD, 2);

182

183 MAI.SrcLangVersion =

184 (std::max(1U, MajorNum) * 100 + MinorNum) * 1000 + RevNum;

185 } else {

186

187

188

189

190 if (!ST->isShader()) {

191 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_CPP;

192 MAI.SrcLangVersion = 100000;

193 } else {

194 MAI.SrcLang = SPIRV::SourceLanguage::Unknown;

195 MAI.SrcLangVersion = 0;

196 }

197 }

198

199 if (auto ExtNode = M.getNamedMetadata("opencl.used.extensions")) {

200 for (unsigned I = 0, E = ExtNode->getNumOperands(); I != E; ++I) {

201 MDNode *MD = ExtNode->getOperand(I);

203 continue;

206 }

207 }

208

209

210

211 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::MemoryModelOperand,

212 MAI.Mem, *ST);

213 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::SourceLanguageOperand,

214 MAI.SrcLang, *ST);

215 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::AddressingModelOperand,

216 MAI.Addr, *ST);

217

218 if (!ST->isShader()) {

219

220 MAI.ExtInstSetMap[static_cast<unsigned>(

221 SPIRV::InstructionSet::OpenCL_std)] = MAI.getNextIDRegister();

222 }

223}

224

225

226

230

231

232 if (UseMI.getOpcode() != SPIRV::OpDecorate &&

233 UseMI.getOpcode() != SPIRV::OpMemberDecorate)

234 continue;

235

236 for (unsigned I = 0; I < UseMI.getNumOperands(); ++I) {

239 continue;

241 }

242 }

243}

244

245

246

247

248

251 bool UseDefReg) {

254 for (unsigned i = 0; i < MI.getNumOperands(); ++i) {

255

256

257

258

259

260

261

262

263 unsigned Opcode = MI.getOpcode();

264 if ((Opcode == SPIRV::OpDecorate) && i >= 2) {

265 unsigned DecorationID = MI.getOperand(1).getImm();

266 if (DecorationID != SPIRV::Decoration::FuncParamAttr &&

267 DecorationID != SPIRV::Decoration::UserSemantic &&

268 DecorationID != SPIRV::Decoration::CacheControlLoadINTEL &&

269 DecorationID != SPIRV::Decoration::CacheControlStoreINTEL)

270 continue;

271 }

273 size_t h;

274 if (MO.isReg()) {

275 if (!UseDefReg && MO.isDef()) {

276 assert(!DefReg.isValid() && "Multiple def registers.");

277 DefReg = MO.getReg();

278 continue;

279 }

281 if (!RegAlias.isValid()) {

283 dbgs() << "Unexpectedly, no global id found for the operand ";

285 dbgs() << "\nInstruction: ";

287 dbgs() << "\n";

288 });

289 report_fatal_error("All v-regs must have been mapped to global id's");

290 }

291

294 } else {

296 }

298 }

299

301

302

303

304 appendDecorationsForReg(MI.getMF()->getRegInfo(), DefReg, Signature);

305 }

306 return Signature;

307}

308

311 unsigned Opcode = MI.getOpcode();

312 switch (Opcode) {

313 case SPIRV::OpTypeForwardPointer:

314

315 return false;

316 case SPIRV::OpVariable:

317 return static_castSPIRV::StorageClass::StorageClass\(

318 MI.getOperand(2).getImm()) != SPIRV::StorageClass::Function;

319 case SPIRV::OpFunction:

320 case SPIRV::OpFunctionParameter:

321 return true;

322 }

323 if (GR->hasConstFunPtr() && Opcode == SPIRV::OpUndef) {

324 Register DefReg = MI.getOperand(0).getReg();

325 for (MachineInstr &UseMI : MRI.use_instructions(DefReg)) {

326 if (UseMI.getOpcode() != SPIRV::OpConstantFunctionPointerINTEL)

327 continue;

328

329

332 MAI.setSkipEmission(&MI);

333 return false;

334 }

335 }

336 return TII->isTypeDeclInstr(MI) || TII->isConstantInstr(MI) ||

337 TII->isInlineAsmDefInstr(MI);

338}

339

340

341

342

343void SPIRVModuleAnalysis::visitFunPtrUse(

345 std::map<const Value *, unsigned> &GlobalToGReg, const MachineFunction *MF,

347 const MachineOperand *OpFunDef =

348 GR->getFunctionDefinitionByUse(&MI.getOperand(2));

350

351 const MachineInstr *OpDefMI = OpFunDef->getParent();

352 assert(OpDefMI && OpDefMI->getOpcode() == SPIRV::OpFunction);

354 const MachineRegisterInfo &FunDefMRI = FunDefMF->getRegInfo();

355 do {

356 visitDecl(FunDefMRI, SignatureToGReg, GlobalToGReg, FunDefMF, *OpDefMI);

358 } while (OpDefMI && (OpDefMI->getOpcode() == SPIRV::OpFunction ||

359 OpDefMI->getOpcode() == SPIRV::OpFunctionParameter));

360

361 MCRegister GlobalFunDefReg =

362 MAI.getRegisterAlias(FunDefMF, OpFunDef->getReg());

364 "Function definition must refer to a global register");

365 MAI.setRegisterAlias(MF, OpReg, GlobalFunDefReg);

366}

367

368

369

370void SPIRVModuleAnalysis::visitDecl(

372 std::map<const Value *, unsigned> &GlobalToGReg, const MachineFunction *MF,

374 unsigned Opcode = MI.getOpcode();

375

376

377 for (const MachineOperand &MO : MI.operands()) {

379 continue;

381

382 if (Opcode == SPIRV::OpConstantFunctionPointerINTEL &&

383 MRI.getRegClass(OpReg) == &SPIRV::pIDRegClass) {

384 visitFunPtrUse(OpReg, SignatureToGReg, GlobalToGReg, MF, MI);

385 continue;

386 }

387

388 if (MAI.hasRegisterAlias(MF, MO.getReg()))

389 continue;

390

391 if (const MachineInstr *OpDefMI = MRI.getUniqueVRegDef(OpReg)) {

392 if (isDeclSection(MRI, *OpDefMI))

393 visitDecl(MRI, SignatureToGReg, GlobalToGReg, MF, *OpDefMI);

394 continue;

395 }

396

397

399 dbgs() << "Unexpectedly, no unique definition for the operand ";

401 dbgs() << "\nInstruction: ";

403 dbgs() << "\n";

404 });

406 "No unique definition is found for the virtual register");

407 }

408

409 MCRegister GReg;

410 bool IsFunDef = false;

411 if (TII->isSpecConstantInstr(MI)) {

412 GReg = MAI.getNextIDRegister();

414 } else if (Opcode == SPIRV::OpFunction ||

415 Opcode == SPIRV::OpFunctionParameter) {

416 GReg = handleFunctionOrParameter(MF, MI, GlobalToGReg, IsFunDef);

417 } else if (Opcode == SPIRV::OpTypeStruct ||

418 Opcode == SPIRV::OpConstantComposite) {

419 GReg = handleTypeDeclOrConstant(MI, SignatureToGReg);

420 const MachineInstr *NextInstr = MI.getNextNode();

421 while (NextInstr &&

422 ((Opcode == SPIRV::OpTypeStruct &&

423 NextInstr->getOpcode() == SPIRV::OpTypeStructContinuedINTEL) ||

424 (Opcode == SPIRV::OpConstantComposite &&

426 SPIRV::OpConstantCompositeContinuedINTEL))) {

427 MCRegister Tmp = handleTypeDeclOrConstant(*NextInstr, SignatureToGReg);

429 MAI.setSkipEmission(NextInstr);

431 }

432 } else if (TII->isTypeDeclInstr(MI) || TII->isConstantInstr(MI) ||

433 TII->isInlineAsmDefInstr(MI)) {

434 GReg = handleTypeDeclOrConstant(MI, SignatureToGReg);

435 } else if (Opcode == SPIRV::OpVariable) {

436 GReg = handleVariable(MF, MI, GlobalToGReg);

437 } else {

439 dbgs() << "\nInstruction: ";

441 dbgs() << "\n";

442 });

444 }

445 MAI.setRegisterAlias(MF, MI.getOperand(0).getReg(), GReg);

446 if (!IsFunDef)

447 MAI.setSkipEmission(&MI);

448}

449

450MCRegister SPIRVModuleAnalysis::handleFunctionOrParameter(

452 std::map<const Value *, unsigned> &GlobalToGReg, bool &IsFunDef) {

453 const Value *GObj = GR->getGlobalObject(MF, MI.getOperand(0).getReg());

454 assert(GObj && "Unregistered global definition");

456 if (F)

458 assert(F && "Expected a reference to a function or an argument");

459 IsFunDef = F->isDeclaration();

460 auto [It, Inserted] = GlobalToGReg.try_emplace(GObj);

461 if (!Inserted)

462 return It->second;

463 MCRegister GReg = MAI.getNextIDRegister();

464 It->second = GReg;

465 if (!IsFunDef)

467 return GReg;

468}

469

471SPIRVModuleAnalysis::handleTypeDeclOrConstant(const MachineInstr &MI,

474 auto [It, Inserted] = SignatureToGReg.try_emplace(MISign);

475 if (!Inserted)

476 return It->second;

477 MCRegister GReg = MAI.getNextIDRegister();

478 It->second = GReg;

480 return GReg;

481}

482

483MCRegister SPIRVModuleAnalysis::handleVariable(

485 std::map<const Value *, unsigned> &GlobalToGReg) {

486 MAI.GlobalVarList.push_back(&MI);

487 const Value *GObj = GR->getGlobalObject(MF, MI.getOperand(0).getReg());

488 assert(GObj && "Unregistered global definition");

489 auto [It, Inserted] = GlobalToGReg.try_emplace(GObj);

490 if (!Inserted)

491 return It->second;

492 MCRegister GReg = MAI.getNextIDRegister();

493 It->second = GReg;

495 return GReg;

496}

497

498void SPIRVModuleAnalysis::collectDeclarations(const Module &M) {

500 std::map<const Value *, unsigned> GlobalToGReg;

501 for (const Function &F : M) {

502 MachineFunction *MF = MMI->getMachineFunction(F);

503 if (!MF)

504 continue;

505 const MachineRegisterInfo &MRI = MF->getRegInfo();

506 unsigned PastHeader = 0;

507 for (MachineBasicBlock &MBB : *MF) {

508 for (MachineInstr &MI : MBB) {

509 if (MI.getNumOperands() == 0)

510 continue;

511 unsigned Opcode = MI.getOpcode();

512 if (Opcode == SPIRV::OpFunction) {

513 if (PastHeader == 0) {

514 PastHeader = 1;

515 continue;

516 }

517 } else if (Opcode == SPIRV::OpFunctionParameter) {

518 if (PastHeader < 2)

519 continue;

520 } else if (PastHeader > 0) {

521 PastHeader = 2;

522 }

523

524 const MachineOperand &DefMO = MI.getOperand(0);

525 switch (Opcode) {

526 case SPIRV::OpExtension:

527 MAI.Reqs.addExtension(SPIRV::Extension::Extension(DefMO.getImm()));

528 MAI.setSkipEmission(&MI);

529 break;

530 case SPIRV::OpCapability:

531 MAI.Reqs.addCapability(SPIRV::Capability::Capability(DefMO.getImm()));

532 MAI.setSkipEmission(&MI);

533 if (PastHeader > 0)

534 PastHeader = 2;

535 break;

536 default:

537 if (DefMO.isReg() && isDeclSection(MRI, MI) &&

538 MAI.hasRegisterAlias(MF, DefMO.getReg()))

539 visitDecl(MRI, SignatureToGReg, GlobalToGReg, MF, MI);

540 }

541 }

542 }

543 }

544}

545

546

547

548

549

550void SPIRVModuleAnalysis::collectFuncNames(MachineInstr &MI,

552 if (MI.getOpcode() == SPIRV::OpDecorate) {

553

554 auto Dec = MI.getOperand(1).getImm();

555 if (Dec == SPIRV::Decoration::LinkageAttributes) {

556 auto Lnk = MI.getOperand(MI.getNumOperands() - 1).getImm();

557 if (Lnk == SPIRV::LinkageType::Import) {

558

559 const Function *ImportedFunc =

562 MAI.FuncMap[ImportedFunc] = MAI.getRegisterAlias(MI.getMF(), Target);

563 }

564 }

565 } else if (MI.getOpcode() == SPIRV::OpFunction) {

566

568 MCRegister GlobalReg = MAI.getRegisterAlias(MI.getMF(), Reg);

570 MAI.FuncMap[F] = GlobalReg;

571 }

572}

573

574

575

576

579 bool Append = true) {

582 auto FoundMI = IS.insert(std::move(MISign));

583 if (!FoundMI.second) {

584 if (MI.getOpcode() == SPIRV::OpDecorate) {

585 assert(MI.getNumOperands() >= 2 &&

586 "Decoration instructions must have at least 2 operands");

588 "Only OpDecorate instructions can be duplicates");

589

590

591

592

593 if (MI.getOperand(1).getImm() != SPIRV::Decoration::FPFastMathMode)

594 return;

595

597 for (const MachineInstr *OrigMI : Decorations) {

598 if (instrToSignature(*OrigMI, MAI, true) == MISign) {

599 assert(OrigMI->getNumOperands() == MI.getNumOperands() &&

600 "Original instruction must have the same number of operands");

602 OrigMI->getNumOperands() == 3 &&

603 "FPFastMathMode decoration must have 3 operands for OpDecorate");

604 unsigned OrigFlags = OrigMI->getOperand(2).getImm();

605 unsigned NewFlags = MI.getOperand(2).getImm();

606 if (OrigFlags == NewFlags)

607 return;

608

609

610 unsigned FinalFlags = OrigFlags | NewFlags;

612 << "Warning: Conflicting FPFastMathMode decoration flags "

613 "in instruction: "

614 << *OrigMI << "Original flags: " << OrigFlags

615 << ", new flags: " << NewFlags

616 << ". They will be merged on a best effort basis, but not "

617 "validated. Final flags: "

618 << FinalFlags << "\n";

622 return;

623 }

624 }

625 assert(false && "No original instruction found for the duplicate "

626 "OpDecorate, but we found one in IS.");

627 }

628 return;

629 }

630

631 if (Append)

633 else

635}

636

637

638

639void SPIRVModuleAnalysis::processOtherInstrs(const Module &M) {

641 for (const Function &F : M) {

642 if (F.isDeclaration())

643 continue;

644 MachineFunction *MF = MMI->getMachineFunction(F);

646

647 for (MachineBasicBlock &MBB : *MF)

648 for (MachineInstr &MI : MBB) {

649 if (MAI.getSkipEmission(&MI))

650 continue;

651 const unsigned OpCode = MI.getOpcode();

652 if (OpCode == SPIRV::OpString) {

654 } else if (OpCode == SPIRV::OpExtInst && MI.getOperand(2).isImm() &&

655 MI.getOperand(2).getImm() ==

656 SPIRV::InstructionSet::

657 NonSemantic_Shader_DebugInfo_100) {

658 MachineOperand Ins = MI.getOperand(3);

659 namespace NS = SPIRV::NonSemanticExtInst;

660 static constexpr int64_t GlobalNonSemanticDITy[] = {

661 NS::DebugSource, NS::DebugCompilationUnit, NS::DebugInfoNone,

662 NS::DebugTypeBasic, NS::DebugTypePointer};

663 bool IsGlobalDI = false;

664 for (unsigned Idx = 0; Idx < std::size(GlobalNonSemanticDITy); ++Idx)

665 IsGlobalDI |= Ins.getImm() == GlobalNonSemanticDITy[Idx];

666 if (IsGlobalDI)

668 } else if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {

670 } else if (OpCode == SPIRV::OpEntryPoint) {

672 } else if (TII->isAliasingInstr(MI)) {

674 } else if (TII->isDecorationInstr(MI)) {

676 collectFuncNames(MI, &F);

677 } else if (TII->isConstantInstr(MI)) {

678

679

681 } else if (OpCode == SPIRV::OpFunction) {

682 collectFuncNames(MI, &F);

683 } else if (OpCode == SPIRV::OpTypeForwardPointer) {

685 }

686 }

687 }

688}

689

690

691

692

693void SPIRVModuleAnalysis::numberRegistersGlobally(const Module &M) {

694 for (const Function &F : M) {

695 if (F.isDeclaration())

696 continue;

697 MachineFunction *MF = MMI->getMachineFunction(F);

699 for (MachineBasicBlock &MBB : *MF) {

700 for (MachineInstr &MI : MBB) {

701 for (MachineOperand &Op : MI.operands()) {

702 if (Op.isReg())

703 continue;

705 if (MAI.hasRegisterAlias(MF, Reg))

706 continue;

707 MCRegister NewReg = MAI.getNextIDRegister();

708 MAI.setRegisterAlias(MF, Reg, NewReg);

709 }

710 if (MI.getOpcode() != SPIRV::OpExtInst)

711 continue;

712 auto Set = MI.getOperand(2).getImm();

713 auto [It, Inserted] = MAI.ExtInstSetMap.try_emplace(Set);

714 if (Inserted)

715 It->second = MAI.getNextIDRegister();

716 }

717 }

718 }

719}

720

721

723 SPIRV::OperandCategory::OperandCategory Category, uint32_t i,

725 addRequirements(getSymbolicOperandRequirements(Category, i, ST, *this));

726}

727

728void SPIRV::RequirementHandler::recursiveAddCapabilities(

730 for (const auto &Cap : ToPrune) {

731 AllCaps.insert(Cap);

734 recursiveAddCapabilities(ImplicitDecls);

735 }

736}

737

739 for (const auto &Cap : ToAdd) {

740 bool IsNewlyInserted = AllCaps.insert(Cap).second;

741 if (!IsNewlyInserted)

742 continue;

745 recursiveAddCapabilities(ImplicitDecls);

746 MinimalCaps.push_back(Cap);

747 }

748}

749

751 const SPIRV::Requirements &Req) {

753 report_fatal_error("Adding SPIR-V requirements this target can't satisfy.");

754

755 if (Req.Cap.has_value())

756 addCapabilities({Req.Cap.value()});

757

758 addExtensions(Req.Exts);

759

761 if (!MaxVersion.empty() && Req.MinVer > MaxVersion) {

763 << " and <= " << MaxVersion << "\n");

764 report_fatal_error("Adding SPIR-V requirements that can't be satisfied.");

765 }

766

767 if (MinVersion.empty() || Req.MinVer > MinVersion)

768 MinVersion = Req.MinVer;

769 }

770

772 if (!MinVersion.empty() && Req.MaxVer < MinVersion) {

774 << " and >= " << MinVersion << "\n");

775 report_fatal_error("Adding SPIR-V requirements that can't be satisfied.");

776 }

777

778 if (MaxVersion.empty() || Req.MaxVer < MaxVersion)

779 MaxVersion = Req.MaxVer;

780 }

781}

782

784 const SPIRVSubtarget &ST) const {

785

786 bool IsSatisfiable = true;

787 auto TargetVer = ST.getSPIRVVersion();

788

789 if (!MaxVersion.empty() && !TargetVer.empty() && MaxVersion < TargetVer) {

791 dbgs() << "Target SPIR-V version too high for required features\n"

792 << "Required max version: " << MaxVersion << " target version "

793 << TargetVer << "\n");

794 IsSatisfiable = false;

795 }

796

797 if (!MinVersion.empty() && !TargetVer.empty() && MinVersion > TargetVer) {

798 LLVM_DEBUG(dbgs() << "Target SPIR-V version too low for required features\n"

799 << "Required min version: " << MinVersion

800 << " target version " << TargetVer << "\n");

801 IsSatisfiable = false;

802 }

803

804 if (!MinVersion.empty() && !MaxVersion.empty() && MinVersion > MaxVersion) {

807 << "Version is too low for some features and too high for others.\n"

808 << "Required SPIR-V min version: " << MinVersion

809 << " required SPIR-V max version " << MaxVersion << "\n");

810 IsSatisfiable = false;

811 }

812

813 AvoidCapabilitiesSet AvoidCaps;

814 if (ST.isShader())

815 AvoidCaps.S.insert(SPIRV::Capability::Shader);

816 else

817 AvoidCaps.S.insert(SPIRV::Capability::Kernel);

818

819 for (auto Cap : MinimalCaps) {

820 if (AvailableCaps.contains(Cap) && !AvoidCaps.S.contains(Cap))

821 continue;

824 OperandCategory::CapabilityOperand, Cap)

825 << "\n");

826 IsSatisfiable = false;

827 }

828

829 for (auto Ext : AllExtensions) {

830 if (ST.canUseExtension(Ext))

831 continue;

834 OperandCategory::ExtensionOperand, Ext)

835 << "\n");

836 IsSatisfiable = false;

837 }

838

839 if (!IsSatisfiable)

840 report_fatal_error("Unable to meet SPIR-V requirements for this target.");

841}

842

843

845 for (const auto Cap : ToAdd)

846 if (AvailableCaps.insert(Cap).second)

848 SPIRV::OperandCategory::CapabilityOperand, Cap));

849}

850

852 const Capability::Capability ToRemove,

853 const Capability::Capability IfPresent) {

854 if (AllCaps.contains(IfPresent))

856}

857

858namespace llvm {

861

862 addAvailableCaps({Capability::Shader, Capability::Linkage, Capability::Int8,

863 Capability::Int16});

864

865 if (ST.isAtLeastSPIRVVer(VersionTuple(1, 3)))

867 Capability::GroupNonUniformVote,

868 Capability::GroupNonUniformArithmetic,

869 Capability::GroupNonUniformBallot,

870 Capability::GroupNonUniformClustered,

871 Capability::GroupNonUniformShuffle,

872 Capability::GroupNonUniformShuffleRelative});

873

874 if (ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))

875 addAvailableCaps({Capability::DotProduct, Capability::DotProductInputAll,

876 Capability::DotProductInput4x8Bit,

877 Capability::DotProductInput4x8BitPacked,

878 Capability::DemoteToHelperInvocation});

879

880

881 for (auto Extension : ST.getAllAvailableExtensions()) {

885 }

886

887 if (ST.isShader()) {

888 initAvailableCapabilitiesForOpenCL(ST);

889 return;

890 }

891

892 if (ST.isShader()) {

893 initAvailableCapabilitiesForVulkan(ST);

894 return;

895 }

896

897 report_fatal_error("Unimplemented environment for SPIR-V generation.");

898}

899

900void RequirementHandler::initAvailableCapabilitiesForOpenCL(

901 const SPIRVSubtarget &ST) {

902

903 addAvailableCaps({Capability::Addresses, Capability::Float16Buffer,

904 Capability::Kernel, Capability::Vector16,

905 Capability::Groups, Capability::GenericPointer,

906 Capability::StorageImageWriteWithoutFormat,

907 Capability::StorageImageReadWithoutFormat});

908 if (ST.hasOpenCLFullProfile())

909 addAvailableCaps({Capability::Int64, Capability::Int64Atomics});

910 if (ST.hasOpenCLImageSupport()) {

911 addAvailableCaps({Capability::ImageBasic, Capability::LiteralSampler,

912 Capability::Image1D, Capability::SampledBuffer,

913 Capability::ImageBuffer});

914 if (ST.isAtLeastOpenCLVer(VersionTuple(2, 0)))

916 }

917 if (ST.isAtLeastSPIRVVer(VersionTuple(1, 1)) &&

918 ST.isAtLeastOpenCLVer(VersionTuple(2, 2)))

919 addAvailableCaps({Capability::SubgroupDispatch, Capability::PipeStorage});

920 if (ST.isAtLeastSPIRVVer(VersionTuple(1, 4)))

921 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,

922 Capability::SignedZeroInfNanPreserve,

923 Capability::RoundingModeRTE,

924 Capability::RoundingModeRTZ});

925

926 addAvailableCaps({Capability::Float16, Capability::Float64});

927

928

929}

930

931void RequirementHandler::initAvailableCapabilitiesForVulkan(

932 const SPIRVSubtarget &ST) {

933

934

935 addAvailableCaps({Capability::Int64, Capability::Float16, Capability::Float64,

936 Capability::GroupNonUniform, Capability::Image1D,

937 Capability::SampledBuffer, Capability::ImageBuffer,

938 Capability::UniformBufferArrayDynamicIndexing,

939 Capability::SampledImageArrayDynamicIndexing,

940 Capability::StorageBufferArrayDynamicIndexing,

941 Capability::StorageImageArrayDynamicIndexing,

942 Capability::DerivativeControl});

943

944

945 if (ST.isAtLeastSPIRVVer(VersionTuple(1, 5))) {

947 {Capability::ShaderNonUniformEXT, Capability::RuntimeDescriptorArrayEXT,

948 Capability::InputAttachmentArrayDynamicIndexingEXT,

949 Capability::UniformTexelBufferArrayDynamicIndexingEXT,

950 Capability::StorageTexelBufferArrayDynamicIndexingEXT,

951 Capability::UniformBufferArrayNonUniformIndexingEXT,

952 Capability::SampledImageArrayNonUniformIndexingEXT,

953 Capability::StorageBufferArrayNonUniformIndexingEXT,

954 Capability::StorageImageArrayNonUniformIndexingEXT,

955 Capability::InputAttachmentArrayNonUniformIndexingEXT,

956 Capability::UniformTexelBufferArrayNonUniformIndexingEXT,

957 Capability::StorageTexelBufferArrayNonUniformIndexingEXT});

958 }

959

960

961 if (ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))

962 addAvailableCaps({Capability::StorageImageWriteWithoutFormat,

963 Capability::StorageImageReadWithoutFormat});

964}

965

966}

967}

968

969

970

971static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex,

974 int64_t DecOp = MI.getOperand(DecIndex).getImm();

975 auto Dec = static_castSPIRV::Decoration::Decoration\(DecOp);

977 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));

978

979 if (Dec == SPIRV::Decoration::BuiltIn) {

980 int64_t BuiltInOp = MI.getOperand(DecIndex + 1).getImm();

981 auto BuiltIn = static_castSPIRV::BuiltIn::BuiltIn\(BuiltInOp);

983 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));

984 } else if (Dec == SPIRV::Decoration::LinkageAttributes) {

985 int64_t LinkageOp = MI.getOperand(MI.getNumOperands() - 1).getImm();

986 SPIRV::LinkageType::LinkageType LnkType =

987 static_castSPIRV::LinkageType::LinkageType\(LinkageOp);

988 if (LnkType == SPIRV::LinkageType::LinkOnceODR)

989 Reqs.addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);

990 } else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||

991 Dec == SPIRV::Decoration::CacheControlStoreINTEL) {

992 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);

993 } else if (Dec == SPIRV::Decoration::HostAccessINTEL) {

994 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access);

995 } else if (Dec == SPIRV::Decoration::InitModeINTEL ||

996 Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {

998 SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);

999 } else if (Dec == SPIRV::Decoration::NonUniformEXT) {

1000 Reqs.addRequirements(SPIRV::Capability::ShaderNonUniformEXT);

1001 } else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {

1002 Reqs.addRequirements(SPIRV::Capability::FPMaxErrorINTEL);

1003 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);

1004 } else if (Dec == SPIRV::Decoration::FPFastMathMode) {

1005 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {

1006 Reqs.addRequirements(SPIRV::Capability::FloatControls2);

1007 Reqs.addExtension(SPIRV::Extension::SPV_KHR_float_controls2);

1008 }

1009 }

1010}

1011

1012

1013static void addOpTypeImageReqs(const MachineInstr &MI,

1016 assert(MI.getNumOperands() >= 8 && "Insufficient operands for OpTypeImage");

1017

1018

1019 int64_t ImgFormatOp = MI.getOperand(7).getImm();

1020 auto ImgFormat = static_castSPIRV::ImageFormat::ImageFormat\(ImgFormatOp);

1022 ImgFormat, ST);

1023

1024 bool IsArrayed = MI.getOperand(4).getImm() == 1;

1025 bool IsMultisampled = MI.getOperand(5).getImm() == 1;

1026 bool NoSampler = MI.getOperand(6).getImm() == 2;

1027

1028 assert(MI.getOperand(2).isImm());

1029 switch (MI.getOperand(2).getImm()) {

1030 case SPIRV::Dim::DIM_1D:

1031 Reqs.addRequirements(NoSampler ? SPIRV::Capability::Image1D

1032 : SPIRV::Capability::Sampled1D);

1033 break;

1034 case SPIRV::Dim::DIM_2D:

1035 if (IsMultisampled && NoSampler)

1037 break;

1038 case SPIRV::Dim::DIM_Cube:

1040 if (IsArrayed)

1041 Reqs.addRequirements(NoSampler ? SPIRV::Capability::ImageCubeArray

1042 : SPIRV::Capability::SampledCubeArray);

1043 break;

1044 case SPIRV::Dim::DIM_Rect:

1045 Reqs.addRequirements(NoSampler ? SPIRV::Capability::ImageRect

1046 : SPIRV::Capability::SampledRect);

1047 break;

1048 case SPIRV::Dim::DIM_Buffer:

1049 Reqs.addRequirements(NoSampler ? SPIRV::Capability::ImageBuffer

1050 : SPIRV::Capability::SampledBuffer);

1051 break;

1052 case SPIRV::Dim::DIM_SubpassData:

1053 Reqs.addRequirements(SPIRV::Capability::InputAttachment);

1054 break;

1055 }

1056

1057

1058 if (ST.isShader()) {

1059 if (MI.getNumOperands() > 8 &&

1060 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)

1061 Reqs.addRequirements(SPIRV::Capability::ImageReadWrite);

1062 else

1064 }

1065}

1066

1067static bool isBFloat16Type(const SPIRVType *TypeDef) {

1069 TypeDef->getOpcode() == SPIRV::OpTypeFloat &&

1071 TypeDef->getOperand(2).getImm() == SPIRV::FPEncoding::BFloat16KHR;

1072}

1073

1074

1075#define ATOM_FLT_REQ_EXT_MSG(ExtName) \

1076 "The atomic float instruction requires the following SPIR-V " \

1077 "extension: SPV_EXT_shader_atomic_float" ExtName

1078static void AddAtomicVectorFloatRequirements(const MachineInstr &MI,

1082 MI.getMF()->getRegInfo().getVRegDef(MI.getOperand(1).getReg());

1083

1085 if (Rank != 2 && Rank != 4)

1087 "must be a 2-component or 4 component vector");

1088

1090 MI.getMF()->getRegInfo().getVRegDef(VecTypeDef->getOperand(1).getReg());

1091

1092 if (EltTypeDef->getOpcode() != SPIRV::OpTypeFloat ||

1095 "The element type for the result type of an atomic vector float "

1096 "instruction must be a 16-bit floating-point scalar");

1097

1098 if (isBFloat16Type(EltTypeDef))

1100 "The element type for the result type of an atomic vector float "

1101 "instruction cannot be a bfloat16 scalar");

1102 if (ST.canUseExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector))

1104 "The atomic float16 vector instruction requires the following SPIR-V "

1105 "extension: SPV_NV_shader_atomic_fp16_vector");

1106

1107 Reqs.addExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector);

1108 Reqs.addCapability(SPIRV::Capability::AtomicFloat16VectorNV);

1109}

1110

1111static void AddAtomicFloatRequirements(const MachineInstr &MI,

1114 assert(MI.getOperand(1).isReg() &&

1115 "Expect register operand in atomic float instruction");

1116 Register TypeReg = MI.getOperand(1).getReg();

1117 SPIRVType *TypeDef = MI.getMF()->getRegInfo().getVRegDef(TypeReg);

1118

1119 if (TypeDef->getOpcode() == SPIRV::OpTypeVector)

1120 return AddAtomicVectorFloatRequirements(MI, Reqs, ST);

1121

1122 if (TypeDef->getOpcode() != SPIRV::OpTypeFloat)

1123 report_fatal_error("Result type of an atomic float instruction must be a "

1124 "floating-point type scalar");

1125

1127 unsigned Op = MI.getOpcode();

1128 if (Op == SPIRV::OpAtomicFAddEXT) {

1129 if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))

1131 Reqs.addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);

1133 case 16:

1134 if (isBFloat16Type(TypeDef)) {

1135 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))

1137 "The atomic bfloat16 instruction requires the following SPIR-V "

1138 "extension: SPV_INTEL_16bit_atomics",

1139 false);

1140 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);

1141 Reqs.addCapability(SPIRV::Capability::AtomicBFloat16AddINTEL);

1142 } else {

1143 if (ST.canUseExtension(

1144 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))

1146 Reqs.addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);

1147 Reqs.addCapability(SPIRV::Capability::AtomicFloat16AddEXT);

1148 }

1149 break;

1150 case 32:

1151 Reqs.addCapability(SPIRV::Capability::AtomicFloat32AddEXT);

1152 break;

1153 case 64:

1154 Reqs.addCapability(SPIRV::Capability::AtomicFloat64AddEXT);

1155 break;

1156 default:

1158 "Unexpected floating-point type width in atomic float instruction");

1159 }

1160 } else {

1161 if (ST.canUseExtension(

1162 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))

1164 Reqs.addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);

1166 case 16:

1167 if (isBFloat16Type(TypeDef)) {

1168 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))

1170 "The atomic bfloat16 instruction requires the following SPIR-V "

1171 "extension: SPV_INTEL_16bit_atomics",

1172 false);

1173 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);

1174 Reqs.addCapability(SPIRV::Capability::AtomicBFloat16MinMaxINTEL);

1175 } else {

1176 Reqs.addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);

1177 }

1178 break;

1179 case 32:

1180 Reqs.addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);

1181 break;

1182 case 64:

1183 Reqs.addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);

1184 break;

1185 default:

1187 "Unexpected floating-point type width in atomic float instruction");

1188 }

1189 }

1190}

1191

1192bool isUniformTexelBuffer(MachineInstr *ImageInst) {

1193 if (ImageInst->getOpcode() != SPIRV::OpTypeImage)

1194 return false;

1197 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;

1198}

1199

1200bool isStorageTexelBuffer(MachineInstr *ImageInst) {

1201 if (ImageInst->getOpcode() != SPIRV::OpTypeImage)

1202 return false;

1205 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;

1206}

1207

1208bool isSampledImage(MachineInstr *ImageInst) {

1209 if (ImageInst->getOpcode() != SPIRV::OpTypeImage)

1210 return false;

1213 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;

1214}

1215

1216bool isInputAttachment(MachineInstr *ImageInst) {

1217 if (ImageInst->getOpcode() != SPIRV::OpTypeImage)

1218 return false;

1221 return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;

1222}

1223

1224bool isStorageImage(MachineInstr *ImageInst) {

1225 if (ImageInst->getOpcode() != SPIRV::OpTypeImage)

1226 return false;

1229 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;

1230}

1231

1232bool isCombinedImageSampler(MachineInstr *SampledImageInst) {

1233 if (SampledImageInst->getOpcode() != SPIRV::OpTypeSampledImage)

1234 return false;

1235

1238 auto *ImageInst = MRI.getUniqueVRegDef(ImageReg);

1239 return isSampledImage(ImageInst);

1240}

1241

1243 for (const auto &MI : MRI.reg_instructions(Reg)) {

1244 if (MI.getOpcode() != SPIRV::OpDecorate)

1245 continue;

1246

1247 uint32_t Dec = MI.getOperand(1).getImm();

1248 if (Dec == SPIRV::Decoration::NonUniformEXT)

1249 return true;

1250 }

1251 return false;

1252}

1253

1254void addOpAccessChainReqs(const MachineInstr &Instr,

1258

1259

1260

1261 Register ResTypeReg = Instr.getOperand(1).getReg();

1262 MachineInstr *ResTypeInst = MRI.getUniqueVRegDef(ResTypeReg);

1263

1264 assert(ResTypeInst->getOpcode() == SPIRV::OpTypePointer);

1266 if (StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&

1267 StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&

1268 StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {

1269 return;

1270 }

1271

1272 bool IsNonUniform =

1273 hasNonUniformDecoration(Instr.getOperand(0).getReg(), MRI);

1274

1275 auto FirstIndexReg = Instr.getOperand(3).getReg();

1276 bool FirstIndexIsConstant =

1278

1279 if (StorageClass == SPIRV::StorageClass::StorageClass::StorageBuffer) {

1280 if (IsNonUniform)

1282 SPIRV::Capability::StorageBufferArrayNonUniformIndexingEXT);

1283 else if (!FirstIndexIsConstant)

1285 SPIRV::Capability::StorageBufferArrayDynamicIndexing);

1286 return;

1287 }

1288

1290 MachineInstr *PointeeType = MRI.getUniqueVRegDef(PointeeTypeReg);

1291 if (PointeeType->getOpcode() != SPIRV::OpTypeImage &&

1292 PointeeType->getOpcode() != SPIRV::OpTypeSampledImage &&

1293 PointeeType->getOpcode() != SPIRV::OpTypeSampler) {

1294 return;

1295 }

1296

1297 if (isUniformTexelBuffer(PointeeType)) {

1298 if (IsNonUniform)

1300 SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);

1301 else if (!FirstIndexIsConstant)

1303 SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);

1304 } else if (isInputAttachment(PointeeType)) {

1305 if (IsNonUniform)

1307 SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);

1308 else if (!FirstIndexIsConstant)

1310 SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);

1311 } else if (isStorageTexelBuffer(PointeeType)) {

1312 if (IsNonUniform)

1314 SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);

1315 else if (!FirstIndexIsConstant)

1317 SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);

1318 } else if (isSampledImage(PointeeType) ||

1319 isCombinedImageSampler(PointeeType) ||

1320 PointeeType->getOpcode() == SPIRV::OpTypeSampler) {

1321 if (IsNonUniform)

1323 SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);

1324 else if (!FirstIndexIsConstant)

1326 SPIRV::Capability::SampledImageArrayDynamicIndexing);

1327 } else if (isStorageImage(PointeeType)) {

1328 if (IsNonUniform)

1330 SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);

1331 else if (!FirstIndexIsConstant)

1333 SPIRV::Capability::StorageImageArrayDynamicIndexing);

1334 }

1335}

1336

1337static bool isImageTypeWithUnknownFormat(SPIRVType *TypeInst) {

1338 if (TypeInst->getOpcode() != SPIRV::OpTypeImage)

1339 return false;

1342}

1343

1344static void AddDotProductRequirements(const MachineInstr &MI,

1347 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product))

1348 Reqs.addExtension(SPIRV::Extension::SPV_KHR_integer_dot_product);

1349 Reqs.addCapability(SPIRV::Capability::DotProduct);

1350

1352 assert(MI.getOperand(2).isReg() && "Unexpected operand in dot");

1353

1354

1356 assert(Input->getOperand(1).isReg() && "Unexpected operand in dot input");

1357 Register InputReg = Input->getOperand(1).getReg();

1358

1359 SPIRVType *TypeDef = MRI.getVRegDef(InputReg);

1360 if (TypeDef->getOpcode() == SPIRV::OpTypeInt) {

1362 Reqs.addCapability(SPIRV::Capability::DotProductInput4x8BitPacked);

1363 } else if (TypeDef->getOpcode() == SPIRV::OpTypeVector) {

1368 "Dot operand of 8-bit integer type requires 4 components");

1369 Reqs.addCapability(SPIRV::Capability::DotProductInput4x8Bit);

1370 } else {

1371 Reqs.addCapability(SPIRV::Capability::DotProductInputAll);

1372 }

1373 }

1374}

1375

1381 if (PtrType) {

1383 if (ASOp.isImm()) {

1384 unsigned AddrSpace = ASOp.getImm();

1385 if (AddrSpace != SPIRV::StorageClass::UniformConstant) {

1386 if (ST.canUseExtension(

1388 SPV_EXT_relaxed_printf_string_address_space)) {

1389 report_fatal_error("SPV_EXT_relaxed_printf_string_address_space is "

1390 "required because printf uses a format string not "

1391 "in constant address space.",

1392 false);

1393 }

1395 SPIRV::Extension::SPV_EXT_relaxed_printf_string_address_space);

1396 }

1397 }

1398 }

1399}

1400

1405 switch (MI.getOpcode()) {

1406 case SPIRV::OpMemoryModel: {

1407 int64_t Addr = MI.getOperand(0).getImm();

1409 Addr, ST);

1410 int64_t Mem = MI.getOperand(1).getImm();

1412 ST);

1413 break;

1414 }

1415 case SPIRV::OpEntryPoint: {

1416 int64_t Exe = MI.getOperand(0).getImm();

1418 Exe, ST);

1419 break;

1420 }

1421 case SPIRV::OpExecutionMode:

1422 case SPIRV::OpExecutionModeId: {

1423 int64_t Exe = MI.getOperand(1).getImm();

1425 Exe, ST);

1426 break;

1427 }

1428 case SPIRV::OpTypeMatrix:

1430 break;

1431 case SPIRV::OpTypeInt: {

1432 unsigned BitWidth = MI.getOperand(1).getImm();

1439 break;

1440 }

1441 case SPIRV::OpDot: {

1443 SPIRVType *TypeDef = MRI.getVRegDef(MI.getOperand(1).getReg());

1444 if (isBFloat16Type(TypeDef))

1445 Reqs.addCapability(SPIRV::Capability::BFloat16DotProductKHR);

1446 break;

1447 }

1448 case SPIRV::OpTypeFloat: {

1449 unsigned BitWidth = MI.getOperand(1).getImm();

1453 if (isBFloat16Type(&MI)) {

1454 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_bfloat16))

1456 "following SPIR-V extension: SPV_KHR_bfloat16",

1457 false);

1458 Reqs.addExtension(SPIRV::Extension::SPV_KHR_bfloat16);

1459 Reqs.addCapability(SPIRV::Capability::BFloat16TypeKHR);

1460 } else {

1462 }

1463 }

1464 break;

1465 }

1466 case SPIRV::OpTypeVector: {

1467 unsigned NumComponents = MI.getOperand(2).getImm();

1468 if (NumComponents == 8 || NumComponents == 16)

1469 Reqs.addCapability(SPIRV::Capability::Vector16);

1470 break;

1471 }

1472 case SPIRV::OpTypePointer: {

1473 auto SC = MI.getOperand(1).getImm();

1475 ST);

1476

1477

1478 if (ST.isShader())

1479 break;

1480 assert(MI.getOperand(2).isReg());

1482 SPIRVType *TypeDef = MRI.getVRegDef(MI.getOperand(2).getReg());

1484 (TypeDef->getOpcode() == SPIRV::OpTypeFloat) &&

1486 Reqs.addCapability(SPIRV::Capability::Float16Buffer);

1487 break;

1488 }

1489 case SPIRV::OpExtInst: {

1490 if (MI.getOperand(2).getImm() ==

1491 static_cast<int64_t>(

1492 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {

1493 Reqs.addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);

1494 break;

1495 }

1496 if (MI.getOperand(3).getImm() ==

1497 static_cast<int64_t>(SPIRV::OpenCLExtInst::printf)) {

1498 addPrintfRequirements(MI, Reqs, ST);

1499 break;

1500 }

1501

1502

1503 break;

1504 }

1505 case SPIRV::OpAliasDomainDeclINTEL:

1506 case SPIRV::OpAliasScopeDeclINTEL:

1507 case SPIRV::OpAliasScopeListDeclINTEL: {

1508 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing);

1509 Reqs.addCapability(SPIRV::Capability::MemoryAccessAliasingINTEL);

1510 break;

1511 }

1512 case SPIRV::OpBitReverse:

1513 case SPIRV::OpBitFieldInsert:

1514 case SPIRV::OpBitFieldSExtract:

1515 case SPIRV::OpBitFieldUExtract:

1516 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {

1518 break;

1519 }

1520 Reqs.addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);

1521 Reqs.addCapability(SPIRV::Capability::BitInstructions);

1522 break;

1523 case SPIRV::OpTypeRuntimeArray:

1525 break;

1526 case SPIRV::OpTypeOpaque:

1527 case SPIRV::OpTypeEvent:

1529 break;

1530 case SPIRV::OpTypePipe:

1531 case SPIRV::OpTypeReserveId:

1533 break;

1534 case SPIRV::OpTypeDeviceEvent:

1535 case SPIRV::OpTypeQueue:

1536 case SPIRV::OpBuildNDRange:

1537 Reqs.addCapability(SPIRV::Capability::DeviceEnqueue);

1538 break;

1539 case SPIRV::OpDecorate:

1540 case SPIRV::OpDecorateId:

1541 case SPIRV::OpDecorateString:

1542 addOpDecorateReqs(MI, 1, Reqs, ST);

1543 break;

1544 case SPIRV::OpMemberDecorate:

1545 case SPIRV::OpMemberDecorateString:

1546 addOpDecorateReqs(MI, 2, Reqs, ST);

1547 break;

1548 case SPIRV::OpInBoundsPtrAccessChain:

1549 Reqs.addCapability(SPIRV::Capability::Addresses);

1550 break;

1551 case SPIRV::OpConstantSampler:

1552 Reqs.addCapability(SPIRV::Capability::LiteralSampler);

1553 break;

1554 case SPIRV::OpInBoundsAccessChain:

1555 case SPIRV::OpAccessChain:

1556 addOpAccessChainReqs(MI, Reqs, ST);

1557 break;

1558 case SPIRV::OpTypeImage:

1559 addOpTypeImageReqs(MI, Reqs, ST);

1560 break;

1561 case SPIRV::OpTypeSampler:

1562 if (ST.isShader()) {

1563 Reqs.addCapability(SPIRV::Capability::ImageBasic);

1564 }

1565 break;

1566 case SPIRV::OpTypeForwardPointer:

1567

1568 Reqs.addCapability(SPIRV::Capability::Addresses);

1569 break;

1570 case SPIRV::OpAtomicFlagTestAndSet:

1571 case SPIRV::OpAtomicLoad:

1572 case SPIRV::OpAtomicStore:

1573 case SPIRV::OpAtomicExchange:

1574 case SPIRV::OpAtomicCompareExchange:

1575 case SPIRV::OpAtomicIIncrement:

1576 case SPIRV::OpAtomicIDecrement:

1577 case SPIRV::OpAtomicIAdd:

1578 case SPIRV::OpAtomicISub:

1579 case SPIRV::OpAtomicUMin:

1580 case SPIRV::OpAtomicUMax:

1581 case SPIRV::OpAtomicSMin:

1582 case SPIRV::OpAtomicSMax:

1583 case SPIRV::OpAtomicAnd:

1584 case SPIRV::OpAtomicOr:

1585 case SPIRV::OpAtomicXor: {

1588 if (MI.getOpcode() == SPIRV::OpAtomicStore) {

1589 assert(MI.getOperand(3).isReg());

1590 InstrPtr = MRI.getVRegDef(MI.getOperand(3).getReg());

1591 assert(InstrPtr && "Unexpected type instruction for OpAtomicStore");

1592 }

1595 SPIRVType *TypeDef = MRI.getVRegDef(TypeReg);

1596 if (TypeDef->getOpcode() == SPIRV::OpTypeInt) {

1599 Reqs.addCapability(SPIRV::Capability::Int64Atomics);

1600 }

1601 break;

1602 }

1603 case SPIRV::OpGroupNonUniformIAdd:

1604 case SPIRV::OpGroupNonUniformFAdd:

1605 case SPIRV::OpGroupNonUniformIMul:

1606 case SPIRV::OpGroupNonUniformFMul:

1607 case SPIRV::OpGroupNonUniformSMin:

1608 case SPIRV::OpGroupNonUniformUMin:

1609 case SPIRV::OpGroupNonUniformFMin:

1610 case SPIRV::OpGroupNonUniformSMax:

1611 case SPIRV::OpGroupNonUniformUMax:

1612 case SPIRV::OpGroupNonUniformFMax:

1613 case SPIRV::OpGroupNonUniformBitwiseAnd:

1614 case SPIRV::OpGroupNonUniformBitwiseOr:

1615 case SPIRV::OpGroupNonUniformBitwiseXor:

1616 case SPIRV::OpGroupNonUniformLogicalAnd:

1617 case SPIRV::OpGroupNonUniformLogicalOr:

1618 case SPIRV::OpGroupNonUniformLogicalXor: {

1619 assert(MI.getOperand(3).isImm());

1620 int64_t GroupOp = MI.getOperand(3).getImm();

1621 switch (GroupOp) {

1622 case SPIRV::GroupOperation::Reduce:

1623 case SPIRV::GroupOperation::InclusiveScan:

1624 case SPIRV::GroupOperation::ExclusiveScan:

1625 Reqs.addCapability(SPIRV::Capability::GroupNonUniformArithmetic);

1626 break;

1627 case SPIRV::GroupOperation::ClusteredReduce:

1628 Reqs.addCapability(SPIRV::Capability::GroupNonUniformClustered);

1629 break;

1630 case SPIRV::GroupOperation::PartitionedReduceNV:

1631 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:

1632 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:

1633 Reqs.addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);

1634 break;

1635 }

1636 break;

1637 }

1638 case SPIRV::OpGroupNonUniformShuffle:

1639 case SPIRV::OpGroupNonUniformShuffleXor:

1640 Reqs.addCapability(SPIRV::Capability::GroupNonUniformShuffle);

1641 break;

1642 case SPIRV::OpGroupNonUniformShuffleUp:

1643 case SPIRV::OpGroupNonUniformShuffleDown:

1644 Reqs.addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);

1645 break;

1646 case SPIRV::OpGroupAll:

1647 case SPIRV::OpGroupAny:

1648 case SPIRV::OpGroupBroadcast:

1649 case SPIRV::OpGroupIAdd:

1650 case SPIRV::OpGroupFAdd:

1651 case SPIRV::OpGroupFMin:

1652 case SPIRV::OpGroupUMin:

1653 case SPIRV::OpGroupSMin:

1654 case SPIRV::OpGroupFMax:

1655 case SPIRV::OpGroupUMax:

1656 case SPIRV::OpGroupSMax:

1658 break;

1659 case SPIRV::OpGroupNonUniformElect:

1660 Reqs.addCapability(SPIRV::Capability::GroupNonUniform);

1661 break;

1662 case SPIRV::OpGroupNonUniformAll:

1663 case SPIRV::OpGroupNonUniformAny:

1664 case SPIRV::OpGroupNonUniformAllEqual:

1665 Reqs.addCapability(SPIRV::Capability::GroupNonUniformVote);

1666 break;

1667 case SPIRV::OpGroupNonUniformBroadcast:

1668 case SPIRV::OpGroupNonUniformBroadcastFirst:

1669 case SPIRV::OpGroupNonUniformBallot:

1670 case SPIRV::OpGroupNonUniformInverseBallot:

1671 case SPIRV::OpGroupNonUniformBallotBitExtract:

1672 case SPIRV::OpGroupNonUniformBallotBitCount:

1673 case SPIRV::OpGroupNonUniformBallotFindLSB:

1674 case SPIRV::OpGroupNonUniformBallotFindMSB:

1675 Reqs.addCapability(SPIRV::Capability::GroupNonUniformBallot);

1676 break;

1677 case SPIRV::OpSubgroupShuffleINTEL:

1678 case SPIRV::OpSubgroupShuffleDownINTEL:

1679 case SPIRV::OpSubgroupShuffleUpINTEL:

1680 case SPIRV::OpSubgroupShuffleXorINTEL:

1681 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {

1682 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_subgroups);

1683 Reqs.addCapability(SPIRV::Capability::SubgroupShuffleINTEL);

1684 }

1685 break;

1686 case SPIRV::OpSubgroupBlockReadINTEL:

1687 case SPIRV::OpSubgroupBlockWriteINTEL:

1688 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {

1689 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_subgroups);

1690 Reqs.addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);

1691 }

1692 break;

1693 case SPIRV::OpSubgroupImageBlockReadINTEL:

1694 case SPIRV::OpSubgroupImageBlockWriteINTEL:

1695 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {

1696 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_subgroups);

1697 Reqs.addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);

1698 }

1699 break;

1700 case SPIRV::OpSubgroupImageMediaBlockReadINTEL:

1701 case SPIRV::OpSubgroupImageMediaBlockWriteINTEL:

1702 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {

1703 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_media_block_io);

1704 Reqs.addCapability(SPIRV::Capability::SubgroupImageMediaBlockIOINTEL);

1705 }

1706 break;

1707 case SPIRV::OpAssumeTrueKHR:

1708 case SPIRV::OpExpectKHR:

1709 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {

1710 Reqs.addExtension(SPIRV::Extension::SPV_KHR_expect_assume);

1711 Reqs.addCapability(SPIRV::Capability::ExpectAssumeKHR);

1712 }

1713 break;

1714 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:

1715 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:

1716 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {

1717 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);

1718 Reqs.addCapability(SPIRV::Capability::USMStorageClassesINTEL);

1719 }

1720 break;

1721 case SPIRV::OpConstantFunctionPointerINTEL:

1722 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {

1723 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);

1724 Reqs.addCapability(SPIRV::Capability::FunctionPointersINTEL);

1725 }

1726 break;

1727 case SPIRV::OpGroupNonUniformRotateKHR:

1728 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))

1729 report_fatal_error("OpGroupNonUniformRotateKHR instruction requires the "

1730 "following SPIR-V extension: SPV_KHR_subgroup_rotate",

1731 false);

1732 Reqs.addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);

1733 Reqs.addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);

1734 Reqs.addCapability(SPIRV::Capability::GroupNonUniform);

1735 break;

1736 case SPIRV::OpFixedCosALTERA:

1737 case SPIRV::OpFixedSinALTERA:

1738 case SPIRV::OpFixedCosPiALTERA:

1739 case SPIRV::OpFixedSinPiALTERA:

1740 case SPIRV::OpFixedExpALTERA:

1741 case SPIRV::OpFixedLogALTERA:

1742 case SPIRV::OpFixedRecipALTERA:

1743 case SPIRV::OpFixedSqrtALTERA:

1744 case SPIRV::OpFixedSinCosALTERA:

1745 case SPIRV::OpFixedSinCosPiALTERA:

1746 case SPIRV::OpFixedRsqrtALTERA:

1747 if (ST.canUseExtension(

1748 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point))

1750 "following SPIR-V extension: "

1751 "SPV_ALTERA_arbitrary_precision_fixed_point",

1752 false);

1754 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point);

1755 Reqs.addCapability(SPIRV::Capability::ArbitraryPrecisionFixedPointALTERA);

1756 break;

1757 case SPIRV::OpGroupIMulKHR:

1758 case SPIRV::OpGroupFMulKHR:

1759 case SPIRV::OpGroupBitwiseAndKHR:

1760 case SPIRV::OpGroupBitwiseOrKHR:

1761 case SPIRV::OpGroupBitwiseXorKHR:

1762 case SPIRV::OpGroupLogicalAndKHR:

1763 case SPIRV::OpGroupLogicalOrKHR:

1764 case SPIRV::OpGroupLogicalXorKHR:

1765 if (ST.canUseExtension(

1766 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {

1767 Reqs.addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);

1768 Reqs.addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);

1769 }

1770 break;

1771 case SPIRV::OpReadClockKHR:

1772 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock))

1774 "following SPIR-V extension: SPV_KHR_shader_clock",

1775 false);

1776 Reqs.addExtension(SPIRV::Extension::SPV_KHR_shader_clock);

1777 Reqs.addCapability(SPIRV::Capability::ShaderClockKHR);

1778 break;

1779 case SPIRV::OpFunctionPointerCallINTEL:

1780 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {

1781 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);

1782 Reqs.addCapability(SPIRV::Capability::FunctionPointersINTEL);

1783 }

1784 break;

1785 case SPIRV::OpAtomicFAddEXT:

1786 case SPIRV::OpAtomicFMinEXT:

1787 case SPIRV::OpAtomicFMaxEXT:

1788 AddAtomicFloatRequirements(MI, Reqs, ST);

1789 break;

1790 case SPIRV::OpConvertBF16ToFINTEL:

1791 case SPIRV::OpConvertFToBF16INTEL:

1792 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {

1793 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);

1794 Reqs.addCapability(SPIRV::Capability::BFloat16ConversionINTEL);

1795 }

1796 break;

1797 case SPIRV::OpRoundFToTF32INTEL:

1798 if (ST.canUseExtension(

1799 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion)) {

1800 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_tensor_float32_conversion);

1801 Reqs.addCapability(SPIRV::Capability::TensorFloat32RoundingINTEL);

1802 }

1803 break;

1804 case SPIRV::OpVariableLengthArrayINTEL:

1805 case SPIRV::OpSaveMemoryINTEL:

1806 case SPIRV::OpRestoreMemoryINTEL:

1807 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {

1808 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);

1809 Reqs.addCapability(SPIRV::Capability::VariableLengthArrayINTEL);

1810 }

1811 break;

1812 case SPIRV::OpAsmTargetINTEL:

1813 case SPIRV::OpAsmINTEL:

1814 case SPIRV::OpAsmCallINTEL:

1815 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly)) {

1816 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_inline_assembly);

1817 Reqs.addCapability(SPIRV::Capability::AsmINTEL);

1818 }

1819 break;

1820 case SPIRV::OpTypeCooperativeMatrixKHR: {

1821 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))

1823 "OpTypeCooperativeMatrixKHR type requires the "

1824 "following SPIR-V extension: SPV_KHR_cooperative_matrix",

1825 false);

1826 Reqs.addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);

1827 Reqs.addCapability(SPIRV::Capability::CooperativeMatrixKHR);

1829 SPIRVType *TypeDef = MRI.getVRegDef(MI.getOperand(1).getReg());

1830 if (isBFloat16Type(TypeDef))

1831 Reqs.addCapability(SPIRV::Capability::BFloat16CooperativeMatrixKHR);

1832 break;

1833 }

1834 case SPIRV::OpArithmeticFenceEXT:

1835 if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))

1837 "following SPIR-V extension: SPV_EXT_arithmetic_fence",

1838 false);

1839 Reqs.addExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence);

1840 Reqs.addCapability(SPIRV::Capability::ArithmeticFenceEXT);

1841 break;

1842 case SPIRV::OpControlBarrierArriveINTEL:

1843 case SPIRV::OpControlBarrierWaitINTEL:

1844 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {

1845 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_split_barrier);

1846 Reqs.addCapability(SPIRV::Capability::SplitBarrierINTEL);

1847 }

1848 break;

1849 case SPIRV::OpCooperativeMatrixMulAddKHR: {

1850 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))

1852 "following SPIR-V extension: "

1853 "SPV_KHR_cooperative_matrix",

1854 false);

1855 Reqs.addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);

1856 Reqs.addCapability(SPIRV::Capability::CooperativeMatrixKHR);

1857 constexpr unsigned MulAddMaxSize = 6;

1858 if (MI.getNumOperands() != MulAddMaxSize)

1859 break;

1860 const int64_t CoopOperands = MI.getOperand(MulAddMaxSize - 1).getImm();

1861 if (CoopOperands &

1862 SPIRV::CooperativeMatrixOperands::MatrixAAndBTF32ComponentsINTEL) {

1863 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))

1864 report_fatal_error("MatrixAAndBTF32ComponentsINTEL type interpretation "

1865 "require the following SPIR-V extension: "

1866 "SPV_INTEL_joint_matrix",

1867 false);

1868 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);

1870 SPIRV::Capability::CooperativeMatrixTF32ComponentTypeINTEL);

1871 }

1873 MatrixAAndBBFloat16ComponentsINTEL ||

1874 CoopOperands &

1875 SPIRV::CooperativeMatrixOperands::MatrixCBFloat16ComponentsINTEL ||

1877 MatrixResultBFloat16ComponentsINTEL) {

1878 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))

1880 "require the following SPIR-V extension: "

1881 "SPV_INTEL_joint_matrix",

1882 false);

1883 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);

1885 SPIRV::Capability::CooperativeMatrixBFloat16ComponentTypeINTEL);

1886 }

1887 break;

1888 }

1889 case SPIRV::OpCooperativeMatrixLoadKHR:

1890 case SPIRV::OpCooperativeMatrixStoreKHR:

1891 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:

1892 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:

1893 case SPIRV::OpCooperativeMatrixPrefetchINTEL: {

1894 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))

1896 "following SPIR-V extension: "

1897 "SPV_KHR_cooperative_matrix",

1898 false);

1899 Reqs.addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);

1900 Reqs.addCapability(SPIRV::Capability::CooperativeMatrixKHR);

1901

1902

1903

1904 std::unordered_map<unsigned, unsigned> LayoutToInstMap = {

1905 {SPIRV::OpCooperativeMatrixLoadKHR, 3},

1906 {SPIRV::OpCooperativeMatrixStoreKHR, 2},

1907 {SPIRV::OpCooperativeMatrixLoadCheckedINTEL, 5},

1908 {SPIRV::OpCooperativeMatrixStoreCheckedINTEL, 4},

1909 {SPIRV::OpCooperativeMatrixPrefetchINTEL, 4}};

1910

1911 const auto OpCode = MI.getOpcode();

1912 const unsigned LayoutNum = LayoutToInstMap[OpCode];

1913 Register RegLayout = MI.getOperand(LayoutNum).getReg();

1915 MachineInstr *MILayout = MRI.getUniqueVRegDef(RegLayout);

1916 if (MILayout->getOpcode() == SPIRV::OpConstantI) {

1917 const unsigned LayoutVal = MILayout->getOperand(2).getImm();

1918 if (LayoutVal ==

1919 static_cast<unsigned>(SPIRV::CooperativeMatrixLayout::PackedINTEL)) {

1920 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))

1921 report_fatal_error("PackedINTEL layout require the following SPIR-V "

1922 "extension: SPV_INTEL_joint_matrix",

1923 false);

1924 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);

1925 Reqs.addCapability(SPIRV::Capability::PackedCooperativeMatrixINTEL);

1926 }

1927 }

1928

1929

1930 if (OpCode == SPIRV::OpCooperativeMatrixLoadKHR ||

1931 OpCode == SPIRV::OpCooperativeMatrixStoreKHR)

1932 break;

1933

1934 std::string InstName;

1935 switch (OpCode) {

1936 case SPIRV::OpCooperativeMatrixPrefetchINTEL:

1937 InstName = "OpCooperativeMatrixPrefetchINTEL";

1938 break;

1939 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:

1940 InstName = "OpCooperativeMatrixLoadCheckedINTEL";

1941 break;

1942 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:

1943 InstName = "OpCooperativeMatrixStoreCheckedINTEL";

1944 break;

1945 }

1946

1947 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix)) {

1948 const std::string ErrorMsg =

1949 InstName + " instruction requires the "

1950 "following SPIR-V extension: SPV_INTEL_joint_matrix";

1952 }

1953 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);

1954 if (OpCode == SPIRV::OpCooperativeMatrixPrefetchINTEL) {

1955 Reqs.addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);

1956 break;

1957 }

1959 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);

1960 break;

1961 }

1962 case SPIRV::OpCooperativeMatrixConstructCheckedINTEL:

1963 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))

1965 "instructions require the following SPIR-V extension: "

1966 "SPV_INTEL_joint_matrix",

1967 false);

1968 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);

1970 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);

1971 break;

1972 case SPIRV::OpReadPipeBlockingALTERA:

1973 case SPIRV::OpWritePipeBlockingALTERA:

1974 if (ST.canUseExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes)) {

1975 Reqs.addExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes);

1976 Reqs.addCapability(SPIRV::Capability::BlockingPipesALTERA);

1977 }

1978 break;

1979 case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:

1980 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))

1981 report_fatal_error("OpCooperativeMatrixGetElementCoordINTEL requires the "

1982 "following SPIR-V extension: SPV_INTEL_joint_matrix",

1983 false);

1984 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);

1986 SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL);

1987 break;

1988 case SPIRV::OpConvertHandleToImageINTEL:

1989 case SPIRV::OpConvertHandleToSamplerINTEL:

1990 case SPIRV::OpConvertHandleToSampledImageINTEL: {

1991 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images))

1992 report_fatal_error("OpConvertHandleTo[Image/Sampler/SampledImage]INTEL "

1993 "instructions require the following SPIR-V extension: "

1994 "SPV_INTEL_bindless_images",

1995 false);

1997 SPIRV::AddressingModel::AddressingModel AddrModel = MAI.Addr;

1999 if (MI.getOpcode() == SPIRV::OpConvertHandleToImageINTEL &&

2000 TyDef->getOpcode() != SPIRV::OpTypeImage) {

2002 "OpConvertHandleToImageINTEL",

2003 false);

2004 } else if (MI.getOpcode() == SPIRV::OpConvertHandleToSamplerINTEL &&

2005 TyDef->getOpcode() != SPIRV::OpTypeSampler) {

2007 "OpConvertHandleToSamplerINTEL",

2008 false);

2009 } else if (MI.getOpcode() == SPIRV::OpConvertHandleToSampledImageINTEL &&

2010 TyDef->getOpcode() != SPIRV::OpTypeSampledImage) {

2012 "OpConvertHandleToSampledImageINTEL",

2013 false);

2014 }

2017 if (!(Bitwidth == 32 && AddrModel == SPIRV::AddressingModel::Physical32) &&

2018 !(Bitwidth == 64 && AddrModel == SPIRV::AddressingModel::Physical64)) {

2020 "Parameter value must be a 32-bit scalar in case of "

2021 "Physical32 addressing model or a 64-bit scalar in case of "

2022 "Physical64 addressing model",

2023 false);

2024 }

2025 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_bindless_images);

2026 Reqs.addCapability(SPIRV::Capability::BindlessImagesINTEL);

2027 break;

2028 }

2029 case SPIRV::OpSubgroup2DBlockLoadINTEL:

2030 case SPIRV::OpSubgroup2DBlockLoadTransposeINTEL:

2031 case SPIRV::OpSubgroup2DBlockLoadTransformINTEL:

2032 case SPIRV::OpSubgroup2DBlockPrefetchINTEL:

2033 case SPIRV::OpSubgroup2DBlockStoreINTEL: {

2034 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_2d_block_io))

2035 report_fatal_error("OpSubgroup2DBlock[Load/LoadTranspose/LoadTransform/"

2036 "Prefetch/Store]INTEL instructions require the "

2037 "following SPIR-V extension: SPV_INTEL_2d_block_io",

2038 false);

2039 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_2d_block_io);

2040 Reqs.addCapability(SPIRV::Capability::Subgroup2DBlockIOINTEL);

2041

2042 const auto OpCode = MI.getOpcode();

2043 if (OpCode == SPIRV::OpSubgroup2DBlockLoadTransposeINTEL) {

2044 Reqs.addCapability(SPIRV::Capability::Subgroup2DBlockTransposeINTEL);

2045 break;

2046 }

2047 if (OpCode == SPIRV::OpSubgroup2DBlockLoadTransformINTEL) {

2048 Reqs.addCapability(SPIRV::Capability::Subgroup2DBlockTransformINTEL);

2049 break;

2050 }

2051 break;

2052 }

2053 case SPIRV::OpKill: {

2055 } break;

2056 case SPIRV::OpDemoteToHelperInvocation:

2057 Reqs.addCapability(SPIRV::Capability::DemoteToHelperInvocation);

2058

2059 if (ST.canUseExtension(

2060 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {

2063 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);

2064 }

2065 break;

2066 case SPIRV::OpSDot:

2067 case SPIRV::OpUDot:

2068 case SPIRV::OpSUDot:

2069 case SPIRV::OpSDotAccSat:

2070 case SPIRV::OpUDotAccSat:

2071 case SPIRV::OpSUDotAccSat:

2072 AddDotProductRequirements(MI, Reqs, ST);

2073 break;

2074 case SPIRV::OpImageRead: {

2075 Register ImageReg = MI.getOperand(2).getReg();

2076 SPIRVType *TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(

2078

2079

2080

2081

2082

2083

2084 if (isImageTypeWithUnknownFormat(TypeDef) && ST.isShader())

2085 Reqs.addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);

2086 break;

2087 }

2088 case SPIRV::OpImageWrite: {

2089 Register ImageReg = MI.getOperand(0).getReg();

2090 SPIRVType *TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(

2092

2093

2094

2095

2096

2097

2098 if (isImageTypeWithUnknownFormat(TypeDef) && ST.isShader())

2099 Reqs.addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);

2100 break;

2101 }

2102 case SPIRV::OpTypeStructContinuedINTEL:

2103 case SPIRV::OpConstantCompositeContinuedINTEL:

2104 case SPIRV::OpSpecConstantCompositeContinuedINTEL:

2105 case SPIRV::OpCompositeConstructContinuedINTEL: {

2106 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_long_composites))

2108 "Continued instructions require the "

2109 "following SPIR-V extension: SPV_INTEL_long_composites",

2110 false);

2111 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_long_composites);

2112 Reqs.addCapability(SPIRV::Capability::LongCompositesINTEL);

2113 break;

2114 }

2115 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {

2116 if (ST.canUseExtension(

2117 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate))

2119 "OpSubgroupMatrixMultiplyAccumulateINTEL instruction requires the "

2120 "following SPIR-V "

2121 "extension: SPV_INTEL_subgroup_matrix_multiply_accumulate",

2122 false);

2124 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate);

2126 SPIRV::Capability::SubgroupMatrixMultiplyAccumulateINTEL);

2127 break;

2128 }

2129 case SPIRV::OpBitwiseFunctionINTEL: {

2130 if (ST.canUseExtension(

2131 SPIRV::Extension::SPV_INTEL_ternary_bitwise_function))

2133 "OpBitwiseFunctionINTEL instruction requires the following SPIR-V "

2134 "extension: SPV_INTEL_ternary_bitwise_function",

2135 false);

2136 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_ternary_bitwise_function);

2137 Reqs.addCapability(SPIRV::Capability::TernaryBitwiseFunctionINTEL);

2138 break;

2139 }

2140 case SPIRV::OpCopyMemorySized: {

2141 Reqs.addCapability(SPIRV::Capability::Addresses);

2142

2143 break;

2144 }

2145 case SPIRV::OpPredicatedLoadINTEL:

2146 case SPIRV::OpPredicatedStoreINTEL: {

2147 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_predicated_io))

2149 "OpPredicated[Load/Store]INTEL instructions require "

2150 "the following SPIR-V extension: SPV_INTEL_predicated_io",

2151 false);

2152 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_predicated_io);

2153 Reqs.addCapability(SPIRV::Capability::PredicatedIOINTEL);

2154 break;

2155 }

2156 case SPIRV::OpFAddS:

2157 case SPIRV::OpFSubS:

2158 case SPIRV::OpFMulS:

2159 case SPIRV::OpFDivS:

2160 case SPIRV::OpFRemS:

2161 case SPIRV::OpFMod:

2162 case SPIRV::OpFNegate:

2163 case SPIRV::OpFAddV:

2164 case SPIRV::OpFSubV:

2165 case SPIRV::OpFMulV:

2166 case SPIRV::OpFDivV:

2167 case SPIRV::OpFRemV:

2168 case SPIRV::OpFNegateV: {

2170 SPIRVType *TypeDef = MRI.getVRegDef(MI.getOperand(1).getReg());

2171 if (TypeDef->getOpcode() == SPIRV::OpTypeVector)

2173 if (isBFloat16Type(TypeDef)) {

2174 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))

2176 "Arithmetic instructions with bfloat16 arguments require the "

2177 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",

2178 false);

2179 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);

2180 Reqs.addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);

2181 }

2182 break;

2183 }

2184 case SPIRV::OpOrdered:

2185 case SPIRV::OpUnordered:

2186 case SPIRV::OpFOrdEqual:

2187 case SPIRV::OpFOrdNotEqual:

2188 case SPIRV::OpFOrdLessThan:

2189 case SPIRV::OpFOrdLessThanEqual:

2190 case SPIRV::OpFOrdGreaterThan:

2191 case SPIRV::OpFOrdGreaterThanEqual:

2192 case SPIRV::OpFUnordEqual:

2193 case SPIRV::OpFUnordNotEqual:

2194 case SPIRV::OpFUnordLessThan:

2195 case SPIRV::OpFUnordLessThanEqual:

2196 case SPIRV::OpFUnordGreaterThan:

2197 case SPIRV::OpFUnordGreaterThanEqual: {

2199 MachineInstr *OperandDef = MRI.getVRegDef(MI.getOperand(2).getReg());

2201 if (TypeDef->getOpcode() == SPIRV::OpTypeVector)

2203 if (isBFloat16Type(TypeDef)) {

2204 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))

2206 "Relational instructions with bfloat16 arguments require the "

2207 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",

2208 false);

2209 Reqs.addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);

2210 Reqs.addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);

2211 }

2212 break;

2213 }

2214 case SPIRV::OpDPdxCoarse:

2215 case SPIRV::OpDPdyCoarse: {

2216 Reqs.addCapability(SPIRV::Capability::DerivativeControl);

2217 break;

2218 }

2219

2220 default:

2221 break;

2222 }

2223

2224

2225

2226

2228 SPIRV::Capability::Shader);

2229}

2230

2233

2236 if (!MF)

2237 continue;

2240 addInstrRequirements(MI, MAI, ST);

2241 }

2242

2243 auto Node = M.getNamedMetadata("spirv.ExecutionMode");

2245 bool RequireFloatControls = false, RequireIntelFloatControls2 = false,

2246 RequireKHRFloatControls2 = false,

2247 VerLower14 = ST.isAtLeastSPIRVVer(VersionTuple(1, 4));

2248 bool HasIntelFloatControls2 =

2249 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);

2250 bool HasKHRFloatControls2 =

2251 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);

2252 for (unsigned i = 0; i < Node->getNumOperands(); i++) {

2256 Constant *C = CMeta->getValue();

2258 auto EM = Const->getZExtValue();

2259

2260

2261 switch (EM) {

2262 case SPIRV::ExecutionMode::DenormPreserve:

2263 case SPIRV::ExecutionMode::DenormFlushToZero:

2264 case SPIRV::ExecutionMode::RoundingModeRTE:

2265 case SPIRV::ExecutionMode::RoundingModeRTZ:

2266 RequireFloatControls = VerLower14;

2268 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);

2269 break;

2270 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:

2271 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:

2272 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:

2273 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:

2274 if (HasIntelFloatControls2) {

2275 RequireIntelFloatControls2 = true;

2277 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);

2278 }

2279 break;

2280 case SPIRV::ExecutionMode::FPFastMathDefault: {

2281 if (HasKHRFloatControls2) {

2282 RequireKHRFloatControls2 = true;

2284 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);

2285 }

2286 break;

2287 }

2288 case SPIRV::ExecutionMode::ContractionOff:

2289 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:

2290 if (HasKHRFloatControls2) {

2291 RequireKHRFloatControls2 = true;

2293 SPIRV::OperandCategory::ExecutionModeOperand,

2294 SPIRV::ExecutionMode::FPFastMathDefault, ST);

2295 } else {

2297 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);

2298 }

2299 break;

2300 default:

2302 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);

2303 }

2304 }

2305 }

2306 }

2307 if (RequireFloatControls &&

2308 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))

2309 MAI.Reqs.addExtension(SPIRV::Extension::SPV_KHR_float_controls);

2310 if (RequireIntelFloatControls2)

2311 MAI.Reqs.addExtension(SPIRV::Extension::SPV_INTEL_float_controls2);

2312 if (RequireKHRFloatControls2)

2313 MAI.Reqs.addExtension(SPIRV::Extension::SPV_KHR_float_controls2);

2314 }

2316 if (F.isDeclaration())

2317 continue;

2318 if (F.getMetadata("reqd_work_group_size"))

2320 SPIRV::OperandCategory::ExecutionModeOperand,

2321 SPIRV::ExecutionMode::LocalSize, ST);

2322 if (F.getFnAttribute("hlsl.numthreads").isValid()) {

2324 SPIRV::OperandCategory::ExecutionModeOperand,

2325 SPIRV::ExecutionMode::LocalSize, ST);

2326 }

2327 if (F.getFnAttribute("enable-maximal-reconvergence").getValueAsBool()) {

2328 MAI.Reqs.addExtension(SPIRV::Extension::SPV_KHR_maximal_reconvergence);

2329 }

2330 if (F.getMetadata("work_group_size_hint"))

2332 SPIRV::OperandCategory::ExecutionModeOperand,

2333 SPIRV::ExecutionMode::LocalSizeHint, ST);

2334 if (F.getMetadata("intel_reqd_sub_group_size"))

2336 SPIRV::OperandCategory::ExecutionModeOperand,

2337 SPIRV::ExecutionMode::SubgroupSize, ST);

2338 if (F.getMetadata("max_work_group_size"))

2340 SPIRV::OperandCategory::ExecutionModeOperand,

2341 SPIRV::ExecutionMode::MaxWorkgroupSizeINTEL, ST);

2342 if (F.getMetadata("vec_type_hint"))

2344 SPIRV::OperandCategory::ExecutionModeOperand,

2345 SPIRV::ExecutionMode::VecTypeHint, ST);

2346

2347 if (F.hasOptNone()) {

2348 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {

2351 } else if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {

2354 }

2355 }

2356 }

2357}

2358

2359static unsigned getFastMathFlags(const MachineInstr &I,

2361 unsigned Flags = SPIRV::FPFastMathMode::None;

2362 bool CanUseKHRFloatControls2 =

2363 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);

2365 Flags |= SPIRV::FPFastMathMode::NotNaN;

2367 Flags |= SPIRV::FPFastMathMode::NotInf;

2369 Flags |= SPIRV::FPFastMathMode::NSZ;

2371 Flags |= SPIRV::FPFastMathMode::AllowRecip;

2373 Flags |= SPIRV::FPFastMathMode::AllowContract;

2375 if (CanUseKHRFloatControls2)

2376

2377

2378

2379

2380

2381

2382

2383 Flags |= SPIRV::FPFastMathMode::NotNaN | SPIRV::FPFastMathMode::NotInf |

2384 SPIRV::FPFastMathMode::NSZ | SPIRV::FPFastMathMode::AllowRecip |

2385 SPIRV::FPFastMathMode::AllowTransform |

2386 SPIRV::FPFastMathMode::AllowReassoc |

2387 SPIRV::FPFastMathMode::AllowContract;

2388 else

2389 Flags |= SPIRV::FPFastMathMode::Fast;

2390 }

2391

2392 if (CanUseKHRFloatControls2) {

2393

2394 assert(!(Flags & SPIRV::FPFastMathMode::Fast) &&

2395 "SPIRV::FPFastMathMode::Fast is deprecated and should not be used "

2396 "anymore.");

2397

2398

2399

2400 assert((!(Flags & SPIRV::FPFastMathMode::AllowTransform) ||

2401 ((Flags & SPIRV::FPFastMathMode::AllowReassoc &&

2402 Flags & SPIRV::FPFastMathMode::AllowContract))) &&

2403 "SPIRV::FPFastMathMode::AllowTransform requires AllowReassoc and "

2404 "AllowContract flags to be enabled as well.");

2405 }

2406

2407 return Flags;

2408}

2409

2410static bool isFastMathModeAvailable(const SPIRVSubtarget &ST) {

2411 if (ST.isKernel())

2412 return true;

2414 return false;

2415 return ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);

2416}

2417

2418static void handleMIFlagDecoration(

2423 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,

2424 SPIRV::Decoration::NoSignedWrap, ST, Reqs)

2425 .IsSatisfiable) {

2427 SPIRV::Decoration::NoSignedWrap, {});

2428 }

2430 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,

2431 SPIRV::Decoration::NoUnsignedWrap, ST,

2432 Reqs)

2433 .IsSatisfiable) {

2435 SPIRV::Decoration::NoUnsignedWrap, {});

2436 }

2437 if (TII.canUseFastMathFlags(

2438 I, ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)))

2439 return;

2440

2441 unsigned FMFlags = getFastMathFlags(I, ST);

2442 if (FMFlags == SPIRV::FPFastMathMode::None) {

2443

2444

2445 if (FPFastMathDefaultInfoVec.empty())

2446 return;

2447

2448

2449

2450

2451

2452

2453

2454

2455

2456

2457

2458

2459

2460

2461 assert(I.getNumOperands() >= 3 && "Expected at least 3 operands");

2462 Register ResReg = I.getOpcode() == SPIRV::OpExtInst

2463 ? I.getOperand(1).getReg()

2464 : I.getOperand(2).getReg();

2468

2469

2470 bool Emit = false;

2472 if (Ty == Elem.Ty) {

2473 FMFlags = Elem.FastMathFlags;

2474 Emit = Elem.ContractionOff || Elem.SignedZeroInfNanPreserve ||

2475 Elem.FPFastMathDefault;

2476 break;

2477 }

2478 }

2479

2480 if (FMFlags == SPIRV::FPFastMathMode::None && !Emit)

2481 return;

2482 }

2483 if (isFastMathModeAvailable(ST)) {

2484 Register DstReg = I.getOperand(0).getReg();

2486 {FMFlags});

2487 }

2488}

2489

2490

2497 if (!MF)

2498 continue;

2499

2500 for (auto &MBB : *MF)

2501 for (auto &MI : MBB)

2502 handleMIFlagDecoration(MI, ST, TII, MAI.Reqs, GR,

2504 }

2505}

2506

2512 if (!MF)

2513 continue;

2515 for (auto &MBB : *MF) {

2516 if (MBB.hasName() || MBB.empty())

2517 continue;

2518

2520 MRI.setRegClass(Reg, &SPIRV::IDRegClass);

2524 }

2525 }

2526}

2527

2528

2533 if (!MF)

2534 continue;

2535 for (auto &MBB : *MF) {

2537 MI.setDesc(TII.get(SPIRV::OpPhi));

2540 MI.insert(MI.operands_begin() + 1,

2541 {MachineOperand::CreateReg(ResTypeReg, false)});

2542 }

2543 }

2544

2546 }

2547}

2548

2553 return it->second;

2554

2555

2556

2557

2560 SPIRV::FPFastMathMode::None);

2562 SPIRV::FPFastMathMode::None);

2564 SPIRV::FPFastMathMode::None);

2566}

2567

2570 const Type *Ty) {

2571 size_t BitWidth = Ty->getScalarSizeInBits();

2572 int Index =

2575 assert(Index >= 0 && Index < 3 &&

2576 "Expected FPFastMathDefaultInfo for half, float, or double");

2577 assert(FPFastMathDefaultInfoVec.size() == 3 &&

2578 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");

2579 return FPFastMathDefaultInfoVec[Index];

2580}

2581

2582static void collectFPFastMathDefaults(const Module &M,

2585 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2))

2586 return;

2587

2588

2589

2590

2591

2592

2593

2594 auto Node = M.getNamedMetadata("spirv.ExecutionMode");

2596 return;

2597

2598 for (unsigned i = 0; i < Node->getNumOperands(); i++) {

2603 const auto EM =

2606 ->getZExtValue();

2607 if (EM == SPIRV::ExecutionMode::FPFastMathDefault) {

2609 "Expected 4 operands for FPFastMathDefault");

2610

2612 unsigned Flags =

2615 ->getZExtValue();

2620 Info.FastMathFlags = Flags;

2621 Info.FPFastMathDefault = true;

2622 } else if (EM == SPIRV::ExecutionMode::ContractionOff) {

2624 "Expected no operands for ContractionOff");

2625

2626

2627

2631 Info.ContractionOff = true;

2632 }

2633 } else if (EM == SPIRV::ExecutionMode::SignedZeroInfNanPreserve) {

2635 "Expected 1 operand for SignedZeroInfNanPreserve");

2636 unsigned TargetWidth =

2639 ->getZExtValue();

2640

2645 assert(Index >= 0 && Index < 3 &&

2646 "Expected FPFastMathDefaultInfo for half, float, or double");

2647 assert(FPFastMathDefaultInfoVec.size() == 3 &&

2648 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");

2649 FPFastMathDefaultInfoVec[Index].SignedZeroInfNanPreserve = true;

2650 }

2651 }

2652}

2666 TII = ST->getInstrInfo();

2667

2669

2670 setBaseInfo(M);

2671

2672 patchPhis(M, GR, *TII, MMI);

2673

2674 addMBBNames(M, *TII, MMI, *ST, MAI);

2675 collectFPFastMathDefaults(M, MAI, *ST);

2676 addDecorations(M, *TII, MMI, *ST, MAI, GR);

2677

2678 collectReqs(M, MAI, MMI, *ST);

2679

2680

2681

2682 collectReqs(M, MAI, MMI, *ST);

2683 collectDeclarations(M);

2684

2685

2686 numberRegistersGlobally(M);

2687

2688

2689 processOtherInstrs(M);

2690

2691

2693 MAI.Reqs.addCapability(SPIRV::Capability::Linkage);

2694

2695

2696 GR->setBound(MAI.MaxID);

2697

2698 return false;

2699}