xref: /src/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp (revision 7a6dacaca14b62ca4b74406814becb87a3fefac0)
159d6cff9SDimitry Andric //===-- SystemZRegisterInfo.cpp - SystemZ register information ------------===//
259d6cff9SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
659d6cff9SDimitry Andric //
759d6cff9SDimitry Andric //===----------------------------------------------------------------------===//
859d6cff9SDimitry Andric 
959d6cff9SDimitry Andric #include "SystemZRegisterInfo.h"
107ab83427SDimitry Andric #include "SystemZInstrInfo.h"
115ca98fd9SDimitry Andric #include "SystemZSubtarget.h"
12044eb2f6SDimitry Andric #include "llvm/ADT/SmallSet.h"
13344a3780SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h"
1459d6cff9SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
1559d6cff9SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
16044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h"
17044eb2f6SDimitry Andric #include "llvm/CodeGen/VirtRegMap.h"
18344a3780SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
195ca98fd9SDimitry Andric 
205ca98fd9SDimitry Andric using namespace llvm;
2159d6cff9SDimitry Andric 
2259d6cff9SDimitry Andric #define GET_REGINFO_TARGET_DESC
2359d6cff9SDimitry Andric #include "SystemZGenRegisterInfo.inc"
2459d6cff9SDimitry Andric 
25044eb2f6SDimitry Andric // Given that MO is a GRX32 operand, return either GR32 or GRH32 if MO
26044eb2f6SDimitry Andric // somehow belongs in it. Otherwise, return GRX32.
getRC32(MachineOperand & MO,const VirtRegMap * VRM,const MachineRegisterInfo * MRI)27044eb2f6SDimitry Andric static const TargetRegisterClass *getRC32(MachineOperand &MO,
28044eb2f6SDimitry Andric                                           const VirtRegMap *VRM,
29044eb2f6SDimitry Andric                                           const MachineRegisterInfo *MRI) {
30044eb2f6SDimitry Andric   const TargetRegisterClass *RC = MRI->getRegClass(MO.getReg());
31044eb2f6SDimitry Andric 
32044eb2f6SDimitry Andric   if (SystemZ::GR32BitRegClass.hasSubClassEq(RC) ||
337fa27ce4SDimitry Andric       MO.getSubReg() == SystemZ::subreg_ll32 ||
347fa27ce4SDimitry Andric       MO.getSubReg() == SystemZ::subreg_l32)
35044eb2f6SDimitry Andric     return &SystemZ::GR32BitRegClass;
36044eb2f6SDimitry Andric   if (SystemZ::GRH32BitRegClass.hasSubClassEq(RC) ||
377fa27ce4SDimitry Andric       MO.getSubReg() == SystemZ::subreg_lh32 ||
387fa27ce4SDimitry Andric       MO.getSubReg() == SystemZ::subreg_h32)
39044eb2f6SDimitry Andric     return &SystemZ::GRH32BitRegClass;
40044eb2f6SDimitry Andric 
41044eb2f6SDimitry Andric   if (VRM && VRM->hasPhys(MO.getReg())) {
421d5ae102SDimitry Andric     Register PhysReg = VRM->getPhys(MO.getReg());
43044eb2f6SDimitry Andric     if (SystemZ::GR32BitRegClass.contains(PhysReg))
44044eb2f6SDimitry Andric       return &SystemZ::GR32BitRegClass;
45044eb2f6SDimitry Andric     assert (SystemZ::GRH32BitRegClass.contains(PhysReg) &&
46044eb2f6SDimitry Andric             "Phys reg not in GR32 or GRH32?");
47044eb2f6SDimitry Andric     return &SystemZ::GRH32BitRegClass;
48044eb2f6SDimitry Andric   }
49044eb2f6SDimitry Andric 
50044eb2f6SDimitry Andric   assert (RC == &SystemZ::GRX32BitRegClass);
51044eb2f6SDimitry Andric   return RC;
52044eb2f6SDimitry Andric }
53044eb2f6SDimitry Andric 
54e6d15924SDimitry Andric // Pass the registers of RC as hints while making sure that if any of these
55e6d15924SDimitry Andric // registers are copy hints (and therefore already in Hints), hint them
56e6d15924SDimitry Andric // first.
addHints(ArrayRef<MCPhysReg> Order,SmallVectorImpl<MCPhysReg> & Hints,const TargetRegisterClass * RC,const MachineRegisterInfo * MRI)57e6d15924SDimitry Andric static void addHints(ArrayRef<MCPhysReg> Order,
58e6d15924SDimitry Andric                      SmallVectorImpl<MCPhysReg> &Hints,
59e6d15924SDimitry Andric                      const TargetRegisterClass *RC,
60e6d15924SDimitry Andric                      const MachineRegisterInfo *MRI) {
61e6d15924SDimitry Andric   SmallSet<unsigned, 4> CopyHints;
62e6d15924SDimitry Andric   CopyHints.insert(Hints.begin(), Hints.end());
63e6d15924SDimitry Andric   Hints.clear();
64e6d15924SDimitry Andric   for (MCPhysReg Reg : Order)
65e6d15924SDimitry Andric     if (CopyHints.count(Reg) &&
66e6d15924SDimitry Andric         RC->contains(Reg) && !MRI->isReserved(Reg))
67e6d15924SDimitry Andric       Hints.push_back(Reg);
68e6d15924SDimitry Andric   for (MCPhysReg Reg : Order)
69e6d15924SDimitry Andric     if (!CopyHints.count(Reg) &&
70e6d15924SDimitry Andric         RC->contains(Reg) && !MRI->isReserved(Reg))
71e6d15924SDimitry Andric       Hints.push_back(Reg);
72e6d15924SDimitry Andric }
73e6d15924SDimitry Andric 
getRegAllocationHints(Register VirtReg,ArrayRef<MCPhysReg> Order,SmallVectorImpl<MCPhysReg> & Hints,const MachineFunction & MF,const VirtRegMap * VRM,const LiveRegMatrix * Matrix) const74cfca06d7SDimitry Andric bool SystemZRegisterInfo::getRegAllocationHints(
75cfca06d7SDimitry Andric     Register VirtReg, ArrayRef<MCPhysReg> Order,
76cfca06d7SDimitry Andric     SmallVectorImpl<MCPhysReg> &Hints, const MachineFunction &MF,
77cfca06d7SDimitry Andric     const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const {
78044eb2f6SDimitry Andric   const MachineRegisterInfo *MRI = &MF.getRegInfo();
79e6d15924SDimitry Andric   const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
80e6d15924SDimitry Andric   const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
81d8e91e46SDimitry Andric 
82d8e91e46SDimitry Andric   bool BaseImplRetVal = TargetRegisterInfo::getRegAllocationHints(
83d8e91e46SDimitry Andric       VirtReg, Order, Hints, MF, VRM, Matrix);
84d8e91e46SDimitry Andric 
85706b4fc4SDimitry Andric   if (VRM != nullptr) {
86706b4fc4SDimitry Andric     // Add any two address hints after any copy hints.
87706b4fc4SDimitry Andric     SmallSet<unsigned, 4> TwoAddrHints;
88706b4fc4SDimitry Andric     for (auto &Use : MRI->reg_nodbg_instructions(VirtReg))
89706b4fc4SDimitry Andric       if (SystemZ::getTwoOperandOpcode(Use.getOpcode()) != -1) {
90706b4fc4SDimitry Andric         const MachineOperand *VRRegMO = nullptr;
91706b4fc4SDimitry Andric         const MachineOperand *OtherMO = nullptr;
92706b4fc4SDimitry Andric         const MachineOperand *CommuMO = nullptr;
93706b4fc4SDimitry Andric         if (VirtReg == Use.getOperand(0).getReg()) {
94706b4fc4SDimitry Andric           VRRegMO = &Use.getOperand(0);
95706b4fc4SDimitry Andric           OtherMO = &Use.getOperand(1);
96706b4fc4SDimitry Andric           if (Use.isCommutable())
97706b4fc4SDimitry Andric             CommuMO = &Use.getOperand(2);
98706b4fc4SDimitry Andric         } else if (VirtReg == Use.getOperand(1).getReg()) {
99706b4fc4SDimitry Andric           VRRegMO = &Use.getOperand(1);
100706b4fc4SDimitry Andric           OtherMO = &Use.getOperand(0);
101706b4fc4SDimitry Andric         } else if (VirtReg == Use.getOperand(2).getReg() &&
102706b4fc4SDimitry Andric                    Use.isCommutable()) {
103706b4fc4SDimitry Andric           VRRegMO = &Use.getOperand(2);
104706b4fc4SDimitry Andric           OtherMO = &Use.getOperand(0);
105706b4fc4SDimitry Andric         } else
106706b4fc4SDimitry Andric           continue;
107706b4fc4SDimitry Andric 
108706b4fc4SDimitry Andric         auto tryAddHint = [&](const MachineOperand *MO) -> void {
109706b4fc4SDimitry Andric           Register Reg = MO->getReg();
110e3b55780SDimitry Andric           Register PhysReg =
111e3b55780SDimitry Andric               Reg.isPhysical() ? Reg : Register(VRM->getPhys(Reg));
112706b4fc4SDimitry Andric           if (PhysReg) {
113706b4fc4SDimitry Andric             if (MO->getSubReg())
114706b4fc4SDimitry Andric               PhysReg = getSubReg(PhysReg, MO->getSubReg());
115706b4fc4SDimitry Andric             if (VRRegMO->getSubReg())
116706b4fc4SDimitry Andric               PhysReg = getMatchingSuperReg(PhysReg, VRRegMO->getSubReg(),
117706b4fc4SDimitry Andric                                             MRI->getRegClass(VirtReg));
118706b4fc4SDimitry Andric             if (!MRI->isReserved(PhysReg) && !is_contained(Hints, PhysReg))
119706b4fc4SDimitry Andric               TwoAddrHints.insert(PhysReg);
120706b4fc4SDimitry Andric           }
121706b4fc4SDimitry Andric         };
122706b4fc4SDimitry Andric         tryAddHint(OtherMO);
123706b4fc4SDimitry Andric         if (CommuMO)
124706b4fc4SDimitry Andric           tryAddHint(CommuMO);
125706b4fc4SDimitry Andric       }
126706b4fc4SDimitry Andric     for (MCPhysReg OrderReg : Order)
127706b4fc4SDimitry Andric       if (TwoAddrHints.count(OrderReg))
128706b4fc4SDimitry Andric         Hints.push_back(OrderReg);
129706b4fc4SDimitry Andric   }
130706b4fc4SDimitry Andric 
131044eb2f6SDimitry Andric   if (MRI->getRegClass(VirtReg) == &SystemZ::GRX32BitRegClass) {
132cfca06d7SDimitry Andric     SmallVector<Register, 8> Worklist;
133cfca06d7SDimitry Andric     SmallSet<Register, 4> DoneRegs;
134044eb2f6SDimitry Andric     Worklist.push_back(VirtReg);
135044eb2f6SDimitry Andric     while (Worklist.size()) {
136cfca06d7SDimitry Andric       Register Reg = Worklist.pop_back_val();
137044eb2f6SDimitry Andric       if (!DoneRegs.insert(Reg).second)
138044eb2f6SDimitry Andric         continue;
139044eb2f6SDimitry Andric 
140e6d15924SDimitry Andric       for (auto &Use : MRI->reg_instructions(Reg)) {
141044eb2f6SDimitry Andric         // For LOCRMux, see if the other operand is already a high or low
142e6d15924SDimitry Andric         // register, and in that case give the corresponding hints for
143044eb2f6SDimitry Andric         // VirtReg. LOCR instructions need both operands in either high or
144e6d15924SDimitry Andric         // low parts. Same handling for SELRMux.
145e6d15924SDimitry Andric         if (Use.getOpcode() == SystemZ::LOCRMux ||
146e6d15924SDimitry Andric             Use.getOpcode() == SystemZ::SELRMux) {
147044eb2f6SDimitry Andric           MachineOperand &TrueMO = Use.getOperand(1);
148044eb2f6SDimitry Andric           MachineOperand &FalseMO = Use.getOperand(2);
149044eb2f6SDimitry Andric           const TargetRegisterClass *RC =
150044eb2f6SDimitry Andric             TRI->getCommonSubClass(getRC32(FalseMO, VRM, MRI),
151044eb2f6SDimitry Andric                                    getRC32(TrueMO, VRM, MRI));
152e6d15924SDimitry Andric           if (Use.getOpcode() == SystemZ::SELRMux)
153e6d15924SDimitry Andric             RC = TRI->getCommonSubClass(RC,
154e6d15924SDimitry Andric                                         getRC32(Use.getOperand(0), VRM, MRI));
155044eb2f6SDimitry Andric           if (RC && RC != &SystemZ::GRX32BitRegClass) {
156e6d15924SDimitry Andric             addHints(Order, Hints, RC, MRI);
157044eb2f6SDimitry Andric             // Return true to make these hints the only regs available to
158044eb2f6SDimitry Andric             // RA. This may mean extra spilling but since the alternative is
159044eb2f6SDimitry Andric             // a jump sequence expansion of the LOCRMux, it is preferred.
160044eb2f6SDimitry Andric             return true;
161044eb2f6SDimitry Andric           }
162044eb2f6SDimitry Andric 
163044eb2f6SDimitry Andric           // Add the other operand of the LOCRMux to the worklist.
1641d5ae102SDimitry Andric           Register OtherReg =
165044eb2f6SDimitry Andric               (TrueMO.getReg() == Reg ? FalseMO.getReg() : TrueMO.getReg());
166044eb2f6SDimitry Andric           if (MRI->getRegClass(OtherReg) == &SystemZ::GRX32BitRegClass)
167044eb2f6SDimitry Andric             Worklist.push_back(OtherReg);
168e6d15924SDimitry Andric         } // end LOCRMux
169e6d15924SDimitry Andric         else if (Use.getOpcode() == SystemZ::CHIMux ||
170e6d15924SDimitry Andric                  Use.getOpcode() == SystemZ::CFIMux) {
171e6d15924SDimitry Andric           if (Use.getOperand(1).getImm() == 0) {
172e6d15924SDimitry Andric             bool OnlyLMuxes = true;
173e6d15924SDimitry Andric             for (MachineInstr &DefMI : MRI->def_instructions(VirtReg))
174e6d15924SDimitry Andric               if (DefMI.getOpcode() != SystemZ::LMux)
175e6d15924SDimitry Andric                 OnlyLMuxes = false;
176e6d15924SDimitry Andric             if (OnlyLMuxes) {
177e6d15924SDimitry Andric               addHints(Order, Hints, &SystemZ::GR32BitRegClass, MRI);
178e6d15924SDimitry Andric               // Return false to make these hints preferred but not obligatory.
179e6d15924SDimitry Andric               return false;
180e6d15924SDimitry Andric             }
181e6d15924SDimitry Andric           }
182e6d15924SDimitry Andric         } // end CHIMux / CFIMux
183044eb2f6SDimitry Andric       }
184044eb2f6SDimitry Andric     }
185044eb2f6SDimitry Andric   }
186044eb2f6SDimitry Andric 
187d8e91e46SDimitry Andric   return BaseImplRetVal;
188044eb2f6SDimitry Andric }
189044eb2f6SDimitry Andric 
1905ca98fd9SDimitry Andric const MCPhysReg *
getCalleeSavedRegs(const MachineFunction * MF) const191344a3780SDimitry Andric SystemZXPLINK64Registers::getCalleeSavedRegs(const MachineFunction *MF) const {
192c0981da4SDimitry Andric   const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
193c0981da4SDimitry Andric   return Subtarget.hasVector() ? CSR_SystemZ_XPLINK64_Vector_SaveList
194c0981da4SDimitry Andric                                : CSR_SystemZ_XPLINK64_SaveList;
195344a3780SDimitry Andric }
196344a3780SDimitry Andric 
197344a3780SDimitry Andric const MCPhysReg *
getCalleeSavedRegs(const MachineFunction * MF) const198344a3780SDimitry Andric SystemZELFRegisters::getCalleeSavedRegs(const MachineFunction *MF) const {
199eb11fae6SDimitry Andric   const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
200706b4fc4SDimitry Andric   if (MF->getFunction().getCallingConv() == CallingConv::GHC)
201706b4fc4SDimitry Andric     return CSR_SystemZ_NoRegs_SaveList;
202eb11fae6SDimitry Andric   if (MF->getFunction().getCallingConv() == CallingConv::AnyReg)
203eb11fae6SDimitry Andric     return Subtarget.hasVector()? CSR_SystemZ_AllRegs_Vector_SaveList
204eb11fae6SDimitry Andric                                 : CSR_SystemZ_AllRegs_SaveList;
20501095a5dSDimitry Andric   if (MF->getSubtarget().getTargetLowering()->supportSwiftError() &&
206044eb2f6SDimitry Andric       MF->getFunction().getAttributes().hasAttrSomewhere(
20701095a5dSDimitry Andric           Attribute::SwiftError))
20801095a5dSDimitry Andric     return CSR_SystemZ_SwiftError_SaveList;
209344a3780SDimitry Andric   return CSR_SystemZ_ELF_SaveList;
2105ca98fd9SDimitry Andric }
21159d6cff9SDimitry Andric 
2125ca98fd9SDimitry Andric const uint32_t *
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID CC) const213344a3780SDimitry Andric SystemZXPLINK64Registers::getCallPreservedMask(const MachineFunction &MF,
214344a3780SDimitry Andric                                                CallingConv::ID CC) const {
215c0981da4SDimitry Andric   const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
216c0981da4SDimitry Andric   return Subtarget.hasVector() ? CSR_SystemZ_XPLINK64_Vector_RegMask
217c0981da4SDimitry Andric                                : CSR_SystemZ_XPLINK64_RegMask;
218344a3780SDimitry Andric }
219344a3780SDimitry Andric 
220344a3780SDimitry Andric const uint32_t *
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID CC) const221344a3780SDimitry Andric SystemZELFRegisters::getCallPreservedMask(const MachineFunction &MF,
2225a5ac124SDimitry Andric                                           CallingConv::ID CC) const {
223eb11fae6SDimitry Andric   const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
224706b4fc4SDimitry Andric   if (CC == CallingConv::GHC)
225706b4fc4SDimitry Andric     return CSR_SystemZ_NoRegs_RegMask;
226eb11fae6SDimitry Andric   if (CC == CallingConv::AnyReg)
227eb11fae6SDimitry Andric     return Subtarget.hasVector()? CSR_SystemZ_AllRegs_Vector_RegMask
228eb11fae6SDimitry Andric                                 : CSR_SystemZ_AllRegs_RegMask;
22901095a5dSDimitry Andric   if (MF.getSubtarget().getTargetLowering()->supportSwiftError() &&
230044eb2f6SDimitry Andric       MF.getFunction().getAttributes().hasAttrSomewhere(
23101095a5dSDimitry Andric           Attribute::SwiftError))
23201095a5dSDimitry Andric     return CSR_SystemZ_SwiftError_RegMask;
233344a3780SDimitry Andric   return CSR_SystemZ_ELF_RegMask;
234344a3780SDimitry Andric }
235344a3780SDimitry Andric 
SystemZRegisterInfo(unsigned int RA)236344a3780SDimitry Andric SystemZRegisterInfo::SystemZRegisterInfo(unsigned int RA)
237344a3780SDimitry Andric     : SystemZGenRegisterInfo(RA) {}
238344a3780SDimitry Andric 
239344a3780SDimitry Andric const MCPhysReg *
getCalleeSavedRegs(const MachineFunction * MF) const240344a3780SDimitry Andric SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
241344a3780SDimitry Andric 
242344a3780SDimitry Andric   const SystemZSubtarget *Subtarget = &MF->getSubtarget<SystemZSubtarget>();
243344a3780SDimitry Andric   SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters();
244344a3780SDimitry Andric 
245344a3780SDimitry Andric   return Regs->getCalleeSavedRegs(MF);
246344a3780SDimitry Andric }
247344a3780SDimitry Andric 
248344a3780SDimitry Andric const uint32_t *
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID CC) const249344a3780SDimitry Andric SystemZRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
250344a3780SDimitry Andric                                           CallingConv::ID CC) const {
251344a3780SDimitry Andric 
252344a3780SDimitry Andric   const SystemZSubtarget *Subtarget = &MF.getSubtarget<SystemZSubtarget>();
253344a3780SDimitry Andric   SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters();
254344a3780SDimitry Andric   return Regs->getCallPreservedMask(MF, CC);
25559d6cff9SDimitry Andric }
25659d6cff9SDimitry Andric 
25759d6cff9SDimitry Andric BitVector
getReservedRegs(const MachineFunction & MF) const25859d6cff9SDimitry Andric SystemZRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
25959d6cff9SDimitry Andric   BitVector Reserved(getNumRegs());
260ee8648bdSDimitry Andric   const SystemZFrameLowering *TFI = getFrameLowering(MF);
261344a3780SDimitry Andric   const SystemZSubtarget *Subtarget = &MF.getSubtarget<SystemZSubtarget>();
262344a3780SDimitry Andric   SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters();
263344a3780SDimitry Andric   if (TFI->hasFP(MF))
264344a3780SDimitry Andric     // The frame pointer. Reserve all aliases.
265344a3780SDimitry Andric     for (MCRegAliasIterator AI(Regs->getFramePointerRegister(), this, true);
266344a3780SDimitry Andric          AI.isValid(); ++AI)
267344a3780SDimitry Andric       Reserved.set(*AI);
26859d6cff9SDimitry Andric 
269344a3780SDimitry Andric   // Reserve all aliases for the stack pointer.
270344a3780SDimitry Andric   for (MCRegAliasIterator AI(Regs->getStackPointerRegister(), this, true);
271344a3780SDimitry Andric        AI.isValid(); ++AI)
272344a3780SDimitry Andric     Reserved.set(*AI);
273b915e9e0SDimitry Andric 
274b915e9e0SDimitry Andric   // A0 and A1 hold the thread pointer.
275b915e9e0SDimitry Andric   Reserved.set(SystemZ::A0);
276b915e9e0SDimitry Andric   Reserved.set(SystemZ::A1);
277b915e9e0SDimitry Andric 
278e6d15924SDimitry Andric   // FPC is the floating-point control register.
279e6d15924SDimitry Andric   Reserved.set(SystemZ::FPC);
280e6d15924SDimitry Andric 
28159d6cff9SDimitry Andric   return Reserved;
28259d6cff9SDimitry Andric }
28359d6cff9SDimitry Andric 
284e3b55780SDimitry Andric bool
eliminateFrameIndex(MachineBasicBlock::iterator MI,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const28559d6cff9SDimitry Andric SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,
28659d6cff9SDimitry Andric                                          int SPAdj, unsigned FIOperandNum,
28759d6cff9SDimitry Andric                                          RegScavenger *RS) const {
28859d6cff9SDimitry Andric   assert(SPAdj == 0 && "Outgoing arguments should be part of the frame");
28959d6cff9SDimitry Andric 
29059d6cff9SDimitry Andric   MachineBasicBlock &MBB = *MI->getParent();
29159d6cff9SDimitry Andric   MachineFunction &MF = *MBB.getParent();
292145449b1SDimitry Andric   auto *TII = MF.getSubtarget<SystemZSubtarget>().getInstrInfo();
293ee8648bdSDimitry Andric   const SystemZFrameLowering *TFI = getFrameLowering(MF);
29459d6cff9SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
29559d6cff9SDimitry Andric 
29659d6cff9SDimitry Andric   // Decompose the frame index into a base and offset.
29759d6cff9SDimitry Andric   int FrameIndex = MI->getOperand(FIOperandNum).getIndex();
298cfca06d7SDimitry Andric   Register BasePtr;
299b60736ecSDimitry Andric   int64_t Offset =
300b60736ecSDimitry Andric       (TFI->getFrameIndexReference(MF, FrameIndex, BasePtr).getFixed() +
30159d6cff9SDimitry Andric        MI->getOperand(FIOperandNum + 1).getImm());
30259d6cff9SDimitry Andric 
30359d6cff9SDimitry Andric   // Special handling of dbg_value instructions.
30459d6cff9SDimitry Andric   if (MI->isDebugValue()) {
30559d6cff9SDimitry Andric     MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, /*isDef*/ false);
306344a3780SDimitry Andric     if (MI->isNonListDebugValue()) {
307cfca06d7SDimitry Andric       MI->getDebugOffset().ChangeToImmediate(Offset);
308344a3780SDimitry Andric     } else {
309344a3780SDimitry Andric       unsigned OpIdx = MI->getDebugOperandIndex(&MI->getOperand(FIOperandNum));
310344a3780SDimitry Andric       SmallVector<uint64_t, 3> Ops;
311344a3780SDimitry Andric       DIExpression::appendOffset(
312344a3780SDimitry Andric           Ops, TFI->getFrameIndexReference(MF, FrameIndex, BasePtr).getFixed());
313344a3780SDimitry Andric       MI->getDebugExpressionOp().setMetadata(
314344a3780SDimitry Andric           DIExpression::appendOpsToArg(MI->getDebugExpression(), Ops, OpIdx));
315344a3780SDimitry Andric     }
316e3b55780SDimitry Andric     return false;
31759d6cff9SDimitry Andric   }
31859d6cff9SDimitry Andric 
31959d6cff9SDimitry Andric   // See if the offset is in range, or if an equivalent instruction that
32059d6cff9SDimitry Andric   // accepts the offset exists.
32159d6cff9SDimitry Andric   unsigned Opcode = MI->getOpcode();
322145449b1SDimitry Andric   unsigned OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset, &*MI);
32301095a5dSDimitry Andric   if (OpcodeForOffset) {
32401095a5dSDimitry Andric     if (OpcodeForOffset == SystemZ::LE &&
32501095a5dSDimitry Andric         MF.getSubtarget<SystemZSubtarget>().hasVector()) {
32601095a5dSDimitry Andric       // If LE is ok for offset, use LDE instead on z13.
32701095a5dSDimitry Andric       OpcodeForOffset = SystemZ::LDE32;
32801095a5dSDimitry Andric     }
32959d6cff9SDimitry Andric     MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false);
33001095a5dSDimitry Andric   }
33159d6cff9SDimitry Andric   else {
33259d6cff9SDimitry Andric     // Create an anchor point that is in range.  Start at 0xffff so that
33359d6cff9SDimitry Andric     // can use LLILH to load the immediate.
33459d6cff9SDimitry Andric     int64_t OldOffset = Offset;
33559d6cff9SDimitry Andric     int64_t Mask = 0xffff;
33659d6cff9SDimitry Andric     do {
33759d6cff9SDimitry Andric       Offset = OldOffset & Mask;
3385ca98fd9SDimitry Andric       OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset);
33959d6cff9SDimitry Andric       Mask >>= 1;
34059d6cff9SDimitry Andric       assert(Mask && "One offset must be OK");
34159d6cff9SDimitry Andric     } while (!OpcodeForOffset);
34259d6cff9SDimitry Andric 
3431d5ae102SDimitry Andric     Register ScratchReg =
34459d6cff9SDimitry Andric         MF.getRegInfo().createVirtualRegister(&SystemZ::ADDR64BitRegClass);
34559d6cff9SDimitry Andric     int64_t HighOffset = OldOffset - Offset;
34659d6cff9SDimitry Andric 
34759d6cff9SDimitry Andric     if (MI->getDesc().TSFlags & SystemZII::HasIndex
34859d6cff9SDimitry Andric         && MI->getOperand(FIOperandNum + 2).getReg() == 0) {
34959d6cff9SDimitry Andric       // Load the offset into the scratch register and use it as an index.
35059d6cff9SDimitry Andric       // The scratch register then dies here.
3515ca98fd9SDimitry Andric       TII->loadImmediate(MBB, MI, ScratchReg, HighOffset);
35259d6cff9SDimitry Andric       MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false);
35359d6cff9SDimitry Andric       MI->getOperand(FIOperandNum + 2).ChangeToRegister(ScratchReg,
35459d6cff9SDimitry Andric                                                         false, false, true);
35559d6cff9SDimitry Andric     } else {
35659d6cff9SDimitry Andric       // Load the anchor address into a scratch register.
3575ca98fd9SDimitry Andric       unsigned LAOpcode = TII->getOpcodeForOffset(SystemZ::LA, HighOffset);
35859d6cff9SDimitry Andric       if (LAOpcode)
3595ca98fd9SDimitry Andric         BuildMI(MBB, MI, DL, TII->get(LAOpcode),ScratchReg)
36059d6cff9SDimitry Andric           .addReg(BasePtr).addImm(HighOffset).addReg(0);
36159d6cff9SDimitry Andric       else {
36259d6cff9SDimitry Andric         // Load the high offset into the scratch register and use it as
36359d6cff9SDimitry Andric         // an index.
3645ca98fd9SDimitry Andric         TII->loadImmediate(MBB, MI, ScratchReg, HighOffset);
365b60736ecSDimitry Andric         BuildMI(MBB, MI, DL, TII->get(SystemZ::LA), ScratchReg)
366b60736ecSDimitry Andric           .addReg(BasePtr, RegState::Kill).addImm(0).addReg(ScratchReg);
36759d6cff9SDimitry Andric       }
36859d6cff9SDimitry Andric 
36959d6cff9SDimitry Andric       // Use the scratch register as the base.  It then dies here.
37059d6cff9SDimitry Andric       MI->getOperand(FIOperandNum).ChangeToRegister(ScratchReg,
37159d6cff9SDimitry Andric                                                     false, false, true);
37259d6cff9SDimitry Andric     }
37359d6cff9SDimitry Andric   }
3745ca98fd9SDimitry Andric   MI->setDesc(TII->get(OpcodeForOffset));
37559d6cff9SDimitry Andric   MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
376e3b55780SDimitry Andric   return false;
37759d6cff9SDimitry Andric }
37859d6cff9SDimitry Andric 
shouldCoalesce(MachineInstr * MI,const TargetRegisterClass * SrcRC,unsigned SubReg,const TargetRegisterClass * DstRC,unsigned DstSubReg,const TargetRegisterClass * NewRC,LiveIntervals & LIS) const379044eb2f6SDimitry Andric bool SystemZRegisterInfo::shouldCoalesce(MachineInstr *MI,
380044eb2f6SDimitry Andric                                          const TargetRegisterClass *SrcRC,
381044eb2f6SDimitry Andric                                          unsigned SubReg,
382044eb2f6SDimitry Andric                                          const TargetRegisterClass *DstRC,
383044eb2f6SDimitry Andric                                          unsigned DstSubReg,
384044eb2f6SDimitry Andric                                          const TargetRegisterClass *NewRC,
385044eb2f6SDimitry Andric                                          LiveIntervals &LIS) const {
386044eb2f6SDimitry Andric   assert (MI->isCopy() && "Only expecting COPY instructions");
387044eb2f6SDimitry Andric 
388044eb2f6SDimitry Andric   // Coalesce anything which is not a COPY involving a subreg to/from GR128.
389044eb2f6SDimitry Andric   if (!(NewRC->hasSuperClassEq(&SystemZ::GR128BitRegClass) &&
3904df029ccSDimitry Andric         (getRegSizeInBits(*SrcRC) <= 64 || getRegSizeInBits(*DstRC) <= 64) &&
3914df029ccSDimitry Andric         !MI->getOperand(1).isUndef()))
392044eb2f6SDimitry Andric     return true;
393044eb2f6SDimitry Andric 
394312c0ed1SDimitry Andric   // Allow coalescing of a GR128 subreg COPY only if the subreg liverange is
395312c0ed1SDimitry Andric   // local to one MBB with not too many interferring physreg clobbers. Otherwise
396044eb2f6SDimitry Andric   // regalloc may run out of registers.
397312c0ed1SDimitry Andric   unsigned SubregOpIdx = getRegSizeInBits(*SrcRC) == 128 ? 0 : 1;
398312c0ed1SDimitry Andric   LiveInterval &LI = LIS.getInterval(MI->getOperand(SubregOpIdx).getReg());
399044eb2f6SDimitry Andric 
400312c0ed1SDimitry Andric   // Check that the subreg is local to MBB.
401044eb2f6SDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
402312c0ed1SDimitry Andric   MachineInstr *FirstMI = LIS.getInstructionFromIndex(LI.beginIndex());
403312c0ed1SDimitry Andric   MachineInstr *LastMI = LIS.getInstructionFromIndex(LI.endIndex());
404312c0ed1SDimitry Andric   if (!FirstMI || FirstMI->getParent() != MBB ||
405312c0ed1SDimitry Andric       !LastMI || LastMI->getParent() != MBB)
406044eb2f6SDimitry Andric     return false;
407044eb2f6SDimitry Andric 
408044eb2f6SDimitry Andric   // Check if coalescing seems safe by finding the set of clobbered physreg
409044eb2f6SDimitry Andric   // pairs in the region.
410044eb2f6SDimitry Andric   BitVector PhysClobbered(getNumRegs());
411312c0ed1SDimitry Andric   for (MachineBasicBlock::iterator MII = FirstMI,
412312c0ed1SDimitry Andric                                    MEE = std::next(LastMI->getIterator());
413312c0ed1SDimitry Andric        MII != MEE; ++MII)
414044eb2f6SDimitry Andric     for (const MachineOperand &MO : MII->operands())
415e3b55780SDimitry Andric       if (MO.isReg() && MO.getReg().isPhysical()) {
4167fa27ce4SDimitry Andric         for (MCPhysReg SI : superregs_inclusive(MO.getReg()))
4177fa27ce4SDimitry Andric           if (NewRC->contains(SI)) {
4187fa27ce4SDimitry Andric             PhysClobbered.set(SI);
419044eb2f6SDimitry Andric             break;
420044eb2f6SDimitry Andric           }
421044eb2f6SDimitry Andric       }
422044eb2f6SDimitry Andric 
423044eb2f6SDimitry Andric   // Demand an arbitrary margin of free regs.
424044eb2f6SDimitry Andric   unsigned const DemandedFreeGR128 = 3;
425044eb2f6SDimitry Andric   if (PhysClobbered.count() > (NewRC->getNumRegs() - DemandedFreeGR128))
426044eb2f6SDimitry Andric     return false;
427044eb2f6SDimitry Andric 
428044eb2f6SDimitry Andric   return true;
429044eb2f6SDimitry Andric }
430044eb2f6SDimitry Andric 
431e6d15924SDimitry Andric Register
getFrameRegister(const MachineFunction & MF) const43259d6cff9SDimitry Andric SystemZRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
433ee8648bdSDimitry Andric   const SystemZFrameLowering *TFI = getFrameLowering(MF);
434344a3780SDimitry Andric   const SystemZSubtarget *Subtarget = &MF.getSubtarget<SystemZSubtarget>();
435344a3780SDimitry Andric   SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters();
436344a3780SDimitry Andric 
437344a3780SDimitry Andric   return TFI->hasFP(MF) ? Regs->getFramePointerRegister()
438344a3780SDimitry Andric                         : Regs->getStackPointerRegister();
43959d6cff9SDimitry Andric }
440eb11fae6SDimitry Andric 
441eb11fae6SDimitry Andric const TargetRegisterClass *
getCrossCopyRegClass(const TargetRegisterClass * RC) const442eb11fae6SDimitry Andric SystemZRegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {
443eb11fae6SDimitry Andric   if (RC == &SystemZ::CCRRegClass)
444eb11fae6SDimitry Andric     return &SystemZ::GR32BitRegClass;
445eb11fae6SDimitry Andric   return RC;
446eb11fae6SDimitry Andric }
447eb11fae6SDimitry Andric 
448