10b57cec5SDimitry Andric //===-- SystemZRegisterInfo.cpp - SystemZ register information ------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "SystemZRegisterInfo.h" 100b57cec5SDimitry Andric #include "SystemZInstrInfo.h" 110b57cec5SDimitry Andric #include "SystemZSubtarget.h" 120b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h" 13fe6060f1SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h" 140b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 150b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 160b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h" 170b57cec5SDimitry Andric #include "llvm/CodeGen/VirtRegMap.h" 18fe6060f1SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric using namespace llvm; 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric #define GET_REGINFO_TARGET_DESC 230b57cec5SDimitry Andric #include "SystemZGenRegisterInfo.inc" 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric // Given that MO is a GRX32 operand, return either GR32 or GRH32 if MO 260b57cec5SDimitry Andric // somehow belongs in it. Otherwise, return GRX32. 270b57cec5SDimitry Andric static const TargetRegisterClass *getRC32(MachineOperand &MO, 280b57cec5SDimitry Andric const VirtRegMap *VRM, 290b57cec5SDimitry Andric const MachineRegisterInfo *MRI) { 300b57cec5SDimitry Andric const TargetRegisterClass *RC = MRI->getRegClass(MO.getReg()); 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric if (SystemZ::GR32BitRegClass.hasSubClassEq(RC) || 330b57cec5SDimitry Andric MO.getSubReg() == SystemZ::subreg_l32 || 340b57cec5SDimitry Andric MO.getSubReg() == SystemZ::subreg_hl32) 350b57cec5SDimitry Andric return &SystemZ::GR32BitRegClass; 360b57cec5SDimitry Andric if (SystemZ::GRH32BitRegClass.hasSubClassEq(RC) || 370b57cec5SDimitry Andric MO.getSubReg() == SystemZ::subreg_h32 || 380b57cec5SDimitry Andric MO.getSubReg() == SystemZ::subreg_hh32) 390b57cec5SDimitry Andric return &SystemZ::GRH32BitRegClass; 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric if (VRM && VRM->hasPhys(MO.getReg())) { 428bcb0991SDimitry Andric Register PhysReg = VRM->getPhys(MO.getReg()); 430b57cec5SDimitry Andric if (SystemZ::GR32BitRegClass.contains(PhysReg)) 440b57cec5SDimitry Andric return &SystemZ::GR32BitRegClass; 450b57cec5SDimitry Andric assert (SystemZ::GRH32BitRegClass.contains(PhysReg) && 460b57cec5SDimitry Andric "Phys reg not in GR32 or GRH32?"); 470b57cec5SDimitry Andric return &SystemZ::GRH32BitRegClass; 480b57cec5SDimitry Andric } 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric assert (RC == &SystemZ::GRX32BitRegClass); 510b57cec5SDimitry Andric return RC; 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric // Pass the registers of RC as hints while making sure that if any of these 550b57cec5SDimitry Andric // registers are copy hints (and therefore already in Hints), hint them 560b57cec5SDimitry Andric // first. 570b57cec5SDimitry Andric static void addHints(ArrayRef<MCPhysReg> Order, 580b57cec5SDimitry Andric SmallVectorImpl<MCPhysReg> &Hints, 590b57cec5SDimitry Andric const TargetRegisterClass *RC, 600b57cec5SDimitry Andric const MachineRegisterInfo *MRI) { 610b57cec5SDimitry Andric SmallSet<unsigned, 4> CopyHints; 620b57cec5SDimitry Andric CopyHints.insert(Hints.begin(), Hints.end()); 630b57cec5SDimitry Andric Hints.clear(); 640b57cec5SDimitry Andric for (MCPhysReg Reg : Order) 650b57cec5SDimitry Andric if (CopyHints.count(Reg) && 660b57cec5SDimitry Andric RC->contains(Reg) && !MRI->isReserved(Reg)) 670b57cec5SDimitry Andric Hints.push_back(Reg); 680b57cec5SDimitry Andric for (MCPhysReg Reg : Order) 690b57cec5SDimitry Andric if (!CopyHints.count(Reg) && 700b57cec5SDimitry Andric RC->contains(Reg) && !MRI->isReserved(Reg)) 710b57cec5SDimitry Andric Hints.push_back(Reg); 720b57cec5SDimitry Andric } 730b57cec5SDimitry Andric 745ffd83dbSDimitry Andric bool SystemZRegisterInfo::getRegAllocationHints( 755ffd83dbSDimitry Andric Register VirtReg, ArrayRef<MCPhysReg> Order, 765ffd83dbSDimitry Andric SmallVectorImpl<MCPhysReg> &Hints, const MachineFunction &MF, 775ffd83dbSDimitry Andric const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const { 780b57cec5SDimitry Andric const MachineRegisterInfo *MRI = &MF.getRegInfo(); 790b57cec5SDimitry Andric const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>(); 800b57cec5SDimitry Andric const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric bool BaseImplRetVal = TargetRegisterInfo::getRegAllocationHints( 830b57cec5SDimitry Andric VirtReg, Order, Hints, MF, VRM, Matrix); 840b57cec5SDimitry Andric 85480093f4SDimitry Andric if (VRM != nullptr) { 86480093f4SDimitry Andric // Add any two address hints after any copy hints. 87480093f4SDimitry Andric SmallSet<unsigned, 4> TwoAddrHints; 88480093f4SDimitry Andric for (auto &Use : MRI->reg_nodbg_instructions(VirtReg)) 89480093f4SDimitry Andric if (SystemZ::getTwoOperandOpcode(Use.getOpcode()) != -1) { 90480093f4SDimitry Andric const MachineOperand *VRRegMO = nullptr; 91480093f4SDimitry Andric const MachineOperand *OtherMO = nullptr; 92480093f4SDimitry Andric const MachineOperand *CommuMO = nullptr; 93480093f4SDimitry Andric if (VirtReg == Use.getOperand(0).getReg()) { 94480093f4SDimitry Andric VRRegMO = &Use.getOperand(0); 95480093f4SDimitry Andric OtherMO = &Use.getOperand(1); 96480093f4SDimitry Andric if (Use.isCommutable()) 97480093f4SDimitry Andric CommuMO = &Use.getOperand(2); 98480093f4SDimitry Andric } else if (VirtReg == Use.getOperand(1).getReg()) { 99480093f4SDimitry Andric VRRegMO = &Use.getOperand(1); 100480093f4SDimitry Andric OtherMO = &Use.getOperand(0); 101480093f4SDimitry Andric } else if (VirtReg == Use.getOperand(2).getReg() && 102480093f4SDimitry Andric Use.isCommutable()) { 103480093f4SDimitry Andric VRRegMO = &Use.getOperand(2); 104480093f4SDimitry Andric OtherMO = &Use.getOperand(0); 105480093f4SDimitry Andric } else 106480093f4SDimitry Andric continue; 107480093f4SDimitry Andric 108480093f4SDimitry Andric auto tryAddHint = [&](const MachineOperand *MO) -> void { 109480093f4SDimitry Andric Register Reg = MO->getReg(); 110e8d8bef9SDimitry Andric Register PhysReg = Register::isPhysicalRegister(Reg) 111e8d8bef9SDimitry Andric ? Reg 112e8d8bef9SDimitry Andric : Register(VRM->getPhys(Reg)); 113480093f4SDimitry Andric if (PhysReg) { 114480093f4SDimitry Andric if (MO->getSubReg()) 115480093f4SDimitry Andric PhysReg = getSubReg(PhysReg, MO->getSubReg()); 116480093f4SDimitry Andric if (VRRegMO->getSubReg()) 117480093f4SDimitry Andric PhysReg = getMatchingSuperReg(PhysReg, VRRegMO->getSubReg(), 118480093f4SDimitry Andric MRI->getRegClass(VirtReg)); 119480093f4SDimitry Andric if (!MRI->isReserved(PhysReg) && !is_contained(Hints, PhysReg)) 120480093f4SDimitry Andric TwoAddrHints.insert(PhysReg); 121480093f4SDimitry Andric } 122480093f4SDimitry Andric }; 123480093f4SDimitry Andric tryAddHint(OtherMO); 124480093f4SDimitry Andric if (CommuMO) 125480093f4SDimitry Andric tryAddHint(CommuMO); 126480093f4SDimitry Andric } 127480093f4SDimitry Andric for (MCPhysReg OrderReg : Order) 128480093f4SDimitry Andric if (TwoAddrHints.count(OrderReg)) 129480093f4SDimitry Andric Hints.push_back(OrderReg); 130480093f4SDimitry Andric } 131480093f4SDimitry Andric 1320b57cec5SDimitry Andric if (MRI->getRegClass(VirtReg) == &SystemZ::GRX32BitRegClass) { 1335ffd83dbSDimitry Andric SmallVector<Register, 8> Worklist; 1345ffd83dbSDimitry Andric SmallSet<Register, 4> DoneRegs; 1350b57cec5SDimitry Andric Worklist.push_back(VirtReg); 1360b57cec5SDimitry Andric while (Worklist.size()) { 1375ffd83dbSDimitry Andric Register Reg = Worklist.pop_back_val(); 1380b57cec5SDimitry Andric if (!DoneRegs.insert(Reg).second) 1390b57cec5SDimitry Andric continue; 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric for (auto &Use : MRI->reg_instructions(Reg)) { 1420b57cec5SDimitry Andric // For LOCRMux, see if the other operand is already a high or low 1430b57cec5SDimitry Andric // register, and in that case give the corresponding hints for 1440b57cec5SDimitry Andric // VirtReg. LOCR instructions need both operands in either high or 1450b57cec5SDimitry Andric // low parts. Same handling for SELRMux. 1460b57cec5SDimitry Andric if (Use.getOpcode() == SystemZ::LOCRMux || 1470b57cec5SDimitry Andric Use.getOpcode() == SystemZ::SELRMux) { 1480b57cec5SDimitry Andric MachineOperand &TrueMO = Use.getOperand(1); 1490b57cec5SDimitry Andric MachineOperand &FalseMO = Use.getOperand(2); 1500b57cec5SDimitry Andric const TargetRegisterClass *RC = 1510b57cec5SDimitry Andric TRI->getCommonSubClass(getRC32(FalseMO, VRM, MRI), 1520b57cec5SDimitry Andric getRC32(TrueMO, VRM, MRI)); 1530b57cec5SDimitry Andric if (Use.getOpcode() == SystemZ::SELRMux) 1540b57cec5SDimitry Andric RC = TRI->getCommonSubClass(RC, 1550b57cec5SDimitry Andric getRC32(Use.getOperand(0), VRM, MRI)); 1560b57cec5SDimitry Andric if (RC && RC != &SystemZ::GRX32BitRegClass) { 1570b57cec5SDimitry Andric addHints(Order, Hints, RC, MRI); 1580b57cec5SDimitry Andric // Return true to make these hints the only regs available to 1590b57cec5SDimitry Andric // RA. This may mean extra spilling but since the alternative is 1600b57cec5SDimitry Andric // a jump sequence expansion of the LOCRMux, it is preferred. 1610b57cec5SDimitry Andric return true; 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric // Add the other operand of the LOCRMux to the worklist. 1658bcb0991SDimitry Andric Register OtherReg = 1660b57cec5SDimitry Andric (TrueMO.getReg() == Reg ? FalseMO.getReg() : TrueMO.getReg()); 1670b57cec5SDimitry Andric if (MRI->getRegClass(OtherReg) == &SystemZ::GRX32BitRegClass) 1680b57cec5SDimitry Andric Worklist.push_back(OtherReg); 1690b57cec5SDimitry Andric } // end LOCRMux 1700b57cec5SDimitry Andric else if (Use.getOpcode() == SystemZ::CHIMux || 1710b57cec5SDimitry Andric Use.getOpcode() == SystemZ::CFIMux) { 1720b57cec5SDimitry Andric if (Use.getOperand(1).getImm() == 0) { 1730b57cec5SDimitry Andric bool OnlyLMuxes = true; 1740b57cec5SDimitry Andric for (MachineInstr &DefMI : MRI->def_instructions(VirtReg)) 1750b57cec5SDimitry Andric if (DefMI.getOpcode() != SystemZ::LMux) 1760b57cec5SDimitry Andric OnlyLMuxes = false; 1770b57cec5SDimitry Andric if (OnlyLMuxes) { 1780b57cec5SDimitry Andric addHints(Order, Hints, &SystemZ::GR32BitRegClass, MRI); 1790b57cec5SDimitry Andric // Return false to make these hints preferred but not obligatory. 1800b57cec5SDimitry Andric return false; 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric } // end CHIMux / CFIMux 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric return BaseImplRetVal; 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric const MCPhysReg * 192fe6060f1SDimitry Andric SystemZXPLINK64Registers::getCalleeSavedRegs(const MachineFunction *MF) const { 193*349cc55cSDimitry Andric const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>(); 194*349cc55cSDimitry Andric return Subtarget.hasVector() ? CSR_SystemZ_XPLINK64_Vector_SaveList 195*349cc55cSDimitry Andric : CSR_SystemZ_XPLINK64_SaveList; 196fe6060f1SDimitry Andric } 197fe6060f1SDimitry Andric 198fe6060f1SDimitry Andric const MCPhysReg * 199fe6060f1SDimitry Andric SystemZELFRegisters::getCalleeSavedRegs(const MachineFunction *MF) const { 2000b57cec5SDimitry Andric const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>(); 201480093f4SDimitry Andric if (MF->getFunction().getCallingConv() == CallingConv::GHC) 202480093f4SDimitry Andric return CSR_SystemZ_NoRegs_SaveList; 2030b57cec5SDimitry Andric if (MF->getFunction().getCallingConv() == CallingConv::AnyReg) 2040b57cec5SDimitry Andric return Subtarget.hasVector()? CSR_SystemZ_AllRegs_Vector_SaveList 2050b57cec5SDimitry Andric : CSR_SystemZ_AllRegs_SaveList; 2060b57cec5SDimitry Andric if (MF->getSubtarget().getTargetLowering()->supportSwiftError() && 2070b57cec5SDimitry Andric MF->getFunction().getAttributes().hasAttrSomewhere( 2080b57cec5SDimitry Andric Attribute::SwiftError)) 2090b57cec5SDimitry Andric return CSR_SystemZ_SwiftError_SaveList; 210fe6060f1SDimitry Andric return CSR_SystemZ_ELF_SaveList; 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric const uint32_t * 214fe6060f1SDimitry Andric SystemZXPLINK64Registers::getCallPreservedMask(const MachineFunction &MF, 215fe6060f1SDimitry Andric CallingConv::ID CC) const { 216*349cc55cSDimitry Andric const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>(); 217*349cc55cSDimitry Andric return Subtarget.hasVector() ? CSR_SystemZ_XPLINK64_Vector_RegMask 218*349cc55cSDimitry Andric : CSR_SystemZ_XPLINK64_RegMask; 219fe6060f1SDimitry Andric } 220fe6060f1SDimitry Andric 221fe6060f1SDimitry Andric const uint32_t * 222fe6060f1SDimitry Andric SystemZELFRegisters::getCallPreservedMask(const MachineFunction &MF, 2230b57cec5SDimitry Andric CallingConv::ID CC) const { 2240b57cec5SDimitry Andric const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>(); 225480093f4SDimitry Andric if (CC == CallingConv::GHC) 226480093f4SDimitry Andric return CSR_SystemZ_NoRegs_RegMask; 2270b57cec5SDimitry Andric if (CC == CallingConv::AnyReg) 2280b57cec5SDimitry Andric return Subtarget.hasVector()? CSR_SystemZ_AllRegs_Vector_RegMask 2290b57cec5SDimitry Andric : CSR_SystemZ_AllRegs_RegMask; 2300b57cec5SDimitry Andric if (MF.getSubtarget().getTargetLowering()->supportSwiftError() && 2310b57cec5SDimitry Andric MF.getFunction().getAttributes().hasAttrSomewhere( 2320b57cec5SDimitry Andric Attribute::SwiftError)) 2330b57cec5SDimitry Andric return CSR_SystemZ_SwiftError_RegMask; 234fe6060f1SDimitry Andric return CSR_SystemZ_ELF_RegMask; 235fe6060f1SDimitry Andric } 236fe6060f1SDimitry Andric 237fe6060f1SDimitry Andric SystemZRegisterInfo::SystemZRegisterInfo(unsigned int RA) 238fe6060f1SDimitry Andric : SystemZGenRegisterInfo(RA) {} 239fe6060f1SDimitry Andric 240fe6060f1SDimitry Andric const MCPhysReg * 241fe6060f1SDimitry Andric SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { 242fe6060f1SDimitry Andric 243fe6060f1SDimitry Andric const SystemZSubtarget *Subtarget = &MF->getSubtarget<SystemZSubtarget>(); 244fe6060f1SDimitry Andric SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters(); 245fe6060f1SDimitry Andric 246fe6060f1SDimitry Andric return Regs->getCalleeSavedRegs(MF); 247fe6060f1SDimitry Andric } 248fe6060f1SDimitry Andric 249fe6060f1SDimitry Andric const uint32_t * 250fe6060f1SDimitry Andric SystemZRegisterInfo::getCallPreservedMask(const MachineFunction &MF, 251fe6060f1SDimitry Andric CallingConv::ID CC) const { 252fe6060f1SDimitry Andric 253fe6060f1SDimitry Andric const SystemZSubtarget *Subtarget = &MF.getSubtarget<SystemZSubtarget>(); 254fe6060f1SDimitry Andric SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters(); 255fe6060f1SDimitry Andric return Regs->getCallPreservedMask(MF, CC); 2560b57cec5SDimitry Andric } 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric BitVector 2590b57cec5SDimitry Andric SystemZRegisterInfo::getReservedRegs(const MachineFunction &MF) const { 2600b57cec5SDimitry Andric BitVector Reserved(getNumRegs()); 2610b57cec5SDimitry Andric const SystemZFrameLowering *TFI = getFrameLowering(MF); 262fe6060f1SDimitry Andric const SystemZSubtarget *Subtarget = &MF.getSubtarget<SystemZSubtarget>(); 263fe6060f1SDimitry Andric SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters(); 264fe6060f1SDimitry Andric if (TFI->hasFP(MF)) 265fe6060f1SDimitry Andric // The frame pointer. Reserve all aliases. 266fe6060f1SDimitry Andric for (MCRegAliasIterator AI(Regs->getFramePointerRegister(), this, true); 267fe6060f1SDimitry Andric AI.isValid(); ++AI) 268fe6060f1SDimitry Andric Reserved.set(*AI); 2690b57cec5SDimitry Andric 270fe6060f1SDimitry Andric // Reserve all aliases for the stack pointer. 271fe6060f1SDimitry Andric for (MCRegAliasIterator AI(Regs->getStackPointerRegister(), this, true); 272fe6060f1SDimitry Andric AI.isValid(); ++AI) 273fe6060f1SDimitry Andric Reserved.set(*AI); 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric // A0 and A1 hold the thread pointer. 2760b57cec5SDimitry Andric Reserved.set(SystemZ::A0); 2770b57cec5SDimitry Andric Reserved.set(SystemZ::A1); 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric // FPC is the floating-point control register. 2800b57cec5SDimitry Andric Reserved.set(SystemZ::FPC); 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric return Reserved; 2830b57cec5SDimitry Andric } 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric void 2860b57cec5SDimitry Andric SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI, 2870b57cec5SDimitry Andric int SPAdj, unsigned FIOperandNum, 2880b57cec5SDimitry Andric RegScavenger *RS) const { 2890b57cec5SDimitry Andric assert(SPAdj == 0 && "Outgoing arguments should be part of the frame"); 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric MachineBasicBlock &MBB = *MI->getParent(); 2920b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 2930b57cec5SDimitry Andric auto *TII = 2940b57cec5SDimitry Andric static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo()); 2950b57cec5SDimitry Andric const SystemZFrameLowering *TFI = getFrameLowering(MF); 2960b57cec5SDimitry Andric DebugLoc DL = MI->getDebugLoc(); 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric // Decompose the frame index into a base and offset. 2990b57cec5SDimitry Andric int FrameIndex = MI->getOperand(FIOperandNum).getIndex(); 3005ffd83dbSDimitry Andric Register BasePtr; 301e8d8bef9SDimitry Andric int64_t Offset = 302e8d8bef9SDimitry Andric (TFI->getFrameIndexReference(MF, FrameIndex, BasePtr).getFixed() + 3030b57cec5SDimitry Andric MI->getOperand(FIOperandNum + 1).getImm()); 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric // Special handling of dbg_value instructions. 3060b57cec5SDimitry Andric if (MI->isDebugValue()) { 3070b57cec5SDimitry Andric MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, /*isDef*/ false); 308fe6060f1SDimitry Andric if (MI->isNonListDebugValue()) { 3095ffd83dbSDimitry Andric MI->getDebugOffset().ChangeToImmediate(Offset); 310fe6060f1SDimitry Andric } else { 311fe6060f1SDimitry Andric unsigned OpIdx = MI->getDebugOperandIndex(&MI->getOperand(FIOperandNum)); 312fe6060f1SDimitry Andric SmallVector<uint64_t, 3> Ops; 313fe6060f1SDimitry Andric DIExpression::appendOffset( 314fe6060f1SDimitry Andric Ops, TFI->getFrameIndexReference(MF, FrameIndex, BasePtr).getFixed()); 315fe6060f1SDimitry Andric MI->getDebugExpressionOp().setMetadata( 316fe6060f1SDimitry Andric DIExpression::appendOpsToArg(MI->getDebugExpression(), Ops, OpIdx)); 317fe6060f1SDimitry Andric } 3180b57cec5SDimitry Andric return; 3190b57cec5SDimitry Andric } 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric // See if the offset is in range, or if an equivalent instruction that 3220b57cec5SDimitry Andric // accepts the offset exists. 3230b57cec5SDimitry Andric unsigned Opcode = MI->getOpcode(); 3240b57cec5SDimitry Andric unsigned OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset); 3250b57cec5SDimitry Andric if (OpcodeForOffset) { 3260b57cec5SDimitry Andric if (OpcodeForOffset == SystemZ::LE && 3270b57cec5SDimitry Andric MF.getSubtarget<SystemZSubtarget>().hasVector()) { 3280b57cec5SDimitry Andric // If LE is ok for offset, use LDE instead on z13. 3290b57cec5SDimitry Andric OpcodeForOffset = SystemZ::LDE32; 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false); 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric else { 3340b57cec5SDimitry Andric // Create an anchor point that is in range. Start at 0xffff so that 3350b57cec5SDimitry Andric // can use LLILH to load the immediate. 3360b57cec5SDimitry Andric int64_t OldOffset = Offset; 3370b57cec5SDimitry Andric int64_t Mask = 0xffff; 3380b57cec5SDimitry Andric do { 3390b57cec5SDimitry Andric Offset = OldOffset & Mask; 3400b57cec5SDimitry Andric OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset); 3410b57cec5SDimitry Andric Mask >>= 1; 3420b57cec5SDimitry Andric assert(Mask && "One offset must be OK"); 3430b57cec5SDimitry Andric } while (!OpcodeForOffset); 3440b57cec5SDimitry Andric 3458bcb0991SDimitry Andric Register ScratchReg = 3460b57cec5SDimitry Andric MF.getRegInfo().createVirtualRegister(&SystemZ::ADDR64BitRegClass); 3470b57cec5SDimitry Andric int64_t HighOffset = OldOffset - Offset; 3480b57cec5SDimitry Andric 3490b57cec5SDimitry Andric if (MI->getDesc().TSFlags & SystemZII::HasIndex 3500b57cec5SDimitry Andric && MI->getOperand(FIOperandNum + 2).getReg() == 0) { 3510b57cec5SDimitry Andric // Load the offset into the scratch register and use it as an index. 3520b57cec5SDimitry Andric // The scratch register then dies here. 3530b57cec5SDimitry Andric TII->loadImmediate(MBB, MI, ScratchReg, HighOffset); 3540b57cec5SDimitry Andric MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false); 3550b57cec5SDimitry Andric MI->getOperand(FIOperandNum + 2).ChangeToRegister(ScratchReg, 3560b57cec5SDimitry Andric false, false, true); 3570b57cec5SDimitry Andric } else { 3580b57cec5SDimitry Andric // Load the anchor address into a scratch register. 3590b57cec5SDimitry Andric unsigned LAOpcode = TII->getOpcodeForOffset(SystemZ::LA, HighOffset); 3600b57cec5SDimitry Andric if (LAOpcode) 3610b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII->get(LAOpcode),ScratchReg) 3620b57cec5SDimitry Andric .addReg(BasePtr).addImm(HighOffset).addReg(0); 3630b57cec5SDimitry Andric else { 3640b57cec5SDimitry Andric // Load the high offset into the scratch register and use it as 3650b57cec5SDimitry Andric // an index. 3660b57cec5SDimitry Andric TII->loadImmediate(MBB, MI, ScratchReg, HighOffset); 367e8d8bef9SDimitry Andric BuildMI(MBB, MI, DL, TII->get(SystemZ::LA), ScratchReg) 368e8d8bef9SDimitry Andric .addReg(BasePtr, RegState::Kill).addImm(0).addReg(ScratchReg); 3690b57cec5SDimitry Andric } 3700b57cec5SDimitry Andric 3710b57cec5SDimitry Andric // Use the scratch register as the base. It then dies here. 3720b57cec5SDimitry Andric MI->getOperand(FIOperandNum).ChangeToRegister(ScratchReg, 3730b57cec5SDimitry Andric false, false, true); 3740b57cec5SDimitry Andric } 3750b57cec5SDimitry Andric } 3760b57cec5SDimitry Andric MI->setDesc(TII->get(OpcodeForOffset)); 3770b57cec5SDimitry Andric MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric bool SystemZRegisterInfo::shouldCoalesce(MachineInstr *MI, 3810b57cec5SDimitry Andric const TargetRegisterClass *SrcRC, 3820b57cec5SDimitry Andric unsigned SubReg, 3830b57cec5SDimitry Andric const TargetRegisterClass *DstRC, 3840b57cec5SDimitry Andric unsigned DstSubReg, 3850b57cec5SDimitry Andric const TargetRegisterClass *NewRC, 3860b57cec5SDimitry Andric LiveIntervals &LIS) const { 3870b57cec5SDimitry Andric assert (MI->isCopy() && "Only expecting COPY instructions"); 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric // Coalesce anything which is not a COPY involving a subreg to/from GR128. 3900b57cec5SDimitry Andric if (!(NewRC->hasSuperClassEq(&SystemZ::GR128BitRegClass) && 3910b57cec5SDimitry Andric (getRegSizeInBits(*SrcRC) <= 64 || getRegSizeInBits(*DstRC) <= 64))) 3920b57cec5SDimitry Andric return true; 3930b57cec5SDimitry Andric 3940b57cec5SDimitry Andric // Allow coalescing of a GR128 subreg COPY only if the live ranges are small 3950b57cec5SDimitry Andric // and local to one MBB with not too much interferring registers. Otherwise 3960b57cec5SDimitry Andric // regalloc may run out of registers. 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric unsigned WideOpNo = (getRegSizeInBits(*SrcRC) == 128 ? 1 : 0); 3998bcb0991SDimitry Andric Register GR128Reg = MI->getOperand(WideOpNo).getReg(); 4008bcb0991SDimitry Andric Register GRNarReg = MI->getOperand((WideOpNo == 1) ? 0 : 1).getReg(); 4010b57cec5SDimitry Andric LiveInterval &IntGR128 = LIS.getInterval(GR128Reg); 4020b57cec5SDimitry Andric LiveInterval &IntGRNar = LIS.getInterval(GRNarReg); 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric // Check that the two virtual registers are local to MBB. 4050b57cec5SDimitry Andric MachineBasicBlock *MBB = MI->getParent(); 4060b57cec5SDimitry Andric MachineInstr *FirstMI_GR128 = 4070b57cec5SDimitry Andric LIS.getInstructionFromIndex(IntGR128.beginIndex()); 4080b57cec5SDimitry Andric MachineInstr *FirstMI_GRNar = 4090b57cec5SDimitry Andric LIS.getInstructionFromIndex(IntGRNar.beginIndex()); 4100b57cec5SDimitry Andric MachineInstr *LastMI_GR128 = LIS.getInstructionFromIndex(IntGR128.endIndex()); 4110b57cec5SDimitry Andric MachineInstr *LastMI_GRNar = LIS.getInstructionFromIndex(IntGRNar.endIndex()); 4120b57cec5SDimitry Andric if ((!FirstMI_GR128 || FirstMI_GR128->getParent() != MBB) || 4130b57cec5SDimitry Andric (!FirstMI_GRNar || FirstMI_GRNar->getParent() != MBB) || 4140b57cec5SDimitry Andric (!LastMI_GR128 || LastMI_GR128->getParent() != MBB) || 4150b57cec5SDimitry Andric (!LastMI_GRNar || LastMI_GRNar->getParent() != MBB)) 4160b57cec5SDimitry Andric return false; 4170b57cec5SDimitry Andric 4180b57cec5SDimitry Andric MachineBasicBlock::iterator MII = nullptr, MEE = nullptr; 4190b57cec5SDimitry Andric if (WideOpNo == 1) { 4200b57cec5SDimitry Andric MII = FirstMI_GR128; 4210b57cec5SDimitry Andric MEE = LastMI_GRNar; 4220b57cec5SDimitry Andric } else { 4230b57cec5SDimitry Andric MII = FirstMI_GRNar; 4240b57cec5SDimitry Andric MEE = LastMI_GR128; 4250b57cec5SDimitry Andric } 4260b57cec5SDimitry Andric 4270b57cec5SDimitry Andric // Check if coalescing seems safe by finding the set of clobbered physreg 4280b57cec5SDimitry Andric // pairs in the region. 4290b57cec5SDimitry Andric BitVector PhysClobbered(getNumRegs()); 4300b57cec5SDimitry Andric MEE++; 4310b57cec5SDimitry Andric for (; MII != MEE; ++MII) { 4320b57cec5SDimitry Andric for (const MachineOperand &MO : MII->operands()) 4338bcb0991SDimitry Andric if (MO.isReg() && Register::isPhysicalRegister(MO.getReg())) { 4340b57cec5SDimitry Andric for (MCSuperRegIterator SI(MO.getReg(), this, true/*IncludeSelf*/); 4350b57cec5SDimitry Andric SI.isValid(); ++SI) 4360b57cec5SDimitry Andric if (NewRC->contains(*SI)) { 4370b57cec5SDimitry Andric PhysClobbered.set(*SI); 4380b57cec5SDimitry Andric break; 4390b57cec5SDimitry Andric } 4400b57cec5SDimitry Andric } 4410b57cec5SDimitry Andric } 4420b57cec5SDimitry Andric 4430b57cec5SDimitry Andric // Demand an arbitrary margin of free regs. 4440b57cec5SDimitry Andric unsigned const DemandedFreeGR128 = 3; 4450b57cec5SDimitry Andric if (PhysClobbered.count() > (NewRC->getNumRegs() - DemandedFreeGR128)) 4460b57cec5SDimitry Andric return false; 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric return true; 4490b57cec5SDimitry Andric } 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric Register 4520b57cec5SDimitry Andric SystemZRegisterInfo::getFrameRegister(const MachineFunction &MF) const { 4530b57cec5SDimitry Andric const SystemZFrameLowering *TFI = getFrameLowering(MF); 454fe6060f1SDimitry Andric const SystemZSubtarget *Subtarget = &MF.getSubtarget<SystemZSubtarget>(); 455fe6060f1SDimitry Andric SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters(); 456fe6060f1SDimitry Andric 457fe6060f1SDimitry Andric return TFI->hasFP(MF) ? Regs->getFramePointerRegister() 458fe6060f1SDimitry Andric : Regs->getStackPointerRegister(); 4590b57cec5SDimitry Andric } 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric const TargetRegisterClass * 4620b57cec5SDimitry Andric SystemZRegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const { 4630b57cec5SDimitry Andric if (RC == &SystemZ::CCRRegClass) 4640b57cec5SDimitry Andric return &SystemZ::GR32BitRegClass; 4650b57cec5SDimitry Andric return RC; 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric 468