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.
getRC32(MachineOperand & MO,const VirtRegMap * VRM,const MachineRegisterInfo * MRI)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.
addHints(ArrayRef<MCPhysReg> Order,SmallVectorImpl<MCPhysReg> & Hints,const TargetRegisterClass * RC,const MachineRegisterInfo * MRI)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
getRegAllocationHints(Register VirtReg,ArrayRef<MCPhysReg> Order,SmallVectorImpl<MCPhysReg> & Hints,const MachineFunction & MF,const VirtRegMap * VRM,const LiveRegMatrix * Matrix) const745ffd83dbSDimitry 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 *
getCalleeSavedRegs(const MachineFunction * MF) const191fe6060f1SDimitry 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 *
getCalleeSavedRegs(const MachineFunction * MF) const198fe6060f1SDimitry 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 *
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID CC) const213fe6060f1SDimitry 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 *
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID CC) const221fe6060f1SDimitry 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
SystemZRegisterInfo(unsigned int RA)236fe6060f1SDimitry Andric SystemZRegisterInfo::SystemZRegisterInfo(unsigned int RA)
237fe6060f1SDimitry Andric : SystemZGenRegisterInfo(RA) {}
238fe6060f1SDimitry Andric
239fe6060f1SDimitry Andric const MCPhysReg *
getCalleeSavedRegs(const MachineFunction * MF) const240fe6060f1SDimitry 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 *
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID CC) const249fe6060f1SDimitry 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
getReservedRegs(const MachineFunction & MF) const2580b57cec5SDimitry 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
eliminateFrameIndex(MachineBasicBlock::iterator MI,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const2850b57cec5SDimitry 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
shouldCoalesce(MachineInstr * MI,const TargetRegisterClass * SrcRC,unsigned SubReg,const TargetRegisterClass * DstRC,unsigned DstSubReg,const TargetRegisterClass * NewRC,LiveIntervals & LIS) const3790b57cec5SDimitry 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
getFrameRegister(const MachineFunction & MF) const4320b57cec5SDimitry 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 *
getCrossCopyRegClass(const TargetRegisterClass * RC) const4420b57cec5SDimitry 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