LLVM 20.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"
20#include "llvm/IR/Attributes.h"
21#include "llvm/IR/Constants.h"
23#include "llvm/IR/IntrinsicsSPIRV.h"
25
26#define DEBUG_TYPE "spirv-prelegalizer"
27
28using namespace llvm;
29
30namespace {
31class SPIRVPreLegalizer : public MachineFunctionPass {
32public:
33 static char ID;
34 SPIRVPreLegalizer() : MachineFunctionPass(ID) {
36 }
37 bool runOnMachineFunction(MachineFunction &MF) override;
38};
39} // namespace
40
41static void
43 const SPIRVSubtarget &STI,
44 DenseMap<MachineInstr *, Type *> &TargetExtConstTypes,
45 SmallSet<Register, 4> &TrackedConstRegs) {
47 DenseMap<MachineInstr *, Register> RegsAlreadyAddedToDT;
48 SmallVector<MachineInstr *, 10> ToErase, ToEraseComposites;
49 for (MachineBasicBlock &MBB : MF) {
50 for (MachineInstr &MI : MBB) {
51 if (!isSpvIntrinsic(MI, Intrinsic::spv_track_constant))
52 continue;
53 ToErase.push_back(&MI);
54 Register SrcReg = MI.getOperand(2).getReg();
55 auto *Const =
56 cast<Constant>(cast<ConstantAsMetadata>(
57 MI.getOperand(3).getMetadata()->getOperand(0))
58 ->getValue());
59 if (auto *GV = dyn_cast<GlobalValue>(Const)) {
60 Register Reg = GR->find(GV, &MF);
61 if (!Reg.isValid()) {
62 GR->add(GV, &MF, SrcReg);
63 GR->addGlobalObject(GV, &MF, SrcReg);
64 } else
65 RegsAlreadyAddedToDT[&MI] = Reg;
66 } else {
67 Register Reg = GR->find(Const, &MF);
68 if (!Reg.isValid()) {
69 if (auto *ConstVec = dyn_cast<ConstantDataVector>(Const)) {
70 auto *BuildVec = MRI.getVRegDef(SrcReg);
71 assert(BuildVec &&
72 BuildVec->getOpcode() == TargetOpcode::G_BUILD_VECTOR);
73 for (unsigned i = 0; i < ConstVec->getNumElements(); ++i) {
74 // Ensure that OpConstantComposite reuses a constant when it's
75 // already created and available in the same machine function.
76 Constant *ElemConst = ConstVec->getElementAsConstant(i);
77 Register ElemReg = GR->find(ElemConst, &MF);
78 if (!ElemReg.isValid())
79 GR->add(ElemConst, &MF, BuildVec->getOperand(1 + i).getReg());
80 else
81 BuildVec->getOperand(1 + i).setReg(ElemReg);
82 }
83 }
84 GR->add(Const, &MF, SrcReg);
85 TrackedConstRegs.insert(SrcReg);
86 if (Const->getType()->isTargetExtTy()) {
87 // remember association so that we can restore it when assign types
88 MachineInstr *SrcMI = MRI.getVRegDef(SrcReg);
89 if (SrcMI && (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT ||
90 SrcMI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF))
91 TargetExtConstTypes[SrcMI] = Const->getType();
92 if (Const->isNullValue()) {
93 MachineIRBuilder MIB(MF);
94 SPIRVType *ExtType =
95 GR->getOrCreateSPIRVType(Const->getType(), MIB);
96 SrcMI->setDesc(STI.getInstrInfo()->get(SPIRV::OpConstantNull));
98 GR->getSPIRVTypeID(ExtType), false));
99 }
100 }
101 } else {
102 RegsAlreadyAddedToDT[&MI] = Reg;
103 // This MI is unused and will be removed. If the MI uses
104 // const_composite, it will be unused and should be removed too.
105 assert(MI.getOperand(2).isReg() && "Reg operand is expected");
106 MachineInstr *SrcMI = MRI.getVRegDef(MI.getOperand(2).getReg());
107 if (SrcMI && isSpvIntrinsic(*SrcMI, Intrinsic::spv_const_composite))
108 ToEraseComposites.push_back(SrcMI);
109 }
110 }
111 }
112 }
113 for (MachineInstr *MI : ToErase) {
114 Register Reg = MI->getOperand(2).getReg();
115 if (RegsAlreadyAddedToDT.contains(MI))
116 Reg = RegsAlreadyAddedToDT[MI];
117 auto *RC = MRI.getRegClassOrNull(MI->getOperand(0).getReg());
118 if (!MRI.getRegClassOrNull(Reg) && RC)
119 MRI.setRegClass(Reg, RC);
120 MRI.replaceRegWith(MI->getOperand(0).getReg(), Reg);
121 MI->eraseFromParent();
122 }
123 for (MachineInstr *MI : ToEraseComposites)
124 MI->eraseFromParent();
125}
126
127static void
129 const SmallSet<Register, 4> &TrackedConstRegs) {
132 const unsigned AssignNameOperandShift = 2;
133 for (MachineBasicBlock &MBB : MF) {
134 for (MachineInstr &MI : MBB) {
135 if (!isSpvIntrinsic(MI, Intrinsic::spv_assign_name))
136 continue;
137 unsigned NumOp = MI.getNumExplicitDefs() + AssignNameOperandShift;
138 while (MI.getOperand(NumOp).isReg()) {
139 MachineOperand &MOp = MI.getOperand(NumOp);
140 MachineInstr *ConstMI = MRI.getVRegDef(MOp.getReg());
141 assert(ConstMI->getOpcode() == TargetOpcode::G_CONSTANT);
142 MI.removeOperand(NumOp);
143 MI.addOperand(MachineOperand::CreateImm(
144 ConstMI->getOperand(1).getCImm()->getZExtValue()));
145 Register DefReg = ConstMI->getOperand(0).getReg();
146 if (MRI.use_empty(DefReg) && !TrackedConstRegs.contains(DefReg))
147 ToErase.push_back(ConstMI);
148 }
149 }
150 }
151 for (MachineInstr *MI : ToErase)
152 MI->eraseFromParent();
153}
154
157 for (MachineRegisterInfo::use_instr_iterator I = MRI->use_instr_begin(Reg),
158 IE = MRI->use_instr_end();
159 I != IE; ++I) {
160 MachineInstr *UseMI = &*I;
161 if ((isSpvIntrinsic(*UseMI, Intrinsic::spv_assign_ptr_type) ||
162 isSpvIntrinsic(*UseMI, Intrinsic::spv_assign_type)) &&
163 UseMI->getOperand(1).getReg() == Reg)
164 return UseMI;
165 }
166 return nullptr;
167}
168
170 Register ResVReg, Register OpReg) {
171 SPIRVType *ResType = GR->getSPIRVTypeForVReg(ResVReg);
172 SPIRVType *OpType = GR->getSPIRVTypeForVReg(OpReg);
173 assert(ResType && OpType && "Operand types are expected");
174 if (!GR->isBitcastCompatible(ResType, OpType))
175 report_fatal_error("incompatible result and operand types in a bitcast");
177 if (!MRI->getRegClassOrNull(ResVReg))
178 MRI->setRegClass(ResVReg, GR->getRegClass(ResType));
179 if (ResType == OpType)
180 MIB.buildInstr(TargetOpcode::COPY).addDef(ResVReg).addUse(OpReg);
181 else
182 MIB.buildInstr(SPIRV::OpBitcast)
183 .addDef(ResVReg)
184 .addUse(GR->getSPIRVTypeID(ResType))
185 .addUse(OpReg);
186}
187
188// We do instruction selections early instead of calling MIB.buildBitcast()
189// generating the general op code G_BITCAST. When MachineVerifier validates
190// G_BITCAST we see a check of a kind: if Source Type is equal to Destination
191// Type then report error "bitcast must change the type". This doesn't take into
192// account the notion of a typed pointer that is important for SPIR-V where a
193// user may and should use bitcast between pointers with different pointee types
194// (https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpBitcast).
195// It's important for correct lowering in SPIR-V, because interpretation of the
196// data type is not left to instructions that utilize the pointer, but encoded
197// by the pointer declaration, and the SPIRV target can and must handle the
198// declaration and use of pointers that specify the type of data they point to.
199// It's not feasible to improve validation of G_BITCAST using just information
200// provided by low level types of source and destination. Therefore we don't
201// produce G_BITCAST as the general op code with semantics different from
202// OpBitcast, but rather lower to OpBitcast immediately. As for now, the only
203// difference would be that CombinerHelper couldn't transform known patterns
204// around G_BUILD_VECTOR. See discussion
205// in https://github.com/llvm/llvm-project/pull/110270 for even more context.
207 MachineIRBuilder MIB) {
209 for (MachineBasicBlock &MBB : MF) {
210 for (MachineInstr &MI : MBB) {
211 if (MI.getOpcode() != TargetOpcode::G_BITCAST)
212 continue;
213 MIB.setInsertPt(*MI.getParent(), MI);
214 buildOpBitcast(GR, MIB, MI.getOperand(0).getReg(),
215 MI.getOperand(1).getReg());
216 ToErase.push_back(&MI);
217 }
218 }
219 for (MachineInstr *MI : ToErase)
220 MI->eraseFromParent();
221}
222
224 MachineIRBuilder MIB) {
225 // Get access to information about available extensions
226 const SPIRVSubtarget *ST =
227 static_cast<const SPIRVSubtarget *>(&MIB.getMF().getSubtarget());
229 for (MachineBasicBlock &MBB : MF) {
230 for (MachineInstr &MI : MBB) {
231 if (!isSpvIntrinsic(MI, Intrinsic::spv_bitcast) &&
232 !isSpvIntrinsic(MI, Intrinsic::spv_ptrcast))
233 continue;
234 assert(MI.getOperand(2).isReg());
235 MIB.setInsertPt(*MI.getParent(), MI);
236 ToErase.push_back(&MI);
237 if (isSpvIntrinsic(MI, Intrinsic::spv_bitcast)) {
238 MIB.buildBitcast(MI.getOperand(0).getReg(), MI.getOperand(2).getReg());
239 continue;
240 }
241 Register Def = MI.getOperand(0).getReg();
242 Register Source = MI.getOperand(2).getReg();
243 Type *ElemTy = getMDOperandAsType(MI.getOperand(3).getMetadata(), 0);
244 SPIRVType *BaseTy = GR->getOrCreateSPIRVType(ElemTy, MIB);
245 SPIRVType *AssignedPtrType = GR->getOrCreateSPIRVPointerType(
247 addressSpaceToStorageClass(MI.getOperand(4).getImm(), *ST));
248
249 // If the ptrcast would be redundant, replace all uses with the source
250 // register.
252 if (GR->getSPIRVTypeForVReg(Source) == AssignedPtrType) {
253 // Erase Def's assign type instruction if we are going to replace Def.
254 if (MachineInstr *AssignMI = findAssignTypeInstr(Def, MRI))
255 ToErase.push_back(AssignMI);
256 MRI->replaceRegWith(Def, Source);
257 } else {
258 GR->assignSPIRVTypeToVReg(AssignedPtrType, Def, MF);
259 MIB.buildBitcast(Def, Source);
260 }
261 }
262 }
263 for (MachineInstr *MI : ToErase)
264 MI->eraseFromParent();
265}
266
267// Translating GV, IRTranslator sometimes generates following IR:
268// %1 = G_GLOBAL_VALUE
269// %2 = COPY %1
270// %3 = G_ADDRSPACE_CAST %2
271//
272// or
273//
274// %1 = G_ZEXT %2
275// G_MEMCPY ... %2 ...
276//
277// New registers have no SPIRVType and no register class info.
278//
279// Set SPIRVType for GV, propagate it from GV to other instructions,
280// also set register classes.
283 MachineIRBuilder &MIB) {
284 SPIRVType *SpvType = nullptr;
285 assert(MI && "Machine instr is expected");
286 if (MI->getOperand(0).isReg()) {
287 Register Reg = MI->getOperand(0).getReg();
288 SpvType = GR->getSPIRVTypeForVReg(Reg);
289 if (!SpvType) {
290 switch (MI->getOpcode()) {
291 case TargetOpcode::G_FCONSTANT:
292 case TargetOpcode::G_CONSTANT: {
293 MIB.setInsertPt(*MI->getParent(), MI);
294 Type *Ty = MI->getOperand(1).getCImm()->getType();
295 SpvType = GR->getOrCreateSPIRVType(Ty, MIB);
296 break;
297 }
298 case TargetOpcode::G_GLOBAL_VALUE: {
299 MIB.setInsertPt(*MI->getParent(), MI);
300 const GlobalValue *Global = MI->getOperand(1).getGlobal();
302 auto *Ty = TypedPointerType::get(ElementTy,
303 Global->getType()->getAddressSpace());
304 SpvType = GR->getOrCreateSPIRVType(Ty, MIB);
305 break;
306 }
307 case TargetOpcode::G_ANYEXT:
308 case TargetOpcode::G_SEXT:
309 case TargetOpcode::G_ZEXT: {
310 if (MI->getOperand(1).isReg()) {
311 if (MachineInstr *DefInstr =
312 MRI.getVRegDef(MI->getOperand(1).getReg())) {
313 if (SPIRVType *Def = propagateSPIRVType(DefInstr, GR, MRI, MIB)) {
314 unsigned CurrentBW = GR->getScalarOrVectorBitWidth(Def);
315 unsigned ExpectedBW =
316 std::max(MRI.getType(Reg).getScalarSizeInBits(), CurrentBW);
317 unsigned NumElements = GR->getScalarOrVectorComponentCount(Def);
318 SpvType = GR->getOrCreateSPIRVIntegerType(ExpectedBW, MIB);
319 if (NumElements > 1)
320 SpvType =
321 GR->getOrCreateSPIRVVectorType(SpvType, NumElements, MIB);
322 }
323 }
324 }
325 break;
326 }
327 case TargetOpcode::G_PTRTOINT:
328 SpvType = GR->getOrCreateSPIRVIntegerType(
329 MRI.getType(Reg).getScalarSizeInBits(), MIB);
330 break;
331 case TargetOpcode::G_TRUNC:
332 case TargetOpcode::G_ADDRSPACE_CAST:
333 case TargetOpcode::G_PTR_ADD:
334 case TargetOpcode::COPY: {
335 MachineOperand &Op = MI->getOperand(1);
336 MachineInstr *Def = Op.isReg() ? MRI.getVRegDef(Op.getReg()) : nullptr;
337 if (Def)
338 SpvType = propagateSPIRVType(Def, GR, MRI, MIB);
339 break;
340 }
341 default:
342 break;
343 }
344 if (SpvType) {
345 // check if the address space needs correction
346 LLT RegType = MRI.getType(Reg);
347 if (SpvType->getOpcode() == SPIRV::OpTypePointer &&
348 RegType.isPointer() &&
350 RegType.getAddressSpace()) {
351 const SPIRVSubtarget &ST =
352 MI->getParent()->getParent()->getSubtarget<SPIRVSubtarget>();
353 SpvType = GR->getOrCreateSPIRVPointerType(
354 GR->getPointeeType(SpvType), *MI, *ST.getInstrInfo(),
356 }
357 GR->assignSPIRVTypeToVReg(SpvType, Reg, MIB.getMF());
358 }
359 if (!MRI.getRegClassOrNull(Reg))
360 MRI.setRegClass(Reg, SpvType ? GR->getRegClass(SpvType)
361 : &SPIRV::iIDRegClass);
362 }
363 }
364 return SpvType;
365}
366
367// To support current approach and limitations wrt. bit width here we widen a
368// scalar register with a bit width greater than 1 to valid sizes and cap it to
369// 64 width.
371 LLT RegType = MRI.getType(Reg);
372 if (!RegType.isScalar())
373 return;
374 unsigned Sz = RegType.getScalarSizeInBits();
375 if (Sz == 1)
376 return;
377 unsigned NewSz = std::min(std::max(1u << Log2_32_Ceil(Sz), 8u), 64u);
378 if (NewSz != Sz)
379 MRI.setType(Reg, LLT::scalar(NewSz));
380}
381
382static std::pair<Register, unsigned>
384 const SPIRVGlobalRegistry &GR) {
385 if (!SpvType)
386 SpvType = GR.getSPIRVTypeForVReg(SrcReg);
387 const TargetRegisterClass *RC = GR.getRegClass(SpvType);
388 Register Reg = MRI.createGenericVirtualRegister(GR.getRegType(SpvType));
389 MRI.setRegClass(Reg, RC);
390 unsigned GetIdOp = SPIRV::GET_ID;
391 if (RC == &SPIRV::fIDRegClass)
392 GetIdOp = SPIRV::GET_fID;
393 else if (RC == &SPIRV::pIDRegClass)
394 GetIdOp = SPIRV::GET_pID;
395 else if (RC == &SPIRV::vfIDRegClass)
396 GetIdOp = SPIRV::GET_vfID;
397 else if (RC == &SPIRV::vpIDRegClass)
398 GetIdOp = SPIRV::GET_vpID;
399 else if (RC == &SPIRV::vIDRegClass)
400 GetIdOp = SPIRV::GET_vID;
401 return {Reg, GetIdOp};
402}
403
405 MachineBasicBlock &MBB = *Def->getParent();
407 Def->getNextNode() ? Def->getNextNode()->getIterator() : MBB.end();
408 // Skip all the PHI and debug instructions.
409 while (DefIt != MBB.end() &&
410 (DefIt->isPHI() || DefIt->isDebugOrPseudoInstr()))
411 DefIt = std::next(DefIt);
412 MIB.setInsertPt(MBB, DefIt);
413}
414
415// Insert ASSIGN_TYPE instuction between Reg and its definition, set NewReg as
416// a dst of the definition, assign SPIRVType to both registers. If SpvType is
417// provided, use it as SPIRVType in ASSIGN_TYPE, otherwise create it from Ty.
418// It's used also in SPIRVBuiltins.cpp.
419// TODO: maybe move to SPIRVUtils.
420namespace llvm {
424 assert((Ty || SpvType) && "Either LLVM or SPIRV type is expected.");
425 MachineInstr *Def = MRI.getVRegDef(Reg);
426 setInsertPtAfterDef(MIB, Def);
427 SpvType = SpvType ? SpvType : GR->getOrCreateSPIRVType(Ty, MIB);
428 Register NewReg = MRI.createGenericVirtualRegister(MRI.getType(Reg));
429 if (auto *RC = MRI.getRegClassOrNull(Reg)) {
430 MRI.setRegClass(NewReg, RC);
431 } else {
432 auto RegClass = GR->getRegClass(SpvType);
433 MRI.setRegClass(NewReg, RegClass);
434 MRI.setRegClass(Reg, RegClass);
435 }
436 GR->assignSPIRVTypeToVReg(SpvType, Reg, MIB.getMF());
437 // This is to make it convenient for Legalizer to get the SPIRVType
438 // when processing the actual MI (i.e. not pseudo one).
439 GR->assignSPIRVTypeToVReg(SpvType, NewReg, MIB.getMF());
440 // Copy MIFlags from Def to ASSIGN_TYPE instruction. It's required to keep
441 // the flags after instruction selection.
442 const uint32_t Flags = Def->getFlags();
443 MIB.buildInstr(SPIRV::ASSIGN_TYPE)
444 .addDef(Reg)
445 .addUse(NewReg)
446 .addUse(GR->getSPIRVTypeID(SpvType))
447 .setMIFlags(Flags);
448 for (unsigned I = 0, E = Def->getNumDefs(); I != E; ++I) {
449 MachineOperand &MO = Def->getOperand(I);
450 if (MO.getReg() == Reg) {
451 MO.setReg(NewReg);
452 break;
453 }
454 }
455 return NewReg;
456}
457
460 MIB.setInsertPt(*MI.getParent(), MI.getIterator());
461 for (auto &Op : MI.operands()) {
462 if (!Op.isReg() || Op.isDef())
463 continue;
464 Register OpReg = Op.getReg();
465 SPIRVType *SpvType = GR->getSPIRVTypeForVReg(OpReg);
466 auto IdOpInfo = createNewIdReg(SpvType, OpReg, MRI, *GR);
467 MIB.buildInstr(IdOpInfo.second).addDef(IdOpInfo.first).addUse(OpReg);
468 const TargetRegisterClass *RC = GR->getRegClass(SpvType);
469 if (RC != MRI.getRegClassOrNull(OpReg))
470 MRI.setRegClass(OpReg, RC);
471 Op.setReg(IdOpInfo.first);
472 }
473}
474} // namespace llvm
475
476static void
479 DenseMap<MachineInstr *, Type *> &TargetExtConstTypes) {
480 // Get access to information about available extensions
481 const SPIRVSubtarget *ST =
482 static_cast<const SPIRVSubtarget *>(&MIB.getMF().getSubtarget());
483
486 DenseMap<MachineInstr *, Register> RegsAlreadyAddedToDT;
487
488 bool IsExtendedInts =
489 ST->canUseExtension(
490 SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers) ||
491 ST->canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
492
493 for (MachineBasicBlock *MBB : post_order(&MF)) {
494 if (MBB->empty())
495 continue;
496
497 bool ReachedBegin = false;
498 for (auto MII = std::prev(MBB->end()), Begin = MBB->begin();
499 !ReachedBegin;) {
500 MachineInstr &MI = *MII;
501 unsigned MIOp = MI.getOpcode();
502
503 if (!IsExtendedInts) {
504 // validate bit width of scalar registers
505 for (const auto &MOP : MI.operands())
506 if (MOP.isReg())
507 widenScalarLLTNextPow2(MOP.getReg(), MRI);
508 }
509
510 if (isSpvIntrinsic(MI, Intrinsic::spv_assign_ptr_type)) {
511 Register Reg = MI.getOperand(1).getReg();
512 MIB.setInsertPt(*MI.getParent(), MI.getIterator());
513 Type *ElementTy = getMDOperandAsType(MI.getOperand(2).getMetadata(), 0);
514 SPIRVType *BaseTy = GR->getOrCreateSPIRVType(ElementTy, MIB);
515 SPIRVType *AssignedPtrType = GR->getOrCreateSPIRVPointerType(
517 addressSpaceToStorageClass(MI.getOperand(3).getImm(), *ST));
518 MachineInstr *Def = MRI.getVRegDef(Reg);
519 assert(Def && "Expecting an instruction that defines the register");
520 // G_GLOBAL_VALUE already has type info.
521 if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE &&
522 Def->getOpcode() != SPIRV::ASSIGN_TYPE)
523 insertAssignInstr(Reg, nullptr, AssignedPtrType, GR, MIB,
524 MF.getRegInfo());
525 ToErase.push_back(&MI);
526 } else if (isSpvIntrinsic(MI, Intrinsic::spv_assign_type)) {
527 Register Reg = MI.getOperand(1).getReg();
528 Type *Ty = getMDOperandAsType(MI.getOperand(2).getMetadata(), 0);
529 MachineInstr *Def = MRI.getVRegDef(Reg);
530 assert(Def && "Expecting an instruction that defines the register");
531 // G_GLOBAL_VALUE already has type info.
532 if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE &&
533 Def->getOpcode() != SPIRV::ASSIGN_TYPE)
534 insertAssignInstr(Reg, Ty, nullptr, GR, MIB, MF.getRegInfo());
535 ToErase.push_back(&MI);
536 } else if (MIOp == TargetOpcode::FAKE_USE && MI.getNumOperands() > 0) {
537 MachineInstr *MdMI = MI.getPrevNode();
538 if (MdMI && isSpvIntrinsic(*MdMI, Intrinsic::spv_value_md)) {
539 // It's an internal service info from before IRTranslator passes.
540 MachineInstr *Def = getVRegDef(MRI, MI.getOperand(0).getReg());
541 for (unsigned I = 1, E = MI.getNumOperands(); I != E && Def; ++I)
542 if (getVRegDef(MRI, MI.getOperand(I).getReg()) != Def)
543 Def = nullptr;
544 if (Def) {
545 const MDNode *MD = MdMI->getOperand(1).getMetadata();
547 cast<MDString>(MD->getOperand(1))->getString();
548 const MDNode *TypeMD = cast<MDNode>(MD->getOperand(0));
549 Type *ValueTy = getMDOperandAsType(TypeMD, 0);
550 GR->addValueAttrs(Def, std::make_pair(ValueTy, ValueName.str()));
551 }
552 ToErase.push_back(MdMI);
553 }
554 ToErase.push_back(&MI);
555 } else if (MIOp == TargetOpcode::G_CONSTANT ||
556 MIOp == TargetOpcode::G_FCONSTANT ||
557 MIOp == TargetOpcode::G_BUILD_VECTOR) {
558 // %rc = G_CONSTANT ty Val
559 // ===>
560 // %cty = OpType* ty
561 // %rctmp = G_CONSTANT ty Val
562 // %rc = ASSIGN_TYPE %rctmp, %cty
563 Register Reg = MI.getOperand(0).getReg();
564 bool NeedAssignType = true;
565 if (MRI.hasOneUse(Reg)) {
566 MachineInstr &UseMI = *MRI.use_instr_begin(Reg);
567 if (isSpvIntrinsic(UseMI, Intrinsic::spv_assign_type) ||
568 isSpvIntrinsic(UseMI, Intrinsic::spv_assign_name))
569 continue;
570 if (UseMI.getOpcode() == SPIRV::ASSIGN_TYPE)
571 NeedAssignType = false;
572 }
573 Type *Ty = nullptr;
574 if (MIOp == TargetOpcode::G_CONSTANT) {
575 auto TargetExtIt = TargetExtConstTypes.find(&MI);
576 Ty = TargetExtIt == TargetExtConstTypes.end()
577 ? MI.getOperand(1).getCImm()->getType()
578 : TargetExtIt->second;
579 const ConstantInt *OpCI = MI.getOperand(1).getCImm();
580 // TODO: we may wish to analyze here if OpCI is zero and LLT RegType =
581 // MRI.getType(Reg); RegType.isPointer() is true, so that we observe
582 // at this point not i64/i32 constant but null pointer in the
583 // corresponding address space of RegType.getAddressSpace(). This may
584 // help to successfully validate the case when a OpConstantComposite's
585 // constituent has type that does not match Result Type of
586 // OpConstantComposite (see, for example,
587 // pointers/PtrCast-null-in-OpSpecConstantOp.ll).
588 Register PrimaryReg = GR->find(OpCI, &MF);
589 if (!PrimaryReg.isValid()) {
590 GR->add(OpCI, &MF, Reg);
591 } else if (PrimaryReg != Reg &&
592 MRI.getType(Reg) == MRI.getType(PrimaryReg)) {
593 auto *RCReg = MRI.getRegClassOrNull(Reg);
594 auto *RCPrimary = MRI.getRegClassOrNull(PrimaryReg);
595 if (!RCReg || RCPrimary == RCReg) {
596 RegsAlreadyAddedToDT[&MI] = PrimaryReg;
597 ToErase.push_back(&MI);
598 NeedAssignType = false;
599 }
600 }
601 } else if (MIOp == TargetOpcode::G_FCONSTANT) {
602 Ty = MI.getOperand(1).getFPImm()->getType();
603 } else {
604 assert(MIOp == TargetOpcode::G_BUILD_VECTOR);
605 Type *ElemTy = nullptr;
606 MachineInstr *ElemMI = MRI.getVRegDef(MI.getOperand(1).getReg());
607 assert(ElemMI);
608
609 if (ElemMI->getOpcode() == TargetOpcode::G_CONSTANT) {
610 ElemTy = ElemMI->getOperand(1).getCImm()->getType();
611 } else if (ElemMI->getOpcode() == TargetOpcode::G_FCONSTANT) {
612 ElemTy = ElemMI->getOperand(1).getFPImm()->getType();
613 } else {
614 // There may be a case when we already know Reg's type.
615 MachineInstr *NextMI = MI.getNextNode();
616 if (!NextMI || NextMI->getOpcode() != SPIRV::ASSIGN_TYPE ||
617 NextMI->getOperand(1).getReg() != Reg)
618 llvm_unreachable("Unexpected opcode");
619 }
620 if (ElemTy)
621 Ty = VectorType::get(
622 ElemTy, MI.getNumExplicitOperands() - MI.getNumExplicitDefs(),
623 false);
624 else
625 NeedAssignType = false;
626 }
627 if (NeedAssignType)
628 insertAssignInstr(Reg, Ty, nullptr, GR, MIB, MRI);
629 } else if (MIOp == TargetOpcode::G_GLOBAL_VALUE) {
630 propagateSPIRVType(&MI, GR, MRI, MIB);
631 }
632
633 if (MII == Begin)
634 ReachedBegin = true;
635 else
636 --MII;
637 }
638 }
639 for (MachineInstr *MI : ToErase) {
640 auto It = RegsAlreadyAddedToDT.find(MI);
641 if (RegsAlreadyAddedToDT.contains(MI))
642 MRI.replaceRegWith(MI->getOperand(0).getReg(), It->second);
643 MI->eraseFromParent();
644 }
645
646 // Address the case when IRTranslator introduces instructions with new
647 // registers without SPIRVType associated.
648 for (MachineBasicBlock &MBB : MF) {
649 for (MachineInstr &MI : MBB) {
650 switch (MI.getOpcode()) {
651 case TargetOpcode::G_TRUNC:
652 case TargetOpcode::G_ANYEXT:
653 case TargetOpcode::G_SEXT:
654 case TargetOpcode::G_ZEXT:
655 case TargetOpcode::G_PTRTOINT:
656 case TargetOpcode::COPY:
657 case TargetOpcode::G_ADDRSPACE_CAST:
658 propagateSPIRVType(&MI, GR, MRI, MIB);
659 break;
660 }
661 }
662 }
663}
664
665// Defined in SPIRVLegalizerInfo.cpp.
666extern bool isTypeFoldingSupported(unsigned Opcode);
667
670 MachineIRBuilder MIB) {
672 for (MachineBasicBlock &MBB : MF)
673 for (MachineInstr &MI : MBB)
674 if (isTypeFoldingSupported(MI.getOpcode()))
675 processInstr(MI, MIB, MRI, GR);
676}
677
678static Register
680 SmallVector<unsigned, 4> *Ops = nullptr) {
681 Register DefReg;
682 unsigned StartOp = InlineAsm::MIOp_FirstOperand,
684 for (unsigned Idx = StartOp, MISz = MI->getNumOperands(); Idx != MISz;
685 ++Idx) {
686 const MachineOperand &MO = MI->getOperand(Idx);
687 if (MO.isMetadata())
688 continue;
689 if (Idx == AsmDescOp && MO.isImm()) {
690 // compute the index of the next operand descriptor
691 const InlineAsm::Flag F(MO.getImm());
692 AsmDescOp += 1 + F.getNumOperandRegisters();
693 continue;
694 }
695 if (MO.isReg() && MO.isDef()) {
696 if (!Ops)
697 return MO.getReg();
698 else
699 DefReg = MO.getReg();
700 } else if (Ops) {
701 Ops->push_back(Idx);
702 }
703 }
704 return DefReg;
705}
706
707static void
709 const SPIRVSubtarget &ST, MachineIRBuilder MIRBuilder,
710 const SmallVector<MachineInstr *> &ToProcess) {
712 Register AsmTargetReg;
713 for (unsigned i = 0, Sz = ToProcess.size(); i + 1 < Sz; i += 2) {
714 MachineInstr *I1 = ToProcess[i], *I2 = ToProcess[i + 1];
715 assert(isSpvIntrinsic(*I1, Intrinsic::spv_inline_asm) && I2->isInlineAsm());
716 MIRBuilder.setInsertPt(*I2->getParent(), *I2);
717
718 if (!AsmTargetReg.isValid()) {
719 // define vendor specific assembly target or dialect
720 AsmTargetReg = MRI.createGenericVirtualRegister(LLT::scalar(32));
721 MRI.setRegClass(AsmTargetReg, &SPIRV::iIDRegClass);
722 auto AsmTargetMIB =
723 MIRBuilder.buildInstr(SPIRV::OpAsmTargetINTEL).addDef(AsmTargetReg);
724 addStringImm(ST.getTargetTripleAsStr(), AsmTargetMIB);
725 GR->add(AsmTargetMIB.getInstr(), &MF, AsmTargetReg);
726 }
727
728 // create types
729 const MDNode *IAMD = I1->getOperand(1).getMetadata();
730 FunctionType *FTy = cast<FunctionType>(getMDOperandAsType(IAMD, 0));
732 for (const auto &ArgTy : FTy->params())
733 ArgTypes.push_back(GR->getOrCreateSPIRVType(ArgTy, MIRBuilder));
734 SPIRVType *RetType =
735 GR->getOrCreateSPIRVType(FTy->getReturnType(), MIRBuilder);
737 FTy, RetType, ArgTypes, MIRBuilder);
738
739 // define vendor specific assembly instructions string
740 Register AsmReg = MRI.createGenericVirtualRegister(LLT::scalar(32));
741 MRI.setRegClass(AsmReg, &SPIRV::iIDRegClass);
742 auto AsmMIB = MIRBuilder.buildInstr(SPIRV::OpAsmINTEL)
743 .addDef(AsmReg)
744 .addUse(GR->getSPIRVTypeID(RetType))
745 .addUse(GR->getSPIRVTypeID(FuncType))
746 .addUse(AsmTargetReg);
747 // inline asm string:
748 addStringImm(I2->getOperand(InlineAsm::MIOp_AsmString).getSymbolName(),
749 AsmMIB);
750 // inline asm constraint string:
751 addStringImm(cast<MDString>(I1->getOperand(2).getMetadata()->getOperand(0))
752 ->getString(),
753 AsmMIB);
754 GR->add(AsmMIB.getInstr(), &MF, AsmReg);
755
756 // calls the inline assembly instruction
757 unsigned ExtraInfo = I2->getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
758 if (ExtraInfo & InlineAsm::Extra_HasSideEffects)
759 MIRBuilder.buildInstr(SPIRV::OpDecorate)
760 .addUse(AsmReg)
761 .addImm(static_cast<uint32_t>(SPIRV::Decoration::SideEffectsINTEL));
762
764 if (!DefReg.isValid()) {
765 DefReg = MRI.createGenericVirtualRegister(LLT::scalar(32));
766 MRI.setRegClass(DefReg, &SPIRV::iIDRegClass);
767 SPIRVType *VoidType = GR->getOrCreateSPIRVType(
768 Type::getVoidTy(MF.getFunction().getContext()), MIRBuilder);
769 GR->assignSPIRVTypeToVReg(VoidType, DefReg, MF);
770 }
771
772 auto AsmCall = MIRBuilder.buildInstr(SPIRV::OpAsmCallINTEL)
773 .addDef(DefReg)
774 .addUse(GR->getSPIRVTypeID(RetType))
775 .addUse(AsmReg);
776 for (unsigned IntrIdx = 3; IntrIdx < I1->getNumOperands(); ++IntrIdx)
777 AsmCall.addUse(I1->getOperand(IntrIdx).getReg());
778 }
779 for (MachineInstr *MI : ToProcess)
780 MI->eraseFromParent();
781}
782
784 const SPIRVSubtarget &ST,
785 MachineIRBuilder MIRBuilder) {
787 for (MachineBasicBlock &MBB : MF) {
788 for (MachineInstr &MI : MBB) {
789 if (isSpvIntrinsic(MI, Intrinsic::spv_inline_asm) ||
790 MI.getOpcode() == TargetOpcode::INLINEASM)
791 ToProcess.push_back(&MI);
792 }
793 }
794 if (ToProcess.size() == 0)
795 return;
796
797 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly))
798 report_fatal_error("Inline assembly instructions require the "
799 "following SPIR-V extension: SPV_INTEL_inline_assembly",
800 false);
801
802 insertInlineAsmProcess(MF, GR, ST, MIRBuilder, ToProcess);
803}
804
807 for (MachineBasicBlock &MBB : MF) {
808 for (MachineInstr &MI : MBB) {
809 if (!isSpvIntrinsic(MI, Intrinsic::spv_assign_decoration))
810 continue;
811 MIB.setInsertPt(*MI.getParent(), MI.getNextNode());
812 buildOpSpirvDecorations(MI.getOperand(1).getReg(), MIB,
813 MI.getOperand(2).getMetadata());
814 ToErase.push_back(&MI);
815 }
816 }
817 for (MachineInstr *MI : ToErase)
818 MI->eraseFromParent();
819}
820
821// LLVM allows the switches to use registers as cases, while SPIR-V required
822// those to be immediate values. This function replaces such operands with the
823// equivalent immediate constant.
826 MachineIRBuilder MIB) {
828 for (MachineBasicBlock &MBB : MF) {
829 for (MachineInstr &MI : MBB) {
830 if (!isSpvIntrinsic(MI, Intrinsic::spv_switch))
831 continue;
832
834 NewOperands.push_back(MI.getOperand(0)); // Opcode
835 NewOperands.push_back(MI.getOperand(1)); // Condition
836 NewOperands.push_back(MI.getOperand(2)); // Default
837 for (unsigned i = 3; i < MI.getNumOperands(); i += 2) {
838 Register Reg = MI.getOperand(i).getReg();
839 MachineInstr *ConstInstr = getDefInstrMaybeConstant(Reg, &MRI);
840 NewOperands.push_back(
842
843 NewOperands.push_back(MI.getOperand(i + 1));
844 }
845
846 assert(MI.getNumOperands() == NewOperands.size());
847 while (MI.getNumOperands() > 0)
848 MI.removeOperand(0);
849 for (auto &MO : NewOperands)
850 MI.addOperand(MO);
851 }
852 }
853}
854
855// Some instructions are used during CodeGen but should never be emitted.
856// Cleaning up those.
859 for (MachineBasicBlock &MBB : MF) {
860 for (MachineInstr &MI : MBB) {
861 if (isSpvIntrinsic(MI, Intrinsic::spv_track_constant) ||
862 MI.getOpcode() == TargetOpcode::G_BRINDIRECT)
863 ToEraseMI.push_back(&MI);
864 }
865 }
866
867 for (MachineInstr *MI : ToEraseMI)
868 MI->eraseFromParent();
869}
870
871// Find all usages of G_BLOCK_ADDR in our intrinsics and replace those
872// operands/registers by the actual MBB it references.
874 MachineIRBuilder MIB) {
875 // Gather the reverse-mapping BB -> MBB.
877 for (MachineBasicBlock &MBB : MF)
878 BB2MBB[MBB.getBasicBlock()] = &MBB;
879
880 // Gather instructions requiring patching. For now, only those can use
881 // G_BLOCK_ADDR.
882 SmallVector<MachineInstr *, 8> InstructionsToPatch;
883 for (MachineBasicBlock &MBB : MF) {
884 for (MachineInstr &MI : MBB) {
885 if (isSpvIntrinsic(MI, Intrinsic::spv_switch) ||
886 isSpvIntrinsic(MI, Intrinsic::spv_loop_merge) ||
887 isSpvIntrinsic(MI, Intrinsic::spv_selection_merge))
888 InstructionsToPatch.push_back(&MI);
889 }
890 }
891
892 // For each instruction to fix, we replace all the G_BLOCK_ADDR operands by
893 // the actual MBB it references. Once those references have been updated, we
894 // can cleanup remaining G_BLOCK_ADDR references.
895 SmallPtrSet<MachineBasicBlock *, 8> ClearAddressTaken;
898 for (MachineInstr *MI : InstructionsToPatch) {
900 for (unsigned i = 0; i < MI->getNumOperands(); ++i) {
901 // The operand is not a register, keep as-is.
902 if (!MI->getOperand(i).isReg()) {
903 NewOps.push_back(MI->getOperand(i));
904 continue;
905 }
906
907 Register Reg = MI->getOperand(i).getReg();
908 MachineInstr *BuildMBB = MRI.getVRegDef(Reg);
909 // The register is not the result of G_BLOCK_ADDR, keep as-is.
910 if (!BuildMBB || BuildMBB->getOpcode() != TargetOpcode::G_BLOCK_ADDR) {
911 NewOps.push_back(MI->getOperand(i));
912 continue;
913 }
914
915 assert(BuildMBB && BuildMBB->getOpcode() == TargetOpcode::G_BLOCK_ADDR &&
916 BuildMBB->getOperand(1).isBlockAddress() &&
917 BuildMBB->getOperand(1).getBlockAddress());
918 BasicBlock *BB =
919 BuildMBB->getOperand(1).getBlockAddress()->getBasicBlock();
920 auto It = BB2MBB.find(BB);
921 if (It == BB2MBB.end())
922 report_fatal_error("cannot find a machine basic block by a basic block "
923 "in a switch statement");
924 MachineBasicBlock *ReferencedBlock = It->second;
925 NewOps.push_back(MachineOperand::CreateMBB(ReferencedBlock));
926
927 ClearAddressTaken.insert(ReferencedBlock);
928 ToEraseMI.insert(BuildMBB);
929 }
930
931 // Replace the operands.
932 assert(MI->getNumOperands() == NewOps.size());
933 while (MI->getNumOperands() > 0)
934 MI->removeOperand(0);
935 for (auto &MO : NewOps)
936 MI->addOperand(MO);
937
938 if (MachineInstr *Next = MI->getNextNode()) {
939 if (isSpvIntrinsic(*Next, Intrinsic::spv_track_constant)) {
940 ToEraseMI.insert(Next);
941 Next = MI->getNextNode();
942 }
943 if (Next && Next->getOpcode() == TargetOpcode::G_BRINDIRECT)
944 ToEraseMI.insert(Next);
945 }
946 }
947
948 // BlockAddress operands were used to keep information between passes,
949 // let's undo the "address taken" status to reflect that Succ doesn't
950 // actually correspond to an IR-level basic block.
951 for (MachineBasicBlock *Succ : ClearAddressTaken)
952 Succ->setAddressTakenIRBlock(nullptr);
953
954 // If we just delete G_BLOCK_ADDR instructions with BlockAddress operands,
955 // this leaves their BasicBlock counterparts in a "address taken" status. This
956 // would make AsmPrinter to generate a series of unneeded labels of a "Address
957 // of block that was removed by CodeGen" kind. Let's first ensure that we
958 // don't have a dangling BlockAddress constants by zapping the BlockAddress
959 // nodes, and only after that proceed with erasing G_BLOCK_ADDR instructions.
960 Constant *Replacement =
961 ConstantInt::get(Type::getInt32Ty(MF.getFunction().getContext()), 1);
962 for (MachineInstr *BlockAddrI : ToEraseMI) {
963 if (BlockAddrI->getOpcode() == TargetOpcode::G_BLOCK_ADDR) {
964 BlockAddress *BA = const_cast<BlockAddress *>(
965 BlockAddrI->getOperand(1).getBlockAddress());
967 ConstantExpr::getIntToPtr(Replacement, BA->getType()));
968 BA->destroyConstant();
969 }
970 BlockAddrI->eraseFromParent();
971 }
972}
973
975 if (MBB.empty())
976 return true;
977
978 // Branching SPIR-V intrinsics are not detected by this generic method.
979 // Thus, we can only trust negative result.
980 if (!MBB.canFallThrough())
981 return false;
982
983 // Otherwise, we must manually check if we have a SPIR-V intrinsic which
984 // prevent an implicit fallthrough.
986 It != E; ++It) {
987 if (isSpvIntrinsic(*It, Intrinsic::spv_switch))
988 return false;
989 }
990 return true;
991}
992
994 MachineIRBuilder MIB) {
995 // It is valid for MachineBasicBlocks to not finish with a branch instruction.
996 // In such cases, they will simply fallthrough their immediate successor.
997 for (MachineBasicBlock &MBB : MF) {
999 continue;
1000
1001 assert(std::distance(MBB.successors().begin(), MBB.successors().end()) ==
1002 1);
1003 MIB.setInsertPt(MBB, MBB.end());
1004 MIB.buildBr(**MBB.successors().begin());
1005 }
1006}
1007
1008bool SPIRVPreLegalizer::runOnMachineFunction(MachineFunction &MF) {
1009 // Initialize the type registry.
1011 SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
1012 GR->setCurrentFunc(MF);
1013 MachineIRBuilder MIB(MF);
1014 // a registry of target extension constants
1015 DenseMap<MachineInstr *, Type *> TargetExtConstTypes;
1016 // to keep record of tracked constants
1017 SmallSet<Register, 4> TrackedConstRegs;
1018 addConstantsToTrack(MF, GR, ST, TargetExtConstTypes, TrackedConstRegs);
1019 foldConstantsIntoIntrinsics(MF, TrackedConstRegs);
1020 insertBitcasts(MF, GR, MIB);
1021 generateAssignInstrs(MF, GR, MIB, TargetExtConstTypes);
1022
1023 processSwitchesConstants(MF, GR, MIB);
1024 processBlockAddr(MF, GR, MIB);
1026
1027 processInstrsWithTypeFolding(MF, GR, MIB);
1029 insertSpirvDecorations(MF, MIB);
1030 insertInlineAsm(MF, GR, ST, MIB);
1031 selectOpBitcasts(MF, GR, MIB);
1032
1033 return true;
1034}
1035
1036INITIALIZE_PASS(SPIRVPreLegalizer, DEBUG_TYPE, "SPIRV pre legalizer", false,
1037 false)
1038
1039char SPIRVPreLegalizer::ID = 0;
1040
1042 return new SPIRVPreLegalizer();
1043}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineBasicBlock & MBB
This file contains the simple types necessary to represent the attributes associated with functions a...
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
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:38
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static Register collectInlineAsmInstrOperands(MachineInstr *MI, SmallVector< unsigned, 4 > *Ops=nullptr)
static void cleanupHelperInstructions(MachineFunction &MF)
static void insertInlineAsm(MachineFunction &MF, SPIRVGlobalRegistry *GR, const SPIRVSubtarget &ST, MachineIRBuilder MIRBuilder)
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 void setInsertPtAfterDef(MachineIRBuilder &MIB, MachineInstr *Def)
static bool isImplicitFallthrough(MachineBasicBlock &MBB)
bool isTypeFoldingSupported(unsigned Opcode)
static void insertBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void processInstrsWithTypeFolding(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void widenScalarLLTNextPow2(Register Reg, MachineRegisterInfo &MRI)
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 buildOpBitcast(SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB, Register ResVReg, Register OpReg)
static void processBlockAddr(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void addConstantsToTrack(MachineFunction &MF, SPIRVGlobalRegistry *GR, const SPIRVSubtarget &STI, DenseMap< MachineInstr *, Type * > &TargetExtConstTypes, SmallSet< Register, 4 > &TrackedConstRegs)
#define DEBUG_TYPE
static void foldConstantsIntoIntrinsics(MachineFunction &MF, const SmallSet< Register, 4 > &TrackedConstRegs)
static void insertSpirvDecorations(MachineFunction &MF, MachineIRBuilder MIB)
static std::pair< Register, unsigned > createNewIdReg(SPIRVType *SpvType, Register SrcReg, MachineRegisterInfo &MRI, const SPIRVGlobalRegistry &GR)
static void generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB, DenseMap< MachineInstr *, Type * > &TargetExtConstTypes)
LLVM Basic Block Representation.
Definition: BasicBlock.h:61
The address of a basic block.
Definition: Constants.h:893
BasicBlock * getBasicBlock() const
Definition: Constants.h:924
static Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
Definition: Constants.cpp:2307
This is the shared class of boolean and integer constants.
Definition: Constants.h:83
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition: Constants.h:157
This is an important base class in LLVM.
Definition: Constant.h:42
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:156
iterator end()
Definition: DenseMap.h:84
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Definition: DenseMap.h:147
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:369
constexpr unsigned getScalarSizeInBits() const
Definition: LowLevelType.h:264
constexpr bool isScalar() const
Definition: LowLevelType.h:146
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
Definition: LowLevelType.h:42
constexpr bool isPointer() const
Definition: LowLevelType.h:149
constexpr unsigned getAddressSpace() const
Definition: LowLevelType.h:270
Metadata node.
Definition: Metadata.h:1069
const MDOperand & getOperand(unsigned I) const
Definition: Metadata.h:1430
reverse_iterator rend()
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
bool canFallThrough()
Return true if the block can implicitly transfer control to the block after it by falling off the end...
iterator_range< succ_iterator > successors()
reverse_iterator rbegin()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
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.
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:69
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:575
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
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:585
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)
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
static MachineOperand CreateImm(int64_t Val)
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,...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
constexpr bool isValid() const
Definition: Register.h:116
SPIRVType * getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, const MachineFunction &MF)
void add(const Constant *C, MachineFunction *MF, Register R)
bool isBitcastCompatible(const SPIRVType *Type1, const SPIRVType *Type2) const
unsigned getScalarOrVectorComponentCount(Register VReg) const
SPIRVType * getPointeeType(SPIRVType *PtrType)
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
SPIRVType * getOrCreateSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite, bool EmitIR=true)
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
Register find(const MachineInstr *MI, MachineFunction *MF)
SPIRVType * getOrCreateSPIRVPointerType(SPIRVType *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SClass=SPIRV::StorageClass::Function)
SPIRVType * getOrCreateSPIRVVectorType(SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
Type * getDeducedGlobalValueType(const GlobalValue *Global)
LLT getRegType(SPIRVType *SpvType) const
void addValueAttrs(MachineInstr *Key, std::pair< Type *, std::string > Val)
SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const
unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) const
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:384
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:519
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:132
bool contains(const T &V) const
Check if the SmallSet contains the given element.
Definition: SmallSet.h:222
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition: SmallSet.h:181
size_t size() const
Definition: SmallVector.h:78
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
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:51
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
static Type * getVoidTy(LLVMContext &C)
static IntegerType * getInt32Ty(LLVMContext &C)
static 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
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:534
#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
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:353
FunctionPass * createSPIRVPreLegalizerPass()
Register 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,...
iterator_range< po_iterator< T > > post_order(const T &G)
constexpr unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
Definition: SPIRVUtils.h:162
Type * toTypedPointer(Type *Ty)
Definition: SPIRVUtils.h:352
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
@ Global
Append to llvm.global_dtors.
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
Definition: SPIRVUtils.cpp:211
void processInstr(MachineInstr &MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR)
MachineInstr * getDefInstrMaybeConstant(Register &ConstReg, const MachineRegisterInfo *MRI)
Definition: SPIRVUtils.cpp:307
Type * getMDOperandAsType(const MDNode *N, unsigned I)
Definition: SPIRVUtils.cpp:338
void initializeSPIRVPreLegalizerPass(PassRegistry &)
bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID)
Definition: SPIRVUtils.cpp:332
void addStringImm(const StringRef &Str, MCInst &Inst)
Definition: SPIRVUtils.cpp:54
MachineInstr * getVRegDef(MachineRegisterInfo &MRI, Register Reg)
Definition: SPIRVUtils.cpp:704
void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder, const MDNode *GVarMD)
Definition: SPIRVUtils.cpp:149