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 static char ID;
79 bool ModuleSectionsEmitted;
80 const SPIRVSubtarget *ST;
81 const SPIRVInstrInfo *TII;
82
83 StringRef getPassName() const override { return "SPIRV Assembly Printer"; }
84 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
85 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
86 const char *ExtraCode, raw_ostream &O) override;
87
88 void outputMCInst(MCInst &Inst);
89 void outputInstruction(const MachineInstr *MI);
90 void outputModuleSection(SPIRV::ModuleSectionType MSType);
91 void outputGlobalRequirements();
92 void outputEntryPoints();
93 void outputDebugSourceAndStrings(const Module &M);
94 void outputOpExtInstImports(const Module &M);
95 void outputOpMemoryModel();
96 void outputOpFunctionEnd();
97 void outputExtFuncDecls();
98 void outputExecutionModeFromMDNode(MCRegister Reg, MDNode *Node,
99 SPIRV::ExecutionMode::ExecutionMode EM,
100 unsigned ExpectMDOps, int64_t DefVal);
101 void outputExecutionModeFromNumthreadsAttribute(
102 const MCRegister &Reg, const Attribute &Attr,
103 SPIRV::ExecutionMode::ExecutionMode EM);
104 void outputExecutionModeFromEnableMaximalReconvergenceAttr(
105 const MCRegister &Reg, const SPIRVSubtarget &ST);
106 void emitSimpleExecutionMode(MCRegister Reg,
107 SPIRV::ExecutionMode::ExecutionMode EM);
108 void outputExecutionMode(const Module &M);
109 void outputAnnotations(const Module &M);
110 void outputModuleSections();
111 void outputFPFastMathDefaultInfo();
112 bool isHidden() {
113 return MF->getFunction()
114 .getFnAttribute(SPIRV_BACKEND_SERVICE_FUN_NAME)
115 .isValid();
116 }
117
118 void emitInstruction(const MachineInstr *MI) override;
119 void emitFunctionEntryLabel() override {}
120 void emitFunctionHeader() override;
121 void emitFunctionBodyStart() override {}
122 void emitFunctionBodyEnd() override;
123 void emitBasicBlockStart(const MachineBasicBlock &MBB) override;
124 void emitBasicBlockEnd(const MachineBasicBlock &MBB) override {}
125 void emitGlobalVariable(const GlobalVariable *GV) override {}
126 void emitOpLabel(const MachineBasicBlock &MBB);
127 void emitEndOfAsmFile(Module &M) override;
128 bool doInitialization(Module &M) override;
129
130 void getAnalysisUsage(AnalysisUsage &AU) const override;
132
133 // Non-owning pointer to the NSDI handler registered via addAsmPrinterHandler.
134 // The handler's lifetime is managed by AsmPrinter (the base class of this
135 // object), so this pointer cannot dangle.
136 SPIRVNonSemanticDebugHandler *NSDebugHandler = nullptr;
137
138 std::unique_ptr<SPIRVAuxDataHandler> AuxDataHandler;
139
140protected:
141 void cleanUp(Module &M);
142};
143} // namespace
144
145void SPIRVAsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
146 AU.addRequired<SPIRVModuleAnalysis>();
147 AU.addPreserved<SPIRVModuleAnalysis>();
149}
150
151// If the module has no functions, we need output global info anyway.
152void SPIRVAsmPrinter::emitEndOfAsmFile(Module &M) {
153 if (!ModuleSectionsEmitted) {
154 outputModuleSections();
155 ModuleSectionsEmitted = true;
156 }
157
158 ST = static_cast<const SPIRVTargetMachine &>(TM).getSubtargetImpl();
159 // SPIRVModuleAnalysis sets GR->Bound = MAI->MaxID before printing. Any IDs
160 // allocated by AsmPrinter handlers (e.g. SPIRVNonSemanticDebugHandler) during
161 // outputModuleSections() are not counted. Refresh the bound here so the
162 // formula below sees the final allocation count.
163 if (MAI)
164 ST->getSPIRVGlobalRegistry()->setBound(MAI->MaxID);
165 VersionTuple SPIRVVersion = ST->getSPIRVVersion();
166 uint32_t Major = SPIRVVersion.getMajor();
167 uint32_t Minor = SPIRVVersion.getMinor().value_or(0);
168 // Bound is an approximation that accounts for the maximum used register
169 // number and number of generated OpLabels
170 unsigned Bound = 2 * (ST->getBound() + 1) + NLabels;
171 if (MCAssembler *Asm = OutStreamer->getAssemblerPtr())
172 static_cast<SPIRVObjectWriter &>(Asm->getWriter())
173 .setBuildVersion(Major, Minor, Bound);
174
175 cleanUp(M);
176}
177
178// Any cleanup actions with the Module after we don't care about its content
179// anymore.
180void SPIRVAsmPrinter::cleanUp(Module &M) {
181 // Verifier disallows uses of intrinsic global variables.
182 for (StringRef GVName :
183 {"llvm.global_ctors", "llvm.global_dtors", "llvm.used"}) {
184 if (GlobalVariable *GV = M.getNamedGlobal(GVName))
185 GV->setName("");
186 }
187}
188
189void SPIRVAsmPrinter::emitFunctionHeader() {
190 if (!ModuleSectionsEmitted) {
191 outputModuleSections();
192 ModuleSectionsEmitted = true;
193 }
194 // Get the subtarget from the current MachineFunction.
195 ST = &MF->getSubtarget<SPIRVSubtarget>();
196 TII = ST->getInstrInfo();
197 const Function &F = MF->getFunction();
198
199 if (isVerbose() && !isHidden()) {
200 OutStreamer->getCommentOS()
201 << "-- Begin function "
202 << GlobalValue::dropLLVMManglingEscape(F.getName()) << '\n';
203 }
204
205 auto Section = getObjFileLowering().SectionForGlobal(&F, TM);
206 MF->setSection(Section);
207
208 // SPIRVAsmPrinter::emitFunctionHeader() does not call the base class,
209 // so handlers never receive beginFunction() from the normal path. Drive the
210 // per-function lifecycle here, matching what AsmPrinter::emitFunctionHeader()
211 // does for other targets.
212 for (auto &Handler : Handlers) {
213 Handler->beginFunction(MF);
214 Handler->beginBasicBlockSection(MF->front());
215 }
216}
217
218void SPIRVAsmPrinter::outputOpFunctionEnd() {
219 MCInst FunctionEndInst;
220 FunctionEndInst.setOpcode(SPIRV::OpFunctionEnd);
221 outputMCInst(FunctionEndInst);
222}
223
224void SPIRVAsmPrinter::emitFunctionBodyEnd() {
225 if (!isHidden())
226 outputOpFunctionEnd();
227}
228
229void SPIRVAsmPrinter::emitOpLabel(const MachineBasicBlock &MBB) {
230 // Do not emit anything if it's an internal service function.
231 if (isHidden())
232 return;
233
234 MCInst LabelInst;
235 LabelInst.setOpcode(SPIRV::OpLabel);
236 LabelInst.addOperand(MCOperand::createReg(MAI->getOrCreateMBBRegister(MBB)));
237 outputMCInst(LabelInst);
238 ++NLabels;
239 LabeledMBB.insert(&MBB);
240}
241
242void SPIRVAsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) {
243 // Do not emit anything if it's an internal service function.
244 if (MBB.empty() || isHidden())
245 return;
246
247 // If it's the first MBB in MF, it has OpFunction and OpFunctionParameter, so
248 // OpLabel should be output after them.
249 if (MBB.getNumber() == MF->front().getNumber()) {
250 for (const MachineInstr &MI : MBB)
251 if (MI.getOpcode() == SPIRV::OpFunction)
252 return;
253 // TODO: this case should be checked by the verifier.
254 report_fatal_error("OpFunction is expected in the front MBB of MF");
255 }
256 emitOpLabel(MBB);
257}
258
259void SPIRVAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
260 raw_ostream &O) {
261 const MachineOperand &MO = MI->getOperand(OpNum);
262
263 switch (MO.getType()) {
266 break;
267
269 O << MO.getImm();
270 break;
271
273 O << MO.getFPImm();
274 break;
275
277 O << *MO.getMBB()->getSymbol();
278 break;
279
281 O << *getSymbol(MO.getGlobal());
282 break;
283
285 MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
286 O << BA->getName();
287 break;
288 }
289
291 O << *GetExternalSymbolSymbol(MO.getSymbolName());
292 break;
293
296 default:
297 llvm_unreachable("<unknown operand type>");
298 }
299}
300
301bool SPIRVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
302 const char *ExtraCode, raw_ostream &O) {
303 if (ExtraCode && ExtraCode[0])
304 return true; // Invalid instruction - SPIR-V does not have special modifiers
305
306 printOperand(MI, OpNo, O);
307 return false;
308}
309
311 const SPIRVInstrInfo *TII) {
312 return TII->isHeaderInstr(*MI) || MI->getOpcode() == SPIRV::OpFunction ||
313 MI->getOpcode() == SPIRV::OpFunctionParameter;
314}
315
316void SPIRVAsmPrinter::outputMCInst(MCInst &Inst) {
317 OutStreamer->emitInstruction(Inst, *OutContext.getSubtargetInfo());
318}
319
320void SPIRVAsmPrinter::outputInstruction(const MachineInstr *MI) {
321 SPIRVMCInstLower MCInstLowering;
322 MCInst TmpInst;
323 MCInstLowering.lower(MI, TmpInst, MAI);
324 outputMCInst(TmpInst);
325}
326
327void SPIRVAsmPrinter::emitInstruction(const MachineInstr *MI) {
328 SPIRV_MC::verifyInstructionPredicates(MI->getOpcode(),
329 getSubtargetInfo().getFeatureBits());
330
331 bool InstructionEmitted = !MAI->getSkipEmission(MI);
332 if (InstructionEmitted)
333 outputInstruction(MI);
334
335 // Output OpLabel after OpFunction and OpFunctionParameter in the first MBB.
336 const MachineInstr *NextMI = MI->getNextNode();
337 bool BlockHasLabel = LabeledMBB.contains(MI->getParent());
338 bool IsFunctionPreambleInstruction = isFuncOrHeaderInstr(MI, TII);
339 bool IsNextInstructionFunctionPreamble =
340 NextMI && isFuncOrHeaderInstr(NextMI, TII);
341 bool ShouldEmitEntryLabel = !BlockHasLabel && IsFunctionPreambleInstruction &&
342 !IsNextInstructionFunctionPreamble;
343 if (ShouldEmitEntryLabel) {
344 assert(MI->getParent()->getNumber() == MF->front().getNumber() &&
345 "OpFunction is not in the front MBB of MF");
346 emitOpLabel(*MI->getParent());
347 if (NSDebugHandler && !isHidden())
348 NSDebugHandler->notifyEntryLabelEmitted(*MF);
349 }
350}
351
352void SPIRVAsmPrinter::outputModuleSection(SPIRV::ModuleSectionType MSType) {
353 for (const MachineInstr *MI : MAI->getMSInstrs(MSType))
354 outputInstruction(MI);
355}
356
357void SPIRVAsmPrinter::outputDebugSourceAndStrings(const Module &M) {
358 // Output OpSourceExtensions.
359 for (auto &Str : MAI->SrcExt) {
360 MCInst Inst;
361 Inst.setOpcode(SPIRV::OpSourceExtension);
362 addStringImm(Str.first(), Inst);
363 outputMCInst(Inst);
364 }
365 // Output OpString.
366 outputModuleSection(SPIRV::MB_DebugStrings);
367 // Output OpSource.
368 MCInst Inst;
369 Inst.setOpcode(SPIRV::OpSource);
370 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->SrcLang)));
371 Inst.addOperand(
372 MCOperand::createImm(static_cast<unsigned>(MAI->SrcLangVersion)));
373 outputMCInst(Inst);
374 // Emit OpString instructions for NSDI file paths and type names here, in
375 // section 7. OpString must precede type/constant declarations per the SPIR-V
376 // module layout (section 2.4). The OpExtInst instructions that reference
377 // these strings are emitted later at section 10 by
378 // emitNonSemanticGlobalDebugInfo().
379 if (NSDebugHandler)
380 NSDebugHandler->emitNonSemanticDebugStrings(*MAI);
381 if (AuxDataHandler)
382 AuxDataHandler->emitAuxDataStrings(*MAI);
383}
384
385void SPIRVAsmPrinter::outputOpExtInstImports(const Module &M) {
386 for (auto &CU : MAI->ExtInstSetMap) {
387 unsigned Set = CU.first;
388 MCRegister Reg = CU.second;
389 MCInst Inst;
390 Inst.setOpcode(SPIRV::OpExtInstImport);
393 static_cast<SPIRV::InstructionSet::InstructionSet>(Set)),
394 Inst);
395 outputMCInst(Inst);
396 }
397}
398
399void SPIRVAsmPrinter::outputOpMemoryModel() {
400 MCInst Inst;
401 Inst.setOpcode(SPIRV::OpMemoryModel);
402 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->Addr)));
403 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->Mem)));
404 outputMCInst(Inst);
405}
406
407// Before the OpEntryPoints' output, we need to add the entry point's
408// interfaces. The interface is a list of IDs of global OpVariable instructions.
409// These declare the set of global variables from a module that form
410// the interface of this entry point.
411void SPIRVAsmPrinter::outputEntryPoints() {
412 // Find all OpVariable IDs with required StorageClass.
413 DenseSet<MCRegister> InterfaceIDs;
414 for (const MachineInstr *MI : MAI->GlobalVarList) {
415 assert(MI->getOpcode() == SPIRV::OpVariable ||
416 MI->getOpcode() == SPIRV::OpUntypedVariableKHR);
417 auto SC = static_cast<SPIRV::StorageClass::StorageClass>(
418 MI->getOperand(2).getImm());
419 // Before version 1.4, the interface's storage classes are limited to
420 // the Input and Output storage classes. Starting with version 1.4,
421 // the interface's storage classes are all storage classes used in
422 // declaring all global variables referenced by the entry point call tree.
423 if (ST->isAtLeastSPIRVVer(VersionTuple(1, 4)) ||
424 SC == SPIRV::StorageClass::Input || SC == SPIRV::StorageClass::Output) {
425 const MachineFunction *MF = MI->getMF();
426 MCRegister Reg = MAI->getRegisterAlias(MF, MI->getOperand(0).getReg());
427 InterfaceIDs.insert(Reg);
428 }
429 }
430
431 // Output OpEntryPoints adding interface args to all of them.
432 for (const MachineInstr *MI : MAI->getMSInstrs(SPIRV::MB_EntryPoints)) {
433 SPIRVMCInstLower MCInstLowering;
434 MCInst TmpInst;
435 MCInstLowering.lower(MI, TmpInst, MAI);
436 for (MCRegister Reg : InterfaceIDs) {
437 assert(Reg.isValid());
439 }
440 outputMCInst(TmpInst);
441 }
442}
443
444// Create global OpCapability instructions for the required capabilities.
445void SPIRVAsmPrinter::outputGlobalRequirements() {
446 // Abort here if not all requirements can be satisfied.
447 MAI->Reqs.checkSatisfiable(*ST);
448
449 for (const auto &Cap : MAI->Reqs.getMinimalCapabilities()) {
450 MCInst Inst;
451 Inst.setOpcode(SPIRV::OpCapability);
453 outputMCInst(Inst);
454 }
455
456 // Generate the final OpExtensions with strings instead of enums.
457 for (const auto &Ext : MAI->Reqs.getExtensions()) {
458 MCInst Inst;
459 Inst.setOpcode(SPIRV::OpExtension);
461 SPIRV::OperandCategory::ExtensionOperand, Ext),
462 Inst);
463 outputMCInst(Inst);
464 }
465 // TODO add a pseudo instr for version number.
466}
467
468void SPIRVAsmPrinter::outputExtFuncDecls() {
469 // Insert OpFunctionEnd after each declaration.
470 auto I = MAI->getMSInstrs(SPIRV::MB_ExtFuncDecls).begin(),
471 E = MAI->getMSInstrs(SPIRV::MB_ExtFuncDecls).end();
472 for (; I != E; ++I) {
473 outputInstruction(*I);
474 if ((I + 1) == E || (*(I + 1))->getOpcode() == SPIRV::OpFunction)
475 outputOpFunctionEnd();
476 }
477}
478
479// Encode LLVM type by SPIR-V execution mode VecTypeHint.
480static unsigned encodeVecTypeHint(Type *Ty) {
481 if (Ty->isHalfTy())
482 return 4;
483 if (Ty->isFloatTy())
484 return 5;
485 if (Ty->isDoubleTy())
486 return 6;
487 if (IntegerType *IntTy = dyn_cast<IntegerType>(Ty)) {
488 switch (IntTy->getIntegerBitWidth()) {
489 case 8:
490 return 0;
491 case 16:
492 return 1;
493 case 32:
494 return 2;
495 case 64:
496 return 3;
497 default:
498 llvm_unreachable("invalid integer type");
499 }
500 }
502 Type *EleTy = VecTy->getElementType();
503 unsigned Size = VecTy->getNumElements();
504 return Size << 16 | encodeVecTypeHint(EleTy);
505 }
506 llvm_unreachable("invalid type");
507}
508
509static void addOpsFromMDNode(MDNode *MDN, MCInst &Inst,
511 for (const MDOperand &MDOp : MDN->operands()) {
512 if (auto *CMeta = dyn_cast<ConstantAsMetadata>(MDOp)) {
513 Constant *C = CMeta->getValue();
514 if (ConstantInt *Const = dyn_cast<ConstantInt>(C)) {
515 Inst.addOperand(MCOperand::createImm(Const->getZExtValue()));
516 } else if (auto *CE = dyn_cast<Function>(C)) {
517 MCRegister FuncReg = MAI->getGlobalObjReg(CE);
518 assert(FuncReg.isValid());
519 Inst.addOperand(MCOperand::createReg(FuncReg));
520 }
521 }
522 }
523}
524
525void SPIRVAsmPrinter::outputExecutionModeFromMDNode(
526 MCRegister Reg, MDNode *Node, SPIRV::ExecutionMode::ExecutionMode EM,
527 unsigned ExpectMDOps, int64_t DefVal) {
528 MCInst Inst;
529 Inst.setOpcode(SPIRV::OpExecutionMode);
531 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(EM)));
532 addOpsFromMDNode(Node, Inst, MAI);
533 // reqd_work_group_size and work_group_size_hint require 3 operands,
534 // if metadata contains less operands, just add a default value
535 unsigned NodeSz = Node->getNumOperands();
536 if (ExpectMDOps > 0 && NodeSz < ExpectMDOps)
537 for (unsigned i = NodeSz; i < ExpectMDOps; ++i)
538 Inst.addOperand(MCOperand::createImm(DefVal));
539 outputMCInst(Inst);
540}
541
542void SPIRVAsmPrinter::outputExecutionModeFromNumthreadsAttribute(
543 const MCRegister &Reg, const Attribute &Attr,
544 SPIRV::ExecutionMode::ExecutionMode EM) {
545 assert(Attr.isValid() && "Function called with an invalid attribute.");
546
547 MCInst Inst;
548 Inst.setOpcode(SPIRV::OpExecutionMode);
550 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(EM)));
551
552 SmallVector<StringRef> NumThreads;
553 Attr.getValueAsString().split(NumThreads, ',');
554 assert(NumThreads.size() == 3 && "invalid numthreads");
555 for (uint32_t i = 0; i < 3; ++i) {
556 uint32_t V;
557 [[maybe_unused]] bool Result = NumThreads[i].getAsInteger(10, V);
558 assert(!Result && "Failed to parse numthreads");
560 }
561
562 outputMCInst(Inst);
563}
564
565void SPIRVAsmPrinter::emitSimpleExecutionMode(
566 MCRegister Reg, SPIRV::ExecutionMode::ExecutionMode EM) {
567 MCInst Inst;
568 Inst.setOpcode(SPIRV::OpExecutionMode);
570 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(EM)));
571 outputMCInst(Inst);
572}
573
574void SPIRVAsmPrinter::outputExecutionModeFromEnableMaximalReconvergenceAttr(
575 const MCRegister &Reg, const SPIRVSubtarget &ST) {
576 assert(ST.canUseExtension(SPIRV::Extension::SPV_KHR_maximal_reconvergence) &&
577 "Function called when SPV_KHR_maximal_reconvergence is not enabled.");
578
579 emitSimpleExecutionMode(Reg, SPIRV::ExecutionMode::MaximallyReconvergesKHR);
580}
581
582void SPIRVAsmPrinter::outputExecutionMode(const Module &M) {
583 NamedMDNode *Node = M.getNamedMetadata("spirv.ExecutionMode");
584 if (Node) {
585 for (unsigned i = 0; i < Node->getNumOperands(); i++) {
586 const auto EM =
588 cast<ConstantAsMetadata>((Node->getOperand(i))->getOperand(1))
589 ->getValue())
590 ->getZExtValue();
591 // Skip ArithmeticPoisonKHR to avoid a duplicate.
592 if (EM == SPIRV::ExecutionMode::ArithmeticPoisonKHR)
593 continue;
594 // If SPV_KHR_float_controls2 is enabled and we find any of
595 // FPFastMathDefault, ContractionOff or SignedZeroInfNanPreserve execution
596 // modes, skip it, it'll be done somewhere else.
597 if (ST->canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
598 if (EM == SPIRV::ExecutionMode::FPFastMathDefault ||
599 EM == SPIRV::ExecutionMode::ContractionOff ||
600 EM == SPIRV::ExecutionMode::SignedZeroInfNanPreserve)
601 continue;
602 }
603
604 MCInst Inst;
605 Inst.setOpcode(SPIRV::OpExecutionMode);
606 addOpsFromMDNode(cast<MDNode>(Node->getOperand(i)), Inst, MAI);
607 outputMCInst(Inst);
608 }
609 outputFPFastMathDefaultInfo();
610 }
611 for (auto FI = M.begin(), E = M.end(); FI != E; ++FI) {
612 const Function &F = *FI;
613 // Only operands of OpEntryPoint instructions are allowed to be
614 // <Entry Point> operands of OpExecutionMode
615 if (F.isDeclaration() || !isEntryPoint(F))
616 continue;
617 MCRegister FReg = MAI->getGlobalObjReg(&F);
618 assert(FReg.isValid());
619
620 if (Attribute Attr = F.getFnAttribute("hlsl.shader"); Attr.isValid()) {
621 // SPIR-V common validation: Fragment requires OriginUpperLeft or
622 // OriginLowerLeft.
623 // VUID-StandaloneSpirv-OriginLowerLeft-04653: Fragment must declare
624 // OriginUpperLeft.
625 if (Attr.getValueAsString() == "pixel") {
626 emitSimpleExecutionMode(FReg, SPIRV::ExecutionMode::OriginUpperLeft);
627 }
628 }
629 if (MDNode *Node = F.getMetadata("reqd_work_group_size"))
630 outputExecutionModeFromMDNode(FReg, Node, SPIRV::ExecutionMode::LocalSize,
631 3, 1);
632 if (Attribute Attr = F.getFnAttribute("hlsl.numthreads"); Attr.isValid())
633 outputExecutionModeFromNumthreadsAttribute(
634 FReg, Attr, SPIRV::ExecutionMode::LocalSize);
635 if (Attribute Attr = F.getFnAttribute("enable-maximal-reconvergence");
636 Attr.getValueAsBool()) {
637 outputExecutionModeFromEnableMaximalReconvergenceAttr(FReg, *ST);
638 }
639 if (MDNode *Node = F.getMetadata("work_group_size_hint"))
640 outputExecutionModeFromMDNode(FReg, Node,
641 SPIRV::ExecutionMode::LocalSizeHint, 3, 1);
642 if (MDNode *Node = F.getMetadata("reqd_sub_group_size"))
643 outputExecutionModeFromMDNode(FReg, Node,
644 SPIRV::ExecutionMode::SubgroupSize, 0, 0);
645 if (MDNode *Node = F.getMetadata("intel_reqd_sub_group_size"))
646 outputExecutionModeFromMDNode(FReg, Node,
647 SPIRV::ExecutionMode::SubgroupSize, 0, 0);
648 if (MDNode *Node = F.getMetadata("max_work_group_size")) {
649 if (ST->canUseExtension(SPIRV::Extension::SPV_INTEL_kernel_attributes))
650 outputExecutionModeFromMDNode(
651 FReg, Node, SPIRV::ExecutionMode::MaxWorkgroupSizeINTEL, 3, 1);
652 }
653 if (MDNode *Node = F.getMetadata("vec_type_hint")) {
654 MCInst Inst;
655 Inst.setOpcode(SPIRV::OpExecutionMode);
657 unsigned EM = static_cast<unsigned>(SPIRV::ExecutionMode::VecTypeHint);
659 unsigned TypeCode = encodeVecTypeHint(getMDOperandAsType(Node, 0));
660 Inst.addOperand(MCOperand::createImm(TypeCode));
661 outputMCInst(Inst);
662 }
663 // Per SPV_KHR_poison_freeze description of PoisonFreezeKHR "If declared,
664 // all entry points must use the ArithmeticPoisonKHR execution mode".
665 if (llvm::is_contained(MAI->Reqs.getMinimalCapabilities(),
666 SPIRV::Capability::PoisonFreezeKHR)) {
667 emitSimpleExecutionMode(FReg, SPIRV::ExecutionMode::ArithmeticPoisonKHR);
668 }
669 // --spirv-fp-contract=off forces to emit ContractionOff for this kernel
670 // entry point, --spirv-fp-contract=fast suppresses it.
671 bool EmitContractionOff =
672 ST->isKernel() && !M.getNamedMetadata("spirv.ExecutionMode") &&
673 SPIRVFPContract != SPIRVFPContractMode::Fast &&
674 (SPIRVFPContract == SPIRVFPContractMode::Off ||
675 !M.getNamedMetadata("opencl.enable.FP_CONTRACT"));
676 if (EmitContractionOff) {
677 if (ST->canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
678 // When SPV_KHR_float_controls2 is enabled, ContractionOff is
679 // deprecated. We need to use FPFastMathDefault with the appropriate
680 // flags instead. Since FPFastMathDefault takes a target type, we need
681 // to emit it for each floating-point type that exists in the module
682 // to match the effect of ContractionOff. As of now, there are 3 FP
683 // types: fp16, fp32 and fp64.
684
685 // We only end up here because there is no "spirv.ExecutionMode"
686 // metadata, so that means no FPFastMathDefault. Therefore, we only
687 // need to make sure AllowContract is set to 0, as the rest of flags.
688 // We still need to emit the OpExecutionMode instruction, otherwise
689 // it's up to the client API to define the flags. Therefore, we need
690 // to find the constant with 0 value.
691
692 // Collect the SPIRVTypes for fp16, fp32, and fp64 and the constant of
693 // type int32 with 0 value to represent the FP Fast Math Mode.
694 std::vector<const MachineInstr *> SPIRVFloatTypes;
695 const MachineInstr *ConstZeroInt32 = nullptr;
696 for (const MachineInstr *MI :
697 MAI->getMSInstrs(SPIRV::MB_TypeConstVars)) {
698 unsigned OpCode = MI->getOpcode();
699
700 // Collect the SPIRV type if it's a float.
701 if (OpCode == SPIRV::OpTypeFloat) {
702 // Skip if the target type is not fp16, fp32, fp64.
703 const unsigned OpTypeFloatSize = MI->getOperand(1).getImm();
704 if (OpTypeFloatSize != 16 && OpTypeFloatSize != 32 &&
705 OpTypeFloatSize != 64) {
706 continue;
707 }
708 SPIRVFloatTypes.push_back(MI);
709 continue;
710 }
711
712 if (OpCode == SPIRV::OpConstantNull) {
713 // Check if the constant is int32, if not skip it.
714 const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
715 MachineInstr *TypeMI = MRI.getVRegDef(MI->getOperand(1).getReg());
716 bool IsInt32Ty = TypeMI &&
717 TypeMI->getOpcode() == SPIRV::OpTypeInt &&
718 TypeMI->getOperand(1).getImm() == 32;
719 if (IsInt32Ty)
720 ConstZeroInt32 = MI;
721 }
722 }
723
724 // When SPV_KHR_float_controls2 is enabled, ContractionOff is
725 // deprecated. We need to use FPFastMathDefault with the appropriate
726 // flags instead. Since FPFastMathDefault takes a target type, we need
727 // to emit it for each floating-point type that exists in the module
728 // to match the effect of ContractionOff. As of now, there are 3 FP
729 // types: fp16, fp32 and fp64.
730 for (const MachineInstr *MI : SPIRVFloatTypes) {
731 MCInst Inst;
732 Inst.setOpcode(SPIRV::OpExecutionModeId);
734 unsigned EM =
735 static_cast<unsigned>(SPIRV::ExecutionMode::FPFastMathDefault);
737 const MachineFunction *MF = MI->getMF();
738 MCRegister TypeReg =
739 MAI->getRegisterAlias(MF, MI->getOperand(0).getReg());
740 Inst.addOperand(MCOperand::createReg(TypeReg));
741 assert(ConstZeroInt32 && "There should be a constant zero.");
742 MCRegister ConstReg = MAI->getRegisterAlias(
743 ConstZeroInt32->getMF(), ConstZeroInt32->getOperand(0).getReg());
744 Inst.addOperand(MCOperand::createReg(ConstReg));
745 outputMCInst(Inst);
746 }
747 } else {
748 emitSimpleExecutionMode(FReg, SPIRV::ExecutionMode::ContractionOff);
749 }
750 }
751 }
752}
753
754void SPIRVAsmPrinter::outputAnnotations(const Module &M) {
755 outputModuleSection(SPIRV::MB_Annotations);
756 // Process llvm.global.annotations special global variable.
757 if (const GlobalVariable *V = M.getNamedGlobal("llvm.global.annotations")) {
758 const ConstantArray *CA = cast<ConstantArray>(V->getOperand(0));
759 for (Value *Op : CA->operands()) {
760 ConstantStruct *CS = cast<ConstantStruct>(Op);
761 // The first field of the struct contains a pointer to
762 // the annotated variable.
763 Value *AnnotatedVar = CS->getOperand(0)->stripPointerCasts();
764 auto *GO = dyn_cast<GlobalObject>(AnnotatedVar);
765 MCRegister Reg = GO ? MAI->getGlobalObjReg(GO) : MCRegister();
766 if (!Reg.isValid()) {
767 std::string DiagMsg;
768 raw_string_ostream OS(DiagMsg);
769 AnnotatedVar->print(OS);
770 DiagMsg = "Unsupported value in llvm.global.annotations: " + DiagMsg;
771 report_fatal_error(DiagMsg.c_str());
772 }
773
774 // The second field contains a pointer to a global annotation string.
775 GlobalVariable *GV =
777
778 StringRef AnnotationString;
779 [[maybe_unused]] bool Success =
780 getConstantStringInfo(GV, AnnotationString);
781 assert(Success && "Failed to get annotation string");
782 MCInst Inst;
783 Inst.setOpcode(SPIRV::OpDecorate);
785 unsigned Dec = static_cast<unsigned>(SPIRV::Decoration::UserSemantic);
787 addStringImm(AnnotationString, Inst);
788 outputMCInst(Inst);
789 }
790 }
791}
792
793void SPIRVAsmPrinter::outputFPFastMathDefaultInfo() {
794 // Collect the SPIRVTypes that are OpTypeFloat and the constants of type
795 // int32, that might be used as FP Fast Math Mode.
796 std::vector<const MachineInstr *> SPIRVFloatTypes;
797 // Hashtable to associate immediate values with the constant holding them.
798 DenseMap<int, const MachineInstr *> ConstMap;
799 for (const MachineInstr *MI : MAI->getMSInstrs(SPIRV::MB_TypeConstVars)) {
800 // Skip if the instruction is not OpTypeFloat or OpConstant.
801 unsigned OpCode = MI->getOpcode();
802 if (OpCode != SPIRV::OpTypeFloat && OpCode != SPIRV::OpConstantI &&
803 OpCode != SPIRV::OpConstantNull)
804 continue;
805
806 // Collect the SPIRV type if it's a float.
807 if (OpCode == SPIRV::OpTypeFloat) {
808 SPIRVFloatTypes.push_back(MI);
809 } else {
810 // Check if the constant is int32, if not skip it.
811 const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
812 MachineInstr *TypeMI = MRI.getVRegDef(MI->getOperand(1).getReg());
813 if (!TypeMI || TypeMI->getOpcode() != SPIRV::OpTypeInt ||
814 TypeMI->getOperand(1).getImm() != 32)
815 continue;
816
817 if (OpCode == SPIRV::OpConstantI)
818 ConstMap[MI->getOperand(2).getImm()] = MI;
819 else
820 ConstMap[0] = MI;
821 }
822 }
823
824 for (const auto &[Func, FPFastMathDefaultInfoVec] :
825 MAI->FPFastMathDefaultInfoMap) {
826 if (FPFastMathDefaultInfoVec.empty())
827 continue;
828
829 for (const MachineInstr *MI : SPIRVFloatTypes) {
830 unsigned OpTypeFloatSize = MI->getOperand(1).getImm();
833 assert(Index < FPFastMathDefaultInfoVec.size() &&
834 "Index out of bounds for FPFastMathDefaultInfoVec");
835 const auto &FPFastMathDefaultInfo = FPFastMathDefaultInfoVec[Index];
836 assert(FPFastMathDefaultInfo.Ty &&
837 "Expected target type for FPFastMathDefaultInfo");
838 assert(FPFastMathDefaultInfo.Ty->getScalarSizeInBits() ==
839 OpTypeFloatSize &&
840 "Mismatched float type size");
841 MCInst Inst;
842 Inst.setOpcode(SPIRV::OpExecutionModeId);
843 MCRegister FuncReg = MAI->getGlobalObjReg(Func);
844 assert(FuncReg.isValid());
845 Inst.addOperand(MCOperand::createReg(FuncReg));
846 Inst.addOperand(
847 MCOperand::createImm(SPIRV::ExecutionMode::FPFastMathDefault));
848 MCRegister TypeReg =
849 MAI->getRegisterAlias(MI->getMF(), MI->getOperand(0).getReg());
850 Inst.addOperand(MCOperand::createReg(TypeReg));
851 unsigned Flags = FPFastMathDefaultInfo.FastMathFlags;
852 if (FPFastMathDefaultInfo.ContractionOff &&
853 (Flags & SPIRV::FPFastMathMode::AllowContract))
855 "Conflicting FPFastMathFlags: ContractionOff and AllowContract");
856
857 if (FPFastMathDefaultInfo.SignedZeroInfNanPreserve &&
858 !(Flags &
859 (SPIRV::FPFastMathMode::NotNaN | SPIRV::FPFastMathMode::NotInf |
860 SPIRV::FPFastMathMode::NSZ))) {
861 if (FPFastMathDefaultInfo.FPFastMathDefault)
862 report_fatal_error("Conflicting FPFastMathFlags: "
863 "SignedZeroInfNanPreserve but at least one of "
864 "NotNaN/NotInf/NSZ is enabled.");
865 }
866
867 // Don't emit if none of the execution modes was used.
868 if (Flags == SPIRV::FPFastMathMode::None &&
869 !FPFastMathDefaultInfo.ContractionOff &&
870 !FPFastMathDefaultInfo.SignedZeroInfNanPreserve &&
871 !FPFastMathDefaultInfo.FPFastMathDefault)
872 continue;
873
874 // Retrieve the constant instruction for the immediate value.
875 auto It = ConstMap.find(Flags);
876 if (It == ConstMap.end())
877 report_fatal_error("Expected constant instruction for FP Fast Math "
878 "Mode operand of FPFastMathDefault execution mode.");
879 const MachineInstr *ConstMI = It->second;
880 MCRegister ConstReg = MAI->getRegisterAlias(
881 ConstMI->getMF(), ConstMI->getOperand(0).getReg());
882 Inst.addOperand(MCOperand::createReg(ConstReg));
883 outputMCInst(Inst);
884 }
885 }
886}
887
888void SPIRVAsmPrinter::outputModuleSections() {
889 const Module *M = MMI->getModule();
890 // Get the global subtarget to output module-level info.
891 ST = static_cast<const SPIRVTargetMachine &>(TM).getSubtargetImpl();
892 TII = ST->getInstrInfo();
893 MAI = &getAnalysis<SPIRVModuleAnalysis>().MAI;
894 assert(ST && TII && MAI && M && "Module analysis is required");
895
896 if (!AuxDataHandler) {
897 auto Handler = std::make_unique<SPIRVAuxDataHandler>(*this, *M);
898 if (Handler->hasWork())
899 AuxDataHandler = std::move(Handler);
900 }
901
902 // Let the NSDI handler add its extension and ext inst import entry to MAI
903 // before the module header sections are emitted.
904 if (NSDebugHandler)
905 NSDebugHandler->prepareModuleOutput(*ST, *MAI);
906 if (AuxDataHandler)
907 AuxDataHandler->prepareModuleOutput(*ST, *MAI);
908
909 // Output instructions according to the Logical Layout of a Module:
910 // 1,2. All OpCapability instructions, then optional OpExtension
911 // instructions.
912 outputGlobalRequirements();
913 // 3. Optional OpExtInstImport instructions.
914 outputOpExtInstImports(*M);
915 // 4. The single required OpMemoryModel instruction.
916 outputOpMemoryModel();
917 // 5. All entry point declarations, using OpEntryPoint.
918 outputEntryPoints();
919 // 6. Execution-mode declarations, using OpExecutionMode or
920 // OpExecutionModeId.
921 outputExecutionMode(*M);
922 // 7a. Debug: all OpString, OpSourceExtension, OpSource, and
923 // OpSourceContinued, without forward references.
924 outputDebugSourceAndStrings(*M);
925 // 7b. Debug: all OpName and all OpMemberName.
926 outputModuleSection(SPIRV::MB_DebugNames);
927 // 7c. Debug: all OpModuleProcessed instructions.
928 outputModuleSection(SPIRV::MB_DebugModuleProcessed);
929 // xxx. SPV_INTEL_memory_access_aliasing instructions go before 8.
930 // "All annotation instructions"
931 outputModuleSection(SPIRV::MB_AliasingInsts);
932 // 8. All annotation instructions (all decorations).
933 outputAnnotations(*M);
934 // 9. All type declarations (OpTypeXXX instructions), all constant
935 // instructions, and all global variable declarations. This section is
936 // the first section to allow use of: OpLine and OpNoLine debug information;
937 // non-semantic instructions with OpExtInst.
938 outputModuleSection(SPIRV::MB_TypeConstVars);
939 // 10. All global NonSemantic.Shader.DebugInfo.100 instructions. The
940 // SPIRVNonSemanticDebugHandler emits these directly as MCInsts; the
941 // MB_NonSemanticGlobalDI section in MAI is intentionally left empty.
942 if (NSDebugHandler)
943 NSDebugHandler->emitNonSemanticGlobalDebugInfo(*MAI);
944 if (AuxDataHandler)
945 AuxDataHandler->emitAuxData(*MAI);
946 // 11. All function declarations (functions without a body).
947 outputExtFuncDecls();
948 // 12. All function definitions (functions with a body).
949 // This is done in regular function output.
950}
951
952bool SPIRVAsmPrinter::doInitialization(Module &M) {
953 ModuleSectionsEmitted = false;
954 if (!M.getModuleInlineAsm().empty()) {
955 M.getContext().emitError(
956 "SPIR-V does not support module-level inline assembly");
957 M.removeModuleInlineAsm();
958 }
959
960 // Register the NSDI handler before calling the base class so that
961 // AsmPrinter::doInitialization() calls Handler->beginModule(M) for it.
962 if (M.getNamedMetadata("llvm.dbg.cu")) {
963 auto Handler = std::make_unique<SPIRVNonSemanticDebugHandler>(*this);
964 NSDebugHandler = Handler.get();
965 addAsmPrinterHandler(std::move(Handler));
966 }
967 // We need to call the parent's one explicitly.
969}
970
971char SPIRVAsmPrinter::ID = 0;
972
973INITIALIZE_PASS(SPIRVAsmPrinter, "spirv-asm-printer", "SPIRV Assembly Printer",
974 false, false)
975
976// Force static initialization.
978LLVMInitializeSPIRVAsmPrinter() {
982}
983
986 SPIRVAsmPrinter &AsmPrinter = static_cast<SPIRVAsmPrinter &>(
987 MAM.getResult<AsmPrinterAnalysis>(M).getPrinter());
990 return PreservedAnalyses::all();
991}
992
996 SPIRVAsmPrinter &AsmPrinter = static_cast<SPIRVAsmPrinter &>(
998 .getCachedResult<AsmPrinterAnalysis>(*MF.getFunction().getParent())
999 ->getPrinter());
1002 return PreservedAnalyses::all();
1003}
1004
1007 SPIRVAsmPrinter &AsmPrinter = static_cast<SPIRVAsmPrinter &>(
1008 MAM.getResult<AsmPrinterAnalysis>(M).getPrinter());
1011 return PreservedAnalyses::all();
1012}
#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:91
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:453
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:105
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:261
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:223
iterator end()
Definition DenseMap.h:141
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',...
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:1069
ArrayRef< MDOperand > operands() const
Definition Metadata.h:1424
Tracking metadata reference owned by Metadata.
Definition Metadata.h:891
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:67
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:713
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:1947
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)