xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/CSKY/CSKYRegisterInfo.cpp (revision 0eae32dcef82f6f06de6419a0d623d7def0cc8f6)
1349cc55cSDimitry Andric //===-- CSKYRegisterInfo.h - CSKY Register Information Impl ---*- C++ -*---===//
2349cc55cSDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6349cc55cSDimitry Andric //
7349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
8349cc55cSDimitry Andric //
9349cc55cSDimitry Andric // This file contains the CSKY implementation of the TargetRegisterInfo class.
10349cc55cSDimitry Andric //
11349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
12349cc55cSDimitry Andric 
13349cc55cSDimitry Andric #include "CSKYRegisterInfo.h"
14349cc55cSDimitry Andric #include "CSKY.h"
15349cc55cSDimitry Andric #include "CSKYSubtarget.h"
16349cc55cSDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
17349cc55cSDimitry Andric #include "llvm/CodeGen/RegisterScavenging.h"
18349cc55cSDimitry Andric #include "llvm/MC/MCContext.h"
19349cc55cSDimitry Andric 
20349cc55cSDimitry Andric #define GET_REGINFO_TARGET_DESC
21349cc55cSDimitry Andric #include "CSKYGenRegisterInfo.inc"
22349cc55cSDimitry Andric 
23349cc55cSDimitry Andric using namespace llvm;
24349cc55cSDimitry Andric 
25349cc55cSDimitry Andric CSKYRegisterInfo::CSKYRegisterInfo()
26349cc55cSDimitry Andric     : CSKYGenRegisterInfo(CSKY::R15, 0, 0, 0) {}
27349cc55cSDimitry Andric 
28349cc55cSDimitry Andric const uint32_t *
29349cc55cSDimitry Andric CSKYRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
30349cc55cSDimitry Andric                                        CallingConv::ID Id) const {
31349cc55cSDimitry Andric   const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>();
32349cc55cSDimitry Andric   return CSR_I32_RegMask;
33349cc55cSDimitry Andric }
34349cc55cSDimitry Andric 
35349cc55cSDimitry Andric Register CSKYRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
36349cc55cSDimitry Andric   const TargetFrameLowering *TFI = getFrameLowering(MF);
37349cc55cSDimitry Andric   return TFI->hasFP(MF) ? CSKY::R8 : CSKY::R14;
38349cc55cSDimitry Andric }
39349cc55cSDimitry Andric 
40349cc55cSDimitry Andric BitVector CSKYRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
41349cc55cSDimitry Andric   const CSKYFrameLowering *TFI = getFrameLowering(MF);
42349cc55cSDimitry Andric   const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>();
43349cc55cSDimitry Andric   BitVector Reserved(getNumRegs());
44349cc55cSDimitry Andric 
45349cc55cSDimitry Andric   // Reserve the base register if we need to allocate
46349cc55cSDimitry Andric   // variable-sized objects at runtime.
47349cc55cSDimitry Andric   if (TFI->hasBP(MF))
48349cc55cSDimitry Andric     markSuperRegs(Reserved, CSKY::R7); // bp
49349cc55cSDimitry Andric 
50349cc55cSDimitry Andric   if (TFI->hasFP(MF))
51349cc55cSDimitry Andric     markSuperRegs(Reserved, CSKY::R8); // fp
52349cc55cSDimitry Andric 
53349cc55cSDimitry Andric   if (!STI.hasE2()) {
54349cc55cSDimitry Andric     for (unsigned i = 0; i < 6; i++)
55349cc55cSDimitry Andric       markSuperRegs(Reserved, CSKY::R8 + i); // R8 - R13
56349cc55cSDimitry Andric   }
57349cc55cSDimitry Andric 
58349cc55cSDimitry Andric   markSuperRegs(Reserved, CSKY::R14); // sp
59349cc55cSDimitry Andric   markSuperRegs(Reserved, CSKY::R15); // lr
60349cc55cSDimitry Andric 
61349cc55cSDimitry Andric   if (!STI.hasHighRegisters()) {
62349cc55cSDimitry Andric     for (unsigned i = 0; i < 10; i++)
63349cc55cSDimitry Andric       markSuperRegs(Reserved, CSKY::R16 + i); // R16 - R25
64349cc55cSDimitry Andric   }
65349cc55cSDimitry Andric 
66349cc55cSDimitry Andric   markSuperRegs(Reserved, CSKY::R26);
67349cc55cSDimitry Andric   markSuperRegs(Reserved, CSKY::R27);
68349cc55cSDimitry Andric   markSuperRegs(Reserved, CSKY::R28); // gp
69349cc55cSDimitry Andric   markSuperRegs(Reserved, CSKY::R29);
70349cc55cSDimitry Andric   markSuperRegs(Reserved, CSKY::R30);
71349cc55cSDimitry Andric   markSuperRegs(Reserved, CSKY::R31); // tp
72349cc55cSDimitry Andric 
73349cc55cSDimitry Andric   assert(checkAllSuperRegsMarked(Reserved));
74349cc55cSDimitry Andric   return Reserved;
75349cc55cSDimitry Andric }
76349cc55cSDimitry Andric 
77349cc55cSDimitry Andric const uint32_t *CSKYRegisterInfo::getNoPreservedMask() const {
78349cc55cSDimitry Andric   return CSR_NoRegs_RegMask;
79349cc55cSDimitry Andric }
80349cc55cSDimitry Andric 
81349cc55cSDimitry Andric const MCPhysReg *
82349cc55cSDimitry Andric CSKYRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
83349cc55cSDimitry Andric   const CSKYSubtarget &STI = MF->getSubtarget<CSKYSubtarget>();
84349cc55cSDimitry Andric   if (MF->getFunction().hasFnAttribute("interrupt")) {
85349cc55cSDimitry Andric     return CSR_GPR_ISR_SaveList;
86349cc55cSDimitry Andric   }
87349cc55cSDimitry Andric 
88349cc55cSDimitry Andric   return CSR_I32_SaveList;
89349cc55cSDimitry Andric }
90349cc55cSDimitry Andric 
91*0eae32dcSDimitry Andric static bool IsLegalOffset(const CSKYInstrInfo *TII, MachineInstr *MI,
92*0eae32dcSDimitry Andric                           int &Offset) {
93*0eae32dcSDimitry Andric   const MCInstrDesc &Desc = MI->getDesc();
94*0eae32dcSDimitry Andric   unsigned AddrMode = (Desc.TSFlags & CSKYII::AddrModeMask);
95*0eae32dcSDimitry Andric   unsigned i = 0;
96*0eae32dcSDimitry Andric   for (; !MI->getOperand(i).isFI(); ++i) {
97*0eae32dcSDimitry Andric     assert(i + 1 < MI->getNumOperands() &&
98*0eae32dcSDimitry Andric            "Instr doesn't have FrameIndex operand!");
99*0eae32dcSDimitry Andric   }
100*0eae32dcSDimitry Andric 
101*0eae32dcSDimitry Andric   if (MI->getOpcode() == CSKY::ADDI32) {
102*0eae32dcSDimitry Andric     if (!isUInt<12>(std::abs(Offset) - 1))
103*0eae32dcSDimitry Andric       return false;
104*0eae32dcSDimitry Andric     if (Offset < 0) {
105*0eae32dcSDimitry Andric       MI->setDesc(TII->get(CSKY::SUBI32));
106*0eae32dcSDimitry Andric       Offset = -Offset;
107*0eae32dcSDimitry Andric     }
108*0eae32dcSDimitry Andric 
109*0eae32dcSDimitry Andric     return true;
110*0eae32dcSDimitry Andric   }
111*0eae32dcSDimitry Andric 
112*0eae32dcSDimitry Andric   if (MI->getOpcode() == CSKY::ADDI16XZ)
113*0eae32dcSDimitry Andric     return false;
114*0eae32dcSDimitry Andric 
115*0eae32dcSDimitry Andric   if (Offset < 0)
116*0eae32dcSDimitry Andric     return false;
117*0eae32dcSDimitry Andric 
118*0eae32dcSDimitry Andric   unsigned NumBits = 0;
119*0eae32dcSDimitry Andric   unsigned Scale = 1;
120*0eae32dcSDimitry Andric   switch (AddrMode) {
121*0eae32dcSDimitry Andric   case CSKYII::AddrMode32B:
122*0eae32dcSDimitry Andric     Scale = 1;
123*0eae32dcSDimitry Andric     NumBits = 12;
124*0eae32dcSDimitry Andric     break;
125*0eae32dcSDimitry Andric   case CSKYII::AddrMode32H:
126*0eae32dcSDimitry Andric     Scale = 2;
127*0eae32dcSDimitry Andric     NumBits = 12;
128*0eae32dcSDimitry Andric     break;
129*0eae32dcSDimitry Andric   case CSKYII::AddrMode32WD:
130*0eae32dcSDimitry Andric     Scale = 4;
131*0eae32dcSDimitry Andric     NumBits = 12;
132*0eae32dcSDimitry Andric     break;
133*0eae32dcSDimitry Andric   case CSKYII::AddrMode16B:
134*0eae32dcSDimitry Andric     Scale = 1;
135*0eae32dcSDimitry Andric     NumBits = 5;
136*0eae32dcSDimitry Andric     break;
137*0eae32dcSDimitry Andric   case CSKYII::AddrMode16H:
138*0eae32dcSDimitry Andric     Scale = 2;
139*0eae32dcSDimitry Andric     NumBits = 5;
140*0eae32dcSDimitry Andric     break;
141*0eae32dcSDimitry Andric   case CSKYII::AddrMode16W:
142*0eae32dcSDimitry Andric     Scale = 4;
143*0eae32dcSDimitry Andric     NumBits = 5;
144*0eae32dcSDimitry Andric     break;
145*0eae32dcSDimitry Andric   case CSKYII::AddrMode32SDF:
146*0eae32dcSDimitry Andric     Scale = 4;
147*0eae32dcSDimitry Andric     NumBits = 8;
148*0eae32dcSDimitry Andric     break;
149*0eae32dcSDimitry Andric   default:
150*0eae32dcSDimitry Andric     llvm_unreachable("Unsupported addressing mode!");
151*0eae32dcSDimitry Andric   }
152*0eae32dcSDimitry Andric 
153*0eae32dcSDimitry Andric   // Cannot encode offset.
154*0eae32dcSDimitry Andric   if ((Offset & (Scale - 1)) != 0)
155*0eae32dcSDimitry Andric     return false;
156*0eae32dcSDimitry Andric 
157*0eae32dcSDimitry Andric   unsigned Mask = (1 << NumBits) - 1;
158*0eae32dcSDimitry Andric   if ((unsigned)Offset <= Mask * Scale)
159*0eae32dcSDimitry Andric     return true;
160*0eae32dcSDimitry Andric 
161*0eae32dcSDimitry Andric   // Offset out of range.
162*0eae32dcSDimitry Andric   return false;
163*0eae32dcSDimitry Andric }
164*0eae32dcSDimitry Andric 
165349cc55cSDimitry Andric void CSKYRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
166349cc55cSDimitry Andric                                            int SPAdj, unsigned FIOperandNum,
167349cc55cSDimitry Andric                                            RegScavenger *RS) const {
168349cc55cSDimitry Andric   assert(SPAdj == 0 && "Unexpected non-zero SPAdj value");
169*0eae32dcSDimitry Andric 
170*0eae32dcSDimitry Andric   MachineInstr *MI = &*II;
171*0eae32dcSDimitry Andric   MachineBasicBlock &MBB = *MI->getParent();
172*0eae32dcSDimitry Andric   MachineFunction &MF = *MI->getParent()->getParent();
173*0eae32dcSDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
174*0eae32dcSDimitry Andric   const CSKYInstrInfo *TII = MF.getSubtarget<CSKYSubtarget>().getInstrInfo();
175*0eae32dcSDimitry Andric   DebugLoc DL = MI->getDebugLoc();
176*0eae32dcSDimitry Andric   const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>();
177*0eae32dcSDimitry Andric 
178*0eae32dcSDimitry Andric   switch (MI->getOpcode()) {
179*0eae32dcSDimitry Andric   default:
180*0eae32dcSDimitry Andric     break;
181*0eae32dcSDimitry Andric   case CSKY::RESTORE_CARRY: {
182*0eae32dcSDimitry Andric     Register NewReg = STI.hasE2()
183*0eae32dcSDimitry Andric                           ? MRI.createVirtualRegister(&CSKY::GPRRegClass)
184*0eae32dcSDimitry Andric                           : MRI.createVirtualRegister(&CSKY::mGPRRegClass);
185*0eae32dcSDimitry Andric 
186*0eae32dcSDimitry Andric     auto *Temp = BuildMI(MBB, II, DL, TII->get(CSKY::LD32W), NewReg)
187*0eae32dcSDimitry Andric                      .add(MI->getOperand(1))
188*0eae32dcSDimitry Andric                      .add(MI->getOperand(2))
189*0eae32dcSDimitry Andric                      .getInstr();
190*0eae32dcSDimitry Andric 
191*0eae32dcSDimitry Andric     BuildMI(MBB, II, DL, TII->get(STI.hasE2() ? CSKY::BTSTI32 : CSKY::BTSTI16),
192*0eae32dcSDimitry Andric             MI->getOperand(0).getReg())
193*0eae32dcSDimitry Andric         .addReg(NewReg, getKillRegState(true))
194*0eae32dcSDimitry Andric         .addImm(0);
195*0eae32dcSDimitry Andric 
196*0eae32dcSDimitry Andric     MI = Temp;
197*0eae32dcSDimitry Andric 
198*0eae32dcSDimitry Andric     MBB.erase(II);
199*0eae32dcSDimitry Andric     break;
200*0eae32dcSDimitry Andric   }
201*0eae32dcSDimitry Andric   case CSKY::SPILL_CARRY: {
202*0eae32dcSDimitry Andric     Register NewReg;
203*0eae32dcSDimitry Andric     if (STI.hasE2()) {
204*0eae32dcSDimitry Andric       NewReg = MRI.createVirtualRegister(&CSKY::GPRRegClass);
205*0eae32dcSDimitry Andric       BuildMI(MBB, II, DL, TII->get(CSKY::MVC32), NewReg)
206*0eae32dcSDimitry Andric           .add(MI->getOperand(0));
207*0eae32dcSDimitry Andric     } else {
208*0eae32dcSDimitry Andric       NewReg = MRI.createVirtualRegister(&CSKY::mGPRRegClass);
209*0eae32dcSDimitry Andric       BuildMI(MBB, II, DL, TII->get(CSKY::MOVI16), NewReg).addImm(0);
210*0eae32dcSDimitry Andric       BuildMI(MBB, II, DL, TII->get(CSKY::ADDC16))
211*0eae32dcSDimitry Andric           .addReg(NewReg, RegState::Define)
212*0eae32dcSDimitry Andric           .addReg(MI->getOperand(0).getReg(), RegState::Define)
213*0eae32dcSDimitry Andric           .addReg(NewReg, getKillRegState(true))
214*0eae32dcSDimitry Andric           .addReg(NewReg, getKillRegState(true))
215*0eae32dcSDimitry Andric           .addReg(MI->getOperand(0).getReg());
216*0eae32dcSDimitry Andric 
217*0eae32dcSDimitry Andric       BuildMI(MBB, II, DL, TII->get(CSKY::BTSTI16), MI->getOperand(0).getReg())
218*0eae32dcSDimitry Andric           .addReg(NewReg)
219*0eae32dcSDimitry Andric           .addImm(0);
220*0eae32dcSDimitry Andric     }
221*0eae32dcSDimitry Andric 
222*0eae32dcSDimitry Andric     MI = BuildMI(MBB, II, DL, TII->get(CSKY::ST32W))
223*0eae32dcSDimitry Andric              .addReg(NewReg, getKillRegState(true))
224*0eae32dcSDimitry Andric              .add(MI->getOperand(1))
225*0eae32dcSDimitry Andric              .add(MI->getOperand(2))
226*0eae32dcSDimitry Andric              .getInstr();
227*0eae32dcSDimitry Andric 
228*0eae32dcSDimitry Andric     MBB.erase(II);
229*0eae32dcSDimitry Andric 
230*0eae32dcSDimitry Andric     break;
231*0eae32dcSDimitry Andric   }
232*0eae32dcSDimitry Andric   }
233*0eae32dcSDimitry Andric 
234*0eae32dcSDimitry Andric   int FrameIndex = MI->getOperand(FIOperandNum).getIndex();
235*0eae32dcSDimitry Andric   Register FrameReg;
236*0eae32dcSDimitry Andric   int Offset = getFrameLowering(MF)
237*0eae32dcSDimitry Andric                    ->getFrameIndexReference(MF, FrameIndex, FrameReg)
238*0eae32dcSDimitry Andric                    .getFixed() +
239*0eae32dcSDimitry Andric                MI->getOperand(FIOperandNum + 1).getImm();
240*0eae32dcSDimitry Andric 
241*0eae32dcSDimitry Andric   if (!isInt<32>(Offset))
242*0eae32dcSDimitry Andric     report_fatal_error(
243*0eae32dcSDimitry Andric         "Frame offsets outside of the signed 32-bit range not supported");
244*0eae32dcSDimitry Andric 
245*0eae32dcSDimitry Andric   bool FrameRegIsKill = false;
246*0eae32dcSDimitry Andric   MachineBasicBlock::iterator NewII(MI);
247*0eae32dcSDimitry Andric   if (!IsLegalOffset(TII, MI, Offset)) {
248*0eae32dcSDimitry Andric     assert(isInt<32>(Offset) && "Int32 expected");
249*0eae32dcSDimitry Andric     // The offset won't fit in an immediate, so use a scratch register instead
250*0eae32dcSDimitry Andric     // Modify Offset and FrameReg appropriately
251*0eae32dcSDimitry Andric     assert(Offset >= 0);
252*0eae32dcSDimitry Andric     Register ScratchReg = TII->movImm(MBB, NewII, DL, Offset);
253*0eae32dcSDimitry Andric     BuildMI(MBB, NewII, DL,
254*0eae32dcSDimitry Andric             TII->get(STI.hasE2() ? CSKY::ADDU32 : CSKY::ADDU16XZ), ScratchReg)
255*0eae32dcSDimitry Andric         .addReg(ScratchReg, RegState::Kill)
256*0eae32dcSDimitry Andric         .addReg(FrameReg);
257*0eae32dcSDimitry Andric 
258*0eae32dcSDimitry Andric     Offset = 0;
259*0eae32dcSDimitry Andric     FrameReg = ScratchReg;
260*0eae32dcSDimitry Andric     FrameRegIsKill = true;
261*0eae32dcSDimitry Andric   }
262*0eae32dcSDimitry Andric 
263*0eae32dcSDimitry Andric   if (Offset == 0 &&
264*0eae32dcSDimitry Andric       (MI->getOpcode() == CSKY::ADDI32 || MI->getOpcode() == CSKY::ADDI16XZ)) {
265*0eae32dcSDimitry Andric     MI->setDesc(TII->get(TargetOpcode::COPY));
266*0eae32dcSDimitry Andric     MI->getOperand(FIOperandNum)
267*0eae32dcSDimitry Andric         .ChangeToRegister(FrameReg, false, false, FrameRegIsKill);
268*0eae32dcSDimitry Andric     MI->RemoveOperand(FIOperandNum + 1);
269*0eae32dcSDimitry Andric   } else {
270*0eae32dcSDimitry Andric     MI->getOperand(FIOperandNum)
271*0eae32dcSDimitry Andric         .ChangeToRegister(FrameReg, false, false, FrameRegIsKill);
272*0eae32dcSDimitry Andric     MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
273*0eae32dcSDimitry Andric   }
274349cc55cSDimitry Andric }
275