ARMFastISel.cpp revision 56d2b72884f98001cefdf8de61d6d7fc00d3df90
1//===-- 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" 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" 43using namespace llvm; 44 45static cl::opt<bool> 46EnableARMFastISel("arm-fast-isel", 47 cl::desc("Turn on experimental ARM fast-isel support"), 48 cl::init(false), cl::Hidden); 49 50namespace { 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; 57 const TargetMachine &TM; 58 const TargetInstrInfo &TII; 59 const TargetLowering &TLI; 60 const ARMFunctionInfo *AFI; 61 62 // Convenience variable to avoid checking all the time. 63 bool isThumb; 64 65 public: 66 explicit ARMFastISel(FunctionLoweringInfo &funcInfo) 67 : FastISel(funcInfo), 68 TM(funcInfo.MF->getTarget()), 69 TII(*TM.getInstrInfo()), 70 TLI(*TM.getTargetLowering()) { 71 Subtarget = &TM.getSubtarget<ARMSubtarget>(); 72 AFI = funcInfo.MF->getInfo<ARMFunctionInfo>(); 73 isThumb = AFI->isThumbFunction(); 74 } 75 76 // Code from FastISel.cpp. 77 virtual unsigned FastEmitInst_(unsigned MachineInstOpcode, 78 const TargetRegisterClass *RC); 79 virtual unsigned FastEmitInst_r(unsigned MachineInstOpcode, 80 const TargetRegisterClass *RC, 81 unsigned Op0, bool Op0IsKill); 82 virtual unsigned FastEmitInst_rr(unsigned MachineInstOpcode, 83 const TargetRegisterClass *RC, 84 unsigned Op0, bool Op0IsKill, 85 unsigned Op1, bool Op1IsKill); 86 virtual unsigned FastEmitInst_ri(unsigned MachineInstOpcode, 87 const TargetRegisterClass *RC, 88 unsigned Op0, bool Op0IsKill, 89 uint64_t Imm); 90 virtual unsigned FastEmitInst_rf(unsigned MachineInstOpcode, 91 const TargetRegisterClass *RC, 92 unsigned Op0, bool Op0IsKill, 93 const ConstantFP *FPImm); 94 virtual unsigned FastEmitInst_i(unsigned MachineInstOpcode, 95 const TargetRegisterClass *RC, 96 uint64_t Imm); 97 virtual unsigned FastEmitInst_rri(unsigned MachineInstOpcode, 98 const TargetRegisterClass *RC, 99 unsigned Op0, bool Op0IsKill, 100 unsigned Op1, bool Op1IsKill, 101 uint64_t Imm); 102 virtual unsigned FastEmitInst_extractsubreg(MVT RetVT, 103 unsigned Op0, bool Op0IsKill, 104 uint32_t Idx); 105 106 // Backend specific FastISel code. 107 virtual bool TargetSelectInstruction(const Instruction *I); 108 virtual unsigned TargetMaterializeConstant(const Constant *C); 109 110 #include "ARMGenFastISel.inc" 111 112 // Instruction selection routines. 113 virtual bool ARMSelectLoad(const Instruction *I); 114 virtual bool ARMSelectStore(const Instruction *I); 115 116 // Utility routines. 117 private: 118 bool isTypeLegal(const Type *Ty, EVT &VT); 119 bool isLoadTypeLegal(const Type *Ty, EVT &VT); 120 bool ARMEmitLoad(EVT VT, unsigned &ResultReg, unsigned Reg, int Offset); 121 bool ARMEmitStore(EVT VT, unsigned SrcReg, unsigned Reg, int Offset); 122 bool ARMLoadAlloca(const Instruction *I); 123 bool ARMStoreAlloca(const Instruction *I, unsigned SrcReg); 124 bool ARMComputeRegOffset(const Value *Obj, unsigned &Reg, int &Offset); 125 bool ARMMaterializeConstant(const ConstantInt *Val, unsigned &Reg); 126 127 bool DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR); 128 const MachineInstrBuilder &AddOptionalDefs(const MachineInstrBuilder &MIB); 129}; 130 131} // end anonymous namespace 132 133// #include "ARMGenCallingConv.inc" 134 135// DefinesOptionalPredicate - This is different from DefinesPredicate in that 136// we don't care about implicit defs here, just places we'll need to add a 137// default CCReg argument. Sets CPSR if we're setting CPSR instead of CCR. 138bool ARMFastISel::DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR) { 139 const TargetInstrDesc &TID = MI->getDesc(); 140 if (!TID.hasOptionalDef()) 141 return false; 142 143 // Look to see if our OptionalDef is defining CPSR or CCR. 144 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 145 const MachineOperand &MO = MI->getOperand(i); 146 if (!MO.isReg() || !MO.isDef()) continue; 147 if (MO.getReg() == ARM::CPSR) 148 *CPSR = true; 149 } 150 return true; 151} 152 153// If the machine is predicable go ahead and add the predicate operands, if 154// it needs default CC operands add those. 155const MachineInstrBuilder & 156ARMFastISel::AddOptionalDefs(const MachineInstrBuilder &MIB) { 157 MachineInstr *MI = &*MIB; 158 159 // Do we use a predicate? 160 if (TII.isPredicable(MI)) 161 AddDefaultPred(MIB); 162 163 // Do we optionally set a predicate? Preds is size > 0 iff the predicate 164 // defines CPSR. All other OptionalDefines in ARM are the CCR register. 165 bool CPSR = false; 166 if (DefinesOptionalPredicate(MI, &CPSR)) { 167 if (CPSR) 168 AddDefaultT1CC(MIB); 169 else 170 AddDefaultCC(MIB); 171 } 172 return MIB; 173} 174 175unsigned ARMFastISel::FastEmitInst_(unsigned MachineInstOpcode, 176 const TargetRegisterClass* RC) { 177 unsigned ResultReg = createResultReg(RC); 178 const TargetInstrDesc &II = TII.get(MachineInstOpcode); 179 180 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)); 181 return ResultReg; 182} 183 184unsigned ARMFastISel::FastEmitInst_r(unsigned MachineInstOpcode, 185 const TargetRegisterClass *RC, 186 unsigned Op0, bool Op0IsKill) { 187 unsigned ResultReg = createResultReg(RC); 188 const TargetInstrDesc &II = TII.get(MachineInstOpcode); 189 190 if (II.getNumDefs() >= 1) 191 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) 192 .addReg(Op0, Op0IsKill * RegState::Kill)); 193 else { 194 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) 195 .addReg(Op0, Op0IsKill * RegState::Kill)); 196 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 197 TII.get(TargetOpcode::COPY), ResultReg) 198 .addReg(II.ImplicitDefs[0])); 199 } 200 return ResultReg; 201} 202 203unsigned ARMFastISel::FastEmitInst_rr(unsigned MachineInstOpcode, 204 const TargetRegisterClass *RC, 205 unsigned Op0, bool Op0IsKill, 206 unsigned Op1, bool Op1IsKill) { 207 unsigned ResultReg = createResultReg(RC); 208 const TargetInstrDesc &II = TII.get(MachineInstOpcode); 209 210 if (II.getNumDefs() >= 1) 211 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) 212 .addReg(Op0, Op0IsKill * RegState::Kill) 213 .addReg(Op1, Op1IsKill * RegState::Kill)); 214 else { 215 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) 216 .addReg(Op0, Op0IsKill * RegState::Kill) 217 .addReg(Op1, Op1IsKill * RegState::Kill)); 218 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 219 TII.get(TargetOpcode::COPY), ResultReg) 220 .addReg(II.ImplicitDefs[0])); 221 } 222 return ResultReg; 223} 224 225unsigned ARMFastISel::FastEmitInst_ri(unsigned MachineInstOpcode, 226 const TargetRegisterClass *RC, 227 unsigned Op0, bool Op0IsKill, 228 uint64_t Imm) { 229 unsigned ResultReg = createResultReg(RC); 230 const TargetInstrDesc &II = TII.get(MachineInstOpcode); 231 232 if (II.getNumDefs() >= 1) 233 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) 234 .addReg(Op0, Op0IsKill * RegState::Kill) 235 .addImm(Imm)); 236 else { 237 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) 238 .addReg(Op0, Op0IsKill * RegState::Kill) 239 .addImm(Imm)); 240 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 241 TII.get(TargetOpcode::COPY), ResultReg) 242 .addReg(II.ImplicitDefs[0])); 243 } 244 return ResultReg; 245} 246 247unsigned ARMFastISel::FastEmitInst_rf(unsigned MachineInstOpcode, 248 const TargetRegisterClass *RC, 249 unsigned Op0, bool Op0IsKill, 250 const ConstantFP *FPImm) { 251 unsigned ResultReg = createResultReg(RC); 252 const TargetInstrDesc &II = TII.get(MachineInstOpcode); 253 254 if (II.getNumDefs() >= 1) 255 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) 256 .addReg(Op0, Op0IsKill * RegState::Kill) 257 .addFPImm(FPImm)); 258 else { 259 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) 260 .addReg(Op0, Op0IsKill * RegState::Kill) 261 .addFPImm(FPImm)); 262 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 263 TII.get(TargetOpcode::COPY), ResultReg) 264 .addReg(II.ImplicitDefs[0])); 265 } 266 return ResultReg; 267} 268 269unsigned ARMFastISel::FastEmitInst_rri(unsigned MachineInstOpcode, 270 const TargetRegisterClass *RC, 271 unsigned Op0, bool Op0IsKill, 272 unsigned Op1, bool Op1IsKill, 273 uint64_t Imm) { 274 unsigned ResultReg = createResultReg(RC); 275 const TargetInstrDesc &II = TII.get(MachineInstOpcode); 276 277 if (II.getNumDefs() >= 1) 278 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) 279 .addReg(Op0, Op0IsKill * RegState::Kill) 280 .addReg(Op1, Op1IsKill * RegState::Kill) 281 .addImm(Imm)); 282 else { 283 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) 284 .addReg(Op0, Op0IsKill * RegState::Kill) 285 .addReg(Op1, Op1IsKill * RegState::Kill) 286 .addImm(Imm)); 287 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 288 TII.get(TargetOpcode::COPY), ResultReg) 289 .addReg(II.ImplicitDefs[0])); 290 } 291 return ResultReg; 292} 293 294unsigned ARMFastISel::FastEmitInst_i(unsigned MachineInstOpcode, 295 const TargetRegisterClass *RC, 296 uint64_t Imm) { 297 unsigned ResultReg = createResultReg(RC); 298 const TargetInstrDesc &II = TII.get(MachineInstOpcode); 299 300 if (II.getNumDefs() >= 1) 301 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) 302 .addImm(Imm)); 303 else { 304 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) 305 .addImm(Imm)); 306 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 307 TII.get(TargetOpcode::COPY), ResultReg) 308 .addReg(II.ImplicitDefs[0])); 309 } 310 return ResultReg; 311} 312 313unsigned ARMFastISel::FastEmitInst_extractsubreg(MVT RetVT, 314 unsigned Op0, bool Op0IsKill, 315 uint32_t Idx) { 316 unsigned ResultReg = createResultReg(TLI.getRegClassFor(RetVT)); 317 assert(TargetRegisterInfo::isVirtualRegister(Op0) && 318 "Cannot yet extract from physregs"); 319 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, 320 DL, TII.get(TargetOpcode::COPY), ResultReg) 321 .addReg(Op0, getKillRegState(Op0IsKill), Idx)); 322 return ResultReg; 323} 324 325unsigned ARMFastISel::TargetMaterializeConstant(const Constant *C) { 326 EVT VT = TLI.getValueType(C->getType(), true); 327 328 // Only handle simple types. 329 if (!VT.isSimple()) return 0; 330 331 // TODO: This should be safe for fp because they're just bits from the 332 // Constant. 333 // TODO: Theoretically we could materialize fp constants with instructions 334 // from VFP3. 335 336 // MachineConstantPool wants an explicit alignment. 337 unsigned Align = TD.getPrefTypeAlignment(C->getType()); 338 if (Align == 0) { 339 // TODO: Figure out if this is correct. 340 Align = TD.getTypeAllocSize(C->getType()); 341 } 342 unsigned Idx = MCP.getConstantPoolIndex(C, Align); 343 344 unsigned DestReg = createResultReg(TLI.getRegClassFor(VT)); 345 // Different addressing modes between ARM/Thumb2 for constant pool loads. 346 if (isThumb) 347 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 348 TII.get(ARM::t2LDRpci)) 349 .addReg(DestReg).addConstantPoolIndex(Idx)); 350 else 351 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 352 TII.get(ARM::LDRcp)) 353 .addReg(DestReg).addConstantPoolIndex(Idx) 354 .addReg(0).addImm(0)); 355 356 return DestReg; 357} 358 359bool ARMFastISel::isTypeLegal(const Type *Ty, EVT &VT) { 360 VT = TLI.getValueType(Ty, true); 361 362 // Only handle simple types. 363 if (VT == MVT::Other || !VT.isSimple()) return false; 364 365 // Handle all legal types, i.e. a register that will directly hold this 366 // value. 367 return TLI.isTypeLegal(VT); 368} 369 370bool ARMFastISel::isLoadTypeLegal(const Type *Ty, EVT &VT) { 371 if (isTypeLegal(Ty, VT)) return true; 372 373 // If this is a type than can be sign or zero-extended to a basic operation 374 // go ahead and accept it now. 375 if (VT == MVT::i8 || VT == MVT::i16) 376 return true; 377 378 return false; 379} 380 381// Computes the Reg+Offset to get to an object. 382bool ARMFastISel::ARMComputeRegOffset(const Value *Obj, unsigned &Reg, 383 int &Offset) { 384 // Some boilerplate from the X86 FastISel. 385 const User *U = NULL; 386 unsigned Opcode = Instruction::UserOp1; 387 if (const Instruction *I = dyn_cast<Instruction>(Obj)) { 388 // Don't walk into other basic blocks; it's possible we haven't 389 // visited them yet, so the instructions may not yet be assigned 390 // virtual registers. 391 if (FuncInfo.MBBMap[I->getParent()] != FuncInfo.MBB) 392 return false; 393 394 Opcode = I->getOpcode(); 395 U = I; 396 } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) { 397 Opcode = C->getOpcode(); 398 U = C; 399 } 400 401 if (const PointerType *Ty = dyn_cast<PointerType>(Obj->getType())) 402 if (Ty->getAddressSpace() > 255) 403 // Fast instruction selection doesn't support the special 404 // address spaces. 405 return false; 406 407 switch (Opcode) { 408 default: 409 //errs() << "Failing Opcode is: " << *Op1 << "\n"; 410 break; 411 case Instruction::Alloca: { 412 assert(false && "Alloca should have been handled earlier!"); 413 return false; 414 } 415 } 416 417 if (const GlobalValue *GV = dyn_cast<GlobalValue>(Obj)) { 418 //errs() << "Failing GV is: " << GV << "\n"; 419 (void)GV; 420 return false; 421 } 422 423 // Try to get this in a register if nothing else has worked. 424 Reg = getRegForValue(Obj); 425 if (Reg == 0) return false; 426 427 // Since the offset may be too large for the load instruction 428 // get the reg+offset into a register. 429 // TODO: Verify the additions work, otherwise we'll need to add the 430 // offset instead of 0 to the instructions and do all sorts of operand 431 // munging. 432 // TODO: Optimize this somewhat. 433 if (Offset != 0) { 434 ARMCC::CondCodes Pred = ARMCC::AL; 435 unsigned PredReg = 0; 436 437 if (!isThumb) 438 emitARMRegPlusImmediate(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 439 Reg, Reg, Offset, Pred, PredReg, 440 static_cast<const ARMBaseInstrInfo&>(TII)); 441 else { 442 assert(AFI->isThumb2Function()); 443 emitT2RegPlusImmediate(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 444 Reg, Reg, Offset, Pred, PredReg, 445 static_cast<const ARMBaseInstrInfo&>(TII)); 446 } 447 } 448 449 return true; 450} 451 452bool ARMFastISel::ARMLoadAlloca(const Instruction *I) { 453 Value *Op0 = I->getOperand(0); 454 455 // Verify it's an alloca. 456 if (const AllocaInst *AI = dyn_cast<AllocaInst>(Op0)) { 457 DenseMap<const AllocaInst*, int>::iterator SI = 458 FuncInfo.StaticAllocaMap.find(AI); 459 460 if (SI != FuncInfo.StaticAllocaMap.end()) { 461 TargetRegisterClass* RC = TLI.getRegClassFor(TLI.getPointerTy()); 462 unsigned ResultReg = createResultReg(RC); 463 TII.loadRegFromStackSlot(*FuncInfo.MBB, *FuncInfo.InsertPt, 464 ResultReg, SI->second, RC, 465 TM.getRegisterInfo()); 466 UpdateValueMap(I, ResultReg); 467 return true; 468 } 469 } 470 return false; 471} 472 473bool ARMFastISel::ARMEmitLoad(EVT VT, unsigned &ResultReg, 474 unsigned Reg, int Offset) { 475 476 assert(VT.isSimple() && "Non-simple types are invalid here!"); 477 unsigned Opc; 478 479 switch (VT.getSimpleVT().SimpleTy) { 480 default: 481 assert(false && "Trying to emit for an unhandled type!"); 482 return false; 483 case MVT::i16: 484 Opc = isThumb ? ARM::tLDRH : ARM::LDRH; 485 VT = MVT::i32; 486 break; 487 case MVT::i8: 488 Opc = isThumb ? ARM::tLDRB : ARM::LDRB; 489 VT = MVT::i32; 490 break; 491 case MVT::i32: 492 Opc = isThumb ? ARM::tLDR : ARM::LDR; 493 break; 494 } 495 496 ResultReg = createResultReg(TLI.getRegClassFor(VT)); 497 498 // TODO: Fix the Addressing modes so that these can share some code. 499 // Since this is a Thumb1 load this will work in Thumb1 or 2 mode. 500 if (isThumb) 501 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 502 TII.get(Opc), ResultReg) 503 .addReg(Reg).addImm(Offset).addReg(0)); 504 else 505 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 506 TII.get(Opc), ResultReg) 507 .addReg(Reg).addReg(0).addImm(Offset)); 508 509 return true; 510} 511 512bool ARMFastISel::ARMStoreAlloca(const Instruction *I, unsigned SrcReg) { 513 Value *Op1 = I->getOperand(1); 514 515 // Verify it's an alloca. 516 if (const AllocaInst *AI = dyn_cast<AllocaInst>(Op1)) { 517 DenseMap<const AllocaInst*, int>::iterator SI = 518 FuncInfo.StaticAllocaMap.find(AI); 519 520 if (SI != FuncInfo.StaticAllocaMap.end()) { 521 TargetRegisterClass* RC = TLI.getRegClassFor(TLI.getPointerTy()); 522 assert(SrcReg != 0 && "Nothing to store!"); 523 TII.storeRegToStackSlot(*FuncInfo.MBB, *FuncInfo.InsertPt, 524 SrcReg, true /*isKill*/, SI->second, RC, 525 TM.getRegisterInfo()); 526 return true; 527 } 528 } 529 return false; 530} 531 532bool ARMFastISel::ARMEmitStore(EVT VT, unsigned SrcReg, 533 unsigned DstReg, int Offset) { 534 unsigned StrOpc; 535 switch (VT.getSimpleVT().SimpleTy) { 536 default: return false; 537 case MVT::i1: 538 case MVT::i8: StrOpc = isThumb ? ARM::tSTRB : ARM::STRB; break; 539 case MVT::i16: StrOpc = isThumb ? ARM::tSTRH : ARM::STRH; break; 540 case MVT::i32: StrOpc = isThumb ? ARM::tSTR : ARM::STR; break; 541 case MVT::f32: 542 if (!Subtarget->hasVFP2()) return false; 543 StrOpc = ARM::VSTRS; 544 break; 545 case MVT::f64: 546 if (!Subtarget->hasVFP2()) return false; 547 StrOpc = ARM::VSTRD; 548 break; 549 } 550 551 if (isThumb) 552 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 553 TII.get(StrOpc), SrcReg) 554 .addReg(DstReg).addImm(Offset).addReg(0)); 555 else 556 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 557 TII.get(StrOpc), SrcReg) 558 .addReg(DstReg).addReg(0).addImm(Offset)); 559 560 return true; 561} 562 563bool ARMFastISel::ARMSelectStore(const Instruction *I) { 564 Value *Op0 = I->getOperand(0); 565 unsigned SrcReg = 0; 566 567 // Yay type legalization 568 EVT VT; 569 if (!isLoadTypeLegal(I->getOperand(0)->getType(), VT)) 570 return false; 571 572 // Get the value to be stored into a register. 573 SrcReg = getRegForValue(Op0); 574 if (SrcReg == 0) 575 return false; 576 577 // If we're an alloca we know we have a frame index and can emit the store 578 // quickly. 579 if (ARMStoreAlloca(I, SrcReg)) 580 return true; 581 582 // Our register and offset with innocuous defaults. 583 unsigned Reg = 0; 584 int Offset = 0; 585 586 // See if we can handle this as Reg + Offset 587 if (!ARMComputeRegOffset(I->getOperand(1), Reg, Offset)) 588 return false; 589 590 if (!ARMEmitStore(VT, SrcReg, Reg, Offset /* 0 */)) return false; 591 592 return false; 593 594} 595 596bool ARMFastISel::ARMSelectLoad(const Instruction *I) { 597 // If we're an alloca we know we have a frame index and can emit the load 598 // directly in short order. 599 if (ARMLoadAlloca(I)) 600 return true; 601 602 // Verify we have a legal type before going any further. 603 EVT VT; 604 if (!isLoadTypeLegal(I->getType(), VT)) 605 return false; 606 607 // Our register and offset with innocuous defaults. 608 unsigned Reg = 0; 609 int Offset = 0; 610 611 // See if we can handle this as Reg + Offset 612 if (!ARMComputeRegOffset(I->getOperand(0), Reg, Offset)) 613 return false; 614 615 unsigned ResultReg; 616 if (!ARMEmitLoad(VT, ResultReg, Reg, Offset /* 0 */)) return false; 617 618 UpdateValueMap(I, ResultReg); 619 return true; 620} 621 622// TODO: SoftFP support. 623bool ARMFastISel::TargetSelectInstruction(const Instruction *I) { 624 // No Thumb-1 for now. 625 if (isThumb && !AFI->isThumb2Function()) return false; 626 627 switch (I->getOpcode()) { 628 case Instruction::Load: 629 return ARMSelectLoad(I); 630 case Instruction::Store: 631 return ARMSelectStore(I); 632 default: break; 633 } 634 return false; 635} 636 637namespace llvm { 638 llvm::FastISel *ARM::createFastISel(FunctionLoweringInfo &funcInfo) { 639 if (EnableARMFastISel) return new ARMFastISel(funcInfo); 640 return 0; 641 } 642} 643