blob: a61fca1f2529184fd59a4dd22db31b20c2ce5fae [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);
125 if (MO.isDef() && MO.isReg() && MO.getReg() == ARM::CPSR)
126 *CPSR = true;
127 }
128 return true;
129}
130
131// If the machine is predicable go ahead and add the predicate operands, if
132// it needs default CC operands add those.
133const MachineInstrBuilder &
134ARMFastISel::AddOptionalDefs(const MachineInstrBuilder &MIB) {
135 MachineInstr *MI = &*MIB;
136
137 // Do we use a predicate?
138 if (TII.isPredicable(MI))
139 AddDefaultPred(MIB);
140
141 // Do we optionally set a predicate? Preds is size > 0 iff the predicate
142 // defines CPSR. All other OptionalDefines in ARM are the CCR register.
Eric Christopher979e0a12010-08-19 15:35:27 +0000143 bool CPSR = false;
Eric Christopher456144e2010-08-19 00:37:05 +0000144 if (DefinesOptionalPredicate(MI, &CPSR)) {
145 if (CPSR)
146 AddDefaultT1CC(MIB);
147 else
148 AddDefaultCC(MIB);
149 }
150 return MIB;
151}
152
Eric Christopher0fe7d542010-08-17 01:25:29 +0000153unsigned ARMFastISel::FastEmitInst_(unsigned MachineInstOpcode,
154 const TargetRegisterClass* RC) {
155 unsigned ResultReg = createResultReg(RC);
156 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
157
Eric Christopher456144e2010-08-19 00:37:05 +0000158 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg));
Eric Christopher0fe7d542010-08-17 01:25:29 +0000159 return ResultReg;
160}
161
162unsigned ARMFastISel::FastEmitInst_r(unsigned MachineInstOpcode,
163 const TargetRegisterClass *RC,
164 unsigned Op0, bool Op0IsKill) {
165 unsigned ResultReg = createResultReg(RC);
166 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
167
168 if (II.getNumDefs() >= 1)
Eric Christopher456144e2010-08-19 00:37:05 +0000169 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000170 .addReg(Op0, Op0IsKill * RegState::Kill));
171 else {
Eric Christopher456144e2010-08-19 00:37:05 +0000172 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000173 .addReg(Op0, Op0IsKill * RegState::Kill));
Eric Christopher456144e2010-08-19 00:37:05 +0000174 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
Eric Christopher0fe7d542010-08-17 01:25:29 +0000175 TII.get(TargetOpcode::COPY), ResultReg)
176 .addReg(II.ImplicitDefs[0]));
177 }
178 return ResultReg;
179}
180
181unsigned ARMFastISel::FastEmitInst_rr(unsigned MachineInstOpcode,
182 const TargetRegisterClass *RC,
183 unsigned Op0, bool Op0IsKill,
184 unsigned Op1, bool Op1IsKill) {
185 unsigned ResultReg = createResultReg(RC);
186 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
187
188 if (II.getNumDefs() >= 1)
Eric Christopher456144e2010-08-19 00:37:05 +0000189 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000190 .addReg(Op0, Op0IsKill * RegState::Kill)
191 .addReg(Op1, Op1IsKill * RegState::Kill));
192 else {
Eric Christopher456144e2010-08-19 00:37:05 +0000193 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000194 .addReg(Op0, Op0IsKill * RegState::Kill)
195 .addReg(Op1, Op1IsKill * RegState::Kill));
Eric Christopher456144e2010-08-19 00:37:05 +0000196 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
Eric Christopher0fe7d542010-08-17 01:25:29 +0000197 TII.get(TargetOpcode::COPY), ResultReg)
198 .addReg(II.ImplicitDefs[0]));
199 }
200 return ResultReg;
201}
202
203unsigned ARMFastISel::FastEmitInst_ri(unsigned MachineInstOpcode,
204 const TargetRegisterClass *RC,
205 unsigned Op0, bool Op0IsKill,
206 uint64_t Imm) {
207 unsigned ResultReg = createResultReg(RC);
208 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
209
210 if (II.getNumDefs() >= 1)
Eric Christopher456144e2010-08-19 00:37:05 +0000211 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000212 .addReg(Op0, Op0IsKill * RegState::Kill)
213 .addImm(Imm));
214 else {
Eric Christopher456144e2010-08-19 00:37:05 +0000215 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000216 .addReg(Op0, Op0IsKill * RegState::Kill)
217 .addImm(Imm));
Eric Christopher456144e2010-08-19 00:37:05 +0000218 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
Eric Christopher0fe7d542010-08-17 01:25:29 +0000219 TII.get(TargetOpcode::COPY), ResultReg)
220 .addReg(II.ImplicitDefs[0]));
221 }
222 return ResultReg;
223}
224
225unsigned ARMFastISel::FastEmitInst_rf(unsigned MachineInstOpcode,
226 const TargetRegisterClass *RC,
227 unsigned Op0, bool Op0IsKill,
228 const ConstantFP *FPImm) {
229 unsigned ResultReg = createResultReg(RC);
230 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
231
232 if (II.getNumDefs() >= 1)
Eric Christopher456144e2010-08-19 00:37:05 +0000233 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000234 .addReg(Op0, Op0IsKill * RegState::Kill)
235 .addFPImm(FPImm));
236 else {
Eric Christopher456144e2010-08-19 00:37:05 +0000237 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000238 .addReg(Op0, Op0IsKill * RegState::Kill)
239 .addFPImm(FPImm));
Eric Christopher456144e2010-08-19 00:37:05 +0000240 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
Eric Christopher0fe7d542010-08-17 01:25:29 +0000241 TII.get(TargetOpcode::COPY), ResultReg)
242 .addReg(II.ImplicitDefs[0]));
243 }
244 return ResultReg;
245}
246
247unsigned ARMFastISel::FastEmitInst_rri(unsigned MachineInstOpcode,
248 const TargetRegisterClass *RC,
249 unsigned Op0, bool Op0IsKill,
250 unsigned Op1, bool Op1IsKill,
251 uint64_t Imm) {
252 unsigned ResultReg = createResultReg(RC);
253 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
254
255 if (II.getNumDefs() >= 1)
Eric Christopher456144e2010-08-19 00:37:05 +0000256 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000257 .addReg(Op0, Op0IsKill * RegState::Kill)
258 .addReg(Op1, Op1IsKill * RegState::Kill)
259 .addImm(Imm));
260 else {
Eric Christopher456144e2010-08-19 00:37:05 +0000261 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000262 .addReg(Op0, Op0IsKill * RegState::Kill)
263 .addReg(Op1, Op1IsKill * RegState::Kill)
264 .addImm(Imm));
Eric Christopher456144e2010-08-19 00:37:05 +0000265 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
Eric Christopher0fe7d542010-08-17 01:25:29 +0000266 TII.get(TargetOpcode::COPY), ResultReg)
267 .addReg(II.ImplicitDefs[0]));
268 }
269 return ResultReg;
270}
271
272unsigned ARMFastISel::FastEmitInst_i(unsigned MachineInstOpcode,
273 const TargetRegisterClass *RC,
274 uint64_t Imm) {
275 unsigned ResultReg = createResultReg(RC);
276 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
277
278 if (II.getNumDefs() >= 1)
Eric Christopher456144e2010-08-19 00:37:05 +0000279 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000280 .addImm(Imm));
281 else {
Eric Christopher456144e2010-08-19 00:37:05 +0000282 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
Eric Christopher0fe7d542010-08-17 01:25:29 +0000283 .addImm(Imm));
Eric Christopher456144e2010-08-19 00:37:05 +0000284 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
Eric Christopher0fe7d542010-08-17 01:25:29 +0000285 TII.get(TargetOpcode::COPY), ResultReg)
286 .addReg(II.ImplicitDefs[0]));
287 }
288 return ResultReg;
289}
290
291unsigned ARMFastISel::FastEmitInst_extractsubreg(MVT RetVT,
292 unsigned Op0, bool Op0IsKill,
293 uint32_t Idx) {
294 unsigned ResultReg = createResultReg(TLI.getRegClassFor(RetVT));
295 assert(TargetRegisterInfo::isVirtualRegister(Op0) &&
296 "Cannot yet extract from physregs");
Eric Christopher456144e2010-08-19 00:37:05 +0000297 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
Eric Christopher0fe7d542010-08-17 01:25:29 +0000298 DL, TII.get(TargetOpcode::COPY), ResultReg)
299 .addReg(Op0, getKillRegState(Op0IsKill), Idx));
300 return ResultReg;
301}
302
Eric Christopherab695882010-07-21 22:26:11 +0000303bool ARMFastISel::TargetSelectInstruction(const Instruction *I) {
304 switch (I->getOpcode()) {
305 default: break;
306 }
307 return false;
308}
309
310namespace llvm {
311 llvm::FastISel *ARM::createFastISel(FunctionLoweringInfo &funcInfo) {
Eric Christopher038fea52010-08-17 00:46:57 +0000312 if (EnableARMFastISel) return new ARMFastISel(funcInfo);
Evan Cheng09447952010-07-26 18:32:55 +0000313 return 0;
Eric Christopherab695882010-07-21 22:26:11 +0000314 }
315}