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