XCore target: addMemOperand as necessary
[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 XCoreRegisterInfo::XCoreRegisterInfo()
42   : XCoreGenRegisterInfo(XCore::LR) {
43 }
44
45 // helper functions
46 static inline bool isImmUs(unsigned val) {
47   return val <= 11;
48 }
49
50 static inline bool isImmU6(unsigned val) {
51   return val < (1 << 6);
52 }
53
54 static inline bool isImmU16(unsigned val) {
55   return val < (1 << 16);
56 }
57
58
59 static void InsertFPImmInst(MachineBasicBlock::iterator II,
60                             const XCoreInstrInfo &TII,
61                             unsigned Reg, unsigned FrameReg, int Offset ) {
62   MachineInstr &MI = *II;
63   MachineBasicBlock &MBB = *MI.getParent();
64   DebugLoc dl = MI.getDebugLoc();
65
66   switch (MI.getOpcode()) {
67   case XCore::LDWFI:
68     BuildMI(MBB, II, dl, TII.get(XCore::LDW_2rus), Reg)
69           .addReg(FrameReg)
70           .addImm(Offset)
71           .addMemOperand(*MI.memoperands_begin());
72     break;
73   case XCore::STWFI:
74     BuildMI(MBB, II, dl, TII.get(XCore::STW_2rus))
75           .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
76           .addReg(FrameReg)
77           .addImm(Offset)
78           .addMemOperand(*MI.memoperands_begin());
79     break;
80   case XCore::LDAWFI:
81     BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l2rus), Reg)
82           .addReg(FrameReg)
83           .addImm(Offset);
84     break;
85   default:
86     llvm_unreachable("Unexpected Opcode");
87   }
88 }
89
90 static void InsertFPConstInst(MachineBasicBlock::iterator II,
91                               const XCoreInstrInfo &TII,
92                               unsigned Reg, unsigned FrameReg,
93                               int Offset, RegScavenger *RS ) {
94   assert(RS && "requiresRegisterScavenging failed");
95   MachineInstr &MI = *II;
96   MachineBasicBlock &MBB = *MI.getParent();
97   DebugLoc dl = MI.getDebugLoc();
98   unsigned ScratchOffset = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0);
99   RS->setUsed(ScratchOffset);
100   TII.loadImmediate(MBB, II, ScratchOffset, Offset);
101
102   switch (MI.getOpcode()) {
103   case XCore::LDWFI:
104     BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg)
105           .addReg(FrameReg)
106           .addReg(ScratchOffset, RegState::Kill)
107           .addMemOperand(*MI.memoperands_begin());
108     break;
109   case XCore::STWFI:
110     BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r))
111           .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
112           .addReg(FrameReg)
113           .addReg(ScratchOffset, RegState::Kill)
114           .addMemOperand(*MI.memoperands_begin());
115     break;
116   case XCore::LDAWFI:
117     BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg)
118           .addReg(FrameReg)
119           .addReg(ScratchOffset, RegState::Kill);
120     break;
121   default:
122     llvm_unreachable("Unexpected Opcode");
123   }
124 }
125
126 static void InsertSPImmInst(MachineBasicBlock::iterator II,
127                             const XCoreInstrInfo &TII,
128                             unsigned Reg, int Offset) {
129   MachineInstr &MI = *II;
130   MachineBasicBlock &MBB = *MI.getParent();
131   DebugLoc dl = MI.getDebugLoc();
132   bool isU6 = isImmU6(Offset);
133
134   switch (MI.getOpcode()) {
135   int NewOpcode;
136   case XCore::LDWFI:
137     NewOpcode = (isU6) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;
138     BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
139           .addImm(Offset)
140           .addMemOperand(*MI.memoperands_begin());
141     break;
142   case XCore::STWFI:
143     NewOpcode = (isU6) ? XCore::STWSP_ru6 : XCore::STWSP_lru6;
144     BuildMI(MBB, II, dl, TII.get(NewOpcode))
145           .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
146           .addImm(Offset)
147           .addMemOperand(*MI.memoperands_begin());
148     break;
149   case XCore::LDAWFI:
150     NewOpcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
151     BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
152           .addImm(Offset);
153     break;
154   default:
155     llvm_unreachable("Unexpected Opcode");
156   }
157 }
158
159 static void InsertSPConstInst(MachineBasicBlock::iterator II,
160                                 const XCoreInstrInfo &TII,
161                                 unsigned Reg, int Offset, RegScavenger *RS ) {
162   assert(RS && "requiresRegisterScavenging failed");
163   MachineInstr &MI = *II;
164   MachineBasicBlock &MBB = *MI.getParent();
165   DebugLoc dl = MI.getDebugLoc();
166   unsigned OpCode = MI.getOpcode();
167
168   unsigned ScratchBase;
169   if (OpCode==XCore::STWFI) {
170     ScratchBase = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0);
171     RS->setUsed(ScratchBase);
172   } else
173     ScratchBase = Reg;
174   BuildMI(MBB, II, dl, TII.get(XCore::LDAWSP_ru6), ScratchBase).addImm(0);
175   unsigned ScratchOffset = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0);
176   RS->setUsed(ScratchOffset);
177   TII.loadImmediate(MBB, II, ScratchOffset, Offset);
178
179   switch (OpCode) {
180   case XCore::LDWFI:
181     BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg)
182           .addReg(ScratchBase, RegState::Kill)
183           .addReg(ScratchOffset, RegState::Kill)
184           .addMemOperand(*MI.memoperands_begin());
185     break;
186   case XCore::STWFI:
187     BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r))
188           .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
189           .addReg(ScratchBase, RegState::Kill)
190           .addReg(ScratchOffset, RegState::Kill)
191           .addMemOperand(*MI.memoperands_begin());
192     break;
193   case XCore::LDAWFI:
194     BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg)
195           .addReg(ScratchBase, RegState::Kill)
196           .addReg(ScratchOffset, RegState::Kill);
197     break;
198   default:
199     llvm_unreachable("Unexpected Opcode");
200   }
201 }
202
203 bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) {
204   return MF.getMMI().hasDebugInfo() ||
205     MF.getFunction()->needsUnwindTableEntry();
206 }
207
208 const uint16_t* XCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
209                                                                          const {
210   // The callee saved registers LR & FP are explicitly handled during
211   // emitPrologue & emitEpilogue and related functions.
212   static const uint16_t CalleeSavedRegs[] = {
213     XCore::R4, XCore::R5, XCore::R6, XCore::R7,
214     XCore::R8, XCore::R9, XCore::R10,
215     0
216   };
217   static const uint16_t CalleeSavedRegsFP[] = {
218     XCore::R4, XCore::R5, XCore::R6, XCore::R7,
219     XCore::R8, XCore::R9,
220     0
221   };
222   const TargetFrameLowering *TFI = MF->getTarget().getFrameLowering();
223   if (TFI->hasFP(*MF))
224     return CalleeSavedRegsFP;
225   return CalleeSavedRegs;
226 }
227
228 BitVector XCoreRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
229   BitVector Reserved(getNumRegs());
230   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
231
232   Reserved.set(XCore::CP);
233   Reserved.set(XCore::DP);
234   Reserved.set(XCore::SP);
235   Reserved.set(XCore::LR);
236   if (TFI->hasFP(MF)) {
237     Reserved.set(XCore::R10);
238   }
239   return Reserved;
240 }
241
242 bool
243 XCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
244   return true;
245 }
246
247 bool
248 XCoreRegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction &MF) const {
249   return true;
250 }
251
252 bool
253 XCoreRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
254   return false;
255 }
256
257 void
258 XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
259                                        int SPAdj, unsigned FIOperandNum,
260                                        RegScavenger *RS) const {
261   assert(SPAdj == 0 && "Unexpected");
262   MachineInstr &MI = *II;
263   MachineOperand &FrameOp = MI.getOperand(FIOperandNum);
264   int FrameIndex = FrameOp.getIndex();
265
266   MachineFunction &MF = *MI.getParent()->getParent();
267   const XCoreInstrInfo &TII =
268           *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo());
269
270   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
271   int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
272   int StackSize = MF.getFrameInfo()->getStackSize();
273
274   #ifndef NDEBUG
275   DEBUG(errs() << "\nFunction         : " 
276         << MF.getName() << "\n");
277   DEBUG(errs() << "<--------->\n");
278   DEBUG(MI.print(errs()));
279   DEBUG(errs() << "FrameIndex         : " << FrameIndex << "\n");
280   DEBUG(errs() << "FrameOffset        : " << Offset << "\n");
281   DEBUG(errs() << "StackSize          : " << StackSize << "\n");
282   #endif
283
284   Offset += StackSize;
285
286   unsigned FrameReg = getFrameRegister(MF);
287
288   // Special handling of DBG_VALUE instructions.
289   if (MI.isDebugValue()) {
290     MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false /*isDef*/);
291     MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
292     return;
293   }
294
295   // fold constant into offset.
296   Offset += MI.getOperand(FIOperandNum + 1).getImm();
297   MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0);
298   
299   assert(Offset%4 == 0 && "Misaligned stack offset");
300   DEBUG(errs() << "Offset             : " << Offset << "\n" << "<--------->\n");
301   Offset/=4;
302   
303   unsigned Reg = MI.getOperand(0).getReg();
304   assert(XCore::GRRegsRegClass.contains(Reg) && "Unexpected register operand");
305
306   if (TFI->hasFP(MF)) {
307     if (isImmUs(Offset))
308       InsertFPImmInst(II, TII, Reg, FrameReg, Offset);
309     else
310       InsertFPConstInst(II, TII, Reg, FrameReg, Offset, RS);
311   } else {
312     if (isImmU16(Offset))
313       InsertSPImmInst(II, TII, Reg, Offset);
314     else
315       InsertSPConstInst(II, TII, Reg, Offset, RS);
316   }
317   // Erase old instruction.
318   MachineBasicBlock &MBB = *MI.getParent();
319   MBB.erase(II);
320 }
321
322
323 unsigned XCoreRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
324   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
325
326   return TFI->hasFP(MF) ? XCore::R10 : XCore::SP;
327 }