xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===-- SystemZRegisterInfo.cpp - SystemZ register information ------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #include "SystemZRegisterInfo.h"
10*0b57cec5SDimitry Andric #include "SystemZInstrInfo.h"
11*0b57cec5SDimitry Andric #include "SystemZSubtarget.h"
12*0b57cec5SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h"
13*0b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h"
14*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
15*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
16*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h"
17*0b57cec5SDimitry Andric #include "llvm/CodeGen/VirtRegMap.h"
18*0b57cec5SDimitry Andric 
19*0b57cec5SDimitry Andric using namespace llvm;
20*0b57cec5SDimitry Andric 
21*0b57cec5SDimitry Andric #define GET_REGINFO_TARGET_DESC
22*0b57cec5SDimitry Andric #include "SystemZGenRegisterInfo.inc"
23*0b57cec5SDimitry Andric 
24*0b57cec5SDimitry Andric SystemZRegisterInfo::SystemZRegisterInfo()
25*0b57cec5SDimitry Andric     : SystemZGenRegisterInfo(SystemZ::R14D) {}
26*0b57cec5SDimitry Andric 
27*0b57cec5SDimitry Andric // Given that MO is a GRX32 operand, return either GR32 or GRH32 if MO
28*0b57cec5SDimitry Andric // somehow belongs in it. Otherwise, return GRX32.
29*0b57cec5SDimitry Andric static const TargetRegisterClass *getRC32(MachineOperand &MO,
30*0b57cec5SDimitry Andric                                           const VirtRegMap *VRM,
31*0b57cec5SDimitry Andric                                           const MachineRegisterInfo *MRI) {
32*0b57cec5SDimitry Andric   const TargetRegisterClass *RC = MRI->getRegClass(MO.getReg());
33*0b57cec5SDimitry Andric 
34*0b57cec5SDimitry Andric   if (SystemZ::GR32BitRegClass.hasSubClassEq(RC) ||
35*0b57cec5SDimitry Andric       MO.getSubReg() == SystemZ::subreg_l32 ||
36*0b57cec5SDimitry Andric       MO.getSubReg() == SystemZ::subreg_hl32)
37*0b57cec5SDimitry Andric     return &SystemZ::GR32BitRegClass;
38*0b57cec5SDimitry Andric   if (SystemZ::GRH32BitRegClass.hasSubClassEq(RC) ||
39*0b57cec5SDimitry Andric       MO.getSubReg() == SystemZ::subreg_h32 ||
40*0b57cec5SDimitry Andric       MO.getSubReg() == SystemZ::subreg_hh32)
41*0b57cec5SDimitry Andric     return &SystemZ::GRH32BitRegClass;
42*0b57cec5SDimitry Andric 
43*0b57cec5SDimitry Andric   if (VRM && VRM->hasPhys(MO.getReg())) {
44*0b57cec5SDimitry Andric     unsigned PhysReg = VRM->getPhys(MO.getReg());
45*0b57cec5SDimitry Andric     if (SystemZ::GR32BitRegClass.contains(PhysReg))
46*0b57cec5SDimitry Andric       return &SystemZ::GR32BitRegClass;
47*0b57cec5SDimitry Andric     assert (SystemZ::GRH32BitRegClass.contains(PhysReg) &&
48*0b57cec5SDimitry Andric             "Phys reg not in GR32 or GRH32?");
49*0b57cec5SDimitry Andric     return &SystemZ::GRH32BitRegClass;
50*0b57cec5SDimitry Andric   }
51*0b57cec5SDimitry Andric 
52*0b57cec5SDimitry Andric   assert (RC == &SystemZ::GRX32BitRegClass);
53*0b57cec5SDimitry Andric   return RC;
54*0b57cec5SDimitry Andric }
55*0b57cec5SDimitry Andric 
56*0b57cec5SDimitry Andric // Pass the registers of RC as hints while making sure that if any of these
57*0b57cec5SDimitry Andric // registers are copy hints (and therefore already in Hints), hint them
58*0b57cec5SDimitry Andric // first.
59*0b57cec5SDimitry Andric static void addHints(ArrayRef<MCPhysReg> Order,
60*0b57cec5SDimitry Andric                      SmallVectorImpl<MCPhysReg> &Hints,
61*0b57cec5SDimitry Andric                      const TargetRegisterClass *RC,
62*0b57cec5SDimitry Andric                      const MachineRegisterInfo *MRI) {
63*0b57cec5SDimitry Andric   SmallSet<unsigned, 4> CopyHints;
64*0b57cec5SDimitry Andric   CopyHints.insert(Hints.begin(), Hints.end());
65*0b57cec5SDimitry Andric   Hints.clear();
66*0b57cec5SDimitry Andric   for (MCPhysReg Reg : Order)
67*0b57cec5SDimitry Andric     if (CopyHints.count(Reg) &&
68*0b57cec5SDimitry Andric         RC->contains(Reg) && !MRI->isReserved(Reg))
69*0b57cec5SDimitry Andric       Hints.push_back(Reg);
70*0b57cec5SDimitry Andric   for (MCPhysReg Reg : Order)
71*0b57cec5SDimitry Andric     if (!CopyHints.count(Reg) &&
72*0b57cec5SDimitry Andric         RC->contains(Reg) && !MRI->isReserved(Reg))
73*0b57cec5SDimitry Andric       Hints.push_back(Reg);
74*0b57cec5SDimitry Andric }
75*0b57cec5SDimitry Andric 
76*0b57cec5SDimitry Andric bool
77*0b57cec5SDimitry Andric SystemZRegisterInfo::getRegAllocationHints(unsigned VirtReg,
78*0b57cec5SDimitry Andric                                            ArrayRef<MCPhysReg> Order,
79*0b57cec5SDimitry Andric                                            SmallVectorImpl<MCPhysReg> &Hints,
80*0b57cec5SDimitry Andric                                            const MachineFunction &MF,
81*0b57cec5SDimitry Andric                                            const VirtRegMap *VRM,
82*0b57cec5SDimitry Andric                                            const LiveRegMatrix *Matrix) const {
83*0b57cec5SDimitry Andric   const MachineRegisterInfo *MRI = &MF.getRegInfo();
84*0b57cec5SDimitry Andric   const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
85*0b57cec5SDimitry Andric   const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
86*0b57cec5SDimitry Andric 
87*0b57cec5SDimitry Andric   bool BaseImplRetVal = TargetRegisterInfo::getRegAllocationHints(
88*0b57cec5SDimitry Andric       VirtReg, Order, Hints, MF, VRM, Matrix);
89*0b57cec5SDimitry Andric 
90*0b57cec5SDimitry Andric   if (MRI->getRegClass(VirtReg) == &SystemZ::GRX32BitRegClass) {
91*0b57cec5SDimitry Andric     SmallVector<unsigned, 8> Worklist;
92*0b57cec5SDimitry Andric     SmallSet<unsigned, 4> DoneRegs;
93*0b57cec5SDimitry Andric     Worklist.push_back(VirtReg);
94*0b57cec5SDimitry Andric     while (Worklist.size()) {
95*0b57cec5SDimitry Andric       unsigned Reg = Worklist.pop_back_val();
96*0b57cec5SDimitry Andric       if (!DoneRegs.insert(Reg).second)
97*0b57cec5SDimitry Andric         continue;
98*0b57cec5SDimitry Andric 
99*0b57cec5SDimitry Andric       for (auto &Use : MRI->reg_instructions(Reg)) {
100*0b57cec5SDimitry Andric         // For LOCRMux, see if the other operand is already a high or low
101*0b57cec5SDimitry Andric         // register, and in that case give the corresponding hints for
102*0b57cec5SDimitry Andric         // VirtReg. LOCR instructions need both operands in either high or
103*0b57cec5SDimitry Andric         // low parts. Same handling for SELRMux.
104*0b57cec5SDimitry Andric         if (Use.getOpcode() == SystemZ::LOCRMux ||
105*0b57cec5SDimitry Andric             Use.getOpcode() == SystemZ::SELRMux) {
106*0b57cec5SDimitry Andric           MachineOperand &TrueMO = Use.getOperand(1);
107*0b57cec5SDimitry Andric           MachineOperand &FalseMO = Use.getOperand(2);
108*0b57cec5SDimitry Andric           const TargetRegisterClass *RC =
109*0b57cec5SDimitry Andric             TRI->getCommonSubClass(getRC32(FalseMO, VRM, MRI),
110*0b57cec5SDimitry Andric                                    getRC32(TrueMO, VRM, MRI));
111*0b57cec5SDimitry Andric           if (Use.getOpcode() == SystemZ::SELRMux)
112*0b57cec5SDimitry Andric             RC = TRI->getCommonSubClass(RC,
113*0b57cec5SDimitry Andric                                         getRC32(Use.getOperand(0), VRM, MRI));
114*0b57cec5SDimitry Andric           if (RC && RC != &SystemZ::GRX32BitRegClass) {
115*0b57cec5SDimitry Andric             addHints(Order, Hints, RC, MRI);
116*0b57cec5SDimitry Andric             // Return true to make these hints the only regs available to
117*0b57cec5SDimitry Andric             // RA. This may mean extra spilling but since the alternative is
118*0b57cec5SDimitry Andric             // a jump sequence expansion of the LOCRMux, it is preferred.
119*0b57cec5SDimitry Andric             return true;
120*0b57cec5SDimitry Andric           }
121*0b57cec5SDimitry Andric 
122*0b57cec5SDimitry Andric           // Add the other operand of the LOCRMux to the worklist.
123*0b57cec5SDimitry Andric           unsigned OtherReg =
124*0b57cec5SDimitry Andric             (TrueMO.getReg() == Reg ? FalseMO.getReg() : TrueMO.getReg());
125*0b57cec5SDimitry Andric           if (MRI->getRegClass(OtherReg) == &SystemZ::GRX32BitRegClass)
126*0b57cec5SDimitry Andric             Worklist.push_back(OtherReg);
127*0b57cec5SDimitry Andric         } // end LOCRMux
128*0b57cec5SDimitry Andric         else if (Use.getOpcode() == SystemZ::CHIMux ||
129*0b57cec5SDimitry Andric                  Use.getOpcode() == SystemZ::CFIMux) {
130*0b57cec5SDimitry Andric           if (Use.getOperand(1).getImm() == 0) {
131*0b57cec5SDimitry Andric             bool OnlyLMuxes = true;
132*0b57cec5SDimitry Andric             for (MachineInstr &DefMI : MRI->def_instructions(VirtReg))
133*0b57cec5SDimitry Andric               if (DefMI.getOpcode() != SystemZ::LMux)
134*0b57cec5SDimitry Andric                 OnlyLMuxes = false;
135*0b57cec5SDimitry Andric             if (OnlyLMuxes) {
136*0b57cec5SDimitry Andric               addHints(Order, Hints, &SystemZ::GR32BitRegClass, MRI);
137*0b57cec5SDimitry Andric               // Return false to make these hints preferred but not obligatory.
138*0b57cec5SDimitry Andric               return false;
139*0b57cec5SDimitry Andric             }
140*0b57cec5SDimitry Andric           }
141*0b57cec5SDimitry Andric         } // end CHIMux / CFIMux
142*0b57cec5SDimitry Andric       }
143*0b57cec5SDimitry Andric     }
144*0b57cec5SDimitry Andric   }
145*0b57cec5SDimitry Andric 
146*0b57cec5SDimitry Andric   if (VRM == nullptr)
147*0b57cec5SDimitry Andric     return BaseImplRetVal;
148*0b57cec5SDimitry Andric 
149*0b57cec5SDimitry Andric   // Add any two address hints after any copy hints.
150*0b57cec5SDimitry Andric   SmallSet<unsigned, 4> TwoAddrHints;
151*0b57cec5SDimitry Andric   for (auto &Use : MRI->reg_nodbg_instructions(VirtReg))
152*0b57cec5SDimitry Andric     if (SystemZ::getTwoOperandOpcode(Use.getOpcode()) != -1) {
153*0b57cec5SDimitry Andric       const MachineOperand *VRRegMO = nullptr;
154*0b57cec5SDimitry Andric       const MachineOperand *OtherMO = nullptr;
155*0b57cec5SDimitry Andric       const MachineOperand *CommuMO = nullptr;
156*0b57cec5SDimitry Andric       if (VirtReg == Use.getOperand(0).getReg()) {
157*0b57cec5SDimitry Andric         VRRegMO = &Use.getOperand(0);
158*0b57cec5SDimitry Andric         OtherMO = &Use.getOperand(1);
159*0b57cec5SDimitry Andric         if (Use.isCommutable())
160*0b57cec5SDimitry Andric           CommuMO = &Use.getOperand(2);
161*0b57cec5SDimitry Andric       } else if (VirtReg == Use.getOperand(1).getReg()) {
162*0b57cec5SDimitry Andric         VRRegMO = &Use.getOperand(1);
163*0b57cec5SDimitry Andric         OtherMO = &Use.getOperand(0);
164*0b57cec5SDimitry Andric       } else if (VirtReg == Use.getOperand(2).getReg() && Use.isCommutable()) {
165*0b57cec5SDimitry Andric         VRRegMO = &Use.getOperand(2);
166*0b57cec5SDimitry Andric         OtherMO = &Use.getOperand(0);
167*0b57cec5SDimitry Andric       } else
168*0b57cec5SDimitry Andric         continue;
169*0b57cec5SDimitry Andric 
170*0b57cec5SDimitry Andric       auto tryAddHint = [&](const MachineOperand *MO) -> void {
171*0b57cec5SDimitry Andric         Register Reg = MO->getReg();
172*0b57cec5SDimitry Andric         Register PhysReg = isPhysicalRegister(Reg) ? Reg : VRM->getPhys(Reg);
173*0b57cec5SDimitry Andric         if (PhysReg) {
174*0b57cec5SDimitry Andric           if (MO->getSubReg())
175*0b57cec5SDimitry Andric             PhysReg = getSubReg(PhysReg, MO->getSubReg());
176*0b57cec5SDimitry Andric           if (VRRegMO->getSubReg())
177*0b57cec5SDimitry Andric             PhysReg = getMatchingSuperReg(PhysReg, VRRegMO->getSubReg(),
178*0b57cec5SDimitry Andric                                           MRI->getRegClass(VirtReg));
179*0b57cec5SDimitry Andric           if (!MRI->isReserved(PhysReg) && !is_contained(Hints, PhysReg))
180*0b57cec5SDimitry Andric             TwoAddrHints.insert(PhysReg);
181*0b57cec5SDimitry Andric         }
182*0b57cec5SDimitry Andric       };
183*0b57cec5SDimitry Andric       tryAddHint(OtherMO);
184*0b57cec5SDimitry Andric       if (CommuMO)
185*0b57cec5SDimitry Andric         tryAddHint(CommuMO);
186*0b57cec5SDimitry Andric     }
187*0b57cec5SDimitry Andric   for (MCPhysReg OrderReg : Order)
188*0b57cec5SDimitry Andric     if (TwoAddrHints.count(OrderReg))
189*0b57cec5SDimitry Andric       Hints.push_back(OrderReg);
190*0b57cec5SDimitry Andric 
191*0b57cec5SDimitry Andric   return BaseImplRetVal;
192*0b57cec5SDimitry Andric }
193*0b57cec5SDimitry Andric 
194*0b57cec5SDimitry Andric const MCPhysReg *
195*0b57cec5SDimitry Andric SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
196*0b57cec5SDimitry Andric   const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
197*0b57cec5SDimitry Andric   if (MF->getFunction().getCallingConv() == CallingConv::AnyReg)
198*0b57cec5SDimitry Andric     return Subtarget.hasVector()? CSR_SystemZ_AllRegs_Vector_SaveList
199*0b57cec5SDimitry Andric                                 : CSR_SystemZ_AllRegs_SaveList;
200*0b57cec5SDimitry Andric   if (MF->getSubtarget().getTargetLowering()->supportSwiftError() &&
201*0b57cec5SDimitry Andric       MF->getFunction().getAttributes().hasAttrSomewhere(
202*0b57cec5SDimitry Andric           Attribute::SwiftError))
203*0b57cec5SDimitry Andric     return CSR_SystemZ_SwiftError_SaveList;
204*0b57cec5SDimitry Andric   return CSR_SystemZ_SaveList;
205*0b57cec5SDimitry Andric }
206*0b57cec5SDimitry Andric 
207*0b57cec5SDimitry Andric const uint32_t *
208*0b57cec5SDimitry Andric SystemZRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
209*0b57cec5SDimitry Andric                                           CallingConv::ID CC) const {
210*0b57cec5SDimitry Andric   const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
211*0b57cec5SDimitry Andric   if (CC == CallingConv::AnyReg)
212*0b57cec5SDimitry Andric     return Subtarget.hasVector()? CSR_SystemZ_AllRegs_Vector_RegMask
213*0b57cec5SDimitry Andric                                 : CSR_SystemZ_AllRegs_RegMask;
214*0b57cec5SDimitry Andric   if (MF.getSubtarget().getTargetLowering()->supportSwiftError() &&
215*0b57cec5SDimitry Andric       MF.getFunction().getAttributes().hasAttrSomewhere(
216*0b57cec5SDimitry Andric           Attribute::SwiftError))
217*0b57cec5SDimitry Andric     return CSR_SystemZ_SwiftError_RegMask;
218*0b57cec5SDimitry Andric   return CSR_SystemZ_RegMask;
219*0b57cec5SDimitry Andric }
220*0b57cec5SDimitry Andric 
221*0b57cec5SDimitry Andric BitVector
222*0b57cec5SDimitry Andric SystemZRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
223*0b57cec5SDimitry Andric   BitVector Reserved(getNumRegs());
224*0b57cec5SDimitry Andric   const SystemZFrameLowering *TFI = getFrameLowering(MF);
225*0b57cec5SDimitry Andric 
226*0b57cec5SDimitry Andric   if (TFI->hasFP(MF)) {
227*0b57cec5SDimitry Andric     // R11D is the frame pointer.  Reserve all aliases.
228*0b57cec5SDimitry Andric     Reserved.set(SystemZ::R11D);
229*0b57cec5SDimitry Andric     Reserved.set(SystemZ::R11L);
230*0b57cec5SDimitry Andric     Reserved.set(SystemZ::R11H);
231*0b57cec5SDimitry Andric     Reserved.set(SystemZ::R10Q);
232*0b57cec5SDimitry Andric   }
233*0b57cec5SDimitry Andric 
234*0b57cec5SDimitry Andric   // R15D is the stack pointer.  Reserve all aliases.
235*0b57cec5SDimitry Andric   Reserved.set(SystemZ::R15D);
236*0b57cec5SDimitry Andric   Reserved.set(SystemZ::R15L);
237*0b57cec5SDimitry Andric   Reserved.set(SystemZ::R15H);
238*0b57cec5SDimitry Andric   Reserved.set(SystemZ::R14Q);
239*0b57cec5SDimitry Andric 
240*0b57cec5SDimitry Andric   // A0 and A1 hold the thread pointer.
241*0b57cec5SDimitry Andric   Reserved.set(SystemZ::A0);
242*0b57cec5SDimitry Andric   Reserved.set(SystemZ::A1);
243*0b57cec5SDimitry Andric 
244*0b57cec5SDimitry Andric   // FPC is the floating-point control register.
245*0b57cec5SDimitry Andric   Reserved.set(SystemZ::FPC);
246*0b57cec5SDimitry Andric 
247*0b57cec5SDimitry Andric   return Reserved;
248*0b57cec5SDimitry Andric }
249*0b57cec5SDimitry Andric 
250*0b57cec5SDimitry Andric void
251*0b57cec5SDimitry Andric SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,
252*0b57cec5SDimitry Andric                                          int SPAdj, unsigned FIOperandNum,
253*0b57cec5SDimitry Andric                                          RegScavenger *RS) const {
254*0b57cec5SDimitry Andric   assert(SPAdj == 0 && "Outgoing arguments should be part of the frame");
255*0b57cec5SDimitry Andric 
256*0b57cec5SDimitry Andric   MachineBasicBlock &MBB = *MI->getParent();
257*0b57cec5SDimitry Andric   MachineFunction &MF = *MBB.getParent();
258*0b57cec5SDimitry Andric   auto *TII =
259*0b57cec5SDimitry Andric       static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo());
260*0b57cec5SDimitry Andric   const SystemZFrameLowering *TFI = getFrameLowering(MF);
261*0b57cec5SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
262*0b57cec5SDimitry Andric 
263*0b57cec5SDimitry Andric   // Decompose the frame index into a base and offset.
264*0b57cec5SDimitry Andric   int FrameIndex = MI->getOperand(FIOperandNum).getIndex();
265*0b57cec5SDimitry Andric   unsigned BasePtr;
266*0b57cec5SDimitry Andric   int64_t Offset = (TFI->getFrameIndexReference(MF, FrameIndex, BasePtr) +
267*0b57cec5SDimitry Andric                     MI->getOperand(FIOperandNum + 1).getImm());
268*0b57cec5SDimitry Andric 
269*0b57cec5SDimitry Andric   // Special handling of dbg_value instructions.
270*0b57cec5SDimitry Andric   if (MI->isDebugValue()) {
271*0b57cec5SDimitry Andric     MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, /*isDef*/ false);
272*0b57cec5SDimitry Andric     MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
273*0b57cec5SDimitry Andric     return;
274*0b57cec5SDimitry Andric   }
275*0b57cec5SDimitry Andric 
276*0b57cec5SDimitry Andric   // See if the offset is in range, or if an equivalent instruction that
277*0b57cec5SDimitry Andric   // accepts the offset exists.
278*0b57cec5SDimitry Andric   unsigned Opcode = MI->getOpcode();
279*0b57cec5SDimitry Andric   unsigned OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset);
280*0b57cec5SDimitry Andric   if (OpcodeForOffset) {
281*0b57cec5SDimitry Andric     if (OpcodeForOffset == SystemZ::LE &&
282*0b57cec5SDimitry Andric         MF.getSubtarget<SystemZSubtarget>().hasVector()) {
283*0b57cec5SDimitry Andric       // If LE is ok for offset, use LDE instead on z13.
284*0b57cec5SDimitry Andric       OpcodeForOffset = SystemZ::LDE32;
285*0b57cec5SDimitry Andric     }
286*0b57cec5SDimitry Andric     MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false);
287*0b57cec5SDimitry Andric   }
288*0b57cec5SDimitry Andric   else {
289*0b57cec5SDimitry Andric     // Create an anchor point that is in range.  Start at 0xffff so that
290*0b57cec5SDimitry Andric     // can use LLILH to load the immediate.
291*0b57cec5SDimitry Andric     int64_t OldOffset = Offset;
292*0b57cec5SDimitry Andric     int64_t Mask = 0xffff;
293*0b57cec5SDimitry Andric     do {
294*0b57cec5SDimitry Andric       Offset = OldOffset & Mask;
295*0b57cec5SDimitry Andric       OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset);
296*0b57cec5SDimitry Andric       Mask >>= 1;
297*0b57cec5SDimitry Andric       assert(Mask && "One offset must be OK");
298*0b57cec5SDimitry Andric     } while (!OpcodeForOffset);
299*0b57cec5SDimitry Andric 
300*0b57cec5SDimitry Andric     unsigned ScratchReg =
301*0b57cec5SDimitry Andric       MF.getRegInfo().createVirtualRegister(&SystemZ::ADDR64BitRegClass);
302*0b57cec5SDimitry Andric     int64_t HighOffset = OldOffset - Offset;
303*0b57cec5SDimitry Andric 
304*0b57cec5SDimitry Andric     if (MI->getDesc().TSFlags & SystemZII::HasIndex
305*0b57cec5SDimitry Andric         && MI->getOperand(FIOperandNum + 2).getReg() == 0) {
306*0b57cec5SDimitry Andric       // Load the offset into the scratch register and use it as an index.
307*0b57cec5SDimitry Andric       // The scratch register then dies here.
308*0b57cec5SDimitry Andric       TII->loadImmediate(MBB, MI, ScratchReg, HighOffset);
309*0b57cec5SDimitry Andric       MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false);
310*0b57cec5SDimitry Andric       MI->getOperand(FIOperandNum + 2).ChangeToRegister(ScratchReg,
311*0b57cec5SDimitry Andric                                                         false, false, true);
312*0b57cec5SDimitry Andric     } else {
313*0b57cec5SDimitry Andric       // Load the anchor address into a scratch register.
314*0b57cec5SDimitry Andric       unsigned LAOpcode = TII->getOpcodeForOffset(SystemZ::LA, HighOffset);
315*0b57cec5SDimitry Andric       if (LAOpcode)
316*0b57cec5SDimitry Andric         BuildMI(MBB, MI, DL, TII->get(LAOpcode),ScratchReg)
317*0b57cec5SDimitry Andric           .addReg(BasePtr).addImm(HighOffset).addReg(0);
318*0b57cec5SDimitry Andric       else {
319*0b57cec5SDimitry Andric         // Load the high offset into the scratch register and use it as
320*0b57cec5SDimitry Andric         // an index.
321*0b57cec5SDimitry Andric         TII->loadImmediate(MBB, MI, ScratchReg, HighOffset);
322*0b57cec5SDimitry Andric         BuildMI(MBB, MI, DL, TII->get(SystemZ::AGR),ScratchReg)
323*0b57cec5SDimitry Andric           .addReg(ScratchReg, RegState::Kill).addReg(BasePtr);
324*0b57cec5SDimitry Andric       }
325*0b57cec5SDimitry Andric 
326*0b57cec5SDimitry Andric       // Use the scratch register as the base.  It then dies here.
327*0b57cec5SDimitry Andric       MI->getOperand(FIOperandNum).ChangeToRegister(ScratchReg,
328*0b57cec5SDimitry Andric                                                     false, false, true);
329*0b57cec5SDimitry Andric     }
330*0b57cec5SDimitry Andric   }
331*0b57cec5SDimitry Andric   MI->setDesc(TII->get(OpcodeForOffset));
332*0b57cec5SDimitry Andric   MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
333*0b57cec5SDimitry Andric }
334*0b57cec5SDimitry Andric 
335*0b57cec5SDimitry Andric bool SystemZRegisterInfo::shouldCoalesce(MachineInstr *MI,
336*0b57cec5SDimitry Andric                                   const TargetRegisterClass *SrcRC,
337*0b57cec5SDimitry Andric                                   unsigned SubReg,
338*0b57cec5SDimitry Andric                                   const TargetRegisterClass *DstRC,
339*0b57cec5SDimitry Andric                                   unsigned DstSubReg,
340*0b57cec5SDimitry Andric                                   const TargetRegisterClass *NewRC,
341*0b57cec5SDimitry Andric                                   LiveIntervals &LIS) const {
342*0b57cec5SDimitry Andric   assert (MI->isCopy() && "Only expecting COPY instructions");
343*0b57cec5SDimitry Andric 
344*0b57cec5SDimitry Andric   // Coalesce anything which is not a COPY involving a subreg to/from GR128.
345*0b57cec5SDimitry Andric   if (!(NewRC->hasSuperClassEq(&SystemZ::GR128BitRegClass) &&
346*0b57cec5SDimitry Andric         (getRegSizeInBits(*SrcRC) <= 64 || getRegSizeInBits(*DstRC) <= 64)))
347*0b57cec5SDimitry Andric     return true;
348*0b57cec5SDimitry Andric 
349*0b57cec5SDimitry Andric   // Allow coalescing of a GR128 subreg COPY only if the live ranges are small
350*0b57cec5SDimitry Andric   // and local to one MBB with not too much interferring registers. Otherwise
351*0b57cec5SDimitry Andric   // regalloc may run out of registers.
352*0b57cec5SDimitry Andric 
353*0b57cec5SDimitry Andric   unsigned WideOpNo = (getRegSizeInBits(*SrcRC) == 128 ? 1 : 0);
354*0b57cec5SDimitry Andric   unsigned GR128Reg = MI->getOperand(WideOpNo).getReg();
355*0b57cec5SDimitry Andric   unsigned GRNarReg = MI->getOperand((WideOpNo == 1) ? 0 : 1).getReg();
356*0b57cec5SDimitry Andric   LiveInterval &IntGR128 = LIS.getInterval(GR128Reg);
357*0b57cec5SDimitry Andric   LiveInterval &IntGRNar = LIS.getInterval(GRNarReg);
358*0b57cec5SDimitry Andric 
359*0b57cec5SDimitry Andric   // Check that the two virtual registers are local to MBB.
360*0b57cec5SDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
361*0b57cec5SDimitry Andric   MachineInstr *FirstMI_GR128 =
362*0b57cec5SDimitry Andric     LIS.getInstructionFromIndex(IntGR128.beginIndex());
363*0b57cec5SDimitry Andric   MachineInstr *FirstMI_GRNar =
364*0b57cec5SDimitry Andric     LIS.getInstructionFromIndex(IntGRNar.beginIndex());
365*0b57cec5SDimitry Andric   MachineInstr *LastMI_GR128 = LIS.getInstructionFromIndex(IntGR128.endIndex());
366*0b57cec5SDimitry Andric   MachineInstr *LastMI_GRNar = LIS.getInstructionFromIndex(IntGRNar.endIndex());
367*0b57cec5SDimitry Andric   if ((!FirstMI_GR128 || FirstMI_GR128->getParent() != MBB) ||
368*0b57cec5SDimitry Andric       (!FirstMI_GRNar || FirstMI_GRNar->getParent() != MBB) ||
369*0b57cec5SDimitry Andric       (!LastMI_GR128 || LastMI_GR128->getParent() != MBB) ||
370*0b57cec5SDimitry Andric       (!LastMI_GRNar || LastMI_GRNar->getParent() != MBB))
371*0b57cec5SDimitry Andric     return false;
372*0b57cec5SDimitry Andric 
373*0b57cec5SDimitry Andric   MachineBasicBlock::iterator MII = nullptr, MEE = nullptr;
374*0b57cec5SDimitry Andric   if (WideOpNo == 1) {
375*0b57cec5SDimitry Andric     MII = FirstMI_GR128;
376*0b57cec5SDimitry Andric     MEE = LastMI_GRNar;
377*0b57cec5SDimitry Andric   } else {
378*0b57cec5SDimitry Andric     MII = FirstMI_GRNar;
379*0b57cec5SDimitry Andric     MEE = LastMI_GR128;
380*0b57cec5SDimitry Andric   }
381*0b57cec5SDimitry Andric 
382*0b57cec5SDimitry Andric   // Check if coalescing seems safe by finding the set of clobbered physreg
383*0b57cec5SDimitry Andric   // pairs in the region.
384*0b57cec5SDimitry Andric   BitVector PhysClobbered(getNumRegs());
385*0b57cec5SDimitry Andric   MEE++;
386*0b57cec5SDimitry Andric   for (; MII != MEE; ++MII) {
387*0b57cec5SDimitry Andric     for (const MachineOperand &MO : MII->operands())
388*0b57cec5SDimitry Andric       if (MO.isReg() && isPhysicalRegister(MO.getReg())) {
389*0b57cec5SDimitry Andric         for (MCSuperRegIterator SI(MO.getReg(), this, true/*IncludeSelf*/);
390*0b57cec5SDimitry Andric              SI.isValid(); ++SI)
391*0b57cec5SDimitry Andric           if (NewRC->contains(*SI)) {
392*0b57cec5SDimitry Andric             PhysClobbered.set(*SI);
393*0b57cec5SDimitry Andric             break;
394*0b57cec5SDimitry Andric           }
395*0b57cec5SDimitry Andric       }
396*0b57cec5SDimitry Andric   }
397*0b57cec5SDimitry Andric 
398*0b57cec5SDimitry Andric   // Demand an arbitrary margin of free regs.
399*0b57cec5SDimitry Andric   unsigned const DemandedFreeGR128 = 3;
400*0b57cec5SDimitry Andric   if (PhysClobbered.count() > (NewRC->getNumRegs() - DemandedFreeGR128))
401*0b57cec5SDimitry Andric     return false;
402*0b57cec5SDimitry Andric 
403*0b57cec5SDimitry Andric   return true;
404*0b57cec5SDimitry Andric }
405*0b57cec5SDimitry Andric 
406*0b57cec5SDimitry Andric Register
407*0b57cec5SDimitry Andric SystemZRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
408*0b57cec5SDimitry Andric   const SystemZFrameLowering *TFI = getFrameLowering(MF);
409*0b57cec5SDimitry Andric   return TFI->hasFP(MF) ? SystemZ::R11D : SystemZ::R15D;
410*0b57cec5SDimitry Andric }
411*0b57cec5SDimitry Andric 
412*0b57cec5SDimitry Andric const TargetRegisterClass *
413*0b57cec5SDimitry Andric SystemZRegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {
414*0b57cec5SDimitry Andric   if (RC == &SystemZ::CCRRegClass)
415*0b57cec5SDimitry Andric     return &SystemZ::GR32BitRegClass;
416*0b57cec5SDimitry Andric   return RC;
417*0b57cec5SDimitry Andric }
418*0b57cec5SDimitry Andric 
419