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