Thumb1InstrInfo.cpp revision f95215f551949d5e5adfbf4753aa833b9009b77a
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/CodeGen/MachineMemOperand.h"
21#include "llvm/CodeGen/PseudoSourceValue.h"
22#include "llvm/ADT/SmallVector.h"
23#include "Thumb1InstrInfo.h"
24
25using namespace llvm;
26
27Thumb1InstrInfo::Thumb1InstrInfo(const ARMSubtarget &STI)
28  : ARMBaseInstrInfo(STI), RI(*this, STI) {
29}
30
31unsigned Thumb1InstrInfo::getUnindexedOpcode(unsigned Opc) const {
32  return 0;
33}
34
35bool
36Thumb1InstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const {
37  if (MBB.empty()) return false;
38
39  switch (MBB.back().getOpcode()) {
40  case ARM::tBX_RET:
41  case ARM::tBX_RET_vararg:
42  case ARM::tPOP_RET:
43  case ARM::tB:
44  case ARM::tBRIND:
45  case ARM::tBR_JTr:
46    return true;
47  default:
48    break;
49  }
50
51  return false;
52}
53
54bool Thumb1InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
55                                   MachineBasicBlock::iterator I,
56                                   unsigned DestReg, unsigned SrcReg,
57                                   const TargetRegisterClass *DestRC,
58                                   const TargetRegisterClass *SrcRC) const {
59  DebugLoc DL = DebugLoc::getUnknownLoc();
60  if (I != MBB.end()) DL = I->getDebugLoc();
61
62  if (DestRC == ARM::GPRRegisterClass) {
63    if (SrcRC == ARM::GPRRegisterClass) {
64      BuildMI(MBB, I, DL, get(ARM::tMOVgpr2gpr), DestReg).addReg(SrcReg);
65      return true;
66    } else if (SrcRC == ARM::tGPRRegisterClass) {
67      BuildMI(MBB, I, DL, get(ARM::tMOVtgpr2gpr), DestReg).addReg(SrcReg);
68      return true;
69    }
70  } else if (DestRC == ARM::tGPRRegisterClass) {
71    if (SrcRC == ARM::GPRRegisterClass) {
72      BuildMI(MBB, I, DL, get(ARM::tMOVgpr2tgpr), DestReg).addReg(SrcReg);
73      return true;
74    } else if (SrcRC == ARM::tGPRRegisterClass) {
75      BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg).addReg(SrcReg);
76      return true;
77    }
78  }
79
80  return false;
81}
82
83bool Thumb1InstrInfo::
84canFoldMemoryOperand(const MachineInstr *MI,
85                     const SmallVectorImpl<unsigned> &Ops) const {
86  if (Ops.size() != 1) return false;
87
88  unsigned OpNum = Ops[0];
89  unsigned Opc = MI->getOpcode();
90  switch (Opc) {
91  default: break;
92  case ARM::tMOVr:
93  case ARM::tMOVtgpr2gpr:
94  case ARM::tMOVgpr2tgpr:
95  case ARM::tMOVgpr2gpr: {
96    if (OpNum == 0) { // move -> store
97      unsigned SrcReg = MI->getOperand(1).getReg();
98      if (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
99          !isARMLowRegister(SrcReg))
100        // tSpill cannot take a high register operand.
101        return false;
102    } else {          // move -> load
103      unsigned DstReg = MI->getOperand(0).getReg();
104      if (TargetRegisterInfo::isPhysicalRegister(DstReg) &&
105          !isARMLowRegister(DstReg))
106        // tRestore cannot target a high register operand.
107        return false;
108    }
109    return true;
110  }
111  }
112
113  return false;
114}
115
116void Thumb1InstrInfo::
117storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
118                    unsigned SrcReg, bool isKill, int FI,
119                    const TargetRegisterClass *RC) const {
120  DebugLoc DL = DebugLoc::getUnknownLoc();
121  if (I != MBB.end()) DL = I->getDebugLoc();
122
123  assert((RC == ARM::tGPRRegisterClass ||
124          (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
125           isARMLowRegister(SrcReg))) && "Unknown regclass!");
126
127  if (RC == ARM::tGPRRegisterClass) {
128    MachineFunction &MF = *MBB.getParent();
129    MachineFrameInfo &MFI = *MF.getFrameInfo();
130    MachineMemOperand *MMO =
131      MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FI),
132                              MachineMemOperand::MOStore, 0,
133                              MFI.getObjectSize(FI),
134                              MFI.getObjectAlignment(FI));
135    AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tSpill))
136                   .addReg(SrcReg, getKillRegState(isKill))
137                   .addFrameIndex(FI).addImm(0).addMemOperand(MMO));
138  }
139}
140
141void Thumb1InstrInfo::
142loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
143                     unsigned DestReg, int FI,
144                     const TargetRegisterClass *RC) const {
145  DebugLoc DL = DebugLoc::getUnknownLoc();
146  if (I != MBB.end()) DL = I->getDebugLoc();
147
148  assert((RC == ARM::tGPRRegisterClass ||
149          (TargetRegisterInfo::isPhysicalRegister(DestReg) &&
150           isARMLowRegister(DestReg))) && "Unknown regclass!");
151
152  if (RC == ARM::tGPRRegisterClass) {
153    MachineFunction &MF = *MBB.getParent();
154    MachineFrameInfo &MFI = *MF.getFrameInfo();
155    MachineMemOperand *MMO =
156      MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FI),
157                              MachineMemOperand::MOLoad, 0,
158                              MFI.getObjectSize(FI),
159                              MFI.getObjectAlignment(FI));
160    AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tRestore), DestReg)
161                   .addFrameIndex(FI).addImm(0).addMemOperand(MMO));
162  }
163}
164
165bool Thumb1InstrInfo::
166spillCalleeSavedRegisters(MachineBasicBlock &MBB,
167                          MachineBasicBlock::iterator MI,
168                          const std::vector<CalleeSavedInfo> &CSI) const {
169  if (CSI.empty())
170    return false;
171
172  DebugLoc DL = DebugLoc::getUnknownLoc();
173  if (MI != MBB.end()) DL = MI->getDebugLoc();
174
175  MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, get(ARM::tPUSH));
176  AddDefaultPred(MIB);
177  MIB.addReg(0); // No write back.
178  for (unsigned i = CSI.size(); i != 0; --i) {
179    unsigned Reg = CSI[i-1].getReg();
180    // Add the callee-saved register as live-in. It's killed at the spill.
181    MBB.addLiveIn(Reg);
182    MIB.addReg(Reg, RegState::Kill);
183  }
184  return true;
185}
186
187bool Thumb1InstrInfo::
188restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
189                            MachineBasicBlock::iterator MI,
190                            const std::vector<CalleeSavedInfo> &CSI) const {
191  MachineFunction &MF = *MBB.getParent();
192  ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
193  if (CSI.empty())
194    return false;
195
196  bool isVarArg = AFI->getVarArgsRegSaveSize() > 0;
197  DebugLoc DL = MI->getDebugLoc();
198  MachineInstrBuilder MIB = BuildMI(MF, DL, get(ARM::tPOP));
199  AddDefaultPred(MIB);
200  MIB.addReg(0); // No write back.
201
202  bool NumRegs = 0;
203  for (unsigned i = CSI.size(); i != 0; --i) {
204    unsigned Reg = CSI[i-1].getReg();
205    if (Reg == ARM::LR) {
206      // Special epilogue for vararg functions. See emitEpilogue
207      if (isVarArg)
208        continue;
209      Reg = ARM::PC;
210      (*MIB).setDesc(get(ARM::tPOP_RET));
211      MI = MBB.erase(MI);
212    }
213    MIB.addReg(Reg, getDefRegState(true));
214    ++NumRegs;
215  }
216
217  // It's illegal to emit pop instruction without operands.
218  if (NumRegs)
219    MBB.insert(MI, &*MIB);
220
221  return true;
222}
223
224MachineInstr *Thumb1InstrInfo::
225foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
226                      const SmallVectorImpl<unsigned> &Ops, int FI) const {
227  if (Ops.size() != 1) return NULL;
228
229  unsigned OpNum = Ops[0];
230  unsigned Opc = MI->getOpcode();
231  MachineInstr *NewMI = NULL;
232  switch (Opc) {
233  default: break;
234  case ARM::tMOVr:
235  case ARM::tMOVtgpr2gpr:
236  case ARM::tMOVgpr2tgpr:
237  case ARM::tMOVgpr2gpr: {
238    if (OpNum == 0) { // move -> store
239      unsigned SrcReg = MI->getOperand(1).getReg();
240      bool isKill = MI->getOperand(1).isKill();
241      if (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
242          !isARMLowRegister(SrcReg))
243        // tSpill cannot take a high register operand.
244        break;
245      NewMI = AddDefaultPred(BuildMI(MF, MI->getDebugLoc(), get(ARM::tSpill))
246                             .addReg(SrcReg, getKillRegState(isKill))
247                             .addFrameIndex(FI).addImm(0));
248    } else {          // move -> load
249      unsigned DstReg = MI->getOperand(0).getReg();
250      if (TargetRegisterInfo::isPhysicalRegister(DstReg) &&
251          !isARMLowRegister(DstReg))
252        // tRestore cannot target a high register operand.
253        break;
254      bool isDead = MI->getOperand(0).isDead();
255      NewMI = AddDefaultPred(BuildMI(MF, MI->getDebugLoc(), get(ARM::tRestore))
256                             .addReg(DstReg,
257                                     RegState::Define | getDeadRegState(isDead))
258                             .addFrameIndex(FI).addImm(0));
259    }
260    break;
261  }
262  }
263
264  return NewMI;
265}
266