1 //===-- SPIRVPostLegalizer.cpp - ammend info after legalization -*- C++ -*-===// 2 // 3 // which may appear after the legalizer pass 4 // 5 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 6 // See https://llvm.org/LICENSE.txt for license information. 7 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 8 // 9 //===----------------------------------------------------------------------===// 10 // 11 // The pass partially apply pre-legalization logic to new instructions inserted 12 // as a result of legalization: 13 // - assigns SPIR-V types to registers for new instructions. 14 // 15 //===----------------------------------------------------------------------===// 16 17 #include "SPIRV.h" 18 #include "SPIRVSubtarget.h" 19 #include "SPIRVUtils.h" 20 #include "llvm/ADT/PostOrderIterator.h" 21 #include "llvm/Analysis/OptimizationRemarkEmitter.h" 22 #include "llvm/IR/Attributes.h" 23 #include "llvm/IR/Constants.h" 24 #include "llvm/IR/DebugInfoMetadata.h" 25 #include "llvm/IR/IntrinsicsSPIRV.h" 26 #include "llvm/Target/TargetIntrinsicInfo.h" 27 28 #define DEBUG_TYPE "spirv-postlegalizer" 29 30 using namespace llvm; 31 32 namespace { 33 class SPIRVPostLegalizer : public MachineFunctionPass { 34 public: 35 static char ID; 36 SPIRVPostLegalizer() : MachineFunctionPass(ID) { 37 initializeSPIRVPostLegalizerPass(*PassRegistry::getPassRegistry()); 38 } 39 bool runOnMachineFunction(MachineFunction &MF) override; 40 }; 41 } // namespace 42 43 // Defined in SPIRVLegalizerInfo.cpp. 44 extern bool isTypeFoldingSupported(unsigned Opcode); 45 46 namespace llvm { 47 // Defined in SPIRVPreLegalizer.cpp. 48 extern Register insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpirvTy, 49 SPIRVGlobalRegistry *GR, 50 MachineIRBuilder &MIB, 51 MachineRegisterInfo &MRI); 52 extern void processInstr(MachineInstr &MI, MachineIRBuilder &MIB, 53 MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR); 54 } // namespace llvm 55 56 static bool isMetaInstrGET(unsigned Opcode) { 57 return Opcode == SPIRV::GET_ID || Opcode == SPIRV::GET_ID64 || 58 Opcode == SPIRV::GET_fID || Opcode == SPIRV::GET_fID64 || 59 Opcode == SPIRV::GET_pID32 || Opcode == SPIRV::GET_pID64 || 60 Opcode == SPIRV::GET_vID || Opcode == SPIRV::GET_vfID || 61 Opcode == SPIRV::GET_vpID32 || Opcode == SPIRV::GET_vpID64; 62 } 63 64 static bool mayBeInserted(unsigned Opcode) { 65 switch (Opcode) { 66 case TargetOpcode::G_SMAX: 67 case TargetOpcode::G_UMAX: 68 case TargetOpcode::G_SMIN: 69 case TargetOpcode::G_UMIN: 70 case TargetOpcode::G_FMINNUM: 71 case TargetOpcode::G_FMINIMUM: 72 case TargetOpcode::G_FMAXNUM: 73 case TargetOpcode::G_FMAXIMUM: 74 return true; 75 default: 76 return isTypeFoldingSupported(Opcode); 77 } 78 } 79 80 static void processNewInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR, 81 MachineIRBuilder MIB) { 82 MachineRegisterInfo &MRI = MF.getRegInfo(); 83 84 for (MachineBasicBlock &MBB : MF) { 85 for (MachineInstr &I : MBB) { 86 const unsigned Opcode = I.getOpcode(); 87 if (Opcode == TargetOpcode::G_UNMERGE_VALUES) { 88 unsigned ArgI = I.getNumOperands() - 1; 89 Register SrcReg = I.getOperand(ArgI).isReg() 90 ? I.getOperand(ArgI).getReg() 91 : Register(0); 92 SPIRVType *DefType = 93 SrcReg.isValid() ? GR->getSPIRVTypeForVReg(SrcReg) : nullptr; 94 if (!DefType || DefType->getOpcode() != SPIRV::OpTypeVector) 95 report_fatal_error( 96 "cannot select G_UNMERGE_VALUES with a non-vector argument"); 97 SPIRVType *ScalarType = 98 GR->getSPIRVTypeForVReg(DefType->getOperand(1).getReg()); 99 for (unsigned i = 0; i < I.getNumDefs(); ++i) { 100 Register ResVReg = I.getOperand(i).getReg(); 101 SPIRVType *ResType = GR->getSPIRVTypeForVReg(ResVReg); 102 if (!ResType) { 103 // There was no "assign type" actions, let's fix this now 104 ResType = ScalarType; 105 MRI.setRegClass(ResVReg, &SPIRV::IDRegClass); 106 MRI.setType(ResVReg, 107 LLT::scalar(GR->getScalarOrVectorBitWidth(ResType))); 108 GR->assignSPIRVTypeToVReg(ResType, ResVReg, *GR->CurMF); 109 } 110 } 111 } else if (mayBeInserted(Opcode) && I.getNumDefs() == 1 && 112 I.getNumOperands() > 1 && I.getOperand(1).isReg()) { 113 // Legalizer may have added a new instructions and introduced new 114 // registers, we must decorate them as if they were introduced in a 115 // non-automatic way 116 Register ResVReg = I.getOperand(0).getReg(); 117 SPIRVType *ResVType = GR->getSPIRVTypeForVReg(ResVReg); 118 // Check if the register defined by the instruction is newly generated 119 // or already processed 120 if (!ResVType) { 121 // Set type of the defined register 122 ResVType = GR->getSPIRVTypeForVReg(I.getOperand(1).getReg()); 123 // Check if we have type defined for operands of the new instruction 124 if (!ResVType) 125 continue; 126 // Set type & class 127 MRI.setRegClass(ResVReg, &SPIRV::IDRegClass); 128 MRI.setType(ResVReg, 129 LLT::scalar(GR->getScalarOrVectorBitWidth(ResVType))); 130 GR->assignSPIRVTypeToVReg(ResVType, ResVReg, *GR->CurMF); 131 } 132 // If this is a simple operation that is to be reduced by TableGen 133 // definition we must apply some of pre-legalizer rules here 134 if (isTypeFoldingSupported(Opcode)) { 135 // Check if the instruction newly generated or already processed 136 MachineInstr *NextMI = I.getNextNode(); 137 if (NextMI && isMetaInstrGET(NextMI->getOpcode())) 138 continue; 139 // Restore usual instructions pattern for the newly inserted 140 // instruction 141 MRI.setRegClass(ResVReg, MRI.getType(ResVReg).isVector() 142 ? &SPIRV::IDRegClass 143 : &SPIRV::ANYIDRegClass); 144 MRI.setType(ResVReg, LLT::scalar(32)); 145 insertAssignInstr(ResVReg, nullptr, ResVType, GR, MIB, MRI); 146 processInstr(I, MIB, MRI, GR); 147 } 148 } 149 } 150 } 151 } 152 153 bool SPIRVPostLegalizer::runOnMachineFunction(MachineFunction &MF) { 154 // Initialize the type registry. 155 const SPIRVSubtarget &ST = MF.getSubtarget<SPIRVSubtarget>(); 156 SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry(); 157 GR->setCurrentFunc(MF); 158 MachineIRBuilder MIB(MF); 159 160 processNewInstrs(MF, GR, MIB); 161 162 return true; 163 } 164 165 INITIALIZE_PASS(SPIRVPostLegalizer, DEBUG_TYPE, "SPIRV post legalizer", false, 166 false) 167 168 char SPIRVPostLegalizer::ID = 0; 169 170 FunctionPass *llvm::createSPIRVPostLegalizerPass() { 171 return new SPIRVPostLegalizer(); 172 } 173