xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
1 //===- LoongArchRegisterInfo.cpp - LoongArch Register Information -*- C++ -*-=//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains the LoongArch implementation of the TargetRegisterInfo
10 // class.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "LoongArchRegisterInfo.h"
15 #include "LoongArch.h"
16 #include "LoongArchInstrInfo.h"
17 #include "LoongArchSubtarget.h"
18 #include "MCTargetDesc/LoongArchBaseInfo.h"
19 #include "MCTargetDesc/LoongArchMCTargetDesc.h"
20 #include "llvm/CodeGen/MachineFrameInfo.h"
21 #include "llvm/CodeGen/MachineFunction.h"
22 #include "llvm/CodeGen/MachineInstrBuilder.h"
23 #include "llvm/CodeGen/RegisterScavenging.h"
24 #include "llvm/CodeGen/TargetFrameLowering.h"
25 #include "llvm/CodeGen/TargetInstrInfo.h"
26 #include "llvm/Support/ErrorHandling.h"
27 
28 using namespace llvm;
29 
30 #define GET_REGINFO_TARGET_DESC
31 #include "LoongArchGenRegisterInfo.inc"
32 
LoongArchRegisterInfo(unsigned HwMode)33 LoongArchRegisterInfo::LoongArchRegisterInfo(unsigned HwMode)
34     : LoongArchGenRegisterInfo(LoongArch::R1, /*DwarfFlavour*/ 0,
35                                /*EHFlavor*/ 0,
36                                /*PC*/ 0, HwMode) {}
37 
38 const MCPhysReg *
getCalleeSavedRegs(const MachineFunction * MF) const39 LoongArchRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
40   auto &Subtarget = MF->getSubtarget<LoongArchSubtarget>();
41 
42   if (MF->getFunction().getCallingConv() == CallingConv::GHC)
43     return CSR_NoRegs_SaveList;
44   switch (Subtarget.getTargetABI()) {
45   default:
46     llvm_unreachable("Unrecognized ABI");
47   case LoongArchABI::ABI_ILP32S:
48   case LoongArchABI::ABI_LP64S:
49     return CSR_ILP32S_LP64S_SaveList;
50   case LoongArchABI::ABI_ILP32F:
51   case LoongArchABI::ABI_LP64F:
52     return CSR_ILP32F_LP64F_SaveList;
53   case LoongArchABI::ABI_ILP32D:
54   case LoongArchABI::ABI_LP64D:
55     return CSR_ILP32D_LP64D_SaveList;
56   }
57 }
58 
59 const uint32_t *
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID CC) const60 LoongArchRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
61                                             CallingConv::ID CC) const {
62   auto &Subtarget = MF.getSubtarget<LoongArchSubtarget>();
63 
64   if (CC == CallingConv::GHC)
65     return CSR_NoRegs_RegMask;
66   switch (Subtarget.getTargetABI()) {
67   default:
68     llvm_unreachable("Unrecognized ABI");
69   case LoongArchABI::ABI_ILP32S:
70   case LoongArchABI::ABI_LP64S:
71     return CSR_ILP32S_LP64S_RegMask;
72   case LoongArchABI::ABI_ILP32F:
73   case LoongArchABI::ABI_LP64F:
74     return CSR_ILP32F_LP64F_RegMask;
75   case LoongArchABI::ABI_ILP32D:
76   case LoongArchABI::ABI_LP64D:
77     return CSR_ILP32D_LP64D_RegMask;
78   }
79 }
80 
getNoPreservedMask() const81 const uint32_t *LoongArchRegisterInfo::getNoPreservedMask() const {
82   return CSR_NoRegs_RegMask;
83 }
84 
85 BitVector
getReservedRegs(const MachineFunction & MF) const86 LoongArchRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
87   const LoongArchFrameLowering *TFI = getFrameLowering(MF);
88   BitVector Reserved(getNumRegs());
89 
90   // Use markSuperRegs to ensure any register aliases are also reserved
91   markSuperRegs(Reserved, LoongArch::R0);  // zero
92   markSuperRegs(Reserved, LoongArch::R2);  // tp
93   markSuperRegs(Reserved, LoongArch::R3);  // sp
94   markSuperRegs(Reserved, LoongArch::R21); // non-allocatable
95   if (TFI->hasFP(MF))
96     markSuperRegs(Reserved, LoongArch::R22); // fp
97   // Reserve the base register if we need to realign the stack and allocate
98   // variable-sized objects at runtime.
99   if (TFI->hasBP(MF))
100     markSuperRegs(Reserved, LoongArchABI::getBPReg()); // bp
101 
102   assert(checkAllSuperRegsMarked(Reserved));
103   return Reserved;
104 }
105 
106 Register
getFrameRegister(const MachineFunction & MF) const107 LoongArchRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
108   const TargetFrameLowering *TFI = getFrameLowering(MF);
109   return TFI->hasFP(MF) ? LoongArch::R22 : LoongArch::R3;
110 }
111 
eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const112 bool LoongArchRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
113                                                 int SPAdj,
114                                                 unsigned FIOperandNum,
115                                                 RegScavenger *RS) const {
116   // TODO: this implementation is a temporary placeholder which does just
117   // enough to allow other aspects of code generation to be tested.
118 
119   assert(SPAdj == 0 && "Unexpected non-zero SPAdj value");
120 
121   MachineInstr &MI = *II;
122   assert(MI.getOperand(FIOperandNum + 1).isImm() &&
123          "Unexpected FI-consuming insn");
124 
125   MachineBasicBlock &MBB = *MI.getParent();
126   MachineFunction &MF = *MI.getParent()->getParent();
127   MachineRegisterInfo &MRI = MF.getRegInfo();
128   const LoongArchSubtarget &STI = MF.getSubtarget<LoongArchSubtarget>();
129   const LoongArchInstrInfo *TII = STI.getInstrInfo();
130   const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
131   DebugLoc DL = MI.getDebugLoc();
132   bool IsLA64 = STI.is64Bit();
133   unsigned MIOpc = MI.getOpcode();
134 
135   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
136   Register FrameReg;
137   StackOffset Offset =
138       TFI->getFrameIndexReference(MF, FrameIndex, FrameReg) +
139       StackOffset::getFixed(MI.getOperand(FIOperandNum + 1).getImm());
140 
141   bool FrameRegIsKill = false;
142 
143   if (!isInt<12>(Offset.getFixed())) {
144     unsigned Addi = IsLA64 ? LoongArch::ADDI_D : LoongArch::ADDI_W;
145     unsigned Add = IsLA64 ? LoongArch::ADD_D : LoongArch::ADD_W;
146 
147     // The offset won't fit in an immediate, so use a scratch register instead.
148     // Modify Offset and FrameReg appropriately.
149     Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
150     TII->movImm(MBB, II, DL, ScratchReg, Offset.getFixed());
151     if (MIOpc == Addi) {
152       BuildMI(MBB, II, DL, TII->get(Add), MI.getOperand(0).getReg())
153           .addReg(FrameReg)
154           .addReg(ScratchReg, RegState::Kill);
155       MI.eraseFromParent();
156       return true;
157     }
158     BuildMI(MBB, II, DL, TII->get(Add), ScratchReg)
159         .addReg(FrameReg)
160         .addReg(ScratchReg, RegState::Kill);
161     Offset = StackOffset::getFixed(0);
162     FrameReg = ScratchReg;
163     FrameRegIsKill = true;
164   }
165 
166   // Spill CFRs.
167   if (MIOpc == LoongArch::PseudoST_CFR) {
168     Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
169     BuildMI(MBB, II, DL, TII->get(LoongArch::MOVCF2GR), ScratchReg)
170         .add(MI.getOperand(0));
171     BuildMI(MBB, II, DL, TII->get(IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))
172         .addReg(ScratchReg, RegState::Kill)
173         .addReg(FrameReg)
174         .addImm(Offset.getFixed());
175     MI.eraseFromParent();
176     return true;
177   }
178 
179   // Reload CFRs.
180   if (MIOpc == LoongArch::PseudoLD_CFR) {
181     Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
182     BuildMI(MBB, II, DL, TII->get(IsLA64 ? LoongArch::LD_D : LoongArch::LD_W),
183             ScratchReg)
184         .addReg(FrameReg)
185         .addImm(Offset.getFixed());
186     BuildMI(MBB, II, DL, TII->get(LoongArch::MOVGR2CF))
187         .add(MI.getOperand(0))
188         .addReg(ScratchReg, RegState::Kill);
189     MI.eraseFromParent();
190     return true;
191   }
192 
193   MI.getOperand(FIOperandNum)
194       .ChangeToRegister(FrameReg, false, false, FrameRegIsKill);
195   MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset.getFixed());
196   return false;
197 }
198 
canRealignStack(const MachineFunction & MF) const199 bool LoongArchRegisterInfo::canRealignStack(const MachineFunction &MF) const {
200   if (!TargetRegisterInfo::canRealignStack(MF))
201     return false;
202 
203   const MachineRegisterInfo *MRI = &MF.getRegInfo();
204   const LoongArchFrameLowering *TFI = getFrameLowering(MF);
205 
206   // Stack realignment requires a frame pointer.  If we already started
207   // register allocation with frame pointer elimination, it is too late now.
208   if (!MRI->canReserveReg(LoongArch::R22))
209     return false;
210 
211   // We may also need a base pointer if there are dynamic allocas or stack
212   // pointer adjustments around calls.
213   if (TFI->hasReservedCallFrame(MF))
214     return true;
215 
216   // A base pointer is required and allowed.  Check that it isn't too late to
217   // reserve it.
218   return MRI->canReserveReg(LoongArchABI::getBPReg());
219 }
220