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 "SPIRVGlobalRegistry.h"
17 #include "SPIRVSubtarget.h"
18 #include "SPIRVUtils.h"
19 #include "llvm/ADT/PostOrderIterator.h"
20 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
21 #include "llvm/IR/Attributes.h"
22 #include "llvm/IR/Constants.h"
23 #include "llvm/IR/DebugInfoMetadata.h"
24 #include "llvm/IR/IntrinsicsSPIRV.h"
25 #include "llvm/Target/TargetIntrinsicInfo.h"
26
27 #define DEBUG_TYPE "spirv-prelegalizer"
28
29 using namespace llvm;
30
31 namespace {
32 class SPIRVPreLegalizer : public MachineFunctionPass {
33 public:
34 static char ID;
SPIRVPreLegalizer()35 SPIRVPreLegalizer() : MachineFunctionPass(ID) {
36 initializeSPIRVPreLegalizerPass(*PassRegistry::getPassRegistry());
37 }
38 bool runOnMachineFunction(MachineFunction &MF) override;
39 };
40 } // namespace
41
addConstantsToTrack(MachineFunction & MF,SPIRVGlobalRegistry * GR)42 static void addConstantsToTrack(MachineFunction &MF, SPIRVGlobalRegistry *GR) {
43 MachineRegisterInfo &MRI = MF.getRegInfo();
44 DenseMap<MachineInstr *, Register> RegsAlreadyAddedToDT;
45 SmallVector<MachineInstr *, 10> ToErase, ToEraseComposites;
46 for (MachineBasicBlock &MBB : MF) {
47 for (MachineInstr &MI : MBB) {
48 if (!isSpvIntrinsic(MI, Intrinsic::spv_track_constant))
49 continue;
50 ToErase.push_back(&MI);
51 auto *Const =
52 cast<Constant>(cast<ConstantAsMetadata>(
53 MI.getOperand(3).getMetadata()->getOperand(0))
54 ->getValue());
55 if (auto *GV = dyn_cast<GlobalValue>(Const)) {
56 Register Reg = GR->find(GV, &MF);
57 if (!Reg.isValid())
58 GR->add(GV, &MF, MI.getOperand(2).getReg());
59 else
60 RegsAlreadyAddedToDT[&MI] = Reg;
61 } else {
62 Register Reg = GR->find(Const, &MF);
63 if (!Reg.isValid()) {
64 if (auto *ConstVec = dyn_cast<ConstantDataVector>(Const)) {
65 auto *BuildVec = MRI.getVRegDef(MI.getOperand(2).getReg());
66 assert(BuildVec &&
67 BuildVec->getOpcode() == TargetOpcode::G_BUILD_VECTOR);
68 for (unsigned i = 0; i < ConstVec->getNumElements(); ++i)
69 GR->add(ConstVec->getElementAsConstant(i), &MF,
70 BuildVec->getOperand(1 + i).getReg());
71 }
72 GR->add(Const, &MF, MI.getOperand(2).getReg());
73 } else {
74 RegsAlreadyAddedToDT[&MI] = Reg;
75 // This MI is unused and will be removed. If the MI uses
76 // const_composite, it will be unused and should be removed too.
77 assert(MI.getOperand(2).isReg() && "Reg operand is expected");
78 MachineInstr *SrcMI = MRI.getVRegDef(MI.getOperand(2).getReg());
79 if (SrcMI && isSpvIntrinsic(*SrcMI, Intrinsic::spv_const_composite))
80 ToEraseComposites.push_back(SrcMI);
81 }
82 }
83 }
84 }
85 for (MachineInstr *MI : ToErase) {
86 Register Reg = MI->getOperand(2).getReg();
87 if (RegsAlreadyAddedToDT.find(MI) != RegsAlreadyAddedToDT.end())
88 Reg = RegsAlreadyAddedToDT[MI];
89 MRI.replaceRegWith(MI->getOperand(0).getReg(), Reg);
90 MI->eraseFromParent();
91 }
92 for (MachineInstr *MI : ToEraseComposites)
93 MI->eraseFromParent();
94 }
95
foldConstantsIntoIntrinsics(MachineFunction & MF)96 static void foldConstantsIntoIntrinsics(MachineFunction &MF) {
97 SmallVector<MachineInstr *, 10> ToErase;
98 MachineRegisterInfo &MRI = MF.getRegInfo();
99 const unsigned AssignNameOperandShift = 2;
100 for (MachineBasicBlock &MBB : MF) {
101 for (MachineInstr &MI : MBB) {
102 if (!isSpvIntrinsic(MI, Intrinsic::spv_assign_name))
103 continue;
104 unsigned NumOp = MI.getNumExplicitDefs() + AssignNameOperandShift;
105 while (MI.getOperand(NumOp).isReg()) {
106 MachineOperand &MOp = MI.getOperand(NumOp);
107 MachineInstr *ConstMI = MRI.getVRegDef(MOp.getReg());
108 assert(ConstMI->getOpcode() == TargetOpcode::G_CONSTANT);
109 MI.removeOperand(NumOp);
110 MI.addOperand(MachineOperand::CreateImm(
111 ConstMI->getOperand(1).getCImm()->getZExtValue()));
112 if (MRI.use_empty(ConstMI->getOperand(0).getReg()))
113 ToErase.push_back(ConstMI);
114 }
115 }
116 }
117 for (MachineInstr *MI : ToErase)
118 MI->eraseFromParent();
119 }
120
insertBitcasts(MachineFunction & MF,SPIRVGlobalRegistry * GR,MachineIRBuilder MIB)121 static void insertBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR,
122 MachineIRBuilder MIB) {
123 SmallVector<MachineInstr *, 10> ToErase;
124 for (MachineBasicBlock &MBB : MF) {
125 for (MachineInstr &MI : MBB) {
126 if (!isSpvIntrinsic(MI, Intrinsic::spv_bitcast))
127 continue;
128 assert(MI.getOperand(2).isReg());
129 MIB.setInsertPt(*MI.getParent(), MI);
130 MIB.buildBitcast(MI.getOperand(0).getReg(), MI.getOperand(2).getReg());
131 ToErase.push_back(&MI);
132 }
133 }
134 for (MachineInstr *MI : ToErase)
135 MI->eraseFromParent();
136 }
137
138 // Translating GV, IRTranslator sometimes generates following IR:
139 // %1 = G_GLOBAL_VALUE
140 // %2 = COPY %1
141 // %3 = G_ADDRSPACE_CAST %2
142 // New registers have no SPIRVType and no register class info.
143 //
144 // Set SPIRVType for GV, propagate it from GV to other instructions,
145 // also set register classes.
propagateSPIRVType(MachineInstr * MI,SPIRVGlobalRegistry * GR,MachineRegisterInfo & MRI,MachineIRBuilder & MIB)146 static SPIRVType *propagateSPIRVType(MachineInstr *MI, SPIRVGlobalRegistry *GR,
147 MachineRegisterInfo &MRI,
148 MachineIRBuilder &MIB) {
149 SPIRVType *SpirvTy = nullptr;
150 assert(MI && "Machine instr is expected");
151 if (MI->getOperand(0).isReg()) {
152 Register Reg = MI->getOperand(0).getReg();
153 SpirvTy = GR->getSPIRVTypeForVReg(Reg);
154 if (!SpirvTy) {
155 switch (MI->getOpcode()) {
156 case TargetOpcode::G_CONSTANT: {
157 MIB.setInsertPt(*MI->getParent(), MI);
158 Type *Ty = MI->getOperand(1).getCImm()->getType();
159 SpirvTy = GR->getOrCreateSPIRVType(Ty, MIB);
160 break;
161 }
162 case TargetOpcode::G_GLOBAL_VALUE: {
163 MIB.setInsertPt(*MI->getParent(), MI);
164 Type *Ty = MI->getOperand(1).getGlobal()->getType();
165 SpirvTy = GR->getOrCreateSPIRVType(Ty, MIB);
166 break;
167 }
168 case TargetOpcode::G_TRUNC:
169 case TargetOpcode::G_ADDRSPACE_CAST:
170 case TargetOpcode::G_PTR_ADD:
171 case TargetOpcode::COPY: {
172 MachineOperand &Op = MI->getOperand(1);
173 MachineInstr *Def = Op.isReg() ? MRI.getVRegDef(Op.getReg()) : nullptr;
174 if (Def)
175 SpirvTy = propagateSPIRVType(Def, GR, MRI, MIB);
176 break;
177 }
178 default:
179 break;
180 }
181 if (SpirvTy)
182 GR->assignSPIRVTypeToVReg(SpirvTy, Reg, MIB.getMF());
183 if (!MRI.getRegClassOrNull(Reg))
184 MRI.setRegClass(Reg, &SPIRV::IDRegClass);
185 }
186 }
187 return SpirvTy;
188 }
189
190 // Insert ASSIGN_TYPE instuction between Reg and its definition, set NewReg as
191 // a dst of the definition, assign SPIRVType to both registers. If SpirvTy is
192 // provided, use it as SPIRVType in ASSIGN_TYPE, otherwise create it from Ty.
193 // TODO: maybe move to SPIRVUtils.
insertAssignInstr(Register Reg,Type * Ty,SPIRVType * SpirvTy,SPIRVGlobalRegistry * GR,MachineIRBuilder & MIB,MachineRegisterInfo & MRI)194 static Register insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpirvTy,
195 SPIRVGlobalRegistry *GR,
196 MachineIRBuilder &MIB,
197 MachineRegisterInfo &MRI) {
198 MachineInstr *Def = MRI.getVRegDef(Reg);
199 assert((Ty || SpirvTy) && "Either LLVM or SPIRV type is expected.");
200 MIB.setInsertPt(*Def->getParent(),
201 (Def->getNextNode() ? Def->getNextNode()->getIterator()
202 : Def->getParent()->end()));
203 Register NewReg = MRI.createGenericVirtualRegister(MRI.getType(Reg));
204 if (auto *RC = MRI.getRegClassOrNull(Reg))
205 MRI.setRegClass(NewReg, RC);
206 SpirvTy = SpirvTy ? SpirvTy : GR->getOrCreateSPIRVType(Ty, MIB);
207 GR->assignSPIRVTypeToVReg(SpirvTy, Reg, MIB.getMF());
208 // This is to make it convenient for Legalizer to get the SPIRVType
209 // when processing the actual MI (i.e. not pseudo one).
210 GR->assignSPIRVTypeToVReg(SpirvTy, NewReg, MIB.getMF());
211 MIB.buildInstr(SPIRV::ASSIGN_TYPE)
212 .addDef(Reg)
213 .addUse(NewReg)
214 .addUse(GR->getSPIRVTypeID(SpirvTy));
215 Def->getOperand(0).setReg(NewReg);
216 MRI.setRegClass(Reg, &SPIRV::ANYIDRegClass);
217 return NewReg;
218 }
219
generateAssignInstrs(MachineFunction & MF,SPIRVGlobalRegistry * GR,MachineIRBuilder MIB)220 static void generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
221 MachineIRBuilder MIB) {
222 MachineRegisterInfo &MRI = MF.getRegInfo();
223 SmallVector<MachineInstr *, 10> ToErase;
224
225 for (MachineBasicBlock *MBB : post_order(&MF)) {
226 if (MBB->empty())
227 continue;
228
229 bool ReachedBegin = false;
230 for (auto MII = std::prev(MBB->end()), Begin = MBB->begin();
231 !ReachedBegin;) {
232 MachineInstr &MI = *MII;
233
234 if (isSpvIntrinsic(MI, Intrinsic::spv_assign_type)) {
235 Register Reg = MI.getOperand(1).getReg();
236 Type *Ty = getMDOperandAsType(MI.getOperand(2).getMetadata(), 0);
237 MachineInstr *Def = MRI.getVRegDef(Reg);
238 assert(Def && "Expecting an instruction that defines the register");
239 // G_GLOBAL_VALUE already has type info.
240 if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE)
241 insertAssignInstr(Reg, Ty, nullptr, GR, MIB, MF.getRegInfo());
242 ToErase.push_back(&MI);
243 } else if (MI.getOpcode() == TargetOpcode::G_CONSTANT ||
244 MI.getOpcode() == TargetOpcode::G_FCONSTANT ||
245 MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR) {
246 // %rc = G_CONSTANT ty Val
247 // ===>
248 // %cty = OpType* ty
249 // %rctmp = G_CONSTANT ty Val
250 // %rc = ASSIGN_TYPE %rctmp, %cty
251 Register Reg = MI.getOperand(0).getReg();
252 if (MRI.hasOneUse(Reg)) {
253 MachineInstr &UseMI = *MRI.use_instr_begin(Reg);
254 if (isSpvIntrinsic(UseMI, Intrinsic::spv_assign_type) ||
255 isSpvIntrinsic(UseMI, Intrinsic::spv_assign_name))
256 continue;
257 }
258 Type *Ty = nullptr;
259 if (MI.getOpcode() == TargetOpcode::G_CONSTANT)
260 Ty = MI.getOperand(1).getCImm()->getType();
261 else if (MI.getOpcode() == TargetOpcode::G_FCONSTANT)
262 Ty = MI.getOperand(1).getFPImm()->getType();
263 else {
264 assert(MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
265 Type *ElemTy = nullptr;
266 MachineInstr *ElemMI = MRI.getVRegDef(MI.getOperand(1).getReg());
267 assert(ElemMI);
268
269 if (ElemMI->getOpcode() == TargetOpcode::G_CONSTANT)
270 ElemTy = ElemMI->getOperand(1).getCImm()->getType();
271 else if (ElemMI->getOpcode() == TargetOpcode::G_FCONSTANT)
272 ElemTy = ElemMI->getOperand(1).getFPImm()->getType();
273 else
274 llvm_unreachable("Unexpected opcode");
275 unsigned NumElts =
276 MI.getNumExplicitOperands() - MI.getNumExplicitDefs();
277 Ty = VectorType::get(ElemTy, NumElts, false);
278 }
279 insertAssignInstr(Reg, Ty, nullptr, GR, MIB, MRI);
280 } else if (MI.getOpcode() == TargetOpcode::G_TRUNC ||
281 MI.getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
282 MI.getOpcode() == TargetOpcode::COPY ||
283 MI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST) {
284 propagateSPIRVType(&MI, GR, MRI, MIB);
285 }
286
287 if (MII == Begin)
288 ReachedBegin = true;
289 else
290 --MII;
291 }
292 }
293 for (MachineInstr *MI : ToErase)
294 MI->eraseFromParent();
295 }
296
297 static std::pair<Register, unsigned>
createNewIdReg(Register ValReg,unsigned Opcode,MachineRegisterInfo & MRI,const SPIRVGlobalRegistry & GR)298 createNewIdReg(Register ValReg, unsigned Opcode, MachineRegisterInfo &MRI,
299 const SPIRVGlobalRegistry &GR) {
300 LLT NewT = LLT::scalar(32);
301 SPIRVType *SpvType = GR.getSPIRVTypeForVReg(ValReg);
302 assert(SpvType && "VReg is expected to have SPIRV type");
303 bool IsFloat = SpvType->getOpcode() == SPIRV::OpTypeFloat;
304 bool IsVectorFloat =
305 SpvType->getOpcode() == SPIRV::OpTypeVector &&
306 GR.getSPIRVTypeForVReg(SpvType->getOperand(1).getReg())->getOpcode() ==
307 SPIRV::OpTypeFloat;
308 IsFloat |= IsVectorFloat;
309 auto GetIdOp = IsFloat ? SPIRV::GET_fID : SPIRV::GET_ID;
310 auto DstClass = IsFloat ? &SPIRV::fIDRegClass : &SPIRV::IDRegClass;
311 if (MRI.getType(ValReg).isPointer()) {
312 NewT = LLT::pointer(0, 32);
313 GetIdOp = SPIRV::GET_pID;
314 DstClass = &SPIRV::pIDRegClass;
315 } else if (MRI.getType(ValReg).isVector()) {
316 NewT = LLT::fixed_vector(2, NewT);
317 GetIdOp = IsFloat ? SPIRV::GET_vfID : SPIRV::GET_vID;
318 DstClass = IsFloat ? &SPIRV::vfIDRegClass : &SPIRV::vIDRegClass;
319 }
320 Register IdReg = MRI.createGenericVirtualRegister(NewT);
321 MRI.setRegClass(IdReg, DstClass);
322 return {IdReg, GetIdOp};
323 }
324
processInstr(MachineInstr & MI,MachineIRBuilder & MIB,MachineRegisterInfo & MRI,SPIRVGlobalRegistry * GR)325 static void processInstr(MachineInstr &MI, MachineIRBuilder &MIB,
326 MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR) {
327 unsigned Opc = MI.getOpcode();
328 assert(MI.getNumDefs() > 0 && MRI.hasOneUse(MI.getOperand(0).getReg()));
329 MachineInstr &AssignTypeInst =
330 *(MRI.use_instr_begin(MI.getOperand(0).getReg()));
331 auto NewReg = createNewIdReg(MI.getOperand(0).getReg(), Opc, MRI, *GR).first;
332 AssignTypeInst.getOperand(1).setReg(NewReg);
333 MI.getOperand(0).setReg(NewReg);
334 MIB.setInsertPt(*MI.getParent(),
335 (MI.getNextNode() ? MI.getNextNode()->getIterator()
336 : MI.getParent()->end()));
337 for (auto &Op : MI.operands()) {
338 if (!Op.isReg() || Op.isDef())
339 continue;
340 auto IdOpInfo = createNewIdReg(Op.getReg(), Opc, MRI, *GR);
341 MIB.buildInstr(IdOpInfo.second).addDef(IdOpInfo.first).addUse(Op.getReg());
342 Op.setReg(IdOpInfo.first);
343 }
344 }
345
346 // Defined in SPIRVLegalizerInfo.cpp.
347 extern bool isTypeFoldingSupported(unsigned Opcode);
348
processInstrsWithTypeFolding(MachineFunction & MF,SPIRVGlobalRegistry * GR,MachineIRBuilder MIB)349 static void processInstrsWithTypeFolding(MachineFunction &MF,
350 SPIRVGlobalRegistry *GR,
351 MachineIRBuilder MIB) {
352 MachineRegisterInfo &MRI = MF.getRegInfo();
353 for (MachineBasicBlock &MBB : MF) {
354 for (MachineInstr &MI : MBB) {
355 if (isTypeFoldingSupported(MI.getOpcode()))
356 processInstr(MI, MIB, MRI, GR);
357 }
358 }
359 for (MachineBasicBlock &MBB : MF) {
360 for (MachineInstr &MI : MBB) {
361 // We need to rewrite dst types for ASSIGN_TYPE instrs to be able
362 // to perform tblgen'erated selection and we can't do that on Legalizer
363 // as it operates on gMIR only.
364 if (MI.getOpcode() != SPIRV::ASSIGN_TYPE)
365 continue;
366 Register SrcReg = MI.getOperand(1).getReg();
367 if (!isTypeFoldingSupported(MRI.getVRegDef(SrcReg)->getOpcode()))
368 continue;
369 Register DstReg = MI.getOperand(0).getReg();
370 if (MRI.getType(DstReg).isVector())
371 MRI.setRegClass(DstReg, &SPIRV::IDRegClass);
372 MRI.setType(DstReg, LLT::scalar(32));
373 }
374 }
375 }
376
processSwitches(MachineFunction & MF,SPIRVGlobalRegistry * GR,MachineIRBuilder MIB)377 static void processSwitches(MachineFunction &MF, SPIRVGlobalRegistry *GR,
378 MachineIRBuilder MIB) {
379 DenseMap<Register, SmallDenseMap<uint64_t, MachineBasicBlock *>>
380 SwitchRegToMBB;
381 DenseMap<Register, MachineBasicBlock *> DefaultMBBs;
382 DenseSet<Register> SwitchRegs;
383 MachineRegisterInfo &MRI = MF.getRegInfo();
384 // Before IRTranslator pass, spv_switch calls are inserted before each
385 // switch instruction. IRTranslator lowers switches to ICMP+CBr+Br triples.
386 // A switch with two cases may be translated to this MIR sequesnce:
387 // intrinsic(@llvm.spv.switch), %CmpReg, %Const0, %Const1
388 // %Dst0 = G_ICMP intpred(eq), %CmpReg, %Const0
389 // G_BRCOND %Dst0, %bb.2
390 // G_BR %bb.5
391 // bb.5.entry:
392 // %Dst1 = G_ICMP intpred(eq), %CmpReg, %Const1
393 // G_BRCOND %Dst1, %bb.3
394 // G_BR %bb.4
395 // bb.2.sw.bb:
396 // ...
397 // bb.3.sw.bb1:
398 // ...
399 // bb.4.sw.epilog:
400 // ...
401 // Walk MIs and collect information about destination MBBs to update
402 // spv_switch call. We assume that all spv_switch precede corresponding ICMPs.
403 for (MachineBasicBlock &MBB : MF) {
404 for (MachineInstr &MI : MBB) {
405 if (isSpvIntrinsic(MI, Intrinsic::spv_switch)) {
406 assert(MI.getOperand(1).isReg());
407 Register Reg = MI.getOperand(1).getReg();
408 SwitchRegs.insert(Reg);
409 // Set the first successor as default MBB to support empty switches.
410 DefaultMBBs[Reg] = *MBB.succ_begin();
411 }
412 // Process only ICMPs that relate to spv_switches.
413 if (MI.getOpcode() == TargetOpcode::G_ICMP && MI.getOperand(2).isReg() &&
414 SwitchRegs.contains(MI.getOperand(2).getReg())) {
415 assert(MI.getOperand(0).isReg() && MI.getOperand(1).isPredicate() &&
416 MI.getOperand(3).isReg());
417 Register Dst = MI.getOperand(0).getReg();
418 // Set type info for destination register of switch's ICMP instruction.
419 if (GR->getSPIRVTypeForVReg(Dst) == nullptr) {
420 MIB.setInsertPt(*MI.getParent(), MI);
421 Type *LLVMTy = IntegerType::get(MF.getFunction().getContext(), 1);
422 SPIRVType *SpirvTy = GR->getOrCreateSPIRVType(LLVMTy, MIB);
423 MRI.setRegClass(Dst, &SPIRV::IDRegClass);
424 GR->assignSPIRVTypeToVReg(SpirvTy, Dst, MIB.getMF());
425 }
426 Register CmpReg = MI.getOperand(2).getReg();
427 MachineOperand &PredOp = MI.getOperand(1);
428 const auto CC = static_cast<CmpInst::Predicate>(PredOp.getPredicate());
429 assert(CC == CmpInst::ICMP_EQ && MRI.hasOneUse(Dst) &&
430 MRI.hasOneDef(CmpReg));
431 uint64_t Val = getIConstVal(MI.getOperand(3).getReg(), &MRI);
432 MachineInstr *CBr = MRI.use_begin(Dst)->getParent();
433 assert(CBr->getOpcode() == SPIRV::G_BRCOND &&
434 CBr->getOperand(1).isMBB());
435 SwitchRegToMBB[CmpReg][Val] = CBr->getOperand(1).getMBB();
436 // The next MI is always BR to either the next case or the default.
437 MachineInstr *NextMI = CBr->getNextNode();
438 assert(NextMI->getOpcode() == SPIRV::G_BR &&
439 NextMI->getOperand(0).isMBB());
440 MachineBasicBlock *NextMBB = NextMI->getOperand(0).getMBB();
441 assert(NextMBB != nullptr);
442 // The default MBB is not started by ICMP with switch's cmp register.
443 if (NextMBB->front().getOpcode() != SPIRV::G_ICMP ||
444 (NextMBB->front().getOperand(2).isReg() &&
445 NextMBB->front().getOperand(2).getReg() != CmpReg))
446 DefaultMBBs[CmpReg] = NextMBB;
447 }
448 }
449 }
450 // Modify spv_switch's operands by collected values. For the example above,
451 // the result will be like this:
452 // intrinsic(@llvm.spv.switch), %CmpReg, %bb.4, i32 0, %bb.2, i32 1, %bb.3
453 // Note that ICMP+CBr+Br sequences are not removed, but ModuleAnalysis marks
454 // them as skipped and AsmPrinter does not output them.
455 for (MachineBasicBlock &MBB : MF) {
456 for (MachineInstr &MI : MBB) {
457 if (!isSpvIntrinsic(MI, Intrinsic::spv_switch))
458 continue;
459 assert(MI.getOperand(1).isReg());
460 Register Reg = MI.getOperand(1).getReg();
461 unsigned NumOp = MI.getNumExplicitOperands();
462 SmallVector<const ConstantInt *, 3> Vals;
463 SmallVector<MachineBasicBlock *, 3> MBBs;
464 for (unsigned i = 2; i < NumOp; i++) {
465 Register CReg = MI.getOperand(i).getReg();
466 uint64_t Val = getIConstVal(CReg, &MRI);
467 MachineInstr *ConstInstr = getDefInstrMaybeConstant(CReg, &MRI);
468 Vals.push_back(ConstInstr->getOperand(1).getCImm());
469 MBBs.push_back(SwitchRegToMBB[Reg][Val]);
470 }
471 for (unsigned i = MI.getNumExplicitOperands() - 1; i > 1; i--)
472 MI.removeOperand(i);
473 MI.addOperand(MachineOperand::CreateMBB(DefaultMBBs[Reg]));
474 for (unsigned i = 0; i < Vals.size(); i++) {
475 MI.addOperand(MachineOperand::CreateCImm(Vals[i]));
476 MI.addOperand(MachineOperand::CreateMBB(MBBs[i]));
477 }
478 }
479 }
480 }
481
runOnMachineFunction(MachineFunction & MF)482 bool SPIRVPreLegalizer::runOnMachineFunction(MachineFunction &MF) {
483 // Initialize the type registry.
484 const SPIRVSubtarget &ST = MF.getSubtarget<SPIRVSubtarget>();
485 SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
486 GR->setCurrentFunc(MF);
487 MachineIRBuilder MIB(MF);
488 addConstantsToTrack(MF, GR);
489 foldConstantsIntoIntrinsics(MF);
490 insertBitcasts(MF, GR, MIB);
491 generateAssignInstrs(MF, GR, MIB);
492 processInstrsWithTypeFolding(MF, GR, MIB);
493 processSwitches(MF, GR, MIB);
494
495 return true;
496 }
497
498 INITIALIZE_PASS(SPIRVPreLegalizer, DEBUG_TYPE, "SPIRV pre legalizer", false,
499 false)
500
501 char SPIRVPreLegalizer::ID = 0;
502
createSPIRVPreLegalizerPass()503 FunctionPass *llvm::createSPIRVPreLegalizerPass() {
504 return new SPIRVPreLegalizer();
505 }
506