XCoreRegisterInfo.cpp revision a347f85dbeee37a7f2bb68df1a7d4cdfbb7b576d
1//===- XCoreRegisterInfo.cpp - XCore Register Information -------*- C++ -*-===//
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 "XCoreMachineFunctionInfo.h"
16#include "XCore.h"
17#include "llvm/CodeGen/MachineInstrBuilder.h"
18#include "llvm/CodeGen/MachineFunction.h"
19#include "llvm/CodeGen/MachineFrameInfo.h"
20#include "llvm/CodeGen/MachineLocation.h"
21#include "llvm/CodeGen/MachineModuleInfo.h"
22#include "llvm/CodeGen/MachineRegisterInfo.h"
23#include "llvm/CodeGen/RegisterScavenging.h"
24#include "llvm/Target/TargetFrameLowering.h"
25#include "llvm/Target/TargetMachine.h"
26#include "llvm/Target/TargetOptions.h"
27#include "llvm/Target/TargetInstrInfo.h"
28#include "llvm/Type.h"
29#include "llvm/Function.h"
30#include "llvm/ADT/BitVector.h"
31#include "llvm/ADT/STLExtras.h"
32#include "llvm/Support/Debug.h"
33#include "llvm/Support/ErrorHandling.h"
34#include "llvm/Support/raw_ostream.h"
35#include "XCoreGenRegisterDesc.inc"
36#include "XCoreGenRegisterInfo.inc"
37using namespace llvm;
38
39XCoreRegisterInfo::XCoreRegisterInfo(const TargetInstrInfo &tii)
40  : XCoreGenRegisterInfo(XCoreRegDesc, XCoreRegInfoDesc,
41                         XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP),
42    TII(tii) {
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
58static const unsigned XCore_ArgRegs[] = {
59  XCore::R0, XCore::R1, XCore::R2, XCore::R3
60};
61
62const unsigned * XCoreRegisterInfo::getArgRegs(const MachineFunction *MF)
63{
64  return XCore_ArgRegs;
65}
66
67unsigned XCoreRegisterInfo::getNumArgRegs(const MachineFunction *MF)
68{
69  return array_lengthof(XCore_ArgRegs);
70}
71
72bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) {
73  return MF.getMMI().hasDebugInfo() ||
74    MF.getFunction()->needsUnwindTableEntry();
75}
76
77const unsigned* XCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
78                                                                         const {
79  static const unsigned CalleeSavedRegs[] = {
80    XCore::R4, XCore::R5, XCore::R6, XCore::R7,
81    XCore::R8, XCore::R9, XCore::R10, XCore::LR,
82    0
83  };
84  return CalleeSavedRegs;
85}
86
87BitVector XCoreRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
88  BitVector Reserved(getNumRegs());
89  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
90
91  Reserved.set(XCore::CP);
92  Reserved.set(XCore::DP);
93  Reserved.set(XCore::SP);
94  Reserved.set(XCore::LR);
95  if (TFI->hasFP(MF)) {
96    Reserved.set(XCore::R10);
97  }
98  return Reserved;
99}
100
101bool
102XCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
103  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
104
105  // TODO can we estimate stack size?
106  return TFI->hasFP(MF);
107}
108
109bool
110XCoreRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
111  return false;
112}
113
114// This function eliminates ADJCALLSTACKDOWN,
115// ADJCALLSTACKUP pseudo instructions
116void XCoreRegisterInfo::
117eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
118                              MachineBasicBlock::iterator I) const {
119  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
120
121  if (!TFI->hasReservedCallFrame(MF)) {
122    // Turn the adjcallstackdown instruction into 'extsp <amt>' and the
123    // adjcallstackup instruction into 'ldaw sp, sp[<amt>]'
124    MachineInstr *Old = I;
125    uint64_t Amount = Old->getOperand(0).getImm();
126    if (Amount != 0) {
127      // We need to keep the stack aligned properly.  To do this, we round the
128      // amount of space needed for the outgoing arguments up to the next
129      // alignment boundary.
130      unsigned Align = TFI->getStackAlignment();
131      Amount = (Amount+Align-1)/Align*Align;
132
133      assert(Amount%4 == 0);
134      Amount /= 4;
135
136      bool isU6 = isImmU6(Amount);
137      if (!isU6 && !isImmU16(Amount)) {
138        // FIX could emit multiple instructions in this case.
139#ifndef NDEBUG
140        errs() << "eliminateCallFramePseudoInstr size too big: "
141               << Amount << "\n";
142#endif
143        llvm_unreachable(0);
144      }
145
146      MachineInstr *New;
147      if (Old->getOpcode() == XCore::ADJCALLSTACKDOWN) {
148        int Opcode = isU6 ? XCore::EXTSP_u6 : XCore::EXTSP_lu6;
149        New=BuildMI(MF, Old->getDebugLoc(), TII.get(Opcode))
150          .addImm(Amount);
151      } else {
152        assert(Old->getOpcode() == XCore::ADJCALLSTACKUP);
153        int Opcode = isU6 ? XCore::LDAWSP_ru6_RRegs : XCore::LDAWSP_lru6_RRegs;
154        New=BuildMI(MF, Old->getDebugLoc(), TII.get(Opcode), XCore::SP)
155          .addImm(Amount);
156      }
157
158      // Replace the pseudo instruction with a new instruction...
159      MBB.insert(I, New);
160    }
161  }
162
163  MBB.erase(I);
164}
165
166void
167XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
168                                       int SPAdj, RegScavenger *RS) const {
169  assert(SPAdj == 0 && "Unexpected");
170  MachineInstr &MI = *II;
171  DebugLoc dl = MI.getDebugLoc();
172  unsigned i = 0;
173
174  while (!MI.getOperand(i).isFI()) {
175    ++i;
176    assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
177  }
178
179  MachineOperand &FrameOp = MI.getOperand(i);
180  int FrameIndex = FrameOp.getIndex();
181
182  MachineFunction &MF = *MI.getParent()->getParent();
183  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
184  int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
185  int StackSize = MF.getFrameInfo()->getStackSize();
186
187  #ifndef NDEBUG
188  DEBUG(errs() << "\nFunction         : "
189        << MF.getFunction()->getName() << "\n");
190  DEBUG(errs() << "<--------->\n");
191  DEBUG(MI.print(errs()));
192  DEBUG(errs() << "FrameIndex         : " << FrameIndex << "\n");
193  DEBUG(errs() << "FrameOffset        : " << Offset << "\n");
194  DEBUG(errs() << "StackSize          : " << StackSize << "\n");
195  #endif
196
197  Offset += StackSize;
198
199  // fold constant into offset.
200  Offset += MI.getOperand(i + 1).getImm();
201  MI.getOperand(i + 1).ChangeToImmediate(0);
202
203  assert(Offset%4 == 0 && "Misaligned stack offset");
204
205  DEBUG(errs() << "Offset             : " << Offset << "\n" << "<--------->\n");
206
207  Offset/=4;
208
209  bool FP = TFI->hasFP(MF);
210
211  unsigned Reg = MI.getOperand(0).getReg();
212  bool isKill = MI.getOpcode() == XCore::STWFI && MI.getOperand(0).isKill();
213
214  assert(XCore::GRRegsRegisterClass->contains(Reg) &&
215         "Unexpected register operand");
216
217  MachineBasicBlock &MBB = *MI.getParent();
218
219  if (FP) {
220    bool isUs = isImmUs(Offset);
221    unsigned FramePtr = XCore::R10;
222
223    if (!isUs) {
224      if (!RS)
225        report_fatal_error("eliminateFrameIndex Frame size too big: " +
226                           Twine(Offset));
227      unsigned ScratchReg = RS->scavengeRegister(XCore::GRRegsRegisterClass, II,
228                                                 SPAdj);
229      loadConstant(MBB, II, ScratchReg, Offset, dl);
230      switch (MI.getOpcode()) {
231      case XCore::LDWFI:
232        BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg)
233              .addReg(FramePtr)
234              .addReg(ScratchReg, RegState::Kill);
235        break;
236      case XCore::STWFI:
237        BuildMI(MBB, II, dl, TII.get(XCore::STW_3r))
238              .addReg(Reg, getKillRegState(isKill))
239              .addReg(FramePtr)
240              .addReg(ScratchReg, RegState::Kill);
241        break;
242      case XCore::LDAWFI:
243        BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg)
244              .addReg(FramePtr)
245              .addReg(ScratchReg, RegState::Kill);
246        break;
247      default:
248        llvm_unreachable("Unexpected Opcode");
249      }
250    } else {
251      switch (MI.getOpcode()) {
252      case XCore::LDWFI:
253        BuildMI(MBB, II, dl, TII.get(XCore::LDW_2rus), Reg)
254              .addReg(FramePtr)
255              .addImm(Offset);
256        break;
257      case XCore::STWFI:
258        BuildMI(MBB, II, dl, TII.get(XCore::STW_2rus))
259              .addReg(Reg, getKillRegState(isKill))
260              .addReg(FramePtr)
261              .addImm(Offset);
262        break;
263      case XCore::LDAWFI:
264        BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l2rus), Reg)
265              .addReg(FramePtr)
266              .addImm(Offset);
267        break;
268      default:
269        llvm_unreachable("Unexpected Opcode");
270      }
271    }
272  } else {
273    bool isU6 = isImmU6(Offset);
274    if (!isU6 && !isImmU16(Offset))
275      report_fatal_error("eliminateFrameIndex Frame size too big: " +
276                         Twine(Offset));
277
278    switch (MI.getOpcode()) {
279    int NewOpcode;
280    case XCore::LDWFI:
281      NewOpcode = (isU6) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;
282      BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
283            .addImm(Offset);
284      break;
285    case XCore::STWFI:
286      NewOpcode = (isU6) ? XCore::STWSP_ru6 : XCore::STWSP_lru6;
287      BuildMI(MBB, II, dl, TII.get(NewOpcode))
288            .addReg(Reg, getKillRegState(isKill))
289            .addImm(Offset);
290      break;
291    case XCore::LDAWFI:
292      NewOpcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
293      BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
294            .addImm(Offset);
295      break;
296    default:
297      llvm_unreachable("Unexpected Opcode");
298    }
299  }
300  // Erase old instruction.
301  MBB.erase(II);
302}
303
304void XCoreRegisterInfo::
305loadConstant(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
306            unsigned DstReg, int64_t Value, DebugLoc dl) const {
307  // TODO use mkmsk if possible.
308  if (!isImmU16(Value)) {
309    // TODO use constant pool.
310    report_fatal_error("loadConstant value too big " + Twine(Value));
311  }
312  int Opcode = isImmU6(Value) ? XCore::LDC_ru6 : XCore::LDC_lru6;
313  BuildMI(MBB, I, dl, TII.get(Opcode), DstReg).addImm(Value);
314}
315
316int XCoreRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
317  return XCoreGenRegisterInfo::getDwarfRegNumFull(RegNum, 0);
318}
319
320int XCoreRegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const {
321  return XCoreGenRegisterInfo::getLLVMRegNumFull(DwarfRegNo,0);
322}
323
324unsigned XCoreRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
325  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
326
327  return TFI->hasFP(MF) ? XCore::R10 : XCore::SP;
328}
329
330unsigned XCoreRegisterInfo::getRARegister() const {
331  return XCore::LR;
332}
333