1ec259036SIlia Diachkov //===- SPIRVISelLowering.cpp - SPIR-V DAG Lowering Impl ---------*- C++ -*-===// 2ec259036SIlia Diachkov // 3ec259036SIlia Diachkov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4ec259036SIlia Diachkov // See https://llvm.org/LICENSE.txt for license information. 5ec259036SIlia Diachkov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6ec259036SIlia Diachkov // 7ec259036SIlia Diachkov //===----------------------------------------------------------------------===// 8ec259036SIlia Diachkov // 9ec259036SIlia Diachkov // This file implements the SPIRVTargetLowering class. 10ec259036SIlia Diachkov // 11ec259036SIlia Diachkov //===----------------------------------------------------------------------===// 12ec259036SIlia Diachkov 13ec259036SIlia Diachkov #include "SPIRVISelLowering.h" 14ec259036SIlia Diachkov #include "SPIRV.h" 15fb1be9b3SVyacheslav Levytskyy #include "SPIRVInstrInfo.h" 16fb1be9b3SVyacheslav Levytskyy #include "SPIRVRegisterBankInfo.h" 17fb1be9b3SVyacheslav Levytskyy #include "SPIRVRegisterInfo.h" 18fb1be9b3SVyacheslav Levytskyy #include "SPIRVSubtarget.h" 19fb1be9b3SVyacheslav Levytskyy #include "SPIRVTargetMachine.h" 20fb1be9b3SVyacheslav Levytskyy #include "llvm/CodeGen/MachineInstrBuilder.h" 21fb1be9b3SVyacheslav Levytskyy #include "llvm/CodeGen/MachineRegisterInfo.h" 223544d200SIlia Diachkov #include "llvm/IR/IntrinsicsSPIRV.h" 23ec259036SIlia Diachkov 24ec259036SIlia Diachkov #define DEBUG_TYPE "spirv-lower" 25ec259036SIlia Diachkov 26ec259036SIlia Diachkov using namespace llvm; 27ec259036SIlia Diachkov 28ec259036SIlia Diachkov unsigned SPIRVTargetLowering::getNumRegistersForCallingConv( 29ec259036SIlia Diachkov LLVMContext &Context, CallingConv::ID CC, EVT VT) const { 30ec259036SIlia Diachkov // This code avoids CallLowering fail inside getVectorTypeBreakdown 31ec259036SIlia Diachkov // on v3i1 arguments. Maybe we need to return 1 for all types. 32ec259036SIlia Diachkov // TODO: remove it once this case is supported by the default implementation. 33ec259036SIlia Diachkov if (VT.isVector() && VT.getVectorNumElements() == 3 && 34ec259036SIlia Diachkov (VT.getVectorElementType() == MVT::i1 || 35ec259036SIlia Diachkov VT.getVectorElementType() == MVT::i8)) 36ec259036SIlia Diachkov return 1; 37dc4330a9SMichal Paszkowski if (!VT.isVector() && VT.isInteger() && VT.getSizeInBits() <= 64) 38dc4330a9SMichal Paszkowski return 1; 39ec259036SIlia Diachkov return getNumRegisters(Context, VT); 40ec259036SIlia Diachkov } 41ec259036SIlia Diachkov 42ec259036SIlia Diachkov MVT SPIRVTargetLowering::getRegisterTypeForCallingConv(LLVMContext &Context, 43ec259036SIlia Diachkov CallingConv::ID CC, 44ec259036SIlia Diachkov EVT VT) const { 45ec259036SIlia Diachkov // This code avoids CallLowering fail inside getVectorTypeBreakdown 46ec259036SIlia Diachkov // on v3i1 arguments. Maybe we need to return i32 for all types. 47ec259036SIlia Diachkov // TODO: remove it once this case is supported by the default implementation. 48ec259036SIlia Diachkov if (VT.isVector() && VT.getVectorNumElements() == 3) { 49ec259036SIlia Diachkov if (VT.getVectorElementType() == MVT::i1) 50ec259036SIlia Diachkov return MVT::v4i1; 51ec259036SIlia Diachkov else if (VT.getVectorElementType() == MVT::i8) 52ec259036SIlia Diachkov return MVT::v4i8; 53ec259036SIlia Diachkov } 54ec259036SIlia Diachkov return getRegisterType(Context, VT); 55ec259036SIlia Diachkov } 563544d200SIlia Diachkov 573544d200SIlia Diachkov bool SPIRVTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info, 583544d200SIlia Diachkov const CallInst &I, 593544d200SIlia Diachkov MachineFunction &MF, 603544d200SIlia Diachkov unsigned Intrinsic) const { 613544d200SIlia Diachkov unsigned AlignIdx = 3; 623544d200SIlia Diachkov switch (Intrinsic) { 633544d200SIlia Diachkov case Intrinsic::spv_load: 643544d200SIlia Diachkov AlignIdx = 2; 656006d43eSCraig Topper [[fallthrough]]; 663544d200SIlia Diachkov case Intrinsic::spv_store: { 673544d200SIlia Diachkov if (I.getNumOperands() >= AlignIdx + 1) { 683544d200SIlia Diachkov auto *AlignOp = cast<ConstantInt>(I.getOperand(AlignIdx)); 693544d200SIlia Diachkov Info.align = Align(AlignOp->getZExtValue()); 703544d200SIlia Diachkov } 713544d200SIlia Diachkov Info.flags = static_cast<MachineMemOperand::Flags>( 723544d200SIlia Diachkov cast<ConstantInt>(I.getOperand(AlignIdx - 1))->getZExtValue()); 733544d200SIlia Diachkov Info.memVT = MVT::i64; 743544d200SIlia Diachkov // TODO: take into account opaque pointers (don't use getElementType). 753544d200SIlia Diachkov // MVT::getVT(PtrTy->getElementType()); 763544d200SIlia Diachkov return true; 773544d200SIlia Diachkov break; 783544d200SIlia Diachkov } 793544d200SIlia Diachkov default: 803544d200SIlia Diachkov break; 813544d200SIlia Diachkov } 823544d200SIlia Diachkov return false; 833544d200SIlia Diachkov } 84fb1be9b3SVyacheslav Levytskyy 85214e6b40SVyacheslav Levytskyy std::pair<unsigned, const TargetRegisterClass *> 86214e6b40SVyacheslav Levytskyy SPIRVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, 87214e6b40SVyacheslav Levytskyy StringRef Constraint, 88214e6b40SVyacheslav Levytskyy MVT VT) const { 89214e6b40SVyacheslav Levytskyy const TargetRegisterClass *RC = nullptr; 90214e6b40SVyacheslav Levytskyy if (Constraint.starts_with("{")) 91214e6b40SVyacheslav Levytskyy return std::make_pair(0u, RC); 92214e6b40SVyacheslav Levytskyy 93214e6b40SVyacheslav Levytskyy if (VT.isFloatingPoint()) 9467d3ef74SVyacheslav Levytskyy RC = VT.isVector() ? &SPIRV::vfIDRegClass : &SPIRV::fIDRegClass; 95214e6b40SVyacheslav Levytskyy else if (VT.isInteger()) 9667d3ef74SVyacheslav Levytskyy RC = VT.isVector() ? &SPIRV::vIDRegClass : &SPIRV::iIDRegClass; 97214e6b40SVyacheslav Levytskyy else 98f9c98068SVyacheslav Levytskyy RC = &SPIRV::iIDRegClass; 99214e6b40SVyacheslav Levytskyy 100214e6b40SVyacheslav Levytskyy return std::make_pair(0u, RC); 101214e6b40SVyacheslav Levytskyy } 102214e6b40SVyacheslav Levytskyy 103ce73e17eSVyacheslav Levytskyy inline Register getTypeReg(MachineRegisterInfo *MRI, Register OpReg) { 104ce73e17eSVyacheslav Levytskyy SPIRVType *TypeInst = MRI->getVRegDef(OpReg); 105ce73e17eSVyacheslav Levytskyy return TypeInst && TypeInst->getOpcode() == SPIRV::OpFunctionParameter 106ce73e17eSVyacheslav Levytskyy ? TypeInst->getOperand(1).getReg() 107ce73e17eSVyacheslav Levytskyy : OpReg; 108ce73e17eSVyacheslav Levytskyy } 109ce73e17eSVyacheslav Levytskyy 110ce73e17eSVyacheslav Levytskyy static void doInsertBitcast(const SPIRVSubtarget &STI, MachineRegisterInfo *MRI, 111ce73e17eSVyacheslav Levytskyy SPIRVGlobalRegistry &GR, MachineInstr &I, 112ce73e17eSVyacheslav Levytskyy Register OpReg, unsigned OpIdx, 113ce73e17eSVyacheslav Levytskyy SPIRVType *NewPtrType) { 114ce73e17eSVyacheslav Levytskyy MachineIRBuilder MIB(I); 115*b5132b7dSVyacheslav Levytskyy Register NewReg = createVirtualRegister(NewPtrType, &GR, MRI, MIB.getMF()); 116ce73e17eSVyacheslav Levytskyy bool Res = MIB.buildInstr(SPIRV::OpBitcast) 117ce73e17eSVyacheslav Levytskyy .addDef(NewReg) 118ce73e17eSVyacheslav Levytskyy .addUse(GR.getSPIRVTypeID(NewPtrType)) 119ce73e17eSVyacheslav Levytskyy .addUse(OpReg) 120ce73e17eSVyacheslav Levytskyy .constrainAllUses(*STI.getInstrInfo(), *STI.getRegisterInfo(), 121ce73e17eSVyacheslav Levytskyy *STI.getRegBankInfo()); 122ce73e17eSVyacheslav Levytskyy if (!Res) 123ce73e17eSVyacheslav Levytskyy report_fatal_error("insert validation bitcast: cannot constrain all uses"); 124ce73e17eSVyacheslav Levytskyy I.getOperand(OpIdx).setReg(NewReg); 125ce73e17eSVyacheslav Levytskyy } 126ce73e17eSVyacheslav Levytskyy 127ce73e17eSVyacheslav Levytskyy static SPIRVType *createNewPtrType(SPIRVGlobalRegistry &GR, MachineInstr &I, 128ce73e17eSVyacheslav Levytskyy SPIRVType *OpType, bool ReuseType, 129ce73e17eSVyacheslav Levytskyy bool EmitIR, SPIRVType *ResType, 130ce73e17eSVyacheslav Levytskyy const Type *ResTy) { 131ce73e17eSVyacheslav Levytskyy SPIRV::StorageClass::StorageClass SC = 132ce73e17eSVyacheslav Levytskyy static_cast<SPIRV::StorageClass::StorageClass>( 133ce73e17eSVyacheslav Levytskyy OpType->getOperand(1).getImm()); 134ce73e17eSVyacheslav Levytskyy MachineIRBuilder MIB(I); 135ce73e17eSVyacheslav Levytskyy SPIRVType *NewBaseType = 136ce73e17eSVyacheslav Levytskyy ReuseType ? ResType 137ce73e17eSVyacheslav Levytskyy : GR.getOrCreateSPIRVType( 138ce73e17eSVyacheslav Levytskyy ResTy, MIB, SPIRV::AccessQualifier::ReadWrite, EmitIR); 139ce73e17eSVyacheslav Levytskyy return GR.getOrCreateSPIRVPointerType(NewBaseType, MIB, SC); 140ce73e17eSVyacheslav Levytskyy } 141ce73e17eSVyacheslav Levytskyy 142fb1be9b3SVyacheslav Levytskyy // Insert a bitcast before the instruction to keep SPIR-V code valid 143fb1be9b3SVyacheslav Levytskyy // when there is a type mismatch between results and operand types. 144fb1be9b3SVyacheslav Levytskyy static void validatePtrTypes(const SPIRVSubtarget &STI, 145fb1be9b3SVyacheslav Levytskyy MachineRegisterInfo *MRI, SPIRVGlobalRegistry &GR, 146b7ac8fddSVyacheslav Levytskyy MachineInstr &I, unsigned OpIdx, 147b7ac8fddSVyacheslav Levytskyy SPIRVType *ResType, const Type *ResTy = nullptr) { 148f7680835SVyacheslav Levytskyy // Get operand type 149f7680835SVyacheslav Levytskyy MachineFunction *MF = I.getParent()->getParent(); 150fb1be9b3SVyacheslav Levytskyy Register OpReg = I.getOperand(OpIdx).getReg(); 151ce73e17eSVyacheslav Levytskyy Register OpTypeReg = getTypeReg(MRI, OpReg); 152f7680835SVyacheslav Levytskyy SPIRVType *OpType = GR.getSPIRVTypeForVReg(OpTypeReg, MF); 153fb1be9b3SVyacheslav Levytskyy if (!ResType || !OpType || OpType->getOpcode() != SPIRV::OpTypePointer) 154fb1be9b3SVyacheslav Levytskyy return; 155f7680835SVyacheslav Levytskyy // Get operand's pointee type 156f7680835SVyacheslav Levytskyy Register ElemTypeReg = OpType->getOperand(2).getReg(); 157f7680835SVyacheslav Levytskyy SPIRVType *ElemType = GR.getSPIRVTypeForVReg(ElemTypeReg, MF); 158b7ac8fddSVyacheslav Levytskyy if (!ElemType) 159b7ac8fddSVyacheslav Levytskyy return; 160f7680835SVyacheslav Levytskyy // Check if we need a bitcast to make a statement valid 161f7680835SVyacheslav Levytskyy bool IsSameMF = MF == ResType->getParent()->getParent(); 162b7ac8fddSVyacheslav Levytskyy bool IsEqualTypes = IsSameMF ? ElemType == ResType 163b7ac8fddSVyacheslav Levytskyy : GR.getTypeForSPIRVType(ElemType) == ResTy; 164b7ac8fddSVyacheslav Levytskyy if (IsEqualTypes) 165fb1be9b3SVyacheslav Levytskyy return; 166fb1be9b3SVyacheslav Levytskyy // There is a type mismatch between results and operand types 167fb1be9b3SVyacheslav Levytskyy // and we insert a bitcast before the instruction to keep SPIR-V code valid 168ce73e17eSVyacheslav Levytskyy SPIRVType *NewPtrType = 169ce73e17eSVyacheslav Levytskyy createNewPtrType(GR, I, OpType, IsSameMF, false, ResType, ResTy); 170fb1be9b3SVyacheslav Levytskyy if (!GR.isBitcastCompatible(NewPtrType, OpType)) 171fb1be9b3SVyacheslav Levytskyy report_fatal_error( 172fb1be9b3SVyacheslav Levytskyy "insert validation bitcast: incompatible result and operand types"); 173ce73e17eSVyacheslav Levytskyy doInsertBitcast(STI, MRI, GR, I, OpReg, OpIdx, NewPtrType); 174ce73e17eSVyacheslav Levytskyy } 175ce73e17eSVyacheslav Levytskyy 176ce73e17eSVyacheslav Levytskyy // Insert a bitcast before OpGroupWaitEvents if the last argument is a pointer 177ce73e17eSVyacheslav Levytskyy // that doesn't point to OpTypeEvent. 178ce73e17eSVyacheslav Levytskyy static void validateGroupWaitEventsPtr(const SPIRVSubtarget &STI, 179ce73e17eSVyacheslav Levytskyy MachineRegisterInfo *MRI, 180ce73e17eSVyacheslav Levytskyy SPIRVGlobalRegistry &GR, 181ce73e17eSVyacheslav Levytskyy MachineInstr &I) { 182ce73e17eSVyacheslav Levytskyy constexpr unsigned OpIdx = 2; 183ce73e17eSVyacheslav Levytskyy MachineFunction *MF = I.getParent()->getParent(); 184ce73e17eSVyacheslav Levytskyy Register OpReg = I.getOperand(OpIdx).getReg(); 185ce73e17eSVyacheslav Levytskyy Register OpTypeReg = getTypeReg(MRI, OpReg); 186ce73e17eSVyacheslav Levytskyy SPIRVType *OpType = GR.getSPIRVTypeForVReg(OpTypeReg, MF); 187ce73e17eSVyacheslav Levytskyy if (!OpType || OpType->getOpcode() != SPIRV::OpTypePointer) 188ce73e17eSVyacheslav Levytskyy return; 189ce73e17eSVyacheslav Levytskyy SPIRVType *ElemType = GR.getSPIRVTypeForVReg(OpType->getOperand(2).getReg()); 190ce73e17eSVyacheslav Levytskyy if (!ElemType || ElemType->getOpcode() == SPIRV::OpTypeEvent) 191ce73e17eSVyacheslav Levytskyy return; 192ce73e17eSVyacheslav Levytskyy // Insert a bitcast before the instruction to keep SPIR-V code valid. 1930f0cfcffSMatt Arsenault LLVMContext &Context = MF->getFunction().getContext(); 194ce73e17eSVyacheslav Levytskyy SPIRVType *NewPtrType = 195ce73e17eSVyacheslav Levytskyy createNewPtrType(GR, I, OpType, false, true, nullptr, 196ce73e17eSVyacheslav Levytskyy TargetExtType::get(Context, "spirv.Event")); 197ce73e17eSVyacheslav Levytskyy doInsertBitcast(STI, MRI, GR, I, OpReg, OpIdx, NewPtrType); 198fb1be9b3SVyacheslav Levytskyy } 199fb1be9b3SVyacheslav Levytskyy 200281f59fdSVyacheslav Levytskyy static void validateLifetimeStart(const SPIRVSubtarget &STI, 201281f59fdSVyacheslav Levytskyy MachineRegisterInfo *MRI, 202281f59fdSVyacheslav Levytskyy SPIRVGlobalRegistry &GR, MachineInstr &I) { 203281f59fdSVyacheslav Levytskyy Register PtrReg = I.getOperand(0).getReg(); 204281f59fdSVyacheslav Levytskyy MachineFunction *MF = I.getParent()->getParent(); 205281f59fdSVyacheslav Levytskyy Register PtrTypeReg = getTypeReg(MRI, PtrReg); 206281f59fdSVyacheslav Levytskyy SPIRVType *PtrType = GR.getSPIRVTypeForVReg(PtrTypeReg, MF); 207281f59fdSVyacheslav Levytskyy SPIRVType *PonteeElemType = PtrType ? GR.getPointeeType(PtrType) : nullptr; 208281f59fdSVyacheslav Levytskyy if (!PonteeElemType || PonteeElemType->getOpcode() == SPIRV::OpTypeVoid || 209281f59fdSVyacheslav Levytskyy (PonteeElemType->getOpcode() == SPIRV::OpTypeInt && 210281f59fdSVyacheslav Levytskyy PonteeElemType->getOperand(1).getImm() == 8)) 211281f59fdSVyacheslav Levytskyy return; 212281f59fdSVyacheslav Levytskyy // To keep the code valid a bitcast must be inserted 213281f59fdSVyacheslav Levytskyy SPIRV::StorageClass::StorageClass SC = 214281f59fdSVyacheslav Levytskyy static_cast<SPIRV::StorageClass::StorageClass>( 215281f59fdSVyacheslav Levytskyy PtrType->getOperand(1).getImm()); 216281f59fdSVyacheslav Levytskyy MachineIRBuilder MIB(I); 217281f59fdSVyacheslav Levytskyy LLVMContext &Context = MF->getFunction().getContext(); 218281f59fdSVyacheslav Levytskyy SPIRVType *ElemType = 219281f59fdSVyacheslav Levytskyy GR.getOrCreateSPIRVType(IntegerType::getInt8Ty(Context), MIB); 220281f59fdSVyacheslav Levytskyy SPIRVType *NewPtrType = GR.getOrCreateSPIRVPointerType(ElemType, MIB, SC); 221281f59fdSVyacheslav Levytskyy doInsertBitcast(STI, MRI, GR, I, PtrReg, 0, NewPtrType); 222281f59fdSVyacheslav Levytskyy } 223281f59fdSVyacheslav Levytskyy 2245a062191SVyacheslav Levytskyy static void validatePtrUnwrapStructField(const SPIRVSubtarget &STI, 225bf9e9e5eSVyacheslav Levytskyy MachineRegisterInfo *MRI, 2265a062191SVyacheslav Levytskyy SPIRVGlobalRegistry &GR, 2275a062191SVyacheslav Levytskyy MachineInstr &I, unsigned OpIdx) { 228bf9e9e5eSVyacheslav Levytskyy MachineFunction *MF = I.getParent()->getParent(); 229bf9e9e5eSVyacheslav Levytskyy Register OpReg = I.getOperand(OpIdx).getReg(); 230bf9e9e5eSVyacheslav Levytskyy Register OpTypeReg = getTypeReg(MRI, OpReg); 231bf9e9e5eSVyacheslav Levytskyy SPIRVType *OpType = GR.getSPIRVTypeForVReg(OpTypeReg, MF); 232bf9e9e5eSVyacheslav Levytskyy if (!OpType || OpType->getOpcode() != SPIRV::OpTypePointer) 233bf9e9e5eSVyacheslav Levytskyy return; 234bf9e9e5eSVyacheslav Levytskyy SPIRVType *ElemType = GR.getSPIRVTypeForVReg(OpType->getOperand(2).getReg()); 235bf9e9e5eSVyacheslav Levytskyy if (!ElemType || ElemType->getOpcode() != SPIRV::OpTypeStruct || 236bf9e9e5eSVyacheslav Levytskyy ElemType->getNumOperands() != 2) 237bf9e9e5eSVyacheslav Levytskyy return; 238bf9e9e5eSVyacheslav Levytskyy // It's a structure-wrapper around another type with a single member field. 239bf9e9e5eSVyacheslav Levytskyy SPIRVType *MemberType = 240bf9e9e5eSVyacheslav Levytskyy GR.getSPIRVTypeForVReg(ElemType->getOperand(1).getReg()); 241bf9e9e5eSVyacheslav Levytskyy if (!MemberType) 242bf9e9e5eSVyacheslav Levytskyy return; 243bf9e9e5eSVyacheslav Levytskyy unsigned MemberTypeOp = MemberType->getOpcode(); 244bf9e9e5eSVyacheslav Levytskyy if (MemberTypeOp != SPIRV::OpTypeVector && MemberTypeOp != SPIRV::OpTypeInt && 245bf9e9e5eSVyacheslav Levytskyy MemberTypeOp != SPIRV::OpTypeFloat && MemberTypeOp != SPIRV::OpTypeBool) 246bf9e9e5eSVyacheslav Levytskyy return; 247bf9e9e5eSVyacheslav Levytskyy // It's a structure-wrapper around a valid type. Insert a bitcast before the 248bf9e9e5eSVyacheslav Levytskyy // instruction to keep SPIR-V code valid. 249bf9e9e5eSVyacheslav Levytskyy SPIRV::StorageClass::StorageClass SC = 250bf9e9e5eSVyacheslav Levytskyy static_cast<SPIRV::StorageClass::StorageClass>( 251bf9e9e5eSVyacheslav Levytskyy OpType->getOperand(1).getImm()); 252bf9e9e5eSVyacheslav Levytskyy MachineIRBuilder MIB(I); 253bf9e9e5eSVyacheslav Levytskyy SPIRVType *NewPtrType = GR.getOrCreateSPIRVPointerType(MemberType, MIB, SC); 254bf9e9e5eSVyacheslav Levytskyy doInsertBitcast(STI, MRI, GR, I, OpReg, OpIdx, NewPtrType); 255bf9e9e5eSVyacheslav Levytskyy } 256bf9e9e5eSVyacheslav Levytskyy 257b7ac8fddSVyacheslav Levytskyy // Insert a bitcast before the function call instruction to keep SPIR-V code 258b7ac8fddSVyacheslav Levytskyy // valid when there is a type mismatch between actual and expected types of an 259b7ac8fddSVyacheslav Levytskyy // argument: 260b7ac8fddSVyacheslav Levytskyy // %formal = OpFunctionParameter %formal_type 261b7ac8fddSVyacheslav Levytskyy // ... 262b7ac8fddSVyacheslav Levytskyy // %res = OpFunctionCall %ty %fun %actual ... 263b7ac8fddSVyacheslav Levytskyy // implies that %actual is of %formal_type, and in case of opaque pointers. 264b7ac8fddSVyacheslav Levytskyy // We may need to insert a bitcast to ensure this. 265b7ac8fddSVyacheslav Levytskyy void validateFunCallMachineDef(const SPIRVSubtarget &STI, 266b7ac8fddSVyacheslav Levytskyy MachineRegisterInfo *DefMRI, 267b7ac8fddSVyacheslav Levytskyy MachineRegisterInfo *CallMRI, 268b7ac8fddSVyacheslav Levytskyy SPIRVGlobalRegistry &GR, MachineInstr &FunCall, 269b7ac8fddSVyacheslav Levytskyy MachineInstr *FunDef) { 270b7ac8fddSVyacheslav Levytskyy if (FunDef->getOpcode() != SPIRV::OpFunction) 271b7ac8fddSVyacheslav Levytskyy return; 272b7ac8fddSVyacheslav Levytskyy unsigned OpIdx = 3; 273b7ac8fddSVyacheslav Levytskyy for (FunDef = FunDef->getNextNode(); 274b7ac8fddSVyacheslav Levytskyy FunDef && FunDef->getOpcode() == SPIRV::OpFunctionParameter && 275b7ac8fddSVyacheslav Levytskyy OpIdx < FunCall.getNumOperands(); 276b7ac8fddSVyacheslav Levytskyy FunDef = FunDef->getNextNode(), OpIdx++) { 277b7ac8fddSVyacheslav Levytskyy SPIRVType *DefPtrType = DefMRI->getVRegDef(FunDef->getOperand(1).getReg()); 278b7ac8fddSVyacheslav Levytskyy SPIRVType *DefElemType = 279b7ac8fddSVyacheslav Levytskyy DefPtrType && DefPtrType->getOpcode() == SPIRV::OpTypePointer 280f7680835SVyacheslav Levytskyy ? GR.getSPIRVTypeForVReg(DefPtrType->getOperand(2).getReg(), 281f7680835SVyacheslav Levytskyy DefPtrType->getParent()->getParent()) 282b7ac8fddSVyacheslav Levytskyy : nullptr; 283b7ac8fddSVyacheslav Levytskyy if (DefElemType) { 284b7ac8fddSVyacheslav Levytskyy const Type *DefElemTy = GR.getTypeForSPIRVType(DefElemType); 28523b058cbSVyacheslav Levytskyy // validatePtrTypes() works in the context if the call site 28623b058cbSVyacheslav Levytskyy // When we process historical records about forward calls 28723b058cbSVyacheslav Levytskyy // we need to switch context to the (forward) call site and 28823b058cbSVyacheslav Levytskyy // then restore it back to the current machine function. 28923b058cbSVyacheslav Levytskyy MachineFunction *CurMF = 290b7ac8fddSVyacheslav Levytskyy GR.setCurrentFunc(*FunCall.getParent()->getParent()); 291b7ac8fddSVyacheslav Levytskyy validatePtrTypes(STI, CallMRI, GR, FunCall, OpIdx, DefElemType, 292b7ac8fddSVyacheslav Levytskyy DefElemTy); 29323b058cbSVyacheslav Levytskyy GR.setCurrentFunc(*CurMF); 294b7ac8fddSVyacheslav Levytskyy } 295b7ac8fddSVyacheslav Levytskyy } 296b7ac8fddSVyacheslav Levytskyy } 297b7ac8fddSVyacheslav Levytskyy 298b7ac8fddSVyacheslav Levytskyy // Ensure there is no mismatch between actual and expected arg types: calls 299b7ac8fddSVyacheslav Levytskyy // with a processed definition. Return Function pointer if it's a forward 300b7ac8fddSVyacheslav Levytskyy // call (ahead of definition), and nullptr otherwise. 301b7ac8fddSVyacheslav Levytskyy const Function *validateFunCall(const SPIRVSubtarget &STI, 302f7680835SVyacheslav Levytskyy MachineRegisterInfo *CallMRI, 303b7ac8fddSVyacheslav Levytskyy SPIRVGlobalRegistry &GR, 304b7ac8fddSVyacheslav Levytskyy MachineInstr &FunCall) { 305b7ac8fddSVyacheslav Levytskyy const GlobalValue *GV = FunCall.getOperand(2).getGlobal(); 306b7ac8fddSVyacheslav Levytskyy const Function *F = dyn_cast<Function>(GV); 307b7ac8fddSVyacheslav Levytskyy MachineInstr *FunDef = 308b7ac8fddSVyacheslav Levytskyy const_cast<MachineInstr *>(GR.getFunctionDefinition(F)); 309b7ac8fddSVyacheslav Levytskyy if (!FunDef) 310b7ac8fddSVyacheslav Levytskyy return F; 311f7680835SVyacheslav Levytskyy MachineRegisterInfo *DefMRI = &FunDef->getParent()->getParent()->getRegInfo(); 312f7680835SVyacheslav Levytskyy validateFunCallMachineDef(STI, DefMRI, CallMRI, GR, FunCall, FunDef); 313b7ac8fddSVyacheslav Levytskyy return nullptr; 314b7ac8fddSVyacheslav Levytskyy } 315b7ac8fddSVyacheslav Levytskyy 316b7ac8fddSVyacheslav Levytskyy // Ensure there is no mismatch between actual and expected arg types: calls 317b7ac8fddSVyacheslav Levytskyy // ahead of a processed definition. 318b7ac8fddSVyacheslav Levytskyy void validateForwardCalls(const SPIRVSubtarget &STI, 319b7ac8fddSVyacheslav Levytskyy MachineRegisterInfo *DefMRI, SPIRVGlobalRegistry &GR, 320b7ac8fddSVyacheslav Levytskyy MachineInstr &FunDef) { 321b7ac8fddSVyacheslav Levytskyy const Function *F = GR.getFunctionByDefinition(&FunDef); 32247e996d8SVyacheslav Levytskyy if (SmallPtrSet<MachineInstr *, 8> *FwdCalls = GR.getForwardCalls(F)) 323b7ac8fddSVyacheslav Levytskyy for (MachineInstr *FunCall : *FwdCalls) { 324b7ac8fddSVyacheslav Levytskyy MachineRegisterInfo *CallMRI = 325b7ac8fddSVyacheslav Levytskyy &FunCall->getParent()->getParent()->getRegInfo(); 326b7ac8fddSVyacheslav Levytskyy validateFunCallMachineDef(STI, DefMRI, CallMRI, GR, *FunCall, &FunDef); 327b7ac8fddSVyacheslav Levytskyy } 328b7ac8fddSVyacheslav Levytskyy } 329b7ac8fddSVyacheslav Levytskyy 3306cce67a8SVyacheslav Levytskyy // Validation of an access chain. 3316cce67a8SVyacheslav Levytskyy void validateAccessChain(const SPIRVSubtarget &STI, MachineRegisterInfo *MRI, 3326cce67a8SVyacheslav Levytskyy SPIRVGlobalRegistry &GR, MachineInstr &I) { 3336cce67a8SVyacheslav Levytskyy SPIRVType *BaseTypeInst = GR.getSPIRVTypeForVReg(I.getOperand(0).getReg()); 3346cce67a8SVyacheslav Levytskyy if (BaseTypeInst && BaseTypeInst->getOpcode() == SPIRV::OpTypePointer) { 3356cce67a8SVyacheslav Levytskyy SPIRVType *BaseElemType = 3366cce67a8SVyacheslav Levytskyy GR.getSPIRVTypeForVReg(BaseTypeInst->getOperand(2).getReg()); 3376cce67a8SVyacheslav Levytskyy validatePtrTypes(STI, MRI, GR, I, 2, BaseElemType); 3386cce67a8SVyacheslav Levytskyy } 3396cce67a8SVyacheslav Levytskyy } 3406cce67a8SVyacheslav Levytskyy 341fb1be9b3SVyacheslav Levytskyy // TODO: the logic of inserting additional bitcast's is to be moved 342fb1be9b3SVyacheslav Levytskyy // to pre-IRTranslation passes eventually 343fb1be9b3SVyacheslav Levytskyy void SPIRVTargetLowering::finalizeLowering(MachineFunction &MF) const { 34423b058cbSVyacheslav Levytskyy // finalizeLowering() is called twice (see GlobalISel/InstructionSelect.cpp) 34523b058cbSVyacheslav Levytskyy // We'd like to avoid the needless second processing pass. 34623b058cbSVyacheslav Levytskyy if (ProcessedMF.find(&MF) != ProcessedMF.end()) 34723b058cbSVyacheslav Levytskyy return; 34823b058cbSVyacheslav Levytskyy 349fb1be9b3SVyacheslav Levytskyy MachineRegisterInfo *MRI = &MF.getRegInfo(); 350fb1be9b3SVyacheslav Levytskyy SPIRVGlobalRegistry &GR = *STI.getSPIRVGlobalRegistry(); 351fb1be9b3SVyacheslav Levytskyy GR.setCurrentFunc(MF); 352fb1be9b3SVyacheslav Levytskyy for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { 353fb1be9b3SVyacheslav Levytskyy MachineBasicBlock *MBB = &*I; 354ebdadcfeSVyacheslav Levytskyy SmallPtrSet<MachineInstr *, 8> ToMove; 355fb1be9b3SVyacheslav Levytskyy for (MachineBasicBlock::iterator MBBI = MBB->begin(), MBBE = MBB->end(); 356fb1be9b3SVyacheslav Levytskyy MBBI != MBBE;) { 357fb1be9b3SVyacheslav Levytskyy MachineInstr &MI = *MBBI++; 358fb1be9b3SVyacheslav Levytskyy switch (MI.getOpcode()) { 3596cce67a8SVyacheslav Levytskyy case SPIRV::OpAtomicLoad: 3606cce67a8SVyacheslav Levytskyy case SPIRV::OpAtomicExchange: 3616cce67a8SVyacheslav Levytskyy case SPIRV::OpAtomicCompareExchange: 3626cce67a8SVyacheslav Levytskyy case SPIRV::OpAtomicCompareExchangeWeak: 3636cce67a8SVyacheslav Levytskyy case SPIRV::OpAtomicIIncrement: 3646cce67a8SVyacheslav Levytskyy case SPIRV::OpAtomicIDecrement: 3656cce67a8SVyacheslav Levytskyy case SPIRV::OpAtomicIAdd: 3666cce67a8SVyacheslav Levytskyy case SPIRV::OpAtomicISub: 3676cce67a8SVyacheslav Levytskyy case SPIRV::OpAtomicSMin: 3686cce67a8SVyacheslav Levytskyy case SPIRV::OpAtomicUMin: 3696cce67a8SVyacheslav Levytskyy case SPIRV::OpAtomicSMax: 3706cce67a8SVyacheslav Levytskyy case SPIRV::OpAtomicUMax: 3716cce67a8SVyacheslav Levytskyy case SPIRV::OpAtomicAnd: 3726cce67a8SVyacheslav Levytskyy case SPIRV::OpAtomicOr: 3736cce67a8SVyacheslav Levytskyy case SPIRV::OpAtomicXor: 3746cce67a8SVyacheslav Levytskyy // for the above listed instructions 3756cce67a8SVyacheslav Levytskyy // OpAtomicXXX <ResType>, ptr %Op, ... 3766cce67a8SVyacheslav Levytskyy // implies that %Op is a pointer to <ResType> 377fb1be9b3SVyacheslav Levytskyy case SPIRV::OpLoad: 378fb1be9b3SVyacheslav Levytskyy // OpLoad <ResType>, ptr %Op implies that %Op is a pointer to <ResType> 379b7ac8fddSVyacheslav Levytskyy validatePtrTypes(STI, MRI, GR, MI, 2, 380b7ac8fddSVyacheslav Levytskyy GR.getSPIRVTypeForVReg(MI.getOperand(0).getReg())); 381fb1be9b3SVyacheslav Levytskyy break; 3826cce67a8SVyacheslav Levytskyy case SPIRV::OpAtomicStore: 3836cce67a8SVyacheslav Levytskyy // OpAtomicStore ptr %Op, <Scope>, <Mem>, <Obj> 3846cce67a8SVyacheslav Levytskyy // implies that %Op points to the <Obj>'s type 3856cce67a8SVyacheslav Levytskyy validatePtrTypes(STI, MRI, GR, MI, 0, 3866cce67a8SVyacheslav Levytskyy GR.getSPIRVTypeForVReg(MI.getOperand(3).getReg())); 3876cce67a8SVyacheslav Levytskyy break; 388fb1be9b3SVyacheslav Levytskyy case SPIRV::OpStore: 389fb1be9b3SVyacheslav Levytskyy // OpStore ptr %Op, <Obj> implies that %Op points to the <Obj>'s type 390b7ac8fddSVyacheslav Levytskyy validatePtrTypes(STI, MRI, GR, MI, 0, 391b7ac8fddSVyacheslav Levytskyy GR.getSPIRVTypeForVReg(MI.getOperand(1).getReg())); 392fb1be9b3SVyacheslav Levytskyy break; 3936cce67a8SVyacheslav Levytskyy case SPIRV::OpPtrCastToGeneric: 39457520985SVyacheslav Levytskyy case SPIRV::OpGenericCastToPtr: 3956cce67a8SVyacheslav Levytskyy validateAccessChain(STI, MRI, GR, MI); 3966cce67a8SVyacheslav Levytskyy break; 397*b5132b7dSVyacheslav Levytskyy case SPIRV::OpPtrAccessChain: 3986cce67a8SVyacheslav Levytskyy case SPIRV::OpInBoundsPtrAccessChain: 3996cce67a8SVyacheslav Levytskyy if (MI.getNumOperands() == 4) 4006cce67a8SVyacheslav Levytskyy validateAccessChain(STI, MRI, GR, MI); 4016cce67a8SVyacheslav Levytskyy break; 402b7ac8fddSVyacheslav Levytskyy 403b7ac8fddSVyacheslav Levytskyy case SPIRV::OpFunctionCall: 404b7ac8fddSVyacheslav Levytskyy // ensure there is no mismatch between actual and expected arg types: 405b7ac8fddSVyacheslav Levytskyy // calls with a processed definition 406b7ac8fddSVyacheslav Levytskyy if (MI.getNumOperands() > 3) 407b7ac8fddSVyacheslav Levytskyy if (const Function *F = validateFunCall(STI, MRI, GR, MI)) 408b7ac8fddSVyacheslav Levytskyy GR.addForwardCall(F, &MI); 409b7ac8fddSVyacheslav Levytskyy break; 410b7ac8fddSVyacheslav Levytskyy case SPIRV::OpFunction: 411b7ac8fddSVyacheslav Levytskyy // ensure there is no mismatch between actual and expected arg types: 412b7ac8fddSVyacheslav Levytskyy // calls ahead of a processed definition 413b7ac8fddSVyacheslav Levytskyy validateForwardCalls(STI, MRI, GR, MI); 414b7ac8fddSVyacheslav Levytskyy break; 415b7ac8fddSVyacheslav Levytskyy 4168ac46d6bSVyacheslav Levytskyy // ensure that LLVM IR add/sub instructions result in logical SPIR-V 4178ac46d6bSVyacheslav Levytskyy // instructions when applied to bool type 4188ac46d6bSVyacheslav Levytskyy case SPIRV::OpIAddS: 4198ac46d6bSVyacheslav Levytskyy case SPIRV::OpIAddV: 4208ac46d6bSVyacheslav Levytskyy case SPIRV::OpISubS: 4218ac46d6bSVyacheslav Levytskyy case SPIRV::OpISubV: 4228ac46d6bSVyacheslav Levytskyy if (GR.isScalarOrVectorOfType(MI.getOperand(1).getReg(), 4238ac46d6bSVyacheslav Levytskyy SPIRV::OpTypeBool)) 4248ac46d6bSVyacheslav Levytskyy MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalNotEqual)); 4258ac46d6bSVyacheslav Levytskyy break; 4268ac46d6bSVyacheslav Levytskyy 427949d70d5SVyacheslav Levytskyy // ensure that LLVM IR bitwise instructions result in logical SPIR-V 428949d70d5SVyacheslav Levytskyy // instructions when applied to bool type 429949d70d5SVyacheslav Levytskyy case SPIRV::OpBitwiseOrS: 430949d70d5SVyacheslav Levytskyy case SPIRV::OpBitwiseOrV: 431949d70d5SVyacheslav Levytskyy if (GR.isScalarOrVectorOfType(MI.getOperand(1).getReg(), 432949d70d5SVyacheslav Levytskyy SPIRV::OpTypeBool)) 433949d70d5SVyacheslav Levytskyy MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalOr)); 434949d70d5SVyacheslav Levytskyy break; 435949d70d5SVyacheslav Levytskyy case SPIRV::OpBitwiseAndS: 436949d70d5SVyacheslav Levytskyy case SPIRV::OpBitwiseAndV: 437949d70d5SVyacheslav Levytskyy if (GR.isScalarOrVectorOfType(MI.getOperand(1).getReg(), 438949d70d5SVyacheslav Levytskyy SPIRV::OpTypeBool)) 439949d70d5SVyacheslav Levytskyy MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalAnd)); 440949d70d5SVyacheslav Levytskyy break; 441949d70d5SVyacheslav Levytskyy case SPIRV::OpBitwiseXorS: 442949d70d5SVyacheslav Levytskyy case SPIRV::OpBitwiseXorV: 443949d70d5SVyacheslav Levytskyy if (GR.isScalarOrVectorOfType(MI.getOperand(1).getReg(), 444949d70d5SVyacheslav Levytskyy SPIRV::OpTypeBool)) 445949d70d5SVyacheslav Levytskyy MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalNotEqual)); 446949d70d5SVyacheslav Levytskyy break; 447281f59fdSVyacheslav Levytskyy case SPIRV::OpLifetimeStart: 448281f59fdSVyacheslav Levytskyy case SPIRV::OpLifetimeStop: 449281f59fdSVyacheslav Levytskyy if (MI.getOperand(1).getImm() > 0) 450281f59fdSVyacheslav Levytskyy validateLifetimeStart(STI, MRI, GR, MI); 451281f59fdSVyacheslav Levytskyy break; 452bf9e9e5eSVyacheslav Levytskyy case SPIRV::OpGroupAsyncCopy: 4535a062191SVyacheslav Levytskyy validatePtrUnwrapStructField(STI, MRI, GR, MI, 3); 4545a062191SVyacheslav Levytskyy validatePtrUnwrapStructField(STI, MRI, GR, MI, 4); 455bf9e9e5eSVyacheslav Levytskyy break; 456ce73e17eSVyacheslav Levytskyy case SPIRV::OpGroupWaitEvents: 457ce73e17eSVyacheslav Levytskyy // OpGroupWaitEvents ..., ..., <pointer to OpTypeEvent> 458ce73e17eSVyacheslav Levytskyy validateGroupWaitEventsPtr(STI, MRI, GR, MI); 459ce73e17eSVyacheslav Levytskyy break; 4601ed1ec9aSVyacheslav Levytskyy case SPIRV::OpConstantI: { 4611ed1ec9aSVyacheslav Levytskyy SPIRVType *Type = GR.getSPIRVTypeForVReg(MI.getOperand(1).getReg()); 4621ed1ec9aSVyacheslav Levytskyy if (Type->getOpcode() != SPIRV::OpTypeInt && MI.getOperand(2).isImm() && 4631ed1ec9aSVyacheslav Levytskyy MI.getOperand(2).getImm() == 0) { 4641ed1ec9aSVyacheslav Levytskyy // Validate the null constant of a target extension type 4651ed1ec9aSVyacheslav Levytskyy MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpConstantNull)); 4661ed1ec9aSVyacheslav Levytskyy for (unsigned i = MI.getNumOperands() - 1; i > 1; --i) 4671ed1ec9aSVyacheslav Levytskyy MI.removeOperand(i); 4681ed1ec9aSVyacheslav Levytskyy } 4691ed1ec9aSVyacheslav Levytskyy } break; 470ebdadcfeSVyacheslav Levytskyy case SPIRV::OpPhi: { 471ebdadcfeSVyacheslav Levytskyy // Phi refers to a type definition that goes after the Phi 472ebdadcfeSVyacheslav Levytskyy // instruction, so that the virtual register definition of the type 473ebdadcfeSVyacheslav Levytskyy // doesn't dominate all uses. Let's place the type definition 474ebdadcfeSVyacheslav Levytskyy // instruction at the end of the predecessor. 475ebdadcfeSVyacheslav Levytskyy MachineBasicBlock *Curr = MI.getParent(); 476ebdadcfeSVyacheslav Levytskyy SPIRVType *Type = GR.getSPIRVTypeForVReg(MI.getOperand(1).getReg()); 477ebdadcfeSVyacheslav Levytskyy if (Type->getParent() == Curr && !Curr->pred_empty()) 478ebdadcfeSVyacheslav Levytskyy ToMove.insert(const_cast<MachineInstr *>(Type)); 479ebdadcfeSVyacheslav Levytskyy } break; 4805a062191SVyacheslav Levytskyy case SPIRV::OpExtInst: { 4815a062191SVyacheslav Levytskyy // prefetch 4825a062191SVyacheslav Levytskyy if (!MI.getOperand(2).isImm() || !MI.getOperand(3).isImm() || 4835a062191SVyacheslav Levytskyy MI.getOperand(2).getImm() != SPIRV::InstructionSet::OpenCL_std) 4845a062191SVyacheslav Levytskyy continue; 4855a062191SVyacheslav Levytskyy switch (MI.getOperand(3).getImm()) { 4868ac46d6bSVyacheslav Levytskyy case SPIRV::OpenCLExtInst::frexp: 4878ac46d6bSVyacheslav Levytskyy case SPIRV::OpenCLExtInst::lgamma_r: 4885a062191SVyacheslav Levytskyy case SPIRV::OpenCLExtInst::remquo: { 4898ac46d6bSVyacheslav Levytskyy // The last operand must be of a pointer to i32 or vector of i32 4908ac46d6bSVyacheslav Levytskyy // values. 4915a062191SVyacheslav Levytskyy MachineIRBuilder MIB(MI); 4925a062191SVyacheslav Levytskyy SPIRVType *Int32Type = GR.getOrCreateSPIRVIntegerType(32, MIB); 4935a062191SVyacheslav Levytskyy SPIRVType *RetType = MRI->getVRegDef(MI.getOperand(1).getReg()); 4945a062191SVyacheslav Levytskyy assert(RetType && "Expected return type"); 4955a062191SVyacheslav Levytskyy validatePtrTypes( 4965a062191SVyacheslav Levytskyy STI, MRI, GR, MI, MI.getNumOperands() - 1, 4975a062191SVyacheslav Levytskyy RetType->getOpcode() != SPIRV::OpTypeVector 4985a062191SVyacheslav Levytskyy ? Int32Type 4995a062191SVyacheslav Levytskyy : GR.getOrCreateSPIRVVectorType( 5005a062191SVyacheslav Levytskyy Int32Type, RetType->getOperand(2).getImm(), MIB)); 5015a062191SVyacheslav Levytskyy } break; 5025a062191SVyacheslav Levytskyy case SPIRV::OpenCLExtInst::fract: 5035a062191SVyacheslav Levytskyy case SPIRV::OpenCLExtInst::modf: 5045a062191SVyacheslav Levytskyy case SPIRV::OpenCLExtInst::sincos: 5055a062191SVyacheslav Levytskyy // The last operand must be of a pointer to the base type represented 5065a062191SVyacheslav Levytskyy // by the previous operand. 5075a062191SVyacheslav Levytskyy assert(MI.getOperand(MI.getNumOperands() - 2).isReg() && 5085a062191SVyacheslav Levytskyy "Expected v-reg"); 5095a062191SVyacheslav Levytskyy validatePtrTypes( 5105a062191SVyacheslav Levytskyy STI, MRI, GR, MI, MI.getNumOperands() - 1, 5115a062191SVyacheslav Levytskyy GR.getSPIRVTypeForVReg( 5125a062191SVyacheslav Levytskyy MI.getOperand(MI.getNumOperands() - 2).getReg())); 5135a062191SVyacheslav Levytskyy break; 5145a062191SVyacheslav Levytskyy case SPIRV::OpenCLExtInst::prefetch: 5155a062191SVyacheslav Levytskyy // Expected `ptr` type is a pointer to float, integer or vector, but 5165a062191SVyacheslav Levytskyy // the pontee value can be wrapped into a struct. 5175a062191SVyacheslav Levytskyy assert(MI.getOperand(MI.getNumOperands() - 2).isReg() && 5185a062191SVyacheslav Levytskyy "Expected v-reg"); 5195a062191SVyacheslav Levytskyy validatePtrUnwrapStructField(STI, MRI, GR, MI, 5205a062191SVyacheslav Levytskyy MI.getNumOperands() - 2); 5215a062191SVyacheslav Levytskyy break; 5225a062191SVyacheslav Levytskyy } 5235a062191SVyacheslav Levytskyy } break; 524fb1be9b3SVyacheslav Levytskyy } 525fb1be9b3SVyacheslav Levytskyy } 526ebdadcfeSVyacheslav Levytskyy for (MachineInstr *MI : ToMove) { 527ebdadcfeSVyacheslav Levytskyy MachineBasicBlock *Curr = MI->getParent(); 528ebdadcfeSVyacheslav Levytskyy MachineBasicBlock *Pred = *Curr->pred_begin(); 529ebdadcfeSVyacheslav Levytskyy Pred->insert(Pred->getFirstTerminator(), Curr->remove_instr(MI)); 530ebdadcfeSVyacheslav Levytskyy } 531fb1be9b3SVyacheslav Levytskyy } 53223b058cbSVyacheslav Levytskyy ProcessedMF.insert(&MF); 533fb1be9b3SVyacheslav Levytskyy TargetLowering::finalizeLowering(MF); 534fb1be9b3SVyacheslav Levytskyy } 535