ARMISelDAGToDAG.cpp revision 205407
1193323Sed//===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file defines an instruction selector for the ARM target. 11193323Sed// 12193323Sed//===----------------------------------------------------------------------===// 13193323Sed 14193323Sed#include "ARM.h" 15193323Sed#include "ARMAddressingModes.h" 16193323Sed#include "ARMISelLowering.h" 17193323Sed#include "ARMTargetMachine.h" 18193323Sed#include "llvm/CallingConv.h" 19193323Sed#include "llvm/Constants.h" 20193323Sed#include "llvm/DerivedTypes.h" 21193323Sed#include "llvm/Function.h" 22193323Sed#include "llvm/Intrinsics.h" 23198090Srdivacky#include "llvm/LLVMContext.h" 24193323Sed#include "llvm/CodeGen/MachineFrameInfo.h" 25193323Sed#include "llvm/CodeGen/MachineFunction.h" 26193323Sed#include "llvm/CodeGen/MachineInstrBuilder.h" 27193323Sed#include "llvm/CodeGen/SelectionDAG.h" 28193323Sed#include "llvm/CodeGen/SelectionDAGISel.h" 29193323Sed#include "llvm/Target/TargetLowering.h" 30193323Sed#include "llvm/Target/TargetOptions.h" 31193323Sed#include "llvm/Support/Compiler.h" 32193323Sed#include "llvm/Support/Debug.h" 33198090Srdivacky#include "llvm/Support/ErrorHandling.h" 34198090Srdivacky#include "llvm/Support/raw_ostream.h" 35198090Srdivacky 36193323Sedusing namespace llvm; 37193323Sed 38193323Sed//===--------------------------------------------------------------------===// 39193323Sed/// ARMDAGToDAGISel - ARM specific code to select ARM machine 40193323Sed/// instructions for SelectionDAG operations. 41193323Sed/// 42193323Sednamespace { 43193323Sedclass ARMDAGToDAGISel : public SelectionDAGISel { 44195098Sed ARMBaseTargetMachine &TM; 45193323Sed 46193323Sed /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can 47193323Sed /// make the right decision when generating code for different targets. 48193323Sed const ARMSubtarget *Subtarget; 49193323Sed 50193323Sedpublic: 51198090Srdivacky explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm, 52198090Srdivacky CodeGenOpt::Level OptLevel) 53198090Srdivacky : SelectionDAGISel(tm, OptLevel), TM(tm), 54193323Sed Subtarget(&TM.getSubtarget<ARMSubtarget>()) { 55193323Sed } 56193323Sed 57193323Sed virtual const char *getPassName() const { 58193323Sed return "ARM Instruction Selection"; 59194612Sed } 60194612Sed 61198090Srdivacky /// getI32Imm - Return a target constant of type i32 with the specified 62198090Srdivacky /// value. 63194612Sed inline SDValue getI32Imm(unsigned Imm) { 64194612Sed return CurDAG->getTargetConstant(Imm, MVT::i32); 65194612Sed } 66194612Sed 67202375Srdivacky SDNode *Select(SDNode *N); 68203954Srdivacky 69202375Srdivacky bool SelectShifterOperandReg(SDNode *Op, SDValue N, SDValue &A, 70195340Sed SDValue &B, SDValue &C); 71202375Srdivacky bool SelectAddrMode2(SDNode *Op, SDValue N, SDValue &Base, 72193323Sed SDValue &Offset, SDValue &Opc); 73202375Srdivacky bool SelectAddrMode2Offset(SDNode *Op, SDValue N, 74193323Sed SDValue &Offset, SDValue &Opc); 75202375Srdivacky bool SelectAddrMode3(SDNode *Op, SDValue N, SDValue &Base, 76193323Sed SDValue &Offset, SDValue &Opc); 77202375Srdivacky bool SelectAddrMode3Offset(SDNode *Op, SDValue N, 78193323Sed SDValue &Offset, SDValue &Opc); 79202375Srdivacky bool SelectAddrMode4(SDNode *Op, SDValue N, SDValue &Addr, 80198090Srdivacky SDValue &Mode); 81202375Srdivacky bool SelectAddrMode5(SDNode *Op, SDValue N, SDValue &Base, 82193323Sed SDValue &Offset); 83205407Srdivacky bool SelectAddrMode6(SDNode *Op, SDValue N, SDValue &Addr, SDValue &Align); 84193323Sed 85202375Srdivacky bool SelectAddrModePC(SDNode *Op, SDValue N, SDValue &Offset, 86195340Sed SDValue &Label); 87193323Sed 88202375Srdivacky bool SelectThumbAddrModeRR(SDNode *Op, SDValue N, SDValue &Base, 89193323Sed SDValue &Offset); 90202375Srdivacky bool SelectThumbAddrModeRI5(SDNode *Op, SDValue N, unsigned Scale, 91193323Sed SDValue &Base, SDValue &OffImm, 92193323Sed SDValue &Offset); 93202375Srdivacky bool SelectThumbAddrModeS1(SDNode *Op, SDValue N, SDValue &Base, 94193323Sed SDValue &OffImm, SDValue &Offset); 95202375Srdivacky bool SelectThumbAddrModeS2(SDNode *Op, SDValue N, SDValue &Base, 96193323Sed SDValue &OffImm, SDValue &Offset); 97202375Srdivacky bool SelectThumbAddrModeS4(SDNode *Op, SDValue N, SDValue &Base, 98193323Sed SDValue &OffImm, SDValue &Offset); 99202375Srdivacky bool SelectThumbAddrModeSP(SDNode *Op, SDValue N, SDValue &Base, 100193323Sed SDValue &OffImm); 101193323Sed 102202375Srdivacky bool SelectT2ShifterOperandReg(SDNode *Op, SDValue N, 103195098Sed SDValue &BaseReg, SDValue &Opc); 104202375Srdivacky bool SelectT2AddrModeImm12(SDNode *Op, SDValue N, SDValue &Base, 105195340Sed SDValue &OffImm); 106202375Srdivacky bool SelectT2AddrModeImm8(SDNode *Op, SDValue N, SDValue &Base, 107195340Sed SDValue &OffImm); 108202375Srdivacky bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N, 109195340Sed SDValue &OffImm); 110202375Srdivacky bool SelectT2AddrModeImm8s4(SDNode *Op, SDValue N, SDValue &Base, 111195340Sed SDValue &OffImm); 112202375Srdivacky bool SelectT2AddrModeSoReg(SDNode *Op, SDValue N, SDValue &Base, 113195340Sed SDValue &OffReg, SDValue &ShImm); 114195340Sed 115193323Sed // Include the pieces autogenerated from the target description. 116193323Sed#include "ARMGenDAGISel.inc" 117193323Sed 118193323Sedprivate: 119195340Sed /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for 120195340Sed /// ARM. 121202375Srdivacky SDNode *SelectARMIndexedLoad(SDNode *N); 122202375Srdivacky SDNode *SelectT2IndexedLoad(SDNode *N); 123195340Sed 124198090Srdivacky /// SelectDYN_ALLOC - Select dynamic alloc for Thumb. 125202375Srdivacky SDNode *SelectDYN_ALLOC(SDNode *N); 126195340Sed 127198090Srdivacky /// SelectVLD - Select NEON load intrinsics. NumVecs should 128198090Srdivacky /// be 2, 3 or 4. The opcode arrays specify the instructions used for 129198090Srdivacky /// loads of D registers and even subregs and odd subregs of Q registers. 130198090Srdivacky /// For NumVecs == 2, QOpcodes1 is not used. 131202375Srdivacky SDNode *SelectVLD(SDNode *N, unsigned NumVecs, unsigned *DOpcodes, 132198090Srdivacky unsigned *QOpcodes0, unsigned *QOpcodes1); 133198090Srdivacky 134198113Srdivacky /// SelectVST - Select NEON store intrinsics. NumVecs should 135198113Srdivacky /// be 2, 3 or 4. The opcode arrays specify the instructions used for 136198113Srdivacky /// stores of D registers and even subregs and odd subregs of Q registers. 137198113Srdivacky /// For NumVecs == 2, QOpcodes1 is not used. 138202375Srdivacky SDNode *SelectVST(SDNode *N, unsigned NumVecs, unsigned *DOpcodes, 139198113Srdivacky unsigned *QOpcodes0, unsigned *QOpcodes1); 140198113Srdivacky 141198090Srdivacky /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should 142198090Srdivacky /// be 2, 3 or 4. The opcode arrays specify the instructions used for 143198090Srdivacky /// load/store of D registers and even subregs and odd subregs of Q registers. 144202375Srdivacky SDNode *SelectVLDSTLane(SDNode *N, bool IsLoad, unsigned NumVecs, 145198090Srdivacky unsigned *DOpcodes, unsigned *QOpcodes0, 146198090Srdivacky unsigned *QOpcodes1); 147198090Srdivacky 148198090Srdivacky /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM. 149202375Srdivacky SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, unsigned Opc); 150198090Srdivacky 151199989Srdivacky /// SelectCMOVOp - Select CMOV instructions for ARM. 152202375Srdivacky SDNode *SelectCMOVOp(SDNode *N); 153202375Srdivacky SDNode *SelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 154199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 155199989Srdivacky SDValue InFlag); 156202375Srdivacky SDNode *SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 157199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 158199989Srdivacky SDValue InFlag); 159202375Srdivacky SDNode *SelectT2CMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 160199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 161199989Srdivacky SDValue InFlag); 162202375Srdivacky SDNode *SelectARMCMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 163199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 164199989Srdivacky SDValue InFlag); 165199989Srdivacky 166195340Sed /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for 167195340Sed /// inline asm expressions. 168195340Sed virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, 169195340Sed char ConstraintCode, 170195340Sed std::vector<SDValue> &OutOps); 171198090Srdivacky 172198090Srdivacky /// PairDRegs - Insert a pair of double registers into an implicit def to 173198090Srdivacky /// form a quad register. 174198090Srdivacky SDNode *PairDRegs(EVT VT, SDValue V0, SDValue V1); 175193323Sed}; 176193323Sed} 177193323Sed 178198090Srdivacky/// isInt32Immediate - This method tests to see if the node is a 32-bit constant 179198090Srdivacky/// operand. If so Imm will receive the 32-bit value. 180198090Srdivackystatic bool isInt32Immediate(SDNode *N, unsigned &Imm) { 181198090Srdivacky if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) { 182198090Srdivacky Imm = cast<ConstantSDNode>(N)->getZExtValue(); 183198090Srdivacky return true; 184198090Srdivacky } 185198090Srdivacky return false; 186198090Srdivacky} 187198090Srdivacky 188198090Srdivacky// isInt32Immediate - This method tests to see if a constant operand. 189198090Srdivacky// If so Imm will receive the 32 bit value. 190198090Srdivackystatic bool isInt32Immediate(SDValue N, unsigned &Imm) { 191198090Srdivacky return isInt32Immediate(N.getNode(), Imm); 192198090Srdivacky} 193198090Srdivacky 194198090Srdivacky// isOpcWithIntImmediate - This method tests to see if the node is a specific 195198090Srdivacky// opcode and that it has a immediate integer right operand. 196198090Srdivacky// If so Imm will receive the 32 bit value. 197198090Srdivackystatic bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) { 198198090Srdivacky return N->getOpcode() == Opc && 199198090Srdivacky isInt32Immediate(N->getOperand(1).getNode(), Imm); 200198090Srdivacky} 201198090Srdivacky 202198090Srdivacky 203202375Srdivackybool ARMDAGToDAGISel::SelectShifterOperandReg(SDNode *Op, 204195340Sed SDValue N, 205195340Sed SDValue &BaseReg, 206195340Sed SDValue &ShReg, 207195340Sed SDValue &Opc) { 208195340Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 209195340Sed 210195340Sed // Don't match base register only case. That is matched to a separate 211195340Sed // lower complexity pattern with explicit register operand. 212195340Sed if (ShOpcVal == ARM_AM::no_shift) return false; 213198090Srdivacky 214195340Sed BaseReg = N.getOperand(0); 215195340Sed unsigned ShImmVal = 0; 216195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 217195340Sed ShReg = CurDAG->getRegister(0, MVT::i32); 218195340Sed ShImmVal = RHS->getZExtValue() & 31; 219195340Sed } else { 220195340Sed ShReg = N.getOperand(1); 221195340Sed } 222195340Sed Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), 223195340Sed MVT::i32); 224195340Sed return true; 225195340Sed} 226195340Sed 227202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode2(SDNode *Op, SDValue N, 228193323Sed SDValue &Base, SDValue &Offset, 229193323Sed SDValue &Opc) { 230193323Sed if (N.getOpcode() == ISD::MUL) { 231193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 232193323Sed // X * [3,5,9] -> X + X * [2,4,8] etc. 233193323Sed int RHSC = (int)RHS->getZExtValue(); 234193323Sed if (RHSC & 1) { 235193323Sed RHSC = RHSC & ~1; 236193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 237193323Sed if (RHSC < 0) { 238193323Sed AddSub = ARM_AM::sub; 239193323Sed RHSC = - RHSC; 240193323Sed } 241193323Sed if (isPowerOf2_32(RHSC)) { 242193323Sed unsigned ShAmt = Log2_32(RHSC); 243193323Sed Base = Offset = N.getOperand(0); 244193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, 245193323Sed ARM_AM::lsl), 246193323Sed MVT::i32); 247193323Sed return true; 248193323Sed } 249193323Sed } 250193323Sed } 251193323Sed } 252193323Sed 253193323Sed if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) { 254193323Sed Base = N; 255193323Sed if (N.getOpcode() == ISD::FrameIndex) { 256193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 257193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 258199989Srdivacky } else if (N.getOpcode() == ARMISD::Wrapper && 259199989Srdivacky !(Subtarget->useMovt() && 260199989Srdivacky N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { 261193323Sed Base = N.getOperand(0); 262193323Sed } 263193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 264193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, 265193323Sed ARM_AM::no_shift), 266193323Sed MVT::i32); 267193323Sed return true; 268193323Sed } 269198090Srdivacky 270193323Sed // Match simple R +/- imm12 operands. 271193323Sed if (N.getOpcode() == ISD::ADD) 272193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 273193323Sed int RHSC = (int)RHS->getZExtValue(); 274193323Sed if ((RHSC >= 0 && RHSC < 0x1000) || 275193323Sed (RHSC < 0 && RHSC > -0x1000)) { // 12 bits. 276193323Sed Base = N.getOperand(0); 277193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 278193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 279193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 280193323Sed } 281193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 282193323Sed 283193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 284193323Sed if (RHSC < 0) { 285193323Sed AddSub = ARM_AM::sub; 286193323Sed RHSC = - RHSC; 287193323Sed } 288193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC, 289193323Sed ARM_AM::no_shift), 290193323Sed MVT::i32); 291193323Sed return true; 292193323Sed } 293193323Sed } 294198090Srdivacky 295198892Srdivacky // Otherwise this is R +/- [possibly shifted] R. 296193323Sed ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::ADD ? ARM_AM::add:ARM_AM::sub; 297193323Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1)); 298193323Sed unsigned ShAmt = 0; 299198090Srdivacky 300193323Sed Base = N.getOperand(0); 301193323Sed Offset = N.getOperand(1); 302198090Srdivacky 303193323Sed if (ShOpcVal != ARM_AM::no_shift) { 304193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 305193323Sed // it. 306193323Sed if (ConstantSDNode *Sh = 307193323Sed dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) { 308193323Sed ShAmt = Sh->getZExtValue(); 309193323Sed Offset = N.getOperand(1).getOperand(0); 310193323Sed } else { 311193323Sed ShOpcVal = ARM_AM::no_shift; 312193323Sed } 313193323Sed } 314198090Srdivacky 315193323Sed // Try matching (R shl C) + (R). 316193323Sed if (N.getOpcode() == ISD::ADD && ShOpcVal == ARM_AM::no_shift) { 317193323Sed ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0)); 318193323Sed if (ShOpcVal != ARM_AM::no_shift) { 319193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't 320193323Sed // fold it. 321193323Sed if (ConstantSDNode *Sh = 322193323Sed dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) { 323193323Sed ShAmt = Sh->getZExtValue(); 324193323Sed Offset = N.getOperand(0).getOperand(0); 325193323Sed Base = N.getOperand(1); 326193323Sed } else { 327193323Sed ShOpcVal = ARM_AM::no_shift; 328193323Sed } 329193323Sed } 330193323Sed } 331198090Srdivacky 332193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 333193323Sed MVT::i32); 334193323Sed return true; 335193323Sed} 336193323Sed 337202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode2Offset(SDNode *Op, SDValue N, 338193323Sed SDValue &Offset, SDValue &Opc) { 339202375Srdivacky unsigned Opcode = Op->getOpcode(); 340193323Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 341193323Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 342193323Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 343193323Sed ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 344193323Sed ? ARM_AM::add : ARM_AM::sub; 345193323Sed if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 346193323Sed int Val = (int)C->getZExtValue(); 347193323Sed if (Val >= 0 && Val < 0x1000) { // 12 bits. 348193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 349193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val, 350193323Sed ARM_AM::no_shift), 351193323Sed MVT::i32); 352193323Sed return true; 353193323Sed } 354193323Sed } 355193323Sed 356193323Sed Offset = N; 357193323Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 358193323Sed unsigned ShAmt = 0; 359193323Sed if (ShOpcVal != ARM_AM::no_shift) { 360193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 361193323Sed // it. 362193323Sed if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 363193323Sed ShAmt = Sh->getZExtValue(); 364193323Sed Offset = N.getOperand(0); 365193323Sed } else { 366193323Sed ShOpcVal = ARM_AM::no_shift; 367193323Sed } 368193323Sed } 369193323Sed 370193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 371193323Sed MVT::i32); 372193323Sed return true; 373193323Sed} 374193323Sed 375193323Sed 376202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode3(SDNode *Op, SDValue N, 377193323Sed SDValue &Base, SDValue &Offset, 378193323Sed SDValue &Opc) { 379193323Sed if (N.getOpcode() == ISD::SUB) { 380193323Sed // X - C is canonicalize to X + -C, no need to handle it here. 381193323Sed Base = N.getOperand(0); 382193323Sed Offset = N.getOperand(1); 383193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32); 384193323Sed return true; 385193323Sed } 386198090Srdivacky 387193323Sed if (N.getOpcode() != ISD::ADD) { 388193323Sed Base = N; 389193323Sed if (N.getOpcode() == ISD::FrameIndex) { 390193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 391193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 392193323Sed } 393193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 394193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32); 395193323Sed return true; 396193323Sed } 397198090Srdivacky 398193323Sed // If the RHS is +/- imm8, fold into addr mode. 399193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 400193323Sed int RHSC = (int)RHS->getZExtValue(); 401193323Sed if ((RHSC >= 0 && RHSC < 256) || 402193323Sed (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed. 403193323Sed Base = N.getOperand(0); 404193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 405193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 406193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 407193323Sed } 408193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 409193323Sed 410193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 411193323Sed if (RHSC < 0) { 412193323Sed AddSub = ARM_AM::sub; 413193323Sed RHSC = - RHSC; 414193323Sed } 415193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32); 416193323Sed return true; 417193323Sed } 418193323Sed } 419198090Srdivacky 420193323Sed Base = N.getOperand(0); 421193323Sed Offset = N.getOperand(1); 422193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32); 423193323Sed return true; 424193323Sed} 425193323Sed 426202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N, 427193323Sed SDValue &Offset, SDValue &Opc) { 428202375Srdivacky unsigned Opcode = Op->getOpcode(); 429193323Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 430193323Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 431193323Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 432193323Sed ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 433193323Sed ? ARM_AM::add : ARM_AM::sub; 434193323Sed if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 435193323Sed int Val = (int)C->getZExtValue(); 436193323Sed if (Val >= 0 && Val < 256) { 437193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 438193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32); 439193323Sed return true; 440193323Sed } 441193323Sed } 442193323Sed 443193323Sed Offset = N; 444193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32); 445193323Sed return true; 446193323Sed} 447193323Sed 448202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode4(SDNode *Op, SDValue N, 449198090Srdivacky SDValue &Addr, SDValue &Mode) { 450198090Srdivacky Addr = N; 451198090Srdivacky Mode = CurDAG->getTargetConstant(0, MVT::i32); 452198090Srdivacky return true; 453198090Srdivacky} 454193323Sed 455202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode5(SDNode *Op, SDValue N, 456193323Sed SDValue &Base, SDValue &Offset) { 457193323Sed if (N.getOpcode() != ISD::ADD) { 458193323Sed Base = N; 459193323Sed if (N.getOpcode() == ISD::FrameIndex) { 460193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 461193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 462199989Srdivacky } else if (N.getOpcode() == ARMISD::Wrapper && 463199989Srdivacky !(Subtarget->useMovt() && 464199989Srdivacky N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { 465193323Sed Base = N.getOperand(0); 466193323Sed } 467193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 468193323Sed MVT::i32); 469193323Sed return true; 470193323Sed } 471198090Srdivacky 472193323Sed // If the RHS is +/- imm8, fold into addr mode. 473193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 474193323Sed int RHSC = (int)RHS->getZExtValue(); 475193323Sed if ((RHSC & 3) == 0) { // The constant is implicitly multiplied by 4. 476193323Sed RHSC >>= 2; 477193323Sed if ((RHSC >= 0 && RHSC < 256) || 478193323Sed (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed. 479193323Sed Base = N.getOperand(0); 480193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 481193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 482193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 483193323Sed } 484193323Sed 485193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 486193323Sed if (RHSC < 0) { 487193323Sed AddSub = ARM_AM::sub; 488193323Sed RHSC = - RHSC; 489193323Sed } 490193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC), 491193323Sed MVT::i32); 492193323Sed return true; 493193323Sed } 494193323Sed } 495193323Sed } 496198090Srdivacky 497193323Sed Base = N; 498193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 499193323Sed MVT::i32); 500193323Sed return true; 501193323Sed} 502193323Sed 503202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Op, SDValue N, 504205407Srdivacky SDValue &Addr, SDValue &Align) { 505195340Sed Addr = N; 506199481Srdivacky // Default to no alignment. 507199481Srdivacky Align = CurDAG->getTargetConstant(0, MVT::i32); 508195340Sed return true; 509195340Sed} 510195340Sed 511202375Srdivackybool ARMDAGToDAGISel::SelectAddrModePC(SDNode *Op, SDValue N, 512198090Srdivacky SDValue &Offset, SDValue &Label) { 513193323Sed if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) { 514193323Sed Offset = N.getOperand(0); 515193323Sed SDValue N1 = N.getOperand(1); 516193323Sed Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(), 517193323Sed MVT::i32); 518193323Sed return true; 519193323Sed } 520193323Sed return false; 521193323Sed} 522193323Sed 523202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDNode *Op, SDValue N, 524193323Sed SDValue &Base, SDValue &Offset){ 525193323Sed // FIXME dl should come from the parent load or store, not the address 526202375Srdivacky DebugLoc dl = Op->getDebugLoc(); 527193323Sed if (N.getOpcode() != ISD::ADD) { 528198090Srdivacky ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N); 529198090Srdivacky if (!NC || NC->getZExtValue() != 0) 530198090Srdivacky return false; 531198090Srdivacky 532198090Srdivacky Base = Offset = N; 533193323Sed return true; 534193323Sed } 535193323Sed 536193323Sed Base = N.getOperand(0); 537193323Sed Offset = N.getOperand(1); 538193323Sed return true; 539193323Sed} 540193323Sed 541193323Sedbool 542202375SrdivackyARMDAGToDAGISel::SelectThumbAddrModeRI5(SDNode *Op, SDValue N, 543193323Sed unsigned Scale, SDValue &Base, 544193323Sed SDValue &OffImm, SDValue &Offset) { 545193323Sed if (Scale == 4) { 546193323Sed SDValue TmpBase, TmpOffImm; 547193323Sed if (SelectThumbAddrModeSP(Op, N, TmpBase, TmpOffImm)) 548193323Sed return false; // We want to select tLDRspi / tSTRspi instead. 549193323Sed if (N.getOpcode() == ARMISD::Wrapper && 550193323Sed N.getOperand(0).getOpcode() == ISD::TargetConstantPool) 551193323Sed return false; // We want to select tLDRpci instead. 552193323Sed } 553193323Sed 554193323Sed if (N.getOpcode() != ISD::ADD) { 555199989Srdivacky if (N.getOpcode() == ARMISD::Wrapper && 556199989Srdivacky !(Subtarget->useMovt() && 557199989Srdivacky N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { 558199989Srdivacky Base = N.getOperand(0); 559199989Srdivacky } else 560199989Srdivacky Base = N; 561199989Srdivacky 562193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 563193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 564193323Sed return true; 565193323Sed } 566193323Sed 567193323Sed // Thumb does not have [sp, r] address mode. 568193323Sed RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 569193323Sed RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1)); 570193323Sed if ((LHSR && LHSR->getReg() == ARM::SP) || 571193323Sed (RHSR && RHSR->getReg() == ARM::SP)) { 572193323Sed Base = N; 573193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 574193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 575193323Sed return true; 576193323Sed } 577193323Sed 578193323Sed // If the RHS is + imm5 * scale, fold into addr mode. 579193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 580193323Sed int RHSC = (int)RHS->getZExtValue(); 581193323Sed if ((RHSC & (Scale-1)) == 0) { // The constant is implicitly multiplied. 582193323Sed RHSC /= Scale; 583193323Sed if (RHSC >= 0 && RHSC < 32) { 584193323Sed Base = N.getOperand(0); 585193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 586193323Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 587193323Sed return true; 588193323Sed } 589193323Sed } 590193323Sed } 591193323Sed 592193323Sed Base = N.getOperand(0); 593193323Sed Offset = N.getOperand(1); 594193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 595193323Sed return true; 596193323Sed} 597193323Sed 598202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeS1(SDNode *Op, SDValue N, 599193323Sed SDValue &Base, SDValue &OffImm, 600193323Sed SDValue &Offset) { 601193323Sed return SelectThumbAddrModeRI5(Op, N, 1, Base, OffImm, Offset); 602193323Sed} 603193323Sed 604202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeS2(SDNode *Op, SDValue N, 605193323Sed SDValue &Base, SDValue &OffImm, 606193323Sed SDValue &Offset) { 607193323Sed return SelectThumbAddrModeRI5(Op, N, 2, Base, OffImm, Offset); 608193323Sed} 609193323Sed 610202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeS4(SDNode *Op, SDValue N, 611193323Sed SDValue &Base, SDValue &OffImm, 612193323Sed SDValue &Offset) { 613193323Sed return SelectThumbAddrModeRI5(Op, N, 4, Base, OffImm, Offset); 614193323Sed} 615193323Sed 616202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDNode *Op, SDValue N, 617193323Sed SDValue &Base, SDValue &OffImm) { 618193323Sed if (N.getOpcode() == ISD::FrameIndex) { 619193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 620193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 621193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 622193323Sed return true; 623193323Sed } 624193323Sed 625193323Sed if (N.getOpcode() != ISD::ADD) 626193323Sed return false; 627193323Sed 628193323Sed RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 629193323Sed if (N.getOperand(0).getOpcode() == ISD::FrameIndex || 630193323Sed (LHSR && LHSR->getReg() == ARM::SP)) { 631193323Sed // If the RHS is + imm8 * scale, fold into addr mode. 632193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 633193323Sed int RHSC = (int)RHS->getZExtValue(); 634193323Sed if ((RHSC & 3) == 0) { // The constant is implicitly multiplied. 635193323Sed RHSC >>= 2; 636193323Sed if (RHSC >= 0 && RHSC < 256) { 637193323Sed Base = N.getOperand(0); 638193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 639193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 640193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 641193323Sed } 642193323Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 643193323Sed return true; 644193323Sed } 645193323Sed } 646193323Sed } 647193323Sed } 648198090Srdivacky 649193323Sed return false; 650193323Sed} 651193323Sed 652202375Srdivackybool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDNode *Op, SDValue N, 653195098Sed SDValue &BaseReg, 654195098Sed SDValue &Opc) { 655195098Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 656195098Sed 657195098Sed // Don't match base register only case. That is matched to a separate 658195098Sed // lower complexity pattern with explicit register operand. 659195098Sed if (ShOpcVal == ARM_AM::no_shift) return false; 660195098Sed 661195098Sed BaseReg = N.getOperand(0); 662195098Sed unsigned ShImmVal = 0; 663195098Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 664195098Sed ShImmVal = RHS->getZExtValue() & 31; 665195098Sed Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal)); 666195098Sed return true; 667195098Sed } 668195098Sed 669195098Sed return false; 670195098Sed} 671195098Sed 672202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDNode *Op, SDValue N, 673195340Sed SDValue &Base, SDValue &OffImm) { 674195340Sed // Match simple R + imm12 operands. 675195340Sed 676198090Srdivacky // Base only. 677198090Srdivacky if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) { 678198090Srdivacky if (N.getOpcode() == ISD::FrameIndex) { 679198090Srdivacky // Match frame index... 680198090Srdivacky int FI = cast<FrameIndexSDNode>(N)->getIndex(); 681198090Srdivacky Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 682198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 683198090Srdivacky return true; 684199989Srdivacky } else if (N.getOpcode() == ARMISD::Wrapper && 685199989Srdivacky !(Subtarget->useMovt() && 686199989Srdivacky N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { 687198090Srdivacky Base = N.getOperand(0); 688198090Srdivacky if (Base.getOpcode() == ISD::TargetConstantPool) 689198090Srdivacky return false; // We want to select t2LDRpci instead. 690198090Srdivacky } else 691198090Srdivacky Base = N; 692198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 693198090Srdivacky return true; 694198090Srdivacky } 695198090Srdivacky 696195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 697198090Srdivacky if (SelectT2AddrModeImm8(Op, N, Base, OffImm)) 698198090Srdivacky // Let t2LDRi8 handle (R - imm8). 699198090Srdivacky return false; 700198090Srdivacky 701195340Sed int RHSC = (int)RHS->getZExtValue(); 702198090Srdivacky if (N.getOpcode() == ISD::SUB) 703198090Srdivacky RHSC = -RHSC; 704198090Srdivacky 705198090Srdivacky if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned) 706195340Sed Base = N.getOperand(0); 707198090Srdivacky if (Base.getOpcode() == ISD::FrameIndex) { 708198090Srdivacky int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 709198090Srdivacky Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 710198090Srdivacky } 711195340Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 712195340Sed return true; 713195340Sed } 714195340Sed } 715195340Sed 716198090Srdivacky // Base only. 717198090Srdivacky Base = N; 718198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 719198090Srdivacky return true; 720195340Sed} 721195340Sed 722202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDNode *Op, SDValue N, 723195340Sed SDValue &Base, SDValue &OffImm) { 724198090Srdivacky // Match simple R - imm8 operands. 725198090Srdivacky if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::SUB) { 726195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 727198090Srdivacky int RHSC = (int)RHS->getSExtValue(); 728198090Srdivacky if (N.getOpcode() == ISD::SUB) 729198090Srdivacky RHSC = -RHSC; 730198090Srdivacky 731198090Srdivacky if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative) 732198090Srdivacky Base = N.getOperand(0); 733198090Srdivacky if (Base.getOpcode() == ISD::FrameIndex) { 734198090Srdivacky int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 735198090Srdivacky Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 736198090Srdivacky } 737195340Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 738195340Sed return true; 739195340Sed } 740195340Sed } 741195340Sed } 742195340Sed 743195340Sed return false; 744195340Sed} 745195340Sed 746202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N, 747195340Sed SDValue &OffImm){ 748202375Srdivacky unsigned Opcode = Op->getOpcode(); 749195340Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 750195340Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 751195340Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 752195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N)) { 753195340Sed int RHSC = (int)RHS->getZExtValue(); 754195340Sed if (RHSC >= 0 && RHSC < 0x100) { // 8 bits. 755198090Srdivacky OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC)) 756195340Sed ? CurDAG->getTargetConstant(RHSC, MVT::i32) 757195340Sed : CurDAG->getTargetConstant(-RHSC, MVT::i32); 758195340Sed return true; 759195340Sed } 760195340Sed } 761195340Sed 762195340Sed return false; 763195340Sed} 764195340Sed 765202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm8s4(SDNode *Op, SDValue N, 766195340Sed SDValue &Base, SDValue &OffImm) { 767195340Sed if (N.getOpcode() == ISD::ADD) { 768195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 769195340Sed int RHSC = (int)RHS->getZExtValue(); 770198090Srdivacky if (((RHSC & 0x3) == 0) && 771198090Srdivacky ((RHSC >= 0 && RHSC < 0x400) || (RHSC < 0 && RHSC > -0x400))) { // 8 bits. 772195340Sed Base = N.getOperand(0); 773195340Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 774195340Sed return true; 775195340Sed } 776195340Sed } 777195340Sed } else if (N.getOpcode() == ISD::SUB) { 778195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 779195340Sed int RHSC = (int)RHS->getZExtValue(); 780195340Sed if (((RHSC & 0x3) == 0) && (RHSC >= 0 && RHSC < 0x400)) { // 8 bits. 781195340Sed Base = N.getOperand(0); 782195340Sed OffImm = CurDAG->getTargetConstant(-RHSC, MVT::i32); 783195340Sed return true; 784195340Sed } 785195340Sed } 786195340Sed } 787195340Sed 788195340Sed return false; 789195340Sed} 790195340Sed 791202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDNode *Op, SDValue N, 792195340Sed SDValue &Base, 793195340Sed SDValue &OffReg, SDValue &ShImm) { 794198090Srdivacky // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12. 795198090Srdivacky if (N.getOpcode() != ISD::ADD) 796198090Srdivacky return false; 797198090Srdivacky 798198090Srdivacky // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8. 799198090Srdivacky if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 800198090Srdivacky int RHSC = (int)RHS->getZExtValue(); 801198090Srdivacky if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned) 802198090Srdivacky return false; 803198090Srdivacky else if (RHSC < 0 && RHSC >= -255) // 8 bits 804198090Srdivacky return false; 805195340Sed } 806195340Sed 807195340Sed // Look for (R + R) or (R + (R << [1,2,3])). 808195340Sed unsigned ShAmt = 0; 809195340Sed Base = N.getOperand(0); 810195340Sed OffReg = N.getOperand(1); 811195340Sed 812195340Sed // Swap if it is ((R << c) + R). 813195340Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg); 814195340Sed if (ShOpcVal != ARM_AM::lsl) { 815195340Sed ShOpcVal = ARM_AM::getShiftOpcForNode(Base); 816195340Sed if (ShOpcVal == ARM_AM::lsl) 817195340Sed std::swap(Base, OffReg); 818198090Srdivacky } 819198090Srdivacky 820195340Sed if (ShOpcVal == ARM_AM::lsl) { 821195340Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 822195340Sed // it. 823195340Sed if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) { 824195340Sed ShAmt = Sh->getZExtValue(); 825195340Sed if (ShAmt >= 4) { 826195340Sed ShAmt = 0; 827195340Sed ShOpcVal = ARM_AM::no_shift; 828195340Sed } else 829195340Sed OffReg = OffReg.getOperand(0); 830195340Sed } else { 831195340Sed ShOpcVal = ARM_AM::no_shift; 832195340Sed } 833198090Srdivacky } 834198090Srdivacky 835195340Sed ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32); 836195340Sed 837195340Sed return true; 838195340Sed} 839195340Sed 840195340Sed//===--------------------------------------------------------------------===// 841195340Sed 842193323Sed/// getAL - Returns a ARMCC::AL immediate node. 843193323Sedstatic inline SDValue getAL(SelectionDAG *CurDAG) { 844193323Sed return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32); 845193323Sed} 846193323Sed 847202375SrdivackySDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) { 848202375Srdivacky LoadSDNode *LD = cast<LoadSDNode>(N); 849195340Sed ISD::MemIndexedMode AM = LD->getAddressingMode(); 850195340Sed if (AM == ISD::UNINDEXED) 851195340Sed return NULL; 852193323Sed 853198090Srdivacky EVT LoadedVT = LD->getMemoryVT(); 854195340Sed SDValue Offset, AMOpc; 855195340Sed bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 856195340Sed unsigned Opcode = 0; 857195340Sed bool Match = false; 858195340Sed if (LoadedVT == MVT::i32 && 859202375Srdivacky SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) { 860195340Sed Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST; 861195340Sed Match = true; 862195340Sed } else if (LoadedVT == MVT::i16 && 863202375Srdivacky SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) { 864195340Sed Match = true; 865195340Sed Opcode = (LD->getExtensionType() == ISD::SEXTLOAD) 866195340Sed ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST) 867195340Sed : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST); 868195340Sed } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) { 869195340Sed if (LD->getExtensionType() == ISD::SEXTLOAD) { 870202375Srdivacky if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) { 871195340Sed Match = true; 872195340Sed Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST; 873195340Sed } 874195340Sed } else { 875202375Srdivacky if (SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) { 876195340Sed Match = true; 877195340Sed Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST; 878195340Sed } 879195340Sed } 880195340Sed } 881195340Sed 882195340Sed if (Match) { 883195340Sed SDValue Chain = LD->getChain(); 884195340Sed SDValue Base = LD->getBasePtr(); 885195340Sed SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG), 886195340Sed CurDAG->getRegister(0, MVT::i32), Chain }; 887202375Srdivacky return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, MVT::i32, 888198090Srdivacky MVT::Other, Ops, 6); 889195340Sed } 890195340Sed 891195340Sed return NULL; 892195340Sed} 893195340Sed 894202375SrdivackySDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) { 895202375Srdivacky LoadSDNode *LD = cast<LoadSDNode>(N); 896195340Sed ISD::MemIndexedMode AM = LD->getAddressingMode(); 897195340Sed if (AM == ISD::UNINDEXED) 898195340Sed return NULL; 899195340Sed 900198090Srdivacky EVT LoadedVT = LD->getMemoryVT(); 901195340Sed bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD; 902195340Sed SDValue Offset; 903195340Sed bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 904195340Sed unsigned Opcode = 0; 905195340Sed bool Match = false; 906202375Srdivacky if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) { 907198090Srdivacky switch (LoadedVT.getSimpleVT().SimpleTy) { 908195340Sed case MVT::i32: 909195340Sed Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST; 910195340Sed break; 911195340Sed case MVT::i16: 912195340Sed if (isSExtLd) 913195340Sed Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST; 914195340Sed else 915195340Sed Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST; 916195340Sed break; 917195340Sed case MVT::i8: 918195340Sed case MVT::i1: 919195340Sed if (isSExtLd) 920195340Sed Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST; 921195340Sed else 922195340Sed Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST; 923195340Sed break; 924195340Sed default: 925195340Sed return NULL; 926195340Sed } 927195340Sed Match = true; 928195340Sed } 929195340Sed 930195340Sed if (Match) { 931195340Sed SDValue Chain = LD->getChain(); 932195340Sed SDValue Base = LD->getBasePtr(); 933195340Sed SDValue Ops[]= { Base, Offset, getAL(CurDAG), 934195340Sed CurDAG->getRegister(0, MVT::i32), Chain }; 935202375Srdivacky return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, MVT::i32, 936198090Srdivacky MVT::Other, Ops, 5); 937195340Sed } 938195340Sed 939195340Sed return NULL; 940195340Sed} 941195340Sed 942202375SrdivackySDNode *ARMDAGToDAGISel::SelectDYN_ALLOC(SDNode *N) { 943198090Srdivacky DebugLoc dl = N->getDebugLoc(); 944202375Srdivacky EVT VT = N->getValueType(0); 945202375Srdivacky SDValue Chain = N->getOperand(0); 946202375Srdivacky SDValue Size = N->getOperand(1); 947202375Srdivacky SDValue Align = N->getOperand(2); 948198090Srdivacky SDValue SP = CurDAG->getRegister(ARM::SP, MVT::i32); 949198090Srdivacky int32_t AlignVal = cast<ConstantSDNode>(Align)->getSExtValue(); 950198090Srdivacky if (AlignVal < 0) 951198090Srdivacky // We need to align the stack. Use Thumb1 tAND which is the only thumb 952198090Srdivacky // instruction that can read and write SP. This matches to a pseudo 953198090Srdivacky // instruction that has a chain to ensure the result is written back to 954198090Srdivacky // the stack pointer. 955198090Srdivacky SP = SDValue(CurDAG->getMachineNode(ARM::tANDsp, dl, VT, SP, Align), 0); 956195340Sed 957198090Srdivacky bool isC = isa<ConstantSDNode>(Size); 958198090Srdivacky uint32_t C = isC ? cast<ConstantSDNode>(Size)->getZExtValue() : ~0UL; 959198090Srdivacky // Handle the most common case for both Thumb1 and Thumb2: 960198090Srdivacky // tSUBspi - immediate is between 0 ... 508 inclusive. 961198090Srdivacky if (C <= 508 && ((C & 3) == 0)) 962198090Srdivacky // FIXME: tSUBspi encode scale 4 implicitly. 963198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::tSUBspi_, VT, MVT::Other, SP, 964198090Srdivacky CurDAG->getTargetConstant(C/4, MVT::i32), 965198090Srdivacky Chain); 966198090Srdivacky 967198090Srdivacky if (Subtarget->isThumb1Only()) { 968198090Srdivacky // Use tADDspr since Thumb1 does not have a sub r, sp, r. ARMISelLowering 969198090Srdivacky // should have negated the size operand already. FIXME: We can't insert 970198090Srdivacky // new target independent node at this stage so we are forced to negate 971198090Srdivacky // it earlier. Is there a better solution? 972198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::tADDspr_, VT, MVT::Other, SP, Size, 973198090Srdivacky Chain); 974198090Srdivacky } else if (Subtarget->isThumb2()) { 975198090Srdivacky if (isC && Predicate_t2_so_imm(Size.getNode())) { 976198090Srdivacky // t2SUBrSPi 977198090Srdivacky SDValue Ops[] = { SP, CurDAG->getTargetConstant(C, MVT::i32), Chain }; 978198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPi_, VT, MVT::Other, Ops, 3); 979198090Srdivacky } else if (isC && Predicate_imm0_4095(Size.getNode())) { 980198090Srdivacky // t2SUBrSPi12 981198090Srdivacky SDValue Ops[] = { SP, CurDAG->getTargetConstant(C, MVT::i32), Chain }; 982198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPi12_, VT, MVT::Other, Ops, 3); 983198090Srdivacky } else { 984198090Srdivacky // t2SUBrSPs 985198090Srdivacky SDValue Ops[] = { SP, Size, 986198090Srdivacky getI32Imm(ARM_AM::getSORegOpc(ARM_AM::lsl,0)), Chain }; 987198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPs_, VT, MVT::Other, Ops, 4); 988198090Srdivacky } 989198090Srdivacky } 990198090Srdivacky 991198090Srdivacky // FIXME: Add ADD / SUB sp instructions for ARM. 992198090Srdivacky return 0; 993198090Srdivacky} 994198090Srdivacky 995198090Srdivacky/// PairDRegs - Insert a pair of double registers into an implicit def to 996198090Srdivacky/// form a quad register. 997198090SrdivackySDNode *ARMDAGToDAGISel::PairDRegs(EVT VT, SDValue V0, SDValue V1) { 998198090Srdivacky DebugLoc dl = V0.getNode()->getDebugLoc(); 999198090Srdivacky SDValue Undef = 1000203954Srdivacky SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0); 1001198090Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::DSUBREG_0, MVT::i32); 1002198090Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::DSUBREG_1, MVT::i32); 1003203954Srdivacky SDNode *Pair = CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, dl, 1004198090Srdivacky VT, Undef, V0, SubReg0); 1005203954Srdivacky return CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, dl, 1006198090Srdivacky VT, SDValue(Pair, 0), V1, SubReg1); 1007198090Srdivacky} 1008198090Srdivacky 1009198090Srdivacky/// GetNEONSubregVT - Given a type for a 128-bit NEON vector, return the type 1010198090Srdivacky/// for a 64-bit subregister of the vector. 1011198090Srdivackystatic EVT GetNEONSubregVT(EVT VT) { 1012198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1013198090Srdivacky default: llvm_unreachable("unhandled NEON type"); 1014198090Srdivacky case MVT::v16i8: return MVT::v8i8; 1015198090Srdivacky case MVT::v8i16: return MVT::v4i16; 1016198090Srdivacky case MVT::v4f32: return MVT::v2f32; 1017198090Srdivacky case MVT::v4i32: return MVT::v2i32; 1018198090Srdivacky case MVT::v2i64: return MVT::v1i64; 1019198090Srdivacky } 1020198090Srdivacky} 1021198090Srdivacky 1022202375SrdivackySDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, unsigned NumVecs, 1023198090Srdivacky unsigned *DOpcodes, unsigned *QOpcodes0, 1024198090Srdivacky unsigned *QOpcodes1) { 1025198090Srdivacky assert(NumVecs >=2 && NumVecs <= 4 && "VLD NumVecs out-of-range"); 1026198090Srdivacky DebugLoc dl = N->getDebugLoc(); 1027198090Srdivacky 1028205407Srdivacky SDValue MemAddr, Align; 1029205407Srdivacky if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, Align)) 1030198090Srdivacky return NULL; 1031198090Srdivacky 1032198090Srdivacky SDValue Chain = N->getOperand(0); 1033198090Srdivacky EVT VT = N->getValueType(0); 1034198090Srdivacky bool is64BitVector = VT.is64BitVector(); 1035198090Srdivacky 1036198090Srdivacky unsigned OpcodeIndex; 1037198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1038198090Srdivacky default: llvm_unreachable("unhandled vld type"); 1039198090Srdivacky // Double-register operations: 1040198090Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1041198090Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1042198090Srdivacky case MVT::v2f32: 1043198090Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1044198090Srdivacky case MVT::v1i64: OpcodeIndex = 3; break; 1045198090Srdivacky // Quad-register operations: 1046198090Srdivacky case MVT::v16i8: OpcodeIndex = 0; break; 1047198090Srdivacky case MVT::v8i16: OpcodeIndex = 1; break; 1048198090Srdivacky case MVT::v4f32: 1049198090Srdivacky case MVT::v4i32: OpcodeIndex = 2; break; 1050198090Srdivacky } 1051198090Srdivacky 1052199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1053205407Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1054198090Srdivacky if (is64BitVector) { 1055198090Srdivacky unsigned Opc = DOpcodes[OpcodeIndex]; 1056205407Srdivacky const SDValue Ops[] = { MemAddr, Align, Pred, Reg0, Chain }; 1057198090Srdivacky std::vector<EVT> ResTys(NumVecs, VT); 1058198090Srdivacky ResTys.push_back(MVT::Other); 1059205407Srdivacky return CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 5); 1060198090Srdivacky } 1061198090Srdivacky 1062198090Srdivacky EVT RegVT = GetNEONSubregVT(VT); 1063198090Srdivacky if (NumVecs == 2) { 1064198090Srdivacky // Quad registers are directly supported for VLD2, 1065198090Srdivacky // loading 2 pairs of D regs. 1066198090Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1067205407Srdivacky const SDValue Ops[] = { MemAddr, Align, Pred, Reg0, Chain }; 1068198090Srdivacky std::vector<EVT> ResTys(4, VT); 1069198090Srdivacky ResTys.push_back(MVT::Other); 1070205407Srdivacky SDNode *VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 5); 1071198090Srdivacky Chain = SDValue(VLd, 4); 1072198090Srdivacky 1073198090Srdivacky // Combine the even and odd subregs to produce the result. 1074198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1075198090Srdivacky SDNode *Q = PairDRegs(VT, SDValue(VLd, 2*Vec), SDValue(VLd, 2*Vec+1)); 1076198090Srdivacky ReplaceUses(SDValue(N, Vec), SDValue(Q, 0)); 1077198090Srdivacky } 1078198090Srdivacky } else { 1079198090Srdivacky // Otherwise, quad registers are loaded with two separate instructions, 1080198090Srdivacky // where one loads the even registers and the other loads the odd registers. 1081198090Srdivacky 1082198090Srdivacky std::vector<EVT> ResTys(NumVecs, RegVT); 1083198090Srdivacky ResTys.push_back(MemAddr.getValueType()); 1084198090Srdivacky ResTys.push_back(MVT::Other); 1085198090Srdivacky 1086198113Srdivacky // Load the even subregs. 1087198090Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1088205407Srdivacky const SDValue OpsA[] = { MemAddr, Align, Reg0, Pred, Reg0, Chain }; 1089205407Srdivacky SDNode *VLdA = CurDAG->getMachineNode(Opc, dl, ResTys, OpsA, 6); 1090198090Srdivacky Chain = SDValue(VLdA, NumVecs+1); 1091198090Srdivacky 1092198113Srdivacky // Load the odd subregs. 1093198090Srdivacky Opc = QOpcodes1[OpcodeIndex]; 1094205407Srdivacky const SDValue OpsB[] = { SDValue(VLdA, NumVecs), 1095205407Srdivacky Align, Reg0, Pred, Reg0, Chain }; 1096205407Srdivacky SDNode *VLdB = CurDAG->getMachineNode(Opc, dl, ResTys, OpsB, 6); 1097198090Srdivacky Chain = SDValue(VLdB, NumVecs+1); 1098198090Srdivacky 1099198090Srdivacky // Combine the even and odd subregs to produce the result. 1100198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1101198090Srdivacky SDNode *Q = PairDRegs(VT, SDValue(VLdA, Vec), SDValue(VLdB, Vec)); 1102198090Srdivacky ReplaceUses(SDValue(N, Vec), SDValue(Q, 0)); 1103198090Srdivacky } 1104198090Srdivacky } 1105198090Srdivacky ReplaceUses(SDValue(N, NumVecs), Chain); 1106198090Srdivacky return NULL; 1107198090Srdivacky} 1108198090Srdivacky 1109202375SrdivackySDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, unsigned NumVecs, 1110198113Srdivacky unsigned *DOpcodes, unsigned *QOpcodes0, 1111198113Srdivacky unsigned *QOpcodes1) { 1112198113Srdivacky assert(NumVecs >=2 && NumVecs <= 4 && "VST NumVecs out-of-range"); 1113198113Srdivacky DebugLoc dl = N->getDebugLoc(); 1114198113Srdivacky 1115205407Srdivacky SDValue MemAddr, Align; 1116205407Srdivacky if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, Align)) 1117198113Srdivacky return NULL; 1118198113Srdivacky 1119198113Srdivacky SDValue Chain = N->getOperand(0); 1120198113Srdivacky EVT VT = N->getOperand(3).getValueType(); 1121198113Srdivacky bool is64BitVector = VT.is64BitVector(); 1122198113Srdivacky 1123198113Srdivacky unsigned OpcodeIndex; 1124198113Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1125198113Srdivacky default: llvm_unreachable("unhandled vst type"); 1126198113Srdivacky // Double-register operations: 1127198113Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1128198113Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1129198113Srdivacky case MVT::v2f32: 1130198113Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1131198113Srdivacky case MVT::v1i64: OpcodeIndex = 3; break; 1132198113Srdivacky // Quad-register operations: 1133198113Srdivacky case MVT::v16i8: OpcodeIndex = 0; break; 1134198113Srdivacky case MVT::v8i16: OpcodeIndex = 1; break; 1135198113Srdivacky case MVT::v4f32: 1136198113Srdivacky case MVT::v4i32: OpcodeIndex = 2; break; 1137198113Srdivacky } 1138198113Srdivacky 1139199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1140205407Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1141199989Srdivacky 1142205407Srdivacky SmallVector<SDValue, 10> Ops; 1143198113Srdivacky Ops.push_back(MemAddr); 1144199481Srdivacky Ops.push_back(Align); 1145198113Srdivacky 1146198113Srdivacky if (is64BitVector) { 1147198113Srdivacky unsigned Opc = DOpcodes[OpcodeIndex]; 1148198113Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1149198113Srdivacky Ops.push_back(N->getOperand(Vec+3)); 1150199989Srdivacky Ops.push_back(Pred); 1151205407Srdivacky Ops.push_back(Reg0); // predicate register 1152198113Srdivacky Ops.push_back(Chain); 1153205407Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+5); 1154198113Srdivacky } 1155198113Srdivacky 1156198113Srdivacky EVT RegVT = GetNEONSubregVT(VT); 1157198113Srdivacky if (NumVecs == 2) { 1158198113Srdivacky // Quad registers are directly supported for VST2, 1159198113Srdivacky // storing 2 pairs of D regs. 1160198113Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1161198113Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1162198113Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT, 1163198113Srdivacky N->getOperand(Vec+3))); 1164198113Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT, 1165198113Srdivacky N->getOperand(Vec+3))); 1166198113Srdivacky } 1167199989Srdivacky Ops.push_back(Pred); 1168205407Srdivacky Ops.push_back(Reg0); // predicate register 1169198113Srdivacky Ops.push_back(Chain); 1170205407Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), 9); 1171198113Srdivacky } 1172198113Srdivacky 1173198113Srdivacky // Otherwise, quad registers are stored with two separate instructions, 1174198113Srdivacky // where one stores the even registers and the other stores the odd registers. 1175198113Srdivacky 1176205407Srdivacky Ops.push_back(Reg0); // post-access address offset 1177198113Srdivacky 1178198113Srdivacky // Store the even subregs. 1179198113Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1180198113Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT, 1181198113Srdivacky N->getOperand(Vec+3))); 1182199989Srdivacky Ops.push_back(Pred); 1183205407Srdivacky Ops.push_back(Reg0); // predicate register 1184198113Srdivacky Ops.push_back(Chain); 1185198113Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1186198113Srdivacky SDNode *VStA = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(), 1187205407Srdivacky MVT::Other, Ops.data(), NumVecs+6); 1188198113Srdivacky Chain = SDValue(VStA, 1); 1189198113Srdivacky 1190198113Srdivacky // Store the odd subregs. 1191198113Srdivacky Ops[0] = SDValue(VStA, 0); // MemAddr 1192198113Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1193205407Srdivacky Ops[Vec+3] = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT, 1194198113Srdivacky N->getOperand(Vec+3)); 1195205407Srdivacky Ops[NumVecs+5] = Chain; 1196198113Srdivacky Opc = QOpcodes1[OpcodeIndex]; 1197198113Srdivacky SDNode *VStB = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(), 1198205407Srdivacky MVT::Other, Ops.data(), NumVecs+6); 1199198113Srdivacky Chain = SDValue(VStB, 1); 1200198113Srdivacky ReplaceUses(SDValue(N, 0), Chain); 1201198113Srdivacky return NULL; 1202198113Srdivacky} 1203198113Srdivacky 1204202375SrdivackySDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, 1205198090Srdivacky unsigned NumVecs, unsigned *DOpcodes, 1206198090Srdivacky unsigned *QOpcodes0, 1207198090Srdivacky unsigned *QOpcodes1) { 1208198090Srdivacky assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range"); 1209198090Srdivacky DebugLoc dl = N->getDebugLoc(); 1210198090Srdivacky 1211205407Srdivacky SDValue MemAddr, Align; 1212205407Srdivacky if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, Align)) 1213198090Srdivacky return NULL; 1214198090Srdivacky 1215198090Srdivacky SDValue Chain = N->getOperand(0); 1216198090Srdivacky unsigned Lane = 1217198090Srdivacky cast<ConstantSDNode>(N->getOperand(NumVecs+3))->getZExtValue(); 1218198090Srdivacky EVT VT = IsLoad ? N->getValueType(0) : N->getOperand(3).getValueType(); 1219198090Srdivacky bool is64BitVector = VT.is64BitVector(); 1220198090Srdivacky 1221198090Srdivacky // Quad registers are handled by load/store of subregs. Find the subreg info. 1222198090Srdivacky unsigned NumElts = 0; 1223198090Srdivacky int SubregIdx = 0; 1224198090Srdivacky EVT RegVT = VT; 1225198090Srdivacky if (!is64BitVector) { 1226198090Srdivacky RegVT = GetNEONSubregVT(VT); 1227198090Srdivacky NumElts = RegVT.getVectorNumElements(); 1228198090Srdivacky SubregIdx = (Lane < NumElts) ? ARM::DSUBREG_0 : ARM::DSUBREG_1; 1229198090Srdivacky } 1230198090Srdivacky 1231198090Srdivacky unsigned OpcodeIndex; 1232198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1233198090Srdivacky default: llvm_unreachable("unhandled vld/vst lane type"); 1234198090Srdivacky // Double-register operations: 1235198090Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1236198090Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1237198090Srdivacky case MVT::v2f32: 1238198090Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1239198090Srdivacky // Quad-register operations: 1240198090Srdivacky case MVT::v8i16: OpcodeIndex = 0; break; 1241198090Srdivacky case MVT::v4f32: 1242198090Srdivacky case MVT::v4i32: OpcodeIndex = 1; break; 1243198090Srdivacky } 1244198090Srdivacky 1245199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1246205407Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1247199989Srdivacky 1248205407Srdivacky SmallVector<SDValue, 10> Ops; 1249198090Srdivacky Ops.push_back(MemAddr); 1250199481Srdivacky Ops.push_back(Align); 1251198090Srdivacky 1252198090Srdivacky unsigned Opc = 0; 1253198090Srdivacky if (is64BitVector) { 1254198090Srdivacky Opc = DOpcodes[OpcodeIndex]; 1255198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1256198090Srdivacky Ops.push_back(N->getOperand(Vec+3)); 1257198090Srdivacky } else { 1258198090Srdivacky // Check if this is loading the even or odd subreg of a Q register. 1259198090Srdivacky if (Lane < NumElts) { 1260198090Srdivacky Opc = QOpcodes0[OpcodeIndex]; 1261198090Srdivacky } else { 1262198090Srdivacky Lane -= NumElts; 1263198090Srdivacky Opc = QOpcodes1[OpcodeIndex]; 1264198090Srdivacky } 1265198090Srdivacky // Extract the subregs of the input vector. 1266198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1267198090Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT, 1268198090Srdivacky N->getOperand(Vec+3))); 1269198090Srdivacky } 1270198090Srdivacky Ops.push_back(getI32Imm(Lane)); 1271199989Srdivacky Ops.push_back(Pred); 1272205407Srdivacky Ops.push_back(Reg0); 1273198090Srdivacky Ops.push_back(Chain); 1274198090Srdivacky 1275198090Srdivacky if (!IsLoad) 1276205407Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+6); 1277198090Srdivacky 1278198090Srdivacky std::vector<EVT> ResTys(NumVecs, RegVT); 1279198090Srdivacky ResTys.push_back(MVT::Other); 1280198090Srdivacky SDNode *VLdLn = 1281205407Srdivacky CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), NumVecs+6); 1282198090Srdivacky // For a 64-bit vector load to D registers, nothing more needs to be done. 1283198090Srdivacky if (is64BitVector) 1284198090Srdivacky return VLdLn; 1285198090Srdivacky 1286198090Srdivacky // For 128-bit vectors, take the 64-bit results of the load and insert them 1287198090Srdivacky // as subregs into the result. 1288198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1289198090Srdivacky SDValue QuadVec = CurDAG->getTargetInsertSubreg(SubregIdx, dl, VT, 1290198090Srdivacky N->getOperand(Vec+3), 1291198090Srdivacky SDValue(VLdLn, Vec)); 1292198090Srdivacky ReplaceUses(SDValue(N, Vec), QuadVec); 1293198090Srdivacky } 1294198090Srdivacky 1295198090Srdivacky Chain = SDValue(VLdLn, NumVecs); 1296198090Srdivacky ReplaceUses(SDValue(N, NumVecs), Chain); 1297198090Srdivacky return NULL; 1298198090Srdivacky} 1299198090Srdivacky 1300202375SrdivackySDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N, 1301198090Srdivacky unsigned Opc) { 1302198090Srdivacky if (!Subtarget->hasV6T2Ops()) 1303198090Srdivacky return NULL; 1304198090Srdivacky 1305198090Srdivacky unsigned Shl_imm = 0; 1306202375Srdivacky if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) { 1307198090Srdivacky assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!"); 1308198090Srdivacky unsigned Srl_imm = 0; 1309202375Srdivacky if (isInt32Immediate(N->getOperand(1), Srl_imm)) { 1310198090Srdivacky assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); 1311198090Srdivacky unsigned Width = 32 - Srl_imm; 1312198090Srdivacky int LSB = Srl_imm - Shl_imm; 1313198396Srdivacky if (LSB < 0) 1314198090Srdivacky return NULL; 1315198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1316202375Srdivacky SDValue Ops[] = { N->getOperand(0).getOperand(0), 1317198090Srdivacky CurDAG->getTargetConstant(LSB, MVT::i32), 1318198090Srdivacky CurDAG->getTargetConstant(Width, MVT::i32), 1319198090Srdivacky getAL(CurDAG), Reg0 }; 1320202375Srdivacky return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); 1321198090Srdivacky } 1322198090Srdivacky } 1323198090Srdivacky return NULL; 1324198090Srdivacky} 1325198090Srdivacky 1326199989SrdivackySDNode *ARMDAGToDAGISel:: 1327202375SrdivackySelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 1328199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1329199989Srdivacky SDValue CPTmp0; 1330199989Srdivacky SDValue CPTmp1; 1331202375Srdivacky if (SelectT2ShifterOperandReg(N, TrueVal, CPTmp0, CPTmp1)) { 1332199989Srdivacky unsigned SOVal = cast<ConstantSDNode>(CPTmp1)->getZExtValue(); 1333199989Srdivacky unsigned SOShOp = ARM_AM::getSORegShOp(SOVal); 1334199989Srdivacky unsigned Opc = 0; 1335199989Srdivacky switch (SOShOp) { 1336199989Srdivacky case ARM_AM::lsl: Opc = ARM::t2MOVCClsl; break; 1337199989Srdivacky case ARM_AM::lsr: Opc = ARM::t2MOVCClsr; break; 1338199989Srdivacky case ARM_AM::asr: Opc = ARM::t2MOVCCasr; break; 1339199989Srdivacky case ARM_AM::ror: Opc = ARM::t2MOVCCror; break; 1340199989Srdivacky default: 1341199989Srdivacky llvm_unreachable("Unknown so_reg opcode!"); 1342199989Srdivacky break; 1343199989Srdivacky } 1344199989Srdivacky SDValue SOShImm = 1345199989Srdivacky CurDAG->getTargetConstant(ARM_AM::getSORegOffset(SOVal), MVT::i32); 1346199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1347199989Srdivacky SDValue Ops[] = { FalseVal, CPTmp0, SOShImm, CC, CCR, InFlag }; 1348202375Srdivacky return CurDAG->SelectNodeTo(N, Opc, MVT::i32,Ops, 6); 1349199989Srdivacky } 1350199989Srdivacky return 0; 1351199989Srdivacky} 1352199989Srdivacky 1353199989SrdivackySDNode *ARMDAGToDAGISel:: 1354202375SrdivackySelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 1355199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1356199989Srdivacky SDValue CPTmp0; 1357199989Srdivacky SDValue CPTmp1; 1358199989Srdivacky SDValue CPTmp2; 1359202375Srdivacky if (SelectShifterOperandReg(N, TrueVal, CPTmp0, CPTmp1, CPTmp2)) { 1360199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1361199989Srdivacky SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, InFlag }; 1362202375Srdivacky return CurDAG->SelectNodeTo(N, ARM::MOVCCs, MVT::i32, Ops, 7); 1363199989Srdivacky } 1364199989Srdivacky return 0; 1365199989Srdivacky} 1366199989Srdivacky 1367199989SrdivackySDNode *ARMDAGToDAGISel:: 1368202375SrdivackySelectT2CMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 1369199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1370199989Srdivacky ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal); 1371199989Srdivacky if (!T) 1372199989Srdivacky return 0; 1373199989Srdivacky 1374199989Srdivacky if (Predicate_t2_so_imm(TrueVal.getNode())) { 1375199989Srdivacky SDValue True = CurDAG->getTargetConstant(T->getZExtValue(), MVT::i32); 1376199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1377199989Srdivacky SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag }; 1378202375Srdivacky return CurDAG->SelectNodeTo(N, 1379199989Srdivacky ARM::t2MOVCCi, MVT::i32, Ops, 5); 1380199989Srdivacky } 1381199989Srdivacky return 0; 1382199989Srdivacky} 1383199989Srdivacky 1384199989SrdivackySDNode *ARMDAGToDAGISel:: 1385202375SrdivackySelectARMCMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 1386199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1387199989Srdivacky ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal); 1388199989Srdivacky if (!T) 1389199989Srdivacky return 0; 1390199989Srdivacky 1391199989Srdivacky if (Predicate_so_imm(TrueVal.getNode())) { 1392199989Srdivacky SDValue True = CurDAG->getTargetConstant(T->getZExtValue(), MVT::i32); 1393199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1394199989Srdivacky SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag }; 1395202375Srdivacky return CurDAG->SelectNodeTo(N, 1396199989Srdivacky ARM::MOVCCi, MVT::i32, Ops, 5); 1397199989Srdivacky } 1398199989Srdivacky return 0; 1399199989Srdivacky} 1400199989Srdivacky 1401202375SrdivackySDNode *ARMDAGToDAGISel::SelectCMOVOp(SDNode *N) { 1402202375Srdivacky EVT VT = N->getValueType(0); 1403202375Srdivacky SDValue FalseVal = N->getOperand(0); 1404202375Srdivacky SDValue TrueVal = N->getOperand(1); 1405202375Srdivacky SDValue CC = N->getOperand(2); 1406202375Srdivacky SDValue CCR = N->getOperand(3); 1407202375Srdivacky SDValue InFlag = N->getOperand(4); 1408199989Srdivacky assert(CC.getOpcode() == ISD::Constant); 1409199989Srdivacky assert(CCR.getOpcode() == ISD::Register); 1410199989Srdivacky ARMCC::CondCodes CCVal = 1411199989Srdivacky (ARMCC::CondCodes)cast<ConstantSDNode>(CC)->getZExtValue(); 1412199989Srdivacky 1413199989Srdivacky if (!Subtarget->isThumb1Only() && VT == MVT::i32) { 1414199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) 1415199989Srdivacky // Emits: (MOVCCs:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) 1416199989Srdivacky // Pattern complexity = 18 cost = 1 size = 0 1417199989Srdivacky SDValue CPTmp0; 1418199989Srdivacky SDValue CPTmp1; 1419199989Srdivacky SDValue CPTmp2; 1420199989Srdivacky if (Subtarget->isThumb()) { 1421202375Srdivacky SDNode *Res = SelectT2CMOVShiftOp(N, FalseVal, TrueVal, 1422199989Srdivacky CCVal, CCR, InFlag); 1423199989Srdivacky if (!Res) 1424202375Srdivacky Res = SelectT2CMOVShiftOp(N, TrueVal, FalseVal, 1425199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1426199989Srdivacky if (Res) 1427199989Srdivacky return Res; 1428199989Srdivacky } else { 1429202375Srdivacky SDNode *Res = SelectARMCMOVShiftOp(N, FalseVal, TrueVal, 1430199989Srdivacky CCVal, CCR, InFlag); 1431199989Srdivacky if (!Res) 1432202375Srdivacky Res = SelectARMCMOVShiftOp(N, TrueVal, FalseVal, 1433199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1434199989Srdivacky if (Res) 1435199989Srdivacky return Res; 1436199989Srdivacky } 1437199989Srdivacky 1438199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, 1439199989Srdivacky // (imm:i32)<<P:Predicate_so_imm>>:$true, 1440199989Srdivacky // (imm:i32):$cc) 1441199989Srdivacky // Emits: (MOVCCi:i32 GPR:i32:$false, 1442199989Srdivacky // (so_imm:i32 (imm:i32):$true), (imm:i32):$cc) 1443199989Srdivacky // Pattern complexity = 10 cost = 1 size = 0 1444199989Srdivacky if (Subtarget->isThumb()) { 1445202375Srdivacky SDNode *Res = SelectT2CMOVSoImmOp(N, FalseVal, TrueVal, 1446199989Srdivacky CCVal, CCR, InFlag); 1447199989Srdivacky if (!Res) 1448202375Srdivacky Res = SelectT2CMOVSoImmOp(N, TrueVal, FalseVal, 1449199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1450199989Srdivacky if (Res) 1451199989Srdivacky return Res; 1452199989Srdivacky } else { 1453202375Srdivacky SDNode *Res = SelectARMCMOVSoImmOp(N, FalseVal, TrueVal, 1454199989Srdivacky CCVal, CCR, InFlag); 1455199989Srdivacky if (!Res) 1456202375Srdivacky Res = SelectARMCMOVSoImmOp(N, TrueVal, FalseVal, 1457199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1458199989Srdivacky if (Res) 1459199989Srdivacky return Res; 1460199989Srdivacky } 1461199989Srdivacky } 1462199989Srdivacky 1463199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1464199989Srdivacky // Emits: (MOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1465199989Srdivacky // Pattern complexity = 6 cost = 1 size = 0 1466199989Srdivacky // 1467199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1468199989Srdivacky // Emits: (tMOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1469199989Srdivacky // Pattern complexity = 6 cost = 11 size = 0 1470199989Srdivacky // 1471199989Srdivacky // Also FCPYScc and FCPYDcc. 1472199989Srdivacky SDValue Tmp2 = CurDAG->getTargetConstant(CCVal, MVT::i32); 1473199989Srdivacky SDValue Ops[] = { FalseVal, TrueVal, Tmp2, CCR, InFlag }; 1474199989Srdivacky unsigned Opc = 0; 1475199989Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1476199989Srdivacky default: assert(false && "Illegal conditional move type!"); 1477199989Srdivacky break; 1478199989Srdivacky case MVT::i32: 1479199989Srdivacky Opc = Subtarget->isThumb() 1480199989Srdivacky ? (Subtarget->hasThumb2() ? ARM::t2MOVCCr : ARM::tMOVCCr_pseudo) 1481199989Srdivacky : ARM::MOVCCr; 1482199989Srdivacky break; 1483199989Srdivacky case MVT::f32: 1484199989Srdivacky Opc = ARM::VMOVScc; 1485199989Srdivacky break; 1486199989Srdivacky case MVT::f64: 1487199989Srdivacky Opc = ARM::VMOVDcc; 1488199989Srdivacky break; 1489199989Srdivacky } 1490202375Srdivacky return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5); 1491199989Srdivacky} 1492199989Srdivacky 1493202375SrdivackySDNode *ARMDAGToDAGISel::Select(SDNode *N) { 1494193323Sed DebugLoc dl = N->getDebugLoc(); 1495193323Sed 1496193323Sed if (N->isMachineOpcode()) 1497193323Sed return NULL; // Already selected. 1498193323Sed 1499193323Sed switch (N->getOpcode()) { 1500193323Sed default: break; 1501193323Sed case ISD::Constant: { 1502193323Sed unsigned Val = cast<ConstantSDNode>(N)->getZExtValue(); 1503193323Sed bool UseCP = true; 1504198090Srdivacky if (Subtarget->hasThumb2()) 1505198090Srdivacky // Thumb2-aware targets have the MOVT instruction, so all immediates can 1506198090Srdivacky // be done with MOV + MOVT, at worst. 1507198090Srdivacky UseCP = 0; 1508198090Srdivacky else { 1509198090Srdivacky if (Subtarget->isThumb()) { 1510194710Sed UseCP = (Val > 255 && // MOV 1511194710Sed ~Val > 255 && // MOV + MVN 1512194710Sed !ARM_AM::isThumbImmShiftedVal(Val)); // MOV + LSL 1513198090Srdivacky } else 1514198090Srdivacky UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV 1515198090Srdivacky ARM_AM::getSOImmVal(~Val) == -1 && // MVN 1516198090Srdivacky !ARM_AM::isSOImmTwoPartVal(Val)); // two instrs. 1517198090Srdivacky } 1518198090Srdivacky 1519193323Sed if (UseCP) { 1520193323Sed SDValue CPIdx = 1521198090Srdivacky CurDAG->getTargetConstantPool(ConstantInt::get( 1522198090Srdivacky Type::getInt32Ty(*CurDAG->getContext()), Val), 1523193323Sed TLI.getPointerTy()); 1524193323Sed 1525193323Sed SDNode *ResNode; 1526198090Srdivacky if (Subtarget->isThumb1Only()) { 1527199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1528198090Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1529198090Srdivacky SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() }; 1530198090Srdivacky ResNode = CurDAG->getMachineNode(ARM::tLDRcp, dl, MVT::i32, MVT::Other, 1531198090Srdivacky Ops, 4); 1532198090Srdivacky } else { 1533193323Sed SDValue Ops[] = { 1534198090Srdivacky CPIdx, 1535193323Sed CurDAG->getRegister(0, MVT::i32), 1536193323Sed CurDAG->getTargetConstant(0, MVT::i32), 1537193323Sed getAL(CurDAG), 1538193323Sed CurDAG->getRegister(0, MVT::i32), 1539193323Sed CurDAG->getEntryNode() 1540193323Sed }; 1541198090Srdivacky ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other, 1542198090Srdivacky Ops, 6); 1543193323Sed } 1544202375Srdivacky ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0)); 1545193323Sed return NULL; 1546193323Sed } 1547198090Srdivacky 1548193323Sed // Other cases are autogenerated. 1549193323Sed break; 1550193323Sed } 1551193323Sed case ISD::FrameIndex: { 1552193323Sed // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm. 1553193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 1554193323Sed SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 1555198090Srdivacky if (Subtarget->isThumb1Only()) { 1556193323Sed return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI, 1557193323Sed CurDAG->getTargetConstant(0, MVT::i32)); 1558193323Sed } else { 1559198090Srdivacky unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ? 1560198090Srdivacky ARM::t2ADDri : ARM::ADDri); 1561193323Sed SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32), 1562198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1563198090Srdivacky CurDAG->getRegister(0, MVT::i32) }; 1564198090Srdivacky return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); 1565193323Sed } 1566193323Sed } 1567198090Srdivacky case ARMISD::DYN_ALLOC: 1568202375Srdivacky return SelectDYN_ALLOC(N); 1569198090Srdivacky case ISD::SRL: 1570202375Srdivacky if (SDNode *I = SelectV6T2BitfieldExtractOp(N, 1571198090Srdivacky Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX)) 1572198090Srdivacky return I; 1573193323Sed break; 1574198090Srdivacky case ISD::SRA: 1575202375Srdivacky if (SDNode *I = SelectV6T2BitfieldExtractOp(N, 1576198090Srdivacky Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)) 1577198090Srdivacky return I; 1578198090Srdivacky break; 1579193323Sed case ISD::MUL: 1580198090Srdivacky if (Subtarget->isThumb1Only()) 1581193323Sed break; 1582202375Srdivacky if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) { 1583193323Sed unsigned RHSV = C->getZExtValue(); 1584193323Sed if (!RHSV) break; 1585193323Sed if (isPowerOf2_32(RHSV-1)) { // 2^n+1? 1586198090Srdivacky unsigned ShImm = Log2_32(RHSV-1); 1587198090Srdivacky if (ShImm >= 32) 1588198090Srdivacky break; 1589202375Srdivacky SDValue V = N->getOperand(0); 1590198090Srdivacky ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); 1591198090Srdivacky SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); 1592198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1593198090Srdivacky if (Subtarget->isThumb()) { 1594198090Srdivacky SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1595198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops, 6); 1596198090Srdivacky } else { 1597198090Srdivacky SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1598198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 7); 1599198090Srdivacky } 1600193323Sed } 1601193323Sed if (isPowerOf2_32(RHSV+1)) { // 2^n-1? 1602198090Srdivacky unsigned ShImm = Log2_32(RHSV+1); 1603198090Srdivacky if (ShImm >= 32) 1604198090Srdivacky break; 1605202375Srdivacky SDValue V = N->getOperand(0); 1606198090Srdivacky ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); 1607198090Srdivacky SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); 1608198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1609198090Srdivacky if (Subtarget->isThumb()) { 1610198090Srdivacky SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0 }; 1611198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops, 5); 1612198090Srdivacky } else { 1613198090Srdivacky SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1614198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 7); 1615198090Srdivacky } 1616193323Sed } 1617193323Sed } 1618193323Sed break; 1619198396Srdivacky case ISD::AND: { 1620198396Srdivacky // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits 1621198396Srdivacky // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits 1622198396Srdivacky // are entirely contributed by c2 and lower 16-bits are entirely contributed 1623198396Srdivacky // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)). 1624198396Srdivacky // Select it to: "movt x, ((c1 & 0xffff) >> 16) 1625202375Srdivacky EVT VT = N->getValueType(0); 1626198396Srdivacky if (VT != MVT::i32) 1627198396Srdivacky break; 1628198396Srdivacky unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2()) 1629198396Srdivacky ? ARM::t2MOVTi16 1630198396Srdivacky : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0); 1631198396Srdivacky if (!Opc) 1632198396Srdivacky break; 1633202375Srdivacky SDValue N0 = N->getOperand(0), N1 = N->getOperand(1); 1634198396Srdivacky ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); 1635198396Srdivacky if (!N1C) 1636198396Srdivacky break; 1637198396Srdivacky if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) { 1638198396Srdivacky SDValue N2 = N0.getOperand(1); 1639198396Srdivacky ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2); 1640198396Srdivacky if (!N2C) 1641198396Srdivacky break; 1642198396Srdivacky unsigned N1CVal = N1C->getZExtValue(); 1643198396Srdivacky unsigned N2CVal = N2C->getZExtValue(); 1644198396Srdivacky if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) && 1645198396Srdivacky (N1CVal & 0xffffU) == 0xffffU && 1646198396Srdivacky (N2CVal & 0xffffU) == 0x0U) { 1647198396Srdivacky SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16, 1648198396Srdivacky MVT::i32); 1649198396Srdivacky SDValue Ops[] = { N0.getOperand(0), Imm16, 1650198396Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; 1651198396Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, Ops, 4); 1652198396Srdivacky } 1653198396Srdivacky } 1654198396Srdivacky break; 1655198396Srdivacky } 1656199481Srdivacky case ARMISD::VMOVRRD: 1657199481Srdivacky return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32, 1658202375Srdivacky N->getOperand(0), getAL(CurDAG), 1659198090Srdivacky CurDAG->getRegister(0, MVT::i32)); 1660193323Sed case ISD::UMUL_LOHI: { 1661198090Srdivacky if (Subtarget->isThumb1Only()) 1662198090Srdivacky break; 1663198090Srdivacky if (Subtarget->isThumb()) { 1664202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 1665193323Sed getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1666193323Sed CurDAG->getRegister(0, MVT::i32) }; 1667198090Srdivacky return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops,4); 1668198090Srdivacky } else { 1669202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 1670198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1671198090Srdivacky CurDAG->getRegister(0, MVT::i32) }; 1672198090Srdivacky return CurDAG->getMachineNode(ARM::UMULL, dl, MVT::i32, MVT::i32, Ops, 5); 1673198090Srdivacky } 1674193323Sed } 1675193323Sed case ISD::SMUL_LOHI: { 1676198090Srdivacky if (Subtarget->isThumb1Only()) 1677198090Srdivacky break; 1678198090Srdivacky if (Subtarget->isThumb()) { 1679202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 1680198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; 1681198090Srdivacky return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops,4); 1682198090Srdivacky } else { 1683202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 1684193323Sed getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1685193323Sed CurDAG->getRegister(0, MVT::i32) }; 1686198090Srdivacky return CurDAG->getMachineNode(ARM::SMULL, dl, MVT::i32, MVT::i32, Ops, 5); 1687198090Srdivacky } 1688193323Sed } 1689193323Sed case ISD::LOAD: { 1690195340Sed SDNode *ResNode = 0; 1691198090Srdivacky if (Subtarget->isThumb() && Subtarget->hasThumb2()) 1692202375Srdivacky ResNode = SelectT2IndexedLoad(N); 1693195340Sed else 1694202375Srdivacky ResNode = SelectARMIndexedLoad(N); 1695195340Sed if (ResNode) 1696195340Sed return ResNode; 1697193323Sed // Other cases are autogenerated. 1698193323Sed break; 1699193323Sed } 1700193323Sed case ARMISD::BRCOND: { 1701193323Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 1702193323Sed // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc) 1703193323Sed // Pattern complexity = 6 cost = 1 size = 0 1704193323Sed 1705193323Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 1706193323Sed // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc) 1707193323Sed // Pattern complexity = 6 cost = 1 size = 0 1708193323Sed 1709195340Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 1710195340Sed // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc) 1711195340Sed // Pattern complexity = 6 cost = 1 size = 0 1712195340Sed 1713198090Srdivacky unsigned Opc = Subtarget->isThumb() ? 1714195340Sed ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc; 1715202375Srdivacky SDValue Chain = N->getOperand(0); 1716202375Srdivacky SDValue N1 = N->getOperand(1); 1717202375Srdivacky SDValue N2 = N->getOperand(2); 1718202375Srdivacky SDValue N3 = N->getOperand(3); 1719202375Srdivacky SDValue InFlag = N->getOperand(4); 1720193323Sed assert(N1.getOpcode() == ISD::BasicBlock); 1721193323Sed assert(N2.getOpcode() == ISD::Constant); 1722193323Sed assert(N3.getOpcode() == ISD::Register); 1723193323Sed 1724193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 1725193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 1726193323Sed MVT::i32); 1727193323Sed SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag }; 1728198090Srdivacky SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other, 1729198090Srdivacky MVT::Flag, Ops, 5); 1730193323Sed Chain = SDValue(ResNode, 0); 1731202375Srdivacky if (N->getNumValues() == 2) { 1732193323Sed InFlag = SDValue(ResNode, 1); 1733202375Srdivacky ReplaceUses(SDValue(N, 1), InFlag); 1734193323Sed } 1735202375Srdivacky ReplaceUses(SDValue(N, 0), 1736199511Srdivacky SDValue(Chain.getNode(), Chain.getResNo())); 1737193323Sed return NULL; 1738193323Sed } 1739199989Srdivacky case ARMISD::CMOV: 1740202375Srdivacky return SelectCMOVOp(N); 1741193323Sed case ARMISD::CNEG: { 1742202375Srdivacky EVT VT = N->getValueType(0); 1743202375Srdivacky SDValue N0 = N->getOperand(0); 1744202375Srdivacky SDValue N1 = N->getOperand(1); 1745202375Srdivacky SDValue N2 = N->getOperand(2); 1746202375Srdivacky SDValue N3 = N->getOperand(3); 1747202375Srdivacky SDValue InFlag = N->getOperand(4); 1748193323Sed assert(N2.getOpcode() == ISD::Constant); 1749193323Sed assert(N3.getOpcode() == ISD::Register); 1750193323Sed 1751193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 1752193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 1753193323Sed MVT::i32); 1754193323Sed SDValue Ops[] = { N0, N1, Tmp2, N3, InFlag }; 1755193323Sed unsigned Opc = 0; 1756198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1757193323Sed default: assert(false && "Illegal conditional move type!"); 1758193323Sed break; 1759193323Sed case MVT::f32: 1760199481Srdivacky Opc = ARM::VNEGScc; 1761193323Sed break; 1762193323Sed case MVT::f64: 1763199481Srdivacky Opc = ARM::VNEGDcc; 1764193323Sed break; 1765193323Sed } 1766202375Srdivacky return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5); 1767193323Sed } 1768193323Sed 1769198090Srdivacky case ARMISD::VZIP: { 1770198090Srdivacky unsigned Opc = 0; 1771198090Srdivacky EVT VT = N->getValueType(0); 1772198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1773198090Srdivacky default: return NULL; 1774198090Srdivacky case MVT::v8i8: Opc = ARM::VZIPd8; break; 1775198090Srdivacky case MVT::v4i16: Opc = ARM::VZIPd16; break; 1776198090Srdivacky case MVT::v2f32: 1777198090Srdivacky case MVT::v2i32: Opc = ARM::VZIPd32; break; 1778198090Srdivacky case MVT::v16i8: Opc = ARM::VZIPq8; break; 1779198090Srdivacky case MVT::v8i16: Opc = ARM::VZIPq16; break; 1780198090Srdivacky case MVT::v4f32: 1781198090Srdivacky case MVT::v4i32: Opc = ARM::VZIPq32; break; 1782193323Sed } 1783199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1784199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1785199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 1786199989Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); 1787198090Srdivacky } 1788198090Srdivacky case ARMISD::VUZP: { 1789198090Srdivacky unsigned Opc = 0; 1790198090Srdivacky EVT VT = N->getValueType(0); 1791198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1792198090Srdivacky default: return NULL; 1793198090Srdivacky case MVT::v8i8: Opc = ARM::VUZPd8; break; 1794198090Srdivacky case MVT::v4i16: Opc = ARM::VUZPd16; break; 1795198090Srdivacky case MVT::v2f32: 1796198090Srdivacky case MVT::v2i32: Opc = ARM::VUZPd32; break; 1797198090Srdivacky case MVT::v16i8: Opc = ARM::VUZPq8; break; 1798198090Srdivacky case MVT::v8i16: Opc = ARM::VUZPq16; break; 1799198090Srdivacky case MVT::v4f32: 1800198090Srdivacky case MVT::v4i32: Opc = ARM::VUZPq32; break; 1801193323Sed } 1802199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1803199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1804199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 1805199989Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); 1806198090Srdivacky } 1807198090Srdivacky case ARMISD::VTRN: { 1808198090Srdivacky unsigned Opc = 0; 1809198090Srdivacky EVT VT = N->getValueType(0); 1810198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1811198090Srdivacky default: return NULL; 1812198090Srdivacky case MVT::v8i8: Opc = ARM::VTRNd8; break; 1813198090Srdivacky case MVT::v4i16: Opc = ARM::VTRNd16; break; 1814198090Srdivacky case MVT::v2f32: 1815198090Srdivacky case MVT::v2i32: Opc = ARM::VTRNd32; break; 1816198090Srdivacky case MVT::v16i8: Opc = ARM::VTRNq8; break; 1817198090Srdivacky case MVT::v8i16: Opc = ARM::VTRNq16; break; 1818198090Srdivacky case MVT::v4f32: 1819198090Srdivacky case MVT::v4i32: Opc = ARM::VTRNq32; break; 1820193323Sed } 1821199989Srdivacky SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); 1822199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1823199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 1824199989Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); 1825193323Sed } 1826194710Sed 1827198090Srdivacky case ISD::INTRINSIC_VOID: 1828198090Srdivacky case ISD::INTRINSIC_W_CHAIN: { 1829198090Srdivacky unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue(); 1830198090Srdivacky switch (IntNo) { 1831198090Srdivacky default: 1832198090Srdivacky break; 1833194710Sed 1834198090Srdivacky case Intrinsic::arm_neon_vld2: { 1835198090Srdivacky unsigned DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16, 1836198090Srdivacky ARM::VLD2d32, ARM::VLD2d64 }; 1837198090Srdivacky unsigned QOpcodes[] = { ARM::VLD2q8, ARM::VLD2q16, ARM::VLD2q32 }; 1838202375Srdivacky return SelectVLD(N, 2, DOpcodes, QOpcodes, 0); 1839198090Srdivacky } 1840194710Sed 1841198090Srdivacky case Intrinsic::arm_neon_vld3: { 1842198090Srdivacky unsigned DOpcodes[] = { ARM::VLD3d8, ARM::VLD3d16, 1843198090Srdivacky ARM::VLD3d32, ARM::VLD3d64 }; 1844205407Srdivacky unsigned QOpcodes0[] = { ARM::VLD3q8_UPD, 1845205407Srdivacky ARM::VLD3q16_UPD, 1846205407Srdivacky ARM::VLD3q32_UPD }; 1847205407Srdivacky unsigned QOpcodes1[] = { ARM::VLD3q8odd_UPD, 1848205407Srdivacky ARM::VLD3q16odd_UPD, 1849205407Srdivacky ARM::VLD3q32odd_UPD }; 1850202375Srdivacky return SelectVLD(N, 3, DOpcodes, QOpcodes0, QOpcodes1); 1851198090Srdivacky } 1852198090Srdivacky 1853198090Srdivacky case Intrinsic::arm_neon_vld4: { 1854198090Srdivacky unsigned DOpcodes[] = { ARM::VLD4d8, ARM::VLD4d16, 1855198090Srdivacky ARM::VLD4d32, ARM::VLD4d64 }; 1856205407Srdivacky unsigned QOpcodes0[] = { ARM::VLD4q8_UPD, 1857205407Srdivacky ARM::VLD4q16_UPD, 1858205407Srdivacky ARM::VLD4q32_UPD }; 1859205407Srdivacky unsigned QOpcodes1[] = { ARM::VLD4q8odd_UPD, 1860205407Srdivacky ARM::VLD4q16odd_UPD, 1861205407Srdivacky ARM::VLD4q32odd_UPD }; 1862202375Srdivacky return SelectVLD(N, 4, DOpcodes, QOpcodes0, QOpcodes1); 1863198090Srdivacky } 1864198090Srdivacky 1865198090Srdivacky case Intrinsic::arm_neon_vld2lane: { 1866198090Srdivacky unsigned DOpcodes[] = { ARM::VLD2LNd8, ARM::VLD2LNd16, ARM::VLD2LNd32 }; 1867205407Srdivacky unsigned QOpcodes0[] = { ARM::VLD2LNq16, ARM::VLD2LNq32 }; 1868205407Srdivacky unsigned QOpcodes1[] = { ARM::VLD2LNq16odd, ARM::VLD2LNq32odd }; 1869202375Srdivacky return SelectVLDSTLane(N, true, 2, DOpcodes, QOpcodes0, QOpcodes1); 1870198090Srdivacky } 1871198090Srdivacky 1872198090Srdivacky case Intrinsic::arm_neon_vld3lane: { 1873198090Srdivacky unsigned DOpcodes[] = { ARM::VLD3LNd8, ARM::VLD3LNd16, ARM::VLD3LNd32 }; 1874205407Srdivacky unsigned QOpcodes0[] = { ARM::VLD3LNq16, ARM::VLD3LNq32 }; 1875205407Srdivacky unsigned QOpcodes1[] = { ARM::VLD3LNq16odd, ARM::VLD3LNq32odd }; 1876202375Srdivacky return SelectVLDSTLane(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1); 1877198090Srdivacky } 1878198090Srdivacky 1879198090Srdivacky case Intrinsic::arm_neon_vld4lane: { 1880198090Srdivacky unsigned DOpcodes[] = { ARM::VLD4LNd8, ARM::VLD4LNd16, ARM::VLD4LNd32 }; 1881205407Srdivacky unsigned QOpcodes0[] = { ARM::VLD4LNq16, ARM::VLD4LNq32 }; 1882205407Srdivacky unsigned QOpcodes1[] = { ARM::VLD4LNq16odd, ARM::VLD4LNq32odd }; 1883202375Srdivacky return SelectVLDSTLane(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1); 1884198090Srdivacky } 1885198090Srdivacky 1886198090Srdivacky case Intrinsic::arm_neon_vst2: { 1887198113Srdivacky unsigned DOpcodes[] = { ARM::VST2d8, ARM::VST2d16, 1888198113Srdivacky ARM::VST2d32, ARM::VST2d64 }; 1889198113Srdivacky unsigned QOpcodes[] = { ARM::VST2q8, ARM::VST2q16, ARM::VST2q32 }; 1890202375Srdivacky return SelectVST(N, 2, DOpcodes, QOpcodes, 0); 1891198090Srdivacky } 1892194710Sed 1893198090Srdivacky case Intrinsic::arm_neon_vst3: { 1894198113Srdivacky unsigned DOpcodes[] = { ARM::VST3d8, ARM::VST3d16, 1895198113Srdivacky ARM::VST3d32, ARM::VST3d64 }; 1896205407Srdivacky unsigned QOpcodes0[] = { ARM::VST3q8_UPD, 1897205407Srdivacky ARM::VST3q16_UPD, 1898205407Srdivacky ARM::VST3q32_UPD }; 1899205407Srdivacky unsigned QOpcodes1[] = { ARM::VST3q8odd_UPD, 1900205407Srdivacky ARM::VST3q16odd_UPD, 1901205407Srdivacky ARM::VST3q32odd_UPD }; 1902202375Srdivacky return SelectVST(N, 3, DOpcodes, QOpcodes0, QOpcodes1); 1903194710Sed } 1904194710Sed 1905198090Srdivacky case Intrinsic::arm_neon_vst4: { 1906198113Srdivacky unsigned DOpcodes[] = { ARM::VST4d8, ARM::VST4d16, 1907198113Srdivacky ARM::VST4d32, ARM::VST4d64 }; 1908205407Srdivacky unsigned QOpcodes0[] = { ARM::VST4q8_UPD, 1909205407Srdivacky ARM::VST4q16_UPD, 1910205407Srdivacky ARM::VST4q32_UPD }; 1911205407Srdivacky unsigned QOpcodes1[] = { ARM::VST4q8odd_UPD, 1912205407Srdivacky ARM::VST4q16odd_UPD, 1913205407Srdivacky ARM::VST4q32odd_UPD }; 1914202375Srdivacky return SelectVST(N, 4, DOpcodes, QOpcodes0, QOpcodes1); 1915198090Srdivacky } 1916198090Srdivacky 1917198090Srdivacky case Intrinsic::arm_neon_vst2lane: { 1918198090Srdivacky unsigned DOpcodes[] = { ARM::VST2LNd8, ARM::VST2LNd16, ARM::VST2LNd32 }; 1919205407Srdivacky unsigned QOpcodes0[] = { ARM::VST2LNq16, ARM::VST2LNq32 }; 1920205407Srdivacky unsigned QOpcodes1[] = { ARM::VST2LNq16odd, ARM::VST2LNq32odd }; 1921202375Srdivacky return SelectVLDSTLane(N, false, 2, DOpcodes, QOpcodes0, QOpcodes1); 1922198090Srdivacky } 1923198090Srdivacky 1924198090Srdivacky case Intrinsic::arm_neon_vst3lane: { 1925198090Srdivacky unsigned DOpcodes[] = { ARM::VST3LNd8, ARM::VST3LNd16, ARM::VST3LNd32 }; 1926205407Srdivacky unsigned QOpcodes0[] = { ARM::VST3LNq16, ARM::VST3LNq32 }; 1927205407Srdivacky unsigned QOpcodes1[] = { ARM::VST3LNq16odd, ARM::VST3LNq32odd }; 1928202375Srdivacky return SelectVLDSTLane(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1); 1929198090Srdivacky } 1930198090Srdivacky 1931198090Srdivacky case Intrinsic::arm_neon_vst4lane: { 1932198090Srdivacky unsigned DOpcodes[] = { ARM::VST4LNd8, ARM::VST4LNd16, ARM::VST4LNd32 }; 1933205407Srdivacky unsigned QOpcodes0[] = { ARM::VST4LNq16, ARM::VST4LNq32 }; 1934205407Srdivacky unsigned QOpcodes1[] = { ARM::VST4LNq16odd, ARM::VST4LNq32odd }; 1935202375Srdivacky return SelectVLDSTLane(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1); 1936198090Srdivacky } 1937198090Srdivacky } 1938194710Sed } 1939194710Sed } 1940194710Sed 1941202375Srdivacky return SelectCode(N); 1942193323Sed} 1943193323Sed 1944193323Sedbool ARMDAGToDAGISel:: 1945193323SedSelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, 1946193323Sed std::vector<SDValue> &OutOps) { 1947193323Sed assert(ConstraintCode == 'm' && "unexpected asm memory constraint"); 1948198090Srdivacky // Require the address to be in a register. That is safe for all ARM 1949198090Srdivacky // variants and it is hard to do anything much smarter without knowing 1950198090Srdivacky // how the operand is used. 1951198090Srdivacky OutOps.push_back(Op); 1952193323Sed return false; 1953193323Sed} 1954193323Sed 1955193323Sed/// createARMISelDag - This pass converts a legalized DAG into a 1956193323Sed/// ARM-specific DAG, ready for instruction scheduling. 1957193323Sed/// 1958198090SrdivackyFunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM, 1959198090Srdivacky CodeGenOpt::Level OptLevel) { 1960198090Srdivacky return new ARMDAGToDAGISel(TM, OptLevel); 1961193323Sed} 1962