15f613dfdSUlrich Weigand //===-- SystemZRegisterInfo.cpp - SystemZ register information ------------===//
25f613dfdSUlrich Weigand //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65f613dfdSUlrich Weigand //
75f613dfdSUlrich Weigand //===----------------------------------------------------------------------===//
85f613dfdSUlrich Weigand
95f613dfdSUlrich Weigand #include "SystemZRegisterInfo.h"
106bda14b3SChandler Carruth #include "SystemZInstrInfo.h"
11673b3afaSEric Christopher #include "SystemZSubtarget.h"
12d2000b45SStephen Tozer #include "llvm/ADT/SmallSet.h"
13f6774130SStephen Tozer #include "llvm/CodeGen/LiveIntervals.h"
145f613dfdSUlrich Weigand #include "llvm/CodeGen/MachineInstrBuilder.h"
155f613dfdSUlrich Weigand #include "llvm/CodeGen/MachineRegisterInfo.h"
161be62f03SDavid Blaikie #include "llvm/CodeGen/TargetFrameLowering.h"
174b017e68SJonas Paulsson #include "llvm/CodeGen/VirtRegMap.h"
18f6774130SStephen Tozer #include "llvm/IR/DebugInfoMetadata.h"
195f613dfdSUlrich Weigand
20d174b72aSChandler Carruth using namespace llvm;
21d174b72aSChandler Carruth
225f613dfdSUlrich Weigand #define GET_REGINFO_TARGET_DESC
235f613dfdSUlrich Weigand #include "SystemZGenRegisterInfo.inc"
245f613dfdSUlrich Weigand
254b017e68SJonas Paulsson // Given that MO is a GRX32 operand, return either GR32 or GRH32 if MO
264b017e68SJonas Paulsson // somehow belongs in it. Otherwise, return GRX32.
getRC32(MachineOperand & MO,const VirtRegMap * VRM,const MachineRegisterInfo * MRI)274b017e68SJonas Paulsson static const TargetRegisterClass *getRC32(MachineOperand &MO,
284b017e68SJonas Paulsson const VirtRegMap *VRM,
294b017e68SJonas Paulsson const MachineRegisterInfo *MRI) {
304b017e68SJonas Paulsson const TargetRegisterClass *RC = MRI->getRegClass(MO.getReg());
314b017e68SJonas Paulsson
324b017e68SJonas Paulsson if (SystemZ::GR32BitRegClass.hasSubClassEq(RC) ||
3312e3a588SJonas Paulsson MO.getSubReg() == SystemZ::subreg_l32 ||
3412e3a588SJonas Paulsson MO.getSubReg() == SystemZ::subreg_hl32)
354b017e68SJonas Paulsson return &SystemZ::GR32BitRegClass;
364b017e68SJonas Paulsson if (SystemZ::GRH32BitRegClass.hasSubClassEq(RC) ||
3712e3a588SJonas Paulsson MO.getSubReg() == SystemZ::subreg_h32 ||
3812e3a588SJonas Paulsson MO.getSubReg() == SystemZ::subreg_hh32)
394b017e68SJonas Paulsson return &SystemZ::GRH32BitRegClass;
404b017e68SJonas Paulsson
414b017e68SJonas Paulsson if (VRM && VRM->hasPhys(MO.getReg())) {
420c476111SDaniel Sanders Register PhysReg = VRM->getPhys(MO.getReg());
434b017e68SJonas Paulsson if (SystemZ::GR32BitRegClass.contains(PhysReg))
444b017e68SJonas Paulsson return &SystemZ::GR32BitRegClass;
454b017e68SJonas Paulsson assert (SystemZ::GRH32BitRegClass.contains(PhysReg) &&
464b017e68SJonas Paulsson "Phys reg not in GR32 or GRH32?");
474b017e68SJonas Paulsson return &SystemZ::GRH32BitRegClass;
484b017e68SJonas Paulsson }
494b017e68SJonas Paulsson
504b017e68SJonas Paulsson assert (RC == &SystemZ::GRX32BitRegClass);
514b017e68SJonas Paulsson return RC;
524b017e68SJonas Paulsson }
534b017e68SJonas Paulsson
54129826cdSJonas Paulsson // Pass the registers of RC as hints while making sure that if any of these
55129826cdSJonas Paulsson // registers are copy hints (and therefore already in Hints), hint them
56129826cdSJonas Paulsson // first.
addHints(ArrayRef<MCPhysReg> Order,SmallVectorImpl<MCPhysReg> & Hints,const TargetRegisterClass * RC,const MachineRegisterInfo * MRI)57129826cdSJonas Paulsson static void addHints(ArrayRef<MCPhysReg> Order,
58129826cdSJonas Paulsson SmallVectorImpl<MCPhysReg> &Hints,
59129826cdSJonas Paulsson const TargetRegisterClass *RC,
60129826cdSJonas Paulsson const MachineRegisterInfo *MRI) {
61129826cdSJonas Paulsson SmallSet<unsigned, 4> CopyHints;
62129826cdSJonas Paulsson CopyHints.insert(Hints.begin(), Hints.end());
63129826cdSJonas Paulsson Hints.clear();
64129826cdSJonas Paulsson for (MCPhysReg Reg : Order)
65129826cdSJonas Paulsson if (CopyHints.count(Reg) &&
66129826cdSJonas Paulsson RC->contains(Reg) && !MRI->isReserved(Reg))
67129826cdSJonas Paulsson Hints.push_back(Reg);
68129826cdSJonas Paulsson for (MCPhysReg Reg : Order)
69129826cdSJonas Paulsson if (!CopyHints.count(Reg) &&
70129826cdSJonas Paulsson RC->contains(Reg) && !MRI->isReserved(Reg))
71129826cdSJonas Paulsson Hints.push_back(Reg);
72129826cdSJonas Paulsson }
73129826cdSJonas Paulsson
getRegAllocationHints(Register VirtReg,ArrayRef<MCPhysReg> Order,SmallVectorImpl<MCPhysReg> & Hints,const MachineFunction & MF,const VirtRegMap * VRM,const LiveRegMatrix * Matrix) const746011627fSMatt Arsenault bool SystemZRegisterInfo::getRegAllocationHints(
756011627fSMatt Arsenault Register VirtReg, ArrayRef<MCPhysReg> Order,
766011627fSMatt Arsenault SmallVectorImpl<MCPhysReg> &Hints, const MachineFunction &MF,
776011627fSMatt Arsenault const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const {
784b017e68SJonas Paulsson const MachineRegisterInfo *MRI = &MF.getRegInfo();
79fdc4ea34SJonas Paulsson const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
80fdc4ea34SJonas Paulsson const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
81e79b1b98SJonas Paulsson
82e79b1b98SJonas Paulsson bool BaseImplRetVal = TargetRegisterInfo::getRegAllocationHints(
83e79b1b98SJonas Paulsson VirtReg, Order, Hints, MF, VRM, Matrix);
84e79b1b98SJonas Paulsson
859fcebad5SJonas Paulsson if (VRM != nullptr) {
869fcebad5SJonas Paulsson // Add any two address hints after any copy hints.
879fcebad5SJonas Paulsson SmallSet<unsigned, 4> TwoAddrHints;
889fcebad5SJonas Paulsson for (auto &Use : MRI->reg_nodbg_instructions(VirtReg))
899fcebad5SJonas Paulsson if (SystemZ::getTwoOperandOpcode(Use.getOpcode()) != -1) {
909fcebad5SJonas Paulsson const MachineOperand *VRRegMO = nullptr;
919fcebad5SJonas Paulsson const MachineOperand *OtherMO = nullptr;
929fcebad5SJonas Paulsson const MachineOperand *CommuMO = nullptr;
939fcebad5SJonas Paulsson if (VirtReg == Use.getOperand(0).getReg()) {
949fcebad5SJonas Paulsson VRRegMO = &Use.getOperand(0);
959fcebad5SJonas Paulsson OtherMO = &Use.getOperand(1);
969fcebad5SJonas Paulsson if (Use.isCommutable())
979fcebad5SJonas Paulsson CommuMO = &Use.getOperand(2);
989fcebad5SJonas Paulsson } else if (VirtReg == Use.getOperand(1).getReg()) {
999fcebad5SJonas Paulsson VRRegMO = &Use.getOperand(1);
1009fcebad5SJonas Paulsson OtherMO = &Use.getOperand(0);
1019fcebad5SJonas Paulsson } else if (VirtReg == Use.getOperand(2).getReg() &&
1029fcebad5SJonas Paulsson Use.isCommutable()) {
1039fcebad5SJonas Paulsson VRRegMO = &Use.getOperand(2);
1049fcebad5SJonas Paulsson OtherMO = &Use.getOperand(0);
1059fcebad5SJonas Paulsson } else
1069fcebad5SJonas Paulsson continue;
1079fcebad5SJonas Paulsson
1089fcebad5SJonas Paulsson auto tryAddHint = [&](const MachineOperand *MO) -> void {
1099fcebad5SJonas Paulsson Register Reg = MO->getReg();
1104cfc4025SMircea Trofin Register PhysReg = Register::isPhysicalRegister(Reg)
1114cfc4025SMircea Trofin ? Reg
1124cfc4025SMircea Trofin : Register(VRM->getPhys(Reg));
1139fcebad5SJonas Paulsson if (PhysReg) {
1149fcebad5SJonas Paulsson if (MO->getSubReg())
1159fcebad5SJonas Paulsson PhysReg = getSubReg(PhysReg, MO->getSubReg());
1169fcebad5SJonas Paulsson if (VRRegMO->getSubReg())
1179fcebad5SJonas Paulsson PhysReg = getMatchingSuperReg(PhysReg, VRRegMO->getSubReg(),
1189fcebad5SJonas Paulsson MRI->getRegClass(VirtReg));
1199fcebad5SJonas Paulsson if (!MRI->isReserved(PhysReg) && !is_contained(Hints, PhysReg))
1209fcebad5SJonas Paulsson TwoAddrHints.insert(PhysReg);
1219fcebad5SJonas Paulsson }
1229fcebad5SJonas Paulsson };
1239fcebad5SJonas Paulsson tryAddHint(OtherMO);
1249fcebad5SJonas Paulsson if (CommuMO)
1259fcebad5SJonas Paulsson tryAddHint(CommuMO);
1269fcebad5SJonas Paulsson }
1279fcebad5SJonas Paulsson for (MCPhysReg OrderReg : Order)
1289fcebad5SJonas Paulsson if (TwoAddrHints.count(OrderReg))
1299fcebad5SJonas Paulsson Hints.push_back(OrderReg);
1309fcebad5SJonas Paulsson }
1319fcebad5SJonas Paulsson
1324b017e68SJonas Paulsson if (MRI->getRegClass(VirtReg) == &SystemZ::GRX32BitRegClass) {
1336011627fSMatt Arsenault SmallVector<Register, 8> Worklist;
1346011627fSMatt Arsenault SmallSet<Register, 4> DoneRegs;
1354b017e68SJonas Paulsson Worklist.push_back(VirtReg);
1364b017e68SJonas Paulsson while (Worklist.size()) {
1376011627fSMatt Arsenault Register Reg = Worklist.pop_back_val();
1384b017e68SJonas Paulsson if (!DoneRegs.insert(Reg).second)
1394b017e68SJonas Paulsson continue;
1404b017e68SJonas Paulsson
1410f0a8b77SUlrich Weigand for (auto &Use : MRI->reg_instructions(Reg)) {
1424b017e68SJonas Paulsson // For LOCRMux, see if the other operand is already a high or low
1430f0a8b77SUlrich Weigand // register, and in that case give the corresponding hints for
1444b017e68SJonas Paulsson // VirtReg. LOCR instructions need both operands in either high or
1450f0a8b77SUlrich Weigand // low parts. Same handling for SELRMux.
1460f0a8b77SUlrich Weigand if (Use.getOpcode() == SystemZ::LOCRMux ||
1470f0a8b77SUlrich Weigand Use.getOpcode() == SystemZ::SELRMux) {
1484b017e68SJonas Paulsson MachineOperand &TrueMO = Use.getOperand(1);
1494b017e68SJonas Paulsson MachineOperand &FalseMO = Use.getOperand(2);
1504b017e68SJonas Paulsson const TargetRegisterClass *RC =
1514b017e68SJonas Paulsson TRI->getCommonSubClass(getRC32(FalseMO, VRM, MRI),
1524b017e68SJonas Paulsson getRC32(TrueMO, VRM, MRI));
1530f0a8b77SUlrich Weigand if (Use.getOpcode() == SystemZ::SELRMux)
1540f0a8b77SUlrich Weigand RC = TRI->getCommonSubClass(RC,
1550f0a8b77SUlrich Weigand getRC32(Use.getOperand(0), VRM, MRI));
1564b017e68SJonas Paulsson if (RC && RC != &SystemZ::GRX32BitRegClass) {
157129826cdSJonas Paulsson addHints(Order, Hints, RC, MRI);
1584b017e68SJonas Paulsson // Return true to make these hints the only regs available to
1594b017e68SJonas Paulsson // RA. This may mean extra spilling but since the alternative is
1604b017e68SJonas Paulsson // a jump sequence expansion of the LOCRMux, it is preferred.
1614b017e68SJonas Paulsson return true;
1624b017e68SJonas Paulsson }
1634b017e68SJonas Paulsson
1644b017e68SJonas Paulsson // Add the other operand of the LOCRMux to the worklist.
1650c476111SDaniel Sanders Register OtherReg =
1664b017e68SJonas Paulsson (TrueMO.getReg() == Reg ? FalseMO.getReg() : TrueMO.getReg());
1674b017e68SJonas Paulsson if (MRI->getRegClass(OtherReg) == &SystemZ::GRX32BitRegClass)
1684b017e68SJonas Paulsson Worklist.push_back(OtherReg);
169129826cdSJonas Paulsson } // end LOCRMux
170129826cdSJonas Paulsson else if (Use.getOpcode() == SystemZ::CHIMux ||
171129826cdSJonas Paulsson Use.getOpcode() == SystemZ::CFIMux) {
172129826cdSJonas Paulsson if (Use.getOperand(1).getImm() == 0) {
173129826cdSJonas Paulsson bool OnlyLMuxes = true;
174129826cdSJonas Paulsson for (MachineInstr &DefMI : MRI->def_instructions(VirtReg))
175129826cdSJonas Paulsson if (DefMI.getOpcode() != SystemZ::LMux)
176129826cdSJonas Paulsson OnlyLMuxes = false;
177129826cdSJonas Paulsson if (OnlyLMuxes) {
178129826cdSJonas Paulsson addHints(Order, Hints, &SystemZ::GR32BitRegClass, MRI);
179129826cdSJonas Paulsson // Return false to make these hints preferred but not obligatory.
180129826cdSJonas Paulsson return false;
181129826cdSJonas Paulsson }
182129826cdSJonas Paulsson }
183129826cdSJonas Paulsson } // end CHIMux / CFIMux
1844b017e68SJonas Paulsson }
1854b017e68SJonas Paulsson }
1864b017e68SJonas Paulsson }
1874b017e68SJonas Paulsson
188e79b1b98SJonas Paulsson return BaseImplRetVal;
1894b017e68SJonas Paulsson }
1904b017e68SJonas Paulsson
191840beec2SCraig Topper const MCPhysReg *
getCalleeSavedRegs(const MachineFunction * MF) const1928a7e2fb5SNeumann Hon SystemZXPLINK64Registers::getCalleeSavedRegs(const MachineFunction *MF) const {
1930a950a2eSKai Nacke const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
1940a950a2eSKai Nacke return Subtarget.hasVector() ? CSR_SystemZ_XPLINK64_Vector_SaveList
1950a950a2eSKai Nacke : CSR_SystemZ_XPLINK64_SaveList;
1968a7e2fb5SNeumann Hon }
1978a7e2fb5SNeumann Hon
1988a7e2fb5SNeumann Hon const MCPhysReg *
getCalleeSavedRegs(const MachineFunction * MF) const1998a7e2fb5SNeumann Hon SystemZELFRegisters::getCalleeSavedRegs(const MachineFunction *MF) const {
2008b19be46SUlrich Weigand const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
20122f94291SUlrich Weigand if (MF->getFunction().getCallingConv() == CallingConv::GHC)
20222f94291SUlrich Weigand return CSR_SystemZ_NoRegs_SaveList;
2038b19be46SUlrich Weigand if (MF->getFunction().getCallingConv() == CallingConv::AnyReg)
2048b19be46SUlrich Weigand return Subtarget.hasVector()? CSR_SystemZ_AllRegs_Vector_SaveList
2058b19be46SUlrich Weigand : CSR_SystemZ_AllRegs_SaveList;
206893110ecSBryan Chan if (MF->getSubtarget().getTargetLowering()->supportSwiftError() &&
207f1caa283SMatthias Braun MF->getFunction().getAttributes().hasAttrSomewhere(
208893110ecSBryan Chan Attribute::SwiftError))
209893110ecSBryan Chan return CSR_SystemZ_SwiftError_SaveList;
2108b624a31SYusra Syeda return CSR_SystemZ_ELF_SaveList;
21102bb0ec3SRichard Sandiford }
2125f613dfdSUlrich Weigand
21302bb0ec3SRichard Sandiford const uint32_t *
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID CC) const2148a7e2fb5SNeumann Hon SystemZXPLINK64Registers::getCallPreservedMask(const MachineFunction &MF,
2158a7e2fb5SNeumann Hon CallingConv::ID CC) const {
2160a950a2eSKai Nacke const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
2170a950a2eSKai Nacke return Subtarget.hasVector() ? CSR_SystemZ_XPLINK64_Vector_RegMask
2180a950a2eSKai Nacke : CSR_SystemZ_XPLINK64_RegMask;
2198a7e2fb5SNeumann Hon }
2208a7e2fb5SNeumann Hon
2218a7e2fb5SNeumann Hon const uint32_t *
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID CC) const2228a7e2fb5SNeumann Hon SystemZELFRegisters::getCallPreservedMask(const MachineFunction &MF,
2239deb75d1SEric Christopher CallingConv::ID CC) const {
2248b19be46SUlrich Weigand const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
22522f94291SUlrich Weigand if (CC == CallingConv::GHC)
22622f94291SUlrich Weigand return CSR_SystemZ_NoRegs_RegMask;
2278b19be46SUlrich Weigand if (CC == CallingConv::AnyReg)
2288b19be46SUlrich Weigand return Subtarget.hasVector()? CSR_SystemZ_AllRegs_Vector_RegMask
2298b19be46SUlrich Weigand : CSR_SystemZ_AllRegs_RegMask;
230893110ecSBryan Chan if (MF.getSubtarget().getTargetLowering()->supportSwiftError() &&
231f1caa283SMatthias Braun MF.getFunction().getAttributes().hasAttrSomewhere(
232893110ecSBryan Chan Attribute::SwiftError))
233893110ecSBryan Chan return CSR_SystemZ_SwiftError_RegMask;
2348b624a31SYusra Syeda return CSR_SystemZ_ELF_RegMask;
2355f613dfdSUlrich Weigand }
2365f613dfdSUlrich Weigand
SystemZRegisterInfo(unsigned int RA)2378a7e2fb5SNeumann Hon SystemZRegisterInfo::SystemZRegisterInfo(unsigned int RA)
2388a7e2fb5SNeumann Hon : SystemZGenRegisterInfo(RA) {}
2398a7e2fb5SNeumann Hon
2408a7e2fb5SNeumann Hon const MCPhysReg *
getCalleeSavedRegs(const MachineFunction * MF) const2418a7e2fb5SNeumann Hon SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
2428a7e2fb5SNeumann Hon
2438a7e2fb5SNeumann Hon const SystemZSubtarget *Subtarget = &MF->getSubtarget<SystemZSubtarget>();
2448a7e2fb5SNeumann Hon SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters();
2458a7e2fb5SNeumann Hon
2468a7e2fb5SNeumann Hon return Regs->getCalleeSavedRegs(MF);
2478a7e2fb5SNeumann Hon }
2488a7e2fb5SNeumann Hon
2498a7e2fb5SNeumann Hon const uint32_t *
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID CC) const2508a7e2fb5SNeumann Hon SystemZRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
2518a7e2fb5SNeumann Hon CallingConv::ID CC) const {
2528a7e2fb5SNeumann Hon
2538a7e2fb5SNeumann Hon const SystemZSubtarget *Subtarget = &MF.getSubtarget<SystemZSubtarget>();
2548a7e2fb5SNeumann Hon SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters();
2558a7e2fb5SNeumann Hon return Regs->getCallPreservedMask(MF, CC);
2568a7e2fb5SNeumann Hon }
2578a7e2fb5SNeumann Hon
2585f613dfdSUlrich Weigand BitVector
getReservedRegs(const MachineFunction & MF) const2595f613dfdSUlrich Weigand SystemZRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
2605f613dfdSUlrich Weigand BitVector Reserved(getNumRegs());
261b73a2ed2SJF Bastien const SystemZFrameLowering *TFI = getFrameLowering(MF);
2628a7e2fb5SNeumann Hon const SystemZSubtarget *Subtarget = &MF.getSubtarget<SystemZSubtarget>();
2638a7e2fb5SNeumann Hon SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters();
2648a7e2fb5SNeumann Hon if (TFI->hasFP(MF))
2658a7e2fb5SNeumann Hon // The frame pointer. Reserve all aliases.
2668a7e2fb5SNeumann Hon for (MCRegAliasIterator AI(Regs->getFramePointerRegister(), this, true);
2678a7e2fb5SNeumann Hon AI.isValid(); ++AI)
2688a7e2fb5SNeumann Hon Reserved.set(*AI);
2695f613dfdSUlrich Weigand
2708a7e2fb5SNeumann Hon // Reserve all aliases for the stack pointer.
2718a7e2fb5SNeumann Hon for (MCRegAliasIterator AI(Regs->getStackPointerRegister(), this, true);
2728a7e2fb5SNeumann Hon AI.isValid(); ++AI)
2738a7e2fb5SNeumann Hon Reserved.set(*AI);
274fffc7110SUlrich Weigand
275fffc7110SUlrich Weigand // A0 and A1 hold the thread pointer.
276fffc7110SUlrich Weigand Reserved.set(SystemZ::A0);
277fffc7110SUlrich Weigand Reserved.set(SystemZ::A1);
278fffc7110SUlrich Weigand
2798e42f6ddSUlrich Weigand // FPC is the floating-point control register.
2808e42f6ddSUlrich Weigand Reserved.set(SystemZ::FPC);
2818e42f6ddSUlrich Weigand
2825f613dfdSUlrich Weigand return Reserved;
2835f613dfdSUlrich Weigand }
2845f613dfdSUlrich Weigand
2855f613dfdSUlrich Weigand void
eliminateFrameIndex(MachineBasicBlock::iterator MI,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const2865f613dfdSUlrich Weigand SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,
2875f613dfdSUlrich Weigand int SPAdj, unsigned FIOperandNum,
2885f613dfdSUlrich Weigand RegScavenger *RS) const {
2895f613dfdSUlrich Weigand assert(SPAdj == 0 && "Outgoing arguments should be part of the frame");
2905f613dfdSUlrich Weigand
2915f613dfdSUlrich Weigand MachineBasicBlock &MBB = *MI->getParent();
2925f613dfdSUlrich Weigand MachineFunction &MF = *MBB.getParent();
293*3432d40cSJonas Paulsson auto *TII = MF.getSubtarget<SystemZSubtarget>().getInstrInfo();
294b73a2ed2SJF Bastien const SystemZFrameLowering *TFI = getFrameLowering(MF);
2955f613dfdSUlrich Weigand DebugLoc DL = MI->getDebugLoc();
2965f613dfdSUlrich Weigand
2975f613dfdSUlrich Weigand // Decompose the frame index into a base and offset.
2985f613dfdSUlrich Weigand int FrameIndex = MI->getOperand(FIOperandNum).getIndex();
2992481f26aSMatt Arsenault Register BasePtr;
300d57bba7cSSander de Smalen int64_t Offset =
301d57bba7cSSander de Smalen (TFI->getFrameIndexReference(MF, FrameIndex, BasePtr).getFixed() +
3025f613dfdSUlrich Weigand MI->getOperand(FIOperandNum + 1).getImm());
3035f613dfdSUlrich Weigand
3045f613dfdSUlrich Weigand // Special handling of dbg_value instructions.
3055f613dfdSUlrich Weigand if (MI->isDebugValue()) {
3065f613dfdSUlrich Weigand MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, /*isDef*/ false);
307f6774130SStephen Tozer if (MI->isNonListDebugValue()) {
308539381daSstozer MI->getDebugOffset().ChangeToImmediate(Offset);
309f6774130SStephen Tozer } else {
310f6774130SStephen Tozer unsigned OpIdx = MI->getDebugOperandIndex(&MI->getOperand(FIOperandNum));
311f6774130SStephen Tozer SmallVector<uint64_t, 3> Ops;
312f6774130SStephen Tozer DIExpression::appendOffset(
313f6774130SStephen Tozer Ops, TFI->getFrameIndexReference(MF, FrameIndex, BasePtr).getFixed());
314f6774130SStephen Tozer MI->getDebugExpressionOp().setMetadata(
315f6774130SStephen Tozer DIExpression::appendOpsToArg(MI->getDebugExpression(), Ops, OpIdx));
316f6774130SStephen Tozer }
3175f613dfdSUlrich Weigand return;
3185f613dfdSUlrich Weigand }
3195f613dfdSUlrich Weigand
3205f613dfdSUlrich Weigand // See if the offset is in range, or if an equivalent instruction that
3215f613dfdSUlrich Weigand // accepts the offset exists.
3225f613dfdSUlrich Weigand unsigned Opcode = MI->getOpcode();
32388c1cd86SJonas Paulsson unsigned OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset, &*MI);
324f0fc5090SJonas Paulsson if (OpcodeForOffset) {
325f0fc5090SJonas Paulsson if (OpcodeForOffset == SystemZ::LE &&
326f0fc5090SJonas Paulsson MF.getSubtarget<SystemZSubtarget>().hasVector()) {
327f0fc5090SJonas Paulsson // If LE is ok for offset, use LDE instead on z13.
328f0fc5090SJonas Paulsson OpcodeForOffset = SystemZ::LDE32;
329f0fc5090SJonas Paulsson }
3305f613dfdSUlrich Weigand MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false);
331f0fc5090SJonas Paulsson }
3325f613dfdSUlrich Weigand else {
3335f613dfdSUlrich Weigand // Create an anchor point that is in range. Start at 0xffff so that
3345f613dfdSUlrich Weigand // can use LLILH to load the immediate.
3355f613dfdSUlrich Weigand int64_t OldOffset = Offset;
3365f613dfdSUlrich Weigand int64_t Mask = 0xffff;
3375f613dfdSUlrich Weigand do {
3385f613dfdSUlrich Weigand Offset = OldOffset & Mask;
33921f5d68aSRichard Sandiford OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset);
3405f613dfdSUlrich Weigand Mask >>= 1;
3415f613dfdSUlrich Weigand assert(Mask && "One offset must be OK");
3425f613dfdSUlrich Weigand } while (!OpcodeForOffset);
3435f613dfdSUlrich Weigand
3440c476111SDaniel Sanders Register ScratchReg =
3455f613dfdSUlrich Weigand MF.getRegInfo().createVirtualRegister(&SystemZ::ADDR64BitRegClass);
3465f613dfdSUlrich Weigand int64_t HighOffset = OldOffset - Offset;
3475f613dfdSUlrich Weigand
3485f613dfdSUlrich Weigand if (MI->getDesc().TSFlags & SystemZII::HasIndex
3495f613dfdSUlrich Weigand && MI->getOperand(FIOperandNum + 2).getReg() == 0) {
3505f613dfdSUlrich Weigand // Load the offset into the scratch register and use it as an index.
3515f613dfdSUlrich Weigand // The scratch register then dies here.
35221f5d68aSRichard Sandiford TII->loadImmediate(MBB, MI, ScratchReg, HighOffset);
3535f613dfdSUlrich Weigand MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false);
3545f613dfdSUlrich Weigand MI->getOperand(FIOperandNum + 2).ChangeToRegister(ScratchReg,
3555f613dfdSUlrich Weigand false, false, true);
3565f613dfdSUlrich Weigand } else {
3575f613dfdSUlrich Weigand // Load the anchor address into a scratch register.
35821f5d68aSRichard Sandiford unsigned LAOpcode = TII->getOpcodeForOffset(SystemZ::LA, HighOffset);
3595f613dfdSUlrich Weigand if (LAOpcode)
36021f5d68aSRichard Sandiford BuildMI(MBB, MI, DL, TII->get(LAOpcode),ScratchReg)
3615f613dfdSUlrich Weigand .addReg(BasePtr).addImm(HighOffset).addReg(0);
3625f613dfdSUlrich Weigand else {
3635f613dfdSUlrich Weigand // Load the high offset into the scratch register and use it as
3645f613dfdSUlrich Weigand // an index.
36521f5d68aSRichard Sandiford TII->loadImmediate(MBB, MI, ScratchReg, HighOffset);
366d851495fSJonas Paulsson BuildMI(MBB, MI, DL, TII->get(SystemZ::LA), ScratchReg)
367d851495fSJonas Paulsson .addReg(BasePtr, RegState::Kill).addImm(0).addReg(ScratchReg);
3685f613dfdSUlrich Weigand }
3695f613dfdSUlrich Weigand
3705f613dfdSUlrich Weigand // Use the scratch register as the base. It then dies here.
3715f613dfdSUlrich Weigand MI->getOperand(FIOperandNum).ChangeToRegister(ScratchReg,
3725f613dfdSUlrich Weigand false, false, true);
3735f613dfdSUlrich Weigand }
3745f613dfdSUlrich Weigand }
37521f5d68aSRichard Sandiford MI->setDesc(TII->get(OpcodeForOffset));
3765f613dfdSUlrich Weigand MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
3775f613dfdSUlrich Weigand }
3785f613dfdSUlrich Weigand
shouldCoalesce(MachineInstr * MI,const TargetRegisterClass * SrcRC,unsigned SubReg,const TargetRegisterClass * DstRC,unsigned DstSubReg,const TargetRegisterClass * NewRC,LiveIntervals & LIS) const379c9e363acSJonas Paulsson bool SystemZRegisterInfo::shouldCoalesce(MachineInstr *MI,
380c9e363acSJonas Paulsson const TargetRegisterClass *SrcRC,
381c9e363acSJonas Paulsson unsigned SubReg,
382c9e363acSJonas Paulsson const TargetRegisterClass *DstRC,
383c9e363acSJonas Paulsson unsigned DstSubReg,
384c9e363acSJonas Paulsson const TargetRegisterClass *NewRC,
385c9e363acSJonas Paulsson LiveIntervals &LIS) const {
386c9e363acSJonas Paulsson assert (MI->isCopy() && "Only expecting COPY instructions");
387c9e363acSJonas Paulsson
388c9e363acSJonas Paulsson // Coalesce anything which is not a COPY involving a subreg to/from GR128.
389c9e363acSJonas Paulsson if (!(NewRC->hasSuperClassEq(&SystemZ::GR128BitRegClass) &&
390c9e363acSJonas Paulsson (getRegSizeInBits(*SrcRC) <= 64 || getRegSizeInBits(*DstRC) <= 64)))
391c9e363acSJonas Paulsson return true;
392c9e363acSJonas Paulsson
393c9e363acSJonas Paulsson // Allow coalescing of a GR128 subreg COPY only if the live ranges are small
394c9e363acSJonas Paulsson // and local to one MBB with not too much interferring registers. Otherwise
395c9e363acSJonas Paulsson // regalloc may run out of registers.
396c9e363acSJonas Paulsson
397c9e363acSJonas Paulsson unsigned WideOpNo = (getRegSizeInBits(*SrcRC) == 128 ? 1 : 0);
3980c476111SDaniel Sanders Register GR128Reg = MI->getOperand(WideOpNo).getReg();
3990c476111SDaniel Sanders Register GRNarReg = MI->getOperand((WideOpNo == 1) ? 0 : 1).getReg();
400c9e363acSJonas Paulsson LiveInterval &IntGR128 = LIS.getInterval(GR128Reg);
401c9e363acSJonas Paulsson LiveInterval &IntGRNar = LIS.getInterval(GRNarReg);
402c9e363acSJonas Paulsson
403c9e363acSJonas Paulsson // Check that the two virtual registers are local to MBB.
404c9e363acSJonas Paulsson MachineBasicBlock *MBB = MI->getParent();
4051993894cSJonas Paulsson MachineInstr *FirstMI_GR128 =
4061993894cSJonas Paulsson LIS.getInstructionFromIndex(IntGR128.beginIndex());
4071993894cSJonas Paulsson MachineInstr *FirstMI_GRNar =
4081993894cSJonas Paulsson LIS.getInstructionFromIndex(IntGRNar.beginIndex());
4091993894cSJonas Paulsson MachineInstr *LastMI_GR128 = LIS.getInstructionFromIndex(IntGR128.endIndex());
4101993894cSJonas Paulsson MachineInstr *LastMI_GRNar = LIS.getInstructionFromIndex(IntGRNar.endIndex());
4111993894cSJonas Paulsson if ((!FirstMI_GR128 || FirstMI_GR128->getParent() != MBB) ||
4121993894cSJonas Paulsson (!FirstMI_GRNar || FirstMI_GRNar->getParent() != MBB) ||
4131993894cSJonas Paulsson (!LastMI_GR128 || LastMI_GR128->getParent() != MBB) ||
4141993894cSJonas Paulsson (!LastMI_GRNar || LastMI_GRNar->getParent() != MBB))
415c9e363acSJonas Paulsson return false;
416c9e363acSJonas Paulsson
4171993894cSJonas Paulsson MachineBasicBlock::iterator MII = nullptr, MEE = nullptr;
418c9e363acSJonas Paulsson if (WideOpNo == 1) {
4191993894cSJonas Paulsson MII = FirstMI_GR128;
4201993894cSJonas Paulsson MEE = LastMI_GRNar;
421c9e363acSJonas Paulsson } else {
4221993894cSJonas Paulsson MII = FirstMI_GRNar;
4231993894cSJonas Paulsson MEE = LastMI_GR128;
424c9e363acSJonas Paulsson }
425c9e363acSJonas Paulsson
426c9e363acSJonas Paulsson // Check if coalescing seems safe by finding the set of clobbered physreg
427c9e363acSJonas Paulsson // pairs in the region.
428c9e363acSJonas Paulsson BitVector PhysClobbered(getNumRegs());
429c9e363acSJonas Paulsson MEE++;
430c9e363acSJonas Paulsson for (; MII != MEE; ++MII) {
431c9e363acSJonas Paulsson for (const MachineOperand &MO : MII->operands())
4322bea69bfSDaniel Sanders if (MO.isReg() && Register::isPhysicalRegister(MO.getReg())) {
433c9e363acSJonas Paulsson for (MCSuperRegIterator SI(MO.getReg(), this, true/*IncludeSelf*/);
434c9e363acSJonas Paulsson SI.isValid(); ++SI)
435c9e363acSJonas Paulsson if (NewRC->contains(*SI)) {
436c9e363acSJonas Paulsson PhysClobbered.set(*SI);
437c9e363acSJonas Paulsson break;
438c9e363acSJonas Paulsson }
439c9e363acSJonas Paulsson }
440c9e363acSJonas Paulsson }
441c9e363acSJonas Paulsson
442c9e363acSJonas Paulsson // Demand an arbitrary margin of free regs.
443c9e363acSJonas Paulsson unsigned const DemandedFreeGR128 = 3;
444c9e363acSJonas Paulsson if (PhysClobbered.count() > (NewRC->getNumRegs() - DemandedFreeGR128))
445c9e363acSJonas Paulsson return false;
446c9e363acSJonas Paulsson
447c9e363acSJonas Paulsson return true;
448c9e363acSJonas Paulsson }
449c9e363acSJonas Paulsson
450e3a676e9SMatt Arsenault Register
getFrameRegister(const MachineFunction & MF) const4515f613dfdSUlrich Weigand SystemZRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
452b73a2ed2SJF Bastien const SystemZFrameLowering *TFI = getFrameLowering(MF);
4538a7e2fb5SNeumann Hon const SystemZSubtarget *Subtarget = &MF.getSubtarget<SystemZSubtarget>();
4548a7e2fb5SNeumann Hon SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters();
4558a7e2fb5SNeumann Hon
4568a7e2fb5SNeumann Hon return TFI->hasFP(MF) ? Regs->getFramePointerRegister()
4578a7e2fb5SNeumann Hon : Regs->getStackPointerRegister();
4585f613dfdSUlrich Weigand }
459b32f3656SUlrich Weigand
460b32f3656SUlrich Weigand const TargetRegisterClass *
getCrossCopyRegClass(const TargetRegisterClass * RC) const461b32f3656SUlrich Weigand SystemZRegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {
462b32f3656SUlrich Weigand if (RC == &SystemZ::CCRRegClass)
463b32f3656SUlrich Weigand return &SystemZ::GR32BitRegClass;
464b32f3656SUlrich Weigand return RC;
465b32f3656SUlrich Weigand }
466b32f3656SUlrich Weigand
467