Path: blob/main/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
96353 views
//===-- SystemZRegisterInfo.cpp - SystemZ register information ------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "SystemZRegisterInfo.h"9#include "SystemZInstrInfo.h"10#include "SystemZSubtarget.h"11#include "llvm/ADT/SmallSet.h"12#include "llvm/CodeGen/LiveIntervals.h"13#include "llvm/CodeGen/MachineInstrBuilder.h"14#include "llvm/CodeGen/MachineRegisterInfo.h"15#include "llvm/CodeGen/TargetFrameLowering.h"16#include "llvm/CodeGen/VirtRegMap.h"17#include "llvm/IR/DebugInfoMetadata.h"1819using namespace llvm;2021#define GET_REGINFO_TARGET_DESC22#include "SystemZGenRegisterInfo.inc"2324// Given that MO is a GRX32 operand, return either GR32 or GRH32 if MO25// somehow belongs in it. Otherwise, return GRX32.26static const TargetRegisterClass *getRC32(MachineOperand &MO,27const VirtRegMap *VRM,28const MachineRegisterInfo *MRI) {29const TargetRegisterClass *RC = MRI->getRegClass(MO.getReg());3031if (SystemZ::GR32BitRegClass.hasSubClassEq(RC) ||32MO.getSubReg() == SystemZ::subreg_ll32 ||33MO.getSubReg() == SystemZ::subreg_l32)34return &SystemZ::GR32BitRegClass;35if (SystemZ::GRH32BitRegClass.hasSubClassEq(RC) ||36MO.getSubReg() == SystemZ::subreg_lh32 ||37MO.getSubReg() == SystemZ::subreg_h32)38return &SystemZ::GRH32BitRegClass;3940if (VRM && VRM->hasPhys(MO.getReg())) {41Register PhysReg = VRM->getPhys(MO.getReg());42if (SystemZ::GR32BitRegClass.contains(PhysReg))43return &SystemZ::GR32BitRegClass;44assert (SystemZ::GRH32BitRegClass.contains(PhysReg) &&45"Phys reg not in GR32 or GRH32?");46return &SystemZ::GRH32BitRegClass;47}4849assert (RC == &SystemZ::GRX32BitRegClass);50return RC;51}5253// Pass the registers of RC as hints while making sure that if any of these54// registers are copy hints (and therefore already in Hints), hint them55// first.56static void addHints(ArrayRef<MCPhysReg> Order,57SmallVectorImpl<MCPhysReg> &Hints,58const TargetRegisterClass *RC,59const MachineRegisterInfo *MRI) {60SmallSet<unsigned, 4> CopyHints;61CopyHints.insert(Hints.begin(), Hints.end());62Hints.clear();63for (MCPhysReg Reg : Order)64if (CopyHints.count(Reg) &&65RC->contains(Reg) && !MRI->isReserved(Reg))66Hints.push_back(Reg);67for (MCPhysReg Reg : Order)68if (!CopyHints.count(Reg) &&69RC->contains(Reg) && !MRI->isReserved(Reg))70Hints.push_back(Reg);71}7273bool SystemZRegisterInfo::getRegAllocationHints(74Register VirtReg, ArrayRef<MCPhysReg> Order,75SmallVectorImpl<MCPhysReg> &Hints, const MachineFunction &MF,76const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const {77const MachineRegisterInfo *MRI = &MF.getRegInfo();78const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();79const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();8081bool BaseImplRetVal = TargetRegisterInfo::getRegAllocationHints(82VirtReg, Order, Hints, MF, VRM, Matrix);8384if (VRM != nullptr) {85// Add any two address hints after any copy hints.86SmallSet<unsigned, 4> TwoAddrHints;87for (auto &Use : MRI->reg_nodbg_instructions(VirtReg))88if (SystemZ::getTwoOperandOpcode(Use.getOpcode()) != -1) {89const MachineOperand *VRRegMO = nullptr;90const MachineOperand *OtherMO = nullptr;91const MachineOperand *CommuMO = nullptr;92if (VirtReg == Use.getOperand(0).getReg()) {93VRRegMO = &Use.getOperand(0);94OtherMO = &Use.getOperand(1);95if (Use.isCommutable())96CommuMO = &Use.getOperand(2);97} else if (VirtReg == Use.getOperand(1).getReg()) {98VRRegMO = &Use.getOperand(1);99OtherMO = &Use.getOperand(0);100} else if (VirtReg == Use.getOperand(2).getReg() &&101Use.isCommutable()) {102VRRegMO = &Use.getOperand(2);103OtherMO = &Use.getOperand(0);104} else105continue;106107auto tryAddHint = [&](const MachineOperand *MO) -> void {108Register Reg = MO->getReg();109Register PhysReg =110Reg.isPhysical() ? Reg : Register(VRM->getPhys(Reg));111if (PhysReg) {112if (MO->getSubReg())113PhysReg = getSubReg(PhysReg, MO->getSubReg());114if (VRRegMO->getSubReg())115PhysReg = getMatchingSuperReg(PhysReg, VRRegMO->getSubReg(),116MRI->getRegClass(VirtReg));117if (!MRI->isReserved(PhysReg) && !is_contained(Hints, PhysReg))118TwoAddrHints.insert(PhysReg);119}120};121tryAddHint(OtherMO);122if (CommuMO)123tryAddHint(CommuMO);124}125for (MCPhysReg OrderReg : Order)126if (TwoAddrHints.count(OrderReg))127Hints.push_back(OrderReg);128}129130if (MRI->getRegClass(VirtReg) == &SystemZ::GRX32BitRegClass) {131SmallVector<Register, 8> Worklist;132SmallSet<Register, 4> DoneRegs;133Worklist.push_back(VirtReg);134while (Worklist.size()) {135Register Reg = Worklist.pop_back_val();136if (!DoneRegs.insert(Reg).second)137continue;138139for (auto &Use : MRI->reg_instructions(Reg)) {140// For LOCRMux, see if the other operand is already a high or low141// register, and in that case give the corresponding hints for142// VirtReg. LOCR instructions need both operands in either high or143// low parts. Same handling for SELRMux.144if (Use.getOpcode() == SystemZ::LOCRMux ||145Use.getOpcode() == SystemZ::SELRMux) {146MachineOperand &TrueMO = Use.getOperand(1);147MachineOperand &FalseMO = Use.getOperand(2);148const TargetRegisterClass *RC =149TRI->getCommonSubClass(getRC32(FalseMO, VRM, MRI),150getRC32(TrueMO, VRM, MRI));151if (Use.getOpcode() == SystemZ::SELRMux)152RC = TRI->getCommonSubClass(RC,153getRC32(Use.getOperand(0), VRM, MRI));154if (RC && RC != &SystemZ::GRX32BitRegClass) {155addHints(Order, Hints, RC, MRI);156// Return true to make these hints the only regs available to157// RA. This may mean extra spilling but since the alternative is158// a jump sequence expansion of the LOCRMux, it is preferred.159return true;160}161162// Add the other operand of the LOCRMux to the worklist.163Register OtherReg =164(TrueMO.getReg() == Reg ? FalseMO.getReg() : TrueMO.getReg());165if (MRI->getRegClass(OtherReg) == &SystemZ::GRX32BitRegClass)166Worklist.push_back(OtherReg);167} // end LOCRMux168else if (Use.getOpcode() == SystemZ::CHIMux ||169Use.getOpcode() == SystemZ::CFIMux) {170if (Use.getOperand(1).getImm() == 0) {171bool OnlyLMuxes = true;172for (MachineInstr &DefMI : MRI->def_instructions(VirtReg))173if (DefMI.getOpcode() != SystemZ::LMux)174OnlyLMuxes = false;175if (OnlyLMuxes) {176addHints(Order, Hints, &SystemZ::GR32BitRegClass, MRI);177// Return false to make these hints preferred but not obligatory.178return false;179}180}181} // end CHIMux / CFIMux182}183}184}185186return BaseImplRetVal;187}188189const MCPhysReg *190SystemZXPLINK64Registers::getCalleeSavedRegs(const MachineFunction *MF) const {191const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();192return Subtarget.hasVector() ? CSR_SystemZ_XPLINK64_Vector_SaveList193: CSR_SystemZ_XPLINK64_SaveList;194}195196const MCPhysReg *197SystemZELFRegisters::getCalleeSavedRegs(const MachineFunction *MF) const {198const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();199if (MF->getFunction().getCallingConv() == CallingConv::GHC)200return CSR_SystemZ_NoRegs_SaveList;201if (MF->getFunction().getCallingConv() == CallingConv::AnyReg)202return Subtarget.hasVector()? CSR_SystemZ_AllRegs_Vector_SaveList203: CSR_SystemZ_AllRegs_SaveList;204if (MF->getSubtarget().getTargetLowering()->supportSwiftError() &&205MF->getFunction().getAttributes().hasAttrSomewhere(206Attribute::SwiftError))207return CSR_SystemZ_SwiftError_SaveList;208return CSR_SystemZ_ELF_SaveList;209}210211const uint32_t *212SystemZXPLINK64Registers::getCallPreservedMask(const MachineFunction &MF,213CallingConv::ID CC) const {214const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();215return Subtarget.hasVector() ? CSR_SystemZ_XPLINK64_Vector_RegMask216: CSR_SystemZ_XPLINK64_RegMask;217}218219const uint32_t *220SystemZELFRegisters::getCallPreservedMask(const MachineFunction &MF,221CallingConv::ID CC) const {222const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();223if (CC == CallingConv::GHC)224return CSR_SystemZ_NoRegs_RegMask;225if (CC == CallingConv::AnyReg)226return Subtarget.hasVector()? CSR_SystemZ_AllRegs_Vector_RegMask227: CSR_SystemZ_AllRegs_RegMask;228if (MF.getSubtarget().getTargetLowering()->supportSwiftError() &&229MF.getFunction().getAttributes().hasAttrSomewhere(230Attribute::SwiftError))231return CSR_SystemZ_SwiftError_RegMask;232return CSR_SystemZ_ELF_RegMask;233}234235SystemZRegisterInfo::SystemZRegisterInfo(unsigned int RA)236: SystemZGenRegisterInfo(RA) {}237238const MCPhysReg *239SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {240241const SystemZSubtarget *Subtarget = &MF->getSubtarget<SystemZSubtarget>();242SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters();243244return Regs->getCalleeSavedRegs(MF);245}246247const uint32_t *248SystemZRegisterInfo::getCallPreservedMask(const MachineFunction &MF,249CallingConv::ID CC) const {250251const SystemZSubtarget *Subtarget = &MF.getSubtarget<SystemZSubtarget>();252SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters();253return Regs->getCallPreservedMask(MF, CC);254}255256BitVector257SystemZRegisterInfo::getReservedRegs(const MachineFunction &MF) const {258BitVector Reserved(getNumRegs());259const SystemZFrameLowering *TFI = getFrameLowering(MF);260const SystemZSubtarget *Subtarget = &MF.getSubtarget<SystemZSubtarget>();261SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters();262if (TFI->hasFP(MF))263// The frame pointer. Reserve all aliases.264for (MCRegAliasIterator AI(Regs->getFramePointerRegister(), this, true);265AI.isValid(); ++AI)266Reserved.set(*AI);267268// Reserve all aliases for the stack pointer.269for (MCRegAliasIterator AI(Regs->getStackPointerRegister(), this, true);270AI.isValid(); ++AI)271Reserved.set(*AI);272273// A0 and A1 hold the thread pointer.274Reserved.set(SystemZ::A0);275Reserved.set(SystemZ::A1);276277// FPC is the floating-point control register.278Reserved.set(SystemZ::FPC);279280return Reserved;281}282283bool284SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,285int SPAdj, unsigned FIOperandNum,286RegScavenger *RS) const {287assert(SPAdj == 0 && "Outgoing arguments should be part of the frame");288289MachineBasicBlock &MBB = *MI->getParent();290MachineFunction &MF = *MBB.getParent();291auto *TII = MF.getSubtarget<SystemZSubtarget>().getInstrInfo();292const SystemZFrameLowering *TFI = getFrameLowering(MF);293DebugLoc DL = MI->getDebugLoc();294295// Decompose the frame index into a base and offset.296int FrameIndex = MI->getOperand(FIOperandNum).getIndex();297Register BasePtr;298int64_t Offset =299(TFI->getFrameIndexReference(MF, FrameIndex, BasePtr).getFixed() +300MI->getOperand(FIOperandNum + 1).getImm());301302// Special handling of dbg_value instructions.303if (MI->isDebugValue()) {304MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, /*isDef*/ false);305if (MI->isNonListDebugValue()) {306MI->getDebugOffset().ChangeToImmediate(Offset);307} else {308unsigned OpIdx = MI->getDebugOperandIndex(&MI->getOperand(FIOperandNum));309SmallVector<uint64_t, 3> Ops;310DIExpression::appendOffset(311Ops, TFI->getFrameIndexReference(MF, FrameIndex, BasePtr).getFixed());312MI->getDebugExpressionOp().setMetadata(313DIExpression::appendOpsToArg(MI->getDebugExpression(), Ops, OpIdx));314}315return false;316}317318// See if the offset is in range, or if an equivalent instruction that319// accepts the offset exists.320unsigned Opcode = MI->getOpcode();321unsigned OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset, &*MI);322if (OpcodeForOffset) {323if (OpcodeForOffset == SystemZ::LE &&324MF.getSubtarget<SystemZSubtarget>().hasVector()) {325// If LE is ok for offset, use LDE instead on z13.326OpcodeForOffset = SystemZ::LDE32;327}328MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false);329}330else {331// Create an anchor point that is in range. Start at 0xffff so that332// can use LLILH to load the immediate.333int64_t OldOffset = Offset;334int64_t Mask = 0xffff;335do {336Offset = OldOffset & Mask;337OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset);338Mask >>= 1;339assert(Mask && "One offset must be OK");340} while (!OpcodeForOffset);341342Register ScratchReg =343MF.getRegInfo().createVirtualRegister(&SystemZ::ADDR64BitRegClass);344int64_t HighOffset = OldOffset - Offset;345346if (MI->getDesc().TSFlags & SystemZII::HasIndex347&& MI->getOperand(FIOperandNum + 2).getReg() == 0) {348// Load the offset into the scratch register and use it as an index.349// The scratch register then dies here.350TII->loadImmediate(MBB, MI, ScratchReg, HighOffset);351MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false);352MI->getOperand(FIOperandNum + 2).ChangeToRegister(ScratchReg,353false, false, true);354} else {355// Load the anchor address into a scratch register.356unsigned LAOpcode = TII->getOpcodeForOffset(SystemZ::LA, HighOffset);357if (LAOpcode)358BuildMI(MBB, MI, DL, TII->get(LAOpcode),ScratchReg)359.addReg(BasePtr).addImm(HighOffset).addReg(0);360else {361// Load the high offset into the scratch register and use it as362// an index.363TII->loadImmediate(MBB, MI, ScratchReg, HighOffset);364BuildMI(MBB, MI, DL, TII->get(SystemZ::LA), ScratchReg)365.addReg(BasePtr, RegState::Kill).addImm(0).addReg(ScratchReg);366}367368// Use the scratch register as the base. It then dies here.369MI->getOperand(FIOperandNum).ChangeToRegister(ScratchReg,370false, false, true);371}372}373MI->setDesc(TII->get(OpcodeForOffset));374MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);375return false;376}377378bool SystemZRegisterInfo::shouldCoalesce(MachineInstr *MI,379const TargetRegisterClass *SrcRC,380unsigned SubReg,381const TargetRegisterClass *DstRC,382unsigned DstSubReg,383const TargetRegisterClass *NewRC,384LiveIntervals &LIS) const {385assert (MI->isCopy() && "Only expecting COPY instructions");386387// Coalesce anything which is not a COPY involving a subreg to/from GR128.388if (!(NewRC->hasSuperClassEq(&SystemZ::GR128BitRegClass) &&389(getRegSizeInBits(*SrcRC) <= 64 || getRegSizeInBits(*DstRC) <= 64) &&390!MI->getOperand(1).isUndef()))391return true;392393// Allow coalescing of a GR128 subreg COPY only if the subreg liverange is394// local to one MBB with not too many interferring physreg clobbers. Otherwise395// regalloc may run out of registers.396unsigned SubregOpIdx = getRegSizeInBits(*SrcRC) == 128 ? 0 : 1;397LiveInterval &LI = LIS.getInterval(MI->getOperand(SubregOpIdx).getReg());398399// Check that the subreg is local to MBB.400MachineBasicBlock *MBB = MI->getParent();401MachineInstr *FirstMI = LIS.getInstructionFromIndex(LI.beginIndex());402MachineInstr *LastMI = LIS.getInstructionFromIndex(LI.endIndex());403if (!FirstMI || FirstMI->getParent() != MBB ||404!LastMI || LastMI->getParent() != MBB)405return false;406407// Check if coalescing seems safe by finding the set of clobbered physreg408// pairs in the region.409BitVector PhysClobbered(getNumRegs());410for (MachineBasicBlock::iterator MII = FirstMI,411MEE = std::next(LastMI->getIterator());412MII != MEE; ++MII)413for (const MachineOperand &MO : MII->operands())414if (MO.isReg() && MO.getReg().isPhysical()) {415for (MCPhysReg SI : superregs_inclusive(MO.getReg()))416if (NewRC->contains(SI)) {417PhysClobbered.set(SI);418break;419}420}421422// Demand an arbitrary margin of free regs.423unsigned const DemandedFreeGR128 = 3;424if (PhysClobbered.count() > (NewRC->getNumRegs() - DemandedFreeGR128))425return false;426427return true;428}429430Register431SystemZRegisterInfo::getFrameRegister(const MachineFunction &MF) const {432const SystemZFrameLowering *TFI = getFrameLowering(MF);433const SystemZSubtarget *Subtarget = &MF.getSubtarget<SystemZSubtarget>();434SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters();435436return TFI->hasFP(MF) ? Regs->getFramePointerRegister()437: Regs->getStackPointerRegister();438}439440const TargetRegisterClass *441SystemZRegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {442if (RC == &SystemZ::CCRRegClass)443return &SystemZ::GR32BitRegClass;444return RC;445}446447448449