XCoreRegisterInfo.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
1//===-- XCoreRegisterInfo.cpp - XCore Register Information ----------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the XCore implementation of the MRegisterInfo class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "XCoreRegisterInfo.h"
15#include "XCore.h"
16#include "XCoreInstrInfo.h"
17#include "XCoreMachineFunctionInfo.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/Target/TargetFrameLowering.h"
33#include "llvm/Target/TargetMachine.h"
34#include "llvm/Target/TargetOptions.h"
35
36#define GET_REGINFO_TARGET_DESC
37#include "XCoreGenRegisterInfo.inc"
38
39using namespace llvm;
40
41XCoreRegisterInfo::XCoreRegisterInfo()
42  : XCoreGenRegisterInfo(XCore::LR) {
43}
44
45// helper functions
46static inline bool isImmUs(unsigned val) {
47  return val <= 11;
48}
49
50static inline bool isImmU6(unsigned val) {
51  return val < (1 << 6);
52}
53
54static inline bool isImmU16(unsigned val) {
55  return val < (1 << 16);
56}
57
58
59static void InsertFPImmInst(MachineBasicBlock::iterator II,
60                            const XCoreInstrInfo &TII,
61                            unsigned Reg, unsigned FrameReg, int Offset ) {
62  MachineInstr &MI = *II;
63  MachineBasicBlock &MBB = *MI.getParent();
64  DebugLoc dl = MI.getDebugLoc();
65
66  switch (MI.getOpcode()) {
67  case XCore::LDWFI:
68    BuildMI(MBB, II, dl, TII.get(XCore::LDW_2rus), Reg)
69          .addReg(FrameReg)
70          .addImm(Offset)
71          .addMemOperand(*MI.memoperands_begin());
72    break;
73  case XCore::STWFI:
74    BuildMI(MBB, II, dl, TII.get(XCore::STW_2rus))
75          .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
76          .addReg(FrameReg)
77          .addImm(Offset)
78          .addMemOperand(*MI.memoperands_begin());
79    break;
80  case XCore::LDAWFI:
81    BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l2rus), Reg)
82          .addReg(FrameReg)
83          .addImm(Offset);
84    break;
85  default:
86    llvm_unreachable("Unexpected Opcode");
87  }
88}
89
90static void InsertFPConstInst(MachineBasicBlock::iterator II,
91                              const XCoreInstrInfo &TII,
92                              unsigned Reg, unsigned FrameReg,
93                              int Offset, RegScavenger *RS ) {
94  assert(RS && "requiresRegisterScavenging failed");
95  MachineInstr &MI = *II;
96  MachineBasicBlock &MBB = *MI.getParent();
97  DebugLoc dl = MI.getDebugLoc();
98  unsigned ScratchOffset = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0);
99  RS->setUsed(ScratchOffset);
100  TII.loadImmediate(MBB, II, ScratchOffset, Offset);
101
102  switch (MI.getOpcode()) {
103  case XCore::LDWFI:
104    BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg)
105          .addReg(FrameReg)
106          .addReg(ScratchOffset, RegState::Kill)
107          .addMemOperand(*MI.memoperands_begin());
108    break;
109  case XCore::STWFI:
110    BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r))
111          .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
112          .addReg(FrameReg)
113          .addReg(ScratchOffset, RegState::Kill)
114          .addMemOperand(*MI.memoperands_begin());
115    break;
116  case XCore::LDAWFI:
117    BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg)
118          .addReg(FrameReg)
119          .addReg(ScratchOffset, RegState::Kill);
120    break;
121  default:
122    llvm_unreachable("Unexpected Opcode");
123  }
124}
125
126static void InsertSPImmInst(MachineBasicBlock::iterator II,
127                            const XCoreInstrInfo &TII,
128                            unsigned Reg, int Offset) {
129  MachineInstr &MI = *II;
130  MachineBasicBlock &MBB = *MI.getParent();
131  DebugLoc dl = MI.getDebugLoc();
132  bool isU6 = isImmU6(Offset);
133
134  switch (MI.getOpcode()) {
135  int NewOpcode;
136  case XCore::LDWFI:
137    NewOpcode = (isU6) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;
138    BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
139          .addImm(Offset)
140          .addMemOperand(*MI.memoperands_begin());
141    break;
142  case XCore::STWFI:
143    NewOpcode = (isU6) ? XCore::STWSP_ru6 : XCore::STWSP_lru6;
144    BuildMI(MBB, II, dl, TII.get(NewOpcode))
145          .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
146          .addImm(Offset)
147          .addMemOperand(*MI.memoperands_begin());
148    break;
149  case XCore::LDAWFI:
150    NewOpcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
151    BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
152          .addImm(Offset);
153    break;
154  default:
155    llvm_unreachable("Unexpected Opcode");
156  }
157}
158
159static void InsertSPConstInst(MachineBasicBlock::iterator II,
160                                const XCoreInstrInfo &TII,
161                                unsigned Reg, int Offset, RegScavenger *RS ) {
162  assert(RS && "requiresRegisterScavenging failed");
163  MachineInstr &MI = *II;
164  MachineBasicBlock &MBB = *MI.getParent();
165  DebugLoc dl = MI.getDebugLoc();
166  unsigned OpCode = MI.getOpcode();
167
168  unsigned ScratchBase;
169  if (OpCode==XCore::STWFI) {
170    ScratchBase = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0);
171    RS->setUsed(ScratchBase);
172  } else
173    ScratchBase = Reg;
174  BuildMI(MBB, II, dl, TII.get(XCore::LDAWSP_ru6), ScratchBase).addImm(0);
175  unsigned ScratchOffset = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0);
176  RS->setUsed(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
203bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) {
204  return MF.getMMI().hasDebugInfo() ||
205    MF.getFunction()->needsUnwindTableEntry();
206}
207
208const uint16_t* XCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
209                                                                         const {
210  // The callee saved registers LR & FP are explicitly handled during
211  // emitPrologue & emitEpilogue and related functions.
212  static const uint16_t CalleeSavedRegs[] = {
213    XCore::R4, XCore::R5, XCore::R6, XCore::R7,
214    XCore::R8, XCore::R9, XCore::R10,
215    0
216  };
217  static const uint16_t CalleeSavedRegsFP[] = {
218    XCore::R4, XCore::R5, XCore::R6, XCore::R7,
219    XCore::R8, XCore::R9,
220    0
221  };
222  const TargetFrameLowering *TFI = MF->getTarget().getFrameLowering();
223  if (TFI->hasFP(*MF))
224    return CalleeSavedRegsFP;
225  return CalleeSavedRegs;
226}
227
228BitVector XCoreRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
229  BitVector Reserved(getNumRegs());
230  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
231
232  Reserved.set(XCore::CP);
233  Reserved.set(XCore::DP);
234  Reserved.set(XCore::SP);
235  Reserved.set(XCore::LR);
236  if (TFI->hasFP(MF)) {
237    Reserved.set(XCore::R10);
238  }
239  return Reserved;
240}
241
242bool
243XCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
244  return true;
245}
246
247bool
248XCoreRegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction &MF) const {
249  return true;
250}
251
252bool
253XCoreRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
254  return false;
255}
256
257void
258XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
259                                       int SPAdj, unsigned FIOperandNum,
260                                       RegScavenger *RS) const {
261  assert(SPAdj == 0 && "Unexpected");
262  MachineInstr &MI = *II;
263  MachineOperand &FrameOp = MI.getOperand(FIOperandNum);
264  int FrameIndex = FrameOp.getIndex();
265
266  MachineFunction &MF = *MI.getParent()->getParent();
267  const XCoreInstrInfo &TII =
268          *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo());
269
270  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
271  int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
272  int StackSize = MF.getFrameInfo()->getStackSize();
273
274  #ifndef NDEBUG
275  DEBUG(errs() << "\nFunction         : "
276        << MF.getName() << "\n");
277  DEBUG(errs() << "<--------->\n");
278  DEBUG(MI.print(errs()));
279  DEBUG(errs() << "FrameIndex         : " << FrameIndex << "\n");
280  DEBUG(errs() << "FrameOffset        : " << Offset << "\n");
281  DEBUG(errs() << "StackSize          : " << StackSize << "\n");
282  #endif
283
284  Offset += StackSize;
285
286  unsigned 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  DEBUG(errs() << "Offset             : " << Offset << "\n" << "<--------->\n");
301  Offset/=4;
302
303  unsigned Reg = MI.getOperand(0).getReg();
304  assert(XCore::GRRegsRegClass.contains(Reg) && "Unexpected register operand");
305
306  if (TFI->hasFP(MF)) {
307    if (isImmUs(Offset))
308      InsertFPImmInst(II, TII, Reg, FrameReg, Offset);
309    else
310      InsertFPConstInst(II, TII, Reg, FrameReg, Offset, RS);
311  } else {
312    if (isImmU16(Offset))
313      InsertSPImmInst(II, TII, Reg, Offset);
314    else
315      InsertSPConstInst(II, TII, Reg, Offset, RS);
316  }
317  // Erase old instruction.
318  MachineBasicBlock &MBB = *MI.getParent();
319  MBB.erase(II);
320}
321
322
323unsigned XCoreRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
324  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
325
326  return TFI->hasFP(MF) ? XCore::R10 : XCore::SP;
327}
328