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.
421 //
422 // This function modifies spv_switch call's operands to include destination
423 // MBBs (default and for each constant value).
424 //
425 // At the end, the function removes redundant [G_SUB] + G_ICMP + G_BRCOND +
426 // G_BR sequences.
427
429
430 // Collect spv_switches and G_ICMPs across all MBBs in MF.
431 std::vector<MachineInstr *> RelevantInsts;
432
433 // Collect redundant MIs from [G_SUB] + G_ICMP + G_BRCOND + G_BR sequences.
434 // After updating spv_switches, the instructions can be removed.
435 std::vector<MachineInstr *> PostUpdateArtifacts;
436
437 // Temporary set of compare registers. G_SUBs and G_ICMPs relating to
438 // spv_switch use these registers.
439 DenseSet<Register> CompareRegs;
440 for (MachineBasicBlock &MBB : MF) {
441 for (MachineInstr &MI : MBB) {
442 // Calls to spv_switch intrinsics representing IR switches.
443 if (isSpvIntrinsic(MI, Intrinsic::spv_switch)) {
444 assert(MI.getOperand(1).isReg());
445 CompareRegs.insert(MI.getOperand(1).getReg());
446 RelevantInsts.push_back(&MI);
447 }
448
449 // G_SUBs coming from range-compare switch lowering. G_SUBs are found
450 // after spv_switch but before G_ICMP.
451 if (MI.getOpcode() == TargetOpcode::G_SUB && MI.getOperand(1).isReg() &&
452 CompareRegs.contains(MI.getOperand(1).getReg())) {
453 assert(MI.getOperand(0).isReg() && MI.getOperand(1).isReg());
454 Register Dst = MI.getOperand(0).getReg();
455 CompareRegs.insert(Dst);
456 PostUpdateArtifacts.push_back(&MI);
457 }
458
459 // G_ICMPs relating to switches.
460 if (MI.getOpcode() == TargetOpcode::G_ICMP && MI.getOperand(2).isReg() &&
461 CompareRegs.contains(MI.getOperand(2).getReg())) {
462 Register Dst = MI.getOperand(0).getReg();
463 RelevantInsts.push_back(&MI);
464 PostUpdateArtifacts.push_back(&MI);
465 MachineInstr *CBr = MRI.use_begin(Dst)->getParent();
466 assert(CBr->getOpcode() == SPIRV::G_BRCOND);
467 PostUpdateArtifacts.push_back(CBr);
468 MachineInstr *Br = CBr->getNextNode();
469 assert(Br->getOpcode() == SPIRV::G_BR);
470 PostUpdateArtifacts.push_back(Br);
471 }
472 }
473 }
474
475 // Update each spv_switch with destination MBBs.
476 for (auto i = RelevantInsts.begin(); i != RelevantInsts.end(); i++) {
477 if (!isSpvIntrinsic(**i, Intrinsic::spv_switch))
478 continue;
479
480 // Currently considered spv_switch.
481 MachineInstr *Switch = *i;
482 // Set the first successor as default MBB to support empty switches.
483 MachineBasicBlock *DefaultMBB = *Switch->getParent()->succ_begin();
484 // Container for mapping values to MMBs.
486
487 // Walk all G_ICMPs to collect ValuesToMBBs. Start at currently considered
488 // spv_switch (i) and break at any spv_switch with the same compare
489 // register (indicating we are back at the same scope).
490 Register CompareReg = Switch->getOperand(1).getReg();
491 for (auto j = i + 1; j != RelevantInsts.end(); j++) {
492 if (isSpvIntrinsic(**j, Intrinsic::spv_switch) &&
493 (*j)->getOperand(1).getReg() == CompareReg)
494 break;
495
496 if (!((*j)->getOpcode() == TargetOpcode::G_ICMP &&
497 (*j)->getOperand(2).getReg() == CompareReg))
498 continue;
499
500 MachineInstr *ICMP = *j;
501 Register Dst = ICMP->getOperand(0).getReg();
502 MachineOperand &PredOp = ICMP->getOperand(1);
503 const auto CC = static_cast<CmpInst::Predicate>(PredOp.getPredicate());
505 MRI.hasOneUse(Dst) && MRI.hasOneDef(CompareReg));
506 uint64_t Value = getIConstVal(ICMP->getOperand(3).getReg(), &MRI);
507 MachineInstr *CBr = MRI.use_begin(Dst)->getParent();
508 assert(CBr->getOpcode() == SPIRV::G_BRCOND && CBr->getOperand(1).isMBB());
510
511 // Map switch case Value to target MBB.
512 ValuesToMBBs[Value] = MBB;
513
514 // Add target MBB as successor to the switch's MBB.
515 Switch->getParent()->addSuccessor(MBB);
516
517 // The next MI is always G_BR to either the next case or the default.
518 MachineInstr *NextMI = CBr->getNextNode();
519 assert(NextMI->getOpcode() == SPIRV::G_BR &&
520 NextMI->getOperand(0).isMBB());
521 MachineBasicBlock *NextMBB = NextMI->getOperand(0).getMBB();
522 // Default MBB does not begin with G_ICMP using spv_switch compare
523 // register.
524 if (NextMBB->front().getOpcode() != SPIRV::G_ICMP ||
525 (NextMBB->front().getOperand(2).isReg() &&
526 NextMBB->front().getOperand(2).getReg() != CompareReg)) {
527 // Set default MBB and add it as successor to the switch's MBB.
528 DefaultMBB = NextMBB;
529 Switch->getParent()->addSuccessor(DefaultMBB);
530 }
531 }
532
533 // Modify considered spv_switch operands using collected Values and
534 // MBBs.
537 for (unsigned k = 2; k < Switch->getNumExplicitOperands(); k++) {
538 Register CReg = Switch->getOperand(k).getReg();
539 uint64_t Val = getIConstVal(CReg, &MRI);
540 MachineInstr *ConstInstr = getDefInstrMaybeConstant(CReg, &MRI);
541 if (!ValuesToMBBs[Val])
542 continue;
543
544 Values.push_back(ConstInstr->getOperand(1).getCImm());
545 MBBs.push_back(ValuesToMBBs[Val]);
546 }
547
548 for (unsigned k = Switch->getNumExplicitOperands() - 1; k > 1; k--)
549 Switch->removeOperand(k);
550
551 Switch->addOperand(MachineOperand::CreateMBB(DefaultMBB));
552 for (unsigned k = 0; k < Values.size(); k++) {
553 Switch->addOperand(MachineOperand::CreateCImm(Values[k]));
554 Switch->addOperand(MachineOperand::CreateMBB(MBBs[k]));
555 }
556 }
557
558 for (MachineInstr *MI : PostUpdateArtifacts) {
559 MachineBasicBlock *ParentMBB = MI->getParent();
560 MI->eraseFromParent();
561 // If G_ICMP + G_BRCOND + G_BR were the only MIs in MBB, erase this MBB. It
562 // can be safely assumed, there are no breaks or phis directing into this
563 // MBB. However, we need to remove this MBB from the CFG graph. MBBs must be
564 // erased top-down.
565 if (ParentMBB->empty()) {
566 while (!ParentMBB->pred_empty())
567 (*ParentMBB->pred_begin())->removeSuccessor(ParentMBB);
568
569 while (!ParentMBB->succ_empty())
570 ParentMBB->removeSuccessor(ParentMBB->succ_begin());
571
572 ParentMBB->eraseFromParent();
573 }
574 }
575}
576
577bool SPIRVPreLegalizer::runOnMachineFunction(MachineFunction &MF) {
578 // Initialize the type registry.
580 SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
581 GR->setCurrentFunc(MF);
582 MachineIRBuilder MIB(MF);
583 addConstantsToTrack(MF, GR);
585 insertBitcasts(MF, GR, MIB);
586 generateAssignInstrs(MF, GR, MIB);
587 processSwitches(MF, GR, MIB);
588 processInstrsWithTypeFolding(MF, GR, MIB);
589
590 return true;
591}
592
593INITIALIZE_PASS(SPIRVPreLegalizer, DEBUG_TYPE, "SPIRV pre legalizer", false,
594 false)
595
596char SPIRVPreLegalizer::ID = 0;
597
599 return new SPIRVPreLegalizer();
600}
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:711
@ ICMP_EQ
equal
Definition: InstrTypes.h:732
@ ICMP_ULE
unsigned less or equal
Definition: InstrTypes.h:737
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:311
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
Definition: LowLevelType.h:42
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
Definition: LowLevelType.h:49
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
Definition: LowLevelType.h:76
void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
void eraseFromParent()
This method unlinks 'this' from the containing function and deletes it.
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.
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 &)