e198d693b8a9c2140f8131331840db5e920b4323
[oota-llvm.git] / lib / Target / XCore / XCoreRegisterInfo.cpp
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
39 using namespace llvm;
40
41 #define DEBUG_TYPE "xcore-reg-info"
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->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
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->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
205 bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) {
206   return MF.getMMI().hasDebugInfo() ||
207     MF.getFunction()->needsUnwindTableEntry();
208 }
209
210 const 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
230 BitVector 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
244 bool
245 XCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
246   return true;
247 }
248
249 bool
250 XCoreRegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction &MF) const {
251   return true;
252 }
253
254 bool
255 XCoreRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
256   return false;
257 }
258
259 void
260 XCoreRegisterInfo::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
325 unsigned XCoreRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
326   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
327
328   return TFI->hasFP(MF) ? XCore::R10 : XCore::SP;
329 }