Checkpoint refactoring of ThumbInstrInfo and ThumbRegisterInfo into Thumb1InstrInfo...
[oota-llvm.git] / lib / Target / ARM / Thumb1InstrInfo.cpp
1 //===- Thumb1InstrInfo.cpp - Thumb-1 Instruction 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 Thumb-1 implementation of the TargetInstrInfo class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "ARMInstrInfo.h"
15 #include "ARM.h"
16 #include "ARMGenInstrInfo.inc"
17 #include "ARMMachineFunctionInfo.h"
18 #include "llvm/CodeGen/MachineFrameInfo.h"
19 #include "llvm/CodeGen/MachineInstrBuilder.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "Thumb1InstrInfo.h"
22
23 using namespace llvm;
24
25 Thumb1InstrInfo::Thumb1InstrInfo(const ARMSubtarget &STI)
26   : ARMBaseInstrInfo(STI), RI(*this, STI) {
27 }
28
29 bool Thumb1InstrInfo::isMoveInstr(const MachineInstr &MI,
30                                   unsigned &SrcReg, unsigned &DstReg,
31                                   unsigned& SrcSubIdx, unsigned& DstSubIdx) const {
32   SrcSubIdx = DstSubIdx = 0; // No sub-registers.
33
34   unsigned oc = MI.getOpcode();
35   switch (oc) {
36   default:
37     return false;
38   case ARM::tMOVr:
39   case ARM::tMOVhir2lor:
40   case ARM::tMOVlor2hir:
41   case ARM::tMOVhir2hir:
42     assert(MI.getDesc().getNumOperands() >= 2 &&
43            MI.getOperand(0).isReg() &&
44            MI.getOperand(1).isReg() &&
45            "Invalid Thumb MOV instruction");
46     SrcReg = MI.getOperand(1).getReg();
47     DstReg = MI.getOperand(0).getReg();
48     return true;
49   }
50 }
51
52 unsigned Thumb1InstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
53                                               int &FrameIndex) const {
54   switch (MI->getOpcode()) {
55   default: break;
56   case ARM::tRestore:
57     if (MI->getOperand(1).isFI() &&
58         MI->getOperand(2).isImm() &&
59         MI->getOperand(2).getImm() == 0) {
60       FrameIndex = MI->getOperand(1).getIndex();
61       return MI->getOperand(0).getReg();
62     }
63     break;
64   }
65   return 0;
66 }
67
68 unsigned Thumb1InstrInfo::isStoreToStackSlot(const MachineInstr *MI,
69                                              int &FrameIndex) const {
70   switch (MI->getOpcode()) {
71   default: break;
72   case ARM::tSpill:
73     if (MI->getOperand(1).isFI() &&
74         MI->getOperand(2).isImm() &&
75         MI->getOperand(2).getImm() == 0) {
76       FrameIndex = MI->getOperand(1).getIndex();
77       return MI->getOperand(0).getReg();
78     }
79     break;
80   }
81   return 0;
82 }
83
84 bool Thumb1InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
85                                    MachineBasicBlock::iterator I,
86                                    unsigned DestReg, unsigned SrcReg,
87                                    const TargetRegisterClass *DestRC,
88                                    const TargetRegisterClass *SrcRC) const {
89   DebugLoc DL = DebugLoc::getUnknownLoc();
90   if (I != MBB.end()) DL = I->getDebugLoc();
91
92   if (DestRC == ARM::GPRRegisterClass) {
93     if (SrcRC == ARM::GPRRegisterClass) {
94       BuildMI(MBB, I, DL, get(ARM::tMOVhir2hir), DestReg).addReg(SrcReg);
95       return true;
96     } else if (SrcRC == ARM::tGPRRegisterClass) {
97       BuildMI(MBB, I, DL, get(ARM::tMOVlor2hir), DestReg).addReg(SrcReg);
98       return true;
99     }
100   } else if (DestRC == ARM::tGPRRegisterClass) {
101     if (SrcRC == ARM::GPRRegisterClass) {
102       BuildMI(MBB, I, DL, get(ARM::tMOVhir2lor), DestReg).addReg(SrcReg);
103       return true;
104     } else if (SrcRC == ARM::tGPRRegisterClass) {
105       BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg).addReg(SrcReg);
106       return true;
107     }
108   }
109
110   return false;
111 }
112
113 bool Thumb1InstrInfo::
114 canFoldMemoryOperand(const MachineInstr *MI,
115                      const SmallVectorImpl<unsigned> &Ops) const {
116   if (Ops.size() != 1) return false;
117
118   unsigned OpNum = Ops[0];
119   unsigned Opc = MI->getOpcode();
120   switch (Opc) {
121   default: break;
122   case ARM::tMOVr:
123   case ARM::tMOVlor2hir:
124   case ARM::tMOVhir2lor:
125   case ARM::tMOVhir2hir: {
126     if (OpNum == 0) { // move -> store
127       unsigned SrcReg = MI->getOperand(1).getReg();
128       if (RI.isPhysicalRegister(SrcReg) && !isARMLowRegister(SrcReg))
129         // tSpill cannot take a high register operand.
130         return false;
131     } else {          // move -> load
132       unsigned DstReg = MI->getOperand(0).getReg();
133       if (RI.isPhysicalRegister(DstReg) && !isARMLowRegister(DstReg))
134         // tRestore cannot target a high register operand.
135         return false;
136     }
137     return true;
138   }
139   }
140
141   return false;
142 }
143
144 void Thumb1InstrInfo::
145 storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
146                     unsigned SrcReg, bool isKill, int FI,
147                     const TargetRegisterClass *RC) const {
148   DebugLoc DL = DebugLoc::getUnknownLoc();
149   if (I != MBB.end()) DL = I->getDebugLoc();
150
151   assert(RC == ARM::tGPRRegisterClass && "Unknown regclass!");
152
153   if (RC == ARM::tGPRRegisterClass) {
154     BuildMI(MBB, I, DL, get(ARM::tSpill))
155       .addReg(SrcReg, getKillRegState(isKill))
156       .addFrameIndex(FI).addImm(0);
157   }
158 }
159
160 void Thumb1InstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg,
161                                      bool isKill,
162                                      SmallVectorImpl<MachineOperand> &Addr,
163                                      const TargetRegisterClass *RC,
164                                      SmallVectorImpl<MachineInstr*> &NewMIs) const{
165   DebugLoc DL = DebugLoc::getUnknownLoc();
166   unsigned Opc = 0;
167
168   assert(RC == ARM::GPRRegisterClass && "Unknown regclass!");
169   if (RC == ARM::GPRRegisterClass) {
170     Opc = Addr[0].isFI() ? ARM::tSpill : ARM::tSTR;
171   }
172
173   MachineInstrBuilder MIB =
174     BuildMI(MF, DL,  get(Opc)).addReg(SrcReg, getKillRegState(isKill));
175   for (unsigned i = 0, e = Addr.size(); i != e; ++i)
176     MIB.addOperand(Addr[i]);
177   NewMIs.push_back(MIB);
178   return;
179 }
180
181 void Thumb1InstrInfo::
182 loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
183                      unsigned DestReg, int FI,
184                      const TargetRegisterClass *RC) const {
185   DebugLoc DL = DebugLoc::getUnknownLoc();
186   if (I != MBB.end()) DL = I->getDebugLoc();
187
188   assert(RC == ARM::tGPRRegisterClass && "Unknown regclass!");
189
190   if (RC == ARM::tGPRRegisterClass) {
191     BuildMI(MBB, I, DL, get(ARM::tRestore), DestReg)
192       .addFrameIndex(FI).addImm(0);
193   }
194 }
195
196 void Thumb1InstrInfo::
197 loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
198                 SmallVectorImpl<MachineOperand> &Addr,
199                 const TargetRegisterClass *RC,
200                 SmallVectorImpl<MachineInstr*> &NewMIs) const {
201   DebugLoc DL = DebugLoc::getUnknownLoc();
202   unsigned Opc = 0;
203
204   if (RC == ARM::GPRRegisterClass) {
205     Opc = Addr[0].isFI() ? ARM::tRestore : ARM::tLDR;
206   }
207
208   MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc), DestReg);
209   for (unsigned i = 0, e = Addr.size(); i != e; ++i)
210     MIB.addOperand(Addr[i]);
211   NewMIs.push_back(MIB);
212   return;
213 }
214
215 bool Thumb1InstrInfo::
216 spillCalleeSavedRegisters(MachineBasicBlock &MBB,
217                           MachineBasicBlock::iterator MI,
218                           const std::vector<CalleeSavedInfo> &CSI) const {
219   if (CSI.empty())
220     return false;
221
222   DebugLoc DL = DebugLoc::getUnknownLoc();
223   if (MI != MBB.end()) DL = MI->getDebugLoc();
224
225   MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, get(ARM::tPUSH));
226   for (unsigned i = CSI.size(); i != 0; --i) {
227     unsigned Reg = CSI[i-1].getReg();
228     // Add the callee-saved register as live-in. It's killed at the spill.
229     MBB.addLiveIn(Reg);
230     MIB.addReg(Reg, RegState::Kill);
231   }
232   return true;
233 }
234
235 bool Thumb1InstrInfo::
236 restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
237                             MachineBasicBlock::iterator MI,
238                             const std::vector<CalleeSavedInfo> &CSI) const {
239   MachineFunction &MF = *MBB.getParent();
240   ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
241   if (CSI.empty())
242     return false;
243
244   bool isVarArg = AFI->getVarArgsRegSaveSize() > 0;
245   MachineInstr *PopMI = MF.CreateMachineInstr(get(ARM::tPOP),MI->getDebugLoc());
246   for (unsigned i = CSI.size(); i != 0; --i) {
247     unsigned Reg = CSI[i-1].getReg();
248     if (Reg == ARM::LR) {
249       // Special epilogue for vararg functions. See emitEpilogue
250       if (isVarArg)
251         continue;
252       Reg = ARM::PC;
253       PopMI->setDesc(get(ARM::tPOP_RET));
254       MI = MBB.erase(MI);
255     }
256     PopMI->addOperand(MachineOperand::CreateReg(Reg, true));
257   }
258
259   // It's illegal to emit pop instruction without operands.
260   if (PopMI->getNumOperands() > 0)
261     MBB.insert(MI, PopMI);
262
263   return true;
264 }
265
266 MachineInstr *Thumb1InstrInfo::
267 foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
268                       const SmallVectorImpl<unsigned> &Ops, int FI) const {
269   if (Ops.size() != 1) return NULL;
270
271   unsigned OpNum = Ops[0];
272   unsigned Opc = MI->getOpcode();
273   MachineInstr *NewMI = NULL;
274   switch (Opc) {
275   default: break;
276   case ARM::tMOVr:
277   case ARM::tMOVlor2hir:
278   case ARM::tMOVhir2lor:
279   case ARM::tMOVhir2hir: {
280     if (OpNum == 0) { // move -> store
281       unsigned SrcReg = MI->getOperand(1).getReg();
282       bool isKill = MI->getOperand(1).isKill();
283       if (RI.isPhysicalRegister(SrcReg) && !isARMLowRegister(SrcReg))
284         // tSpill cannot take a high register operand.
285         break;
286       NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::tSpill))
287         .addReg(SrcReg, getKillRegState(isKill))
288         .addFrameIndex(FI).addImm(0);
289     } else {          // move -> load
290       unsigned DstReg = MI->getOperand(0).getReg();
291       if (RI.isPhysicalRegister(DstReg) && !isARMLowRegister(DstReg))
292         // tRestore cannot target a high register operand.
293         break;
294       bool isDead = MI->getOperand(0).isDead();
295       NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::tRestore))
296         .addReg(DstReg, RegState::Define | getDeadRegState(isDead))
297         .addFrameIndex(FI).addImm(0);
298     }
299     break;
300   }
301   }
302
303   return NewMI;
304 }