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