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) || 3306c3fb27SDimitry Andric MO.getSubReg() == SystemZ::subreg_ll32 || 3406c3fb27SDimitry Andric MO.getSubReg() == SystemZ::subreg_l32) 350b57cec5SDimitry Andric return &SystemZ::GR32BitRegClass; 360b57cec5SDimitry Andric if (SystemZ::GRH32BitRegClass.hasSubClassEq(RC) || 3706c3fb27SDimitry Andric MO.getSubReg() == SystemZ::subreg_lh32 || 3806c3fb27SDimitry Andric MO.getSubReg() == SystemZ::subreg_h32) 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(); 110bdd1243dSDimitry Andric Register PhysReg = 111bdd1243dSDimitry Andric Reg.isPhysical() ? Reg : Register(VRM->getPhys(Reg)); 112480093f4SDimitry Andric if (PhysReg) { 113480093f4SDimitry Andric if (MO->getSubReg()) 114480093f4SDimitry Andric PhysReg = getSubReg(PhysReg, MO->getSubReg()); 115480093f4SDimitry Andric if (VRRegMO->getSubReg()) 116480093f4SDimitry Andric PhysReg = getMatchingSuperReg(PhysReg, VRRegMO->getSubReg(), 117480093f4SDimitry Andric MRI->getRegClass(VirtReg)); 118480093f4SDimitry Andric if (!MRI->isReserved(PhysReg) && !is_contained(Hints, PhysReg)) 119480093f4SDimitry Andric TwoAddrHints.insert(PhysReg); 120480093f4SDimitry Andric } 121480093f4SDimitry Andric }; 122480093f4SDimitry Andric tryAddHint(OtherMO); 123480093f4SDimitry Andric if (CommuMO) 124480093f4SDimitry Andric tryAddHint(CommuMO); 125480093f4SDimitry Andric } 126480093f4SDimitry Andric for (MCPhysReg OrderReg : Order) 127480093f4SDimitry Andric if (TwoAddrHints.count(OrderReg)) 128480093f4SDimitry Andric Hints.push_back(OrderReg); 129480093f4SDimitry Andric } 130480093f4SDimitry Andric 1310b57cec5SDimitry Andric if (MRI->getRegClass(VirtReg) == &SystemZ::GRX32BitRegClass) { 1325ffd83dbSDimitry Andric SmallVector<Register, 8> Worklist; 1335ffd83dbSDimitry Andric SmallSet<Register, 4> DoneRegs; 1340b57cec5SDimitry Andric Worklist.push_back(VirtReg); 1350b57cec5SDimitry Andric while (Worklist.size()) { 1365ffd83dbSDimitry Andric Register Reg = Worklist.pop_back_val(); 1370b57cec5SDimitry Andric if (!DoneRegs.insert(Reg).second) 1380b57cec5SDimitry Andric continue; 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric for (auto &Use : MRI->reg_instructions(Reg)) { 1410b57cec5SDimitry Andric // For LOCRMux, see if the other operand is already a high or low 1420b57cec5SDimitry Andric // register, and in that case give the corresponding hints for 1430b57cec5SDimitry Andric // VirtReg. LOCR instructions need both operands in either high or 1440b57cec5SDimitry Andric // low parts. Same handling for SELRMux. 1450b57cec5SDimitry Andric if (Use.getOpcode() == SystemZ::LOCRMux || 1460b57cec5SDimitry Andric Use.getOpcode() == SystemZ::SELRMux) { 1470b57cec5SDimitry Andric MachineOperand &TrueMO = Use.getOperand(1); 1480b57cec5SDimitry Andric MachineOperand &FalseMO = Use.getOperand(2); 1490b57cec5SDimitry Andric const TargetRegisterClass *RC = 1500b57cec5SDimitry Andric TRI->getCommonSubClass(getRC32(FalseMO, VRM, MRI), 1510b57cec5SDimitry Andric getRC32(TrueMO, VRM, MRI)); 1520b57cec5SDimitry Andric if (Use.getOpcode() == SystemZ::SELRMux) 1530b57cec5SDimitry Andric RC = TRI->getCommonSubClass(RC, 1540b57cec5SDimitry Andric getRC32(Use.getOperand(0), VRM, MRI)); 1550b57cec5SDimitry Andric if (RC && RC != &SystemZ::GRX32BitRegClass) { 1560b57cec5SDimitry Andric addHints(Order, Hints, RC, MRI); 1570b57cec5SDimitry Andric // Return true to make these hints the only regs available to 1580b57cec5SDimitry Andric // RA. This may mean extra spilling but since the alternative is 1590b57cec5SDimitry Andric // a jump sequence expansion of the LOCRMux, it is preferred. 1600b57cec5SDimitry Andric return true; 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric // Add the other operand of the LOCRMux to the worklist. 1648bcb0991SDimitry Andric Register OtherReg = 1650b57cec5SDimitry Andric (TrueMO.getReg() == Reg ? FalseMO.getReg() : TrueMO.getReg()); 1660b57cec5SDimitry Andric if (MRI->getRegClass(OtherReg) == &SystemZ::GRX32BitRegClass) 1670b57cec5SDimitry Andric Worklist.push_back(OtherReg); 1680b57cec5SDimitry Andric } // end LOCRMux 1690b57cec5SDimitry Andric else if (Use.getOpcode() == SystemZ::CHIMux || 1700b57cec5SDimitry Andric Use.getOpcode() == SystemZ::CFIMux) { 1710b57cec5SDimitry Andric if (Use.getOperand(1).getImm() == 0) { 1720b57cec5SDimitry Andric bool OnlyLMuxes = true; 1730b57cec5SDimitry Andric for (MachineInstr &DefMI : MRI->def_instructions(VirtReg)) 1740b57cec5SDimitry Andric if (DefMI.getOpcode() != SystemZ::LMux) 1750b57cec5SDimitry Andric OnlyLMuxes = false; 1760b57cec5SDimitry Andric if (OnlyLMuxes) { 1770b57cec5SDimitry Andric addHints(Order, Hints, &SystemZ::GR32BitRegClass, MRI); 1780b57cec5SDimitry Andric // Return false to make these hints preferred but not obligatory. 1790b57cec5SDimitry Andric return false; 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric } // end CHIMux / CFIMux 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric return BaseImplRetVal; 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric const MCPhysReg * 191fe6060f1SDimitry Andric SystemZXPLINK64Registers::getCalleeSavedRegs(const MachineFunction *MF) const { 192349cc55cSDimitry Andric const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>(); 193349cc55cSDimitry Andric return Subtarget.hasVector() ? CSR_SystemZ_XPLINK64_Vector_SaveList 194349cc55cSDimitry Andric : CSR_SystemZ_XPLINK64_SaveList; 195fe6060f1SDimitry Andric } 196fe6060f1SDimitry Andric 197fe6060f1SDimitry Andric const MCPhysReg * 198fe6060f1SDimitry Andric SystemZELFRegisters::getCalleeSavedRegs(const MachineFunction *MF) const { 1990b57cec5SDimitry Andric const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>(); 200480093f4SDimitry Andric if (MF->getFunction().getCallingConv() == CallingConv::GHC) 201480093f4SDimitry Andric return CSR_SystemZ_NoRegs_SaveList; 2020b57cec5SDimitry Andric if (MF->getFunction().getCallingConv() == CallingConv::AnyReg) 2030b57cec5SDimitry Andric return Subtarget.hasVector()? CSR_SystemZ_AllRegs_Vector_SaveList 2040b57cec5SDimitry Andric : CSR_SystemZ_AllRegs_SaveList; 2050b57cec5SDimitry Andric if (MF->getSubtarget().getTargetLowering()->supportSwiftError() && 2060b57cec5SDimitry Andric MF->getFunction().getAttributes().hasAttrSomewhere( 2070b57cec5SDimitry Andric Attribute::SwiftError)) 2080b57cec5SDimitry Andric return CSR_SystemZ_SwiftError_SaveList; 209fe6060f1SDimitry Andric return CSR_SystemZ_ELF_SaveList; 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric const uint32_t * 213fe6060f1SDimitry Andric SystemZXPLINK64Registers::getCallPreservedMask(const MachineFunction &MF, 214fe6060f1SDimitry Andric CallingConv::ID CC) const { 215349cc55cSDimitry Andric const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>(); 216349cc55cSDimitry Andric return Subtarget.hasVector() ? CSR_SystemZ_XPLINK64_Vector_RegMask 217349cc55cSDimitry Andric : CSR_SystemZ_XPLINK64_RegMask; 218fe6060f1SDimitry Andric } 219fe6060f1SDimitry Andric 220fe6060f1SDimitry Andric const uint32_t * 221fe6060f1SDimitry Andric SystemZELFRegisters::getCallPreservedMask(const MachineFunction &MF, 2220b57cec5SDimitry Andric CallingConv::ID CC) const { 2230b57cec5SDimitry Andric const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>(); 224480093f4SDimitry Andric if (CC == CallingConv::GHC) 225480093f4SDimitry Andric return CSR_SystemZ_NoRegs_RegMask; 2260b57cec5SDimitry Andric if (CC == CallingConv::AnyReg) 2270b57cec5SDimitry Andric return Subtarget.hasVector()? CSR_SystemZ_AllRegs_Vector_RegMask 2280b57cec5SDimitry Andric : CSR_SystemZ_AllRegs_RegMask; 2290b57cec5SDimitry Andric if (MF.getSubtarget().getTargetLowering()->supportSwiftError() && 2300b57cec5SDimitry Andric MF.getFunction().getAttributes().hasAttrSomewhere( 2310b57cec5SDimitry Andric Attribute::SwiftError)) 2320b57cec5SDimitry Andric return CSR_SystemZ_SwiftError_RegMask; 233fe6060f1SDimitry Andric return CSR_SystemZ_ELF_RegMask; 234fe6060f1SDimitry Andric } 235fe6060f1SDimitry Andric 236fe6060f1SDimitry Andric SystemZRegisterInfo::SystemZRegisterInfo(unsigned int RA) 237fe6060f1SDimitry Andric : SystemZGenRegisterInfo(RA) {} 238fe6060f1SDimitry Andric 239fe6060f1SDimitry Andric const MCPhysReg * 240fe6060f1SDimitry Andric SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { 241fe6060f1SDimitry Andric 242fe6060f1SDimitry Andric const SystemZSubtarget *Subtarget = &MF->getSubtarget<SystemZSubtarget>(); 243fe6060f1SDimitry Andric SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters(); 244fe6060f1SDimitry Andric 245fe6060f1SDimitry Andric return Regs->getCalleeSavedRegs(MF); 246fe6060f1SDimitry Andric } 247fe6060f1SDimitry Andric 248fe6060f1SDimitry Andric const uint32_t * 249fe6060f1SDimitry Andric SystemZRegisterInfo::getCallPreservedMask(const MachineFunction &MF, 250fe6060f1SDimitry Andric CallingConv::ID CC) const { 251fe6060f1SDimitry Andric 252fe6060f1SDimitry Andric const SystemZSubtarget *Subtarget = &MF.getSubtarget<SystemZSubtarget>(); 253fe6060f1SDimitry Andric SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters(); 254fe6060f1SDimitry Andric return Regs->getCallPreservedMask(MF, CC); 2550b57cec5SDimitry Andric } 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric BitVector 2580b57cec5SDimitry Andric SystemZRegisterInfo::getReservedRegs(const MachineFunction &MF) const { 2590b57cec5SDimitry Andric BitVector Reserved(getNumRegs()); 2600b57cec5SDimitry Andric const SystemZFrameLowering *TFI = getFrameLowering(MF); 261fe6060f1SDimitry Andric const SystemZSubtarget *Subtarget = &MF.getSubtarget<SystemZSubtarget>(); 262fe6060f1SDimitry Andric SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters(); 263fe6060f1SDimitry Andric if (TFI->hasFP(MF)) 264fe6060f1SDimitry Andric // The frame pointer. Reserve all aliases. 265fe6060f1SDimitry Andric for (MCRegAliasIterator AI(Regs->getFramePointerRegister(), this, true); 266fe6060f1SDimitry Andric AI.isValid(); ++AI) 267fe6060f1SDimitry Andric Reserved.set(*AI); 2680b57cec5SDimitry Andric 269fe6060f1SDimitry Andric // Reserve all aliases for the stack pointer. 270fe6060f1SDimitry Andric for (MCRegAliasIterator AI(Regs->getStackPointerRegister(), this, true); 271fe6060f1SDimitry Andric AI.isValid(); ++AI) 272fe6060f1SDimitry Andric Reserved.set(*AI); 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric // A0 and A1 hold the thread pointer. 2750b57cec5SDimitry Andric Reserved.set(SystemZ::A0); 2760b57cec5SDimitry Andric Reserved.set(SystemZ::A1); 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric // FPC is the floating-point control register. 2790b57cec5SDimitry Andric Reserved.set(SystemZ::FPC); 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric return Reserved; 2820b57cec5SDimitry Andric } 2830b57cec5SDimitry Andric 284bdd1243dSDimitry Andric bool 2850b57cec5SDimitry Andric SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI, 2860b57cec5SDimitry Andric int SPAdj, unsigned FIOperandNum, 2870b57cec5SDimitry Andric RegScavenger *RS) const { 2880b57cec5SDimitry Andric assert(SPAdj == 0 && "Outgoing arguments should be part of the frame"); 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric MachineBasicBlock &MBB = *MI->getParent(); 2910b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 29281ad6265SDimitry Andric auto *TII = MF.getSubtarget<SystemZSubtarget>().getInstrInfo(); 2930b57cec5SDimitry Andric const SystemZFrameLowering *TFI = getFrameLowering(MF); 2940b57cec5SDimitry Andric DebugLoc DL = MI->getDebugLoc(); 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric // Decompose the frame index into a base and offset. 2970b57cec5SDimitry Andric int FrameIndex = MI->getOperand(FIOperandNum).getIndex(); 2985ffd83dbSDimitry Andric Register BasePtr; 299e8d8bef9SDimitry Andric int64_t Offset = 300e8d8bef9SDimitry Andric (TFI->getFrameIndexReference(MF, FrameIndex, BasePtr).getFixed() + 3010b57cec5SDimitry Andric MI->getOperand(FIOperandNum + 1).getImm()); 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric // Special handling of dbg_value instructions. 3040b57cec5SDimitry Andric if (MI->isDebugValue()) { 3050b57cec5SDimitry Andric MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, /*isDef*/ false); 306fe6060f1SDimitry Andric if (MI->isNonListDebugValue()) { 3075ffd83dbSDimitry Andric MI->getDebugOffset().ChangeToImmediate(Offset); 308fe6060f1SDimitry Andric } else { 309fe6060f1SDimitry Andric unsigned OpIdx = MI->getDebugOperandIndex(&MI->getOperand(FIOperandNum)); 310fe6060f1SDimitry Andric SmallVector<uint64_t, 3> Ops; 311fe6060f1SDimitry Andric DIExpression::appendOffset( 312fe6060f1SDimitry Andric Ops, TFI->getFrameIndexReference(MF, FrameIndex, BasePtr).getFixed()); 313fe6060f1SDimitry Andric MI->getDebugExpressionOp().setMetadata( 314fe6060f1SDimitry Andric DIExpression::appendOpsToArg(MI->getDebugExpression(), Ops, OpIdx)); 315fe6060f1SDimitry Andric } 316bdd1243dSDimitry Andric return false; 3170b57cec5SDimitry Andric } 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andric // See if the offset is in range, or if an equivalent instruction that 3200b57cec5SDimitry Andric // accepts the offset exists. 3210b57cec5SDimitry Andric unsigned Opcode = MI->getOpcode(); 32281ad6265SDimitry Andric unsigned OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset, &*MI); 3230b57cec5SDimitry Andric if (OpcodeForOffset) { 3240b57cec5SDimitry Andric if (OpcodeForOffset == SystemZ::LE && 3250b57cec5SDimitry Andric MF.getSubtarget<SystemZSubtarget>().hasVector()) { 3260b57cec5SDimitry Andric // If LE is ok for offset, use LDE instead on z13. 3270b57cec5SDimitry Andric OpcodeForOffset = SystemZ::LDE32; 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false); 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric else { 3320b57cec5SDimitry Andric // Create an anchor point that is in range. Start at 0xffff so that 3330b57cec5SDimitry Andric // can use LLILH to load the immediate. 3340b57cec5SDimitry Andric int64_t OldOffset = Offset; 3350b57cec5SDimitry Andric int64_t Mask = 0xffff; 3360b57cec5SDimitry Andric do { 3370b57cec5SDimitry Andric Offset = OldOffset & Mask; 3380b57cec5SDimitry Andric OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset); 3390b57cec5SDimitry Andric Mask >>= 1; 3400b57cec5SDimitry Andric assert(Mask && "One offset must be OK"); 3410b57cec5SDimitry Andric } while (!OpcodeForOffset); 3420b57cec5SDimitry Andric 3438bcb0991SDimitry Andric Register ScratchReg = 3440b57cec5SDimitry Andric MF.getRegInfo().createVirtualRegister(&SystemZ::ADDR64BitRegClass); 3450b57cec5SDimitry Andric int64_t HighOffset = OldOffset - Offset; 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andric if (MI->getDesc().TSFlags & SystemZII::HasIndex 3480b57cec5SDimitry Andric && MI->getOperand(FIOperandNum + 2).getReg() == 0) { 3490b57cec5SDimitry Andric // Load the offset into the scratch register and use it as an index. 3500b57cec5SDimitry Andric // The scratch register then dies here. 3510b57cec5SDimitry Andric TII->loadImmediate(MBB, MI, ScratchReg, HighOffset); 3520b57cec5SDimitry Andric MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false); 3530b57cec5SDimitry Andric MI->getOperand(FIOperandNum + 2).ChangeToRegister(ScratchReg, 3540b57cec5SDimitry Andric false, false, true); 3550b57cec5SDimitry Andric } else { 3560b57cec5SDimitry Andric // Load the anchor address into a scratch register. 3570b57cec5SDimitry Andric unsigned LAOpcode = TII->getOpcodeForOffset(SystemZ::LA, HighOffset); 3580b57cec5SDimitry Andric if (LAOpcode) 3590b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII->get(LAOpcode),ScratchReg) 3600b57cec5SDimitry Andric .addReg(BasePtr).addImm(HighOffset).addReg(0); 3610b57cec5SDimitry Andric else { 3620b57cec5SDimitry Andric // Load the high offset into the scratch register and use it as 3630b57cec5SDimitry Andric // an index. 3640b57cec5SDimitry Andric TII->loadImmediate(MBB, MI, ScratchReg, HighOffset); 365e8d8bef9SDimitry Andric BuildMI(MBB, MI, DL, TII->get(SystemZ::LA), ScratchReg) 366e8d8bef9SDimitry Andric .addReg(BasePtr, RegState::Kill).addImm(0).addReg(ScratchReg); 3670b57cec5SDimitry Andric } 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric // Use the scratch register as the base. It then dies here. 3700b57cec5SDimitry Andric MI->getOperand(FIOperandNum).ChangeToRegister(ScratchReg, 3710b57cec5SDimitry Andric false, false, true); 3720b57cec5SDimitry Andric } 3730b57cec5SDimitry Andric } 3740b57cec5SDimitry Andric MI->setDesc(TII->get(OpcodeForOffset)); 3750b57cec5SDimitry Andric MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); 376bdd1243dSDimitry Andric return false; 3770b57cec5SDimitry Andric } 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric bool SystemZRegisterInfo::shouldCoalesce(MachineInstr *MI, 3800b57cec5SDimitry Andric const TargetRegisterClass *SrcRC, 3810b57cec5SDimitry Andric unsigned SubReg, 3820b57cec5SDimitry Andric const TargetRegisterClass *DstRC, 3830b57cec5SDimitry Andric unsigned DstSubReg, 3840b57cec5SDimitry Andric const TargetRegisterClass *NewRC, 3850b57cec5SDimitry Andric LiveIntervals &LIS) const { 3860b57cec5SDimitry Andric assert (MI->isCopy() && "Only expecting COPY instructions"); 3870b57cec5SDimitry Andric 3880b57cec5SDimitry Andric // Coalesce anything which is not a COPY involving a subreg to/from GR128. 3890b57cec5SDimitry Andric if (!(NewRC->hasSuperClassEq(&SystemZ::GR128BitRegClass) && 390*7a6dacacSDimitry Andric (getRegSizeInBits(*SrcRC) <= 64 || getRegSizeInBits(*DstRC) <= 64) && 391*7a6dacacSDimitry Andric !MI->getOperand(1).isUndef())) 3920b57cec5SDimitry Andric return true; 3930b57cec5SDimitry Andric 3945f757f3fSDimitry Andric // Allow coalescing of a GR128 subreg COPY only if the subreg liverange is 3955f757f3fSDimitry Andric // local to one MBB with not too many interferring physreg clobbers. Otherwise 3960b57cec5SDimitry Andric // regalloc may run out of registers. 3975f757f3fSDimitry Andric unsigned SubregOpIdx = getRegSizeInBits(*SrcRC) == 128 ? 0 : 1; 3985f757f3fSDimitry Andric LiveInterval &LI = LIS.getInterval(MI->getOperand(SubregOpIdx).getReg()); 3990b57cec5SDimitry Andric 4005f757f3fSDimitry Andric // Check that the subreg is local to MBB. 4010b57cec5SDimitry Andric MachineBasicBlock *MBB = MI->getParent(); 4025f757f3fSDimitry Andric MachineInstr *FirstMI = LIS.getInstructionFromIndex(LI.beginIndex()); 4035f757f3fSDimitry Andric MachineInstr *LastMI = LIS.getInstructionFromIndex(LI.endIndex()); 4045f757f3fSDimitry Andric if (!FirstMI || FirstMI->getParent() != MBB || 4055f757f3fSDimitry Andric !LastMI || LastMI->getParent() != MBB) 4060b57cec5SDimitry Andric return false; 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric // Check if coalescing seems safe by finding the set of clobbered physreg 4090b57cec5SDimitry Andric // pairs in the region. 4100b57cec5SDimitry Andric BitVector PhysClobbered(getNumRegs()); 4115f757f3fSDimitry Andric for (MachineBasicBlock::iterator MII = FirstMI, 4125f757f3fSDimitry Andric MEE = std::next(LastMI->getIterator()); 4135f757f3fSDimitry Andric MII != MEE; ++MII) 4140b57cec5SDimitry Andric for (const MachineOperand &MO : MII->operands()) 415bdd1243dSDimitry Andric if (MO.isReg() && MO.getReg().isPhysical()) { 41606c3fb27SDimitry Andric for (MCPhysReg SI : superregs_inclusive(MO.getReg())) 41706c3fb27SDimitry Andric if (NewRC->contains(SI)) { 41806c3fb27SDimitry Andric PhysClobbered.set(SI); 4190b57cec5SDimitry Andric break; 4200b57cec5SDimitry Andric } 4210b57cec5SDimitry Andric } 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric // Demand an arbitrary margin of free regs. 4240b57cec5SDimitry Andric unsigned const DemandedFreeGR128 = 3; 4250b57cec5SDimitry Andric if (PhysClobbered.count() > (NewRC->getNumRegs() - DemandedFreeGR128)) 4260b57cec5SDimitry Andric return false; 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric return true; 4290b57cec5SDimitry Andric } 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric Register 4320b57cec5SDimitry Andric SystemZRegisterInfo::getFrameRegister(const MachineFunction &MF) const { 4330b57cec5SDimitry Andric const SystemZFrameLowering *TFI = getFrameLowering(MF); 434fe6060f1SDimitry Andric const SystemZSubtarget *Subtarget = &MF.getSubtarget<SystemZSubtarget>(); 435fe6060f1SDimitry Andric SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters(); 436fe6060f1SDimitry Andric 437fe6060f1SDimitry Andric return TFI->hasFP(MF) ? Regs->getFramePointerRegister() 438fe6060f1SDimitry Andric : Regs->getStackPointerRegister(); 4390b57cec5SDimitry Andric } 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric const TargetRegisterClass * 4420b57cec5SDimitry Andric SystemZRegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const { 4430b57cec5SDimitry Andric if (RC == &SystemZ::CCRRegClass) 4440b57cec5SDimitry Andric return &SystemZ::GR32BitRegClass; 4450b57cec5SDimitry Andric return RC; 4460b57cec5SDimitry Andric } 4470b57cec5SDimitry Andric 448