//===-- SystemZRegisterInfo.cpp - SystemZ register information ------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "SystemZRegisterInfo.h" #include "SystemZInstrInfo.h" #include "SystemZSubtarget.h" #include "llvm/CodeGen/LiveIntervals.h" #include "llvm/ADT/SmallSet.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/TargetFrameLowering.h" #include "llvm/CodeGen/VirtRegMap.h" using namespace llvm; #define GET_REGINFO_TARGET_DESC #include "SystemZGenRegisterInfo.inc" SystemZRegisterInfo::SystemZRegisterInfo() : SystemZGenRegisterInfo(SystemZ::R14D) {} // Given that MO is a GRX32 operand, return either GR32 or GRH32 if MO // somehow belongs in it. Otherwise, return GRX32. static const TargetRegisterClass *getRC32(MachineOperand &MO, const VirtRegMap *VRM, const MachineRegisterInfo *MRI) { const TargetRegisterClass *RC = MRI->getRegClass(MO.getReg()); if (SystemZ::GR32BitRegClass.hasSubClassEq(RC) || MO.getSubReg() == SystemZ::subreg_l32 || MO.getSubReg() == SystemZ::subreg_hl32) return &SystemZ::GR32BitRegClass; if (SystemZ::GRH32BitRegClass.hasSubClassEq(RC) || MO.getSubReg() == SystemZ::subreg_h32 || MO.getSubReg() == SystemZ::subreg_hh32) return &SystemZ::GRH32BitRegClass; if (VRM && VRM->hasPhys(MO.getReg())) { unsigned PhysReg = VRM->getPhys(MO.getReg()); if (SystemZ::GR32BitRegClass.contains(PhysReg)) return &SystemZ::GR32BitRegClass; assert (SystemZ::GRH32BitRegClass.contains(PhysReg) && "Phys reg not in GR32 or GRH32?"); return &SystemZ::GRH32BitRegClass; } assert (RC == &SystemZ::GRX32BitRegClass); return RC; } bool SystemZRegisterInfo::getRegAllocationHints(unsigned VirtReg, ArrayRef<MCPhysReg> Order, SmallVectorImpl<MCPhysReg> &Hints, const MachineFunction &MF, const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const { const MachineRegisterInfo *MRI = &MF.getRegInfo(); const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); if (MRI->getRegClass(VirtReg) == &SystemZ::GRX32BitRegClass) { SmallVector<unsigned, 8> Worklist; SmallSet<unsigned, 4> DoneRegs; Worklist.push_back(VirtReg); while (Worklist.size()) { unsigned Reg = Worklist.pop_back_val(); if (!DoneRegs.insert(Reg).second) continue; for (auto &Use : MRI->use_instructions(Reg)) // For LOCRMux, see if the other operand is already a high or low // register, and in that case give the correpsonding hints for // VirtReg. LOCR instructions need both operands in either high or // low parts. if (Use.getOpcode() == SystemZ::LOCRMux) { MachineOperand &TrueMO = Use.getOperand(1); MachineOperand &FalseMO = Use.getOperand(2); const TargetRegisterClass *RC = TRI->getCommonSubClass(getRC32(FalseMO, VRM, MRI), getRC32(TrueMO, VRM, MRI)); if (RC && RC != &SystemZ::GRX32BitRegClass) { for (MCPhysReg Reg : Order) if (RC->contains(Reg) && !MRI->isReserved(Reg)) Hints.push_back(Reg); // Return true to make these hints the only regs available to // RA. This may mean extra spilling but since the alternative is // a jump sequence expansion of the LOCRMux, it is preferred. return true; } // Add the other operand of the LOCRMux to the worklist. unsigned OtherReg = (TrueMO.getReg() == Reg ? FalseMO.getReg() : TrueMO.getReg()); if (MRI->getRegClass(OtherReg) == &SystemZ::GRX32BitRegClass) Worklist.push_back(OtherReg); } } } return TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints, MF, VRM, Matrix); } const MCPhysReg * SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>(); if (MF->getFunction().getCallingConv() == CallingConv::AnyReg) return Subtarget.hasVector()? CSR_SystemZ_AllRegs_Vector_SaveList : CSR_SystemZ_AllRegs_SaveList; if (MF->getSubtarget().getTargetLowering()->supportSwiftError() && MF->getFunction().getAttributes().hasAttrSomewhere( Attribute::SwiftError)) return CSR_SystemZ_SwiftError_SaveList; return CSR_SystemZ_SaveList; } const uint32_t * SystemZRegisterInfo::getCallPreservedMask(const MachineFunction &MF, CallingConv::ID CC) const { const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>(); if (CC == CallingConv::AnyReg) return Subtarget.hasVector()? CSR_SystemZ_AllRegs_Vector_RegMask : CSR_SystemZ_AllRegs_RegMask; if (MF.getSubtarget().getTargetLowering()->supportSwiftError() && MF.getFunction().getAttributes().hasAttrSomewhere( Attribute::SwiftError)) return CSR_SystemZ_SwiftError_RegMask; return CSR_SystemZ_RegMask; } BitVector SystemZRegisterInfo::getReservedRegs(const MachineFunction &MF) const { BitVector Reserved(getNumRegs()); const SystemZFrameLowering *TFI = getFrameLowering(MF); if (TFI->hasFP(MF)) { // R11D is the frame pointer. Reserve all aliases. Reserved.set(SystemZ::R11D); Reserved.set(SystemZ::R11L); Reserved.set(SystemZ::R11H); Reserved.set(SystemZ::R10Q); } // R15D is the stack pointer. Reserve all aliases. Reserved.set(SystemZ::R15D); Reserved.set(SystemZ::R15L); Reserved.set(SystemZ::R15H); Reserved.set(SystemZ::R14Q); // A0 and A1 hold the thread pointer. Reserved.set(SystemZ::A0); Reserved.set(SystemZ::A1); return Reserved; } void SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj, unsigned FIOperandNum, RegScavenger *RS) const { assert(SPAdj == 0 && "Outgoing arguments should be part of the frame"); MachineBasicBlock &MBB = *MI->getParent(); MachineFunction &MF = *MBB.getParent(); auto *TII = static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo()); const SystemZFrameLowering *TFI = getFrameLowering(MF); DebugLoc DL = MI->getDebugLoc(); // Decompose the frame index into a base and offset. int FrameIndex = MI->getOperand(FIOperandNum).getIndex(); unsigned BasePtr; int64_t Offset = (TFI->getFrameIndexReference(MF, FrameIndex, BasePtr) + MI->getOperand(FIOperandNum + 1).getImm()); // Special handling of dbg_value instructions. if (MI->isDebugValue()) { MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, /*isDef*/ false); MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); return; } // See if the offset is in range, or if an equivalent instruction that // accepts the offset exists. unsigned Opcode = MI->getOpcode(); unsigned OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset); if (OpcodeForOffset) { if (OpcodeForOffset == SystemZ::LE && MF.getSubtarget<SystemZSubtarget>().hasVector()) { // If LE is ok for offset, use LDE instead on z13. OpcodeForOffset = SystemZ::LDE32; } MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false); } else { // Create an anchor point that is in range. Start at 0xffff so that // can use LLILH to load the immediate. int64_t OldOffset = Offset; int64_t Mask = 0xffff; do { Offset = OldOffset & Mask; OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset); Mask >>= 1; assert(Mask && "One offset must be OK"); } while (!OpcodeForOffset); unsigned ScratchReg = MF.getRegInfo().createVirtualRegister(&SystemZ::ADDR64BitRegClass); int64_t HighOffset = OldOffset - Offset; if (MI->getDesc().TSFlags & SystemZII::HasIndex && MI->getOperand(FIOperandNum + 2).getReg() == 0) { // Load the offset into the scratch register and use it as an index. // The scratch register then dies here. TII->loadImmediate(MBB, MI, ScratchReg, HighOffset); MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false); MI->getOperand(FIOperandNum + 2).ChangeToRegister(ScratchReg, false, false, true); } else { // Load the anchor address into a scratch register. unsigned LAOpcode = TII->getOpcodeForOffset(SystemZ::LA, HighOffset); if (LAOpcode) BuildMI(MBB, MI, DL, TII->get(LAOpcode),ScratchReg) .addReg(BasePtr).addImm(HighOffset).addReg(0); else { // Load the high offset into the scratch register and use it as // an index. TII->loadImmediate(MBB, MI, ScratchReg, HighOffset); BuildMI(MBB, MI, DL, TII->get(SystemZ::AGR),ScratchReg) .addReg(ScratchReg, RegState::Kill).addReg(BasePtr); } // Use the scratch register as the base. It then dies here. MI->getOperand(FIOperandNum).ChangeToRegister(ScratchReg, false, false, true); } } MI->setDesc(TII->get(OpcodeForOffset)); MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); } bool SystemZRegisterInfo::shouldCoalesce(MachineInstr *MI, const TargetRegisterClass *SrcRC, unsigned SubReg, const TargetRegisterClass *DstRC, unsigned DstSubReg, const TargetRegisterClass *NewRC, LiveIntervals &LIS) const { assert (MI->isCopy() && "Only expecting COPY instructions"); // Coalesce anything which is not a COPY involving a subreg to/from GR128. if (!(NewRC->hasSuperClassEq(&SystemZ::GR128BitRegClass) && (getRegSizeInBits(*SrcRC) <= 64 || getRegSizeInBits(*DstRC) <= 64))) return true; // Allow coalescing of a GR128 subreg COPY only if the live ranges are small // and local to one MBB with not too much interferring registers. Otherwise // regalloc may run out of registers. unsigned WideOpNo = (getRegSizeInBits(*SrcRC) == 128 ? 1 : 0); unsigned GR128Reg = MI->getOperand(WideOpNo).getReg(); unsigned GRNarReg = MI->getOperand((WideOpNo == 1) ? 0 : 1).getReg(); LiveInterval &IntGR128 = LIS.getInterval(GR128Reg); LiveInterval &IntGRNar = LIS.getInterval(GRNarReg); // Check that the two virtual registers are local to MBB. MachineBasicBlock *MBB = MI->getParent(); if (LIS.isLiveInToMBB(IntGR128, MBB) || LIS.isLiveOutOfMBB(IntGR128, MBB) || LIS.isLiveInToMBB(IntGRNar, MBB) || LIS.isLiveOutOfMBB(IntGRNar, MBB)) return false; // Find the first and last MIs of the registers. MachineInstr *FirstMI = nullptr, *LastMI = nullptr; if (WideOpNo == 1) { FirstMI = LIS.getInstructionFromIndex(IntGR128.beginIndex()); LastMI = LIS.getInstructionFromIndex(IntGRNar.endIndex()); } else { FirstMI = LIS.getInstructionFromIndex(IntGRNar.beginIndex()); LastMI = LIS.getInstructionFromIndex(IntGR128.endIndex()); } assert (FirstMI && LastMI && "No instruction from index?"); // Check if coalescing seems safe by finding the set of clobbered physreg // pairs in the region. BitVector PhysClobbered(getNumRegs()); MachineBasicBlock::iterator MII = FirstMI, MEE = LastMI; MEE++; for (; MII != MEE; ++MII) { for (const MachineOperand &MO : MII->operands()) if (MO.isReg() && isPhysicalRegister(MO.getReg())) { for (MCSuperRegIterator SI(MO.getReg(), this, true/*IncludeSelf*/); SI.isValid(); ++SI) if (NewRC->contains(*SI)) { PhysClobbered.set(*SI); break; } } } // Demand an arbitrary margin of free regs. unsigned const DemandedFreeGR128 = 3; if (PhysClobbered.count() > (NewRC->getNumRegs() - DemandedFreeGR128)) return false; return true; } unsigned SystemZRegisterInfo::getFrameRegister(const MachineFunction &MF) const { const SystemZFrameLowering *TFI = getFrameLowering(MF); return TFI->hasFP(MF) ? SystemZ::R11D : SystemZ::R15D; } const TargetRegisterClass * SystemZRegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const { if (RC == &SystemZ::CCRRegClass) return &SystemZ::GR32BitRegClass; return RC; }