LLVM 22.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 {
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 =
58 cast<Constant>(cast<ConstantAsMetadata>(
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());
99 SPIRVType *ExtType = GR->getOrCreateSPIRVType(
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
164 for (MachineRegisterInfo::use_instr_iterator I = MRI->use_instr_begin(Reg),
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 SPIRVType *ResType = GR->getSPIRVTypeForVReg(ResVReg);
179 SPIRVType *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");
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 do instruction selections early instead of calling MIB.buildBitcast()
196// generating the general op code G_BITCAST. When MachineVerifier validates
197// G_BITCAST we see a check of a kind: if Source Type is equal to Destination
198// Type then report error "bitcast must change the type". This doesn't take into
199// account the notion of a typed pointer that is important for SPIR-V where a
200// user may and should use bitcast between pointers with different pointee types
201// (https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpBitcast).
202// It's important for correct lowering in SPIR-V, because interpretation of the
203// data type is not left to instructions that utilize the pointer, but encoded
204// by the pointer declaration, and the SPIRV target can and must handle the
205// declaration and use of pointers that specify the type of data they point to.
206// It's not feasible to improve validation of G_BITCAST using just information
207// provided by low level types of source and destination. Therefore we don't
208// produce G_BITCAST as the general op code with semantics different from
209// OpBitcast, but rather lower to OpBitcast immediately. As for now, the only
210// difference would be that CombinerHelper couldn't transform known patterns
211// around G_BUILD_VECTOR. See discussion
212// in https://github.com/llvm/llvm-project/pull/110270 for even more context.
214 MachineIRBuilder MIB) {
216 for (MachineBasicBlock &MBB : MF) {
217 for (MachineInstr &MI : MBB) {
218 if (MI.getOpcode() != TargetOpcode::G_BITCAST)
219 continue;
220 MIB.setInsertPt(*MI.getParent(), MI);
221 buildOpBitcast(GR, MIB, MI.getOperand(0).getReg(),
222 MI.getOperand(1).getReg());
223 ToErase.push_back(&MI);
224 }
225 }
226 for (MachineInstr *MI : ToErase) {
228 MI->eraseFromParent();
229 }
230}
231
233 MachineIRBuilder MIB) {
234 // Get access to information about available extensions
235 const SPIRVSubtarget *ST =
236 static_cast<const SPIRVSubtarget *>(&MIB.getMF().getSubtarget());
238 for (MachineBasicBlock &MBB : MF) {
239 for (MachineInstr &MI : MBB) {
240 if (!isSpvIntrinsic(MI, Intrinsic::spv_bitcast) &&
241 !isSpvIntrinsic(MI, Intrinsic::spv_ptrcast))
242 continue;
243 assert(MI.getOperand(2).isReg());
244 MIB.setInsertPt(*MI.getParent(), MI);
245 ToErase.push_back(&MI);
246 if (isSpvIntrinsic(MI, Intrinsic::spv_bitcast)) {
247 MIB.buildBitcast(MI.getOperand(0).getReg(), MI.getOperand(2).getReg());
248 continue;
249 }
250 Register Def = MI.getOperand(0).getReg();
251 Register Source = MI.getOperand(2).getReg();
252 Type *ElemTy = getMDOperandAsType(MI.getOperand(3).getMetadata(), 0);
253 SPIRVType *AssignedPtrType = GR->getOrCreateSPIRVPointerType(
254 ElemTy, MI,
255 addressSpaceToStorageClass(MI.getOperand(4).getImm(), *ST));
256
257 // If the ptrcast would be redundant, replace all uses with the source
258 // register.
260 if (GR->getSPIRVTypeForVReg(Source) == AssignedPtrType) {
261 // Erase Def's assign type instruction if we are going to replace Def.
262 if (MachineInstr *AssignMI = findAssignTypeInstr(Def, MRI))
263 ToErase.push_back(AssignMI);
264 MRI->replaceRegWith(Def, Source);
265 } else {
266 if (!GR->getSPIRVTypeForVReg(Def, &MF))
267 GR->assignSPIRVTypeToVReg(AssignedPtrType, Def, MF);
268 MIB.buildBitcast(Def, Source);
269 }
270 }
271 }
272 for (MachineInstr *MI : ToErase) {
274 MI->eraseFromParent();
275 }
276}
277
278// Translating GV, IRTranslator sometimes generates following IR:
279// %1 = G_GLOBAL_VALUE
280// %2 = COPY %1
281// %3 = G_ADDRSPACE_CAST %2
282//
283// or
284//
285// %1 = G_ZEXT %2
286// G_MEMCPY ... %2 ...
287//
288// New registers have no SPIRVType and no register class info.
289//
290// Set SPIRVType for GV, propagate it from GV to other instructions,
291// also set register classes.
294 MachineIRBuilder &MIB) {
295 SPIRVType *SpvType = nullptr;
296 assert(MI && "Machine instr is expected");
297 if (MI->getOperand(0).isReg()) {
298 Register Reg = MI->getOperand(0).getReg();
299 SpvType = GR->getSPIRVTypeForVReg(Reg);
300 if (!SpvType) {
301 switch (MI->getOpcode()) {
302 case TargetOpcode::G_FCONSTANT:
303 case TargetOpcode::G_CONSTANT: {
304 MIB.setInsertPt(*MI->getParent(), MI);
305 Type *Ty = MI->getOperand(1).getCImm()->getType();
306 SpvType = GR->getOrCreateSPIRVType(
307 Ty, MIB, SPIRV::AccessQualifier::ReadWrite, true);
308 break;
309 }
310 case TargetOpcode::G_GLOBAL_VALUE: {
311 MIB.setInsertPt(*MI->getParent(), MI);
312 const GlobalValue *Global = MI->getOperand(1).getGlobal();
314 auto *Ty = TypedPointerType::get(ElementTy,
315 Global->getType()->getAddressSpace());
316 SpvType = GR->getOrCreateSPIRVType(
317 Ty, MIB, SPIRV::AccessQualifier::ReadWrite, true);
318 break;
319 }
320 case TargetOpcode::G_ANYEXT:
321 case TargetOpcode::G_SEXT:
322 case TargetOpcode::G_ZEXT: {
323 if (MI->getOperand(1).isReg()) {
324 if (MachineInstr *DefInstr =
325 MRI.getVRegDef(MI->getOperand(1).getReg())) {
326 if (SPIRVType *Def = propagateSPIRVType(DefInstr, GR, MRI, MIB)) {
327 unsigned CurrentBW = GR->getScalarOrVectorBitWidth(Def);
328 unsigned ExpectedBW =
329 std::max(MRI.getType(Reg).getScalarSizeInBits(), CurrentBW);
330 unsigned NumElements = GR->getScalarOrVectorComponentCount(Def);
331 SpvType = GR->getOrCreateSPIRVIntegerType(ExpectedBW, MIB);
332 if (NumElements > 1)
333 SpvType = GR->getOrCreateSPIRVVectorType(SpvType, NumElements,
334 MIB, true);
335 }
336 }
337 }
338 break;
339 }
340 case TargetOpcode::G_PTRTOINT:
341 SpvType = GR->getOrCreateSPIRVIntegerType(
342 MRI.getType(Reg).getScalarSizeInBits(), MIB);
343 break;
344 case TargetOpcode::G_TRUNC:
345 case TargetOpcode::G_ADDRSPACE_CAST:
346 case TargetOpcode::G_PTR_ADD:
347 case TargetOpcode::COPY: {
348 MachineOperand &Op = MI->getOperand(1);
349 MachineInstr *Def = Op.isReg() ? MRI.getVRegDef(Op.getReg()) : nullptr;
350 if (Def)
351 SpvType = propagateSPIRVType(Def, GR, MRI, MIB);
352 break;
353 }
354 default:
355 break;
356 }
357 if (SpvType) {
358 // check if the address space needs correction
359 LLT RegType = MRI.getType(Reg);
360 if (SpvType->getOpcode() == SPIRV::OpTypePointer &&
361 RegType.isPointer() &&
363 RegType.getAddressSpace()) {
364 const SPIRVSubtarget &ST =
365 MI->getParent()->getParent()->getSubtarget<SPIRVSubtarget>();
366 auto TSC = addressSpaceToStorageClass(RegType.getAddressSpace(), ST);
367 SpvType = GR->changePointerStorageClass(SpvType, TSC, *MI);
368 }
369 GR->assignSPIRVTypeToVReg(SpvType, Reg, MIB.getMF());
370 }
371 if (!MRI.getRegClassOrNull(Reg))
372 MRI.setRegClass(Reg, SpvType ? GR->getRegClass(SpvType)
373 : &SPIRV::iIDRegClass);
374 }
375 }
376 return SpvType;
377}
378
379// To support current approach and limitations wrt. bit width here we widen a
380// scalar register with a bit width greater than 1 to valid sizes and cap it to
381// 64 width.
382static unsigned widenBitWidthToNextPow2(unsigned BitWidth) {
383 if (BitWidth == 1)
384 return 1; // No need to widen 1-bit values
385 return std::min(std::max(1u << Log2_32_Ceil(BitWidth), 8u), 64u);
386}
387
389 LLT RegType = MRI.getType(Reg);
390 if (!RegType.isScalar())
391 return;
392 unsigned CurrentWidth = RegType.getScalarSizeInBits();
393 unsigned NewWidth = widenBitWidthToNextPow2(CurrentWidth);
394 if (NewWidth != CurrentWidth)
395 MRI.setType(Reg, LLT::scalar(NewWidth));
396}
397
398static void widenCImmType(MachineOperand &MOP) {
399 const ConstantInt *CImmVal = MOP.getCImm();
400 unsigned CurrentWidth = CImmVal->getBitWidth();
401 unsigned NewWidth = widenBitWidthToNextPow2(CurrentWidth);
402 if (NewWidth != CurrentWidth) {
403 // Replace the immediate value with the widened version
404 MOP.setCImm(ConstantInt::get(CImmVal->getType()->getContext(),
405 CImmVal->getValue().zextOrTrunc(NewWidth)));
406 }
407}
408
410 MachineBasicBlock &MBB = *Def->getParent();
412 Def->getNextNode() ? Def->getNextNode()->getIterator() : MBB.end();
413 // Skip all the PHI and debug instructions.
414 while (DefIt != MBB.end() &&
415 (DefIt->isPHI() || DefIt->isDebugOrPseudoInstr()))
416 DefIt = std::next(DefIt);
417 MIB.setInsertPt(MBB, DefIt);
418}
419
420namespace llvm {
421void insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpvType,
424 assert((Ty || SpvType) && "Either LLVM or SPIRV type is expected.");
425 MachineInstr *Def = MRI.getVRegDef(Reg);
426 setInsertPtAfterDef(MIB, Def);
427 if (!SpvType)
428 SpvType = GR->getOrCreateSPIRVType(Ty, MIB,
429 SPIRV::AccessQualifier::ReadWrite, true);
430
431 if (!isTypeFoldingSupported(Def->getOpcode())) {
432 // No need to generate SPIRV::ASSIGN_TYPE pseudo-instruction
433 if (!MRI.getRegClassOrNull(Reg))
434 MRI.setRegClass(Reg, GR->getRegClass(SpvType));
435 if (!MRI.getType(Reg).isValid())
436 MRI.setType(Reg, GR->getRegType(SpvType));
437 GR->assignSPIRVTypeToVReg(SpvType, Reg, MIB.getMF());
438 return;
439 }
440
441 // Tablegen definition assumes SPIRV::ASSIGN_TYPE pseudo-instruction is
442 // present after each auto-folded instruction to take a type reference from.
443 Register NewReg = MRI.createGenericVirtualRegister(MRI.getType(Reg));
444 const auto *RegClass = GR->getRegClass(SpvType);
445 MRI.setRegClass(NewReg, RegClass);
446 MRI.setRegClass(Reg, RegClass);
447
448 GR->assignSPIRVTypeToVReg(SpvType, Reg, MIB.getMF());
449 // This is to make it convenient for Legalizer to get the SPIRVType
450 // when processing the actual MI (i.e. not pseudo one).
451 GR->assignSPIRVTypeToVReg(SpvType, NewReg, MIB.getMF());
452 // Copy MIFlags from Def to ASSIGN_TYPE instruction. It's required to keep
453 // the flags after instruction selection.
454 const uint32_t Flags = Def->getFlags();
455 MIB.buildInstr(SPIRV::ASSIGN_TYPE)
456 .addDef(Reg)
457 .addUse(NewReg)
458 .addUse(GR->getSPIRVTypeID(SpvType))
459 .setMIFlags(Flags);
460 for (unsigned I = 0, E = Def->getNumDefs(); I != E; ++I) {
461 MachineOperand &MO = Def->getOperand(I);
462 if (MO.getReg() == Reg) {
463 MO.setReg(NewReg);
464 break;
465 }
466 }
467}
468
471 SPIRVType *KnownResType) {
472 MIB.setInsertPt(*MI.getParent(), MI.getIterator());
473 for (auto &Op : MI.operands()) {
474 if (!Op.isReg() || Op.isDef())
475 continue;
476 Register OpReg = Op.getReg();
477 SPIRVType *SpvType = GR->getSPIRVTypeForVReg(OpReg);
478 if (!SpvType && KnownResType) {
479 SpvType = KnownResType;
480 GR->assignSPIRVTypeToVReg(KnownResType, OpReg, *MI.getMF());
481 }
482 assert(SpvType);
483 if (!MRI.getRegClassOrNull(OpReg))
484 MRI.setRegClass(OpReg, GR->getRegClass(SpvType));
485 if (!MRI.getType(OpReg).isValid())
486 MRI.setType(OpReg, GR->getRegType(SpvType));
487 }
488}
489} // namespace llvm
490
491static void
494 DenseMap<MachineInstr *, Type *> &TargetExtConstTypes) {
495 // Get access to information about available extensions
496 const SPIRVSubtarget *ST =
497 static_cast<const SPIRVSubtarget *>(&MIB.getMF().getSubtarget());
498
501 DenseMap<MachineInstr *, Register> RegsAlreadyAddedToDT;
502
503 bool IsExtendedInts =
504 ST->canUseExtension(
505 SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers) ||
506 ST->canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions) ||
507 ST->canUseExtension(SPIRV::Extension::SPV_INTEL_int4);
508
509 for (MachineBasicBlock *MBB : post_order(&MF)) {
510 if (MBB->empty())
511 continue;
512
513 bool ReachedBegin = false;
514 for (auto MII = std::prev(MBB->end()), Begin = MBB->begin();
515 !ReachedBegin;) {
516 MachineInstr &MI = *MII;
517 unsigned MIOp = MI.getOpcode();
518
519 if (!IsExtendedInts) {
520 // validate bit width of scalar registers and constant immediates
521 for (auto &MOP : MI.operands()) {
522 if (MOP.isReg())
523 widenScalarType(MOP.getReg(), MRI);
524 else if (MOP.isCImm())
525 widenCImmType(MOP);
526 }
527 }
528
529 if (isSpvIntrinsic(MI, Intrinsic::spv_assign_ptr_type)) {
530 Register Reg = MI.getOperand(1).getReg();
531 MIB.setInsertPt(*MI.getParent(), MI.getIterator());
532 Type *ElementTy = getMDOperandAsType(MI.getOperand(2).getMetadata(), 0);
533 SPIRVType *AssignedPtrType = GR->getOrCreateSPIRVPointerType(
534 ElementTy, MI,
535 addressSpaceToStorageClass(MI.getOperand(3).getImm(), *ST));
536 MachineInstr *Def = MRI.getVRegDef(Reg);
537 assert(Def && "Expecting an instruction that defines the register");
538 // G_GLOBAL_VALUE already has type info.
539 if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE &&
540 Def->getOpcode() != SPIRV::ASSIGN_TYPE)
541 insertAssignInstr(Reg, nullptr, AssignedPtrType, GR, MIB,
542 MF.getRegInfo());
543 ToErase.push_back(&MI);
544 } else if (isSpvIntrinsic(MI, Intrinsic::spv_assign_type)) {
545 Register Reg = MI.getOperand(1).getReg();
546 Type *Ty = getMDOperandAsType(MI.getOperand(2).getMetadata(), 0);
547 MachineInstr *Def = MRI.getVRegDef(Reg);
548 assert(Def && "Expecting an instruction that defines the register");
549 // G_GLOBAL_VALUE already has type info.
550 if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE &&
551 Def->getOpcode() != SPIRV::ASSIGN_TYPE)
552 insertAssignInstr(Reg, Ty, nullptr, GR, MIB, MF.getRegInfo());
553 ToErase.push_back(&MI);
554 } else if (MIOp == TargetOpcode::FAKE_USE && MI.getNumOperands() > 0) {
555 MachineInstr *MdMI = MI.getPrevNode();
556 if (MdMI && isSpvIntrinsic(*MdMI, Intrinsic::spv_value_md)) {
557 // It's an internal service info from before IRTranslator passes.
558 MachineInstr *Def = getVRegDef(MRI, MI.getOperand(0).getReg());
559 for (unsigned I = 1, E = MI.getNumOperands(); I != E && Def; ++I)
560 if (getVRegDef(MRI, MI.getOperand(I).getReg()) != Def)
561 Def = nullptr;
562 if (Def) {
563 const MDNode *MD = MdMI->getOperand(1).getMetadata();
565 cast<MDString>(MD->getOperand(1))->getString();
566 const MDNode *TypeMD = cast<MDNode>(MD->getOperand(0));
567 Type *ValueTy = getMDOperandAsType(TypeMD, 0);
568 GR->addValueAttrs(Def, std::make_pair(ValueTy, ValueName.str()));
569 }
570 ToErase.push_back(MdMI);
571 }
572 ToErase.push_back(&MI);
573 } else if (MIOp == TargetOpcode::G_CONSTANT ||
574 MIOp == TargetOpcode::G_FCONSTANT ||
575 MIOp == TargetOpcode::G_BUILD_VECTOR) {
576 // %rc = G_CONSTANT ty Val
577 // ===>
578 // %cty = OpType* ty
579 // %rctmp = G_CONSTANT ty Val
580 // %rc = ASSIGN_TYPE %rctmp, %cty
581 Register Reg = MI.getOperand(0).getReg();
582 bool NeedAssignType = true;
583 if (MRI.hasOneUse(Reg)) {
584 MachineInstr &UseMI = *MRI.use_instr_begin(Reg);
585 if (isSpvIntrinsic(UseMI, Intrinsic::spv_assign_type) ||
586 isSpvIntrinsic(UseMI, Intrinsic::spv_assign_name))
587 continue;
588 if (UseMI.getOpcode() == SPIRV::ASSIGN_TYPE)
589 NeedAssignType = false;
590 }
591 Type *Ty = nullptr;
592 if (MIOp == TargetOpcode::G_CONSTANT) {
593 auto TargetExtIt = TargetExtConstTypes.find(&MI);
594 Ty = TargetExtIt == TargetExtConstTypes.end()
595 ? MI.getOperand(1).getCImm()->getType()
596 : TargetExtIt->second;
597 const ConstantInt *OpCI = MI.getOperand(1).getCImm();
598 // TODO: we may wish to analyze here if OpCI is zero and LLT RegType =
599 // MRI.getType(Reg); RegType.isPointer() is true, so that we observe
600 // at this point not i64/i32 constant but null pointer in the
601 // corresponding address space of RegType.getAddressSpace(). This may
602 // help to successfully validate the case when a OpConstantComposite's
603 // constituent has type that does not match Result Type of
604 // OpConstantComposite (see, for example,
605 // pointers/PtrCast-null-in-OpSpecConstantOp.ll).
606 Register PrimaryReg = GR->find(OpCI, &MF);
607 if (!PrimaryReg.isValid()) {
608 GR->add(OpCI, &MI);
609 } else if (PrimaryReg != Reg &&
610 MRI.getType(Reg) == MRI.getType(PrimaryReg)) {
611 auto *RCReg = MRI.getRegClassOrNull(Reg);
612 auto *RCPrimary = MRI.getRegClassOrNull(PrimaryReg);
613 if (!RCReg || RCPrimary == RCReg) {
614 RegsAlreadyAddedToDT[&MI] = PrimaryReg;
615 ToErase.push_back(&MI);
616 NeedAssignType = false;
617 }
618 }
619 } else if (MIOp == TargetOpcode::G_FCONSTANT) {
620 Ty = MI.getOperand(1).getFPImm()->getType();
621 } else {
622 assert(MIOp == TargetOpcode::G_BUILD_VECTOR);
623 Type *ElemTy = nullptr;
624 MachineInstr *ElemMI = MRI.getVRegDef(MI.getOperand(1).getReg());
625 assert(ElemMI);
626
627 if (ElemMI->getOpcode() == TargetOpcode::G_CONSTANT) {
628 ElemTy = ElemMI->getOperand(1).getCImm()->getType();
629 } else if (ElemMI->getOpcode() == TargetOpcode::G_FCONSTANT) {
630 ElemTy = ElemMI->getOperand(1).getFPImm()->getType();
631 } else {
632 if (const SPIRVType *ElemSpvType =
633 GR->getSPIRVTypeForVReg(MI.getOperand(1).getReg(), &MF))
634 ElemTy = const_cast<Type *>(GR->getTypeForSPIRVType(ElemSpvType));
635 if (!ElemTy) {
636 // There may be a case when we already know Reg's type.
637 MachineInstr *NextMI = MI.getNextNode();
638 if (!NextMI || NextMI->getOpcode() != SPIRV::ASSIGN_TYPE ||
639 NextMI->getOperand(1).getReg() != Reg)
640 llvm_unreachable("Unexpected opcode");
641 }
642 }
643 if (ElemTy)
644 Ty = VectorType::get(
645 ElemTy, MI.getNumExplicitOperands() - MI.getNumExplicitDefs(),
646 false);
647 else
648 NeedAssignType = false;
649 }
650 if (NeedAssignType)
651 insertAssignInstr(Reg, Ty, nullptr, GR, MIB, MRI);
652 } else if (MIOp == TargetOpcode::G_GLOBAL_VALUE) {
653 propagateSPIRVType(&MI, GR, MRI, MIB);
654 }
655
656 if (MII == Begin)
657 ReachedBegin = true;
658 else
659 --MII;
660 }
661 }
662 for (MachineInstr *MI : ToErase) {
663 auto It = RegsAlreadyAddedToDT.find(MI);
664 if (It != RegsAlreadyAddedToDT.end())
665 MRI.replaceRegWith(MI->getOperand(0).getReg(), It->second);
667 MI->eraseFromParent();
668 }
669
670 // Address the case when IRTranslator introduces instructions with new
671 // registers without SPIRVType associated.
672 for (MachineBasicBlock &MBB : MF) {
673 for (MachineInstr &MI : MBB) {
674 switch (MI.getOpcode()) {
675 case TargetOpcode::G_TRUNC:
676 case TargetOpcode::G_ANYEXT:
677 case TargetOpcode::G_SEXT:
678 case TargetOpcode::G_ZEXT:
679 case TargetOpcode::G_PTRTOINT:
680 case TargetOpcode::COPY:
681 case TargetOpcode::G_ADDRSPACE_CAST:
682 propagateSPIRVType(&MI, GR, MRI, MIB);
683 break;
684 }
685 }
686 }
687}
688
691 MachineIRBuilder MIB) {
693 for (MachineBasicBlock &MBB : MF)
694 for (MachineInstr &MI : MBB)
695 if (isTypeFoldingSupported(MI.getOpcode()))
696 processInstr(MI, MIB, MRI, GR, nullptr);
697}
698
699static Register
701 SmallVector<unsigned, 4> *Ops = nullptr) {
702 Register DefReg;
703 unsigned StartOp = InlineAsm::MIOp_FirstOperand,
705 for (unsigned Idx = StartOp, MISz = MI->getNumOperands(); Idx != MISz;
706 ++Idx) {
707 const MachineOperand &MO = MI->getOperand(Idx);
708 if (MO.isMetadata())
709 continue;
710 if (Idx == AsmDescOp && MO.isImm()) {
711 // compute the index of the next operand descriptor
712 const InlineAsm::Flag F(MO.getImm());
713 AsmDescOp += 1 + F.getNumOperandRegisters();
714 continue;
715 }
716 if (MO.isReg() && MO.isDef()) {
717 if (!Ops)
718 return MO.getReg();
719 else
720 DefReg = MO.getReg();
721 } else if (Ops) {
722 Ops->push_back(Idx);
723 }
724 }
725 return DefReg;
726}
727
728static void
730 const SPIRVSubtarget &ST, MachineIRBuilder MIRBuilder,
731 const SmallVector<MachineInstr *> &ToProcess) {
733 Register AsmTargetReg;
734 for (unsigned i = 0, Sz = ToProcess.size(); i + 1 < Sz; i += 2) {
735 MachineInstr *I1 = ToProcess[i], *I2 = ToProcess[i + 1];
736 assert(isSpvIntrinsic(*I1, Intrinsic::spv_inline_asm) && I2->isInlineAsm());
737 MIRBuilder.setInsertPt(*I2->getParent(), *I2);
738
739 if (!AsmTargetReg.isValid()) {
740 // define vendor specific assembly target or dialect
741 AsmTargetReg = MRI.createGenericVirtualRegister(LLT::scalar(32));
742 MRI.setRegClass(AsmTargetReg, &SPIRV::iIDRegClass);
743 auto AsmTargetMIB =
744 MIRBuilder.buildInstr(SPIRV::OpAsmTargetINTEL).addDef(AsmTargetReg);
745 addStringImm(ST.getTargetTripleAsStr(), AsmTargetMIB);
746 GR->add(AsmTargetMIB.getInstr(), AsmTargetMIB);
747 }
748
749 // create types
750 const MDNode *IAMD = I1->getOperand(1).getMetadata();
751 FunctionType *FTy = cast<FunctionType>(getMDOperandAsType(IAMD, 0));
753 for (const auto &ArgTy : FTy->params())
754 ArgTypes.push_back(GR->getOrCreateSPIRVType(
755 ArgTy, MIRBuilder, SPIRV::AccessQualifier::ReadWrite, true));
756 SPIRVType *RetType =
757 GR->getOrCreateSPIRVType(FTy->getReturnType(), MIRBuilder,
758 SPIRV::AccessQualifier::ReadWrite, true);
760 FTy, RetType, ArgTypes, MIRBuilder);
761
762 // define vendor specific assembly instructions string
763 Register AsmReg = MRI.createGenericVirtualRegister(LLT::scalar(32));
764 MRI.setRegClass(AsmReg, &SPIRV::iIDRegClass);
765 auto AsmMIB = MIRBuilder.buildInstr(SPIRV::OpAsmINTEL)
766 .addDef(AsmReg)
767 .addUse(GR->getSPIRVTypeID(RetType))
768 .addUse(GR->getSPIRVTypeID(FuncType))
769 .addUse(AsmTargetReg);
770 // inline asm string:
771 addStringImm(I2->getOperand(InlineAsm::MIOp_AsmString).getSymbolName(),
772 AsmMIB);
773 // inline asm constraint string:
774 addStringImm(cast<MDString>(I1->getOperand(2).getMetadata()->getOperand(0))
775 ->getString(),
776 AsmMIB);
777 GR->add(AsmMIB.getInstr(), AsmMIB);
778
779 // calls the inline assembly instruction
780 unsigned ExtraInfo = I2->getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
781 if (ExtraInfo & InlineAsm::Extra_HasSideEffects)
782 MIRBuilder.buildInstr(SPIRV::OpDecorate)
783 .addUse(AsmReg)
784 .addImm(static_cast<uint32_t>(SPIRV::Decoration::SideEffectsINTEL));
785
787 if (!DefReg.isValid()) {
788 DefReg = MRI.createGenericVirtualRegister(LLT::scalar(32));
789 MRI.setRegClass(DefReg, &SPIRV::iIDRegClass);
790 SPIRVType *VoidType = GR->getOrCreateSPIRVType(
791 Type::getVoidTy(MF.getFunction().getContext()), MIRBuilder,
792 SPIRV::AccessQualifier::ReadWrite, true);
793 GR->assignSPIRVTypeToVReg(VoidType, DefReg, MF);
794 }
795
796 auto AsmCall = MIRBuilder.buildInstr(SPIRV::OpAsmCallINTEL)
797 .addDef(DefReg)
798 .addUse(GR->getSPIRVTypeID(RetType))
799 .addUse(AsmReg);
800 for (unsigned IntrIdx = 3; IntrIdx < I1->getNumOperands(); ++IntrIdx)
801 AsmCall.addUse(I1->getOperand(IntrIdx).getReg());
802 }
803 for (MachineInstr *MI : ToProcess) {
805 MI->eraseFromParent();
806 }
807}
808
810 const SPIRVSubtarget &ST,
811 MachineIRBuilder MIRBuilder) {
813 for (MachineBasicBlock &MBB : MF) {
814 for (MachineInstr &MI : MBB) {
815 if (isSpvIntrinsic(MI, Intrinsic::spv_inline_asm) ||
816 MI.getOpcode() == TargetOpcode::INLINEASM)
817 ToProcess.push_back(&MI);
818 }
819 }
820 if (ToProcess.size() == 0)
821 return;
822
823 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly))
824 report_fatal_error("Inline assembly instructions require the "
825 "following SPIR-V extension: SPV_INTEL_inline_assembly",
826 false);
827
828 insertInlineAsmProcess(MF, GR, ST, MIRBuilder, ToProcess);
829}
830
832 union {
833 float F;
834 uint32_t Spir;
835 } FPMaxError;
836 FPMaxError.F = F;
837 return FPMaxError.Spir;
838}
839
841 MachineIRBuilder MIB) {
843 for (MachineBasicBlock &MBB : MF) {
844 for (MachineInstr &MI : MBB) {
845 if (!isSpvIntrinsic(MI, Intrinsic::spv_assign_decoration) &&
846 !isSpvIntrinsic(MI, Intrinsic::spv_assign_aliasing_decoration) &&
847 !isSpvIntrinsic(MI, Intrinsic::spv_assign_fpmaxerror_decoration))
848 continue;
849 MIB.setInsertPt(*MI.getParent(), MI.getNextNode());
850 if (isSpvIntrinsic(MI, Intrinsic::spv_assign_decoration)) {
851 buildOpSpirvDecorations(MI.getOperand(1).getReg(), MIB,
852 MI.getOperand(2).getMetadata());
853 } else if (isSpvIntrinsic(MI,
854 Intrinsic::spv_assign_fpmaxerror_decoration)) {
855 ConstantFP *OpV = mdconst::dyn_extract<ConstantFP>(
856 MI.getOperand(2).getMetadata()->getOperand(0));
857 uint32_t OpValue =
859
860 buildOpDecorate(MI.getOperand(1).getReg(), MIB,
861 SPIRV::Decoration::FPMaxErrorDecorationINTEL,
862 {OpValue});
863 } else {
864 GR->buildMemAliasingOpDecorate(MI.getOperand(1).getReg(), MIB,
865 MI.getOperand(2).getImm(),
866 MI.getOperand(3).getMetadata());
867 }
868
869 ToErase.push_back(&MI);
870 }
871 }
872 for (MachineInstr *MI : ToErase) {
874 MI->eraseFromParent();
875 }
876}
877
878// LLVM allows the switches to use registers as cases, while SPIR-V required
879// those to be immediate values. This function replaces such operands with the
880// equivalent immediate constant.
883 MachineIRBuilder MIB) {
885 for (MachineBasicBlock &MBB : MF) {
886 for (MachineInstr &MI : MBB) {
887 if (!isSpvIntrinsic(MI, Intrinsic::spv_switch))
888 continue;
889
891 NewOperands.push_back(MI.getOperand(0)); // Opcode
892 NewOperands.push_back(MI.getOperand(1)); // Condition
893 NewOperands.push_back(MI.getOperand(2)); // Default
894 for (unsigned i = 3; i < MI.getNumOperands(); i += 2) {
895 Register Reg = MI.getOperand(i).getReg();
896 MachineInstr *ConstInstr = getDefInstrMaybeConstant(Reg, &MRI);
897 NewOperands.push_back(
899
900 NewOperands.push_back(MI.getOperand(i + 1));
901 }
902
903 assert(MI.getNumOperands() == NewOperands.size());
904 while (MI.getNumOperands() > 0)
905 MI.removeOperand(0);
906 for (auto &MO : NewOperands)
907 MI.addOperand(MO);
908 }
909 }
910}
911
912// Some instructions are used during CodeGen but should never be emitted.
913// Cleaning up those.
917 for (MachineBasicBlock &MBB : MF) {
918 for (MachineInstr &MI : MBB) {
919 if (isSpvIntrinsic(MI, Intrinsic::spv_track_constant) ||
920 MI.getOpcode() == TargetOpcode::G_BRINDIRECT)
921 ToEraseMI.push_back(&MI);
922 }
923 }
924
925 for (MachineInstr *MI : ToEraseMI) {
927 MI->eraseFromParent();
928 }
929}
930
931// Find all usages of G_BLOCK_ADDR in our intrinsics and replace those
932// operands/registers by the actual MBB it references.
934 MachineIRBuilder MIB) {
935 // Gather the reverse-mapping BB -> MBB.
937 for (MachineBasicBlock &MBB : MF)
938 BB2MBB[MBB.getBasicBlock()] = &MBB;
939
940 // Gather instructions requiring patching. For now, only those can use
941 // G_BLOCK_ADDR.
942 SmallVector<MachineInstr *, 8> InstructionsToPatch;
943 for (MachineBasicBlock &MBB : MF) {
944 for (MachineInstr &MI : MBB) {
945 if (isSpvIntrinsic(MI, Intrinsic::spv_switch) ||
946 isSpvIntrinsic(MI, Intrinsic::spv_loop_merge) ||
947 isSpvIntrinsic(MI, Intrinsic::spv_selection_merge))
948 InstructionsToPatch.push_back(&MI);
949 }
950 }
951
952 // For each instruction to fix, we replace all the G_BLOCK_ADDR operands by
953 // the actual MBB it references. Once those references have been updated, we
954 // can cleanup remaining G_BLOCK_ADDR references.
955 SmallPtrSet<MachineBasicBlock *, 8> ClearAddressTaken;
958 for (MachineInstr *MI : InstructionsToPatch) {
960 for (unsigned i = 0; i < MI->getNumOperands(); ++i) {
961 // The operand is not a register, keep as-is.
962 if (!MI->getOperand(i).isReg()) {
963 NewOps.push_back(MI->getOperand(i));
964 continue;
965 }
966
967 Register Reg = MI->getOperand(i).getReg();
968 MachineInstr *BuildMBB = MRI.getVRegDef(Reg);
969 // The register is not the result of G_BLOCK_ADDR, keep as-is.
970 if (!BuildMBB || BuildMBB->getOpcode() != TargetOpcode::G_BLOCK_ADDR) {
971 NewOps.push_back(MI->getOperand(i));
972 continue;
973 }
974
975 assert(BuildMBB && BuildMBB->getOpcode() == TargetOpcode::G_BLOCK_ADDR &&
976 BuildMBB->getOperand(1).isBlockAddress() &&
977 BuildMBB->getOperand(1).getBlockAddress());
978 BasicBlock *BB =
979 BuildMBB->getOperand(1).getBlockAddress()->getBasicBlock();
980 auto It = BB2MBB.find(BB);
981 if (It == BB2MBB.end())
982 report_fatal_error("cannot find a machine basic block by a basic block "
983 "in a switch statement");
984 MachineBasicBlock *ReferencedBlock = It->second;
985 NewOps.push_back(MachineOperand::CreateMBB(ReferencedBlock));
986
987 ClearAddressTaken.insert(ReferencedBlock);
988 ToEraseMI.insert(BuildMBB);
989 }
990
991 // Replace the operands.
992 assert(MI->getNumOperands() == NewOps.size());
993 while (MI->getNumOperands() > 0)
994 MI->removeOperand(0);
995 for (auto &MO : NewOps)
996 MI->addOperand(MO);
997
998 if (MachineInstr *Next = MI->getNextNode()) {
999 if (isSpvIntrinsic(*Next, Intrinsic::spv_track_constant)) {
1000 ToEraseMI.insert(Next);
1001 Next = MI->getNextNode();
1002 }
1003 if (Next && Next->getOpcode() == TargetOpcode::G_BRINDIRECT)
1004 ToEraseMI.insert(Next);
1005 }
1006 }
1007
1008 // BlockAddress operands were used to keep information between passes,
1009 // let's undo the "address taken" status to reflect that Succ doesn't
1010 // actually correspond to an IR-level basic block.
1011 for (MachineBasicBlock *Succ : ClearAddressTaken)
1012 Succ->setAddressTakenIRBlock(nullptr);
1013
1014 // If we just delete G_BLOCK_ADDR instructions with BlockAddress operands,
1015 // this leaves their BasicBlock counterparts in a "address taken" status. This
1016 // would make AsmPrinter to generate a series of unneeded labels of a "Address
1017 // of block that was removed by CodeGen" kind. Let's first ensure that we
1018 // don't have a dangling BlockAddress constants by zapping the BlockAddress
1019 // nodes, and only after that proceed with erasing G_BLOCK_ADDR instructions.
1020 Constant *Replacement =
1021 ConstantInt::get(Type::getInt32Ty(MF.getFunction().getContext()), 1);
1022 for (MachineInstr *BlockAddrI : ToEraseMI) {
1023 if (BlockAddrI->getOpcode() == TargetOpcode::G_BLOCK_ADDR) {
1024 BlockAddress *BA = const_cast<BlockAddress *>(
1025 BlockAddrI->getOperand(1).getBlockAddress());
1027 ConstantExpr::getIntToPtr(Replacement, BA->getType()));
1028 BA->destroyConstant();
1029 }
1030 GR->invalidateMachineInstr(BlockAddrI);
1031 BlockAddrI->eraseFromParent();
1032 }
1033}
1034
1036 if (MBB.empty())
1037 return true;
1038
1039 // Branching SPIR-V intrinsics are not detected by this generic method.
1040 // Thus, we can only trust negative result.
1041 if (!MBB.canFallThrough())
1042 return false;
1043
1044 // Otherwise, we must manually check if we have a SPIR-V intrinsic which
1045 // prevent an implicit fallthrough.
1047 It != E; ++It) {
1048 if (isSpvIntrinsic(*It, Intrinsic::spv_switch))
1049 return false;
1050 }
1051 return true;
1052}
1053
1055 MachineIRBuilder MIB) {
1056 // It is valid for MachineBasicBlocks to not finish with a branch instruction.
1057 // In such cases, they will simply fallthrough their immediate successor.
1058 for (MachineBasicBlock &MBB : MF) {
1060 continue;
1061
1062 assert(std::distance(MBB.successors().begin(), MBB.successors().end()) ==
1063 1);
1064 MIB.setInsertPt(MBB, MBB.end());
1065 MIB.buildBr(**MBB.successors().begin());
1066 }
1067}
1068
1069bool SPIRVPreLegalizer::runOnMachineFunction(MachineFunction &MF) {
1070 // Initialize the type registry.
1072 SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
1073 GR->setCurrentFunc(MF);
1074 MachineIRBuilder MIB(MF);
1075 // a registry of target extension constants
1076 DenseMap<MachineInstr *, Type *> TargetExtConstTypes;
1077 // to keep record of tracked constants
1078 addConstantsToTrack(MF, GR, ST, TargetExtConstTypes);
1079 foldConstantsIntoIntrinsics(MF, GR, MIB);
1080 insertBitcasts(MF, GR, MIB);
1081 generateAssignInstrs(MF, GR, MIB, TargetExtConstTypes);
1082
1083 processSwitchesConstants(MF, GR, MIB);
1084 processBlockAddr(MF, GR, MIB);
1086
1087 processInstrsWithTypeFolding(MF, GR, MIB);
1089 insertSpirvDecorations(MF, GR, MIB);
1090 insertInlineAsm(MF, GR, ST, MIB);
1091 selectOpBitcasts(MF, GR, MIB);
1092
1093 return true;
1094}
1095
1096INITIALIZE_PASS(SPIRVPreLegalizer, DEBUG_TYPE, "SPIRV pre legalizer", false,
1097 false)
1098
1099char SPIRVPreLegalizer::ID = 0;
1100
1102 return new SPIRVPreLegalizer();
1103}
unsigned const MachineRegisterInfo * MRI
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...
Provides analysis for continuously CSEing during GISel passes.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
Provides analysis for querying information about KnownBits during GISel passes.
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
#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 selectOpBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
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 SPIRVType * propagateSPIRVType(MachineInstr *MI, SPIRVGlobalRegistry *GR, MachineRegisterInfo &MRI, 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)
#define DEBUG_TYPE
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:6143
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
Definition: APInt.cpp:1033
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:899
BasicBlock * getBasicBlock() const
Definition: Constants.h:934
static LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
Definition: Constants.cpp:2314
ConstantFP - Floating Point Values [float, double].
Definition: Constants.h:277
const APFloat & getValueAPF() const
Definition: Constants.h:320
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:157
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition: Constants.h:154
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.
Definition: Constants.cpp:489
This class represents an Operation in the Expression.
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:177
iterator end()
Definition: DenseMap.h:87
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:314
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:359
To use KnownBitsInfo analysis in a pass, KnownBitsInfo &Info = getAnalysis<GISelValueTrackingInfoAnal...
constexpr unsigned getScalarSizeInBits() const
Definition: LowLevelType.h:265
constexpr bool isScalar() const
Definition: LowLevelType.h:147
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
Definition: LowLevelType.h:43
constexpr bool isPointer() const
Definition: LowLevelType.h:150
constexpr unsigned getAddressSpace() const
Definition: LowLevelType.h:271
Metadata node.
Definition: Metadata.h:1077
const MDOperand & getOperand(unsigned I) const
Definition: Metadata.h:1445
reverse_iterator rend()
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI bool canFallThrough()
Return true if the block can implicitly transfer control to the block after it by falling off the end...
LLVM_ABI iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
iterator_range< succ_iterator > successors()
reverse_iterator rbegin()
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.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
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 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.
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 & setMIFlags(unsigned Flags) const
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:72
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:587
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
Definition: MachineInstr.h:595
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)
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
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)
defusechain_iterator - This class provides iterator support for machine operands in the function that...
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
constexpr bool isValid() const
Definition: Register.h:107
SPIRVType * getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, const MachineFunction &MF)
SPIRVType * changePointerStorageClass(SPIRVType *PtrType, SPIRV::StorageClass::StorageClass SC, MachineInstr &I)
const Type * getTypeForSPIRVType(const SPIRVType *Ty) const
bool isBitcastCompatible(const SPIRVType *Type1, const SPIRVType *Type2) const
unsigned getScalarOrVectorComponentCount(Register VReg) const
SPIRVType * getOrCreateSPIRVType(const Type *Type, MachineInstr &I, SPIRV::AccessQualifier::AccessQualifier AQ, bool EmitIR)
SPIRVType * getOrCreateSPIRVPointerType(const Type *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SC)
void invalidateMachineInstr(MachineInstr *MI)
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
void addGlobalObject(const Value *V, const MachineFunction *MF, Register R)
SPIRVType * getOrCreateOpTypeFunctionWithArgs(const Type *Ty, SPIRVType *RetType, const SmallVectorImpl< SPIRVType * > &ArgTypes, MachineIRBuilder &MIRBuilder)
const TargetRegisterClass * getRegClass(SPIRVType *SpvType) const
SPIRVType * getOrCreateSPIRVVectorType(SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder, bool EmitIR)
SPIRVType * getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
Type * getDeducedGlobalValueType(const GlobalValue *Global)
LLT getRegType(SPIRVType *SpvType) const
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
unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) 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.
Definition: SmallPtrSet.h:401
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:541
size_t size() const
Definition: SmallVector.h:79
void push_back(const T &Elt)
Definition: SmallVector.h:414
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
StringMapEntry - This is used to represent one value that is inserted into a StringMap.
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:45
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition: Type.h:128
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:256
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:546
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
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:113
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:349
void insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpirvTy, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB, MachineRegisterInfo &MRI)
Helper external function for inserting ASSIGN_TYPE instuction between Reg and its definition,...
bool isTypeFoldingSupported(unsigned Opcode)
Definition: SPIRVUtils.cpp:958
FunctionPass * createSPIRVPreLegalizerPass()
iterator_range< po_iterator< T > > post_order(const T &G)
constexpr unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
Definition: SPIRVUtils.h:191
void processInstr(MachineInstr &MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR, SPIRVType *KnownResType)
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
Definition: SPIRVUtils.cpp:140
Type * toTypedPointer(Type *Ty)
Definition: SPIRVUtils.h:385
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition: Error.cpp:167
@ Global
Append to llvm.global_dtors.
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
Definition: SPIRVUtils.cpp:245
MachineInstr * getDefInstrMaybeConstant(Register &ConstReg, const MachineRegisterInfo *MRI)
Definition: SPIRVUtils.cpp:345
constexpr unsigned BitWidth
Definition: BitmaskEnum.h:223
Type * getMDOperandAsType(const MDNode *N, unsigned I)
Definition: SPIRVUtils.cpp:380
bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID)
Definition: SPIRVUtils.cpp:374
void addStringImm(const StringRef &Str, MCInst &Inst)
Definition: SPIRVUtils.cpp:54
MachineInstr * getVRegDef(MachineRegisterInfo &MRI, Register Reg)
Definition: SPIRVUtils.cpp:747
void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder, const MDNode *GVarMD)
Definition: SPIRVUtils.cpp:183