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);
109 virtual bool ARMSelectStore(const Instruction *I);
113 bool isTypeLegal(const Type *Ty, EVT &VT);
114 bool isLoadTypeLegal(const Type *Ty, EVT &VT);
115 bool ARMEmitLoad(EVT VT, unsigned &ResultReg, unsigned Reg, int Offset);
116 bool ARMEmitStore(EVT VT, unsigned SrcReg, unsigned Reg, int Offset);
117 bool ARMLoadAlloca(const Instruction *I);
118 bool ARMStoreAlloca(const Instruction *I, unsigned SrcReg);
119 bool ARMComputeRegOffset(const Value *Obj, unsigned &Reg, int &Offset);
120 bool ARMMaterializeConstant(const ConstantInt *Val, unsigned &Reg);
122 bool DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR);
123 const MachineInstrBuilder &AddOptionalDefs(const MachineInstrBuilder &MIB);
126 } // end anonymous namespace
128 // #include "ARMGenCallingConv.inc"
130 // DefinesOptionalPredicate - This is different from DefinesPredicate in that
131 // we don't care about implicit defs here, just places we'll need to add a
132 // default CCReg argument. Sets CPSR if we're setting CPSR instead of CCR.
133 bool ARMFastISel::DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR) {
134 const TargetInstrDesc &TID = MI->getDesc();
135 if (!TID.hasOptionalDef())
138 // Look to see if our OptionalDef is defining CPSR or CCR.
139 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
140 const MachineOperand &MO = MI->getOperand(i);
141 if (!MO.isReg() || !MO.isDef()) continue;
142 if (MO.getReg() == ARM::CPSR)
148 // If the machine is predicable go ahead and add the predicate operands, if
149 // it needs default CC operands add those.
150 const MachineInstrBuilder &
151 ARMFastISel::AddOptionalDefs(const MachineInstrBuilder &MIB) {
152 MachineInstr *MI = &*MIB;
154 // Do we use a predicate?
155 if (TII.isPredicable(MI))
158 // Do we optionally set a predicate? Preds is size > 0 iff the predicate
159 // defines CPSR. All other OptionalDefines in ARM are the CCR register.
161 if (DefinesOptionalPredicate(MI, &CPSR)) {
170 unsigned ARMFastISel::FastEmitInst_(unsigned MachineInstOpcode,
171 const TargetRegisterClass* RC) {
172 unsigned ResultReg = createResultReg(RC);
173 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
175 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg));
179 unsigned ARMFastISel::FastEmitInst_r(unsigned MachineInstOpcode,
180 const TargetRegisterClass *RC,
181 unsigned Op0, bool Op0IsKill) {
182 unsigned ResultReg = createResultReg(RC);
183 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
185 if (II.getNumDefs() >= 1)
186 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
187 .addReg(Op0, Op0IsKill * RegState::Kill));
189 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
190 .addReg(Op0, Op0IsKill * RegState::Kill));
191 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
192 TII.get(TargetOpcode::COPY), ResultReg)
193 .addReg(II.ImplicitDefs[0]));
198 unsigned ARMFastISel::FastEmitInst_rr(unsigned MachineInstOpcode,
199 const TargetRegisterClass *RC,
200 unsigned Op0, bool Op0IsKill,
201 unsigned Op1, bool Op1IsKill) {
202 unsigned ResultReg = createResultReg(RC);
203 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
205 if (II.getNumDefs() >= 1)
206 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
207 .addReg(Op0, Op0IsKill * RegState::Kill)
208 .addReg(Op1, Op1IsKill * RegState::Kill));
210 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
211 .addReg(Op0, Op0IsKill * RegState::Kill)
212 .addReg(Op1, Op1IsKill * RegState::Kill));
213 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
214 TII.get(TargetOpcode::COPY), ResultReg)
215 .addReg(II.ImplicitDefs[0]));
220 unsigned ARMFastISel::FastEmitInst_ri(unsigned MachineInstOpcode,
221 const TargetRegisterClass *RC,
222 unsigned Op0, bool Op0IsKill,
224 unsigned ResultReg = createResultReg(RC);
225 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
227 if (II.getNumDefs() >= 1)
228 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
229 .addReg(Op0, Op0IsKill * RegState::Kill)
232 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
233 .addReg(Op0, Op0IsKill * RegState::Kill)
235 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
236 TII.get(TargetOpcode::COPY), ResultReg)
237 .addReg(II.ImplicitDefs[0]));
242 unsigned ARMFastISel::FastEmitInst_rf(unsigned MachineInstOpcode,
243 const TargetRegisterClass *RC,
244 unsigned Op0, bool Op0IsKill,
245 const ConstantFP *FPImm) {
246 unsigned ResultReg = createResultReg(RC);
247 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
249 if (II.getNumDefs() >= 1)
250 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
251 .addReg(Op0, Op0IsKill * RegState::Kill)
254 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
255 .addReg(Op0, Op0IsKill * RegState::Kill)
257 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
258 TII.get(TargetOpcode::COPY), ResultReg)
259 .addReg(II.ImplicitDefs[0]));
264 unsigned ARMFastISel::FastEmitInst_rri(unsigned MachineInstOpcode,
265 const TargetRegisterClass *RC,
266 unsigned Op0, bool Op0IsKill,
267 unsigned Op1, bool Op1IsKill,
269 unsigned ResultReg = createResultReg(RC);
270 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
272 if (II.getNumDefs() >= 1)
273 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
274 .addReg(Op0, Op0IsKill * RegState::Kill)
275 .addReg(Op1, Op1IsKill * RegState::Kill)
278 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
279 .addReg(Op0, Op0IsKill * RegState::Kill)
280 .addReg(Op1, Op1IsKill * RegState::Kill)
282 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
283 TII.get(TargetOpcode::COPY), ResultReg)
284 .addReg(II.ImplicitDefs[0]));
289 unsigned ARMFastISel::FastEmitInst_i(unsigned MachineInstOpcode,
290 const TargetRegisterClass *RC,
292 unsigned ResultReg = createResultReg(RC);
293 const TargetInstrDesc &II = TII.get(MachineInstOpcode);
295 if (II.getNumDefs() >= 1)
296 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)
299 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II)
301 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
302 TII.get(TargetOpcode::COPY), ResultReg)
303 .addReg(II.ImplicitDefs[0]));
308 unsigned ARMFastISel::FastEmitInst_extractsubreg(MVT RetVT,
309 unsigned Op0, bool Op0IsKill,
311 unsigned ResultReg = createResultReg(TLI.getRegClassFor(RetVT));
312 assert(TargetRegisterInfo::isVirtualRegister(Op0) &&
313 "Cannot yet extract from physregs");
314 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
315 DL, TII.get(TargetOpcode::COPY), ResultReg)
316 .addReg(Op0, getKillRegState(Op0IsKill), Idx));
320 bool ARMFastISel::isTypeLegal(const Type *Ty, EVT &VT) {
321 VT = TLI.getValueType(Ty, true);
323 // Only handle simple types.
324 if (VT == MVT::Other || !VT.isSimple()) return false;
326 // Handle all legal types, i.e. a register that will directly hold this
328 return TLI.isTypeLegal(VT);
331 bool ARMFastISel::isLoadTypeLegal(const Type *Ty, EVT &VT) {
332 if (isTypeLegal(Ty, VT)) return true;
334 // If this is a type than can be sign or zero-extended to a basic operation
335 // go ahead and accept it now.
336 if (VT == MVT::i8 || VT == MVT::i16)
342 // Computes the Reg+Offset to get to an object.
343 bool ARMFastISel::ARMComputeRegOffset(const Value *Obj, unsigned &Reg,
345 // Some boilerplate from the X86 FastISel.
346 const User *U = NULL;
347 unsigned Opcode = Instruction::UserOp1;
348 if (const Instruction *I = dyn_cast<Instruction>(Obj)) {
349 // Don't walk into other basic blocks; it's possible we haven't
350 // visited them yet, so the instructions may not yet be assigned
351 // virtual registers.
352 if (FuncInfo.MBBMap[I->getParent()] != FuncInfo.MBB)
355 Opcode = I->getOpcode();
357 } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) {
358 Opcode = C->getOpcode();
362 if (const PointerType *Ty = dyn_cast<PointerType>(Obj->getType()))
363 if (Ty->getAddressSpace() > 255)
364 // Fast instruction selection doesn't support the special
370 //errs() << "Failing Opcode is: " << *Op1 << "\n";
372 case Instruction::Alloca: {
373 assert(false && "Alloca should have been handled earlier!");
378 if (const GlobalValue *GV = dyn_cast<GlobalValue>(Obj)) {
379 //errs() << "Failing GV is: " << GV << "\n";
384 // Try to get this in a register if nothing else has worked.
385 Reg = getRegForValue(Obj);
386 if (Reg == 0) return false;
388 // Since the offset may be too large for the load instruction
389 // get the reg+offset into a register.
390 // TODO: Verify the additions work, otherwise we'll need to add the
391 // offset instead of 0 to the instructions and do all sorts of operand
393 // TODO: Optimize this somewhat.
395 ARMCC::CondCodes Pred = ARMCC::AL;
396 unsigned PredReg = 0;
398 if (!AFI->isThumbFunction())
399 emitARMRegPlusImmediate(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
400 Reg, Reg, Offset, Pred, PredReg,
401 static_cast<const ARMBaseInstrInfo&>(TII));
403 assert(AFI->isThumb2Function());
404 emitT2RegPlusImmediate(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
405 Reg, Reg, Offset, Pred, PredReg,
406 static_cast<const ARMBaseInstrInfo&>(TII));
413 bool ARMFastISel::ARMLoadAlloca(const Instruction *I) {
414 Value *Op0 = I->getOperand(0);
416 // Verify it's an alloca.
417 if (const AllocaInst *AI = dyn_cast<AllocaInst>(Op0)) {
418 DenseMap<const AllocaInst*, int>::iterator SI =
419 FuncInfo.StaticAllocaMap.find(AI);
421 if (SI != FuncInfo.StaticAllocaMap.end()) {
422 TargetRegisterClass* RC = TLI.getRegClassFor(TLI.getPointerTy());
423 unsigned ResultReg = createResultReg(RC);
424 TII.loadRegFromStackSlot(*FuncInfo.MBB, *FuncInfo.InsertPt,
425 ResultReg, SI->second, RC,
426 TM.getRegisterInfo());
427 UpdateValueMap(I, ResultReg);
434 bool ARMFastISel::ARMEmitLoad(EVT VT, unsigned &ResultReg,
435 unsigned Reg, int Offset) {
437 assert(VT.isSimple() && "Non-simple types are invalid here!");
439 bool isThumb = AFI->isThumbFunction();
442 switch (VT.getSimpleVT().SimpleTy) {
444 assert(false && "Trying to emit for an unhandled type!");
447 Opc = isThumb ? ARM::tLDRH : ARM::LDRH;
451 Opc = isThumb ? ARM::tLDRB : ARM::LDRB;
455 Opc = isThumb ? ARM::tLDR : ARM::LDR;
459 ResultReg = createResultReg(TLI.getRegClassFor(VT));
461 // TODO: Fix the Addressing modes so that these can share some code.
462 // Since this is a Thumb1 load this will work in Thumb1 or 2 mode.
464 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
465 TII.get(Opc), ResultReg)
466 .addReg(Reg).addImm(Offset).addReg(0));
468 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
469 TII.get(Opc), ResultReg)
470 .addReg(Reg).addReg(0).addImm(Offset));
475 bool ARMFastISel::ARMMaterializeConstant(const ConstantInt *CI, unsigned &Reg) {
478 bool isThumb = AFI->isThumbFunction();
479 EVT VT = TLI.getValueType(CI->getType(), true);
481 switch (VT.getSimpleVT().SimpleTy) {
482 default: return false;
483 case MVT::i1: Signed = false; // FALLTHROUGH to handle as i8.
487 Opc = isThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm; break;
490 Reg = createResultReg(TLI.getRegClassFor(VT));
491 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Opc),
493 .addImm(Signed ? (uint64_t) CI->getSExtValue() :
494 CI->getZExtValue()));
499 bool ARMFastISel::ARMStoreAlloca(const Instruction *I, unsigned SrcReg) {
500 Value *Op1 = I->getOperand(1);
502 // Verify it's an alloca.
503 if (const AllocaInst *AI = dyn_cast<AllocaInst>(Op1)) {
504 DenseMap<const AllocaInst*, int>::iterator SI =
505 FuncInfo.StaticAllocaMap.find(AI);
507 if (SI != FuncInfo.StaticAllocaMap.end()) {
508 TargetRegisterClass* RC = TLI.getRegClassFor(TLI.getPointerTy());
509 assert(SrcReg != 0 && "Nothing to store!");
510 TII.storeRegToStackSlot(*FuncInfo.MBB, *FuncInfo.InsertPt,
511 SrcReg, true /*isKill*/, SI->second, RC,
512 TM.getRegisterInfo());
519 bool ARMFastISel::ARMEmitStore(EVT VT, unsigned SrcReg,
520 unsigned DstReg, int Offset) {
521 bool isThumb = AFI->isThumbFunction();
524 switch (VT.getSimpleVT().SimpleTy) {
525 default: return false;
527 case MVT::i8: StrOpc = isThumb ? ARM::tSTRB : ARM::STRB; break;
528 case MVT::i16: StrOpc = isThumb ? ARM::tSTRH : ARM::STRH; break;
529 case MVT::i32: StrOpc = isThumb ? ARM::tSTR : ARM::STR; break;
533 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
534 TII.get(StrOpc), SrcReg)
535 .addReg(DstReg).addImm(Offset).addReg(0));
537 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
538 TII.get(StrOpc), SrcReg)
539 .addReg(DstReg).addReg(0).addImm(Offset));
544 bool ARMFastISel::ARMSelectStore(const Instruction *I) {
545 Value *Op0 = I->getOperand(0);
548 // Yay type legalization
550 if (!isLoadTypeLegal(I->getOperand(0)->getType(), VT))
553 // First see if we're a constant that we want to store, we'll need to
554 // materialize that into a register.
555 // Handle 'null' like i32/i64 0.
556 if (isa<ConstantPointerNull>(Op0))
557 Op0 = Constant::getNullValue(TD.getIntPtrType(Op0->getContext()));
559 // If this is a store of a simple constant, materialize the constant into
560 // a register then emit the store into the location.
561 if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op0))
562 if (!ARMMaterializeConstant(CI, SrcReg))
565 // If Reg is still 0, try to get the value into a register.
567 SrcReg = getRegForValue(Op0);
571 // If we're an alloca we know we have a frame index and can emit the store
573 if (ARMStoreAlloca(I, SrcReg))
576 // Our register and offset with innocuous defaults.
580 // See if we can handle this as Reg + Offset
581 if (!ARMComputeRegOffset(I->getOperand(1), Reg, Offset))
584 if (!ARMEmitStore(VT, SrcReg, Reg, Offset /* 0 */)) return false;
590 bool ARMFastISel::ARMSelectLoad(const Instruction *I) {
591 // If we're an alloca we know we have a frame index and can emit the load
592 // directly in short order.
593 if (ARMLoadAlloca(I))
596 // Verify we have a legal type before going any further.
598 if (!isLoadTypeLegal(I->getType(), VT))
601 // Our register and offset with innocuous defaults.
605 // See if we can handle this as Reg + Offset
606 if (!ARMComputeRegOffset(I->getOperand(0), Reg, Offset))
610 if (!ARMEmitLoad(VT, ResultReg, Reg, Offset /* 0 */)) return false;
612 UpdateValueMap(I, ResultReg);
616 bool ARMFastISel::TargetSelectInstruction(const Instruction *I) {
617 // No Thumb-1 for now.
618 if (AFI->isThumbFunction() && !AFI->isThumb2Function()) return false;
620 switch (I->getOpcode()) {
621 case Instruction::Load:
622 return ARMSelectLoad(I);
623 case Instruction::Store:
624 return ARMSelectStore(I);
631 llvm::FastISel *ARM::createFastISel(FunctionLoweringInfo &funcInfo) {
632 if (EnableARMFastISel) return new ARMFastISel(funcInfo);