ARMISelDAGToDAG.cpp revision 202878
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 67202375Srdivacky SDNode *Select(SDNode *N); 68193323Sed virtual void InstructionSelect(); 69202375Srdivacky bool SelectShifterOperandReg(SDNode *Op, SDValue N, SDValue &A, 70195340Sed SDValue &B, SDValue &C); 71202375Srdivacky bool SelectAddrMode2(SDNode *Op, SDValue N, SDValue &Base, 72193323Sed SDValue &Offset, SDValue &Opc); 73202375Srdivacky bool SelectAddrMode2Offset(SDNode *Op, SDValue N, 74193323Sed SDValue &Offset, SDValue &Opc); 75202375Srdivacky bool SelectAddrMode3(SDNode *Op, SDValue N, SDValue &Base, 76193323Sed SDValue &Offset, SDValue &Opc); 77202375Srdivacky bool SelectAddrMode3Offset(SDNode *Op, SDValue N, 78193323Sed SDValue &Offset, SDValue &Opc); 79202375Srdivacky bool SelectAddrMode4(SDNode *Op, SDValue N, SDValue &Addr, 80198090Srdivacky SDValue &Mode); 81202375Srdivacky bool SelectAddrMode5(SDNode *Op, SDValue N, SDValue &Base, 82193323Sed SDValue &Offset); 83202375Srdivacky bool SelectAddrMode6(SDNode *Op, SDValue N, SDValue &Addr, SDValue &Update, 84199481Srdivacky SDValue &Opc, SDValue &Align); 85193323Sed 86202375Srdivacky bool SelectAddrModePC(SDNode *Op, SDValue N, SDValue &Offset, 87195340Sed SDValue &Label); 88193323Sed 89202375Srdivacky bool SelectThumbAddrModeRR(SDNode *Op, SDValue N, SDValue &Base, 90193323Sed SDValue &Offset); 91202375Srdivacky bool SelectThumbAddrModeRI5(SDNode *Op, SDValue N, unsigned Scale, 92193323Sed SDValue &Base, SDValue &OffImm, 93193323Sed SDValue &Offset); 94202375Srdivacky bool SelectThumbAddrModeS1(SDNode *Op, SDValue N, SDValue &Base, 95193323Sed SDValue &OffImm, SDValue &Offset); 96202375Srdivacky bool SelectThumbAddrModeS2(SDNode *Op, SDValue N, SDValue &Base, 97193323Sed SDValue &OffImm, SDValue &Offset); 98202375Srdivacky bool SelectThumbAddrModeS4(SDNode *Op, SDValue N, SDValue &Base, 99193323Sed SDValue &OffImm, SDValue &Offset); 100202375Srdivacky bool SelectThumbAddrModeSP(SDNode *Op, SDValue N, SDValue &Base, 101193323Sed SDValue &OffImm); 102193323Sed 103202375Srdivacky bool SelectT2ShifterOperandReg(SDNode *Op, SDValue N, 104195098Sed SDValue &BaseReg, SDValue &Opc); 105202375Srdivacky bool SelectT2AddrModeImm12(SDNode *Op, SDValue N, SDValue &Base, 106195340Sed SDValue &OffImm); 107202375Srdivacky bool SelectT2AddrModeImm8(SDNode *Op, SDValue N, SDValue &Base, 108195340Sed SDValue &OffImm); 109202375Srdivacky bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N, 110195340Sed SDValue &OffImm); 111202375Srdivacky bool SelectT2AddrModeImm8s4(SDNode *Op, SDValue N, SDValue &Base, 112195340Sed SDValue &OffImm); 113202375Srdivacky bool SelectT2AddrModeSoReg(SDNode *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. 122202375Srdivacky SDNode *SelectARMIndexedLoad(SDNode *N); 123202375Srdivacky SDNode *SelectT2IndexedLoad(SDNode *N); 124195340Sed 125198090Srdivacky /// SelectDYN_ALLOC - Select dynamic alloc for Thumb. 126202375Srdivacky SDNode *SelectDYN_ALLOC(SDNode *N); 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. 132202375Srdivacky SDNode *SelectVLD(SDNode *N, 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. 139202375Srdivacky SDNode *SelectVST(SDNode *N, 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. 145202375Srdivacky SDNode *SelectVLDSTLane(SDNode *N, bool IsLoad, unsigned NumVecs, 146198090Srdivacky unsigned *DOpcodes, unsigned *QOpcodes0, 147198090Srdivacky unsigned *QOpcodes1); 148198090Srdivacky 149198090Srdivacky /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM. 150202375Srdivacky SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, unsigned Opc); 151198090Srdivacky 152199989Srdivacky /// SelectCMOVOp - Select CMOV instructions for ARM. 153202375Srdivacky SDNode *SelectCMOVOp(SDNode *N); 154202375Srdivacky SDNode *SelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 155199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 156199989Srdivacky SDValue InFlag); 157202375Srdivacky SDNode *SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 158199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 159199989Srdivacky SDValue InFlag); 160202375Srdivacky SDNode *SelectT2CMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 161199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 162199989Srdivacky SDValue InFlag); 163202375Srdivacky SDNode *SelectARMCMOVSoImmOp(SDNode *N, 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 209202375Srdivackybool ARMDAGToDAGISel::SelectShifterOperandReg(SDNode *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 233202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode2(SDNode *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 343202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode2Offset(SDNode *Op, SDValue N, 344193323Sed SDValue &Offset, SDValue &Opc) { 345202375Srdivacky 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 382202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode3(SDNode *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 432202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N, 433193323Sed SDValue &Offset, SDValue &Opc) { 434202375Srdivacky 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 454202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode4(SDNode *Op, SDValue N, 455198090Srdivacky SDValue &Addr, SDValue &Mode) { 456198090Srdivacky Addr = N; 457198090Srdivacky Mode = CurDAG->getTargetConstant(0, MVT::i32); 458198090Srdivacky return true; 459198090Srdivacky} 460193323Sed 461202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode5(SDNode *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 509202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode6(SDNode *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 521202375Srdivackybool ARMDAGToDAGISel::SelectAddrModePC(SDNode *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 533202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDNode *Op, SDValue N, 534193323Sed SDValue &Base, SDValue &Offset){ 535193323Sed // FIXME dl should come from the parent load or store, not the address 536202375Srdivacky 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 552202375SrdivackyARMDAGToDAGISel::SelectThumbAddrModeRI5(SDNode *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 608202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeS1(SDNode *Op, SDValue N, 609193323Sed SDValue &Base, SDValue &OffImm, 610193323Sed SDValue &Offset) { 611193323Sed return SelectThumbAddrModeRI5(Op, N, 1, Base, OffImm, Offset); 612193323Sed} 613193323Sed 614202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeS2(SDNode *Op, SDValue N, 615193323Sed SDValue &Base, SDValue &OffImm, 616193323Sed SDValue &Offset) { 617193323Sed return SelectThumbAddrModeRI5(Op, N, 2, Base, OffImm, Offset); 618193323Sed} 619193323Sed 620202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeS4(SDNode *Op, SDValue N, 621193323Sed SDValue &Base, SDValue &OffImm, 622193323Sed SDValue &Offset) { 623193323Sed return SelectThumbAddrModeRI5(Op, N, 4, Base, OffImm, Offset); 624193323Sed} 625193323Sed 626202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDNode *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 662202375Srdivackybool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDNode *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 682202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDNode *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 732202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDNode *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 756202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N, 757195340Sed SDValue &OffImm){ 758202375Srdivacky 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 775202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm8s4(SDNode *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 801202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDNode *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 857202375SrdivackySDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) { 858202375Srdivacky LoadSDNode *LD = cast<LoadSDNode>(N); 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 && 869202375Srdivacky SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) { 870195340Sed Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST; 871195340Sed Match = true; 872195340Sed } else if (LoadedVT == MVT::i16 && 873202375Srdivacky SelectAddrMode3Offset(N, 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) { 880202375Srdivacky if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) { 881195340Sed Match = true; 882195340Sed Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST; 883195340Sed } 884195340Sed } else { 885202375Srdivacky if (SelectAddrMode2Offset(N, 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 }; 897202375Srdivacky return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, MVT::i32, 898198090Srdivacky MVT::Other, Ops, 6); 899195340Sed } 900195340Sed 901195340Sed return NULL; 902195340Sed} 903195340Sed 904202375SrdivackySDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) { 905202375Srdivacky LoadSDNode *LD = cast<LoadSDNode>(N); 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; 916202375Srdivacky if (SelectT2AddrModeImm8Offset(N, 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 }; 945202375Srdivacky return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, MVT::i32, 946198090Srdivacky MVT::Other, Ops, 5); 947195340Sed } 948195340Sed 949195340Sed return NULL; 950195340Sed} 951195340Sed 952202375SrdivackySDNode *ARMDAGToDAGISel::SelectDYN_ALLOC(SDNode *N) { 953198090Srdivacky DebugLoc dl = N->getDebugLoc(); 954202375Srdivacky EVT VT = N->getValueType(0); 955202375Srdivacky SDValue Chain = N->getOperand(0); 956202375Srdivacky SDValue Size = N->getOperand(1); 957202375Srdivacky SDValue Align = N->getOperand(2); 958198090Srdivacky SDValue SP = CurDAG->getRegister(ARM::SP, MVT::i32); 959198090Srdivacky int32_t AlignVal = cast<ConstantSDNode>(Align)->getSExtValue(); 960198090Srdivacky if (AlignVal < 0) 961198090Srdivacky // We need to align the stack. Use Thumb1 tAND which is the only thumb 962198090Srdivacky // instruction that can read and write SP. This matches to a pseudo 963198090Srdivacky // instruction that has a chain to ensure the result is written back to 964198090Srdivacky // the stack pointer. 965198090Srdivacky SP = SDValue(CurDAG->getMachineNode(ARM::tANDsp, dl, VT, SP, Align), 0); 966195340Sed 967198090Srdivacky bool isC = isa<ConstantSDNode>(Size); 968198090Srdivacky uint32_t C = isC ? cast<ConstantSDNode>(Size)->getZExtValue() : ~0UL; 969198090Srdivacky // Handle the most common case for both Thumb1 and Thumb2: 970198090Srdivacky // tSUBspi - immediate is between 0 ... 508 inclusive. 971198090Srdivacky if (C <= 508 && ((C & 3) == 0)) 972198090Srdivacky // FIXME: tSUBspi encode scale 4 implicitly. 973198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::tSUBspi_, VT, MVT::Other, SP, 974198090Srdivacky CurDAG->getTargetConstant(C/4, MVT::i32), 975198090Srdivacky Chain); 976198090Srdivacky 977198090Srdivacky if (Subtarget->isThumb1Only()) { 978198090Srdivacky // Use tADDspr since Thumb1 does not have a sub r, sp, r. ARMISelLowering 979198090Srdivacky // should have negated the size operand already. FIXME: We can't insert 980198090Srdivacky // new target independent node at this stage so we are forced to negate 981198090Srdivacky // it earlier. Is there a better solution? 982198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::tADDspr_, VT, MVT::Other, SP, Size, 983198090Srdivacky Chain); 984198090Srdivacky } else if (Subtarget->isThumb2()) { 985198090Srdivacky if (isC && Predicate_t2_so_imm(Size.getNode())) { 986198090Srdivacky // t2SUBrSPi 987198090Srdivacky SDValue Ops[] = { SP, CurDAG->getTargetConstant(C, MVT::i32), Chain }; 988198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPi_, VT, MVT::Other, Ops, 3); 989198090Srdivacky } else if (isC && Predicate_imm0_4095(Size.getNode())) { 990198090Srdivacky // t2SUBrSPi12 991198090Srdivacky SDValue Ops[] = { SP, CurDAG->getTargetConstant(C, MVT::i32), Chain }; 992198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPi12_, VT, MVT::Other, Ops, 3); 993198090Srdivacky } else { 994198090Srdivacky // t2SUBrSPs 995198090Srdivacky SDValue Ops[] = { SP, Size, 996198090Srdivacky getI32Imm(ARM_AM::getSORegOpc(ARM_AM::lsl,0)), Chain }; 997198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPs_, VT, MVT::Other, Ops, 4); 998198090Srdivacky } 999198090Srdivacky } 1000198090Srdivacky 1001198090Srdivacky // FIXME: Add ADD / SUB sp instructions for ARM. 1002198090Srdivacky return 0; 1003198090Srdivacky} 1004198090Srdivacky 1005198090Srdivacky/// PairDRegs - Insert a pair of double registers into an implicit def to 1006198090Srdivacky/// form a quad register. 1007198090SrdivackySDNode *ARMDAGToDAGISel::PairDRegs(EVT VT, SDValue V0, SDValue V1) { 1008198090Srdivacky DebugLoc dl = V0.getNode()->getDebugLoc(); 1009198090Srdivacky SDValue Undef = 1010198090Srdivacky SDValue(CurDAG->getMachineNode(TargetInstrInfo::IMPLICIT_DEF, dl, VT), 0); 1011198090Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::DSUBREG_0, MVT::i32); 1012198090Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::DSUBREG_1, MVT::i32); 1013198090Srdivacky SDNode *Pair = CurDAG->getMachineNode(TargetInstrInfo::INSERT_SUBREG, dl, 1014198090Srdivacky VT, Undef, V0, SubReg0); 1015198090Srdivacky return CurDAG->getMachineNode(TargetInstrInfo::INSERT_SUBREG, dl, 1016198090Srdivacky VT, SDValue(Pair, 0), V1, SubReg1); 1017198090Srdivacky} 1018198090Srdivacky 1019198090Srdivacky/// GetNEONSubregVT - Given a type for a 128-bit NEON vector, return the type 1020198090Srdivacky/// for a 64-bit subregister of the vector. 1021198090Srdivackystatic EVT GetNEONSubregVT(EVT VT) { 1022198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1023198090Srdivacky default: llvm_unreachable("unhandled NEON type"); 1024198090Srdivacky case MVT::v16i8: return MVT::v8i8; 1025198090Srdivacky case MVT::v8i16: return MVT::v4i16; 1026198090Srdivacky case MVT::v4f32: return MVT::v2f32; 1027198090Srdivacky case MVT::v4i32: return MVT::v2i32; 1028198090Srdivacky case MVT::v2i64: return MVT::v1i64; 1029198090Srdivacky } 1030198090Srdivacky} 1031198090Srdivacky 1032202375SrdivackySDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, unsigned NumVecs, 1033198090Srdivacky unsigned *DOpcodes, unsigned *QOpcodes0, 1034198090Srdivacky unsigned *QOpcodes1) { 1035198090Srdivacky assert(NumVecs >=2 && NumVecs <= 4 && "VLD NumVecs out-of-range"); 1036198090Srdivacky DebugLoc dl = N->getDebugLoc(); 1037198090Srdivacky 1038199481Srdivacky SDValue MemAddr, MemUpdate, MemOpc, Align; 1039202375Srdivacky if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, MemUpdate, MemOpc, Align)) 1040198090Srdivacky return NULL; 1041198090Srdivacky 1042198090Srdivacky SDValue Chain = N->getOperand(0); 1043198090Srdivacky EVT VT = N->getValueType(0); 1044198090Srdivacky bool is64BitVector = VT.is64BitVector(); 1045198090Srdivacky 1046198090Srdivacky unsigned OpcodeIndex; 1047198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1048198090Srdivacky default: llvm_unreachable("unhandled vld type"); 1049198090Srdivacky // Double-register operations: 1050198090Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1051198090Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1052198090Srdivacky case MVT::v2f32: 1053198090Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1054198090Srdivacky case MVT::v1i64: OpcodeIndex = 3; break; 1055198090Srdivacky // Quad-register operations: 1056198090Srdivacky case MVT::v16i8: OpcodeIndex = 0; break; 1057198090Srdivacky case MVT::v8i16: OpcodeIndex = 1; break; 1058198090Srdivacky case MVT::v4f32: 1059198090Srdivacky case MVT::v4i32: OpcodeIndex = 2; break; 1060198090Srdivacky } 1061198090Srdivacky 1062199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1063199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1064198090Srdivacky if (is64BitVector) { 1065198090Srdivacky unsigned Opc = DOpcodes[OpcodeIndex]; 1066199989Srdivacky const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, Align, 1067199989Srdivacky Pred, PredReg, Chain }; 1068198090Srdivacky std::vector<EVT> ResTys(NumVecs, VT); 1069198090Srdivacky ResTys.push_back(MVT::Other); 1070199989Srdivacky return CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 7); 1071198090Srdivacky } 1072198090Srdivacky 1073198090Srdivacky EVT RegVT = GetNEONSubregVT(VT); 1074198090Srdivacky if (NumVecs == 2) { 1075198090Srdivacky // Quad registers are directly supported for VLD2, 1076198090Srdivacky // loading 2 pairs of D regs. 1077198090Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1078199989Srdivacky const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, Align, 1079199989Srdivacky Pred, PredReg, Chain }; 1080198090Srdivacky std::vector<EVT> ResTys(4, VT); 1081198090Srdivacky ResTys.push_back(MVT::Other); 1082199989Srdivacky SDNode *VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 7); 1083198090Srdivacky Chain = SDValue(VLd, 4); 1084198090Srdivacky 1085198090Srdivacky // Combine the even and odd subregs to produce the result. 1086198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1087198090Srdivacky SDNode *Q = PairDRegs(VT, SDValue(VLd, 2*Vec), SDValue(VLd, 2*Vec+1)); 1088198090Srdivacky ReplaceUses(SDValue(N, Vec), SDValue(Q, 0)); 1089198090Srdivacky } 1090198090Srdivacky } else { 1091198090Srdivacky // Otherwise, quad registers are loaded with two separate instructions, 1092198090Srdivacky // where one loads the even registers and the other loads the odd registers. 1093198090Srdivacky 1094198090Srdivacky // Enable writeback to the address register. 1095198090Srdivacky MemOpc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(true), MVT::i32); 1096198090Srdivacky 1097198090Srdivacky std::vector<EVT> ResTys(NumVecs, RegVT); 1098198090Srdivacky ResTys.push_back(MemAddr.getValueType()); 1099198090Srdivacky ResTys.push_back(MVT::Other); 1100198090Srdivacky 1101198113Srdivacky // Load the even subregs. 1102198090Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1103199989Srdivacky const SDValue OpsA[] = { MemAddr, MemUpdate, MemOpc, Align, 1104199989Srdivacky Pred, PredReg, Chain }; 1105199989Srdivacky SDNode *VLdA = CurDAG->getMachineNode(Opc, dl, ResTys, OpsA, 7); 1106198090Srdivacky Chain = SDValue(VLdA, NumVecs+1); 1107198090Srdivacky 1108198113Srdivacky // Load the odd subregs. 1109198090Srdivacky Opc = QOpcodes1[OpcodeIndex]; 1110199481Srdivacky const SDValue OpsB[] = { SDValue(VLdA, NumVecs), MemUpdate, MemOpc, 1111199989Srdivacky Align, Pred, PredReg, Chain }; 1112199989Srdivacky SDNode *VLdB = CurDAG->getMachineNode(Opc, dl, ResTys, OpsB, 7); 1113198090Srdivacky Chain = SDValue(VLdB, NumVecs+1); 1114198090Srdivacky 1115198090Srdivacky // Combine the even and odd subregs to produce the result. 1116198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1117198090Srdivacky SDNode *Q = PairDRegs(VT, SDValue(VLdA, Vec), SDValue(VLdB, Vec)); 1118198090Srdivacky ReplaceUses(SDValue(N, Vec), SDValue(Q, 0)); 1119198090Srdivacky } 1120198090Srdivacky } 1121198090Srdivacky ReplaceUses(SDValue(N, NumVecs), Chain); 1122198090Srdivacky return NULL; 1123198090Srdivacky} 1124198090Srdivacky 1125202375SrdivackySDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, unsigned NumVecs, 1126198113Srdivacky unsigned *DOpcodes, unsigned *QOpcodes0, 1127198113Srdivacky unsigned *QOpcodes1) { 1128198113Srdivacky assert(NumVecs >=2 && NumVecs <= 4 && "VST NumVecs out-of-range"); 1129198113Srdivacky DebugLoc dl = N->getDebugLoc(); 1130198113Srdivacky 1131199481Srdivacky SDValue MemAddr, MemUpdate, MemOpc, Align; 1132202375Srdivacky if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, MemUpdate, MemOpc, Align)) 1133198113Srdivacky return NULL; 1134198113Srdivacky 1135198113Srdivacky SDValue Chain = N->getOperand(0); 1136198113Srdivacky EVT VT = N->getOperand(3).getValueType(); 1137198113Srdivacky bool is64BitVector = VT.is64BitVector(); 1138198113Srdivacky 1139198113Srdivacky unsigned OpcodeIndex; 1140198113Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1141198113Srdivacky default: llvm_unreachable("unhandled vst type"); 1142198113Srdivacky // Double-register operations: 1143198113Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1144198113Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1145198113Srdivacky case MVT::v2f32: 1146198113Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1147198113Srdivacky case MVT::v1i64: OpcodeIndex = 3; break; 1148198113Srdivacky // Quad-register operations: 1149198113Srdivacky case MVT::v16i8: OpcodeIndex = 0; break; 1150198113Srdivacky case MVT::v8i16: OpcodeIndex = 1; break; 1151198113Srdivacky case MVT::v4f32: 1152198113Srdivacky case MVT::v4i32: OpcodeIndex = 2; break; 1153198113Srdivacky } 1154198113Srdivacky 1155199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1156199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1157199989Srdivacky 1158198113Srdivacky SmallVector<SDValue, 8> Ops; 1159198113Srdivacky Ops.push_back(MemAddr); 1160198113Srdivacky Ops.push_back(MemUpdate); 1161198113Srdivacky Ops.push_back(MemOpc); 1162199481Srdivacky Ops.push_back(Align); 1163198113Srdivacky 1164198113Srdivacky if (is64BitVector) { 1165198113Srdivacky unsigned Opc = DOpcodes[OpcodeIndex]; 1166198113Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1167198113Srdivacky Ops.push_back(N->getOperand(Vec+3)); 1168199989Srdivacky Ops.push_back(Pred); 1169199989Srdivacky Ops.push_back(PredReg); 1170198113Srdivacky Ops.push_back(Chain); 1171199989Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+7); 1172198113Srdivacky } 1173198113Srdivacky 1174198113Srdivacky EVT RegVT = GetNEONSubregVT(VT); 1175198113Srdivacky if (NumVecs == 2) { 1176198113Srdivacky // Quad registers are directly supported for VST2, 1177198113Srdivacky // storing 2 pairs of D regs. 1178198113Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1179198113Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1180198113Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT, 1181198113Srdivacky N->getOperand(Vec+3))); 1182198113Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT, 1183198113Srdivacky N->getOperand(Vec+3))); 1184198113Srdivacky } 1185199989Srdivacky Ops.push_back(Pred); 1186199989Srdivacky Ops.push_back(PredReg); 1187198113Srdivacky Ops.push_back(Chain); 1188199989Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), 11); 1189198113Srdivacky } 1190198113Srdivacky 1191198113Srdivacky // Otherwise, quad registers are stored with two separate instructions, 1192198113Srdivacky // where one stores the even registers and the other stores the odd registers. 1193198113Srdivacky 1194198113Srdivacky // Enable writeback to the address register. 1195198113Srdivacky MemOpc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(true), MVT::i32); 1196198113Srdivacky 1197198113Srdivacky // Store the even subregs. 1198198113Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1199198113Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT, 1200198113Srdivacky N->getOperand(Vec+3))); 1201199989Srdivacky Ops.push_back(Pred); 1202199989Srdivacky Ops.push_back(PredReg); 1203198113Srdivacky Ops.push_back(Chain); 1204198113Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1205198113Srdivacky SDNode *VStA = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(), 1206199989Srdivacky MVT::Other, Ops.data(), NumVecs+7); 1207198113Srdivacky Chain = SDValue(VStA, 1); 1208198113Srdivacky 1209198113Srdivacky // Store the odd subregs. 1210198113Srdivacky Ops[0] = SDValue(VStA, 0); // MemAddr 1211198113Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1212199481Srdivacky Ops[Vec+4] = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT, 1213198113Srdivacky N->getOperand(Vec+3)); 1214199989Srdivacky Ops[NumVecs+4] = Pred; 1215199989Srdivacky Ops[NumVecs+5] = PredReg; 1216199989Srdivacky Ops[NumVecs+6] = Chain; 1217198113Srdivacky Opc = QOpcodes1[OpcodeIndex]; 1218198113Srdivacky SDNode *VStB = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(), 1219199989Srdivacky MVT::Other, Ops.data(), NumVecs+7); 1220198113Srdivacky Chain = SDValue(VStB, 1); 1221198113Srdivacky ReplaceUses(SDValue(N, 0), Chain); 1222198113Srdivacky return NULL; 1223198113Srdivacky} 1224198113Srdivacky 1225202375SrdivackySDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, 1226198090Srdivacky unsigned NumVecs, unsigned *DOpcodes, 1227198090Srdivacky unsigned *QOpcodes0, 1228198090Srdivacky unsigned *QOpcodes1) { 1229198090Srdivacky assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range"); 1230198090Srdivacky DebugLoc dl = N->getDebugLoc(); 1231198090Srdivacky 1232199481Srdivacky SDValue MemAddr, MemUpdate, MemOpc, Align; 1233202375Srdivacky if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, MemUpdate, MemOpc, Align)) 1234198090Srdivacky return NULL; 1235198090Srdivacky 1236198090Srdivacky SDValue Chain = N->getOperand(0); 1237198090Srdivacky unsigned Lane = 1238198090Srdivacky cast<ConstantSDNode>(N->getOperand(NumVecs+3))->getZExtValue(); 1239198090Srdivacky EVT VT = IsLoad ? N->getValueType(0) : N->getOperand(3).getValueType(); 1240198090Srdivacky bool is64BitVector = VT.is64BitVector(); 1241198090Srdivacky 1242198090Srdivacky // Quad registers are handled by load/store of subregs. Find the subreg info. 1243198090Srdivacky unsigned NumElts = 0; 1244198090Srdivacky int SubregIdx = 0; 1245198090Srdivacky EVT RegVT = VT; 1246198090Srdivacky if (!is64BitVector) { 1247198090Srdivacky RegVT = GetNEONSubregVT(VT); 1248198090Srdivacky NumElts = RegVT.getVectorNumElements(); 1249198090Srdivacky SubregIdx = (Lane < NumElts) ? ARM::DSUBREG_0 : ARM::DSUBREG_1; 1250198090Srdivacky } 1251198090Srdivacky 1252198090Srdivacky unsigned OpcodeIndex; 1253198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1254198090Srdivacky default: llvm_unreachable("unhandled vld/vst lane type"); 1255198090Srdivacky // Double-register operations: 1256198090Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1257198090Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1258198090Srdivacky case MVT::v2f32: 1259198090Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1260198090Srdivacky // Quad-register operations: 1261198090Srdivacky case MVT::v8i16: OpcodeIndex = 0; break; 1262198090Srdivacky case MVT::v4f32: 1263198090Srdivacky case MVT::v4i32: OpcodeIndex = 1; break; 1264198090Srdivacky } 1265198090Srdivacky 1266199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1267199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1268199989Srdivacky 1269198090Srdivacky SmallVector<SDValue, 9> Ops; 1270198090Srdivacky Ops.push_back(MemAddr); 1271198090Srdivacky Ops.push_back(MemUpdate); 1272198090Srdivacky Ops.push_back(MemOpc); 1273199481Srdivacky Ops.push_back(Align); 1274198090Srdivacky 1275198090Srdivacky unsigned Opc = 0; 1276198090Srdivacky if (is64BitVector) { 1277198090Srdivacky Opc = DOpcodes[OpcodeIndex]; 1278198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1279198090Srdivacky Ops.push_back(N->getOperand(Vec+3)); 1280198090Srdivacky } else { 1281198090Srdivacky // Check if this is loading the even or odd subreg of a Q register. 1282198090Srdivacky if (Lane < NumElts) { 1283198090Srdivacky Opc = QOpcodes0[OpcodeIndex]; 1284198090Srdivacky } else { 1285198090Srdivacky Lane -= NumElts; 1286198090Srdivacky Opc = QOpcodes1[OpcodeIndex]; 1287198090Srdivacky } 1288198090Srdivacky // Extract the subregs of the input vector. 1289198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1290198090Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT, 1291198090Srdivacky N->getOperand(Vec+3))); 1292198090Srdivacky } 1293198090Srdivacky Ops.push_back(getI32Imm(Lane)); 1294199989Srdivacky Ops.push_back(Pred); 1295199989Srdivacky Ops.push_back(PredReg); 1296198090Srdivacky Ops.push_back(Chain); 1297198090Srdivacky 1298198090Srdivacky if (!IsLoad) 1299202878Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+8); 1300198090Srdivacky 1301198090Srdivacky std::vector<EVT> ResTys(NumVecs, RegVT); 1302198090Srdivacky ResTys.push_back(MVT::Other); 1303198090Srdivacky SDNode *VLdLn = 1304202878Srdivacky CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), NumVecs+8); 1305198090Srdivacky // For a 64-bit vector load to D registers, nothing more needs to be done. 1306198090Srdivacky if (is64BitVector) 1307198090Srdivacky return VLdLn; 1308198090Srdivacky 1309198090Srdivacky // For 128-bit vectors, take the 64-bit results of the load and insert them 1310198090Srdivacky // as subregs into the result. 1311198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1312198090Srdivacky SDValue QuadVec = CurDAG->getTargetInsertSubreg(SubregIdx, dl, VT, 1313198090Srdivacky N->getOperand(Vec+3), 1314198090Srdivacky SDValue(VLdLn, Vec)); 1315198090Srdivacky ReplaceUses(SDValue(N, Vec), QuadVec); 1316198090Srdivacky } 1317198090Srdivacky 1318198090Srdivacky Chain = SDValue(VLdLn, NumVecs); 1319198090Srdivacky ReplaceUses(SDValue(N, NumVecs), Chain); 1320198090Srdivacky return NULL; 1321198090Srdivacky} 1322198090Srdivacky 1323202375SrdivackySDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N, 1324198090Srdivacky unsigned Opc) { 1325198090Srdivacky if (!Subtarget->hasV6T2Ops()) 1326198090Srdivacky return NULL; 1327198090Srdivacky 1328198090Srdivacky unsigned Shl_imm = 0; 1329202375Srdivacky if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) { 1330198090Srdivacky assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!"); 1331198090Srdivacky unsigned Srl_imm = 0; 1332202375Srdivacky if (isInt32Immediate(N->getOperand(1), Srl_imm)) { 1333198090Srdivacky assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); 1334198090Srdivacky unsigned Width = 32 - Srl_imm; 1335198090Srdivacky int LSB = Srl_imm - Shl_imm; 1336198396Srdivacky if (LSB < 0) 1337198090Srdivacky return NULL; 1338198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1339202375Srdivacky SDValue Ops[] = { N->getOperand(0).getOperand(0), 1340198090Srdivacky CurDAG->getTargetConstant(LSB, MVT::i32), 1341198090Srdivacky CurDAG->getTargetConstant(Width, MVT::i32), 1342198090Srdivacky getAL(CurDAG), Reg0 }; 1343202375Srdivacky return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); 1344198090Srdivacky } 1345198090Srdivacky } 1346198090Srdivacky return NULL; 1347198090Srdivacky} 1348198090Srdivacky 1349199989SrdivackySDNode *ARMDAGToDAGISel:: 1350202375SrdivackySelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 1351199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1352199989Srdivacky SDValue CPTmp0; 1353199989Srdivacky SDValue CPTmp1; 1354202375Srdivacky if (SelectT2ShifterOperandReg(N, TrueVal, CPTmp0, CPTmp1)) { 1355199989Srdivacky unsigned SOVal = cast<ConstantSDNode>(CPTmp1)->getZExtValue(); 1356199989Srdivacky unsigned SOShOp = ARM_AM::getSORegShOp(SOVal); 1357199989Srdivacky unsigned Opc = 0; 1358199989Srdivacky switch (SOShOp) { 1359199989Srdivacky case ARM_AM::lsl: Opc = ARM::t2MOVCClsl; break; 1360199989Srdivacky case ARM_AM::lsr: Opc = ARM::t2MOVCClsr; break; 1361199989Srdivacky case ARM_AM::asr: Opc = ARM::t2MOVCCasr; break; 1362199989Srdivacky case ARM_AM::ror: Opc = ARM::t2MOVCCror; break; 1363199989Srdivacky default: 1364199989Srdivacky llvm_unreachable("Unknown so_reg opcode!"); 1365199989Srdivacky break; 1366199989Srdivacky } 1367199989Srdivacky SDValue SOShImm = 1368199989Srdivacky CurDAG->getTargetConstant(ARM_AM::getSORegOffset(SOVal), MVT::i32); 1369199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1370199989Srdivacky SDValue Ops[] = { FalseVal, CPTmp0, SOShImm, CC, CCR, InFlag }; 1371202375Srdivacky return CurDAG->SelectNodeTo(N, Opc, MVT::i32,Ops, 6); 1372199989Srdivacky } 1373199989Srdivacky return 0; 1374199989Srdivacky} 1375199989Srdivacky 1376199989SrdivackySDNode *ARMDAGToDAGISel:: 1377202375SrdivackySelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 1378199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1379199989Srdivacky SDValue CPTmp0; 1380199989Srdivacky SDValue CPTmp1; 1381199989Srdivacky SDValue CPTmp2; 1382202375Srdivacky if (SelectShifterOperandReg(N, TrueVal, CPTmp0, CPTmp1, CPTmp2)) { 1383199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1384199989Srdivacky SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, InFlag }; 1385202375Srdivacky return CurDAG->SelectNodeTo(N, ARM::MOVCCs, MVT::i32, Ops, 7); 1386199989Srdivacky } 1387199989Srdivacky return 0; 1388199989Srdivacky} 1389199989Srdivacky 1390199989SrdivackySDNode *ARMDAGToDAGISel:: 1391202375SrdivackySelectT2CMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 1392199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1393199989Srdivacky ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal); 1394199989Srdivacky if (!T) 1395199989Srdivacky return 0; 1396199989Srdivacky 1397199989Srdivacky if (Predicate_t2_so_imm(TrueVal.getNode())) { 1398199989Srdivacky SDValue True = CurDAG->getTargetConstant(T->getZExtValue(), MVT::i32); 1399199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1400199989Srdivacky SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag }; 1401202375Srdivacky return CurDAG->SelectNodeTo(N, 1402199989Srdivacky ARM::t2MOVCCi, MVT::i32, Ops, 5); 1403199989Srdivacky } 1404199989Srdivacky return 0; 1405199989Srdivacky} 1406199989Srdivacky 1407199989SrdivackySDNode *ARMDAGToDAGISel:: 1408202375SrdivackySelectARMCMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 1409199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1410199989Srdivacky ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal); 1411199989Srdivacky if (!T) 1412199989Srdivacky return 0; 1413199989Srdivacky 1414199989Srdivacky if (Predicate_so_imm(TrueVal.getNode())) { 1415199989Srdivacky SDValue True = CurDAG->getTargetConstant(T->getZExtValue(), MVT::i32); 1416199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1417199989Srdivacky SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag }; 1418202375Srdivacky return CurDAG->SelectNodeTo(N, 1419199989Srdivacky ARM::MOVCCi, MVT::i32, Ops, 5); 1420199989Srdivacky } 1421199989Srdivacky return 0; 1422199989Srdivacky} 1423199989Srdivacky 1424202375SrdivackySDNode *ARMDAGToDAGISel::SelectCMOVOp(SDNode *N) { 1425202375Srdivacky EVT VT = N->getValueType(0); 1426202375Srdivacky SDValue FalseVal = N->getOperand(0); 1427202375Srdivacky SDValue TrueVal = N->getOperand(1); 1428202375Srdivacky SDValue CC = N->getOperand(2); 1429202375Srdivacky SDValue CCR = N->getOperand(3); 1430202375Srdivacky SDValue InFlag = N->getOperand(4); 1431199989Srdivacky assert(CC.getOpcode() == ISD::Constant); 1432199989Srdivacky assert(CCR.getOpcode() == ISD::Register); 1433199989Srdivacky ARMCC::CondCodes CCVal = 1434199989Srdivacky (ARMCC::CondCodes)cast<ConstantSDNode>(CC)->getZExtValue(); 1435199989Srdivacky 1436199989Srdivacky if (!Subtarget->isThumb1Only() && VT == MVT::i32) { 1437199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) 1438199989Srdivacky // Emits: (MOVCCs:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) 1439199989Srdivacky // Pattern complexity = 18 cost = 1 size = 0 1440199989Srdivacky SDValue CPTmp0; 1441199989Srdivacky SDValue CPTmp1; 1442199989Srdivacky SDValue CPTmp2; 1443199989Srdivacky if (Subtarget->isThumb()) { 1444202375Srdivacky SDNode *Res = SelectT2CMOVShiftOp(N, FalseVal, TrueVal, 1445199989Srdivacky CCVal, CCR, InFlag); 1446199989Srdivacky if (!Res) 1447202375Srdivacky Res = SelectT2CMOVShiftOp(N, TrueVal, FalseVal, 1448199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1449199989Srdivacky if (Res) 1450199989Srdivacky return Res; 1451199989Srdivacky } else { 1452202375Srdivacky SDNode *Res = SelectARMCMOVShiftOp(N, FalseVal, TrueVal, 1453199989Srdivacky CCVal, CCR, InFlag); 1454199989Srdivacky if (!Res) 1455202375Srdivacky Res = SelectARMCMOVShiftOp(N, TrueVal, FalseVal, 1456199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1457199989Srdivacky if (Res) 1458199989Srdivacky return Res; 1459199989Srdivacky } 1460199989Srdivacky 1461199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, 1462199989Srdivacky // (imm:i32)<<P:Predicate_so_imm>>:$true, 1463199989Srdivacky // (imm:i32):$cc) 1464199989Srdivacky // Emits: (MOVCCi:i32 GPR:i32:$false, 1465199989Srdivacky // (so_imm:i32 (imm:i32):$true), (imm:i32):$cc) 1466199989Srdivacky // Pattern complexity = 10 cost = 1 size = 0 1467199989Srdivacky if (Subtarget->isThumb()) { 1468202375Srdivacky SDNode *Res = SelectT2CMOVSoImmOp(N, FalseVal, TrueVal, 1469199989Srdivacky CCVal, CCR, InFlag); 1470199989Srdivacky if (!Res) 1471202375Srdivacky Res = SelectT2CMOVSoImmOp(N, TrueVal, FalseVal, 1472199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1473199989Srdivacky if (Res) 1474199989Srdivacky return Res; 1475199989Srdivacky } else { 1476202375Srdivacky SDNode *Res = SelectARMCMOVSoImmOp(N, FalseVal, TrueVal, 1477199989Srdivacky CCVal, CCR, InFlag); 1478199989Srdivacky if (!Res) 1479202375Srdivacky Res = SelectARMCMOVSoImmOp(N, TrueVal, FalseVal, 1480199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1481199989Srdivacky if (Res) 1482199989Srdivacky return Res; 1483199989Srdivacky } 1484199989Srdivacky } 1485199989Srdivacky 1486199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1487199989Srdivacky // Emits: (MOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1488199989Srdivacky // Pattern complexity = 6 cost = 1 size = 0 1489199989Srdivacky // 1490199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1491199989Srdivacky // Emits: (tMOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1492199989Srdivacky // Pattern complexity = 6 cost = 11 size = 0 1493199989Srdivacky // 1494199989Srdivacky // Also FCPYScc and FCPYDcc. 1495199989Srdivacky SDValue Tmp2 = CurDAG->getTargetConstant(CCVal, MVT::i32); 1496199989Srdivacky SDValue Ops[] = { FalseVal, TrueVal, Tmp2, CCR, InFlag }; 1497199989Srdivacky unsigned Opc = 0; 1498199989Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1499199989Srdivacky default: assert(false && "Illegal conditional move type!"); 1500199989Srdivacky break; 1501199989Srdivacky case MVT::i32: 1502199989Srdivacky Opc = Subtarget->isThumb() 1503199989Srdivacky ? (Subtarget->hasThumb2() ? ARM::t2MOVCCr : ARM::tMOVCCr_pseudo) 1504199989Srdivacky : ARM::MOVCCr; 1505199989Srdivacky break; 1506199989Srdivacky case MVT::f32: 1507199989Srdivacky Opc = ARM::VMOVScc; 1508199989Srdivacky break; 1509199989Srdivacky case MVT::f64: 1510199989Srdivacky Opc = ARM::VMOVDcc; 1511199989Srdivacky break; 1512199989Srdivacky } 1513202375Srdivacky return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5); 1514199989Srdivacky} 1515199989Srdivacky 1516202375SrdivackySDNode *ARMDAGToDAGISel::Select(SDNode *N) { 1517193323Sed DebugLoc dl = N->getDebugLoc(); 1518193323Sed 1519193323Sed if (N->isMachineOpcode()) 1520193323Sed return NULL; // Already selected. 1521193323Sed 1522193323Sed switch (N->getOpcode()) { 1523193323Sed default: break; 1524193323Sed case ISD::Constant: { 1525193323Sed unsigned Val = cast<ConstantSDNode>(N)->getZExtValue(); 1526193323Sed bool UseCP = true; 1527198090Srdivacky if (Subtarget->hasThumb2()) 1528198090Srdivacky // Thumb2-aware targets have the MOVT instruction, so all immediates can 1529198090Srdivacky // be done with MOV + MOVT, at worst. 1530198090Srdivacky UseCP = 0; 1531198090Srdivacky else { 1532198090Srdivacky if (Subtarget->isThumb()) { 1533194710Sed UseCP = (Val > 255 && // MOV 1534194710Sed ~Val > 255 && // MOV + MVN 1535194710Sed !ARM_AM::isThumbImmShiftedVal(Val)); // MOV + LSL 1536198090Srdivacky } else 1537198090Srdivacky UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV 1538198090Srdivacky ARM_AM::getSOImmVal(~Val) == -1 && // MVN 1539198090Srdivacky !ARM_AM::isSOImmTwoPartVal(Val)); // two instrs. 1540198090Srdivacky } 1541198090Srdivacky 1542193323Sed if (UseCP) { 1543193323Sed SDValue CPIdx = 1544198090Srdivacky CurDAG->getTargetConstantPool(ConstantInt::get( 1545198090Srdivacky Type::getInt32Ty(*CurDAG->getContext()), Val), 1546193323Sed TLI.getPointerTy()); 1547193323Sed 1548193323Sed SDNode *ResNode; 1549198090Srdivacky if (Subtarget->isThumb1Only()) { 1550199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1551198090Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1552198090Srdivacky SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() }; 1553198090Srdivacky ResNode = CurDAG->getMachineNode(ARM::tLDRcp, dl, MVT::i32, MVT::Other, 1554198090Srdivacky Ops, 4); 1555198090Srdivacky } else { 1556193323Sed SDValue Ops[] = { 1557198090Srdivacky CPIdx, 1558193323Sed CurDAG->getRegister(0, MVT::i32), 1559193323Sed CurDAG->getTargetConstant(0, MVT::i32), 1560193323Sed getAL(CurDAG), 1561193323Sed CurDAG->getRegister(0, MVT::i32), 1562193323Sed CurDAG->getEntryNode() 1563193323Sed }; 1564198090Srdivacky ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other, 1565198090Srdivacky Ops, 6); 1566193323Sed } 1567202375Srdivacky ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0)); 1568193323Sed return NULL; 1569193323Sed } 1570198090Srdivacky 1571193323Sed // Other cases are autogenerated. 1572193323Sed break; 1573193323Sed } 1574193323Sed case ISD::FrameIndex: { 1575193323Sed // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm. 1576193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 1577193323Sed SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 1578198090Srdivacky if (Subtarget->isThumb1Only()) { 1579193323Sed return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI, 1580193323Sed CurDAG->getTargetConstant(0, MVT::i32)); 1581193323Sed } else { 1582198090Srdivacky unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ? 1583198090Srdivacky ARM::t2ADDri : ARM::ADDri); 1584193323Sed SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32), 1585198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1586198090Srdivacky CurDAG->getRegister(0, MVT::i32) }; 1587198090Srdivacky return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); 1588193323Sed } 1589193323Sed } 1590198090Srdivacky case ARMISD::DYN_ALLOC: 1591202375Srdivacky return SelectDYN_ALLOC(N); 1592198090Srdivacky case ISD::SRL: 1593202375Srdivacky if (SDNode *I = SelectV6T2BitfieldExtractOp(N, 1594198090Srdivacky Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX)) 1595198090Srdivacky return I; 1596193323Sed break; 1597198090Srdivacky case ISD::SRA: 1598202375Srdivacky if (SDNode *I = SelectV6T2BitfieldExtractOp(N, 1599198090Srdivacky Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)) 1600198090Srdivacky return I; 1601198090Srdivacky break; 1602193323Sed case ISD::MUL: 1603198090Srdivacky if (Subtarget->isThumb1Only()) 1604193323Sed break; 1605202375Srdivacky if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) { 1606193323Sed unsigned RHSV = C->getZExtValue(); 1607193323Sed if (!RHSV) break; 1608193323Sed if (isPowerOf2_32(RHSV-1)) { // 2^n+1? 1609198090Srdivacky unsigned ShImm = Log2_32(RHSV-1); 1610198090Srdivacky if (ShImm >= 32) 1611198090Srdivacky break; 1612202375Srdivacky SDValue V = N->getOperand(0); 1613198090Srdivacky ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); 1614198090Srdivacky SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); 1615198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1616198090Srdivacky if (Subtarget->isThumb()) { 1617198090Srdivacky SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1618198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops, 6); 1619198090Srdivacky } else { 1620198090Srdivacky SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1621198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 7); 1622198090Srdivacky } 1623193323Sed } 1624193323Sed if (isPowerOf2_32(RHSV+1)) { // 2^n-1? 1625198090Srdivacky unsigned ShImm = Log2_32(RHSV+1); 1626198090Srdivacky if (ShImm >= 32) 1627198090Srdivacky break; 1628202375Srdivacky SDValue V = N->getOperand(0); 1629198090Srdivacky ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); 1630198090Srdivacky SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); 1631198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1632198090Srdivacky if (Subtarget->isThumb()) { 1633198090Srdivacky SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0 }; 1634198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops, 5); 1635198090Srdivacky } else { 1636198090Srdivacky SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1637198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 7); 1638198090Srdivacky } 1639193323Sed } 1640193323Sed } 1641193323Sed break; 1642198396Srdivacky case ISD::AND: { 1643198396Srdivacky // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits 1644198396Srdivacky // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits 1645198396Srdivacky // are entirely contributed by c2 and lower 16-bits are entirely contributed 1646198396Srdivacky // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)). 1647198396Srdivacky // Select it to: "movt x, ((c1 & 0xffff) >> 16) 1648202375Srdivacky EVT VT = N->getValueType(0); 1649198396Srdivacky if (VT != MVT::i32) 1650198396Srdivacky break; 1651198396Srdivacky unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2()) 1652198396Srdivacky ? ARM::t2MOVTi16 1653198396Srdivacky : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0); 1654198396Srdivacky if (!Opc) 1655198396Srdivacky break; 1656202375Srdivacky SDValue N0 = N->getOperand(0), N1 = N->getOperand(1); 1657198396Srdivacky ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); 1658198396Srdivacky if (!N1C) 1659198396Srdivacky break; 1660198396Srdivacky if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) { 1661198396Srdivacky SDValue N2 = N0.getOperand(1); 1662198396Srdivacky ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2); 1663198396Srdivacky if (!N2C) 1664198396Srdivacky break; 1665198396Srdivacky unsigned N1CVal = N1C->getZExtValue(); 1666198396Srdivacky unsigned N2CVal = N2C->getZExtValue(); 1667198396Srdivacky if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) && 1668198396Srdivacky (N1CVal & 0xffffU) == 0xffffU && 1669198396Srdivacky (N2CVal & 0xffffU) == 0x0U) { 1670198396Srdivacky SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16, 1671198396Srdivacky MVT::i32); 1672198396Srdivacky SDValue Ops[] = { N0.getOperand(0), Imm16, 1673198396Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; 1674198396Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, Ops, 4); 1675198396Srdivacky } 1676198396Srdivacky } 1677198396Srdivacky break; 1678198396Srdivacky } 1679199481Srdivacky case ARMISD::VMOVRRD: 1680199481Srdivacky return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32, 1681202375Srdivacky N->getOperand(0), getAL(CurDAG), 1682198090Srdivacky CurDAG->getRegister(0, MVT::i32)); 1683193323Sed case ISD::UMUL_LOHI: { 1684198090Srdivacky if (Subtarget->isThumb1Only()) 1685198090Srdivacky break; 1686198090Srdivacky if (Subtarget->isThumb()) { 1687202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 1688193323Sed getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1689193323Sed CurDAG->getRegister(0, MVT::i32) }; 1690198090Srdivacky return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops,4); 1691198090Srdivacky } else { 1692202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 1693198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1694198090Srdivacky CurDAG->getRegister(0, MVT::i32) }; 1695198090Srdivacky return CurDAG->getMachineNode(ARM::UMULL, dl, MVT::i32, MVT::i32, Ops, 5); 1696198090Srdivacky } 1697193323Sed } 1698193323Sed case ISD::SMUL_LOHI: { 1699198090Srdivacky if (Subtarget->isThumb1Only()) 1700198090Srdivacky break; 1701198090Srdivacky if (Subtarget->isThumb()) { 1702202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 1703198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; 1704198090Srdivacky return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops,4); 1705198090Srdivacky } else { 1706202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 1707193323Sed getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1708193323Sed CurDAG->getRegister(0, MVT::i32) }; 1709198090Srdivacky return CurDAG->getMachineNode(ARM::SMULL, dl, MVT::i32, MVT::i32, Ops, 5); 1710198090Srdivacky } 1711193323Sed } 1712193323Sed case ISD::LOAD: { 1713195340Sed SDNode *ResNode = 0; 1714198090Srdivacky if (Subtarget->isThumb() && Subtarget->hasThumb2()) 1715202375Srdivacky ResNode = SelectT2IndexedLoad(N); 1716195340Sed else 1717202375Srdivacky ResNode = SelectARMIndexedLoad(N); 1718195340Sed if (ResNode) 1719195340Sed return ResNode; 1720193323Sed // Other cases are autogenerated. 1721193323Sed break; 1722193323Sed } 1723193323Sed case ARMISD::BRCOND: { 1724193323Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 1725193323Sed // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc) 1726193323Sed // Pattern complexity = 6 cost = 1 size = 0 1727193323Sed 1728193323Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 1729193323Sed // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc) 1730193323Sed // Pattern complexity = 6 cost = 1 size = 0 1731193323Sed 1732195340Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 1733195340Sed // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc) 1734195340Sed // Pattern complexity = 6 cost = 1 size = 0 1735195340Sed 1736198090Srdivacky unsigned Opc = Subtarget->isThumb() ? 1737195340Sed ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc; 1738202375Srdivacky SDValue Chain = N->getOperand(0); 1739202375Srdivacky SDValue N1 = N->getOperand(1); 1740202375Srdivacky SDValue N2 = N->getOperand(2); 1741202375Srdivacky SDValue N3 = N->getOperand(3); 1742202375Srdivacky SDValue InFlag = N->getOperand(4); 1743193323Sed assert(N1.getOpcode() == ISD::BasicBlock); 1744193323Sed assert(N2.getOpcode() == ISD::Constant); 1745193323Sed assert(N3.getOpcode() == ISD::Register); 1746193323Sed 1747193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 1748193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 1749193323Sed MVT::i32); 1750193323Sed SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag }; 1751198090Srdivacky SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other, 1752198090Srdivacky MVT::Flag, Ops, 5); 1753193323Sed Chain = SDValue(ResNode, 0); 1754202375Srdivacky if (N->getNumValues() == 2) { 1755193323Sed InFlag = SDValue(ResNode, 1); 1756202375Srdivacky ReplaceUses(SDValue(N, 1), InFlag); 1757193323Sed } 1758202375Srdivacky ReplaceUses(SDValue(N, 0), 1759199511Srdivacky SDValue(Chain.getNode(), Chain.getResNo())); 1760193323Sed return NULL; 1761193323Sed } 1762199989Srdivacky case ARMISD::CMOV: 1763202375Srdivacky return SelectCMOVOp(N); 1764193323Sed case ARMISD::CNEG: { 1765202375Srdivacky EVT VT = N->getValueType(0); 1766202375Srdivacky SDValue N0 = N->getOperand(0); 1767202375Srdivacky SDValue N1 = N->getOperand(1); 1768202375Srdivacky SDValue N2 = N->getOperand(2); 1769202375Srdivacky SDValue N3 = N->getOperand(3); 1770202375Srdivacky SDValue InFlag = N->getOperand(4); 1771193323Sed assert(N2.getOpcode() == ISD::Constant); 1772193323Sed assert(N3.getOpcode() == ISD::Register); 1773193323Sed 1774193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 1775193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 1776193323Sed MVT::i32); 1777193323Sed SDValue Ops[] = { N0, N1, Tmp2, N3, InFlag }; 1778193323Sed unsigned Opc = 0; 1779198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1780193323Sed default: assert(false && "Illegal conditional move type!"); 1781193323Sed break; 1782193323Sed case MVT::f32: 1783199481Srdivacky Opc = ARM::VNEGScc; 1784193323Sed break; 1785193323Sed case MVT::f64: 1786199481Srdivacky Opc = ARM::VNEGDcc; 1787193323Sed break; 1788193323Sed } 1789202375Srdivacky return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5); 1790193323Sed } 1791193323Sed 1792198090Srdivacky case ARMISD::VZIP: { 1793198090Srdivacky unsigned Opc = 0; 1794198090Srdivacky EVT VT = N->getValueType(0); 1795198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1796198090Srdivacky default: return NULL; 1797198090Srdivacky case MVT::v8i8: Opc = ARM::VZIPd8; break; 1798198090Srdivacky case MVT::v4i16: Opc = ARM::VZIPd16; break; 1799198090Srdivacky case MVT::v2f32: 1800198090Srdivacky case MVT::v2i32: Opc = ARM::VZIPd32; break; 1801198090Srdivacky case MVT::v16i8: Opc = ARM::VZIPq8; break; 1802198090Srdivacky case MVT::v8i16: Opc = ARM::VZIPq16; break; 1803198090Srdivacky case MVT::v4f32: 1804198090Srdivacky case MVT::v4i32: Opc = ARM::VZIPq32; break; 1805193323Sed } 1806199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1807199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1808199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 1809199989Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); 1810198090Srdivacky } 1811198090Srdivacky case ARMISD::VUZP: { 1812198090Srdivacky unsigned Opc = 0; 1813198090Srdivacky EVT VT = N->getValueType(0); 1814198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1815198090Srdivacky default: return NULL; 1816198090Srdivacky case MVT::v8i8: Opc = ARM::VUZPd8; break; 1817198090Srdivacky case MVT::v4i16: Opc = ARM::VUZPd16; break; 1818198090Srdivacky case MVT::v2f32: 1819198090Srdivacky case MVT::v2i32: Opc = ARM::VUZPd32; break; 1820198090Srdivacky case MVT::v16i8: Opc = ARM::VUZPq8; break; 1821198090Srdivacky case MVT::v8i16: Opc = ARM::VUZPq16; break; 1822198090Srdivacky case MVT::v4f32: 1823198090Srdivacky case MVT::v4i32: Opc = ARM::VUZPq32; break; 1824193323Sed } 1825199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1826199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1827199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 1828199989Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); 1829198090Srdivacky } 1830198090Srdivacky case ARMISD::VTRN: { 1831198090Srdivacky unsigned Opc = 0; 1832198090Srdivacky EVT VT = N->getValueType(0); 1833198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1834198090Srdivacky default: return NULL; 1835198090Srdivacky case MVT::v8i8: Opc = ARM::VTRNd8; break; 1836198090Srdivacky case MVT::v4i16: Opc = ARM::VTRNd16; break; 1837198090Srdivacky case MVT::v2f32: 1838198090Srdivacky case MVT::v2i32: Opc = ARM::VTRNd32; break; 1839198090Srdivacky case MVT::v16i8: Opc = ARM::VTRNq8; break; 1840198090Srdivacky case MVT::v8i16: Opc = ARM::VTRNq16; break; 1841198090Srdivacky case MVT::v4f32: 1842198090Srdivacky case MVT::v4i32: Opc = ARM::VTRNq32; break; 1843193323Sed } 1844199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1845199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1846199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 1847199989Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); 1848193323Sed } 1849194710Sed 1850198090Srdivacky case ISD::INTRINSIC_VOID: 1851198090Srdivacky case ISD::INTRINSIC_W_CHAIN: { 1852198090Srdivacky unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue(); 1853198090Srdivacky switch (IntNo) { 1854198090Srdivacky default: 1855198090Srdivacky break; 1856194710Sed 1857198090Srdivacky case Intrinsic::arm_neon_vld2: { 1858198090Srdivacky unsigned DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16, 1859198090Srdivacky ARM::VLD2d32, ARM::VLD2d64 }; 1860198090Srdivacky unsigned QOpcodes[] = { ARM::VLD2q8, ARM::VLD2q16, ARM::VLD2q32 }; 1861202375Srdivacky return SelectVLD(N, 2, DOpcodes, QOpcodes, 0); 1862198090Srdivacky } 1863194710Sed 1864198090Srdivacky case Intrinsic::arm_neon_vld3: { 1865198090Srdivacky unsigned DOpcodes[] = { ARM::VLD3d8, ARM::VLD3d16, 1866198090Srdivacky ARM::VLD3d32, ARM::VLD3d64 }; 1867198090Srdivacky unsigned QOpcodes0[] = { ARM::VLD3q8a, ARM::VLD3q16a, ARM::VLD3q32a }; 1868198090Srdivacky unsigned QOpcodes1[] = { ARM::VLD3q8b, ARM::VLD3q16b, ARM::VLD3q32b }; 1869202375Srdivacky return SelectVLD(N, 3, DOpcodes, QOpcodes0, QOpcodes1); 1870198090Srdivacky } 1871198090Srdivacky 1872198090Srdivacky case Intrinsic::arm_neon_vld4: { 1873198090Srdivacky unsigned DOpcodes[] = { ARM::VLD4d8, ARM::VLD4d16, 1874198090Srdivacky ARM::VLD4d32, ARM::VLD4d64 }; 1875198090Srdivacky unsigned QOpcodes0[] = { ARM::VLD4q8a, ARM::VLD4q16a, ARM::VLD4q32a }; 1876198090Srdivacky unsigned QOpcodes1[] = { ARM::VLD4q8b, ARM::VLD4q16b, ARM::VLD4q32b }; 1877202375Srdivacky return SelectVLD(N, 4, DOpcodes, QOpcodes0, QOpcodes1); 1878198090Srdivacky } 1879198090Srdivacky 1880198090Srdivacky case Intrinsic::arm_neon_vld2lane: { 1881198090Srdivacky unsigned DOpcodes[] = { ARM::VLD2LNd8, ARM::VLD2LNd16, ARM::VLD2LNd32 }; 1882198090Srdivacky unsigned QOpcodes0[] = { ARM::VLD2LNq16a, ARM::VLD2LNq32a }; 1883198090Srdivacky unsigned QOpcodes1[] = { ARM::VLD2LNq16b, ARM::VLD2LNq32b }; 1884202375Srdivacky return SelectVLDSTLane(N, true, 2, DOpcodes, QOpcodes0, QOpcodes1); 1885198090Srdivacky } 1886198090Srdivacky 1887198090Srdivacky case Intrinsic::arm_neon_vld3lane: { 1888198090Srdivacky unsigned DOpcodes[] = { ARM::VLD3LNd8, ARM::VLD3LNd16, ARM::VLD3LNd32 }; 1889198090Srdivacky unsigned QOpcodes0[] = { ARM::VLD3LNq16a, ARM::VLD3LNq32a }; 1890198090Srdivacky unsigned QOpcodes1[] = { ARM::VLD3LNq16b, ARM::VLD3LNq32b }; 1891202375Srdivacky return SelectVLDSTLane(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1); 1892198090Srdivacky } 1893198090Srdivacky 1894198090Srdivacky case Intrinsic::arm_neon_vld4lane: { 1895198090Srdivacky unsigned DOpcodes[] = { ARM::VLD4LNd8, ARM::VLD4LNd16, ARM::VLD4LNd32 }; 1896198090Srdivacky unsigned QOpcodes0[] = { ARM::VLD4LNq16a, ARM::VLD4LNq32a }; 1897198090Srdivacky unsigned QOpcodes1[] = { ARM::VLD4LNq16b, ARM::VLD4LNq32b }; 1898202375Srdivacky return SelectVLDSTLane(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1); 1899198090Srdivacky } 1900198090Srdivacky 1901198090Srdivacky case Intrinsic::arm_neon_vst2: { 1902198113Srdivacky unsigned DOpcodes[] = { ARM::VST2d8, ARM::VST2d16, 1903198113Srdivacky ARM::VST2d32, ARM::VST2d64 }; 1904198113Srdivacky unsigned QOpcodes[] = { ARM::VST2q8, ARM::VST2q16, ARM::VST2q32 }; 1905202375Srdivacky return SelectVST(N, 2, DOpcodes, QOpcodes, 0); 1906198090Srdivacky } 1907194710Sed 1908198090Srdivacky case Intrinsic::arm_neon_vst3: { 1909198113Srdivacky unsigned DOpcodes[] = { ARM::VST3d8, ARM::VST3d16, 1910198113Srdivacky ARM::VST3d32, ARM::VST3d64 }; 1911198113Srdivacky unsigned QOpcodes0[] = { ARM::VST3q8a, ARM::VST3q16a, ARM::VST3q32a }; 1912198113Srdivacky unsigned QOpcodes1[] = { ARM::VST3q8b, ARM::VST3q16b, ARM::VST3q32b }; 1913202375Srdivacky return SelectVST(N, 3, DOpcodes, QOpcodes0, QOpcodes1); 1914194710Sed } 1915194710Sed 1916198090Srdivacky case Intrinsic::arm_neon_vst4: { 1917198113Srdivacky unsigned DOpcodes[] = { ARM::VST4d8, ARM::VST4d16, 1918198113Srdivacky ARM::VST4d32, ARM::VST4d64 }; 1919198113Srdivacky unsigned QOpcodes0[] = { ARM::VST4q8a, ARM::VST4q16a, ARM::VST4q32a }; 1920198113Srdivacky unsigned QOpcodes1[] = { ARM::VST4q8b, ARM::VST4q16b, ARM::VST4q32b }; 1921202375Srdivacky return SelectVST(N, 4, DOpcodes, QOpcodes0, QOpcodes1); 1922198090Srdivacky } 1923198090Srdivacky 1924198090Srdivacky case Intrinsic::arm_neon_vst2lane: { 1925198090Srdivacky unsigned DOpcodes[] = { ARM::VST2LNd8, ARM::VST2LNd16, ARM::VST2LNd32 }; 1926198090Srdivacky unsigned QOpcodes0[] = { ARM::VST2LNq16a, ARM::VST2LNq32a }; 1927198090Srdivacky unsigned QOpcodes1[] = { ARM::VST2LNq16b, ARM::VST2LNq32b }; 1928202375Srdivacky return SelectVLDSTLane(N, false, 2, DOpcodes, QOpcodes0, QOpcodes1); 1929198090Srdivacky } 1930198090Srdivacky 1931198090Srdivacky case Intrinsic::arm_neon_vst3lane: { 1932198090Srdivacky unsigned DOpcodes[] = { ARM::VST3LNd8, ARM::VST3LNd16, ARM::VST3LNd32 }; 1933198090Srdivacky unsigned QOpcodes0[] = { ARM::VST3LNq16a, ARM::VST3LNq32a }; 1934198090Srdivacky unsigned QOpcodes1[] = { ARM::VST3LNq16b, ARM::VST3LNq32b }; 1935202375Srdivacky return SelectVLDSTLane(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1); 1936198090Srdivacky } 1937198090Srdivacky 1938198090Srdivacky case Intrinsic::arm_neon_vst4lane: { 1939198090Srdivacky unsigned DOpcodes[] = { ARM::VST4LNd8, ARM::VST4LNd16, ARM::VST4LNd32 }; 1940198090Srdivacky unsigned QOpcodes0[] = { ARM::VST4LNq16a, ARM::VST4LNq32a }; 1941198090Srdivacky unsigned QOpcodes1[] = { ARM::VST4LNq16b, ARM::VST4LNq32b }; 1942202375Srdivacky return SelectVLDSTLane(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1); 1943198090Srdivacky } 1944198090Srdivacky } 1945194710Sed } 1946194710Sed } 1947194710Sed 1948202375Srdivacky return SelectCode(N); 1949193323Sed} 1950193323Sed 1951193323Sedbool ARMDAGToDAGISel:: 1952193323SedSelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, 1953193323Sed std::vector<SDValue> &OutOps) { 1954193323Sed assert(ConstraintCode == 'm' && "unexpected asm memory constraint"); 1955198090Srdivacky // Require the address to be in a register. That is safe for all ARM 1956198090Srdivacky // variants and it is hard to do anything much smarter without knowing 1957198090Srdivacky // how the operand is used. 1958198090Srdivacky OutOps.push_back(Op); 1959193323Sed return false; 1960193323Sed} 1961193323Sed 1962193323Sed/// createARMISelDag - This pass converts a legalized DAG into a 1963193323Sed/// ARM-specific DAG, ready for instruction scheduling. 1964193323Sed/// 1965198090SrdivackyFunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM, 1966198090Srdivacky CodeGenOpt::Level OptLevel) { 1967198090Srdivacky return new ARMDAGToDAGISel(TM, OptLevel); 1968193323Sed} 1969