LLVM 17.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
43 DenseMap<MachineInstr *, Register> RegsAlreadyAddedToDT;
44 SmallVector<MachineInstr *, 10> ToErase, ToEraseComposites;
45 for (MachineBasicBlock &MBB : MF) {
46 for (MachineInstr &MI : MBB) {
47 if (!isSpvIntrinsic(MI, Intrinsic::spv_track_constant))
48 continue;
49 ToErase.push_back(&MI);
50 auto *Const =
51 cast<Constant>(cast<ConstantAsMetadata>(
52 MI.getOperand(3).getMetadata()->getOperand(0))
53 ->getValue());
54 if (auto *GV = dyn_cast<GlobalValue>(Const)) {
55 Register Reg = GR->find(GV, &MF);
56 if (!Reg.isValid())
57 GR->add(GV, &MF, MI.getOperand(2).getReg());
58 else
59 RegsAlreadyAddedToDT[&MI] = Reg;
60 } else {
61 Register Reg = GR->find(Const, &MF);
62 if (!Reg.isValid()) {
63 if (auto *ConstVec = dyn_cast<ConstantDataVector>(Const)) {
64 auto *BuildVec = MRI.getVRegDef(MI.getOperand(2).getReg());
65 assert(BuildVec &&
66 BuildVec->getOpcode() == TargetOpcode::G_BUILD_VECTOR);
67 for (unsigned i = 0; i < ConstVec->getNumElements(); ++i)
68 GR->add(ConstVec->getElementAsConstant(i), &MF,
69 BuildVec->getOperand(1 + i).getReg());
70 }
71 GR->add(Const, &MF, MI.getOperand(2).getReg());
72 } else {
73 RegsAlreadyAddedToDT[&MI] = Reg;
74 // This MI is unused and will be removed. If the MI uses
75 // const_composite, it will be unused and should be removed too.
76 assert(MI.getOperand(2).isReg() && "Reg operand is expected");
77 MachineInstr *SrcMI = MRI.getVRegDef(MI.getOperand(2).getReg());
78 if (SrcMI && isSpvIntrinsic(*SrcMI, Intrinsic::spv_const_composite))
79 ToEraseComposites.push_back(SrcMI);
80 }
81 }
82 }
83 }
84 for (MachineInstr *MI : ToErase) {
85 Register Reg = MI->getOperand(2).getReg();
86 if (RegsAlreadyAddedToDT.find(MI) != RegsAlreadyAddedToDT.end())
87 Reg = RegsAlreadyAddedToDT[MI];
88 auto *RC = MRI.getRegClassOrNull(MI->getOperand(0).getReg());
89 if (!MRI.getRegClassOrNull(Reg) && RC)
90 MRI.setRegClass(Reg, RC);
91 MRI.replaceRegWith(MI->getOperand(0).getReg(), Reg);
92 MI->eraseFromParent();
93 }
94 for (MachineInstr *MI : ToEraseComposites)
95 MI->eraseFromParent();
96}
97
101 const unsigned AssignNameOperandShift = 2;
102 for (MachineBasicBlock &MBB : MF) {
103 for (MachineInstr &MI : MBB) {
104 if (!isSpvIntrinsic(MI, Intrinsic::spv_assign_name))
105 continue;
106 unsigned NumOp = MI.getNumExplicitDefs() + AssignNameOperandShift;
107 while (MI.getOperand(NumOp).isReg()) {
108 MachineOperand &MOp = MI.getOperand(NumOp);
109 MachineInstr *ConstMI = MRI.getVRegDef(MOp.getReg());
110 assert(ConstMI->getOpcode() == TargetOpcode::G_CONSTANT);
111 MI.removeOperand(NumOp);
112 MI.addOperand(MachineOperand::CreateImm(
113 ConstMI->getOperand(1).getCImm()->getZExtValue()));
114 if (MRI.use_empty(ConstMI->getOperand(0).getReg()))
115 ToErase.push_back(ConstMI);
116 }
117 }
118 }
119 for (MachineInstr *MI : ToErase)
120 MI->eraseFromParent();
121}
122
124 MachineIRBuilder MIB) {
126 for (MachineBasicBlock &MBB : MF) {
127 for (MachineInstr &MI : MBB) {
128 if (!isSpvIntrinsic(MI, Intrinsic::spv_bitcast))
129 continue;
130 assert(MI.getOperand(2).isReg());
131 MIB.setInsertPt(*MI.getParent(), MI);
132 MIB.buildBitcast(MI.getOperand(0).getReg(), MI.getOperand(2).getReg());
133 ToErase.push_back(&MI);
134 }
135 }
136 for (MachineInstr *MI : ToErase)
137 MI->eraseFromParent();
138}
139
140// Translating GV, IRTranslator sometimes generates following IR:
141// %1 = G_GLOBAL_VALUE
142// %2 = COPY %1
143// %3 = G_ADDRSPACE_CAST %2
144// New registers have no SPIRVType and no register class info.
145//
146// Set SPIRVType for GV, propagate it from GV to other instructions,
147// also set register classes.
150 MachineIRBuilder &MIB) {
151 SPIRVType *SpirvTy = nullptr;
152 assert(MI && "Machine instr is expected");
153 if (MI->getOperand(0).isReg()) {
154 Register Reg = MI->getOperand(0).getReg();
155 SpirvTy = GR->getSPIRVTypeForVReg(Reg);
156 if (!SpirvTy) {
157 switch (MI->getOpcode()) {
158 case TargetOpcode::G_CONSTANT: {
159 MIB.setInsertPt(*MI->getParent(), MI);
160 Type *Ty = MI->getOperand(1).getCImm()->getType();
161 SpirvTy = GR->getOrCreateSPIRVType(Ty, MIB);
162 break;
163 }
164 case TargetOpcode::G_GLOBAL_VALUE: {
165 MIB.setInsertPt(*MI->getParent(), MI);
166 Type *Ty = MI->getOperand(1).getGlobal()->getType();
167 SpirvTy = GR->getOrCreateSPIRVType(Ty, MIB);
168 break;
169 }
170 case TargetOpcode::G_TRUNC:
171 case TargetOpcode::G_ADDRSPACE_CAST:
172 case TargetOpcode::G_PTR_ADD:
173 case TargetOpcode::COPY: {
174 MachineOperand &Op = MI->getOperand(1);
175 MachineInstr *Def = Op.isReg() ? MRI.getVRegDef(Op.getReg()) : nullptr;
176 if (Def)
177 SpirvTy = propagateSPIRVType(Def, GR, MRI, MIB);
178 break;
179 }
180 default:
181 break;
182 }
183 if (SpirvTy)
184 GR->assignSPIRVTypeToVReg(SpirvTy, Reg, MIB.getMF());
185 if (!MRI.getRegClassOrNull(Reg))
186 MRI.setRegClass(Reg, &SPIRV::IDRegClass);
187 }
188 }
189 return SpirvTy;
190}
191
192// Insert ASSIGN_TYPE instuction between Reg and its definition, set NewReg as
193// a dst of the definition, assign SPIRVType to both registers. If SpirvTy is
194// provided, use it as SPIRVType in ASSIGN_TYPE, otherwise create it from Ty.
195// It's used also in SPIRVBuiltins.cpp.
196// TODO: maybe move to SPIRVUtils.
197namespace llvm {
201 MachineInstr *Def = MRI.getVRegDef(Reg);
202 assert((Ty || SpirvTy) && "Either LLVM or SPIRV type is expected.");
203 MIB.setInsertPt(*Def->getParent(),
204 (Def->getNextNode() ? Def->getNextNode()->getIterator()
205 : Def->getParent()->end()));
206 Register NewReg = MRI.createGenericVirtualRegister(MRI.getType(Reg));
207 if (auto *RC = MRI.getRegClassOrNull(Reg)) {
208 MRI.setRegClass(NewReg, RC);
209 } else {
210 MRI.setRegClass(NewReg, &SPIRV::IDRegClass);
211 MRI.setRegClass(Reg, &SPIRV::IDRegClass);
212 }
213 SpirvTy = SpirvTy ? SpirvTy : GR->getOrCreateSPIRVType(Ty, MIB);
214 GR->assignSPIRVTypeToVReg(SpirvTy, Reg, MIB.getMF());
215 // This is to make it convenient for Legalizer to get the SPIRVType
216 // when processing the actual MI (i.e. not pseudo one).
217 GR->assignSPIRVTypeToVReg(SpirvTy, NewReg, MIB.getMF());
218 // Copy MIFlags from Def to ASSIGN_TYPE instruction. It's required to keep
219 // the flags after instruction selection.
220 const uint16_t Flags = Def->getFlags();
221 MIB.buildInstr(SPIRV::ASSIGN_TYPE)
222 .addDef(Reg)
223 .addUse(NewReg)
224 .addUse(GR->getSPIRVTypeID(SpirvTy))
226 Def->getOperand(0).setReg(NewReg);
227 return NewReg;
228}
229} // namespace llvm
230
232 MachineIRBuilder MIB) {
235
236 for (MachineBasicBlock *MBB : post_order(&MF)) {
237 if (MBB->empty())
238 continue;
239
240 bool ReachedBegin = false;
241 for (auto MII = std::prev(MBB->end()), Begin = MBB->begin();
242 !ReachedBegin;) {
243 MachineInstr &MI = *MII;
244
245 if (isSpvIntrinsic(MI, Intrinsic::spv_assign_type)) {
246 Register Reg = MI.getOperand(1).getReg();
247 Type *Ty = getMDOperandAsType(MI.getOperand(2).getMetadata(), 0);
248 MachineInstr *Def = MRI.getVRegDef(Reg);
249 assert(Def && "Expecting an instruction that defines the register");
250 // G_GLOBAL_VALUE already has type info.
251 if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE)
252 insertAssignInstr(Reg, Ty, nullptr, GR, MIB, MF.getRegInfo());
253 ToErase.push_back(&MI);
254 } else if (MI.getOpcode() == TargetOpcode::G_CONSTANT ||
255 MI.getOpcode() == TargetOpcode::G_FCONSTANT ||
256 MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR) {
257 // %rc = G_CONSTANT ty Val
258 // ===>
259 // %cty = OpType* ty
260 // %rctmp = G_CONSTANT ty Val
261 // %rc = ASSIGN_TYPE %rctmp, %cty
262 Register Reg = MI.getOperand(0).getReg();
263 if (MRI.hasOneUse(Reg)) {
264 MachineInstr &UseMI = *MRI.use_instr_begin(Reg);
265 if (isSpvIntrinsic(UseMI, Intrinsic::spv_assign_type) ||
266 isSpvIntrinsic(UseMI, Intrinsic::spv_assign_name))
267 continue;
268 }
269 Type *Ty = nullptr;
270 if (MI.getOpcode() == TargetOpcode::G_CONSTANT)
271 Ty = MI.getOperand(1).getCImm()->getType();
272 else if (MI.getOpcode() == TargetOpcode::G_FCONSTANT)
273 Ty = MI.getOperand(1).getFPImm()->getType();
274 else {
275 assert(MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
276 Type *ElemTy = nullptr;
277 MachineInstr *ElemMI = MRI.getVRegDef(MI.getOperand(1).getReg());
278 assert(ElemMI);
279
280 if (ElemMI->getOpcode() == TargetOpcode::G_CONSTANT)
281 ElemTy = ElemMI->getOperand(1).getCImm()->getType();
282 else if (ElemMI->getOpcode() == TargetOpcode::G_FCONSTANT)
283 ElemTy = ElemMI->getOperand(1).getFPImm()->getType();
284 else
285 llvm_unreachable("Unexpected opcode");
286 unsigned NumElts =
287 MI.getNumExplicitOperands() - MI.getNumExplicitDefs();
288 Ty = VectorType::get(ElemTy, NumElts, false);
289 }
290 insertAssignInstr(Reg, Ty, nullptr, GR, MIB, MRI);
291 } else if (MI.getOpcode() == TargetOpcode::G_TRUNC ||
292 MI.getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
293 MI.getOpcode() == TargetOpcode::COPY ||
294 MI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST) {
295 propagateSPIRVType(&MI, GR, MRI, MIB);
296 }
297
298 if (MII == Begin)
299 ReachedBegin = true;
300 else
301 --MII;
302 }
303 }
304 for (MachineInstr *MI : ToErase)
305 MI->eraseFromParent();
306}
307
308static std::pair<Register, unsigned>
310 const SPIRVGlobalRegistry &GR) {
311 LLT NewT = LLT::scalar(32);
312 SPIRVType *SpvType = GR.getSPIRVTypeForVReg(ValReg);
313 assert(SpvType && "VReg is expected to have SPIRV type");
314 bool IsFloat = SpvType->getOpcode() == SPIRV::OpTypeFloat;
315 bool IsVectorFloat =
316 SpvType->getOpcode() == SPIRV::OpTypeVector &&
317 GR.getSPIRVTypeForVReg(SpvType->getOperand(1).getReg())->getOpcode() ==
318 SPIRV::OpTypeFloat;
319 IsFloat |= IsVectorFloat;
320 auto GetIdOp = IsFloat ? SPIRV::GET_fID : SPIRV::GET_ID;
321 auto DstClass = IsFloat ? &SPIRV::fIDRegClass : &SPIRV::IDRegClass;
322 if (MRI.getType(ValReg).isPointer()) {
323 NewT = LLT::pointer(0, 32);
324 GetIdOp = SPIRV::GET_pID;
325 DstClass = &SPIRV::pIDRegClass;
326 } else if (MRI.getType(ValReg).isVector()) {
327 NewT = LLT::fixed_vector(2, NewT);
328 GetIdOp = IsFloat ? SPIRV::GET_vfID : SPIRV::GET_vID;
329 DstClass = IsFloat ? &SPIRV::vfIDRegClass : &SPIRV::vIDRegClass;
330 }
331 Register IdReg = MRI.createGenericVirtualRegister(NewT);
332 MRI.setRegClass(IdReg, DstClass);
333 return {IdReg, GetIdOp};
334}
335
338 unsigned Opc = MI.getOpcode();
339 assert(MI.getNumDefs() > 0 && MRI.hasOneUse(MI.getOperand(0).getReg()));
340 MachineInstr &AssignTypeInst =
341 *(MRI.use_instr_begin(MI.getOperand(0).getReg()));
342 auto NewReg = createNewIdReg(MI.getOperand(0).getReg(), Opc, MRI, *GR).first;
343 AssignTypeInst.getOperand(1).setReg(NewReg);
344 MI.getOperand(0).setReg(NewReg);
345 MIB.setInsertPt(*MI.getParent(),
346 (MI.getNextNode() ? MI.getNextNode()->getIterator()
347 : MI.getParent()->end()));
348 for (auto &Op : MI.operands()) {
349 if (!Op.isReg() || Op.isDef())
350 continue;
351 auto IdOpInfo = createNewIdReg(Op.getReg(), Opc, MRI, *GR);
352 MIB.buildInstr(IdOpInfo.second).addDef(IdOpInfo.first).addUse(Op.getReg());
353 Op.setReg(IdOpInfo.first);
354 }
355}
356
357// Defined in SPIRVLegalizerInfo.cpp.
358extern bool isTypeFoldingSupported(unsigned Opcode);
359
362 MachineIRBuilder MIB) {
364 for (MachineBasicBlock &MBB : MF) {
365 for (MachineInstr &MI : MBB) {
366 if (isTypeFoldingSupported(MI.getOpcode()))
367 processInstr(MI, MIB, MRI, GR);
368 }
369 }
370 for (MachineBasicBlock &MBB : MF) {
371 for (MachineInstr &MI : MBB) {
372 // We need to rewrite dst types for ASSIGN_TYPE instrs to be able
373 // to perform tblgen'erated selection and we can't do that on Legalizer
374 // as it operates on gMIR only.
375 if (MI.getOpcode() != SPIRV::ASSIGN_TYPE)
376 continue;
377 Register SrcReg = MI.getOperand(1).getReg();
378 unsigned Opcode = MRI.getVRegDef(SrcReg)->getOpcode();
379 if (!isTypeFoldingSupported(Opcode))
380 continue;
381 Register DstReg = MI.getOperand(0).getReg();
382 if (MRI.getType(DstReg).isVector())
383 MRI.setRegClass(DstReg, &SPIRV::IDRegClass);
384 // Don't need to reset type of register holding constant and used in
385 // G_ADDRSPACE_CAST, since it braaks legalizer.
386 if (Opcode == TargetOpcode::G_CONSTANT && MRI.hasOneUse(DstReg)) {
387 MachineInstr &UseMI = *MRI.use_instr_begin(DstReg);
388 if (UseMI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST)
389 continue;
390 }
391 MRI.setType(DstReg, LLT::scalar(32));
392 }
393 }
394}
395
397 MachineIRBuilder MIB) {
398 // Before IRTranslator pass, calls to spv_switch intrinsic are inserted before
399 // each switch instruction. IRTranslator lowers switches to G_ICMP + G_BRCOND
400 // + G_BR triples. A switch with two cases may be transformed to this MIR
401 // sequence:
402 //
403 // intrinsic(@llvm.spv.switch), %CmpReg, %Const0, %Const1
404 // %Dst0 = G_ICMP intpred(eq), %CmpReg, %Const0
405 // G_BRCOND %Dst0, %bb.2
406 // G_BR %bb.5
407 // bb.5.entry:
408 // %Dst1 = G_ICMP intpred(eq), %CmpReg, %Const1
409 // G_BRCOND %Dst1, %bb.3
410 // G_BR %bb.4
411 // bb.2.sw.bb:
412 // ...
413 // bb.3.sw.bb1:
414 // ...
415 // bb.4.sw.epilog:
416 // ...
417 //
418 // Sometimes (in case of range-compare switches), additional G_SUBs
419 // instructions are inserted before G_ICMPs. Those need to be additionally
420 // processed and require type assignment.
421 //
422 // This function modifies spv_switch call's operands to include destination
423 // MBBs (default and for each constant value).
424 // Note that this function does not remove G_ICMP + G_BRCOND + G_BR sequences,
425 // but they are marked by ModuleAnalysis as skipped and as a result AsmPrinter
426 // does not output them.
427
429
430 // Collect all MIs relevant to switches across all MBBs in MF.
431 std::vector<MachineInstr *> RelevantInsts;
432
433 // Temporary set of compare registers. G_SUBs and G_ICMPs relating to
434 // spv_switch use these registers.
435 DenseSet<Register> CompareRegs;
436 for (MachineBasicBlock &MBB : MF) {
437 for (MachineInstr &MI : MBB) {
438 // Calls to spv_switch intrinsics representing IR switches.
439 if (isSpvIntrinsic(MI, Intrinsic::spv_switch)) {
440 assert(MI.getOperand(1).isReg());
441 CompareRegs.insert(MI.getOperand(1).getReg());
442 RelevantInsts.push_back(&MI);
443 }
444
445 // G_SUBs coming from range-compare switch lowering. G_SUBs are found
446 // after spv_switch but before G_ICMP.
447 if (MI.getOpcode() == TargetOpcode::G_SUB && MI.getOperand(1).isReg() &&
448 CompareRegs.contains(MI.getOperand(1).getReg())) {
449 assert(MI.getOperand(0).isReg() && MI.getOperand(1).isReg());
450 Register Dst = MI.getOperand(0).getReg();
451 CompareRegs.insert(Dst);
452 SPIRVType *Ty = GR->getSPIRVTypeForVReg(MI.getOperand(1).getReg());
453 insertAssignInstr(Dst, nullptr, Ty, GR, MIB, MRI);
454 }
455
456 // G_ICMPs relating to switches.
457 if (MI.getOpcode() == TargetOpcode::G_ICMP && MI.getOperand(2).isReg() &&
458 CompareRegs.contains(MI.getOperand(2).getReg())) {
459 Register Dst = MI.getOperand(0).getReg();
460 // Set type info for destination register of switch's ICMP instruction.
461 if (GR->getSPIRVTypeForVReg(Dst) == nullptr) {
462 MIB.setInsertPt(*MI.getParent(), MI);
463 Type *LLVMTy = IntegerType::get(MF.getFunction().getContext(), 1);
464 SPIRVType *SpirvTy = GR->getOrCreateSPIRVType(LLVMTy, MIB);
465 MRI.setRegClass(Dst, &SPIRV::IDRegClass);
466 GR->assignSPIRVTypeToVReg(SpirvTy, Dst, MIB.getMF());
467 }
468 RelevantInsts.push_back(&MI);
469 }
470 }
471 }
472
473 // Update each spv_switch with destination MBBs.
474 for (auto i = RelevantInsts.begin(); i != RelevantInsts.end(); i++) {
475 if (!isSpvIntrinsic(**i, Intrinsic::spv_switch))
476 continue;
477
478 // Currently considered spv_switch.
479 MachineInstr *Switch = *i;
480 // Set the first successor as default MBB to support empty switches.
481 MachineBasicBlock *DefaultMBB = *Switch->getParent()->succ_begin();
482 // Container for mapping values to MMBs.
484
485 // Walk all G_ICMPs to collect ValuesToMBBs. Start at currently considered
486 // spv_switch (i) and break at any spv_switch with the same compare
487 // register (indicating we are back at the same scope).
488 Register CompareReg = Switch->getOperand(1).getReg();
489 for (auto j = i + 1; j != RelevantInsts.end(); j++) {
490 if (isSpvIntrinsic(**j, Intrinsic::spv_switch) &&
491 (*j)->getOperand(1).getReg() == CompareReg)
492 break;
493
494 if (!((*j)->getOpcode() == TargetOpcode::G_ICMP &&
495 (*j)->getOperand(2).getReg() == CompareReg))
496 continue;
497
498 MachineInstr *ICMP = *j;
499 Register Dst = ICMP->getOperand(0).getReg();
500 MachineOperand &PredOp = ICMP->getOperand(1);
501 const auto CC = static_cast<CmpInst::Predicate>(PredOp.getPredicate());
503 MRI.hasOneUse(Dst) && MRI.hasOneDef(CompareReg));
504 uint64_t Value = getIConstVal(ICMP->getOperand(3).getReg(), &MRI);
505 MachineInstr *CBr = MRI.use_begin(Dst)->getParent();
506 assert(CBr->getOpcode() == SPIRV::G_BRCOND && CBr->getOperand(1).isMBB());
508
509 // Map switch case Value to target MBB.
510 ValuesToMBBs[Value] = MBB;
511
512 // The next MI is always G_BR to either the next case or the default.
513 MachineInstr *NextMI = CBr->getNextNode();
514 assert(NextMI->getOpcode() == SPIRV::G_BR &&
515 NextMI->getOperand(0).isMBB());
516 MachineBasicBlock *NextMBB = NextMI->getOperand(0).getMBB();
517 // Default MBB does not begin with G_ICMP using spv_switch compare
518 // register.
519 if (NextMBB->front().getOpcode() != SPIRV::G_ICMP ||
520 (NextMBB->front().getOperand(2).isReg() &&
521 NextMBB->front().getOperand(2).getReg() != CompareReg))
522 DefaultMBB = NextMBB;
523 }
524
525 // Modify considered spv_switch operands using collected Values and
526 // MBBs.
529 for (unsigned k = 2; k < Switch->getNumExplicitOperands(); k++) {
530 Register CReg = Switch->getOperand(k).getReg();
531 uint64_t Val = getIConstVal(CReg, &MRI);
532 MachineInstr *ConstInstr = getDefInstrMaybeConstant(CReg, &MRI);
533 if (!ValuesToMBBs[Val])
534 continue;
535
536 Values.push_back(ConstInstr->getOperand(1).getCImm());
537 MBBs.push_back(ValuesToMBBs[Val]);
538 }
539
540 for (unsigned k = Switch->getNumExplicitOperands() - 1; k > 1; k--)
541 Switch->removeOperand(k);
542
543 Switch->addOperand(MachineOperand::CreateMBB(DefaultMBB));
544 for (unsigned k = 0; k < Values.size(); k++) {
545 Switch->addOperand(MachineOperand::CreateCImm(Values[k]));
546 Switch->addOperand(MachineOperand::CreateMBB(MBBs[k]));
547 }
548 }
549}
550
551bool SPIRVPreLegalizer::runOnMachineFunction(MachineFunction &MF) {
552 // Initialize the type registry.
554 SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
555 GR->setCurrentFunc(MF);
556 MachineIRBuilder MIB(MF);
557 addConstantsToTrack(MF, GR);
559 insertBitcasts(MF, GR, MIB);
560 generateAssignInstrs(MF, GR, MIB);
561 processSwitches(MF, GR, MIB);
562 processInstrsWithTypeFolding(MF, GR, MIB);
563
564 return true;
565}
566
567INITIALIZE_PASS(SPIRVPreLegalizer, DEBUG_TYPE, "SPIRV pre legalizer", false,
568 false)
569
570char SPIRVPreLegalizer::ID = 0;
571
573 return new SPIRVPreLegalizer();
574}
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...
IRTranslator LLVM IR MI
#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())
bool isTypeFoldingSupported(unsigned Opcode)
static void insertBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void processInstr(MachineInstr &MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR)
static void processInstrsWithTypeFolding(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static SPIRVType * propagateSPIRVType(MachineInstr *MI, SPIRVGlobalRegistry *GR, MachineRegisterInfo &MRI, MachineIRBuilder &MIB)
static void processSwitches(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static std::pair< Register, unsigned > createNewIdReg(Register ValReg, unsigned Opcode, MachineRegisterInfo &MRI, const SPIRVGlobalRegistry &GR)
static void generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void addConstantsToTrack(MachineFunction &MF, SPIRVGlobalRegistry *GR)
#define DEBUG_TYPE
static void foldConstantsIntoIntrinsics(MachineFunction &MF)
@ Flags
Definition: TextStubV5.cpp:93
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition: InstrTypes.h:718
@ ICMP_EQ
equal
Definition: InstrTypes.h:739
@ ICMP_ULE
unsigned less or equal
Definition: InstrTypes.h:744
IntegerType * getType() const
getType - Specialize the getType() method to always return an IntegerType, which reduces the amount o...
Definition: Constants.h:176
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:145
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:155
iterator end()
Definition: DenseMap.h:84
Implements a dense probed hash-table based set.
Definition: DenseSet.h:271
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:308
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:319
static IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition: Type.cpp:331
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
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.
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.
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:68
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:516
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:526
MachineOperand class - Representation of each machine instruction operand.
const ConstantInt * getCImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
static MachineOperand CreateCImm(const ConstantInt *CI)
void setReg(Register Reg)
Change the register this operand corresponds to.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
const ConstantFP * getFPImm() const
unsigned getPredicate() const
static MachineOperand CreateMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0)
bool isMBB() const
isMBB - Tests if this is a MO_MachineBasicBlock operand.
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
void add(const Constant *C, MachineFunction *MF, Register R)
SPIRVType * getSPIRVTypeForVReg(Register VReg) const
Register find(const Constant *C, MachineFunction *MF)
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
SPIRVType * getOrCreateSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite, bool EmitIR=true)
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, MachineFunction &MF)
size_t size() const
Definition: SmallVector.h:91
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
LLVM Value Representation.
Definition: Value.h:74
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:206
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
Definition: DenseSet.h:185
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
Definition: ilist_node.h:289
#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
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)
uint64_t getIConstVal(Register ConstReg, const MachineRegisterInfo *MRI)
Definition: SPIRVUtils.cpp:223
bool isSpvIntrinsic(MachineInstr &MI, Intrinsic::ID IntrinsicID)
Definition: SPIRVUtils.cpp:229
MachineInstr * getDefInstrMaybeConstant(Register &ConstReg, const MachineRegisterInfo *MRI)
Definition: SPIRVUtils.cpp:209
Type * getMDOperandAsType(const MDNode *N, unsigned I)
Definition: SPIRVUtils.cpp:234
void initializeSPIRVPreLegalizerPass(PassRegistry &)