xref: /src/contrib/llvm-project/llvm/lib/Target/Mips/MipsMachineFunction.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
163faed5bSDimitry Andric //===-- MipsMachineFunctionInfo.cpp - Private data used for Mips ----------===//
263faed5bSDimitry 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
663faed5bSDimitry Andric //
763faed5bSDimitry Andric //===----------------------------------------------------------------------===//
863faed5bSDimitry Andric 
95a5ac124SDimitry Andric #include "MipsMachineFunction.h"
107ab83427SDimitry Andric #include "MCTargetDesc/MipsABIInfo.h"
1163faed5bSDimitry Andric #include "MipsSubtarget.h"
125a5ac124SDimitry Andric #include "MipsTargetMachine.h"
1371d5a254SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
1463faed5bSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
1571d5a254SDimitry Andric #include "llvm/CodeGen/PseudoSourceValue.h"
16b1c73532SDimitry Andric #include "llvm/CodeGen/PseudoSourceValueManager.h"
17044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
1863faed5bSDimitry Andric #include "llvm/Support/CommandLine.h"
1963faed5bSDimitry Andric 
2063faed5bSDimitry Andric using namespace llvm;
2163faed5bSDimitry Andric 
2263faed5bSDimitry Andric static cl::opt<bool>
2363faed5bSDimitry Andric FixGlobalBaseReg("mips-fix-global-base-reg", cl::Hidden, cl::init(true),
2463faed5bSDimitry Andric                  cl::desc("Always use $gp as the global base register."));
2563faed5bSDimitry Andric 
26145449b1SDimitry Andric MachineFunctionInfo *
clone(BumpPtrAllocator & Allocator,MachineFunction & DestMF,const DenseMap<MachineBasicBlock *,MachineBasicBlock * > & Src2DstMBB) const27145449b1SDimitry Andric MipsFunctionInfo::clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,
28145449b1SDimitry Andric                         const DenseMap<MachineBasicBlock *, MachineBasicBlock *>
29145449b1SDimitry Andric                             &Src2DstMBB) const {
30145449b1SDimitry Andric   return DestMF.cloneInfo<MipsFunctionInfo>(*this);
31145449b1SDimitry Andric }
32145449b1SDimitry Andric 
3371d5a254SDimitry Andric MipsFunctionInfo::~MipsFunctionInfo() = default;
34f8af5cf6SDimitry Andric 
globalBaseRegSet() const3563faed5bSDimitry Andric bool MipsFunctionInfo::globalBaseRegSet() const {
3663faed5bSDimitry Andric   return GlobalBaseReg;
3763faed5bSDimitry Andric }
3863faed5bSDimitry Andric 
getGlobalBaseRegClass(MachineFunction & MF)39eb11fae6SDimitry Andric static const TargetRegisterClass &getGlobalBaseRegClass(MachineFunction &MF) {
40145449b1SDimitry Andric   auto &STI = MF.getSubtarget<MipsSubtarget>();
41eb11fae6SDimitry Andric   auto &TM = static_cast<const MipsTargetMachine &>(MF.getTarget());
42eb11fae6SDimitry Andric 
43eb11fae6SDimitry Andric   if (STI.inMips16Mode())
44eb11fae6SDimitry Andric     return Mips::CPU16RegsRegClass;
45eb11fae6SDimitry Andric 
46eb11fae6SDimitry Andric   if (STI.inMicroMipsMode())
47eb11fae6SDimitry Andric     return Mips::GPRMM16RegClass;
48eb11fae6SDimitry Andric 
49eb11fae6SDimitry Andric   if (TM.getABI().IsN64())
50eb11fae6SDimitry Andric     return Mips::GPR64RegClass;
51eb11fae6SDimitry Andric 
52eb11fae6SDimitry Andric   return Mips::GPR32RegClass;
53eb11fae6SDimitry Andric }
54eb11fae6SDimitry Andric 
getGlobalBaseReg(MachineFunction & MF)55cfca06d7SDimitry Andric Register MipsFunctionInfo::getGlobalBaseReg(MachineFunction &MF) {
56eb11fae6SDimitry Andric   if (!GlobalBaseReg)
57eb11fae6SDimitry Andric     GlobalBaseReg =
58eb11fae6SDimitry Andric         MF.getRegInfo().createVirtualRegister(&getGlobalBaseRegClass(MF));
5963faed5bSDimitry Andric   return GlobalBaseReg;
6063faed5bSDimitry Andric }
6163faed5bSDimitry Andric 
getGlobalBaseRegForGlobalISel(MachineFunction & MF)62cfca06d7SDimitry Andric Register MipsFunctionInfo::getGlobalBaseRegForGlobalISel(MachineFunction &MF) {
63e6d15924SDimitry Andric   if (!GlobalBaseReg) {
64cfca06d7SDimitry Andric     getGlobalBaseReg(MF);
65cfca06d7SDimitry Andric     initGlobalBaseReg(MF);
66e6d15924SDimitry Andric   }
67e6d15924SDimitry Andric   return GlobalBaseReg;
68e6d15924SDimitry Andric }
69e6d15924SDimitry Andric 
initGlobalBaseReg(MachineFunction & MF)70cfca06d7SDimitry Andric void MipsFunctionInfo::initGlobalBaseReg(MachineFunction &MF) {
71e6d15924SDimitry Andric   if (!GlobalBaseReg)
72e6d15924SDimitry Andric     return;
73e6d15924SDimitry Andric 
74e6d15924SDimitry Andric   MachineBasicBlock &MBB = MF.front();
75e6d15924SDimitry Andric   MachineBasicBlock::iterator I = MBB.begin();
76e6d15924SDimitry Andric   MachineRegisterInfo &RegInfo = MF.getRegInfo();
77e6d15924SDimitry Andric   const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
78e6d15924SDimitry Andric   DebugLoc DL;
79e6d15924SDimitry Andric   const TargetRegisterClass *RC;
80e6d15924SDimitry Andric   const MipsABIInfo &ABI =
81e6d15924SDimitry Andric       static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI();
82e6d15924SDimitry Andric   RC = (ABI.IsN64()) ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
83e6d15924SDimitry Andric 
84cfca06d7SDimitry Andric   Register V0 = RegInfo.createVirtualRegister(RC);
85cfca06d7SDimitry Andric   Register V1 = RegInfo.createVirtualRegister(RC);
86e6d15924SDimitry Andric 
87e6d15924SDimitry Andric   if (ABI.IsN64()) {
88e6d15924SDimitry Andric     MF.getRegInfo().addLiveIn(Mips::T9_64);
89e6d15924SDimitry Andric     MBB.addLiveIn(Mips::T9_64);
90e6d15924SDimitry Andric 
91e6d15924SDimitry Andric     // lui $v0, %hi(%neg(%gp_rel(fname)))
92e6d15924SDimitry Andric     // daddu $v1, $v0, $t9
93e6d15924SDimitry Andric     // daddiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname)))
94e6d15924SDimitry Andric     const GlobalValue *FName = &MF.getFunction();
95e6d15924SDimitry Andric     BuildMI(MBB, I, DL, TII.get(Mips::LUi64), V0)
96e6d15924SDimitry Andric         .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
97e6d15924SDimitry Andric     BuildMI(MBB, I, DL, TII.get(Mips::DADDu), V1).addReg(V0)
98e6d15924SDimitry Andric         .addReg(Mips::T9_64);
99e6d15924SDimitry Andric     BuildMI(MBB, I, DL, TII.get(Mips::DADDiu), GlobalBaseReg).addReg(V1)
100e6d15924SDimitry Andric         .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO);
101e6d15924SDimitry Andric     return;
102e6d15924SDimitry Andric   }
103e6d15924SDimitry Andric 
104e6d15924SDimitry Andric   if (!MF.getTarget().isPositionIndependent()) {
105e6d15924SDimitry Andric     // Set global register to __gnu_local_gp.
106e6d15924SDimitry Andric     //
107e6d15924SDimitry Andric     // lui   $v0, %hi(__gnu_local_gp)
108e6d15924SDimitry Andric     // addiu $globalbasereg, $v0, %lo(__gnu_local_gp)
109e6d15924SDimitry Andric     BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0)
110e6d15924SDimitry Andric         .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_HI);
111e6d15924SDimitry Andric     BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V0)
112e6d15924SDimitry Andric         .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_LO);
113e6d15924SDimitry Andric     return;
114e6d15924SDimitry Andric   }
115e6d15924SDimitry Andric 
116e6d15924SDimitry Andric   MF.getRegInfo().addLiveIn(Mips::T9);
117e6d15924SDimitry Andric   MBB.addLiveIn(Mips::T9);
118e6d15924SDimitry Andric 
119e6d15924SDimitry Andric   if (ABI.IsN32()) {
120e6d15924SDimitry Andric     // lui $v0, %hi(%neg(%gp_rel(fname)))
121e6d15924SDimitry Andric     // addu $v1, $v0, $t9
122e6d15924SDimitry Andric     // addiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname)))
123e6d15924SDimitry Andric     const GlobalValue *FName = &MF.getFunction();
124e6d15924SDimitry Andric     BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0)
125e6d15924SDimitry Andric         .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
126e6d15924SDimitry Andric     BuildMI(MBB, I, DL, TII.get(Mips::ADDu), V1).addReg(V0).addReg(Mips::T9);
127e6d15924SDimitry Andric     BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V1)
128e6d15924SDimitry Andric         .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO);
129e6d15924SDimitry Andric     return;
130e6d15924SDimitry Andric   }
131e6d15924SDimitry Andric 
132e6d15924SDimitry Andric   assert(ABI.IsO32());
133e6d15924SDimitry Andric 
134e6d15924SDimitry Andric   // For O32 ABI, the following instruction sequence is emitted to initialize
135e6d15924SDimitry Andric   // the global base register:
136e6d15924SDimitry Andric   //
137e6d15924SDimitry Andric   //  0. lui   $2, %hi(_gp_disp)
138e6d15924SDimitry Andric   //  1. addiu $2, $2, %lo(_gp_disp)
139e6d15924SDimitry Andric   //  2. addu  $globalbasereg, $2, $t9
140e6d15924SDimitry Andric   //
141e6d15924SDimitry Andric   // We emit only the last instruction here.
142e6d15924SDimitry Andric   //
143e6d15924SDimitry Andric   // GNU linker requires that the first two instructions appear at the beginning
144e6d15924SDimitry Andric   // of a function and no instructions be inserted before or between them.
145e6d15924SDimitry Andric   // The two instructions are emitted during lowering to MC layer in order to
146e6d15924SDimitry Andric   // avoid any reordering.
147e6d15924SDimitry Andric   //
148e6d15924SDimitry Andric   // Register $2 (Mips::V0) is added to the list of live-in registers to ensure
149e6d15924SDimitry Andric   // the value instruction 1 (addiu) defines is valid when instruction 2 (addu)
150e6d15924SDimitry Andric   // reads it.
151e6d15924SDimitry Andric   MF.getRegInfo().addLiveIn(Mips::V0);
152e6d15924SDimitry Andric   MBB.addLiveIn(Mips::V0);
153e6d15924SDimitry Andric   BuildMI(MBB, I, DL, TII.get(Mips::ADDu), GlobalBaseReg)
154e6d15924SDimitry Andric       .addReg(Mips::V0).addReg(Mips::T9);
155e6d15924SDimitry Andric }
156e6d15924SDimitry Andric 
createEhDataRegsFI(MachineFunction & MF)157cfca06d7SDimitry Andric void MipsFunctionInfo::createEhDataRegsFI(MachineFunction &MF) {
15812f3ca4cSDimitry Andric   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
1596f8fc217SDimitry Andric   for (int &I : EhDataRegFI) {
16012f3ca4cSDimitry Andric     const TargetRegisterClass &RC =
1615a5ac124SDimitry Andric         static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI().IsN64()
16212f3ca4cSDimitry Andric             ? Mips::GPR64RegClass
16312f3ca4cSDimitry Andric             : Mips::GPR32RegClass;
1644a16efa3SDimitry Andric 
1656f8fc217SDimitry Andric     I = MF.getFrameInfo().CreateStackObject(TRI.getSpillSize(RC),
1666f8fc217SDimitry Andric                                             TRI.getSpillAlign(RC), false);
1674a16efa3SDimitry Andric   }
1684a16efa3SDimitry Andric }
1694a16efa3SDimitry Andric 
createISRRegFI(MachineFunction & MF)170cfca06d7SDimitry Andric void MipsFunctionInfo::createISRRegFI(MachineFunction &MF) {
171dd58ef01SDimitry Andric   // ISRs require spill slots for Status & ErrorPC Coprocessor 0 registers.
172dd58ef01SDimitry Andric   // The current implementation only supports Mips32r2+ not Mips64rX. Status
173b915e9e0SDimitry Andric   // is always 32 bits, ErrorPC is 32 or 64 bits dependent on architecture,
174dd58ef01SDimitry Andric   // however Mips32r2+ is the supported architecture.
17512f3ca4cSDimitry Andric   const TargetRegisterClass &RC = Mips::GPR32RegClass;
17612f3ca4cSDimitry Andric   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
177dd58ef01SDimitry Andric 
1786f8fc217SDimitry Andric   for (int &I : ISRDataRegFI)
1796f8fc217SDimitry Andric     I = MF.getFrameInfo().CreateStackObject(TRI.getSpillSize(RC),
1806f8fc217SDimitry Andric                                             TRI.getSpillAlign(RC), false);
181dd58ef01SDimitry Andric }
182dd58ef01SDimitry Andric 
isEhDataRegFI(int FI) const1834a16efa3SDimitry Andric bool MipsFunctionInfo::isEhDataRegFI(int FI) const {
1844a16efa3SDimitry Andric   return CallsEhReturn && (FI == EhDataRegFI[0] || FI == EhDataRegFI[1]
1854a16efa3SDimitry Andric                         || FI == EhDataRegFI[2] || FI == EhDataRegFI[3]);
1864a16efa3SDimitry Andric }
1874a16efa3SDimitry Andric 
isISRRegFI(int FI) const188dd58ef01SDimitry Andric bool MipsFunctionInfo::isISRRegFI(int FI) const {
189dd58ef01SDimitry Andric   return IsISR && (FI == ISRDataRegFI[0] || FI == ISRDataRegFI[1]);
190dd58ef01SDimitry Andric }
callPtrInfo(MachineFunction & MF,const char * ES)191cfca06d7SDimitry Andric MachinePointerInfo MipsFunctionInfo::callPtrInfo(MachineFunction &MF,
192cfca06d7SDimitry Andric                                                  const char *ES) {
193dd58ef01SDimitry Andric   return MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES));
194f8af5cf6SDimitry Andric }
195f8af5cf6SDimitry Andric 
callPtrInfo(MachineFunction & MF,const GlobalValue * GV)196cfca06d7SDimitry Andric MachinePointerInfo MipsFunctionInfo::callPtrInfo(MachineFunction &MF,
197cfca06d7SDimitry Andric                                                  const GlobalValue *GV) {
198dd58ef01SDimitry Andric   return MachinePointerInfo(MF.getPSVManager().getGlobalValueCallEntry(GV));
199f8af5cf6SDimitry Andric }
200f8af5cf6SDimitry Andric 
getMoveF64ViaSpillFI(MachineFunction & MF,const TargetRegisterClass * RC)201cfca06d7SDimitry Andric int MipsFunctionInfo::getMoveF64ViaSpillFI(MachineFunction &MF,
202cfca06d7SDimitry Andric                                            const TargetRegisterClass *RC) {
20312f3ca4cSDimitry Andric   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
2045ca98fd9SDimitry Andric   if (MoveF64ViaSpillFI == -1) {
205b915e9e0SDimitry Andric     MoveF64ViaSpillFI = MF.getFrameInfo().CreateStackObject(
206cfca06d7SDimitry Andric         TRI.getSpillSize(*RC), TRI.getSpillAlign(*RC), false);
2075ca98fd9SDimitry Andric   }
2085ca98fd9SDimitry Andric   return MoveF64ViaSpillFI;
2095ca98fd9SDimitry Andric }
2105ca98fd9SDimitry Andric 
anchor()21163faed5bSDimitry Andric void MipsFunctionInfo::anchor() {}
212