Thumb1InstrInfo.cpp revision d83360694a6d82772cf31a0be8a64570c2e5cb88
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
23using namespace llvm;
24
25Thumb1InstrInfo::Thumb1InstrInfo(const ARMSubtarget &STI)
26  : ARMBaseInstrInfo(STI), RI(*this, STI) {
27}
28
29unsigned Thumb1InstrInfo::getUnindexedOpcode(unsigned Opc) const {
30  return 0;
31}
32
33unsigned 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
56bool
57Thumb1InstrInfo::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
74bool 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
97unsigned 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
113unsigned 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
129bool 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
158bool Thumb1InstrInfo::
159canFoldMemoryOperand(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
189void Thumb1InstrInfo::
190storeRegToStackSlot(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
205void Thumb1InstrInfo::
206loadRegFromStackSlot(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
220bool Thumb1InstrInfo::
221spillCalleeSavedRegisters(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
240bool Thumb1InstrInfo::
241restoreCalleeSavedRegisters(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
271MachineInstr *Thumb1InstrInfo::
272foldMemoryOperandImpl(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}
311