LLVM 22.0.0git
SPIRVGlobalRegistry.cpp
Go to the documentation of this file.
1//===-- SPIRVGlobalRegistry.cpp - SPIR-V Global Registry --------*- 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 the implementation of the SPIRVGlobalRegistry class,
10// which is used to maintain rich type information required for SPIR-V even
11// after lowering from LLVM IR to GMIR. It can convert an llvm::Type into
12// an OpTypeXXX instruction, and map it to a virtual register. Also it builds
13// and supports consistency of constants and global variables.
14//
15//===----------------------------------------------------------------------===//
16
17#include "SPIRVGlobalRegistry.h"
18#include "SPIRV.h"
19#include "SPIRVBuiltins.h"
20#include "SPIRVSubtarget.h"
21#include "SPIRVUtils.h"
22#include "llvm/ADT/APInt.h"
23#include "llvm/IR/Constants.h"
25#include "llvm/IR/Intrinsics.h"
26#include "llvm/IR/IntrinsicsSPIRV.h"
27#include "llvm/IR/Type.h"
30#include <cassert>
31#include <functional>
32
33using namespace llvm;
34
35static bool allowEmitFakeUse(const Value *Arg) {
36 if (isSpvIntrinsic(Arg))
37 return false;
39 return false;
40 if (const auto *LI = dyn_cast<LoadInst>(Arg))
41 if (LI->getType()->isAggregateType())
42 return false;
43 return true;
44}
45
46static unsigned typeToAddressSpace(const Type *Ty) {
47 if (auto PType = dyn_cast<TypedPointerType>(Ty))
48 return PType->getAddressSpace();
49 if (auto PType = dyn_cast<PointerType>(Ty))
50 return PType->getAddressSpace();
51 if (auto *ExtTy = dyn_cast<TargetExtType>(Ty);
52 ExtTy && isTypedPointerWrapper(ExtTy))
53 return ExtTy->getIntParameter(0);
54 reportFatalInternalError("Unable to convert LLVM type to SPIRVType");
55}
56
57static bool
58storageClassRequiresExplictLayout(SPIRV::StorageClass::StorageClass SC) {
59 switch (SC) {
60 case SPIRV::StorageClass::Uniform:
61 case SPIRV::StorageClass::PushConstant:
62 case SPIRV::StorageClass::StorageBuffer:
63 case SPIRV::StorageClass::PhysicalStorageBufferEXT:
64 return true;
65 case SPIRV::StorageClass::UniformConstant:
66 case SPIRV::StorageClass::Input:
67 case SPIRV::StorageClass::Output:
68 case SPIRV::StorageClass::Workgroup:
69 case SPIRV::StorageClass::CrossWorkgroup:
70 case SPIRV::StorageClass::Private:
71 case SPIRV::StorageClass::Function:
72 case SPIRV::StorageClass::Generic:
73 case SPIRV::StorageClass::AtomicCounter:
74 case SPIRV::StorageClass::Image:
75 case SPIRV::StorageClass::CallableDataNV:
76 case SPIRV::StorageClass::IncomingCallableDataNV:
77 case SPIRV::StorageClass::RayPayloadNV:
78 case SPIRV::StorageClass::HitAttributeNV:
79 case SPIRV::StorageClass::IncomingRayPayloadNV:
80 case SPIRV::StorageClass::ShaderRecordBufferNV:
81 case SPIRV::StorageClass::CodeSectionINTEL:
82 case SPIRV::StorageClass::DeviceOnlyINTEL:
83 case SPIRV::StorageClass::HostOnlyINTEL:
84 return false;
85 }
86 llvm_unreachable("Unknown SPIRV::StorageClass enum");
87}
88
90 : PointerSize(PointerSize), Bound(0), CurMF(nullptr) {}
91
93 Register VReg,
95 const SPIRVInstrInfo &TII) {
97 assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
98 return SpirvType;
99}
100
101SPIRVType *
104 const SPIRVInstrInfo &TII) {
106 assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
107 return SpirvType;
108}
109
111 SPIRVType *BaseType, unsigned NumElements, Register VReg, MachineInstr &I,
112 const SPIRVInstrInfo &TII) {
113 SPIRVType *SpirvType =
115 assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
116 return SpirvType;
117}
118
120 const Type *Type, Register VReg, MachineIRBuilder &MIRBuilder,
121 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
122 SPIRVType *SpirvType =
123 getOrCreateSPIRVType(Type, MIRBuilder, AccessQual, EmitIR);
124 assignSPIRVTypeToVReg(SpirvType, VReg, MIRBuilder.getMF());
125 return SpirvType;
126}
127
129 Register VReg,
130 const MachineFunction &MF) {
131 VRegToTypeMap[&MF][VReg] = SpirvType;
132}
133
135 auto Res = MRI.createGenericVirtualRegister(LLT::scalar(64));
136 MRI.setRegClass(Res, &SPIRV::TYPERegClass);
137 return Res;
138}
139
141 return createTypeVReg(MIRBuilder.getMF().getRegInfo());
142}
143
144SPIRVType *SPIRVGlobalRegistry::getOpTypeBool(MachineIRBuilder &MIRBuilder) {
145 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
146 return MIRBuilder.buildInstr(SPIRV::OpTypeBool)
147 .addDef(createTypeVReg(MIRBuilder));
148 });
149}
150
151unsigned SPIRVGlobalRegistry::adjustOpTypeIntWidth(unsigned Width) const {
152 if (Width > 64)
153 report_fatal_error("Unsupported integer width!");
154 const SPIRVSubtarget &ST = cast<SPIRVSubtarget>(CurMF->getSubtarget());
155 if (ST.canUseExtension(
156 SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers) ||
157 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4))
158 return Width;
159 if (Width <= 8)
160 Width = 8;
161 else if (Width <= 16)
162 Width = 16;
163 else if (Width <= 32)
164 Width = 32;
165 else
166 Width = 64;
167 return Width;
168}
169
170SPIRVType *SPIRVGlobalRegistry::getOpTypeInt(unsigned Width,
171 MachineIRBuilder &MIRBuilder,
172 bool IsSigned) {
173 Width = adjustOpTypeIntWidth(Width);
174 const SPIRVSubtarget &ST =
176 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
177 if (Width == 4 && ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) {
178 MIRBuilder.buildInstr(SPIRV::OpExtension)
179 .addImm(SPIRV::Extension::SPV_INTEL_int4);
180 MIRBuilder.buildInstr(SPIRV::OpCapability)
181 .addImm(SPIRV::Capability::Int4TypeINTEL);
182 } else if ((!isPowerOf2_32(Width) || Width < 8) &&
183 ST.canUseExtension(
184 SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers)) {
185 MIRBuilder.buildInstr(SPIRV::OpExtension)
186 .addImm(SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers);
187 MIRBuilder.buildInstr(SPIRV::OpCapability)
188 .addImm(SPIRV::Capability::ArbitraryPrecisionIntegersINTEL);
189 }
190 return MIRBuilder.buildInstr(SPIRV::OpTypeInt)
191 .addDef(createTypeVReg(MIRBuilder))
192 .addImm(Width)
193 .addImm(IsSigned ? 1 : 0);
194 });
195}
196
197SPIRVType *SPIRVGlobalRegistry::getOpTypeFloat(uint32_t Width,
198 MachineIRBuilder &MIRBuilder) {
199 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
200 return MIRBuilder.buildInstr(SPIRV::OpTypeFloat)
201 .addDef(createTypeVReg(MIRBuilder))
202 .addImm(Width);
203 });
204}
205
206SPIRVType *
207SPIRVGlobalRegistry::getOpTypeFloat(uint32_t Width,
208 MachineIRBuilder &MIRBuilder,
209 SPIRV::FPEncoding::FPEncoding FPEncode) {
210 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
211 return MIRBuilder.buildInstr(SPIRV::OpTypeFloat)
212 .addDef(createTypeVReg(MIRBuilder))
213 .addImm(Width)
214 .addImm(FPEncode);
215 });
216}
217
218SPIRVType *SPIRVGlobalRegistry::getOpTypeVoid(MachineIRBuilder &MIRBuilder) {
219 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
220 return MIRBuilder.buildInstr(SPIRV::OpTypeVoid)
221 .addDef(createTypeVReg(MIRBuilder));
222 });
223}
224
226 // TODO:
227 // - review other data structure wrt. possible issues related to removal
228 // of a machine instruction during instruction selection.
229 const MachineFunction *MF = MI->getMF();
230 auto It = LastInsertedTypeMap.find(MF);
231 if (It == LastInsertedTypeMap.end())
232 return;
233 if (It->second == MI)
234 LastInsertedTypeMap.erase(MF);
235 // remove from the duplicate tracker to avoid incorrect reuse
236 erase(MI);
237}
238
239SPIRVType *SPIRVGlobalRegistry::createOpType(
240 MachineIRBuilder &MIRBuilder,
241 std::function<MachineInstr *(MachineIRBuilder &)> Op) {
242 auto oldInsertPoint = MIRBuilder.getInsertPt();
243 MachineBasicBlock *OldMBB = &MIRBuilder.getMBB();
244 MachineBasicBlock *NewMBB = &*MIRBuilder.getMF().begin();
245
246 auto LastInsertedType = LastInsertedTypeMap.find(CurMF);
247 if (LastInsertedType != LastInsertedTypeMap.end()) {
248 auto It = LastInsertedType->second->getIterator();
249 // It might happen that this instruction was removed from the first MBB,
250 // hence the Parent's check.
252 if (It->getParent() != NewMBB)
253 InsertAt = oldInsertPoint->getParent() == NewMBB
254 ? oldInsertPoint
255 : getInsertPtValidEnd(NewMBB);
256 else if (It->getNextNode())
257 InsertAt = It->getNextNode()->getIterator();
258 else
259 InsertAt = getInsertPtValidEnd(NewMBB);
260 MIRBuilder.setInsertPt(*NewMBB, InsertAt);
261 } else {
262 MIRBuilder.setInsertPt(*NewMBB, NewMBB->begin());
263 auto Result = LastInsertedTypeMap.try_emplace(CurMF, nullptr);
264 assert(Result.second);
265 LastInsertedType = Result.first;
266 }
267
268 MachineInstr *Type = Op(MIRBuilder);
269 // We expect all users of this function to insert definitions at the insertion
270 // point set above that is always the first MBB.
271 assert(Type->getParent() == NewMBB);
272 LastInsertedType->second = Type;
273
274 MIRBuilder.setInsertPt(*OldMBB, oldInsertPoint);
275 return Type;
276}
277
278SPIRVType *SPIRVGlobalRegistry::getOpTypeVector(uint32_t NumElems,
279 SPIRVType *ElemType,
280 MachineIRBuilder &MIRBuilder) {
281 auto EleOpc = ElemType->getOpcode();
282 (void)EleOpc;
283 assert((EleOpc == SPIRV::OpTypeInt || EleOpc == SPIRV::OpTypeFloat ||
284 EleOpc == SPIRV::OpTypeBool) &&
285 "Invalid vector element type");
286
287 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
288 return MIRBuilder.buildInstr(SPIRV::OpTypeVector)
289 .addDef(createTypeVReg(MIRBuilder))
290 .addUse(getSPIRVTypeID(ElemType))
291 .addImm(NumElems);
292 });
293}
294
296 SPIRVType *SpvType,
297 const SPIRVInstrInfo &TII,
298 bool ZeroAsNull) {
299 LLVMContext &Ctx = CurMF->getFunction().getContext();
300 auto *const CF = ConstantFP::get(Ctx, Val);
301 const MachineInstr *MI = findMI(CF, CurMF);
302 if (MI && (MI->getOpcode() == SPIRV::OpConstantNull ||
303 MI->getOpcode() == SPIRV::OpConstantF))
304 return MI->getOperand(0).getReg();
305 return createConstFP(CF, I, SpvType, TII, ZeroAsNull);
306}
307
309 MachineInstr &I, SPIRVType *SpvType,
310 const SPIRVInstrInfo &TII,
311 bool ZeroAsNull) {
312 unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);
313 LLT LLTy = LLT::scalar(BitWidth);
314 Register Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
315 CurMF->getRegInfo().setRegClass(Res, &SPIRV::fIDRegClass);
317
318 MachineInstr *DepMI = const_cast<MachineInstr *>(SpvType);
319 MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());
320 SPIRVType *NewType =
321 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
323 // In OpenCL OpConstantNull - Scalar floating point: +0.0 (all bits 0)
324 if (CF->getValue().isPosZero() && ZeroAsNull) {
325 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
326 .addDef(Res)
327 .addUse(getSPIRVTypeID(SpvType));
328 } else {
329 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantF)
330 .addDef(Res)
331 .addUse(getSPIRVTypeID(SpvType));
334 MIB);
335 }
336 const auto &ST = CurMF->getSubtarget();
337 constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
338 *ST.getRegisterInfo(),
339 *ST.getRegBankInfo());
340 return MIB;
341 });
342 add(CF, NewType);
343 return Res;
344}
345
347 SPIRVType *SpvType,
348 const SPIRVInstrInfo &TII,
349 bool ZeroAsNull) {
351 auto *const CI = ConstantInt::get(const_cast<IntegerType *>(Ty), Val);
352 const MachineInstr *MI = findMI(CI, CurMF);
353 if (MI && (MI->getOpcode() == SPIRV::OpConstantNull ||
354 MI->getOpcode() == SPIRV::OpConstantI))
355 return MI->getOperand(0).getReg();
356 return createConstInt(CI, I, SpvType, TII, ZeroAsNull);
357}
358
361 SPIRVType *SpvType,
362 const SPIRVInstrInfo &TII,
363 bool ZeroAsNull) {
364 unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);
365 LLT LLTy = LLT::scalar(BitWidth);
366 Register Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
367 CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
369
370 MachineInstr *DepMI = const_cast<MachineInstr *>(SpvType);
371 MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());
372 SPIRVType *NewType =
373 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
375 if (BitWidth == 1) {
376 MIB = MIRBuilder
377 .buildInstr(CI->isZero() ? SPIRV::OpConstantFalse
378 : SPIRV::OpConstantTrue)
379 .addDef(Res)
380 .addUse(getSPIRVTypeID(SpvType));
381 } else if (!CI->isZero() || !ZeroAsNull) {
382 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)
383 .addDef(Res)
384 .addUse(getSPIRVTypeID(SpvType));
385 addNumImm(APInt(BitWidth, CI->getZExtValue()), MIB);
386 } else {
387 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
388 .addDef(Res)
389 .addUse(getSPIRVTypeID(SpvType));
390 }
391 const auto &ST = CurMF->getSubtarget();
392 constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
393 *ST.getRegisterInfo(),
394 *ST.getRegBankInfo());
395 return MIB;
396 });
397 add(CI, NewType);
398 return Res;
399}
400
402 MachineIRBuilder &MIRBuilder,
403 SPIRVType *SpvType, bool EmitIR,
404 bool ZeroAsNull) {
405 assert(SpvType);
406 auto &MF = MIRBuilder.getMF();
408 auto *const CI = ConstantInt::get(const_cast<IntegerType *>(Ty), Val);
409 Register Res = find(CI, &MF);
410 if (Res.isValid())
411 return Res;
412
413 unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);
414 LLT LLTy = LLT::scalar(BitWidth);
415 MachineRegisterInfo &MRI = MF.getRegInfo();
416 Res = MRI.createGenericVirtualRegister(LLTy);
417 MRI.setRegClass(Res, &SPIRV::iIDRegClass);
418 assignTypeToVReg(Ty, Res, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
419 EmitIR);
420
421 SPIRVType *NewType =
422 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
423 if (EmitIR)
424 return MIRBuilder.buildConstant(Res, *CI);
425 Register SpvTypeReg = getSPIRVTypeID(SpvType);
427 if (Val || !ZeroAsNull) {
428 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)
429 .addDef(Res)
430 .addUse(SpvTypeReg);
431 addNumImm(APInt(BitWidth, Val), MIB);
432 } else {
433 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
434 .addDef(Res)
435 .addUse(SpvTypeReg);
436 }
437 const auto &Subtarget = CurMF->getSubtarget();
438 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
439 *Subtarget.getRegisterInfo(),
440 *Subtarget.getRegBankInfo());
441 return MIB;
442 });
443 add(CI, NewType);
444 return Res;
445}
446
448 MachineIRBuilder &MIRBuilder,
449 SPIRVType *SpvType) {
450 auto &MF = MIRBuilder.getMF();
451 LLVMContext &Ctx = MF.getFunction().getContext();
452 if (!SpvType)
453 SpvType = getOrCreateSPIRVType(Type::getFloatTy(Ctx), MIRBuilder,
454 SPIRV::AccessQualifier::ReadWrite, true);
455 auto *const CF = ConstantFP::get(Ctx, Val);
456 Register Res = find(CF, &MF);
457 if (Res.isValid())
458 return Res;
459
461 Res = MF.getRegInfo().createGenericVirtualRegister(LLTy);
462 MF.getRegInfo().setRegClass(Res, &SPIRV::fIDRegClass);
463 assignSPIRVTypeToVReg(SpvType, Res, MF);
464
465 SPIRVType *NewType =
466 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
468 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantF)
469 .addDef(Res)
470 .addUse(getSPIRVTypeID(SpvType));
471 addNumImm(CF->getValueAPF().bitcastToAPInt(), MIB);
472 return MIB;
473 });
474 add(CF, NewType);
475 return Res;
476}
477
478Register SPIRVGlobalRegistry::getOrCreateBaseRegister(
479 Constant *Val, MachineInstr &I, SPIRVType *SpvType,
480 const SPIRVInstrInfo &TII, unsigned BitWidth, bool ZeroAsNull) {
481 SPIRVType *Type = SpvType;
482 if (SpvType->getOpcode() == SPIRV::OpTypeVector ||
483 SpvType->getOpcode() == SPIRV::OpTypeArray) {
484 auto EleTypeReg = SpvType->getOperand(1).getReg();
485 Type = getSPIRVTypeForVReg(EleTypeReg);
486 }
487 if (Type->getOpcode() == SPIRV::OpTypeFloat) {
489 return getOrCreateConstFP(cast<ConstantFP>(Val)->getValue(), I, SpvBaseType,
490 TII, ZeroAsNull);
491 }
492 assert(Type->getOpcode() == SPIRV::OpTypeInt);
495 SpvBaseType, TII, ZeroAsNull);
496}
497
498Register SPIRVGlobalRegistry::getOrCreateCompositeOrNull(
499 Constant *Val, MachineInstr &I, SPIRVType *SpvType,
500 const SPIRVInstrInfo &TII, Constant *CA, unsigned BitWidth,
501 unsigned ElemCnt, bool ZeroAsNull) {
502 if (Register R = find(CA, CurMF); R.isValid())
503 return R;
504
505 bool IsNull = Val->isNullValue() && ZeroAsNull;
506 Register ElemReg;
507 if (!IsNull)
508 ElemReg =
509 getOrCreateBaseRegister(Val, I, SpvType, TII, BitWidth, ZeroAsNull);
510
511 LLT LLTy = LLT::scalar(64);
512 Register Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
513 CurMF->getRegInfo().setRegClass(Res, getRegClass(SpvType));
514 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
515
516 MachineInstr *DepMI = const_cast<MachineInstr *>(SpvType);
517 MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());
518 const MachineInstr *NewMI =
519 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
520 MachineInstrBuilder MIB;
521 if (!IsNull) {
522 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantComposite)
523 .addDef(Res)
524 .addUse(getSPIRVTypeID(SpvType));
525 for (unsigned i = 0; i < ElemCnt; ++i)
526 MIB.addUse(ElemReg);
527 } else {
528 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
529 .addDef(Res)
530 .addUse(getSPIRVTypeID(SpvType));
531 }
532 const auto &Subtarget = CurMF->getSubtarget();
533 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
534 *Subtarget.getRegisterInfo(),
535 *Subtarget.getRegBankInfo());
536 return MIB;
537 });
538 add(CA, NewMI);
539 return Res;
540}
541
544 SPIRVType *SpvType,
545 const SPIRVInstrInfo &TII,
546 bool ZeroAsNull) {
547 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
548 assert(LLVMTy->isVectorTy());
549 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
550 Type *LLVMBaseTy = LLVMVecTy->getElementType();
551 assert(LLVMBaseTy->isIntegerTy());
552 auto *ConstVal = ConstantInt::get(LLVMBaseTy, Val);
553 auto *ConstVec =
554 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstVal);
555 unsigned BW = getScalarOrVectorBitWidth(SpvType);
556 return getOrCreateCompositeOrNull(ConstVal, I, SpvType, TII, ConstVec, BW,
557 SpvType->getOperand(2).getImm(),
558 ZeroAsNull);
559}
560
563 SPIRVType *SpvType,
564 const SPIRVInstrInfo &TII,
565 bool ZeroAsNull) {
566 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
567 assert(LLVMTy->isVectorTy());
568 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
569 Type *LLVMBaseTy = LLVMVecTy->getElementType();
570 assert(LLVMBaseTy->isFloatingPointTy());
571 auto *ConstVal = ConstantFP::get(LLVMBaseTy, Val);
572 auto *ConstVec =
573 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstVal);
574 unsigned BW = getScalarOrVectorBitWidth(SpvType);
575 return getOrCreateCompositeOrNull(ConstVal, I, SpvType, TII, ConstVec, BW,
576 SpvType->getOperand(2).getImm(),
577 ZeroAsNull);
578}
579
581 uint64_t Val, size_t Num, MachineInstr &I, SPIRVType *SpvType,
582 const SPIRVInstrInfo &TII) {
583 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
584 assert(LLVMTy->isArrayTy());
585 const ArrayType *LLVMArrTy = cast<ArrayType>(LLVMTy);
586 Type *LLVMBaseTy = LLVMArrTy->getElementType();
587 Constant *CI = ConstantInt::get(LLVMBaseTy, Val);
588 SPIRVType *SpvBaseTy = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
589 unsigned BW = getScalarOrVectorBitWidth(SpvBaseTy);
590 // The following is reasonably unique key that is better that [Val]. The naive
591 // alternative would be something along the lines of:
592 // SmallVector<Constant *> NumCI(Num, CI);
593 // Constant *UniqueKey =
594 // ConstantArray::get(const_cast<ArrayType*>(LLVMArrTy), NumCI);
595 // that would be a truly unique but dangerous key, because it could lead to
596 // the creation of constants of arbitrary length (that is, the parameter of
597 // memset) which were missing in the original module.
599 {PoisonValue::get(const_cast<ArrayType *>(LLVMArrTy)),
600 ConstantInt::get(LLVMBaseTy, Val), ConstantInt::get(LLVMBaseTy, Num)});
601 return getOrCreateCompositeOrNull(CI, I, SpvType, TII, UniqueKey, BW,
602 LLVMArrTy->getNumElements());
603}
604
605Register SPIRVGlobalRegistry::getOrCreateIntCompositeOrNull(
606 uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR,
607 Constant *CA, unsigned BitWidth, unsigned ElemCnt) {
608 if (Register R = find(CA, CurMF); R.isValid())
609 return R;
610
611 Register ElemReg;
612 if (Val || EmitIR) {
613 SPIRVType *SpvBaseType = getOrCreateSPIRVIntegerType(BitWidth, MIRBuilder);
614 ElemReg = buildConstantInt(Val, MIRBuilder, SpvBaseType, EmitIR);
615 }
616 LLT LLTy = EmitIR ? LLT::fixed_vector(ElemCnt, BitWidth) : LLT::scalar(64);
617 Register Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
618 CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
619 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
620
621 const MachineInstr *NewMI =
622 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
623 if (EmitIR)
624 return MIRBuilder.buildSplatBuildVector(Res, ElemReg);
625
626 if (Val) {
627 auto MIB = MIRBuilder.buildInstr(SPIRV::OpConstantComposite)
628 .addDef(Res)
629 .addUse(getSPIRVTypeID(SpvType));
630 for (unsigned i = 0; i < ElemCnt; ++i)
631 MIB.addUse(ElemReg);
632 return MIB;
633 }
634
635 return MIRBuilder.buildInstr(SPIRV::OpConstantNull)
636 .addDef(Res)
637 .addUse(getSPIRVTypeID(SpvType));
638 });
639 add(CA, NewMI);
640 return Res;
641}
642
645 MachineIRBuilder &MIRBuilder,
646 SPIRVType *SpvType, bool EmitIR) {
647 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
648 assert(LLVMTy->isVectorTy());
649 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
650 Type *LLVMBaseTy = LLVMVecTy->getElementType();
651 const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
652 auto ConstVec =
653 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstInt);
654 unsigned BW = getScalarOrVectorBitWidth(SpvType);
655 return getOrCreateIntCompositeOrNull(Val, MIRBuilder, SpvType, EmitIR,
656 ConstVec, BW,
657 SpvType->getOperand(2).getImm());
658}
659
662 SPIRVType *SpvType) {
663 const Type *Ty = getTypeForSPIRVType(SpvType);
664 unsigned AddressSpace = typeToAddressSpace(Ty);
665 Type *ElemTy = ::getPointeeType(Ty);
666 assert(ElemTy);
669 Register Res = find(CP, CurMF);
670 if (Res.isValid())
671 return Res;
672
673 LLT LLTy = LLT::pointer(AddressSpace, PointerSize);
674 Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
675 CurMF->getRegInfo().setRegClass(Res, &SPIRV::pIDRegClass);
676 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
677
678 const MachineInstr *NewMI =
679 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
680 return MIRBuilder.buildInstr(SPIRV::OpConstantNull)
681 .addDef(Res)
682 .addUse(getSPIRVTypeID(SpvType));
683 });
684 add(CP, NewMI);
685 return Res;
686}
687
690 unsigned Param, unsigned FilerMode,
691 MachineIRBuilder &MIRBuilder) {
692 auto Sampler =
693 ResReg.isValid()
694 ? ResReg
695 : MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::iIDRegClass);
696 SPIRVType *TypeSampler = getOrCreateOpTypeSampler(MIRBuilder);
697 Register TypeSamplerReg = getSPIRVTypeID(TypeSampler);
698 // We cannot use createOpType() logic here, because of the
699 // GlobalISel/IRTranslator.cpp check for a tail call that expects that
700 // MIRBuilder.getInsertPt() has a previous instruction. If this constant is
701 // inserted as a result of "__translate_sampler_initializer()" this would
702 // break this IRTranslator assumption.
703 MIRBuilder.buildInstr(SPIRV::OpConstantSampler)
704 .addDef(Sampler)
705 .addUse(TypeSamplerReg)
707 .addImm(Param)
708 .addImm(FilerMode);
709 return Sampler;
710}
711
713 Register ResVReg, SPIRVType *BaseType, StringRef Name,
714 const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage,
715 const MachineInstr *Init, bool IsConst, bool HasLinkageTy,
716 SPIRV::LinkageType::LinkageType LinkageType, MachineIRBuilder &MIRBuilder,
717 bool IsInstSelector) {
718 const GlobalVariable *GVar = nullptr;
719 if (GV) {
721 } else {
722 // If GV is not passed explicitly, use the name to find or construct
723 // the global variable.
724 Module *M = MIRBuilder.getMF().getFunction().getParent();
725 GVar = M->getGlobalVariable(Name);
726 if (GVar == nullptr) {
727 const Type *Ty = getTypeForSPIRVType(BaseType); // TODO: check type.
728 // Module takes ownership of the global var.
729 GVar = new GlobalVariable(*M, const_cast<Type *>(Ty), false,
731 Twine(Name));
732 }
733 GV = GVar;
734 }
735
736 const MachineFunction *MF = &MIRBuilder.getMF();
737 Register Reg = find(GVar, MF);
738 if (Reg.isValid()) {
739 if (Reg != ResVReg)
740 MIRBuilder.buildCopy(ResVReg, Reg);
741 return ResVReg;
742 }
743
744 auto MIB = MIRBuilder.buildInstr(SPIRV::OpVariable)
745 .addDef(ResVReg)
747 .addImm(static_cast<uint32_t>(Storage));
748 if (Init != 0)
749 MIB.addUse(Init->getOperand(0).getReg());
750 // ISel may introduce a new register on this step, so we need to add it to
751 // DT and correct its type avoiding fails on the next stage.
752 if (IsInstSelector) {
753 const auto &Subtarget = CurMF->getSubtarget();
754 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
755 *Subtarget.getRegisterInfo(),
756 *Subtarget.getRegBankInfo());
757 }
758 add(GVar, MIB);
759
760 Reg = MIB->getOperand(0).getReg();
761 addGlobalObject(GVar, MF, Reg);
762
763 // Set to Reg the same type as ResVReg has.
764 auto MRI = MIRBuilder.getMRI();
765 if (Reg != ResVReg) {
766 LLT RegLLTy =
767 LLT::pointer(MRI->getType(ResVReg).getAddressSpace(), getPointerSize());
768 MRI->setType(Reg, RegLLTy);
769 assignSPIRVTypeToVReg(BaseType, Reg, MIRBuilder.getMF());
770 } else {
771 // Our knowledge about the type may be updated.
772 // If that's the case, we need to update a type
773 // associated with the register.
774 SPIRVType *DefType = getSPIRVTypeForVReg(ResVReg);
775 if (!DefType || DefType != BaseType)
776 assignSPIRVTypeToVReg(BaseType, Reg, MIRBuilder.getMF());
777 }
778
779 // If it's a global variable with name, output OpName for it.
780 if (GVar && GVar->hasName())
781 buildOpName(Reg, GVar->getName(), MIRBuilder);
782
783 // Output decorations for the GV.
784 // TODO: maybe move to GenerateDecorations pass.
785 const SPIRVSubtarget &ST =
787 if (IsConst && !ST.isShader())
788 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Constant, {});
789
790 if (GVar && GVar->getAlign().valueOrOne().value() != 1 && !ST.isShader()) {
791 unsigned Alignment = (unsigned)GVar->getAlign().valueOrOne().value();
792 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Alignment, {Alignment});
793 }
794
795 if (HasLinkageTy)
796 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::LinkageAttributes,
797 {static_cast<uint32_t>(LinkageType)}, Name);
798
799 SPIRV::BuiltIn::BuiltIn BuiltInId;
800 if (getSpirvBuiltInIdByName(Name, BuiltInId))
801 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::BuiltIn,
802 {static_cast<uint32_t>(BuiltInId)});
803
804 // If it's a global variable with "spirv.Decorations" metadata node
805 // recognize it as a SPIR-V friendly LLVM IR and parse "spirv.Decorations"
806 // arguments.
807 MDNode *GVarMD = nullptr;
808 if (GVar && (GVarMD = GVar->getMetadata("spirv.Decorations")) != nullptr)
809 buildOpSpirvDecorations(Reg, MIRBuilder, GVarMD);
810
811 return Reg;
812}
813
814// Returns a name based on the Type. Notes that this does not look at
815// decorations, and will return the same string for two types that are the same
816// except for decorations.
818 const SPIRVType *VarType, uint32_t Set, uint32_t Binding, StringRef Name,
819 MachineIRBuilder &MIRBuilder) {
820 Register VarReg =
821 MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::iIDRegClass);
822
823 buildGlobalVariable(VarReg, VarType, Name, nullptr,
824 getPointerStorageClass(VarType), nullptr, false, false,
825 SPIRV::LinkageType::Import, MIRBuilder, false);
826
827 buildOpDecorate(VarReg, MIRBuilder, SPIRV::Decoration::DescriptorSet, {Set});
828 buildOpDecorate(VarReg, MIRBuilder, SPIRV::Decoration::Binding, {Binding});
829 return VarReg;
830}
831
832// TODO: Double check the calls to getOpTypeArray to make sure that `ElemType`
833// is explicitly laid out when required.
834SPIRVType *SPIRVGlobalRegistry::getOpTypeArray(uint32_t NumElems,
835 SPIRVType *ElemType,
836 MachineIRBuilder &MIRBuilder,
837 bool ExplicitLayoutRequired,
838 bool EmitIR) {
839 assert((ElemType->getOpcode() != SPIRV::OpTypeVoid) &&
840 "Invalid array element type");
841 SPIRVType *SpvTypeInt32 = getOrCreateSPIRVIntegerType(32, MIRBuilder);
842 SPIRVType *ArrayType = nullptr;
843 const SPIRVSubtarget &ST =
845 if (NumElems != 0) {
846 Register NumElementsVReg =
847 buildConstantInt(NumElems, MIRBuilder, SpvTypeInt32, EmitIR);
848 ArrayType = createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
849 return MIRBuilder.buildInstr(SPIRV::OpTypeArray)
850 .addDef(createTypeVReg(MIRBuilder))
851 .addUse(getSPIRVTypeID(ElemType))
852 .addUse(NumElementsVReg);
853 });
854 } else {
855 assert(ST.isShader() && "Runtime arrays are not allowed in non-shader "
856 "SPIR-V modules.");
857 if (!ST.isShader())
858 return nullptr;
859 ArrayType = createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
860 return MIRBuilder.buildInstr(SPIRV::OpTypeRuntimeArray)
861 .addDef(createTypeVReg(MIRBuilder))
862 .addUse(getSPIRVTypeID(ElemType));
863 });
864 }
865
866 if (ExplicitLayoutRequired && !isResourceType(ElemType)) {
867 Type *ET = const_cast<Type *>(getTypeForSPIRVType(ElemType));
868 addArrayStrideDecorations(ArrayType->defs().begin()->getReg(), ET,
869 MIRBuilder);
870 }
871
872 return ArrayType;
873}
874
875SPIRVType *SPIRVGlobalRegistry::getOpTypeOpaque(const StructType *Ty,
876 MachineIRBuilder &MIRBuilder) {
877 assert(Ty->hasName());
878 const StringRef Name = Ty->hasName() ? Ty->getName() : "";
879 Register ResVReg = createTypeVReg(MIRBuilder);
880 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
881 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeOpaque).addDef(ResVReg);
882 addStringImm(Name, MIB);
883 buildOpName(ResVReg, Name, MIRBuilder);
884 return MIB;
885 });
886}
887
888SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(
889 const StructType *Ty, MachineIRBuilder &MIRBuilder,
890 SPIRV::AccessQualifier::AccessQualifier AccQual,
891 StructOffsetDecorator Decorator, bool EmitIR) {
892 const SPIRVSubtarget &ST =
894 SmallVector<Register, 4> FieldTypes;
895 constexpr unsigned MaxWordCount = UINT16_MAX;
896 const size_t NumElements = Ty->getNumElements();
897
898 size_t MaxNumElements = MaxWordCount - 2;
899 size_t SPIRVStructNumElements = NumElements;
900 if (NumElements > MaxNumElements) {
901 // Do adjustments for continued instructions.
902 SPIRVStructNumElements = MaxNumElements;
903 MaxNumElements = MaxWordCount - 1;
904 }
905
906 for (const auto &Elem : Ty->elements()) {
907 SPIRVType *ElemTy = findSPIRVType(
908 toTypedPointer(Elem), MIRBuilder, AccQual,
909 /* ExplicitLayoutRequired= */ Decorator != nullptr, EmitIR);
910 assert(ElemTy && ElemTy->getOpcode() != SPIRV::OpTypeVoid &&
911 "Invalid struct element type");
912 FieldTypes.push_back(getSPIRVTypeID(ElemTy));
913 }
914 Register ResVReg = createTypeVReg(MIRBuilder);
915 if (Ty->hasName())
916 buildOpName(ResVReg, Ty->getName(), MIRBuilder);
917 if (Ty->isPacked() && !ST.isShader())
918 buildOpDecorate(ResVReg, MIRBuilder, SPIRV::Decoration::CPacked, {});
919
920 SPIRVType *SPVType =
921 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
922 auto MIBStruct =
923 MIRBuilder.buildInstr(SPIRV::OpTypeStruct).addDef(ResVReg);
924 for (size_t I = 0; I < SPIRVStructNumElements; ++I)
925 MIBStruct.addUse(FieldTypes[I]);
926 for (size_t I = SPIRVStructNumElements; I < NumElements;
927 I += MaxNumElements) {
928 auto MIBCont =
929 MIRBuilder.buildInstr(SPIRV::OpTypeStructContinuedINTEL);
930 for (size_t J = I; J < std::min(I + MaxNumElements, NumElements); ++J)
931 MIBCont.addUse(FieldTypes[I]);
932 }
933 return MIBStruct;
934 });
935
936 if (Decorator)
937 Decorator(SPVType->defs().begin()->getReg());
938
939 return SPVType;
940}
941
942SPIRVType *SPIRVGlobalRegistry::getOrCreateSpecialType(
943 const Type *Ty, MachineIRBuilder &MIRBuilder,
944 SPIRV::AccessQualifier::AccessQualifier AccQual) {
945 assert(isSpecialOpaqueType(Ty) && "Not a special opaque builtin type");
946 return SPIRV::lowerBuiltinType(Ty, AccQual, MIRBuilder, this);
947}
948
949SPIRVType *SPIRVGlobalRegistry::getOpTypePointer(
950 SPIRV::StorageClass::StorageClass SC, SPIRVType *ElemType,
951 MachineIRBuilder &MIRBuilder, Register Reg) {
952 if (!Reg.isValid())
953 Reg = createTypeVReg(MIRBuilder);
954
955 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
956 return MIRBuilder.buildInstr(SPIRV::OpTypePointer)
957 .addDef(Reg)
958 .addImm(static_cast<uint32_t>(SC))
959 .addUse(getSPIRVTypeID(ElemType));
960 });
961}
962
963SPIRVType *SPIRVGlobalRegistry::getOpTypeForwardPointer(
964 SPIRV::StorageClass::StorageClass SC, MachineIRBuilder &MIRBuilder) {
965 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
966 return MIRBuilder.buildInstr(SPIRV::OpTypeForwardPointer)
967 .addUse(createTypeVReg(MIRBuilder))
968 .addImm(static_cast<uint32_t>(SC));
969 });
970}
971
972SPIRVType *SPIRVGlobalRegistry::getOpTypeFunction(
973 SPIRVType *RetType, const SmallVectorImpl<SPIRVType *> &ArgTypes,
974 MachineIRBuilder &MIRBuilder) {
975 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
976 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFunction)
977 .addDef(createTypeVReg(MIRBuilder))
978 .addUse(getSPIRVTypeID(RetType));
979 for (const SPIRVType *ArgType : ArgTypes)
980 MIB.addUse(getSPIRVTypeID(ArgType));
981 return MIB;
982 });
983}
984
986 const Type *Ty, SPIRVType *RetType,
987 const SmallVectorImpl<SPIRVType *> &ArgTypes,
988 MachineIRBuilder &MIRBuilder) {
989 if (const MachineInstr *MI = findMI(Ty, false, &MIRBuilder.getMF()))
990 return MI;
991 const MachineInstr *NewMI = getOpTypeFunction(RetType, ArgTypes, MIRBuilder);
992 add(Ty, false, NewMI);
993 return finishCreatingSPIRVType(Ty, NewMI);
994}
995
996SPIRVType *SPIRVGlobalRegistry::findSPIRVType(
997 const Type *Ty, MachineIRBuilder &MIRBuilder,
998 SPIRV::AccessQualifier::AccessQualifier AccQual,
999 bool ExplicitLayoutRequired, bool EmitIR) {
1000 Ty = adjustIntTypeByWidth(Ty);
1001 // TODO: findMI needs to know if a layout is required.
1002 if (const MachineInstr *MI =
1003 findMI(Ty, ExplicitLayoutRequired, &MIRBuilder.getMF()))
1004 return MI;
1005 if (auto It = ForwardPointerTypes.find(Ty); It != ForwardPointerTypes.end())
1006 return It->second;
1007 return restOfCreateSPIRVType(Ty, MIRBuilder, AccQual, ExplicitLayoutRequired,
1008 EmitIR);
1009}
1010
1012 assert(SpirvType && "Attempting to get type id for nullptr type.");
1013 if (SpirvType->getOpcode() == SPIRV::OpTypeForwardPointer ||
1014 SpirvType->getOpcode() == SPIRV::OpTypeStructContinuedINTEL)
1015 return SpirvType->uses().begin()->getReg();
1016 return SpirvType->defs().begin()->getReg();
1017}
1018
1019// We need to use a new LLVM integer type if there is a mismatch between
1020// number of bits in LLVM and SPIRV integer types to let DuplicateTracker
1021// ensure uniqueness of a SPIRV type by the corresponding LLVM type. Without
1022// such an adjustment SPIRVGlobalRegistry::getOpTypeInt() could create the
1023// same "OpTypeInt 8" type for a series of LLVM integer types with number of
1024// bits less than 8. This would lead to duplicate type definitions
1025// eventually due to the method that DuplicateTracker utilizes to reason
1026// about uniqueness of type records.
1027const Type *SPIRVGlobalRegistry::adjustIntTypeByWidth(const Type *Ty) const {
1028 if (auto IType = dyn_cast<IntegerType>(Ty)) {
1029 unsigned SrcBitWidth = IType->getBitWidth();
1030 if (SrcBitWidth > 1) {
1031 unsigned BitWidth = adjustOpTypeIntWidth(SrcBitWidth);
1032 // Maybe change source LLVM type to keep DuplicateTracker consistent.
1033 if (SrcBitWidth != BitWidth)
1034 Ty = IntegerType::get(Ty->getContext(), BitWidth);
1035 }
1036 }
1037 return Ty;
1038}
1039
1040SPIRVType *SPIRVGlobalRegistry::createSPIRVType(
1041 const Type *Ty, MachineIRBuilder &MIRBuilder,
1042 SPIRV::AccessQualifier::AccessQualifier AccQual,
1043 bool ExplicitLayoutRequired, bool EmitIR) {
1044 if (isSpecialOpaqueType(Ty))
1045 return getOrCreateSpecialType(Ty, MIRBuilder, AccQual);
1046
1047 if (const MachineInstr *MI =
1048 findMI(Ty, ExplicitLayoutRequired, &MIRBuilder.getMF()))
1049 return MI;
1050
1051 if (auto IType = dyn_cast<IntegerType>(Ty)) {
1052 const unsigned Width = IType->getBitWidth();
1053 return Width == 1 ? getOpTypeBool(MIRBuilder)
1054 : getOpTypeInt(Width, MIRBuilder, false);
1055 }
1056 if (Ty->isFloatingPointTy()) {
1057 if (Ty->isBFloatTy()) {
1058 return getOpTypeFloat(Ty->getPrimitiveSizeInBits(), MIRBuilder,
1059 SPIRV::FPEncoding::BFloat16KHR);
1060 } else {
1061 return getOpTypeFloat(Ty->getPrimitiveSizeInBits(), MIRBuilder);
1062 }
1063 }
1064 if (Ty->isVoidTy())
1065 return getOpTypeVoid(MIRBuilder);
1066 if (Ty->isVectorTy()) {
1067 SPIRVType *El =
1068 findSPIRVType(cast<FixedVectorType>(Ty)->getElementType(), MIRBuilder,
1069 AccQual, ExplicitLayoutRequired, EmitIR);
1070 return getOpTypeVector(cast<FixedVectorType>(Ty)->getNumElements(), El,
1071 MIRBuilder);
1072 }
1073 if (Ty->isArrayTy()) {
1074 SPIRVType *El = findSPIRVType(Ty->getArrayElementType(), MIRBuilder,
1075 AccQual, ExplicitLayoutRequired, EmitIR);
1076 return getOpTypeArray(Ty->getArrayNumElements(), El, MIRBuilder,
1077 ExplicitLayoutRequired, EmitIR);
1078 }
1079 if (auto SType = dyn_cast<StructType>(Ty)) {
1080 if (SType->isOpaque())
1081 return getOpTypeOpaque(SType, MIRBuilder);
1082
1083 StructOffsetDecorator Decorator = nullptr;
1084 if (ExplicitLayoutRequired) {
1085 Decorator = [&MIRBuilder, SType, this](Register Reg) {
1086 addStructOffsetDecorations(Reg, const_cast<StructType *>(SType),
1087 MIRBuilder);
1088 };
1089 }
1090 return getOpTypeStruct(SType, MIRBuilder, AccQual, std::move(Decorator),
1091 EmitIR);
1092 }
1093 if (auto FType = dyn_cast<FunctionType>(Ty)) {
1094 SPIRVType *RetTy = findSPIRVType(FType->getReturnType(), MIRBuilder,
1095 AccQual, ExplicitLayoutRequired, EmitIR);
1096 SmallVector<SPIRVType *, 4> ParamTypes;
1097 for (const auto &ParamTy : FType->params())
1098 ParamTypes.push_back(findSPIRVType(ParamTy, MIRBuilder, AccQual,
1099 ExplicitLayoutRequired, EmitIR));
1100 return getOpTypeFunction(RetTy, ParamTypes, MIRBuilder);
1101 }
1102
1103 unsigned AddrSpace = typeToAddressSpace(Ty);
1104 SPIRVType *SpvElementType = nullptr;
1105 if (Type *ElemTy = ::getPointeeType(Ty))
1106 SpvElementType = getOrCreateSPIRVType(ElemTy, MIRBuilder, AccQual, EmitIR);
1107 else
1108 SpvElementType = getOrCreateSPIRVIntegerType(8, MIRBuilder);
1109
1110 // Get access to information about available extensions
1111 const SPIRVSubtarget *ST =
1112 static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());
1113 auto SC = addressSpaceToStorageClass(AddrSpace, *ST);
1114
1115 Type *ElemTy = ::getPointeeType(Ty);
1116 if (!ElemTy) {
1117 ElemTy = Type::getInt8Ty(MIRBuilder.getContext());
1118 }
1119
1120 // If we have forward pointer associated with this type, use its register
1121 // operand to create OpTypePointer.
1122 if (auto It = ForwardPointerTypes.find(Ty); It != ForwardPointerTypes.end()) {
1123 Register Reg = getSPIRVTypeID(It->second);
1124 // TODO: what does getOpTypePointer do?
1125 return getOpTypePointer(SC, SpvElementType, MIRBuilder, Reg);
1126 }
1127
1128 return getOrCreateSPIRVPointerType(ElemTy, MIRBuilder, SC);
1129}
1130
1131SPIRVType *SPIRVGlobalRegistry::restOfCreateSPIRVType(
1132 const Type *Ty, MachineIRBuilder &MIRBuilder,
1133 SPIRV::AccessQualifier::AccessQualifier AccessQual,
1134 bool ExplicitLayoutRequired, bool EmitIR) {
1135 // TODO: Could this create a problem if one requires an explicit layout, and
1136 // the next time it does not?
1137 if (TypesInProcessing.count(Ty) && !isPointerTyOrWrapper(Ty))
1138 return nullptr;
1139 TypesInProcessing.insert(Ty);
1140 SPIRVType *SpirvType = createSPIRVType(Ty, MIRBuilder, AccessQual,
1141 ExplicitLayoutRequired, EmitIR);
1142 TypesInProcessing.erase(Ty);
1143 VRegToTypeMap[&MIRBuilder.getMF()][getSPIRVTypeID(SpirvType)] = SpirvType;
1144
1145 // TODO: We could end up with two SPIR-V types pointing to the same llvm type.
1146 // Is that a problem?
1147 SPIRVToLLVMType[SpirvType] = unifyPtrType(Ty);
1148
1149 if (SpirvType->getOpcode() == SPIRV::OpTypeForwardPointer ||
1150 findMI(Ty, false, &MIRBuilder.getMF()) || isSpecialOpaqueType(Ty))
1151 return SpirvType;
1152
1153 if (auto *ExtTy = dyn_cast<TargetExtType>(Ty);
1154 ExtTy && isTypedPointerWrapper(ExtTy))
1155 add(ExtTy->getTypeParameter(0), ExtTy->getIntParameter(0), SpirvType);
1156 else if (!isPointerTy(Ty))
1157 add(Ty, ExplicitLayoutRequired, SpirvType);
1158 else if (isTypedPointerTy(Ty))
1159 add(cast<TypedPointerType>(Ty)->getElementType(),
1160 getPointerAddressSpace(Ty), SpirvType);
1161 else
1163 getPointerAddressSpace(Ty), SpirvType);
1164 return SpirvType;
1165}
1166
1167SPIRVType *
1169 const MachineFunction *MF) const {
1170 auto t = VRegToTypeMap.find(MF ? MF : CurMF);
1171 if (t != VRegToTypeMap.end()) {
1172 auto tt = t->second.find(VReg);
1173 if (tt != t->second.end())
1174 return tt->second;
1175 }
1176 return nullptr;
1177}
1178
1180 MachineFunction *MF) {
1181 if (!MF)
1182 MF = CurMF;
1183 MachineInstr *Instr = getVRegDef(MF->getRegInfo(), VReg);
1184 return getSPIRVTypeForVReg(Instr->getOperand(1).getReg(), MF);
1185}
1186
1188 const Type *Ty, MachineIRBuilder &MIRBuilder,
1189 SPIRV::AccessQualifier::AccessQualifier AccessQual,
1190 bool ExplicitLayoutRequired, bool EmitIR) {
1191 const MachineFunction *MF = &MIRBuilder.getMF();
1192 Register Reg;
1193 if (auto *ExtTy = dyn_cast<TargetExtType>(Ty);
1194 ExtTy && isTypedPointerWrapper(ExtTy))
1195 Reg = find(ExtTy->getTypeParameter(0), ExtTy->getIntParameter(0), MF);
1196 else if (!isPointerTy(Ty))
1197 Reg = find(Ty = adjustIntTypeByWidth(Ty), ExplicitLayoutRequired, MF);
1198 else if (isTypedPointerTy(Ty))
1199 Reg = find(cast<TypedPointerType>(Ty)->getElementType(),
1200 getPointerAddressSpace(Ty), MF);
1201 else
1202 Reg = find(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),
1203 getPointerAddressSpace(Ty), MF);
1204 if (Reg.isValid() && !isSpecialOpaqueType(Ty))
1205 return getSPIRVTypeForVReg(Reg);
1206
1207 TypesInProcessing.clear();
1208 SPIRVType *STy = restOfCreateSPIRVType(Ty, MIRBuilder, AccessQual,
1209 ExplicitLayoutRequired, EmitIR);
1210 // Create normal pointer types for the corresponding OpTypeForwardPointers.
1211 for (auto &CU : ForwardPointerTypes) {
1212 // Pointer type themselves do not require an explicit layout. The types
1213 // they pointer to might, but that is taken care of when creating the type.
1214 bool PtrNeedsLayout = false;
1215 const Type *Ty2 = CU.first;
1216 SPIRVType *STy2 = CU.second;
1217 if ((Reg = find(Ty2, PtrNeedsLayout, MF)).isValid())
1218 STy2 = getSPIRVTypeForVReg(Reg);
1219 else
1220 STy2 = restOfCreateSPIRVType(Ty2, MIRBuilder, AccessQual, PtrNeedsLayout,
1221 EmitIR);
1222 if (Ty == Ty2)
1223 STy = STy2;
1224 }
1225 ForwardPointerTypes.clear();
1226 return STy;
1227}
1228
1230 unsigned TypeOpcode) const {
1232 assert(Type && "isScalarOfType VReg has no type assigned");
1233 return Type->getOpcode() == TypeOpcode;
1234}
1235
1237 unsigned TypeOpcode) const {
1239 assert(Type && "isScalarOrVectorOfType VReg has no type assigned");
1240 if (Type->getOpcode() == TypeOpcode)
1241 return true;
1242 if (Type->getOpcode() == SPIRV::OpTypeVector) {
1243 Register ScalarTypeVReg = Type->getOperand(1).getReg();
1244 SPIRVType *ScalarType = getSPIRVTypeForVReg(ScalarTypeVReg);
1245 return ScalarType->getOpcode() == TypeOpcode;
1246 }
1247 return false;
1248}
1249
1251 switch (Type->getOpcode()) {
1252 case SPIRV::OpTypeImage:
1253 case SPIRV::OpTypeSampler:
1254 case SPIRV::OpTypeSampledImage:
1255 return true;
1256 case SPIRV::OpTypeStruct:
1257 return hasBlockDecoration(Type);
1258 default:
1259 return false;
1260 }
1261 return false;
1262}
1263unsigned
1267
1268unsigned
1270 if (!Type)
1271 return 0;
1272 return Type->getOpcode() == SPIRV::OpTypeVector
1273 ? static_cast<unsigned>(Type->getOperand(2).getImm())
1274 : 1;
1275}
1276
1277SPIRVType *
1281
1282SPIRVType *
1284 if (!Type)
1285 return nullptr;
1286 Register ScalarReg = Type->getOpcode() == SPIRV::OpTypeVector
1287 ? Type->getOperand(1).getReg()
1288 : Type->getOperand(0).getReg();
1289 SPIRVType *ScalarType = getSPIRVTypeForVReg(ScalarReg);
1290 assert(isScalarOrVectorOfType(Type->getOperand(0).getReg(),
1291 ScalarType->getOpcode()));
1292 return ScalarType;
1293}
1294
1295unsigned
1297 assert(Type && "Invalid Type pointer");
1298 if (Type->getOpcode() == SPIRV::OpTypeVector) {
1299 auto EleTypeReg = Type->getOperand(1).getReg();
1300 Type = getSPIRVTypeForVReg(EleTypeReg);
1301 }
1302 if (Type->getOpcode() == SPIRV::OpTypeInt ||
1303 Type->getOpcode() == SPIRV::OpTypeFloat)
1304 return Type->getOperand(1).getImm();
1305 if (Type->getOpcode() == SPIRV::OpTypeBool)
1306 return 1;
1307 llvm_unreachable("Attempting to get bit width of non-integer/float type.");
1308}
1309
1311 const SPIRVType *Type) const {
1312 assert(Type && "Invalid Type pointer");
1313 unsigned NumElements = 1;
1314 if (Type->getOpcode() == SPIRV::OpTypeVector) {
1315 NumElements = static_cast<unsigned>(Type->getOperand(2).getImm());
1316 Type = getSPIRVTypeForVReg(Type->getOperand(1).getReg());
1317 }
1318 return Type->getOpcode() == SPIRV::OpTypeInt ||
1319 Type->getOpcode() == SPIRV::OpTypeFloat
1320 ? NumElements * Type->getOperand(1).getImm()
1321 : 0;
1322}
1323
1325 const SPIRVType *Type) const {
1326 if (Type && Type->getOpcode() == SPIRV::OpTypeVector)
1327 Type = getSPIRVTypeForVReg(Type->getOperand(1).getReg());
1328 return Type && Type->getOpcode() == SPIRV::OpTypeInt ? Type : nullptr;
1329}
1330
1333 return IntType && IntType->getOperand(2).getImm() != 0;
1334}
1335
1337 return PtrType && PtrType->getOpcode() == SPIRV::OpTypePointer
1338 ? getSPIRVTypeForVReg(PtrType->getOperand(2).getReg())
1339 : nullptr;
1340}
1341
1343 SPIRVType *ElemType = getPointeeType(getSPIRVTypeForVReg(PtrReg));
1344 return ElemType ? ElemType->getOpcode() : 0;
1345}
1346
1348 const SPIRVType *Type2) const {
1349 if (!Type1 || !Type2)
1350 return false;
1351 auto Op1 = Type1->getOpcode(), Op2 = Type2->getOpcode();
1352 // Ignore difference between <1.5 and >=1.5 protocol versions:
1353 // it's valid if either Result Type or Operand is a pointer, and the other
1354 // is a pointer, an integer scalar, or an integer vector.
1355 if (Op1 == SPIRV::OpTypePointer &&
1356 (Op2 == SPIRV::OpTypePointer || retrieveScalarOrVectorIntType(Type2)))
1357 return true;
1358 if (Op2 == SPIRV::OpTypePointer &&
1359 (Op1 == SPIRV::OpTypePointer || retrieveScalarOrVectorIntType(Type1)))
1360 return true;
1361 unsigned Bits1 = getNumScalarOrVectorTotalBitWidth(Type1),
1362 Bits2 = getNumScalarOrVectorTotalBitWidth(Type2);
1363 return Bits1 > 0 && Bits1 == Bits2;
1364}
1365
1366SPIRV::StorageClass::StorageClass
1369 assert(Type && Type->getOpcode() == SPIRV::OpTypePointer &&
1370 Type->getOperand(1).isImm() && "Pointer type is expected");
1372}
1373
1374SPIRV::StorageClass::StorageClass
1376 return static_cast<SPIRV::StorageClass::StorageClass>(
1377 Type->getOperand(1).getImm());
1378}
1379
1381 MachineIRBuilder &MIRBuilder, Type *ElemType,
1382 SPIRV::StorageClass::StorageClass SC, bool IsWritable, bool EmitIr) {
1383 auto Key = SPIRV::irhandle_vkbuffer(ElemType, SC, IsWritable);
1384 if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
1385 return MI;
1386
1387 bool ExplicitLayoutRequired = storageClassRequiresExplictLayout(SC);
1388 // We need to get the SPIR-V type for the element here, so we can add the
1389 // decoration to it.
1390 auto *T = StructType::create(ElemType);
1391 auto *BlockType =
1392 getOrCreateSPIRVType(T, MIRBuilder, SPIRV::AccessQualifier::None,
1393 ExplicitLayoutRequired, EmitIr);
1394
1395 buildOpDecorate(BlockType->defs().begin()->getReg(), MIRBuilder,
1396 SPIRV::Decoration::Block, {});
1397
1398 if (!IsWritable) {
1399 buildOpMemberDecorate(BlockType->defs().begin()->getReg(), MIRBuilder,
1400 SPIRV::Decoration::NonWritable, 0, {});
1401 }
1402
1403 SPIRVType *R = getOrCreateSPIRVPointerTypeInternal(BlockType, MIRBuilder, SC);
1404 add(Key, R);
1405 return R;
1406}
1407
1409 MachineIRBuilder &MIRBuilder, const TargetExtType *T, bool EmitIr) {
1410 auto Key = SPIRV::handle(T);
1411 if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
1412 return MI;
1413
1414 StructType *ST = cast<StructType>(T->getTypeParameter(0));
1415 ArrayRef<uint32_t> Offsets = T->int_params().slice(1);
1416 assert(ST->getNumElements() == Offsets.size());
1417
1418 StructOffsetDecorator Decorator = [&MIRBuilder, &Offsets](Register Reg) {
1419 for (uint32_t I = 0; I < Offsets.size(); ++I) {
1420 buildOpMemberDecorate(Reg, MIRBuilder, SPIRV::Decoration::Offset, I,
1421 {Offsets[I]});
1422 }
1423 };
1424
1425 // We need a new OpTypeStruct instruction because decorations will be
1426 // different from a struct with an explicit layout created from a different
1427 // entry point.
1428 SPIRVType *SPIRVStructType =
1429 getOpTypeStruct(ST, MIRBuilder, SPIRV::AccessQualifier::None,
1430 std::move(Decorator), EmitIr);
1431 add(Key, SPIRVStructType);
1432 return SPIRVStructType;
1433}
1434
1436 const TargetExtType *ExtensionType,
1437 const SPIRV::AccessQualifier::AccessQualifier Qualifier,
1438 MachineIRBuilder &MIRBuilder) {
1439 assert(ExtensionType->getNumTypeParameters() == 1 &&
1440 "SPIR-V image builtin type must have sampled type parameter!");
1441 const SPIRVType *SampledType =
1442 getOrCreateSPIRVType(ExtensionType->getTypeParameter(0), MIRBuilder,
1443 SPIRV::AccessQualifier::ReadWrite, true);
1444 assert((ExtensionType->getNumIntParameters() == 7 ||
1445 ExtensionType->getNumIntParameters() == 6) &&
1446 "Invalid number of parameters for SPIR-V image builtin!");
1447
1448 SPIRV::AccessQualifier::AccessQualifier accessQualifier =
1449 SPIRV::AccessQualifier::None;
1450 if (ExtensionType->getNumIntParameters() == 7) {
1451 accessQualifier = Qualifier == SPIRV::AccessQualifier::WriteOnly
1452 ? SPIRV::AccessQualifier::WriteOnly
1453 : SPIRV::AccessQualifier::AccessQualifier(
1454 ExtensionType->getIntParameter(6));
1455 }
1456
1457 // Create or get an existing type from GlobalRegistry.
1458 SPIRVType *R = getOrCreateOpTypeImage(
1459 MIRBuilder, SampledType,
1460 SPIRV::Dim::Dim(ExtensionType->getIntParameter(0)),
1461 ExtensionType->getIntParameter(1), ExtensionType->getIntParameter(2),
1462 ExtensionType->getIntParameter(3), ExtensionType->getIntParameter(4),
1463 SPIRV::ImageFormat::ImageFormat(ExtensionType->getIntParameter(5)),
1464 accessQualifier);
1465 SPIRVToLLVMType[R] = ExtensionType;
1466 return R;
1467}
1468
1469SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeImage(
1470 MachineIRBuilder &MIRBuilder, SPIRVType *SampledType, SPIRV::Dim::Dim Dim,
1471 uint32_t Depth, uint32_t Arrayed, uint32_t Multisampled, uint32_t Sampled,
1472 SPIRV::ImageFormat::ImageFormat ImageFormat,
1473 SPIRV::AccessQualifier::AccessQualifier AccessQual) {
1474 auto Key = SPIRV::irhandle_image(SPIRVToLLVMType.lookup(SampledType), Dim,
1475 Depth, Arrayed, Multisampled, Sampled,
1476 ImageFormat, AccessQual);
1477 if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
1478 return MI;
1479 const MachineInstr *NewMI =
1480 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1481 auto MIB =
1482 MIRBuilder.buildInstr(SPIRV::OpTypeImage)
1483 .addDef(createTypeVReg(MIRBuilder))
1484 .addUse(getSPIRVTypeID(SampledType))
1485 .addImm(Dim)
1486 .addImm(Depth) // Depth (whether or not it is a Depth image).
1487 .addImm(Arrayed) // Arrayed.
1488 .addImm(Multisampled) // Multisampled (0 = only single-sample).
1489 .addImm(Sampled) // Sampled (0 = usage known at runtime).
1490 .addImm(ImageFormat);
1491 if (AccessQual != SPIRV::AccessQualifier::None)
1492 MIB.addImm(AccessQual);
1493 return MIB;
1494 });
1495 add(Key, NewMI);
1496 return NewMI;
1497}
1498
1499SPIRVType *
1502 const MachineFunction *MF = &MIRBuilder.getMF();
1503 if (const MachineInstr *MI = findMI(Key, MF))
1504 return MI;
1505 const MachineInstr *NewMI =
1506 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1507 return MIRBuilder.buildInstr(SPIRV::OpTypeSampler)
1508 .addDef(createTypeVReg(MIRBuilder));
1509 });
1510 add(Key, NewMI);
1511 return NewMI;
1512}
1513
1515 MachineIRBuilder &MIRBuilder,
1516 SPIRV::AccessQualifier::AccessQualifier AccessQual) {
1517 auto Key = SPIRV::irhandle_pipe(AccessQual);
1518 if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
1519 return MI;
1520 const MachineInstr *NewMI =
1521 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1522 return MIRBuilder.buildInstr(SPIRV::OpTypePipe)
1523 .addDef(createTypeVReg(MIRBuilder))
1524 .addImm(AccessQual);
1525 });
1526 add(Key, NewMI);
1527 return NewMI;
1528}
1529
1531 MachineIRBuilder &MIRBuilder) {
1532 auto Key = SPIRV::irhandle_event();
1533 if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
1534 return MI;
1535 const MachineInstr *NewMI =
1536 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1537 return MIRBuilder.buildInstr(SPIRV::OpTypeDeviceEvent)
1538 .addDef(createTypeVReg(MIRBuilder));
1539 });
1540 add(Key, NewMI);
1541 return NewMI;
1542}
1543
1545 SPIRVType *ImageType, MachineIRBuilder &MIRBuilder) {
1547 SPIRVToLLVMType.lookup(MIRBuilder.getMF().getRegInfo().getVRegDef(
1548 ImageType->getOperand(1).getReg())),
1549 ImageType);
1550 if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
1551 return MI;
1552 const MachineInstr *NewMI =
1553 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1554 return MIRBuilder.buildInstr(SPIRV::OpTypeSampledImage)
1555 .addDef(createTypeVReg(MIRBuilder))
1556 .addUse(getSPIRVTypeID(ImageType));
1557 });
1558 add(Key, NewMI);
1559 return NewMI;
1560}
1561
1563 MachineIRBuilder &MIRBuilder, const TargetExtType *ExtensionType,
1564 const SPIRVType *ElemType, uint32_t Scope, uint32_t Rows, uint32_t Columns,
1565 uint32_t Use, bool EmitIR) {
1566 if (const MachineInstr *MI =
1567 findMI(ExtensionType, false, &MIRBuilder.getMF()))
1568 return MI;
1569 const MachineInstr *NewMI =
1570 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1571 SPIRVType *SpvTypeInt32 = getOrCreateSPIRVIntegerType(32, MIRBuilder);
1572 const Type *ET = getTypeForSPIRVType(ElemType);
1573 if (ET->isIntegerTy() && ET->getIntegerBitWidth() == 4 &&
1575 .canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) {
1576 MIRBuilder.buildInstr(SPIRV::OpCapability)
1577 .addImm(SPIRV::Capability::Int4CooperativeMatrixINTEL);
1578 }
1579 return MIRBuilder.buildInstr(SPIRV::OpTypeCooperativeMatrixKHR)
1580 .addDef(createTypeVReg(MIRBuilder))
1581 .addUse(getSPIRVTypeID(ElemType))
1582 .addUse(buildConstantInt(Scope, MIRBuilder, SpvTypeInt32, EmitIR))
1583 .addUse(buildConstantInt(Rows, MIRBuilder, SpvTypeInt32, EmitIR))
1584 .addUse(buildConstantInt(Columns, MIRBuilder, SpvTypeInt32, EmitIR))
1585 .addUse(buildConstantInt(Use, MIRBuilder, SpvTypeInt32, EmitIR));
1586 });
1587 add(ExtensionType, false, NewMI);
1588 return NewMI;
1589}
1590
1592 const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode) {
1593 if (const MachineInstr *MI = findMI(Ty, false, &MIRBuilder.getMF()))
1594 return MI;
1595 const MachineInstr *NewMI =
1596 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1597 return MIRBuilder.buildInstr(Opcode).addDef(createTypeVReg(MIRBuilder));
1598 });
1599 add(Ty, false, NewMI);
1600 return NewMI;
1601}
1602
1604 const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode,
1606 if (const MachineInstr *MI = findMI(Ty, false, &MIRBuilder.getMF()))
1607 return MI;
1608 Register ResVReg = createTypeVReg(MIRBuilder);
1609 const MachineInstr *NewMI =
1610 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1611 MachineInstrBuilder MIB = MIRBuilder.buildInstr(SPIRV::UNKNOWN_type)
1612 .addDef(ResVReg)
1613 .addImm(Opcode);
1614 for (MCOperand Operand : Operands) {
1615 if (Operand.isReg()) {
1616 MIB.addUse(Operand.getReg());
1617 } else if (Operand.isImm()) {
1618 MIB.addImm(Operand.getImm());
1619 }
1620 }
1621 return MIB;
1622 });
1623 add(Ty, false, NewMI);
1624 return NewMI;
1625}
1626
1627// Returns nullptr if unable to recognize SPIRV type name
1629 StringRef TypeStr, MachineIRBuilder &MIRBuilder, bool EmitIR,
1630 SPIRV::StorageClass::StorageClass SC,
1631 SPIRV::AccessQualifier::AccessQualifier AQ) {
1632 unsigned VecElts = 0;
1633 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
1634
1635 // Parse strings representing either a SPIR-V or OpenCL builtin type.
1636 if (hasBuiltinTypePrefix(TypeStr))
1638 TypeStr.str(), MIRBuilder.getContext()),
1639 MIRBuilder, AQ, false, true);
1640
1641 // Parse type name in either "typeN" or "type vector[N]" format, where
1642 // N is the number of elements of the vector.
1643 Type *Ty;
1644
1645 Ty = parseBasicTypeName(TypeStr, Ctx);
1646 if (!Ty)
1647 // Unable to recognize SPIRV type name
1648 return nullptr;
1649
1650 const SPIRVType *SpirvTy =
1651 getOrCreateSPIRVType(Ty, MIRBuilder, AQ, false, true);
1652
1653 // Handle "type*" or "type* vector[N]".
1654 if (TypeStr.consume_front("*"))
1655 SpirvTy = getOrCreateSPIRVPointerType(Ty, MIRBuilder, SC);
1656
1657 // Handle "typeN*" or "type vector[N]*".
1658 bool IsPtrToVec = TypeStr.consume_back("*");
1659
1660 if (TypeStr.consume_front(" vector[")) {
1661 TypeStr = TypeStr.substr(0, TypeStr.find(']'));
1662 }
1663 TypeStr.getAsInteger(10, VecElts);
1664 if (VecElts > 0)
1665 SpirvTy = getOrCreateSPIRVVectorType(SpirvTy, VecElts, MIRBuilder, EmitIR);
1666
1667 if (IsPtrToVec)
1668 SpirvTy = getOrCreateSPIRVPointerType(SpirvTy, MIRBuilder, SC);
1669
1670 return SpirvTy;
1671}
1672
1673SPIRVType *
1675 MachineIRBuilder &MIRBuilder) {
1676 return getOrCreateSPIRVType(
1678 MIRBuilder, SPIRV::AccessQualifier::ReadWrite, false, true);
1679}
1680
1681SPIRVType *SPIRVGlobalRegistry::finishCreatingSPIRVType(const Type *LLVMTy,
1682 SPIRVType *SpirvType) {
1683 assert(CurMF == SpirvType->getMF());
1684 VRegToTypeMap[CurMF][getSPIRVTypeID(SpirvType)] = SpirvType;
1685 SPIRVToLLVMType[SpirvType] = unifyPtrType(LLVMTy);
1686 return SpirvType;
1687}
1688
1690 MachineInstr &I,
1691 const SPIRVInstrInfo &TII,
1692 unsigned SPIRVOPcode,
1693 Type *Ty) {
1694 if (const MachineInstr *MI = findMI(Ty, false, CurMF))
1695 return MI;
1696 MachineBasicBlock &DepMBB = I.getMF()->front();
1697 MachineIRBuilder MIRBuilder(DepMBB, DepMBB.getFirstNonPHI());
1698 const MachineInstr *NewMI =
1699 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1700 return BuildMI(MIRBuilder.getMBB(), *MIRBuilder.getInsertPt(),
1701 MIRBuilder.getDL(), TII.get(SPIRVOPcode))
1702 .addDef(createTypeVReg(CurMF->getRegInfo()))
1704 .addImm(0);
1705 });
1706 add(Ty, false, NewMI);
1707 return finishCreatingSPIRVType(Ty, NewMI);
1708}
1709
1711 unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII) {
1712 // Maybe adjust bit width to keep DuplicateTracker consistent. Without
1713 // such an adjustment SPIRVGlobalRegistry::getOpTypeInt() could create, for
1714 // example, the same "OpTypeInt 8" type for a series of LLVM integer types
1715 // with number of bits less than 8, causing duplicate type definitions.
1716 if (BitWidth > 1)
1717 BitWidth = adjustOpTypeIntWidth(BitWidth);
1718 Type *LLVMTy = IntegerType::get(CurMF->getFunction().getContext(), BitWidth);
1719 return getOrCreateSPIRVType(BitWidth, I, TII, SPIRV::OpTypeInt, LLVMTy);
1720}
1721
1723 unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII) {
1724 LLVMContext &Ctx = CurMF->getFunction().getContext();
1725 Type *LLVMTy;
1726 switch (BitWidth) {
1727 case 16:
1728 LLVMTy = Type::getHalfTy(Ctx);
1729 break;
1730 case 32:
1731 LLVMTy = Type::getFloatTy(Ctx);
1732 break;
1733 case 64:
1734 LLVMTy = Type::getDoubleTy(Ctx);
1735 break;
1736 default:
1737 llvm_unreachable("Bit width is of unexpected size.");
1738 }
1739 return getOrCreateSPIRVType(BitWidth, I, TII, SPIRV::OpTypeFloat, LLVMTy);
1740}
1741
1742SPIRVType *
1744 bool EmitIR) {
1745 return getOrCreateSPIRVType(
1746 IntegerType::get(MIRBuilder.getMF().getFunction().getContext(), 1),
1747 MIRBuilder, SPIRV::AccessQualifier::ReadWrite, false, EmitIR);
1748}
1749
1750SPIRVType *
1752 const SPIRVInstrInfo &TII) {
1753 Type *Ty = IntegerType::get(CurMF->getFunction().getContext(), 1);
1754 if (const MachineInstr *MI = findMI(Ty, false, CurMF))
1755 return MI;
1756 MachineBasicBlock &DepMBB = I.getMF()->front();
1757 MachineIRBuilder MIRBuilder(DepMBB, DepMBB.getFirstNonPHI());
1758 const MachineInstr *NewMI =
1759 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1760 return BuildMI(MIRBuilder.getMBB(), *MIRBuilder.getInsertPt(),
1761 MIRBuilder.getDL(), TII.get(SPIRV::OpTypeBool))
1762 .addDef(createTypeVReg(CurMF->getRegInfo()));
1763 });
1764 add(Ty, false, NewMI);
1765 return finishCreatingSPIRVType(Ty, NewMI);
1766}
1767
1769 SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder,
1770 bool EmitIR) {
1771 return getOrCreateSPIRVType(
1773 NumElements),
1774 MIRBuilder, SPIRV::AccessQualifier::ReadWrite, false, EmitIR);
1775}
1776
1778 SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
1779 const SPIRVInstrInfo &TII) {
1781 const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
1782 if (const MachineInstr *MI = findMI(Ty, false, CurMF))
1783 return MI;
1784 MachineInstr *DepMI = const_cast<MachineInstr *>(BaseType);
1785 MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());
1786 const MachineInstr *NewMI =
1787 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1788 return BuildMI(MIRBuilder.getMBB(), *MIRBuilder.getInsertPt(),
1789 MIRBuilder.getDL(), TII.get(SPIRV::OpTypeVector))
1790 .addDef(createTypeVReg(CurMF->getRegInfo()))
1792 .addImm(NumElements);
1793 });
1794 add(Ty, false, NewMI);
1795 return finishCreatingSPIRVType(Ty, NewMI);
1796}
1797
1799 const Type *BaseType, MachineInstr &I,
1800 SPIRV::StorageClass::StorageClass SC) {
1801 MachineIRBuilder MIRBuilder(I);
1802 return getOrCreateSPIRVPointerType(BaseType, MIRBuilder, SC);
1803}
1804
1806 const Type *BaseType, MachineIRBuilder &MIRBuilder,
1807 SPIRV::StorageClass::StorageClass SC) {
1808 // TODO: Need to check if EmitIr should always be true.
1809 SPIRVType *SpirvBaseType = getOrCreateSPIRVType(
1810 BaseType, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
1812 assert(SpirvBaseType);
1813 return getOrCreateSPIRVPointerTypeInternal(SpirvBaseType, MIRBuilder, SC);
1814}
1815
1817 SPIRVType *PtrType, SPIRV::StorageClass::StorageClass SC, MachineInstr &I) {
1818 [[maybe_unused]] SPIRV::StorageClass::StorageClass OldSC =
1819 getPointerStorageClass(PtrType);
1822
1823 SPIRVType *PointeeType = getPointeeType(PtrType);
1824 MachineIRBuilder MIRBuilder(I);
1825 return getOrCreateSPIRVPointerTypeInternal(PointeeType, MIRBuilder, SC);
1826}
1827
1829 SPIRVType *BaseType, MachineIRBuilder &MIRBuilder,
1830 SPIRV::StorageClass::StorageClass SC) {
1831 const Type *LLVMType = getTypeForSPIRVType(BaseType);
1833 SPIRVType *R = getOrCreateSPIRVPointerType(LLVMType, MIRBuilder, SC);
1834 assert(
1835 getPointeeType(R) == BaseType &&
1836 "The base type was not correctly laid out for the given storage class.");
1837 return R;
1838}
1839
1840SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVPointerTypeInternal(
1841 SPIRVType *BaseType, MachineIRBuilder &MIRBuilder,
1842 SPIRV::StorageClass::StorageClass SC) {
1843 const Type *PointerElementType = getTypeForSPIRVType(BaseType);
1845 if (const MachineInstr *MI = findMI(PointerElementType, AddressSpace, CurMF))
1846 return MI;
1847 Type *Ty = TypedPointerType::get(const_cast<Type *>(PointerElementType),
1848 AddressSpace);
1849 const MachineInstr *NewMI =
1850 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1851 return BuildMI(MIRBuilder.getMBB(), MIRBuilder.getInsertPt(),
1852 MIRBuilder.getDebugLoc(),
1853 MIRBuilder.getTII().get(SPIRV::OpTypePointer))
1855 .addImm(static_cast<uint32_t>(SC))
1857 });
1858 add(PointerElementType, AddressSpace, NewMI);
1859 return finishCreatingSPIRVType(Ty, NewMI);
1860}
1861
1863 SPIRVType *SpvType,
1864 const SPIRVInstrInfo &TII) {
1865 UndefValue *UV =
1866 UndefValue::get(const_cast<Type *>(getTypeForSPIRVType(SpvType)));
1867 Register Res = find(UV, CurMF);
1868 if (Res.isValid())
1869 return Res;
1870
1871 LLT LLTy = LLT::scalar(64);
1872 Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
1873 CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
1874 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
1875
1876 MachineInstr *DepMI = const_cast<MachineInstr *>(SpvType);
1877 MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());
1878 const MachineInstr *NewMI =
1879 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1880 auto MIB = BuildMI(MIRBuilder.getMBB(), *MIRBuilder.getInsertPt(),
1881 MIRBuilder.getDL(), TII.get(SPIRV::OpUndef))
1882 .addDef(Res)
1883 .addUse(getSPIRVTypeID(SpvType));
1884 const auto &ST = CurMF->getSubtarget();
1885 constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
1886 *ST.getRegisterInfo(),
1887 *ST.getRegBankInfo());
1888 return MIB;
1889 });
1890 add(UV, NewMI);
1891 return Res;
1892}
1893
1894const TargetRegisterClass *
1896 unsigned Opcode = SpvType->getOpcode();
1897 switch (Opcode) {
1898 case SPIRV::OpTypeFloat:
1899 return &SPIRV::fIDRegClass;
1900 case SPIRV::OpTypePointer:
1901 return &SPIRV::pIDRegClass;
1902 case SPIRV::OpTypeVector: {
1903 SPIRVType *ElemType = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
1904 unsigned ElemOpcode = ElemType ? ElemType->getOpcode() : 0;
1905 if (ElemOpcode == SPIRV::OpTypeFloat)
1906 return &SPIRV::vfIDRegClass;
1907 if (ElemOpcode == SPIRV::OpTypePointer)
1908 return &SPIRV::vpIDRegClass;
1909 return &SPIRV::vIDRegClass;
1910 }
1911 }
1912 return &SPIRV::iIDRegClass;
1913}
1914
1915inline unsigned getAS(SPIRVType *SpvType) {
1917 static_cast<SPIRV::StorageClass::StorageClass>(
1918 SpvType->getOperand(1).getImm()));
1919}
1920
1922 unsigned Opcode = SpvType ? SpvType->getOpcode() : 0;
1923 switch (Opcode) {
1924 case SPIRV::OpTypeInt:
1925 case SPIRV::OpTypeFloat:
1926 case SPIRV::OpTypeBool:
1927 return LLT::scalar(getScalarOrVectorBitWidth(SpvType));
1928 case SPIRV::OpTypePointer:
1929 return LLT::pointer(getAS(SpvType), getPointerSize());
1930 case SPIRV::OpTypeVector: {
1931 SPIRVType *ElemType = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
1932 LLT ET;
1933 switch (ElemType ? ElemType->getOpcode() : 0) {
1934 case SPIRV::OpTypePointer:
1935 ET = LLT::pointer(getAS(ElemType), getPointerSize());
1936 break;
1937 case SPIRV::OpTypeInt:
1938 case SPIRV::OpTypeFloat:
1939 case SPIRV::OpTypeBool:
1940 ET = LLT::scalar(getScalarOrVectorBitWidth(ElemType));
1941 break;
1942 default:
1943 ET = LLT::scalar(64);
1944 }
1945 return LLT::fixed_vector(
1946 static_cast<unsigned>(SpvType->getOperand(2).getImm()), ET);
1947 }
1948 }
1949 return LLT::scalar(64);
1950}
1951
1952// Aliasing list MD contains several scope MD nodes whithin it. Each scope MD
1953// has a selfreference and an extra MD node for aliasing domain and also it
1954// can contain an optional string operand. Domain MD contains a self-reference
1955// with an optional string operand. Here we unfold the list, creating SPIR-V
1956// aliasing instructions.
1957// TODO: add support for an optional string operand.
1959 MachineIRBuilder &MIRBuilder, const MDNode *AliasingListMD) {
1960 if (AliasingListMD->getNumOperands() == 0)
1961 return nullptr;
1962 if (auto L = AliasInstMDMap.find(AliasingListMD); L != AliasInstMDMap.end())
1963 return L->second;
1964
1966 MachineRegisterInfo *MRI = MIRBuilder.getMRI();
1967 for (const MDOperand &MDListOp : AliasingListMD->operands()) {
1968 if (MDNode *ScopeMD = dyn_cast<MDNode>(MDListOp)) {
1969 if (ScopeMD->getNumOperands() < 2)
1970 return nullptr;
1971 MDNode *DomainMD = dyn_cast<MDNode>(ScopeMD->getOperand(1));
1972 if (!DomainMD)
1973 return nullptr;
1974 auto *Domain = [&] {
1975 auto D = AliasInstMDMap.find(DomainMD);
1976 if (D != AliasInstMDMap.end())
1977 return D->second;
1978 const Register Ret = MRI->createVirtualRegister(&SPIRV::IDRegClass);
1979 auto MIB =
1980 MIRBuilder.buildInstr(SPIRV::OpAliasDomainDeclINTEL).addDef(Ret);
1981 return MIB.getInstr();
1982 }();
1983 AliasInstMDMap.insert(std::make_pair(DomainMD, Domain));
1984 auto *Scope = [&] {
1985 auto S = AliasInstMDMap.find(ScopeMD);
1986 if (S != AliasInstMDMap.end())
1987 return S->second;
1988 const Register Ret = MRI->createVirtualRegister(&SPIRV::IDRegClass);
1989 auto MIB = MIRBuilder.buildInstr(SPIRV::OpAliasScopeDeclINTEL)
1990 .addDef(Ret)
1991 .addUse(Domain->getOperand(0).getReg());
1992 return MIB.getInstr();
1993 }();
1994 AliasInstMDMap.insert(std::make_pair(ScopeMD, Scope));
1995 ScopeList.push_back(Scope);
1996 }
1997 }
1998
1999 const Register Ret = MRI->createVirtualRegister(&SPIRV::IDRegClass);
2000 auto MIB =
2001 MIRBuilder.buildInstr(SPIRV::OpAliasScopeListDeclINTEL).addDef(Ret);
2002 for (auto *Scope : ScopeList)
2003 MIB.addUse(Scope->getOperand(0).getReg());
2004 auto List = MIB.getInstr();
2005 AliasInstMDMap.insert(std::make_pair(AliasingListMD, List));
2006 return List;
2007}
2008
2010 Register Reg, MachineIRBuilder &MIRBuilder, uint32_t Dec,
2011 const MDNode *AliasingListMD) {
2012 MachineInstr *AliasList =
2013 getOrAddMemAliasingINTELInst(MIRBuilder, AliasingListMD);
2014 if (!AliasList)
2015 return;
2016 MIRBuilder.buildInstr(SPIRV::OpDecorate)
2017 .addUse(Reg)
2018 .addImm(Dec)
2019 .addUse(AliasList->getOperand(0).getReg());
2020}
2022 bool DeleteOld) {
2023 Old->replaceAllUsesWith(New);
2024 updateIfExistDeducedElementType(Old, New, DeleteOld);
2025 updateIfExistAssignPtrTypeInstr(Old, New, DeleteOld);
2026}
2027
2029 Value *Arg) {
2030 Value *OfType = getNormalizedPoisonValue(Ty);
2031 CallInst *AssignCI = nullptr;
2032 if (Arg->getType()->isAggregateType() && Ty->isAggregateType() &&
2033 allowEmitFakeUse(Arg)) {
2034 LLVMContext &Ctx = Arg->getContext();
2037 MDString::get(Ctx, Arg->getName())};
2038 B.CreateIntrinsic(Intrinsic::spv_value_md,
2039 {MetadataAsValue::get(Ctx, MDTuple::get(Ctx, ArgMDs))});
2040 AssignCI = B.CreateIntrinsic(Intrinsic::fake_use, {Arg});
2041 } else {
2042 AssignCI = buildIntrWithMD(Intrinsic::spv_assign_type, {Arg->getType()},
2043 OfType, Arg, {}, B);
2044 }
2045 addAssignPtrTypeInstr(Arg, AssignCI);
2046}
2047
2049 Value *Arg) {
2050 Value *OfType = PoisonValue::get(ElemTy);
2051 CallInst *AssignPtrTyCI = findAssignPtrTypeInstr(Arg);
2052 Function *CurrF =
2053 B.GetInsertBlock() ? B.GetInsertBlock()->getParent() : nullptr;
2054 if (AssignPtrTyCI == nullptr ||
2055 AssignPtrTyCI->getParent()->getParent() != CurrF) {
2056 AssignPtrTyCI = buildIntrWithMD(
2057 Intrinsic::spv_assign_ptr_type, {Arg->getType()}, OfType, Arg,
2058 {B.getInt32(getPointerAddressSpace(Arg->getType()))}, B);
2059 addDeducedElementType(AssignPtrTyCI, ElemTy);
2060 addDeducedElementType(Arg, ElemTy);
2061 addAssignPtrTypeInstr(Arg, AssignPtrTyCI);
2062 } else {
2063 updateAssignType(AssignPtrTyCI, Arg, OfType);
2064 }
2065}
2066
2068 Value *OfType) {
2069 AssignCI->setArgOperand(1, buildMD(OfType));
2070 if (cast<IntrinsicInst>(AssignCI)->getIntrinsicID() !=
2071 Intrinsic::spv_assign_ptr_type)
2072 return;
2073
2074 // update association with the pointee type
2075 Type *ElemTy = OfType->getType();
2076 addDeducedElementType(AssignCI, ElemTy);
2077 addDeducedElementType(Arg, ElemTy);
2078}
2079
2080void SPIRVGlobalRegistry::addStructOffsetDecorations(
2081 Register Reg, StructType *Ty, MachineIRBuilder &MIRBuilder) {
2082 DataLayout DL;
2083 ArrayRef<TypeSize> Offsets = DL.getStructLayout(Ty)->getMemberOffsets();
2084 for (uint32_t I = 0; I < Ty->getNumElements(); ++I) {
2085 buildOpMemberDecorate(Reg, MIRBuilder, SPIRV::Decoration::Offset, I,
2086 {static_cast<uint32_t>(Offsets[I])});
2087 }
2088}
2089
2090void SPIRVGlobalRegistry::addArrayStrideDecorations(
2091 Register Reg, Type *ElementType, MachineIRBuilder &MIRBuilder) {
2092 uint32_t SizeInBytes = DataLayout().getTypeSizeInBits(ElementType) / 8;
2093 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::ArrayStride,
2094 {SizeInBytes});
2095}
2096
2097bool SPIRVGlobalRegistry::hasBlockDecoration(SPIRVType *Type) const {
2099 for (const MachineInstr &Use :
2100 Type->getMF()->getRegInfo().use_instructions(Def)) {
2101 if (Use.getOpcode() != SPIRV::OpDecorate)
2102 continue;
2103
2104 if (Use.getOperand(1).getImm() == SPIRV::Decoration::Block)
2105 return true;
2106 }
2107 return false;
2108}
unsigned const MachineRegisterInfo * MRI
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis false
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:58
mir Rename Register Operands
Register Reg
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define T
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
static unsigned getNumElements(Type *Ty)
static bool storageClassRequiresExplictLayout(SPIRV::StorageClass::StorageClass SC)
static Register createTypeVReg(MachineRegisterInfo &MRI)
unsigned getAS(SPIRVType *SpvType)
static bool allowEmitFakeUse(const Value *Arg)
static unsigned typeToAddressSpace(const Type *Ty)
APInt bitcastToAPInt() const
Definition APFloat.h:1353
bool isPosZero() const
Definition APFloat.h:1460
Class for arbitrary precision integers.
Definition APInt.h:78
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1540
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
Class to represent array types.
uint64_t getNumElements() const
Type * getElementType() const
void setArgOperand(unsigned i, Value *v)
This class represents a function call, abstracting a target machine's calling convention.
ConstantFP - Floating Point Values [float, double].
Definition Constants.h:277
const APFloat & getValue() const
Definition Constants.h:321
const APFloat & getValueAPF() const
Definition Constants.h:320
This is the shared class of boolean and integer constants.
Definition Constants.h:87
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
Definition Constants.h:214
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition Constants.h:163
static Constant * getAnon(ArrayRef< Constant * > V, bool Packed=false)
Return an anonymous struct that has the specified elements.
Definition Constants.h:486
static LLVM_ABI ConstantTargetNone * get(TargetExtType *T)
Static factory methods - Return objects of the specified value.
static LLVM_ABI Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
This is an important base class in LLVM.
Definition Constant.h:43
LLVM_ABI const APInt & getUniqueInteger() const
If C is a constant integer then return its value, otherwise C must be a vector of constant integers,...
LLVM_ABI bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
Definition Constants.cpp:90
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:63
Class to represent fixed width SIMD vectors.
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:803
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:359
MDNode * getMetadata(unsigned KindID) const
Get the current metadata attachments for the given kind, if any.
Definition Value.h:576
Module * getParent()
Get the module that this global value is contained inside of...
@ ExternalLinkage
Externally visible function.
Definition GlobalValue.h:53
MaybeAlign getAlign() const
Returns the alignment of the given variable.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2780
Class to represent integer types.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition Type.cpp:319
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition MCInstrInfo.h:64
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
Metadata node.
Definition Metadata.h:1077
ArrayRef< MDOperand > operands() const
Definition Metadata.h:1443
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1565
unsigned getNumOperands() const
Return number of MDNode operands.
Definition Metadata.h:1451
Tracking metadata reference owned by Metadata.
Definition Metadata.h:899
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
Definition Metadata.cpp:607
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1522
LLVM_ABI iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
MachineInstrBundleIterator< MachineInstr > iterator
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Helper class to build MachineInstr.
void setInsertPt(MachineBasicBlock &MBB, MachineBasicBlock::iterator II)
Set the insertion point before the specified position.
LLVMContext & getContext() const
const TargetInstrInfo & getTII()
MachineBasicBlock::iterator getInsertPt()
Current insertion point for new instructions.
MachineInstrBuilder buildSplatBuildVector(const DstOp &Res, const SrcOp &Src)
Build and insert Res = G_BUILD_VECTOR with Src replicated to fill the number of elements.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
const DebugLoc & getDL()
Getter for DebugLoc.
MachineFunction & getMF()
Getter for the function we currently build.
const MachineBasicBlock & getMBB() const
Getter for the basic block we currently build.
const DebugLoc & getDebugLoc()
Get the current instruction's debug location.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
mop_range defs()
Returns all explicit operands that are register definitions.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
LLVM_ABI void insert(mop_iterator InsertBefore, ArrayRef< MachineOperand > Ops)
Inserts Ops BEFORE It. Can untie/retie tied operands.
mop_range uses()
Returns all operands which may be register uses.
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
int64_t getImm() const
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
static LLVM_ABI MetadataAsValue * get(LLVMContext &Context, Metadata *MD)
Definition Metadata.cpp:103
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Wrapper class representing virtual and physical registers.
Definition Register.h:19
constexpr bool isValid() const
Definition Register.h:107
SPIRVType * getOrCreateOpTypePipe(MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AccQual)
unsigned getNumScalarOrVectorTotalBitWidth(const SPIRVType *Type) const
SPIRVType * getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
Register getOrCreateConstInt(uint64_t Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII, bool ZeroAsNull=true)
SPIRVType * getResultType(Register VReg, MachineFunction *MF=nullptr)
void addAssignPtrTypeInstr(Value *Val, CallInst *AssignPtrTyCI)
SPIRVType * getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder, bool EmitIR)
void buildAssignPtr(IRBuilder<> &B, Type *ElemTy, Value *Arg)
SPIRVType * assignFloatTypeToVReg(unsigned BitWidth, Register VReg, MachineInstr &I, const SPIRVInstrInfo &TII)
MachineInstr * getOrAddMemAliasingINTELInst(MachineIRBuilder &MIRBuilder, const MDNode *AliasingListMD)
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, const MachineFunction &MF)
SPIRVType * assignVectTypeToVReg(SPIRVType *BaseType, unsigned NumElements, Register VReg, MachineInstr &I, const SPIRVInstrInfo &TII)
Register getOrCreateUndef(MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
void replaceAllUsesWith(Value *Old, Value *New, bool DeleteOld=true)
SPIRVType * changePointerStorageClass(SPIRVType *PtrType, SPIRV::StorageClass::StorageClass SC, MachineInstr &I)
const Type * getTypeForSPIRVType(const SPIRVType *Ty) const
SPIRVType * getOrCreateUnknownType(const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode, const ArrayRef< MCOperand > Operands)
bool isBitcastCompatible(const SPIRVType *Type1, const SPIRVType *Type2) const
unsigned getScalarOrVectorComponentCount(Register VReg) const
Register createConstInt(const ConstantInt *CI, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII, bool ZeroAsNull)
SPIRVType * getOrCreateSPIRVFloatType(unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII)
bool isScalarOrVectorSigned(const SPIRVType *Type) const
void addDeducedElementType(Value *Val, Type *Ty)
SPIRVGlobalRegistry(unsigned PointerSize)
Register getOrCreateGlobalVariableWithBinding(const SPIRVType *VarType, uint32_t Set, uint32_t Binding, StringRef Name, MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateSPIRVType(const Type *Type, MachineInstr &I, SPIRV::AccessQualifier::AccessQualifier AQ, bool EmitIR)
SPIRVType * getOrCreateSPIRVPointerType(const Type *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SC)
SPIRVType * getOrCreateOpTypeByOpcode(const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode)
Register buildConstantFP(APFloat Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType=nullptr)
SPIRVType * getPointeeType(SPIRVType *PtrType)
void invalidateMachineInstr(MachineInstr *MI)
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
Register createConstFP(const ConstantFP *CF, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII, bool ZeroAsNull)
void updateIfExistDeducedElementType(Value *OldVal, Value *NewVal, bool DeleteOld)
bool isScalarOfType(Register VReg, unsigned TypeOpcode) const
Register buildGlobalVariable(Register Reg, SPIRVType *BaseType, StringRef Name, const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage, const MachineInstr *Init, bool IsConst, bool HasLinkageTy, SPIRV::LinkageType::LinkageType LinkageType, MachineIRBuilder &MIRBuilder, bool IsInstSelector)
SPIRVType * assignIntTypeToVReg(unsigned BitWidth, Register VReg, MachineInstr &I, const SPIRVInstrInfo &TII)
unsigned getPointeeTypeOp(Register PtrReg)
SPIRVType * getOrCreateOpTypeSampledImage(SPIRVType *ImageType, MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateVulkanBufferType(MachineIRBuilder &MIRBuilder, Type *ElemType, SPIRV::StorageClass::StorageClass SC, bool IsWritable, bool EmitIr=false)
SPIRVType * getOrCreateSPIRVTypeByName(StringRef TypeStr, MachineIRBuilder &MIRBuilder, bool EmitIR, SPIRV::StorageClass::StorageClass SC=SPIRV::StorageClass::Function, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite)
SPIRVType * getOrCreateLayoutType(MachineIRBuilder &MIRBuilder, const TargetExtType *T, bool EmitIr=false)
void addGlobalObject(const Value *V, const MachineFunction *MF, Register R)
SPIRVType * getScalarOrVectorComponentType(Register VReg) const
SPIRVType * getOrCreateOpTypeFunctionWithArgs(const Type *Ty, SPIRVType *RetType, const SmallVectorImpl< SPIRVType * > &ArgTypes, MachineIRBuilder &MIRBuilder)
void buildAssignType(IRBuilder<> &B, Type *Ty, Value *Arg)
Register getOrCreateConsIntVector(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR)
const TargetRegisterClass * getRegClass(SPIRVType *SpvType) const
void updateIfExistAssignPtrTypeInstr(Value *OldVal, Value *NewVal, bool DeleteOld)
SPIRVType * getOrCreateSPIRVVectorType(SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder, bool EmitIR)
SPIRVType * getOrCreateOpTypeCoopMatr(MachineIRBuilder &MIRBuilder, const TargetExtType *ExtensionType, const SPIRVType *ElemType, uint32_t Scope, uint32_t Rows, uint32_t Columns, uint32_t Use, bool EmitIR)
bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const
Register getOrCreateConstIntArray(uint64_t Val, size_t Num, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
Register getOrCreateConstVector(uint64_t Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII, bool ZeroAsNull=true)
SPIRVType * getOrCreateOpTypeDeviceEvent(MachineIRBuilder &MIRBuilder)
SPIRVType * getImageType(const TargetExtType *ExtensionType, const SPIRV::AccessQualifier::AccessQualifier Qualifier, MachineIRBuilder &MIRBuilder)
bool isResourceType(SPIRVType *Type) const
SPIRVType * getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
Register buildConstantInt(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR, bool ZeroAsNull=true)
SPIRVType * assignTypeToVReg(const Type *Type, Register VReg, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AQ, bool EmitIR)
LLT getRegType(SPIRVType *SpvType) const
void buildMemAliasingOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, uint32_t Dec, const MDNode *GVarMD)
SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const
SPIRVType * getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder)
Register buildConstantSampler(Register Res, unsigned AddrMode, unsigned Param, unsigned FilerMode, MachineIRBuilder &MIRBuilder)
void updateAssignType(CallInst *AssignCI, Value *Arg, Value *OfType)
Register getOrCreateConstFP(APFloat Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII, bool ZeroAsNull=true)
CallInst * findAssignPtrTypeInstr(const Value *Val)
Register getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder, SPIRVType *SpvType)
unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) const
const SPIRVType * retrieveScalarOrVectorIntType(const SPIRVType *Type) const
const MachineInstr * findMI(SPIRV::IRHandle Handle, const MachineFunction *MF)
bool erase(const MachineInstr *MI)
bool add(SPIRV::IRHandle Handle, const MachineInstr *MI)
Register find(SPIRV::IRHandle Handle, const MachineFunction *MF)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
Definition StringRef.h:665
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition StringRef.h:480
std::string str() const
str - Get the contents as an std::string.
Definition StringRef.h:233
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:581
bool consume_front(StringRef Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
Definition StringRef.h:645
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition StringRef.h:301
Class to represent struct types.
ArrayRef< Type * > elements() const
static LLVM_ABI StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition Type.cpp:620
bool isPacked() const
unsigned getNumElements() const
Random access to the elements.
bool hasName() const
Return true if this is a named struct that has a non-empty name.
LLVM_ABI StringRef getName() const
Return the name for this struct type if it has an identity.
Definition Type.cpp:697
Class to represent target extensions types, which are generally unintrospectable from target-independ...
unsigned getNumIntParameters() const
Type * getTypeParameter(unsigned i) const
unsigned getNumTypeParameters() const
unsigned getIntParameter(unsigned i) const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
LLVM_ABI unsigned getIntegerBitWidth() const
bool isVectorTy() const
True if this is an instance of VectorType.
Definition Type.h:273
bool isArrayTy() const
True if this is an instance of ArrayType.
Definition Type.h:264
Type * getArrayElementType() const
Definition Type.h:408
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
Definition Type.h:145
LLVM_ABI uint64_t getArrayNumElements() const
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Definition Type.cpp:295
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Definition Type.cpp:198
bool isAggregateType() const
Return true if the type is an aggregate type.
Definition Type.h:304
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition Type.h:184
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:240
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
Definition Type.cpp:286
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
Definition Type.cpp:285
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
Definition Type.cpp:283
bool isVoidTy() const
Return true if this is 'void'.
Definition Type.h:139
static LLVM_ABI TypedPointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
'undef' values are things that do not have specified contents.
Definition Constants.h:1420
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
static ConstantAsMetadata * getConstant(Value *C)
Definition Metadata.h:479
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:256
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:546
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.cpp:1101
bool hasName() const
Definition Value.h:262
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:322
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
Type * getElementType() const
const ParentTy * getParent() const
Definition ilist_node.h:34
self_iterator getIterator()
Definition ilist_node.h:134
IteratorT begin() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
IRHandle handle(const Type *Ty)
IRHandle irhandle_sampled_image(const Type *SampledTy, const MachineInstr *ImageTy)
IRHandle irhandle_vkbuffer(const Type *ElementType, StorageClass::StorageClass SC, bool IsWriteable)
IRHandle irhandle_sampler()
TargetExtType * parseBuiltinTypeNameToTargetExtType(std::string TypeName, LLVMContext &Context)
Translates a string representing a SPIR-V or OpenCL builtin type to a TargetExtType that can be furth...
SPIRVType * lowerBuiltinType(const Type *OpaqueType, SPIRV::AccessQualifier::AccessQualifier AccessQual, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
IRHandle irhandle_event()
IRHandle irhandle_pipe(uint8_t AQ)
IRHandle irhandle_image(const Type *SampledTy, unsigned Dim, unsigned Depth, unsigned Arrayed, unsigned MS, unsigned Sampled, unsigned ImageFormat, unsigned AQ=0)
NodeAddr< DefNode * > Def
Definition RDFGraph.h:384
NodeAddr< UseNode * > Use
Definition RDFGraph.h:385
This is an optimization pass for GlobalISel generic memory operations.
void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)
bool isTypedPointerWrapper(const TargetExtType *ExtTy)
Definition SPIRVUtils.h:330
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
unsigned getPointerAddressSpace(const Type *T)
Definition SPIRVUtils.h:294
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:649
void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB)
LLVM_ABI bool constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
Definition Utils.cpp:155
CallInst * buildIntrWithMD(Intrinsic::ID IntrID, ArrayRef< Type * > Types, Value *Arg, Value *Arg2, ArrayRef< Constant * > Imms, IRBuilder<> &B)
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
Definition Error.cpp:177
constexpr unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
Definition SPIRVUtils.h:191
bool getSpirvBuiltInIdByName(llvm::StringRef Name, SPIRV::BuiltIn::BuiltIn &BI)
MetadataAsValue * buildMD(Value *Arg)
Definition SPIRVUtils.h:440
bool isTypedPointerTy(const Type *T)
Definition SPIRVUtils.h:278
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
Type * getTypedPointerWrapper(Type *ElemTy, unsigned AS)
Definition SPIRVUtils.h:325
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:288
void buildOpMemberDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, uint32_t Member, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
Type * toTypedPointer(Type *Ty)
Definition SPIRVUtils.h:385
bool isSpecialOpaqueType(const Type *Ty)
bool isPointerTy(const Type *T)
Definition SPIRVUtils.h:288
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
MachineBasicBlock::iterator getInsertPtValidEnd(MachineBasicBlock *MBB)
const Type * unifyPtrType(const Type *Ty)
Definition SPIRVUtils.h:412
const MachineInstr SPIRVType
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:548
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
std::function< void(Register)> StructOffsetDecorator
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
Type * parseBasicTypeName(StringRef &TypeName, LLVMContext &Ctx)
DWARFExpression::Operation Op
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:565
bool hasBuiltinTypePrefix(StringRef Name)
bool isPointerTyOrWrapper(const Type *Ty)
Definition SPIRVUtils.h:337
bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID)
PoisonValue * getNormalizedPoisonValue(Type *Ty)
Definition SPIRVUtils.h:436
void addStringImm(const StringRef &Str, MCInst &Inst)
MachineInstr * getVRegDef(MachineRegisterInfo &MRI, Register Reg)
void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder, const MDNode *GVarMD)
uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:85
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
Definition Alignment.h:141