]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/Target/ARM/ThumbInstrInfo.cpp
Import LLVM r74383.
[FreeBSD/FreeBSD.git] / lib / Target / ARM / ThumbInstrInfo.cpp
1 //===- ThumbInstrInfo.cpp - Thumb 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 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 "ThumbInstrInfo.h"
22
23 using namespace llvm;
24
25 ThumbInstrInfo::ThumbInstrInfo(const ARMSubtarget &STI)
26   : ARMBaseInstrInfo(STI) {
27 }
28
29 bool ThumbInstrInfo::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 ThumbInstrInfo::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 ThumbInstrInfo::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 ThumbInstrInfo::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 void ThumbInstrInfo::
118 storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
119                     unsigned SrcReg, bool isKill, int FI,
120                     const TargetRegisterClass *RC) const {
121   DebugLoc DL = DebugLoc::getUnknownLoc();
122   if (I != MBB.end()) DL = I->getDebugLoc();
123
124   assert(RC == ARM::tGPRRegisterClass && "Unknown regclass!");
125
126   // FIXME: Thumb2
127   if (RC == ARM::tGPRRegisterClass) {
128     BuildMI(MBB, I, DL, get(ARM::tSpill))
129       .addReg(SrcReg, getKillRegState(isKill))
130       .addFrameIndex(FI).addImm(0);
131   }
132 }
133
134 void ThumbInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg,
135                                     bool isKill,
136                                     SmallVectorImpl<MachineOperand> &Addr,
137                                     const TargetRegisterClass *RC,
138                                    SmallVectorImpl<MachineInstr*> &NewMIs) const{
139   DebugLoc DL = DebugLoc::getUnknownLoc();
140   unsigned Opc = 0;
141
142   // FIXME: Thumb2. Is GPRRegClass here correct?
143   assert(RC == ARM::GPRRegisterClass && "Unknown regclass!");
144   if (RC == ARM::GPRRegisterClass) {
145     Opc = Addr[0].isFI() ? ARM::tSpill : ARM::tSTR;
146   }
147
148   MachineInstrBuilder MIB =
149     BuildMI(MF, DL,  get(Opc)).addReg(SrcReg, getKillRegState(isKill));
150   for (unsigned i = 0, e = Addr.size(); i != e; ++i)
151     MIB.addOperand(Addr[i]);
152   NewMIs.push_back(MIB);
153   return;
154 }
155
156 void ThumbInstrInfo::
157 loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
158                      unsigned DestReg, int FI,
159                      const TargetRegisterClass *RC) const {
160   DebugLoc DL = DebugLoc::getUnknownLoc();
161   if (I != MBB.end()) DL = I->getDebugLoc();
162
163   // FIXME: Thumb2
164   assert(RC == ARM::tGPRRegisterClass && "Unknown regclass!");
165
166   if (RC == ARM::tGPRRegisterClass) {
167     BuildMI(MBB, I, DL, get(ARM::tRestore), DestReg)
168       .addFrameIndex(FI).addImm(0);
169   }
170 }
171
172 void ThumbInstrInfo::
173 loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
174                 SmallVectorImpl<MachineOperand> &Addr,
175                 const TargetRegisterClass *RC,
176                 SmallVectorImpl<MachineInstr*> &NewMIs) const {
177   DebugLoc DL = DebugLoc::getUnknownLoc();
178   unsigned Opc = 0;
179
180   // FIXME: Thumb2. Is GPRRegClass ok here?
181   if (RC == ARM::GPRRegisterClass) {
182     Opc = Addr[0].isFI() ? ARM::tRestore : ARM::tLDR;
183   }
184
185   MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc), DestReg);
186   for (unsigned i = 0, e = Addr.size(); i != e; ++i)
187     MIB.addOperand(Addr[i]);
188   NewMIs.push_back(MIB);
189   return;
190 }
191
192 bool ThumbInstrInfo::
193 spillCalleeSavedRegisters(MachineBasicBlock &MBB,
194                           MachineBasicBlock::iterator MI,
195                           const std::vector<CalleeSavedInfo> &CSI) const {
196   if (CSI.empty())
197     return false;
198
199   DebugLoc DL = DebugLoc::getUnknownLoc();
200   if (MI != MBB.end()) DL = MI->getDebugLoc();
201
202   MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, get(ARM::tPUSH));
203   for (unsigned i = CSI.size(); i != 0; --i) {
204     unsigned Reg = CSI[i-1].getReg();
205     // Add the callee-saved register as live-in. It's killed at the spill.
206     MBB.addLiveIn(Reg);
207     MIB.addReg(Reg, RegState::Kill);
208   }
209   return true;
210 }
211
212 bool ThumbInstrInfo::
213 restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
214                             MachineBasicBlock::iterator MI,
215                             const std::vector<CalleeSavedInfo> &CSI) const {
216   MachineFunction &MF = *MBB.getParent();
217   ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
218   if (CSI.empty())
219     return false;
220
221   bool isVarArg = AFI->getVarArgsRegSaveSize() > 0;
222   MachineInstr *PopMI = MF.CreateMachineInstr(get(ARM::tPOP),MI->getDebugLoc());
223   for (unsigned i = CSI.size(); i != 0; --i) {
224     unsigned Reg = CSI[i-1].getReg();
225     if (Reg == ARM::LR) {
226       // Special epilogue for vararg functions. See emitEpilogue
227       if (isVarArg)
228         continue;
229       Reg = ARM::PC;
230       PopMI->setDesc(get(ARM::tPOP_RET));
231       MI = MBB.erase(MI);
232     }
233     PopMI->addOperand(MachineOperand::CreateReg(Reg, true));
234   }
235
236   // It's illegal to emit pop instruction without operands.
237   if (PopMI->getNumOperands() > 0)
238     MBB.insert(MI, PopMI);
239
240   return true;
241 }
242
243 MachineInstr *ThumbInstrInfo::
244 foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
245                       const SmallVectorImpl<unsigned> &Ops, int FI) const {
246   if (Ops.size() != 1) return NULL;
247   const ARMRegisterInfo &RI = getRegisterInfo();
248
249   unsigned OpNum = Ops[0];
250   unsigned Opc = MI->getOpcode();
251   MachineInstr *NewMI = NULL;
252   switch (Opc) {
253   default: break;
254   case ARM::tMOVr:
255   case ARM::tMOVlor2hir:
256   case ARM::tMOVhir2lor:
257   case ARM::tMOVhir2hir: {
258     if (OpNum == 0) { // move -> store
259       unsigned SrcReg = MI->getOperand(1).getReg();
260       bool isKill = MI->getOperand(1).isKill();
261       if (RI.isPhysicalRegister(SrcReg) && !RI.isLowRegister(SrcReg))
262         // tSpill cannot take a high register operand.
263         break;
264       NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::tSpill))
265         .addReg(SrcReg, getKillRegState(isKill))
266         .addFrameIndex(FI).addImm(0);
267     } else {          // move -> load
268       unsigned DstReg = MI->getOperand(0).getReg();
269       if (RI.isPhysicalRegister(DstReg) && !RI.isLowRegister(DstReg))
270         // tRestore cannot target a high register operand.
271         break;
272       bool isDead = MI->getOperand(0).isDead();
273       NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::tRestore))
274         .addReg(DstReg, RegState::Define | getDeadRegState(isDead))
275         .addFrameIndex(FI).addImm(0);
276     }
277     break;
278   }
279   }
280
281   return NewMI;
282 }