Path: blob/main/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVPostLegalizer.cpp
35266 views
//===-- SPIRVPostLegalizer.cpp - ammend info after legalization -*- C++ -*-===//1//2// which may appear after the legalizer pass3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9//10// The pass partially apply pre-legalization logic to new instructions inserted11// as a result of legalization:12// - assigns SPIR-V types to registers for new instructions.13//14//===----------------------------------------------------------------------===//1516#include "SPIRV.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"2627#define DEBUG_TYPE "spirv-postlegalizer"2829using namespace llvm;3031namespace {32class SPIRVPostLegalizer : public MachineFunctionPass {33public:34static char ID;35SPIRVPostLegalizer() : MachineFunctionPass(ID) {36initializeSPIRVPostLegalizerPass(*PassRegistry::getPassRegistry());37}38bool runOnMachineFunction(MachineFunction &MF) override;39};40} // namespace4142// Defined in SPIRVLegalizerInfo.cpp.43extern bool isTypeFoldingSupported(unsigned Opcode);4445namespace llvm {46// Defined in SPIRVPreLegalizer.cpp.47extern Register insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpirvTy,48SPIRVGlobalRegistry *GR,49MachineIRBuilder &MIB,50MachineRegisterInfo &MRI);51extern void processInstr(MachineInstr &MI, MachineIRBuilder &MIB,52MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR);53} // namespace llvm5455static bool isMetaInstrGET(unsigned Opcode) {56return Opcode == SPIRV::GET_ID || Opcode == SPIRV::GET_ID64 ||57Opcode == SPIRV::GET_fID || Opcode == SPIRV::GET_fID64 ||58Opcode == SPIRV::GET_pID32 || Opcode == SPIRV::GET_pID64 ||59Opcode == SPIRV::GET_vID || Opcode == SPIRV::GET_vfID ||60Opcode == SPIRV::GET_vpID32 || Opcode == SPIRV::GET_vpID64;61}6263static bool mayBeInserted(unsigned Opcode) {64switch (Opcode) {65case TargetOpcode::G_SMAX:66case TargetOpcode::G_UMAX:67case TargetOpcode::G_SMIN:68case TargetOpcode::G_UMIN:69case TargetOpcode::G_FMINNUM:70case TargetOpcode::G_FMINIMUM:71case TargetOpcode::G_FMAXNUM:72case TargetOpcode::G_FMAXIMUM:73return true;74default:75return isTypeFoldingSupported(Opcode);76}77}7879static void processNewInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,80MachineIRBuilder MIB) {81MachineRegisterInfo &MRI = MF.getRegInfo();8283for (MachineBasicBlock &MBB : MF) {84for (MachineInstr &I : MBB) {85const unsigned Opcode = I.getOpcode();86if (Opcode == TargetOpcode::G_UNMERGE_VALUES) {87unsigned ArgI = I.getNumOperands() - 1;88Register SrcReg = I.getOperand(ArgI).isReg()89? I.getOperand(ArgI).getReg()90: Register(0);91SPIRVType *DefType =92SrcReg.isValid() ? GR->getSPIRVTypeForVReg(SrcReg) : nullptr;93if (!DefType || DefType->getOpcode() != SPIRV::OpTypeVector)94report_fatal_error(95"cannot select G_UNMERGE_VALUES with a non-vector argument");96SPIRVType *ScalarType =97GR->getSPIRVTypeForVReg(DefType->getOperand(1).getReg());98for (unsigned i = 0; i < I.getNumDefs(); ++i) {99Register ResVReg = I.getOperand(i).getReg();100SPIRVType *ResType = GR->getSPIRVTypeForVReg(ResVReg);101if (!ResType) {102// There was no "assign type" actions, let's fix this now103ResType = ScalarType;104MRI.setRegClass(ResVReg, &SPIRV::IDRegClass);105MRI.setType(ResVReg,106LLT::scalar(GR->getScalarOrVectorBitWidth(ResType)));107GR->assignSPIRVTypeToVReg(ResType, ResVReg, *GR->CurMF);108}109}110} else if (mayBeInserted(Opcode) && I.getNumDefs() == 1 &&111I.getNumOperands() > 1 && I.getOperand(1).isReg()) {112// Legalizer may have added a new instructions and introduced new113// registers, we must decorate them as if they were introduced in a114// non-automatic way115Register ResVReg = I.getOperand(0).getReg();116SPIRVType *ResVType = GR->getSPIRVTypeForVReg(ResVReg);117// Check if the register defined by the instruction is newly generated118// or already processed119if (!ResVType) {120// Set type of the defined register121ResVType = GR->getSPIRVTypeForVReg(I.getOperand(1).getReg());122// Check if we have type defined for operands of the new instruction123if (!ResVType)124continue;125// Set type & class126MRI.setRegClass(ResVReg, &SPIRV::IDRegClass);127MRI.setType(ResVReg,128LLT::scalar(GR->getScalarOrVectorBitWidth(ResVType)));129GR->assignSPIRVTypeToVReg(ResVType, ResVReg, *GR->CurMF);130}131// If this is a simple operation that is to be reduced by TableGen132// definition we must apply some of pre-legalizer rules here133if (isTypeFoldingSupported(Opcode)) {134// Check if the instruction newly generated or already processed135MachineInstr *NextMI = I.getNextNode();136if (NextMI && isMetaInstrGET(NextMI->getOpcode()))137continue;138// Restore usual instructions pattern for the newly inserted139// instruction140MRI.setRegClass(ResVReg, MRI.getType(ResVReg).isVector()141? &SPIRV::IDRegClass142: &SPIRV::ANYIDRegClass);143MRI.setType(ResVReg, LLT::scalar(32));144insertAssignInstr(ResVReg, nullptr, ResVType, GR, MIB, MRI);145processInstr(I, MIB, MRI, GR);146}147}148}149}150}151152bool SPIRVPostLegalizer::runOnMachineFunction(MachineFunction &MF) {153// Initialize the type registry.154const SPIRVSubtarget &ST = MF.getSubtarget<SPIRVSubtarget>();155SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();156GR->setCurrentFunc(MF);157MachineIRBuilder MIB(MF);158159processNewInstrs(MF, GR, MIB);160161return true;162}163164INITIALIZE_PASS(SPIRVPostLegalizer, DEBUG_TYPE, "SPIRV post legalizer", false,165false)166167char SPIRVPostLegalizer::ID = 0;168169FunctionPass *llvm::createSPIRVPostLegalizerPass() {170return new SPIRVPostLegalizer();171}172173174