xref: /llvm-project/llvm/lib/Target/XCore/XCoreRegisterInfo.cpp (revision ed8019d9fbed2e6a6b08f8f73e9fa54a24f3ed52)
1 //===-- XCoreRegisterInfo.cpp - XCore Register Information ----------------===//
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 XCore implementation of the MRegisterInfo class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "XCoreRegisterInfo.h"
14 #include "XCoreInstrInfo.h"
15 #include "XCoreSubtarget.h"
16 #include "llvm/ADT/BitVector.h"
17 #include "llvm/CodeGen/MachineFrameInfo.h"
18 #include "llvm/CodeGen/MachineFunction.h"
19 #include "llvm/CodeGen/MachineInstrBuilder.h"
20 #include "llvm/CodeGen/MachineModuleInfo.h"
21 #include "llvm/CodeGen/RegisterScavenging.h"
22 #include "llvm/CodeGen/TargetFrameLowering.h"
23 #include "llvm/IR/Function.h"
24 #include "llvm/IR/Type.h"
25 #include "llvm/Support/Debug.h"
26 #include "llvm/Support/ErrorHandling.h"
27 #include "llvm/Support/raw_ostream.h"
28 #include "llvm/Target/TargetMachine.h"
29 #include "llvm/Target/TargetOptions.h"
30 
31 using namespace llvm;
32 
33 #define DEBUG_TYPE "xcore-reg-info"
34 
35 #define GET_REGINFO_TARGET_DESC
36 #include "XCoreGenRegisterInfo.inc"
37 
38 XCoreRegisterInfo::XCoreRegisterInfo()
39   : XCoreGenRegisterInfo(XCore::LR) {
40 }
41 
42 // helper functions
43 static inline bool isImmUs(unsigned val) {
44   return val <= 11;
45 }
46 
47 static inline bool isImmU6(unsigned val) {
48   return val < (1 << 6);
49 }
50 
51 static inline bool isImmU16(unsigned val) {
52   return val < (1 << 16);
53 }
54 
55 
56 static void InsertFPImmInst(MachineBasicBlock::iterator II,
57                             const XCoreInstrInfo &TII,
58                             unsigned Reg, unsigned FrameReg, int Offset ) {
59   MachineInstr &MI = *II;
60   MachineBasicBlock &MBB = *MI.getParent();
61   DebugLoc dl = MI.getDebugLoc();
62 
63   switch (MI.getOpcode()) {
64   case XCore::LDWFI:
65     BuildMI(MBB, II, dl, TII.get(XCore::LDW_2rus), Reg)
66           .addReg(FrameReg)
67           .addImm(Offset)
68           .addMemOperand(*MI.memoperands_begin());
69     break;
70   case XCore::STWFI:
71     BuildMI(MBB, II, dl, TII.get(XCore::STW_2rus))
72           .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
73           .addReg(FrameReg)
74           .addImm(Offset)
75           .addMemOperand(*MI.memoperands_begin());
76     break;
77   case XCore::LDAWFI:
78     BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l2rus), Reg)
79           .addReg(FrameReg)
80           .addImm(Offset);
81     break;
82   default:
83     llvm_unreachable("Unexpected Opcode");
84   }
85 }
86 
87 static void InsertFPConstInst(MachineBasicBlock::iterator II,
88                               const XCoreInstrInfo &TII,
89                               unsigned Reg, unsigned FrameReg,
90                               int Offset, RegScavenger *RS ) {
91   assert(RS && "requiresRegisterScavenging failed");
92   MachineInstr &MI = *II;
93   MachineBasicBlock &MBB = *MI.getParent();
94   DebugLoc dl = MI.getDebugLoc();
95   Register ScratchOffset =
96       RS->scavengeRegisterBackwards(XCore::GRRegsRegClass, II, false, 0);
97   RS->setRegUsed(ScratchOffset);
98   TII.loadImmediate(MBB, II, ScratchOffset, Offset);
99 
100   switch (MI.getOpcode()) {
101   case XCore::LDWFI:
102     BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg)
103           .addReg(FrameReg)
104           .addReg(ScratchOffset, RegState::Kill)
105           .addMemOperand(*MI.memoperands_begin());
106     break;
107   case XCore::STWFI:
108     BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r))
109           .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
110           .addReg(FrameReg)
111           .addReg(ScratchOffset, RegState::Kill)
112           .addMemOperand(*MI.memoperands_begin());
113     break;
114   case XCore::LDAWFI:
115     BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg)
116           .addReg(FrameReg)
117           .addReg(ScratchOffset, RegState::Kill);
118     break;
119   default:
120     llvm_unreachable("Unexpected Opcode");
121   }
122 }
123 
124 static void InsertSPImmInst(MachineBasicBlock::iterator II,
125                             const XCoreInstrInfo &TII,
126                             unsigned Reg, int Offset) {
127   MachineInstr &MI = *II;
128   MachineBasicBlock &MBB = *MI.getParent();
129   DebugLoc dl = MI.getDebugLoc();
130   bool isU6 = isImmU6(Offset);
131 
132   switch (MI.getOpcode()) {
133   int NewOpcode;
134   case XCore::LDWFI:
135     NewOpcode = (isU6) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;
136     BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
137           .addImm(Offset)
138           .addMemOperand(*MI.memoperands_begin());
139     break;
140   case XCore::STWFI:
141     NewOpcode = (isU6) ? XCore::STWSP_ru6 : XCore::STWSP_lru6;
142     BuildMI(MBB, II, dl, TII.get(NewOpcode))
143           .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
144           .addImm(Offset)
145           .addMemOperand(*MI.memoperands_begin());
146     break;
147   case XCore::LDAWFI:
148     NewOpcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
149     BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
150           .addImm(Offset);
151     break;
152   default:
153     llvm_unreachable("Unexpected Opcode");
154   }
155 }
156 
157 static void InsertSPConstInst(MachineBasicBlock::iterator II,
158                                 const XCoreInstrInfo &TII,
159                                 unsigned Reg, int Offset, RegScavenger *RS ) {
160   assert(RS && "requiresRegisterScavenging failed");
161   MachineInstr &MI = *II;
162   MachineBasicBlock &MBB = *MI.getParent();
163   DebugLoc dl = MI.getDebugLoc();
164   unsigned OpCode = MI.getOpcode();
165 
166   unsigned ScratchBase;
167   if (OpCode==XCore::STWFI) {
168     ScratchBase =
169         RS->scavengeRegisterBackwards(XCore::GRRegsRegClass, II, false, 0);
170     RS->setRegUsed(ScratchBase);
171   } else
172     ScratchBase = Reg;
173   BuildMI(MBB, II, dl, TII.get(XCore::LDAWSP_ru6), ScratchBase).addImm(0);
174   Register ScratchOffset =
175       RS->scavengeRegisterBackwards(XCore::GRRegsRegClass, II, false, 0);
176   RS->setRegUsed(ScratchOffset);
177   TII.loadImmediate(MBB, II, ScratchOffset, Offset);
178 
179   switch (OpCode) {
180   case XCore::LDWFI:
181     BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg)
182           .addReg(ScratchBase, RegState::Kill)
183           .addReg(ScratchOffset, RegState::Kill)
184           .addMemOperand(*MI.memoperands_begin());
185     break;
186   case XCore::STWFI:
187     BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r))
188           .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
189           .addReg(ScratchBase, RegState::Kill)
190           .addReg(ScratchOffset, RegState::Kill)
191           .addMemOperand(*MI.memoperands_begin());
192     break;
193   case XCore::LDAWFI:
194     BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg)
195           .addReg(ScratchBase, RegState::Kill)
196           .addReg(ScratchOffset, RegState::Kill);
197     break;
198   default:
199     llvm_unreachable("Unexpected Opcode");
200   }
201 }
202 
203 bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) {
204   return MF.needsFrameMoves();
205 }
206 
207 const MCPhysReg *
208 XCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
209   // The callee saved registers LR & FP are explicitly handled during
210   // emitPrologue & emitEpilogue and related functions.
211   static const MCPhysReg CalleeSavedRegs[] = {
212     XCore::R4, XCore::R5, XCore::R6, XCore::R7,
213     XCore::R8, XCore::R9, XCore::R10,
214     0
215   };
216   static const MCPhysReg CalleeSavedRegsFP[] = {
217     XCore::R4, XCore::R5, XCore::R6, XCore::R7,
218     XCore::R8, XCore::R9,
219     0
220   };
221   const XCoreFrameLowering *TFI = getFrameLowering(*MF);
222   if (TFI->hasFP(*MF))
223     return CalleeSavedRegsFP;
224   return CalleeSavedRegs;
225 }
226 
227 BitVector XCoreRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
228   BitVector Reserved(getNumRegs());
229   const XCoreFrameLowering *TFI = getFrameLowering(MF);
230 
231   Reserved.set(XCore::CP);
232   Reserved.set(XCore::DP);
233   Reserved.set(XCore::SP);
234   Reserved.set(XCore::LR);
235   if (TFI->hasFP(MF)) {
236     Reserved.set(XCore::R10);
237   }
238   return Reserved;
239 }
240 
241 bool
242 XCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
243   return true;
244 }
245 
246 bool
247 XCoreRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
248   return false;
249 }
250 
251 bool
252 XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
253                                        int SPAdj, unsigned FIOperandNum,
254                                        RegScavenger *RS) const {
255   assert(SPAdj == 0 && "Unexpected");
256   MachineInstr &MI = *II;
257   MachineOperand &FrameOp = MI.getOperand(FIOperandNum);
258   int FrameIndex = FrameOp.getIndex();
259 
260   MachineFunction &MF = *MI.getParent()->getParent();
261   const XCoreInstrInfo &TII =
262       *static_cast<const XCoreInstrInfo *>(MF.getSubtarget().getInstrInfo());
263 
264   const XCoreFrameLowering *TFI = getFrameLowering(MF);
265   int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex);
266   int StackSize = MF.getFrameInfo().getStackSize();
267 
268   #ifndef NDEBUG
269   LLVM_DEBUG(errs() << "\nFunction         : " << MF.getName() << "\n");
270   LLVM_DEBUG(errs() << "<--------->\n");
271   LLVM_DEBUG(MI.print(errs()));
272   LLVM_DEBUG(errs() << "FrameIndex         : " << FrameIndex << "\n");
273   LLVM_DEBUG(errs() << "FrameOffset        : " << Offset << "\n");
274   LLVM_DEBUG(errs() << "StackSize          : " << StackSize << "\n");
275 #endif
276 
277   Offset += StackSize;
278 
279   Register FrameReg = getFrameRegister(MF);
280 
281   // Special handling of DBG_VALUE instructions.
282   if (MI.isDebugValue()) {
283     MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false /*isDef*/);
284     MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
285     return false;
286   }
287 
288   // fold constant into offset.
289   Offset += MI.getOperand(FIOperandNum + 1).getImm();
290   MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0);
291 
292   assert(Offset%4 == 0 && "Misaligned stack offset");
293   LLVM_DEBUG(errs() << "Offset             : " << Offset << "\n"
294                     << "<--------->\n");
295   Offset/=4;
296 
297   Register Reg = MI.getOperand(0).getReg();
298   assert(XCore::GRRegsRegClass.contains(Reg) && "Unexpected register operand");
299 
300   if (TFI->hasFP(MF)) {
301     if (isImmUs(Offset))
302       InsertFPImmInst(II, TII, Reg, FrameReg, Offset);
303     else
304       InsertFPConstInst(II, TII, Reg, FrameReg, Offset, RS);
305   } else {
306     if (isImmU16(Offset))
307       InsertSPImmInst(II, TII, Reg, Offset);
308     else
309       InsertSPConstInst(II, TII, Reg, Offset, RS);
310   }
311   // Erase old instruction.
312   MachineBasicBlock &MBB = *MI.getParent();
313   MBB.erase(II);
314   return true;
315 }
316 
317 
318 Register XCoreRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
319   const XCoreFrameLowering *TFI = getFrameLowering(MF);
320 
321   return TFI->hasFP(MF) ? XCore::R10 : XCore::SP;
322 }
323