1 //===-- ARMFastISel.cpp - ARM FastISel implementation ---------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
14 //===----------------------------------------------------------------------===//
17 #include "ARMBaseInstrInfo.h"
18 #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"
29 #include "llvm/CodeGen/MachineInstrBuilder.h"
30 #include "llvm/CodeGen/MachineModuleInfo.h"
31 #include "llvm/CodeGen/MachineConstantPool.h"
32 #include "llvm/CodeGen/MachineFrameInfo.h"
33 #include "llvm/CodeGen/MachineRegisterInfo.h"
34 #include "llvm/Support/CallSite.h"
35 #include "llvm/Support/CommandLine.h"
36 #include "llvm/Support/ErrorHandling.h"
37 #include "llvm/Support/GetElementPtrTypeIterator.h"
38 #include "llvm/Target/TargetData.h"
39 #include "llvm/Target/TargetInstrInfo.h"
40 #include "llvm/Target/TargetLowering.h"
41 #include "llvm/Target/TargetMachine.h"
42 #include "llvm/Target/TargetOptions.h"
46 EnableARMFastISel("arm-fast-isel",
47 cl::desc("Turn on experimental ARM fast-isel support"),
48 cl::init(false), cl::Hidden);
52 class ARMFastISel : public FastISel {
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;
57 const TargetMachine &TM;
58 const TargetInstrInfo &TII;
59 const TargetLowering &TLI;
60 const ARMFunctionInfo *AFI;
63 explicit ARMFastISel(FunctionLoweringInfo &funcInfo)
65 TM(funcInfo.MF->getTarget()),
66 TII(*TM.getInstrInfo()),
67 TLI(*TM.getTargetLowering()) {
68 Subtarget = &TM.getSubtarget<ARMSubtarget>();
69 AFI = funcInfo.MF->getInfo<ARMFunctionInfo>();
72 // Code from FastISel.cpp.
73 virtual unsigned FastEmitInst_(unsigned MachineInstOpcode,
74 const TargetRegisterClass *RC);
75 virtual unsigned FastEmitInst_r(unsigned MachineInstOpcode,
76 const TargetRegisterClass *RC,
77 unsigned Op0, bool Op0IsKill);
78 virtual unsigned FastEmitInst_rr(unsigned MachineInstOpcode,
79 const TargetRegisterClass *RC,
80 unsigned Op0, bool Op0IsKill,
81 unsigned Op1, bool Op1IsKill);
82 virtual unsigned FastEmitInst_ri(unsigned MachineInstOpcode,
83 const TargetRegisterClass *RC,
84 unsigned Op0, bool Op0IsKill,
86 virtual unsigned FastEmitInst_rf(unsigned MachineInstOpcode,
87 const TargetRegisterClass *RC,
88 unsigned Op0, bool Op0IsKill,
89 const ConstantFP *FPImm);
90 virtual unsigned FastEmitInst_i(unsigned MachineInstOpcode,
91 const TargetRegisterClass *RC,
93 virtual unsigned FastEmitInst_rri(unsigned MachineInstOpcode,
94 const TargetRegisterClass *RC,
95 unsigned Op0, bool Op0IsKill,
96 unsigned Op1, bool Op1IsKill,
98 virtual unsigned FastEmitInst_extractsubreg(MVT RetVT,
99 unsigned Op0, bool Op0IsKill,
102 // Backend specific FastISel code.
103 virtual bool TargetSelectInstruction(const Instruction *I);
105 #include "ARMGenFastISel.inc"
107 // Instruction selection routines.
108 virtual bool ARMSelectLoad(const Instruction *I);
112 bool ARMComputeRegOffset(const Instruction *I, unsigned &Reg, int &Offset);
114 bool DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR);
115 const MachineInstrBuilder &AddOptionalDefs(const MachineInstrBuilder &MIB);
118 } // end anonymous namespace
120 // #include "ARMGenCallingConv.inc"
122 // DefinesOptionalPredicate - This is different from DefinesPredicate in that
123 // we don't care about implicit defs here, just places we'll need to add a
124 // default CCReg argument. Sets CPSR if we're setting CPSR instead of CCR.
125 bool ARMFastISel::DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR) {
126 const TargetInstrDesc &TID = MI->getDesc();
127 if (!TID.hasOptionalDef())
130 // Look to see if our OptionalDef is defining CPSR or CCR.
131 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
132 const MachineOperand &MO = MI->getOperand(i);
133 if (!MO.isReg() || !MO.isDef()) continue;
134 if (MO.getReg() == ARM::CPSR)
140 // If the machine is predicable go ahead and add the predicate operands, if
141 // it needs default CC operands add those.
142 const MachineInstrBuilder &
143 ARMFastISel::AddOptionalDefs(const MachineInstrBuilder &MIB) {
144 MachineInstr *MI = &*MIB;
146 // Do we use a predicate?
147 if (TII.isPredicable(MI))
150 // Do we optionally set a predicate? Preds is size > 0 iff the predicate
151 // defines CPSR. All other OptionalDefines in ARM are the CCR register.
153 if (DefinesOptionalPredicate(MI, &CPSR)) {
162 unsigned ARMFastISel::FastEmitInst_(unsigned MachineInstOpcode,
163 const TargetRegisterClass* RC) {
164 unsigned ResultReg = createResultReg(RC);
165 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
167 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg));
171 unsigned ARMFastISel::FastEmitInst_r(unsigned MachineInstOpcode,
172 const TargetRegisterClass *RC,
173 unsigned Op0, bool Op0IsKill) {
174 unsigned ResultReg = createResultReg(RC);
175 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
177 if (II.getNumDefs() >= 1)
178 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
179 .addReg(Op0, Op0IsKill * RegState::Kill));
181 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
182 .addReg(Op0, Op0IsKill * RegState::Kill));
183 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
184 TII.get(TargetOpcode::COPY), ResultReg)
185 .addReg(II.ImplicitDefs[0]));
190 unsigned ARMFastISel::FastEmitInst_rr(unsigned MachineInstOpcode,
191 const TargetRegisterClass *RC,
192 unsigned Op0, bool Op0IsKill,
193 unsigned Op1, bool Op1IsKill) {
194 unsigned ResultReg = createResultReg(RC);
195 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
197 if (II.getNumDefs() >= 1)
198 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
199 .addReg(Op0, Op0IsKill * RegState::Kill)
200 .addReg(Op1, Op1IsKill * RegState::Kill));
202 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
203 .addReg(Op0, Op0IsKill * RegState::Kill)
204 .addReg(Op1, Op1IsKill * RegState::Kill));
205 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
206 TII.get(TargetOpcode::COPY), ResultReg)
207 .addReg(II.ImplicitDefs[0]));
212 unsigned ARMFastISel::FastEmitInst_ri(unsigned MachineInstOpcode,
213 const TargetRegisterClass *RC,
214 unsigned Op0, bool Op0IsKill,
216 unsigned ResultReg = createResultReg(RC);
217 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
219 if (II.getNumDefs() >= 1)
220 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
221 .addReg(Op0, Op0IsKill * RegState::Kill)
224 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
225 .addReg(Op0, Op0IsKill * RegState::Kill)
227 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
228 TII.get(TargetOpcode::COPY), ResultReg)
229 .addReg(II.ImplicitDefs[0]));
234 unsigned ARMFastISel::FastEmitInst_rf(unsigned MachineInstOpcode,
235 const TargetRegisterClass *RC,
236 unsigned Op0, bool Op0IsKill,
237 const ConstantFP *FPImm) {
238 unsigned ResultReg = createResultReg(RC);
239 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
241 if (II.getNumDefs() >= 1)
242 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
243 .addReg(Op0, Op0IsKill * RegState::Kill)
246 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
247 .addReg(Op0, Op0IsKill * RegState::Kill)
249 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
250 TII.get(TargetOpcode::COPY), ResultReg)
251 .addReg(II.ImplicitDefs[0]));
256 unsigned ARMFastISel::FastEmitInst_rri(unsigned MachineInstOpcode,
257 const TargetRegisterClass *RC,
258 unsigned Op0, bool Op0IsKill,
259 unsigned Op1, bool Op1IsKill,
261 unsigned ResultReg = createResultReg(RC);
262 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
264 if (II.getNumDefs() >= 1)
265 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
266 .addReg(Op0, Op0IsKill * RegState::Kill)
267 .addReg(Op1, Op1IsKill * RegState::Kill)
270 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
271 .addReg(Op0, Op0IsKill * RegState::Kill)
272 .addReg(Op1, Op1IsKill * RegState::Kill)
274 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
275 TII.get(TargetOpcode::COPY), ResultReg)
276 .addReg(II.ImplicitDefs[0]));
281 unsigned ARMFastISel::FastEmitInst_i(unsigned MachineInstOpcode,
282 const TargetRegisterClass *RC,
284 unsigned ResultReg = createResultReg(RC);
285 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
287 if (II.getNumDefs() >= 1)
288 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
291 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
293 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
294 TII.get(TargetOpcode::COPY), ResultReg)
295 .addReg(II.ImplicitDefs[0]));
300 unsigned ARMFastISel::FastEmitInst_extractsubreg(MVT RetVT,
301 unsigned Op0, bool Op0IsKill,
303 unsigned ResultReg = createResultReg(TLI.getRegClassFor(RetVT));
304 assert(TargetRegisterInfo::isVirtualRegister(Op0) &&
305 "Cannot yet extract from physregs");
306 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
307 DL, TII.get(TargetOpcode::COPY), ResultReg)
308 .addReg(Op0, getKillRegState(Op0IsKill), Idx));
312 bool ARMFastISel::ARMComputeRegOffset(const Instruction *I, unsigned &Reg,
314 // Some boilerplate from the X86 FastISel.
315 const User *U = NULL;
316 Value *Op1 = I->getOperand(0);
317 unsigned Opcode = Instruction::UserOp1;
318 if (const Instruction *I = dyn_cast<Instruction>(Op1)) {
319 // Don't walk into other basic blocks; it's possible we haven't
320 // visited them yet, so the instructions may not yet be assigned
321 // virtual registers.
322 if (FuncInfo.MBBMap[I->getParent()] != FuncInfo.MBB)
325 Opcode = I->getOpcode();
327 } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Op1)) {
328 Opcode = C->getOpcode();
332 if (const PointerType *Ty = dyn_cast<PointerType>(Op1->getType()))
333 if (Ty->getAddressSpace() > 255)
334 // Fast instruction selection doesn't support the special
340 //errs() << "Failing Opcode is: " << *Op1 << "\n";
342 case Instruction::Alloca: {
343 // Do static allocas.
344 const AllocaInst *A = cast<AllocaInst>(Op1);
345 DenseMap<const AllocaInst*, int>::iterator SI =
346 FuncInfo.StaticAllocaMap.find(A);
347 if (SI != FuncInfo.StaticAllocaMap.end())
349 TM.getRegisterInfo()->getFrameIndexReference(*FuncInfo.MF,
359 bool ARMFastISel::ARMSelectLoad(const Instruction *I) {
364 // See if we can handle this as Reg + Offset
365 if (!ARMComputeRegOffset(I, Reg, Offset))
368 unsigned ResultReg = createResultReg(ARM::GPRRegisterClass);
369 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
370 TII.get(ARM::LDR), ResultReg)
371 .addImm(0).addReg(Reg).addImm(Offset));
376 bool ARMFastISel::TargetSelectInstruction(const Instruction *I) {
377 // No Thumb-1 for now.
378 if (AFI->isThumbFunction() && !AFI->isThumb2Function()) return false;
380 switch (I->getOpcode()) {
381 case Instruction::Load:
382 return ARMSelectLoad(I);
389 llvm::FastISel *ARM::createFastISel(FunctionLoweringInfo &funcInfo) {
390 if (EnableARMFastISel) return new ARMFastISel(funcInfo);