ARMFastISel.cpp revision 61c3f9ae0624281a7feb0027b8bb87874fadbcd4
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 public: 63 explicit ARMFastISel(FunctionLoweringInfo &funcInfo) 64 : FastISel(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>(); 70 } 71 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, 85 uint64_t Imm); 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, 92 uint64_t Imm); 93 virtual unsigned FastEmitInst_rri(unsigned MachineInstOpcode, 94 const TargetRegisterClass *RC, 95 unsigned Op0, bool Op0IsKill, 96 unsigned Op1, bool Op1IsKill, 97 uint64_t Imm); 98 virtual unsigned FastEmitInst_extractsubreg(MVT RetVT, 99 unsigned Op0, bool Op0IsKill, 100 uint32_t Idx); 101 102 // Backend specific FastISel code. 103 virtual bool TargetSelectInstruction(const Instruction *I); 104 105 #include "ARMGenFastISel.inc" 106 107 // Instruction selection routines. 108 virtual bool ARMSelectLoad(const Instruction *I); 109 110 // Utility routines. 111 private: 112 bool isTypeLegal(const Type *Ty, EVT &VT); 113 bool ARMEmitLoad(EVT VT, unsigned &ResultReg, unsigned Reg, int Offset); 114 bool ARMLoadAlloca(const Instruction *I); 115 bool ARMComputeRegOffset(const Value *Obj, unsigned &Reg, int &Offset); 116 117 bool DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR); 118 const MachineInstrBuilder &AddOptionalDefs(const MachineInstrBuilder &MIB); 119}; 120 121} // end anonymous namespace 122 123// #include "ARMGenCallingConv.inc" 124 125// DefinesOptionalPredicate - This is different from DefinesPredicate in that 126// we don't care about implicit defs here, just places we'll need to add a 127// default CCReg argument. Sets CPSR if we're setting CPSR instead of CCR. 128bool ARMFastISel::DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR) { 129 const TargetInstrDesc &TID = MI->getDesc(); 130 if (!TID.hasOptionalDef()) 131 return false; 132 133 // Look to see if our OptionalDef is defining CPSR or CCR. 134 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 135 const MachineOperand &MO = MI->getOperand(i); 136 if (!MO.isReg() || !MO.isDef()) continue; 137 if (MO.getReg() == ARM::CPSR) 138 *CPSR = true; 139 } 140 return true; 141} 142 143// If the machine is predicable go ahead and add the predicate operands, if 144// it needs default CC operands add those. 145const MachineInstrBuilder & 146ARMFastISel::AddOptionalDefs(const MachineInstrBuilder &MIB) { 147 MachineInstr *MI = &*MIB; 148 149 // Do we use a predicate? 150 if (TII.isPredicable(MI)) 151 AddDefaultPred(MIB); 152 153 // Do we optionally set a predicate? Preds is size > 0 iff the predicate 154 // defines CPSR. All other OptionalDefines in ARM are the CCR register. 155 bool CPSR = false; 156 if (DefinesOptionalPredicate(MI, &CPSR)) { 157 if (CPSR) 158 AddDefaultT1CC(MIB); 159 else 160 AddDefaultCC(MIB); 161 } 162 return MIB; 163} 164 165unsigned ARMFastISel::FastEmitInst_(unsigned MachineInstOpcode, 166 const TargetRegisterClass* RC) { 167 unsigned ResultReg = createResultReg(RC); 168 const TargetInstrDesc &II = TII.get(MachineInstOpcode); 169 170 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)); 171 return ResultReg; 172} 173 174unsigned ARMFastISel::FastEmitInst_r(unsigned MachineInstOpcode, 175 const TargetRegisterClass *RC, 176 unsigned Op0, bool Op0IsKill) { 177 unsigned ResultReg = createResultReg(RC); 178 const TargetInstrDesc &II = TII.get(MachineInstOpcode); 179 180 if (II.getNumDefs() >= 1) 181 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) 182 .addReg(Op0, Op0IsKill * RegState::Kill)); 183 else { 184 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) 185 .addReg(Op0, Op0IsKill * RegState::Kill)); 186 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 187 TII.get(TargetOpcode::COPY), ResultReg) 188 .addReg(II.ImplicitDefs[0])); 189 } 190 return ResultReg; 191} 192 193unsigned ARMFastISel::FastEmitInst_rr(unsigned MachineInstOpcode, 194 const TargetRegisterClass *RC, 195 unsigned Op0, bool Op0IsKill, 196 unsigned Op1, bool Op1IsKill) { 197 unsigned ResultReg = createResultReg(RC); 198 const TargetInstrDesc &II = TII.get(MachineInstOpcode); 199 200 if (II.getNumDefs() >= 1) 201 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) 202 .addReg(Op0, Op0IsKill * RegState::Kill) 203 .addReg(Op1, Op1IsKill * RegState::Kill)); 204 else { 205 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) 206 .addReg(Op0, Op0IsKill * RegState::Kill) 207 .addReg(Op1, Op1IsKill * RegState::Kill)); 208 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 209 TII.get(TargetOpcode::COPY), ResultReg) 210 .addReg(II.ImplicitDefs[0])); 211 } 212 return ResultReg; 213} 214 215unsigned ARMFastISel::FastEmitInst_ri(unsigned MachineInstOpcode, 216 const TargetRegisterClass *RC, 217 unsigned Op0, bool Op0IsKill, 218 uint64_t Imm) { 219 unsigned ResultReg = createResultReg(RC); 220 const TargetInstrDesc &II = TII.get(MachineInstOpcode); 221 222 if (II.getNumDefs() >= 1) 223 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) 224 .addReg(Op0, Op0IsKill * RegState::Kill) 225 .addImm(Imm)); 226 else { 227 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) 228 .addReg(Op0, Op0IsKill * RegState::Kill) 229 .addImm(Imm)); 230 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 231 TII.get(TargetOpcode::COPY), ResultReg) 232 .addReg(II.ImplicitDefs[0])); 233 } 234 return ResultReg; 235} 236 237unsigned ARMFastISel::FastEmitInst_rf(unsigned MachineInstOpcode, 238 const TargetRegisterClass *RC, 239 unsigned Op0, bool Op0IsKill, 240 const ConstantFP *FPImm) { 241 unsigned ResultReg = createResultReg(RC); 242 const TargetInstrDesc &II = TII.get(MachineInstOpcode); 243 244 if (II.getNumDefs() >= 1) 245 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) 246 .addReg(Op0, Op0IsKill * RegState::Kill) 247 .addFPImm(FPImm)); 248 else { 249 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) 250 .addReg(Op0, Op0IsKill * RegState::Kill) 251 .addFPImm(FPImm)); 252 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 253 TII.get(TargetOpcode::COPY), ResultReg) 254 .addReg(II.ImplicitDefs[0])); 255 } 256 return ResultReg; 257} 258 259unsigned ARMFastISel::FastEmitInst_rri(unsigned MachineInstOpcode, 260 const TargetRegisterClass *RC, 261 unsigned Op0, bool Op0IsKill, 262 unsigned Op1, bool Op1IsKill, 263 uint64_t Imm) { 264 unsigned ResultReg = createResultReg(RC); 265 const TargetInstrDesc &II = TII.get(MachineInstOpcode); 266 267 if (II.getNumDefs() >= 1) 268 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) 269 .addReg(Op0, Op0IsKill * RegState::Kill) 270 .addReg(Op1, Op1IsKill * RegState::Kill) 271 .addImm(Imm)); 272 else { 273 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) 274 .addReg(Op0, Op0IsKill * RegState::Kill) 275 .addReg(Op1, Op1IsKill * RegState::Kill) 276 .addImm(Imm)); 277 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 278 TII.get(TargetOpcode::COPY), ResultReg) 279 .addReg(II.ImplicitDefs[0])); 280 } 281 return ResultReg; 282} 283 284unsigned ARMFastISel::FastEmitInst_i(unsigned MachineInstOpcode, 285 const TargetRegisterClass *RC, 286 uint64_t Imm) { 287 unsigned ResultReg = createResultReg(RC); 288 const TargetInstrDesc &II = TII.get(MachineInstOpcode); 289 290 if (II.getNumDefs() >= 1) 291 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) 292 .addImm(Imm)); 293 else { 294 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) 295 .addImm(Imm)); 296 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 297 TII.get(TargetOpcode::COPY), ResultReg) 298 .addReg(II.ImplicitDefs[0])); 299 } 300 return ResultReg; 301} 302 303unsigned ARMFastISel::FastEmitInst_extractsubreg(MVT RetVT, 304 unsigned Op0, bool Op0IsKill, 305 uint32_t Idx) { 306 unsigned ResultReg = createResultReg(TLI.getRegClassFor(RetVT)); 307 assert(TargetRegisterInfo::isVirtualRegister(Op0) && 308 "Cannot yet extract from physregs"); 309 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, 310 DL, TII.get(TargetOpcode::COPY), ResultReg) 311 .addReg(Op0, getKillRegState(Op0IsKill), Idx)); 312 return ResultReg; 313} 314 315bool ARMFastISel::isTypeLegal(const Type *Ty, EVT &VT) { 316 VT = TLI.getValueType(Ty, true); 317 318 // Only handle simple types. 319 if (VT == MVT::Other || !VT.isSimple()) return false; 320 321 // For now, only handle 32-bit types. 322 return VT == MVT::i32; 323} 324 325// Computes the Reg+Offset to get to an object. 326bool ARMFastISel::ARMComputeRegOffset(const Value *Obj, unsigned &Reg, 327 int &Offset) { 328 // Some boilerplate from the X86 FastISel. 329 const User *U = NULL; 330 unsigned Opcode = Instruction::UserOp1; 331 if (const Instruction *I = dyn_cast<Instruction>(Obj)) { 332 // Don't walk into other basic blocks; it's possible we haven't 333 // visited them yet, so the instructions may not yet be assigned 334 // virtual registers. 335 if (FuncInfo.MBBMap[I->getParent()] != FuncInfo.MBB) 336 return false; 337 338 Opcode = I->getOpcode(); 339 U = I; 340 } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) { 341 Opcode = C->getOpcode(); 342 U = C; 343 } 344 345 if (const PointerType *Ty = dyn_cast<PointerType>(Obj->getType())) 346 if (Ty->getAddressSpace() > 255) 347 // Fast instruction selection doesn't support the special 348 // address spaces. 349 return false; 350 351 switch (Opcode) { 352 default: 353 //errs() << "Failing Opcode is: " << *Op1 << "\n"; 354 break; 355 case Instruction::Alloca: { 356 assert(false && "Alloca should have been handled earlier!"); 357 return false; 358 } 359 } 360 361 if (const GlobalValue *GV = dyn_cast<GlobalValue>(Obj)) { 362 //errs() << "Failing GV is: " << GV << "\n"; 363 (void)GV; 364 return false; 365 } 366 367 // Try to get this in a register if nothing else has worked. 368 Reg = getRegForValue(Obj); 369 return Reg != 0; 370} 371 372bool ARMFastISel::ARMLoadAlloca(const Instruction *I) { 373 Value *Op0 = I->getOperand(0); 374 375 // Verify it's an alloca. 376 if (const AllocaInst *AI = dyn_cast<AllocaInst>(Op0)) { 377 DenseMap<const AllocaInst*, int>::iterator SI = 378 FuncInfo.StaticAllocaMap.find(AI); 379 380 if (SI != FuncInfo.StaticAllocaMap.end()) { 381 TargetRegisterClass* RC = TLI.getRegClassFor(TLI.getPointerTy()); 382 unsigned ResultReg = createResultReg(RC); 383 TII.loadRegFromStackSlot(*FuncInfo.MBB, *FuncInfo.InsertPt, 384 ResultReg, SI->second, RC, 385 TM.getRegisterInfo()); 386 UpdateValueMap(I, ResultReg); 387 return true; 388 } 389 } 390 391 return false; 392} 393 394bool ARMFastISel::ARMEmitLoad(EVT VT, unsigned &ResultReg, 395 unsigned Reg, int Offset) { 396 397 assert(VT.isSimple() && "Non-simple types are invalid here!"); 398 switch (VT.getSimpleVT().SimpleTy) { 399 default: return false; 400 case MVT::i32: { 401 ResultReg = createResultReg(ARM::GPRRegisterClass); 402 // TODO: Fix the Addressing modes so that these can share some code. 403 // Since this is a Thumb1 load this will work in Thumb1 or 2 mode. 404 if (AFI->isThumbFunction()) 405 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 406 TII.get(ARM::tLDR), ResultReg) 407 .addReg(Reg).addImm(Offset).addReg(0)); 408 else 409 AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 410 TII.get(ARM::LDR), ResultReg) 411 .addReg(Reg).addReg(0).addImm(Offset)); 412 return true; 413 } 414 } 415} 416 417bool ARMFastISel::ARMSelectLoad(const Instruction *I) { 418 // If we're an alloca we know we have a frame index and can emit the load 419 // directly in short order. 420 if (ARMLoadAlloca(I)) 421 return true; 422 423 // Verify we have a legal type before going any further. 424 EVT VT; 425 if (!isTypeLegal(I->getType(), VT)) 426 return false; 427 428 // Our register and offset with innocuous defaults. 429 unsigned Reg = 0; 430 int Offset = 0; 431 432 // See if we can handle this as Reg + Offset 433 if (!ARMComputeRegOffset(I->getOperand(0), Reg, Offset)) 434 return false; 435 436 // Since the offset may be too large for the load instruction 437 // get the reg+offset into a register. 438 // TODO: Optimize this somewhat. 439 ARMCC::CondCodes Pred = ARMCC::AL; 440 unsigned PredReg = 0; 441 442 if (!AFI->isThumbFunction()) 443 emitARMRegPlusImmediate(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 444 Reg, Reg, Offset, Pred, PredReg, 445 static_cast<const ARMBaseInstrInfo&>(TII)); 446 else { 447 assert(AFI->isThumb2Function()); 448 emitT2RegPlusImmediate(*FuncInfo.MBB, FuncInfo.InsertPt, DL, 449 Reg, Reg, Offset, Pred, PredReg, 450 static_cast<const ARMBaseInstrInfo&>(TII)); 451 } 452 453 unsigned ResultReg; 454 // TODO: Verify the additions above work, otherwise we'll need to add the 455 // offset instead of 0 and do all sorts of operand munging. 456 if (!ARMEmitLoad(VT, ResultReg, Reg, 0)) return false; 457 458 UpdateValueMap(I, ResultReg); 459 return true; 460} 461 462bool ARMFastISel::TargetSelectInstruction(const Instruction *I) { 463 // No Thumb-1 for now. 464 if (AFI->isThumbFunction() && !AFI->isThumb2Function()) return false; 465 466 switch (I->getOpcode()) { 467 case Instruction::Load: 468 return ARMSelectLoad(I); 469 default: break; 470 } 471 return false; 472} 473 474namespace llvm { 475 llvm::FastISel *ARM::createFastISel(FunctionLoweringInfo &funcInfo) { 476 if (EnableARMFastISel) return new ARMFastISel(funcInfo); 477 return 0; 478 } 479} 480