XCore target: Make handling of large frames not dependent upon an FP.
[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 "XCoreMachineFunctionInfo.h"
17 #include "llvm/ADT/BitVector.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/CodeGen/MachineConstantPool.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/Constants.h"
27 #include "llvm/IR/Function.h"
28 #include "llvm/IR/Type.h"
29 #include "llvm/Support/Debug.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/MathExtras.h"
32 #include "llvm/Support/raw_ostream.h"
33 #include "llvm/Target/TargetFrameLowering.h"
34 #include "llvm/Target/TargetInstrInfo.h"
35 #include "llvm/Target/TargetMachine.h"
36 #include "llvm/Target/TargetOptions.h"
37
38 #define GET_REGINFO_TARGET_DESC
39 #include "XCoreGenRegisterInfo.inc"
40
41 using namespace llvm;
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 static void loadConstant(MachineBasicBlock::iterator II,
61                          const TargetInstrInfo &TII,
62                          unsigned DstReg, int64_t Value) {
63   MachineInstr &MI = *II;
64   MachineBasicBlock &MBB = *MI.getParent();
65   DebugLoc dl = MI.getDebugLoc();
66
67   if (isMask_32(Value)) {
68     int N = Log2_32(Value) + 1;
69     BuildMI(MBB, II, dl, TII.get(XCore::MKMSK_rus), DstReg).addImm(N);
70   } else if (isImmU16(Value)) {
71     int Opcode = isImmU6(Value) ? XCore::LDC_ru6 : XCore::LDC_lru6;
72     BuildMI(MBB, II, dl, TII.get(Opcode), DstReg).addImm(Value);
73   } else {
74     MachineConstantPool *ConstantPool = MBB.getParent()->getConstantPool();
75     const Constant *C = ConstantInt::get(
76         Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Value);
77     unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
78     BuildMI(MBB, II, dl, TII.get(XCore::LDWCP_lru6), DstReg)
79         .addConstantPoolIndex(Idx);
80   }
81 }
82
83 static void InsertFPImmInst(MachineBasicBlock::iterator II,
84                             const TargetInstrInfo &TII,
85                             unsigned Reg, unsigned FrameReg, int Offset ) {
86   MachineInstr &MI = *II;
87   MachineBasicBlock &MBB = *MI.getParent();
88   DebugLoc dl = MI.getDebugLoc();
89
90   switch (MI.getOpcode()) {
91   case XCore::LDWFI:
92     BuildMI(MBB, II, dl, TII.get(XCore::LDW_2rus), Reg)
93           .addReg(FrameReg)
94           .addImm(Offset);
95     break;
96   case XCore::STWFI:
97     BuildMI(MBB, II, dl, TII.get(XCore::STW_2rus))
98           .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
99           .addReg(FrameReg)
100           .addImm(Offset);
101     break;
102   case XCore::LDAWFI:
103     BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l2rus), Reg)
104           .addReg(FrameReg)
105           .addImm(Offset);
106     break;
107   default:
108     llvm_unreachable("Unexpected Opcode");
109   }
110 }
111
112 static void InsertFPConstInst(MachineBasicBlock::iterator II,
113                               const TargetInstrInfo &TII,
114                               unsigned Reg, unsigned FrameReg,
115                               int Offset, RegScavenger *RS ) {
116   assert(RS && "requiresRegisterScavenging failed");
117   MachineInstr &MI = *II;
118   MachineBasicBlock &MBB = *MI.getParent();
119   DebugLoc dl = MI.getDebugLoc();
120
121   unsigned ScratchOffset = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0);
122   RS->setUsed(ScratchOffset);
123   loadConstant(II, TII, ScratchOffset, Offset);
124
125   switch (MI.getOpcode()) {
126   case XCore::LDWFI:
127     BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg)
128           .addReg(FrameReg)
129           .addReg(ScratchOffset, RegState::Kill);
130     break;
131   case XCore::STWFI:
132     BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r))
133           .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
134           .addReg(FrameReg)
135           .addReg(ScratchOffset, RegState::Kill);
136     break;
137   case XCore::LDAWFI:
138     BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg)
139           .addReg(FrameReg)
140           .addReg(ScratchOffset, RegState::Kill);
141     break;
142   default:
143     llvm_unreachable("Unexpected Opcode");
144   }
145 }
146
147 static void InsertSPImmInst(MachineBasicBlock::iterator II,
148                             const TargetInstrInfo &TII,
149                             unsigned Reg, int Offset) {
150   MachineInstr &MI = *II;
151   MachineBasicBlock &MBB = *MI.getParent();
152   DebugLoc dl = MI.getDebugLoc();
153   bool isU6 = isImmU6(Offset);
154   switch (MI.getOpcode()) {
155   int NewOpcode;
156   case XCore::LDWFI:
157     NewOpcode = (isU6) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;
158     BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
159           .addImm(Offset);
160     break;
161   case XCore::STWFI:
162     NewOpcode = (isU6) ? XCore::STWSP_ru6 : XCore::STWSP_lru6;
163     BuildMI(MBB, II, dl, TII.get(NewOpcode))
164           .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
165           .addImm(Offset);
166     break;
167   case XCore::LDAWFI:
168     NewOpcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
169     BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
170           .addImm(Offset);
171     break;
172   default:
173     llvm_unreachable("Unexpected Opcode");
174   }
175 }
176
177 static void InsertSPConstInst(MachineBasicBlock::iterator II,
178                                 const TargetInstrInfo &TII,
179                                 unsigned Reg, int Offset, RegScavenger *RS ) {
180   assert(RS && "requiresRegisterScavenging failed");
181   MachineInstr &MI = *II;
182   MachineBasicBlock &MBB = *MI.getParent();
183   DebugLoc dl = MI.getDebugLoc();
184   unsigned OpCode = MI.getOpcode();
185
186   unsigned ScratchBase;
187   if (OpCode==XCore::STWFI) {
188     ScratchBase = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0);
189     RS->setUsed(ScratchBase);
190   } else
191     ScratchBase = Reg;
192   BuildMI(MBB, II, dl, TII.get(XCore::LDAWSP_ru6), ScratchBase).addImm(0);
193   unsigned ScratchOffset = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0);
194   RS->setUsed(ScratchOffset);
195   loadConstant(II, TII, ScratchOffset, Offset);
196
197   switch (OpCode) {
198   case XCore::LDWFI:
199     BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg)
200           .addReg(ScratchBase, RegState::Kill)
201           .addReg(ScratchOffset, RegState::Kill);
202     break;
203   case XCore::STWFI:
204     BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r))
205           .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
206           .addReg(ScratchBase, RegState::Kill)
207           .addReg(ScratchOffset, RegState::Kill);
208     break;
209   case XCore::LDAWFI:
210     BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg)
211           .addReg(ScratchBase, RegState::Kill)
212           .addReg(ScratchOffset, RegState::Kill);
213     break;
214   default:
215     llvm_unreachable("Unexpected Opcode");
216   }
217 }
218
219 bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) {
220   return MF.getMMI().hasDebugInfo() ||
221     MF.getFunction()->needsUnwindTableEntry();
222 }
223
224 const uint16_t* XCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
225                                                                          const {
226   static const uint16_t CalleeSavedRegs[] = {
227     XCore::R4, XCore::R5, XCore::R6, XCore::R7,
228     XCore::R8, XCore::R9, XCore::R10, XCore::LR,
229     0
230   };
231   return CalleeSavedRegs;
232 }
233
234 BitVector XCoreRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
235   BitVector Reserved(getNumRegs());
236   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
237
238   Reserved.set(XCore::CP);
239   Reserved.set(XCore::DP);
240   Reserved.set(XCore::SP);
241   Reserved.set(XCore::LR);
242   if (TFI->hasFP(MF)) {
243     Reserved.set(XCore::R10);
244   }
245   return Reserved;
246 }
247
248 bool
249 XCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
250   return true;
251 }
252
253 bool
254 XCoreRegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction &MF) const {
255   return true;
256 }
257
258 bool
259 XCoreRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
260   return false;
261 }
262
263 void
264 XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
265                                        int SPAdj, unsigned FIOperandNum,
266                                        RegScavenger *RS) const {
267   assert(SPAdj == 0 && "Unexpected");
268   MachineInstr &MI = *II;
269   MachineOperand &FrameOp = MI.getOperand(FIOperandNum);
270   int FrameIndex = FrameOp.getIndex();
271
272   MachineFunction &MF = *MI.getParent()->getParent();
273   const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
274   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
275   int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
276   int StackSize = MF.getFrameInfo()->getStackSize();
277
278   #ifndef NDEBUG
279   DEBUG(errs() << "\nFunction         : " 
280         << MF.getName() << "\n");
281   DEBUG(errs() << "<--------->\n");
282   DEBUG(MI.print(errs()));
283   DEBUG(errs() << "FrameIndex         : " << FrameIndex << "\n");
284   DEBUG(errs() << "FrameOffset        : " << Offset << "\n");
285   DEBUG(errs() << "StackSize          : " << StackSize << "\n");
286   #endif
287
288   Offset += StackSize;
289
290   unsigned FrameReg = getFrameRegister(MF);
291
292   // Special handling of DBG_VALUE instructions.
293   if (MI.isDebugValue()) {
294     MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false /*isDef*/);
295     MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
296     return;
297   }
298
299   // fold constant into offset.
300   Offset += MI.getOperand(FIOperandNum + 1).getImm();
301   MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0);
302   
303   assert(Offset%4 == 0 && "Misaligned stack offset");
304   DEBUG(errs() << "Offset             : " << Offset << "\n" << "<--------->\n");
305   Offset/=4;
306   
307   unsigned Reg = MI.getOperand(0).getReg();
308   assert(XCore::GRRegsRegClass.contains(Reg) && "Unexpected register operand");
309
310   if (TFI->hasFP(MF)) {
311     if (isImmUs(Offset))
312       InsertFPImmInst(II, TII, Reg, FrameReg, Offset);
313     else
314       InsertFPConstInst(II, TII, Reg, FrameReg, Offset, RS);
315   } else {
316     if (isImmU16(Offset))
317       InsertSPImmInst(II, TII, Reg, Offset);
318     else
319       InsertSPConstInst(II, TII, Reg, Offset, RS);
320   }
321   // Erase old instruction.
322   MachineBasicBlock &MBB = *MI.getParent();
323   MBB.erase(II);
324 }
325
326
327 unsigned XCoreRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
328   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
329
330   return TFI->hasFP(MF) ? XCore::R10 : XCore::SP;
331 }