ARMISelDAGToDAG.cpp revision 193323
1193323Sed//===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file defines an instruction selector for the ARM target. 11193323Sed// 12193323Sed//===----------------------------------------------------------------------===// 13193323Sed 14193323Sed#include "ARM.h" 15193323Sed#include "ARMAddressingModes.h" 16193323Sed#include "ARMConstantPoolValue.h" 17193323Sed#include "ARMISelLowering.h" 18193323Sed#include "ARMTargetMachine.h" 19193323Sed#include "llvm/CallingConv.h" 20193323Sed#include "llvm/Constants.h" 21193323Sed#include "llvm/DerivedTypes.h" 22193323Sed#include "llvm/Function.h" 23193323Sed#include "llvm/Intrinsics.h" 24193323Sed#include "llvm/CodeGen/MachineFrameInfo.h" 25193323Sed#include "llvm/CodeGen/MachineFunction.h" 26193323Sed#include "llvm/CodeGen/MachineInstrBuilder.h" 27193323Sed#include "llvm/CodeGen/SelectionDAG.h" 28193323Sed#include "llvm/CodeGen/SelectionDAGISel.h" 29193323Sed#include "llvm/Target/TargetLowering.h" 30193323Sed#include "llvm/Target/TargetOptions.h" 31193323Sed#include "llvm/Support/Compiler.h" 32193323Sed#include "llvm/Support/Debug.h" 33193323Sedusing namespace llvm; 34193323Sed 35193323Sed//===--------------------------------------------------------------------===// 36193323Sed/// ARMDAGToDAGISel - ARM specific code to select ARM machine 37193323Sed/// instructions for SelectionDAG operations. 38193323Sed/// 39193323Sednamespace { 40193323Sedclass ARMDAGToDAGISel : public SelectionDAGISel { 41193323Sed ARMTargetMachine &TM; 42193323Sed 43193323Sed /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can 44193323Sed /// make the right decision when generating code for different targets. 45193323Sed const ARMSubtarget *Subtarget; 46193323Sed 47193323Sedpublic: 48193323Sed explicit ARMDAGToDAGISel(ARMTargetMachine &tm) 49193323Sed : SelectionDAGISel(tm), TM(tm), 50193323Sed Subtarget(&TM.getSubtarget<ARMSubtarget>()) { 51193323Sed } 52193323Sed 53193323Sed virtual const char *getPassName() const { 54193323Sed return "ARM Instruction Selection"; 55193323Sed } 56193323Sed 57193323Sed SDNode *Select(SDValue Op); 58193323Sed virtual void InstructionSelect(); 59193323Sed bool SelectAddrMode2(SDValue Op, SDValue N, SDValue &Base, 60193323Sed SDValue &Offset, SDValue &Opc); 61193323Sed bool SelectAddrMode2Offset(SDValue Op, SDValue N, 62193323Sed SDValue &Offset, SDValue &Opc); 63193323Sed bool SelectAddrMode3(SDValue Op, SDValue N, SDValue &Base, 64193323Sed SDValue &Offset, SDValue &Opc); 65193323Sed bool SelectAddrMode3Offset(SDValue Op, SDValue N, 66193323Sed SDValue &Offset, SDValue &Opc); 67193323Sed bool SelectAddrMode5(SDValue Op, SDValue N, SDValue &Base, 68193323Sed SDValue &Offset); 69193323Sed 70193323Sed bool SelectAddrModePC(SDValue Op, SDValue N, SDValue &Offset, 71193323Sed SDValue &Label); 72193323Sed 73193323Sed bool SelectThumbAddrModeRR(SDValue Op, SDValue N, SDValue &Base, 74193323Sed SDValue &Offset); 75193323Sed bool SelectThumbAddrModeRI5(SDValue Op, SDValue N, unsigned Scale, 76193323Sed SDValue &Base, SDValue &OffImm, 77193323Sed SDValue &Offset); 78193323Sed bool SelectThumbAddrModeS1(SDValue Op, SDValue N, SDValue &Base, 79193323Sed SDValue &OffImm, SDValue &Offset); 80193323Sed bool SelectThumbAddrModeS2(SDValue Op, SDValue N, SDValue &Base, 81193323Sed SDValue &OffImm, SDValue &Offset); 82193323Sed bool SelectThumbAddrModeS4(SDValue Op, SDValue N, SDValue &Base, 83193323Sed SDValue &OffImm, SDValue &Offset); 84193323Sed bool SelectThumbAddrModeSP(SDValue Op, SDValue N, SDValue &Base, 85193323Sed SDValue &OffImm); 86193323Sed 87193323Sed bool SelectShifterOperandReg(SDValue Op, SDValue N, SDValue &A, 88193323Sed SDValue &B, SDValue &C); 89193323Sed 90193323Sed // Include the pieces autogenerated from the target description. 91193323Sed#include "ARMGenDAGISel.inc" 92193323Sed 93193323Sedprivate: 94193323Sed /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for 95193323Sed /// inline asm expressions. 96193323Sed virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, 97193323Sed char ConstraintCode, 98193323Sed std::vector<SDValue> &OutOps); 99193323Sed}; 100193323Sed} 101193323Sed 102193323Sedvoid ARMDAGToDAGISel::InstructionSelect() { 103193323Sed DEBUG(BB->dump()); 104193323Sed 105193323Sed SelectRoot(*CurDAG); 106193323Sed CurDAG->RemoveDeadNodes(); 107193323Sed} 108193323Sed 109193323Sedbool ARMDAGToDAGISel::SelectAddrMode2(SDValue Op, SDValue N, 110193323Sed SDValue &Base, SDValue &Offset, 111193323Sed SDValue &Opc) { 112193323Sed if (N.getOpcode() == ISD::MUL) { 113193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 114193323Sed // X * [3,5,9] -> X + X * [2,4,8] etc. 115193323Sed int RHSC = (int)RHS->getZExtValue(); 116193323Sed if (RHSC & 1) { 117193323Sed RHSC = RHSC & ~1; 118193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 119193323Sed if (RHSC < 0) { 120193323Sed AddSub = ARM_AM::sub; 121193323Sed RHSC = - RHSC; 122193323Sed } 123193323Sed if (isPowerOf2_32(RHSC)) { 124193323Sed unsigned ShAmt = Log2_32(RHSC); 125193323Sed Base = Offset = N.getOperand(0); 126193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, 127193323Sed ARM_AM::lsl), 128193323Sed MVT::i32); 129193323Sed return true; 130193323Sed } 131193323Sed } 132193323Sed } 133193323Sed } 134193323Sed 135193323Sed if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) { 136193323Sed Base = N; 137193323Sed if (N.getOpcode() == ISD::FrameIndex) { 138193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 139193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 140193323Sed } else if (N.getOpcode() == ARMISD::Wrapper) { 141193323Sed Base = N.getOperand(0); 142193323Sed } 143193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 144193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, 145193323Sed ARM_AM::no_shift), 146193323Sed MVT::i32); 147193323Sed return true; 148193323Sed } 149193323Sed 150193323Sed // Match simple R +/- imm12 operands. 151193323Sed if (N.getOpcode() == ISD::ADD) 152193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 153193323Sed int RHSC = (int)RHS->getZExtValue(); 154193323Sed if ((RHSC >= 0 && RHSC < 0x1000) || 155193323Sed (RHSC < 0 && RHSC > -0x1000)) { // 12 bits. 156193323Sed Base = N.getOperand(0); 157193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 158193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 159193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 160193323Sed } 161193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 162193323Sed 163193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 164193323Sed if (RHSC < 0) { 165193323Sed AddSub = ARM_AM::sub; 166193323Sed RHSC = - RHSC; 167193323Sed } 168193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC, 169193323Sed ARM_AM::no_shift), 170193323Sed MVT::i32); 171193323Sed return true; 172193323Sed } 173193323Sed } 174193323Sed 175193323Sed // Otherwise this is R +/- [possibly shifted] R 176193323Sed ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::ADD ? ARM_AM::add:ARM_AM::sub; 177193323Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1)); 178193323Sed unsigned ShAmt = 0; 179193323Sed 180193323Sed Base = N.getOperand(0); 181193323Sed Offset = N.getOperand(1); 182193323Sed 183193323Sed if (ShOpcVal != ARM_AM::no_shift) { 184193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 185193323Sed // it. 186193323Sed if (ConstantSDNode *Sh = 187193323Sed dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) { 188193323Sed ShAmt = Sh->getZExtValue(); 189193323Sed Offset = N.getOperand(1).getOperand(0); 190193323Sed } else { 191193323Sed ShOpcVal = ARM_AM::no_shift; 192193323Sed } 193193323Sed } 194193323Sed 195193323Sed // Try matching (R shl C) + (R). 196193323Sed if (N.getOpcode() == ISD::ADD && ShOpcVal == ARM_AM::no_shift) { 197193323Sed ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0)); 198193323Sed if (ShOpcVal != ARM_AM::no_shift) { 199193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't 200193323Sed // fold it. 201193323Sed if (ConstantSDNode *Sh = 202193323Sed dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) { 203193323Sed ShAmt = Sh->getZExtValue(); 204193323Sed Offset = N.getOperand(0).getOperand(0); 205193323Sed Base = N.getOperand(1); 206193323Sed } else { 207193323Sed ShOpcVal = ARM_AM::no_shift; 208193323Sed } 209193323Sed } 210193323Sed } 211193323Sed 212193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 213193323Sed MVT::i32); 214193323Sed return true; 215193323Sed} 216193323Sed 217193323Sedbool ARMDAGToDAGISel::SelectAddrMode2Offset(SDValue Op, SDValue N, 218193323Sed SDValue &Offset, SDValue &Opc) { 219193323Sed unsigned Opcode = Op.getOpcode(); 220193323Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 221193323Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 222193323Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 223193323Sed ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 224193323Sed ? ARM_AM::add : ARM_AM::sub; 225193323Sed if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 226193323Sed int Val = (int)C->getZExtValue(); 227193323Sed if (Val >= 0 && Val < 0x1000) { // 12 bits. 228193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 229193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val, 230193323Sed ARM_AM::no_shift), 231193323Sed MVT::i32); 232193323Sed return true; 233193323Sed } 234193323Sed } 235193323Sed 236193323Sed Offset = N; 237193323Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 238193323Sed unsigned ShAmt = 0; 239193323Sed if (ShOpcVal != ARM_AM::no_shift) { 240193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 241193323Sed // it. 242193323Sed if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 243193323Sed ShAmt = Sh->getZExtValue(); 244193323Sed Offset = N.getOperand(0); 245193323Sed } else { 246193323Sed ShOpcVal = ARM_AM::no_shift; 247193323Sed } 248193323Sed } 249193323Sed 250193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 251193323Sed MVT::i32); 252193323Sed return true; 253193323Sed} 254193323Sed 255193323Sed 256193323Sedbool ARMDAGToDAGISel::SelectAddrMode3(SDValue Op, SDValue N, 257193323Sed SDValue &Base, SDValue &Offset, 258193323Sed SDValue &Opc) { 259193323Sed if (N.getOpcode() == ISD::SUB) { 260193323Sed // X - C is canonicalize to X + -C, no need to handle it here. 261193323Sed Base = N.getOperand(0); 262193323Sed Offset = N.getOperand(1); 263193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32); 264193323Sed return true; 265193323Sed } 266193323Sed 267193323Sed if (N.getOpcode() != ISD::ADD) { 268193323Sed Base = N; 269193323Sed if (N.getOpcode() == ISD::FrameIndex) { 270193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 271193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 272193323Sed } 273193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 274193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32); 275193323Sed return true; 276193323Sed } 277193323Sed 278193323Sed // If the RHS is +/- imm8, fold into addr mode. 279193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 280193323Sed int RHSC = (int)RHS->getZExtValue(); 281193323Sed if ((RHSC >= 0 && RHSC < 256) || 282193323Sed (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed. 283193323Sed Base = N.getOperand(0); 284193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 285193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 286193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 287193323Sed } 288193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 289193323Sed 290193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 291193323Sed if (RHSC < 0) { 292193323Sed AddSub = ARM_AM::sub; 293193323Sed RHSC = - RHSC; 294193323Sed } 295193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32); 296193323Sed return true; 297193323Sed } 298193323Sed } 299193323Sed 300193323Sed Base = N.getOperand(0); 301193323Sed Offset = N.getOperand(1); 302193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32); 303193323Sed return true; 304193323Sed} 305193323Sed 306193323Sedbool ARMDAGToDAGISel::SelectAddrMode3Offset(SDValue Op, SDValue N, 307193323Sed SDValue &Offset, SDValue &Opc) { 308193323Sed unsigned Opcode = Op.getOpcode(); 309193323Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 310193323Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 311193323Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 312193323Sed ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 313193323Sed ? ARM_AM::add : ARM_AM::sub; 314193323Sed if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 315193323Sed int Val = (int)C->getZExtValue(); 316193323Sed if (Val >= 0 && Val < 256) { 317193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 318193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32); 319193323Sed return true; 320193323Sed } 321193323Sed } 322193323Sed 323193323Sed Offset = N; 324193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32); 325193323Sed return true; 326193323Sed} 327193323Sed 328193323Sed 329193323Sedbool ARMDAGToDAGISel::SelectAddrMode5(SDValue Op, SDValue N, 330193323Sed SDValue &Base, SDValue &Offset) { 331193323Sed if (N.getOpcode() != ISD::ADD) { 332193323Sed Base = N; 333193323Sed if (N.getOpcode() == ISD::FrameIndex) { 334193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 335193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 336193323Sed } else if (N.getOpcode() == ARMISD::Wrapper) { 337193323Sed Base = N.getOperand(0); 338193323Sed } 339193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 340193323Sed MVT::i32); 341193323Sed return true; 342193323Sed } 343193323Sed 344193323Sed // If the RHS is +/- imm8, fold into addr mode. 345193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 346193323Sed int RHSC = (int)RHS->getZExtValue(); 347193323Sed if ((RHSC & 3) == 0) { // The constant is implicitly multiplied by 4. 348193323Sed RHSC >>= 2; 349193323Sed if ((RHSC >= 0 && RHSC < 256) || 350193323Sed (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed. 351193323Sed Base = N.getOperand(0); 352193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 353193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 354193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 355193323Sed } 356193323Sed 357193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 358193323Sed if (RHSC < 0) { 359193323Sed AddSub = ARM_AM::sub; 360193323Sed RHSC = - RHSC; 361193323Sed } 362193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC), 363193323Sed MVT::i32); 364193323Sed return true; 365193323Sed } 366193323Sed } 367193323Sed } 368193323Sed 369193323Sed Base = N; 370193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 371193323Sed MVT::i32); 372193323Sed return true; 373193323Sed} 374193323Sed 375193323Sedbool ARMDAGToDAGISel::SelectAddrModePC(SDValue Op, SDValue N, 376193323Sed SDValue &Offset, SDValue &Label) { 377193323Sed if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) { 378193323Sed Offset = N.getOperand(0); 379193323Sed SDValue N1 = N.getOperand(1); 380193323Sed Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(), 381193323Sed MVT::i32); 382193323Sed return true; 383193323Sed } 384193323Sed return false; 385193323Sed} 386193323Sed 387193323Sedbool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue Op, SDValue N, 388193323Sed SDValue &Base, SDValue &Offset){ 389193323Sed // FIXME dl should come from the parent load or store, not the address 390193323Sed DebugLoc dl = Op.getDebugLoc(); 391193323Sed if (N.getOpcode() != ISD::ADD) { 392193323Sed Base = N; 393193323Sed // We must materialize a zero in a reg! Returning a constant here 394193323Sed // wouldn't work without additional code to position the node within 395193323Sed // ISel's topological ordering in a place where ISel will process it 396193323Sed // normally. Instead, just explicitly issue a tMOVri8 node! 397193323Sed Offset = SDValue(CurDAG->getTargetNode(ARM::tMOVi8, dl, MVT::i32, 398193323Sed CurDAG->getTargetConstant(0, MVT::i32)), 0); 399193323Sed return true; 400193323Sed } 401193323Sed 402193323Sed Base = N.getOperand(0); 403193323Sed Offset = N.getOperand(1); 404193323Sed return true; 405193323Sed} 406193323Sed 407193323Sedbool 408193323SedARMDAGToDAGISel::SelectThumbAddrModeRI5(SDValue Op, SDValue N, 409193323Sed unsigned Scale, SDValue &Base, 410193323Sed SDValue &OffImm, SDValue &Offset) { 411193323Sed if (Scale == 4) { 412193323Sed SDValue TmpBase, TmpOffImm; 413193323Sed if (SelectThumbAddrModeSP(Op, N, TmpBase, TmpOffImm)) 414193323Sed return false; // We want to select tLDRspi / tSTRspi instead. 415193323Sed if (N.getOpcode() == ARMISD::Wrapper && 416193323Sed N.getOperand(0).getOpcode() == ISD::TargetConstantPool) 417193323Sed return false; // We want to select tLDRpci instead. 418193323Sed } 419193323Sed 420193323Sed if (N.getOpcode() != ISD::ADD) { 421193323Sed Base = (N.getOpcode() == ARMISD::Wrapper) ? N.getOperand(0) : N; 422193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 423193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 424193323Sed return true; 425193323Sed } 426193323Sed 427193323Sed // Thumb does not have [sp, r] address mode. 428193323Sed RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 429193323Sed RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1)); 430193323Sed if ((LHSR && LHSR->getReg() == ARM::SP) || 431193323Sed (RHSR && RHSR->getReg() == ARM::SP)) { 432193323Sed Base = N; 433193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 434193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 435193323Sed return true; 436193323Sed } 437193323Sed 438193323Sed // If the RHS is + imm5 * scale, fold into addr mode. 439193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 440193323Sed int RHSC = (int)RHS->getZExtValue(); 441193323Sed if ((RHSC & (Scale-1)) == 0) { // The constant is implicitly multiplied. 442193323Sed RHSC /= Scale; 443193323Sed if (RHSC >= 0 && RHSC < 32) { 444193323Sed Base = N.getOperand(0); 445193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 446193323Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 447193323Sed return true; 448193323Sed } 449193323Sed } 450193323Sed } 451193323Sed 452193323Sed Base = N.getOperand(0); 453193323Sed Offset = N.getOperand(1); 454193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 455193323Sed return true; 456193323Sed} 457193323Sed 458193323Sedbool ARMDAGToDAGISel::SelectThumbAddrModeS1(SDValue Op, SDValue N, 459193323Sed SDValue &Base, SDValue &OffImm, 460193323Sed SDValue &Offset) { 461193323Sed return SelectThumbAddrModeRI5(Op, N, 1, Base, OffImm, Offset); 462193323Sed} 463193323Sed 464193323Sedbool ARMDAGToDAGISel::SelectThumbAddrModeS2(SDValue Op, SDValue N, 465193323Sed SDValue &Base, SDValue &OffImm, 466193323Sed SDValue &Offset) { 467193323Sed return SelectThumbAddrModeRI5(Op, N, 2, Base, OffImm, Offset); 468193323Sed} 469193323Sed 470193323Sedbool ARMDAGToDAGISel::SelectThumbAddrModeS4(SDValue Op, SDValue N, 471193323Sed SDValue &Base, SDValue &OffImm, 472193323Sed SDValue &Offset) { 473193323Sed return SelectThumbAddrModeRI5(Op, N, 4, Base, OffImm, Offset); 474193323Sed} 475193323Sed 476193323Sedbool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue Op, SDValue N, 477193323Sed SDValue &Base, SDValue &OffImm) { 478193323Sed if (N.getOpcode() == ISD::FrameIndex) { 479193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 480193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 481193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 482193323Sed return true; 483193323Sed } 484193323Sed 485193323Sed if (N.getOpcode() != ISD::ADD) 486193323Sed return false; 487193323Sed 488193323Sed RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 489193323Sed if (N.getOperand(0).getOpcode() == ISD::FrameIndex || 490193323Sed (LHSR && LHSR->getReg() == ARM::SP)) { 491193323Sed // If the RHS is + imm8 * scale, fold into addr mode. 492193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 493193323Sed int RHSC = (int)RHS->getZExtValue(); 494193323Sed if ((RHSC & 3) == 0) { // The constant is implicitly multiplied. 495193323Sed RHSC >>= 2; 496193323Sed if (RHSC >= 0 && RHSC < 256) { 497193323Sed Base = N.getOperand(0); 498193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 499193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 500193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 501193323Sed } 502193323Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 503193323Sed return true; 504193323Sed } 505193323Sed } 506193323Sed } 507193323Sed } 508193323Sed 509193323Sed return false; 510193323Sed} 511193323Sed 512193323Sedbool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue Op, 513193323Sed SDValue N, 514193323Sed SDValue &BaseReg, 515193323Sed SDValue &ShReg, 516193323Sed SDValue &Opc) { 517193323Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 518193323Sed 519193323Sed // Don't match base register only case. That is matched to a separate 520193323Sed // lower complexity pattern with explicit register operand. 521193323Sed if (ShOpcVal == ARM_AM::no_shift) return false; 522193323Sed 523193323Sed BaseReg = N.getOperand(0); 524193323Sed unsigned ShImmVal = 0; 525193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 526193323Sed ShReg = CurDAG->getRegister(0, MVT::i32); 527193323Sed ShImmVal = RHS->getZExtValue() & 31; 528193323Sed } else { 529193323Sed ShReg = N.getOperand(1); 530193323Sed } 531193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), 532193323Sed MVT::i32); 533193323Sed return true; 534193323Sed} 535193323Sed 536193323Sed/// getAL - Returns a ARMCC::AL immediate node. 537193323Sedstatic inline SDValue getAL(SelectionDAG *CurDAG) { 538193323Sed return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32); 539193323Sed} 540193323Sed 541193323Sed 542193323SedSDNode *ARMDAGToDAGISel::Select(SDValue Op) { 543193323Sed SDNode *N = Op.getNode(); 544193323Sed DebugLoc dl = N->getDebugLoc(); 545193323Sed 546193323Sed if (N->isMachineOpcode()) 547193323Sed return NULL; // Already selected. 548193323Sed 549193323Sed switch (N->getOpcode()) { 550193323Sed default: break; 551193323Sed case ISD::Constant: { 552193323Sed unsigned Val = cast<ConstantSDNode>(N)->getZExtValue(); 553193323Sed bool UseCP = true; 554193323Sed if (Subtarget->isThumb()) 555193323Sed UseCP = (Val > 255 && // MOV 556193323Sed ~Val > 255 && // MOV + MVN 557193323Sed !ARM_AM::isThumbImmShiftedVal(Val)); // MOV + LSL 558193323Sed else 559193323Sed UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV 560193323Sed ARM_AM::getSOImmVal(~Val) == -1 && // MVN 561193323Sed !ARM_AM::isSOImmTwoPartVal(Val)); // two instrs. 562193323Sed if (UseCP) { 563193323Sed SDValue CPIdx = 564193323Sed CurDAG->getTargetConstantPool(ConstantInt::get(Type::Int32Ty, Val), 565193323Sed TLI.getPointerTy()); 566193323Sed 567193323Sed SDNode *ResNode; 568193323Sed if (Subtarget->isThumb()) 569193323Sed ResNode = CurDAG->getTargetNode(ARM::tLDRcp, dl, MVT::i32, MVT::Other, 570193323Sed CPIdx, CurDAG->getEntryNode()); 571193323Sed else { 572193323Sed SDValue Ops[] = { 573193323Sed CPIdx, 574193323Sed CurDAG->getRegister(0, MVT::i32), 575193323Sed CurDAG->getTargetConstant(0, MVT::i32), 576193323Sed getAL(CurDAG), 577193323Sed CurDAG->getRegister(0, MVT::i32), 578193323Sed CurDAG->getEntryNode() 579193323Sed }; 580193323Sed ResNode=CurDAG->getTargetNode(ARM::LDRcp, dl, MVT::i32, MVT::Other, 581193323Sed Ops, 6); 582193323Sed } 583193323Sed ReplaceUses(Op, SDValue(ResNode, 0)); 584193323Sed return NULL; 585193323Sed } 586193323Sed 587193323Sed // Other cases are autogenerated. 588193323Sed break; 589193323Sed } 590193323Sed case ISD::FrameIndex: { 591193323Sed // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm. 592193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 593193323Sed SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 594193323Sed if (Subtarget->isThumb()) { 595193323Sed return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI, 596193323Sed CurDAG->getTargetConstant(0, MVT::i32)); 597193323Sed } else { 598193323Sed SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32), 599193323Sed getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 600193323Sed CurDAG->getRegister(0, MVT::i32) }; 601193323Sed return CurDAG->SelectNodeTo(N, ARM::ADDri, MVT::i32, Ops, 5); 602193323Sed } 603193323Sed } 604193323Sed case ISD::ADD: { 605193323Sed if (!Subtarget->isThumb()) 606193323Sed break; 607193323Sed // Select add sp, c to tADDhirr. 608193323Sed SDValue N0 = Op.getOperand(0); 609193323Sed SDValue N1 = Op.getOperand(1); 610193323Sed RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(Op.getOperand(0)); 611193323Sed RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(Op.getOperand(1)); 612193323Sed if (LHSR && LHSR->getReg() == ARM::SP) { 613193323Sed std::swap(N0, N1); 614193323Sed std::swap(LHSR, RHSR); 615193323Sed } 616193323Sed if (RHSR && RHSR->getReg() == ARM::SP) { 617193323Sed SDValue Val = SDValue(CurDAG->getTargetNode(ARM::tMOVlor2hir, dl, 618193323Sed Op.getValueType(), N0, N0), 0); 619193323Sed return CurDAG->SelectNodeTo(N, ARM::tADDhirr, Op.getValueType(), Val, N1); 620193323Sed } 621193323Sed break; 622193323Sed } 623193323Sed case ISD::MUL: 624193323Sed if (Subtarget->isThumb()) 625193323Sed break; 626193323Sed if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) { 627193323Sed unsigned RHSV = C->getZExtValue(); 628193323Sed if (!RHSV) break; 629193323Sed if (isPowerOf2_32(RHSV-1)) { // 2^n+1? 630193323Sed SDValue V = Op.getOperand(0); 631193323Sed unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV-1)); 632193323Sed SDValue Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32), 633193323Sed CurDAG->getTargetConstant(ShImm, MVT::i32), 634193323Sed getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 635193323Sed CurDAG->getRegister(0, MVT::i32) }; 636193323Sed return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 7); 637193323Sed } 638193323Sed if (isPowerOf2_32(RHSV+1)) { // 2^n-1? 639193323Sed SDValue V = Op.getOperand(0); 640193323Sed unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV+1)); 641193323Sed SDValue Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32), 642193323Sed CurDAG->getTargetConstant(ShImm, MVT::i32), 643193323Sed getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 644193323Sed CurDAG->getRegister(0, MVT::i32) }; 645193323Sed return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 7); 646193323Sed } 647193323Sed } 648193323Sed break; 649193323Sed case ARMISD::FMRRD: 650193323Sed return CurDAG->getTargetNode(ARM::FMRRD, dl, MVT::i32, MVT::i32, 651193323Sed Op.getOperand(0), getAL(CurDAG), 652193323Sed CurDAG->getRegister(0, MVT::i32)); 653193323Sed case ISD::UMUL_LOHI: { 654193323Sed SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), 655193323Sed getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 656193323Sed CurDAG->getRegister(0, MVT::i32) }; 657193323Sed return CurDAG->getTargetNode(ARM::UMULL, dl, MVT::i32, MVT::i32, Ops, 5); 658193323Sed } 659193323Sed case ISD::SMUL_LOHI: { 660193323Sed SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), 661193323Sed getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 662193323Sed CurDAG->getRegister(0, MVT::i32) }; 663193323Sed return CurDAG->getTargetNode(ARM::SMULL, dl, MVT::i32, MVT::i32, Ops, 5); 664193323Sed } 665193323Sed case ISD::LOAD: { 666193323Sed LoadSDNode *LD = cast<LoadSDNode>(Op); 667193323Sed ISD::MemIndexedMode AM = LD->getAddressingMode(); 668193323Sed MVT LoadedVT = LD->getMemoryVT(); 669193323Sed if (AM != ISD::UNINDEXED) { 670193323Sed SDValue Offset, AMOpc; 671193323Sed bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 672193323Sed unsigned Opcode = 0; 673193323Sed bool Match = false; 674193323Sed if (LoadedVT == MVT::i32 && 675193323Sed SelectAddrMode2Offset(Op, LD->getOffset(), Offset, AMOpc)) { 676193323Sed Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST; 677193323Sed Match = true; 678193323Sed } else if (LoadedVT == MVT::i16 && 679193323Sed SelectAddrMode3Offset(Op, LD->getOffset(), Offset, AMOpc)) { 680193323Sed Match = true; 681193323Sed Opcode = (LD->getExtensionType() == ISD::SEXTLOAD) 682193323Sed ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST) 683193323Sed : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST); 684193323Sed } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) { 685193323Sed if (LD->getExtensionType() == ISD::SEXTLOAD) { 686193323Sed if (SelectAddrMode3Offset(Op, LD->getOffset(), Offset, AMOpc)) { 687193323Sed Match = true; 688193323Sed Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST; 689193323Sed } 690193323Sed } else { 691193323Sed if (SelectAddrMode2Offset(Op, LD->getOffset(), Offset, AMOpc)) { 692193323Sed Match = true; 693193323Sed Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST; 694193323Sed } 695193323Sed } 696193323Sed } 697193323Sed 698193323Sed if (Match) { 699193323Sed SDValue Chain = LD->getChain(); 700193323Sed SDValue Base = LD->getBasePtr(); 701193323Sed SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG), 702193323Sed CurDAG->getRegister(0, MVT::i32), Chain }; 703193323Sed return CurDAG->getTargetNode(Opcode, dl, MVT::i32, MVT::i32, 704193323Sed MVT::Other, Ops, 6); 705193323Sed } 706193323Sed } 707193323Sed // Other cases are autogenerated. 708193323Sed break; 709193323Sed } 710193323Sed case ARMISD::BRCOND: { 711193323Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 712193323Sed // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc) 713193323Sed // Pattern complexity = 6 cost = 1 size = 0 714193323Sed 715193323Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 716193323Sed // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc) 717193323Sed // Pattern complexity = 6 cost = 1 size = 0 718193323Sed 719193323Sed unsigned Opc = Subtarget->isThumb() ? ARM::tBcc : ARM::Bcc; 720193323Sed SDValue Chain = Op.getOperand(0); 721193323Sed SDValue N1 = Op.getOperand(1); 722193323Sed SDValue N2 = Op.getOperand(2); 723193323Sed SDValue N3 = Op.getOperand(3); 724193323Sed SDValue InFlag = Op.getOperand(4); 725193323Sed assert(N1.getOpcode() == ISD::BasicBlock); 726193323Sed assert(N2.getOpcode() == ISD::Constant); 727193323Sed assert(N3.getOpcode() == ISD::Register); 728193323Sed 729193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 730193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 731193323Sed MVT::i32); 732193323Sed SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag }; 733193323Sed SDNode *ResNode = CurDAG->getTargetNode(Opc, dl, MVT::Other, 734193323Sed MVT::Flag, Ops, 5); 735193323Sed Chain = SDValue(ResNode, 0); 736193323Sed if (Op.getNode()->getNumValues() == 2) { 737193323Sed InFlag = SDValue(ResNode, 1); 738193323Sed ReplaceUses(SDValue(Op.getNode(), 1), InFlag); 739193323Sed } 740193323Sed ReplaceUses(SDValue(Op.getNode(), 0), SDValue(Chain.getNode(), Chain.getResNo())); 741193323Sed return NULL; 742193323Sed } 743193323Sed case ARMISD::CMOV: { 744193323Sed bool isThumb = Subtarget->isThumb(); 745193323Sed MVT VT = Op.getValueType(); 746193323Sed SDValue N0 = Op.getOperand(0); 747193323Sed SDValue N1 = Op.getOperand(1); 748193323Sed SDValue N2 = Op.getOperand(2); 749193323Sed SDValue N3 = Op.getOperand(3); 750193323Sed SDValue InFlag = Op.getOperand(4); 751193323Sed assert(N2.getOpcode() == ISD::Constant); 752193323Sed assert(N3.getOpcode() == ISD::Register); 753193323Sed 754193323Sed // Pattern: (ARMcmov:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) 755193323Sed // Emits: (MOVCCs:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) 756193323Sed // Pattern complexity = 18 cost = 1 size = 0 757193323Sed SDValue CPTmp0; 758193323Sed SDValue CPTmp1; 759193323Sed SDValue CPTmp2; 760193323Sed if (!isThumb && VT == MVT::i32 && 761193323Sed SelectShifterOperandReg(Op, N1, CPTmp0, CPTmp1, CPTmp2)) { 762193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 763193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 764193323Sed MVT::i32); 765193323Sed SDValue Ops[] = { N0, CPTmp0, CPTmp1, CPTmp2, Tmp2, N3, InFlag }; 766193323Sed return CurDAG->SelectNodeTo(Op.getNode(), ARM::MOVCCs, MVT::i32, Ops, 7); 767193323Sed } 768193323Sed 769193323Sed // Pattern: (ARMcmov:i32 GPR:i32:$false, 770193323Sed // (imm:i32)<<P:Predicate_so_imm>><<X:so_imm_XFORM>>:$true, 771193323Sed // (imm:i32):$cc) 772193323Sed // Emits: (MOVCCi:i32 GPR:i32:$false, 773193323Sed // (so_imm_XFORM:i32 (imm:i32):$true), (imm:i32):$cc) 774193323Sed // Pattern complexity = 10 cost = 1 size = 0 775193323Sed if (VT == MVT::i32 && 776193323Sed N3.getOpcode() == ISD::Constant && 777193323Sed Predicate_so_imm(N3.getNode())) { 778193323Sed SDValue Tmp1 = CurDAG->getTargetConstant(((unsigned) 779193323Sed cast<ConstantSDNode>(N1)->getZExtValue()), 780193323Sed MVT::i32); 781193323Sed Tmp1 = Transform_so_imm_XFORM(Tmp1.getNode()); 782193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 783193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 784193323Sed MVT::i32); 785193323Sed SDValue Ops[] = { N0, Tmp1, Tmp2, N3, InFlag }; 786193323Sed return CurDAG->SelectNodeTo(Op.getNode(), ARM::MOVCCi, MVT::i32, Ops, 5); 787193323Sed } 788193323Sed 789193323Sed // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 790193323Sed // Emits: (MOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 791193323Sed // Pattern complexity = 6 cost = 1 size = 0 792193323Sed // 793193323Sed // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 794193323Sed // Emits: (tMOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 795193323Sed // Pattern complexity = 6 cost = 11 size = 0 796193323Sed // 797193323Sed // Also FCPYScc and FCPYDcc. 798193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 799193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 800193323Sed MVT::i32); 801193323Sed SDValue Ops[] = { N0, N1, Tmp2, N3, InFlag }; 802193323Sed unsigned Opc = 0; 803193323Sed switch (VT.getSimpleVT()) { 804193323Sed default: assert(false && "Illegal conditional move type!"); 805193323Sed break; 806193323Sed case MVT::i32: 807193323Sed Opc = isThumb ? ARM::tMOVCCr : ARM::MOVCCr; 808193323Sed break; 809193323Sed case MVT::f32: 810193323Sed Opc = ARM::FCPYScc; 811193323Sed break; 812193323Sed case MVT::f64: 813193323Sed Opc = ARM::FCPYDcc; 814193323Sed break; 815193323Sed } 816193323Sed return CurDAG->SelectNodeTo(Op.getNode(), Opc, VT, Ops, 5); 817193323Sed } 818193323Sed case ARMISD::CNEG: { 819193323Sed MVT VT = Op.getValueType(); 820193323Sed SDValue N0 = Op.getOperand(0); 821193323Sed SDValue N1 = Op.getOperand(1); 822193323Sed SDValue N2 = Op.getOperand(2); 823193323Sed SDValue N3 = Op.getOperand(3); 824193323Sed SDValue InFlag = Op.getOperand(4); 825193323Sed assert(N2.getOpcode() == ISD::Constant); 826193323Sed assert(N3.getOpcode() == ISD::Register); 827193323Sed 828193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 829193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 830193323Sed MVT::i32); 831193323Sed SDValue Ops[] = { N0, N1, Tmp2, N3, InFlag }; 832193323Sed unsigned Opc = 0; 833193323Sed switch (VT.getSimpleVT()) { 834193323Sed default: assert(false && "Illegal conditional move type!"); 835193323Sed break; 836193323Sed case MVT::f32: 837193323Sed Opc = ARM::FNEGScc; 838193323Sed break; 839193323Sed case MVT::f64: 840193323Sed Opc = ARM::FNEGDcc; 841193323Sed break; 842193323Sed } 843193323Sed return CurDAG->SelectNodeTo(Op.getNode(), Opc, VT, Ops, 5); 844193323Sed } 845193323Sed 846193323Sed case ISD::DECLARE: { 847193323Sed SDValue Chain = Op.getOperand(0); 848193323Sed SDValue N1 = Op.getOperand(1); 849193323Sed SDValue N2 = Op.getOperand(2); 850193323Sed FrameIndexSDNode *FINode = dyn_cast<FrameIndexSDNode>(N1); 851193323Sed // FIXME: handle VLAs. 852193323Sed if (!FINode) { 853193323Sed ReplaceUses(Op.getValue(0), Chain); 854193323Sed return NULL; 855193323Sed } 856193323Sed if (N2.getOpcode() == ARMISD::PIC_ADD && isa<LoadSDNode>(N2.getOperand(0))) 857193323Sed N2 = N2.getOperand(0); 858193323Sed LoadSDNode *Ld = dyn_cast<LoadSDNode>(N2); 859193323Sed if (!Ld) { 860193323Sed ReplaceUses(Op.getValue(0), Chain); 861193323Sed return NULL; 862193323Sed } 863193323Sed SDValue BasePtr = Ld->getBasePtr(); 864193323Sed assert(BasePtr.getOpcode() == ARMISD::Wrapper && 865193323Sed isa<ConstantPoolSDNode>(BasePtr.getOperand(0)) && 866193323Sed "llvm.dbg.variable should be a constantpool node"); 867193323Sed ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(BasePtr.getOperand(0)); 868193323Sed GlobalValue *GV = 0; 869193323Sed if (CP->isMachineConstantPoolEntry()) { 870193323Sed ARMConstantPoolValue *ACPV = (ARMConstantPoolValue*)CP->getMachineCPVal(); 871193323Sed GV = ACPV->getGV(); 872193323Sed } else 873193323Sed GV = dyn_cast<GlobalValue>(CP->getConstVal()); 874193323Sed if (!GV) { 875193323Sed ReplaceUses(Op.getValue(0), Chain); 876193323Sed return NULL; 877193323Sed } 878193323Sed 879193323Sed SDValue Tmp1 = CurDAG->getTargetFrameIndex(FINode->getIndex(), 880193323Sed TLI.getPointerTy()); 881193323Sed SDValue Tmp2 = CurDAG->getTargetGlobalAddress(GV, TLI.getPointerTy()); 882193323Sed SDValue Ops[] = { Tmp1, Tmp2, Chain }; 883193323Sed return CurDAG->getTargetNode(TargetInstrInfo::DECLARE, dl, 884193323Sed MVT::Other, Ops, 3); 885193323Sed } 886193323Sed } 887193323Sed 888193323Sed return SelectCode(Op); 889193323Sed} 890193323Sed 891193323Sedbool ARMDAGToDAGISel:: 892193323SedSelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, 893193323Sed std::vector<SDValue> &OutOps) { 894193323Sed assert(ConstraintCode == 'm' && "unexpected asm memory constraint"); 895193323Sed 896193323Sed SDValue Base, Offset, Opc; 897193323Sed if (!SelectAddrMode2(Op, Op, Base, Offset, Opc)) 898193323Sed return true; 899193323Sed 900193323Sed OutOps.push_back(Base); 901193323Sed OutOps.push_back(Offset); 902193323Sed OutOps.push_back(Opc); 903193323Sed return false; 904193323Sed} 905193323Sed 906193323Sed/// createARMISelDag - This pass converts a legalized DAG into a 907193323Sed/// ARM-specific DAG, ready for instruction scheduling. 908193323Sed/// 909193323SedFunctionPass *llvm::createARMISelDag(ARMTargetMachine &TM) { 910193323Sed return new ARMDAGToDAGISel(TM); 911193323Sed} 912