ARMISelDAGToDAG.cpp revision 199989
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 "ARMISelLowering.h" 17193323Sed#include "ARMTargetMachine.h" 18193323Sed#include "llvm/CallingConv.h" 19193323Sed#include "llvm/Constants.h" 20193323Sed#include "llvm/DerivedTypes.h" 21193323Sed#include "llvm/Function.h" 22193323Sed#include "llvm/Intrinsics.h" 23198090Srdivacky#include "llvm/LLVMContext.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" 33198090Srdivacky#include "llvm/Support/ErrorHandling.h" 34198090Srdivacky#include "llvm/Support/raw_ostream.h" 35198090Srdivacky 36193323Sedusing namespace llvm; 37193323Sed 38193323Sed//===--------------------------------------------------------------------===// 39193323Sed/// ARMDAGToDAGISel - ARM specific code to select ARM machine 40193323Sed/// instructions for SelectionDAG operations. 41193323Sed/// 42193323Sednamespace { 43193323Sedclass ARMDAGToDAGISel : public SelectionDAGISel { 44195098Sed ARMBaseTargetMachine &TM; 45193323Sed 46193323Sed /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can 47193323Sed /// make the right decision when generating code for different targets. 48193323Sed const ARMSubtarget *Subtarget; 49193323Sed 50193323Sedpublic: 51198090Srdivacky explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm, 52198090Srdivacky CodeGenOpt::Level OptLevel) 53198090Srdivacky : SelectionDAGISel(tm, OptLevel), TM(tm), 54193323Sed Subtarget(&TM.getSubtarget<ARMSubtarget>()) { 55193323Sed } 56193323Sed 57193323Sed virtual const char *getPassName() const { 58193323Sed return "ARM Instruction Selection"; 59194612Sed } 60194612Sed 61198090Srdivacky /// getI32Imm - Return a target constant of type i32 with the specified 62198090Srdivacky /// value. 63194612Sed inline SDValue getI32Imm(unsigned Imm) { 64194612Sed return CurDAG->getTargetConstant(Imm, MVT::i32); 65194612Sed } 66194612Sed 67193323Sed SDNode *Select(SDValue Op); 68193323Sed virtual void InstructionSelect(); 69195340Sed bool SelectShifterOperandReg(SDValue Op, SDValue N, SDValue &A, 70195340Sed SDValue &B, SDValue &C); 71193323Sed bool SelectAddrMode2(SDValue Op, SDValue N, SDValue &Base, 72193323Sed SDValue &Offset, SDValue &Opc); 73193323Sed bool SelectAddrMode2Offset(SDValue Op, SDValue N, 74193323Sed SDValue &Offset, SDValue &Opc); 75193323Sed bool SelectAddrMode3(SDValue Op, SDValue N, SDValue &Base, 76193323Sed SDValue &Offset, SDValue &Opc); 77193323Sed bool SelectAddrMode3Offset(SDValue Op, SDValue N, 78193323Sed SDValue &Offset, SDValue &Opc); 79198090Srdivacky bool SelectAddrMode4(SDValue Op, SDValue N, SDValue &Addr, 80198090Srdivacky SDValue &Mode); 81193323Sed bool SelectAddrMode5(SDValue Op, SDValue N, SDValue &Base, 82193323Sed SDValue &Offset); 83195340Sed bool SelectAddrMode6(SDValue Op, SDValue N, SDValue &Addr, SDValue &Update, 84199481Srdivacky SDValue &Opc, SDValue &Align); 85193323Sed 86193323Sed bool SelectAddrModePC(SDValue Op, SDValue N, SDValue &Offset, 87195340Sed SDValue &Label); 88193323Sed 89193323Sed bool SelectThumbAddrModeRR(SDValue Op, SDValue N, SDValue &Base, 90193323Sed SDValue &Offset); 91193323Sed bool SelectThumbAddrModeRI5(SDValue Op, SDValue N, unsigned Scale, 92193323Sed SDValue &Base, SDValue &OffImm, 93193323Sed SDValue &Offset); 94193323Sed bool SelectThumbAddrModeS1(SDValue Op, SDValue N, SDValue &Base, 95193323Sed SDValue &OffImm, SDValue &Offset); 96193323Sed bool SelectThumbAddrModeS2(SDValue Op, SDValue N, SDValue &Base, 97193323Sed SDValue &OffImm, SDValue &Offset); 98193323Sed bool SelectThumbAddrModeS4(SDValue Op, SDValue N, SDValue &Base, 99193323Sed SDValue &OffImm, SDValue &Offset); 100193323Sed bool SelectThumbAddrModeSP(SDValue Op, SDValue N, SDValue &Base, 101193323Sed SDValue &OffImm); 102193323Sed 103195098Sed bool SelectT2ShifterOperandReg(SDValue Op, SDValue N, 104195098Sed SDValue &BaseReg, SDValue &Opc); 105195340Sed bool SelectT2AddrModeImm12(SDValue Op, SDValue N, SDValue &Base, 106195340Sed SDValue &OffImm); 107195340Sed bool SelectT2AddrModeImm8(SDValue Op, SDValue N, SDValue &Base, 108195340Sed SDValue &OffImm); 109195340Sed bool SelectT2AddrModeImm8Offset(SDValue Op, SDValue N, 110195340Sed SDValue &OffImm); 111195340Sed bool SelectT2AddrModeImm8s4(SDValue Op, SDValue N, SDValue &Base, 112195340Sed SDValue &OffImm); 113195340Sed bool SelectT2AddrModeSoReg(SDValue Op, SDValue N, SDValue &Base, 114195340Sed SDValue &OffReg, SDValue &ShImm); 115195340Sed 116193323Sed // Include the pieces autogenerated from the target description. 117193323Sed#include "ARMGenDAGISel.inc" 118193323Sed 119193323Sedprivate: 120195340Sed /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for 121195340Sed /// ARM. 122195340Sed SDNode *SelectARMIndexedLoad(SDValue Op); 123195340Sed SDNode *SelectT2IndexedLoad(SDValue Op); 124195340Sed 125198090Srdivacky /// SelectDYN_ALLOC - Select dynamic alloc for Thumb. 126198090Srdivacky SDNode *SelectDYN_ALLOC(SDValue Op); 127195340Sed 128198090Srdivacky /// SelectVLD - Select NEON load intrinsics. NumVecs should 129198090Srdivacky /// be 2, 3 or 4. The opcode arrays specify the instructions used for 130198090Srdivacky /// loads of D registers and even subregs and odd subregs of Q registers. 131198090Srdivacky /// For NumVecs == 2, QOpcodes1 is not used. 132198090Srdivacky SDNode *SelectVLD(SDValue Op, unsigned NumVecs, unsigned *DOpcodes, 133198090Srdivacky unsigned *QOpcodes0, unsigned *QOpcodes1); 134198090Srdivacky 135198113Srdivacky /// SelectVST - Select NEON store intrinsics. NumVecs should 136198113Srdivacky /// be 2, 3 or 4. The opcode arrays specify the instructions used for 137198113Srdivacky /// stores of D registers and even subregs and odd subregs of Q registers. 138198113Srdivacky /// For NumVecs == 2, QOpcodes1 is not used. 139198113Srdivacky SDNode *SelectVST(SDValue Op, unsigned NumVecs, unsigned *DOpcodes, 140198113Srdivacky unsigned *QOpcodes0, unsigned *QOpcodes1); 141198113Srdivacky 142198090Srdivacky /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should 143198090Srdivacky /// be 2, 3 or 4. The opcode arrays specify the instructions used for 144198090Srdivacky /// load/store of D registers and even subregs and odd subregs of Q registers. 145198090Srdivacky SDNode *SelectVLDSTLane(SDValue Op, bool IsLoad, unsigned NumVecs, 146198090Srdivacky unsigned *DOpcodes, unsigned *QOpcodes0, 147198090Srdivacky unsigned *QOpcodes1); 148198090Srdivacky 149198090Srdivacky /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM. 150198090Srdivacky SDNode *SelectV6T2BitfieldExtractOp(SDValue Op, unsigned Opc); 151198090Srdivacky 152199989Srdivacky /// SelectCMOVOp - Select CMOV instructions for ARM. 153199989Srdivacky SDNode *SelectCMOVOp(SDValue Op); 154199989Srdivacky SDNode *SelectT2CMOVShiftOp(SDValue Op, SDValue FalseVal, SDValue TrueVal, 155199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 156199989Srdivacky SDValue InFlag); 157199989Srdivacky SDNode *SelectARMCMOVShiftOp(SDValue Op, SDValue FalseVal, SDValue TrueVal, 158199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 159199989Srdivacky SDValue InFlag); 160199989Srdivacky SDNode *SelectT2CMOVSoImmOp(SDValue Op, SDValue FalseVal, SDValue TrueVal, 161199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 162199989Srdivacky SDValue InFlag); 163199989Srdivacky SDNode *SelectARMCMOVSoImmOp(SDValue Op, SDValue FalseVal, SDValue TrueVal, 164199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 165199989Srdivacky SDValue InFlag); 166199989Srdivacky 167195340Sed /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for 168195340Sed /// inline asm expressions. 169195340Sed virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, 170195340Sed char ConstraintCode, 171195340Sed std::vector<SDValue> &OutOps); 172198090Srdivacky 173198090Srdivacky /// PairDRegs - Insert a pair of double registers into an implicit def to 174198090Srdivacky /// form a quad register. 175198090Srdivacky SDNode *PairDRegs(EVT VT, SDValue V0, SDValue V1); 176193323Sed}; 177193323Sed} 178193323Sed 179198090Srdivacky/// isInt32Immediate - This method tests to see if the node is a 32-bit constant 180198090Srdivacky/// operand. If so Imm will receive the 32-bit value. 181198090Srdivackystatic bool isInt32Immediate(SDNode *N, unsigned &Imm) { 182198090Srdivacky if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) { 183198090Srdivacky Imm = cast<ConstantSDNode>(N)->getZExtValue(); 184198090Srdivacky return true; 185198090Srdivacky } 186198090Srdivacky return false; 187198090Srdivacky} 188198090Srdivacky 189198090Srdivacky// isInt32Immediate - This method tests to see if a constant operand. 190198090Srdivacky// If so Imm will receive the 32 bit value. 191198090Srdivackystatic bool isInt32Immediate(SDValue N, unsigned &Imm) { 192198090Srdivacky return isInt32Immediate(N.getNode(), Imm); 193198090Srdivacky} 194198090Srdivacky 195198090Srdivacky// isOpcWithIntImmediate - This method tests to see if the node is a specific 196198090Srdivacky// opcode and that it has a immediate integer right operand. 197198090Srdivacky// If so Imm will receive the 32 bit value. 198198090Srdivackystatic bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) { 199198090Srdivacky return N->getOpcode() == Opc && 200198090Srdivacky isInt32Immediate(N->getOperand(1).getNode(), Imm); 201198090Srdivacky} 202198090Srdivacky 203198090Srdivacky 204193323Sedvoid ARMDAGToDAGISel::InstructionSelect() { 205193323Sed SelectRoot(*CurDAG); 206193323Sed CurDAG->RemoveDeadNodes(); 207193323Sed} 208193323Sed 209195340Sedbool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue Op, 210195340Sed SDValue N, 211195340Sed SDValue &BaseReg, 212195340Sed SDValue &ShReg, 213195340Sed SDValue &Opc) { 214195340Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 215195340Sed 216195340Sed // Don't match base register only case. That is matched to a separate 217195340Sed // lower complexity pattern with explicit register operand. 218195340Sed if (ShOpcVal == ARM_AM::no_shift) return false; 219198090Srdivacky 220195340Sed BaseReg = N.getOperand(0); 221195340Sed unsigned ShImmVal = 0; 222195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 223195340Sed ShReg = CurDAG->getRegister(0, MVT::i32); 224195340Sed ShImmVal = RHS->getZExtValue() & 31; 225195340Sed } else { 226195340Sed ShReg = N.getOperand(1); 227195340Sed } 228195340Sed Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), 229195340Sed MVT::i32); 230195340Sed return true; 231195340Sed} 232195340Sed 233193323Sedbool ARMDAGToDAGISel::SelectAddrMode2(SDValue Op, SDValue N, 234193323Sed SDValue &Base, SDValue &Offset, 235193323Sed SDValue &Opc) { 236193323Sed if (N.getOpcode() == ISD::MUL) { 237193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 238193323Sed // X * [3,5,9] -> X + X * [2,4,8] etc. 239193323Sed int RHSC = (int)RHS->getZExtValue(); 240193323Sed if (RHSC & 1) { 241193323Sed RHSC = RHSC & ~1; 242193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 243193323Sed if (RHSC < 0) { 244193323Sed AddSub = ARM_AM::sub; 245193323Sed RHSC = - RHSC; 246193323Sed } 247193323Sed if (isPowerOf2_32(RHSC)) { 248193323Sed unsigned ShAmt = Log2_32(RHSC); 249193323Sed Base = Offset = N.getOperand(0); 250193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, 251193323Sed ARM_AM::lsl), 252193323Sed MVT::i32); 253193323Sed return true; 254193323Sed } 255193323Sed } 256193323Sed } 257193323Sed } 258193323Sed 259193323Sed if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) { 260193323Sed Base = N; 261193323Sed if (N.getOpcode() == ISD::FrameIndex) { 262193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 263193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 264199989Srdivacky } else if (N.getOpcode() == ARMISD::Wrapper && 265199989Srdivacky !(Subtarget->useMovt() && 266199989Srdivacky N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { 267193323Sed Base = N.getOperand(0); 268193323Sed } 269193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 270193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, 271193323Sed ARM_AM::no_shift), 272193323Sed MVT::i32); 273193323Sed return true; 274193323Sed } 275198090Srdivacky 276193323Sed // Match simple R +/- imm12 operands. 277193323Sed if (N.getOpcode() == ISD::ADD) 278193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 279193323Sed int RHSC = (int)RHS->getZExtValue(); 280193323Sed if ((RHSC >= 0 && RHSC < 0x1000) || 281193323Sed (RHSC < 0 && RHSC > -0x1000)) { // 12 bits. 282193323Sed Base = N.getOperand(0); 283193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 284193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 285193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 286193323Sed } 287193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 288193323Sed 289193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 290193323Sed if (RHSC < 0) { 291193323Sed AddSub = ARM_AM::sub; 292193323Sed RHSC = - RHSC; 293193323Sed } 294193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC, 295193323Sed ARM_AM::no_shift), 296193323Sed MVT::i32); 297193323Sed return true; 298193323Sed } 299193323Sed } 300198090Srdivacky 301198892Srdivacky // Otherwise this is R +/- [possibly shifted] R. 302193323Sed ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::ADD ? ARM_AM::add:ARM_AM::sub; 303193323Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1)); 304193323Sed unsigned ShAmt = 0; 305198090Srdivacky 306193323Sed Base = N.getOperand(0); 307193323Sed Offset = N.getOperand(1); 308198090Srdivacky 309193323Sed if (ShOpcVal != ARM_AM::no_shift) { 310193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 311193323Sed // it. 312193323Sed if (ConstantSDNode *Sh = 313193323Sed dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) { 314193323Sed ShAmt = Sh->getZExtValue(); 315193323Sed Offset = N.getOperand(1).getOperand(0); 316193323Sed } else { 317193323Sed ShOpcVal = ARM_AM::no_shift; 318193323Sed } 319193323Sed } 320198090Srdivacky 321193323Sed // Try matching (R shl C) + (R). 322193323Sed if (N.getOpcode() == ISD::ADD && ShOpcVal == ARM_AM::no_shift) { 323193323Sed ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0)); 324193323Sed if (ShOpcVal != ARM_AM::no_shift) { 325193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't 326193323Sed // fold it. 327193323Sed if (ConstantSDNode *Sh = 328193323Sed dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) { 329193323Sed ShAmt = Sh->getZExtValue(); 330193323Sed Offset = N.getOperand(0).getOperand(0); 331193323Sed Base = N.getOperand(1); 332193323Sed } else { 333193323Sed ShOpcVal = ARM_AM::no_shift; 334193323Sed } 335193323Sed } 336193323Sed } 337198090Srdivacky 338193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 339193323Sed MVT::i32); 340193323Sed return true; 341193323Sed} 342193323Sed 343193323Sedbool ARMDAGToDAGISel::SelectAddrMode2Offset(SDValue Op, SDValue N, 344193323Sed SDValue &Offset, SDValue &Opc) { 345193323Sed unsigned Opcode = Op.getOpcode(); 346193323Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 347193323Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 348193323Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 349193323Sed ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 350193323Sed ? ARM_AM::add : ARM_AM::sub; 351193323Sed if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 352193323Sed int Val = (int)C->getZExtValue(); 353193323Sed if (Val >= 0 && Val < 0x1000) { // 12 bits. 354193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 355193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val, 356193323Sed ARM_AM::no_shift), 357193323Sed MVT::i32); 358193323Sed return true; 359193323Sed } 360193323Sed } 361193323Sed 362193323Sed Offset = N; 363193323Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 364193323Sed unsigned ShAmt = 0; 365193323Sed if (ShOpcVal != ARM_AM::no_shift) { 366193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 367193323Sed // it. 368193323Sed if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 369193323Sed ShAmt = Sh->getZExtValue(); 370193323Sed Offset = N.getOperand(0); 371193323Sed } else { 372193323Sed ShOpcVal = ARM_AM::no_shift; 373193323Sed } 374193323Sed } 375193323Sed 376193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 377193323Sed MVT::i32); 378193323Sed return true; 379193323Sed} 380193323Sed 381193323Sed 382193323Sedbool ARMDAGToDAGISel::SelectAddrMode3(SDValue Op, SDValue N, 383193323Sed SDValue &Base, SDValue &Offset, 384193323Sed SDValue &Opc) { 385193323Sed if (N.getOpcode() == ISD::SUB) { 386193323Sed // X - C is canonicalize to X + -C, no need to handle it here. 387193323Sed Base = N.getOperand(0); 388193323Sed Offset = N.getOperand(1); 389193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32); 390193323Sed return true; 391193323Sed } 392198090Srdivacky 393193323Sed if (N.getOpcode() != ISD::ADD) { 394193323Sed Base = N; 395193323Sed if (N.getOpcode() == ISD::FrameIndex) { 396193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 397193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 398193323Sed } 399193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 400193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32); 401193323Sed return true; 402193323Sed } 403198090Srdivacky 404193323Sed // If the RHS is +/- imm8, fold into addr mode. 405193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 406193323Sed int RHSC = (int)RHS->getZExtValue(); 407193323Sed if ((RHSC >= 0 && RHSC < 256) || 408193323Sed (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed. 409193323Sed Base = N.getOperand(0); 410193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 411193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 412193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 413193323Sed } 414193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 415193323Sed 416193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 417193323Sed if (RHSC < 0) { 418193323Sed AddSub = ARM_AM::sub; 419193323Sed RHSC = - RHSC; 420193323Sed } 421193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32); 422193323Sed return true; 423193323Sed } 424193323Sed } 425198090Srdivacky 426193323Sed Base = N.getOperand(0); 427193323Sed Offset = N.getOperand(1); 428193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32); 429193323Sed return true; 430193323Sed} 431193323Sed 432193323Sedbool ARMDAGToDAGISel::SelectAddrMode3Offset(SDValue Op, SDValue N, 433193323Sed SDValue &Offset, SDValue &Opc) { 434193323Sed unsigned Opcode = Op.getOpcode(); 435193323Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 436193323Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 437193323Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 438193323Sed ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 439193323Sed ? ARM_AM::add : ARM_AM::sub; 440193323Sed if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 441193323Sed int Val = (int)C->getZExtValue(); 442193323Sed if (Val >= 0 && Val < 256) { 443193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 444193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32); 445193323Sed return true; 446193323Sed } 447193323Sed } 448193323Sed 449193323Sed Offset = N; 450193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32); 451193323Sed return true; 452193323Sed} 453193323Sed 454198090Srdivackybool ARMDAGToDAGISel::SelectAddrMode4(SDValue Op, SDValue N, 455198090Srdivacky SDValue &Addr, SDValue &Mode) { 456198090Srdivacky Addr = N; 457198090Srdivacky Mode = CurDAG->getTargetConstant(0, MVT::i32); 458198090Srdivacky return true; 459198090Srdivacky} 460193323Sed 461193323Sedbool ARMDAGToDAGISel::SelectAddrMode5(SDValue Op, SDValue N, 462193323Sed SDValue &Base, SDValue &Offset) { 463193323Sed if (N.getOpcode() != ISD::ADD) { 464193323Sed Base = N; 465193323Sed if (N.getOpcode() == ISD::FrameIndex) { 466193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 467193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 468199989Srdivacky } else if (N.getOpcode() == ARMISD::Wrapper && 469199989Srdivacky !(Subtarget->useMovt() && 470199989Srdivacky N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { 471193323Sed Base = N.getOperand(0); 472193323Sed } 473193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 474193323Sed MVT::i32); 475193323Sed return true; 476193323Sed } 477198090Srdivacky 478193323Sed // If the RHS is +/- imm8, fold into addr mode. 479193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 480193323Sed int RHSC = (int)RHS->getZExtValue(); 481193323Sed if ((RHSC & 3) == 0) { // The constant is implicitly multiplied by 4. 482193323Sed RHSC >>= 2; 483193323Sed if ((RHSC >= 0 && RHSC < 256) || 484193323Sed (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed. 485193323Sed Base = N.getOperand(0); 486193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 487193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 488193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 489193323Sed } 490193323Sed 491193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 492193323Sed if (RHSC < 0) { 493193323Sed AddSub = ARM_AM::sub; 494193323Sed RHSC = - RHSC; 495193323Sed } 496193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC), 497193323Sed MVT::i32); 498193323Sed return true; 499193323Sed } 500193323Sed } 501193323Sed } 502198090Srdivacky 503193323Sed Base = N; 504193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 505193323Sed MVT::i32); 506193323Sed return true; 507193323Sed} 508193323Sed 509195340Sedbool ARMDAGToDAGISel::SelectAddrMode6(SDValue Op, SDValue N, 510195340Sed SDValue &Addr, SDValue &Update, 511199481Srdivacky SDValue &Opc, SDValue &Align) { 512195340Sed Addr = N; 513198090Srdivacky // Default to no writeback. 514195340Sed Update = CurDAG->getRegister(0, MVT::i32); 515195340Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(false), MVT::i32); 516199481Srdivacky // Default to no alignment. 517199481Srdivacky Align = CurDAG->getTargetConstant(0, MVT::i32); 518195340Sed return true; 519195340Sed} 520195340Sed 521193323Sedbool ARMDAGToDAGISel::SelectAddrModePC(SDValue Op, SDValue N, 522198090Srdivacky SDValue &Offset, SDValue &Label) { 523193323Sed if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) { 524193323Sed Offset = N.getOperand(0); 525193323Sed SDValue N1 = N.getOperand(1); 526193323Sed Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(), 527193323Sed MVT::i32); 528193323Sed return true; 529193323Sed } 530193323Sed return false; 531193323Sed} 532193323Sed 533193323Sedbool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue Op, SDValue N, 534193323Sed SDValue &Base, SDValue &Offset){ 535193323Sed // FIXME dl should come from the parent load or store, not the address 536193323Sed DebugLoc dl = Op.getDebugLoc(); 537193323Sed if (N.getOpcode() != ISD::ADD) { 538198090Srdivacky ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N); 539198090Srdivacky if (!NC || NC->getZExtValue() != 0) 540198090Srdivacky return false; 541198090Srdivacky 542198090Srdivacky Base = Offset = N; 543193323Sed return true; 544193323Sed } 545193323Sed 546193323Sed Base = N.getOperand(0); 547193323Sed Offset = N.getOperand(1); 548193323Sed return true; 549193323Sed} 550193323Sed 551193323Sedbool 552193323SedARMDAGToDAGISel::SelectThumbAddrModeRI5(SDValue Op, SDValue N, 553193323Sed unsigned Scale, SDValue &Base, 554193323Sed SDValue &OffImm, SDValue &Offset) { 555193323Sed if (Scale == 4) { 556193323Sed SDValue TmpBase, TmpOffImm; 557193323Sed if (SelectThumbAddrModeSP(Op, N, TmpBase, TmpOffImm)) 558193323Sed return false; // We want to select tLDRspi / tSTRspi instead. 559193323Sed if (N.getOpcode() == ARMISD::Wrapper && 560193323Sed N.getOperand(0).getOpcode() == ISD::TargetConstantPool) 561193323Sed return false; // We want to select tLDRpci instead. 562193323Sed } 563193323Sed 564193323Sed if (N.getOpcode() != ISD::ADD) { 565199989Srdivacky if (N.getOpcode() == ARMISD::Wrapper && 566199989Srdivacky !(Subtarget->useMovt() && 567199989Srdivacky N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { 568199989Srdivacky Base = N.getOperand(0); 569199989Srdivacky } else 570199989Srdivacky Base = N; 571199989Srdivacky 572193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 573193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 574193323Sed return true; 575193323Sed } 576193323Sed 577193323Sed // Thumb does not have [sp, r] address mode. 578193323Sed RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 579193323Sed RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1)); 580193323Sed if ((LHSR && LHSR->getReg() == ARM::SP) || 581193323Sed (RHSR && RHSR->getReg() == ARM::SP)) { 582193323Sed Base = N; 583193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 584193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 585193323Sed return true; 586193323Sed } 587193323Sed 588193323Sed // If the RHS is + imm5 * scale, fold into addr mode. 589193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 590193323Sed int RHSC = (int)RHS->getZExtValue(); 591193323Sed if ((RHSC & (Scale-1)) == 0) { // The constant is implicitly multiplied. 592193323Sed RHSC /= Scale; 593193323Sed if (RHSC >= 0 && RHSC < 32) { 594193323Sed Base = N.getOperand(0); 595193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 596193323Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 597193323Sed return true; 598193323Sed } 599193323Sed } 600193323Sed } 601193323Sed 602193323Sed Base = N.getOperand(0); 603193323Sed Offset = N.getOperand(1); 604193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 605193323Sed return true; 606193323Sed} 607193323Sed 608193323Sedbool ARMDAGToDAGISel::SelectThumbAddrModeS1(SDValue Op, SDValue N, 609193323Sed SDValue &Base, SDValue &OffImm, 610193323Sed SDValue &Offset) { 611193323Sed return SelectThumbAddrModeRI5(Op, N, 1, Base, OffImm, Offset); 612193323Sed} 613193323Sed 614193323Sedbool ARMDAGToDAGISel::SelectThumbAddrModeS2(SDValue Op, SDValue N, 615193323Sed SDValue &Base, SDValue &OffImm, 616193323Sed SDValue &Offset) { 617193323Sed return SelectThumbAddrModeRI5(Op, N, 2, Base, OffImm, Offset); 618193323Sed} 619193323Sed 620193323Sedbool ARMDAGToDAGISel::SelectThumbAddrModeS4(SDValue Op, SDValue N, 621193323Sed SDValue &Base, SDValue &OffImm, 622193323Sed SDValue &Offset) { 623193323Sed return SelectThumbAddrModeRI5(Op, N, 4, Base, OffImm, Offset); 624193323Sed} 625193323Sed 626193323Sedbool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue Op, SDValue N, 627193323Sed SDValue &Base, SDValue &OffImm) { 628193323Sed if (N.getOpcode() == ISD::FrameIndex) { 629193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 630193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 631193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 632193323Sed return true; 633193323Sed } 634193323Sed 635193323Sed if (N.getOpcode() != ISD::ADD) 636193323Sed return false; 637193323Sed 638193323Sed RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 639193323Sed if (N.getOperand(0).getOpcode() == ISD::FrameIndex || 640193323Sed (LHSR && LHSR->getReg() == ARM::SP)) { 641193323Sed // If the RHS is + imm8 * scale, fold into addr mode. 642193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 643193323Sed int RHSC = (int)RHS->getZExtValue(); 644193323Sed if ((RHSC & 3) == 0) { // The constant is implicitly multiplied. 645193323Sed RHSC >>= 2; 646193323Sed if (RHSC >= 0 && RHSC < 256) { 647193323Sed Base = N.getOperand(0); 648193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 649193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 650193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 651193323Sed } 652193323Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 653193323Sed return true; 654193323Sed } 655193323Sed } 656193323Sed } 657193323Sed } 658198090Srdivacky 659193323Sed return false; 660193323Sed} 661193323Sed 662195098Sedbool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue Op, SDValue N, 663195098Sed SDValue &BaseReg, 664195098Sed SDValue &Opc) { 665195098Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 666195098Sed 667195098Sed // Don't match base register only case. That is matched to a separate 668195098Sed // lower complexity pattern with explicit register operand. 669195098Sed if (ShOpcVal == ARM_AM::no_shift) return false; 670195098Sed 671195098Sed BaseReg = N.getOperand(0); 672195098Sed unsigned ShImmVal = 0; 673195098Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 674195098Sed ShImmVal = RHS->getZExtValue() & 31; 675195098Sed Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal)); 676195098Sed return true; 677195098Sed } 678195098Sed 679195098Sed return false; 680195098Sed} 681195098Sed 682195340Sedbool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue Op, SDValue N, 683195340Sed SDValue &Base, SDValue &OffImm) { 684195340Sed // Match simple R + imm12 operands. 685195340Sed 686198090Srdivacky // Base only. 687198090Srdivacky if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) { 688198090Srdivacky if (N.getOpcode() == ISD::FrameIndex) { 689198090Srdivacky // Match frame index... 690198090Srdivacky int FI = cast<FrameIndexSDNode>(N)->getIndex(); 691198090Srdivacky Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 692198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 693198090Srdivacky return true; 694199989Srdivacky } else if (N.getOpcode() == ARMISD::Wrapper && 695199989Srdivacky !(Subtarget->useMovt() && 696199989Srdivacky N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { 697198090Srdivacky Base = N.getOperand(0); 698198090Srdivacky if (Base.getOpcode() == ISD::TargetConstantPool) 699198090Srdivacky return false; // We want to select t2LDRpci instead. 700198090Srdivacky } else 701198090Srdivacky Base = N; 702198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 703198090Srdivacky return true; 704198090Srdivacky } 705198090Srdivacky 706195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 707198090Srdivacky if (SelectT2AddrModeImm8(Op, N, Base, OffImm)) 708198090Srdivacky // Let t2LDRi8 handle (R - imm8). 709198090Srdivacky return false; 710198090Srdivacky 711195340Sed int RHSC = (int)RHS->getZExtValue(); 712198090Srdivacky if (N.getOpcode() == ISD::SUB) 713198090Srdivacky RHSC = -RHSC; 714198090Srdivacky 715198090Srdivacky if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned) 716195340Sed Base = N.getOperand(0); 717198090Srdivacky if (Base.getOpcode() == ISD::FrameIndex) { 718198090Srdivacky int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 719198090Srdivacky Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 720198090Srdivacky } 721195340Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 722195340Sed return true; 723195340Sed } 724195340Sed } 725195340Sed 726198090Srdivacky // Base only. 727198090Srdivacky Base = N; 728198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 729198090Srdivacky return true; 730195340Sed} 731195340Sed 732195340Sedbool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue Op, SDValue N, 733195340Sed SDValue &Base, SDValue &OffImm) { 734198090Srdivacky // Match simple R - imm8 operands. 735198090Srdivacky if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::SUB) { 736195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 737198090Srdivacky int RHSC = (int)RHS->getSExtValue(); 738198090Srdivacky if (N.getOpcode() == ISD::SUB) 739198090Srdivacky RHSC = -RHSC; 740198090Srdivacky 741198090Srdivacky if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative) 742198090Srdivacky Base = N.getOperand(0); 743198090Srdivacky if (Base.getOpcode() == ISD::FrameIndex) { 744198090Srdivacky int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 745198090Srdivacky Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 746198090Srdivacky } 747195340Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 748195340Sed return true; 749195340Sed } 750195340Sed } 751195340Sed } 752195340Sed 753195340Sed return false; 754195340Sed} 755195340Sed 756195340Sedbool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDValue Op, SDValue N, 757195340Sed SDValue &OffImm){ 758195340Sed unsigned Opcode = Op.getOpcode(); 759195340Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 760195340Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 761195340Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 762195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N)) { 763195340Sed int RHSC = (int)RHS->getZExtValue(); 764195340Sed if (RHSC >= 0 && RHSC < 0x100) { // 8 bits. 765198090Srdivacky OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC)) 766195340Sed ? CurDAG->getTargetConstant(RHSC, MVT::i32) 767195340Sed : CurDAG->getTargetConstant(-RHSC, MVT::i32); 768195340Sed return true; 769195340Sed } 770195340Sed } 771195340Sed 772195340Sed return false; 773195340Sed} 774195340Sed 775195340Sedbool ARMDAGToDAGISel::SelectT2AddrModeImm8s4(SDValue Op, SDValue N, 776195340Sed SDValue &Base, SDValue &OffImm) { 777195340Sed if (N.getOpcode() == ISD::ADD) { 778195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 779195340Sed int RHSC = (int)RHS->getZExtValue(); 780198090Srdivacky if (((RHSC & 0x3) == 0) && 781198090Srdivacky ((RHSC >= 0 && RHSC < 0x400) || (RHSC < 0 && RHSC > -0x400))) { // 8 bits. 782195340Sed Base = N.getOperand(0); 783195340Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 784195340Sed return true; 785195340Sed } 786195340Sed } 787195340Sed } else if (N.getOpcode() == ISD::SUB) { 788195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 789195340Sed int RHSC = (int)RHS->getZExtValue(); 790195340Sed if (((RHSC & 0x3) == 0) && (RHSC >= 0 && RHSC < 0x400)) { // 8 bits. 791195340Sed Base = N.getOperand(0); 792195340Sed OffImm = CurDAG->getTargetConstant(-RHSC, MVT::i32); 793195340Sed return true; 794195340Sed } 795195340Sed } 796195340Sed } 797195340Sed 798195340Sed return false; 799195340Sed} 800195340Sed 801195340Sedbool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue Op, SDValue N, 802195340Sed SDValue &Base, 803195340Sed SDValue &OffReg, SDValue &ShImm) { 804198090Srdivacky // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12. 805198090Srdivacky if (N.getOpcode() != ISD::ADD) 806198090Srdivacky return false; 807198090Srdivacky 808198090Srdivacky // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8. 809198090Srdivacky if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 810198090Srdivacky int RHSC = (int)RHS->getZExtValue(); 811198090Srdivacky if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned) 812198090Srdivacky return false; 813198090Srdivacky else if (RHSC < 0 && RHSC >= -255) // 8 bits 814198090Srdivacky return false; 815195340Sed } 816195340Sed 817195340Sed // Look for (R + R) or (R + (R << [1,2,3])). 818195340Sed unsigned ShAmt = 0; 819195340Sed Base = N.getOperand(0); 820195340Sed OffReg = N.getOperand(1); 821195340Sed 822195340Sed // Swap if it is ((R << c) + R). 823195340Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg); 824195340Sed if (ShOpcVal != ARM_AM::lsl) { 825195340Sed ShOpcVal = ARM_AM::getShiftOpcForNode(Base); 826195340Sed if (ShOpcVal == ARM_AM::lsl) 827195340Sed std::swap(Base, OffReg); 828198090Srdivacky } 829198090Srdivacky 830195340Sed if (ShOpcVal == ARM_AM::lsl) { 831195340Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 832195340Sed // it. 833195340Sed if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) { 834195340Sed ShAmt = Sh->getZExtValue(); 835195340Sed if (ShAmt >= 4) { 836195340Sed ShAmt = 0; 837195340Sed ShOpcVal = ARM_AM::no_shift; 838195340Sed } else 839195340Sed OffReg = OffReg.getOperand(0); 840195340Sed } else { 841195340Sed ShOpcVal = ARM_AM::no_shift; 842195340Sed } 843198090Srdivacky } 844198090Srdivacky 845195340Sed ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32); 846195340Sed 847195340Sed return true; 848195340Sed} 849195340Sed 850195340Sed//===--------------------------------------------------------------------===// 851195340Sed 852193323Sed/// getAL - Returns a ARMCC::AL immediate node. 853193323Sedstatic inline SDValue getAL(SelectionDAG *CurDAG) { 854193323Sed return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32); 855193323Sed} 856193323Sed 857195340SedSDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDValue Op) { 858195340Sed LoadSDNode *LD = cast<LoadSDNode>(Op); 859195340Sed ISD::MemIndexedMode AM = LD->getAddressingMode(); 860195340Sed if (AM == ISD::UNINDEXED) 861195340Sed return NULL; 862193323Sed 863198090Srdivacky EVT LoadedVT = LD->getMemoryVT(); 864195340Sed SDValue Offset, AMOpc; 865195340Sed bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 866195340Sed unsigned Opcode = 0; 867195340Sed bool Match = false; 868195340Sed if (LoadedVT == MVT::i32 && 869195340Sed SelectAddrMode2Offset(Op, LD->getOffset(), Offset, AMOpc)) { 870195340Sed Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST; 871195340Sed Match = true; 872195340Sed } else if (LoadedVT == MVT::i16 && 873195340Sed SelectAddrMode3Offset(Op, LD->getOffset(), Offset, AMOpc)) { 874195340Sed Match = true; 875195340Sed Opcode = (LD->getExtensionType() == ISD::SEXTLOAD) 876195340Sed ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST) 877195340Sed : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST); 878195340Sed } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) { 879195340Sed if (LD->getExtensionType() == ISD::SEXTLOAD) { 880195340Sed if (SelectAddrMode3Offset(Op, LD->getOffset(), Offset, AMOpc)) { 881195340Sed Match = true; 882195340Sed Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST; 883195340Sed } 884195340Sed } else { 885195340Sed if (SelectAddrMode2Offset(Op, LD->getOffset(), Offset, AMOpc)) { 886195340Sed Match = true; 887195340Sed Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST; 888195340Sed } 889195340Sed } 890195340Sed } 891195340Sed 892195340Sed if (Match) { 893195340Sed SDValue Chain = LD->getChain(); 894195340Sed SDValue Base = LD->getBasePtr(); 895195340Sed SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG), 896195340Sed CurDAG->getRegister(0, MVT::i32), Chain }; 897198090Srdivacky return CurDAG->getMachineNode(Opcode, Op.getDebugLoc(), MVT::i32, MVT::i32, 898198090Srdivacky MVT::Other, Ops, 6); 899195340Sed } 900195340Sed 901195340Sed return NULL; 902195340Sed} 903195340Sed 904195340SedSDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDValue Op) { 905195340Sed LoadSDNode *LD = cast<LoadSDNode>(Op); 906195340Sed ISD::MemIndexedMode AM = LD->getAddressingMode(); 907195340Sed if (AM == ISD::UNINDEXED) 908195340Sed return NULL; 909195340Sed 910198090Srdivacky EVT LoadedVT = LD->getMemoryVT(); 911195340Sed bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD; 912195340Sed SDValue Offset; 913195340Sed bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 914195340Sed unsigned Opcode = 0; 915195340Sed bool Match = false; 916195340Sed if (SelectT2AddrModeImm8Offset(Op, LD->getOffset(), Offset)) { 917198090Srdivacky switch (LoadedVT.getSimpleVT().SimpleTy) { 918195340Sed case MVT::i32: 919195340Sed Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST; 920195340Sed break; 921195340Sed case MVT::i16: 922195340Sed if (isSExtLd) 923195340Sed Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST; 924195340Sed else 925195340Sed Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST; 926195340Sed break; 927195340Sed case MVT::i8: 928195340Sed case MVT::i1: 929195340Sed if (isSExtLd) 930195340Sed Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST; 931195340Sed else 932195340Sed Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST; 933195340Sed break; 934195340Sed default: 935195340Sed return NULL; 936195340Sed } 937195340Sed Match = true; 938195340Sed } 939195340Sed 940195340Sed if (Match) { 941195340Sed SDValue Chain = LD->getChain(); 942195340Sed SDValue Base = LD->getBasePtr(); 943195340Sed SDValue Ops[]= { Base, Offset, getAL(CurDAG), 944195340Sed CurDAG->getRegister(0, MVT::i32), Chain }; 945198090Srdivacky return CurDAG->getMachineNode(Opcode, Op.getDebugLoc(), MVT::i32, MVT::i32, 946198090Srdivacky MVT::Other, Ops, 5); 947195340Sed } 948195340Sed 949195340Sed return NULL; 950195340Sed} 951195340Sed 952198090SrdivackySDNode *ARMDAGToDAGISel::SelectDYN_ALLOC(SDValue Op) { 953198090Srdivacky SDNode *N = Op.getNode(); 954198090Srdivacky DebugLoc dl = N->getDebugLoc(); 955198090Srdivacky EVT VT = Op.getValueType(); 956198090Srdivacky SDValue Chain = Op.getOperand(0); 957198090Srdivacky SDValue Size = Op.getOperand(1); 958198090Srdivacky SDValue Align = Op.getOperand(2); 959198090Srdivacky SDValue SP = CurDAG->getRegister(ARM::SP, MVT::i32); 960198090Srdivacky int32_t AlignVal = cast<ConstantSDNode>(Align)->getSExtValue(); 961198090Srdivacky if (AlignVal < 0) 962198090Srdivacky // We need to align the stack. Use Thumb1 tAND which is the only thumb 963198090Srdivacky // instruction that can read and write SP. This matches to a pseudo 964198090Srdivacky // instruction that has a chain to ensure the result is written back to 965198090Srdivacky // the stack pointer. 966198090Srdivacky SP = SDValue(CurDAG->getMachineNode(ARM::tANDsp, dl, VT, SP, Align), 0); 967195340Sed 968198090Srdivacky bool isC = isa<ConstantSDNode>(Size); 969198090Srdivacky uint32_t C = isC ? cast<ConstantSDNode>(Size)->getZExtValue() : ~0UL; 970198090Srdivacky // Handle the most common case for both Thumb1 and Thumb2: 971198090Srdivacky // tSUBspi - immediate is between 0 ... 508 inclusive. 972198090Srdivacky if (C <= 508 && ((C & 3) == 0)) 973198090Srdivacky // FIXME: tSUBspi encode scale 4 implicitly. 974198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::tSUBspi_, VT, MVT::Other, SP, 975198090Srdivacky CurDAG->getTargetConstant(C/4, MVT::i32), 976198090Srdivacky Chain); 977198090Srdivacky 978198090Srdivacky if (Subtarget->isThumb1Only()) { 979198090Srdivacky // Use tADDspr since Thumb1 does not have a sub r, sp, r. ARMISelLowering 980198090Srdivacky // should have negated the size operand already. FIXME: We can't insert 981198090Srdivacky // new target independent node at this stage so we are forced to negate 982198090Srdivacky // it earlier. Is there a better solution? 983198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::tADDspr_, VT, MVT::Other, SP, Size, 984198090Srdivacky Chain); 985198090Srdivacky } else if (Subtarget->isThumb2()) { 986198090Srdivacky if (isC && Predicate_t2_so_imm(Size.getNode())) { 987198090Srdivacky // t2SUBrSPi 988198090Srdivacky SDValue Ops[] = { SP, CurDAG->getTargetConstant(C, MVT::i32), Chain }; 989198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPi_, VT, MVT::Other, Ops, 3); 990198090Srdivacky } else if (isC && Predicate_imm0_4095(Size.getNode())) { 991198090Srdivacky // t2SUBrSPi12 992198090Srdivacky SDValue Ops[] = { SP, CurDAG->getTargetConstant(C, MVT::i32), Chain }; 993198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPi12_, VT, MVT::Other, Ops, 3); 994198090Srdivacky } else { 995198090Srdivacky // t2SUBrSPs 996198090Srdivacky SDValue Ops[] = { SP, Size, 997198090Srdivacky getI32Imm(ARM_AM::getSORegOpc(ARM_AM::lsl,0)), Chain }; 998198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPs_, VT, MVT::Other, Ops, 4); 999198090Srdivacky } 1000198090Srdivacky } 1001198090Srdivacky 1002198090Srdivacky // FIXME: Add ADD / SUB sp instructions for ARM. 1003198090Srdivacky return 0; 1004198090Srdivacky} 1005198090Srdivacky 1006198090Srdivacky/// PairDRegs - Insert a pair of double registers into an implicit def to 1007198090Srdivacky/// form a quad register. 1008198090SrdivackySDNode *ARMDAGToDAGISel::PairDRegs(EVT VT, SDValue V0, SDValue V1) { 1009198090Srdivacky DebugLoc dl = V0.getNode()->getDebugLoc(); 1010198090Srdivacky SDValue Undef = 1011198090Srdivacky SDValue(CurDAG->getMachineNode(TargetInstrInfo::IMPLICIT_DEF, dl, VT), 0); 1012198090Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::DSUBREG_0, MVT::i32); 1013198090Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::DSUBREG_1, MVT::i32); 1014198090Srdivacky SDNode *Pair = CurDAG->getMachineNode(TargetInstrInfo::INSERT_SUBREG, dl, 1015198090Srdivacky VT, Undef, V0, SubReg0); 1016198090Srdivacky return CurDAG->getMachineNode(TargetInstrInfo::INSERT_SUBREG, dl, 1017198090Srdivacky VT, SDValue(Pair, 0), V1, SubReg1); 1018198090Srdivacky} 1019198090Srdivacky 1020198090Srdivacky/// GetNEONSubregVT - Given a type for a 128-bit NEON vector, return the type 1021198090Srdivacky/// for a 64-bit subregister of the vector. 1022198090Srdivackystatic EVT GetNEONSubregVT(EVT VT) { 1023198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1024198090Srdivacky default: llvm_unreachable("unhandled NEON type"); 1025198090Srdivacky case MVT::v16i8: return MVT::v8i8; 1026198090Srdivacky case MVT::v8i16: return MVT::v4i16; 1027198090Srdivacky case MVT::v4f32: return MVT::v2f32; 1028198090Srdivacky case MVT::v4i32: return MVT::v2i32; 1029198090Srdivacky case MVT::v2i64: return MVT::v1i64; 1030198090Srdivacky } 1031198090Srdivacky} 1032198090Srdivacky 1033198090SrdivackySDNode *ARMDAGToDAGISel::SelectVLD(SDValue Op, unsigned NumVecs, 1034198090Srdivacky unsigned *DOpcodes, unsigned *QOpcodes0, 1035198090Srdivacky unsigned *QOpcodes1) { 1036198090Srdivacky assert(NumVecs >=2 && NumVecs <= 4 && "VLD NumVecs out-of-range"); 1037198090Srdivacky SDNode *N = Op.getNode(); 1038198090Srdivacky DebugLoc dl = N->getDebugLoc(); 1039198090Srdivacky 1040199481Srdivacky SDValue MemAddr, MemUpdate, MemOpc, Align; 1041199481Srdivacky if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc, Align)) 1042198090Srdivacky return NULL; 1043198090Srdivacky 1044198090Srdivacky SDValue Chain = N->getOperand(0); 1045198090Srdivacky EVT VT = N->getValueType(0); 1046198090Srdivacky bool is64BitVector = VT.is64BitVector(); 1047198090Srdivacky 1048198090Srdivacky unsigned OpcodeIndex; 1049198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1050198090Srdivacky default: llvm_unreachable("unhandled vld type"); 1051198090Srdivacky // Double-register operations: 1052198090Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1053198090Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1054198090Srdivacky case MVT::v2f32: 1055198090Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1056198090Srdivacky case MVT::v1i64: OpcodeIndex = 3; break; 1057198090Srdivacky // Quad-register operations: 1058198090Srdivacky case MVT::v16i8: OpcodeIndex = 0; break; 1059198090Srdivacky case MVT::v8i16: OpcodeIndex = 1; break; 1060198090Srdivacky case MVT::v4f32: 1061198090Srdivacky case MVT::v4i32: OpcodeIndex = 2; break; 1062198090Srdivacky } 1063198090Srdivacky 1064199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1065199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1066198090Srdivacky if (is64BitVector) { 1067198090Srdivacky unsigned Opc = DOpcodes[OpcodeIndex]; 1068199989Srdivacky const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, Align, 1069199989Srdivacky Pred, PredReg, Chain }; 1070198090Srdivacky std::vector<EVT> ResTys(NumVecs, VT); 1071198090Srdivacky ResTys.push_back(MVT::Other); 1072199989Srdivacky return CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 7); 1073198090Srdivacky } 1074198090Srdivacky 1075198090Srdivacky EVT RegVT = GetNEONSubregVT(VT); 1076198090Srdivacky if (NumVecs == 2) { 1077198090Srdivacky // Quad registers are directly supported for VLD2, 1078198090Srdivacky // loading 2 pairs of D regs. 1079198090Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1080199989Srdivacky const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, Align, 1081199989Srdivacky Pred, PredReg, Chain }; 1082198090Srdivacky std::vector<EVT> ResTys(4, VT); 1083198090Srdivacky ResTys.push_back(MVT::Other); 1084199989Srdivacky SDNode *VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 7); 1085198090Srdivacky Chain = SDValue(VLd, 4); 1086198090Srdivacky 1087198090Srdivacky // Combine the even and odd subregs to produce the result. 1088198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1089198090Srdivacky SDNode *Q = PairDRegs(VT, SDValue(VLd, 2*Vec), SDValue(VLd, 2*Vec+1)); 1090198090Srdivacky ReplaceUses(SDValue(N, Vec), SDValue(Q, 0)); 1091198090Srdivacky } 1092198090Srdivacky } else { 1093198090Srdivacky // Otherwise, quad registers are loaded with two separate instructions, 1094198090Srdivacky // where one loads the even registers and the other loads the odd registers. 1095198090Srdivacky 1096198090Srdivacky // Enable writeback to the address register. 1097198090Srdivacky MemOpc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(true), MVT::i32); 1098198090Srdivacky 1099198090Srdivacky std::vector<EVT> ResTys(NumVecs, RegVT); 1100198090Srdivacky ResTys.push_back(MemAddr.getValueType()); 1101198090Srdivacky ResTys.push_back(MVT::Other); 1102198090Srdivacky 1103198113Srdivacky // Load the even subregs. 1104198090Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1105199989Srdivacky const SDValue OpsA[] = { MemAddr, MemUpdate, MemOpc, Align, 1106199989Srdivacky Pred, PredReg, Chain }; 1107199989Srdivacky SDNode *VLdA = CurDAG->getMachineNode(Opc, dl, ResTys, OpsA, 7); 1108198090Srdivacky Chain = SDValue(VLdA, NumVecs+1); 1109198090Srdivacky 1110198113Srdivacky // Load the odd subregs. 1111198090Srdivacky Opc = QOpcodes1[OpcodeIndex]; 1112199481Srdivacky const SDValue OpsB[] = { SDValue(VLdA, NumVecs), MemUpdate, MemOpc, 1113199989Srdivacky Align, Pred, PredReg, Chain }; 1114199989Srdivacky SDNode *VLdB = CurDAG->getMachineNode(Opc, dl, ResTys, OpsB, 7); 1115198090Srdivacky Chain = SDValue(VLdB, NumVecs+1); 1116198090Srdivacky 1117198090Srdivacky // Combine the even and odd subregs to produce the result. 1118198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1119198090Srdivacky SDNode *Q = PairDRegs(VT, SDValue(VLdA, Vec), SDValue(VLdB, Vec)); 1120198090Srdivacky ReplaceUses(SDValue(N, Vec), SDValue(Q, 0)); 1121198090Srdivacky } 1122198090Srdivacky } 1123198090Srdivacky ReplaceUses(SDValue(N, NumVecs), Chain); 1124198090Srdivacky return NULL; 1125198090Srdivacky} 1126198090Srdivacky 1127198113SrdivackySDNode *ARMDAGToDAGISel::SelectVST(SDValue Op, unsigned NumVecs, 1128198113Srdivacky unsigned *DOpcodes, unsigned *QOpcodes0, 1129198113Srdivacky unsigned *QOpcodes1) { 1130198113Srdivacky assert(NumVecs >=2 && NumVecs <= 4 && "VST NumVecs out-of-range"); 1131198113Srdivacky SDNode *N = Op.getNode(); 1132198113Srdivacky DebugLoc dl = N->getDebugLoc(); 1133198113Srdivacky 1134199481Srdivacky SDValue MemAddr, MemUpdate, MemOpc, Align; 1135199481Srdivacky if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc, Align)) 1136198113Srdivacky return NULL; 1137198113Srdivacky 1138198113Srdivacky SDValue Chain = N->getOperand(0); 1139198113Srdivacky EVT VT = N->getOperand(3).getValueType(); 1140198113Srdivacky bool is64BitVector = VT.is64BitVector(); 1141198113Srdivacky 1142198113Srdivacky unsigned OpcodeIndex; 1143198113Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1144198113Srdivacky default: llvm_unreachable("unhandled vst type"); 1145198113Srdivacky // Double-register operations: 1146198113Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1147198113Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1148198113Srdivacky case MVT::v2f32: 1149198113Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1150198113Srdivacky case MVT::v1i64: OpcodeIndex = 3; break; 1151198113Srdivacky // Quad-register operations: 1152198113Srdivacky case MVT::v16i8: OpcodeIndex = 0; break; 1153198113Srdivacky case MVT::v8i16: OpcodeIndex = 1; break; 1154198113Srdivacky case MVT::v4f32: 1155198113Srdivacky case MVT::v4i32: OpcodeIndex = 2; break; 1156198113Srdivacky } 1157198113Srdivacky 1158199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1159199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1160199989Srdivacky 1161198113Srdivacky SmallVector<SDValue, 8> Ops; 1162198113Srdivacky Ops.push_back(MemAddr); 1163198113Srdivacky Ops.push_back(MemUpdate); 1164198113Srdivacky Ops.push_back(MemOpc); 1165199481Srdivacky Ops.push_back(Align); 1166198113Srdivacky 1167198113Srdivacky if (is64BitVector) { 1168198113Srdivacky unsigned Opc = DOpcodes[OpcodeIndex]; 1169198113Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1170198113Srdivacky Ops.push_back(N->getOperand(Vec+3)); 1171199989Srdivacky Ops.push_back(Pred); 1172199989Srdivacky Ops.push_back(PredReg); 1173198113Srdivacky Ops.push_back(Chain); 1174199989Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+7); 1175198113Srdivacky } 1176198113Srdivacky 1177198113Srdivacky EVT RegVT = GetNEONSubregVT(VT); 1178198113Srdivacky if (NumVecs == 2) { 1179198113Srdivacky // Quad registers are directly supported for VST2, 1180198113Srdivacky // storing 2 pairs of D regs. 1181198113Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1182198113Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1183198113Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT, 1184198113Srdivacky N->getOperand(Vec+3))); 1185198113Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT, 1186198113Srdivacky N->getOperand(Vec+3))); 1187198113Srdivacky } 1188199989Srdivacky Ops.push_back(Pred); 1189199989Srdivacky Ops.push_back(PredReg); 1190198113Srdivacky Ops.push_back(Chain); 1191199989Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), 11); 1192198113Srdivacky } 1193198113Srdivacky 1194198113Srdivacky // Otherwise, quad registers are stored with two separate instructions, 1195198113Srdivacky // where one stores the even registers and the other stores the odd registers. 1196198113Srdivacky 1197198113Srdivacky // Enable writeback to the address register. 1198198113Srdivacky MemOpc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(true), MVT::i32); 1199198113Srdivacky 1200198113Srdivacky // Store the even subregs. 1201198113Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1202198113Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT, 1203198113Srdivacky N->getOperand(Vec+3))); 1204199989Srdivacky Ops.push_back(Pred); 1205199989Srdivacky Ops.push_back(PredReg); 1206198113Srdivacky Ops.push_back(Chain); 1207198113Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1208198113Srdivacky SDNode *VStA = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(), 1209199989Srdivacky MVT::Other, Ops.data(), NumVecs+7); 1210198113Srdivacky Chain = SDValue(VStA, 1); 1211198113Srdivacky 1212198113Srdivacky // Store the odd subregs. 1213198113Srdivacky Ops[0] = SDValue(VStA, 0); // MemAddr 1214198113Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1215199481Srdivacky Ops[Vec+4] = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT, 1216198113Srdivacky N->getOperand(Vec+3)); 1217199989Srdivacky Ops[NumVecs+4] = Pred; 1218199989Srdivacky Ops[NumVecs+5] = PredReg; 1219199989Srdivacky Ops[NumVecs+6] = Chain; 1220198113Srdivacky Opc = QOpcodes1[OpcodeIndex]; 1221198113Srdivacky SDNode *VStB = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(), 1222199989Srdivacky MVT::Other, Ops.data(), NumVecs+7); 1223198113Srdivacky Chain = SDValue(VStB, 1); 1224198113Srdivacky ReplaceUses(SDValue(N, 0), Chain); 1225198113Srdivacky return NULL; 1226198113Srdivacky} 1227198113Srdivacky 1228198090SrdivackySDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDValue Op, bool IsLoad, 1229198090Srdivacky unsigned NumVecs, unsigned *DOpcodes, 1230198090Srdivacky unsigned *QOpcodes0, 1231198090Srdivacky unsigned *QOpcodes1) { 1232198090Srdivacky assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range"); 1233198090Srdivacky SDNode *N = Op.getNode(); 1234198090Srdivacky DebugLoc dl = N->getDebugLoc(); 1235198090Srdivacky 1236199481Srdivacky SDValue MemAddr, MemUpdate, MemOpc, Align; 1237199481Srdivacky if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc, Align)) 1238198090Srdivacky return NULL; 1239198090Srdivacky 1240198090Srdivacky SDValue Chain = N->getOperand(0); 1241198090Srdivacky unsigned Lane = 1242198090Srdivacky cast<ConstantSDNode>(N->getOperand(NumVecs+3))->getZExtValue(); 1243198090Srdivacky EVT VT = IsLoad ? N->getValueType(0) : N->getOperand(3).getValueType(); 1244198090Srdivacky bool is64BitVector = VT.is64BitVector(); 1245198090Srdivacky 1246198090Srdivacky // Quad registers are handled by load/store of subregs. Find the subreg info. 1247198090Srdivacky unsigned NumElts = 0; 1248198090Srdivacky int SubregIdx = 0; 1249198090Srdivacky EVT RegVT = VT; 1250198090Srdivacky if (!is64BitVector) { 1251198090Srdivacky RegVT = GetNEONSubregVT(VT); 1252198090Srdivacky NumElts = RegVT.getVectorNumElements(); 1253198090Srdivacky SubregIdx = (Lane < NumElts) ? ARM::DSUBREG_0 : ARM::DSUBREG_1; 1254198090Srdivacky } 1255198090Srdivacky 1256198090Srdivacky unsigned OpcodeIndex; 1257198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1258198090Srdivacky default: llvm_unreachable("unhandled vld/vst lane type"); 1259198090Srdivacky // Double-register operations: 1260198090Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1261198090Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1262198090Srdivacky case MVT::v2f32: 1263198090Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1264198090Srdivacky // Quad-register operations: 1265198090Srdivacky case MVT::v8i16: OpcodeIndex = 0; break; 1266198090Srdivacky case MVT::v4f32: 1267198090Srdivacky case MVT::v4i32: OpcodeIndex = 1; break; 1268198090Srdivacky } 1269198090Srdivacky 1270199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1271199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1272199989Srdivacky 1273198090Srdivacky SmallVector<SDValue, 9> Ops; 1274198090Srdivacky Ops.push_back(MemAddr); 1275198090Srdivacky Ops.push_back(MemUpdate); 1276198090Srdivacky Ops.push_back(MemOpc); 1277199481Srdivacky Ops.push_back(Align); 1278198090Srdivacky 1279198090Srdivacky unsigned Opc = 0; 1280198090Srdivacky if (is64BitVector) { 1281198090Srdivacky Opc = DOpcodes[OpcodeIndex]; 1282198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1283198090Srdivacky Ops.push_back(N->getOperand(Vec+3)); 1284198090Srdivacky } else { 1285198090Srdivacky // Check if this is loading the even or odd subreg of a Q register. 1286198090Srdivacky if (Lane < NumElts) { 1287198090Srdivacky Opc = QOpcodes0[OpcodeIndex]; 1288198090Srdivacky } else { 1289198090Srdivacky Lane -= NumElts; 1290198090Srdivacky Opc = QOpcodes1[OpcodeIndex]; 1291198090Srdivacky } 1292198090Srdivacky // Extract the subregs of the input vector. 1293198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1294198090Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT, 1295198090Srdivacky N->getOperand(Vec+3))); 1296198090Srdivacky } 1297198090Srdivacky Ops.push_back(getI32Imm(Lane)); 1298199989Srdivacky Ops.push_back(Pred); 1299199989Srdivacky Ops.push_back(PredReg); 1300198090Srdivacky Ops.push_back(Chain); 1301198090Srdivacky 1302198090Srdivacky if (!IsLoad) 1303199989Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+7); 1304198090Srdivacky 1305198090Srdivacky std::vector<EVT> ResTys(NumVecs, RegVT); 1306198090Srdivacky ResTys.push_back(MVT::Other); 1307198090Srdivacky SDNode *VLdLn = 1308199989Srdivacky CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), NumVecs+7); 1309198090Srdivacky // For a 64-bit vector load to D registers, nothing more needs to be done. 1310198090Srdivacky if (is64BitVector) 1311198090Srdivacky return VLdLn; 1312198090Srdivacky 1313198090Srdivacky // For 128-bit vectors, take the 64-bit results of the load and insert them 1314198090Srdivacky // as subregs into the result. 1315198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1316198090Srdivacky SDValue QuadVec = CurDAG->getTargetInsertSubreg(SubregIdx, dl, VT, 1317198090Srdivacky N->getOperand(Vec+3), 1318198090Srdivacky SDValue(VLdLn, Vec)); 1319198090Srdivacky ReplaceUses(SDValue(N, Vec), QuadVec); 1320198090Srdivacky } 1321198090Srdivacky 1322198090Srdivacky Chain = SDValue(VLdLn, NumVecs); 1323198090Srdivacky ReplaceUses(SDValue(N, NumVecs), Chain); 1324198090Srdivacky return NULL; 1325198090Srdivacky} 1326198090Srdivacky 1327198090SrdivackySDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDValue Op, 1328198090Srdivacky unsigned Opc) { 1329198090Srdivacky if (!Subtarget->hasV6T2Ops()) 1330198090Srdivacky return NULL; 1331198090Srdivacky 1332198090Srdivacky unsigned Shl_imm = 0; 1333199989Srdivacky if (isOpcWithIntImmediate(Op.getOperand(0).getNode(), ISD::SHL, Shl_imm)) { 1334198090Srdivacky assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!"); 1335198090Srdivacky unsigned Srl_imm = 0; 1336198090Srdivacky if (isInt32Immediate(Op.getOperand(1), Srl_imm)) { 1337198090Srdivacky assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); 1338198090Srdivacky unsigned Width = 32 - Srl_imm; 1339198090Srdivacky int LSB = Srl_imm - Shl_imm; 1340198396Srdivacky if (LSB < 0) 1341198090Srdivacky return NULL; 1342198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1343198090Srdivacky SDValue Ops[] = { Op.getOperand(0).getOperand(0), 1344198090Srdivacky CurDAG->getTargetConstant(LSB, MVT::i32), 1345198090Srdivacky CurDAG->getTargetConstant(Width, MVT::i32), 1346198090Srdivacky getAL(CurDAG), Reg0 }; 1347198090Srdivacky return CurDAG->SelectNodeTo(Op.getNode(), Opc, MVT::i32, Ops, 5); 1348198090Srdivacky } 1349198090Srdivacky } 1350198090Srdivacky return NULL; 1351198090Srdivacky} 1352198090Srdivacky 1353199989SrdivackySDNode *ARMDAGToDAGISel:: 1354199989SrdivackySelectT2CMOVShiftOp(SDValue Op, SDValue FalseVal, SDValue TrueVal, 1355199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1356199989Srdivacky SDValue CPTmp0; 1357199989Srdivacky SDValue CPTmp1; 1358199989Srdivacky if (SelectT2ShifterOperandReg(Op, TrueVal, CPTmp0, CPTmp1)) { 1359199989Srdivacky unsigned SOVal = cast<ConstantSDNode>(CPTmp1)->getZExtValue(); 1360199989Srdivacky unsigned SOShOp = ARM_AM::getSORegShOp(SOVal); 1361199989Srdivacky unsigned Opc = 0; 1362199989Srdivacky switch (SOShOp) { 1363199989Srdivacky case ARM_AM::lsl: Opc = ARM::t2MOVCClsl; break; 1364199989Srdivacky case ARM_AM::lsr: Opc = ARM::t2MOVCClsr; break; 1365199989Srdivacky case ARM_AM::asr: Opc = ARM::t2MOVCCasr; break; 1366199989Srdivacky case ARM_AM::ror: Opc = ARM::t2MOVCCror; break; 1367199989Srdivacky default: 1368199989Srdivacky llvm_unreachable("Unknown so_reg opcode!"); 1369199989Srdivacky break; 1370199989Srdivacky } 1371199989Srdivacky SDValue SOShImm = 1372199989Srdivacky CurDAG->getTargetConstant(ARM_AM::getSORegOffset(SOVal), MVT::i32); 1373199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1374199989Srdivacky SDValue Ops[] = { FalseVal, CPTmp0, SOShImm, CC, CCR, InFlag }; 1375199989Srdivacky return CurDAG->SelectNodeTo(Op.getNode(), Opc, MVT::i32,Ops, 6); 1376199989Srdivacky } 1377199989Srdivacky return 0; 1378199989Srdivacky} 1379199989Srdivacky 1380199989SrdivackySDNode *ARMDAGToDAGISel:: 1381199989SrdivackySelectARMCMOVShiftOp(SDValue Op, SDValue FalseVal, SDValue TrueVal, 1382199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1383199989Srdivacky SDValue CPTmp0; 1384199989Srdivacky SDValue CPTmp1; 1385199989Srdivacky SDValue CPTmp2; 1386199989Srdivacky if (SelectShifterOperandReg(Op, TrueVal, CPTmp0, CPTmp1, CPTmp2)) { 1387199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1388199989Srdivacky SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, InFlag }; 1389199989Srdivacky return CurDAG->SelectNodeTo(Op.getNode(), ARM::MOVCCs, MVT::i32, Ops, 7); 1390199989Srdivacky } 1391199989Srdivacky return 0; 1392199989Srdivacky} 1393199989Srdivacky 1394199989SrdivackySDNode *ARMDAGToDAGISel:: 1395199989SrdivackySelectT2CMOVSoImmOp(SDValue Op, SDValue FalseVal, SDValue TrueVal, 1396199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1397199989Srdivacky ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal); 1398199989Srdivacky if (!T) 1399199989Srdivacky return 0; 1400199989Srdivacky 1401199989Srdivacky if (Predicate_t2_so_imm(TrueVal.getNode())) { 1402199989Srdivacky SDValue True = CurDAG->getTargetConstant(T->getZExtValue(), MVT::i32); 1403199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1404199989Srdivacky SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag }; 1405199989Srdivacky return CurDAG->SelectNodeTo(Op.getNode(), 1406199989Srdivacky ARM::t2MOVCCi, MVT::i32, Ops, 5); 1407199989Srdivacky } 1408199989Srdivacky return 0; 1409199989Srdivacky} 1410199989Srdivacky 1411199989SrdivackySDNode *ARMDAGToDAGISel:: 1412199989SrdivackySelectARMCMOVSoImmOp(SDValue Op, SDValue FalseVal, SDValue TrueVal, 1413199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1414199989Srdivacky ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal); 1415199989Srdivacky if (!T) 1416199989Srdivacky return 0; 1417199989Srdivacky 1418199989Srdivacky if (Predicate_so_imm(TrueVal.getNode())) { 1419199989Srdivacky SDValue True = CurDAG->getTargetConstant(T->getZExtValue(), MVT::i32); 1420199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1421199989Srdivacky SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag }; 1422199989Srdivacky return CurDAG->SelectNodeTo(Op.getNode(), 1423199989Srdivacky ARM::MOVCCi, MVT::i32, Ops, 5); 1424199989Srdivacky } 1425199989Srdivacky return 0; 1426199989Srdivacky} 1427199989Srdivacky 1428199989SrdivackySDNode *ARMDAGToDAGISel::SelectCMOVOp(SDValue Op) { 1429199989Srdivacky EVT VT = Op.getValueType(); 1430199989Srdivacky SDValue FalseVal = Op.getOperand(0); 1431199989Srdivacky SDValue TrueVal = Op.getOperand(1); 1432199989Srdivacky SDValue CC = Op.getOperand(2); 1433199989Srdivacky SDValue CCR = Op.getOperand(3); 1434199989Srdivacky SDValue InFlag = Op.getOperand(4); 1435199989Srdivacky assert(CC.getOpcode() == ISD::Constant); 1436199989Srdivacky assert(CCR.getOpcode() == ISD::Register); 1437199989Srdivacky ARMCC::CondCodes CCVal = 1438199989Srdivacky (ARMCC::CondCodes)cast<ConstantSDNode>(CC)->getZExtValue(); 1439199989Srdivacky 1440199989Srdivacky if (!Subtarget->isThumb1Only() && VT == MVT::i32) { 1441199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) 1442199989Srdivacky // Emits: (MOVCCs:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) 1443199989Srdivacky // Pattern complexity = 18 cost = 1 size = 0 1444199989Srdivacky SDValue CPTmp0; 1445199989Srdivacky SDValue CPTmp1; 1446199989Srdivacky SDValue CPTmp2; 1447199989Srdivacky if (Subtarget->isThumb()) { 1448199989Srdivacky SDNode *Res = SelectT2CMOVShiftOp(Op, FalseVal, TrueVal, 1449199989Srdivacky CCVal, CCR, InFlag); 1450199989Srdivacky if (!Res) 1451199989Srdivacky Res = SelectT2CMOVShiftOp(Op, TrueVal, FalseVal, 1452199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1453199989Srdivacky if (Res) 1454199989Srdivacky return Res; 1455199989Srdivacky } else { 1456199989Srdivacky SDNode *Res = SelectARMCMOVShiftOp(Op, FalseVal, TrueVal, 1457199989Srdivacky CCVal, CCR, InFlag); 1458199989Srdivacky if (!Res) 1459199989Srdivacky Res = SelectARMCMOVShiftOp(Op, TrueVal, FalseVal, 1460199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1461199989Srdivacky if (Res) 1462199989Srdivacky return Res; 1463199989Srdivacky } 1464199989Srdivacky 1465199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, 1466199989Srdivacky // (imm:i32)<<P:Predicate_so_imm>>:$true, 1467199989Srdivacky // (imm:i32):$cc) 1468199989Srdivacky // Emits: (MOVCCi:i32 GPR:i32:$false, 1469199989Srdivacky // (so_imm:i32 (imm:i32):$true), (imm:i32):$cc) 1470199989Srdivacky // Pattern complexity = 10 cost = 1 size = 0 1471199989Srdivacky if (Subtarget->isThumb()) { 1472199989Srdivacky SDNode *Res = SelectT2CMOVSoImmOp(Op, FalseVal, TrueVal, 1473199989Srdivacky CCVal, CCR, InFlag); 1474199989Srdivacky if (!Res) 1475199989Srdivacky Res = SelectT2CMOVSoImmOp(Op, TrueVal, FalseVal, 1476199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1477199989Srdivacky if (Res) 1478199989Srdivacky return Res; 1479199989Srdivacky } else { 1480199989Srdivacky SDNode *Res = SelectARMCMOVSoImmOp(Op, FalseVal, TrueVal, 1481199989Srdivacky CCVal, CCR, InFlag); 1482199989Srdivacky if (!Res) 1483199989Srdivacky Res = SelectARMCMOVSoImmOp(Op, TrueVal, FalseVal, 1484199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1485199989Srdivacky if (Res) 1486199989Srdivacky return Res; 1487199989Srdivacky } 1488199989Srdivacky } 1489199989Srdivacky 1490199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1491199989Srdivacky // Emits: (MOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1492199989Srdivacky // Pattern complexity = 6 cost = 1 size = 0 1493199989Srdivacky // 1494199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1495199989Srdivacky // Emits: (tMOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1496199989Srdivacky // Pattern complexity = 6 cost = 11 size = 0 1497199989Srdivacky // 1498199989Srdivacky // Also FCPYScc and FCPYDcc. 1499199989Srdivacky SDValue Tmp2 = CurDAG->getTargetConstant(CCVal, MVT::i32); 1500199989Srdivacky SDValue Ops[] = { FalseVal, TrueVal, Tmp2, CCR, InFlag }; 1501199989Srdivacky unsigned Opc = 0; 1502199989Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1503199989Srdivacky default: assert(false && "Illegal conditional move type!"); 1504199989Srdivacky break; 1505199989Srdivacky case MVT::i32: 1506199989Srdivacky Opc = Subtarget->isThumb() 1507199989Srdivacky ? (Subtarget->hasThumb2() ? ARM::t2MOVCCr : ARM::tMOVCCr_pseudo) 1508199989Srdivacky : ARM::MOVCCr; 1509199989Srdivacky break; 1510199989Srdivacky case MVT::f32: 1511199989Srdivacky Opc = ARM::VMOVScc; 1512199989Srdivacky break; 1513199989Srdivacky case MVT::f64: 1514199989Srdivacky Opc = ARM::VMOVDcc; 1515199989Srdivacky break; 1516199989Srdivacky } 1517199989Srdivacky return CurDAG->SelectNodeTo(Op.getNode(), Opc, VT, Ops, 5); 1518199989Srdivacky} 1519199989Srdivacky 1520193323SedSDNode *ARMDAGToDAGISel::Select(SDValue Op) { 1521193323Sed SDNode *N = Op.getNode(); 1522193323Sed DebugLoc dl = N->getDebugLoc(); 1523193323Sed 1524193323Sed if (N->isMachineOpcode()) 1525193323Sed return NULL; // Already selected. 1526193323Sed 1527193323Sed switch (N->getOpcode()) { 1528193323Sed default: break; 1529193323Sed case ISD::Constant: { 1530193323Sed unsigned Val = cast<ConstantSDNode>(N)->getZExtValue(); 1531193323Sed bool UseCP = true; 1532198090Srdivacky if (Subtarget->hasThumb2()) 1533198090Srdivacky // Thumb2-aware targets have the MOVT instruction, so all immediates can 1534198090Srdivacky // be done with MOV + MOVT, at worst. 1535198090Srdivacky UseCP = 0; 1536198090Srdivacky else { 1537198090Srdivacky if (Subtarget->isThumb()) { 1538194710Sed UseCP = (Val > 255 && // MOV 1539194710Sed ~Val > 255 && // MOV + MVN 1540194710Sed !ARM_AM::isThumbImmShiftedVal(Val)); // MOV + LSL 1541198090Srdivacky } else 1542198090Srdivacky UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV 1543198090Srdivacky ARM_AM::getSOImmVal(~Val) == -1 && // MVN 1544198090Srdivacky !ARM_AM::isSOImmTwoPartVal(Val)); // two instrs. 1545198090Srdivacky } 1546198090Srdivacky 1547193323Sed if (UseCP) { 1548193323Sed SDValue CPIdx = 1549198090Srdivacky CurDAG->getTargetConstantPool(ConstantInt::get( 1550198090Srdivacky Type::getInt32Ty(*CurDAG->getContext()), Val), 1551193323Sed TLI.getPointerTy()); 1552193323Sed 1553193323Sed SDNode *ResNode; 1554198090Srdivacky if (Subtarget->isThumb1Only()) { 1555199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1556198090Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1557198090Srdivacky SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() }; 1558198090Srdivacky ResNode = CurDAG->getMachineNode(ARM::tLDRcp, dl, MVT::i32, MVT::Other, 1559198090Srdivacky Ops, 4); 1560198090Srdivacky } else { 1561193323Sed SDValue Ops[] = { 1562198090Srdivacky CPIdx, 1563193323Sed CurDAG->getRegister(0, MVT::i32), 1564193323Sed CurDAG->getTargetConstant(0, MVT::i32), 1565193323Sed getAL(CurDAG), 1566193323Sed CurDAG->getRegister(0, MVT::i32), 1567193323Sed CurDAG->getEntryNode() 1568193323Sed }; 1569198090Srdivacky ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other, 1570198090Srdivacky Ops, 6); 1571193323Sed } 1572193323Sed ReplaceUses(Op, SDValue(ResNode, 0)); 1573193323Sed return NULL; 1574193323Sed } 1575198090Srdivacky 1576193323Sed // Other cases are autogenerated. 1577193323Sed break; 1578193323Sed } 1579193323Sed case ISD::FrameIndex: { 1580193323Sed // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm. 1581193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 1582193323Sed SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 1583198090Srdivacky if (Subtarget->isThumb1Only()) { 1584193323Sed return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI, 1585193323Sed CurDAG->getTargetConstant(0, MVT::i32)); 1586193323Sed } else { 1587198090Srdivacky unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ? 1588198090Srdivacky ARM::t2ADDri : ARM::ADDri); 1589193323Sed SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32), 1590198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1591198090Srdivacky CurDAG->getRegister(0, MVT::i32) }; 1592198090Srdivacky return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); 1593193323Sed } 1594193323Sed } 1595198090Srdivacky case ARMISD::DYN_ALLOC: 1596198090Srdivacky return SelectDYN_ALLOC(Op); 1597198090Srdivacky case ISD::SRL: 1598198090Srdivacky if (SDNode *I = SelectV6T2BitfieldExtractOp(Op, 1599198090Srdivacky Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX)) 1600198090Srdivacky return I; 1601193323Sed break; 1602198090Srdivacky case ISD::SRA: 1603198090Srdivacky if (SDNode *I = SelectV6T2BitfieldExtractOp(Op, 1604198090Srdivacky Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)) 1605198090Srdivacky return I; 1606198090Srdivacky break; 1607193323Sed case ISD::MUL: 1608198090Srdivacky if (Subtarget->isThumb1Only()) 1609193323Sed break; 1610193323Sed if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) { 1611193323Sed unsigned RHSV = C->getZExtValue(); 1612193323Sed if (!RHSV) break; 1613193323Sed if (isPowerOf2_32(RHSV-1)) { // 2^n+1? 1614198090Srdivacky unsigned ShImm = Log2_32(RHSV-1); 1615198090Srdivacky if (ShImm >= 32) 1616198090Srdivacky break; 1617193323Sed SDValue V = Op.getOperand(0); 1618198090Srdivacky ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); 1619198090Srdivacky SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); 1620198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1621198090Srdivacky if (Subtarget->isThumb()) { 1622198090Srdivacky SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1623198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops, 6); 1624198090Srdivacky } else { 1625198090Srdivacky SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1626198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 7); 1627198090Srdivacky } 1628193323Sed } 1629193323Sed if (isPowerOf2_32(RHSV+1)) { // 2^n-1? 1630198090Srdivacky unsigned ShImm = Log2_32(RHSV+1); 1631198090Srdivacky if (ShImm >= 32) 1632198090Srdivacky break; 1633193323Sed SDValue V = Op.getOperand(0); 1634198090Srdivacky ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); 1635198090Srdivacky SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); 1636198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1637198090Srdivacky if (Subtarget->isThumb()) { 1638198090Srdivacky SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0 }; 1639198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops, 5); 1640198090Srdivacky } else { 1641198090Srdivacky SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1642198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 7); 1643198090Srdivacky } 1644193323Sed } 1645193323Sed } 1646193323Sed break; 1647198396Srdivacky case ISD::AND: { 1648198396Srdivacky // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits 1649198396Srdivacky // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits 1650198396Srdivacky // are entirely contributed by c2 and lower 16-bits are entirely contributed 1651198396Srdivacky // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)). 1652198396Srdivacky // Select it to: "movt x, ((c1 & 0xffff) >> 16) 1653198396Srdivacky EVT VT = Op.getValueType(); 1654198396Srdivacky if (VT != MVT::i32) 1655198396Srdivacky break; 1656198396Srdivacky unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2()) 1657198396Srdivacky ? ARM::t2MOVTi16 1658198396Srdivacky : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0); 1659198396Srdivacky if (!Opc) 1660198396Srdivacky break; 1661198396Srdivacky SDValue N0 = Op.getOperand(0), N1 = Op.getOperand(1); 1662198396Srdivacky ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); 1663198396Srdivacky if (!N1C) 1664198396Srdivacky break; 1665198396Srdivacky if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) { 1666198396Srdivacky SDValue N2 = N0.getOperand(1); 1667198396Srdivacky ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2); 1668198396Srdivacky if (!N2C) 1669198396Srdivacky break; 1670198396Srdivacky unsigned N1CVal = N1C->getZExtValue(); 1671198396Srdivacky unsigned N2CVal = N2C->getZExtValue(); 1672198396Srdivacky if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) && 1673198396Srdivacky (N1CVal & 0xffffU) == 0xffffU && 1674198396Srdivacky (N2CVal & 0xffffU) == 0x0U) { 1675198396Srdivacky SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16, 1676198396Srdivacky MVT::i32); 1677198396Srdivacky SDValue Ops[] = { N0.getOperand(0), Imm16, 1678198396Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; 1679198396Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, Ops, 4); 1680198396Srdivacky } 1681198396Srdivacky } 1682198396Srdivacky break; 1683198396Srdivacky } 1684199481Srdivacky case ARMISD::VMOVRRD: 1685199481Srdivacky return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32, 1686198090Srdivacky Op.getOperand(0), getAL(CurDAG), 1687198090Srdivacky CurDAG->getRegister(0, MVT::i32)); 1688193323Sed case ISD::UMUL_LOHI: { 1689198090Srdivacky if (Subtarget->isThumb1Only()) 1690198090Srdivacky break; 1691198090Srdivacky if (Subtarget->isThumb()) { 1692198090Srdivacky SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), 1693193323Sed getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1694193323Sed CurDAG->getRegister(0, MVT::i32) }; 1695198090Srdivacky return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops,4); 1696198090Srdivacky } else { 1697198090Srdivacky SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), 1698198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1699198090Srdivacky CurDAG->getRegister(0, MVT::i32) }; 1700198090Srdivacky return CurDAG->getMachineNode(ARM::UMULL, dl, MVT::i32, MVT::i32, Ops, 5); 1701198090Srdivacky } 1702193323Sed } 1703193323Sed case ISD::SMUL_LOHI: { 1704198090Srdivacky if (Subtarget->isThumb1Only()) 1705198090Srdivacky break; 1706198090Srdivacky if (Subtarget->isThumb()) { 1707198090Srdivacky SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), 1708198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; 1709198090Srdivacky return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops,4); 1710198090Srdivacky } else { 1711198090Srdivacky SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), 1712193323Sed getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1713193323Sed CurDAG->getRegister(0, MVT::i32) }; 1714198090Srdivacky return CurDAG->getMachineNode(ARM::SMULL, dl, MVT::i32, MVT::i32, Ops, 5); 1715198090Srdivacky } 1716193323Sed } 1717193323Sed case ISD::LOAD: { 1718195340Sed SDNode *ResNode = 0; 1719198090Srdivacky if (Subtarget->isThumb() && Subtarget->hasThumb2()) 1720195340Sed ResNode = SelectT2IndexedLoad(Op); 1721195340Sed else 1722195340Sed ResNode = SelectARMIndexedLoad(Op); 1723195340Sed if (ResNode) 1724195340Sed return ResNode; 1725193323Sed // Other cases are autogenerated. 1726193323Sed break; 1727193323Sed } 1728193323Sed case ARMISD::BRCOND: { 1729193323Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 1730193323Sed // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc) 1731193323Sed // Pattern complexity = 6 cost = 1 size = 0 1732193323Sed 1733193323Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 1734193323Sed // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc) 1735193323Sed // Pattern complexity = 6 cost = 1 size = 0 1736193323Sed 1737195340Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 1738195340Sed // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc) 1739195340Sed // Pattern complexity = 6 cost = 1 size = 0 1740195340Sed 1741198090Srdivacky unsigned Opc = Subtarget->isThumb() ? 1742195340Sed ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc; 1743193323Sed SDValue Chain = Op.getOperand(0); 1744193323Sed SDValue N1 = Op.getOperand(1); 1745193323Sed SDValue N2 = Op.getOperand(2); 1746193323Sed SDValue N3 = Op.getOperand(3); 1747193323Sed SDValue InFlag = Op.getOperand(4); 1748193323Sed assert(N1.getOpcode() == ISD::BasicBlock); 1749193323Sed assert(N2.getOpcode() == ISD::Constant); 1750193323Sed assert(N3.getOpcode() == ISD::Register); 1751193323Sed 1752193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 1753193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 1754193323Sed MVT::i32); 1755193323Sed SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag }; 1756198090Srdivacky SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other, 1757198090Srdivacky MVT::Flag, Ops, 5); 1758193323Sed Chain = SDValue(ResNode, 0); 1759193323Sed if (Op.getNode()->getNumValues() == 2) { 1760193323Sed InFlag = SDValue(ResNode, 1); 1761193323Sed ReplaceUses(SDValue(Op.getNode(), 1), InFlag); 1762193323Sed } 1763199511Srdivacky ReplaceUses(SDValue(Op.getNode(), 0), 1764199511Srdivacky SDValue(Chain.getNode(), Chain.getResNo())); 1765193323Sed return NULL; 1766193323Sed } 1767199989Srdivacky case ARMISD::CMOV: 1768199989Srdivacky return SelectCMOVOp(Op); 1769193323Sed case ARMISD::CNEG: { 1770198090Srdivacky EVT VT = Op.getValueType(); 1771193323Sed SDValue N0 = Op.getOperand(0); 1772193323Sed SDValue N1 = Op.getOperand(1); 1773193323Sed SDValue N2 = Op.getOperand(2); 1774193323Sed SDValue N3 = Op.getOperand(3); 1775193323Sed SDValue InFlag = Op.getOperand(4); 1776193323Sed assert(N2.getOpcode() == ISD::Constant); 1777193323Sed assert(N3.getOpcode() == ISD::Register); 1778193323Sed 1779193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 1780193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 1781193323Sed MVT::i32); 1782193323Sed SDValue Ops[] = { N0, N1, Tmp2, N3, InFlag }; 1783193323Sed unsigned Opc = 0; 1784198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1785193323Sed default: assert(false && "Illegal conditional move type!"); 1786193323Sed break; 1787193323Sed case MVT::f32: 1788199481Srdivacky Opc = ARM::VNEGScc; 1789193323Sed break; 1790193323Sed case MVT::f64: 1791199481Srdivacky Opc = ARM::VNEGDcc; 1792193323Sed break; 1793193323Sed } 1794193323Sed return CurDAG->SelectNodeTo(Op.getNode(), Opc, VT, Ops, 5); 1795193323Sed } 1796193323Sed 1797198090Srdivacky case ARMISD::VZIP: { 1798198090Srdivacky unsigned Opc = 0; 1799198090Srdivacky EVT VT = N->getValueType(0); 1800198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1801198090Srdivacky default: return NULL; 1802198090Srdivacky case MVT::v8i8: Opc = ARM::VZIPd8; break; 1803198090Srdivacky case MVT::v4i16: Opc = ARM::VZIPd16; break; 1804198090Srdivacky case MVT::v2f32: 1805198090Srdivacky case MVT::v2i32: Opc = ARM::VZIPd32; break; 1806198090Srdivacky case MVT::v16i8: Opc = ARM::VZIPq8; break; 1807198090Srdivacky case MVT::v8i16: Opc = ARM::VZIPq16; break; 1808198090Srdivacky case MVT::v4f32: 1809198090Srdivacky case MVT::v4i32: Opc = ARM::VZIPq32; break; 1810193323Sed } 1811199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1812199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1813199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 1814199989Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); 1815198090Srdivacky } 1816198090Srdivacky case ARMISD::VUZP: { 1817198090Srdivacky unsigned Opc = 0; 1818198090Srdivacky EVT VT = N->getValueType(0); 1819198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1820198090Srdivacky default: return NULL; 1821198090Srdivacky case MVT::v8i8: Opc = ARM::VUZPd8; break; 1822198090Srdivacky case MVT::v4i16: Opc = ARM::VUZPd16; break; 1823198090Srdivacky case MVT::v2f32: 1824198090Srdivacky case MVT::v2i32: Opc = ARM::VUZPd32; break; 1825198090Srdivacky case MVT::v16i8: Opc = ARM::VUZPq8; break; 1826198090Srdivacky case MVT::v8i16: Opc = ARM::VUZPq16; break; 1827198090Srdivacky case MVT::v4f32: 1828198090Srdivacky case MVT::v4i32: Opc = ARM::VUZPq32; break; 1829193323Sed } 1830199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1831199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1832199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 1833199989Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); 1834198090Srdivacky } 1835198090Srdivacky case ARMISD::VTRN: { 1836198090Srdivacky unsigned Opc = 0; 1837198090Srdivacky EVT VT = N->getValueType(0); 1838198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1839198090Srdivacky default: return NULL; 1840198090Srdivacky case MVT::v8i8: Opc = ARM::VTRNd8; break; 1841198090Srdivacky case MVT::v4i16: Opc = ARM::VTRNd16; break; 1842198090Srdivacky case MVT::v2f32: 1843198090Srdivacky case MVT::v2i32: Opc = ARM::VTRNd32; break; 1844198090Srdivacky case MVT::v16i8: Opc = ARM::VTRNq8; break; 1845198090Srdivacky case MVT::v8i16: Opc = ARM::VTRNq16; break; 1846198090Srdivacky case MVT::v4f32: 1847198090Srdivacky case MVT::v4i32: Opc = ARM::VTRNq32; break; 1848193323Sed } 1849199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1850199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1851199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 1852199989Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); 1853193323Sed } 1854194710Sed 1855198090Srdivacky case ISD::INTRINSIC_VOID: 1856198090Srdivacky case ISD::INTRINSIC_W_CHAIN: { 1857198090Srdivacky unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue(); 1858198090Srdivacky switch (IntNo) { 1859198090Srdivacky default: 1860198090Srdivacky break; 1861194710Sed 1862198090Srdivacky case Intrinsic::arm_neon_vld2: { 1863198090Srdivacky unsigned DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16, 1864198090Srdivacky ARM::VLD2d32, ARM::VLD2d64 }; 1865198090Srdivacky unsigned QOpcodes[] = { ARM::VLD2q8, ARM::VLD2q16, ARM::VLD2q32 }; 1866198090Srdivacky return SelectVLD(Op, 2, DOpcodes, QOpcodes, 0); 1867198090Srdivacky } 1868194710Sed 1869198090Srdivacky case Intrinsic::arm_neon_vld3: { 1870198090Srdivacky unsigned DOpcodes[] = { ARM::VLD3d8, ARM::VLD3d16, 1871198090Srdivacky ARM::VLD3d32, ARM::VLD3d64 }; 1872198090Srdivacky unsigned QOpcodes0[] = { ARM::VLD3q8a, ARM::VLD3q16a, ARM::VLD3q32a }; 1873198090Srdivacky unsigned QOpcodes1[] = { ARM::VLD3q8b, ARM::VLD3q16b, ARM::VLD3q32b }; 1874198090Srdivacky return SelectVLD(Op, 3, DOpcodes, QOpcodes0, QOpcodes1); 1875198090Srdivacky } 1876198090Srdivacky 1877198090Srdivacky case Intrinsic::arm_neon_vld4: { 1878198090Srdivacky unsigned DOpcodes[] = { ARM::VLD4d8, ARM::VLD4d16, 1879198090Srdivacky ARM::VLD4d32, ARM::VLD4d64 }; 1880198090Srdivacky unsigned QOpcodes0[] = { ARM::VLD4q8a, ARM::VLD4q16a, ARM::VLD4q32a }; 1881198090Srdivacky unsigned QOpcodes1[] = { ARM::VLD4q8b, ARM::VLD4q16b, ARM::VLD4q32b }; 1882198090Srdivacky return SelectVLD(Op, 4, DOpcodes, QOpcodes0, QOpcodes1); 1883198090Srdivacky } 1884198090Srdivacky 1885198090Srdivacky case Intrinsic::arm_neon_vld2lane: { 1886198090Srdivacky unsigned DOpcodes[] = { ARM::VLD2LNd8, ARM::VLD2LNd16, ARM::VLD2LNd32 }; 1887198090Srdivacky unsigned QOpcodes0[] = { ARM::VLD2LNq16a, ARM::VLD2LNq32a }; 1888198090Srdivacky unsigned QOpcodes1[] = { ARM::VLD2LNq16b, ARM::VLD2LNq32b }; 1889198090Srdivacky return SelectVLDSTLane(Op, true, 2, DOpcodes, QOpcodes0, QOpcodes1); 1890198090Srdivacky } 1891198090Srdivacky 1892198090Srdivacky case Intrinsic::arm_neon_vld3lane: { 1893198090Srdivacky unsigned DOpcodes[] = { ARM::VLD3LNd8, ARM::VLD3LNd16, ARM::VLD3LNd32 }; 1894198090Srdivacky unsigned QOpcodes0[] = { ARM::VLD3LNq16a, ARM::VLD3LNq32a }; 1895198090Srdivacky unsigned QOpcodes1[] = { ARM::VLD3LNq16b, ARM::VLD3LNq32b }; 1896198090Srdivacky return SelectVLDSTLane(Op, true, 3, DOpcodes, QOpcodes0, QOpcodes1); 1897198090Srdivacky } 1898198090Srdivacky 1899198090Srdivacky case Intrinsic::arm_neon_vld4lane: { 1900198090Srdivacky unsigned DOpcodes[] = { ARM::VLD4LNd8, ARM::VLD4LNd16, ARM::VLD4LNd32 }; 1901198090Srdivacky unsigned QOpcodes0[] = { ARM::VLD4LNq16a, ARM::VLD4LNq32a }; 1902198090Srdivacky unsigned QOpcodes1[] = { ARM::VLD4LNq16b, ARM::VLD4LNq32b }; 1903198090Srdivacky return SelectVLDSTLane(Op, true, 4, DOpcodes, QOpcodes0, QOpcodes1); 1904198090Srdivacky } 1905198090Srdivacky 1906198090Srdivacky case Intrinsic::arm_neon_vst2: { 1907198113Srdivacky unsigned DOpcodes[] = { ARM::VST2d8, ARM::VST2d16, 1908198113Srdivacky ARM::VST2d32, ARM::VST2d64 }; 1909198113Srdivacky unsigned QOpcodes[] = { ARM::VST2q8, ARM::VST2q16, ARM::VST2q32 }; 1910198113Srdivacky return SelectVST(Op, 2, DOpcodes, QOpcodes, 0); 1911198090Srdivacky } 1912194710Sed 1913198090Srdivacky case Intrinsic::arm_neon_vst3: { 1914198113Srdivacky unsigned DOpcodes[] = { ARM::VST3d8, ARM::VST3d16, 1915198113Srdivacky ARM::VST3d32, ARM::VST3d64 }; 1916198113Srdivacky unsigned QOpcodes0[] = { ARM::VST3q8a, ARM::VST3q16a, ARM::VST3q32a }; 1917198113Srdivacky unsigned QOpcodes1[] = { ARM::VST3q8b, ARM::VST3q16b, ARM::VST3q32b }; 1918198113Srdivacky return SelectVST(Op, 3, DOpcodes, QOpcodes0, QOpcodes1); 1919194710Sed } 1920194710Sed 1921198090Srdivacky case Intrinsic::arm_neon_vst4: { 1922198113Srdivacky unsigned DOpcodes[] = { ARM::VST4d8, ARM::VST4d16, 1923198113Srdivacky ARM::VST4d32, ARM::VST4d64 }; 1924198113Srdivacky unsigned QOpcodes0[] = { ARM::VST4q8a, ARM::VST4q16a, ARM::VST4q32a }; 1925198113Srdivacky unsigned QOpcodes1[] = { ARM::VST4q8b, ARM::VST4q16b, ARM::VST4q32b }; 1926198113Srdivacky return SelectVST(Op, 4, DOpcodes, QOpcodes0, QOpcodes1); 1927198090Srdivacky } 1928198090Srdivacky 1929198090Srdivacky case Intrinsic::arm_neon_vst2lane: { 1930198090Srdivacky unsigned DOpcodes[] = { ARM::VST2LNd8, ARM::VST2LNd16, ARM::VST2LNd32 }; 1931198090Srdivacky unsigned QOpcodes0[] = { ARM::VST2LNq16a, ARM::VST2LNq32a }; 1932198090Srdivacky unsigned QOpcodes1[] = { ARM::VST2LNq16b, ARM::VST2LNq32b }; 1933198090Srdivacky return SelectVLDSTLane(Op, false, 2, DOpcodes, QOpcodes0, QOpcodes1); 1934198090Srdivacky } 1935198090Srdivacky 1936198090Srdivacky case Intrinsic::arm_neon_vst3lane: { 1937198090Srdivacky unsigned DOpcodes[] = { ARM::VST3LNd8, ARM::VST3LNd16, ARM::VST3LNd32 }; 1938198090Srdivacky unsigned QOpcodes0[] = { ARM::VST3LNq16a, ARM::VST3LNq32a }; 1939198090Srdivacky unsigned QOpcodes1[] = { ARM::VST3LNq16b, ARM::VST3LNq32b }; 1940198090Srdivacky return SelectVLDSTLane(Op, false, 3, DOpcodes, QOpcodes0, QOpcodes1); 1941198090Srdivacky } 1942198090Srdivacky 1943198090Srdivacky case Intrinsic::arm_neon_vst4lane: { 1944198090Srdivacky unsigned DOpcodes[] = { ARM::VST4LNd8, ARM::VST4LNd16, ARM::VST4LNd32 }; 1945198090Srdivacky unsigned QOpcodes0[] = { ARM::VST4LNq16a, ARM::VST4LNq32a }; 1946198090Srdivacky unsigned QOpcodes1[] = { ARM::VST4LNq16b, ARM::VST4LNq32b }; 1947198090Srdivacky return SelectVLDSTLane(Op, false, 4, DOpcodes, QOpcodes0, QOpcodes1); 1948198090Srdivacky } 1949198090Srdivacky } 1950194710Sed } 1951194710Sed } 1952194710Sed 1953193323Sed return SelectCode(Op); 1954193323Sed} 1955193323Sed 1956193323Sedbool ARMDAGToDAGISel:: 1957193323SedSelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, 1958193323Sed std::vector<SDValue> &OutOps) { 1959193323Sed assert(ConstraintCode == 'm' && "unexpected asm memory constraint"); 1960198090Srdivacky // Require the address to be in a register. That is safe for all ARM 1961198090Srdivacky // variants and it is hard to do anything much smarter without knowing 1962198090Srdivacky // how the operand is used. 1963198090Srdivacky OutOps.push_back(Op); 1964193323Sed return false; 1965193323Sed} 1966193323Sed 1967193323Sed/// createARMISelDag - This pass converts a legalized DAG into a 1968193323Sed/// ARM-specific DAG, ready for instruction scheduling. 1969193323Sed/// 1970198090SrdivackyFunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM, 1971198090Srdivacky CodeGenOpt::Level OptLevel) { 1972198090Srdivacky return new ARMDAGToDAGISel(TM, OptLevel); 1973193323Sed} 1974