blob: ff984471148bb33781a53ae42729cb0ac33b1f36 [file] [log] [blame]
David Goodwinaca520d2009-07-02 22:18:33 +00001//===- Thumb1InstrInfo.cpp - Thumb-1 Instruction Information --------*- C++ -*-===//
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +00002//
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//
David Goodwinaca520d2009-07-02 22:18:33 +000010// This file contains the Thumb-1 implementation of the TargetInstrInfo class.
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +000011//
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"
David Goodwinaca520d2009-07-02 22:18:33 +000021#include "Thumb1InstrInfo.h"
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +000022
23using namespace llvm;
24
David Goodwinaca520d2009-07-02 22:18:33 +000025Thumb1InstrInfo::Thumb1InstrInfo(const ARMSubtarget &STI)
Anton Korobeynikovcbce7922009-06-27 12:16:40 +000026 : ARMBaseInstrInfo(STI), RI(*this, STI) {
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +000027}
28
Evan Cheng7bd2ad12009-07-11 06:43:01 +000029unsigned Thumb1InstrInfo::getUnindexedOpcode(unsigned Opc) const {
David Goodwin41afec22009-07-08 16:09:28 +000030 return 0;
31}
32
Evan Cheng7bd2ad12009-07-11 06:43:01 +000033unsigned Thumb1InstrInfo::getOpcode(ARMII::Op Op) const {
David Goodwin41afec22009-07-08 16:09:28 +000034 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;
David Goodwin1f0bb992009-07-08 20:28:28 +000040 case ARMII::BX_RET: return ARM::tBX_RET;
David Goodwin7938afc2009-07-24 00:16:18 +000041 case ARMII::LDRri: return 0;
David Goodwin41afec22009-07-08 16:09:28 +000042 case ARMII::MOVr: return ARM::tMOVr;
David Goodwin7938afc2009-07-24 00:16:18 +000043 case ARMII::STRri: return 0;
David Goodwin41afec22009-07-08 16:09:28 +000044 case ARMII::SUBri: return ARM::tSUBi8;
45 case ARMII::SUBrs: return 0;
46 case ARMII::SUBrr: return ARM::tSUBrr;
David Goodwin41afec22009-07-08 16:09:28 +000047 default:
48 break;
49 }
50
51 return 0;
52}
53
54bool
55Thumb1InstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const {
56 if (MBB.empty()) return false;
57
58 switch (MBB.back().getOpcode()) {
59 case ARM::tBX_RET:
60 case ARM::tBX_RET_vararg:
61 case ARM::tPOP_RET:
62 case ARM::tB:
63 case ARM::tBR_JTr:
64 return true;
65 default:
66 break;
67 }
68
69 return false;
70}
71
David Goodwinaca520d2009-07-02 22:18:33 +000072bool Thumb1InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
73 MachineBasicBlock::iterator I,
74 unsigned DestReg, unsigned SrcReg,
75 const TargetRegisterClass *DestRC,
76 const TargetRegisterClass *SrcRC) const {
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +000077 DebugLoc DL = DebugLoc::getUnknownLoc();
78 if (I != MBB.end()) DL = I->getDebugLoc();
79
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +000080 if (DestRC == ARM::GPRRegisterClass) {
81 if (SrcRC == ARM::GPRRegisterClass) {
Evan Chengdf827f22009-07-26 23:59:01 +000082 BuildMI(MBB, I, DL, get(ARM::tMOVgpr2gpr), DestReg).addReg(SrcReg);
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +000083 return true;
84 } else if (SrcRC == ARM::tGPRRegisterClass) {
Evan Chengdf827f22009-07-26 23:59:01 +000085 BuildMI(MBB, I, DL, get(ARM::tMOVtgpr2gpr), DestReg).addReg(SrcReg);
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +000086 return true;
87 }
88 } else if (DestRC == ARM::tGPRRegisterClass) {
89 if (SrcRC == ARM::GPRRegisterClass) {
Evan Chengdf827f22009-07-26 23:59:01 +000090 BuildMI(MBB, I, DL, get(ARM::tMOVgpr2tgpr), DestReg).addReg(SrcReg);
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +000091 return true;
92 } else if (SrcRC == ARM::tGPRRegisterClass) {
93 BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg).addReg(SrcReg);
94 return true;
95 }
96 }
97
98 return false;
99}
100
David Goodwinaca520d2009-07-02 22:18:33 +0000101bool Thumb1InstrInfo::
Anton Korobeynikovcbce7922009-06-27 12:16:40 +0000102canFoldMemoryOperand(const MachineInstr *MI,
103 const SmallVectorImpl<unsigned> &Ops) const {
104 if (Ops.size() != 1) return false;
105
106 unsigned OpNum = Ops[0];
107 unsigned Opc = MI->getOpcode();
108 switch (Opc) {
109 default: break;
110 case ARM::tMOVr:
Evan Chengdf827f22009-07-26 23:59:01 +0000111 case ARM::tMOVtgpr2gpr:
112 case ARM::tMOVgpr2tgpr:
113 case ARM::tMOVgpr2gpr: {
Anton Korobeynikovcbce7922009-06-27 12:16:40 +0000114 if (OpNum == 0) { // move -> store
115 unsigned SrcReg = MI->getOperand(1).getReg();
Anton Korobeynikov0a90fcd2009-06-27 12:59:03 +0000116 if (RI.isPhysicalRegister(SrcReg) && !isARMLowRegister(SrcReg))
Anton Korobeynikovcbce7922009-06-27 12:16:40 +0000117 // tSpill cannot take a high register operand.
118 return false;
119 } else { // move -> load
120 unsigned DstReg = MI->getOperand(0).getReg();
Anton Korobeynikov0a90fcd2009-06-27 12:59:03 +0000121 if (RI.isPhysicalRegister(DstReg) && !isARMLowRegister(DstReg))
Anton Korobeynikovcbce7922009-06-27 12:16:40 +0000122 // tRestore cannot target a high register operand.
123 return false;
124 }
125 return true;
126 }
127 }
128
129 return false;
130}
131
David Goodwinaca520d2009-07-02 22:18:33 +0000132void Thumb1InstrInfo::
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +0000133storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
134 unsigned SrcReg, bool isKill, int FI,
135 const TargetRegisterClass *RC) const {
136 DebugLoc DL = DebugLoc::getUnknownLoc();
137 if (I != MBB.end()) DL = I->getDebugLoc();
138
139 assert(RC == ARM::tGPRRegisterClass && "Unknown regclass!");
140
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +0000141 if (RC == ARM::tGPRRegisterClass) {
Evan Cheng7bd2ad12009-07-11 06:43:01 +0000142 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tSpill))
143 .addReg(SrcReg, getKillRegState(isKill))
144 .addFrameIndex(FI).addImm(0));
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +0000145 }
146}
147
David Goodwinaca520d2009-07-02 22:18:33 +0000148void Thumb1InstrInfo::
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +0000149loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
150 unsigned DestReg, int FI,
151 const TargetRegisterClass *RC) const {
152 DebugLoc DL = DebugLoc::getUnknownLoc();
153 if (I != MBB.end()) DL = I->getDebugLoc();
154
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +0000155 assert(RC == ARM::tGPRRegisterClass && "Unknown regclass!");
156
157 if (RC == ARM::tGPRRegisterClass) {
Evan Cheng7bd2ad12009-07-11 06:43:01 +0000158 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tRestore), DestReg)
159 .addFrameIndex(FI).addImm(0));
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +0000160 }
161}
162
David Goodwinaca520d2009-07-02 22:18:33 +0000163bool Thumb1InstrInfo::
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +0000164spillCalleeSavedRegisters(MachineBasicBlock &MBB,
165 MachineBasicBlock::iterator MI,
166 const std::vector<CalleeSavedInfo> &CSI) const {
167 if (CSI.empty())
168 return false;
169
170 DebugLoc DL = DebugLoc::getUnknownLoc();
171 if (MI != MBB.end()) DL = MI->getDebugLoc();
172
173 MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, get(ARM::tPUSH));
174 for (unsigned i = CSI.size(); i != 0; --i) {
175 unsigned Reg = CSI[i-1].getReg();
176 // Add the callee-saved register as live-in. It's killed at the spill.
177 MBB.addLiveIn(Reg);
178 MIB.addReg(Reg, RegState::Kill);
179 }
180 return true;
181}
182
David Goodwinaca520d2009-07-02 22:18:33 +0000183bool Thumb1InstrInfo::
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +0000184restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
185 MachineBasicBlock::iterator MI,
186 const std::vector<CalleeSavedInfo> &CSI) const {
187 MachineFunction &MF = *MBB.getParent();
188 ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
189 if (CSI.empty())
190 return false;
191
192 bool isVarArg = AFI->getVarArgsRegSaveSize() > 0;
193 MachineInstr *PopMI = MF.CreateMachineInstr(get(ARM::tPOP),MI->getDebugLoc());
194 for (unsigned i = CSI.size(); i != 0; --i) {
195 unsigned Reg = CSI[i-1].getReg();
196 if (Reg == ARM::LR) {
197 // Special epilogue for vararg functions. See emitEpilogue
198 if (isVarArg)
199 continue;
200 Reg = ARM::PC;
201 PopMI->setDesc(get(ARM::tPOP_RET));
202 MI = MBB.erase(MI);
203 }
204 PopMI->addOperand(MachineOperand::CreateReg(Reg, true));
205 }
206
207 // It's illegal to emit pop instruction without operands.
208 if (PopMI->getNumOperands() > 0)
209 MBB.insert(MI, PopMI);
210
211 return true;
212}
213
David Goodwinaca520d2009-07-02 22:18:33 +0000214MachineInstr *Thumb1InstrInfo::
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +0000215foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
216 const SmallVectorImpl<unsigned> &Ops, int FI) const {
217 if (Ops.size() != 1) return NULL;
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +0000218
219 unsigned OpNum = Ops[0];
220 unsigned Opc = MI->getOpcode();
221 MachineInstr *NewMI = NULL;
222 switch (Opc) {
223 default: break;
224 case ARM::tMOVr:
Evan Chengdf827f22009-07-26 23:59:01 +0000225 case ARM::tMOVtgpr2gpr:
226 case ARM::tMOVgpr2tgpr:
227 case ARM::tMOVgpr2gpr: {
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +0000228 if (OpNum == 0) { // move -> store
229 unsigned SrcReg = MI->getOperand(1).getReg();
230 bool isKill = MI->getOperand(1).isKill();
Anton Korobeynikov0a90fcd2009-06-27 12:59:03 +0000231 if (RI.isPhysicalRegister(SrcReg) && !isARMLowRegister(SrcReg))
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +0000232 // tSpill cannot take a high register operand.
233 break;
Evan Cheng7bd2ad12009-07-11 06:43:01 +0000234 NewMI = AddDefaultPred(BuildMI(MF, MI->getDebugLoc(), get(ARM::tSpill))
235 .addReg(SrcReg, getKillRegState(isKill))
236 .addFrameIndex(FI).addImm(0));
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +0000237 } else { // move -> load
238 unsigned DstReg = MI->getOperand(0).getReg();
Anton Korobeynikov0a90fcd2009-06-27 12:59:03 +0000239 if (RI.isPhysicalRegister(DstReg) && !isARMLowRegister(DstReg))
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +0000240 // tRestore cannot target a high register operand.
241 break;
242 bool isDead = MI->getOperand(0).isDead();
Evan Cheng7bd2ad12009-07-11 06:43:01 +0000243 NewMI = AddDefaultPred(BuildMI(MF, MI->getDebugLoc(), get(ARM::tRestore))
244 .addReg(DstReg,
245 RegState::Define | getDeadRegState(isDead))
246 .addFrameIndex(FI).addImm(0));
Anton Korobeynikov65d16ea2009-06-26 21:28:53 +0000247 }
248 break;
249 }
250 }
251
252 return NewMI;
253}