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