LLVM 23.0.0git
SPIRVPreLegalizer.cpp
Go to the documentation of this file.
1//===-- SPIRVPreLegalizer.cpp - prepare IR for legalization -----*- 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// The pass prepares IR for legalization: it assigns SPIR-V types to registers
10// and removes intrinsics which holded these types during IR translation.
11// Also it processes constants and registers them in GR to avoid duplication.
12//
13//===----------------------------------------------------------------------===//
14
15#include "SPIRV.h"
16#include "SPIRVSubtarget.h"
17#include "SPIRVUtils.h"
21#include "llvm/IR/Attributes.h"
22#include "llvm/IR/Constants.h"
23#include "llvm/IR/IntrinsicsSPIRV.h"
24
25#define DEBUG_TYPE "spirv-prelegalizer"
26
27using namespace llvm;
28
29namespace {
30class SPIRVPreLegalizer : public MachineFunctionPass {
31public:
32 static char ID;
33 SPIRVPreLegalizer() : MachineFunctionPass(ID) {}
34 bool runOnMachineFunction(MachineFunction &MF) override;
35 void getAnalysisUsage(AnalysisUsage &AU) const override;
36};
37} // namespace
38
39void SPIRVPreLegalizer::getAnalysisUsage(AnalysisUsage &AU) const {
40 AU.addPreserved<GISelValueTrackingAnalysisLegacy>();
42}
43
44static void
46 const SPIRVSubtarget &STI,
47 DenseMap<MachineInstr *, Type *> &TargetExtConstTypes) {
49 DenseMap<MachineInstr *, Register> RegsAlreadyAddedToDT;
50 SmallVector<MachineInstr *, 10> ToErase, ToEraseComposites;
51 for (MachineBasicBlock &MBB : MF) {
52 for (MachineInstr &MI : MBB) {
53 if (!isSpvIntrinsic(MI, Intrinsic::spv_track_constant))
54 continue;
55 ToErase.push_back(&MI);
56 Register SrcReg = MI.getOperand(2).getReg();
57 auto *Const =
59 MI.getOperand(3).getMetadata()->getOperand(0))
60 ->getValue());
61 if (auto *GV = dyn_cast<GlobalValue>(Const)) {
62 Register Reg = GR->find(GV, &MF);
63 if (!Reg.isValid()) {
64 GR->add(GV, MRI.getVRegDef(SrcReg));
65 GR->addGlobalObject(GV, &MF, SrcReg);
66 } else
67 RegsAlreadyAddedToDT[&MI] = Reg;
68 } else {
69 Register Reg = GR->find(Const, &MF);
70 if (!Reg.isValid()) {
71 if (auto *ConstVec = dyn_cast<ConstantDataVector>(Const)) {
72 auto *BuildVec = MRI.getVRegDef(SrcReg);
73 assert(BuildVec &&
74 BuildVec->getOpcode() == TargetOpcode::G_BUILD_VECTOR);
75 GR->add(Const, BuildVec);
76 for (unsigned i = 0; i < ConstVec->getNumElements(); ++i) {
77 // Ensure that OpConstantComposite reuses a constant when it's
78 // already created and available in the same machine function.
79 Constant *ElemConst = ConstVec->getElementAsConstant(i);
80 Register ElemReg = GR->find(ElemConst, &MF);
81 if (!ElemReg.isValid())
82 GR->add(ElemConst,
83 MRI.getVRegDef(BuildVec->getOperand(1 + i).getReg()));
84 else
85 BuildVec->getOperand(1 + i).setReg(ElemReg);
86 }
87 }
88 if (Const->getType()->isTargetExtTy()) {
89 // remember association so that we can restore it when assign types
90 MachineInstr *SrcMI = MRI.getVRegDef(SrcReg);
91 if (SrcMI)
92 GR->add(Const, SrcMI);
93 if (SrcMI && (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT ||
94 SrcMI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF))
95 TargetExtConstTypes[SrcMI] = Const->getType();
96 if (Const->isNullValue()) {
97 MachineBasicBlock &DepMBB = MF.front();
98 MachineIRBuilder MIB(DepMBB, DepMBB.getFirstNonPHI());
100 Const->getType(), MIB, SPIRV::AccessQualifier::ReadWrite,
101 true);
102 assert(SrcMI && "Expected source instruction to be valid");
103 SrcMI->setDesc(STI.getInstrInfo()->get(SPIRV::OpConstantNull));
105 GR->getSPIRVTypeID(ExtType), false));
106 }
107 }
108 } else {
109 RegsAlreadyAddedToDT[&MI] = Reg;
110 // This MI is unused and will be removed. If the MI uses
111 // const_composite, it will be unused and should be removed too.
112 assert(MI.getOperand(2).isReg() && "Reg operand is expected");
113 MachineInstr *SrcMI = MRI.getVRegDef(MI.getOperand(2).getReg());
114 if (SrcMI && isSpvIntrinsic(*SrcMI, Intrinsic::spv_const_composite))
115 ToEraseComposites.push_back(SrcMI);
116 }
117 }
118 }
119 }
120 for (MachineInstr *MI : ToErase) {
121 Register Reg = MI->getOperand(2).getReg();
122 auto It = RegsAlreadyAddedToDT.find(MI);
123 if (It != RegsAlreadyAddedToDT.end())
124 Reg = It->second;
125 auto *RC = MRI.getRegClassOrNull(MI->getOperand(0).getReg());
126 if (!MRI.getRegClassOrNull(Reg) && RC)
127 MRI.setRegClass(Reg, RC);
128 MRI.replaceRegWith(MI->getOperand(0).getReg(), Reg);
130 MI->eraseFromParent();
131 }
132 for (MachineInstr *MI : ToEraseComposites) {
134 MI->eraseFromParent();
135 }
136}
137
140 MachineIRBuilder MIB) {
142 for (MachineBasicBlock &MBB : MF) {
143 for (MachineInstr &MI : MBB) {
144 if (!isSpvIntrinsic(MI, Intrinsic::spv_assign_name))
145 continue;
146 const MDNode *MD = MI.getOperand(2).getMetadata();
147 StringRef ValueName = cast<MDString>(MD->getOperand(0))->getString();
148 if (ValueName.size() > 0) {
149 MIB.setInsertPt(*MI.getParent(), MI);
150 buildOpName(MI.getOperand(1).getReg(), ValueName, MIB);
151 }
152 ToErase.push_back(&MI);
153 }
154 for (MachineInstr *MI : ToErase) {
156 MI->eraseFromParent();
157 }
158 ToErase.clear();
159 }
160}
161
163 MachineRegisterInfo *MRI) {
165 IE = MRI->use_instr_end();
166 I != IE; ++I) {
167 MachineInstr *UseMI = &*I;
168 if ((isSpvIntrinsic(*UseMI, Intrinsic::spv_assign_ptr_type) ||
169 isSpvIntrinsic(*UseMI, Intrinsic::spv_assign_type)) &&
170 UseMI->getOperand(1).getReg() == Reg)
171 return UseMI;
172 }
173 return nullptr;
174}
175
177 Register ResVReg, Register OpReg) {
178 SPIRVTypeInst ResType = GR->getSPIRVTypeForVReg(ResVReg);
179 SPIRVTypeInst OpType = GR->getSPIRVTypeForVReg(OpReg);
180 assert(ResType && OpType && "Operand types are expected");
181 if (!GR->isBitcastCompatible(ResType, OpType))
182 report_fatal_error("incompatible result and operand types in a bitcast");
183 MachineRegisterInfo *MRI = MIB.getMRI();
184 if (!MRI->getRegClassOrNull(ResVReg))
185 MRI->setRegClass(ResVReg, GR->getRegClass(ResType));
186 if (ResType == OpType)
187 MIB.buildInstr(TargetOpcode::COPY).addDef(ResVReg).addUse(OpReg);
188 else
189 MIB.buildInstr(SPIRV::OpBitcast)
190 .addDef(ResVReg)
191 .addUse(GR->getSPIRVTypeID(ResType))
192 .addUse(OpReg);
193}
194
195// We lower G_BITCAST to OpBitcast here to avoid a MachineVerifier error.
196// The verifier checks if the source and destination LLTs of a G_BITCAST are
197// different, but this check is too strict for SPIR-V's typed pointers, which
198// may have the same LLT but different SPIRV type (e.g. pointers to different
199// pointee types). By lowering to OpBitcast here, we bypass the verifier's
200// check. See discussion in https://github.com/llvm/llvm-project/pull/110270
201// for more context.
202//
203// We also handle the llvm.spv.bitcast intrinsic here. If the source and
204// destination SPIR-V types are the same, we lower it to a COPY to enable
205// further optimizations like copy propagation.
207 MachineIRBuilder MIB) {
209 for (MachineBasicBlock &MBB : MF) {
210 for (MachineInstr &MI : MBB) {
211 if (isSpvIntrinsic(MI, Intrinsic::spv_bitcast)) {
212 Register DstReg = MI.getOperand(0).getReg();
213 Register SrcReg = MI.getOperand(2).getReg();
214 SPIRVTypeInst DstType = GR->getSPIRVTypeForVReg(DstReg);
215 assert(
216 DstType &&
217 "Expected destination SPIR-V type to have been assigned already.");
218 SPIRVTypeInst SrcType = GR->getSPIRVTypeForVReg(SrcReg);
219 assert(SrcType &&
220 "Expected source SPIR-V type to have been assigned already.");
221 if (DstType == SrcType) {
222 MIB.setInsertPt(*MI.getParent(), MI);
223 MIB.buildCopy(DstReg, SrcReg);
224 ToErase.push_back(&MI);
225 continue;
226 }
227 }
228
229 if (MI.getOpcode() != TargetOpcode::G_BITCAST)
230 continue;
231
232 MIB.setInsertPt(*MI.getParent(), MI);
233 buildOpBitcast(GR, MIB, MI.getOperand(0).getReg(),
234 MI.getOperand(1).getReg());
235 ToErase.push_back(&MI);
236 }
237 }
238 for (MachineInstr *MI : ToErase) {
240 MI->eraseFromParent();
241 }
242}
243
245 MachineIRBuilder MIB) {
246 // Get access to information about available extensions
247 const SPIRVSubtarget *ST =
248 static_cast<const SPIRVSubtarget *>(&MIB.getMF().getSubtarget());
250 for (MachineBasicBlock &MBB : MF) {
251 for (MachineInstr &MI : MBB) {
252 if (!isSpvIntrinsic(MI, Intrinsic::spv_ptrcast))
253 continue;
254 assert(MI.getOperand(2).isReg());
255 MIB.setInsertPt(*MI.getParent(), MI);
256 ToErase.push_back(&MI);
257 Register Def = MI.getOperand(0).getReg();
258 Register Source = MI.getOperand(2).getReg();
259 Type *ElemTy = getMDOperandAsType(MI.getOperand(3).getMetadata(), 0);
260 auto SC =
261 isa<FunctionType>(ElemTy)
262 ? SPIRV::StorageClass::CodeSectionINTEL
263 : addressSpaceToStorageClass(MI.getOperand(4).getImm(), *ST);
264 SPIRVTypeInst AssignedPtrType =
265 GR->getOrCreateSPIRVPointerType(ElemTy, MI, SC);
266
267 // If the ptrcast would be redundant, replace all uses with the source
268 // register.
269 MachineRegisterInfo *MRI = MIB.getMRI();
270 if (GR->getSPIRVTypeForVReg(Source) == AssignedPtrType) {
271 // Erase Def's assign type instruction if we are going to replace Def.
272 if (MachineInstr *AssignMI = findAssignTypeInstr(Def, MRI))
273 ToErase.push_back(AssignMI);
274 MRI->replaceRegWith(Def, Source);
275 } else {
276 if (!GR->getSPIRVTypeForVReg(Def, &MF))
277 GR->assignSPIRVTypeToVReg(AssignedPtrType, Def, MF);
278 MIB.buildBitcast(Def, Source);
279 }
280 }
281 }
282 for (MachineInstr *MI : ToErase) {
284 MI->eraseFromParent();
285 }
286}
287
288// Translating GV, IRTranslator sometimes generates following IR:
289// %1 = G_GLOBAL_VALUE
290// %2 = COPY %1
291// %3 = G_ADDRSPACE_CAST %2
292//
293// or
294//
295// %1 = G_ZEXT %2
296// G_MEMCPY ... %2 ...
297//
298// New registers have no SPIRV type and no register class info.
299//
300// Set SPIRV type for GV, propagate it from GV to other instructions,
301// also set register classes.
305 MachineIRBuilder &MIB) {
306 SPIRVTypeInst SpvType = nullptr;
307 assert(MI && "Machine instr is expected");
308 if (MI->getOperand(0).isReg()) {
309 Register Reg = MI->getOperand(0).getReg();
310 SpvType = GR->getSPIRVTypeForVReg(Reg);
311 if (!SpvType) {
312 switch (MI->getOpcode()) {
313 case TargetOpcode::G_FCONSTANT:
314 case TargetOpcode::G_CONSTANT: {
315 MIB.setInsertPt(*MI->getParent(), MI);
316 Type *Ty = MI->getOperand(1).getCImm()->getType();
317 SpvType = GR->getOrCreateSPIRVType(
318 Ty, MIB, SPIRV::AccessQualifier::ReadWrite, true);
319 break;
320 }
321 case TargetOpcode::G_GLOBAL_VALUE: {
322 MIB.setInsertPt(*MI->getParent(), MI);
323 const GlobalValue *Global = MI->getOperand(1).getGlobal();
325 auto *Ty = TypedPointerType::get(ElementTy,
326 Global->getType()->getAddressSpace());
327 SpvType = GR->getOrCreateSPIRVType(
328 Ty, MIB, SPIRV::AccessQualifier::ReadWrite, true);
329 break;
330 }
331 case TargetOpcode::G_ANYEXT:
332 case TargetOpcode::G_SEXT:
333 case TargetOpcode::G_ZEXT: {
334 if (MI->getOperand(1).isReg()) {
335 if (MachineInstr *DefInstr =
336 MRI.getVRegDef(MI->getOperand(1).getReg())) {
337 if (SPIRVTypeInst Def =
338 propagateSPIRVType(DefInstr, GR, MRI, MIB)) {
339 unsigned CurrentBW = GR->getScalarOrVectorBitWidth(Def);
340 unsigned ExpectedBW =
341 std::max(MRI.getType(Reg).getScalarSizeInBits(), CurrentBW);
342 unsigned NumElements = GR->getScalarOrVectorComponentCount(Def);
343 SpvType = GR->getOrCreateSPIRVIntegerType(ExpectedBW, MIB);
344 if (NumElements > 1)
345 SpvType = GR->getOrCreateSPIRVVectorType(SpvType, NumElements,
346 MIB, true);
347 }
348 }
349 }
350 break;
351 }
352 case TargetOpcode::G_PTRTOINT:
353 SpvType = GR->getOrCreateSPIRVIntegerType(
354 MRI.getType(Reg).getScalarSizeInBits(), MIB);
355 break;
356 case TargetOpcode::G_TRUNC:
357 case TargetOpcode::G_ADDRSPACE_CAST:
358 case TargetOpcode::G_PTR_ADD:
359 case TargetOpcode::COPY: {
360 MachineOperand &Op = MI->getOperand(1);
361 MachineInstr *Def = Op.isReg() ? MRI.getVRegDef(Op.getReg()) : nullptr;
362 if (Def)
363 SpvType = propagateSPIRVType(Def, GR, MRI, MIB);
364 break;
365 }
366 default:
367 break;
368 }
369 if (SpvType) {
370 // check if the address space needs correction
371 LLT RegType = MRI.getType(Reg);
372 if (SpvType->getOpcode() == SPIRV::OpTypePointer &&
373 RegType.isPointer() &&
375 RegType.getAddressSpace()) {
376 const SPIRVSubtarget &ST =
377 MI->getParent()->getParent()->getSubtarget<SPIRVSubtarget>();
378 auto TSC = addressSpaceToStorageClass(RegType.getAddressSpace(), ST);
379 SpvType = GR->changePointerStorageClass(SpvType, TSC, *MI);
380 }
381 GR->assignSPIRVTypeToVReg(SpvType, Reg, MIB.getMF());
382 }
383 if (!MRI.getRegClassOrNull(Reg))
384 MRI.setRegClass(Reg, SpvType ? GR->getRegClass(SpvType)
385 : &SPIRV::iIDRegClass);
386 }
387 }
388 return SpvType;
389}
390
391// To support current approach and limitations wrt. bit width here we widen a
392// scalar register with a bit width greater than 1 to valid sizes and cap it to
393// 128 width.
394static unsigned widenBitWidthToNextPow2(unsigned BitWidth) {
395 if (BitWidth == 1)
396 return 1; // No need to widen 1-bit values
397 return std::min(std::max(1u << Log2_32_Ceil(BitWidth), 8u), 128u);
398}
399
401 LLT RegType = MRI.getType(Reg);
402 if (!RegType.isScalar())
403 return;
404 unsigned CurrentWidth = RegType.getScalarSizeInBits();
405 unsigned NewWidth = widenBitWidthToNextPow2(CurrentWidth);
406 if (NewWidth != CurrentWidth)
407 MRI.setType(Reg, LLT::scalar(NewWidth));
408}
409
410static void widenCImmType(MachineOperand &MOP) {
411 const ConstantInt *CImmVal = MOP.getCImm();
412 unsigned CurrentWidth = CImmVal->getBitWidth();
413 unsigned NewWidth = widenBitWidthToNextPow2(CurrentWidth);
414 if (NewWidth != CurrentWidth) {
415 // Replace the immediate value with the widened version
416 MOP.setCImm(ConstantInt::get(CImmVal->getType()->getContext(),
417 CImmVal->getValue().zextOrTrunc(NewWidth)));
418 }
419}
420
422 MachineBasicBlock &MBB = *Def->getParent();
424 Def->getNextNode() ? Def->getNextNode()->getIterator() : MBB.end();
425 // Skip all the PHI and debug instructions.
426 while (DefIt != MBB.end() &&
427 (DefIt->isPHI() || DefIt->isDebugOrPseudoInstr()))
428 DefIt = std::next(DefIt);
429 MIB.setInsertPt(MBB, DefIt);
430}
431
432namespace llvm {
435 MachineRegisterInfo &MRI) {
436 assert((Ty || SpvType) && "Either LLVM or SPIRV type is expected.");
437 MachineInstr *Def = MRI.getVRegDef(Reg);
438 setInsertPtAfterDef(MIB, Def);
439 if (!SpvType)
440 SpvType = GR->getOrCreateSPIRVType(Ty, MIB,
441 SPIRV::AccessQualifier::ReadWrite, true);
442 if (!MRI.getRegClassOrNull(Reg))
443 MRI.setRegClass(Reg, GR->getRegClass(SpvType));
444 if (!MRI.getType(Reg).isValid())
445 MRI.setType(Reg, GR->getRegType(SpvType));
446 GR->assignSPIRVTypeToVReg(SpvType, Reg, MIB.getMF());
447}
448
451 SPIRVTypeInst KnownResType) {
452 MIB.setInsertPt(*MI.getParent(), MI.getIterator());
453 for (auto &Op : MI.operands()) {
454 if (!Op.isReg() || Op.isDef())
455 continue;
456 Register OpReg = Op.getReg();
457 SPIRVTypeInst SpvType = GR->getSPIRVTypeForVReg(OpReg);
458 if (!SpvType && KnownResType) {
459 SpvType = KnownResType;
460 GR->assignSPIRVTypeToVReg(KnownResType, OpReg, *MI.getMF());
461 }
462 assert(SpvType);
463 if (!MRI.getRegClassOrNull(OpReg))
464 MRI.setRegClass(OpReg, GR->getRegClass(SpvType));
465 if (!MRI.getType(OpReg).isValid())
466 MRI.setType(OpReg, GR->getRegType(SpvType));
467 }
468}
469} // namespace llvm
470
471static void
474 DenseMap<MachineInstr *, Type *> &TargetExtConstTypes) {
475 // Get access to information about available extensions
476 const SPIRVSubtarget *ST =
477 static_cast<const SPIRVSubtarget *>(&MIB.getMF().getSubtarget());
478
481 DenseMap<MachineInstr *, Register> RegsAlreadyAddedToDT;
482
483 bool IsExtendedInts =
484 ST->canUseExtension(
485 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers) ||
486 ST->canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions) ||
487 ST->canUseExtension(SPIRV::Extension::SPV_INTEL_int4);
488
489 if (!IsExtendedInts) {
490 // Without arbitrary precision integer extensions, SPIR-V only supports
491 // integer widths of 8, 16, 32, 64. Non-standard widths (e.g., i24, i40)
492 // must be widened to the next power of two.
493 //
494 // G_TRUNC requires special handling because its semantics depend on the
495 // original destination width. For example:
496 // %dst:s24 = G_TRUNC %src:s64
497 // After widening s24 to s32, we cannot simply do:
498 // %dst:s32 = G_TRUNC %src:s64
499 // because this would keep 32 bits instead of 24. Instead, we insert a
500 // G_AND to mask the value to the original width:
501 // %mask:s64 = G_CONSTANT 0xFFFFFF ; 24-bit mask
502 // %masked:s64 = G_AND %src:s64, %mask
503 // %dst:s32 = G_TRUNC %masked:s64
504 // If src and dst widen to the same size, G_TRUNC is replaced entirely:
505 // %mask:s64 = G_CONSTANT 0xFFFFFFFFFF ; 40-bit mask
506 // %dst:s64 = G_AND %src:s64, %mask
507 SmallVector<MachineInstr *, 8> TruncToRemove;
508 for (MachineBasicBlock &MBB : MF) {
509 for (MachineInstr &MI : MBB) {
510 unsigned MIOp = MI.getOpcode();
511 if (MIOp != TargetOpcode::G_TRUNC)
512 continue;
513 assert(MI.getNumOperands() == 2);
514 assert(MI.getOperand(0).isReg());
515 assert(MI.getOperand(1).isReg());
516
517 Register DstReg = MI.getOperand(0).getReg();
518 Register SrcReg = MI.getOperand(1).getReg();
519
520 // TODO: handle vector types.
521 if (!MRI.getType(DstReg).isScalar()) {
522 assert(!MRI.getType(SrcReg).isScalar());
523 continue;
524 }
525
526 unsigned OriginalDstWidth = MRI.getType(DstReg).getScalarSizeInBits();
527 unsigned OriginalSrcWidth = MRI.getType(SrcReg).getScalarSizeInBits();
528
529 unsigned NewDstWidth = widenBitWidthToNextPow2(OriginalDstWidth);
530 unsigned NewSrcWidth = widenBitWidthToNextPow2(OriginalSrcWidth);
531
532 // No Dst width change means no truncation semantics change.
533 if (OriginalDstWidth == NewDstWidth)
534 continue;
535
536 MRI.setType(SrcReg, LLT::scalar(NewSrcWidth));
537 MRI.setType(DstReg, LLT::scalar(NewDstWidth));
538
539 MIB.setInsertPt(MBB, MI.getIterator());
540 APInt Mask = APInt::getLowBitsSet(NewSrcWidth, OriginalDstWidth);
541 auto MaskReg = MIB.buildConstant(LLT::scalar(NewSrcWidth), Mask);
542 Register MaskedReg =
544 MIB.buildAnd(MaskedReg, SrcReg, MaskReg);
545
546 if (NewSrcWidth == NewDstWidth) {
547 MRI.replaceRegWith(DstReg, MaskedReg);
548 TruncToRemove.push_back(&MI);
549 } else {
550 MI.getOperand(1).setReg(MaskedReg);
551 }
552 }
553 }
554 for (MachineInstr *MI : TruncToRemove)
555 MI->eraseFromParent();
556 }
557
558 for (MachineBasicBlock *MBB : post_order(&MF)) {
559 if (MBB->empty())
560 continue;
561
562 bool ReachedBegin = false;
563 for (auto MII = std::prev(MBB->end()), Begin = MBB->begin();
564 !ReachedBegin;) {
565 MachineInstr &MI = *MII;
566 unsigned MIOp = MI.getOpcode();
567
568 if (!IsExtendedInts) {
569 // validate bit width of scalar registers and constant immediates
570 for (auto &MOP : MI.operands()) {
571 if (MOP.isReg())
572 widenScalarType(MOP.getReg(), MRI);
573 else if (MOP.isCImm())
574 widenCImmType(MOP);
575 }
576 }
577
578 if (isSpvIntrinsic(MI, Intrinsic::spv_assign_ptr_type)) {
579 Register Reg = MI.getOperand(1).getReg();
580 MIB.setInsertPt(*MI.getParent(), MI.getIterator());
581 Type *ElementTy = getMDOperandAsType(MI.getOperand(2).getMetadata(), 0);
582 SPIRVTypeInst AssignedPtrType = GR->getOrCreateSPIRVPointerType(
583 ElementTy, MI,
584 addressSpaceToStorageClass(MI.getOperand(3).getImm(), *ST));
585 MachineInstr *Def = MRI.getVRegDef(Reg);
586 assert(Def && "Expecting an instruction that defines the register");
587 // G_GLOBAL_VALUE already has type info.
588 if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE)
589 updateRegType(Reg, nullptr, AssignedPtrType, GR, MIB,
590 MF.getRegInfo());
591 ToErase.push_back(&MI);
592 } else if (isSpvIntrinsic(MI, Intrinsic::spv_assign_type)) {
593 Register Reg = MI.getOperand(1).getReg();
594 Type *Ty = getMDOperandAsType(MI.getOperand(2).getMetadata(), 0);
595 MachineInstr *Def = MRI.getVRegDef(Reg);
596 assert(Def && "Expecting an instruction that defines the register");
597 // G_GLOBAL_VALUE already has type info.
598 if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE)
599 updateRegType(Reg, Ty, nullptr, GR, MIB, MF.getRegInfo());
600 ToErase.push_back(&MI);
601 } else if (MIOp == TargetOpcode::FAKE_USE && MI.getNumOperands() > 0) {
602 MachineInstr *MdMI = MI.getPrevNode();
603 if (MdMI && isSpvIntrinsic(*MdMI, Intrinsic::spv_value_md)) {
604 // It's an internal service info from before IRTranslator passes.
605 MachineInstr *Def = getVRegDef(MRI, MI.getOperand(0).getReg());
606 for (unsigned I = 1, E = MI.getNumOperands(); I != E && Def; ++I)
607 if (getVRegDef(MRI, MI.getOperand(I).getReg()) != Def)
608 Def = nullptr;
609 if (Def) {
610 const MDNode *MD = MdMI->getOperand(1).getMetadata();
612 cast<MDString>(MD->getOperand(1))->getString();
613 const MDNode *TypeMD = cast<MDNode>(MD->getOperand(0));
614 Type *ValueTy = getMDOperandAsType(TypeMD, 0);
615 GR->addValueAttrs(Def, std::make_pair(ValueTy, ValueName.str()));
616 }
617 ToErase.push_back(MdMI);
618 }
619 ToErase.push_back(&MI);
620 } else if (MIOp == TargetOpcode::G_CONSTANT ||
621 MIOp == TargetOpcode::G_FCONSTANT ||
622 MIOp == TargetOpcode::G_BUILD_VECTOR) {
623 // %rc = G_CONSTANT ty Val
624 // Ensure %rc has a valid SPIR-V type assigned in the Global Registry.
625 Register Reg = MI.getOperand(0).getReg();
626 bool NeedAssignType = !GR->getSPIRVTypeForVReg(Reg);
627 Type *Ty = nullptr;
628 if (MIOp == TargetOpcode::G_CONSTANT) {
629 auto TargetExtIt = TargetExtConstTypes.find(&MI);
630 Ty = TargetExtIt == TargetExtConstTypes.end()
631 ? MI.getOperand(1).getCImm()->getType()
632 : TargetExtIt->second;
633 const ConstantInt *OpCI = MI.getOperand(1).getCImm();
634 // TODO: we may wish to analyze here if OpCI is zero and LLT RegType =
635 // MRI.getType(Reg); RegType.isPointer() is true, so that we observe
636 // at this point not i64/i32 constant but null pointer in the
637 // corresponding address space of RegType.getAddressSpace(). This may
638 // help to successfully validate the case when a OpConstantComposite's
639 // constituent has type that does not match Result Type of
640 // OpConstantComposite (see, for example,
641 // pointers/PtrCast-null-in-OpSpecConstantOp.ll).
642 Register PrimaryReg = GR->find(OpCI, &MF);
643 if (!PrimaryReg.isValid()) {
644 GR->add(OpCI, &MI);
645 } else if (PrimaryReg != Reg &&
646 MRI.getType(Reg) == MRI.getType(PrimaryReg)) {
647 auto *RCReg = MRI.getRegClassOrNull(Reg);
648 auto *RCPrimary = MRI.getRegClassOrNull(PrimaryReg);
649 if (!RCReg || RCPrimary == RCReg) {
650 RegsAlreadyAddedToDT[&MI] = PrimaryReg;
651 ToErase.push_back(&MI);
652 NeedAssignType = false;
653 }
654 }
655 } else if (MIOp == TargetOpcode::G_FCONSTANT) {
656 Ty = MI.getOperand(1).getFPImm()->getType();
657 } else {
658 assert(MIOp == TargetOpcode::G_BUILD_VECTOR);
659 Type *ElemTy = nullptr;
660 MachineInstr *ElemMI = MRI.getVRegDef(MI.getOperand(1).getReg());
661 assert(ElemMI);
662
663 if (ElemMI->getOpcode() == TargetOpcode::G_CONSTANT) {
664 ElemTy = ElemMI->getOperand(1).getCImm()->getType();
665 } else if (ElemMI->getOpcode() == TargetOpcode::G_FCONSTANT) {
666 ElemTy = ElemMI->getOperand(1).getFPImm()->getType();
667 } else {
668 if (SPIRVTypeInst ElemSpvType =
669 GR->getSPIRVTypeForVReg(MI.getOperand(1).getReg(), &MF))
670 ElemTy = const_cast<Type *>(GR->getTypeForSPIRVType(ElemSpvType));
671 }
672 if (ElemTy)
673 Ty = VectorType::get(
674 ElemTy, MI.getNumExplicitOperands() - MI.getNumExplicitDefs(),
675 false);
676 else
677 NeedAssignType = false;
678 }
679 if (NeedAssignType)
680 updateRegType(Reg, Ty, nullptr, GR, MIB, MRI);
681 } else if (MIOp == TargetOpcode::G_GLOBAL_VALUE) {
682 propagateSPIRVType(&MI, GR, MRI, MIB);
683 }
684
685 if (MII == Begin)
686 ReachedBegin = true;
687 else
688 --MII;
689 }
690 }
691 for (MachineInstr *MI : ToErase) {
692 auto It = RegsAlreadyAddedToDT.find(MI);
693 if (It != RegsAlreadyAddedToDT.end())
694 MRI.replaceRegWith(MI->getOperand(0).getReg(), It->second);
696 MI->eraseFromParent();
697 }
698
699 // Address the case when IRTranslator introduces instructions with new
700 // registers without associated SPIRV type.
701 for (MachineBasicBlock &MBB : MF) {
702 for (MachineInstr &MI : MBB) {
703 switch (MI.getOpcode()) {
704 case TargetOpcode::G_TRUNC:
705 case TargetOpcode::G_ANYEXT:
706 case TargetOpcode::G_SEXT:
707 case TargetOpcode::G_ZEXT:
708 case TargetOpcode::G_PTRTOINT:
709 case TargetOpcode::COPY:
710 case TargetOpcode::G_ADDRSPACE_CAST:
711 propagateSPIRVType(&MI, GR, MRI, MIB);
712 break;
713 }
714 }
715 }
716}
717
720 MachineIRBuilder MIB) {
722 for (MachineBasicBlock &MBB : MF)
723 for (MachineInstr &MI : MBB)
724 if (isTypeFoldingSupported(MI.getOpcode()))
725 processInstr(MI, MIB, MRI, GR, nullptr);
726}
727
728static Register
730 SmallVector<unsigned, 4> *Ops = nullptr) {
731 Register DefReg;
732 unsigned StartOp = InlineAsm::MIOp_FirstOperand,
734 for (unsigned Idx = StartOp, MISz = MI->getNumOperands(); Idx != MISz;
735 ++Idx) {
736 const MachineOperand &MO = MI->getOperand(Idx);
737 if (MO.isMetadata())
738 continue;
739 if (Idx == AsmDescOp && MO.isImm()) {
740 // compute the index of the next operand descriptor
741 const InlineAsm::Flag F(MO.getImm());
742 AsmDescOp += 1 + F.getNumOperandRegisters();
743 continue;
744 }
745 if (MO.isReg() && MO.isDef()) {
746 if (!Ops)
747 return MO.getReg();
748 else
749 DefReg = MO.getReg();
750 } else if (Ops) {
751 Ops->push_back(Idx);
752 }
753 }
754 return DefReg;
755}
756
757static void
759 const SPIRVSubtarget &ST, MachineIRBuilder MIRBuilder,
760 const SmallVector<MachineInstr *> &ToProcess) {
762 Register AsmTargetReg;
763 for (unsigned i = 0, Sz = ToProcess.size(); i + 1 < Sz; i += 2) {
764 MachineInstr *I1 = ToProcess[i], *I2 = ToProcess[i + 1];
765 assert(isSpvIntrinsic(*I1, Intrinsic::spv_inline_asm) && I2->isInlineAsm());
766 MIRBuilder.setInsertPt(*I2->getParent(), *I2);
767
768 if (!AsmTargetReg.isValid()) {
769 // define vendor specific assembly target or dialect
770 AsmTargetReg = MRI.createGenericVirtualRegister(LLT::scalar(32));
771 MRI.setRegClass(AsmTargetReg, &SPIRV::iIDRegClass);
772 auto AsmTargetMIB =
773 MIRBuilder.buildInstr(SPIRV::OpAsmTargetINTEL).addDef(AsmTargetReg);
774 addStringImm(ST.getTargetTripleAsStr(), AsmTargetMIB);
775 GR->add(AsmTargetMIB.getInstr(), AsmTargetMIB);
776 }
777
778 // create types
779 const MDNode *IAMD = I1->getOperand(1).getMetadata();
782 for (const auto &ArgTy : FTy->params())
783 ArgTypes.push_back(GR->getOrCreateSPIRVType(
784 ArgTy, MIRBuilder, SPIRV::AccessQualifier::ReadWrite, true));
785 SPIRVTypeInst RetType =
786 GR->getOrCreateSPIRVType(FTy->getReturnType(), MIRBuilder,
787 SPIRV::AccessQualifier::ReadWrite, true);
789 FTy, RetType, ArgTypes, MIRBuilder);
790
791 // define vendor specific assembly instructions string
793 MRI.setRegClass(AsmReg, &SPIRV::iIDRegClass);
794 auto AsmMIB = MIRBuilder.buildInstr(SPIRV::OpAsmINTEL)
795 .addDef(AsmReg)
796 .addUse(GR->getSPIRVTypeID(RetType))
797 .addUse(GR->getSPIRVTypeID(FuncType))
798 .addUse(AsmTargetReg);
799 // inline asm string:
800 addStringImm(I2->getOperand(InlineAsm::MIOp_AsmString).getSymbolName(),
801 AsmMIB);
802 // inline asm constraint string:
803 addStringImm(cast<MDString>(I1->getOperand(2).getMetadata()->getOperand(0))
804 ->getString(),
805 AsmMIB);
806 GR->add(AsmMIB.getInstr(), AsmMIB);
807
808 // calls the inline assembly instruction
809 unsigned ExtraInfo = I2->getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
810 if (ExtraInfo & InlineAsm::Extra_HasSideEffects)
811 MIRBuilder.buildInstr(SPIRV::OpDecorate)
812 .addUse(AsmReg)
813 .addImm(static_cast<uint32_t>(SPIRV::Decoration::SideEffectsINTEL));
814
816 if (!DefReg.isValid()) {
818 MRI.setRegClass(DefReg, &SPIRV::iIDRegClass);
819 SPIRVTypeInst VoidType = GR->getOrCreateSPIRVType(
820 Type::getVoidTy(MF.getFunction().getContext()), MIRBuilder,
821 SPIRV::AccessQualifier::ReadWrite, true);
822 GR->assignSPIRVTypeToVReg(VoidType, DefReg, MF);
823 }
824
825 auto AsmCall = MIRBuilder.buildInstr(SPIRV::OpAsmCallINTEL)
826 .addDef(DefReg)
827 .addUse(GR->getSPIRVTypeID(RetType))
828 .addUse(AsmReg);
829 for (unsigned IntrIdx = 3; IntrIdx < I1->getNumOperands(); ++IntrIdx)
830 AsmCall.addUse(I1->getOperand(IntrIdx).getReg());
831 }
832 for (MachineInstr *MI : ToProcess) {
834 MI->eraseFromParent();
835 }
836}
837
839 const SPIRVSubtarget &ST,
840 MachineIRBuilder MIRBuilder) {
842 for (MachineBasicBlock &MBB : MF) {
843 for (MachineInstr &MI : MBB) {
844 if (isSpvIntrinsic(MI, Intrinsic::spv_inline_asm) ||
845 MI.getOpcode() == TargetOpcode::INLINEASM)
846 ToProcess.push_back(&MI);
847 }
848 }
849 if (ToProcess.size() == 0)
850 return;
851
852 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly))
853 report_fatal_error("Inline assembly instructions require the "
854 "following SPIR-V extension: SPV_INTEL_inline_assembly",
855 false);
856
857 insertInlineAsmProcess(MF, GR, ST, MIRBuilder, ToProcess);
858}
859
861 union {
862 float F;
863 uint32_t Spir;
864 } FPMaxError;
865 FPMaxError.F = F;
866 return FPMaxError.Spir;
867}
868
870 MachineIRBuilder MIB) {
873 for (MachineBasicBlock &MBB : MF) {
874 for (MachineInstr &MI : MBB) {
875 if (!isSpvIntrinsic(MI, Intrinsic::spv_assign_decoration) &&
876 !isSpvIntrinsic(MI, Intrinsic::spv_assign_aliasing_decoration) &&
877 !isSpvIntrinsic(MI, Intrinsic::spv_assign_fpmaxerror_decoration))
878 continue;
879 MIB.setInsertPt(*MI.getParent(), MI.getNextNode());
880 if (isSpvIntrinsic(MI, Intrinsic::spv_assign_decoration)) {
881 buildOpSpirvDecorations(MI.getOperand(1).getReg(), MIB,
882 MI.getOperand(2).getMetadata(), ST);
883 } else if (isSpvIntrinsic(MI,
884 Intrinsic::spv_assign_fpmaxerror_decoration)) {
886 MI.getOperand(2).getMetadata()->getOperand(0));
887 uint32_t OpValue =
889
890 buildOpDecorate(MI.getOperand(1).getReg(), MIB,
891 SPIRV::Decoration::FPMaxErrorDecorationINTEL,
892 {OpValue});
893 } else {
894 GR->buildMemAliasingOpDecorate(MI.getOperand(1).getReg(), MIB,
895 MI.getOperand(2).getImm(),
896 MI.getOperand(3).getMetadata());
897 }
898
899 ToErase.push_back(&MI);
900 }
901 }
902 for (MachineInstr *MI : ToErase) {
904 MI->eraseFromParent();
905 }
906}
907
908// LLVM allows the switches to use registers as cases, while SPIR-V required
909// those to be immediate values. This function replaces such operands with the
910// equivalent immediate constant.
913 MachineIRBuilder MIB) {
915 for (MachineBasicBlock &MBB : MF) {
916 for (MachineInstr &MI : MBB) {
917 if (!isSpvIntrinsic(MI, Intrinsic::spv_switch))
918 continue;
919
921 NewOperands.push_back(MI.getOperand(0)); // Opcode
922 NewOperands.push_back(MI.getOperand(1)); // Condition
923 NewOperands.push_back(MI.getOperand(2)); // Default
924 for (unsigned i = 3; i < MI.getNumOperands(); i += 2) {
925 Register Reg = MI.getOperand(i).getReg();
926 MachineInstr *ConstInstr = getDefInstrMaybeConstant(Reg, &MRI);
927 NewOperands.push_back(
929
930 NewOperands.push_back(MI.getOperand(i + 1));
931 }
932
933 assert(MI.getNumOperands() == NewOperands.size());
934 while (MI.getNumOperands() > 0)
935 MI.removeOperand(0);
936 for (auto &MO : NewOperands)
937 MI.addOperand(MO);
938 }
939 }
940}
941
942// Some instructions are used during CodeGen but should never be emitted.
943// Cleaning up those.
947 for (MachineBasicBlock &MBB : MF) {
948 for (MachineInstr &MI : MBB) {
949 if (isSpvIntrinsic(MI, Intrinsic::spv_track_constant) ||
950 MI.getOpcode() == TargetOpcode::G_BRINDIRECT)
951 ToEraseMI.push_back(&MI);
952 }
953 }
954
955 for (MachineInstr *MI : ToEraseMI) {
957 MI->eraseFromParent();
958 }
959}
960
961// Find all usages of G_BLOCK_ADDR in our intrinsics and replace those
962// operands/registers by the actual MBB it references.
964 MachineIRBuilder MIB) {
965 // Gather the reverse-mapping BB -> MBB.
967 for (MachineBasicBlock &MBB : MF)
968 BB2MBB[MBB.getBasicBlock()] = &MBB;
969
970 // Gather instructions requiring patching. For now, only those can use
971 // G_BLOCK_ADDR.
972 SmallVector<MachineInstr *, 8> InstructionsToPatch;
973 for (MachineBasicBlock &MBB : MF) {
974 for (MachineInstr &MI : MBB) {
975 if (isSpvIntrinsic(MI, Intrinsic::spv_switch) ||
976 isSpvIntrinsic(MI, Intrinsic::spv_loop_merge) ||
977 isSpvIntrinsic(MI, Intrinsic::spv_selection_merge))
978 InstructionsToPatch.push_back(&MI);
979 }
980 }
981
982 // For each instruction to fix, we replace all the G_BLOCK_ADDR operands by
983 // the actual MBB it references. Once those references have been updated, we
984 // can cleanup remaining G_BLOCK_ADDR references.
985 SmallPtrSet<MachineBasicBlock *, 8> ClearAddressTaken;
988 for (MachineInstr *MI : InstructionsToPatch) {
990 for (unsigned i = 0; i < MI->getNumOperands(); ++i) {
991 // The operand is not a register, keep as-is.
992 if (!MI->getOperand(i).isReg()) {
993 NewOps.push_back(MI->getOperand(i));
994 continue;
995 }
996
997 Register Reg = MI->getOperand(i).getReg();
998 MachineInstr *BuildMBB = MRI.getVRegDef(Reg);
999 // The register is not the result of G_BLOCK_ADDR, keep as-is.
1000 if (!BuildMBB || BuildMBB->getOpcode() != TargetOpcode::G_BLOCK_ADDR) {
1001 NewOps.push_back(MI->getOperand(i));
1002 continue;
1003 }
1004
1005 assert(BuildMBB && BuildMBB->getOpcode() == TargetOpcode::G_BLOCK_ADDR &&
1006 BuildMBB->getOperand(1).isBlockAddress() &&
1007 BuildMBB->getOperand(1).getBlockAddress());
1008 BasicBlock *BB =
1009 BuildMBB->getOperand(1).getBlockAddress()->getBasicBlock();
1010 auto It = BB2MBB.find(BB);
1011 if (It == BB2MBB.end())
1012 report_fatal_error("cannot find a machine basic block by a basic block "
1013 "in a switch statement");
1014 MachineBasicBlock *ReferencedBlock = It->second;
1015 NewOps.push_back(MachineOperand::CreateMBB(ReferencedBlock));
1016
1017 ClearAddressTaken.insert(ReferencedBlock);
1018 ToEraseMI.insert(BuildMBB);
1019 }
1020
1021 // Replace the operands.
1022 assert(MI->getNumOperands() == NewOps.size());
1023 while (MI->getNumOperands() > 0)
1024 MI->removeOperand(0);
1025 for (auto &MO : NewOps)
1026 MI->addOperand(MO);
1027
1028 if (MachineInstr *Next = MI->getNextNode()) {
1029 if (isSpvIntrinsic(*Next, Intrinsic::spv_track_constant)) {
1030 ToEraseMI.insert(Next);
1031 Next = MI->getNextNode();
1032 }
1033 if (Next && Next->getOpcode() == TargetOpcode::G_BRINDIRECT)
1034 ToEraseMI.insert(Next);
1035 }
1036 }
1037
1038 // BlockAddress operands were used to keep information between passes,
1039 // let's undo the "address taken" status to reflect that Succ doesn't
1040 // actually correspond to an IR-level basic block.
1041 for (MachineBasicBlock *Succ : ClearAddressTaken)
1042 Succ->setAddressTakenIRBlock(nullptr);
1043
1044 // If we just delete G_BLOCK_ADDR instructions with BlockAddress operands,
1045 // this leaves their BasicBlock counterparts in a "address taken" status. This
1046 // would make AsmPrinter to generate a series of unneeded labels of a "Address
1047 // of block that was removed by CodeGen" kind. Let's first ensure that we
1048 // don't have a dangling BlockAddress constants by zapping the BlockAddress
1049 // nodes, and only after that proceed with erasing G_BLOCK_ADDR instructions.
1050 Constant *Replacement =
1051 ConstantInt::get(Type::getInt32Ty(MF.getFunction().getContext()), 1);
1052 for (MachineInstr *BlockAddrI : ToEraseMI) {
1053 if (BlockAddrI->getOpcode() == TargetOpcode::G_BLOCK_ADDR) {
1054 BlockAddress *BA = const_cast<BlockAddress *>(
1055 BlockAddrI->getOperand(1).getBlockAddress());
1057 ConstantExpr::getIntToPtr(Replacement, BA->getType()));
1058 BA->destroyConstant();
1059 }
1060 GR->invalidateMachineInstr(BlockAddrI);
1061 BlockAddrI->eraseFromParent();
1062 }
1063}
1064
1066 if (MBB.empty())
1067 return MBB.getNextNode() != nullptr;
1068
1069 // Branching SPIR-V intrinsics are not detected by this generic method.
1070 // Thus, we can only trust negative result.
1071 if (!MBB.canFallThrough())
1072 return false;
1073
1074 // Otherwise, we must manually check if we have a SPIR-V intrinsic which
1075 // prevent an implicit fallthrough.
1076 for (MachineBasicBlock::reverse_iterator It = MBB.rbegin(), E = MBB.rend();
1077 It != E; ++It) {
1078 if (isSpvIntrinsic(*It, Intrinsic::spv_switch))
1079 return false;
1080 }
1081 return true;
1082}
1083
1085 MachineIRBuilder MIB) {
1086 // It is valid for MachineBasicBlocks to not finish with a branch instruction.
1087 // In such cases, they will simply fallthrough their immediate successor.
1088 for (MachineBasicBlock &MBB : MF) {
1090 continue;
1091
1092 assert(MBB.succ_size() == 1);
1093 MIB.setInsertPt(MBB, MBB.end());
1094 MIB.buildBr(**MBB.successors().begin());
1095 }
1096}
1097
1098bool SPIRVPreLegalizer::runOnMachineFunction(MachineFunction &MF) {
1099 // Initialize the type registry.
1100 const SPIRVSubtarget &ST = MF.getSubtarget<SPIRVSubtarget>();
1101 SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
1102 GR->setCurrentFunc(MF);
1103 MachineIRBuilder MIB(MF);
1104 // a registry of target extension constants
1105 DenseMap<MachineInstr *, Type *> TargetExtConstTypes;
1106 // to keep record of tracked constants
1107 addConstantsToTrack(MF, GR, ST, TargetExtConstTypes);
1108 foldConstantsIntoIntrinsics(MF, GR, MIB);
1109 insertBitcasts(MF, GR, MIB);
1110 generateAssignInstrs(MF, GR, MIB, TargetExtConstTypes);
1111
1112 processSwitchesConstants(MF, GR, MIB);
1113 processBlockAddr(MF, GR, MIB);
1115
1116 processInstrsWithTypeFolding(MF, GR, MIB);
1118 insertSpirvDecorations(MF, GR, MIB);
1119 insertInlineAsm(MF, GR, ST, MIB);
1120 lowerBitcasts(MF, GR, MIB);
1121
1122 return true;
1123}
1124
1125INITIALIZE_PASS(SPIRVPreLegalizer, DEBUG_TYPE, "SPIRV pre legalizer", false,
1126 false)
1127
1128char SPIRVPreLegalizer::ID = 0;
1129
1130FunctionPass *llvm::createSPIRVPreLegalizerPass() {
1131 return new SPIRVPreLegalizer();
1132}
MachineInstrBuilder & UseMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Provides analysis for continuously CSEing during GISel passes.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Provides analysis for querying information about KnownBits during GISel passes.
#define DEBUG_TYPE
IRTranslator LLVM IR MI
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
static Register collectInlineAsmInstrOperands(MachineInstr *MI, SmallVector< unsigned, 4 > *Ops=nullptr)
static void insertInlineAsm(MachineFunction &MF, SPIRVGlobalRegistry *GR, const SPIRVSubtarget &ST, MachineIRBuilder MIRBuilder)
static void cleanupHelperInstructions(MachineFunction &MF, SPIRVGlobalRegistry *GR)
static void insertInlineAsmProcess(MachineFunction &MF, SPIRVGlobalRegistry *GR, const SPIRVSubtarget &ST, MachineIRBuilder MIRBuilder, const SmallVector< MachineInstr * > &ToProcess)
static void removeImplicitFallthroughs(MachineFunction &MF, MachineIRBuilder MIB)
static unsigned widenBitWidthToNextPow2(unsigned BitWidth)
static void setInsertPtAfterDef(MachineIRBuilder &MIB, MachineInstr *Def)
static bool isImplicitFallthrough(MachineBasicBlock &MBB)
static void insertSpirvDecorations(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void insertBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void processInstrsWithTypeFolding(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void processSwitchesConstants(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void lowerBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static MachineInstr * findAssignTypeInstr(Register Reg, MachineRegisterInfo *MRI)
static void widenCImmType(MachineOperand &MOP)
static void buildOpBitcast(SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB, Register ResVReg, Register OpReg)
static void processBlockAddr(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void widenScalarType(Register Reg, MachineRegisterInfo &MRI)
static void foldConstantsIntoIntrinsics(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void addConstantsToTrack(MachineFunction &MF, SPIRVGlobalRegistry *GR, const SPIRVSubtarget &STI, DenseMap< MachineInstr *, Type * > &TargetExtConstTypes)
static uint32_t convertFloatToSPIRVWord(float F)
static SPIRVTypeInst propagateSPIRVType(MachineInstr *MI, SPIRVGlobalRegistry *GR, MachineRegisterInfo &MRI, MachineIRBuilder &MIB)
static void generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB, DenseMap< MachineInstr *, Type * > &TargetExtConstTypes)
LLVM_ABI float convertToFloat() const
Converts this APFloat to host float value.
Definition APFloat.cpp:5977
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
Definition APInt.cpp:1075
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
Definition APInt.h:307
Represent the analysis usage information of a pass.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
The address of a basic block.
Definition Constants.h:1065
BasicBlock * getBasicBlock() const
Definition Constants.h:1100
static LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
ConstantFP - Floating Point Values [float, double].
Definition Constants.h:420
const APFloat & getValueAPF() const
Definition Constants.h:463
This is the shared class of boolean and integer constants.
Definition Constants.h:87
unsigned getBitWidth() const
getBitWidth - Return the scalar bitwidth of this constant.
Definition Constants.h:162
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition Constants.h:159
This is an important base class in LLVM.
Definition Constant.h:43
LLVM_ABI void destroyConstant()
Called if some element of this constant is no longer valid.
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:178
iterator end()
Definition DenseMap.h:81
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:358
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
Metadata node.
Definition Metadata.h:1080
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1444
LLVM_ABI iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
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.
const MachineBasicBlock & front() const
Helper class to build MachineInstr.
MachineInstrBuilder buildBr(MachineBasicBlock &Dest)
Build and insert G_BR Dest.
void setInsertPt(MachineBasicBlock &MBB, MachineBasicBlock::iterator II)
Set the insertion point before the specified position.
MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_AND Op0, Op1.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildBitcast(const DstOp &Dst, const SrcOp &Src)
Build and insert Dst = G_BITCAST Src.
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 & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
const ConstantInt * getCImm() const
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
const MDNode * getMetadata() const
static MachineOperand CreateCImm(const ConstantInt *CI)
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isMetadata() const
isMetadata - Tests if this is a MO_Metadata operand.
const BlockAddress * getBlockAddress() const
void setCImm(const ConstantInt *CI)
bool isBlockAddress() const
isBlockAddress - Tests if this is a MO_BlockAddress operand.
Register getReg() const
getReg - Returns the register number.
const ConstantFP * getFPImm() const
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
static MachineOperand CreateMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
defusechain_instr_iterator< true, false, false, true > use_instr_iterator
use_instr_iterator/use_instr_begin/use_instr_end - Walk all uses of the specified register,...
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
use_instr_iterator use_instr_begin(Register RegNo) const
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
static use_instr_iterator use_instr_end()
LLVM_ABI void setType(Register VReg, LLT Ty)
Set the low-level type of VReg to Ty.
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isValid() const
Definition Register.h:112
void assignSPIRVTypeToVReg(SPIRVTypeInst Type, Register VReg, const MachineFunction &MF)
SPIRVTypeInst getOrCreateOpTypeFunctionWithArgs(const Type *Ty, SPIRVTypeInst RetType, const SmallVectorImpl< SPIRVTypeInst > &ArgTypes, MachineIRBuilder &MIRBuilder)
const TargetRegisterClass * getRegClass(SPIRVTypeInst SpvType) const
unsigned getScalarOrVectorBitWidth(SPIRVTypeInst Type) const
SPIRVTypeInst getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
SPIRVTypeInst getOrCreateSPIRVVectorType(SPIRVTypeInst BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder, bool EmitIR)
unsigned getScalarOrVectorComponentCount(Register VReg) const
const Type * getTypeForSPIRVType(SPIRVTypeInst Ty) const
bool isBitcastCompatible(SPIRVTypeInst Type1, SPIRVTypeInst Type2) const
LLT getRegType(SPIRVTypeInst SpvType) const
void invalidateMachineInstr(MachineInstr *MI)
SPIRVTypeInst getOrCreateSPIRVPointerType(const Type *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SC)
Register getSPIRVTypeID(SPIRVTypeInst SpirvType) const
SPIRVTypeInst changePointerStorageClass(SPIRVTypeInst PtrType, SPIRV::StorageClass::StorageClass SC, MachineInstr &I)
void addGlobalObject(const Value *V, const MachineFunction *MF, Register R)
SPIRVTypeInst getOrCreateSPIRVType(const Type *Type, MachineInstr &I, SPIRV::AccessQualifier::AccessQualifier AQ, bool EmitIR)
SPIRVTypeInst getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
Type * getDeducedGlobalValueType(const GlobalValue *Global)
void addValueAttrs(MachineInstr *Key, std::pair< Type *, std::string > Val)
void buildMemAliasingOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, uint32_t Dec, const MDNode *GVarMD)
SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const
bool add(SPIRV::IRHandle Handle, const MachineInstr *MI)
Register find(SPIRV::IRHandle Handle, const MachineFunction *MF)
const SPIRVInstrInfo * getInstrInfo() const override
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
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
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:313
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Definition Type.cpp:286
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition Type.h:130
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.
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:549
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract(Y &&MD)
Extract a Value from Metadata, if any.
Definition Metadata.h:696
This is an optimization pass for GlobalISel generic memory operations.
void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
Definition MathExtras.h:344
StringMapEntry< Value * > ValueName
Definition Value.h:56
bool isTypeFoldingSupported(unsigned Opcode)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
FunctionPass * createSPIRVPreLegalizerPass()
void updateRegType(Register Reg, Type *Ty, SPIRVTypeInst SpirvTy, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB, MachineRegisterInfo &MRI)
Helper external function for assigning a SPIRV type to a register, ensuring the register class and ty...
constexpr unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
Definition SPIRVUtils.h:248
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
Type * toTypedPointer(Type *Ty)
Definition SPIRVUtils.h:466
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
auto post_order(const T &G)
Post-order traversal of a graph.
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:547
@ Global
Append to llvm.global_dtors.
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder, const MDNode *GVarMD, const SPIRVSubtarget &ST)
void processInstr(MachineInstr &MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR, SPIRVTypeInst KnownResType)
FunctionAddr VTableAddr Next
Definition InstrProf.h:141
DWARFExpression::Operation Op
MachineInstr * getDefInstrMaybeConstant(Register &ConstReg, const MachineRegisterInfo *MRI)
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
Type * getMDOperandAsType(const MDNode *N, unsigned I)
bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID)
void addStringImm(const StringRef &Str, MCInst &Inst)
MachineInstr * getVRegDef(MachineRegisterInfo &MRI, Register Reg)