LLVM 19.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 "SPIRVTargetMachine.h"
22#include "SPIRVUtils.h"
23
24using namespace llvm;
26 : PointerSize(PointerSize) {}
27
29 Register VReg,
31 const SPIRVInstrInfo &TII) {
33 assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
34 return SpirvType;
35}
36
38 SPIRVType *BaseType, unsigned NumElements, Register VReg, MachineInstr &I,
39 const SPIRVInstrInfo &TII) {
40 SPIRVType *SpirvType =
42 assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
43 return SpirvType;
44}
45
47 const Type *Type, Register VReg, MachineIRBuilder &MIRBuilder,
48 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
49
50 SPIRVType *SpirvType =
51 getOrCreateSPIRVType(Type, MIRBuilder, AccessQual, EmitIR);
52 assignSPIRVTypeToVReg(SpirvType, VReg, MIRBuilder.getMF());
53 return SpirvType;
54}
55
57 Register VReg,
58 MachineFunction &MF) {
59 VRegToTypeMap[&MF][VReg] = SpirvType;
60}
61
63 auto &MRI = MIRBuilder.getMF().getRegInfo();
64 auto Res = MRI.createGenericVirtualRegister(LLT::scalar(32));
65 MRI.setRegClass(Res, &SPIRV::TYPERegClass);
66 return Res;
67}
68
70 auto Res = MRI.createGenericVirtualRegister(LLT::scalar(32));
71 MRI.setRegClass(Res, &SPIRV::TYPERegClass);
72 return Res;
73}
74
75SPIRVType *SPIRVGlobalRegistry::getOpTypeBool(MachineIRBuilder &MIRBuilder) {
76 return MIRBuilder.buildInstr(SPIRV::OpTypeBool)
77 .addDef(createTypeVReg(MIRBuilder));
78}
79
80SPIRVType *SPIRVGlobalRegistry::getOpTypeInt(uint32_t Width,
81 MachineIRBuilder &MIRBuilder,
82 bool IsSigned) {
83 assert(Width <= 64 && "Unsupported integer width!");
84 const SPIRVSubtarget &ST =
85 cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget());
86 if (ST.canUseExtension(
87 SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers)) {
88 MIRBuilder.buildInstr(SPIRV::OpExtension)
89 .addImm(SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers);
90 MIRBuilder.buildInstr(SPIRV::OpCapability)
91 .addImm(SPIRV::Capability::ArbitraryPrecisionIntegersINTEL);
92 } else if (Width <= 8)
93 Width = 8;
94 else if (Width <= 16)
95 Width = 16;
96 else if (Width <= 32)
97 Width = 32;
98 else if (Width <= 64)
99 Width = 64;
100
101 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeInt)
102 .addDef(createTypeVReg(MIRBuilder))
103 .addImm(Width)
104 .addImm(IsSigned ? 1 : 0);
105 return MIB;
106}
107
108SPIRVType *SPIRVGlobalRegistry::getOpTypeFloat(uint32_t Width,
109 MachineIRBuilder &MIRBuilder) {
110 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFloat)
111 .addDef(createTypeVReg(MIRBuilder))
112 .addImm(Width);
113 return MIB;
114}
115
116SPIRVType *SPIRVGlobalRegistry::getOpTypeVoid(MachineIRBuilder &MIRBuilder) {
117 return MIRBuilder.buildInstr(SPIRV::OpTypeVoid)
118 .addDef(createTypeVReg(MIRBuilder));
119}
120
121SPIRVType *SPIRVGlobalRegistry::getOpTypeVector(uint32_t NumElems,
122 SPIRVType *ElemType,
123 MachineIRBuilder &MIRBuilder) {
124 auto EleOpc = ElemType->getOpcode();
125 assert((EleOpc == SPIRV::OpTypeInt || EleOpc == SPIRV::OpTypeFloat ||
126 EleOpc == SPIRV::OpTypeBool) &&
127 "Invalid vector element type");
128
129 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeVector)
130 .addDef(createTypeVReg(MIRBuilder))
131 .addUse(getSPIRVTypeID(ElemType))
132 .addImm(NumElems);
133 return MIB;
134}
135
136std::tuple<Register, ConstantInt *, bool>
137SPIRVGlobalRegistry::getOrCreateConstIntReg(uint64_t Val, SPIRVType *SpvType,
138 MachineIRBuilder *MIRBuilder,
140 const SPIRVInstrInfo *TII) {
141 const IntegerType *LLVMIntTy;
142 if (SpvType)
143 LLVMIntTy = cast<IntegerType>(getTypeForSPIRVType(SpvType));
144 else
146 bool NewInstr = false;
147 // Find a constant in DT or build a new one.
148 ConstantInt *CI = ConstantInt::get(const_cast<IntegerType *>(LLVMIntTy), Val);
149 Register Res = DT.find(CI, CurMF);
150 if (!Res.isValid()) {
151 unsigned BitWidth = SpvType ? getScalarOrVectorBitWidth(SpvType) : 32;
152 LLT LLTy = LLT::scalar(32);
154 CurMF->getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
155 if (MIRBuilder)
156 assignTypeToVReg(LLVMIntTy, Res, *MIRBuilder);
157 else
159 DT.add(CI, CurMF, Res);
160 NewInstr = true;
161 }
162 return std::make_tuple(Res, CI, NewInstr);
163}
164
166 SPIRVType *SpvType,
167 const SPIRVInstrInfo &TII) {
168 assert(SpvType);
169 ConstantInt *CI;
170 Register Res;
171 bool New;
172 std::tie(Res, CI, New) =
173 getOrCreateConstIntReg(Val, SpvType, nullptr, &I, &TII);
174 // If we have found Res register which is defined by the passed G_CONSTANT
175 // machine instruction, a new constant instruction should be created.
176 if (!New && (!I.getOperand(0).isReg() || Res != I.getOperand(0).getReg()))
177 return Res;
179 MachineBasicBlock &BB = *I.getParent();
180 if (Val) {
181 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantI))
182 .addDef(Res)
183 .addUse(getSPIRVTypeID(SpvType));
184 addNumImm(APInt(getScalarOrVectorBitWidth(SpvType), Val), MIB);
185 } else {
186 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
187 .addDef(Res)
188 .addUse(getSPIRVTypeID(SpvType));
189 }
190 const auto &ST = CurMF->getSubtarget();
191 constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
192 *ST.getRegisterInfo(), *ST.getRegBankInfo());
193 return Res;
194}
195
197 MachineIRBuilder &MIRBuilder,
198 SPIRVType *SpvType,
199 bool EmitIR) {
200 auto &MF = MIRBuilder.getMF();
201 const IntegerType *LLVMIntTy;
202 if (SpvType)
203 LLVMIntTy = cast<IntegerType>(getTypeForSPIRVType(SpvType));
204 else
205 LLVMIntTy = IntegerType::getInt32Ty(MF.getFunction().getContext());
206 // Find a constant in DT or build a new one.
207 const auto ConstInt =
208 ConstantInt::get(const_cast<IntegerType *>(LLVMIntTy), Val);
209 Register Res = DT.find(ConstInt, &MF);
210 if (!Res.isValid()) {
211 unsigned BitWidth = SpvType ? getScalarOrVectorBitWidth(SpvType) : 32;
212 LLT LLTy = LLT::scalar(EmitIR ? BitWidth : 32);
213 Res = MF.getRegInfo().createGenericVirtualRegister(LLTy);
214 MF.getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
215 assignTypeToVReg(LLVMIntTy, Res, MIRBuilder,
216 SPIRV::AccessQualifier::ReadWrite, EmitIR);
217 DT.add(ConstInt, &MIRBuilder.getMF(), Res);
218 if (EmitIR) {
219 MIRBuilder.buildConstant(Res, *ConstInt);
220 } else {
222 if (Val) {
223 assert(SpvType);
224 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)
225 .addDef(Res)
226 .addUse(getSPIRVTypeID(SpvType));
227 addNumImm(APInt(BitWidth, Val), MIB);
228 } else {
229 assert(SpvType);
230 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
231 .addDef(Res)
232 .addUse(getSPIRVTypeID(SpvType));
233 }
234 const auto &Subtarget = CurMF->getSubtarget();
235 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
236 *Subtarget.getRegisterInfo(),
237 *Subtarget.getRegBankInfo());
238 }
239 }
240 return Res;
241}
242
244 MachineIRBuilder &MIRBuilder,
245 SPIRVType *SpvType) {
246 auto &MF = MIRBuilder.getMF();
247 auto &Ctx = MF.getFunction().getContext();
248 if (!SpvType) {
249 const Type *LLVMFPTy = Type::getFloatTy(Ctx);
250 SpvType = getOrCreateSPIRVType(LLVMFPTy, MIRBuilder);
251 }
252 // Find a constant in DT or build a new one.
253 const auto ConstFP = ConstantFP::get(Ctx, Val);
254 Register Res = DT.find(ConstFP, &MF);
255 if (!Res.isValid()) {
256 Res = MF.getRegInfo().createGenericVirtualRegister(LLT::scalar(32));
257 MF.getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
258 assignSPIRVTypeToVReg(SpvType, Res, MF);
259 DT.add(ConstFP, &MF, Res);
260
262 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantF)
263 .addDef(Res)
264 .addUse(getSPIRVTypeID(SpvType));
265 addNumImm(ConstFP->getValueAPF().bitcastToAPInt(), MIB);
266 }
267
268 return Res;
269}
270
271Register SPIRVGlobalRegistry::getOrCreateIntCompositeOrNull(
272 uint64_t Val, MachineInstr &I, SPIRVType *SpvType,
273 const SPIRVInstrInfo &TII, Constant *CA, unsigned BitWidth,
274 unsigned ElemCnt) {
275 // Find a constant vector in DT or build a new one.
276 Register Res = DT.find(CA, CurMF);
277 if (!Res.isValid()) {
279 // SpvScalConst should be created before SpvVecConst to avoid undefined ID
280 // error on validation.
281 // TODO: can moved below once sorting of types/consts/defs is implemented.
282 Register SpvScalConst;
283 if (Val)
284 SpvScalConst = getOrCreateConstInt(Val, I, SpvBaseType, TII);
285 // TODO: maybe use bitwidth of base type.
286 LLT LLTy = LLT::scalar(32);
287 Register SpvVecConst =
289 CurMF->getRegInfo().setRegClass(SpvVecConst, &SPIRV::IDRegClass);
290 assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
291 DT.add(CA, CurMF, SpvVecConst);
293 MachineBasicBlock &BB = *I.getParent();
294 if (Val) {
295 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantComposite))
296 .addDef(SpvVecConst)
297 .addUse(getSPIRVTypeID(SpvType));
298 for (unsigned i = 0; i < ElemCnt; ++i)
299 MIB.addUse(SpvScalConst);
300 } else {
301 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
302 .addDef(SpvVecConst)
303 .addUse(getSPIRVTypeID(SpvType));
304 }
305 const auto &Subtarget = CurMF->getSubtarget();
306 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
307 *Subtarget.getRegisterInfo(),
308 *Subtarget.getRegBankInfo());
309 return SpvVecConst;
310 }
311 return Res;
312}
313
316 SPIRVType *SpvType,
317 const SPIRVInstrInfo &TII) {
318 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
319 assert(LLVMTy->isVectorTy());
320 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
321 Type *LLVMBaseTy = LLVMVecTy->getElementType();
322 const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
323 auto ConstVec =
324 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstInt);
325 unsigned BW = getScalarOrVectorBitWidth(SpvType);
326 return getOrCreateIntCompositeOrNull(Val, I, SpvType, TII, ConstVec, BW,
327 SpvType->getOperand(2).getImm());
328}
329
332 SPIRVType *SpvType,
333 const SPIRVInstrInfo &TII) {
334 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
335 assert(LLVMTy->isArrayTy());
336 const ArrayType *LLVMArrTy = cast<ArrayType>(LLVMTy);
337 Type *LLVMBaseTy = LLVMArrTy->getElementType();
338 const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
339 auto ConstArr =
340 ConstantArray::get(const_cast<ArrayType *>(LLVMArrTy), {ConstInt});
341 SPIRVType *SpvBaseTy = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
342 unsigned BW = getScalarOrVectorBitWidth(SpvBaseTy);
343 return getOrCreateIntCompositeOrNull(Val, I, SpvType, TII, ConstArr, BW,
344 LLVMArrTy->getNumElements());
345}
346
347Register SPIRVGlobalRegistry::getOrCreateIntCompositeOrNull(
348 uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR,
349 Constant *CA, unsigned BitWidth, unsigned ElemCnt) {
350 Register Res = DT.find(CA, CurMF);
351 if (!Res.isValid()) {
352 Register SpvScalConst;
353 if (Val || EmitIR) {
354 SPIRVType *SpvBaseType =
356 SpvScalConst = buildConstantInt(Val, MIRBuilder, SpvBaseType, EmitIR);
357 }
358 LLT LLTy = EmitIR ? LLT::fixed_vector(ElemCnt, BitWidth) : LLT::scalar(32);
359 Register SpvVecConst =
361 CurMF->getRegInfo().setRegClass(SpvVecConst, &SPIRV::IDRegClass);
362 assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
363 DT.add(CA, CurMF, SpvVecConst);
364 if (EmitIR) {
365 MIRBuilder.buildSplatVector(SpvVecConst, SpvScalConst);
366 } else {
367 if (Val) {
368 auto MIB = MIRBuilder.buildInstr(SPIRV::OpConstantComposite)
369 .addDef(SpvVecConst)
370 .addUse(getSPIRVTypeID(SpvType));
371 for (unsigned i = 0; i < ElemCnt; ++i)
372 MIB.addUse(SpvScalConst);
373 } else {
374 MIRBuilder.buildInstr(SPIRV::OpConstantNull)
375 .addDef(SpvVecConst)
376 .addUse(getSPIRVTypeID(SpvType));
377 }
378 }
379 return SpvVecConst;
380 }
381 return Res;
382}
383
386 MachineIRBuilder &MIRBuilder,
387 SPIRVType *SpvType, bool EmitIR) {
388 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
389 assert(LLVMTy->isVectorTy());
390 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
391 Type *LLVMBaseTy = LLVMVecTy->getElementType();
392 const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
393 auto ConstVec =
394 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstInt);
395 unsigned BW = getScalarOrVectorBitWidth(SpvType);
396 return getOrCreateIntCompositeOrNull(Val, MIRBuilder, SpvType, EmitIR,
397 ConstVec, BW,
398 SpvType->getOperand(2).getImm());
399}
400
403 MachineIRBuilder &MIRBuilder,
404 SPIRVType *SpvType, bool EmitIR) {
405 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
406 assert(LLVMTy->isArrayTy());
407 const ArrayType *LLVMArrTy = cast<ArrayType>(LLVMTy);
408 Type *LLVMBaseTy = LLVMArrTy->getElementType();
409 const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
410 auto ConstArr =
411 ConstantArray::get(const_cast<ArrayType *>(LLVMArrTy), {ConstInt});
412 SPIRVType *SpvBaseTy = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
413 unsigned BW = getScalarOrVectorBitWidth(SpvBaseTy);
414 return getOrCreateIntCompositeOrNull(Val, MIRBuilder, SpvType, EmitIR,
415 ConstArr, BW,
416 LLVMArrTy->getNumElements());
417}
418
421 SPIRVType *SpvType) {
422 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
423 const PointerType *LLVMPtrTy = cast<PointerType>(LLVMTy);
424 // Find a constant in DT or build a new one.
425 Constant *CP = ConstantPointerNull::get(const_cast<PointerType *>(LLVMPtrTy));
426 Register Res = DT.find(CP, CurMF);
427 if (!Res.isValid()) {
428 LLT LLTy = LLT::pointer(LLVMPtrTy->getAddressSpace(), PointerSize);
430 CurMF->getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
431 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
432 MIRBuilder.buildInstr(SPIRV::OpConstantNull)
433 .addDef(Res)
434 .addUse(getSPIRVTypeID(SpvType));
435 DT.add(CP, CurMF, Res);
436 }
437 return Res;
438}
439
441 Register ResReg, unsigned AddrMode, unsigned Param, unsigned FilerMode,
442 MachineIRBuilder &MIRBuilder, SPIRVType *SpvType) {
443 SPIRVType *SampTy;
444 if (SpvType)
445 SampTy = getOrCreateSPIRVType(getTypeForSPIRVType(SpvType), MIRBuilder);
446 else if ((SampTy = getOrCreateSPIRVTypeByName("opencl.sampler_t",
447 MIRBuilder)) == nullptr)
448 report_fatal_error("Unable to recognize SPIRV type name: opencl.sampler_t");
449
450 auto Sampler =
451 ResReg.isValid()
452 ? ResReg
453 : MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::IDRegClass);
454 auto Res = MIRBuilder.buildInstr(SPIRV::OpConstantSampler)
455 .addDef(Sampler)
456 .addUse(getSPIRVTypeID(SampTy))
458 .addImm(Param)
459 .addImm(FilerMode);
460 assert(Res->getOperand(0).isReg());
461 return Res->getOperand(0).getReg();
462}
463
466 const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage,
467 const MachineInstr *Init, bool IsConst, bool HasLinkageTy,
468 SPIRV::LinkageType::LinkageType LinkageType, MachineIRBuilder &MIRBuilder,
469 bool IsInstSelector) {
470 const GlobalVariable *GVar = nullptr;
471 if (GV)
472 GVar = cast<const GlobalVariable>(GV);
473 else {
474 // If GV is not passed explicitly, use the name to find or construct
475 // the global variable.
476 Module *M = MIRBuilder.getMF().getFunction().getParent();
477 GVar = M->getGlobalVariable(Name);
478 if (GVar == nullptr) {
479 const Type *Ty = getTypeForSPIRVType(BaseType); // TODO: check type.
480 GVar = new GlobalVariable(*M, const_cast<Type *>(Ty), false,
482 Twine(Name));
483 }
484 GV = GVar;
485 }
486 Register Reg = DT.find(GVar, &MIRBuilder.getMF());
487 if (Reg.isValid()) {
488 if (Reg != ResVReg)
489 MIRBuilder.buildCopy(ResVReg, Reg);
490 return ResVReg;
491 }
492
493 auto MIB = MIRBuilder.buildInstr(SPIRV::OpVariable)
494 .addDef(ResVReg)
496 .addImm(static_cast<uint32_t>(Storage));
497
498 if (Init != 0) {
499 MIB.addUse(Init->getOperand(0).getReg());
500 }
501
502 // ISel may introduce a new register on this step, so we need to add it to
503 // DT and correct its type avoiding fails on the next stage.
504 if (IsInstSelector) {
505 const auto &Subtarget = CurMF->getSubtarget();
506 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
507 *Subtarget.getRegisterInfo(),
508 *Subtarget.getRegBankInfo());
509 }
510 Reg = MIB->getOperand(0).getReg();
511 DT.add(GVar, &MIRBuilder.getMF(), Reg);
512
513 // Set to Reg the same type as ResVReg has.
514 auto MRI = MIRBuilder.getMRI();
515 assert(MRI->getType(ResVReg).isPointer() && "Pointer type is expected");
516 if (Reg != ResVReg) {
517 LLT RegLLTy = LLT::pointer(MRI->getType(ResVReg).getAddressSpace(), 32);
518 MRI->setType(Reg, RegLLTy);
519 assignSPIRVTypeToVReg(BaseType, Reg, MIRBuilder.getMF());
520 }
521
522 // If it's a global variable with name, output OpName for it.
523 if (GVar && GVar->hasName())
524 buildOpName(Reg, GVar->getName(), MIRBuilder);
525
526 // Output decorations for the GV.
527 // TODO: maybe move to GenerateDecorations pass.
528 if (IsConst)
529 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Constant, {});
530
531 if (GVar && GVar->getAlign().valueOrOne().value() != 1) {
532 unsigned Alignment = (unsigned)GVar->getAlign().valueOrOne().value();
533 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Alignment, {Alignment});
534 }
535
536 if (HasLinkageTy)
537 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::LinkageAttributes,
538 {static_cast<uint32_t>(LinkageType)}, Name);
539
540 SPIRV::BuiltIn::BuiltIn BuiltInId;
541 if (getSpirvBuiltInIdByName(Name, BuiltInId))
542 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::BuiltIn,
543 {static_cast<uint32_t>(BuiltInId)});
544
545 return Reg;
546}
547
548SPIRVType *SPIRVGlobalRegistry::getOpTypeArray(uint32_t NumElems,
549 SPIRVType *ElemType,
550 MachineIRBuilder &MIRBuilder,
551 bool EmitIR) {
552 assert((ElemType->getOpcode() != SPIRV::OpTypeVoid) &&
553 "Invalid array element type");
554 Register NumElementsVReg =
555 buildConstantInt(NumElems, MIRBuilder, nullptr, EmitIR);
556 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeArray)
557 .addDef(createTypeVReg(MIRBuilder))
558 .addUse(getSPIRVTypeID(ElemType))
559 .addUse(NumElementsVReg);
560 return MIB;
561}
562
563SPIRVType *SPIRVGlobalRegistry::getOpTypeOpaque(const StructType *Ty,
564 MachineIRBuilder &MIRBuilder) {
565 assert(Ty->hasName());
566 const StringRef Name = Ty->hasName() ? Ty->getName() : "";
567 Register ResVReg = createTypeVReg(MIRBuilder);
568 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeOpaque).addDef(ResVReg);
569 addStringImm(Name, MIB);
570 buildOpName(ResVReg, Name, MIRBuilder);
571 return MIB;
572}
573
574SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(const StructType *Ty,
575 MachineIRBuilder &MIRBuilder,
576 bool EmitIR) {
577 SmallVector<Register, 4> FieldTypes;
578 for (const auto &Elem : Ty->elements()) {
579 SPIRVType *ElemTy = findSPIRVType(Elem, MIRBuilder);
580 assert(ElemTy && ElemTy->getOpcode() != SPIRV::OpTypeVoid &&
581 "Invalid struct element type");
582 FieldTypes.push_back(getSPIRVTypeID(ElemTy));
583 }
584 Register ResVReg = createTypeVReg(MIRBuilder);
585 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeStruct).addDef(ResVReg);
586 for (const auto &Ty : FieldTypes)
587 MIB.addUse(Ty);
588 if (Ty->hasName())
589 buildOpName(ResVReg, Ty->getName(), MIRBuilder);
590 if (Ty->isPacked())
591 buildOpDecorate(ResVReg, MIRBuilder, SPIRV::Decoration::CPacked, {});
592 return MIB;
593}
594
595SPIRVType *SPIRVGlobalRegistry::getOrCreateSpecialType(
596 const Type *Ty, MachineIRBuilder &MIRBuilder,
597 SPIRV::AccessQualifier::AccessQualifier AccQual) {
598 assert(isSpecialOpaqueType(Ty) && "Not a special opaque builtin type");
599 return SPIRV::lowerBuiltinType(Ty, AccQual, MIRBuilder, this);
600}
601
602SPIRVType *SPIRVGlobalRegistry::getOpTypePointer(
603 SPIRV::StorageClass::StorageClass SC, SPIRVType *ElemType,
604 MachineIRBuilder &MIRBuilder, Register Reg) {
605 if (!Reg.isValid())
606 Reg = createTypeVReg(MIRBuilder);
607 return MIRBuilder.buildInstr(SPIRV::OpTypePointer)
608 .addDef(Reg)
609 .addImm(static_cast<uint32_t>(SC))
610 .addUse(getSPIRVTypeID(ElemType));
611}
612
613SPIRVType *SPIRVGlobalRegistry::getOpTypeForwardPointer(
614 SPIRV::StorageClass::StorageClass SC, MachineIRBuilder &MIRBuilder) {
615 return MIRBuilder.buildInstr(SPIRV::OpTypeForwardPointer)
616 .addUse(createTypeVReg(MIRBuilder))
617 .addImm(static_cast<uint32_t>(SC));
618}
619
620SPIRVType *SPIRVGlobalRegistry::getOpTypeFunction(
621 SPIRVType *RetType, const SmallVectorImpl<SPIRVType *> &ArgTypes,
622 MachineIRBuilder &MIRBuilder) {
623 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFunction)
624 .addDef(createTypeVReg(MIRBuilder))
625 .addUse(getSPIRVTypeID(RetType));
626 for (const SPIRVType *ArgType : ArgTypes)
627 MIB.addUse(getSPIRVTypeID(ArgType));
628 return MIB;
629}
630
632 const Type *Ty, SPIRVType *RetType,
633 const SmallVectorImpl<SPIRVType *> &ArgTypes,
634 MachineIRBuilder &MIRBuilder) {
635 Register Reg = DT.find(Ty, &MIRBuilder.getMF());
636 if (Reg.isValid())
637 return getSPIRVTypeForVReg(Reg);
638 SPIRVType *SpirvType = getOpTypeFunction(RetType, ArgTypes, MIRBuilder);
639 DT.add(Ty, CurMF, getSPIRVTypeID(SpirvType));
640 return finishCreatingSPIRVType(Ty, SpirvType);
641}
642
643SPIRVType *SPIRVGlobalRegistry::findSPIRVType(
644 const Type *Ty, MachineIRBuilder &MIRBuilder,
645 SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
646 Register Reg = DT.find(Ty, &MIRBuilder.getMF());
647 if (Reg.isValid())
648 return getSPIRVTypeForVReg(Reg);
649 if (ForwardPointerTypes.contains(Ty))
650 return ForwardPointerTypes[Ty];
651 return restOfCreateSPIRVType(Ty, MIRBuilder, AccQual, EmitIR);
652}
653
655 assert(SpirvType && "Attempting to get type id for nullptr type.");
656 if (SpirvType->getOpcode() == SPIRV::OpTypeForwardPointer)
657 return SpirvType->uses().begin()->getReg();
658 return SpirvType->defs().begin()->getReg();
659}
660
661SPIRVType *SPIRVGlobalRegistry::createSPIRVType(
662 const Type *Ty, MachineIRBuilder &MIRBuilder,
663 SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
664 if (isSpecialOpaqueType(Ty))
665 return getOrCreateSpecialType(Ty, MIRBuilder, AccQual);
666 auto &TypeToSPIRVTypeMap = DT.getTypes()->getAllUses();
667 auto t = TypeToSPIRVTypeMap.find(Ty);
668 if (t != TypeToSPIRVTypeMap.end()) {
669 auto tt = t->second.find(&MIRBuilder.getMF());
670 if (tt != t->second.end())
671 return getSPIRVTypeForVReg(tt->second);
672 }
673
674 if (auto IType = dyn_cast<IntegerType>(Ty)) {
675 const unsigned Width = IType->getBitWidth();
676 return Width == 1 ? getOpTypeBool(MIRBuilder)
677 : getOpTypeInt(Width, MIRBuilder, false);
678 }
679 if (Ty->isFloatingPointTy())
680 return getOpTypeFloat(Ty->getPrimitiveSizeInBits(), MIRBuilder);
681 if (Ty->isVoidTy())
682 return getOpTypeVoid(MIRBuilder);
683 if (Ty->isVectorTy()) {
684 SPIRVType *El =
685 findSPIRVType(cast<FixedVectorType>(Ty)->getElementType(), MIRBuilder);
686 return getOpTypeVector(cast<FixedVectorType>(Ty)->getNumElements(), El,
687 MIRBuilder);
688 }
689 if (Ty->isArrayTy()) {
690 SPIRVType *El = findSPIRVType(Ty->getArrayElementType(), MIRBuilder);
691 return getOpTypeArray(Ty->getArrayNumElements(), El, MIRBuilder, EmitIR);
692 }
693 if (auto SType = dyn_cast<StructType>(Ty)) {
694 if (SType->isOpaque())
695 return getOpTypeOpaque(SType, MIRBuilder);
696 return getOpTypeStruct(SType, MIRBuilder, EmitIR);
697 }
698 if (auto FType = dyn_cast<FunctionType>(Ty)) {
699 SPIRVType *RetTy = findSPIRVType(FType->getReturnType(), MIRBuilder);
701 for (const auto &t : FType->params()) {
702 ParamTypes.push_back(findSPIRVType(t, MIRBuilder));
703 }
704 return getOpTypeFunction(RetTy, ParamTypes, MIRBuilder);
705 }
706 if (auto PType = dyn_cast<PointerType>(Ty)) {
707 SPIRVType *SpvElementType;
708 // At the moment, all opaque pointers correspond to i8 element type.
709 // TODO: change the implementation once opaque pointers are supported
710 // in the SPIR-V specification.
711 SpvElementType = getOrCreateSPIRVIntegerType(8, MIRBuilder);
712 auto SC = addressSpaceToStorageClass(PType->getAddressSpace());
713 // Null pointer means we have a loop in type definitions, make and
714 // return corresponding OpTypeForwardPointer.
715 if (SpvElementType == nullptr) {
716 if (!ForwardPointerTypes.contains(Ty))
717 ForwardPointerTypes[PType] = getOpTypeForwardPointer(SC, MIRBuilder);
718 return ForwardPointerTypes[PType];
719 }
720 // If we have forward pointer associated with this type, use its register
721 // operand to create OpTypePointer.
722 if (ForwardPointerTypes.contains(PType)) {
723 Register Reg = getSPIRVTypeID(ForwardPointerTypes[PType]);
724 return getOpTypePointer(SC, SpvElementType, MIRBuilder, Reg);
725 }
726
727 return getOrCreateSPIRVPointerType(SpvElementType, MIRBuilder, SC);
728 }
729 llvm_unreachable("Unable to convert LLVM type to SPIRVType");
730}
731
732SPIRVType *SPIRVGlobalRegistry::restOfCreateSPIRVType(
733 const Type *Ty, MachineIRBuilder &MIRBuilder,
734 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
735 if (TypesInProcessing.count(Ty) && !Ty->isPointerTy())
736 return nullptr;
737 TypesInProcessing.insert(Ty);
738 SPIRVType *SpirvType = createSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR);
739 TypesInProcessing.erase(Ty);
740 VRegToTypeMap[&MIRBuilder.getMF()][getSPIRVTypeID(SpirvType)] = SpirvType;
741 SPIRVToLLVMType[SpirvType] = Ty;
742 Register Reg = DT.find(Ty, &MIRBuilder.getMF());
743 // Do not add OpTypeForwardPointer to DT, a corresponding normal pointer type
744 // will be added later. For special types it is already added to DT.
745 if (SpirvType->getOpcode() != SPIRV::OpTypeForwardPointer && !Reg.isValid() &&
746 !isSpecialOpaqueType(Ty)) {
747 if (!Ty->isPointerTy())
748 DT.add(Ty, &MIRBuilder.getMF(), getSPIRVTypeID(SpirvType));
749 else
750 DT.add(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),
751 Ty->getPointerAddressSpace(), &MIRBuilder.getMF(),
752 getSPIRVTypeID(SpirvType));
753 }
754
755 return SpirvType;
756}
757
759 auto t = VRegToTypeMap.find(CurMF);
760 if (t != VRegToTypeMap.end()) {
761 auto tt = t->second.find(VReg);
762 if (tt != t->second.end())
763 return tt->second;
764 }
765 return nullptr;
766}
767
769 const Type *Ty, MachineIRBuilder &MIRBuilder,
770 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
771 Register Reg;
772 if (!Ty->isPointerTy())
773 Reg = DT.find(Ty, &MIRBuilder.getMF());
774 else
775 Reg =
776 DT.find(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),
777 Ty->getPointerAddressSpace(), &MIRBuilder.getMF());
778
779 if (Reg.isValid() && !isSpecialOpaqueType(Ty))
780 return getSPIRVTypeForVReg(Reg);
781 TypesInProcessing.clear();
782 SPIRVType *STy = restOfCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR);
783 // Create normal pointer types for the corresponding OpTypeForwardPointers.
784 for (auto &CU : ForwardPointerTypes) {
785 const Type *Ty2 = CU.first;
786 SPIRVType *STy2 = CU.second;
787 if ((Reg = DT.find(Ty2, &MIRBuilder.getMF())).isValid())
788 STy2 = getSPIRVTypeForVReg(Reg);
789 else
790 STy2 = restOfCreateSPIRVType(Ty2, MIRBuilder, AccessQual, EmitIR);
791 if (Ty == Ty2)
792 STy = STy2;
793 }
794 ForwardPointerTypes.clear();
795 return STy;
796}
797
799 unsigned TypeOpcode) const {
801 assert(Type && "isScalarOfType VReg has no type assigned");
802 return Type->getOpcode() == TypeOpcode;
803}
804
806 unsigned TypeOpcode) const {
808 assert(Type && "isScalarOrVectorOfType VReg has no type assigned");
809 if (Type->getOpcode() == TypeOpcode)
810 return true;
811 if (Type->getOpcode() == SPIRV::OpTypeVector) {
812 Register ScalarTypeVReg = Type->getOperand(1).getReg();
813 SPIRVType *ScalarType = getSPIRVTypeForVReg(ScalarTypeVReg);
814 return ScalarType->getOpcode() == TypeOpcode;
815 }
816 return false;
817}
818
819unsigned
821 assert(Type && "Invalid Type pointer");
822 if (Type->getOpcode() == SPIRV::OpTypeVector) {
823 auto EleTypeReg = Type->getOperand(1).getReg();
824 Type = getSPIRVTypeForVReg(EleTypeReg);
825 }
826 if (Type->getOpcode() == SPIRV::OpTypeInt ||
827 Type->getOpcode() == SPIRV::OpTypeFloat)
828 return Type->getOperand(1).getImm();
829 if (Type->getOpcode() == SPIRV::OpTypeBool)
830 return 1;
831 llvm_unreachable("Attempting to get bit width of non-integer/float type.");
832}
833
835 assert(Type && "Invalid Type pointer");
836 if (Type->getOpcode() == SPIRV::OpTypeVector) {
837 auto EleTypeReg = Type->getOperand(1).getReg();
838 Type = getSPIRVTypeForVReg(EleTypeReg);
839 }
840 if (Type->getOpcode() == SPIRV::OpTypeInt)
841 return Type->getOperand(2).getImm() != 0;
842 llvm_unreachable("Attempting to get sign of non-integer type.");
843}
844
845SPIRV::StorageClass::StorageClass
848 assert(Type && Type->getOpcode() == SPIRV::OpTypePointer &&
849 Type->getOperand(1).isImm() && "Pointer type is expected");
850 return static_cast<SPIRV::StorageClass::StorageClass>(
851 Type->getOperand(1).getImm());
852}
853
855 MachineIRBuilder &MIRBuilder, SPIRVType *SampledType, SPIRV::Dim::Dim Dim,
856 uint32_t Depth, uint32_t Arrayed, uint32_t Multisampled, uint32_t Sampled,
857 SPIRV::ImageFormat::ImageFormat ImageFormat,
858 SPIRV::AccessQualifier::AccessQualifier AccessQual) {
859 SPIRV::ImageTypeDescriptor TD(SPIRVToLLVMType.lookup(SampledType), Dim, Depth,
860 Arrayed, Multisampled, Sampled, ImageFormat,
861 AccessQual);
862 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
863 return Res;
864 Register ResVReg = createTypeVReg(MIRBuilder);
865 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
866 return MIRBuilder.buildInstr(SPIRV::OpTypeImage)
867 .addDef(ResVReg)
868 .addUse(getSPIRVTypeID(SampledType))
869 .addImm(Dim)
870 .addImm(Depth) // Depth (whether or not it is a Depth image).
871 .addImm(Arrayed) // Arrayed.
872 .addImm(Multisampled) // Multisampled (0 = only single-sample).
873 .addImm(Sampled) // Sampled (0 = usage known at runtime).
874 .addImm(ImageFormat)
875 .addImm(AccessQual);
876}
877
878SPIRVType *
881 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
882 return Res;
883 Register ResVReg = createTypeVReg(MIRBuilder);
884 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
885 return MIRBuilder.buildInstr(SPIRV::OpTypeSampler).addDef(ResVReg);
886}
887
889 MachineIRBuilder &MIRBuilder,
890 SPIRV::AccessQualifier::AccessQualifier AccessQual) {
891 SPIRV::PipeTypeDescriptor TD(AccessQual);
892 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
893 return Res;
894 Register ResVReg = createTypeVReg(MIRBuilder);
895 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
896 return MIRBuilder.buildInstr(SPIRV::OpTypePipe)
897 .addDef(ResVReg)
898 .addImm(AccessQual);
899}
900
902 MachineIRBuilder &MIRBuilder) {
904 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
905 return Res;
906 Register ResVReg = createTypeVReg(MIRBuilder);
907 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
908 return MIRBuilder.buildInstr(SPIRV::OpTypeDeviceEvent).addDef(ResVReg);
909}
910
912 SPIRVType *ImageType, MachineIRBuilder &MIRBuilder) {
914 SPIRVToLLVMType.lookup(MIRBuilder.getMF().getRegInfo().getVRegDef(
915 ImageType->getOperand(1).getReg())),
916 ImageType);
917 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
918 return Res;
919 Register ResVReg = createTypeVReg(MIRBuilder);
920 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
921 return MIRBuilder.buildInstr(SPIRV::OpTypeSampledImage)
922 .addDef(ResVReg)
923 .addUse(getSPIRVTypeID(ImageType));
924}
925
927 const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode) {
928 Register ResVReg = DT.find(Ty, &MIRBuilder.getMF());
929 if (ResVReg.isValid())
930 return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(ResVReg);
931 ResVReg = createTypeVReg(MIRBuilder);
932 SPIRVType *SpirvTy = MIRBuilder.buildInstr(Opcode).addDef(ResVReg);
933 DT.add(Ty, &MIRBuilder.getMF(), ResVReg);
934 return SpirvTy;
935}
936
937const MachineInstr *
938SPIRVGlobalRegistry::checkSpecialInstr(const SPIRV::SpecialTypeDescriptor &TD,
939 MachineIRBuilder &MIRBuilder) {
940 Register Reg = DT.find(TD, &MIRBuilder.getMF());
941 if (Reg.isValid())
942 return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(Reg);
943 return nullptr;
944}
945
946// Returns nullptr if unable to recognize SPIRV type name
947// TODO: maybe use tablegen to implement this.
949 StringRef TypeStr, MachineIRBuilder &MIRBuilder,
950 SPIRV::StorageClass::StorageClass SC,
951 SPIRV::AccessQualifier::AccessQualifier AQ) {
952 unsigned VecElts = 0;
953 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
954
955 // Parse strings representing either a SPIR-V or OpenCL builtin type.
956 if (hasBuiltinTypePrefix(TypeStr))
958 SPIRV::parseBuiltinTypeNameToTargetExtType(TypeStr.str(), MIRBuilder),
959 MIRBuilder, AQ);
960
961 // Parse type name in either "typeN" or "type vector[N]" format, where
962 // N is the number of elements of the vector.
963 Type *Ty;
964
965 TypeStr.consume_front("atomic_");
966
967 if (TypeStr.starts_with("void")) {
968 Ty = Type::getVoidTy(Ctx);
969 TypeStr = TypeStr.substr(strlen("void"));
970 } else if (TypeStr.starts_with("bool")) {
971 Ty = Type::getIntNTy(Ctx, 1);
972 TypeStr = TypeStr.substr(strlen("bool"));
973 } else if (TypeStr.starts_with("char") || TypeStr.starts_with("uchar")) {
974 Ty = Type::getInt8Ty(Ctx);
975 TypeStr = TypeStr.starts_with("char") ? TypeStr.substr(strlen("char"))
976 : TypeStr.substr(strlen("uchar"));
977 } else if (TypeStr.starts_with("short") || TypeStr.starts_with("ushort")) {
978 Ty = Type::getInt16Ty(Ctx);
979 TypeStr = TypeStr.starts_with("short") ? TypeStr.substr(strlen("short"))
980 : TypeStr.substr(strlen("ushort"));
981 } else if (TypeStr.starts_with("int") || TypeStr.starts_with("uint")) {
982 Ty = Type::getInt32Ty(Ctx);
983 TypeStr = TypeStr.starts_with("int") ? TypeStr.substr(strlen("int"))
984 : TypeStr.substr(strlen("uint"));
985 } else if (TypeStr.starts_with("long") || TypeStr.starts_with("ulong")) {
986 Ty = Type::getInt64Ty(Ctx);
987 TypeStr = TypeStr.starts_with("long") ? TypeStr.substr(strlen("long"))
988 : TypeStr.substr(strlen("ulong"));
989 } else if (TypeStr.starts_with("half")) {
990 Ty = Type::getHalfTy(Ctx);
991 TypeStr = TypeStr.substr(strlen("half"));
992 } else if (TypeStr.starts_with("float")) {
993 Ty = Type::getFloatTy(Ctx);
994 TypeStr = TypeStr.substr(strlen("float"));
995 } else if (TypeStr.starts_with("double")) {
996 Ty = Type::getDoubleTy(Ctx);
997 TypeStr = TypeStr.substr(strlen("double"));
998 } else {
999 // Unable to recognize SPIRV type name
1000 return nullptr;
1001 }
1002
1003 auto SpirvTy = getOrCreateSPIRVType(Ty, MIRBuilder, AQ);
1004
1005 // Handle "type*" or "type* vector[N]".
1006 if (TypeStr.starts_with("*")) {
1007 SpirvTy = getOrCreateSPIRVPointerType(SpirvTy, MIRBuilder, SC);
1008 TypeStr = TypeStr.substr(strlen("*"));
1009 }
1010
1011 // Handle "typeN*" or "type vector[N]*".
1012 bool IsPtrToVec = TypeStr.consume_back("*");
1013
1014 if (TypeStr.consume_front(" vector[")) {
1015 TypeStr = TypeStr.substr(0, TypeStr.find(']'));
1016 }
1017 TypeStr.getAsInteger(10, VecElts);
1018 if (VecElts > 0)
1019 SpirvTy = getOrCreateSPIRVVectorType(SpirvTy, VecElts, MIRBuilder);
1020
1021 if (IsPtrToVec)
1022 SpirvTy = getOrCreateSPIRVPointerType(SpirvTy, MIRBuilder, SC);
1023
1024 return SpirvTy;
1025}
1026
1027SPIRVType *
1029 MachineIRBuilder &MIRBuilder) {
1030 return getOrCreateSPIRVType(
1032 MIRBuilder);
1033}
1034
1035SPIRVType *SPIRVGlobalRegistry::finishCreatingSPIRVType(const Type *LLVMTy,
1036 SPIRVType *SpirvType) {
1037 assert(CurMF == SpirvType->getMF());
1038 VRegToTypeMap[CurMF][getSPIRVTypeID(SpirvType)] = SpirvType;
1039 SPIRVToLLVMType[SpirvType] = LLVMTy;
1040 return SpirvType;
1041}
1042
1044 unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII) {
1046 Register Reg = DT.find(LLVMTy, CurMF);
1047 if (Reg.isValid())
1048 return getSPIRVTypeForVReg(Reg);
1049 MachineBasicBlock &BB = *I.getParent();
1050 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeInt))
1053 .addImm(0);
1054 DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1055 return finishCreatingSPIRVType(LLVMTy, MIB);
1056}
1057
1058SPIRVType *
1060 return getOrCreateSPIRVType(
1061 IntegerType::get(MIRBuilder.getMF().getFunction().getContext(), 1),
1062 MIRBuilder);
1063}
1064
1065SPIRVType *
1067 const SPIRVInstrInfo &TII) {
1069 Register Reg = DT.find(LLVMTy, CurMF);
1070 if (Reg.isValid())
1071 return getSPIRVTypeForVReg(Reg);
1072 MachineBasicBlock &BB = *I.getParent();
1073 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeBool))
1075 DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1076 return finishCreatingSPIRVType(LLVMTy, MIB);
1077}
1078
1080 SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder) {
1081 return getOrCreateSPIRVType(
1083 NumElements),
1084 MIRBuilder);
1085}
1086
1088 SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
1089 const SPIRVInstrInfo &TII) {
1090 Type *LLVMTy = FixedVectorType::get(
1091 const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
1092 Register Reg = DT.find(LLVMTy, CurMF);
1093 if (Reg.isValid())
1094 return getSPIRVTypeForVReg(Reg);
1095 MachineBasicBlock &BB = *I.getParent();
1096 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeVector))
1099 .addImm(NumElements);
1100 DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1101 return finishCreatingSPIRVType(LLVMTy, MIB);
1102}
1103
1105 SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
1106 const SPIRVInstrInfo &TII) {
1107 Type *LLVMTy = ArrayType::get(
1108 const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
1109 Register Reg = DT.find(LLVMTy, CurMF);
1110 if (Reg.isValid())
1111 return getSPIRVTypeForVReg(Reg);
1112 MachineBasicBlock &BB = *I.getParent();
1113 SPIRVType *SpirvType = getOrCreateSPIRVIntegerType(32, I, TII);
1114 Register Len = getOrCreateConstInt(NumElements, I, SpirvType, TII);
1115 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeArray))
1118 .addUse(Len);
1119 DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1120 return finishCreatingSPIRVType(LLVMTy, MIB);
1121}
1122
1124 SPIRVType *BaseType, MachineIRBuilder &MIRBuilder,
1125 SPIRV::StorageClass::StorageClass SC) {
1126 const Type *PointerElementType = getTypeForSPIRVType(BaseType);
1128 Type *LLVMTy =
1129 PointerType::get(const_cast<Type *>(PointerElementType), AddressSpace);
1130 Register Reg = DT.find(PointerElementType, AddressSpace, CurMF);
1131 if (Reg.isValid())
1132 return getSPIRVTypeForVReg(Reg);
1133 auto MIB = BuildMI(MIRBuilder.getMBB(), MIRBuilder.getInsertPt(),
1134 MIRBuilder.getDebugLoc(),
1135 MIRBuilder.getTII().get(SPIRV::OpTypePointer))
1137 .addImm(static_cast<uint32_t>(SC))
1139 DT.add(PointerElementType, AddressSpace, CurMF, getSPIRVTypeID(MIB));
1140 return finishCreatingSPIRVType(LLVMTy, MIB);
1141}
1142
1145 SPIRV::StorageClass::StorageClass SC) {
1146 const Type *PointerElementType = getTypeForSPIRVType(BaseType);
1148 Type *LLVMTy =
1149 PointerType::get(const_cast<Type *>(PointerElementType), AddressSpace);
1150 Register Reg = DT.find(PointerElementType, AddressSpace, CurMF);
1151 if (Reg.isValid())
1152 return getSPIRVTypeForVReg(Reg);
1153 MachineBasicBlock &BB = *I.getParent();
1154 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypePointer))
1156 .addImm(static_cast<uint32_t>(SC))
1158 DT.add(PointerElementType, AddressSpace, CurMF, getSPIRVTypeID(MIB));
1159 return finishCreatingSPIRVType(LLVMTy, MIB);
1160}
1161
1163 SPIRVType *SpvType,
1164 const SPIRVInstrInfo &TII) {
1165 assert(SpvType);
1166 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
1167 assert(LLVMTy);
1168 // Find a constant in DT or build a new one.
1169 UndefValue *UV = UndefValue::get(const_cast<Type *>(LLVMTy));
1170 Register Res = DT.find(UV, CurMF);
1171 if (Res.isValid())
1172 return Res;
1173 LLT LLTy = LLT::scalar(32);
1175 CurMF->getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
1176 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
1177 DT.add(UV, CurMF, Res);
1178
1180 MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpUndef))
1181 .addDef(Res)
1182 .addUse(getSPIRVTypeID(SpvType));
1183 const auto &ST = CurMF->getSubtarget();
1184 constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
1185 *ST.getRegisterInfo(), *ST.getRegBankInfo());
1186 return Res;
1187}
unsigned const MachineRegisterInfo * MRI
return RetTy
std::string Name
const HexagonInstrInfo * TII
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static Register createTypeVReg(MachineIRBuilder &MIRBuilder)
Class for arbitrary precision integers.
Definition: APInt.h:76
Class to represent array types.
Definition: DerivedTypes.h:371
uint64_t getNumElements() const
Definition: DerivedTypes.h:383
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Definition: Type.cpp:647
Type * getElementType() const
Definition: DerivedTypes.h:384
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
Definition: Constants.cpp:1235
static Constant * get(Type *Ty, double V)
This returns a ConstantFP, or a vector containing a splat of a ConstantFP, for the specified value in...
Definition: Constants.cpp:927
This is the shared class of boolean and integer constants.
Definition: Constants.h:79
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:888
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
Definition: Constants.cpp:1691
static Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
Definition: Constants.cpp:1385
This is an important base class in LLVM.
Definition: Constant.h:41
Class to represent fixed width SIMD vectors.
Definition: DerivedTypes.h:539
static FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition: Type.cpp:692
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:342
MaybeAlign getAlign() const
Returns the alignment of the given variable or function.
Definition: GlobalObject.h:80
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:655
@ ExternalLinkage
Externally visible function.
Definition: GlobalValue.h:52
Class to represent integer types.
Definition: DerivedTypes.h:40
static IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition: Type.cpp:278
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
Definition: LowLevelType.h:42
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
Definition: LowLevelType.h:49
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
Definition: LowLevelType.h:92
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition: MCInstrInfo.h:63
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.
const TargetInstrInfo & getTII()
MachineBasicBlock::iterator getInsertPt()
Current insertion point for new instructions.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildSplatVector(const DstOp &Res, const SrcOp &Src)
Build and insert Res = G_BUILD_VECTOR with Src replicated to fill the number of elements.
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.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
Definition: MachineInstr.h:68
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:543
iterator_range< mop_iterator > uses()
Returns a range that includes all operands that are register uses.
Definition: MachineInstr.h:707
iterator_range< mop_iterator > defs()
Returns a range over all explicit operands that are register definitions.
Definition: MachineInstr.h:696
const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:553
int64_t getImm() const
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
Class to represent pointers.
Definition: DerivedTypes.h:646
static PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Definition: DerivedTypes.h:679
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
constexpr bool isValid() const
Definition: Register.h:116
void add(const Type *Ty, const MachineFunction *MF, Register R)
Register find(const Type *Ty, const MachineFunction *MF)
const SPIRVDuplicatesTracker< Type > * getTypes()
SPIRVType * getOrCreateOpTypePipe(MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AccQual)
Register getOrCreateConsIntVector(uint64_t Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
SPIRVType * assignVectTypeToVReg(SPIRVType *BaseType, unsigned NumElements, Register VReg, MachineInstr &I, const SPIRVInstrInfo &TII)
Register getOrCreateUndef(MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
SPIRVType * getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder)
const Type * getTypeForSPIRVType(const SPIRVType *Ty) const
Register buildConstantSampler(Register Res, unsigned AddrMode, unsigned Param, unsigned FilerMode, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType)
SPIRVType * getOrCreateOpTypeImage(MachineIRBuilder &MIRBuilder, SPIRVType *SampledType, SPIRV::Dim::Dim Dim, uint32_t Depth, uint32_t Arrayed, uint32_t Multisampled, uint32_t Sampled, SPIRV::ImageFormat::ImageFormat ImageFormat, SPIRV::AccessQualifier::AccessQualifier AccQual)
bool isScalarOrVectorSigned(const SPIRVType *Type) const
SPIRVType * getSPIRVTypeForVReg(Register VReg) const
SPIRVGlobalRegistry(unsigned PointerSize)
SPIRVType * getOrCreateOpTypeByOpcode(const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode)
Register buildConstantFP(APFloat Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType=nullptr)
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
SPIRVType * getOrCreateSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite, bool EmitIR=true)
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, MachineFunction &MF)
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)
SPIRVType * getOrCreateOpTypeSampledImage(SPIRVType *ImageType, MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateSPIRVTypeByName(StringRef TypeStr, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SC=SPIRV::StorageClass::Function, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite)
SPIRVType * assignTypeToVReg(const Type *Type, Register VReg, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite, bool EmitIR=true)
SPIRVType * getOrCreateOpTypeFunctionWithArgs(const Type *Ty, SPIRVType *RetType, const SmallVectorImpl< SPIRVType * > &ArgTypes, MachineIRBuilder &MIRBuilder)
bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const
SPIRVType * getOrCreateOpTypeDeviceEvent(MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateSPIRVPointerType(SPIRVType *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SClass=SPIRV::StorageClass::Function)
SPIRVType * getOrCreateSPIRVVectorType(SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
Register getOrCreateConsIntArray(uint64_t Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
SPIRVType * getOrCreateSPIRVArrayType(SPIRVType *BaseType, unsigned NumElements, MachineInstr &I, const SPIRVInstrInfo &TII)
SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const
SPIRVType * getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder)
Register buildConstantInt(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType=nullptr, bool EmitIR=true)
Register getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder, SPIRVType *SpvType)
unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) const
Register getOrCreateConstInt(uint64_t Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
Definition: StringRef.h:651
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:466
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:222
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:567
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:257
bool consume_front(StringRef Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
Definition: StringRef.h:631
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition: StringRef.h:293
Class to represent struct types.
Definition: DerivedTypes.h:216
ArrayRef< Type * > elements() const
Definition: DerivedTypes.h:333
bool isPacked() const
Definition: DerivedTypes.h:278
bool hasName() const
Return true if this is a named struct that has a non-empty name.
Definition: DerivedTypes.h:304
StringRef getName() const
Return the name for this struct type if it has an identity.
Definition: Type.cpp:590
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
static Type * getHalfTy(LLVMContext &C)
static Type * getDoubleTy(LLVMContext &C)
bool isVectorTy() const
True if this is an instance of VectorType.
Definition: Type.h:265
bool isArrayTy() const
True if this is an instance of ArrayType.
Definition: Type.h:252
bool isPointerTy() const
True if this is an instance of PointerType.
Definition: Type.h:255
Type * getArrayElementType() const
Definition: Type.h:404
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
uint64_t getArrayNumElements() const
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static Type * getVoidTy(LLVMContext &C)
static IntegerType * getInt16Ty(LLVMContext &C)
static IntegerType * getInt8Ty(LLVMContext &C)
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition: Type.h:185
static IntegerType * getInt32Ty(LLVMContext &C)
static IntegerType * getInt64Ty(LLVMContext &C)
static Type * getFloatTy(LLVMContext &C)
TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isVoidTy() const
Return true if this is 'void'.
Definition: Type.h:140
'undef' values are things that do not have specified contents.
Definition: Constants.h:1336
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1724
bool hasName() const
Definition: Value.h:261
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
Definition: DerivedTypes.h:641
Type * getElementType() const
Definition: DerivedTypes.h:436
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ SC
CHAIN = SC CHAIN, Imm128 - System call.
SPIRVType * lowerBuiltinType(const Type *OpaqueType, SPIRV::AccessQualifier::AccessQualifier AccessQual, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
const TargetExtType * parseBuiltinTypeNameToTargetExtType(std::string TypeName, MachineIRBuilder &MIRBuilder)
Translates a string representing a SPIR-V or OpenCL builtin type to a TargetExtType that can be furth...
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)
Definition: SPIRVUtils.cpp:99
unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
Definition: SPIRVUtils.cpp:137
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB)
Definition: SPIRVUtils.cpp:79
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:153
AddressSpace
Definition: NVPTXBaseInfo.h:21
bool getSpirvBuiltInIdByName(llvm::StringRef Name, SPIRV::BuiltIn::BuiltIn &BI)
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
Definition: SPIRVUtils.cpp:116
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace)
Definition: SPIRVUtils.cpp:157
bool isSpecialOpaqueType(const Type *Ty)
Definition: SPIRVUtils.cpp:343
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:156
constexpr unsigned BitWidth
Definition: BitmaskEnum.h:191
bool hasBuiltinTypePrefix(StringRef Name)
Definition: SPIRVUtils.cpp:337
void addStringImm(const StringRef &Str, MCInst &Inst)
Definition: SPIRVUtils.cpp:50
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