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