XCoreRegisterInfo.cpp revision dce4a407a24b04eebc6a376f8e62b41aaa7b071f
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
36using namespace llvm;
37
38#define DEBUG_TYPE "xcore-reg-info"
39
40#define GET_REGINFO_TARGET_DESC
41#include "XCoreGenRegisterInfo.inc"
42
43XCoreRegisterInfo::XCoreRegisterInfo()
44  : XCoreGenRegisterInfo(XCore::LR) {
45}
46
47// helper functions
48static inline bool isImmUs(unsigned val) {
49  return val <= 11;
50}
51
52static inline bool isImmU6(unsigned val) {
53  return val < (1 << 6);
54}
55
56static inline bool isImmU16(unsigned val) {
57  return val < (1 << 16);
58}
59
60
61static 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
92static 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->setUsed(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
128static 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
161static 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->setUsed(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->setUsed(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
205bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) {
206  return MF.getMMI().hasDebugInfo() ||
207    MF.getFunction()->needsUnwindTableEntry();
208}
209
210const MCPhysReg* XCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
211                                                                         const {
212  // The callee saved registers LR & FP are explicitly handled during
213  // emitPrologue & emitEpilogue and related functions.
214  static const MCPhysReg CalleeSavedRegs[] = {
215    XCore::R4, XCore::R5, XCore::R6, XCore::R7,
216    XCore::R8, XCore::R9, XCore::R10,
217    0
218  };
219  static const MCPhysReg CalleeSavedRegsFP[] = {
220    XCore::R4, XCore::R5, XCore::R6, XCore::R7,
221    XCore::R8, XCore::R9,
222    0
223  };
224  const TargetFrameLowering *TFI = MF->getTarget().getFrameLowering();
225  if (TFI->hasFP(*MF))
226    return CalleeSavedRegsFP;
227  return CalleeSavedRegs;
228}
229
230BitVector XCoreRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
231  BitVector Reserved(getNumRegs());
232  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
233
234  Reserved.set(XCore::CP);
235  Reserved.set(XCore::DP);
236  Reserved.set(XCore::SP);
237  Reserved.set(XCore::LR);
238  if (TFI->hasFP(MF)) {
239    Reserved.set(XCore::R10);
240  }
241  return Reserved;
242}
243
244bool
245XCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
246  return true;
247}
248
249bool
250XCoreRegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction &MF) const {
251  return true;
252}
253
254bool
255XCoreRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
256  return false;
257}
258
259void
260XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
261                                       int SPAdj, unsigned FIOperandNum,
262                                       RegScavenger *RS) const {
263  assert(SPAdj == 0 && "Unexpected");
264  MachineInstr &MI = *II;
265  MachineOperand &FrameOp = MI.getOperand(FIOperandNum);
266  int FrameIndex = FrameOp.getIndex();
267
268  MachineFunction &MF = *MI.getParent()->getParent();
269  const XCoreInstrInfo &TII =
270          *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo());
271
272  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
273  int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
274  int StackSize = MF.getFrameInfo()->getStackSize();
275
276  #ifndef NDEBUG
277  DEBUG(errs() << "\nFunction         : "
278        << MF.getName() << "\n");
279  DEBUG(errs() << "<--------->\n");
280  DEBUG(MI.print(errs()));
281  DEBUG(errs() << "FrameIndex         : " << FrameIndex << "\n");
282  DEBUG(errs() << "FrameOffset        : " << Offset << "\n");
283  DEBUG(errs() << "StackSize          : " << StackSize << "\n");
284  #endif
285
286  Offset += StackSize;
287
288  unsigned FrameReg = getFrameRegister(MF);
289
290  // Special handling of DBG_VALUE instructions.
291  if (MI.isDebugValue()) {
292    MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false /*isDef*/);
293    MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
294    return;
295  }
296
297  // fold constant into offset.
298  Offset += MI.getOperand(FIOperandNum + 1).getImm();
299  MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0);
300
301  assert(Offset%4 == 0 && "Misaligned stack offset");
302  DEBUG(errs() << "Offset             : " << Offset << "\n" << "<--------->\n");
303  Offset/=4;
304
305  unsigned Reg = MI.getOperand(0).getReg();
306  assert(XCore::GRRegsRegClass.contains(Reg) && "Unexpected register operand");
307
308  if (TFI->hasFP(MF)) {
309    if (isImmUs(Offset))
310      InsertFPImmInst(II, TII, Reg, FrameReg, Offset);
311    else
312      InsertFPConstInst(II, TII, Reg, FrameReg, Offset, RS);
313  } else {
314    if (isImmU16(Offset))
315      InsertSPImmInst(II, TII, Reg, Offset);
316    else
317      InsertSPConstInst(II, TII, Reg, Offset, RS);
318  }
319  // Erase old instruction.
320  MachineBasicBlock &MBB = *MI.getParent();
321  MBB.erase(II);
322}
323
324
325unsigned XCoreRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
326  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
327
328  return TFI->hasFP(MF) ? XCore::R10 : XCore::SP;
329}
330