LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
XCoreRegisterInfo.cpp
Go to the documentation of this file.
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"
17 #include "llvm/ADT/BitVector.h"
18 #include "llvm/ADT/STLExtras.h"
25 #include "llvm/IR/Function.h"
26 #include "llvm/IR/Type.h"
27 #include "llvm/Support/Debug.h"
34 
35 #define GET_REGINFO_TARGET_DESC
36 #include "XCoreGenRegisterInfo.inc"
37 
38 using namespace llvm;
39 
41  : XCoreGenRegisterInfo(XCore::LR) {
42 }
43 
44 // helper functions
45 static inline bool isImmUs(unsigned val) {
46  return val <= 11;
47 }
48 
49 static inline bool isImmU6(unsigned val) {
50  return val < (1 << 6);
51 }
52 
53 static inline bool isImmU16(unsigned val) {
54  return val < (1 << 16);
55 }
56 
58  return MF.getMMI().hasDebugInfo() ||
60 }
61 
63  const {
64  static const uint16_t CalleeSavedRegs[] = {
65  XCore::R4, XCore::R5, XCore::R6, XCore::R7,
66  XCore::R8, XCore::R9, XCore::R10, XCore::LR,
67  0
68  };
69  return CalleeSavedRegs;
70 }
71 
73  BitVector Reserved(getNumRegs());
75 
76  Reserved.set(XCore::CP);
77  Reserved.set(XCore::DP);
78  Reserved.set(XCore::SP);
79  Reserved.set(XCore::LR);
80  if (TFI->hasFP(MF)) {
81  Reserved.set(XCore::R10);
82  }
83  return Reserved;
84 }
85 
86 bool
89 
90  // TODO can we estimate stack size?
91  return TFI->hasFP(MF);
92 }
93 
94 bool
96  return requiresRegisterScavenging(MF);
97 }
98 
99 bool
101  return false;
102 }
103 
104 void
106  int SPAdj, unsigned FIOperandNum,
107  RegScavenger *RS) const {
108  assert(SPAdj == 0 && "Unexpected");
109  MachineInstr &MI = *II;
110  DebugLoc dl = MI.getDebugLoc();
111  MachineOperand &FrameOp = MI.getOperand(FIOperandNum);
112  int FrameIndex = FrameOp.getIndex();
113 
114  MachineFunction &MF = *MI.getParent()->getParent();
115  const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
116  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
117  int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
118  int StackSize = MF.getFrameInfo()->getStackSize();
119 
120  #ifndef NDEBUG
121  DEBUG(errs() << "\nFunction : "
122  << MF.getName() << "\n");
123  DEBUG(errs() << "<--------->\n");
124  DEBUG(MI.print(errs()));
125  DEBUG(errs() << "FrameIndex : " << FrameIndex << "\n");
126  DEBUG(errs() << "FrameOffset : " << Offset << "\n");
127  DEBUG(errs() << "StackSize : " << StackSize << "\n");
128  #endif
129 
130  Offset += StackSize;
131 
132  unsigned FrameReg = getFrameRegister(MF);
133 
134  // Special handling of DBG_VALUE instructions.
135  if (MI.isDebugValue()) {
136  MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false /*isDef*/);
137  MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
138  return;
139  }
140 
141  // fold constant into offset.
142  Offset += MI.getOperand(FIOperandNum + 1).getImm();
143  MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0);
144 
145  assert(Offset%4 == 0 && "Misaligned stack offset");
146 
147  DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n");
148 
149  Offset/=4;
150 
151  bool FP = TFI->hasFP(MF);
152 
153  unsigned Reg = MI.getOperand(0).getReg();
154  bool isKill = MI.getOpcode() == XCore::STWFI && MI.getOperand(0).isKill();
155 
156  assert(XCore::GRRegsRegClass.contains(Reg) && "Unexpected register operand");
157 
158  MachineBasicBlock &MBB = *MI.getParent();
159 
160  if (FP) {
161  bool isUs = isImmUs(Offset);
162 
163  if (!isUs) {
164  if (!RS)
165  report_fatal_error("eliminateFrameIndex Frame size too big: " +
166  Twine(Offset));
167  unsigned ScratchReg = RS->scavengeRegister(&XCore::GRRegsRegClass, II,
168  SPAdj);
169  loadConstant(MBB, II, ScratchReg, Offset, dl);
170  switch (MI.getOpcode()) {
171  case XCore::LDWFI:
172  BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg)
173  .addReg(FrameReg)
174  .addReg(ScratchReg, RegState::Kill);
175  break;
176  case XCore::STWFI:
177  BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r))
178  .addReg(Reg, getKillRegState(isKill))
179  .addReg(FrameReg)
180  .addReg(ScratchReg, RegState::Kill);
181  break;
182  case XCore::LDAWFI:
183  BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg)
184  .addReg(FrameReg)
185  .addReg(ScratchReg, RegState::Kill);
186  break;
187  default:
188  llvm_unreachable("Unexpected Opcode");
189  }
190  } else {
191  switch (MI.getOpcode()) {
192  case XCore::LDWFI:
193  BuildMI(MBB, II, dl, TII.get(XCore::LDW_2rus), Reg)
194  .addReg(FrameReg)
195  .addImm(Offset);
196  break;
197  case XCore::STWFI:
198  BuildMI(MBB, II, dl, TII.get(XCore::STW_2rus))
199  .addReg(Reg, getKillRegState(isKill))
200  .addReg(FrameReg)
201  .addImm(Offset);
202  break;
203  case XCore::LDAWFI:
204  BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l2rus), Reg)
205  .addReg(FrameReg)
206  .addImm(Offset);
207  break;
208  default:
209  llvm_unreachable("Unexpected Opcode");
210  }
211  }
212  } else {
213  bool isU6 = isImmU6(Offset);
214  if (!isU6 && !isImmU16(Offset))
215  report_fatal_error("eliminateFrameIndex Frame size too big: " +
216  Twine(Offset));
217 
218  switch (MI.getOpcode()) {
219  int NewOpcode;
220  case XCore::LDWFI:
221  NewOpcode = (isU6) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;
222  BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
223  .addImm(Offset);
224  break;
225  case XCore::STWFI:
226  NewOpcode = (isU6) ? XCore::STWSP_ru6 : XCore::STWSP_lru6;
227  BuildMI(MBB, II, dl, TII.get(NewOpcode))
228  .addReg(Reg, getKillRegState(isKill))
229  .addImm(Offset);
230  break;
231  case XCore::LDAWFI:
232  NewOpcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
233  BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
234  .addImm(Offset);
235  break;
236  default:
237  llvm_unreachable("Unexpected Opcode");
238  }
239  }
240  // Erase old instruction.
241  MBB.erase(II);
242 }
243 
244 void XCoreRegisterInfo::
246  unsigned DstReg, int64_t Value, DebugLoc dl) const {
247  // TODO use mkmsk if possible.
248  if (!isImmU16(Value)) {
249  // TODO use constant pool.
250  report_fatal_error("loadConstant value too big " + Twine(Value));
251  }
252  int Opcode = isImmU6(Value) ? XCore::LDC_ru6 : XCore::LDC_lru6;
253  const TargetInstrInfo &TII = *MBB.getParent()->getTarget().getInstrInfo();
254  BuildMI(MBB, I, dl, TII.get(Opcode), DstReg).addImm(Value);
255 }
256 
258  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
259 
260  return TFI->hasFP(MF) ? XCore::R10 : XCore::SP;
261 }
const MachineFunction * getParent() const
BitVector & set()
Definition: BitVector.h:236
instr_iterator erase(instr_iterator I)
raw_ostream & errs()
#define R4(n)
bool useFPForScavengingIndex(const MachineFunction &MF) const
void ChangeToRegister(unsigned Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isDebug=false)
const Function * getFunction() const
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, bool gen_crash_diag=true)
uint64_t getStackSize() const
const HexagonInstrInfo * TII
virtual bool hasFP(const MachineFunction &MF) const =0
#define llvm_unreachable(msg)
const MachineInstrBuilder & addImm(int64_t Val) const
static bool needsFrameMoves(const MachineFunction &MF)
Return whether to emit frame moves.
bool isKill() const
int getOpcode() const
Definition: MachineInstr.h:261
int64_t getImm() const
unsigned getKillRegState(bool B)
void ChangeToImmediate(int64_t ImmVal)
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:119
bool isDebugValue() const
Definition: MachineInstr.h:639
bundle_iterator< MachineInstr, instr_iterator > iterator
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:267
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
virtual const TargetFrameLowering * getFrameLowering() const
const MCInstrDesc & get(unsigned Opcode) const
Definition: MCInstrInfo.h:48
int64_t getObjectOffset(int ObjectIdx) const
bool trackLivenessAfterRegAlloc(const MachineFunction &MF) const
virtual const TargetInstrInfo * getInstrInfo() const
void eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS=NULL) const
unsigned getFrameRegister(const MachineFunction &MF) const
#define R6(n)
static bool isImmUs(unsigned val)
BitVector getReservedRegs(const MachineFunction &MF) const
bool needsUnwindTableEntry() const
True if this function needs an unwind table.
Definition: Function.h:293
MachineFrameInfo * getFrameInfo()
static bool isImmU6(unsigned val)
void print(raw_ostream &OS, const TargetMachine *TM=0, bool SkipOpers=false) const
static bool isImmU16(unsigned val)
bool requiresRegisterScavenging(const MachineFunction &MF) const
const uint16_t * getCalleeSavedRegs(const MachineFunction *MF=0) const
Code Generation virtual methods...
#define I(x, y, z)
Definition: MD5.cpp:54
const TargetMachine & getTarget() const
unsigned getReg() const
getReg - Returns the register number.
LLVM Value Representation.
Definition: Value.h:66
#define DEBUG(X)
Definition: Debug.h:97
MachineModuleInfo & getMMI() const
StringRef getName() const
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
DebugLoc getDebugLoc() const
Definition: MachineInstr.h:244
unsigned scavengeRegister(const TargetRegisterClass *RegClass, MachineBasicBlock::iterator I, int SPAdj)