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