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