ARMISelDAGToDAG.cpp revision a8e2989ece6dc46df59b0768184028257f913843
1//===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file was developed by Chris Lattner and is distributed under 6// the University of Illinois Open Source License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines an instruction selector for the ARM target. 11// 12//===----------------------------------------------------------------------===// 13 14#include "ARM.h" 15#include "ARMISelLowering.h" 16#include "ARMTargetMachine.h" 17#include "ARMAddressingModes.h" 18#include "llvm/CallingConv.h" 19#include "llvm/Constants.h" 20#include "llvm/DerivedTypes.h" 21#include "llvm/Function.h" 22#include "llvm/Intrinsics.h" 23#include "llvm/CodeGen/MachineFrameInfo.h" 24#include "llvm/CodeGen/MachineFunction.h" 25#include "llvm/CodeGen/MachineInstrBuilder.h" 26#include "llvm/CodeGen/SelectionDAG.h" 27#include "llvm/CodeGen/SelectionDAGISel.h" 28#include "llvm/CodeGen/SSARegMap.h" 29#include "llvm/Target/TargetLowering.h" 30#include "llvm/Support/Debug.h" 31#include <iostream> 32using namespace llvm; 33 34//===--------------------------------------------------------------------===// 35/// ARMDAGToDAGISel - ARM specific code to select ARM machine 36/// instructions for SelectionDAG operations. 37/// 38namespace { 39class ARMDAGToDAGISel : public SelectionDAGISel { 40 ARMTargetLowering Lowering; 41 42 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can 43 /// make the right decision when generating code for different targets. 44 const ARMSubtarget *Subtarget; 45 46public: 47 ARMDAGToDAGISel(ARMTargetMachine &TM) 48 : SelectionDAGISel(Lowering), Lowering(TM), 49 Subtarget(&TM.getSubtarget<ARMSubtarget>()) { 50 } 51 52 virtual const char *getPassName() const { 53 return "ARM Instruction Selection"; 54 } 55 56 SDNode *Select(SDOperand Op); 57 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG); 58 bool SelectAddrMode2(SDOperand Op, SDOperand N, SDOperand &Base, 59 SDOperand &Offset, SDOperand &Opc); 60 bool SelectAddrMode2Offset(SDOperand Op, SDOperand N, 61 SDOperand &Offset, SDOperand &Opc); 62 bool SelectAddrMode3(SDOperand Op, SDOperand N, SDOperand &Base, 63 SDOperand &Offset, SDOperand &Opc); 64 bool SelectAddrMode3Offset(SDOperand Op, SDOperand N, 65 SDOperand &Offset, SDOperand &Opc); 66 bool SelectAddrMode5(SDOperand Op, SDOperand N, SDOperand &Base, 67 SDOperand &Offset); 68 69 bool SelectAddrModePC(SDOperand Op, SDOperand N, SDOperand &Offset, 70 SDOperand &Label); 71 72 bool SelectThumbAddrModeRR(SDOperand Op, SDOperand N, SDOperand &Base, 73 SDOperand &Offset); 74 bool SelectThumbAddrModeRI5_1(SDOperand Op, SDOperand N, SDOperand &Base, 75 SDOperand &Offset); 76 bool SelectThumbAddrModeRI5_2(SDOperand Op, SDOperand N, SDOperand &Base, 77 SDOperand &Offset); 78 bool SelectThumbAddrModeRI5_4(SDOperand Op, SDOperand N, SDOperand &Base, 79 SDOperand &Offset); 80 bool SelectThumbAddrModeSP(SDOperand Op, SDOperand N, SDOperand &Base, 81 SDOperand &Offset); 82 83 bool SelectShifterOperandReg(SDOperand Op, SDOperand N, SDOperand &A, 84 SDOperand &B, SDOperand &C); 85 86 // Include the pieces autogenerated from the target description. 87#include "ARMGenDAGISel.inc" 88}; 89} 90 91void ARMDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) { 92 DEBUG(BB->dump()); 93 94 DAG.setRoot(SelectRoot(DAG.getRoot())); 95 DAG.RemoveDeadNodes(); 96 97 ScheduleAndEmitDAG(DAG); 98} 99 100bool ARMDAGToDAGISel::SelectAddrMode2(SDOperand Op, SDOperand N, 101 SDOperand &Base, SDOperand &Offset, 102 SDOperand &Opc) { 103 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) { 104 Base = N; 105 if (N.getOpcode() == ISD::FrameIndex) { 106 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 107 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 108 } else if (N.getOpcode() == ARMISD::Wrapper) { 109 Base = N.getOperand(0); 110 } 111 Offset = CurDAG->getRegister(0, MVT::i32); 112 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, 113 ARM_AM::no_shift), 114 MVT::i32); 115 return true; 116 } 117 118 // Match simple R +/- imm12 operands. 119 if (N.getOpcode() == ISD::ADD) 120 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 121 int RHSC = (int)RHS->getValue(); 122 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits. 123 Base = N.getOperand(0); 124 Offset = CurDAG->getRegister(0, MVT::i32); 125 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, RHSC, 126 ARM_AM::no_shift), 127 MVT::i32); 128 return true; 129 } else if (RHSC < 0 && RHSC > -0x1000) { 130 Base = N.getOperand(0); 131 Offset = CurDAG->getRegister(0, MVT::i32); 132 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::sub, -RHSC, 133 ARM_AM::no_shift), 134 MVT::i32); 135 return true; 136 } 137 } 138 139 // Otherwise this is R +/- [possibly shifted] R 140 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::ADD ? ARM_AM::add:ARM_AM::sub; 141 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1)); 142 unsigned ShAmt = 0; 143 144 Base = N.getOperand(0); 145 Offset = N.getOperand(1); 146 147 if (ShOpcVal != ARM_AM::no_shift) { 148 // Check to see if the RHS of the shift is a constant, if not, we can't fold 149 // it. 150 if (ConstantSDNode *Sh = 151 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) { 152 ShAmt = Sh->getValue(); 153 Offset = N.getOperand(1).getOperand(0); 154 } else { 155 ShOpcVal = ARM_AM::no_shift; 156 } 157 } 158 159 // Try matching (R shl C) + (R). 160 if (N.getOpcode() == ISD::ADD && ShOpcVal == ARM_AM::no_shift) { 161 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0)); 162 if (ShOpcVal != ARM_AM::no_shift) { 163 // Check to see if the RHS of the shift is a constant, if not, we can't 164 // fold it. 165 if (ConstantSDNode *Sh = 166 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) { 167 ShAmt = Sh->getValue(); 168 Offset = N.getOperand(0).getOperand(0); 169 Base = N.getOperand(1); 170 } else { 171 ShOpcVal = ARM_AM::no_shift; 172 } 173 } 174 } 175 176 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 177 MVT::i32); 178 return true; 179} 180 181bool ARMDAGToDAGISel::SelectAddrMode2Offset(SDOperand Op, SDOperand N, 182 SDOperand &Offset, SDOperand &Opc) { 183 unsigned Opcode = Op.getOpcode(); 184 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 185 ? cast<LoadSDNode>(Op)->getAddressingMode() 186 : cast<StoreSDNode>(Op)->getAddressingMode(); 187 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 188 ? ARM_AM::add : ARM_AM::sub; 189 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 190 int Val = (int)C->getValue(); 191 if (Val >= 0 && Val < 0x1000) { // 12 bits. 192 Offset = CurDAG->getRegister(0, MVT::i32); 193 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val, 194 ARM_AM::no_shift), 195 MVT::i32); 196 return true; 197 } 198 } 199 200 Offset = N; 201 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 202 unsigned ShAmt = 0; 203 if (ShOpcVal != ARM_AM::no_shift) { 204 // Check to see if the RHS of the shift is a constant, if not, we can't fold 205 // it. 206 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 207 ShAmt = Sh->getValue(); 208 Offset = N.getOperand(0); 209 } else { 210 ShOpcVal = ARM_AM::no_shift; 211 } 212 } 213 214 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 215 MVT::i32); 216 return true; 217} 218 219 220bool ARMDAGToDAGISel::SelectAddrMode3(SDOperand Op, SDOperand N, 221 SDOperand &Base, SDOperand &Offset, 222 SDOperand &Opc) { 223 if (N.getOpcode() == ISD::SUB) { 224 // X - C is canonicalize to X + -C, no need to handle it here. 225 Base = N.getOperand(0); 226 Offset = N.getOperand(1); 227 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32); 228 return true; 229 } 230 231 if (N.getOpcode() != ISD::ADD) { 232 Base = N; 233 if (N.getOpcode() == ISD::FrameIndex) { 234 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 235 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 236 } 237 Offset = CurDAG->getRegister(0, MVT::i32); 238 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32); 239 return true; 240 } 241 242 // If the RHS is +/- imm8, fold into addr mode. 243 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 244 int RHSC = (int)RHS->getValue(); 245 if (RHSC >= 0 && RHSC < 256) { 246 Base = N.getOperand(0); 247 Offset = CurDAG->getRegister(0, MVT::i32); 248 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, RHSC), 249 MVT::i32); 250 return true; 251 } else if (RHSC < 0 && RHSC > -256) { // note -256 itself isn't allowed. 252 Base = N.getOperand(0); 253 Offset = CurDAG->getRegister(0, MVT::i32); 254 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, -RHSC), 255 MVT::i32); 256 return true; 257 } 258 } 259 260 Base = N.getOperand(0); 261 Offset = N.getOperand(1); 262 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32); 263 return true; 264} 265 266bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDOperand Op, SDOperand N, 267 SDOperand &Offset, SDOperand &Opc) { 268 unsigned Opcode = Op.getOpcode(); 269 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 270 ? cast<LoadSDNode>(Op)->getAddressingMode() 271 : cast<StoreSDNode>(Op)->getAddressingMode(); 272 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 273 ? ARM_AM::add : ARM_AM::sub; 274 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 275 int Val = (int)C->getValue(); 276 if (Val >= 0 && Val < 256) { 277 Offset = CurDAG->getRegister(0, MVT::i32); 278 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32); 279 return true; 280 } 281 } 282 283 Offset = N; 284 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32); 285 return true; 286} 287 288 289bool ARMDAGToDAGISel::SelectAddrMode5(SDOperand Op, SDOperand N, 290 SDOperand &Base, SDOperand &Offset) { 291 if (N.getOpcode() != ISD::ADD) { 292 Base = N; 293 if (N.getOpcode() == ISD::FrameIndex) { 294 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 295 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 296 } else if (N.getOpcode() == ARMISD::Wrapper) { 297 Base = N.getOperand(0); 298 } 299 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 300 MVT::i32); 301 return true; 302 } 303 304 // If the RHS is +/- imm8, fold into addr mode. 305 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 306 int RHSC = (int)RHS->getValue(); 307 if ((RHSC & 3) == 0) { // The constant is implicitly multiplied by 4. 308 RHSC >>= 2; 309 if (RHSC >= 0 && RHSC < 256) { 310 Base = N.getOperand(0); 311 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, RHSC), 312 MVT::i32); 313 return true; 314 } else if (RHSC < 0 && RHSC > -256) { // note -256 itself isn't allowed. 315 Base = N.getOperand(0); 316 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::sub,-RHSC), 317 MVT::i32); 318 return true; 319 } 320 } 321 } 322 323 Base = N; 324 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 325 MVT::i32); 326 return true; 327} 328 329bool ARMDAGToDAGISel::SelectAddrModePC(SDOperand Op, SDOperand N, 330 SDOperand &Offset, SDOperand &Label) { 331 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) { 332 Offset = N.getOperand(0); 333 SDOperand N1 = N.getOperand(1); 334 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getValue(), 335 MVT::i32); 336 return true; 337 } 338 return false; 339} 340 341bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDOperand Op, SDOperand N, 342 SDOperand &Base, SDOperand &Offset){ 343 if (N.getOpcode() != ISD::ADD) 344 return false; 345 Base = N.getOperand(0); 346 Offset = N.getOperand(1); 347 return true; 348} 349 350static bool SelectThumbAddrModeRI5(SDOperand N, unsigned Scale, 351 TargetLowering &TLI, SelectionDAG *CurDAG, 352 SDOperand &Base, SDOperand &Offset) { 353 if (N.getOpcode() == ISD::FrameIndex) 354 return false; 355 356 if (N.getOpcode() != ISD::ADD) { 357 Base = (N.getOpcode() == ARMISD::Wrapper) ? N.getOperand(0) : N; 358 Offset = CurDAG->getTargetConstant(0, MVT::i32); 359 return true; 360 } 361 362 // If the RHS is + imm5 * scale, fold into addr mode. 363 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 364 int RHSC = (int)RHS->getValue(); 365 if ((RHSC & (Scale-1)) == 0) { // The constant is implicitly multiplied. 366 RHSC /= Scale; 367 if (RHSC >= 0 && RHSC < 32) { 368 Base = N.getOperand(0); 369 Offset = CurDAG->getTargetConstant(RHSC, MVT::i32); 370 return true; 371 } 372 } 373 } 374 375 return false; 376} 377 378bool ARMDAGToDAGISel::SelectThumbAddrModeRI5_1(SDOperand Op, SDOperand N, 379 SDOperand &Base, SDOperand &Offset){ 380 return SelectThumbAddrModeRI5(N, 1, TLI, CurDAG, Base, Offset); 381} 382 383bool ARMDAGToDAGISel::SelectThumbAddrModeRI5_2(SDOperand Op, SDOperand N, 384 SDOperand &Base, SDOperand &Offset){ 385 return SelectThumbAddrModeRI5(N, 2, TLI, CurDAG, Base, Offset); 386} 387 388bool ARMDAGToDAGISel::SelectThumbAddrModeRI5_4(SDOperand Op, SDOperand N, 389 SDOperand &Base, SDOperand &Offset){ 390 return SelectThumbAddrModeRI5(N, 4, TLI, CurDAG, Base, Offset); 391} 392 393bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDOperand Op, SDOperand N, 394 SDOperand &Base, SDOperand &Offset) { 395 if (N.getOpcode() == ISD::FrameIndex) { 396 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 397 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 398 Offset = CurDAG->getTargetConstant(0, MVT::i32); 399 return true; 400 } 401 402 return false; 403} 404 405bool ARMDAGToDAGISel::SelectShifterOperandReg(SDOperand Op, 406 SDOperand N, 407 SDOperand &BaseReg, 408 SDOperand &ShReg, 409 SDOperand &Opc) { 410 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 411 412 // Don't match base register only case. That is matched to a separate 413 // lower complexity pattern with explicit register operand. 414 if (ShOpcVal == ARM_AM::no_shift) return false; 415 416 BaseReg = N.getOperand(0); 417 unsigned ShImmVal = 0; 418 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 419 ShReg = CurDAG->getRegister(0, MVT::i32); 420 ShImmVal = RHS->getValue() & 31; 421 } else { 422 ShReg = N.getOperand(1); 423 } 424 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), 425 MVT::i32); 426 return true; 427} 428 429 430SDNode *ARMDAGToDAGISel::Select(SDOperand Op) { 431 SDNode *N = Op.Val; 432 unsigned Opcode = N->getOpcode(); 433 434 if (Opcode >= ISD::BUILTIN_OP_END && Opcode < ARMISD::FIRST_NUMBER) 435 return NULL; // Already selected. 436 437 switch (N->getOpcode()) { 438 default: break; 439 case ISD::Constant: { 440 unsigned Val = cast<ConstantSDNode>(N)->getValue(); 441 bool UseCP = true; 442 if (Subtarget->isThumb()) 443 UseCP = (Val > 255 && // MOV 444 ~Val > 255 && // MOV + MVN 445 !ARM_AM::isThumbImmShiftedVal(Val)); // MOV + LSL 446 else 447 UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV 448 ARM_AM::getSOImmVal(~Val) == -1 && // MVN 449 !ARM_AM::isSOImmTwoPartVal(Val)); // two instrs. 450 if (UseCP) { 451 SDOperand CPIdx = 452 CurDAG->getTargetConstantPool(ConstantInt::get(Type::Int32Ty, Val), 453 TLI.getPointerTy()); 454 SDOperand Ops[] = { 455 CPIdx, 456 CurDAG->getRegister(0, MVT::i32), 457 CurDAG->getTargetConstant(0, MVT::i32), 458 CurDAG->getEntryNode() 459 }; 460 SDNode *ResNode = 461 CurDAG->getTargetNode(ARM::LDR, MVT::i32, MVT::Other, Ops, 4); 462 ReplaceUses(Op, SDOperand(ResNode, 0)); 463 return NULL; 464 } 465 466 // Other cases are autogenerated. 467 break; 468 } 469 case ISD::FrameIndex: { 470 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm. 471 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 472 unsigned Opc = Subtarget->isThumb() ? ARM::tADDrSPi : ARM::ADDri; 473 SDOperand TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 474 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, TFI, 475 CurDAG->getTargetConstant(0, MVT::i32)); 476 } 477 case ISD::MUL: 478 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) { 479 unsigned RHSV = C->getValue(); 480 if (!RHSV) break; 481 if (isPowerOf2_32(RHSV-1)) { // 2^n+1? 482 SDOperand V = Op.getOperand(0); 483 AddToISelQueue(V); 484 unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV-1)); 485 SDOperand Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32), 486 CurDAG->getTargetConstant(ShImm, MVT::i32) 487 }; 488 return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 4); 489 } 490 if (isPowerOf2_32(RHSV+1)) { // 2^n-1? 491 SDOperand V = Op.getOperand(0); 492 AddToISelQueue(V); 493 unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV+1)); 494 SDOperand Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32), 495 CurDAG->getTargetConstant(ShImm, MVT::i32) 496 }; 497 return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 4); 498 } 499 } 500 break; 501 case ARMISD::FMRRD: 502 AddToISelQueue(Op.getOperand(0)); 503 return CurDAG->getTargetNode(ARM::FMRRD, MVT::i32, MVT::i32, 504 Op.getOperand(0)); 505 case ARMISD::MULHILOU: 506 AddToISelQueue(Op.getOperand(0)); 507 AddToISelQueue(Op.getOperand(1)); 508 return CurDAG->getTargetNode(ARM::UMULL, MVT::i32, MVT::i32, 509 Op.getOperand(0), Op.getOperand(1)); 510 case ARMISD::MULHILOS: 511 AddToISelQueue(Op.getOperand(0)); 512 AddToISelQueue(Op.getOperand(1)); 513 return CurDAG->getTargetNode(ARM::SMULL, MVT::i32, MVT::i32, 514 Op.getOperand(0), Op.getOperand(1)); 515 case ISD::LOAD: { 516 LoadSDNode *LD = cast<LoadSDNode>(Op); 517 ISD::MemIndexedMode AM = LD->getAddressingMode(); 518 MVT::ValueType LoadedVT = LD->getLoadedVT(); 519 if (AM != ISD::UNINDEXED) { 520 SDOperand Offset, AMOpc; 521 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 522 unsigned Opcode = 0; 523 bool Match = false; 524 if (LoadedVT == MVT::i32 && 525 SelectAddrMode2Offset(Op, LD->getOffset(), Offset, AMOpc)) { 526 Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST; 527 Match = true; 528 } else if (LoadedVT == MVT::i16 && 529 SelectAddrMode3Offset(Op, LD->getOffset(), Offset, AMOpc)) { 530 Match = true; 531 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD) 532 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST) 533 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST); 534 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) { 535 if (LD->getExtensionType() == ISD::SEXTLOAD) { 536 if (SelectAddrMode3Offset(Op, LD->getOffset(), Offset, AMOpc)) { 537 Match = true; 538 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST; 539 } 540 } else { 541 if (SelectAddrMode2Offset(Op, LD->getOffset(), Offset, AMOpc)) { 542 Match = true; 543 Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST; 544 } 545 } 546 } 547 548 if (Match) { 549 SDOperand Chain = LD->getChain(); 550 SDOperand Base = LD->getBasePtr(); 551 AddToISelQueue(Chain); 552 AddToISelQueue(Base); 553 AddToISelQueue(Offset); 554 SDOperand Ops[] = { Base, Offset, AMOpc, Chain }; 555 return CurDAG->getTargetNode(Opcode, MVT::i32, MVT::i32, 556 MVT::Other, Ops, 4); 557 } 558 } 559 // Other cases are autogenerated. 560 break; 561 } 562 } 563 564 return SelectCode(Op); 565} 566 567/// createARMISelDag - This pass converts a legalized DAG into a 568/// ARM-specific DAG, ready for instruction scheduling. 569/// 570FunctionPass *llvm::createARMISelDag(ARMTargetMachine &TM) { 571 return new ARMDAGToDAGISel(TM); 572} 573