blob: 6281c3a3b0b3c899ea066eb9fb13d1fbeb403e2e [file] [log] [blame]
Eric Christopherab695882010-07-21 22:26:11 +00001//===-- ARMFastISel.cpp - ARM FastISel implementation ---------------------===//
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 defines the ARM-specific support for the FastISel class. Some
11// of the target-specific code is generated by tablegen in the file
12// ARMGenFastISel.inc, which is #included here.
13//
14//===----------------------------------------------------------------------===//
15
16#include "ARM.h"
Eric Christopher456144e2010-08-19 00:37:05 +000017#include "ARMBaseInstrInfo.h"
Eric Christopherab695882010-07-21 22:26:11 +000018#include "ARMRegisterInfo.h"
19#include "ARMTargetMachine.h"
20#include "ARMSubtarget.h"
21#include "llvm/CallingConv.h"
22#include "llvm/DerivedTypes.h"
23#include "llvm/GlobalVariable.h"
24#include "llvm/Instructions.h"
25#include "llvm/IntrinsicInst.h"
26#include "llvm/CodeGen/Analysis.h"
27#include "llvm/CodeGen/FastISel.h"
28#include "llvm/CodeGen/FunctionLoweringInfo.h"
Eric Christopher0fe7d542010-08-17 01:25:29 +000029#include "llvm/CodeGen/MachineInstrBuilder.h"
30#include "llvm/CodeGen/MachineModuleInfo.h"
Eric Christopherab695882010-07-21 22:26:11 +000031#include "llvm/CodeGen/MachineConstantPool.h"
32#include "llvm/CodeGen/MachineFrameInfo.h"
33#include "llvm/CodeGen/MachineRegisterInfo.h"
34#include "llvm/Support/CallSite.h"
Eric Christopher038fea52010-08-17 00:46:57 +000035#include "llvm/Support/CommandLine.h"
Eric Christopherab695882010-07-21 22:26:11 +000036#include "llvm/Support/ErrorHandling.h"
37#include "llvm/Support/GetElementPtrTypeIterator.h"
Eric Christopher0fe7d542010-08-17 01:25:29 +000038#include "llvm/Target/TargetData.h"
39#include "llvm/Target/TargetInstrInfo.h"
40#include "llvm/Target/TargetLowering.h"
41#include "llvm/Target/TargetMachine.h"
Eric Christopherab695882010-07-21 22:26:11 +000042#include "llvm/Target/TargetOptions.h"
43using namespace llvm;
44
Eric Christopher038fea52010-08-17 00:46:57 +000045static cl::opt<bool>
46EnableARMFastISel("arm-fast-isel",
47 cl::desc("Turn on experimental ARM fast-isel support"),
48 cl::init(false), cl::Hidden);
49
Eric Christopherab695882010-07-21 22:26:11 +000050namespace {
51
52class ARMFastISel : public FastISel {
53
54 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
55 /// make the right decision when generating code for different targets.
56 const ARMSubtarget *Subtarget;
Eric Christopher0fe7d542010-08-17 01:25:29 +000057 const TargetMachine &TM;
58 const TargetInstrInfo &TII;
59 const TargetLowering &TLI;
Eric Christopherab695882010-07-21 22:26:11 +000060
61 public:
Eric Christopher0fe7d542010-08-17 01:25:29 +000062 explicit ARMFastISel(FunctionLoweringInfo &funcInfo)
63 : FastISel(funcInfo),
64 TM(funcInfo.MF->getTarget()),
65 TII(*TM.getInstrInfo()),
66 TLI(*TM.getTargetLowering()) {
Eric Christopherab695882010-07-21 22:26:11 +000067 Subtarget = &TM.getSubtarget<ARMSubtarget>();
68 }
69
Eric Christophercb592292010-08-20 00:20:31 +000070 // Code from FastISel.cpp.
Eric Christopher0fe7d542010-08-17 01:25:29 +000071 virtual unsigned FastEmitInst_(unsigned MachineInstOpcode,
72 const TargetRegisterClass *RC);
73 virtual unsigned FastEmitInst_r(unsigned MachineInstOpcode,
74 const TargetRegisterClass *RC,
75 unsigned Op0, bool Op0IsKill);
76 virtual unsigned FastEmitInst_rr(unsigned MachineInstOpcode,
77 const TargetRegisterClass *RC,
78 unsigned Op0, bool Op0IsKill,
79 unsigned Op1, bool Op1IsKill);
80 virtual unsigned FastEmitInst_ri(unsigned MachineInstOpcode,
81 const TargetRegisterClass *RC,
82 unsigned Op0, bool Op0IsKill,
83 uint64_t Imm);
84 virtual unsigned FastEmitInst_rf(unsigned MachineInstOpcode,
85 const TargetRegisterClass *RC,
86 unsigned Op0, bool Op0IsKill,
87 const ConstantFP *FPImm);
88 virtual unsigned FastEmitInst_i(unsigned MachineInstOpcode,
89 const TargetRegisterClass *RC,
90 uint64_t Imm);
91 virtual unsigned FastEmitInst_rri(unsigned MachineInstOpcode,
92 const TargetRegisterClass *RC,
93 unsigned Op0, bool Op0IsKill,
94 unsigned Op1, bool Op1IsKill,
95 uint64_t Imm);
96 virtual unsigned FastEmitInst_extractsubreg(MVT RetVT,
97 unsigned Op0, bool Op0IsKill,
98 uint32_t Idx);
Eric Christophercb592292010-08-20 00:20:31 +000099
100 // Backend specific FastISel code.
Eric Christopherab695882010-07-21 22:26:11 +0000101 virtual bool TargetSelectInstruction(const Instruction *I);
102
103 #include "ARMGenFastISel.inc"
104
Eric Christopher456144e2010-08-19 00:37:05 +0000105 private:
106 bool DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR);
107 const MachineInstrBuilder &AddOptionalDefs(const MachineInstrBuilder &MIB);
108};
Eric Christopherab695882010-07-21 22:26:11 +0000109
110} // end anonymous namespace
111
112// #include "ARMGenCallingConv.inc"
113
Eric Christopher456144e2010-08-19 00:37:05 +0000114// DefinesOptionalPredicate - This is different from DefinesPredicate in that
115// we don't care about implicit defs here, just places we'll need to add a
116// default CCReg argument. Sets CPSR if we're setting CPSR instead of CCR.
117bool ARMFastISel::DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR) {
118 const TargetInstrDesc &TID = MI->getDesc();
119 if (!TID.hasOptionalDef())
120 return false;
121
122 // Look to see if our OptionalDef is defining CPSR or CCR.
123 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
124 const MachineOperand &MO = MI->getOperand(i);
Eric Christopherf762fbe2010-08-20 00:36:24 +0000125 if (!MO.isReg() || !MO.isDef()) continue;
126 if (MO.getReg() == ARM::CPSR)
Eric Christopher456144e2010-08-19 00:37:05 +0000127 *CPSR = true;
128 }
129 return true;
130}
131
132// If the machine is predicable go ahead and add the predicate operands, if
133// it needs default CC operands add those.
134const MachineInstrBuilder &
135ARMFastISel::AddOptionalDefs(const MachineInstrBuilder &MIB) {
136 MachineInstr *MI = &*MIB;
137
138 // Do we use a predicate?
139 if (TII.isPredicable(MI))
140 AddDefaultPred(MIB);
141
142 // Do we optionally set a predicate? Preds is size > 0 iff the predicate
143 // defines CPSR. All other OptionalDefines in ARM are the CCR register.
Eric Christopher979e0a12010-08-19 15:35:27 +0000144 bool CPSR = false;
Eric Christopher456144e2010-08-19 00:37:05 +0000145 if (DefinesOptionalPredicate(MI, &CPSR)) {
146 if (CPSR)
147 AddDefaultT1CC(MIB);
148 else
149 AddDefaultCC(MIB);
150 }
151 return MIB;
152}
153
Eric Christopher0fe7d542010-08-17 01:25:29 +0000154unsigned ARMFastISel::FastEmitInst_(unsigned MachineInstOpcode,
155 const TargetRegisterClass* RC) {
156 unsigned ResultReg = createResultReg(RC);
157 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
158
Eric Christopher456144e2010-08-19 00:37:05 +0000159 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg));
Eric Christopher0fe7d542010-08-17 01:25:29 +0000160 return ResultReg;
161}
162
163unsigned ARMFastISel::FastEmitInst_r(unsigned MachineInstOpcode,
164 const TargetRegisterClass *RC,
165 unsigned Op0, bool Op0IsKill) {
166 unsigned ResultReg = createResultReg(RC);
167 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
168
169 if (II.getNumDefs() >= 1)
Eric Christopher456144e2010-08-19 00:37:05 +0000170 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000171 .addReg(Op0, Op0IsKill * RegState::Kill));
172 else {
Eric Christopher456144e2010-08-19 00:37:05 +0000173 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000174 .addReg(Op0, Op0IsKill * RegState::Kill));
Eric Christopher456144e2010-08-19 00:37:05 +0000175 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
Eric Christopher0fe7d542010-08-17 01:25:29 +0000176 TII.get(TargetOpcode::COPY), ResultReg)
177 .addReg(II.ImplicitDefs[0]));
178 }
179 return ResultReg;
180}
181
182unsigned ARMFastISel::FastEmitInst_rr(unsigned MachineInstOpcode,
183 const TargetRegisterClass *RC,
184 unsigned Op0, bool Op0IsKill,
185 unsigned Op1, bool Op1IsKill) {
186 unsigned ResultReg = createResultReg(RC);
187 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
188
189 if (II.getNumDefs() >= 1)
Eric Christopher456144e2010-08-19 00:37:05 +0000190 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000191 .addReg(Op0, Op0IsKill * RegState::Kill)
192 .addReg(Op1, Op1IsKill * RegState::Kill));
193 else {
Eric Christopher456144e2010-08-19 00:37:05 +0000194 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000195 .addReg(Op0, Op0IsKill * RegState::Kill)
196 .addReg(Op1, Op1IsKill * RegState::Kill));
Eric Christopher456144e2010-08-19 00:37:05 +0000197 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
Eric Christopher0fe7d542010-08-17 01:25:29 +0000198 TII.get(TargetOpcode::COPY), ResultReg)
199 .addReg(II.ImplicitDefs[0]));
200 }
201 return ResultReg;
202}
203
204unsigned ARMFastISel::FastEmitInst_ri(unsigned MachineInstOpcode,
205 const TargetRegisterClass *RC,
206 unsigned Op0, bool Op0IsKill,
207 uint64_t Imm) {
208 unsigned ResultReg = createResultReg(RC);
209 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
210
211 if (II.getNumDefs() >= 1)
Eric Christopher456144e2010-08-19 00:37:05 +0000212 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000213 .addReg(Op0, Op0IsKill * RegState::Kill)
214 .addImm(Imm));
215 else {
Eric Christopher456144e2010-08-19 00:37:05 +0000216 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000217 .addReg(Op0, Op0IsKill * RegState::Kill)
218 .addImm(Imm));
Eric Christopher456144e2010-08-19 00:37:05 +0000219 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
Eric Christopher0fe7d542010-08-17 01:25:29 +0000220 TII.get(TargetOpcode::COPY), ResultReg)
221 .addReg(II.ImplicitDefs[0]));
222 }
223 return ResultReg;
224}
225
226unsigned ARMFastISel::FastEmitInst_rf(unsigned MachineInstOpcode,
227 const TargetRegisterClass *RC,
228 unsigned Op0, bool Op0IsKill,
229 const ConstantFP *FPImm) {
230 unsigned ResultReg = createResultReg(RC);
231 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
232
233 if (II.getNumDefs() >= 1)
Eric Christopher456144e2010-08-19 00:37:05 +0000234 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000235 .addReg(Op0, Op0IsKill * RegState::Kill)
236 .addFPImm(FPImm));
237 else {
Eric Christopher456144e2010-08-19 00:37:05 +0000238 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000239 .addReg(Op0, Op0IsKill * RegState::Kill)
240 .addFPImm(FPImm));
Eric Christopher456144e2010-08-19 00:37:05 +0000241 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
Eric Christopher0fe7d542010-08-17 01:25:29 +0000242 TII.get(TargetOpcode::COPY), ResultReg)
243 .addReg(II.ImplicitDefs[0]));
244 }
245 return ResultReg;
246}
247
248unsigned ARMFastISel::FastEmitInst_rri(unsigned MachineInstOpcode,
249 const TargetRegisterClass *RC,
250 unsigned Op0, bool Op0IsKill,
251 unsigned Op1, bool Op1IsKill,
252 uint64_t Imm) {
253 unsigned ResultReg = createResultReg(RC);
254 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
255
256 if (II.getNumDefs() >= 1)
Eric Christopher456144e2010-08-19 00:37:05 +0000257 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000258 .addReg(Op0, Op0IsKill * RegState::Kill)
259 .addReg(Op1, Op1IsKill * RegState::Kill)
260 .addImm(Imm));
261 else {
Eric Christopher456144e2010-08-19 00:37:05 +0000262 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000263 .addReg(Op0, Op0IsKill * RegState::Kill)
264 .addReg(Op1, Op1IsKill * RegState::Kill)
265 .addImm(Imm));
Eric Christopher456144e2010-08-19 00:37:05 +0000266 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
Eric Christopher0fe7d542010-08-17 01:25:29 +0000267 TII.get(TargetOpcode::COPY), ResultReg)
268 .addReg(II.ImplicitDefs[0]));
269 }
270 return ResultReg;
271}
272
273unsigned ARMFastISel::FastEmitInst_i(unsigned MachineInstOpcode,
274 const TargetRegisterClass *RC,
275 uint64_t Imm) {
276 unsigned ResultReg = createResultReg(RC);
277 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
278
279 if (II.getNumDefs() >= 1)
Eric Christopher456144e2010-08-19 00:37:05 +0000280 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000281 .addImm(Imm));
282 else {
Eric Christopher456144e2010-08-19 00:37:05 +0000283 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000284 .addImm(Imm));
Eric Christopher456144e2010-08-19 00:37:05 +0000285 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
Eric Christopher0fe7d542010-08-17 01:25:29 +0000286 TII.get(TargetOpcode::COPY), ResultReg)
287 .addReg(II.ImplicitDefs[0]));
288 }
289 return ResultReg;
290}
291
292unsigned ARMFastISel::FastEmitInst_extractsubreg(MVT RetVT,
293 unsigned Op0, bool Op0IsKill,
294 uint32_t Idx) {
295 unsigned ResultReg = createResultReg(TLI.getRegClassFor(RetVT));
296 assert(TargetRegisterInfo::isVirtualRegister(Op0) &&
297 "Cannot yet extract from physregs");
Eric Christopher456144e2010-08-19 00:37:05 +0000298 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
Eric Christopher0fe7d542010-08-17 01:25:29 +0000299 DL, TII.get(TargetOpcode::COPY), ResultReg)
300 .addReg(Op0, getKillRegState(Op0IsKill), Idx));
301 return ResultReg;
302}
303
Eric Christopherab695882010-07-21 22:26:11 +0000304bool ARMFastISel::TargetSelectInstruction(const Instruction *I) {
305 switch (I->getOpcode()) {
306 default: break;
307 }
308 return false;
309}
310
311namespace llvm {
312 llvm::FastISel *ARM::createFastISel(FunctionLoweringInfo &funcInfo) {
Eric Christopher038fea52010-08-17 00:46:57 +0000313 if (EnableARMFastISel) return new ARMFastISel(funcInfo);
Evan Cheng09447952010-07-26 18:32:55 +0000314 return 0;
Eric Christopherab695882010-07-21 22:26:11 +0000315 }
316}