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