LLVM 24.0.0git
SPIRVAsmPrinter.cpp
Go to the documentation of this file.
1//===-- SPIRVAsmPrinter.cpp - SPIR-V LLVM assembly writer ------*- C++ -*--===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains a printer that converts from our internal representation
10// of machine-dependent LLVM code to the SPIR-V assembly language.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPIRVAsmPrinter.h"
16#include "SPIRV.h"
17#include "SPIRVAuxDataHandler.h"
18#include "SPIRVInstrInfo.h"
19#include "SPIRVMCInstLower.h"
20#include "SPIRVModuleAnalysis.h"
22#include "SPIRVSubtarget.h"
23#include "SPIRVTargetMachine.h"
24#include "SPIRVUtils.h"
26#include "llvm/ADT/DenseMap.h"
36#include "llvm/IR/Analysis.h"
37#include "llvm/IR/PassManager.h"
38#include "llvm/MC/MCAsmInfo.h"
39#include "llvm/MC/MCAssembler.h"
40#include "llvm/MC/MCInst.h"
43#include "llvm/MC/MCStreamer.h"
44#include "llvm/MC/MCSymbol.h"
49
50using namespace llvm;
51
52#define DEBUG_TYPE "asm-printer"
53
54namespace {
55enum class SPIRVFPContractMode { On, Off, Fast };
56
57static cl::opt<SPIRVFPContractMode> SPIRVFPContract(
58 "spirv-fp-contract",
59 cl::desc("Override FP contraction policy for SPIR-V kernel entry points"),
61 clEnumValN(SPIRVFPContractMode::On, "on",
62 "Follow IR metadata (default)"),
63 clEnumValN(SPIRVFPContractMode::Off, "off",
64 "Force ContractionOff on all kernel entry points"),
65 clEnumValN(SPIRVFPContractMode::Fast, "fast",
66 "Suppress ContractionOff on all kernel entry points")),
67 cl::init(SPIRVFPContractMode::On));
68
69class SPIRVAsmPrinter : public AsmPrinter {
70 unsigned NLabels = 0;
72
73public:
74 explicit SPIRVAsmPrinter(TargetMachine &TM,
75 std::unique_ptr<MCStreamer> Streamer)
76 : AsmPrinter(TM, std::move(Streamer), ID), ModuleSectionsEmitted(false),
77 ST(nullptr), TII(nullptr), MAI(nullptr) {
78 GetMAI = [this] {
79 return &getAnalysis<SPIRVModuleAnalysisWrapperPass>().MAI;
80 };
81 }
82 static char ID;
83 bool ModuleSectionsEmitted;
84 const SPIRVSubtarget *ST;
85 const SPIRVInstrInfo *TII;
86
87 StringRef getPassName() const override { return "SPIRV Assembly Printer"; }
88 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
89 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
90 const char *ExtraCode, raw_ostream &O) override;
91
92 void outputMCInst(MCInst &Inst);
93 void outputInstruction(const MachineInstr *MI);
94 void outputModuleSection(SPIRV::ModuleSectionType MSType);
95 void outputGlobalRequirements();
96 void outputEntryPoints();
97 void outputDebugSourceAndStrings(const Module &M);
98 void outputOpExtInstImports(const Module &M);
99 void outputOpMemoryModel();
100 void outputOpFunctionEnd();
101 void outputExtFuncDecls();
102 void outputExecutionModeFromMDNode(MCRegister Reg, MDNode *Node,
103 SPIRV::ExecutionMode::ExecutionMode EM,
104 unsigned ExpectMDOps, int64_t DefVal);
105 void outputExecutionModeFromNumthreadsAttribute(
106 const MCRegister &Reg, const Attribute &Attr,
107 SPIRV::ExecutionMode::ExecutionMode EM);
108 void outputExecutionModeFromEnableMaximalReconvergenceAttr(
109 const MCRegister &Reg, const SPIRVSubtarget &ST);
110 void emitSimpleExecutionMode(MCRegister Reg,
111 SPIRV::ExecutionMode::ExecutionMode EM);
112 void outputExecutionMode(const Module &M);
113 void outputAnnotations(const Module &M);
114 void outputModuleSections();
115 void outputFPFastMathDefaultInfo();
116 bool isHidden() {
117 return MF->getFunction()
118 .getFnAttribute(SPIRV_BACKEND_SERVICE_FUN_NAME)
119 .isValid();
120 }
121
122 void emitInstruction(const MachineInstr *MI) override;
123 void emitFunctionEntryLabel() override {}
124 void emitFunctionHeader() override;
125 void emitFunctionBodyStart() override {}
126 void emitFunctionBodyEnd() override;
127 void emitBasicBlockStart(const MachineBasicBlock &MBB) override;
128 void emitBasicBlockEnd(const MachineBasicBlock &MBB) override {}
129 void emitGlobalVariable(const GlobalVariable *GV) override {}
130 void emitOpLabel(const MachineBasicBlock &MBB);
131 void emitEndOfAsmFile(Module &M) override;
132 bool doInitialization(Module &M) override;
133
134 void getAnalysisUsage(AnalysisUsage &AU) const override;
136 std::function<SPIRV::ModuleAnalysisInfo *()> GetMAI;
137
138 // Non-owning pointer to the NSDI handler registered via addAsmPrinterHandler.
139 // The handler's lifetime is managed by AsmPrinter (the base class of this
140 // object), so this pointer cannot dangle.
141 SPIRVNonSemanticDebugHandler *NSDebugHandler = nullptr;
142
143 std::unique_ptr<SPIRVAuxDataHandler> AuxDataHandler;
144
145protected:
146 void cleanUp(Module &M);
147};
148} // namespace
149
150void SPIRVAsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
151 AU.addRequired<SPIRVModuleAnalysisWrapperPass>();
152 AU.addPreserved<SPIRVModuleAnalysisWrapperPass>();
154}
155
156// If the module has no functions, we need output global info anyway.
157void SPIRVAsmPrinter::emitEndOfAsmFile(Module &M) {
158 if (!ModuleSectionsEmitted) {
159 outputModuleSections();
160 ModuleSectionsEmitted = true;
161 }
162
163 ST = static_cast<const SPIRVTargetMachine &>(TM).getSubtargetImpl();
164 // SPIRVModuleAnalysis sets GR->Bound = MAI->MaxID before printing. Any IDs
165 // allocated by AsmPrinter handlers (e.g. SPIRVNonSemanticDebugHandler) during
166 // outputModuleSections() are not counted. Refresh the bound here so the
167 // formula below sees the final allocation count.
168 if (MAI)
169 ST->getSPIRVGlobalRegistry()->setBound(MAI->MaxID);
170 VersionTuple SPIRVVersion = ST->getSPIRVVersion();
171 uint32_t Major = SPIRVVersion.getMajor();
172 uint32_t Minor = SPIRVVersion.getMinor().value_or(0);
173 // Bound is an approximation that accounts for the maximum used register
174 // number and number of generated OpLabels
175 unsigned Bound = 2 * (ST->getBound() + 1) + NLabels;
176 if (MCAssembler *Asm = OutStreamer->getAssemblerPtr())
177 static_cast<SPIRVObjectWriter &>(Asm->getWriter())
178 .setBuildVersion(Major, Minor, Bound);
179
180 cleanUp(M);
181}
182
183// Any cleanup actions with the Module after we don't care about its content
184// anymore.
185void SPIRVAsmPrinter::cleanUp(Module &M) {
186 // Verifier disallows uses of intrinsic global variables.
187 for (StringRef GVName :
188 {"llvm.global_ctors", "llvm.global_dtors", "llvm.used"}) {
189 if (GlobalVariable *GV = M.getNamedGlobal(GVName))
190 GV->setName("");
191 }
192}
193
194void SPIRVAsmPrinter::emitFunctionHeader() {
195 if (!ModuleSectionsEmitted) {
196 outputModuleSections();
197 ModuleSectionsEmitted = true;
198 }
199 // Get the subtarget from the current MachineFunction.
200 ST = &MF->getSubtarget<SPIRVSubtarget>();
201 TII = ST->getInstrInfo();
202 const Function &F = MF->getFunction();
203
204 if (isVerbose() && !isHidden()) {
205 OutStreamer->getCommentOS()
206 << "-- Begin function "
207 << GlobalValue::dropLLVMManglingEscape(F.getName()) << '\n';
208 }
209
210 auto Section = getObjFileLowering().SectionForGlobal(&F, TM);
211 MF->setSection(Section);
212
213 // SPIRVAsmPrinter::emitFunctionHeader() does not call the base class,
214 // so handlers never receive beginFunction() from the normal path. Drive the
215 // per-function lifecycle here, matching what AsmPrinter::emitFunctionHeader()
216 // does for other targets.
217 for (auto &Handler : Handlers) {
218 Handler->beginFunction(MF);
219 Handler->beginBasicBlockSection(MF->front());
220 }
221}
222
223void SPIRVAsmPrinter::outputOpFunctionEnd() {
224 MCInst FunctionEndInst;
225 FunctionEndInst.setOpcode(SPIRV::OpFunctionEnd);
226 outputMCInst(FunctionEndInst);
227}
228
229void SPIRVAsmPrinter::emitFunctionBodyEnd() {
230 if (!isHidden())
231 outputOpFunctionEnd();
232}
233
234void SPIRVAsmPrinter::emitOpLabel(const MachineBasicBlock &MBB) {
235 // Do not emit anything if it's an internal service function.
236 if (isHidden())
237 return;
238
239 MCInst LabelInst;
240 LabelInst.setOpcode(SPIRV::OpLabel);
241 LabelInst.addOperand(MCOperand::createReg(MAI->getOrCreateMBBRegister(MBB)));
242 outputMCInst(LabelInst);
243 ++NLabels;
244 LabeledMBB.insert(&MBB);
245}
246
247void SPIRVAsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) {
248 // Do not emit anything if it's an internal service function.
249 if (MBB.empty() || isHidden())
250 return;
251
252 // If it's the first MBB in MF, it has OpFunction and OpFunctionParameter, so
253 // OpLabel should be output after them.
254 if (MBB.getNumber() == MF->front().getNumber()) {
255 for (const MachineInstr &MI : MBB)
256 if (MI.getOpcode() == SPIRV::OpFunction)
257 return;
258 // TODO: this case should be checked by the verifier.
259 report_fatal_error("OpFunction is expected in the front MBB of MF");
260 }
261 emitOpLabel(MBB);
262}
263
264void SPIRVAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
265 raw_ostream &O) {
266 const MachineOperand &MO = MI->getOperand(OpNum);
267
268 switch (MO.getType()) {
271 break;
272
274 O << MO.getImm();
275 break;
276
278 O << MO.getFPImm();
279 break;
280
282 O << *MO.getMBB()->getSymbol();
283 break;
284
286 O << *getSymbol(MO.getGlobal());
287 break;
288
290 MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
291 O << BA->getName();
292 break;
293 }
294
296 O << *GetExternalSymbolSymbol(MO.getSymbolName());
297 break;
298
301 default:
302 llvm_unreachable("<unknown operand type>");
303 }
304}
305
306bool SPIRVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
307 const char *ExtraCode, raw_ostream &O) {
308 if (ExtraCode && ExtraCode[0])
309 return true; // Invalid instruction - SPIR-V does not have special modifiers
310
311 printOperand(MI, OpNo, O);
312 return false;
313}
314
316 const SPIRVInstrInfo *TII) {
317 return TII->isHeaderInstr(*MI) || MI->getOpcode() == SPIRV::OpFunction ||
318 MI->getOpcode() == SPIRV::OpFunctionParameter;
319}
320
321void SPIRVAsmPrinter::outputMCInst(MCInst &Inst) {
322 OutStreamer->emitInstruction(Inst, *OutContext.getSubtargetInfo());
323}
324
325void SPIRVAsmPrinter::outputInstruction(const MachineInstr *MI) {
326 SPIRVMCInstLower MCInstLowering;
327 MCInst TmpInst;
328 MCInstLowering.lower(MI, TmpInst, MAI);
329 outputMCInst(TmpInst);
330}
331
332void SPIRVAsmPrinter::emitInstruction(const MachineInstr *MI) {
333 SPIRV_MC::verifyInstructionPredicates(MI->getOpcode(),
334 getSubtargetInfo().getFeatureBits());
335
336 bool InstructionEmitted = !MAI->getSkipEmission(MI);
337 if (InstructionEmitted)
338 outputInstruction(MI);
339
340 // Output OpLabel after OpFunction and OpFunctionParameter in the first MBB.
341 const MachineInstr *NextMI = MI->getNextNode();
342 bool BlockHasLabel = LabeledMBB.contains(MI->getParent());
343 bool IsFunctionPreambleInstruction = isFuncOrHeaderInstr(MI, TII);
344 bool IsNextInstructionFunctionPreamble =
345 NextMI && isFuncOrHeaderInstr(NextMI, TII);
346 bool ShouldEmitEntryLabel = !BlockHasLabel && IsFunctionPreambleInstruction &&
347 !IsNextInstructionFunctionPreamble;
348 if (ShouldEmitEntryLabel) {
349 assert(MI->getParent()->getNumber() == MF->front().getNumber() &&
350 "OpFunction is not in the front MBB of MF");
351 emitOpLabel(*MI->getParent());
352 if (NSDebugHandler && !isHidden())
353 NSDebugHandler->notifyEntryLabelEmitted(*MF);
354 }
355}
356
357void SPIRVAsmPrinter::outputModuleSection(SPIRV::ModuleSectionType MSType) {
358 for (const MachineInstr *MI : MAI->getMSInstrs(MSType))
359 outputInstruction(MI);
360}
361
362void SPIRVAsmPrinter::outputDebugSourceAndStrings(const Module &M) {
363 // Output OpSourceExtensions.
364 for (auto &Str : MAI->SrcExt) {
365 MCInst Inst;
366 Inst.setOpcode(SPIRV::OpSourceExtension);
367 addStringImm(Str.first(), Inst);
368 outputMCInst(Inst);
369 }
370 // Output OpString.
371 outputModuleSection(SPIRV::MB_DebugStrings);
372 // Output OpSource.
373 MCInst Inst;
374 Inst.setOpcode(SPIRV::OpSource);
375 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->SrcLang)));
376 Inst.addOperand(
377 MCOperand::createImm(static_cast<unsigned>(MAI->SrcLangVersion)));
378 outputMCInst(Inst);
379 // Emit OpString instructions for NSDI file paths and type names here, in
380 // section 7. OpString must precede type/constant declarations per the SPIR-V
381 // module layout (section 2.4). The OpExtInst instructions that reference
382 // these strings are emitted later at section 10 by
383 // emitNonSemanticGlobalDebugInfo().
384 if (NSDebugHandler)
385 NSDebugHandler->emitNonSemanticDebugStrings(*MAI);
386 if (AuxDataHandler)
387 AuxDataHandler->emitAuxDataStrings(*MAI);
388}
389
390void SPIRVAsmPrinter::outputOpExtInstImports(const Module &M) {
391 for (auto &CU : MAI->ExtInstSetMap) {
392 unsigned Set = CU.first;
393 MCRegister Reg = CU.second;
394 MCInst Inst;
395 Inst.setOpcode(SPIRV::OpExtInstImport);
398 static_cast<SPIRV::InstructionSet::InstructionSet>(Set)),
399 Inst);
400 outputMCInst(Inst);
401 }
402}
403
404void SPIRVAsmPrinter::outputOpMemoryModel() {
405 MCInst Inst;
406 Inst.setOpcode(SPIRV::OpMemoryModel);
407 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->Addr)));
408 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->Mem)));
409 outputMCInst(Inst);
410}
411
412// Before the OpEntryPoints' output, we need to add the entry point's
413// interfaces. The interface is a list of IDs of global OpVariable instructions.
414// These declare the set of global variables from a module that form
415// the interface of this entry point.
416void SPIRVAsmPrinter::outputEntryPoints() {
417 // Find all OpVariable IDs with required StorageClass.
418 DenseSet<MCRegister> InterfaceIDs;
419 for (const MachineInstr *MI : MAI->GlobalVarList) {
420 assert(MI->getOpcode() == SPIRV::OpVariable ||
421 MI->getOpcode() == SPIRV::OpUntypedVariableKHR);
422 auto SC = static_cast<SPIRV::StorageClass::StorageClass>(
423 MI->getOperand(2).getImm());
424 // Before version 1.4, the interface's storage classes are limited to
425 // the Input and Output storage classes. Starting with version 1.4,
426 // the interface's storage classes are all storage classes used in
427 // declaring all global variables referenced by the entry point call tree.
428 if (ST->isAtLeastSPIRVVer(VersionTuple(1, 4)) ||
429 SC == SPIRV::StorageClass::Input || SC == SPIRV::StorageClass::Output) {
430 const MachineFunction *MF = MI->getMF();
431 MCRegister Reg = MAI->getRegisterAlias(MF, MI->getOperand(0).getReg());
432 InterfaceIDs.insert(Reg);
433 }
434 }
435
436 // Output OpEntryPoints adding interface args to all of them.
437 for (const MachineInstr *MI : MAI->getMSInstrs(SPIRV::MB_EntryPoints)) {
438 SPIRVMCInstLower MCInstLowering;
439 MCInst TmpInst;
440 MCInstLowering.lower(MI, TmpInst, MAI);
441 for (MCRegister Reg : InterfaceIDs) {
442 assert(Reg.isValid());
444 }
445 outputMCInst(TmpInst);
446 }
447}
448
449// Create global OpCapability instructions for the required capabilities.
450void SPIRVAsmPrinter::outputGlobalRequirements() {
451 // Abort here if not all requirements can be satisfied.
452 MAI->Reqs.checkSatisfiable(*ST);
453
454 for (const auto &Cap : MAI->Reqs.getMinimalCapabilities()) {
455 MCInst Inst;
456 Inst.setOpcode(SPIRV::OpCapability);
458 outputMCInst(Inst);
459 }
460
461 // Generate the final OpExtensions with strings instead of enums.
462 for (const auto &Ext : MAI->Reqs.getExtensions()) {
463 MCInst Inst;
464 Inst.setOpcode(SPIRV::OpExtension);
466 SPIRV::OperandCategory::ExtensionOperand, Ext),
467 Inst);
468 outputMCInst(Inst);
469 }
470 // TODO add a pseudo instr for version number.
471}
472
473void SPIRVAsmPrinter::outputExtFuncDecls() {
474 // Insert OpFunctionEnd after each declaration.
475 auto I = MAI->getMSInstrs(SPIRV::MB_ExtFuncDecls).begin(),
476 E = MAI->getMSInstrs(SPIRV::MB_ExtFuncDecls).end();
477 for (; I != E; ++I) {
478 outputInstruction(*I);
479 if ((I + 1) == E || (*(I + 1))->getOpcode() == SPIRV::OpFunction)
480 outputOpFunctionEnd();
481 }
482}
483
484// Encode LLVM type by SPIR-V execution mode VecTypeHint.
485static unsigned encodeVecTypeHint(Type *Ty) {
486 if (Ty->isHalfTy())
487 return 4;
488 if (Ty->isFloatTy())
489 return 5;
490 if (Ty->isDoubleTy())
491 return 6;
492 if (IntegerType *IntTy = dyn_cast<IntegerType>(Ty)) {
493 switch (IntTy->getIntegerBitWidth()) {
494 case 8:
495 return 0;
496 case 16:
497 return 1;
498 case 32:
499 return 2;
500 case 64:
501 return 3;
502 default:
503 llvm_unreachable("invalid integer type");
504 }
505 }
507 Type *EleTy = VecTy->getElementType();
508 unsigned Size = VecTy->getNumElements();
509 return Size << 16 | encodeVecTypeHint(EleTy);
510 }
511 llvm_unreachable("invalid type");
512}
513
514static void addOpsFromMDNode(MDNode *MDN, MCInst &Inst,
516 for (const MDOperand &MDOp : MDN->operands()) {
517 if (auto *CMeta = dyn_cast<ConstantAsMetadata>(MDOp)) {
518 Constant *C = CMeta->getValue();
519 if (ConstantInt *Const = dyn_cast<ConstantInt>(C)) {
520 Inst.addOperand(MCOperand::createImm(Const->getZExtValue()));
521 } else if (auto *CE = dyn_cast<Function>(C)) {
522 MCRegister FuncReg = MAI->getGlobalObjReg(CE);
523 assert(FuncReg.isValid());
524 Inst.addOperand(MCOperand::createReg(FuncReg));
525 }
526 }
527 }
528}
529
530void SPIRVAsmPrinter::outputExecutionModeFromMDNode(
531 MCRegister Reg, MDNode *Node, SPIRV::ExecutionMode::ExecutionMode EM,
532 unsigned ExpectMDOps, int64_t DefVal) {
533 MCInst Inst;
534 Inst.setOpcode(SPIRV::OpExecutionMode);
536 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(EM)));
537 addOpsFromMDNode(Node, Inst, MAI);
538 // reqd_work_group_size and work_group_size_hint require 3 operands,
539 // if metadata contains less operands, just add a default value
540 unsigned NodeSz = Node->getNumOperands();
541 if (ExpectMDOps > 0 && NodeSz < ExpectMDOps)
542 for (unsigned i = NodeSz; i < ExpectMDOps; ++i)
543 Inst.addOperand(MCOperand::createImm(DefVal));
544 outputMCInst(Inst);
545}
546
547void SPIRVAsmPrinter::outputExecutionModeFromNumthreadsAttribute(
548 const MCRegister &Reg, const Attribute &Attr,
549 SPIRV::ExecutionMode::ExecutionMode EM) {
550 assert(Attr.isValid() && "Function called with an invalid attribute.");
551
552 MCInst Inst;
553 Inst.setOpcode(SPIRV::OpExecutionMode);
555 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(EM)));
556
557 SmallVector<StringRef> NumThreads;
558 Attr.getValueAsString().split(NumThreads, ',');
559 assert(NumThreads.size() == 3 && "invalid numthreads");
560 for (uint32_t i = 0; i < 3; ++i) {
561 uint32_t V;
562 [[maybe_unused]] bool Result = NumThreads[i].getAsInteger(10, V);
563 assert(!Result && "Failed to parse numthreads");
565 }
566
567 outputMCInst(Inst);
568}
569
570void SPIRVAsmPrinter::emitSimpleExecutionMode(
571 MCRegister Reg, SPIRV::ExecutionMode::ExecutionMode EM) {
572 MCInst Inst;
573 Inst.setOpcode(SPIRV::OpExecutionMode);
575 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(EM)));
576 outputMCInst(Inst);
577}
578
579void SPIRVAsmPrinter::outputExecutionModeFromEnableMaximalReconvergenceAttr(
580 const MCRegister &Reg, const SPIRVSubtarget &ST) {
581 assert(ST.canUseExtension(SPIRV::Extension::SPV_KHR_maximal_reconvergence) &&
582 "Function called when SPV_KHR_maximal_reconvergence is not enabled.");
583
584 emitSimpleExecutionMode(Reg, SPIRV::ExecutionMode::MaximallyReconvergesKHR);
585}
586
587void SPIRVAsmPrinter::outputExecutionMode(const Module &M) {
588 NamedMDNode *Node = M.getNamedMetadata("spirv.ExecutionMode");
589 if (Node) {
590 for (unsigned i = 0; i < Node->getNumOperands(); i++) {
591 const auto EM =
593 cast<ConstantAsMetadata>((Node->getOperand(i))->getOperand(1))
594 ->getValue())
595 ->getZExtValue();
596 // Skip ArithmeticPoisonKHR to avoid a duplicate.
597 if (EM == SPIRV::ExecutionMode::ArithmeticPoisonKHR)
598 continue;
599 // If SPV_KHR_float_controls2 is enabled and we find any of
600 // FPFastMathDefault, ContractionOff or SignedZeroInfNanPreserve execution
601 // modes, skip it, it'll be done somewhere else.
602 if (ST->canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
603 if (EM == SPIRV::ExecutionMode::FPFastMathDefault ||
604 EM == SPIRV::ExecutionMode::ContractionOff ||
605 EM == SPIRV::ExecutionMode::SignedZeroInfNanPreserve)
606 continue;
607 }
608
609 MCInst Inst;
610 Inst.setOpcode(SPIRV::OpExecutionMode);
611 addOpsFromMDNode(cast<MDNode>(Node->getOperand(i)), Inst, MAI);
612 outputMCInst(Inst);
613 }
614 outputFPFastMathDefaultInfo();
615 }
616 for (auto FI = M.begin(), E = M.end(); FI != E; ++FI) {
617 const Function &F = *FI;
618 // Only operands of OpEntryPoint instructions are allowed to be
619 // <Entry Point> operands of OpExecutionMode
620 if (F.isDeclaration() || !isEntryPoint(F))
621 continue;
622 MCRegister FReg = MAI->getGlobalObjReg(&F);
623 assert(FReg.isValid());
624
625 if (Attribute Attr = F.getFnAttribute("hlsl.shader"); Attr.isValid()) {
626 // SPIR-V common validation: Fragment requires OriginUpperLeft or
627 // OriginLowerLeft.
628 // VUID-StandaloneSpirv-OriginLowerLeft-04653: Fragment must declare
629 // OriginUpperLeft.
630 if (Attr.getValueAsString() == "pixel") {
631 emitSimpleExecutionMode(FReg, SPIRV::ExecutionMode::OriginUpperLeft);
632 }
633 }
634 if (MDNode *Node = F.getMetadata("reqd_work_group_size"))
635 outputExecutionModeFromMDNode(FReg, Node, SPIRV::ExecutionMode::LocalSize,
636 3, 1);
637 if (Attribute Attr = F.getFnAttribute("hlsl.numthreads"); Attr.isValid())
638 outputExecutionModeFromNumthreadsAttribute(
639 FReg, Attr, SPIRV::ExecutionMode::LocalSize);
640 if (Attribute Attr = F.getFnAttribute("enable-maximal-reconvergence");
641 Attr.getValueAsBool()) {
642 outputExecutionModeFromEnableMaximalReconvergenceAttr(FReg, *ST);
643 }
644 if (MDNode *Node = F.getMetadata("work_group_size_hint"))
645 outputExecutionModeFromMDNode(FReg, Node,
646 SPIRV::ExecutionMode::LocalSizeHint, 3, 1);
647 if (MDNode *Node = F.getMetadata("reqd_sub_group_size"))
648 outputExecutionModeFromMDNode(FReg, Node,
649 SPIRV::ExecutionMode::SubgroupSize, 0, 0);
650 if (MDNode *Node = F.getMetadata("intel_reqd_sub_group_size"))
651 outputExecutionModeFromMDNode(FReg, Node,
652 SPIRV::ExecutionMode::SubgroupSize, 0, 0);
653 if (MDNode *Node = F.getMetadata("max_work_group_size")) {
654 if (ST->canUseExtension(SPIRV::Extension::SPV_INTEL_kernel_attributes))
655 outputExecutionModeFromMDNode(
656 FReg, Node, SPIRV::ExecutionMode::MaxWorkgroupSizeINTEL, 3, 1);
657 }
658 if (MDNode *Node = F.getMetadata("vec_type_hint")) {
659 MCInst Inst;
660 Inst.setOpcode(SPIRV::OpExecutionMode);
662 unsigned EM = static_cast<unsigned>(SPIRV::ExecutionMode::VecTypeHint);
664 unsigned TypeCode = encodeVecTypeHint(getMDOperandAsType(Node, 0));
665 Inst.addOperand(MCOperand::createImm(TypeCode));
666 outputMCInst(Inst);
667 }
668 // Per SPV_KHR_poison_freeze description of PoisonFreezeKHR "If declared,
669 // all entry points must use the ArithmeticPoisonKHR execution mode".
670 if (llvm::is_contained(MAI->Reqs.getMinimalCapabilities(),
671 SPIRV::Capability::PoisonFreezeKHR)) {
672 emitSimpleExecutionMode(FReg, SPIRV::ExecutionMode::ArithmeticPoisonKHR);
673 }
674 // --spirv-fp-contract=off forces to emit ContractionOff for this kernel
675 // entry point, --spirv-fp-contract=fast suppresses it.
676 bool EmitContractionOff =
677 ST->isKernel() && !M.getNamedMetadata("spirv.ExecutionMode") &&
678 SPIRVFPContract != SPIRVFPContractMode::Fast &&
679 (SPIRVFPContract == SPIRVFPContractMode::Off ||
680 !M.getNamedMetadata("opencl.enable.FP_CONTRACT"));
681 if (EmitContractionOff) {
682 if (ST->canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
683 // When SPV_KHR_float_controls2 is enabled, ContractionOff is
684 // deprecated. We need to use FPFastMathDefault with the appropriate
685 // flags instead. Since FPFastMathDefault takes a target type, we need
686 // to emit it for each floating-point type that exists in the module
687 // to match the effect of ContractionOff. As of now, there are 3 FP
688 // types: fp16, fp32 and fp64.
689
690 // We only end up here because there is no "spirv.ExecutionMode"
691 // metadata, so that means no FPFastMathDefault. Therefore, we only
692 // need to make sure AllowContract is set to 0, as the rest of flags.
693 // We still need to emit the OpExecutionMode instruction, otherwise
694 // it's up to the client API to define the flags. Therefore, we need
695 // to find the constant with 0 value.
696
697 // Collect the SPIRVTypes for fp16, fp32, and fp64 and the constant of
698 // type int32 with 0 value to represent the FP Fast Math Mode.
699 std::vector<const MachineInstr *> SPIRVFloatTypes;
700 const MachineInstr *ConstZeroInt32 = nullptr;
701 for (const MachineInstr *MI :
702 MAI->getMSInstrs(SPIRV::MB_TypeConstVars)) {
703 unsigned OpCode = MI->getOpcode();
704
705 // Collect the SPIRV type if it's a float.
706 if (OpCode == SPIRV::OpTypeFloat) {
707 // Skip if the target type is not fp16, fp32, fp64.
708 const unsigned OpTypeFloatSize = MI->getOperand(1).getImm();
709 if (OpTypeFloatSize != 16 && OpTypeFloatSize != 32 &&
710 OpTypeFloatSize != 64) {
711 continue;
712 }
713 SPIRVFloatTypes.push_back(MI);
714 continue;
715 }
716
717 if (OpCode == SPIRV::OpConstantNull) {
718 // Check if the constant is int32, if not skip it.
719 const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
720 MachineInstr *TypeMI = MRI.getVRegDef(MI->getOperand(1).getReg());
721 bool IsInt32Ty = TypeMI &&
722 TypeMI->getOpcode() == SPIRV::OpTypeInt &&
723 TypeMI->getOperand(1).getImm() == 32;
724 if (IsInt32Ty)
725 ConstZeroInt32 = MI;
726 }
727 }
728
729 // When SPV_KHR_float_controls2 is enabled, ContractionOff is
730 // deprecated. We need to use FPFastMathDefault with the appropriate
731 // flags instead. Since FPFastMathDefault takes a target type, we need
732 // to emit it for each floating-point type that exists in the module
733 // to match the effect of ContractionOff. As of now, there are 3 FP
734 // types: fp16, fp32 and fp64.
735 for (const MachineInstr *MI : SPIRVFloatTypes) {
736 MCInst Inst;
737 Inst.setOpcode(SPIRV::OpExecutionModeId);
739 unsigned EM =
740 static_cast<unsigned>(SPIRV::ExecutionMode::FPFastMathDefault);
742 const MachineFunction *MF = MI->getMF();
743 MCRegister TypeReg =
744 MAI->getRegisterAlias(MF, MI->getOperand(0).getReg());
745 Inst.addOperand(MCOperand::createReg(TypeReg));
746 assert(ConstZeroInt32 && "There should be a constant zero.");
747 MCRegister ConstReg = MAI->getRegisterAlias(
748 ConstZeroInt32->getMF(), ConstZeroInt32->getOperand(0).getReg());
749 Inst.addOperand(MCOperand::createReg(ConstReg));
750 outputMCInst(Inst);
751 }
752 } else {
753 emitSimpleExecutionMode(FReg, SPIRV::ExecutionMode::ContractionOff);
754 }
755 }
756 }
757}
758
759void SPIRVAsmPrinter::outputAnnotations(const Module &M) {
760 outputModuleSection(SPIRV::MB_Annotations);
761 // Process llvm.global.annotations special global variable.
762 if (const GlobalVariable *V = M.getNamedGlobal("llvm.global.annotations")) {
763 const ConstantArray *CA = cast<ConstantArray>(V->getOperand(0));
764 for (Value *Op : CA->operands()) {
765 ConstantStruct *CS = cast<ConstantStruct>(Op);
766 // The first field of the struct contains a pointer to
767 // the annotated variable.
768 Value *AnnotatedVar = CS->getOperand(0)->stripPointerCasts();
769 auto *GO = dyn_cast<GlobalObject>(AnnotatedVar);
770 MCRegister Reg = GO ? MAI->getGlobalObjReg(GO) : MCRegister();
771 if (!Reg.isValid()) {
772 std::string DiagMsg;
773 raw_string_ostream OS(DiagMsg);
774 AnnotatedVar->print(OS);
775 DiagMsg = "Unsupported value in llvm.global.annotations: " + DiagMsg;
776 report_fatal_error(DiagMsg.c_str());
777 }
778
779 // The second field contains a pointer to a global annotation string.
780 GlobalVariable *GV =
782
783 StringRef AnnotationString;
784 [[maybe_unused]] bool Success =
785 getConstantStringInfo(GV, AnnotationString);
786 assert(Success && "Failed to get annotation string");
787 MCInst Inst;
788 Inst.setOpcode(SPIRV::OpDecorate);
790 unsigned Dec = static_cast<unsigned>(SPIRV::Decoration::UserSemantic);
792 addStringImm(AnnotationString, Inst);
793 outputMCInst(Inst);
794 }
795 }
796}
797
798void SPIRVAsmPrinter::outputFPFastMathDefaultInfo() {
799 // Collect the SPIRVTypes that are OpTypeFloat and the constants of type
800 // int32, that might be used as FP Fast Math Mode.
801 std::vector<const MachineInstr *> SPIRVFloatTypes;
802 // Hashtable to associate immediate values with the constant holding them.
803 DenseMap<int, const MachineInstr *> ConstMap;
804 for (const MachineInstr *MI : MAI->getMSInstrs(SPIRV::MB_TypeConstVars)) {
805 // Skip if the instruction is not OpTypeFloat or OpConstant.
806 unsigned OpCode = MI->getOpcode();
807 if (OpCode != SPIRV::OpTypeFloat && OpCode != SPIRV::OpConstantI &&
808 OpCode != SPIRV::OpConstantNull)
809 continue;
810
811 // Collect the SPIRV type if it's a float.
812 if (OpCode == SPIRV::OpTypeFloat) {
813 SPIRVFloatTypes.push_back(MI);
814 } else {
815 // Check if the constant is int32, if not skip it.
816 const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
817 MachineInstr *TypeMI = MRI.getVRegDef(MI->getOperand(1).getReg());
818 if (!TypeMI || TypeMI->getOpcode() != SPIRV::OpTypeInt ||
819 TypeMI->getOperand(1).getImm() != 32)
820 continue;
821
822 if (OpCode == SPIRV::OpConstantI)
823 ConstMap[MI->getOperand(2).getImm()] = MI;
824 else
825 ConstMap[0] = MI;
826 }
827 }
828
829 for (const auto &[Func, FPFastMathDefaultInfoVec] :
830 MAI->FPFastMathDefaultInfoMap) {
831 if (FPFastMathDefaultInfoVec.empty())
832 continue;
833
834 for (const MachineInstr *MI : SPIRVFloatTypes) {
835 unsigned OpTypeFloatSize = MI->getOperand(1).getImm();
838 assert(Index < FPFastMathDefaultInfoVec.size() &&
839 "Index out of bounds for FPFastMathDefaultInfoVec");
840 const auto &FPFastMathDefaultInfo = FPFastMathDefaultInfoVec[Index];
841 assert(FPFastMathDefaultInfo.Ty &&
842 "Expected target type for FPFastMathDefaultInfo");
843 assert(FPFastMathDefaultInfo.Ty->getScalarSizeInBits() ==
844 OpTypeFloatSize &&
845 "Mismatched float type size");
846 MCInst Inst;
847 Inst.setOpcode(SPIRV::OpExecutionModeId);
848 MCRegister FuncReg = MAI->getGlobalObjReg(Func);
849 assert(FuncReg.isValid());
850 Inst.addOperand(MCOperand::createReg(FuncReg));
851 Inst.addOperand(
852 MCOperand::createImm(SPIRV::ExecutionMode::FPFastMathDefault));
853 MCRegister TypeReg =
854 MAI->getRegisterAlias(MI->getMF(), MI->getOperand(0).getReg());
855 Inst.addOperand(MCOperand::createReg(TypeReg));
856 unsigned Flags = FPFastMathDefaultInfo.FastMathFlags;
857 if (FPFastMathDefaultInfo.ContractionOff &&
858 (Flags & SPIRV::FPFastMathMode::AllowContract))
860 "Conflicting FPFastMathFlags: ContractionOff and AllowContract");
861
862 if (FPFastMathDefaultInfo.SignedZeroInfNanPreserve &&
863 !(Flags &
864 (SPIRV::FPFastMathMode::NotNaN | SPIRV::FPFastMathMode::NotInf |
865 SPIRV::FPFastMathMode::NSZ))) {
866 if (FPFastMathDefaultInfo.FPFastMathDefault)
867 report_fatal_error("Conflicting FPFastMathFlags: "
868 "SignedZeroInfNanPreserve but at least one of "
869 "NotNaN/NotInf/NSZ is enabled.");
870 }
871
872 // Don't emit if none of the execution modes was used.
873 if (Flags == SPIRV::FPFastMathMode::None &&
874 !FPFastMathDefaultInfo.ContractionOff &&
875 !FPFastMathDefaultInfo.SignedZeroInfNanPreserve &&
876 !FPFastMathDefaultInfo.FPFastMathDefault)
877 continue;
878
879 // Retrieve the constant instruction for the immediate value.
880 auto It = ConstMap.find(Flags);
881 if (It == ConstMap.end())
882 report_fatal_error("Expected constant instruction for FP Fast Math "
883 "Mode operand of FPFastMathDefault execution mode.");
884 const MachineInstr *ConstMI = It->second;
885 MCRegister ConstReg = MAI->getRegisterAlias(
886 ConstMI->getMF(), ConstMI->getOperand(0).getReg());
887 Inst.addOperand(MCOperand::createReg(ConstReg));
888 outputMCInst(Inst);
889 }
890 }
891}
892
893void SPIRVAsmPrinter::outputModuleSections() {
894 const Module *M = MMI->getModule();
895 // Get the global subtarget to output module-level info.
896 ST = static_cast<const SPIRVTargetMachine &>(TM).getSubtargetImpl();
897 TII = ST->getInstrInfo();
898 MAI = GetMAI();
899 assert(ST && TII && MAI && M && "Module analysis is required");
900
901 if (!AuxDataHandler) {
902 auto Handler = std::make_unique<SPIRVAuxDataHandler>(*this, *M);
903 if (Handler->hasWork())
904 AuxDataHandler = std::move(Handler);
905 }
906
907 // Let the NSDI handler add its extension and ext inst import entry to MAI
908 // before the module header sections are emitted.
909 if (NSDebugHandler)
910 NSDebugHandler->prepareModuleOutput(*ST, *MAI);
911 if (AuxDataHandler)
912 AuxDataHandler->prepareModuleOutput(*ST, *MAI);
913
914 // Output instructions according to the Logical Layout of a Module:
915 // 1,2. All OpCapability instructions, then optional OpExtension
916 // instructions.
917 outputGlobalRequirements();
918 // 3. Optional OpExtInstImport instructions.
919 outputOpExtInstImports(*M);
920 // 4. The single required OpMemoryModel instruction.
921 outputOpMemoryModel();
922 // 5. All entry point declarations, using OpEntryPoint.
923 outputEntryPoints();
924 // 6. Execution-mode declarations, using OpExecutionMode or
925 // OpExecutionModeId.
926 outputExecutionMode(*M);
927 // 7a. Debug: all OpString, OpSourceExtension, OpSource, and
928 // OpSourceContinued, without forward references.
929 outputDebugSourceAndStrings(*M);
930 // 7b. Debug: all OpName and all OpMemberName.
931 outputModuleSection(SPIRV::MB_DebugNames);
932 // 7c. Debug: all OpModuleProcessed instructions.
933 outputModuleSection(SPIRV::MB_DebugModuleProcessed);
934 // xxx. SPV_INTEL_memory_access_aliasing instructions go before 8.
935 // "All annotation instructions"
936 outputModuleSection(SPIRV::MB_AliasingInsts);
937 // 8. All annotation instructions (all decorations).
938 outputAnnotations(*M);
939 // 9. All type declarations (OpTypeXXX instructions), all constant
940 // instructions, and all global variable declarations. This section is
941 // the first section to allow use of: OpLine and OpNoLine debug information;
942 // non-semantic instructions with OpExtInst.
943 outputModuleSection(SPIRV::MB_TypeConstVars);
944 // 10. All global NonSemantic.Shader.DebugInfo.100 instructions. The
945 // SPIRVNonSemanticDebugHandler emits these directly as MCInsts; the
946 // MB_NonSemanticGlobalDI section in MAI is intentionally left empty.
947 if (NSDebugHandler)
948 NSDebugHandler->emitNonSemanticGlobalDebugInfo(*MAI);
949 if (AuxDataHandler)
950 AuxDataHandler->emitAuxData(*MAI);
951 // 11. All function declarations (functions without a body).
952 outputExtFuncDecls();
953 // 12. All function definitions (functions with a body).
954 // This is done in regular function output.
955}
956
957bool SPIRVAsmPrinter::doInitialization(Module &M) {
958 ModuleSectionsEmitted = false;
959 if (!M.getModuleInlineAsm().empty()) {
960 M.getContext().emitError(
961 "SPIR-V does not support module-level inline assembly");
962 M.removeModuleInlineAsm();
963 }
964
965 // Register the NSDI handler before calling the base class so that
966 // AsmPrinter::doInitialization() calls Handler->beginModule(M) for it.
967 if (M.getNamedMetadata("llvm.dbg.cu")) {
968 auto Handler = std::make_unique<SPIRVNonSemanticDebugHandler>(*this);
969 NSDebugHandler = Handler.get();
970 addAsmPrinterHandler(std::move(Handler));
971 }
972 // We need to call the parent's one explicitly.
974}
975
976char SPIRVAsmPrinter::ID = 0;
977
978INITIALIZE_PASS(SPIRVAsmPrinter, "spirv-asm-printer", "SPIRV Assembly Printer",
979 false, false)
980
981// Force static initialization.
983LLVMInitializeSPIRVAsmPrinter() {
987}
988
991 SPIRVAsmPrinter &AsmPrinter = static_cast<SPIRVAsmPrinter &>(
992 MAM.getResult<AsmPrinterAnalysis>(M).getPrinter());
995 return PreservedAnalyses::all();
996}
997
1001 SPIRVAsmPrinter &AsmPrinter = static_cast<SPIRVAsmPrinter &>(
1003 .getCachedResult<AsmPrinterAnalysis>(*MF.getFunction().getParent())
1004 ->getPrinter());
1006 AsmPrinter.GetMAI = [&MFAM, &MF] {
1008 .getCachedResult<SPIRVModuleAnalysis>(*MF.getFunction().getParent());
1009 };
1011 return PreservedAnalyses::all();
1012}
1013
1016 SPIRVAsmPrinter &AsmPrinter = static_cast<SPIRVAsmPrinter &>(
1017 MAM.getResult<AsmPrinterAnalysis>(M).getPrinter());
1019 AsmPrinter.GetMAI = [&MAM, &M] {
1020 return MAM.getCachedResult<SPIRVModuleAnalysis>(M);
1021 };
1023 return PreservedAnalyses::all();
1024}
#define Success
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
static const Function * getParent(const Value *V)
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
#define LLVM_ABI
Definition Compiler.h:215
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
This file defines the DenseMap class.
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register Reg
ModuleAnalysisManager MAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static void addOpsFromMDNode(MDNode *MDN, MCInst &Inst, SPIRV::ModuleAnalysisInfo *MAI)
static bool isFuncOrHeaderInstr(const MachineInstr *MI, const SPIRVInstrInfo *TII)
static unsigned encodeVecTypeHint(Type *Ty)
#define SPIRV_BACKEND_SERVICE_FUN_NAME
Definition SPIRVUtils.h:567
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
std::unique_ptr< MCStreamer > && Streamer
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
This class is intended to be used as a driving class for all asm writers.
Definition AsmPrinter.h:95
bool doInitialization(Module &M) override
Set up the AsmPrinter when we are working on a new module.
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
bool doFinalization(Module &M) override
Shut down the asmprinter.
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
Definition AsmPrinter.h:466
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:106
LLVM_ABI bool getValueAsBool() const
Return the attribute's value as a boolean.
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition Attributes.h:266
This is the shared class of boolean and integer constants.
Definition Constants.h:87
This is an important base class in LLVM.
Definition Constant.h:43
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:767
iterator end()
Definition DenseMap.h:687
Class to represent fixed width SIMD vectors.
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
Module * getParent()
Get the module that this global value is contained inside of...
Class to represent integer types.
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
void addOperand(const MCOperand Op)
Definition MCInst.h:215
void setOpcode(unsigned Op)
Definition MCInst.h:201
static MCOperand createReg(MCRegister Reg)
Definition MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
constexpr bool isValid() const
Definition MCRegister.h:84
StringRef getName() const
getName - Get the symbol name.
Definition MCSymbol.h:188
Metadata node.
Definition Metadata.h:1081
ArrayRef< MDOperand > operands() const
Definition Metadata.h:1435
Tracking metadata reference owned by Metadata.
Definition Metadata.h:902
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const MachineOperand & getOperand(unsigned i) const
const GlobalValue * getGlobal() const
int64_t getImm() const
MachineBasicBlock * getMBB() const
const BlockAddress * getBlockAddress() const
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
const ConstantFP * getFPImm() const
@ MO_Immediate
Immediate operand.
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.
@ MO_GlobalAddress
Address of a global value.
@ MO_BlockAddress
Address of a basic block.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
@ MO_JumpTableIndex
Address of indexed Jump Table for switch.
@ MO_FPImmediate
Floating-point immediate operand.
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
const MachineFunction & getMF() const
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
constexpr bool isValid() const
Definition Register.h:112
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
static const char * getRegisterName(MCRegister Reg)
void lower(const MachineInstr *MI, MCInst &OutMI, SPIRV::ModuleAnalysisInfo *MAI) const
AsmPrinter handler that emits NonSemantic.Shader.DebugInfo.100 (NSDI) instructions for the SPIR-V bac...
void emitNonSemanticDebugStrings(SPIRV::ModuleAnalysisInfo &MAI)
Emit OpString instructions for all NSDI file paths and basic type names into the debug section (secti...
void emitNonSemanticGlobalDebugInfo(SPIRV::ModuleAnalysisInfo &MAI)
Emit module-scope NSDI instructions (DebugSource, DebugCompilationUnit, DebugTypeBasic,...
void prepareModuleOutput(const SPIRVSubtarget &ST, SPIRV::ModuleAnalysisInfo &MAI)
Add SPV_KHR_non_semantic_info extension and NonSemantic.Shader.DebugInfo.100 ext inst set entry to MA...
void notifyEntryLabelEmitted(const MachineFunction &MF)
Called after the synthesized entry OpLabel has been emitted.
const SPIRVInstrInfo * getInstrInfo() const override
bool isAtLeastSPIRVVer(VersionTuple VerToCompareTo) const
SPIRVGlobalRegistry * getSPIRVGlobalRegistry() const
VersionTuple getSPIRVVersion() const
unsigned getBound() const
bool canUseExtension(SPIRV::Extension::Extension E) const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:736
Primary interface to the complete machine description for the target machine.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
op_range operands()
Definition User.h:267
Value * getOperand(unsigned i) const
Definition User.h:207
LLVM_ABI void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition Value.cpp:712
unsigned getMajor() const
Retrieve the major version number.
std::optional< unsigned > getMinor() const
Retrieve the minor version number, if provided.
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
Pass manager infrastructure for declaring and invalidating analyses.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
OuterAnalysisManagerProxy< ModuleAnalysisManager, MachineFunction > ModuleAnalysisManagerMachineFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
void addStringImm(StringRef Str, MCInst &Inst)
Target & getTheSPIRV32Target()
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
DenseMap< Value *, Constant * > ConstMap
LLVM_ABI bool getConstantStringInfo(const Value *V, StringRef &Str, bool TrimAtNul=true)
This function computes the length of a null-terminated C string pointed to by V.
std::string getExtInstSetName(SPIRV::InstructionSet::InstructionSet Set)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI void setupModuleAsmPrinter(Module &M, ModuleAnalysisManager &MAM, AsmPrinter &AsmPrinter)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
std::string getSymbolicOperandMnemonic(SPIRV::OperandCategory::OperandCategory Category, int32_t Value)
bool isEntryPoint(const Function &F)
Target & getTheSPIRV64Target()
Target & getTheSPIRVLogicalTarget()
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
LLVM_ABI void setupMachineFunctionAsmPrinter(MachineFunctionAnalysisManager &MFAM, MachineFunction &MF, AsmPrinter &AsmPrinter)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
Type * getMDOperandAsType(const MDNode *N, unsigned I)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...
static size_t computeFPFastMathDefaultInfoVecIndex(size_t BitWidth)
Definition SPIRVUtils.h:154
MCRegister getGlobalObjReg(const GlobalObject *GO)