xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
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