ARMISelDAGToDAG.cpp revision 203954
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 61203954Srdivacky virtual void InstructionSelect(); 62203954Srdivacky 63198090Srdivacky /// getI32Imm - Return a target constant of type i32 with the specified 64198090Srdivacky /// value. 65194612Sed inline SDValue getI32Imm(unsigned Imm) { 66194612Sed return CurDAG->getTargetConstant(Imm, MVT::i32); 67194612Sed } 68194612Sed 69202375Srdivacky SDNode *Select(SDNode *N); 70203954Srdivacky 71202375Srdivacky bool SelectShifterOperandReg(SDNode *Op, SDValue N, SDValue &A, 72195340Sed SDValue &B, SDValue &C); 73202375Srdivacky bool SelectAddrMode2(SDNode *Op, SDValue N, SDValue &Base, 74193323Sed SDValue &Offset, SDValue &Opc); 75202375Srdivacky bool SelectAddrMode2Offset(SDNode *Op, SDValue N, 76193323Sed SDValue &Offset, SDValue &Opc); 77202375Srdivacky bool SelectAddrMode3(SDNode *Op, SDValue N, SDValue &Base, 78193323Sed SDValue &Offset, SDValue &Opc); 79202375Srdivacky bool SelectAddrMode3Offset(SDNode *Op, SDValue N, 80193323Sed SDValue &Offset, SDValue &Opc); 81202375Srdivacky bool SelectAddrMode4(SDNode *Op, SDValue N, SDValue &Addr, 82198090Srdivacky SDValue &Mode); 83202375Srdivacky bool SelectAddrMode5(SDNode *Op, SDValue N, SDValue &Base, 84193323Sed SDValue &Offset); 85202375Srdivacky bool SelectAddrMode6(SDNode *Op, SDValue N, SDValue &Addr, SDValue &Update, 86199481Srdivacky SDValue &Opc, SDValue &Align); 87193323Sed 88202375Srdivacky bool SelectAddrModePC(SDNode *Op, SDValue N, SDValue &Offset, 89195340Sed SDValue &Label); 90193323Sed 91202375Srdivacky bool SelectThumbAddrModeRR(SDNode *Op, SDValue N, SDValue &Base, 92193323Sed SDValue &Offset); 93202375Srdivacky bool SelectThumbAddrModeRI5(SDNode *Op, SDValue N, unsigned Scale, 94193323Sed SDValue &Base, SDValue &OffImm, 95193323Sed SDValue &Offset); 96202375Srdivacky bool SelectThumbAddrModeS1(SDNode *Op, SDValue N, SDValue &Base, 97193323Sed SDValue &OffImm, SDValue &Offset); 98202375Srdivacky bool SelectThumbAddrModeS2(SDNode *Op, SDValue N, SDValue &Base, 99193323Sed SDValue &OffImm, SDValue &Offset); 100202375Srdivacky bool SelectThumbAddrModeS4(SDNode *Op, SDValue N, SDValue &Base, 101193323Sed SDValue &OffImm, SDValue &Offset); 102202375Srdivacky bool SelectThumbAddrModeSP(SDNode *Op, SDValue N, SDValue &Base, 103193323Sed SDValue &OffImm); 104193323Sed 105202375Srdivacky bool SelectT2ShifterOperandReg(SDNode *Op, SDValue N, 106195098Sed SDValue &BaseReg, SDValue &Opc); 107202375Srdivacky bool SelectT2AddrModeImm12(SDNode *Op, SDValue N, SDValue &Base, 108195340Sed SDValue &OffImm); 109202375Srdivacky bool SelectT2AddrModeImm8(SDNode *Op, SDValue N, SDValue &Base, 110195340Sed SDValue &OffImm); 111202375Srdivacky bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N, 112195340Sed SDValue &OffImm); 113202375Srdivacky bool SelectT2AddrModeImm8s4(SDNode *Op, SDValue N, SDValue &Base, 114195340Sed SDValue &OffImm); 115202375Srdivacky bool SelectT2AddrModeSoReg(SDNode *Op, SDValue N, SDValue &Base, 116195340Sed SDValue &OffReg, SDValue &ShImm); 117195340Sed 118193323Sed // Include the pieces autogenerated from the target description. 119193323Sed#include "ARMGenDAGISel.inc" 120193323Sed 121193323Sedprivate: 122195340Sed /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for 123195340Sed /// ARM. 124202375Srdivacky SDNode *SelectARMIndexedLoad(SDNode *N); 125202375Srdivacky SDNode *SelectT2IndexedLoad(SDNode *N); 126195340Sed 127198090Srdivacky /// SelectDYN_ALLOC - Select dynamic alloc for Thumb. 128202375Srdivacky SDNode *SelectDYN_ALLOC(SDNode *N); 129195340Sed 130198090Srdivacky /// SelectVLD - Select NEON load intrinsics. NumVecs should 131198090Srdivacky /// be 2, 3 or 4. The opcode arrays specify the instructions used for 132198090Srdivacky /// loads of D registers and even subregs and odd subregs of Q registers. 133198090Srdivacky /// For NumVecs == 2, QOpcodes1 is not used. 134202375Srdivacky SDNode *SelectVLD(SDNode *N, unsigned NumVecs, unsigned *DOpcodes, 135198090Srdivacky unsigned *QOpcodes0, unsigned *QOpcodes1); 136198090Srdivacky 137198113Srdivacky /// SelectVST - Select NEON store intrinsics. NumVecs should 138198113Srdivacky /// be 2, 3 or 4. The opcode arrays specify the instructions used for 139198113Srdivacky /// stores of D registers and even subregs and odd subregs of Q registers. 140198113Srdivacky /// For NumVecs == 2, QOpcodes1 is not used. 141202375Srdivacky SDNode *SelectVST(SDNode *N, unsigned NumVecs, unsigned *DOpcodes, 142198113Srdivacky unsigned *QOpcodes0, unsigned *QOpcodes1); 143198113Srdivacky 144198090Srdivacky /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should 145198090Srdivacky /// be 2, 3 or 4. The opcode arrays specify the instructions used for 146198090Srdivacky /// load/store of D registers and even subregs and odd subregs of Q registers. 147202375Srdivacky SDNode *SelectVLDSTLane(SDNode *N, bool IsLoad, unsigned NumVecs, 148198090Srdivacky unsigned *DOpcodes, unsigned *QOpcodes0, 149198090Srdivacky unsigned *QOpcodes1); 150198090Srdivacky 151198090Srdivacky /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM. 152202375Srdivacky SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, unsigned Opc); 153198090Srdivacky 154199989Srdivacky /// SelectCMOVOp - Select CMOV instructions for ARM. 155202375Srdivacky SDNode *SelectCMOVOp(SDNode *N); 156202375Srdivacky SDNode *SelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 157199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 158199989Srdivacky SDValue InFlag); 159202375Srdivacky SDNode *SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 160199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 161199989Srdivacky SDValue InFlag); 162202375Srdivacky SDNode *SelectT2CMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 163199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 164199989Srdivacky SDValue InFlag); 165202375Srdivacky SDNode *SelectARMCMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 166199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 167199989Srdivacky SDValue InFlag); 168199989Srdivacky 169195340Sed /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for 170195340Sed /// inline asm expressions. 171195340Sed virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, 172195340Sed char ConstraintCode, 173195340Sed std::vector<SDValue> &OutOps); 174198090Srdivacky 175198090Srdivacky /// PairDRegs - Insert a pair of double registers into an implicit def to 176198090Srdivacky /// form a quad register. 177198090Srdivacky SDNode *PairDRegs(EVT VT, SDValue V0, SDValue V1); 178193323Sed}; 179193323Sed} 180193323Sed 181198090Srdivacky/// isInt32Immediate - This method tests to see if the node is a 32-bit constant 182198090Srdivacky/// operand. If so Imm will receive the 32-bit value. 183198090Srdivackystatic bool isInt32Immediate(SDNode *N, unsigned &Imm) { 184198090Srdivacky if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) { 185198090Srdivacky Imm = cast<ConstantSDNode>(N)->getZExtValue(); 186198090Srdivacky return true; 187198090Srdivacky } 188198090Srdivacky return false; 189198090Srdivacky} 190198090Srdivacky 191198090Srdivacky// isInt32Immediate - This method tests to see if a constant operand. 192198090Srdivacky// If so Imm will receive the 32 bit value. 193198090Srdivackystatic bool isInt32Immediate(SDValue N, unsigned &Imm) { 194198090Srdivacky return isInt32Immediate(N.getNode(), Imm); 195198090Srdivacky} 196198090Srdivacky 197198090Srdivacky// isOpcWithIntImmediate - This method tests to see if the node is a specific 198198090Srdivacky// opcode and that it has a immediate integer right operand. 199198090Srdivacky// If so Imm will receive the 32 bit value. 200198090Srdivackystatic bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) { 201198090Srdivacky return N->getOpcode() == Opc && 202198090Srdivacky isInt32Immediate(N->getOperand(1).getNode(), Imm); 203198090Srdivacky} 204198090Srdivacky 205198090Srdivacky 206193323Sedvoid ARMDAGToDAGISel::InstructionSelect() { 207193323Sed SelectRoot(*CurDAG); 208193323Sed CurDAG->RemoveDeadNodes(); 209193323Sed} 210193323Sed 211202375Srdivackybool ARMDAGToDAGISel::SelectShifterOperandReg(SDNode *Op, 212195340Sed SDValue N, 213195340Sed SDValue &BaseReg, 214195340Sed SDValue &ShReg, 215195340Sed SDValue &Opc) { 216195340Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 217195340Sed 218195340Sed // Don't match base register only case. That is matched to a separate 219195340Sed // lower complexity pattern with explicit register operand. 220195340Sed if (ShOpcVal == ARM_AM::no_shift) return false; 221198090Srdivacky 222195340Sed BaseReg = N.getOperand(0); 223195340Sed unsigned ShImmVal = 0; 224195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 225195340Sed ShReg = CurDAG->getRegister(0, MVT::i32); 226195340Sed ShImmVal = RHS->getZExtValue() & 31; 227195340Sed } else { 228195340Sed ShReg = N.getOperand(1); 229195340Sed } 230195340Sed Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), 231195340Sed MVT::i32); 232195340Sed return true; 233195340Sed} 234195340Sed 235202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode2(SDNode *Op, SDValue N, 236193323Sed SDValue &Base, SDValue &Offset, 237193323Sed SDValue &Opc) { 238193323Sed if (N.getOpcode() == ISD::MUL) { 239193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 240193323Sed // X * [3,5,9] -> X + X * [2,4,8] etc. 241193323Sed int RHSC = (int)RHS->getZExtValue(); 242193323Sed if (RHSC & 1) { 243193323Sed RHSC = RHSC & ~1; 244193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 245193323Sed if (RHSC < 0) { 246193323Sed AddSub = ARM_AM::sub; 247193323Sed RHSC = - RHSC; 248193323Sed } 249193323Sed if (isPowerOf2_32(RHSC)) { 250193323Sed unsigned ShAmt = Log2_32(RHSC); 251193323Sed Base = Offset = N.getOperand(0); 252193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, 253193323Sed ARM_AM::lsl), 254193323Sed MVT::i32); 255193323Sed return true; 256193323Sed } 257193323Sed } 258193323Sed } 259193323Sed } 260193323Sed 261193323Sed if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) { 262193323Sed Base = N; 263193323Sed if (N.getOpcode() == ISD::FrameIndex) { 264193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 265193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 266199989Srdivacky } else if (N.getOpcode() == ARMISD::Wrapper && 267199989Srdivacky !(Subtarget->useMovt() && 268199989Srdivacky N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { 269193323Sed Base = N.getOperand(0); 270193323Sed } 271193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 272193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, 273193323Sed ARM_AM::no_shift), 274193323Sed MVT::i32); 275193323Sed return true; 276193323Sed } 277198090Srdivacky 278193323Sed // Match simple R +/- imm12 operands. 279193323Sed if (N.getOpcode() == ISD::ADD) 280193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 281193323Sed int RHSC = (int)RHS->getZExtValue(); 282193323Sed if ((RHSC >= 0 && RHSC < 0x1000) || 283193323Sed (RHSC < 0 && RHSC > -0x1000)) { // 12 bits. 284193323Sed Base = N.getOperand(0); 285193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 286193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 287193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 288193323Sed } 289193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 290193323Sed 291193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 292193323Sed if (RHSC < 0) { 293193323Sed AddSub = ARM_AM::sub; 294193323Sed RHSC = - RHSC; 295193323Sed } 296193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC, 297193323Sed ARM_AM::no_shift), 298193323Sed MVT::i32); 299193323Sed return true; 300193323Sed } 301193323Sed } 302198090Srdivacky 303198892Srdivacky // Otherwise this is R +/- [possibly shifted] R. 304193323Sed ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::ADD ? ARM_AM::add:ARM_AM::sub; 305193323Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1)); 306193323Sed unsigned ShAmt = 0; 307198090Srdivacky 308193323Sed Base = N.getOperand(0); 309193323Sed Offset = N.getOperand(1); 310198090Srdivacky 311193323Sed if (ShOpcVal != ARM_AM::no_shift) { 312193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 313193323Sed // it. 314193323Sed if (ConstantSDNode *Sh = 315193323Sed dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) { 316193323Sed ShAmt = Sh->getZExtValue(); 317193323Sed Offset = N.getOperand(1).getOperand(0); 318193323Sed } else { 319193323Sed ShOpcVal = ARM_AM::no_shift; 320193323Sed } 321193323Sed } 322198090Srdivacky 323193323Sed // Try matching (R shl C) + (R). 324193323Sed if (N.getOpcode() == ISD::ADD && ShOpcVal == ARM_AM::no_shift) { 325193323Sed ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0)); 326193323Sed if (ShOpcVal != ARM_AM::no_shift) { 327193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't 328193323Sed // fold it. 329193323Sed if (ConstantSDNode *Sh = 330193323Sed dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) { 331193323Sed ShAmt = Sh->getZExtValue(); 332193323Sed Offset = N.getOperand(0).getOperand(0); 333193323Sed Base = N.getOperand(1); 334193323Sed } else { 335193323Sed ShOpcVal = ARM_AM::no_shift; 336193323Sed } 337193323Sed } 338193323Sed } 339198090Srdivacky 340193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 341193323Sed MVT::i32); 342193323Sed return true; 343193323Sed} 344193323Sed 345202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode2Offset(SDNode *Op, SDValue N, 346193323Sed SDValue &Offset, SDValue &Opc) { 347202375Srdivacky unsigned Opcode = Op->getOpcode(); 348193323Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 349193323Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 350193323Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 351193323Sed ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 352193323Sed ? ARM_AM::add : ARM_AM::sub; 353193323Sed if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 354193323Sed int Val = (int)C->getZExtValue(); 355193323Sed if (Val >= 0 && Val < 0x1000) { // 12 bits. 356193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 357193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val, 358193323Sed ARM_AM::no_shift), 359193323Sed MVT::i32); 360193323Sed return true; 361193323Sed } 362193323Sed } 363193323Sed 364193323Sed Offset = N; 365193323Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 366193323Sed unsigned ShAmt = 0; 367193323Sed if (ShOpcVal != ARM_AM::no_shift) { 368193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 369193323Sed // it. 370193323Sed if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 371193323Sed ShAmt = Sh->getZExtValue(); 372193323Sed Offset = N.getOperand(0); 373193323Sed } else { 374193323Sed ShOpcVal = ARM_AM::no_shift; 375193323Sed } 376193323Sed } 377193323Sed 378193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 379193323Sed MVT::i32); 380193323Sed return true; 381193323Sed} 382193323Sed 383193323Sed 384202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode3(SDNode *Op, SDValue N, 385193323Sed SDValue &Base, SDValue &Offset, 386193323Sed SDValue &Opc) { 387193323Sed if (N.getOpcode() == ISD::SUB) { 388193323Sed // X - C is canonicalize to X + -C, no need to handle it here. 389193323Sed Base = N.getOperand(0); 390193323Sed Offset = N.getOperand(1); 391193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32); 392193323Sed return true; 393193323Sed } 394198090Srdivacky 395193323Sed if (N.getOpcode() != ISD::ADD) { 396193323Sed Base = N; 397193323Sed if (N.getOpcode() == ISD::FrameIndex) { 398193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 399193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 400193323Sed } 401193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 402193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32); 403193323Sed return true; 404193323Sed } 405198090Srdivacky 406193323Sed // If the RHS is +/- imm8, fold into addr mode. 407193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 408193323Sed int RHSC = (int)RHS->getZExtValue(); 409193323Sed if ((RHSC >= 0 && RHSC < 256) || 410193323Sed (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed. 411193323Sed Base = N.getOperand(0); 412193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 413193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 414193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 415193323Sed } 416193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 417193323Sed 418193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 419193323Sed if (RHSC < 0) { 420193323Sed AddSub = ARM_AM::sub; 421193323Sed RHSC = - RHSC; 422193323Sed } 423193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32); 424193323Sed return true; 425193323Sed } 426193323Sed } 427198090Srdivacky 428193323Sed Base = N.getOperand(0); 429193323Sed Offset = N.getOperand(1); 430193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32); 431193323Sed return true; 432193323Sed} 433193323Sed 434202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N, 435193323Sed SDValue &Offset, SDValue &Opc) { 436202375Srdivacky unsigned Opcode = Op->getOpcode(); 437193323Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 438193323Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 439193323Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 440193323Sed ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 441193323Sed ? ARM_AM::add : ARM_AM::sub; 442193323Sed if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 443193323Sed int Val = (int)C->getZExtValue(); 444193323Sed if (Val >= 0 && Val < 256) { 445193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 446193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32); 447193323Sed return true; 448193323Sed } 449193323Sed } 450193323Sed 451193323Sed Offset = N; 452193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32); 453193323Sed return true; 454193323Sed} 455193323Sed 456202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode4(SDNode *Op, SDValue N, 457198090Srdivacky SDValue &Addr, SDValue &Mode) { 458198090Srdivacky Addr = N; 459198090Srdivacky Mode = CurDAG->getTargetConstant(0, MVT::i32); 460198090Srdivacky return true; 461198090Srdivacky} 462193323Sed 463202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode5(SDNode *Op, SDValue N, 464193323Sed SDValue &Base, SDValue &Offset) { 465193323Sed if (N.getOpcode() != ISD::ADD) { 466193323Sed Base = N; 467193323Sed if (N.getOpcode() == ISD::FrameIndex) { 468193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 469193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 470199989Srdivacky } else if (N.getOpcode() == ARMISD::Wrapper && 471199989Srdivacky !(Subtarget->useMovt() && 472199989Srdivacky N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { 473193323Sed Base = N.getOperand(0); 474193323Sed } 475193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 476193323Sed MVT::i32); 477193323Sed return true; 478193323Sed } 479198090Srdivacky 480193323Sed // If the RHS is +/- imm8, fold into addr mode. 481193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 482193323Sed int RHSC = (int)RHS->getZExtValue(); 483193323Sed if ((RHSC & 3) == 0) { // The constant is implicitly multiplied by 4. 484193323Sed RHSC >>= 2; 485193323Sed if ((RHSC >= 0 && RHSC < 256) || 486193323Sed (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed. 487193323Sed Base = N.getOperand(0); 488193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 489193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 490193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 491193323Sed } 492193323Sed 493193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 494193323Sed if (RHSC < 0) { 495193323Sed AddSub = ARM_AM::sub; 496193323Sed RHSC = - RHSC; 497193323Sed } 498193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC), 499193323Sed MVT::i32); 500193323Sed return true; 501193323Sed } 502193323Sed } 503193323Sed } 504198090Srdivacky 505193323Sed Base = N; 506193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 507193323Sed MVT::i32); 508193323Sed return true; 509193323Sed} 510193323Sed 511202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Op, SDValue N, 512195340Sed SDValue &Addr, SDValue &Update, 513199481Srdivacky SDValue &Opc, SDValue &Align) { 514195340Sed Addr = N; 515198090Srdivacky // Default to no writeback. 516195340Sed Update = CurDAG->getRegister(0, MVT::i32); 517195340Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(false), MVT::i32); 518199481Srdivacky // Default to no alignment. 519199481Srdivacky Align = CurDAG->getTargetConstant(0, MVT::i32); 520195340Sed return true; 521195340Sed} 522195340Sed 523202375Srdivackybool ARMDAGToDAGISel::SelectAddrModePC(SDNode *Op, SDValue N, 524198090Srdivacky SDValue &Offset, SDValue &Label) { 525193323Sed if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) { 526193323Sed Offset = N.getOperand(0); 527193323Sed SDValue N1 = N.getOperand(1); 528193323Sed Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(), 529193323Sed MVT::i32); 530193323Sed return true; 531193323Sed } 532193323Sed return false; 533193323Sed} 534193323Sed 535202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDNode *Op, SDValue N, 536193323Sed SDValue &Base, SDValue &Offset){ 537193323Sed // FIXME dl should come from the parent load or store, not the address 538202375Srdivacky DebugLoc dl = Op->getDebugLoc(); 539193323Sed if (N.getOpcode() != ISD::ADD) { 540198090Srdivacky ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N); 541198090Srdivacky if (!NC || NC->getZExtValue() != 0) 542198090Srdivacky return false; 543198090Srdivacky 544198090Srdivacky Base = Offset = N; 545193323Sed return true; 546193323Sed } 547193323Sed 548193323Sed Base = N.getOperand(0); 549193323Sed Offset = N.getOperand(1); 550193323Sed return true; 551193323Sed} 552193323Sed 553193323Sedbool 554202375SrdivackyARMDAGToDAGISel::SelectThumbAddrModeRI5(SDNode *Op, SDValue N, 555193323Sed unsigned Scale, SDValue &Base, 556193323Sed SDValue &OffImm, SDValue &Offset) { 557193323Sed if (Scale == 4) { 558193323Sed SDValue TmpBase, TmpOffImm; 559193323Sed if (SelectThumbAddrModeSP(Op, N, TmpBase, TmpOffImm)) 560193323Sed return false; // We want to select tLDRspi / tSTRspi instead. 561193323Sed if (N.getOpcode() == ARMISD::Wrapper && 562193323Sed N.getOperand(0).getOpcode() == ISD::TargetConstantPool) 563193323Sed return false; // We want to select tLDRpci instead. 564193323Sed } 565193323Sed 566193323Sed if (N.getOpcode() != ISD::ADD) { 567199989Srdivacky if (N.getOpcode() == ARMISD::Wrapper && 568199989Srdivacky !(Subtarget->useMovt() && 569199989Srdivacky N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { 570199989Srdivacky Base = N.getOperand(0); 571199989Srdivacky } else 572199989Srdivacky Base = N; 573199989Srdivacky 574193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 575193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 576193323Sed return true; 577193323Sed } 578193323Sed 579193323Sed // Thumb does not have [sp, r] address mode. 580193323Sed RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 581193323Sed RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1)); 582193323Sed if ((LHSR && LHSR->getReg() == ARM::SP) || 583193323Sed (RHSR && RHSR->getReg() == ARM::SP)) { 584193323Sed Base = N; 585193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 586193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 587193323Sed return true; 588193323Sed } 589193323Sed 590193323Sed // If the RHS is + imm5 * scale, fold into addr mode. 591193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 592193323Sed int RHSC = (int)RHS->getZExtValue(); 593193323Sed if ((RHSC & (Scale-1)) == 0) { // The constant is implicitly multiplied. 594193323Sed RHSC /= Scale; 595193323Sed if (RHSC >= 0 && RHSC < 32) { 596193323Sed Base = N.getOperand(0); 597193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 598193323Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 599193323Sed return true; 600193323Sed } 601193323Sed } 602193323Sed } 603193323Sed 604193323Sed Base = N.getOperand(0); 605193323Sed Offset = N.getOperand(1); 606193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 607193323Sed return true; 608193323Sed} 609193323Sed 610202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeS1(SDNode *Op, SDValue N, 611193323Sed SDValue &Base, SDValue &OffImm, 612193323Sed SDValue &Offset) { 613193323Sed return SelectThumbAddrModeRI5(Op, N, 1, Base, OffImm, Offset); 614193323Sed} 615193323Sed 616202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeS2(SDNode *Op, SDValue N, 617193323Sed SDValue &Base, SDValue &OffImm, 618193323Sed SDValue &Offset) { 619193323Sed return SelectThumbAddrModeRI5(Op, N, 2, Base, OffImm, Offset); 620193323Sed} 621193323Sed 622202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeS4(SDNode *Op, SDValue N, 623193323Sed SDValue &Base, SDValue &OffImm, 624193323Sed SDValue &Offset) { 625193323Sed return SelectThumbAddrModeRI5(Op, N, 4, Base, OffImm, Offset); 626193323Sed} 627193323Sed 628202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDNode *Op, SDValue N, 629193323Sed SDValue &Base, SDValue &OffImm) { 630193323Sed if (N.getOpcode() == ISD::FrameIndex) { 631193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 632193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 633193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 634193323Sed return true; 635193323Sed } 636193323Sed 637193323Sed if (N.getOpcode() != ISD::ADD) 638193323Sed return false; 639193323Sed 640193323Sed RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 641193323Sed if (N.getOperand(0).getOpcode() == ISD::FrameIndex || 642193323Sed (LHSR && LHSR->getReg() == ARM::SP)) { 643193323Sed // If the RHS is + imm8 * scale, fold into addr mode. 644193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 645193323Sed int RHSC = (int)RHS->getZExtValue(); 646193323Sed if ((RHSC & 3) == 0) { // The constant is implicitly multiplied. 647193323Sed RHSC >>= 2; 648193323Sed if (RHSC >= 0 && RHSC < 256) { 649193323Sed Base = N.getOperand(0); 650193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 651193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 652193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 653193323Sed } 654193323Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 655193323Sed return true; 656193323Sed } 657193323Sed } 658193323Sed } 659193323Sed } 660198090Srdivacky 661193323Sed return false; 662193323Sed} 663193323Sed 664202375Srdivackybool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDNode *Op, SDValue N, 665195098Sed SDValue &BaseReg, 666195098Sed SDValue &Opc) { 667195098Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 668195098Sed 669195098Sed // Don't match base register only case. That is matched to a separate 670195098Sed // lower complexity pattern with explicit register operand. 671195098Sed if (ShOpcVal == ARM_AM::no_shift) return false; 672195098Sed 673195098Sed BaseReg = N.getOperand(0); 674195098Sed unsigned ShImmVal = 0; 675195098Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 676195098Sed ShImmVal = RHS->getZExtValue() & 31; 677195098Sed Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal)); 678195098Sed return true; 679195098Sed } 680195098Sed 681195098Sed return false; 682195098Sed} 683195098Sed 684202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDNode *Op, SDValue N, 685195340Sed SDValue &Base, SDValue &OffImm) { 686195340Sed // Match simple R + imm12 operands. 687195340Sed 688198090Srdivacky // Base only. 689198090Srdivacky if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) { 690198090Srdivacky if (N.getOpcode() == ISD::FrameIndex) { 691198090Srdivacky // Match frame index... 692198090Srdivacky int FI = cast<FrameIndexSDNode>(N)->getIndex(); 693198090Srdivacky Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 694198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 695198090Srdivacky return true; 696199989Srdivacky } else if (N.getOpcode() == ARMISD::Wrapper && 697199989Srdivacky !(Subtarget->useMovt() && 698199989Srdivacky N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { 699198090Srdivacky Base = N.getOperand(0); 700198090Srdivacky if (Base.getOpcode() == ISD::TargetConstantPool) 701198090Srdivacky return false; // We want to select t2LDRpci instead. 702198090Srdivacky } else 703198090Srdivacky Base = N; 704198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 705198090Srdivacky return true; 706198090Srdivacky } 707198090Srdivacky 708195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 709198090Srdivacky if (SelectT2AddrModeImm8(Op, N, Base, OffImm)) 710198090Srdivacky // Let t2LDRi8 handle (R - imm8). 711198090Srdivacky return false; 712198090Srdivacky 713195340Sed int RHSC = (int)RHS->getZExtValue(); 714198090Srdivacky if (N.getOpcode() == ISD::SUB) 715198090Srdivacky RHSC = -RHSC; 716198090Srdivacky 717198090Srdivacky if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned) 718195340Sed Base = N.getOperand(0); 719198090Srdivacky if (Base.getOpcode() == ISD::FrameIndex) { 720198090Srdivacky int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 721198090Srdivacky Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 722198090Srdivacky } 723195340Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 724195340Sed return true; 725195340Sed } 726195340Sed } 727195340Sed 728198090Srdivacky // Base only. 729198090Srdivacky Base = N; 730198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 731198090Srdivacky return true; 732195340Sed} 733195340Sed 734202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDNode *Op, SDValue N, 735195340Sed SDValue &Base, SDValue &OffImm) { 736198090Srdivacky // Match simple R - imm8 operands. 737198090Srdivacky if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::SUB) { 738195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 739198090Srdivacky int RHSC = (int)RHS->getSExtValue(); 740198090Srdivacky if (N.getOpcode() == ISD::SUB) 741198090Srdivacky RHSC = -RHSC; 742198090Srdivacky 743198090Srdivacky if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative) 744198090Srdivacky Base = N.getOperand(0); 745198090Srdivacky if (Base.getOpcode() == ISD::FrameIndex) { 746198090Srdivacky int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 747198090Srdivacky Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 748198090Srdivacky } 749195340Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 750195340Sed return true; 751195340Sed } 752195340Sed } 753195340Sed } 754195340Sed 755195340Sed return false; 756195340Sed} 757195340Sed 758202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N, 759195340Sed SDValue &OffImm){ 760202375Srdivacky unsigned Opcode = Op->getOpcode(); 761195340Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 762195340Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 763195340Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 764195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N)) { 765195340Sed int RHSC = (int)RHS->getZExtValue(); 766195340Sed if (RHSC >= 0 && RHSC < 0x100) { // 8 bits. 767198090Srdivacky OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC)) 768195340Sed ? CurDAG->getTargetConstant(RHSC, MVT::i32) 769195340Sed : CurDAG->getTargetConstant(-RHSC, MVT::i32); 770195340Sed return true; 771195340Sed } 772195340Sed } 773195340Sed 774195340Sed return false; 775195340Sed} 776195340Sed 777202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm8s4(SDNode *Op, SDValue N, 778195340Sed SDValue &Base, SDValue &OffImm) { 779195340Sed if (N.getOpcode() == ISD::ADD) { 780195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 781195340Sed int RHSC = (int)RHS->getZExtValue(); 782198090Srdivacky if (((RHSC & 0x3) == 0) && 783198090Srdivacky ((RHSC >= 0 && RHSC < 0x400) || (RHSC < 0 && RHSC > -0x400))) { // 8 bits. 784195340Sed Base = N.getOperand(0); 785195340Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 786195340Sed return true; 787195340Sed } 788195340Sed } 789195340Sed } else if (N.getOpcode() == ISD::SUB) { 790195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 791195340Sed int RHSC = (int)RHS->getZExtValue(); 792195340Sed if (((RHSC & 0x3) == 0) && (RHSC >= 0 && RHSC < 0x400)) { // 8 bits. 793195340Sed Base = N.getOperand(0); 794195340Sed OffImm = CurDAG->getTargetConstant(-RHSC, MVT::i32); 795195340Sed return true; 796195340Sed } 797195340Sed } 798195340Sed } 799195340Sed 800195340Sed return false; 801195340Sed} 802195340Sed 803202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDNode *Op, SDValue N, 804195340Sed SDValue &Base, 805195340Sed SDValue &OffReg, SDValue &ShImm) { 806198090Srdivacky // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12. 807198090Srdivacky if (N.getOpcode() != ISD::ADD) 808198090Srdivacky return false; 809198090Srdivacky 810198090Srdivacky // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8. 811198090Srdivacky if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 812198090Srdivacky int RHSC = (int)RHS->getZExtValue(); 813198090Srdivacky if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned) 814198090Srdivacky return false; 815198090Srdivacky else if (RHSC < 0 && RHSC >= -255) // 8 bits 816198090Srdivacky return false; 817195340Sed } 818195340Sed 819195340Sed // Look for (R + R) or (R + (R << [1,2,3])). 820195340Sed unsigned ShAmt = 0; 821195340Sed Base = N.getOperand(0); 822195340Sed OffReg = N.getOperand(1); 823195340Sed 824195340Sed // Swap if it is ((R << c) + R). 825195340Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg); 826195340Sed if (ShOpcVal != ARM_AM::lsl) { 827195340Sed ShOpcVal = ARM_AM::getShiftOpcForNode(Base); 828195340Sed if (ShOpcVal == ARM_AM::lsl) 829195340Sed std::swap(Base, OffReg); 830198090Srdivacky } 831198090Srdivacky 832195340Sed if (ShOpcVal == ARM_AM::lsl) { 833195340Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 834195340Sed // it. 835195340Sed if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) { 836195340Sed ShAmt = Sh->getZExtValue(); 837195340Sed if (ShAmt >= 4) { 838195340Sed ShAmt = 0; 839195340Sed ShOpcVal = ARM_AM::no_shift; 840195340Sed } else 841195340Sed OffReg = OffReg.getOperand(0); 842195340Sed } else { 843195340Sed ShOpcVal = ARM_AM::no_shift; 844195340Sed } 845198090Srdivacky } 846198090Srdivacky 847195340Sed ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32); 848195340Sed 849195340Sed return true; 850195340Sed} 851195340Sed 852195340Sed//===--------------------------------------------------------------------===// 853195340Sed 854193323Sed/// getAL - Returns a ARMCC::AL immediate node. 855193323Sedstatic inline SDValue getAL(SelectionDAG *CurDAG) { 856193323Sed return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32); 857193323Sed} 858193323Sed 859202375SrdivackySDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) { 860202375Srdivacky LoadSDNode *LD = cast<LoadSDNode>(N); 861195340Sed ISD::MemIndexedMode AM = LD->getAddressingMode(); 862195340Sed if (AM == ISD::UNINDEXED) 863195340Sed return NULL; 864193323Sed 865198090Srdivacky EVT LoadedVT = LD->getMemoryVT(); 866195340Sed SDValue Offset, AMOpc; 867195340Sed bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 868195340Sed unsigned Opcode = 0; 869195340Sed bool Match = false; 870195340Sed if (LoadedVT == MVT::i32 && 871202375Srdivacky SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) { 872195340Sed Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST; 873195340Sed Match = true; 874195340Sed } else if (LoadedVT == MVT::i16 && 875202375Srdivacky SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) { 876195340Sed Match = true; 877195340Sed Opcode = (LD->getExtensionType() == ISD::SEXTLOAD) 878195340Sed ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST) 879195340Sed : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST); 880195340Sed } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) { 881195340Sed if (LD->getExtensionType() == ISD::SEXTLOAD) { 882202375Srdivacky if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) { 883195340Sed Match = true; 884195340Sed Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST; 885195340Sed } 886195340Sed } else { 887202375Srdivacky if (SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) { 888195340Sed Match = true; 889195340Sed Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST; 890195340Sed } 891195340Sed } 892195340Sed } 893195340Sed 894195340Sed if (Match) { 895195340Sed SDValue Chain = LD->getChain(); 896195340Sed SDValue Base = LD->getBasePtr(); 897195340Sed SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG), 898195340Sed CurDAG->getRegister(0, MVT::i32), Chain }; 899202375Srdivacky return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, MVT::i32, 900198090Srdivacky MVT::Other, Ops, 6); 901195340Sed } 902195340Sed 903195340Sed return NULL; 904195340Sed} 905195340Sed 906202375SrdivackySDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) { 907202375Srdivacky LoadSDNode *LD = cast<LoadSDNode>(N); 908195340Sed ISD::MemIndexedMode AM = LD->getAddressingMode(); 909195340Sed if (AM == ISD::UNINDEXED) 910195340Sed return NULL; 911195340Sed 912198090Srdivacky EVT LoadedVT = LD->getMemoryVT(); 913195340Sed bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD; 914195340Sed SDValue Offset; 915195340Sed bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 916195340Sed unsigned Opcode = 0; 917195340Sed bool Match = false; 918202375Srdivacky if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) { 919198090Srdivacky switch (LoadedVT.getSimpleVT().SimpleTy) { 920195340Sed case MVT::i32: 921195340Sed Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST; 922195340Sed break; 923195340Sed case MVT::i16: 924195340Sed if (isSExtLd) 925195340Sed Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST; 926195340Sed else 927195340Sed Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST; 928195340Sed break; 929195340Sed case MVT::i8: 930195340Sed case MVT::i1: 931195340Sed if (isSExtLd) 932195340Sed Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST; 933195340Sed else 934195340Sed Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST; 935195340Sed break; 936195340Sed default: 937195340Sed return NULL; 938195340Sed } 939195340Sed Match = true; 940195340Sed } 941195340Sed 942195340Sed if (Match) { 943195340Sed SDValue Chain = LD->getChain(); 944195340Sed SDValue Base = LD->getBasePtr(); 945195340Sed SDValue Ops[]= { Base, Offset, getAL(CurDAG), 946195340Sed CurDAG->getRegister(0, MVT::i32), Chain }; 947202375Srdivacky return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, MVT::i32, 948198090Srdivacky MVT::Other, Ops, 5); 949195340Sed } 950195340Sed 951195340Sed return NULL; 952195340Sed} 953195340Sed 954202375SrdivackySDNode *ARMDAGToDAGISel::SelectDYN_ALLOC(SDNode *N) { 955198090Srdivacky DebugLoc dl = N->getDebugLoc(); 956202375Srdivacky EVT VT = N->getValueType(0); 957202375Srdivacky SDValue Chain = N->getOperand(0); 958202375Srdivacky SDValue Size = N->getOperand(1); 959202375Srdivacky SDValue Align = N->getOperand(2); 960198090Srdivacky SDValue SP = CurDAG->getRegister(ARM::SP, MVT::i32); 961198090Srdivacky int32_t AlignVal = cast<ConstantSDNode>(Align)->getSExtValue(); 962198090Srdivacky if (AlignVal < 0) 963198090Srdivacky // We need to align the stack. Use Thumb1 tAND which is the only thumb 964198090Srdivacky // instruction that can read and write SP. This matches to a pseudo 965198090Srdivacky // instruction that has a chain to ensure the result is written back to 966198090Srdivacky // the stack pointer. 967198090Srdivacky SP = SDValue(CurDAG->getMachineNode(ARM::tANDsp, dl, VT, SP, Align), 0); 968195340Sed 969198090Srdivacky bool isC = isa<ConstantSDNode>(Size); 970198090Srdivacky uint32_t C = isC ? cast<ConstantSDNode>(Size)->getZExtValue() : ~0UL; 971198090Srdivacky // Handle the most common case for both Thumb1 and Thumb2: 972198090Srdivacky // tSUBspi - immediate is between 0 ... 508 inclusive. 973198090Srdivacky if (C <= 508 && ((C & 3) == 0)) 974198090Srdivacky // FIXME: tSUBspi encode scale 4 implicitly. 975198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::tSUBspi_, VT, MVT::Other, SP, 976198090Srdivacky CurDAG->getTargetConstant(C/4, MVT::i32), 977198090Srdivacky Chain); 978198090Srdivacky 979198090Srdivacky if (Subtarget->isThumb1Only()) { 980198090Srdivacky // Use tADDspr since Thumb1 does not have a sub r, sp, r. ARMISelLowering 981198090Srdivacky // should have negated the size operand already. FIXME: We can't insert 982198090Srdivacky // new target independent node at this stage so we are forced to negate 983198090Srdivacky // it earlier. Is there a better solution? 984198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::tADDspr_, VT, MVT::Other, SP, Size, 985198090Srdivacky Chain); 986198090Srdivacky } else if (Subtarget->isThumb2()) { 987198090Srdivacky if (isC && Predicate_t2_so_imm(Size.getNode())) { 988198090Srdivacky // t2SUBrSPi 989198090Srdivacky SDValue Ops[] = { SP, CurDAG->getTargetConstant(C, MVT::i32), Chain }; 990198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPi_, VT, MVT::Other, Ops, 3); 991198090Srdivacky } else if (isC && Predicate_imm0_4095(Size.getNode())) { 992198090Srdivacky // t2SUBrSPi12 993198090Srdivacky SDValue Ops[] = { SP, CurDAG->getTargetConstant(C, MVT::i32), Chain }; 994198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPi12_, VT, MVT::Other, Ops, 3); 995198090Srdivacky } else { 996198090Srdivacky // t2SUBrSPs 997198090Srdivacky SDValue Ops[] = { SP, Size, 998198090Srdivacky getI32Imm(ARM_AM::getSORegOpc(ARM_AM::lsl,0)), Chain }; 999198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPs_, VT, MVT::Other, Ops, 4); 1000198090Srdivacky } 1001198090Srdivacky } 1002198090Srdivacky 1003198090Srdivacky // FIXME: Add ADD / SUB sp instructions for ARM. 1004198090Srdivacky return 0; 1005198090Srdivacky} 1006198090Srdivacky 1007198090Srdivacky/// PairDRegs - Insert a pair of double registers into an implicit def to 1008198090Srdivacky/// form a quad register. 1009198090SrdivackySDNode *ARMDAGToDAGISel::PairDRegs(EVT VT, SDValue V0, SDValue V1) { 1010198090Srdivacky DebugLoc dl = V0.getNode()->getDebugLoc(); 1011198090Srdivacky SDValue Undef = 1012203954Srdivacky SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0); 1013198090Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::DSUBREG_0, MVT::i32); 1014198090Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::DSUBREG_1, MVT::i32); 1015203954Srdivacky SDNode *Pair = CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, dl, 1016198090Srdivacky VT, Undef, V0, SubReg0); 1017203954Srdivacky return CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, dl, 1018198090Srdivacky VT, SDValue(Pair, 0), V1, SubReg1); 1019198090Srdivacky} 1020198090Srdivacky 1021198090Srdivacky/// GetNEONSubregVT - Given a type for a 128-bit NEON vector, return the type 1022198090Srdivacky/// for a 64-bit subregister of the vector. 1023198090Srdivackystatic EVT GetNEONSubregVT(EVT VT) { 1024198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1025198090Srdivacky default: llvm_unreachable("unhandled NEON type"); 1026198090Srdivacky case MVT::v16i8: return MVT::v8i8; 1027198090Srdivacky case MVT::v8i16: return MVT::v4i16; 1028198090Srdivacky case MVT::v4f32: return MVT::v2f32; 1029198090Srdivacky case MVT::v4i32: return MVT::v2i32; 1030198090Srdivacky case MVT::v2i64: return MVT::v1i64; 1031198090Srdivacky } 1032198090Srdivacky} 1033198090Srdivacky 1034202375SrdivackySDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, unsigned NumVecs, 1035198090Srdivacky unsigned *DOpcodes, unsigned *QOpcodes0, 1036198090Srdivacky unsigned *QOpcodes1) { 1037198090Srdivacky assert(NumVecs >=2 && NumVecs <= 4 && "VLD NumVecs out-of-range"); 1038198090Srdivacky DebugLoc dl = N->getDebugLoc(); 1039198090Srdivacky 1040199481Srdivacky SDValue MemAddr, MemUpdate, MemOpc, Align; 1041202375Srdivacky if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, MemUpdate, MemOpc, Align)) 1042198090Srdivacky return NULL; 1043198090Srdivacky 1044198090Srdivacky SDValue Chain = N->getOperand(0); 1045198090Srdivacky EVT VT = N->getValueType(0); 1046198090Srdivacky bool is64BitVector = VT.is64BitVector(); 1047198090Srdivacky 1048198090Srdivacky unsigned OpcodeIndex; 1049198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1050198090Srdivacky default: llvm_unreachable("unhandled vld type"); 1051198090Srdivacky // Double-register operations: 1052198090Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1053198090Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1054198090Srdivacky case MVT::v2f32: 1055198090Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1056198090Srdivacky case MVT::v1i64: OpcodeIndex = 3; break; 1057198090Srdivacky // Quad-register operations: 1058198090Srdivacky case MVT::v16i8: OpcodeIndex = 0; break; 1059198090Srdivacky case MVT::v8i16: OpcodeIndex = 1; break; 1060198090Srdivacky case MVT::v4f32: 1061198090Srdivacky case MVT::v4i32: OpcodeIndex = 2; break; 1062198090Srdivacky } 1063198090Srdivacky 1064199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1065199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1066198090Srdivacky if (is64BitVector) { 1067198090Srdivacky unsigned Opc = DOpcodes[OpcodeIndex]; 1068199989Srdivacky const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, Align, 1069199989Srdivacky Pred, PredReg, Chain }; 1070198090Srdivacky std::vector<EVT> ResTys(NumVecs, VT); 1071198090Srdivacky ResTys.push_back(MVT::Other); 1072199989Srdivacky return CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 7); 1073198090Srdivacky } 1074198090Srdivacky 1075198090Srdivacky EVT RegVT = GetNEONSubregVT(VT); 1076198090Srdivacky if (NumVecs == 2) { 1077198090Srdivacky // Quad registers are directly supported for VLD2, 1078198090Srdivacky // loading 2 pairs of D regs. 1079198090Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1080199989Srdivacky const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, Align, 1081199989Srdivacky Pred, PredReg, Chain }; 1082198090Srdivacky std::vector<EVT> ResTys(4, VT); 1083198090Srdivacky ResTys.push_back(MVT::Other); 1084199989Srdivacky SDNode *VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 7); 1085198090Srdivacky Chain = SDValue(VLd, 4); 1086198090Srdivacky 1087198090Srdivacky // Combine the even and odd subregs to produce the result. 1088198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1089198090Srdivacky SDNode *Q = PairDRegs(VT, SDValue(VLd, 2*Vec), SDValue(VLd, 2*Vec+1)); 1090198090Srdivacky ReplaceUses(SDValue(N, Vec), SDValue(Q, 0)); 1091198090Srdivacky } 1092198090Srdivacky } else { 1093198090Srdivacky // Otherwise, quad registers are loaded with two separate instructions, 1094198090Srdivacky // where one loads the even registers and the other loads the odd registers. 1095198090Srdivacky 1096198090Srdivacky // Enable writeback to the address register. 1097198090Srdivacky MemOpc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(true), MVT::i32); 1098198090Srdivacky 1099198090Srdivacky std::vector<EVT> ResTys(NumVecs, RegVT); 1100198090Srdivacky ResTys.push_back(MemAddr.getValueType()); 1101198090Srdivacky ResTys.push_back(MVT::Other); 1102198090Srdivacky 1103198113Srdivacky // Load the even subregs. 1104198090Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1105199989Srdivacky const SDValue OpsA[] = { MemAddr, MemUpdate, MemOpc, Align, 1106199989Srdivacky Pred, PredReg, Chain }; 1107199989Srdivacky SDNode *VLdA = CurDAG->getMachineNode(Opc, dl, ResTys, OpsA, 7); 1108198090Srdivacky Chain = SDValue(VLdA, NumVecs+1); 1109198090Srdivacky 1110198113Srdivacky // Load the odd subregs. 1111198090Srdivacky Opc = QOpcodes1[OpcodeIndex]; 1112199481Srdivacky const SDValue OpsB[] = { SDValue(VLdA, NumVecs), MemUpdate, MemOpc, 1113199989Srdivacky Align, Pred, PredReg, Chain }; 1114199989Srdivacky SDNode *VLdB = CurDAG->getMachineNode(Opc, dl, ResTys, OpsB, 7); 1115198090Srdivacky Chain = SDValue(VLdB, NumVecs+1); 1116198090Srdivacky 1117198090Srdivacky // Combine the even and odd subregs to produce the result. 1118198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1119198090Srdivacky SDNode *Q = PairDRegs(VT, SDValue(VLdA, Vec), SDValue(VLdB, Vec)); 1120198090Srdivacky ReplaceUses(SDValue(N, Vec), SDValue(Q, 0)); 1121198090Srdivacky } 1122198090Srdivacky } 1123198090Srdivacky ReplaceUses(SDValue(N, NumVecs), Chain); 1124198090Srdivacky return NULL; 1125198090Srdivacky} 1126198090Srdivacky 1127202375SrdivackySDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, unsigned NumVecs, 1128198113Srdivacky unsigned *DOpcodes, unsigned *QOpcodes0, 1129198113Srdivacky unsigned *QOpcodes1) { 1130198113Srdivacky assert(NumVecs >=2 && NumVecs <= 4 && "VST NumVecs out-of-range"); 1131198113Srdivacky DebugLoc dl = N->getDebugLoc(); 1132198113Srdivacky 1133199481Srdivacky SDValue MemAddr, MemUpdate, MemOpc, Align; 1134202375Srdivacky if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, MemUpdate, MemOpc, Align)) 1135198113Srdivacky return NULL; 1136198113Srdivacky 1137198113Srdivacky SDValue Chain = N->getOperand(0); 1138198113Srdivacky EVT VT = N->getOperand(3).getValueType(); 1139198113Srdivacky bool is64BitVector = VT.is64BitVector(); 1140198113Srdivacky 1141198113Srdivacky unsigned OpcodeIndex; 1142198113Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1143198113Srdivacky default: llvm_unreachable("unhandled vst type"); 1144198113Srdivacky // Double-register operations: 1145198113Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1146198113Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1147198113Srdivacky case MVT::v2f32: 1148198113Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1149198113Srdivacky case MVT::v1i64: OpcodeIndex = 3; break; 1150198113Srdivacky // Quad-register operations: 1151198113Srdivacky case MVT::v16i8: OpcodeIndex = 0; break; 1152198113Srdivacky case MVT::v8i16: OpcodeIndex = 1; break; 1153198113Srdivacky case MVT::v4f32: 1154198113Srdivacky case MVT::v4i32: OpcodeIndex = 2; break; 1155198113Srdivacky } 1156198113Srdivacky 1157199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1158199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1159199989Srdivacky 1160198113Srdivacky SmallVector<SDValue, 8> Ops; 1161198113Srdivacky Ops.push_back(MemAddr); 1162198113Srdivacky Ops.push_back(MemUpdate); 1163198113Srdivacky Ops.push_back(MemOpc); 1164199481Srdivacky Ops.push_back(Align); 1165198113Srdivacky 1166198113Srdivacky if (is64BitVector) { 1167198113Srdivacky unsigned Opc = DOpcodes[OpcodeIndex]; 1168198113Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1169198113Srdivacky Ops.push_back(N->getOperand(Vec+3)); 1170199989Srdivacky Ops.push_back(Pred); 1171199989Srdivacky Ops.push_back(PredReg); 1172198113Srdivacky Ops.push_back(Chain); 1173199989Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+7); 1174198113Srdivacky } 1175198113Srdivacky 1176198113Srdivacky EVT RegVT = GetNEONSubregVT(VT); 1177198113Srdivacky if (NumVecs == 2) { 1178198113Srdivacky // Quad registers are directly supported for VST2, 1179198113Srdivacky // storing 2 pairs of D regs. 1180198113Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1181198113Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1182198113Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT, 1183198113Srdivacky N->getOperand(Vec+3))); 1184198113Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT, 1185198113Srdivacky N->getOperand(Vec+3))); 1186198113Srdivacky } 1187199989Srdivacky Ops.push_back(Pred); 1188199989Srdivacky Ops.push_back(PredReg); 1189198113Srdivacky Ops.push_back(Chain); 1190199989Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), 11); 1191198113Srdivacky } 1192198113Srdivacky 1193198113Srdivacky // Otherwise, quad registers are stored with two separate instructions, 1194198113Srdivacky // where one stores the even registers and the other stores the odd registers. 1195198113Srdivacky 1196198113Srdivacky // Enable writeback to the address register. 1197198113Srdivacky MemOpc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(true), MVT::i32); 1198198113Srdivacky 1199198113Srdivacky // Store the even subregs. 1200198113Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1201198113Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT, 1202198113Srdivacky N->getOperand(Vec+3))); 1203199989Srdivacky Ops.push_back(Pred); 1204199989Srdivacky Ops.push_back(PredReg); 1205198113Srdivacky Ops.push_back(Chain); 1206198113Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1207198113Srdivacky SDNode *VStA = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(), 1208199989Srdivacky MVT::Other, Ops.data(), NumVecs+7); 1209198113Srdivacky Chain = SDValue(VStA, 1); 1210198113Srdivacky 1211198113Srdivacky // Store the odd subregs. 1212198113Srdivacky Ops[0] = SDValue(VStA, 0); // MemAddr 1213198113Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1214199481Srdivacky Ops[Vec+4] = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT, 1215198113Srdivacky N->getOperand(Vec+3)); 1216199989Srdivacky Ops[NumVecs+4] = Pred; 1217199989Srdivacky Ops[NumVecs+5] = PredReg; 1218199989Srdivacky Ops[NumVecs+6] = Chain; 1219198113Srdivacky Opc = QOpcodes1[OpcodeIndex]; 1220198113Srdivacky SDNode *VStB = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(), 1221199989Srdivacky MVT::Other, Ops.data(), NumVecs+7); 1222198113Srdivacky Chain = SDValue(VStB, 1); 1223198113Srdivacky ReplaceUses(SDValue(N, 0), Chain); 1224198113Srdivacky return NULL; 1225198113Srdivacky} 1226198113Srdivacky 1227202375SrdivackySDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, 1228198090Srdivacky unsigned NumVecs, unsigned *DOpcodes, 1229198090Srdivacky unsigned *QOpcodes0, 1230198090Srdivacky unsigned *QOpcodes1) { 1231198090Srdivacky assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range"); 1232198090Srdivacky DebugLoc dl = N->getDebugLoc(); 1233198090Srdivacky 1234199481Srdivacky SDValue MemAddr, MemUpdate, MemOpc, Align; 1235202375Srdivacky if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, MemUpdate, MemOpc, Align)) 1236198090Srdivacky return NULL; 1237198090Srdivacky 1238198090Srdivacky SDValue Chain = N->getOperand(0); 1239198090Srdivacky unsigned Lane = 1240198090Srdivacky cast<ConstantSDNode>(N->getOperand(NumVecs+3))->getZExtValue(); 1241198090Srdivacky EVT VT = IsLoad ? N->getValueType(0) : N->getOperand(3).getValueType(); 1242198090Srdivacky bool is64BitVector = VT.is64BitVector(); 1243198090Srdivacky 1244198090Srdivacky // Quad registers are handled by load/store of subregs. Find the subreg info. 1245198090Srdivacky unsigned NumElts = 0; 1246198090Srdivacky int SubregIdx = 0; 1247198090Srdivacky EVT RegVT = VT; 1248198090Srdivacky if (!is64BitVector) { 1249198090Srdivacky RegVT = GetNEONSubregVT(VT); 1250198090Srdivacky NumElts = RegVT.getVectorNumElements(); 1251198090Srdivacky SubregIdx = (Lane < NumElts) ? ARM::DSUBREG_0 : ARM::DSUBREG_1; 1252198090Srdivacky } 1253198090Srdivacky 1254198090Srdivacky unsigned OpcodeIndex; 1255198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1256198090Srdivacky default: llvm_unreachable("unhandled vld/vst lane type"); 1257198090Srdivacky // Double-register operations: 1258198090Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1259198090Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1260198090Srdivacky case MVT::v2f32: 1261198090Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1262198090Srdivacky // Quad-register operations: 1263198090Srdivacky case MVT::v8i16: OpcodeIndex = 0; break; 1264198090Srdivacky case MVT::v4f32: 1265198090Srdivacky case MVT::v4i32: OpcodeIndex = 1; break; 1266198090Srdivacky } 1267198090Srdivacky 1268199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1269199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1270199989Srdivacky 1271198090Srdivacky SmallVector<SDValue, 9> Ops; 1272198090Srdivacky Ops.push_back(MemAddr); 1273198090Srdivacky Ops.push_back(MemUpdate); 1274198090Srdivacky Ops.push_back(MemOpc); 1275199481Srdivacky Ops.push_back(Align); 1276198090Srdivacky 1277198090Srdivacky unsigned Opc = 0; 1278198090Srdivacky if (is64BitVector) { 1279198090Srdivacky Opc = DOpcodes[OpcodeIndex]; 1280198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1281198090Srdivacky Ops.push_back(N->getOperand(Vec+3)); 1282198090Srdivacky } else { 1283198090Srdivacky // Check if this is loading the even or odd subreg of a Q register. 1284198090Srdivacky if (Lane < NumElts) { 1285198090Srdivacky Opc = QOpcodes0[OpcodeIndex]; 1286198090Srdivacky } else { 1287198090Srdivacky Lane -= NumElts; 1288198090Srdivacky Opc = QOpcodes1[OpcodeIndex]; 1289198090Srdivacky } 1290198090Srdivacky // Extract the subregs of the input vector. 1291198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1292198090Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT, 1293198090Srdivacky N->getOperand(Vec+3))); 1294198090Srdivacky } 1295198090Srdivacky Ops.push_back(getI32Imm(Lane)); 1296199989Srdivacky Ops.push_back(Pred); 1297199989Srdivacky Ops.push_back(PredReg); 1298198090Srdivacky Ops.push_back(Chain); 1299198090Srdivacky 1300198090Srdivacky if (!IsLoad) 1301202878Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+8); 1302198090Srdivacky 1303198090Srdivacky std::vector<EVT> ResTys(NumVecs, RegVT); 1304198090Srdivacky ResTys.push_back(MVT::Other); 1305198090Srdivacky SDNode *VLdLn = 1306202878Srdivacky CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), NumVecs+8); 1307198090Srdivacky // For a 64-bit vector load to D registers, nothing more needs to be done. 1308198090Srdivacky if (is64BitVector) 1309198090Srdivacky return VLdLn; 1310198090Srdivacky 1311198090Srdivacky // For 128-bit vectors, take the 64-bit results of the load and insert them 1312198090Srdivacky // as subregs into the result. 1313198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1314198090Srdivacky SDValue QuadVec = CurDAG->getTargetInsertSubreg(SubregIdx, dl, VT, 1315198090Srdivacky N->getOperand(Vec+3), 1316198090Srdivacky SDValue(VLdLn, Vec)); 1317198090Srdivacky ReplaceUses(SDValue(N, Vec), QuadVec); 1318198090Srdivacky } 1319198090Srdivacky 1320198090Srdivacky Chain = SDValue(VLdLn, NumVecs); 1321198090Srdivacky ReplaceUses(SDValue(N, NumVecs), Chain); 1322198090Srdivacky return NULL; 1323198090Srdivacky} 1324198090Srdivacky 1325202375SrdivackySDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N, 1326198090Srdivacky unsigned Opc) { 1327198090Srdivacky if (!Subtarget->hasV6T2Ops()) 1328198090Srdivacky return NULL; 1329198090Srdivacky 1330198090Srdivacky unsigned Shl_imm = 0; 1331202375Srdivacky if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) { 1332198090Srdivacky assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!"); 1333198090Srdivacky unsigned Srl_imm = 0; 1334202375Srdivacky if (isInt32Immediate(N->getOperand(1), Srl_imm)) { 1335198090Srdivacky assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); 1336198090Srdivacky unsigned Width = 32 - Srl_imm; 1337198090Srdivacky int LSB = Srl_imm - Shl_imm; 1338198396Srdivacky if (LSB < 0) 1339198090Srdivacky return NULL; 1340198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1341202375Srdivacky SDValue Ops[] = { N->getOperand(0).getOperand(0), 1342198090Srdivacky CurDAG->getTargetConstant(LSB, MVT::i32), 1343198090Srdivacky CurDAG->getTargetConstant(Width, MVT::i32), 1344198090Srdivacky getAL(CurDAG), Reg0 }; 1345202375Srdivacky return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); 1346198090Srdivacky } 1347198090Srdivacky } 1348198090Srdivacky return NULL; 1349198090Srdivacky} 1350198090Srdivacky 1351199989SrdivackySDNode *ARMDAGToDAGISel:: 1352202375SrdivackySelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 1353199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1354199989Srdivacky SDValue CPTmp0; 1355199989Srdivacky SDValue CPTmp1; 1356202375Srdivacky if (SelectT2ShifterOperandReg(N, TrueVal, CPTmp0, CPTmp1)) { 1357199989Srdivacky unsigned SOVal = cast<ConstantSDNode>(CPTmp1)->getZExtValue(); 1358199989Srdivacky unsigned SOShOp = ARM_AM::getSORegShOp(SOVal); 1359199989Srdivacky unsigned Opc = 0; 1360199989Srdivacky switch (SOShOp) { 1361199989Srdivacky case ARM_AM::lsl: Opc = ARM::t2MOVCClsl; break; 1362199989Srdivacky case ARM_AM::lsr: Opc = ARM::t2MOVCClsr; break; 1363199989Srdivacky case ARM_AM::asr: Opc = ARM::t2MOVCCasr; break; 1364199989Srdivacky case ARM_AM::ror: Opc = ARM::t2MOVCCror; break; 1365199989Srdivacky default: 1366199989Srdivacky llvm_unreachable("Unknown so_reg opcode!"); 1367199989Srdivacky break; 1368199989Srdivacky } 1369199989Srdivacky SDValue SOShImm = 1370199989Srdivacky CurDAG->getTargetConstant(ARM_AM::getSORegOffset(SOVal), MVT::i32); 1371199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1372199989Srdivacky SDValue Ops[] = { FalseVal, CPTmp0, SOShImm, CC, CCR, InFlag }; 1373202375Srdivacky return CurDAG->SelectNodeTo(N, Opc, MVT::i32,Ops, 6); 1374199989Srdivacky } 1375199989Srdivacky return 0; 1376199989Srdivacky} 1377199989Srdivacky 1378199989SrdivackySDNode *ARMDAGToDAGISel:: 1379202375SrdivackySelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 1380199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1381199989Srdivacky SDValue CPTmp0; 1382199989Srdivacky SDValue CPTmp1; 1383199989Srdivacky SDValue CPTmp2; 1384202375Srdivacky if (SelectShifterOperandReg(N, TrueVal, CPTmp0, CPTmp1, CPTmp2)) { 1385199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1386199989Srdivacky SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, InFlag }; 1387202375Srdivacky return CurDAG->SelectNodeTo(N, ARM::MOVCCs, MVT::i32, Ops, 7); 1388199989Srdivacky } 1389199989Srdivacky return 0; 1390199989Srdivacky} 1391199989Srdivacky 1392199989SrdivackySDNode *ARMDAGToDAGISel:: 1393202375SrdivackySelectT2CMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 1394199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1395199989Srdivacky ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal); 1396199989Srdivacky if (!T) 1397199989Srdivacky return 0; 1398199989Srdivacky 1399199989Srdivacky if (Predicate_t2_so_imm(TrueVal.getNode())) { 1400199989Srdivacky SDValue True = CurDAG->getTargetConstant(T->getZExtValue(), MVT::i32); 1401199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1402199989Srdivacky SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag }; 1403202375Srdivacky return CurDAG->SelectNodeTo(N, 1404199989Srdivacky ARM::t2MOVCCi, MVT::i32, Ops, 5); 1405199989Srdivacky } 1406199989Srdivacky return 0; 1407199989Srdivacky} 1408199989Srdivacky 1409199989SrdivackySDNode *ARMDAGToDAGISel:: 1410202375SrdivackySelectARMCMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 1411199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1412199989Srdivacky ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal); 1413199989Srdivacky if (!T) 1414199989Srdivacky return 0; 1415199989Srdivacky 1416199989Srdivacky if (Predicate_so_imm(TrueVal.getNode())) { 1417199989Srdivacky SDValue True = CurDAG->getTargetConstant(T->getZExtValue(), MVT::i32); 1418199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1419199989Srdivacky SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag }; 1420202375Srdivacky return CurDAG->SelectNodeTo(N, 1421199989Srdivacky ARM::MOVCCi, MVT::i32, Ops, 5); 1422199989Srdivacky } 1423199989Srdivacky return 0; 1424199989Srdivacky} 1425199989Srdivacky 1426202375SrdivackySDNode *ARMDAGToDAGISel::SelectCMOVOp(SDNode *N) { 1427202375Srdivacky EVT VT = N->getValueType(0); 1428202375Srdivacky SDValue FalseVal = N->getOperand(0); 1429202375Srdivacky SDValue TrueVal = N->getOperand(1); 1430202375Srdivacky SDValue CC = N->getOperand(2); 1431202375Srdivacky SDValue CCR = N->getOperand(3); 1432202375Srdivacky SDValue InFlag = N->getOperand(4); 1433199989Srdivacky assert(CC.getOpcode() == ISD::Constant); 1434199989Srdivacky assert(CCR.getOpcode() == ISD::Register); 1435199989Srdivacky ARMCC::CondCodes CCVal = 1436199989Srdivacky (ARMCC::CondCodes)cast<ConstantSDNode>(CC)->getZExtValue(); 1437199989Srdivacky 1438199989Srdivacky if (!Subtarget->isThumb1Only() && VT == MVT::i32) { 1439199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) 1440199989Srdivacky // Emits: (MOVCCs:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) 1441199989Srdivacky // Pattern complexity = 18 cost = 1 size = 0 1442199989Srdivacky SDValue CPTmp0; 1443199989Srdivacky SDValue CPTmp1; 1444199989Srdivacky SDValue CPTmp2; 1445199989Srdivacky if (Subtarget->isThumb()) { 1446202375Srdivacky SDNode *Res = SelectT2CMOVShiftOp(N, FalseVal, TrueVal, 1447199989Srdivacky CCVal, CCR, InFlag); 1448199989Srdivacky if (!Res) 1449202375Srdivacky Res = SelectT2CMOVShiftOp(N, TrueVal, FalseVal, 1450199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1451199989Srdivacky if (Res) 1452199989Srdivacky return Res; 1453199989Srdivacky } else { 1454202375Srdivacky SDNode *Res = SelectARMCMOVShiftOp(N, FalseVal, TrueVal, 1455199989Srdivacky CCVal, CCR, InFlag); 1456199989Srdivacky if (!Res) 1457202375Srdivacky Res = SelectARMCMOVShiftOp(N, TrueVal, FalseVal, 1458199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1459199989Srdivacky if (Res) 1460199989Srdivacky return Res; 1461199989Srdivacky } 1462199989Srdivacky 1463199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, 1464199989Srdivacky // (imm:i32)<<P:Predicate_so_imm>>:$true, 1465199989Srdivacky // (imm:i32):$cc) 1466199989Srdivacky // Emits: (MOVCCi:i32 GPR:i32:$false, 1467199989Srdivacky // (so_imm:i32 (imm:i32):$true), (imm:i32):$cc) 1468199989Srdivacky // Pattern complexity = 10 cost = 1 size = 0 1469199989Srdivacky if (Subtarget->isThumb()) { 1470202375Srdivacky SDNode *Res = SelectT2CMOVSoImmOp(N, FalseVal, TrueVal, 1471199989Srdivacky CCVal, CCR, InFlag); 1472199989Srdivacky if (!Res) 1473202375Srdivacky Res = SelectT2CMOVSoImmOp(N, TrueVal, FalseVal, 1474199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1475199989Srdivacky if (Res) 1476199989Srdivacky return Res; 1477199989Srdivacky } else { 1478202375Srdivacky SDNode *Res = SelectARMCMOVSoImmOp(N, FalseVal, TrueVal, 1479199989Srdivacky CCVal, CCR, InFlag); 1480199989Srdivacky if (!Res) 1481202375Srdivacky Res = SelectARMCMOVSoImmOp(N, TrueVal, FalseVal, 1482199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1483199989Srdivacky if (Res) 1484199989Srdivacky return Res; 1485199989Srdivacky } 1486199989Srdivacky } 1487199989Srdivacky 1488199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1489199989Srdivacky // Emits: (MOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1490199989Srdivacky // Pattern complexity = 6 cost = 1 size = 0 1491199989Srdivacky // 1492199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1493199989Srdivacky // Emits: (tMOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1494199989Srdivacky // Pattern complexity = 6 cost = 11 size = 0 1495199989Srdivacky // 1496199989Srdivacky // Also FCPYScc and FCPYDcc. 1497199989Srdivacky SDValue Tmp2 = CurDAG->getTargetConstant(CCVal, MVT::i32); 1498199989Srdivacky SDValue Ops[] = { FalseVal, TrueVal, Tmp2, CCR, InFlag }; 1499199989Srdivacky unsigned Opc = 0; 1500199989Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1501199989Srdivacky default: assert(false && "Illegal conditional move type!"); 1502199989Srdivacky break; 1503199989Srdivacky case MVT::i32: 1504199989Srdivacky Opc = Subtarget->isThumb() 1505199989Srdivacky ? (Subtarget->hasThumb2() ? ARM::t2MOVCCr : ARM::tMOVCCr_pseudo) 1506199989Srdivacky : ARM::MOVCCr; 1507199989Srdivacky break; 1508199989Srdivacky case MVT::f32: 1509199989Srdivacky Opc = ARM::VMOVScc; 1510199989Srdivacky break; 1511199989Srdivacky case MVT::f64: 1512199989Srdivacky Opc = ARM::VMOVDcc; 1513199989Srdivacky break; 1514199989Srdivacky } 1515202375Srdivacky return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5); 1516199989Srdivacky} 1517199989Srdivacky 1518202375SrdivackySDNode *ARMDAGToDAGISel::Select(SDNode *N) { 1519193323Sed DebugLoc dl = N->getDebugLoc(); 1520193323Sed 1521193323Sed if (N->isMachineOpcode()) 1522193323Sed return NULL; // Already selected. 1523193323Sed 1524193323Sed switch (N->getOpcode()) { 1525193323Sed default: break; 1526193323Sed case ISD::Constant: { 1527193323Sed unsigned Val = cast<ConstantSDNode>(N)->getZExtValue(); 1528193323Sed bool UseCP = true; 1529198090Srdivacky if (Subtarget->hasThumb2()) 1530198090Srdivacky // Thumb2-aware targets have the MOVT instruction, so all immediates can 1531198090Srdivacky // be done with MOV + MOVT, at worst. 1532198090Srdivacky UseCP = 0; 1533198090Srdivacky else { 1534198090Srdivacky if (Subtarget->isThumb()) { 1535194710Sed UseCP = (Val > 255 && // MOV 1536194710Sed ~Val > 255 && // MOV + MVN 1537194710Sed !ARM_AM::isThumbImmShiftedVal(Val)); // MOV + LSL 1538198090Srdivacky } else 1539198090Srdivacky UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV 1540198090Srdivacky ARM_AM::getSOImmVal(~Val) == -1 && // MVN 1541198090Srdivacky !ARM_AM::isSOImmTwoPartVal(Val)); // two instrs. 1542198090Srdivacky } 1543198090Srdivacky 1544193323Sed if (UseCP) { 1545193323Sed SDValue CPIdx = 1546198090Srdivacky CurDAG->getTargetConstantPool(ConstantInt::get( 1547198090Srdivacky Type::getInt32Ty(*CurDAG->getContext()), Val), 1548193323Sed TLI.getPointerTy()); 1549193323Sed 1550193323Sed SDNode *ResNode; 1551198090Srdivacky if (Subtarget->isThumb1Only()) { 1552199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1553198090Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1554198090Srdivacky SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() }; 1555198090Srdivacky ResNode = CurDAG->getMachineNode(ARM::tLDRcp, dl, MVT::i32, MVT::Other, 1556198090Srdivacky Ops, 4); 1557198090Srdivacky } else { 1558193323Sed SDValue Ops[] = { 1559198090Srdivacky CPIdx, 1560193323Sed CurDAG->getRegister(0, MVT::i32), 1561193323Sed CurDAG->getTargetConstant(0, MVT::i32), 1562193323Sed getAL(CurDAG), 1563193323Sed CurDAG->getRegister(0, MVT::i32), 1564193323Sed CurDAG->getEntryNode() 1565193323Sed }; 1566198090Srdivacky ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other, 1567198090Srdivacky Ops, 6); 1568193323Sed } 1569202375Srdivacky ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0)); 1570193323Sed return NULL; 1571193323Sed } 1572198090Srdivacky 1573193323Sed // Other cases are autogenerated. 1574193323Sed break; 1575193323Sed } 1576193323Sed case ISD::FrameIndex: { 1577193323Sed // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm. 1578193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 1579193323Sed SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 1580198090Srdivacky if (Subtarget->isThumb1Only()) { 1581193323Sed return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI, 1582193323Sed CurDAG->getTargetConstant(0, MVT::i32)); 1583193323Sed } else { 1584198090Srdivacky unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ? 1585198090Srdivacky ARM::t2ADDri : ARM::ADDri); 1586193323Sed SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32), 1587198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1588198090Srdivacky CurDAG->getRegister(0, MVT::i32) }; 1589198090Srdivacky return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); 1590193323Sed } 1591193323Sed } 1592198090Srdivacky case ARMISD::DYN_ALLOC: 1593202375Srdivacky return SelectDYN_ALLOC(N); 1594198090Srdivacky case ISD::SRL: 1595202375Srdivacky if (SDNode *I = SelectV6T2BitfieldExtractOp(N, 1596198090Srdivacky Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX)) 1597198090Srdivacky return I; 1598193323Sed break; 1599198090Srdivacky case ISD::SRA: 1600202375Srdivacky if (SDNode *I = SelectV6T2BitfieldExtractOp(N, 1601198090Srdivacky Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)) 1602198090Srdivacky return I; 1603198090Srdivacky break; 1604193323Sed case ISD::MUL: 1605198090Srdivacky if (Subtarget->isThumb1Only()) 1606193323Sed break; 1607202375Srdivacky if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) { 1608193323Sed unsigned RHSV = C->getZExtValue(); 1609193323Sed if (!RHSV) break; 1610193323Sed if (isPowerOf2_32(RHSV-1)) { // 2^n+1? 1611198090Srdivacky unsigned ShImm = Log2_32(RHSV-1); 1612198090Srdivacky if (ShImm >= 32) 1613198090Srdivacky break; 1614202375Srdivacky SDValue V = N->getOperand(0); 1615198090Srdivacky ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); 1616198090Srdivacky SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); 1617198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1618198090Srdivacky if (Subtarget->isThumb()) { 1619198090Srdivacky SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1620198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops, 6); 1621198090Srdivacky } else { 1622198090Srdivacky SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1623198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 7); 1624198090Srdivacky } 1625193323Sed } 1626193323Sed if (isPowerOf2_32(RHSV+1)) { // 2^n-1? 1627198090Srdivacky unsigned ShImm = Log2_32(RHSV+1); 1628198090Srdivacky if (ShImm >= 32) 1629198090Srdivacky break; 1630202375Srdivacky SDValue V = N->getOperand(0); 1631198090Srdivacky ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); 1632198090Srdivacky SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); 1633198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1634198090Srdivacky if (Subtarget->isThumb()) { 1635198090Srdivacky SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0 }; 1636198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops, 5); 1637198090Srdivacky } else { 1638198090Srdivacky SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1639198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 7); 1640198090Srdivacky } 1641193323Sed } 1642193323Sed } 1643193323Sed break; 1644198396Srdivacky case ISD::AND: { 1645198396Srdivacky // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits 1646198396Srdivacky // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits 1647198396Srdivacky // are entirely contributed by c2 and lower 16-bits are entirely contributed 1648198396Srdivacky // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)). 1649198396Srdivacky // Select it to: "movt x, ((c1 & 0xffff) >> 16) 1650202375Srdivacky EVT VT = N->getValueType(0); 1651198396Srdivacky if (VT != MVT::i32) 1652198396Srdivacky break; 1653198396Srdivacky unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2()) 1654198396Srdivacky ? ARM::t2MOVTi16 1655198396Srdivacky : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0); 1656198396Srdivacky if (!Opc) 1657198396Srdivacky break; 1658202375Srdivacky SDValue N0 = N->getOperand(0), N1 = N->getOperand(1); 1659198396Srdivacky ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); 1660198396Srdivacky if (!N1C) 1661198396Srdivacky break; 1662198396Srdivacky if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) { 1663198396Srdivacky SDValue N2 = N0.getOperand(1); 1664198396Srdivacky ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2); 1665198396Srdivacky if (!N2C) 1666198396Srdivacky break; 1667198396Srdivacky unsigned N1CVal = N1C->getZExtValue(); 1668198396Srdivacky unsigned N2CVal = N2C->getZExtValue(); 1669198396Srdivacky if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) && 1670198396Srdivacky (N1CVal & 0xffffU) == 0xffffU && 1671198396Srdivacky (N2CVal & 0xffffU) == 0x0U) { 1672198396Srdivacky SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16, 1673198396Srdivacky MVT::i32); 1674198396Srdivacky SDValue Ops[] = { N0.getOperand(0), Imm16, 1675198396Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; 1676198396Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, Ops, 4); 1677198396Srdivacky } 1678198396Srdivacky } 1679198396Srdivacky break; 1680198396Srdivacky } 1681199481Srdivacky case ARMISD::VMOVRRD: 1682199481Srdivacky return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32, 1683202375Srdivacky N->getOperand(0), getAL(CurDAG), 1684198090Srdivacky CurDAG->getRegister(0, MVT::i32)); 1685193323Sed case ISD::UMUL_LOHI: { 1686198090Srdivacky if (Subtarget->isThumb1Only()) 1687198090Srdivacky break; 1688198090Srdivacky if (Subtarget->isThumb()) { 1689202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 1690193323Sed getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1691193323Sed CurDAG->getRegister(0, MVT::i32) }; 1692198090Srdivacky return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops,4); 1693198090Srdivacky } else { 1694202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 1695198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1696198090Srdivacky CurDAG->getRegister(0, MVT::i32) }; 1697198090Srdivacky return CurDAG->getMachineNode(ARM::UMULL, dl, MVT::i32, MVT::i32, Ops, 5); 1698198090Srdivacky } 1699193323Sed } 1700193323Sed case ISD::SMUL_LOHI: { 1701198090Srdivacky if (Subtarget->isThumb1Only()) 1702198090Srdivacky break; 1703198090Srdivacky if (Subtarget->isThumb()) { 1704202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 1705198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; 1706198090Srdivacky return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops,4); 1707198090Srdivacky } else { 1708202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 1709193323Sed getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1710193323Sed CurDAG->getRegister(0, MVT::i32) }; 1711198090Srdivacky return CurDAG->getMachineNode(ARM::SMULL, dl, MVT::i32, MVT::i32, Ops, 5); 1712198090Srdivacky } 1713193323Sed } 1714193323Sed case ISD::LOAD: { 1715195340Sed SDNode *ResNode = 0; 1716198090Srdivacky if (Subtarget->isThumb() && Subtarget->hasThumb2()) 1717202375Srdivacky ResNode = SelectT2IndexedLoad(N); 1718195340Sed else 1719202375Srdivacky ResNode = SelectARMIndexedLoad(N); 1720195340Sed if (ResNode) 1721195340Sed return ResNode; 1722193323Sed // Other cases are autogenerated. 1723193323Sed break; 1724193323Sed } 1725193323Sed case ARMISD::BRCOND: { 1726193323Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 1727193323Sed // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc) 1728193323Sed // Pattern complexity = 6 cost = 1 size = 0 1729193323Sed 1730193323Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 1731193323Sed // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc) 1732193323Sed // Pattern complexity = 6 cost = 1 size = 0 1733193323Sed 1734195340Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 1735195340Sed // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc) 1736195340Sed // Pattern complexity = 6 cost = 1 size = 0 1737195340Sed 1738198090Srdivacky unsigned Opc = Subtarget->isThumb() ? 1739195340Sed ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc; 1740202375Srdivacky SDValue Chain = N->getOperand(0); 1741202375Srdivacky SDValue N1 = N->getOperand(1); 1742202375Srdivacky SDValue N2 = N->getOperand(2); 1743202375Srdivacky SDValue N3 = N->getOperand(3); 1744202375Srdivacky SDValue InFlag = N->getOperand(4); 1745193323Sed assert(N1.getOpcode() == ISD::BasicBlock); 1746193323Sed assert(N2.getOpcode() == ISD::Constant); 1747193323Sed assert(N3.getOpcode() == ISD::Register); 1748193323Sed 1749193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 1750193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 1751193323Sed MVT::i32); 1752193323Sed SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag }; 1753198090Srdivacky SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other, 1754198090Srdivacky MVT::Flag, Ops, 5); 1755193323Sed Chain = SDValue(ResNode, 0); 1756202375Srdivacky if (N->getNumValues() == 2) { 1757193323Sed InFlag = SDValue(ResNode, 1); 1758202375Srdivacky ReplaceUses(SDValue(N, 1), InFlag); 1759193323Sed } 1760202375Srdivacky ReplaceUses(SDValue(N, 0), 1761199511Srdivacky SDValue(Chain.getNode(), Chain.getResNo())); 1762193323Sed return NULL; 1763193323Sed } 1764199989Srdivacky case ARMISD::CMOV: 1765202375Srdivacky return SelectCMOVOp(N); 1766193323Sed case ARMISD::CNEG: { 1767202375Srdivacky EVT VT = N->getValueType(0); 1768202375Srdivacky SDValue N0 = N->getOperand(0); 1769202375Srdivacky SDValue N1 = N->getOperand(1); 1770202375Srdivacky SDValue N2 = N->getOperand(2); 1771202375Srdivacky SDValue N3 = N->getOperand(3); 1772202375Srdivacky SDValue InFlag = N->getOperand(4); 1773193323Sed assert(N2.getOpcode() == ISD::Constant); 1774193323Sed assert(N3.getOpcode() == ISD::Register); 1775193323Sed 1776193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 1777193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 1778193323Sed MVT::i32); 1779193323Sed SDValue Ops[] = { N0, N1, Tmp2, N3, InFlag }; 1780193323Sed unsigned Opc = 0; 1781198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1782193323Sed default: assert(false && "Illegal conditional move type!"); 1783193323Sed break; 1784193323Sed case MVT::f32: 1785199481Srdivacky Opc = ARM::VNEGScc; 1786193323Sed break; 1787193323Sed case MVT::f64: 1788199481Srdivacky Opc = ARM::VNEGDcc; 1789193323Sed break; 1790193323Sed } 1791202375Srdivacky return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5); 1792193323Sed } 1793193323Sed 1794198090Srdivacky case ARMISD::VZIP: { 1795198090Srdivacky unsigned Opc = 0; 1796198090Srdivacky EVT VT = N->getValueType(0); 1797198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1798198090Srdivacky default: return NULL; 1799198090Srdivacky case MVT::v8i8: Opc = ARM::VZIPd8; break; 1800198090Srdivacky case MVT::v4i16: Opc = ARM::VZIPd16; break; 1801198090Srdivacky case MVT::v2f32: 1802198090Srdivacky case MVT::v2i32: Opc = ARM::VZIPd32; break; 1803198090Srdivacky case MVT::v16i8: Opc = ARM::VZIPq8; break; 1804198090Srdivacky case MVT::v8i16: Opc = ARM::VZIPq16; break; 1805198090Srdivacky case MVT::v4f32: 1806198090Srdivacky case MVT::v4i32: Opc = ARM::VZIPq32; break; 1807193323Sed } 1808199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1809199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1810199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 1811199989Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); 1812198090Srdivacky } 1813198090Srdivacky case ARMISD::VUZP: { 1814198090Srdivacky unsigned Opc = 0; 1815198090Srdivacky EVT VT = N->getValueType(0); 1816198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1817198090Srdivacky default: return NULL; 1818198090Srdivacky case MVT::v8i8: Opc = ARM::VUZPd8; break; 1819198090Srdivacky case MVT::v4i16: Opc = ARM::VUZPd16; break; 1820198090Srdivacky case MVT::v2f32: 1821198090Srdivacky case MVT::v2i32: Opc = ARM::VUZPd32; break; 1822198090Srdivacky case MVT::v16i8: Opc = ARM::VUZPq8; break; 1823198090Srdivacky case MVT::v8i16: Opc = ARM::VUZPq16; break; 1824198090Srdivacky case MVT::v4f32: 1825198090Srdivacky case MVT::v4i32: Opc = ARM::VUZPq32; break; 1826193323Sed } 1827199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1828199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1829199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 1830199989Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); 1831198090Srdivacky } 1832198090Srdivacky case ARMISD::VTRN: { 1833198090Srdivacky unsigned Opc = 0; 1834198090Srdivacky EVT VT = N->getValueType(0); 1835198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1836198090Srdivacky default: return NULL; 1837198090Srdivacky case MVT::v8i8: Opc = ARM::VTRNd8; break; 1838198090Srdivacky case MVT::v4i16: Opc = ARM::VTRNd16; break; 1839198090Srdivacky case MVT::v2f32: 1840198090Srdivacky case MVT::v2i32: Opc = ARM::VTRNd32; break; 1841198090Srdivacky case MVT::v16i8: Opc = ARM::VTRNq8; break; 1842198090Srdivacky case MVT::v8i16: Opc = ARM::VTRNq16; break; 1843198090Srdivacky case MVT::v4f32: 1844198090Srdivacky case MVT::v4i32: Opc = ARM::VTRNq32; break; 1845193323Sed } 1846199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1847199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1848199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 1849199989Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); 1850193323Sed } 1851194710Sed 1852198090Srdivacky case ISD::INTRINSIC_VOID: 1853198090Srdivacky case ISD::INTRINSIC_W_CHAIN: { 1854198090Srdivacky unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue(); 1855198090Srdivacky switch (IntNo) { 1856198090Srdivacky default: 1857198090Srdivacky break; 1858194710Sed 1859198090Srdivacky case Intrinsic::arm_neon_vld2: { 1860198090Srdivacky unsigned DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16, 1861198090Srdivacky ARM::VLD2d32, ARM::VLD2d64 }; 1862198090Srdivacky unsigned QOpcodes[] = { ARM::VLD2q8, ARM::VLD2q16, ARM::VLD2q32 }; 1863202375Srdivacky return SelectVLD(N, 2, DOpcodes, QOpcodes, 0); 1864198090Srdivacky } 1865194710Sed 1866198090Srdivacky case Intrinsic::arm_neon_vld3: { 1867198090Srdivacky unsigned DOpcodes[] = { ARM::VLD3d8, ARM::VLD3d16, 1868198090Srdivacky ARM::VLD3d32, ARM::VLD3d64 }; 1869198090Srdivacky unsigned QOpcodes0[] = { ARM::VLD3q8a, ARM::VLD3q16a, ARM::VLD3q32a }; 1870198090Srdivacky unsigned QOpcodes1[] = { ARM::VLD3q8b, ARM::VLD3q16b, ARM::VLD3q32b }; 1871202375Srdivacky return SelectVLD(N, 3, DOpcodes, QOpcodes0, QOpcodes1); 1872198090Srdivacky } 1873198090Srdivacky 1874198090Srdivacky case Intrinsic::arm_neon_vld4: { 1875198090Srdivacky unsigned DOpcodes[] = { ARM::VLD4d8, ARM::VLD4d16, 1876198090Srdivacky ARM::VLD4d32, ARM::VLD4d64 }; 1877198090Srdivacky unsigned QOpcodes0[] = { ARM::VLD4q8a, ARM::VLD4q16a, ARM::VLD4q32a }; 1878198090Srdivacky unsigned QOpcodes1[] = { ARM::VLD4q8b, ARM::VLD4q16b, ARM::VLD4q32b }; 1879202375Srdivacky return SelectVLD(N, 4, DOpcodes, QOpcodes0, QOpcodes1); 1880198090Srdivacky } 1881198090Srdivacky 1882198090Srdivacky case Intrinsic::arm_neon_vld2lane: { 1883198090Srdivacky unsigned DOpcodes[] = { ARM::VLD2LNd8, ARM::VLD2LNd16, ARM::VLD2LNd32 }; 1884198090Srdivacky unsigned QOpcodes0[] = { ARM::VLD2LNq16a, ARM::VLD2LNq32a }; 1885198090Srdivacky unsigned QOpcodes1[] = { ARM::VLD2LNq16b, ARM::VLD2LNq32b }; 1886202375Srdivacky return SelectVLDSTLane(N, true, 2, DOpcodes, QOpcodes0, QOpcodes1); 1887198090Srdivacky } 1888198090Srdivacky 1889198090Srdivacky case Intrinsic::arm_neon_vld3lane: { 1890198090Srdivacky unsigned DOpcodes[] = { ARM::VLD3LNd8, ARM::VLD3LNd16, ARM::VLD3LNd32 }; 1891198090Srdivacky unsigned QOpcodes0[] = { ARM::VLD3LNq16a, ARM::VLD3LNq32a }; 1892198090Srdivacky unsigned QOpcodes1[] = { ARM::VLD3LNq16b, ARM::VLD3LNq32b }; 1893202375Srdivacky return SelectVLDSTLane(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1); 1894198090Srdivacky } 1895198090Srdivacky 1896198090Srdivacky case Intrinsic::arm_neon_vld4lane: { 1897198090Srdivacky unsigned DOpcodes[] = { ARM::VLD4LNd8, ARM::VLD4LNd16, ARM::VLD4LNd32 }; 1898198090Srdivacky unsigned QOpcodes0[] = { ARM::VLD4LNq16a, ARM::VLD4LNq32a }; 1899198090Srdivacky unsigned QOpcodes1[] = { ARM::VLD4LNq16b, ARM::VLD4LNq32b }; 1900202375Srdivacky return SelectVLDSTLane(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1); 1901198090Srdivacky } 1902198090Srdivacky 1903198090Srdivacky case Intrinsic::arm_neon_vst2: { 1904198113Srdivacky unsigned DOpcodes[] = { ARM::VST2d8, ARM::VST2d16, 1905198113Srdivacky ARM::VST2d32, ARM::VST2d64 }; 1906198113Srdivacky unsigned QOpcodes[] = { ARM::VST2q8, ARM::VST2q16, ARM::VST2q32 }; 1907202375Srdivacky return SelectVST(N, 2, DOpcodes, QOpcodes, 0); 1908198090Srdivacky } 1909194710Sed 1910198090Srdivacky case Intrinsic::arm_neon_vst3: { 1911198113Srdivacky unsigned DOpcodes[] = { ARM::VST3d8, ARM::VST3d16, 1912198113Srdivacky ARM::VST3d32, ARM::VST3d64 }; 1913198113Srdivacky unsigned QOpcodes0[] = { ARM::VST3q8a, ARM::VST3q16a, ARM::VST3q32a }; 1914198113Srdivacky unsigned QOpcodes1[] = { ARM::VST3q8b, ARM::VST3q16b, ARM::VST3q32b }; 1915202375Srdivacky return SelectVST(N, 3, DOpcodes, QOpcodes0, QOpcodes1); 1916194710Sed } 1917194710Sed 1918198090Srdivacky case Intrinsic::arm_neon_vst4: { 1919198113Srdivacky unsigned DOpcodes[] = { ARM::VST4d8, ARM::VST4d16, 1920198113Srdivacky ARM::VST4d32, ARM::VST4d64 }; 1921198113Srdivacky unsigned QOpcodes0[] = { ARM::VST4q8a, ARM::VST4q16a, ARM::VST4q32a }; 1922198113Srdivacky unsigned QOpcodes1[] = { ARM::VST4q8b, ARM::VST4q16b, ARM::VST4q32b }; 1923202375Srdivacky return SelectVST(N, 4, DOpcodes, QOpcodes0, QOpcodes1); 1924198090Srdivacky } 1925198090Srdivacky 1926198090Srdivacky case Intrinsic::arm_neon_vst2lane: { 1927198090Srdivacky unsigned DOpcodes[] = { ARM::VST2LNd8, ARM::VST2LNd16, ARM::VST2LNd32 }; 1928198090Srdivacky unsigned QOpcodes0[] = { ARM::VST2LNq16a, ARM::VST2LNq32a }; 1929198090Srdivacky unsigned QOpcodes1[] = { ARM::VST2LNq16b, ARM::VST2LNq32b }; 1930202375Srdivacky return SelectVLDSTLane(N, false, 2, DOpcodes, QOpcodes0, QOpcodes1); 1931198090Srdivacky } 1932198090Srdivacky 1933198090Srdivacky case Intrinsic::arm_neon_vst3lane: { 1934198090Srdivacky unsigned DOpcodes[] = { ARM::VST3LNd8, ARM::VST3LNd16, ARM::VST3LNd32 }; 1935198090Srdivacky unsigned QOpcodes0[] = { ARM::VST3LNq16a, ARM::VST3LNq32a }; 1936198090Srdivacky unsigned QOpcodes1[] = { ARM::VST3LNq16b, ARM::VST3LNq32b }; 1937202375Srdivacky return SelectVLDSTLane(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1); 1938198090Srdivacky } 1939198090Srdivacky 1940198090Srdivacky case Intrinsic::arm_neon_vst4lane: { 1941198090Srdivacky unsigned DOpcodes[] = { ARM::VST4LNd8, ARM::VST4LNd16, ARM::VST4LNd32 }; 1942198090Srdivacky unsigned QOpcodes0[] = { ARM::VST4LNq16a, ARM::VST4LNq32a }; 1943198090Srdivacky unsigned QOpcodes1[] = { ARM::VST4LNq16b, ARM::VST4LNq32b }; 1944202375Srdivacky return SelectVLDSTLane(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1); 1945198090Srdivacky } 1946198090Srdivacky } 1947194710Sed } 1948194710Sed } 1949194710Sed 1950202375Srdivacky return SelectCode(N); 1951193323Sed} 1952193323Sed 1953193323Sedbool ARMDAGToDAGISel:: 1954193323SedSelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, 1955193323Sed std::vector<SDValue> &OutOps) { 1956193323Sed assert(ConstraintCode == 'm' && "unexpected asm memory constraint"); 1957198090Srdivacky // Require the address to be in a register. That is safe for all ARM 1958198090Srdivacky // variants and it is hard to do anything much smarter without knowing 1959198090Srdivacky // how the operand is used. 1960198090Srdivacky OutOps.push_back(Op); 1961193323Sed return false; 1962193323Sed} 1963193323Sed 1964193323Sed/// createARMISelDag - This pass converts a legalized DAG into a 1965193323Sed/// ARM-specific DAG, ready for instruction scheduling. 1966193323Sed/// 1967198090SrdivackyFunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM, 1968198090Srdivacky CodeGenOpt::Level OptLevel) { 1969198090Srdivacky return new ARMDAGToDAGISel(TM, OptLevel); 1970193323Sed} 1971