ARMISelDAGToDAG.cpp revision 212904
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 14210299Sed#define DEBUG_TYPE "arm-isel" 15193323Sed#include "ARM.h" 16193323Sed#include "ARMAddressingModes.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" 31207631Srdivacky#include "llvm/Support/CommandLine.h" 32193323Sed#include "llvm/Support/Compiler.h" 33193323Sed#include "llvm/Support/Debug.h" 34198090Srdivacky#include "llvm/Support/ErrorHandling.h" 35198090Srdivacky#include "llvm/Support/raw_ostream.h" 36198090Srdivacky 37193323Sedusing namespace llvm; 38193323Sed 39212904Sdimstatic cl::opt<bool> 40212904SdimDisableShifterOp("disable-shifter-op", cl::Hidden, 41212904Sdim cl::desc("Disable isel of shifter-op"), 42212904Sdim cl::init(false)); 43212904Sdim 44193323Sed//===--------------------------------------------------------------------===// 45193323Sed/// ARMDAGToDAGISel - ARM specific code to select ARM machine 46193323Sed/// instructions for SelectionDAG operations. 47193323Sed/// 48193323Sednamespace { 49193323Sedclass ARMDAGToDAGISel : public SelectionDAGISel { 50195098Sed ARMBaseTargetMachine &TM; 51193323Sed 52193323Sed /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can 53193323Sed /// make the right decision when generating code for different targets. 54193323Sed const ARMSubtarget *Subtarget; 55193323Sed 56193323Sedpublic: 57198090Srdivacky explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm, 58198090Srdivacky CodeGenOpt::Level OptLevel) 59198090Srdivacky : SelectionDAGISel(tm, OptLevel), TM(tm), 60193323Sed Subtarget(&TM.getSubtarget<ARMSubtarget>()) { 61193323Sed } 62193323Sed 63193323Sed virtual const char *getPassName() const { 64193323Sed return "ARM Instruction Selection"; 65194612Sed } 66194612Sed 67198090Srdivacky /// getI32Imm - Return a target constant of type i32 with the specified 68198090Srdivacky /// value. 69194612Sed inline SDValue getI32Imm(unsigned Imm) { 70194612Sed return CurDAG->getTargetConstant(Imm, MVT::i32); 71194612Sed } 72194612Sed 73202375Srdivacky SDNode *Select(SDNode *N); 74203954Srdivacky 75202375Srdivacky bool SelectShifterOperandReg(SDNode *Op, SDValue N, SDValue &A, 76195340Sed SDValue &B, SDValue &C); 77202375Srdivacky bool SelectAddrMode2(SDNode *Op, SDValue N, SDValue &Base, 78193323Sed SDValue &Offset, SDValue &Opc); 79202375Srdivacky bool SelectAddrMode2Offset(SDNode *Op, SDValue N, 80193323Sed SDValue &Offset, SDValue &Opc); 81202375Srdivacky bool SelectAddrMode3(SDNode *Op, SDValue N, SDValue &Base, 82193323Sed SDValue &Offset, SDValue &Opc); 83202375Srdivacky bool SelectAddrMode3Offset(SDNode *Op, SDValue N, 84193323Sed SDValue &Offset, SDValue &Opc); 85202375Srdivacky bool SelectAddrMode4(SDNode *Op, SDValue N, SDValue &Addr, 86198090Srdivacky SDValue &Mode); 87202375Srdivacky bool SelectAddrMode5(SDNode *Op, SDValue N, SDValue &Base, 88193323Sed SDValue &Offset); 89205407Srdivacky bool SelectAddrMode6(SDNode *Op, SDValue N, SDValue &Addr, SDValue &Align); 90193323Sed 91202375Srdivacky bool SelectAddrModePC(SDNode *Op, SDValue N, SDValue &Offset, 92195340Sed SDValue &Label); 93193323Sed 94202375Srdivacky bool SelectThumbAddrModeRR(SDNode *Op, SDValue N, SDValue &Base, 95193323Sed SDValue &Offset); 96202375Srdivacky bool SelectThumbAddrModeRI5(SDNode *Op, SDValue N, unsigned Scale, 97193323Sed SDValue &Base, SDValue &OffImm, 98193323Sed SDValue &Offset); 99202375Srdivacky bool SelectThumbAddrModeS1(SDNode *Op, SDValue N, SDValue &Base, 100193323Sed SDValue &OffImm, SDValue &Offset); 101202375Srdivacky bool SelectThumbAddrModeS2(SDNode *Op, SDValue N, SDValue &Base, 102193323Sed SDValue &OffImm, SDValue &Offset); 103202375Srdivacky bool SelectThumbAddrModeS4(SDNode *Op, SDValue N, SDValue &Base, 104193323Sed SDValue &OffImm, SDValue &Offset); 105202375Srdivacky bool SelectThumbAddrModeSP(SDNode *Op, SDValue N, SDValue &Base, 106193323Sed SDValue &OffImm); 107193323Sed 108202375Srdivacky bool SelectT2ShifterOperandReg(SDNode *Op, SDValue N, 109195098Sed SDValue &BaseReg, SDValue &Opc); 110202375Srdivacky bool SelectT2AddrModeImm12(SDNode *Op, SDValue N, SDValue &Base, 111195340Sed SDValue &OffImm); 112202375Srdivacky bool SelectT2AddrModeImm8(SDNode *Op, SDValue N, SDValue &Base, 113195340Sed SDValue &OffImm); 114202375Srdivacky bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N, 115195340Sed SDValue &OffImm); 116202375Srdivacky bool SelectT2AddrModeImm8s4(SDNode *Op, SDValue N, SDValue &Base, 117195340Sed SDValue &OffImm); 118202375Srdivacky bool SelectT2AddrModeSoReg(SDNode *Op, SDValue N, SDValue &Base, 119195340Sed SDValue &OffReg, SDValue &ShImm); 120195340Sed 121212904Sdim inline bool Pred_so_imm(SDNode *inN) const { 122212904Sdim ConstantSDNode *N = cast<ConstantSDNode>(inN); 123212904Sdim return ARM_AM::getSOImmVal(N->getZExtValue()) != -1; 124212904Sdim } 125212904Sdim 126212904Sdim inline bool Pred_t2_so_imm(SDNode *inN) const { 127212904Sdim ConstantSDNode *N = cast<ConstantSDNode>(inN); 128212904Sdim return ARM_AM::getT2SOImmVal(N->getZExtValue()) != -1; 129212904Sdim } 130212904Sdim 131193323Sed // Include the pieces autogenerated from the target description. 132193323Sed#include "ARMGenDAGISel.inc" 133193323Sed 134193323Sedprivate: 135195340Sed /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for 136195340Sed /// ARM. 137202375Srdivacky SDNode *SelectARMIndexedLoad(SDNode *N); 138202375Srdivacky SDNode *SelectT2IndexedLoad(SDNode *N); 139195340Sed 140206083Srdivacky /// SelectVLD - Select NEON load intrinsics. NumVecs should be 141206083Srdivacky /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for 142198090Srdivacky /// loads of D registers and even subregs and odd subregs of Q registers. 143206083Srdivacky /// For NumVecs <= 2, QOpcodes1 is not used. 144202375Srdivacky SDNode *SelectVLD(SDNode *N, unsigned NumVecs, unsigned *DOpcodes, 145198090Srdivacky unsigned *QOpcodes0, unsigned *QOpcodes1); 146198090Srdivacky 147198113Srdivacky /// SelectVST - Select NEON store intrinsics. NumVecs should 148206083Srdivacky /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for 149198113Srdivacky /// stores of D registers and even subregs and odd subregs of Q registers. 150206083Srdivacky /// For NumVecs <= 2, QOpcodes1 is not used. 151202375Srdivacky SDNode *SelectVST(SDNode *N, unsigned NumVecs, unsigned *DOpcodes, 152198113Srdivacky unsigned *QOpcodes0, unsigned *QOpcodes1); 153198113Srdivacky 154198090Srdivacky /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should 155198090Srdivacky /// be 2, 3 or 4. The opcode arrays specify the instructions used for 156198090Srdivacky /// load/store of D registers and even subregs and odd subregs of Q registers. 157202375Srdivacky SDNode *SelectVLDSTLane(SDNode *N, bool IsLoad, unsigned NumVecs, 158198090Srdivacky unsigned *DOpcodes, unsigned *QOpcodes0, 159198090Srdivacky unsigned *QOpcodes1); 160198090Srdivacky 161210299Sed /// SelectVTBL - Select NEON VTBL and VTBX intrinsics. NumVecs should be 2, 162210299Sed /// 3 or 4. These are custom-selected so that a REG_SEQUENCE can be 163210299Sed /// generated to force the table registers to be consecutive. 164210299Sed SDNode *SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs, unsigned Opc); 165210299Sed 166198090Srdivacky /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM. 167207618Srdivacky SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, bool isSigned); 168198090Srdivacky 169199989Srdivacky /// SelectCMOVOp - Select CMOV instructions for ARM. 170202375Srdivacky SDNode *SelectCMOVOp(SDNode *N); 171202375Srdivacky SDNode *SelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 172199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 173199989Srdivacky SDValue InFlag); 174202375Srdivacky SDNode *SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 175199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 176199989Srdivacky SDValue InFlag); 177202375Srdivacky SDNode *SelectT2CMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 178199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 179199989Srdivacky SDValue InFlag); 180202375Srdivacky SDNode *SelectARMCMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 181199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 182199989Srdivacky SDValue InFlag); 183199989Srdivacky 184208599Srdivacky SDNode *SelectConcatVector(SDNode *N); 185208599Srdivacky 186195340Sed /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for 187195340Sed /// inline asm expressions. 188195340Sed virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, 189195340Sed char ConstraintCode, 190195340Sed std::vector<SDValue> &OutOps); 191198090Srdivacky 192210299Sed // Form pairs of consecutive S, D, or Q registers. 193210299Sed SDNode *PairSRegs(EVT VT, SDValue V0, SDValue V1); 194198090Srdivacky SDNode *PairDRegs(EVT VT, SDValue V0, SDValue V1); 195208599Srdivacky SDNode *PairQRegs(EVT VT, SDValue V0, SDValue V1); 196208599Srdivacky 197210299Sed // Form sequences of 4 consecutive S, D, or Q registers. 198210299Sed SDNode *QuadSRegs(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3); 199208599Srdivacky SDNode *QuadDRegs(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3); 200208599Srdivacky SDNode *QuadQRegs(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3); 201208599Srdivacky 202210299Sed // Form sequences of 8 consecutive D registers. 203208599Srdivacky SDNode *OctoDRegs(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3, 204208599Srdivacky SDValue V4, SDValue V5, SDValue V6, SDValue V7); 205193323Sed}; 206193323Sed} 207193323Sed 208198090Srdivacky/// isInt32Immediate - This method tests to see if the node is a 32-bit constant 209198090Srdivacky/// operand. If so Imm will receive the 32-bit value. 210198090Srdivackystatic bool isInt32Immediate(SDNode *N, unsigned &Imm) { 211198090Srdivacky if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) { 212198090Srdivacky Imm = cast<ConstantSDNode>(N)->getZExtValue(); 213198090Srdivacky return true; 214198090Srdivacky } 215198090Srdivacky return false; 216198090Srdivacky} 217198090Srdivacky 218198090Srdivacky// isInt32Immediate - This method tests to see if a constant operand. 219198090Srdivacky// If so Imm will receive the 32 bit value. 220198090Srdivackystatic bool isInt32Immediate(SDValue N, unsigned &Imm) { 221198090Srdivacky return isInt32Immediate(N.getNode(), Imm); 222198090Srdivacky} 223198090Srdivacky 224198090Srdivacky// isOpcWithIntImmediate - This method tests to see if the node is a specific 225198090Srdivacky// opcode and that it has a immediate integer right operand. 226198090Srdivacky// If so Imm will receive the 32 bit value. 227198090Srdivackystatic bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) { 228198090Srdivacky return N->getOpcode() == Opc && 229198090Srdivacky isInt32Immediate(N->getOperand(1).getNode(), Imm); 230198090Srdivacky} 231198090Srdivacky 232198090Srdivacky 233202375Srdivackybool ARMDAGToDAGISel::SelectShifterOperandReg(SDNode *Op, 234195340Sed SDValue N, 235195340Sed SDValue &BaseReg, 236195340Sed SDValue &ShReg, 237195340Sed SDValue &Opc) { 238212904Sdim if (DisableShifterOp) 239212904Sdim return false; 240212904Sdim 241195340Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 242195340Sed 243195340Sed // Don't match base register only case. That is matched to a separate 244195340Sed // lower complexity pattern with explicit register operand. 245195340Sed if (ShOpcVal == ARM_AM::no_shift) return false; 246198090Srdivacky 247195340Sed BaseReg = N.getOperand(0); 248195340Sed unsigned ShImmVal = 0; 249195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 250195340Sed ShReg = CurDAG->getRegister(0, MVT::i32); 251195340Sed ShImmVal = RHS->getZExtValue() & 31; 252195340Sed } else { 253195340Sed ShReg = N.getOperand(1); 254195340Sed } 255195340Sed Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), 256195340Sed MVT::i32); 257195340Sed return true; 258195340Sed} 259195340Sed 260202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode2(SDNode *Op, SDValue N, 261193323Sed SDValue &Base, SDValue &Offset, 262193323Sed SDValue &Opc) { 263193323Sed if (N.getOpcode() == ISD::MUL) { 264193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 265193323Sed // X * [3,5,9] -> X + X * [2,4,8] etc. 266193323Sed int RHSC = (int)RHS->getZExtValue(); 267193323Sed if (RHSC & 1) { 268193323Sed RHSC = RHSC & ~1; 269193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 270193323Sed if (RHSC < 0) { 271193323Sed AddSub = ARM_AM::sub; 272193323Sed RHSC = - RHSC; 273193323Sed } 274193323Sed if (isPowerOf2_32(RHSC)) { 275193323Sed unsigned ShAmt = Log2_32(RHSC); 276193323Sed Base = Offset = N.getOperand(0); 277193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, 278193323Sed ARM_AM::lsl), 279193323Sed MVT::i32); 280193323Sed return true; 281193323Sed } 282193323Sed } 283193323Sed } 284193323Sed } 285193323Sed 286193323Sed if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) { 287193323Sed Base = N; 288193323Sed if (N.getOpcode() == ISD::FrameIndex) { 289193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 290193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 291199989Srdivacky } else if (N.getOpcode() == ARMISD::Wrapper && 292199989Srdivacky !(Subtarget->useMovt() && 293199989Srdivacky N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { 294193323Sed Base = N.getOperand(0); 295193323Sed } 296193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 297193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, 298193323Sed ARM_AM::no_shift), 299193323Sed MVT::i32); 300193323Sed return true; 301193323Sed } 302198090Srdivacky 303193323Sed // Match simple R +/- imm12 operands. 304193323Sed if (N.getOpcode() == ISD::ADD) 305193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 306193323Sed int RHSC = (int)RHS->getZExtValue(); 307193323Sed if ((RHSC >= 0 && RHSC < 0x1000) || 308193323Sed (RHSC < 0 && RHSC > -0x1000)) { // 12 bits. 309193323Sed Base = N.getOperand(0); 310193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 311193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 312193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 313193323Sed } 314193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 315193323Sed 316193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 317193323Sed if (RHSC < 0) { 318193323Sed AddSub = ARM_AM::sub; 319193323Sed RHSC = - RHSC; 320193323Sed } 321193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC, 322193323Sed ARM_AM::no_shift), 323193323Sed MVT::i32); 324193323Sed return true; 325193323Sed } 326193323Sed } 327198090Srdivacky 328198892Srdivacky // Otherwise this is R +/- [possibly shifted] R. 329193323Sed ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::ADD ? ARM_AM::add:ARM_AM::sub; 330193323Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1)); 331193323Sed unsigned ShAmt = 0; 332198090Srdivacky 333193323Sed Base = N.getOperand(0); 334193323Sed Offset = N.getOperand(1); 335198090Srdivacky 336193323Sed if (ShOpcVal != ARM_AM::no_shift) { 337193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 338193323Sed // it. 339193323Sed if (ConstantSDNode *Sh = 340193323Sed dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) { 341193323Sed ShAmt = Sh->getZExtValue(); 342193323Sed Offset = N.getOperand(1).getOperand(0); 343193323Sed } else { 344193323Sed ShOpcVal = ARM_AM::no_shift; 345193323Sed } 346193323Sed } 347198090Srdivacky 348193323Sed // Try matching (R shl C) + (R). 349193323Sed if (N.getOpcode() == ISD::ADD && ShOpcVal == ARM_AM::no_shift) { 350193323Sed ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0)); 351193323Sed if (ShOpcVal != ARM_AM::no_shift) { 352193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't 353193323Sed // fold it. 354193323Sed if (ConstantSDNode *Sh = 355193323Sed dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) { 356193323Sed ShAmt = Sh->getZExtValue(); 357193323Sed Offset = N.getOperand(0).getOperand(0); 358193323Sed Base = N.getOperand(1); 359193323Sed } else { 360193323Sed ShOpcVal = ARM_AM::no_shift; 361193323Sed } 362193323Sed } 363193323Sed } 364198090Srdivacky 365193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 366193323Sed MVT::i32); 367193323Sed return true; 368193323Sed} 369193323Sed 370202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode2Offset(SDNode *Op, SDValue N, 371193323Sed SDValue &Offset, SDValue &Opc) { 372202375Srdivacky unsigned Opcode = Op->getOpcode(); 373193323Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 374193323Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 375193323Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 376193323Sed ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 377193323Sed ? ARM_AM::add : ARM_AM::sub; 378193323Sed if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 379193323Sed int Val = (int)C->getZExtValue(); 380193323Sed if (Val >= 0 && Val < 0x1000) { // 12 bits. 381193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 382193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val, 383193323Sed ARM_AM::no_shift), 384193323Sed MVT::i32); 385193323Sed return true; 386193323Sed } 387193323Sed } 388193323Sed 389193323Sed Offset = N; 390193323Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 391193323Sed unsigned ShAmt = 0; 392193323Sed if (ShOpcVal != ARM_AM::no_shift) { 393193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 394193323Sed // it. 395193323Sed if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 396193323Sed ShAmt = Sh->getZExtValue(); 397193323Sed Offset = N.getOperand(0); 398193323Sed } else { 399193323Sed ShOpcVal = ARM_AM::no_shift; 400193323Sed } 401193323Sed } 402193323Sed 403193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 404193323Sed MVT::i32); 405193323Sed return true; 406193323Sed} 407193323Sed 408193323Sed 409202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode3(SDNode *Op, SDValue N, 410193323Sed SDValue &Base, SDValue &Offset, 411193323Sed SDValue &Opc) { 412193323Sed if (N.getOpcode() == ISD::SUB) { 413193323Sed // X - C is canonicalize to X + -C, no need to handle it here. 414193323Sed Base = N.getOperand(0); 415193323Sed Offset = N.getOperand(1); 416193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32); 417193323Sed return true; 418193323Sed } 419198090Srdivacky 420193323Sed if (N.getOpcode() != ISD::ADD) { 421193323Sed Base = N; 422193323Sed if (N.getOpcode() == ISD::FrameIndex) { 423193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 424193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 425193323Sed } 426193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 427193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32); 428193323Sed return true; 429193323Sed } 430198090Srdivacky 431193323Sed // If the RHS is +/- imm8, fold into addr mode. 432193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 433193323Sed int RHSC = (int)RHS->getZExtValue(); 434193323Sed if ((RHSC >= 0 && RHSC < 256) || 435193323Sed (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed. 436193323Sed Base = N.getOperand(0); 437193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 438193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 439193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 440193323Sed } 441193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 442193323Sed 443193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 444193323Sed if (RHSC < 0) { 445193323Sed AddSub = ARM_AM::sub; 446193323Sed RHSC = - RHSC; 447193323Sed } 448193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32); 449193323Sed return true; 450193323Sed } 451193323Sed } 452198090Srdivacky 453193323Sed Base = N.getOperand(0); 454193323Sed Offset = N.getOperand(1); 455193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32); 456193323Sed return true; 457193323Sed} 458193323Sed 459202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N, 460193323Sed SDValue &Offset, SDValue &Opc) { 461202375Srdivacky unsigned Opcode = Op->getOpcode(); 462193323Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 463193323Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 464193323Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 465193323Sed ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 466193323Sed ? ARM_AM::add : ARM_AM::sub; 467193323Sed if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 468193323Sed int Val = (int)C->getZExtValue(); 469193323Sed if (Val >= 0 && Val < 256) { 470193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 471193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32); 472193323Sed return true; 473193323Sed } 474193323Sed } 475193323Sed 476193323Sed Offset = N; 477193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32); 478193323Sed return true; 479193323Sed} 480193323Sed 481202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode4(SDNode *Op, SDValue N, 482198090Srdivacky SDValue &Addr, SDValue &Mode) { 483198090Srdivacky Addr = N; 484212904Sdim Mode = CurDAG->getTargetConstant(ARM_AM::getAM4ModeImm(ARM_AM::ia), MVT::i32); 485198090Srdivacky return true; 486198090Srdivacky} 487193323Sed 488202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode5(SDNode *Op, SDValue N, 489193323Sed SDValue &Base, SDValue &Offset) { 490193323Sed if (N.getOpcode() != ISD::ADD) { 491193323Sed Base = N; 492193323Sed if (N.getOpcode() == ISD::FrameIndex) { 493193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 494193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 495199989Srdivacky } else if (N.getOpcode() == ARMISD::Wrapper && 496199989Srdivacky !(Subtarget->useMovt() && 497199989Srdivacky N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { 498193323Sed Base = N.getOperand(0); 499193323Sed } 500193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 501193323Sed MVT::i32); 502193323Sed return true; 503193323Sed } 504198090Srdivacky 505193323Sed // If the RHS is +/- imm8, fold into addr mode. 506193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 507193323Sed int RHSC = (int)RHS->getZExtValue(); 508193323Sed if ((RHSC & 3) == 0) { // The constant is implicitly multiplied by 4. 509193323Sed RHSC >>= 2; 510193323Sed if ((RHSC >= 0 && RHSC < 256) || 511193323Sed (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed. 512193323Sed Base = N.getOperand(0); 513193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 514193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 515193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 516193323Sed } 517193323Sed 518193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 519193323Sed if (RHSC < 0) { 520193323Sed AddSub = ARM_AM::sub; 521193323Sed RHSC = - RHSC; 522193323Sed } 523193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC), 524193323Sed MVT::i32); 525193323Sed return true; 526193323Sed } 527193323Sed } 528193323Sed } 529198090Srdivacky 530193323Sed Base = N; 531193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 532193323Sed MVT::i32); 533193323Sed return true; 534193323Sed} 535193323Sed 536202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Op, SDValue N, 537205407Srdivacky SDValue &Addr, SDValue &Align) { 538195340Sed Addr = N; 539199481Srdivacky // Default to no alignment. 540199481Srdivacky Align = CurDAG->getTargetConstant(0, MVT::i32); 541195340Sed return true; 542195340Sed} 543195340Sed 544202375Srdivackybool ARMDAGToDAGISel::SelectAddrModePC(SDNode *Op, SDValue N, 545198090Srdivacky SDValue &Offset, SDValue &Label) { 546193323Sed if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) { 547193323Sed Offset = N.getOperand(0); 548193323Sed SDValue N1 = N.getOperand(1); 549193323Sed Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(), 550193323Sed MVT::i32); 551193323Sed return true; 552193323Sed } 553193323Sed return false; 554193323Sed} 555193323Sed 556202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDNode *Op, SDValue N, 557193323Sed SDValue &Base, SDValue &Offset){ 558193323Sed // FIXME dl should come from the parent load or store, not the address 559193323Sed if (N.getOpcode() != ISD::ADD) { 560198090Srdivacky ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N); 561210299Sed if (!NC || !NC->isNullValue()) 562198090Srdivacky return false; 563198090Srdivacky 564198090Srdivacky Base = Offset = N; 565193323Sed return true; 566193323Sed } 567193323Sed 568193323Sed Base = N.getOperand(0); 569193323Sed Offset = N.getOperand(1); 570193323Sed return true; 571193323Sed} 572193323Sed 573193323Sedbool 574202375SrdivackyARMDAGToDAGISel::SelectThumbAddrModeRI5(SDNode *Op, SDValue N, 575193323Sed unsigned Scale, SDValue &Base, 576193323Sed SDValue &OffImm, SDValue &Offset) { 577193323Sed if (Scale == 4) { 578193323Sed SDValue TmpBase, TmpOffImm; 579193323Sed if (SelectThumbAddrModeSP(Op, N, TmpBase, TmpOffImm)) 580193323Sed return false; // We want to select tLDRspi / tSTRspi instead. 581193323Sed if (N.getOpcode() == ARMISD::Wrapper && 582193323Sed N.getOperand(0).getOpcode() == ISD::TargetConstantPool) 583193323Sed return false; // We want to select tLDRpci instead. 584193323Sed } 585193323Sed 586193323Sed if (N.getOpcode() != ISD::ADD) { 587199989Srdivacky if (N.getOpcode() == ARMISD::Wrapper && 588199989Srdivacky !(Subtarget->useMovt() && 589199989Srdivacky N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { 590199989Srdivacky Base = N.getOperand(0); 591199989Srdivacky } else 592199989Srdivacky Base = N; 593199989Srdivacky 594193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 595193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 596193323Sed return true; 597193323Sed } 598193323Sed 599193323Sed // Thumb does not have [sp, r] address mode. 600193323Sed RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 601193323Sed RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1)); 602193323Sed if ((LHSR && LHSR->getReg() == ARM::SP) || 603193323Sed (RHSR && RHSR->getReg() == ARM::SP)) { 604193323Sed Base = N; 605193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 606193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 607193323Sed return true; 608193323Sed } 609193323Sed 610193323Sed // If the RHS is + imm5 * scale, fold into addr mode. 611193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 612193323Sed int RHSC = (int)RHS->getZExtValue(); 613193323Sed if ((RHSC & (Scale-1)) == 0) { // The constant is implicitly multiplied. 614193323Sed RHSC /= Scale; 615193323Sed if (RHSC >= 0 && RHSC < 32) { 616193323Sed Base = N.getOperand(0); 617193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 618193323Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 619193323Sed return true; 620193323Sed } 621193323Sed } 622193323Sed } 623193323Sed 624193323Sed Base = N.getOperand(0); 625193323Sed Offset = N.getOperand(1); 626193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 627193323Sed return true; 628193323Sed} 629193323Sed 630202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeS1(SDNode *Op, SDValue N, 631193323Sed SDValue &Base, SDValue &OffImm, 632193323Sed SDValue &Offset) { 633193323Sed return SelectThumbAddrModeRI5(Op, N, 1, Base, OffImm, Offset); 634193323Sed} 635193323Sed 636202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeS2(SDNode *Op, SDValue N, 637193323Sed SDValue &Base, SDValue &OffImm, 638193323Sed SDValue &Offset) { 639193323Sed return SelectThumbAddrModeRI5(Op, N, 2, Base, OffImm, Offset); 640193323Sed} 641193323Sed 642202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeS4(SDNode *Op, SDValue N, 643193323Sed SDValue &Base, SDValue &OffImm, 644193323Sed SDValue &Offset) { 645193323Sed return SelectThumbAddrModeRI5(Op, N, 4, Base, OffImm, Offset); 646193323Sed} 647193323Sed 648202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDNode *Op, SDValue N, 649193323Sed SDValue &Base, SDValue &OffImm) { 650193323Sed if (N.getOpcode() == ISD::FrameIndex) { 651193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 652193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 653193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 654193323Sed return true; 655193323Sed } 656193323Sed 657193323Sed if (N.getOpcode() != ISD::ADD) 658193323Sed return false; 659193323Sed 660193323Sed RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 661193323Sed if (N.getOperand(0).getOpcode() == ISD::FrameIndex || 662193323Sed (LHSR && LHSR->getReg() == ARM::SP)) { 663193323Sed // If the RHS is + imm8 * scale, fold into addr mode. 664193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 665193323Sed int RHSC = (int)RHS->getZExtValue(); 666193323Sed if ((RHSC & 3) == 0) { // The constant is implicitly multiplied. 667193323Sed RHSC >>= 2; 668193323Sed if (RHSC >= 0 && RHSC < 256) { 669193323Sed Base = N.getOperand(0); 670193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 671193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 672193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 673193323Sed } 674193323Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 675193323Sed return true; 676193323Sed } 677193323Sed } 678193323Sed } 679193323Sed } 680198090Srdivacky 681193323Sed return false; 682193323Sed} 683193323Sed 684202375Srdivackybool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDNode *Op, SDValue N, 685195098Sed SDValue &BaseReg, 686195098Sed SDValue &Opc) { 687212904Sdim if (DisableShifterOp) 688212904Sdim return false; 689212904Sdim 690195098Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 691195098Sed 692195098Sed // Don't match base register only case. That is matched to a separate 693195098Sed // lower complexity pattern with explicit register operand. 694195098Sed if (ShOpcVal == ARM_AM::no_shift) return false; 695195098Sed 696195098Sed BaseReg = N.getOperand(0); 697195098Sed unsigned ShImmVal = 0; 698195098Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 699195098Sed ShImmVal = RHS->getZExtValue() & 31; 700195098Sed Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal)); 701195098Sed return true; 702195098Sed } 703195098Sed 704195098Sed return false; 705195098Sed} 706195098Sed 707202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDNode *Op, SDValue N, 708195340Sed SDValue &Base, SDValue &OffImm) { 709195340Sed // Match simple R + imm12 operands. 710195340Sed 711198090Srdivacky // Base only. 712198090Srdivacky if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) { 713198090Srdivacky if (N.getOpcode() == ISD::FrameIndex) { 714198090Srdivacky // Match frame index... 715198090Srdivacky int FI = cast<FrameIndexSDNode>(N)->getIndex(); 716198090Srdivacky Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 717198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 718198090Srdivacky return true; 719199989Srdivacky } else if (N.getOpcode() == ARMISD::Wrapper && 720199989Srdivacky !(Subtarget->useMovt() && 721199989Srdivacky N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { 722198090Srdivacky Base = N.getOperand(0); 723198090Srdivacky if (Base.getOpcode() == ISD::TargetConstantPool) 724198090Srdivacky return false; // We want to select t2LDRpci instead. 725198090Srdivacky } else 726198090Srdivacky Base = N; 727198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 728198090Srdivacky return true; 729198090Srdivacky } 730198090Srdivacky 731195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 732198090Srdivacky if (SelectT2AddrModeImm8(Op, N, Base, OffImm)) 733198090Srdivacky // Let t2LDRi8 handle (R - imm8). 734198090Srdivacky return false; 735198090Srdivacky 736195340Sed int RHSC = (int)RHS->getZExtValue(); 737198090Srdivacky if (N.getOpcode() == ISD::SUB) 738198090Srdivacky RHSC = -RHSC; 739198090Srdivacky 740198090Srdivacky if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned) 741195340Sed Base = N.getOperand(0); 742198090Srdivacky if (Base.getOpcode() == ISD::FrameIndex) { 743198090Srdivacky int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 744198090Srdivacky Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 745198090Srdivacky } 746195340Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 747195340Sed return true; 748195340Sed } 749195340Sed } 750195340Sed 751198090Srdivacky // Base only. 752198090Srdivacky Base = N; 753198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 754198090Srdivacky return true; 755195340Sed} 756195340Sed 757202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDNode *Op, SDValue N, 758195340Sed SDValue &Base, SDValue &OffImm) { 759198090Srdivacky // Match simple R - imm8 operands. 760198090Srdivacky if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::SUB) { 761195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 762198090Srdivacky int RHSC = (int)RHS->getSExtValue(); 763198090Srdivacky if (N.getOpcode() == ISD::SUB) 764198090Srdivacky RHSC = -RHSC; 765198090Srdivacky 766198090Srdivacky if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative) 767198090Srdivacky Base = N.getOperand(0); 768198090Srdivacky if (Base.getOpcode() == ISD::FrameIndex) { 769198090Srdivacky int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 770198090Srdivacky Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 771198090Srdivacky } 772195340Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 773195340Sed return true; 774195340Sed } 775195340Sed } 776195340Sed } 777195340Sed 778195340Sed return false; 779195340Sed} 780195340Sed 781202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N, 782195340Sed SDValue &OffImm){ 783202375Srdivacky unsigned Opcode = Op->getOpcode(); 784195340Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 785195340Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 786195340Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 787195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N)) { 788195340Sed int RHSC = (int)RHS->getZExtValue(); 789195340Sed if (RHSC >= 0 && RHSC < 0x100) { // 8 bits. 790198090Srdivacky OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC)) 791195340Sed ? CurDAG->getTargetConstant(RHSC, MVT::i32) 792195340Sed : CurDAG->getTargetConstant(-RHSC, MVT::i32); 793195340Sed return true; 794195340Sed } 795195340Sed } 796195340Sed 797195340Sed return false; 798195340Sed} 799195340Sed 800202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm8s4(SDNode *Op, SDValue N, 801195340Sed SDValue &Base, SDValue &OffImm) { 802195340Sed if (N.getOpcode() == ISD::ADD) { 803195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 804195340Sed int RHSC = (int)RHS->getZExtValue(); 805210299Sed // 8 bits. 806198090Srdivacky if (((RHSC & 0x3) == 0) && 807210299Sed ((RHSC >= 0 && RHSC < 0x400) || (RHSC < 0 && RHSC > -0x400))) { 808195340Sed Base = N.getOperand(0); 809195340Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 810195340Sed return true; 811195340Sed } 812195340Sed } 813195340Sed } else if (N.getOpcode() == ISD::SUB) { 814195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 815195340Sed int RHSC = (int)RHS->getZExtValue(); 816210299Sed // 8 bits. 817210299Sed if (((RHSC & 0x3) == 0) && (RHSC >= 0 && RHSC < 0x400)) { 818195340Sed Base = N.getOperand(0); 819195340Sed OffImm = CurDAG->getTargetConstant(-RHSC, MVT::i32); 820195340Sed return true; 821195340Sed } 822195340Sed } 823195340Sed } 824195340Sed 825195340Sed return false; 826195340Sed} 827195340Sed 828202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDNode *Op, SDValue N, 829195340Sed SDValue &Base, 830195340Sed SDValue &OffReg, SDValue &ShImm) { 831198090Srdivacky // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12. 832198090Srdivacky if (N.getOpcode() != ISD::ADD) 833198090Srdivacky return false; 834198090Srdivacky 835198090Srdivacky // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8. 836198090Srdivacky if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 837198090Srdivacky int RHSC = (int)RHS->getZExtValue(); 838198090Srdivacky if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned) 839198090Srdivacky return false; 840198090Srdivacky else if (RHSC < 0 && RHSC >= -255) // 8 bits 841198090Srdivacky return false; 842195340Sed } 843195340Sed 844195340Sed // Look for (R + R) or (R + (R << [1,2,3])). 845195340Sed unsigned ShAmt = 0; 846195340Sed Base = N.getOperand(0); 847195340Sed OffReg = N.getOperand(1); 848195340Sed 849195340Sed // Swap if it is ((R << c) + R). 850195340Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg); 851195340Sed if (ShOpcVal != ARM_AM::lsl) { 852195340Sed ShOpcVal = ARM_AM::getShiftOpcForNode(Base); 853195340Sed if (ShOpcVal == ARM_AM::lsl) 854195340Sed std::swap(Base, OffReg); 855198090Srdivacky } 856198090Srdivacky 857195340Sed if (ShOpcVal == ARM_AM::lsl) { 858195340Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 859195340Sed // it. 860195340Sed if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) { 861195340Sed ShAmt = Sh->getZExtValue(); 862195340Sed if (ShAmt >= 4) { 863195340Sed ShAmt = 0; 864195340Sed ShOpcVal = ARM_AM::no_shift; 865195340Sed } else 866195340Sed OffReg = OffReg.getOperand(0); 867195340Sed } else { 868195340Sed ShOpcVal = ARM_AM::no_shift; 869195340Sed } 870198090Srdivacky } 871198090Srdivacky 872195340Sed ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32); 873195340Sed 874195340Sed return true; 875195340Sed} 876195340Sed 877195340Sed//===--------------------------------------------------------------------===// 878195340Sed 879193323Sed/// getAL - Returns a ARMCC::AL immediate node. 880193323Sedstatic inline SDValue getAL(SelectionDAG *CurDAG) { 881193323Sed return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32); 882193323Sed} 883193323Sed 884202375SrdivackySDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) { 885202375Srdivacky LoadSDNode *LD = cast<LoadSDNode>(N); 886195340Sed ISD::MemIndexedMode AM = LD->getAddressingMode(); 887195340Sed if (AM == ISD::UNINDEXED) 888195340Sed return NULL; 889193323Sed 890198090Srdivacky EVT LoadedVT = LD->getMemoryVT(); 891195340Sed SDValue Offset, AMOpc; 892195340Sed bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 893195340Sed unsigned Opcode = 0; 894195340Sed bool Match = false; 895195340Sed if (LoadedVT == MVT::i32 && 896202375Srdivacky SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) { 897195340Sed Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST; 898195340Sed Match = true; 899195340Sed } else if (LoadedVT == MVT::i16 && 900202375Srdivacky SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) { 901195340Sed Match = true; 902195340Sed Opcode = (LD->getExtensionType() == ISD::SEXTLOAD) 903195340Sed ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST) 904195340Sed : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST); 905195340Sed } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) { 906195340Sed if (LD->getExtensionType() == ISD::SEXTLOAD) { 907202375Srdivacky if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) { 908195340Sed Match = true; 909195340Sed Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST; 910195340Sed } 911195340Sed } else { 912202375Srdivacky if (SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) { 913195340Sed Match = true; 914195340Sed Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST; 915195340Sed } 916195340Sed } 917195340Sed } 918195340Sed 919195340Sed if (Match) { 920195340Sed SDValue Chain = LD->getChain(); 921195340Sed SDValue Base = LD->getBasePtr(); 922195340Sed SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG), 923195340Sed CurDAG->getRegister(0, MVT::i32), Chain }; 924202375Srdivacky return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, MVT::i32, 925198090Srdivacky MVT::Other, Ops, 6); 926195340Sed } 927195340Sed 928195340Sed return NULL; 929195340Sed} 930195340Sed 931202375SrdivackySDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) { 932202375Srdivacky LoadSDNode *LD = cast<LoadSDNode>(N); 933195340Sed ISD::MemIndexedMode AM = LD->getAddressingMode(); 934195340Sed if (AM == ISD::UNINDEXED) 935195340Sed return NULL; 936195340Sed 937198090Srdivacky EVT LoadedVT = LD->getMemoryVT(); 938195340Sed bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD; 939195340Sed SDValue Offset; 940195340Sed bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 941195340Sed unsigned Opcode = 0; 942195340Sed bool Match = false; 943202375Srdivacky if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) { 944198090Srdivacky switch (LoadedVT.getSimpleVT().SimpleTy) { 945195340Sed case MVT::i32: 946195340Sed Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST; 947195340Sed break; 948195340Sed case MVT::i16: 949195340Sed if (isSExtLd) 950195340Sed Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST; 951195340Sed else 952195340Sed Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST; 953195340Sed break; 954195340Sed case MVT::i8: 955195340Sed case MVT::i1: 956195340Sed if (isSExtLd) 957195340Sed Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST; 958195340Sed else 959195340Sed Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST; 960195340Sed break; 961195340Sed default: 962195340Sed return NULL; 963195340Sed } 964195340Sed Match = true; 965195340Sed } 966195340Sed 967195340Sed if (Match) { 968195340Sed SDValue Chain = LD->getChain(); 969195340Sed SDValue Base = LD->getBasePtr(); 970195340Sed SDValue Ops[]= { Base, Offset, getAL(CurDAG), 971195340Sed CurDAG->getRegister(0, MVT::i32), Chain }; 972202375Srdivacky return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, MVT::i32, 973198090Srdivacky MVT::Other, Ops, 5); 974195340Sed } 975195340Sed 976195340Sed return NULL; 977195340Sed} 978195340Sed 979210299Sed/// PairSRegs - Form a D register from a pair of S registers. 980210299Sed/// 981210299SedSDNode *ARMDAGToDAGISel::PairSRegs(EVT VT, SDValue V0, SDValue V1) { 982210299Sed DebugLoc dl = V0.getNode()->getDebugLoc(); 983210299Sed SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32); 984210299Sed SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32); 985210299Sed const SDValue Ops[] = { V0, SubReg0, V1, SubReg1 }; 986210299Sed return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 4); 987210299Sed} 988210299Sed 989208599Srdivacky/// PairDRegs - Form a quad register from a pair of D registers. 990208599Srdivacky/// 991198090SrdivackySDNode *ARMDAGToDAGISel::PairDRegs(EVT VT, SDValue V0, SDValue V1) { 992198090Srdivacky DebugLoc dl = V0.getNode()->getDebugLoc(); 993208599Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32); 994208599Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32); 995210299Sed const SDValue Ops[] = { V0, SubReg0, V1, SubReg1 }; 996210299Sed return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 4); 997198090Srdivacky} 998198090Srdivacky 999208599Srdivacky/// PairQRegs - Form 4 consecutive D registers from a pair of Q registers. 1000208599Srdivacky/// 1001208599SrdivackySDNode *ARMDAGToDAGISel::PairQRegs(EVT VT, SDValue V0, SDValue V1) { 1002208599Srdivacky DebugLoc dl = V0.getNode()->getDebugLoc(); 1003208599Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32); 1004208599Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32); 1005208599Srdivacky const SDValue Ops[] = { V0, SubReg0, V1, SubReg1 }; 1006208599Srdivacky return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 4); 1007208599Srdivacky} 1008208599Srdivacky 1009210299Sed/// QuadSRegs - Form 4 consecutive S registers. 1010210299Sed/// 1011210299SedSDNode *ARMDAGToDAGISel::QuadSRegs(EVT VT, SDValue V0, SDValue V1, 1012210299Sed SDValue V2, SDValue V3) { 1013210299Sed DebugLoc dl = V0.getNode()->getDebugLoc(); 1014210299Sed SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32); 1015210299Sed SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32); 1016210299Sed SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, MVT::i32); 1017210299Sed SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, MVT::i32); 1018210299Sed const SDValue Ops[] = { V0, SubReg0, V1, SubReg1, V2, SubReg2, V3, SubReg3 }; 1019210299Sed return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 8); 1020210299Sed} 1021210299Sed 1022208599Srdivacky/// QuadDRegs - Form 4 consecutive D registers. 1023208599Srdivacky/// 1024208599SrdivackySDNode *ARMDAGToDAGISel::QuadDRegs(EVT VT, SDValue V0, SDValue V1, 1025208599Srdivacky SDValue V2, SDValue V3) { 1026208599Srdivacky DebugLoc dl = V0.getNode()->getDebugLoc(); 1027208599Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32); 1028208599Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32); 1029208599Srdivacky SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, MVT::i32); 1030208599Srdivacky SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, MVT::i32); 1031208599Srdivacky const SDValue Ops[] = { V0, SubReg0, V1, SubReg1, V2, SubReg2, V3, SubReg3 }; 1032208599Srdivacky return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 8); 1033208599Srdivacky} 1034208599Srdivacky 1035208599Srdivacky/// QuadQRegs - Form 4 consecutive Q registers. 1036208599Srdivacky/// 1037208599SrdivackySDNode *ARMDAGToDAGISel::QuadQRegs(EVT VT, SDValue V0, SDValue V1, 1038208599Srdivacky SDValue V2, SDValue V3) { 1039208599Srdivacky DebugLoc dl = V0.getNode()->getDebugLoc(); 1040208599Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32); 1041208599Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32); 1042208599Srdivacky SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, MVT::i32); 1043208599Srdivacky SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, MVT::i32); 1044208599Srdivacky const SDValue Ops[] = { V0, SubReg0, V1, SubReg1, V2, SubReg2, V3, SubReg3 }; 1045208599Srdivacky return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 8); 1046208599Srdivacky} 1047208599Srdivacky 1048208599Srdivacky/// OctoDRegs - Form 8 consecutive D registers. 1049208599Srdivacky/// 1050208599SrdivackySDNode *ARMDAGToDAGISel::OctoDRegs(EVT VT, SDValue V0, SDValue V1, 1051208599Srdivacky SDValue V2, SDValue V3, 1052208599Srdivacky SDValue V4, SDValue V5, 1053208599Srdivacky SDValue V6, SDValue V7) { 1054208599Srdivacky DebugLoc dl = V0.getNode()->getDebugLoc(); 1055208599Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32); 1056208599Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32); 1057208599Srdivacky SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, MVT::i32); 1058208599Srdivacky SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, MVT::i32); 1059208599Srdivacky SDValue SubReg4 = CurDAG->getTargetConstant(ARM::dsub_4, MVT::i32); 1060208599Srdivacky SDValue SubReg5 = CurDAG->getTargetConstant(ARM::dsub_5, MVT::i32); 1061208599Srdivacky SDValue SubReg6 = CurDAG->getTargetConstant(ARM::dsub_6, MVT::i32); 1062208599Srdivacky SDValue SubReg7 = CurDAG->getTargetConstant(ARM::dsub_7, MVT::i32); 1063208599Srdivacky const SDValue Ops[] ={ V0, SubReg0, V1, SubReg1, V2, SubReg2, V3, SubReg3, 1064208599Srdivacky V4, SubReg4, V5, SubReg5, V6, SubReg6, V7, SubReg7 }; 1065208599Srdivacky return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 16); 1066208599Srdivacky} 1067208599Srdivacky 1068198090Srdivacky/// GetNEONSubregVT - Given a type for a 128-bit NEON vector, return the type 1069198090Srdivacky/// for a 64-bit subregister of the vector. 1070198090Srdivackystatic EVT GetNEONSubregVT(EVT VT) { 1071198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1072198090Srdivacky default: llvm_unreachable("unhandled NEON type"); 1073198090Srdivacky case MVT::v16i8: return MVT::v8i8; 1074198090Srdivacky case MVT::v8i16: return MVT::v4i16; 1075198090Srdivacky case MVT::v4f32: return MVT::v2f32; 1076198090Srdivacky case MVT::v4i32: return MVT::v2i32; 1077198090Srdivacky case MVT::v2i64: return MVT::v1i64; 1078198090Srdivacky } 1079198090Srdivacky} 1080198090Srdivacky 1081202375SrdivackySDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, unsigned NumVecs, 1082198090Srdivacky unsigned *DOpcodes, unsigned *QOpcodes0, 1083198090Srdivacky unsigned *QOpcodes1) { 1084206083Srdivacky assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range"); 1085198090Srdivacky DebugLoc dl = N->getDebugLoc(); 1086198090Srdivacky 1087205407Srdivacky SDValue MemAddr, Align; 1088205407Srdivacky if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, Align)) 1089198090Srdivacky return NULL; 1090198090Srdivacky 1091198090Srdivacky SDValue Chain = N->getOperand(0); 1092198090Srdivacky EVT VT = N->getValueType(0); 1093198090Srdivacky bool is64BitVector = VT.is64BitVector(); 1094198090Srdivacky 1095198090Srdivacky unsigned OpcodeIndex; 1096198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1097198090Srdivacky default: llvm_unreachable("unhandled vld type"); 1098198090Srdivacky // Double-register operations: 1099198090Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1100198090Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1101198090Srdivacky case MVT::v2f32: 1102198090Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1103198090Srdivacky case MVT::v1i64: OpcodeIndex = 3; break; 1104198090Srdivacky // Quad-register operations: 1105198090Srdivacky case MVT::v16i8: OpcodeIndex = 0; break; 1106198090Srdivacky case MVT::v8i16: OpcodeIndex = 1; break; 1107198090Srdivacky case MVT::v4f32: 1108198090Srdivacky case MVT::v4i32: OpcodeIndex = 2; break; 1109206083Srdivacky case MVT::v2i64: OpcodeIndex = 3; 1110206083Srdivacky assert(NumVecs == 1 && "v2i64 type only supported for VLD1"); 1111206083Srdivacky break; 1112198090Srdivacky } 1113198090Srdivacky 1114212904Sdim EVT ResTy; 1115212904Sdim if (NumVecs == 1) 1116212904Sdim ResTy = VT; 1117212904Sdim else { 1118212904Sdim unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs; 1119212904Sdim if (!is64BitVector) 1120212904Sdim ResTyElts *= 2; 1121212904Sdim ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts); 1122212904Sdim } 1123212904Sdim 1124207618Srdivacky SDValue Pred = getAL(CurDAG); 1125205407Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1126212904Sdim SDValue SuperReg; 1127198090Srdivacky if (is64BitVector) { 1128198090Srdivacky unsigned Opc = DOpcodes[OpcodeIndex]; 1129205407Srdivacky const SDValue Ops[] = { MemAddr, Align, Pred, Reg0, Chain }; 1130212904Sdim SDNode *VLd = CurDAG->getMachineNode(Opc, dl, ResTy, MVT::Other, Ops, 5); 1131212904Sdim if (NumVecs == 1) 1132208599Srdivacky return VLd; 1133208599Srdivacky 1134212904Sdim SuperReg = SDValue(VLd, 0); 1135208599Srdivacky assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering"); 1136208599Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1137208599Srdivacky SDValue D = CurDAG->getTargetExtractSubreg(ARM::dsub_0+Vec, 1138212904Sdim dl, VT, SuperReg); 1139208599Srdivacky ReplaceUses(SDValue(N, Vec), D); 1140208599Srdivacky } 1141212904Sdim ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1)); 1142208599Srdivacky return NULL; 1143198090Srdivacky } 1144198090Srdivacky 1145206083Srdivacky if (NumVecs <= 2) { 1146206083Srdivacky // Quad registers are directly supported for VLD1 and VLD2, 1147206083Srdivacky // loading pairs of D regs. 1148198090Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1149205407Srdivacky const SDValue Ops[] = { MemAddr, Align, Pred, Reg0, Chain }; 1150212904Sdim SDNode *VLd = CurDAG->getMachineNode(Opc, dl, ResTy, MVT::Other, Ops, 5); 1151212904Sdim if (NumVecs == 1) 1152212904Sdim return VLd; 1153198090Srdivacky 1154212904Sdim SuperReg = SDValue(VLd, 0); 1155212904Sdim Chain = SDValue(VLd, 1); 1156212904Sdim 1157198090Srdivacky } else { 1158198090Srdivacky // Otherwise, quad registers are loaded with two separate instructions, 1159198090Srdivacky // where one loads the even registers and the other loads the odd registers. 1160212904Sdim EVT AddrTy = MemAddr.getValueType(); 1161198090Srdivacky 1162198113Srdivacky // Load the even subregs. 1163198090Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1164212904Sdim SDValue ImplDef = 1165212904Sdim SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0); 1166212904Sdim const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain }; 1167212904Sdim SDNode *VLdA = 1168212904Sdim CurDAG->getMachineNode(Opc, dl, ResTy, AddrTy, MVT::Other, OpsA, 7); 1169212904Sdim Chain = SDValue(VLdA, 2); 1170198090Srdivacky 1171198113Srdivacky // Load the odd subregs. 1172198090Srdivacky Opc = QOpcodes1[OpcodeIndex]; 1173212904Sdim const SDValue OpsB[] = { SDValue(VLdA, 1), Align, Reg0, SDValue(VLdA, 0), 1174212904Sdim Pred, Reg0, Chain }; 1175212904Sdim SDNode *VLdB = 1176212904Sdim CurDAG->getMachineNode(Opc, dl, ResTy, AddrTy, MVT::Other, OpsB, 7); 1177212904Sdim SuperReg = SDValue(VLdB, 0); 1178212904Sdim Chain = SDValue(VLdB, 2); 1179212904Sdim } 1180198090Srdivacky 1181212904Sdim // Extract out the Q registers. 1182212904Sdim assert(ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering"); 1183212904Sdim for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1184212904Sdim SDValue Q = CurDAG->getTargetExtractSubreg(ARM::qsub_0+Vec, 1185212904Sdim dl, VT, SuperReg); 1186212904Sdim ReplaceUses(SDValue(N, Vec), Q); 1187198090Srdivacky } 1188198090Srdivacky ReplaceUses(SDValue(N, NumVecs), Chain); 1189198090Srdivacky return NULL; 1190198090Srdivacky} 1191198090Srdivacky 1192202375SrdivackySDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, unsigned NumVecs, 1193198113Srdivacky unsigned *DOpcodes, unsigned *QOpcodes0, 1194198113Srdivacky unsigned *QOpcodes1) { 1195210299Sed assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range"); 1196198113Srdivacky DebugLoc dl = N->getDebugLoc(); 1197198113Srdivacky 1198205407Srdivacky SDValue MemAddr, Align; 1199205407Srdivacky if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, Align)) 1200198113Srdivacky return NULL; 1201198113Srdivacky 1202198113Srdivacky SDValue Chain = N->getOperand(0); 1203198113Srdivacky EVT VT = N->getOperand(3).getValueType(); 1204198113Srdivacky bool is64BitVector = VT.is64BitVector(); 1205198113Srdivacky 1206198113Srdivacky unsigned OpcodeIndex; 1207198113Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1208198113Srdivacky default: llvm_unreachable("unhandled vst type"); 1209198113Srdivacky // Double-register operations: 1210198113Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1211198113Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1212198113Srdivacky case MVT::v2f32: 1213198113Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1214198113Srdivacky case MVT::v1i64: OpcodeIndex = 3; break; 1215198113Srdivacky // Quad-register operations: 1216198113Srdivacky case MVT::v16i8: OpcodeIndex = 0; break; 1217198113Srdivacky case MVT::v8i16: OpcodeIndex = 1; break; 1218198113Srdivacky case MVT::v4f32: 1219198113Srdivacky case MVT::v4i32: OpcodeIndex = 2; break; 1220206083Srdivacky case MVT::v2i64: OpcodeIndex = 3; 1221206083Srdivacky assert(NumVecs == 1 && "v2i64 type only supported for VST1"); 1222206083Srdivacky break; 1223198113Srdivacky } 1224198113Srdivacky 1225207618Srdivacky SDValue Pred = getAL(CurDAG); 1226205407Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1227199989Srdivacky 1228212904Sdim SmallVector<SDValue, 7> Ops; 1229198113Srdivacky Ops.push_back(MemAddr); 1230199481Srdivacky Ops.push_back(Align); 1231198113Srdivacky 1232198113Srdivacky if (is64BitVector) { 1233212904Sdim if (NumVecs == 1) { 1234212904Sdim Ops.push_back(N->getOperand(3)); 1235212904Sdim } else { 1236208599Srdivacky SDValue RegSeq; 1237208599Srdivacky SDValue V0 = N->getOperand(0+3); 1238208599Srdivacky SDValue V1 = N->getOperand(1+3); 1239208599Srdivacky 1240208599Srdivacky // Form a REG_SEQUENCE to force register allocation. 1241208599Srdivacky if (NumVecs == 2) 1242208599Srdivacky RegSeq = SDValue(PairDRegs(MVT::v2i64, V0, V1), 0); 1243208599Srdivacky else { 1244208599Srdivacky SDValue V2 = N->getOperand(2+3); 1245208599Srdivacky // If it's a vld3, form a quad D-register and leave the last part as 1246208599Srdivacky // an undef. 1247208599Srdivacky SDValue V3 = (NumVecs == 3) 1248208599Srdivacky ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0) 1249208599Srdivacky : N->getOperand(3+3); 1250208599Srdivacky RegSeq = SDValue(QuadDRegs(MVT::v4i64, V0, V1, V2, V3), 0); 1251208599Srdivacky } 1252212904Sdim Ops.push_back(RegSeq); 1253208599Srdivacky } 1254199989Srdivacky Ops.push_back(Pred); 1255205407Srdivacky Ops.push_back(Reg0); // predicate register 1256198113Srdivacky Ops.push_back(Chain); 1257208599Srdivacky unsigned Opc = DOpcodes[OpcodeIndex]; 1258212904Sdim return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), 6); 1259198113Srdivacky } 1260198113Srdivacky 1261206083Srdivacky if (NumVecs <= 2) { 1262212904Sdim // Quad registers are directly supported for VST1 and VST2. 1263198113Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1264212904Sdim if (NumVecs == 1) { 1265212904Sdim Ops.push_back(N->getOperand(3)); 1266212904Sdim } else { 1267212904Sdim // Form a QQ register. 1268208599Srdivacky SDValue Q0 = N->getOperand(3); 1269208599Srdivacky SDValue Q1 = N->getOperand(4); 1270212904Sdim Ops.push_back(SDValue(PairQRegs(MVT::v4i64, Q0, Q1), 0)); 1271198113Srdivacky } 1272212904Sdim Ops.push_back(Pred); 1273212904Sdim Ops.push_back(Reg0); // predicate register 1274212904Sdim Ops.push_back(Chain); 1275212904Sdim return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), 6); 1276198113Srdivacky } 1277198113Srdivacky 1278198113Srdivacky // Otherwise, quad registers are stored with two separate instructions, 1279198113Srdivacky // where one stores the even registers and the other stores the odd registers. 1280198113Srdivacky 1281210299Sed // Form the QQQQ REG_SEQUENCE. 1282212904Sdim SDValue V0 = N->getOperand(0+3); 1283212904Sdim SDValue V1 = N->getOperand(1+3); 1284212904Sdim SDValue V2 = N->getOperand(2+3); 1285212904Sdim SDValue V3 = (NumVecs == 3) 1286212904Sdim ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0) 1287212904Sdim : N->getOperand(3+3); 1288212904Sdim SDValue RegSeq = SDValue(QuadQRegs(MVT::v8i64, V0, V1, V2, V3), 0); 1289198113Srdivacky 1290210299Sed // Store the even D registers. 1291210299Sed Ops.push_back(Reg0); // post-access address offset 1292212904Sdim Ops.push_back(RegSeq); 1293210299Sed Ops.push_back(Pred); 1294210299Sed Ops.push_back(Reg0); // predicate register 1295210299Sed Ops.push_back(Chain); 1296210299Sed unsigned Opc = QOpcodes0[OpcodeIndex]; 1297210299Sed SDNode *VStA = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(), 1298212904Sdim MVT::Other, Ops.data(), 7); 1299210299Sed Chain = SDValue(VStA, 1); 1300208599Srdivacky 1301210299Sed // Store the odd D registers. 1302210299Sed Ops[0] = SDValue(VStA, 0); // MemAddr 1303212904Sdim Ops[6] = Chain; 1304210299Sed Opc = QOpcodes1[OpcodeIndex]; 1305210299Sed SDNode *VStB = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(), 1306212904Sdim MVT::Other, Ops.data(), 7); 1307210299Sed Chain = SDValue(VStB, 1); 1308210299Sed ReplaceUses(SDValue(N, 0), Chain); 1309210299Sed return NULL; 1310198113Srdivacky} 1311198113Srdivacky 1312202375SrdivackySDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, 1313198090Srdivacky unsigned NumVecs, unsigned *DOpcodes, 1314198090Srdivacky unsigned *QOpcodes0, 1315198090Srdivacky unsigned *QOpcodes1) { 1316198090Srdivacky assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range"); 1317198090Srdivacky DebugLoc dl = N->getDebugLoc(); 1318198090Srdivacky 1319205407Srdivacky SDValue MemAddr, Align; 1320205407Srdivacky if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, Align)) 1321198090Srdivacky return NULL; 1322198090Srdivacky 1323198090Srdivacky SDValue Chain = N->getOperand(0); 1324198090Srdivacky unsigned Lane = 1325198090Srdivacky cast<ConstantSDNode>(N->getOperand(NumVecs+3))->getZExtValue(); 1326198090Srdivacky EVT VT = IsLoad ? N->getValueType(0) : N->getOperand(3).getValueType(); 1327198090Srdivacky bool is64BitVector = VT.is64BitVector(); 1328198090Srdivacky 1329198090Srdivacky // Quad registers are handled by load/store of subregs. Find the subreg info. 1330198090Srdivacky unsigned NumElts = 0; 1331208599Srdivacky bool Even = false; 1332198090Srdivacky EVT RegVT = VT; 1333198090Srdivacky if (!is64BitVector) { 1334198090Srdivacky RegVT = GetNEONSubregVT(VT); 1335198090Srdivacky NumElts = RegVT.getVectorNumElements(); 1336208599Srdivacky Even = Lane < NumElts; 1337198090Srdivacky } 1338198090Srdivacky 1339198090Srdivacky unsigned OpcodeIndex; 1340198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1341198090Srdivacky default: llvm_unreachable("unhandled vld/vst lane type"); 1342198090Srdivacky // Double-register operations: 1343198090Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1344198090Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1345198090Srdivacky case MVT::v2f32: 1346198090Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1347198090Srdivacky // Quad-register operations: 1348198090Srdivacky case MVT::v8i16: OpcodeIndex = 0; break; 1349198090Srdivacky case MVT::v4f32: 1350198090Srdivacky case MVT::v4i32: OpcodeIndex = 1; break; 1351198090Srdivacky } 1352198090Srdivacky 1353207618Srdivacky SDValue Pred = getAL(CurDAG); 1354205407Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1355199989Srdivacky 1356205407Srdivacky SmallVector<SDValue, 10> Ops; 1357198090Srdivacky Ops.push_back(MemAddr); 1358199481Srdivacky Ops.push_back(Align); 1359198090Srdivacky 1360198090Srdivacky unsigned Opc = 0; 1361198090Srdivacky if (is64BitVector) { 1362198090Srdivacky Opc = DOpcodes[OpcodeIndex]; 1363210299Sed SDValue RegSeq; 1364210299Sed SDValue V0 = N->getOperand(0+3); 1365210299Sed SDValue V1 = N->getOperand(1+3); 1366210299Sed if (NumVecs == 2) { 1367210299Sed RegSeq = SDValue(PairDRegs(MVT::v2i64, V0, V1), 0); 1368208599Srdivacky } else { 1369210299Sed SDValue V2 = N->getOperand(2+3); 1370210299Sed SDValue V3 = (NumVecs == 3) 1371210299Sed ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0) 1372210299Sed : N->getOperand(3+3); 1373210299Sed RegSeq = SDValue(QuadDRegs(MVT::v4i64, V0, V1, V2, V3), 0); 1374208599Srdivacky } 1375210299Sed 1376210299Sed // Now extract the D registers back out. 1377210299Sed Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_0, dl, VT, RegSeq)); 1378210299Sed Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_1, dl, VT, RegSeq)); 1379210299Sed if (NumVecs > 2) 1380210299Sed Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_2, dl, VT,RegSeq)); 1381210299Sed if (NumVecs > 3) 1382210299Sed Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_3, dl, VT,RegSeq)); 1383198090Srdivacky } else { 1384198090Srdivacky // Check if this is loading the even or odd subreg of a Q register. 1385198090Srdivacky if (Lane < NumElts) { 1386198090Srdivacky Opc = QOpcodes0[OpcodeIndex]; 1387198090Srdivacky } else { 1388198090Srdivacky Lane -= NumElts; 1389198090Srdivacky Opc = QOpcodes1[OpcodeIndex]; 1390198090Srdivacky } 1391208599Srdivacky 1392210299Sed SDValue RegSeq; 1393210299Sed SDValue V0 = N->getOperand(0+3); 1394210299Sed SDValue V1 = N->getOperand(1+3); 1395210299Sed if (NumVecs == 2) { 1396210299Sed RegSeq = SDValue(PairQRegs(MVT::v4i64, V0, V1), 0); 1397208599Srdivacky } else { 1398210299Sed SDValue V2 = N->getOperand(2+3); 1399210299Sed SDValue V3 = (NumVecs == 3) 1400210299Sed ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0) 1401210299Sed : N->getOperand(3+3); 1402210299Sed RegSeq = SDValue(QuadQRegs(MVT::v8i64, V0, V1, V2, V3), 0); 1403208599Srdivacky } 1404210299Sed 1405210299Sed // Extract the subregs of the input vector. 1406210299Sed unsigned SubIdx = Even ? ARM::dsub_0 : ARM::dsub_1; 1407210299Sed for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1408210299Sed Ops.push_back(CurDAG->getTargetExtractSubreg(SubIdx+Vec*2, dl, RegVT, 1409210299Sed RegSeq)); 1410198090Srdivacky } 1411198090Srdivacky Ops.push_back(getI32Imm(Lane)); 1412199989Srdivacky Ops.push_back(Pred); 1413205407Srdivacky Ops.push_back(Reg0); 1414198090Srdivacky Ops.push_back(Chain); 1415198090Srdivacky 1416198090Srdivacky if (!IsLoad) 1417205407Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+6); 1418198090Srdivacky 1419198090Srdivacky std::vector<EVT> ResTys(NumVecs, RegVT); 1420198090Srdivacky ResTys.push_back(MVT::Other); 1421208599Srdivacky SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(),NumVecs+6); 1422208599Srdivacky 1423210299Sed // Form a REG_SEQUENCE to force register allocation. 1424210299Sed SDValue RegSeq; 1425210299Sed if (is64BitVector) { 1426210299Sed SDValue V0 = SDValue(VLdLn, 0); 1427210299Sed SDValue V1 = SDValue(VLdLn, 1); 1428210299Sed if (NumVecs == 2) { 1429210299Sed RegSeq = SDValue(PairDRegs(MVT::v2i64, V0, V1), 0); 1430210299Sed } else { 1431210299Sed SDValue V2 = SDValue(VLdLn, 2); 1432210299Sed // If it's a vld3, form a quad D-register but discard the last part. 1433210299Sed SDValue V3 = (NumVecs == 3) 1434210299Sed ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0) 1435210299Sed : SDValue(VLdLn, 3); 1436210299Sed RegSeq = SDValue(QuadDRegs(MVT::v4i64, V0, V1, V2, V3), 0); 1437210299Sed } 1438210299Sed } else { 1439210299Sed // For 128-bit vectors, take the 64-bit results of the load and insert 1440210299Sed // them as subregs into the result. 1441210299Sed SDValue V[8]; 1442210299Sed for (unsigned Vec = 0, i = 0; Vec < NumVecs; ++Vec, i+=2) { 1443210299Sed if (Even) { 1444210299Sed V[i] = SDValue(VLdLn, Vec); 1445210299Sed V[i+1] = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, 1446210299Sed dl, RegVT), 0); 1447208599Srdivacky } else { 1448210299Sed V[i] = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, 1449210299Sed dl, RegVT), 0); 1450210299Sed V[i+1] = SDValue(VLdLn, Vec); 1451208599Srdivacky } 1452208599Srdivacky } 1453210299Sed if (NumVecs == 3) 1454210299Sed V[6] = V[7] = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, 1455210299Sed dl, RegVT), 0); 1456208599Srdivacky 1457210299Sed if (NumVecs == 2) 1458210299Sed RegSeq = SDValue(QuadDRegs(MVT::v4i64, V[0], V[1], V[2], V[3]), 0); 1459210299Sed else 1460210299Sed RegSeq = SDValue(OctoDRegs(MVT::v8i64, V[0], V[1], V[2], V[3], 1461210299Sed V[4], V[5], V[6], V[7]), 0); 1462208599Srdivacky } 1463208599Srdivacky 1464210299Sed assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering"); 1465210299Sed assert(ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering"); 1466210299Sed unsigned SubIdx = is64BitVector ? ARM::dsub_0 : ARM::qsub_0; 1467210299Sed for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1468210299Sed ReplaceUses(SDValue(N, Vec), 1469210299Sed CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, RegSeq)); 1470210299Sed ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, NumVecs)); 1471210299Sed return NULL; 1472210299Sed} 1473198090Srdivacky 1474210299SedSDNode *ARMDAGToDAGISel::SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs, 1475210299Sed unsigned Opc) { 1476210299Sed assert(NumVecs >= 2 && NumVecs <= 4 && "VTBL NumVecs out-of-range"); 1477210299Sed DebugLoc dl = N->getDebugLoc(); 1478210299Sed EVT VT = N->getValueType(0); 1479210299Sed unsigned FirstTblReg = IsExt ? 2 : 1; 1480210299Sed 1481210299Sed // Form a REG_SEQUENCE to force register allocation. 1482210299Sed SDValue RegSeq; 1483210299Sed SDValue V0 = N->getOperand(FirstTblReg + 0); 1484210299Sed SDValue V1 = N->getOperand(FirstTblReg + 1); 1485210299Sed if (NumVecs == 2) 1486210299Sed RegSeq = SDValue(PairDRegs(MVT::v16i8, V0, V1), 0); 1487210299Sed else { 1488210299Sed SDValue V2 = N->getOperand(FirstTblReg + 2); 1489210299Sed // If it's a vtbl3, form a quad D-register and leave the last part as 1490210299Sed // an undef. 1491210299Sed SDValue V3 = (NumVecs == 3) 1492210299Sed ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0) 1493210299Sed : N->getOperand(FirstTblReg + 3); 1494210299Sed RegSeq = SDValue(QuadDRegs(MVT::v4i64, V0, V1, V2, V3), 0); 1495198090Srdivacky } 1496198090Srdivacky 1497210299Sed // Now extract the D registers back out. 1498210299Sed SmallVector<SDValue, 6> Ops; 1499210299Sed if (IsExt) 1500210299Sed Ops.push_back(N->getOperand(1)); 1501210299Sed Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_0, dl, VT, RegSeq)); 1502210299Sed Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_1, dl, VT, RegSeq)); 1503210299Sed if (NumVecs > 2) 1504210299Sed Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_2, dl, VT, RegSeq)); 1505210299Sed if (NumVecs > 3) 1506210299Sed Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_3, dl, VT, RegSeq)); 1507210299Sed 1508210299Sed Ops.push_back(N->getOperand(FirstTblReg + NumVecs)); 1509210299Sed Ops.push_back(getAL(CurDAG)); // predicate 1510210299Sed Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // predicate register 1511210299Sed return CurDAG->getMachineNode(Opc, dl, VT, Ops.data(), Ops.size()); 1512198090Srdivacky} 1513198090Srdivacky 1514202375SrdivackySDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N, 1515207618Srdivacky bool isSigned) { 1516198090Srdivacky if (!Subtarget->hasV6T2Ops()) 1517198090Srdivacky return NULL; 1518198090Srdivacky 1519207618Srdivacky unsigned Opc = isSigned ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX) 1520207618Srdivacky : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX); 1521207618Srdivacky 1522207618Srdivacky 1523207618Srdivacky // For unsigned extracts, check for a shift right and mask 1524207618Srdivacky unsigned And_imm = 0; 1525207618Srdivacky if (N->getOpcode() == ISD::AND) { 1526207618Srdivacky if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) { 1527207618Srdivacky 1528207618Srdivacky // The immediate is a mask of the low bits iff imm & (imm+1) == 0 1529207618Srdivacky if (And_imm & (And_imm + 1)) 1530207618Srdivacky return NULL; 1531207618Srdivacky 1532207618Srdivacky unsigned Srl_imm = 0; 1533207618Srdivacky if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, 1534207618Srdivacky Srl_imm)) { 1535207618Srdivacky assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); 1536207618Srdivacky 1537207618Srdivacky unsigned Width = CountTrailingOnes_32(And_imm); 1538207618Srdivacky unsigned LSB = Srl_imm; 1539207618Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1540207618Srdivacky SDValue Ops[] = { N->getOperand(0).getOperand(0), 1541207618Srdivacky CurDAG->getTargetConstant(LSB, MVT::i32), 1542207618Srdivacky CurDAG->getTargetConstant(Width, MVT::i32), 1543207618Srdivacky getAL(CurDAG), Reg0 }; 1544207618Srdivacky return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); 1545207618Srdivacky } 1546207618Srdivacky } 1547207618Srdivacky return NULL; 1548207618Srdivacky } 1549207618Srdivacky 1550207618Srdivacky // Otherwise, we're looking for a shift of a shift 1551198090Srdivacky unsigned Shl_imm = 0; 1552202375Srdivacky if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) { 1553198090Srdivacky assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!"); 1554198090Srdivacky unsigned Srl_imm = 0; 1555202375Srdivacky if (isInt32Immediate(N->getOperand(1), Srl_imm)) { 1556198090Srdivacky assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); 1557198090Srdivacky unsigned Width = 32 - Srl_imm; 1558198090Srdivacky int LSB = Srl_imm - Shl_imm; 1559198396Srdivacky if (LSB < 0) 1560198090Srdivacky return NULL; 1561198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1562202375Srdivacky SDValue Ops[] = { N->getOperand(0).getOperand(0), 1563198090Srdivacky CurDAG->getTargetConstant(LSB, MVT::i32), 1564198090Srdivacky CurDAG->getTargetConstant(Width, MVT::i32), 1565198090Srdivacky getAL(CurDAG), Reg0 }; 1566202375Srdivacky return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); 1567198090Srdivacky } 1568198090Srdivacky } 1569198090Srdivacky return NULL; 1570198090Srdivacky} 1571198090Srdivacky 1572199989SrdivackySDNode *ARMDAGToDAGISel:: 1573202375SrdivackySelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 1574199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1575199989Srdivacky SDValue CPTmp0; 1576199989Srdivacky SDValue CPTmp1; 1577202375Srdivacky if (SelectT2ShifterOperandReg(N, TrueVal, CPTmp0, CPTmp1)) { 1578199989Srdivacky unsigned SOVal = cast<ConstantSDNode>(CPTmp1)->getZExtValue(); 1579199989Srdivacky unsigned SOShOp = ARM_AM::getSORegShOp(SOVal); 1580199989Srdivacky unsigned Opc = 0; 1581199989Srdivacky switch (SOShOp) { 1582199989Srdivacky case ARM_AM::lsl: Opc = ARM::t2MOVCClsl; break; 1583199989Srdivacky case ARM_AM::lsr: Opc = ARM::t2MOVCClsr; break; 1584199989Srdivacky case ARM_AM::asr: Opc = ARM::t2MOVCCasr; break; 1585199989Srdivacky case ARM_AM::ror: Opc = ARM::t2MOVCCror; break; 1586199989Srdivacky default: 1587199989Srdivacky llvm_unreachable("Unknown so_reg opcode!"); 1588199989Srdivacky break; 1589199989Srdivacky } 1590199989Srdivacky SDValue SOShImm = 1591199989Srdivacky CurDAG->getTargetConstant(ARM_AM::getSORegOffset(SOVal), MVT::i32); 1592199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1593199989Srdivacky SDValue Ops[] = { FalseVal, CPTmp0, SOShImm, CC, CCR, InFlag }; 1594202375Srdivacky return CurDAG->SelectNodeTo(N, Opc, MVT::i32,Ops, 6); 1595199989Srdivacky } 1596199989Srdivacky return 0; 1597199989Srdivacky} 1598199989Srdivacky 1599199989SrdivackySDNode *ARMDAGToDAGISel:: 1600202375SrdivackySelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 1601199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1602199989Srdivacky SDValue CPTmp0; 1603199989Srdivacky SDValue CPTmp1; 1604199989Srdivacky SDValue CPTmp2; 1605202375Srdivacky if (SelectShifterOperandReg(N, TrueVal, CPTmp0, CPTmp1, CPTmp2)) { 1606199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1607199989Srdivacky SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, InFlag }; 1608202375Srdivacky return CurDAG->SelectNodeTo(N, ARM::MOVCCs, MVT::i32, Ops, 7); 1609199989Srdivacky } 1610199989Srdivacky return 0; 1611199989Srdivacky} 1612199989Srdivacky 1613199989SrdivackySDNode *ARMDAGToDAGISel:: 1614202375SrdivackySelectT2CMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 1615199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1616199989Srdivacky ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal); 1617199989Srdivacky if (!T) 1618199989Srdivacky return 0; 1619199989Srdivacky 1620212904Sdim if (Pred_t2_so_imm(TrueVal.getNode())) { 1621199989Srdivacky SDValue True = CurDAG->getTargetConstant(T->getZExtValue(), MVT::i32); 1622199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1623199989Srdivacky SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag }; 1624202375Srdivacky return CurDAG->SelectNodeTo(N, 1625199989Srdivacky ARM::t2MOVCCi, MVT::i32, Ops, 5); 1626199989Srdivacky } 1627199989Srdivacky return 0; 1628199989Srdivacky} 1629199989Srdivacky 1630199989SrdivackySDNode *ARMDAGToDAGISel:: 1631202375SrdivackySelectARMCMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 1632199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1633199989Srdivacky ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal); 1634199989Srdivacky if (!T) 1635199989Srdivacky return 0; 1636199989Srdivacky 1637212904Sdim if (Pred_so_imm(TrueVal.getNode())) { 1638199989Srdivacky SDValue True = CurDAG->getTargetConstant(T->getZExtValue(), MVT::i32); 1639199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1640199989Srdivacky SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag }; 1641202375Srdivacky return CurDAG->SelectNodeTo(N, 1642199989Srdivacky ARM::MOVCCi, MVT::i32, Ops, 5); 1643199989Srdivacky } 1644199989Srdivacky return 0; 1645199989Srdivacky} 1646199989Srdivacky 1647202375SrdivackySDNode *ARMDAGToDAGISel::SelectCMOVOp(SDNode *N) { 1648202375Srdivacky EVT VT = N->getValueType(0); 1649202375Srdivacky SDValue FalseVal = N->getOperand(0); 1650202375Srdivacky SDValue TrueVal = N->getOperand(1); 1651202375Srdivacky SDValue CC = N->getOperand(2); 1652202375Srdivacky SDValue CCR = N->getOperand(3); 1653202375Srdivacky SDValue InFlag = N->getOperand(4); 1654199989Srdivacky assert(CC.getOpcode() == ISD::Constant); 1655199989Srdivacky assert(CCR.getOpcode() == ISD::Register); 1656199989Srdivacky ARMCC::CondCodes CCVal = 1657199989Srdivacky (ARMCC::CondCodes)cast<ConstantSDNode>(CC)->getZExtValue(); 1658199989Srdivacky 1659199989Srdivacky if (!Subtarget->isThumb1Only() && VT == MVT::i32) { 1660199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) 1661199989Srdivacky // Emits: (MOVCCs:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) 1662199989Srdivacky // Pattern complexity = 18 cost = 1 size = 0 1663199989Srdivacky SDValue CPTmp0; 1664199989Srdivacky SDValue CPTmp1; 1665199989Srdivacky SDValue CPTmp2; 1666199989Srdivacky if (Subtarget->isThumb()) { 1667202375Srdivacky SDNode *Res = SelectT2CMOVShiftOp(N, FalseVal, TrueVal, 1668199989Srdivacky CCVal, CCR, InFlag); 1669199989Srdivacky if (!Res) 1670202375Srdivacky Res = SelectT2CMOVShiftOp(N, TrueVal, FalseVal, 1671199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1672199989Srdivacky if (Res) 1673199989Srdivacky return Res; 1674199989Srdivacky } else { 1675202375Srdivacky SDNode *Res = SelectARMCMOVShiftOp(N, FalseVal, TrueVal, 1676199989Srdivacky CCVal, CCR, InFlag); 1677199989Srdivacky if (!Res) 1678202375Srdivacky Res = SelectARMCMOVShiftOp(N, TrueVal, FalseVal, 1679199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1680199989Srdivacky if (Res) 1681199989Srdivacky return Res; 1682199989Srdivacky } 1683199989Srdivacky 1684199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, 1685212904Sdim // (imm:i32)<<P:Pred_so_imm>>:$true, 1686199989Srdivacky // (imm:i32):$cc) 1687199989Srdivacky // Emits: (MOVCCi:i32 GPR:i32:$false, 1688199989Srdivacky // (so_imm:i32 (imm:i32):$true), (imm:i32):$cc) 1689199989Srdivacky // Pattern complexity = 10 cost = 1 size = 0 1690199989Srdivacky if (Subtarget->isThumb()) { 1691202375Srdivacky SDNode *Res = SelectT2CMOVSoImmOp(N, FalseVal, TrueVal, 1692199989Srdivacky CCVal, CCR, InFlag); 1693199989Srdivacky if (!Res) 1694202375Srdivacky Res = SelectT2CMOVSoImmOp(N, TrueVal, FalseVal, 1695199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1696199989Srdivacky if (Res) 1697199989Srdivacky return Res; 1698199989Srdivacky } else { 1699202375Srdivacky SDNode *Res = SelectARMCMOVSoImmOp(N, FalseVal, TrueVal, 1700199989Srdivacky CCVal, CCR, InFlag); 1701199989Srdivacky if (!Res) 1702202375Srdivacky Res = SelectARMCMOVSoImmOp(N, TrueVal, FalseVal, 1703199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1704199989Srdivacky if (Res) 1705199989Srdivacky return Res; 1706199989Srdivacky } 1707199989Srdivacky } 1708199989Srdivacky 1709199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1710199989Srdivacky // Emits: (MOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1711199989Srdivacky // Pattern complexity = 6 cost = 1 size = 0 1712199989Srdivacky // 1713199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1714199989Srdivacky // Emits: (tMOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1715199989Srdivacky // Pattern complexity = 6 cost = 11 size = 0 1716199989Srdivacky // 1717199989Srdivacky // Also FCPYScc and FCPYDcc. 1718199989Srdivacky SDValue Tmp2 = CurDAG->getTargetConstant(CCVal, MVT::i32); 1719199989Srdivacky SDValue Ops[] = { FalseVal, TrueVal, Tmp2, CCR, InFlag }; 1720199989Srdivacky unsigned Opc = 0; 1721199989Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1722199989Srdivacky default: assert(false && "Illegal conditional move type!"); 1723199989Srdivacky break; 1724199989Srdivacky case MVT::i32: 1725199989Srdivacky Opc = Subtarget->isThumb() 1726199989Srdivacky ? (Subtarget->hasThumb2() ? ARM::t2MOVCCr : ARM::tMOVCCr_pseudo) 1727199989Srdivacky : ARM::MOVCCr; 1728199989Srdivacky break; 1729199989Srdivacky case MVT::f32: 1730199989Srdivacky Opc = ARM::VMOVScc; 1731199989Srdivacky break; 1732199989Srdivacky case MVT::f64: 1733199989Srdivacky Opc = ARM::VMOVDcc; 1734199989Srdivacky break; 1735199989Srdivacky } 1736202375Srdivacky return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5); 1737199989Srdivacky} 1738199989Srdivacky 1739208599SrdivackySDNode *ARMDAGToDAGISel::SelectConcatVector(SDNode *N) { 1740208599Srdivacky // The only time a CONCAT_VECTORS operation can have legal types is when 1741208599Srdivacky // two 64-bit vectors are concatenated to a 128-bit vector. 1742208599Srdivacky EVT VT = N->getValueType(0); 1743208599Srdivacky if (!VT.is128BitVector() || N->getNumOperands() != 2) 1744208599Srdivacky llvm_unreachable("unexpected CONCAT_VECTORS"); 1745208599Srdivacky DebugLoc dl = N->getDebugLoc(); 1746208599Srdivacky SDValue V0 = N->getOperand(0); 1747208599Srdivacky SDValue V1 = N->getOperand(1); 1748208599Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32); 1749208599Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32); 1750208599Srdivacky const SDValue Ops[] = { V0, SubReg0, V1, SubReg1 }; 1751208599Srdivacky return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 4); 1752208599Srdivacky} 1753208599Srdivacky 1754202375SrdivackySDNode *ARMDAGToDAGISel::Select(SDNode *N) { 1755193323Sed DebugLoc dl = N->getDebugLoc(); 1756193323Sed 1757193323Sed if (N->isMachineOpcode()) 1758193323Sed return NULL; // Already selected. 1759193323Sed 1760193323Sed switch (N->getOpcode()) { 1761193323Sed default: break; 1762193323Sed case ISD::Constant: { 1763193323Sed unsigned Val = cast<ConstantSDNode>(N)->getZExtValue(); 1764193323Sed bool UseCP = true; 1765198090Srdivacky if (Subtarget->hasThumb2()) 1766198090Srdivacky // Thumb2-aware targets have the MOVT instruction, so all immediates can 1767198090Srdivacky // be done with MOV + MOVT, at worst. 1768198090Srdivacky UseCP = 0; 1769198090Srdivacky else { 1770198090Srdivacky if (Subtarget->isThumb()) { 1771194710Sed UseCP = (Val > 255 && // MOV 1772194710Sed ~Val > 255 && // MOV + MVN 1773194710Sed !ARM_AM::isThumbImmShiftedVal(Val)); // MOV + LSL 1774198090Srdivacky } else 1775198090Srdivacky UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV 1776198090Srdivacky ARM_AM::getSOImmVal(~Val) == -1 && // MVN 1777198090Srdivacky !ARM_AM::isSOImmTwoPartVal(Val)); // two instrs. 1778198090Srdivacky } 1779198090Srdivacky 1780193323Sed if (UseCP) { 1781193323Sed SDValue CPIdx = 1782198090Srdivacky CurDAG->getTargetConstantPool(ConstantInt::get( 1783198090Srdivacky Type::getInt32Ty(*CurDAG->getContext()), Val), 1784193323Sed TLI.getPointerTy()); 1785193323Sed 1786193323Sed SDNode *ResNode; 1787198090Srdivacky if (Subtarget->isThumb1Only()) { 1788207618Srdivacky SDValue Pred = getAL(CurDAG); 1789198090Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1790198090Srdivacky SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() }; 1791198090Srdivacky ResNode = CurDAG->getMachineNode(ARM::tLDRcp, dl, MVT::i32, MVT::Other, 1792198090Srdivacky Ops, 4); 1793198090Srdivacky } else { 1794193323Sed SDValue Ops[] = { 1795198090Srdivacky CPIdx, 1796193323Sed CurDAG->getRegister(0, MVT::i32), 1797193323Sed CurDAG->getTargetConstant(0, MVT::i32), 1798193323Sed getAL(CurDAG), 1799193323Sed CurDAG->getRegister(0, MVT::i32), 1800193323Sed CurDAG->getEntryNode() 1801193323Sed }; 1802198090Srdivacky ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other, 1803198090Srdivacky Ops, 6); 1804193323Sed } 1805202375Srdivacky ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0)); 1806193323Sed return NULL; 1807193323Sed } 1808198090Srdivacky 1809193323Sed // Other cases are autogenerated. 1810193323Sed break; 1811193323Sed } 1812193323Sed case ISD::FrameIndex: { 1813193323Sed // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm. 1814193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 1815193323Sed SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 1816198090Srdivacky if (Subtarget->isThumb1Only()) { 1817193323Sed return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI, 1818193323Sed CurDAG->getTargetConstant(0, MVT::i32)); 1819193323Sed } else { 1820198090Srdivacky unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ? 1821198090Srdivacky ARM::t2ADDri : ARM::ADDri); 1822193323Sed SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32), 1823198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1824198090Srdivacky CurDAG->getRegister(0, MVT::i32) }; 1825198090Srdivacky return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); 1826193323Sed } 1827193323Sed } 1828198090Srdivacky case ISD::SRL: 1829207618Srdivacky if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false)) 1830198090Srdivacky return I; 1831193323Sed break; 1832198090Srdivacky case ISD::SRA: 1833207618Srdivacky if (SDNode *I = SelectV6T2BitfieldExtractOp(N, true)) 1834198090Srdivacky return I; 1835198090Srdivacky break; 1836193323Sed case ISD::MUL: 1837198090Srdivacky if (Subtarget->isThumb1Only()) 1838193323Sed break; 1839202375Srdivacky if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) { 1840193323Sed unsigned RHSV = C->getZExtValue(); 1841193323Sed if (!RHSV) break; 1842193323Sed if (isPowerOf2_32(RHSV-1)) { // 2^n+1? 1843198090Srdivacky unsigned ShImm = Log2_32(RHSV-1); 1844198090Srdivacky if (ShImm >= 32) 1845198090Srdivacky break; 1846202375Srdivacky SDValue V = N->getOperand(0); 1847198090Srdivacky ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); 1848198090Srdivacky SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); 1849198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1850198090Srdivacky if (Subtarget->isThumb()) { 1851198090Srdivacky SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1852198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops, 6); 1853198090Srdivacky } else { 1854198090Srdivacky SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1855198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 7); 1856198090Srdivacky } 1857193323Sed } 1858193323Sed if (isPowerOf2_32(RHSV+1)) { // 2^n-1? 1859198090Srdivacky unsigned ShImm = Log2_32(RHSV+1); 1860198090Srdivacky if (ShImm >= 32) 1861198090Srdivacky break; 1862202375Srdivacky SDValue V = N->getOperand(0); 1863198090Srdivacky ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); 1864198090Srdivacky SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); 1865198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1866198090Srdivacky if (Subtarget->isThumb()) { 1867210299Sed SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1868210299Sed return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops, 6); 1869198090Srdivacky } else { 1870198090Srdivacky SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1871198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 7); 1872198090Srdivacky } 1873193323Sed } 1874193323Sed } 1875193323Sed break; 1876198396Srdivacky case ISD::AND: { 1877207618Srdivacky // Check for unsigned bitfield extract 1878207618Srdivacky if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false)) 1879207618Srdivacky return I; 1880207618Srdivacky 1881198396Srdivacky // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits 1882198396Srdivacky // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits 1883198396Srdivacky // are entirely contributed by c2 and lower 16-bits are entirely contributed 1884198396Srdivacky // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)). 1885198396Srdivacky // Select it to: "movt x, ((c1 & 0xffff) >> 16) 1886202375Srdivacky EVT VT = N->getValueType(0); 1887198396Srdivacky if (VT != MVT::i32) 1888198396Srdivacky break; 1889198396Srdivacky unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2()) 1890198396Srdivacky ? ARM::t2MOVTi16 1891198396Srdivacky : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0); 1892198396Srdivacky if (!Opc) 1893198396Srdivacky break; 1894202375Srdivacky SDValue N0 = N->getOperand(0), N1 = N->getOperand(1); 1895198396Srdivacky ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); 1896198396Srdivacky if (!N1C) 1897198396Srdivacky break; 1898198396Srdivacky if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) { 1899198396Srdivacky SDValue N2 = N0.getOperand(1); 1900198396Srdivacky ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2); 1901198396Srdivacky if (!N2C) 1902198396Srdivacky break; 1903198396Srdivacky unsigned N1CVal = N1C->getZExtValue(); 1904198396Srdivacky unsigned N2CVal = N2C->getZExtValue(); 1905198396Srdivacky if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) && 1906198396Srdivacky (N1CVal & 0xffffU) == 0xffffU && 1907198396Srdivacky (N2CVal & 0xffffU) == 0x0U) { 1908198396Srdivacky SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16, 1909198396Srdivacky MVT::i32); 1910198396Srdivacky SDValue Ops[] = { N0.getOperand(0), Imm16, 1911198396Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; 1912198396Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, Ops, 4); 1913198396Srdivacky } 1914198396Srdivacky } 1915198396Srdivacky break; 1916198396Srdivacky } 1917199481Srdivacky case ARMISD::VMOVRRD: 1918199481Srdivacky return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32, 1919202375Srdivacky N->getOperand(0), getAL(CurDAG), 1920198090Srdivacky CurDAG->getRegister(0, MVT::i32)); 1921193323Sed case ISD::UMUL_LOHI: { 1922198090Srdivacky if (Subtarget->isThumb1Only()) 1923198090Srdivacky break; 1924198090Srdivacky if (Subtarget->isThumb()) { 1925202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 1926193323Sed getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1927193323Sed CurDAG->getRegister(0, MVT::i32) }; 1928210299Sed return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32,Ops,4); 1929198090Srdivacky } else { 1930202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 1931198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1932198090Srdivacky CurDAG->getRegister(0, MVT::i32) }; 1933198090Srdivacky return CurDAG->getMachineNode(ARM::UMULL, dl, MVT::i32, MVT::i32, Ops, 5); 1934198090Srdivacky } 1935193323Sed } 1936193323Sed case ISD::SMUL_LOHI: { 1937198090Srdivacky if (Subtarget->isThumb1Only()) 1938198090Srdivacky break; 1939198090Srdivacky if (Subtarget->isThumb()) { 1940202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 1941198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; 1942210299Sed return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32,Ops,4); 1943198090Srdivacky } else { 1944202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 1945193323Sed getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1946193323Sed CurDAG->getRegister(0, MVT::i32) }; 1947198090Srdivacky return CurDAG->getMachineNode(ARM::SMULL, dl, MVT::i32, MVT::i32, Ops, 5); 1948198090Srdivacky } 1949193323Sed } 1950193323Sed case ISD::LOAD: { 1951195340Sed SDNode *ResNode = 0; 1952198090Srdivacky if (Subtarget->isThumb() && Subtarget->hasThumb2()) 1953202375Srdivacky ResNode = SelectT2IndexedLoad(N); 1954195340Sed else 1955202375Srdivacky ResNode = SelectARMIndexedLoad(N); 1956195340Sed if (ResNode) 1957195340Sed return ResNode; 1958193323Sed // Other cases are autogenerated. 1959193323Sed break; 1960193323Sed } 1961193323Sed case ARMISD::BRCOND: { 1962193323Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 1963193323Sed // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc) 1964193323Sed // Pattern complexity = 6 cost = 1 size = 0 1965193323Sed 1966193323Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 1967193323Sed // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc) 1968193323Sed // Pattern complexity = 6 cost = 1 size = 0 1969193323Sed 1970195340Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 1971195340Sed // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc) 1972195340Sed // Pattern complexity = 6 cost = 1 size = 0 1973195340Sed 1974198090Srdivacky unsigned Opc = Subtarget->isThumb() ? 1975195340Sed ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc; 1976202375Srdivacky SDValue Chain = N->getOperand(0); 1977202375Srdivacky SDValue N1 = N->getOperand(1); 1978202375Srdivacky SDValue N2 = N->getOperand(2); 1979202375Srdivacky SDValue N3 = N->getOperand(3); 1980202375Srdivacky SDValue InFlag = N->getOperand(4); 1981193323Sed assert(N1.getOpcode() == ISD::BasicBlock); 1982193323Sed assert(N2.getOpcode() == ISD::Constant); 1983193323Sed assert(N3.getOpcode() == ISD::Register); 1984193323Sed 1985193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 1986193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 1987193323Sed MVT::i32); 1988193323Sed SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag }; 1989198090Srdivacky SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other, 1990198090Srdivacky MVT::Flag, Ops, 5); 1991193323Sed Chain = SDValue(ResNode, 0); 1992202375Srdivacky if (N->getNumValues() == 2) { 1993193323Sed InFlag = SDValue(ResNode, 1); 1994202375Srdivacky ReplaceUses(SDValue(N, 1), InFlag); 1995193323Sed } 1996202375Srdivacky ReplaceUses(SDValue(N, 0), 1997199511Srdivacky SDValue(Chain.getNode(), Chain.getResNo())); 1998193323Sed return NULL; 1999193323Sed } 2000199989Srdivacky case ARMISD::CMOV: 2001202375Srdivacky return SelectCMOVOp(N); 2002193323Sed case ARMISD::CNEG: { 2003202375Srdivacky EVT VT = N->getValueType(0); 2004202375Srdivacky SDValue N0 = N->getOperand(0); 2005202375Srdivacky SDValue N1 = N->getOperand(1); 2006202375Srdivacky SDValue N2 = N->getOperand(2); 2007202375Srdivacky SDValue N3 = N->getOperand(3); 2008202375Srdivacky SDValue InFlag = N->getOperand(4); 2009193323Sed assert(N2.getOpcode() == ISD::Constant); 2010193323Sed assert(N3.getOpcode() == ISD::Register); 2011193323Sed 2012193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 2013193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 2014193323Sed MVT::i32); 2015193323Sed SDValue Ops[] = { N0, N1, Tmp2, N3, InFlag }; 2016193323Sed unsigned Opc = 0; 2017198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 2018193323Sed default: assert(false && "Illegal conditional move type!"); 2019193323Sed break; 2020193323Sed case MVT::f32: 2021199481Srdivacky Opc = ARM::VNEGScc; 2022193323Sed break; 2023193323Sed case MVT::f64: 2024199481Srdivacky Opc = ARM::VNEGDcc; 2025193323Sed break; 2026193323Sed } 2027202375Srdivacky return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5); 2028193323Sed } 2029193323Sed 2030198090Srdivacky case ARMISD::VZIP: { 2031198090Srdivacky unsigned Opc = 0; 2032198090Srdivacky EVT VT = N->getValueType(0); 2033198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 2034198090Srdivacky default: return NULL; 2035198090Srdivacky case MVT::v8i8: Opc = ARM::VZIPd8; break; 2036198090Srdivacky case MVT::v4i16: Opc = ARM::VZIPd16; break; 2037198090Srdivacky case MVT::v2f32: 2038198090Srdivacky case MVT::v2i32: Opc = ARM::VZIPd32; break; 2039198090Srdivacky case MVT::v16i8: Opc = ARM::VZIPq8; break; 2040198090Srdivacky case MVT::v8i16: Opc = ARM::VZIPq16; break; 2041198090Srdivacky case MVT::v4f32: 2042198090Srdivacky case MVT::v4i32: Opc = ARM::VZIPq32; break; 2043193323Sed } 2044207618Srdivacky SDValue Pred = getAL(CurDAG); 2045199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 2046199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 2047199989Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); 2048198090Srdivacky } 2049198090Srdivacky case ARMISD::VUZP: { 2050198090Srdivacky unsigned Opc = 0; 2051198090Srdivacky EVT VT = N->getValueType(0); 2052198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 2053198090Srdivacky default: return NULL; 2054198090Srdivacky case MVT::v8i8: Opc = ARM::VUZPd8; break; 2055198090Srdivacky case MVT::v4i16: Opc = ARM::VUZPd16; break; 2056198090Srdivacky case MVT::v2f32: 2057198090Srdivacky case MVT::v2i32: Opc = ARM::VUZPd32; break; 2058198090Srdivacky case MVT::v16i8: Opc = ARM::VUZPq8; break; 2059198090Srdivacky case MVT::v8i16: Opc = ARM::VUZPq16; break; 2060198090Srdivacky case MVT::v4f32: 2061198090Srdivacky case MVT::v4i32: Opc = ARM::VUZPq32; break; 2062193323Sed } 2063207618Srdivacky SDValue Pred = getAL(CurDAG); 2064199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 2065199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 2066199989Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); 2067198090Srdivacky } 2068198090Srdivacky case ARMISD::VTRN: { 2069198090Srdivacky unsigned Opc = 0; 2070198090Srdivacky EVT VT = N->getValueType(0); 2071198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 2072198090Srdivacky default: return NULL; 2073198090Srdivacky case MVT::v8i8: Opc = ARM::VTRNd8; break; 2074198090Srdivacky case MVT::v4i16: Opc = ARM::VTRNd16; break; 2075198090Srdivacky case MVT::v2f32: 2076198090Srdivacky case MVT::v2i32: Opc = ARM::VTRNd32; break; 2077198090Srdivacky case MVT::v16i8: Opc = ARM::VTRNq8; break; 2078198090Srdivacky case MVT::v8i16: Opc = ARM::VTRNq16; break; 2079198090Srdivacky case MVT::v4f32: 2080198090Srdivacky case MVT::v4i32: Opc = ARM::VTRNq32; break; 2081193323Sed } 2082207618Srdivacky SDValue Pred = getAL(CurDAG); 2083199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 2084199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 2085199989Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); 2086193323Sed } 2087210299Sed case ARMISD::BUILD_VECTOR: { 2088210299Sed EVT VecVT = N->getValueType(0); 2089210299Sed EVT EltVT = VecVT.getVectorElementType(); 2090210299Sed unsigned NumElts = VecVT.getVectorNumElements(); 2091210299Sed if (EltVT.getSimpleVT() == MVT::f64) { 2092210299Sed assert(NumElts == 2 && "unexpected type for BUILD_VECTOR"); 2093210299Sed return PairDRegs(VecVT, N->getOperand(0), N->getOperand(1)); 2094210299Sed } 2095210299Sed assert(EltVT.getSimpleVT() == MVT::f32 && 2096210299Sed "unexpected type for BUILD_VECTOR"); 2097210299Sed if (NumElts == 2) 2098210299Sed return PairSRegs(VecVT, N->getOperand(0), N->getOperand(1)); 2099210299Sed assert(NumElts == 4 && "unexpected type for BUILD_VECTOR"); 2100210299Sed return QuadSRegs(VecVT, N->getOperand(0), N->getOperand(1), 2101210299Sed N->getOperand(2), N->getOperand(3)); 2102210299Sed } 2103194710Sed 2104198090Srdivacky case ISD::INTRINSIC_VOID: 2105198090Srdivacky case ISD::INTRINSIC_W_CHAIN: { 2106198090Srdivacky unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue(); 2107198090Srdivacky switch (IntNo) { 2108198090Srdivacky default: 2109198090Srdivacky break; 2110194710Sed 2111206083Srdivacky case Intrinsic::arm_neon_vld1: { 2112206083Srdivacky unsigned DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16, 2113206083Srdivacky ARM::VLD1d32, ARM::VLD1d64 }; 2114212904Sdim unsigned QOpcodes[] = { ARM::VLD1q8Pseudo, ARM::VLD1q16Pseudo, 2115212904Sdim ARM::VLD1q32Pseudo, ARM::VLD1q64Pseudo }; 2116206083Srdivacky return SelectVLD(N, 1, DOpcodes, QOpcodes, 0); 2117206083Srdivacky } 2118206083Srdivacky 2119198090Srdivacky case Intrinsic::arm_neon_vld2: { 2120212904Sdim unsigned DOpcodes[] = { ARM::VLD2d8Pseudo, ARM::VLD2d16Pseudo, 2121212904Sdim ARM::VLD2d32Pseudo, ARM::VLD1q64Pseudo }; 2122212904Sdim unsigned QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo, 2123212904Sdim ARM::VLD2q32Pseudo }; 2124202375Srdivacky return SelectVLD(N, 2, DOpcodes, QOpcodes, 0); 2125198090Srdivacky } 2126194710Sed 2127198090Srdivacky case Intrinsic::arm_neon_vld3: { 2128212904Sdim unsigned DOpcodes[] = { ARM::VLD3d8Pseudo, ARM::VLD3d16Pseudo, 2129212904Sdim ARM::VLD3d32Pseudo, ARM::VLD1d64TPseudo }; 2130212904Sdim unsigned QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD, 2131212904Sdim ARM::VLD3q16Pseudo_UPD, 2132212904Sdim ARM::VLD3q32Pseudo_UPD }; 2133212904Sdim unsigned QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD, 2134212904Sdim ARM::VLD3q16oddPseudo_UPD, 2135212904Sdim ARM::VLD3q32oddPseudo_UPD }; 2136202375Srdivacky return SelectVLD(N, 3, DOpcodes, QOpcodes0, QOpcodes1); 2137198090Srdivacky } 2138198090Srdivacky 2139198090Srdivacky case Intrinsic::arm_neon_vld4: { 2140212904Sdim unsigned DOpcodes[] = { ARM::VLD4d8Pseudo, ARM::VLD4d16Pseudo, 2141212904Sdim ARM::VLD4d32Pseudo, ARM::VLD1d64QPseudo }; 2142212904Sdim unsigned QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD, 2143212904Sdim ARM::VLD4q16Pseudo_UPD, 2144212904Sdim ARM::VLD4q32Pseudo_UPD }; 2145212904Sdim unsigned QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD, 2146212904Sdim ARM::VLD4q16oddPseudo_UPD, 2147212904Sdim ARM::VLD4q32oddPseudo_UPD }; 2148202375Srdivacky return SelectVLD(N, 4, DOpcodes, QOpcodes0, QOpcodes1); 2149198090Srdivacky } 2150198090Srdivacky 2151198090Srdivacky case Intrinsic::arm_neon_vld2lane: { 2152198090Srdivacky unsigned DOpcodes[] = { ARM::VLD2LNd8, ARM::VLD2LNd16, ARM::VLD2LNd32 }; 2153205407Srdivacky unsigned QOpcodes0[] = { ARM::VLD2LNq16, ARM::VLD2LNq32 }; 2154205407Srdivacky unsigned QOpcodes1[] = { ARM::VLD2LNq16odd, ARM::VLD2LNq32odd }; 2155202375Srdivacky return SelectVLDSTLane(N, true, 2, DOpcodes, QOpcodes0, QOpcodes1); 2156198090Srdivacky } 2157198090Srdivacky 2158198090Srdivacky case Intrinsic::arm_neon_vld3lane: { 2159198090Srdivacky unsigned DOpcodes[] = { ARM::VLD3LNd8, ARM::VLD3LNd16, ARM::VLD3LNd32 }; 2160205407Srdivacky unsigned QOpcodes0[] = { ARM::VLD3LNq16, ARM::VLD3LNq32 }; 2161205407Srdivacky unsigned QOpcodes1[] = { ARM::VLD3LNq16odd, ARM::VLD3LNq32odd }; 2162202375Srdivacky return SelectVLDSTLane(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1); 2163198090Srdivacky } 2164198090Srdivacky 2165198090Srdivacky case Intrinsic::arm_neon_vld4lane: { 2166198090Srdivacky unsigned DOpcodes[] = { ARM::VLD4LNd8, ARM::VLD4LNd16, ARM::VLD4LNd32 }; 2167205407Srdivacky unsigned QOpcodes0[] = { ARM::VLD4LNq16, ARM::VLD4LNq32 }; 2168205407Srdivacky unsigned QOpcodes1[] = { ARM::VLD4LNq16odd, ARM::VLD4LNq32odd }; 2169202375Srdivacky return SelectVLDSTLane(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1); 2170198090Srdivacky } 2171198090Srdivacky 2172206083Srdivacky case Intrinsic::arm_neon_vst1: { 2173206083Srdivacky unsigned DOpcodes[] = { ARM::VST1d8, ARM::VST1d16, 2174206083Srdivacky ARM::VST1d32, ARM::VST1d64 }; 2175212904Sdim unsigned QOpcodes[] = { ARM::VST1q8Pseudo, ARM::VST1q16Pseudo, 2176212904Sdim ARM::VST1q32Pseudo, ARM::VST1q64Pseudo }; 2177206083Srdivacky return SelectVST(N, 1, DOpcodes, QOpcodes, 0); 2178206083Srdivacky } 2179206083Srdivacky 2180198090Srdivacky case Intrinsic::arm_neon_vst2: { 2181212904Sdim unsigned DOpcodes[] = { ARM::VST2d8Pseudo, ARM::VST2d16Pseudo, 2182212904Sdim ARM::VST2d32Pseudo, ARM::VST1q64Pseudo }; 2183212904Sdim unsigned QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo, 2184212904Sdim ARM::VST2q32Pseudo }; 2185202375Srdivacky return SelectVST(N, 2, DOpcodes, QOpcodes, 0); 2186198090Srdivacky } 2187194710Sed 2188198090Srdivacky case Intrinsic::arm_neon_vst3: { 2189212904Sdim unsigned DOpcodes[] = { ARM::VST3d8Pseudo, ARM::VST3d16Pseudo, 2190212904Sdim ARM::VST3d32Pseudo, ARM::VST1d64TPseudo }; 2191212904Sdim unsigned QOpcodes0[] = { ARM::VST3q8Pseudo_UPD, 2192212904Sdim ARM::VST3q16Pseudo_UPD, 2193212904Sdim ARM::VST3q32Pseudo_UPD }; 2194212904Sdim unsigned QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD, 2195212904Sdim ARM::VST3q16oddPseudo_UPD, 2196212904Sdim ARM::VST3q32oddPseudo_UPD }; 2197202375Srdivacky return SelectVST(N, 3, DOpcodes, QOpcodes0, QOpcodes1); 2198194710Sed } 2199194710Sed 2200198090Srdivacky case Intrinsic::arm_neon_vst4: { 2201212904Sdim unsigned DOpcodes[] = { ARM::VST4d8Pseudo, ARM::VST4d16Pseudo, 2202212904Sdim ARM::VST4d32Pseudo, ARM::VST1d64QPseudo }; 2203212904Sdim unsigned QOpcodes0[] = { ARM::VST4q8Pseudo_UPD, 2204212904Sdim ARM::VST4q16Pseudo_UPD, 2205212904Sdim ARM::VST4q32Pseudo_UPD }; 2206212904Sdim unsigned QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD, 2207212904Sdim ARM::VST4q16oddPseudo_UPD, 2208212904Sdim ARM::VST4q32oddPseudo_UPD }; 2209202375Srdivacky return SelectVST(N, 4, DOpcodes, QOpcodes0, QOpcodes1); 2210198090Srdivacky } 2211198090Srdivacky 2212198090Srdivacky case Intrinsic::arm_neon_vst2lane: { 2213198090Srdivacky unsigned DOpcodes[] = { ARM::VST2LNd8, ARM::VST2LNd16, ARM::VST2LNd32 }; 2214205407Srdivacky unsigned QOpcodes0[] = { ARM::VST2LNq16, ARM::VST2LNq32 }; 2215205407Srdivacky unsigned QOpcodes1[] = { ARM::VST2LNq16odd, ARM::VST2LNq32odd }; 2216202375Srdivacky return SelectVLDSTLane(N, false, 2, DOpcodes, QOpcodes0, QOpcodes1); 2217198090Srdivacky } 2218198090Srdivacky 2219198090Srdivacky case Intrinsic::arm_neon_vst3lane: { 2220198090Srdivacky unsigned DOpcodes[] = { ARM::VST3LNd8, ARM::VST3LNd16, ARM::VST3LNd32 }; 2221205407Srdivacky unsigned QOpcodes0[] = { ARM::VST3LNq16, ARM::VST3LNq32 }; 2222205407Srdivacky unsigned QOpcodes1[] = { ARM::VST3LNq16odd, ARM::VST3LNq32odd }; 2223202375Srdivacky return SelectVLDSTLane(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1); 2224198090Srdivacky } 2225198090Srdivacky 2226198090Srdivacky case Intrinsic::arm_neon_vst4lane: { 2227198090Srdivacky unsigned DOpcodes[] = { ARM::VST4LNd8, ARM::VST4LNd16, ARM::VST4LNd32 }; 2228205407Srdivacky unsigned QOpcodes0[] = { ARM::VST4LNq16, ARM::VST4LNq32 }; 2229205407Srdivacky unsigned QOpcodes1[] = { ARM::VST4LNq16odd, ARM::VST4LNq32odd }; 2230202375Srdivacky return SelectVLDSTLane(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1); 2231198090Srdivacky } 2232198090Srdivacky } 2233208599Srdivacky break; 2234194710Sed } 2235208599Srdivacky 2236210299Sed case ISD::INTRINSIC_WO_CHAIN: { 2237210299Sed unsigned IntNo = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue(); 2238210299Sed switch (IntNo) { 2239210299Sed default: 2240210299Sed break; 2241210299Sed 2242210299Sed case Intrinsic::arm_neon_vtbl2: 2243210299Sed return SelectVTBL(N, false, 2, ARM::VTBL2); 2244210299Sed case Intrinsic::arm_neon_vtbl3: 2245210299Sed return SelectVTBL(N, false, 3, ARM::VTBL3); 2246210299Sed case Intrinsic::arm_neon_vtbl4: 2247210299Sed return SelectVTBL(N, false, 4, ARM::VTBL4); 2248210299Sed 2249210299Sed case Intrinsic::arm_neon_vtbx2: 2250210299Sed return SelectVTBL(N, true, 2, ARM::VTBX2); 2251210299Sed case Intrinsic::arm_neon_vtbx3: 2252210299Sed return SelectVTBL(N, true, 3, ARM::VTBX3); 2253210299Sed case Intrinsic::arm_neon_vtbx4: 2254210299Sed return SelectVTBL(N, true, 4, ARM::VTBX4); 2255210299Sed } 2256210299Sed break; 2257210299Sed } 2258210299Sed 2259208599Srdivacky case ISD::CONCAT_VECTORS: 2260208599Srdivacky return SelectConcatVector(N); 2261194710Sed } 2262194710Sed 2263202375Srdivacky return SelectCode(N); 2264193323Sed} 2265193323Sed 2266193323Sedbool ARMDAGToDAGISel:: 2267193323SedSelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, 2268193323Sed std::vector<SDValue> &OutOps) { 2269193323Sed assert(ConstraintCode == 'm' && "unexpected asm memory constraint"); 2270198090Srdivacky // Require the address to be in a register. That is safe for all ARM 2271198090Srdivacky // variants and it is hard to do anything much smarter without knowing 2272198090Srdivacky // how the operand is used. 2273198090Srdivacky OutOps.push_back(Op); 2274193323Sed return false; 2275193323Sed} 2276193323Sed 2277193323Sed/// createARMISelDag - This pass converts a legalized DAG into a 2278193323Sed/// ARM-specific DAG, ready for instruction scheduling. 2279193323Sed/// 2280198090SrdivackyFunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM, 2281198090Srdivacky CodeGenOpt::Level OptLevel) { 2282198090Srdivacky return new ARMDAGToDAGISel(TM, OptLevel); 2283193323Sed} 2284