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/CodeGen/LiveIntervals.h" 130b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.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" 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric using namespace llvm; 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric #define GET_REGINFO_TARGET_DESC 220b57cec5SDimitry Andric #include "SystemZGenRegisterInfo.inc" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric SystemZRegisterInfo::SystemZRegisterInfo() 250b57cec5SDimitry Andric : SystemZGenRegisterInfo(SystemZ::R14D) {} 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric // Given that MO is a GRX32 operand, return either GR32 or GRH32 if MO 280b57cec5SDimitry Andric // somehow belongs in it. Otherwise, return GRX32. 290b57cec5SDimitry Andric static const TargetRegisterClass *getRC32(MachineOperand &MO, 300b57cec5SDimitry Andric const VirtRegMap *VRM, 310b57cec5SDimitry Andric const MachineRegisterInfo *MRI) { 320b57cec5SDimitry Andric const TargetRegisterClass *RC = MRI->getRegClass(MO.getReg()); 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric if (SystemZ::GR32BitRegClass.hasSubClassEq(RC) || 350b57cec5SDimitry Andric MO.getSubReg() == SystemZ::subreg_l32 || 360b57cec5SDimitry Andric MO.getSubReg() == SystemZ::subreg_hl32) 370b57cec5SDimitry Andric return &SystemZ::GR32BitRegClass; 380b57cec5SDimitry Andric if (SystemZ::GRH32BitRegClass.hasSubClassEq(RC) || 390b57cec5SDimitry Andric MO.getSubReg() == SystemZ::subreg_h32 || 400b57cec5SDimitry Andric MO.getSubReg() == SystemZ::subreg_hh32) 410b57cec5SDimitry Andric return &SystemZ::GRH32BitRegClass; 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric if (VRM && VRM->hasPhys(MO.getReg())) { 44*8bcb0991SDimitry Andric Register PhysReg = VRM->getPhys(MO.getReg()); 450b57cec5SDimitry Andric if (SystemZ::GR32BitRegClass.contains(PhysReg)) 460b57cec5SDimitry Andric return &SystemZ::GR32BitRegClass; 470b57cec5SDimitry Andric assert (SystemZ::GRH32BitRegClass.contains(PhysReg) && 480b57cec5SDimitry Andric "Phys reg not in GR32 or GRH32?"); 490b57cec5SDimitry Andric return &SystemZ::GRH32BitRegClass; 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric assert (RC == &SystemZ::GRX32BitRegClass); 530b57cec5SDimitry Andric return RC; 540b57cec5SDimitry Andric } 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric // Pass the registers of RC as hints while making sure that if any of these 570b57cec5SDimitry Andric // registers are copy hints (and therefore already in Hints), hint them 580b57cec5SDimitry Andric // first. 590b57cec5SDimitry Andric static void addHints(ArrayRef<MCPhysReg> Order, 600b57cec5SDimitry Andric SmallVectorImpl<MCPhysReg> &Hints, 610b57cec5SDimitry Andric const TargetRegisterClass *RC, 620b57cec5SDimitry Andric const MachineRegisterInfo *MRI) { 630b57cec5SDimitry Andric SmallSet<unsigned, 4> CopyHints; 640b57cec5SDimitry Andric CopyHints.insert(Hints.begin(), Hints.end()); 650b57cec5SDimitry Andric Hints.clear(); 660b57cec5SDimitry Andric for (MCPhysReg Reg : Order) 670b57cec5SDimitry Andric if (CopyHints.count(Reg) && 680b57cec5SDimitry Andric RC->contains(Reg) && !MRI->isReserved(Reg)) 690b57cec5SDimitry Andric Hints.push_back(Reg); 700b57cec5SDimitry Andric for (MCPhysReg Reg : Order) 710b57cec5SDimitry Andric if (!CopyHints.count(Reg) && 720b57cec5SDimitry Andric RC->contains(Reg) && !MRI->isReserved(Reg)) 730b57cec5SDimitry Andric Hints.push_back(Reg); 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric bool 770b57cec5SDimitry Andric SystemZRegisterInfo::getRegAllocationHints(unsigned VirtReg, 780b57cec5SDimitry Andric ArrayRef<MCPhysReg> Order, 790b57cec5SDimitry Andric SmallVectorImpl<MCPhysReg> &Hints, 800b57cec5SDimitry Andric const MachineFunction &MF, 810b57cec5SDimitry Andric const VirtRegMap *VRM, 820b57cec5SDimitry Andric const LiveRegMatrix *Matrix) const { 830b57cec5SDimitry Andric const MachineRegisterInfo *MRI = &MF.getRegInfo(); 840b57cec5SDimitry Andric const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>(); 850b57cec5SDimitry Andric const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric bool BaseImplRetVal = TargetRegisterInfo::getRegAllocationHints( 880b57cec5SDimitry Andric VirtReg, Order, Hints, MF, VRM, Matrix); 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric if (MRI->getRegClass(VirtReg) == &SystemZ::GRX32BitRegClass) { 910b57cec5SDimitry Andric SmallVector<unsigned, 8> Worklist; 920b57cec5SDimitry Andric SmallSet<unsigned, 4> DoneRegs; 930b57cec5SDimitry Andric Worklist.push_back(VirtReg); 940b57cec5SDimitry Andric while (Worklist.size()) { 950b57cec5SDimitry Andric unsigned Reg = Worklist.pop_back_val(); 960b57cec5SDimitry Andric if (!DoneRegs.insert(Reg).second) 970b57cec5SDimitry Andric continue; 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric for (auto &Use : MRI->reg_instructions(Reg)) { 1000b57cec5SDimitry Andric // For LOCRMux, see if the other operand is already a high or low 1010b57cec5SDimitry Andric // register, and in that case give the corresponding hints for 1020b57cec5SDimitry Andric // VirtReg. LOCR instructions need both operands in either high or 1030b57cec5SDimitry Andric // low parts. Same handling for SELRMux. 1040b57cec5SDimitry Andric if (Use.getOpcode() == SystemZ::LOCRMux || 1050b57cec5SDimitry Andric Use.getOpcode() == SystemZ::SELRMux) { 1060b57cec5SDimitry Andric MachineOperand &TrueMO = Use.getOperand(1); 1070b57cec5SDimitry Andric MachineOperand &FalseMO = Use.getOperand(2); 1080b57cec5SDimitry Andric const TargetRegisterClass *RC = 1090b57cec5SDimitry Andric TRI->getCommonSubClass(getRC32(FalseMO, VRM, MRI), 1100b57cec5SDimitry Andric getRC32(TrueMO, VRM, MRI)); 1110b57cec5SDimitry Andric if (Use.getOpcode() == SystemZ::SELRMux) 1120b57cec5SDimitry Andric RC = TRI->getCommonSubClass(RC, 1130b57cec5SDimitry Andric getRC32(Use.getOperand(0), VRM, MRI)); 1140b57cec5SDimitry Andric if (RC && RC != &SystemZ::GRX32BitRegClass) { 1150b57cec5SDimitry Andric addHints(Order, Hints, RC, MRI); 1160b57cec5SDimitry Andric // Return true to make these hints the only regs available to 1170b57cec5SDimitry Andric // RA. This may mean extra spilling but since the alternative is 1180b57cec5SDimitry Andric // a jump sequence expansion of the LOCRMux, it is preferred. 1190b57cec5SDimitry Andric return true; 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric // Add the other operand of the LOCRMux to the worklist. 123*8bcb0991SDimitry Andric Register OtherReg = 1240b57cec5SDimitry Andric (TrueMO.getReg() == Reg ? FalseMO.getReg() : TrueMO.getReg()); 1250b57cec5SDimitry Andric if (MRI->getRegClass(OtherReg) == &SystemZ::GRX32BitRegClass) 1260b57cec5SDimitry Andric Worklist.push_back(OtherReg); 1270b57cec5SDimitry Andric } // end LOCRMux 1280b57cec5SDimitry Andric else if (Use.getOpcode() == SystemZ::CHIMux || 1290b57cec5SDimitry Andric Use.getOpcode() == SystemZ::CFIMux) { 1300b57cec5SDimitry Andric if (Use.getOperand(1).getImm() == 0) { 1310b57cec5SDimitry Andric bool OnlyLMuxes = true; 1320b57cec5SDimitry Andric for (MachineInstr &DefMI : MRI->def_instructions(VirtReg)) 1330b57cec5SDimitry Andric if (DefMI.getOpcode() != SystemZ::LMux) 1340b57cec5SDimitry Andric OnlyLMuxes = false; 1350b57cec5SDimitry Andric if (OnlyLMuxes) { 1360b57cec5SDimitry Andric addHints(Order, Hints, &SystemZ::GR32BitRegClass, MRI); 1370b57cec5SDimitry Andric // Return false to make these hints preferred but not obligatory. 1380b57cec5SDimitry Andric return false; 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric } // end CHIMux / CFIMux 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric if (VRM == nullptr) 1470b57cec5SDimitry Andric return BaseImplRetVal; 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric // Add any two address hints after any copy hints. 1500b57cec5SDimitry Andric SmallSet<unsigned, 4> TwoAddrHints; 1510b57cec5SDimitry Andric for (auto &Use : MRI->reg_nodbg_instructions(VirtReg)) 1520b57cec5SDimitry Andric if (SystemZ::getTwoOperandOpcode(Use.getOpcode()) != -1) { 1530b57cec5SDimitry Andric const MachineOperand *VRRegMO = nullptr; 1540b57cec5SDimitry Andric const MachineOperand *OtherMO = nullptr; 1550b57cec5SDimitry Andric const MachineOperand *CommuMO = nullptr; 1560b57cec5SDimitry Andric if (VirtReg == Use.getOperand(0).getReg()) { 1570b57cec5SDimitry Andric VRRegMO = &Use.getOperand(0); 1580b57cec5SDimitry Andric OtherMO = &Use.getOperand(1); 1590b57cec5SDimitry Andric if (Use.isCommutable()) 1600b57cec5SDimitry Andric CommuMO = &Use.getOperand(2); 1610b57cec5SDimitry Andric } else if (VirtReg == Use.getOperand(1).getReg()) { 1620b57cec5SDimitry Andric VRRegMO = &Use.getOperand(1); 1630b57cec5SDimitry Andric OtherMO = &Use.getOperand(0); 1640b57cec5SDimitry Andric } else if (VirtReg == Use.getOperand(2).getReg() && Use.isCommutable()) { 1650b57cec5SDimitry Andric VRRegMO = &Use.getOperand(2); 1660b57cec5SDimitry Andric OtherMO = &Use.getOperand(0); 1670b57cec5SDimitry Andric } else 1680b57cec5SDimitry Andric continue; 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric auto tryAddHint = [&](const MachineOperand *MO) -> void { 1710b57cec5SDimitry Andric Register Reg = MO->getReg(); 172*8bcb0991SDimitry Andric Register PhysReg = 173*8bcb0991SDimitry Andric Register::isPhysicalRegister(Reg) ? Reg : VRM->getPhys(Reg); 1740b57cec5SDimitry Andric if (PhysReg) { 1750b57cec5SDimitry Andric if (MO->getSubReg()) 1760b57cec5SDimitry Andric PhysReg = getSubReg(PhysReg, MO->getSubReg()); 1770b57cec5SDimitry Andric if (VRRegMO->getSubReg()) 1780b57cec5SDimitry Andric PhysReg = getMatchingSuperReg(PhysReg, VRRegMO->getSubReg(), 1790b57cec5SDimitry Andric MRI->getRegClass(VirtReg)); 1800b57cec5SDimitry Andric if (!MRI->isReserved(PhysReg) && !is_contained(Hints, PhysReg)) 1810b57cec5SDimitry Andric TwoAddrHints.insert(PhysReg); 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric }; 1840b57cec5SDimitry Andric tryAddHint(OtherMO); 1850b57cec5SDimitry Andric if (CommuMO) 1860b57cec5SDimitry Andric tryAddHint(CommuMO); 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric for (MCPhysReg OrderReg : Order) 1890b57cec5SDimitry Andric if (TwoAddrHints.count(OrderReg)) 1900b57cec5SDimitry Andric Hints.push_back(OrderReg); 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric return BaseImplRetVal; 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric const MCPhysReg * 1960b57cec5SDimitry Andric SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { 1970b57cec5SDimitry Andric const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>(); 1980b57cec5SDimitry Andric if (MF->getFunction().getCallingConv() == CallingConv::AnyReg) 1990b57cec5SDimitry Andric return Subtarget.hasVector()? CSR_SystemZ_AllRegs_Vector_SaveList 2000b57cec5SDimitry Andric : CSR_SystemZ_AllRegs_SaveList; 2010b57cec5SDimitry Andric if (MF->getSubtarget().getTargetLowering()->supportSwiftError() && 2020b57cec5SDimitry Andric MF->getFunction().getAttributes().hasAttrSomewhere( 2030b57cec5SDimitry Andric Attribute::SwiftError)) 2040b57cec5SDimitry Andric return CSR_SystemZ_SwiftError_SaveList; 2050b57cec5SDimitry Andric return CSR_SystemZ_SaveList; 2060b57cec5SDimitry Andric } 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric const uint32_t * 2090b57cec5SDimitry Andric SystemZRegisterInfo::getCallPreservedMask(const MachineFunction &MF, 2100b57cec5SDimitry Andric CallingConv::ID CC) const { 2110b57cec5SDimitry Andric const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>(); 2120b57cec5SDimitry Andric if (CC == CallingConv::AnyReg) 2130b57cec5SDimitry Andric return Subtarget.hasVector()? CSR_SystemZ_AllRegs_Vector_RegMask 2140b57cec5SDimitry Andric : CSR_SystemZ_AllRegs_RegMask; 2150b57cec5SDimitry Andric if (MF.getSubtarget().getTargetLowering()->supportSwiftError() && 2160b57cec5SDimitry Andric MF.getFunction().getAttributes().hasAttrSomewhere( 2170b57cec5SDimitry Andric Attribute::SwiftError)) 2180b57cec5SDimitry Andric return CSR_SystemZ_SwiftError_RegMask; 2190b57cec5SDimitry Andric return CSR_SystemZ_RegMask; 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric BitVector 2230b57cec5SDimitry Andric SystemZRegisterInfo::getReservedRegs(const MachineFunction &MF) const { 2240b57cec5SDimitry Andric BitVector Reserved(getNumRegs()); 2250b57cec5SDimitry Andric const SystemZFrameLowering *TFI = getFrameLowering(MF); 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric if (TFI->hasFP(MF)) { 2280b57cec5SDimitry Andric // R11D is the frame pointer. Reserve all aliases. 2290b57cec5SDimitry Andric Reserved.set(SystemZ::R11D); 2300b57cec5SDimitry Andric Reserved.set(SystemZ::R11L); 2310b57cec5SDimitry Andric Reserved.set(SystemZ::R11H); 2320b57cec5SDimitry Andric Reserved.set(SystemZ::R10Q); 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric // R15D is the stack pointer. Reserve all aliases. 2360b57cec5SDimitry Andric Reserved.set(SystemZ::R15D); 2370b57cec5SDimitry Andric Reserved.set(SystemZ::R15L); 2380b57cec5SDimitry Andric Reserved.set(SystemZ::R15H); 2390b57cec5SDimitry Andric Reserved.set(SystemZ::R14Q); 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric // A0 and A1 hold the thread pointer. 2420b57cec5SDimitry Andric Reserved.set(SystemZ::A0); 2430b57cec5SDimitry Andric Reserved.set(SystemZ::A1); 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric // FPC is the floating-point control register. 2460b57cec5SDimitry Andric Reserved.set(SystemZ::FPC); 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric return Reserved; 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric void 2520b57cec5SDimitry Andric SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI, 2530b57cec5SDimitry Andric int SPAdj, unsigned FIOperandNum, 2540b57cec5SDimitry Andric RegScavenger *RS) const { 2550b57cec5SDimitry Andric assert(SPAdj == 0 && "Outgoing arguments should be part of the frame"); 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric MachineBasicBlock &MBB = *MI->getParent(); 2580b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 2590b57cec5SDimitry Andric auto *TII = 2600b57cec5SDimitry Andric static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo()); 2610b57cec5SDimitry Andric const SystemZFrameLowering *TFI = getFrameLowering(MF); 2620b57cec5SDimitry Andric DebugLoc DL = MI->getDebugLoc(); 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric // Decompose the frame index into a base and offset. 2650b57cec5SDimitry Andric int FrameIndex = MI->getOperand(FIOperandNum).getIndex(); 2660b57cec5SDimitry Andric unsigned BasePtr; 2670b57cec5SDimitry Andric int64_t Offset = (TFI->getFrameIndexReference(MF, FrameIndex, BasePtr) + 2680b57cec5SDimitry Andric MI->getOperand(FIOperandNum + 1).getImm()); 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric // Special handling of dbg_value instructions. 2710b57cec5SDimitry Andric if (MI->isDebugValue()) { 2720b57cec5SDimitry Andric MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, /*isDef*/ false); 2730b57cec5SDimitry Andric MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); 2740b57cec5SDimitry Andric return; 2750b57cec5SDimitry Andric } 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric // See if the offset is in range, or if an equivalent instruction that 2780b57cec5SDimitry Andric // accepts the offset exists. 2790b57cec5SDimitry Andric unsigned Opcode = MI->getOpcode(); 2800b57cec5SDimitry Andric unsigned OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset); 2810b57cec5SDimitry Andric if (OpcodeForOffset) { 2820b57cec5SDimitry Andric if (OpcodeForOffset == SystemZ::LE && 2830b57cec5SDimitry Andric MF.getSubtarget<SystemZSubtarget>().hasVector()) { 2840b57cec5SDimitry Andric // If LE is ok for offset, use LDE instead on z13. 2850b57cec5SDimitry Andric OpcodeForOffset = SystemZ::LDE32; 2860b57cec5SDimitry Andric } 2870b57cec5SDimitry Andric MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false); 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric else { 2900b57cec5SDimitry Andric // Create an anchor point that is in range. Start at 0xffff so that 2910b57cec5SDimitry Andric // can use LLILH to load the immediate. 2920b57cec5SDimitry Andric int64_t OldOffset = Offset; 2930b57cec5SDimitry Andric int64_t Mask = 0xffff; 2940b57cec5SDimitry Andric do { 2950b57cec5SDimitry Andric Offset = OldOffset & Mask; 2960b57cec5SDimitry Andric OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset); 2970b57cec5SDimitry Andric Mask >>= 1; 2980b57cec5SDimitry Andric assert(Mask && "One offset must be OK"); 2990b57cec5SDimitry Andric } while (!OpcodeForOffset); 3000b57cec5SDimitry Andric 301*8bcb0991SDimitry Andric Register ScratchReg = 3020b57cec5SDimitry Andric MF.getRegInfo().createVirtualRegister(&SystemZ::ADDR64BitRegClass); 3030b57cec5SDimitry Andric int64_t HighOffset = OldOffset - Offset; 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric if (MI->getDesc().TSFlags & SystemZII::HasIndex 3060b57cec5SDimitry Andric && MI->getOperand(FIOperandNum + 2).getReg() == 0) { 3070b57cec5SDimitry Andric // Load the offset into the scratch register and use it as an index. 3080b57cec5SDimitry Andric // The scratch register then dies here. 3090b57cec5SDimitry Andric TII->loadImmediate(MBB, MI, ScratchReg, HighOffset); 3100b57cec5SDimitry Andric MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false); 3110b57cec5SDimitry Andric MI->getOperand(FIOperandNum + 2).ChangeToRegister(ScratchReg, 3120b57cec5SDimitry Andric false, false, true); 3130b57cec5SDimitry Andric } else { 3140b57cec5SDimitry Andric // Load the anchor address into a scratch register. 3150b57cec5SDimitry Andric unsigned LAOpcode = TII->getOpcodeForOffset(SystemZ::LA, HighOffset); 3160b57cec5SDimitry Andric if (LAOpcode) 3170b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII->get(LAOpcode),ScratchReg) 3180b57cec5SDimitry Andric .addReg(BasePtr).addImm(HighOffset).addReg(0); 3190b57cec5SDimitry Andric else { 3200b57cec5SDimitry Andric // Load the high offset into the scratch register and use it as 3210b57cec5SDimitry Andric // an index. 3220b57cec5SDimitry Andric TII->loadImmediate(MBB, MI, ScratchReg, HighOffset); 3230b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII->get(SystemZ::AGR),ScratchReg) 3240b57cec5SDimitry Andric .addReg(ScratchReg, RegState::Kill).addReg(BasePtr); 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric // Use the scratch register as the base. It then dies here. 3280b57cec5SDimitry Andric MI->getOperand(FIOperandNum).ChangeToRegister(ScratchReg, 3290b57cec5SDimitry Andric false, false, true); 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric } 3320b57cec5SDimitry Andric MI->setDesc(TII->get(OpcodeForOffset)); 3330b57cec5SDimitry Andric MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); 3340b57cec5SDimitry Andric } 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric bool SystemZRegisterInfo::shouldCoalesce(MachineInstr *MI, 3370b57cec5SDimitry Andric const TargetRegisterClass *SrcRC, 3380b57cec5SDimitry Andric unsigned SubReg, 3390b57cec5SDimitry Andric const TargetRegisterClass *DstRC, 3400b57cec5SDimitry Andric unsigned DstSubReg, 3410b57cec5SDimitry Andric const TargetRegisterClass *NewRC, 3420b57cec5SDimitry Andric LiveIntervals &LIS) const { 3430b57cec5SDimitry Andric assert (MI->isCopy() && "Only expecting COPY instructions"); 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric // Coalesce anything which is not a COPY involving a subreg to/from GR128. 3460b57cec5SDimitry Andric if (!(NewRC->hasSuperClassEq(&SystemZ::GR128BitRegClass) && 3470b57cec5SDimitry Andric (getRegSizeInBits(*SrcRC) <= 64 || getRegSizeInBits(*DstRC) <= 64))) 3480b57cec5SDimitry Andric return true; 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric // Allow coalescing of a GR128 subreg COPY only if the live ranges are small 3510b57cec5SDimitry Andric // and local to one MBB with not too much interferring registers. Otherwise 3520b57cec5SDimitry Andric // regalloc may run out of registers. 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric unsigned WideOpNo = (getRegSizeInBits(*SrcRC) == 128 ? 1 : 0); 355*8bcb0991SDimitry Andric Register GR128Reg = MI->getOperand(WideOpNo).getReg(); 356*8bcb0991SDimitry Andric Register GRNarReg = MI->getOperand((WideOpNo == 1) ? 0 : 1).getReg(); 3570b57cec5SDimitry Andric LiveInterval &IntGR128 = LIS.getInterval(GR128Reg); 3580b57cec5SDimitry Andric LiveInterval &IntGRNar = LIS.getInterval(GRNarReg); 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric // Check that the two virtual registers are local to MBB. 3610b57cec5SDimitry Andric MachineBasicBlock *MBB = MI->getParent(); 3620b57cec5SDimitry Andric MachineInstr *FirstMI_GR128 = 3630b57cec5SDimitry Andric LIS.getInstructionFromIndex(IntGR128.beginIndex()); 3640b57cec5SDimitry Andric MachineInstr *FirstMI_GRNar = 3650b57cec5SDimitry Andric LIS.getInstructionFromIndex(IntGRNar.beginIndex()); 3660b57cec5SDimitry Andric MachineInstr *LastMI_GR128 = LIS.getInstructionFromIndex(IntGR128.endIndex()); 3670b57cec5SDimitry Andric MachineInstr *LastMI_GRNar = LIS.getInstructionFromIndex(IntGRNar.endIndex()); 3680b57cec5SDimitry Andric if ((!FirstMI_GR128 || FirstMI_GR128->getParent() != MBB) || 3690b57cec5SDimitry Andric (!FirstMI_GRNar || FirstMI_GRNar->getParent() != MBB) || 3700b57cec5SDimitry Andric (!LastMI_GR128 || LastMI_GR128->getParent() != MBB) || 3710b57cec5SDimitry Andric (!LastMI_GRNar || LastMI_GRNar->getParent() != MBB)) 3720b57cec5SDimitry Andric return false; 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric MachineBasicBlock::iterator MII = nullptr, MEE = nullptr; 3750b57cec5SDimitry Andric if (WideOpNo == 1) { 3760b57cec5SDimitry Andric MII = FirstMI_GR128; 3770b57cec5SDimitry Andric MEE = LastMI_GRNar; 3780b57cec5SDimitry Andric } else { 3790b57cec5SDimitry Andric MII = FirstMI_GRNar; 3800b57cec5SDimitry Andric MEE = LastMI_GR128; 3810b57cec5SDimitry Andric } 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric // Check if coalescing seems safe by finding the set of clobbered physreg 3840b57cec5SDimitry Andric // pairs in the region. 3850b57cec5SDimitry Andric BitVector PhysClobbered(getNumRegs()); 3860b57cec5SDimitry Andric MEE++; 3870b57cec5SDimitry Andric for (; MII != MEE; ++MII) { 3880b57cec5SDimitry Andric for (const MachineOperand &MO : MII->operands()) 389*8bcb0991SDimitry Andric if (MO.isReg() && Register::isPhysicalRegister(MO.getReg())) { 3900b57cec5SDimitry Andric for (MCSuperRegIterator SI(MO.getReg(), this, true/*IncludeSelf*/); 3910b57cec5SDimitry Andric SI.isValid(); ++SI) 3920b57cec5SDimitry Andric if (NewRC->contains(*SI)) { 3930b57cec5SDimitry Andric PhysClobbered.set(*SI); 3940b57cec5SDimitry Andric break; 3950b57cec5SDimitry Andric } 3960b57cec5SDimitry Andric } 3970b57cec5SDimitry Andric } 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric // Demand an arbitrary margin of free regs. 4000b57cec5SDimitry Andric unsigned const DemandedFreeGR128 = 3; 4010b57cec5SDimitry Andric if (PhysClobbered.count() > (NewRC->getNumRegs() - DemandedFreeGR128)) 4020b57cec5SDimitry Andric return false; 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric return true; 4050b57cec5SDimitry Andric } 4060b57cec5SDimitry Andric 4070b57cec5SDimitry Andric Register 4080b57cec5SDimitry Andric SystemZRegisterInfo::getFrameRegister(const MachineFunction &MF) const { 4090b57cec5SDimitry Andric const SystemZFrameLowering *TFI = getFrameLowering(MF); 4100b57cec5SDimitry Andric return TFI->hasFP(MF) ? SystemZ::R11D : SystemZ::R15D; 4110b57cec5SDimitry Andric } 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric const TargetRegisterClass * 4140b57cec5SDimitry Andric SystemZRegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const { 4150b57cec5SDimitry Andric if (RC == &SystemZ::CCRRegClass) 4160b57cec5SDimitry Andric return &SystemZ::GR32BitRegClass; 4170b57cec5SDimitry Andric return RC; 4180b57cec5SDimitry Andric } 4190b57cec5SDimitry Andric 420