ARMISelDAGToDAG.cpp revision 208599
1193323Sed//===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file defines an instruction selector for the ARM target. 11193323Sed// 12193323Sed//===----------------------------------------------------------------------===// 13193323Sed 14193323Sed#include "ARM.h" 15193323Sed#include "ARMAddressingModes.h" 16193323Sed#include "ARMTargetMachine.h" 17193323Sed#include "llvm/CallingConv.h" 18193323Sed#include "llvm/Constants.h" 19193323Sed#include "llvm/DerivedTypes.h" 20193323Sed#include "llvm/Function.h" 21193323Sed#include "llvm/Intrinsics.h" 22198090Srdivacky#include "llvm/LLVMContext.h" 23193323Sed#include "llvm/CodeGen/MachineFrameInfo.h" 24193323Sed#include "llvm/CodeGen/MachineFunction.h" 25193323Sed#include "llvm/CodeGen/MachineInstrBuilder.h" 26193323Sed#include "llvm/CodeGen/SelectionDAG.h" 27193323Sed#include "llvm/CodeGen/SelectionDAGISel.h" 28193323Sed#include "llvm/Target/TargetLowering.h" 29193323Sed#include "llvm/Target/TargetOptions.h" 30207631Srdivacky#include "llvm/Support/CommandLine.h" 31193323Sed#include "llvm/Support/Compiler.h" 32193323Sed#include "llvm/Support/Debug.h" 33198090Srdivacky#include "llvm/Support/ErrorHandling.h" 34198090Srdivacky#include "llvm/Support/raw_ostream.h" 35198090Srdivacky 36193323Sedusing namespace llvm; 37193323Sed 38207631Srdivackystatic cl::opt<bool> 39207631SrdivackyUseRegSeq("neon-reg-sequence", cl::Hidden, 40208599Srdivacky cl::desc("Use reg_sequence to model ld / st of multiple neon regs"), 41208599Srdivacky cl::init(true)); 42207631Srdivacky 43193323Sed//===--------------------------------------------------------------------===// 44193323Sed/// ARMDAGToDAGISel - ARM specific code to select ARM machine 45193323Sed/// instructions for SelectionDAG operations. 46193323Sed/// 47193323Sednamespace { 48193323Sedclass ARMDAGToDAGISel : public SelectionDAGISel { 49195098Sed ARMBaseTargetMachine &TM; 50193323Sed 51193323Sed /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can 52193323Sed /// make the right decision when generating code for different targets. 53193323Sed const ARMSubtarget *Subtarget; 54193323Sed 55193323Sedpublic: 56198090Srdivacky explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm, 57198090Srdivacky CodeGenOpt::Level OptLevel) 58198090Srdivacky : SelectionDAGISel(tm, OptLevel), TM(tm), 59193323Sed Subtarget(&TM.getSubtarget<ARMSubtarget>()) { 60193323Sed } 61193323Sed 62193323Sed virtual const char *getPassName() const { 63193323Sed return "ARM Instruction Selection"; 64194612Sed } 65194612Sed 66198090Srdivacky /// getI32Imm - Return a target constant of type i32 with the specified 67198090Srdivacky /// value. 68194612Sed inline SDValue getI32Imm(unsigned Imm) { 69194612Sed return CurDAG->getTargetConstant(Imm, MVT::i32); 70194612Sed } 71194612Sed 72202375Srdivacky SDNode *Select(SDNode *N); 73203954Srdivacky 74202375Srdivacky bool SelectShifterOperandReg(SDNode *Op, SDValue N, SDValue &A, 75195340Sed SDValue &B, SDValue &C); 76202375Srdivacky bool SelectAddrMode2(SDNode *Op, SDValue N, SDValue &Base, 77193323Sed SDValue &Offset, SDValue &Opc); 78202375Srdivacky bool SelectAddrMode2Offset(SDNode *Op, SDValue N, 79193323Sed SDValue &Offset, SDValue &Opc); 80202375Srdivacky bool SelectAddrMode3(SDNode *Op, SDValue N, SDValue &Base, 81193323Sed SDValue &Offset, SDValue &Opc); 82202375Srdivacky bool SelectAddrMode3Offset(SDNode *Op, SDValue N, 83193323Sed SDValue &Offset, SDValue &Opc); 84202375Srdivacky bool SelectAddrMode4(SDNode *Op, SDValue N, SDValue &Addr, 85198090Srdivacky SDValue &Mode); 86202375Srdivacky bool SelectAddrMode5(SDNode *Op, SDValue N, SDValue &Base, 87193323Sed SDValue &Offset); 88205407Srdivacky bool SelectAddrMode6(SDNode *Op, SDValue N, SDValue &Addr, SDValue &Align); 89193323Sed 90202375Srdivacky bool SelectAddrModePC(SDNode *Op, SDValue N, SDValue &Offset, 91195340Sed SDValue &Label); 92193323Sed 93202375Srdivacky bool SelectThumbAddrModeRR(SDNode *Op, SDValue N, SDValue &Base, 94193323Sed SDValue &Offset); 95202375Srdivacky bool SelectThumbAddrModeRI5(SDNode *Op, SDValue N, unsigned Scale, 96193323Sed SDValue &Base, SDValue &OffImm, 97193323Sed SDValue &Offset); 98202375Srdivacky bool SelectThumbAddrModeS1(SDNode *Op, SDValue N, SDValue &Base, 99193323Sed SDValue &OffImm, SDValue &Offset); 100202375Srdivacky bool SelectThumbAddrModeS2(SDNode *Op, SDValue N, SDValue &Base, 101193323Sed SDValue &OffImm, SDValue &Offset); 102202375Srdivacky bool SelectThumbAddrModeS4(SDNode *Op, SDValue N, SDValue &Base, 103193323Sed SDValue &OffImm, SDValue &Offset); 104202375Srdivacky bool SelectThumbAddrModeSP(SDNode *Op, SDValue N, SDValue &Base, 105193323Sed SDValue &OffImm); 106193323Sed 107202375Srdivacky bool SelectT2ShifterOperandReg(SDNode *Op, SDValue N, 108195098Sed SDValue &BaseReg, SDValue &Opc); 109202375Srdivacky bool SelectT2AddrModeImm12(SDNode *Op, SDValue N, SDValue &Base, 110195340Sed SDValue &OffImm); 111202375Srdivacky bool SelectT2AddrModeImm8(SDNode *Op, SDValue N, SDValue &Base, 112195340Sed SDValue &OffImm); 113202375Srdivacky bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N, 114195340Sed SDValue &OffImm); 115202375Srdivacky bool SelectT2AddrModeImm8s4(SDNode *Op, SDValue N, SDValue &Base, 116195340Sed SDValue &OffImm); 117202375Srdivacky bool SelectT2AddrModeSoReg(SDNode *Op, SDValue N, SDValue &Base, 118195340Sed SDValue &OffReg, SDValue &ShImm); 119195340Sed 120193323Sed // Include the pieces autogenerated from the target description. 121193323Sed#include "ARMGenDAGISel.inc" 122193323Sed 123193323Sedprivate: 124195340Sed /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for 125195340Sed /// ARM. 126202375Srdivacky SDNode *SelectARMIndexedLoad(SDNode *N); 127202375Srdivacky SDNode *SelectT2IndexedLoad(SDNode *N); 128195340Sed 129206083Srdivacky /// SelectVLD - Select NEON load intrinsics. NumVecs should be 130206083Srdivacky /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for 131198090Srdivacky /// loads of D registers and even subregs and odd subregs of Q registers. 132206083Srdivacky /// For NumVecs <= 2, QOpcodes1 is not used. 133202375Srdivacky SDNode *SelectVLD(SDNode *N, unsigned NumVecs, unsigned *DOpcodes, 134198090Srdivacky unsigned *QOpcodes0, unsigned *QOpcodes1); 135198090Srdivacky 136198113Srdivacky /// SelectVST - Select NEON store intrinsics. NumVecs should 137206083Srdivacky /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for 138198113Srdivacky /// stores of D registers and even subregs and odd subregs of Q registers. 139206083Srdivacky /// For NumVecs <= 2, QOpcodes1 is not used. 140202375Srdivacky SDNode *SelectVST(SDNode *N, unsigned NumVecs, unsigned *DOpcodes, 141198113Srdivacky unsigned *QOpcodes0, unsigned *QOpcodes1); 142198113Srdivacky 143198090Srdivacky /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should 144198090Srdivacky /// be 2, 3 or 4. The opcode arrays specify the instructions used for 145198090Srdivacky /// load/store of D registers and even subregs and odd subregs of Q registers. 146202375Srdivacky SDNode *SelectVLDSTLane(SDNode *N, bool IsLoad, unsigned NumVecs, 147198090Srdivacky unsigned *DOpcodes, unsigned *QOpcodes0, 148198090Srdivacky unsigned *QOpcodes1); 149198090Srdivacky 150198090Srdivacky /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM. 151207618Srdivacky SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, bool isSigned); 152198090Srdivacky 153199989Srdivacky /// SelectCMOVOp - Select CMOV instructions for ARM. 154202375Srdivacky SDNode *SelectCMOVOp(SDNode *N); 155202375Srdivacky SDNode *SelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 156199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 157199989Srdivacky SDValue InFlag); 158202375Srdivacky SDNode *SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 159199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 160199989Srdivacky SDValue InFlag); 161202375Srdivacky SDNode *SelectT2CMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 162199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 163199989Srdivacky SDValue InFlag); 164202375Srdivacky SDNode *SelectARMCMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 165199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, 166199989Srdivacky SDValue InFlag); 167199989Srdivacky 168208599Srdivacky SDNode *SelectConcatVector(SDNode *N); 169208599Srdivacky 170195340Sed /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for 171195340Sed /// inline asm expressions. 172195340Sed virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, 173195340Sed char ConstraintCode, 174195340Sed std::vector<SDValue> &OutOps); 175198090Srdivacky 176208599Srdivacky /// PairDRegs - Form a quad register from a pair of D registers. 177208599Srdivacky /// 178198090Srdivacky SDNode *PairDRegs(EVT VT, SDValue V0, SDValue V1); 179208599Srdivacky 180208599Srdivacky /// PairDRegs - Form a quad register pair from a pair of Q registers. 181208599Srdivacky /// 182208599Srdivacky SDNode *PairQRegs(EVT VT, SDValue V0, SDValue V1); 183208599Srdivacky 184208599Srdivacky /// QuadDRegs - Form a quad register pair from a quad of D registers. 185208599Srdivacky /// 186208599Srdivacky SDNode *QuadDRegs(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3); 187208599Srdivacky 188208599Srdivacky /// QuadQRegs - Form 4 consecutive Q registers. 189208599Srdivacky /// 190208599Srdivacky SDNode *QuadQRegs(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3); 191208599Srdivacky 192208599Srdivacky /// OctoDRegs - Form 8 consecutive D registers. 193208599Srdivacky /// 194208599Srdivacky SDNode *OctoDRegs(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3, 195208599Srdivacky SDValue V4, SDValue V5, SDValue V6, SDValue V7); 196193323Sed}; 197193323Sed} 198193323Sed 199198090Srdivacky/// isInt32Immediate - This method tests to see if the node is a 32-bit constant 200198090Srdivacky/// operand. If so Imm will receive the 32-bit value. 201198090Srdivackystatic bool isInt32Immediate(SDNode *N, unsigned &Imm) { 202198090Srdivacky if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) { 203198090Srdivacky Imm = cast<ConstantSDNode>(N)->getZExtValue(); 204198090Srdivacky return true; 205198090Srdivacky } 206198090Srdivacky return false; 207198090Srdivacky} 208198090Srdivacky 209198090Srdivacky// isInt32Immediate - This method tests to see if a constant operand. 210198090Srdivacky// If so Imm will receive the 32 bit value. 211198090Srdivackystatic bool isInt32Immediate(SDValue N, unsigned &Imm) { 212198090Srdivacky return isInt32Immediate(N.getNode(), Imm); 213198090Srdivacky} 214198090Srdivacky 215198090Srdivacky// isOpcWithIntImmediate - This method tests to see if the node is a specific 216198090Srdivacky// opcode and that it has a immediate integer right operand. 217198090Srdivacky// If so Imm will receive the 32 bit value. 218198090Srdivackystatic bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) { 219198090Srdivacky return N->getOpcode() == Opc && 220198090Srdivacky isInt32Immediate(N->getOperand(1).getNode(), Imm); 221198090Srdivacky} 222198090Srdivacky 223198090Srdivacky 224202375Srdivackybool ARMDAGToDAGISel::SelectShifterOperandReg(SDNode *Op, 225195340Sed SDValue N, 226195340Sed SDValue &BaseReg, 227195340Sed SDValue &ShReg, 228195340Sed SDValue &Opc) { 229195340Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 230195340Sed 231195340Sed // Don't match base register only case. That is matched to a separate 232195340Sed // lower complexity pattern with explicit register operand. 233195340Sed if (ShOpcVal == ARM_AM::no_shift) return false; 234198090Srdivacky 235195340Sed BaseReg = N.getOperand(0); 236195340Sed unsigned ShImmVal = 0; 237195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 238195340Sed ShReg = CurDAG->getRegister(0, MVT::i32); 239195340Sed ShImmVal = RHS->getZExtValue() & 31; 240195340Sed } else { 241195340Sed ShReg = N.getOperand(1); 242195340Sed } 243195340Sed Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), 244195340Sed MVT::i32); 245195340Sed return true; 246195340Sed} 247195340Sed 248202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode2(SDNode *Op, SDValue N, 249193323Sed SDValue &Base, SDValue &Offset, 250193323Sed SDValue &Opc) { 251193323Sed if (N.getOpcode() == ISD::MUL) { 252193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 253193323Sed // X * [3,5,9] -> X + X * [2,4,8] etc. 254193323Sed int RHSC = (int)RHS->getZExtValue(); 255193323Sed if (RHSC & 1) { 256193323Sed RHSC = RHSC & ~1; 257193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 258193323Sed if (RHSC < 0) { 259193323Sed AddSub = ARM_AM::sub; 260193323Sed RHSC = - RHSC; 261193323Sed } 262193323Sed if (isPowerOf2_32(RHSC)) { 263193323Sed unsigned ShAmt = Log2_32(RHSC); 264193323Sed Base = Offset = N.getOperand(0); 265193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, 266193323Sed ARM_AM::lsl), 267193323Sed MVT::i32); 268193323Sed return true; 269193323Sed } 270193323Sed } 271193323Sed } 272193323Sed } 273193323Sed 274193323Sed if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) { 275193323Sed Base = N; 276193323Sed if (N.getOpcode() == ISD::FrameIndex) { 277193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 278193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 279199989Srdivacky } else if (N.getOpcode() == ARMISD::Wrapper && 280199989Srdivacky !(Subtarget->useMovt() && 281199989Srdivacky N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { 282193323Sed Base = N.getOperand(0); 283193323Sed } 284193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 285193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, 286193323Sed ARM_AM::no_shift), 287193323Sed MVT::i32); 288193323Sed return true; 289193323Sed } 290198090Srdivacky 291193323Sed // Match simple R +/- imm12 operands. 292193323Sed if (N.getOpcode() == ISD::ADD) 293193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 294193323Sed int RHSC = (int)RHS->getZExtValue(); 295193323Sed if ((RHSC >= 0 && RHSC < 0x1000) || 296193323Sed (RHSC < 0 && RHSC > -0x1000)) { // 12 bits. 297193323Sed Base = N.getOperand(0); 298193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 299193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 300193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 301193323Sed } 302193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 303193323Sed 304193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 305193323Sed if (RHSC < 0) { 306193323Sed AddSub = ARM_AM::sub; 307193323Sed RHSC = - RHSC; 308193323Sed } 309193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC, 310193323Sed ARM_AM::no_shift), 311193323Sed MVT::i32); 312193323Sed return true; 313193323Sed } 314193323Sed } 315198090Srdivacky 316198892Srdivacky // Otherwise this is R +/- [possibly shifted] R. 317193323Sed ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::ADD ? ARM_AM::add:ARM_AM::sub; 318193323Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1)); 319193323Sed unsigned ShAmt = 0; 320198090Srdivacky 321193323Sed Base = N.getOperand(0); 322193323Sed Offset = N.getOperand(1); 323198090Srdivacky 324193323Sed if (ShOpcVal != ARM_AM::no_shift) { 325193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 326193323Sed // it. 327193323Sed if (ConstantSDNode *Sh = 328193323Sed dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) { 329193323Sed ShAmt = Sh->getZExtValue(); 330193323Sed Offset = N.getOperand(1).getOperand(0); 331193323Sed } else { 332193323Sed ShOpcVal = ARM_AM::no_shift; 333193323Sed } 334193323Sed } 335198090Srdivacky 336193323Sed // Try matching (R shl C) + (R). 337193323Sed if (N.getOpcode() == ISD::ADD && ShOpcVal == ARM_AM::no_shift) { 338193323Sed ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0)); 339193323Sed if (ShOpcVal != ARM_AM::no_shift) { 340193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't 341193323Sed // fold it. 342193323Sed if (ConstantSDNode *Sh = 343193323Sed dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) { 344193323Sed ShAmt = Sh->getZExtValue(); 345193323Sed Offset = N.getOperand(0).getOperand(0); 346193323Sed Base = N.getOperand(1); 347193323Sed } else { 348193323Sed ShOpcVal = ARM_AM::no_shift; 349193323Sed } 350193323Sed } 351193323Sed } 352198090Srdivacky 353193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 354193323Sed MVT::i32); 355193323Sed return true; 356193323Sed} 357193323Sed 358202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode2Offset(SDNode *Op, SDValue N, 359193323Sed SDValue &Offset, SDValue &Opc) { 360202375Srdivacky unsigned Opcode = Op->getOpcode(); 361193323Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 362193323Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 363193323Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 364193323Sed ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 365193323Sed ? ARM_AM::add : ARM_AM::sub; 366193323Sed if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 367193323Sed int Val = (int)C->getZExtValue(); 368193323Sed if (Val >= 0 && Val < 0x1000) { // 12 bits. 369193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 370193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val, 371193323Sed ARM_AM::no_shift), 372193323Sed MVT::i32); 373193323Sed return true; 374193323Sed } 375193323Sed } 376193323Sed 377193323Sed Offset = N; 378193323Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 379193323Sed unsigned ShAmt = 0; 380193323Sed if (ShOpcVal != ARM_AM::no_shift) { 381193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 382193323Sed // it. 383193323Sed if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 384193323Sed ShAmt = Sh->getZExtValue(); 385193323Sed Offset = N.getOperand(0); 386193323Sed } else { 387193323Sed ShOpcVal = ARM_AM::no_shift; 388193323Sed } 389193323Sed } 390193323Sed 391193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 392193323Sed MVT::i32); 393193323Sed return true; 394193323Sed} 395193323Sed 396193323Sed 397202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode3(SDNode *Op, SDValue N, 398193323Sed SDValue &Base, SDValue &Offset, 399193323Sed SDValue &Opc) { 400193323Sed if (N.getOpcode() == ISD::SUB) { 401193323Sed // X - C is canonicalize to X + -C, no need to handle it here. 402193323Sed Base = N.getOperand(0); 403193323Sed Offset = N.getOperand(1); 404193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32); 405193323Sed return true; 406193323Sed } 407198090Srdivacky 408193323Sed if (N.getOpcode() != ISD::ADD) { 409193323Sed Base = N; 410193323Sed if (N.getOpcode() == ISD::FrameIndex) { 411193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 412193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 413193323Sed } 414193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 415193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32); 416193323Sed return true; 417193323Sed } 418198090Srdivacky 419193323Sed // If the RHS is +/- imm8, fold into addr mode. 420193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 421193323Sed int RHSC = (int)RHS->getZExtValue(); 422193323Sed if ((RHSC >= 0 && RHSC < 256) || 423193323Sed (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed. 424193323Sed Base = N.getOperand(0); 425193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 426193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 427193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 428193323Sed } 429193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 430193323Sed 431193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 432193323Sed if (RHSC < 0) { 433193323Sed AddSub = ARM_AM::sub; 434193323Sed RHSC = - RHSC; 435193323Sed } 436193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32); 437193323Sed return true; 438193323Sed } 439193323Sed } 440198090Srdivacky 441193323Sed Base = N.getOperand(0); 442193323Sed Offset = N.getOperand(1); 443193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32); 444193323Sed return true; 445193323Sed} 446193323Sed 447202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N, 448193323Sed SDValue &Offset, SDValue &Opc) { 449202375Srdivacky unsigned Opcode = Op->getOpcode(); 450193323Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 451193323Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 452193323Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 453193323Sed ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 454193323Sed ? ARM_AM::add : ARM_AM::sub; 455193323Sed if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 456193323Sed int Val = (int)C->getZExtValue(); 457193323Sed if (Val >= 0 && Val < 256) { 458193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 459193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32); 460193323Sed return true; 461193323Sed } 462193323Sed } 463193323Sed 464193323Sed Offset = N; 465193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32); 466193323Sed return true; 467193323Sed} 468193323Sed 469202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode4(SDNode *Op, SDValue N, 470198090Srdivacky SDValue &Addr, SDValue &Mode) { 471198090Srdivacky Addr = N; 472198090Srdivacky Mode = CurDAG->getTargetConstant(0, MVT::i32); 473198090Srdivacky return true; 474198090Srdivacky} 475193323Sed 476202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode5(SDNode *Op, SDValue N, 477193323Sed SDValue &Base, SDValue &Offset) { 478193323Sed if (N.getOpcode() != ISD::ADD) { 479193323Sed Base = N; 480193323Sed if (N.getOpcode() == ISD::FrameIndex) { 481193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 482193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 483199989Srdivacky } else if (N.getOpcode() == ARMISD::Wrapper && 484199989Srdivacky !(Subtarget->useMovt() && 485199989Srdivacky N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { 486193323Sed Base = N.getOperand(0); 487193323Sed } 488193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 489193323Sed MVT::i32); 490193323Sed return true; 491193323Sed } 492198090Srdivacky 493193323Sed // If the RHS is +/- imm8, fold into addr mode. 494193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 495193323Sed int RHSC = (int)RHS->getZExtValue(); 496193323Sed if ((RHSC & 3) == 0) { // The constant is implicitly multiplied by 4. 497193323Sed RHSC >>= 2; 498193323Sed if ((RHSC >= 0 && RHSC < 256) || 499193323Sed (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed. 500193323Sed Base = N.getOperand(0); 501193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 502193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 503193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 504193323Sed } 505193323Sed 506193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 507193323Sed if (RHSC < 0) { 508193323Sed AddSub = ARM_AM::sub; 509193323Sed RHSC = - RHSC; 510193323Sed } 511193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC), 512193323Sed MVT::i32); 513193323Sed return true; 514193323Sed } 515193323Sed } 516193323Sed } 517198090Srdivacky 518193323Sed Base = N; 519193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 520193323Sed MVT::i32); 521193323Sed return true; 522193323Sed} 523193323Sed 524202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Op, SDValue N, 525205407Srdivacky SDValue &Addr, SDValue &Align) { 526195340Sed Addr = N; 527199481Srdivacky // Default to no alignment. 528199481Srdivacky Align = CurDAG->getTargetConstant(0, MVT::i32); 529195340Sed return true; 530195340Sed} 531195340Sed 532202375Srdivackybool ARMDAGToDAGISel::SelectAddrModePC(SDNode *Op, SDValue N, 533198090Srdivacky SDValue &Offset, SDValue &Label) { 534193323Sed if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) { 535193323Sed Offset = N.getOperand(0); 536193323Sed SDValue N1 = N.getOperand(1); 537193323Sed Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(), 538193323Sed MVT::i32); 539193323Sed return true; 540193323Sed } 541193323Sed return false; 542193323Sed} 543193323Sed 544202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDNode *Op, SDValue N, 545193323Sed SDValue &Base, SDValue &Offset){ 546193323Sed // FIXME dl should come from the parent load or store, not the address 547202375Srdivacky DebugLoc dl = Op->getDebugLoc(); 548193323Sed if (N.getOpcode() != ISD::ADD) { 549198090Srdivacky ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N); 550198090Srdivacky if (!NC || NC->getZExtValue() != 0) 551198090Srdivacky return false; 552198090Srdivacky 553198090Srdivacky Base = Offset = N; 554193323Sed return true; 555193323Sed } 556193323Sed 557193323Sed Base = N.getOperand(0); 558193323Sed Offset = N.getOperand(1); 559193323Sed return true; 560193323Sed} 561193323Sed 562193323Sedbool 563202375SrdivackyARMDAGToDAGISel::SelectThumbAddrModeRI5(SDNode *Op, SDValue N, 564193323Sed unsigned Scale, SDValue &Base, 565193323Sed SDValue &OffImm, SDValue &Offset) { 566193323Sed if (Scale == 4) { 567193323Sed SDValue TmpBase, TmpOffImm; 568193323Sed if (SelectThumbAddrModeSP(Op, N, TmpBase, TmpOffImm)) 569193323Sed return false; // We want to select tLDRspi / tSTRspi instead. 570193323Sed if (N.getOpcode() == ARMISD::Wrapper && 571193323Sed N.getOperand(0).getOpcode() == ISD::TargetConstantPool) 572193323Sed return false; // We want to select tLDRpci instead. 573193323Sed } 574193323Sed 575193323Sed if (N.getOpcode() != ISD::ADD) { 576199989Srdivacky if (N.getOpcode() == ARMISD::Wrapper && 577199989Srdivacky !(Subtarget->useMovt() && 578199989Srdivacky N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { 579199989Srdivacky Base = N.getOperand(0); 580199989Srdivacky } else 581199989Srdivacky Base = N; 582199989Srdivacky 583193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 584193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 585193323Sed return true; 586193323Sed } 587193323Sed 588193323Sed // Thumb does not have [sp, r] address mode. 589193323Sed RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 590193323Sed RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1)); 591193323Sed if ((LHSR && LHSR->getReg() == ARM::SP) || 592193323Sed (RHSR && RHSR->getReg() == ARM::SP)) { 593193323Sed Base = N; 594193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 595193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 596193323Sed return true; 597193323Sed } 598193323Sed 599193323Sed // If the RHS is + imm5 * scale, fold into addr mode. 600193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 601193323Sed int RHSC = (int)RHS->getZExtValue(); 602193323Sed if ((RHSC & (Scale-1)) == 0) { // The constant is implicitly multiplied. 603193323Sed RHSC /= Scale; 604193323Sed if (RHSC >= 0 && RHSC < 32) { 605193323Sed Base = N.getOperand(0); 606193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 607193323Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 608193323Sed return true; 609193323Sed } 610193323Sed } 611193323Sed } 612193323Sed 613193323Sed Base = N.getOperand(0); 614193323Sed Offset = N.getOperand(1); 615193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 616193323Sed return true; 617193323Sed} 618193323Sed 619202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeS1(SDNode *Op, SDValue N, 620193323Sed SDValue &Base, SDValue &OffImm, 621193323Sed SDValue &Offset) { 622193323Sed return SelectThumbAddrModeRI5(Op, N, 1, Base, OffImm, Offset); 623193323Sed} 624193323Sed 625202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeS2(SDNode *Op, SDValue N, 626193323Sed SDValue &Base, SDValue &OffImm, 627193323Sed SDValue &Offset) { 628193323Sed return SelectThumbAddrModeRI5(Op, N, 2, Base, OffImm, Offset); 629193323Sed} 630193323Sed 631202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeS4(SDNode *Op, SDValue N, 632193323Sed SDValue &Base, SDValue &OffImm, 633193323Sed SDValue &Offset) { 634193323Sed return SelectThumbAddrModeRI5(Op, N, 4, Base, OffImm, Offset); 635193323Sed} 636193323Sed 637202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDNode *Op, SDValue N, 638193323Sed SDValue &Base, SDValue &OffImm) { 639193323Sed if (N.getOpcode() == ISD::FrameIndex) { 640193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 641193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 642193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 643193323Sed return true; 644193323Sed } 645193323Sed 646193323Sed if (N.getOpcode() != ISD::ADD) 647193323Sed return false; 648193323Sed 649193323Sed RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 650193323Sed if (N.getOperand(0).getOpcode() == ISD::FrameIndex || 651193323Sed (LHSR && LHSR->getReg() == ARM::SP)) { 652193323Sed // If the RHS is + imm8 * scale, fold into addr mode. 653193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 654193323Sed int RHSC = (int)RHS->getZExtValue(); 655193323Sed if ((RHSC & 3) == 0) { // The constant is implicitly multiplied. 656193323Sed RHSC >>= 2; 657193323Sed if (RHSC >= 0 && RHSC < 256) { 658193323Sed Base = N.getOperand(0); 659193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 660193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 661193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 662193323Sed } 663193323Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 664193323Sed return true; 665193323Sed } 666193323Sed } 667193323Sed } 668193323Sed } 669198090Srdivacky 670193323Sed return false; 671193323Sed} 672193323Sed 673202375Srdivackybool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDNode *Op, SDValue N, 674195098Sed SDValue &BaseReg, 675195098Sed SDValue &Opc) { 676195098Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 677195098Sed 678195098Sed // Don't match base register only case. That is matched to a separate 679195098Sed // lower complexity pattern with explicit register operand. 680195098Sed if (ShOpcVal == ARM_AM::no_shift) return false; 681195098Sed 682195098Sed BaseReg = N.getOperand(0); 683195098Sed unsigned ShImmVal = 0; 684195098Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 685195098Sed ShImmVal = RHS->getZExtValue() & 31; 686195098Sed Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal)); 687195098Sed return true; 688195098Sed } 689195098Sed 690195098Sed return false; 691195098Sed} 692195098Sed 693202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDNode *Op, SDValue N, 694195340Sed SDValue &Base, SDValue &OffImm) { 695195340Sed // Match simple R + imm12 operands. 696195340Sed 697198090Srdivacky // Base only. 698198090Srdivacky if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) { 699198090Srdivacky if (N.getOpcode() == ISD::FrameIndex) { 700198090Srdivacky // Match frame index... 701198090Srdivacky int FI = cast<FrameIndexSDNode>(N)->getIndex(); 702198090Srdivacky Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 703198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 704198090Srdivacky return true; 705199989Srdivacky } else if (N.getOpcode() == ARMISD::Wrapper && 706199989Srdivacky !(Subtarget->useMovt() && 707199989Srdivacky N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { 708198090Srdivacky Base = N.getOperand(0); 709198090Srdivacky if (Base.getOpcode() == ISD::TargetConstantPool) 710198090Srdivacky return false; // We want to select t2LDRpci instead. 711198090Srdivacky } else 712198090Srdivacky Base = N; 713198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 714198090Srdivacky return true; 715198090Srdivacky } 716198090Srdivacky 717195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 718198090Srdivacky if (SelectT2AddrModeImm8(Op, N, Base, OffImm)) 719198090Srdivacky // Let t2LDRi8 handle (R - imm8). 720198090Srdivacky return false; 721198090Srdivacky 722195340Sed int RHSC = (int)RHS->getZExtValue(); 723198090Srdivacky if (N.getOpcode() == ISD::SUB) 724198090Srdivacky RHSC = -RHSC; 725198090Srdivacky 726198090Srdivacky if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned) 727195340Sed Base = N.getOperand(0); 728198090Srdivacky if (Base.getOpcode() == ISD::FrameIndex) { 729198090Srdivacky int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 730198090Srdivacky Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 731198090Srdivacky } 732195340Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 733195340Sed return true; 734195340Sed } 735195340Sed } 736195340Sed 737198090Srdivacky // Base only. 738198090Srdivacky Base = N; 739198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 740198090Srdivacky return true; 741195340Sed} 742195340Sed 743202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDNode *Op, SDValue N, 744195340Sed SDValue &Base, SDValue &OffImm) { 745198090Srdivacky // Match simple R - imm8 operands. 746198090Srdivacky if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::SUB) { 747195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 748198090Srdivacky int RHSC = (int)RHS->getSExtValue(); 749198090Srdivacky if (N.getOpcode() == ISD::SUB) 750198090Srdivacky RHSC = -RHSC; 751198090Srdivacky 752198090Srdivacky if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative) 753198090Srdivacky Base = N.getOperand(0); 754198090Srdivacky if (Base.getOpcode() == ISD::FrameIndex) { 755198090Srdivacky int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 756198090Srdivacky Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 757198090Srdivacky } 758195340Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 759195340Sed return true; 760195340Sed } 761195340Sed } 762195340Sed } 763195340Sed 764195340Sed return false; 765195340Sed} 766195340Sed 767202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N, 768195340Sed SDValue &OffImm){ 769202375Srdivacky unsigned Opcode = Op->getOpcode(); 770195340Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 771195340Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 772195340Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 773195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N)) { 774195340Sed int RHSC = (int)RHS->getZExtValue(); 775195340Sed if (RHSC >= 0 && RHSC < 0x100) { // 8 bits. 776198090Srdivacky OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC)) 777195340Sed ? CurDAG->getTargetConstant(RHSC, MVT::i32) 778195340Sed : CurDAG->getTargetConstant(-RHSC, MVT::i32); 779195340Sed return true; 780195340Sed } 781195340Sed } 782195340Sed 783195340Sed return false; 784195340Sed} 785195340Sed 786202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm8s4(SDNode *Op, SDValue N, 787195340Sed SDValue &Base, SDValue &OffImm) { 788195340Sed if (N.getOpcode() == ISD::ADD) { 789195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 790195340Sed int RHSC = (int)RHS->getZExtValue(); 791198090Srdivacky if (((RHSC & 0x3) == 0) && 792198090Srdivacky ((RHSC >= 0 && RHSC < 0x400) || (RHSC < 0 && RHSC > -0x400))) { // 8 bits. 793195340Sed Base = N.getOperand(0); 794195340Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 795195340Sed return true; 796195340Sed } 797195340Sed } 798195340Sed } else if (N.getOpcode() == ISD::SUB) { 799195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 800195340Sed int RHSC = (int)RHS->getZExtValue(); 801195340Sed if (((RHSC & 0x3) == 0) && (RHSC >= 0 && RHSC < 0x400)) { // 8 bits. 802195340Sed Base = N.getOperand(0); 803195340Sed OffImm = CurDAG->getTargetConstant(-RHSC, MVT::i32); 804195340Sed return true; 805195340Sed } 806195340Sed } 807195340Sed } 808195340Sed 809195340Sed return false; 810195340Sed} 811195340Sed 812202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDNode *Op, SDValue N, 813195340Sed SDValue &Base, 814195340Sed SDValue &OffReg, SDValue &ShImm) { 815198090Srdivacky // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12. 816198090Srdivacky if (N.getOpcode() != ISD::ADD) 817198090Srdivacky return false; 818198090Srdivacky 819198090Srdivacky // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8. 820198090Srdivacky if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 821198090Srdivacky int RHSC = (int)RHS->getZExtValue(); 822198090Srdivacky if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned) 823198090Srdivacky return false; 824198090Srdivacky else if (RHSC < 0 && RHSC >= -255) // 8 bits 825198090Srdivacky return false; 826195340Sed } 827195340Sed 828195340Sed // Look for (R + R) or (R + (R << [1,2,3])). 829195340Sed unsigned ShAmt = 0; 830195340Sed Base = N.getOperand(0); 831195340Sed OffReg = N.getOperand(1); 832195340Sed 833195340Sed // Swap if it is ((R << c) + R). 834195340Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg); 835195340Sed if (ShOpcVal != ARM_AM::lsl) { 836195340Sed ShOpcVal = ARM_AM::getShiftOpcForNode(Base); 837195340Sed if (ShOpcVal == ARM_AM::lsl) 838195340Sed std::swap(Base, OffReg); 839198090Srdivacky } 840198090Srdivacky 841195340Sed if (ShOpcVal == ARM_AM::lsl) { 842195340Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 843195340Sed // it. 844195340Sed if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) { 845195340Sed ShAmt = Sh->getZExtValue(); 846195340Sed if (ShAmt >= 4) { 847195340Sed ShAmt = 0; 848195340Sed ShOpcVal = ARM_AM::no_shift; 849195340Sed } else 850195340Sed OffReg = OffReg.getOperand(0); 851195340Sed } else { 852195340Sed ShOpcVal = ARM_AM::no_shift; 853195340Sed } 854198090Srdivacky } 855198090Srdivacky 856195340Sed ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32); 857195340Sed 858195340Sed return true; 859195340Sed} 860195340Sed 861195340Sed//===--------------------------------------------------------------------===// 862195340Sed 863193323Sed/// getAL - Returns a ARMCC::AL immediate node. 864193323Sedstatic inline SDValue getAL(SelectionDAG *CurDAG) { 865193323Sed return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32); 866193323Sed} 867193323Sed 868202375SrdivackySDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) { 869202375Srdivacky LoadSDNode *LD = cast<LoadSDNode>(N); 870195340Sed ISD::MemIndexedMode AM = LD->getAddressingMode(); 871195340Sed if (AM == ISD::UNINDEXED) 872195340Sed return NULL; 873193323Sed 874198090Srdivacky EVT LoadedVT = LD->getMemoryVT(); 875195340Sed SDValue Offset, AMOpc; 876195340Sed bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 877195340Sed unsigned Opcode = 0; 878195340Sed bool Match = false; 879195340Sed if (LoadedVT == MVT::i32 && 880202375Srdivacky SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) { 881195340Sed Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST; 882195340Sed Match = true; 883195340Sed } else if (LoadedVT == MVT::i16 && 884202375Srdivacky SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) { 885195340Sed Match = true; 886195340Sed Opcode = (LD->getExtensionType() == ISD::SEXTLOAD) 887195340Sed ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST) 888195340Sed : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST); 889195340Sed } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) { 890195340Sed if (LD->getExtensionType() == ISD::SEXTLOAD) { 891202375Srdivacky if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) { 892195340Sed Match = true; 893195340Sed Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST; 894195340Sed } 895195340Sed } else { 896202375Srdivacky if (SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) { 897195340Sed Match = true; 898195340Sed Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST; 899195340Sed } 900195340Sed } 901195340Sed } 902195340Sed 903195340Sed if (Match) { 904195340Sed SDValue Chain = LD->getChain(); 905195340Sed SDValue Base = LD->getBasePtr(); 906195340Sed SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG), 907195340Sed CurDAG->getRegister(0, MVT::i32), Chain }; 908202375Srdivacky return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, MVT::i32, 909198090Srdivacky MVT::Other, Ops, 6); 910195340Sed } 911195340Sed 912195340Sed return NULL; 913195340Sed} 914195340Sed 915202375SrdivackySDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) { 916202375Srdivacky LoadSDNode *LD = cast<LoadSDNode>(N); 917195340Sed ISD::MemIndexedMode AM = LD->getAddressingMode(); 918195340Sed if (AM == ISD::UNINDEXED) 919195340Sed return NULL; 920195340Sed 921198090Srdivacky EVT LoadedVT = LD->getMemoryVT(); 922195340Sed bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD; 923195340Sed SDValue Offset; 924195340Sed bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 925195340Sed unsigned Opcode = 0; 926195340Sed bool Match = false; 927202375Srdivacky if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) { 928198090Srdivacky switch (LoadedVT.getSimpleVT().SimpleTy) { 929195340Sed case MVT::i32: 930195340Sed Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST; 931195340Sed break; 932195340Sed case MVT::i16: 933195340Sed if (isSExtLd) 934195340Sed Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST; 935195340Sed else 936195340Sed Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST; 937195340Sed break; 938195340Sed case MVT::i8: 939195340Sed case MVT::i1: 940195340Sed if (isSExtLd) 941195340Sed Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST; 942195340Sed else 943195340Sed Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST; 944195340Sed break; 945195340Sed default: 946195340Sed return NULL; 947195340Sed } 948195340Sed Match = true; 949195340Sed } 950195340Sed 951195340Sed if (Match) { 952195340Sed SDValue Chain = LD->getChain(); 953195340Sed SDValue Base = LD->getBasePtr(); 954195340Sed SDValue Ops[]= { Base, Offset, getAL(CurDAG), 955195340Sed CurDAG->getRegister(0, MVT::i32), Chain }; 956202375Srdivacky return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, MVT::i32, 957198090Srdivacky MVT::Other, Ops, 5); 958195340Sed } 959195340Sed 960195340Sed return NULL; 961195340Sed} 962195340Sed 963208599Srdivacky/// PairDRegs - Form a quad register from a pair of D registers. 964208599Srdivacky/// 965198090SrdivackySDNode *ARMDAGToDAGISel::PairDRegs(EVT VT, SDValue V0, SDValue V1) { 966198090Srdivacky DebugLoc dl = V0.getNode()->getDebugLoc(); 967208599Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32); 968208599Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32); 969208599Srdivacky if (llvm::ModelWithRegSequence()) { 970207631Srdivacky const SDValue Ops[] = { V0, SubReg0, V1, SubReg1 }; 971207631Srdivacky return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 4); 972207631Srdivacky } 973198090Srdivacky SDValue Undef = 974203954Srdivacky SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0); 975203954Srdivacky SDNode *Pair = CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, dl, 976198090Srdivacky VT, Undef, V0, SubReg0); 977203954Srdivacky return CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, dl, 978198090Srdivacky VT, SDValue(Pair, 0), V1, SubReg1); 979198090Srdivacky} 980198090Srdivacky 981208599Srdivacky/// PairQRegs - Form 4 consecutive D registers from a pair of Q registers. 982208599Srdivacky/// 983208599SrdivackySDNode *ARMDAGToDAGISel::PairQRegs(EVT VT, SDValue V0, SDValue V1) { 984208599Srdivacky DebugLoc dl = V0.getNode()->getDebugLoc(); 985208599Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32); 986208599Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32); 987208599Srdivacky const SDValue Ops[] = { V0, SubReg0, V1, SubReg1 }; 988208599Srdivacky return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 4); 989208599Srdivacky} 990208599Srdivacky 991208599Srdivacky/// QuadDRegs - Form 4 consecutive D registers. 992208599Srdivacky/// 993208599SrdivackySDNode *ARMDAGToDAGISel::QuadDRegs(EVT VT, SDValue V0, SDValue V1, 994208599Srdivacky SDValue V2, SDValue V3) { 995208599Srdivacky DebugLoc dl = V0.getNode()->getDebugLoc(); 996208599Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32); 997208599Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32); 998208599Srdivacky SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, MVT::i32); 999208599Srdivacky SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, MVT::i32); 1000208599Srdivacky const SDValue Ops[] = { V0, SubReg0, V1, SubReg1, V2, SubReg2, V3, SubReg3 }; 1001208599Srdivacky return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 8); 1002208599Srdivacky} 1003208599Srdivacky 1004208599Srdivacky/// QuadQRegs - Form 4 consecutive Q registers. 1005208599Srdivacky/// 1006208599SrdivackySDNode *ARMDAGToDAGISel::QuadQRegs(EVT VT, SDValue V0, SDValue V1, 1007208599Srdivacky SDValue V2, SDValue V3) { 1008208599Srdivacky DebugLoc dl = V0.getNode()->getDebugLoc(); 1009208599Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32); 1010208599Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32); 1011208599Srdivacky SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, MVT::i32); 1012208599Srdivacky SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, MVT::i32); 1013208599Srdivacky const SDValue Ops[] = { V0, SubReg0, V1, SubReg1, V2, SubReg2, V3, SubReg3 }; 1014208599Srdivacky return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 8); 1015208599Srdivacky} 1016208599Srdivacky 1017208599Srdivacky/// OctoDRegs - Form 8 consecutive D registers. 1018208599Srdivacky/// 1019208599SrdivackySDNode *ARMDAGToDAGISel::OctoDRegs(EVT VT, SDValue V0, SDValue V1, 1020208599Srdivacky SDValue V2, SDValue V3, 1021208599Srdivacky SDValue V4, SDValue V5, 1022208599Srdivacky SDValue V6, SDValue V7) { 1023208599Srdivacky DebugLoc dl = V0.getNode()->getDebugLoc(); 1024208599Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32); 1025208599Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32); 1026208599Srdivacky SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, MVT::i32); 1027208599Srdivacky SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, MVT::i32); 1028208599Srdivacky SDValue SubReg4 = CurDAG->getTargetConstant(ARM::dsub_4, MVT::i32); 1029208599Srdivacky SDValue SubReg5 = CurDAG->getTargetConstant(ARM::dsub_5, MVT::i32); 1030208599Srdivacky SDValue SubReg6 = CurDAG->getTargetConstant(ARM::dsub_6, MVT::i32); 1031208599Srdivacky SDValue SubReg7 = CurDAG->getTargetConstant(ARM::dsub_7, MVT::i32); 1032208599Srdivacky const SDValue Ops[] ={ V0, SubReg0, V1, SubReg1, V2, SubReg2, V3, SubReg3, 1033208599Srdivacky V4, SubReg4, V5, SubReg5, V6, SubReg6, V7, SubReg7 }; 1034208599Srdivacky return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 16); 1035208599Srdivacky} 1036208599Srdivacky 1037198090Srdivacky/// GetNEONSubregVT - Given a type for a 128-bit NEON vector, return the type 1038198090Srdivacky/// for a 64-bit subregister of the vector. 1039198090Srdivackystatic EVT GetNEONSubregVT(EVT VT) { 1040198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1041198090Srdivacky default: llvm_unreachable("unhandled NEON type"); 1042198090Srdivacky case MVT::v16i8: return MVT::v8i8; 1043198090Srdivacky case MVT::v8i16: return MVT::v4i16; 1044198090Srdivacky case MVT::v4f32: return MVT::v2f32; 1045198090Srdivacky case MVT::v4i32: return MVT::v2i32; 1046198090Srdivacky case MVT::v2i64: return MVT::v1i64; 1047198090Srdivacky } 1048198090Srdivacky} 1049198090Srdivacky 1050202375SrdivackySDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, unsigned NumVecs, 1051198090Srdivacky unsigned *DOpcodes, unsigned *QOpcodes0, 1052198090Srdivacky unsigned *QOpcodes1) { 1053206083Srdivacky assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range"); 1054198090Srdivacky DebugLoc dl = N->getDebugLoc(); 1055198090Srdivacky 1056205407Srdivacky SDValue MemAddr, Align; 1057205407Srdivacky if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, Align)) 1058198090Srdivacky return NULL; 1059198090Srdivacky 1060198090Srdivacky SDValue Chain = N->getOperand(0); 1061198090Srdivacky EVT VT = N->getValueType(0); 1062198090Srdivacky bool is64BitVector = VT.is64BitVector(); 1063198090Srdivacky 1064198090Srdivacky unsigned OpcodeIndex; 1065198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1066198090Srdivacky default: llvm_unreachable("unhandled vld type"); 1067198090Srdivacky // Double-register operations: 1068198090Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1069198090Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1070198090Srdivacky case MVT::v2f32: 1071198090Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1072198090Srdivacky case MVT::v1i64: OpcodeIndex = 3; break; 1073198090Srdivacky // Quad-register operations: 1074198090Srdivacky case MVT::v16i8: OpcodeIndex = 0; break; 1075198090Srdivacky case MVT::v8i16: OpcodeIndex = 1; break; 1076198090Srdivacky case MVT::v4f32: 1077198090Srdivacky case MVT::v4i32: OpcodeIndex = 2; break; 1078206083Srdivacky case MVT::v2i64: OpcodeIndex = 3; 1079206083Srdivacky assert(NumVecs == 1 && "v2i64 type only supported for VLD1"); 1080206083Srdivacky break; 1081198090Srdivacky } 1082198090Srdivacky 1083207618Srdivacky SDValue Pred = getAL(CurDAG); 1084205407Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1085198090Srdivacky if (is64BitVector) { 1086198090Srdivacky unsigned Opc = DOpcodes[OpcodeIndex]; 1087205407Srdivacky const SDValue Ops[] = { MemAddr, Align, Pred, Reg0, Chain }; 1088198090Srdivacky std::vector<EVT> ResTys(NumVecs, VT); 1089198090Srdivacky ResTys.push_back(MVT::Other); 1090208599Srdivacky SDNode *VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 5); 1091208599Srdivacky if (!llvm::ModelWithRegSequence() || NumVecs < 2) 1092208599Srdivacky return VLd; 1093208599Srdivacky 1094208599Srdivacky SDValue RegSeq; 1095208599Srdivacky SDValue V0 = SDValue(VLd, 0); 1096208599Srdivacky SDValue V1 = SDValue(VLd, 1); 1097208599Srdivacky 1098208599Srdivacky // Form a REG_SEQUENCE to force register allocation. 1099208599Srdivacky if (NumVecs == 2) 1100208599Srdivacky RegSeq = SDValue(PairDRegs(MVT::v2i64, V0, V1), 0); 1101208599Srdivacky else { 1102208599Srdivacky SDValue V2 = SDValue(VLd, 2); 1103208599Srdivacky // If it's a vld3, form a quad D-register but discard the last part. 1104208599Srdivacky SDValue V3 = (NumVecs == 3) 1105208599Srdivacky ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0) 1106208599Srdivacky : SDValue(VLd, 3); 1107208599Srdivacky RegSeq = SDValue(QuadDRegs(MVT::v4i64, V0, V1, V2, V3), 0); 1108208599Srdivacky } 1109208599Srdivacky 1110208599Srdivacky assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering"); 1111208599Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1112208599Srdivacky SDValue D = CurDAG->getTargetExtractSubreg(ARM::dsub_0+Vec, 1113208599Srdivacky dl, VT, RegSeq); 1114208599Srdivacky ReplaceUses(SDValue(N, Vec), D); 1115208599Srdivacky } 1116208599Srdivacky ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, NumVecs)); 1117208599Srdivacky return NULL; 1118198090Srdivacky } 1119198090Srdivacky 1120198090Srdivacky EVT RegVT = GetNEONSubregVT(VT); 1121206083Srdivacky if (NumVecs <= 2) { 1122206083Srdivacky // Quad registers are directly supported for VLD1 and VLD2, 1123206083Srdivacky // loading pairs of D regs. 1124198090Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1125205407Srdivacky const SDValue Ops[] = { MemAddr, Align, Pred, Reg0, Chain }; 1126206083Srdivacky std::vector<EVT> ResTys(2 * NumVecs, RegVT); 1127198090Srdivacky ResTys.push_back(MVT::Other); 1128205407Srdivacky SDNode *VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 5); 1129206083Srdivacky Chain = SDValue(VLd, 2 * NumVecs); 1130198090Srdivacky 1131198090Srdivacky // Combine the even and odd subregs to produce the result. 1132208599Srdivacky if (llvm::ModelWithRegSequence()) { 1133208599Srdivacky if (NumVecs == 1) { 1134208599Srdivacky SDNode *Q = PairDRegs(VT, SDValue(VLd, 0), SDValue(VLd, 1)); 1135208599Srdivacky ReplaceUses(SDValue(N, 0), SDValue(Q, 0)); 1136208599Srdivacky } else { 1137208599Srdivacky SDValue QQ = SDValue(QuadDRegs(MVT::v4i64, 1138208599Srdivacky SDValue(VLd, 0), SDValue(VLd, 1), 1139208599Srdivacky SDValue(VLd, 2), SDValue(VLd, 3)), 0); 1140208599Srdivacky SDValue Q0 = CurDAG->getTargetExtractSubreg(ARM::qsub_0, dl, VT, QQ); 1141208599Srdivacky SDValue Q1 = CurDAG->getTargetExtractSubreg(ARM::qsub_1, dl, VT, QQ); 1142208599Srdivacky ReplaceUses(SDValue(N, 0), Q0); 1143208599Srdivacky ReplaceUses(SDValue(N, 1), Q1); 1144208599Srdivacky } 1145208599Srdivacky } else { 1146208599Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1147208599Srdivacky SDNode *Q = PairDRegs(VT, SDValue(VLd, 2*Vec), SDValue(VLd, 2*Vec+1)); 1148208599Srdivacky ReplaceUses(SDValue(N, Vec), SDValue(Q, 0)); 1149208599Srdivacky } 1150198090Srdivacky } 1151198090Srdivacky } else { 1152198090Srdivacky // Otherwise, quad registers are loaded with two separate instructions, 1153198090Srdivacky // where one loads the even registers and the other loads the odd registers. 1154198090Srdivacky 1155198090Srdivacky std::vector<EVT> ResTys(NumVecs, RegVT); 1156198090Srdivacky ResTys.push_back(MemAddr.getValueType()); 1157198090Srdivacky ResTys.push_back(MVT::Other); 1158198090Srdivacky 1159198113Srdivacky // Load the even subregs. 1160198090Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1161205407Srdivacky const SDValue OpsA[] = { MemAddr, Align, Reg0, Pred, Reg0, Chain }; 1162205407Srdivacky SDNode *VLdA = CurDAG->getMachineNode(Opc, dl, ResTys, OpsA, 6); 1163198090Srdivacky Chain = SDValue(VLdA, NumVecs+1); 1164198090Srdivacky 1165198113Srdivacky // Load the odd subregs. 1166198090Srdivacky Opc = QOpcodes1[OpcodeIndex]; 1167205407Srdivacky const SDValue OpsB[] = { SDValue(VLdA, NumVecs), 1168205407Srdivacky Align, Reg0, Pred, Reg0, Chain }; 1169205407Srdivacky SDNode *VLdB = CurDAG->getMachineNode(Opc, dl, ResTys, OpsB, 6); 1170198090Srdivacky Chain = SDValue(VLdB, NumVecs+1); 1171198090Srdivacky 1172208599Srdivacky if (llvm::ModelWithRegSequence()) { 1173208599Srdivacky SDValue V0 = SDValue(VLdA, 0); 1174208599Srdivacky SDValue V1 = SDValue(VLdB, 0); 1175208599Srdivacky SDValue V2 = SDValue(VLdA, 1); 1176208599Srdivacky SDValue V3 = SDValue(VLdB, 1); 1177208599Srdivacky SDValue V4 = SDValue(VLdA, 2); 1178208599Srdivacky SDValue V5 = SDValue(VLdB, 2); 1179208599Srdivacky SDValue V6 = (NumVecs == 3) 1180208599Srdivacky ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,RegVT), 1181208599Srdivacky 0) 1182208599Srdivacky : SDValue(VLdA, 3); 1183208599Srdivacky SDValue V7 = (NumVecs == 3) 1184208599Srdivacky ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,RegVT), 1185208599Srdivacky 0) 1186208599Srdivacky : SDValue(VLdB, 3); 1187208599Srdivacky SDValue RegSeq = SDValue(OctoDRegs(MVT::v8i64, V0, V1, V2, V3, 1188208599Srdivacky V4, V5, V6, V7), 0); 1189208599Srdivacky 1190208599Srdivacky // Extract out the 3 / 4 Q registers. 1191208599Srdivacky assert(ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering"); 1192208599Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1193208599Srdivacky SDValue Q = CurDAG->getTargetExtractSubreg(ARM::qsub_0+Vec, 1194208599Srdivacky dl, VT, RegSeq); 1195208599Srdivacky ReplaceUses(SDValue(N, Vec), Q); 1196208599Srdivacky } 1197208599Srdivacky } else { 1198208599Srdivacky // Combine the even and odd subregs to produce the result. 1199208599Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1200208599Srdivacky SDNode *Q = PairDRegs(VT, SDValue(VLdA, Vec), SDValue(VLdB, Vec)); 1201208599Srdivacky ReplaceUses(SDValue(N, Vec), SDValue(Q, 0)); 1202208599Srdivacky } 1203198090Srdivacky } 1204198090Srdivacky } 1205198090Srdivacky ReplaceUses(SDValue(N, NumVecs), Chain); 1206198090Srdivacky return NULL; 1207198090Srdivacky} 1208198090Srdivacky 1209202375SrdivackySDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, unsigned NumVecs, 1210198113Srdivacky unsigned *DOpcodes, unsigned *QOpcodes0, 1211198113Srdivacky unsigned *QOpcodes1) { 1212206083Srdivacky assert(NumVecs >=1 && NumVecs <= 4 && "VST NumVecs out-of-range"); 1213198113Srdivacky DebugLoc dl = N->getDebugLoc(); 1214198113Srdivacky 1215205407Srdivacky SDValue MemAddr, Align; 1216205407Srdivacky if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, Align)) 1217198113Srdivacky return NULL; 1218198113Srdivacky 1219198113Srdivacky SDValue Chain = N->getOperand(0); 1220198113Srdivacky EVT VT = N->getOperand(3).getValueType(); 1221198113Srdivacky bool is64BitVector = VT.is64BitVector(); 1222198113Srdivacky 1223198113Srdivacky unsigned OpcodeIndex; 1224198113Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1225198113Srdivacky default: llvm_unreachable("unhandled vst type"); 1226198113Srdivacky // Double-register operations: 1227198113Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1228198113Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1229198113Srdivacky case MVT::v2f32: 1230198113Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1231198113Srdivacky case MVT::v1i64: OpcodeIndex = 3; break; 1232198113Srdivacky // Quad-register operations: 1233198113Srdivacky case MVT::v16i8: OpcodeIndex = 0; break; 1234198113Srdivacky case MVT::v8i16: OpcodeIndex = 1; break; 1235198113Srdivacky case MVT::v4f32: 1236198113Srdivacky case MVT::v4i32: OpcodeIndex = 2; break; 1237206083Srdivacky case MVT::v2i64: OpcodeIndex = 3; 1238206083Srdivacky assert(NumVecs == 1 && "v2i64 type only supported for VST1"); 1239206083Srdivacky break; 1240198113Srdivacky } 1241198113Srdivacky 1242207618Srdivacky SDValue Pred = getAL(CurDAG); 1243205407Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1244199989Srdivacky 1245205407Srdivacky SmallVector<SDValue, 10> Ops; 1246198113Srdivacky Ops.push_back(MemAddr); 1247199481Srdivacky Ops.push_back(Align); 1248198113Srdivacky 1249198113Srdivacky if (is64BitVector) { 1250208599Srdivacky if (llvm::ModelWithRegSequence() && NumVecs >= 2) { 1251208599Srdivacky SDValue RegSeq; 1252208599Srdivacky SDValue V0 = N->getOperand(0+3); 1253208599Srdivacky SDValue V1 = N->getOperand(1+3); 1254208599Srdivacky 1255208599Srdivacky // Form a REG_SEQUENCE to force register allocation. 1256208599Srdivacky if (NumVecs == 2) 1257208599Srdivacky RegSeq = SDValue(PairDRegs(MVT::v2i64, V0, V1), 0); 1258208599Srdivacky else { 1259208599Srdivacky SDValue V2 = N->getOperand(2+3); 1260208599Srdivacky // If it's a vld3, form a quad D-register and leave the last part as 1261208599Srdivacky // an undef. 1262208599Srdivacky SDValue V3 = (NumVecs == 3) 1263208599Srdivacky ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0) 1264208599Srdivacky : N->getOperand(3+3); 1265208599Srdivacky RegSeq = SDValue(QuadDRegs(MVT::v4i64, V0, V1, V2, V3), 0); 1266208599Srdivacky } 1267208599Srdivacky 1268208599Srdivacky // Now extract the D registers back out. 1269208599Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_0, dl, VT, 1270208599Srdivacky RegSeq)); 1271208599Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_1, dl, VT, 1272208599Srdivacky RegSeq)); 1273208599Srdivacky if (NumVecs > 2) 1274208599Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_2, dl, VT, 1275208599Srdivacky RegSeq)); 1276208599Srdivacky if (NumVecs > 3) 1277208599Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_3, dl, VT, 1278208599Srdivacky RegSeq)); 1279208599Srdivacky } else { 1280208599Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1281208599Srdivacky Ops.push_back(N->getOperand(Vec+3)); 1282208599Srdivacky } 1283199989Srdivacky Ops.push_back(Pred); 1284205407Srdivacky Ops.push_back(Reg0); // predicate register 1285198113Srdivacky Ops.push_back(Chain); 1286208599Srdivacky unsigned Opc = DOpcodes[OpcodeIndex]; 1287205407Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+5); 1288198113Srdivacky } 1289198113Srdivacky 1290198113Srdivacky EVT RegVT = GetNEONSubregVT(VT); 1291206083Srdivacky if (NumVecs <= 2) { 1292206083Srdivacky // Quad registers are directly supported for VST1 and VST2, 1293206083Srdivacky // storing pairs of D regs. 1294198113Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1295208599Srdivacky if (llvm::ModelWithRegSequence() && NumVecs == 2) { 1296208599Srdivacky // First extract the pair of Q registers. 1297208599Srdivacky SDValue Q0 = N->getOperand(3); 1298208599Srdivacky SDValue Q1 = N->getOperand(4); 1299208599Srdivacky 1300208599Srdivacky // Form a QQ register. 1301208599Srdivacky SDValue QQ = SDValue(PairQRegs(MVT::v4i64, Q0, Q1), 0); 1302208599Srdivacky 1303208599Srdivacky // Now extract the D registers back out. 1304208599Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_0, dl, RegVT, 1305208599Srdivacky QQ)); 1306208599Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_1, dl, RegVT, 1307208599Srdivacky QQ)); 1308208599Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_2, dl, RegVT, 1309208599Srdivacky QQ)); 1310208599Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_3, dl, RegVT, 1311208599Srdivacky QQ)); 1312208599Srdivacky Ops.push_back(Pred); 1313208599Srdivacky Ops.push_back(Reg0); // predicate register 1314208599Srdivacky Ops.push_back(Chain); 1315208599Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), 5 + 4); 1316208599Srdivacky } else { 1317208599Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1318208599Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_0, dl, RegVT, 1319208599Srdivacky N->getOperand(Vec+3))); 1320208599Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_1, dl, RegVT, 1321208599Srdivacky N->getOperand(Vec+3))); 1322208599Srdivacky } 1323208599Srdivacky Ops.push_back(Pred); 1324208599Srdivacky Ops.push_back(Reg0); // predicate register 1325208599Srdivacky Ops.push_back(Chain); 1326208599Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), 1327208599Srdivacky 5 + 2 * NumVecs); 1328198113Srdivacky } 1329198113Srdivacky } 1330198113Srdivacky 1331198113Srdivacky // Otherwise, quad registers are stored with two separate instructions, 1332198113Srdivacky // where one stores the even registers and the other stores the odd registers. 1333208599Srdivacky if (llvm::ModelWithRegSequence()) { 1334208599Srdivacky // Form the QQQQ REG_SEQUENCE. 1335208599Srdivacky SDValue V[8]; 1336208599Srdivacky for (unsigned Vec = 0, i = 0; Vec < NumVecs; ++Vec, i+=2) { 1337208599Srdivacky V[i] = CurDAG->getTargetExtractSubreg(ARM::dsub_0, dl, RegVT, 1338208599Srdivacky N->getOperand(Vec+3)); 1339208599Srdivacky V[i+1] = CurDAG->getTargetExtractSubreg(ARM::dsub_1, dl, RegVT, 1340208599Srdivacky N->getOperand(Vec+3)); 1341208599Srdivacky } 1342208599Srdivacky if (NumVecs == 3) 1343208599Srdivacky V[6] = V[7] = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, 1344208599Srdivacky dl, RegVT), 0); 1345198113Srdivacky 1346208599Srdivacky SDValue RegSeq = SDValue(OctoDRegs(MVT::v8i64, V[0], V[1], V[2], V[3], 1347208599Srdivacky V[4], V[5], V[6], V[7]), 0); 1348198113Srdivacky 1349208599Srdivacky // Store the even D registers. 1350208599Srdivacky assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering"); 1351208599Srdivacky Ops.push_back(Reg0); // post-access address offset 1352208599Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1353208599Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_0+Vec*2, dl, 1354208599Srdivacky RegVT, RegSeq)); 1355208599Srdivacky Ops.push_back(Pred); 1356208599Srdivacky Ops.push_back(Reg0); // predicate register 1357208599Srdivacky Ops.push_back(Chain); 1358208599Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1359208599Srdivacky SDNode *VStA = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(), 1360208599Srdivacky MVT::Other, Ops.data(), NumVecs+6); 1361208599Srdivacky Chain = SDValue(VStA, 1); 1362198113Srdivacky 1363208599Srdivacky // Store the odd D registers. 1364208599Srdivacky Ops[0] = SDValue(VStA, 0); // MemAddr 1365208599Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1366208599Srdivacky Ops[Vec+3] = CurDAG->getTargetExtractSubreg(ARM::dsub_1+Vec*2, dl, 1367208599Srdivacky RegVT, RegSeq); 1368208599Srdivacky Ops[NumVecs+5] = Chain; 1369208599Srdivacky Opc = QOpcodes1[OpcodeIndex]; 1370208599Srdivacky SDNode *VStB = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(), 1371208599Srdivacky MVT::Other, Ops.data(), NumVecs+6); 1372208599Srdivacky Chain = SDValue(VStB, 1); 1373208599Srdivacky ReplaceUses(SDValue(N, 0), Chain); 1374208599Srdivacky return NULL; 1375208599Srdivacky } else { 1376208599Srdivacky Ops.push_back(Reg0); // post-access address offset 1377208599Srdivacky 1378208599Srdivacky // Store the even subregs. 1379208599Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1380208599Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_0, dl, RegVT, 1381208599Srdivacky N->getOperand(Vec+3))); 1382208599Srdivacky Ops.push_back(Pred); 1383208599Srdivacky Ops.push_back(Reg0); // predicate register 1384208599Srdivacky Ops.push_back(Chain); 1385208599Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1386208599Srdivacky SDNode *VStA = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(), 1387208599Srdivacky MVT::Other, Ops.data(), NumVecs+6); 1388208599Srdivacky Chain = SDValue(VStA, 1); 1389208599Srdivacky 1390208599Srdivacky // Store the odd subregs. 1391208599Srdivacky Ops[0] = SDValue(VStA, 0); // MemAddr 1392208599Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1393208599Srdivacky Ops[Vec+3] = CurDAG->getTargetExtractSubreg(ARM::dsub_1, dl, RegVT, 1394208599Srdivacky N->getOperand(Vec+3)); 1395208599Srdivacky Ops[NumVecs+5] = Chain; 1396208599Srdivacky Opc = QOpcodes1[OpcodeIndex]; 1397208599Srdivacky SDNode *VStB = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(), 1398208599Srdivacky MVT::Other, Ops.data(), NumVecs+6); 1399208599Srdivacky Chain = SDValue(VStB, 1); 1400208599Srdivacky ReplaceUses(SDValue(N, 0), Chain); 1401208599Srdivacky return NULL; 1402208599Srdivacky } 1403198113Srdivacky} 1404198113Srdivacky 1405202375SrdivackySDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, 1406198090Srdivacky unsigned NumVecs, unsigned *DOpcodes, 1407198090Srdivacky unsigned *QOpcodes0, 1408198090Srdivacky unsigned *QOpcodes1) { 1409198090Srdivacky assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range"); 1410198090Srdivacky DebugLoc dl = N->getDebugLoc(); 1411198090Srdivacky 1412205407Srdivacky SDValue MemAddr, Align; 1413205407Srdivacky if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, Align)) 1414198090Srdivacky return NULL; 1415198090Srdivacky 1416198090Srdivacky SDValue Chain = N->getOperand(0); 1417198090Srdivacky unsigned Lane = 1418198090Srdivacky cast<ConstantSDNode>(N->getOperand(NumVecs+3))->getZExtValue(); 1419198090Srdivacky EVT VT = IsLoad ? N->getValueType(0) : N->getOperand(3).getValueType(); 1420198090Srdivacky bool is64BitVector = VT.is64BitVector(); 1421198090Srdivacky 1422198090Srdivacky // Quad registers are handled by load/store of subregs. Find the subreg info. 1423198090Srdivacky unsigned NumElts = 0; 1424198090Srdivacky int SubregIdx = 0; 1425208599Srdivacky bool Even = false; 1426198090Srdivacky EVT RegVT = VT; 1427198090Srdivacky if (!is64BitVector) { 1428198090Srdivacky RegVT = GetNEONSubregVT(VT); 1429198090Srdivacky NumElts = RegVT.getVectorNumElements(); 1430208599Srdivacky SubregIdx = (Lane < NumElts) ? ARM::dsub_0 : ARM::dsub_1; 1431208599Srdivacky Even = Lane < NumElts; 1432198090Srdivacky } 1433198090Srdivacky 1434198090Srdivacky unsigned OpcodeIndex; 1435198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1436198090Srdivacky default: llvm_unreachable("unhandled vld/vst lane type"); 1437198090Srdivacky // Double-register operations: 1438198090Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1439198090Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1440198090Srdivacky case MVT::v2f32: 1441198090Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1442198090Srdivacky // Quad-register operations: 1443198090Srdivacky case MVT::v8i16: OpcodeIndex = 0; break; 1444198090Srdivacky case MVT::v4f32: 1445198090Srdivacky case MVT::v4i32: OpcodeIndex = 1; break; 1446198090Srdivacky } 1447198090Srdivacky 1448207618Srdivacky SDValue Pred = getAL(CurDAG); 1449205407Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1450199989Srdivacky 1451205407Srdivacky SmallVector<SDValue, 10> Ops; 1452198090Srdivacky Ops.push_back(MemAddr); 1453199481Srdivacky Ops.push_back(Align); 1454198090Srdivacky 1455198090Srdivacky unsigned Opc = 0; 1456198090Srdivacky if (is64BitVector) { 1457198090Srdivacky Opc = DOpcodes[OpcodeIndex]; 1458208599Srdivacky if (llvm::ModelWithRegSequence()) { 1459208599Srdivacky SDValue RegSeq; 1460208599Srdivacky SDValue V0 = N->getOperand(0+3); 1461208599Srdivacky SDValue V1 = N->getOperand(1+3); 1462208599Srdivacky if (NumVecs == 2) { 1463208599Srdivacky RegSeq = SDValue(PairDRegs(MVT::v2i64, V0, V1), 0); 1464208599Srdivacky } else { 1465208599Srdivacky SDValue V2 = N->getOperand(2+3); 1466208599Srdivacky SDValue V3 = (NumVecs == 3) 1467208599Srdivacky ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0) 1468208599Srdivacky : N->getOperand(3+3); 1469208599Srdivacky RegSeq = SDValue(QuadDRegs(MVT::v4i64, V0, V1, V2, V3), 0); 1470208599Srdivacky } 1471208599Srdivacky 1472208599Srdivacky // Now extract the D registers back out. 1473208599Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_0, dl, VT, 1474208599Srdivacky RegSeq)); 1475208599Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_1, dl, VT, 1476208599Srdivacky RegSeq)); 1477208599Srdivacky if (NumVecs > 2) 1478208599Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_2, dl, VT, 1479208599Srdivacky RegSeq)); 1480208599Srdivacky if (NumVecs > 3) 1481208599Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_3, dl, VT, 1482208599Srdivacky RegSeq)); 1483208599Srdivacky } else { 1484208599Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1485208599Srdivacky Ops.push_back(N->getOperand(Vec+3)); 1486208599Srdivacky } 1487198090Srdivacky } else { 1488198090Srdivacky // Check if this is loading the even or odd subreg of a Q register. 1489198090Srdivacky if (Lane < NumElts) { 1490198090Srdivacky Opc = QOpcodes0[OpcodeIndex]; 1491198090Srdivacky } else { 1492198090Srdivacky Lane -= NumElts; 1493198090Srdivacky Opc = QOpcodes1[OpcodeIndex]; 1494198090Srdivacky } 1495208599Srdivacky 1496208599Srdivacky if (llvm::ModelWithRegSequence()) { 1497208599Srdivacky SDValue RegSeq; 1498208599Srdivacky SDValue V0 = N->getOperand(0+3); 1499208599Srdivacky SDValue V1 = N->getOperand(1+3); 1500208599Srdivacky if (NumVecs == 2) { 1501208599Srdivacky RegSeq = SDValue(PairQRegs(MVT::v4i64, V0, V1), 0); 1502208599Srdivacky } else { 1503208599Srdivacky SDValue V2 = N->getOperand(2+3); 1504208599Srdivacky SDValue V3 = (NumVecs == 3) 1505208599Srdivacky ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0) 1506208599Srdivacky : N->getOperand(3+3); 1507208599Srdivacky RegSeq = SDValue(QuadQRegs(MVT::v8i64, V0, V1, V2, V3), 0); 1508208599Srdivacky } 1509208599Srdivacky 1510208599Srdivacky // Extract the subregs of the input vector. 1511208599Srdivacky unsigned SubIdx = Even ? ARM::dsub_0 : ARM::dsub_1; 1512208599Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1513208599Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(SubIdx+Vec*2, dl, RegVT, 1514208599Srdivacky RegSeq)); 1515208599Srdivacky } else { 1516208599Srdivacky // Extract the subregs of the input vector. 1517208599Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1518208599Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT, 1519208599Srdivacky N->getOperand(Vec+3))); 1520208599Srdivacky } 1521198090Srdivacky } 1522198090Srdivacky Ops.push_back(getI32Imm(Lane)); 1523199989Srdivacky Ops.push_back(Pred); 1524205407Srdivacky Ops.push_back(Reg0); 1525198090Srdivacky Ops.push_back(Chain); 1526198090Srdivacky 1527198090Srdivacky if (!IsLoad) 1528205407Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+6); 1529198090Srdivacky 1530198090Srdivacky std::vector<EVT> ResTys(NumVecs, RegVT); 1531198090Srdivacky ResTys.push_back(MVT::Other); 1532208599Srdivacky SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(),NumVecs+6); 1533208599Srdivacky 1534208599Srdivacky if (llvm::ModelWithRegSequence()) { 1535208599Srdivacky // Form a REG_SEQUENCE to force register allocation. 1536208599Srdivacky SDValue RegSeq; 1537208599Srdivacky if (is64BitVector) { 1538208599Srdivacky SDValue V0 = SDValue(VLdLn, 0); 1539208599Srdivacky SDValue V1 = SDValue(VLdLn, 1); 1540208599Srdivacky if (NumVecs == 2) { 1541208599Srdivacky RegSeq = SDValue(PairDRegs(MVT::v2i64, V0, V1), 0); 1542208599Srdivacky } else { 1543208599Srdivacky SDValue V2 = SDValue(VLdLn, 2); 1544208599Srdivacky // If it's a vld3, form a quad D-register but discard the last part. 1545208599Srdivacky SDValue V3 = (NumVecs == 3) 1546208599Srdivacky ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0) 1547208599Srdivacky : SDValue(VLdLn, 3); 1548208599Srdivacky RegSeq = SDValue(QuadDRegs(MVT::v4i64, V0, V1, V2, V3), 0); 1549208599Srdivacky } 1550208599Srdivacky } else { 1551208599Srdivacky // For 128-bit vectors, take the 64-bit results of the load and insert them 1552208599Srdivacky // as subregs into the result. 1553208599Srdivacky SDValue V[8]; 1554208599Srdivacky for (unsigned Vec = 0, i = 0; Vec < NumVecs; ++Vec, i+=2) { 1555208599Srdivacky if (Even) { 1556208599Srdivacky V[i] = SDValue(VLdLn, Vec); 1557208599Srdivacky V[i+1] = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, 1558208599Srdivacky dl, RegVT), 0); 1559208599Srdivacky } else { 1560208599Srdivacky V[i] = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, 1561208599Srdivacky dl, RegVT), 0); 1562208599Srdivacky V[i+1] = SDValue(VLdLn, Vec); 1563208599Srdivacky } 1564208599Srdivacky } 1565208599Srdivacky if (NumVecs == 3) 1566208599Srdivacky V[6] = V[7] = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, 1567208599Srdivacky dl, RegVT), 0); 1568208599Srdivacky 1569208599Srdivacky if (NumVecs == 2) 1570208599Srdivacky RegSeq = SDValue(QuadDRegs(MVT::v4i64, V[0], V[1], V[2], V[3]), 0); 1571208599Srdivacky else 1572208599Srdivacky RegSeq = SDValue(OctoDRegs(MVT::v8i64, V[0], V[1], V[2], V[3], 1573208599Srdivacky V[4], V[5], V[6], V[7]), 0); 1574208599Srdivacky } 1575208599Srdivacky 1576208599Srdivacky assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering"); 1577208599Srdivacky assert(ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering"); 1578208599Srdivacky unsigned SubIdx = is64BitVector ? ARM::dsub_0 : ARM::qsub_0; 1579208599Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1580208599Srdivacky ReplaceUses(SDValue(N, Vec), 1581208599Srdivacky CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, RegSeq)); 1582208599Srdivacky ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, NumVecs)); 1583208599Srdivacky return NULL; 1584208599Srdivacky } 1585208599Srdivacky 1586198090Srdivacky // For a 64-bit vector load to D registers, nothing more needs to be done. 1587198090Srdivacky if (is64BitVector) 1588198090Srdivacky return VLdLn; 1589198090Srdivacky 1590198090Srdivacky // For 128-bit vectors, take the 64-bit results of the load and insert them 1591198090Srdivacky // as subregs into the result. 1592198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1593198090Srdivacky SDValue QuadVec = CurDAG->getTargetInsertSubreg(SubregIdx, dl, VT, 1594198090Srdivacky N->getOperand(Vec+3), 1595198090Srdivacky SDValue(VLdLn, Vec)); 1596198090Srdivacky ReplaceUses(SDValue(N, Vec), QuadVec); 1597198090Srdivacky } 1598198090Srdivacky 1599198090Srdivacky Chain = SDValue(VLdLn, NumVecs); 1600198090Srdivacky ReplaceUses(SDValue(N, NumVecs), Chain); 1601198090Srdivacky return NULL; 1602198090Srdivacky} 1603198090Srdivacky 1604202375SrdivackySDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N, 1605207618Srdivacky bool isSigned) { 1606198090Srdivacky if (!Subtarget->hasV6T2Ops()) 1607198090Srdivacky return NULL; 1608198090Srdivacky 1609207618Srdivacky unsigned Opc = isSigned ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX) 1610207618Srdivacky : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX); 1611207618Srdivacky 1612207618Srdivacky 1613207618Srdivacky // For unsigned extracts, check for a shift right and mask 1614207618Srdivacky unsigned And_imm = 0; 1615207618Srdivacky if (N->getOpcode() == ISD::AND) { 1616207618Srdivacky if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) { 1617207618Srdivacky 1618207618Srdivacky // The immediate is a mask of the low bits iff imm & (imm+1) == 0 1619207618Srdivacky if (And_imm & (And_imm + 1)) 1620207618Srdivacky return NULL; 1621207618Srdivacky 1622207618Srdivacky unsigned Srl_imm = 0; 1623207618Srdivacky if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, 1624207618Srdivacky Srl_imm)) { 1625207618Srdivacky assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); 1626207618Srdivacky 1627207618Srdivacky unsigned Width = CountTrailingOnes_32(And_imm); 1628207618Srdivacky unsigned LSB = Srl_imm; 1629207618Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1630207618Srdivacky SDValue Ops[] = { N->getOperand(0).getOperand(0), 1631207618Srdivacky CurDAG->getTargetConstant(LSB, MVT::i32), 1632207618Srdivacky CurDAG->getTargetConstant(Width, MVT::i32), 1633207618Srdivacky getAL(CurDAG), Reg0 }; 1634207618Srdivacky return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); 1635207618Srdivacky } 1636207618Srdivacky } 1637207618Srdivacky return NULL; 1638207618Srdivacky } 1639207618Srdivacky 1640207618Srdivacky // Otherwise, we're looking for a shift of a shift 1641198090Srdivacky unsigned Shl_imm = 0; 1642202375Srdivacky if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) { 1643198090Srdivacky assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!"); 1644198090Srdivacky unsigned Srl_imm = 0; 1645202375Srdivacky if (isInt32Immediate(N->getOperand(1), Srl_imm)) { 1646198090Srdivacky assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); 1647198090Srdivacky unsigned Width = 32 - Srl_imm; 1648198090Srdivacky int LSB = Srl_imm - Shl_imm; 1649198396Srdivacky if (LSB < 0) 1650198090Srdivacky return NULL; 1651198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1652202375Srdivacky SDValue Ops[] = { N->getOperand(0).getOperand(0), 1653198090Srdivacky CurDAG->getTargetConstant(LSB, MVT::i32), 1654198090Srdivacky CurDAG->getTargetConstant(Width, MVT::i32), 1655198090Srdivacky getAL(CurDAG), Reg0 }; 1656202375Srdivacky return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); 1657198090Srdivacky } 1658198090Srdivacky } 1659198090Srdivacky return NULL; 1660198090Srdivacky} 1661198090Srdivacky 1662199989SrdivackySDNode *ARMDAGToDAGISel:: 1663202375SrdivackySelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 1664199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1665199989Srdivacky SDValue CPTmp0; 1666199989Srdivacky SDValue CPTmp1; 1667202375Srdivacky if (SelectT2ShifterOperandReg(N, TrueVal, CPTmp0, CPTmp1)) { 1668199989Srdivacky unsigned SOVal = cast<ConstantSDNode>(CPTmp1)->getZExtValue(); 1669199989Srdivacky unsigned SOShOp = ARM_AM::getSORegShOp(SOVal); 1670199989Srdivacky unsigned Opc = 0; 1671199989Srdivacky switch (SOShOp) { 1672199989Srdivacky case ARM_AM::lsl: Opc = ARM::t2MOVCClsl; break; 1673199989Srdivacky case ARM_AM::lsr: Opc = ARM::t2MOVCClsr; break; 1674199989Srdivacky case ARM_AM::asr: Opc = ARM::t2MOVCCasr; break; 1675199989Srdivacky case ARM_AM::ror: Opc = ARM::t2MOVCCror; break; 1676199989Srdivacky default: 1677199989Srdivacky llvm_unreachable("Unknown so_reg opcode!"); 1678199989Srdivacky break; 1679199989Srdivacky } 1680199989Srdivacky SDValue SOShImm = 1681199989Srdivacky CurDAG->getTargetConstant(ARM_AM::getSORegOffset(SOVal), MVT::i32); 1682199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1683199989Srdivacky SDValue Ops[] = { FalseVal, CPTmp0, SOShImm, CC, CCR, InFlag }; 1684202375Srdivacky return CurDAG->SelectNodeTo(N, Opc, MVT::i32,Ops, 6); 1685199989Srdivacky } 1686199989Srdivacky return 0; 1687199989Srdivacky} 1688199989Srdivacky 1689199989SrdivackySDNode *ARMDAGToDAGISel:: 1690202375SrdivackySelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 1691199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1692199989Srdivacky SDValue CPTmp0; 1693199989Srdivacky SDValue CPTmp1; 1694199989Srdivacky SDValue CPTmp2; 1695202375Srdivacky if (SelectShifterOperandReg(N, TrueVal, CPTmp0, CPTmp1, CPTmp2)) { 1696199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1697199989Srdivacky SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, InFlag }; 1698202375Srdivacky return CurDAG->SelectNodeTo(N, ARM::MOVCCs, MVT::i32, Ops, 7); 1699199989Srdivacky } 1700199989Srdivacky return 0; 1701199989Srdivacky} 1702199989Srdivacky 1703199989SrdivackySDNode *ARMDAGToDAGISel:: 1704202375SrdivackySelectT2CMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 1705199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1706199989Srdivacky ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal); 1707199989Srdivacky if (!T) 1708199989Srdivacky return 0; 1709199989Srdivacky 1710199989Srdivacky if (Predicate_t2_so_imm(TrueVal.getNode())) { 1711199989Srdivacky SDValue True = CurDAG->getTargetConstant(T->getZExtValue(), MVT::i32); 1712199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1713199989Srdivacky SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag }; 1714202375Srdivacky return CurDAG->SelectNodeTo(N, 1715199989Srdivacky ARM::t2MOVCCi, MVT::i32, Ops, 5); 1716199989Srdivacky } 1717199989Srdivacky return 0; 1718199989Srdivacky} 1719199989Srdivacky 1720199989SrdivackySDNode *ARMDAGToDAGISel:: 1721202375SrdivackySelectARMCMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, 1722199989Srdivacky ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { 1723199989Srdivacky ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal); 1724199989Srdivacky if (!T) 1725199989Srdivacky return 0; 1726199989Srdivacky 1727199989Srdivacky if (Predicate_so_imm(TrueVal.getNode())) { 1728199989Srdivacky SDValue True = CurDAG->getTargetConstant(T->getZExtValue(), MVT::i32); 1729199989Srdivacky SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); 1730199989Srdivacky SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag }; 1731202375Srdivacky return CurDAG->SelectNodeTo(N, 1732199989Srdivacky ARM::MOVCCi, MVT::i32, Ops, 5); 1733199989Srdivacky } 1734199989Srdivacky return 0; 1735199989Srdivacky} 1736199989Srdivacky 1737202375SrdivackySDNode *ARMDAGToDAGISel::SelectCMOVOp(SDNode *N) { 1738202375Srdivacky EVT VT = N->getValueType(0); 1739202375Srdivacky SDValue FalseVal = N->getOperand(0); 1740202375Srdivacky SDValue TrueVal = N->getOperand(1); 1741202375Srdivacky SDValue CC = N->getOperand(2); 1742202375Srdivacky SDValue CCR = N->getOperand(3); 1743202375Srdivacky SDValue InFlag = N->getOperand(4); 1744199989Srdivacky assert(CC.getOpcode() == ISD::Constant); 1745199989Srdivacky assert(CCR.getOpcode() == ISD::Register); 1746199989Srdivacky ARMCC::CondCodes CCVal = 1747199989Srdivacky (ARMCC::CondCodes)cast<ConstantSDNode>(CC)->getZExtValue(); 1748199989Srdivacky 1749199989Srdivacky if (!Subtarget->isThumb1Only() && VT == MVT::i32) { 1750199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) 1751199989Srdivacky // Emits: (MOVCCs:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) 1752199989Srdivacky // Pattern complexity = 18 cost = 1 size = 0 1753199989Srdivacky SDValue CPTmp0; 1754199989Srdivacky SDValue CPTmp1; 1755199989Srdivacky SDValue CPTmp2; 1756199989Srdivacky if (Subtarget->isThumb()) { 1757202375Srdivacky SDNode *Res = SelectT2CMOVShiftOp(N, FalseVal, TrueVal, 1758199989Srdivacky CCVal, CCR, InFlag); 1759199989Srdivacky if (!Res) 1760202375Srdivacky Res = SelectT2CMOVShiftOp(N, TrueVal, FalseVal, 1761199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1762199989Srdivacky if (Res) 1763199989Srdivacky return Res; 1764199989Srdivacky } else { 1765202375Srdivacky SDNode *Res = SelectARMCMOVShiftOp(N, FalseVal, TrueVal, 1766199989Srdivacky CCVal, CCR, InFlag); 1767199989Srdivacky if (!Res) 1768202375Srdivacky Res = SelectARMCMOVShiftOp(N, TrueVal, FalseVal, 1769199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1770199989Srdivacky if (Res) 1771199989Srdivacky return Res; 1772199989Srdivacky } 1773199989Srdivacky 1774199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, 1775199989Srdivacky // (imm:i32)<<P:Predicate_so_imm>>:$true, 1776199989Srdivacky // (imm:i32):$cc) 1777199989Srdivacky // Emits: (MOVCCi:i32 GPR:i32:$false, 1778199989Srdivacky // (so_imm:i32 (imm:i32):$true), (imm:i32):$cc) 1779199989Srdivacky // Pattern complexity = 10 cost = 1 size = 0 1780199989Srdivacky if (Subtarget->isThumb()) { 1781202375Srdivacky SDNode *Res = SelectT2CMOVSoImmOp(N, FalseVal, TrueVal, 1782199989Srdivacky CCVal, CCR, InFlag); 1783199989Srdivacky if (!Res) 1784202375Srdivacky Res = SelectT2CMOVSoImmOp(N, TrueVal, FalseVal, 1785199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1786199989Srdivacky if (Res) 1787199989Srdivacky return Res; 1788199989Srdivacky } else { 1789202375Srdivacky SDNode *Res = SelectARMCMOVSoImmOp(N, FalseVal, TrueVal, 1790199989Srdivacky CCVal, CCR, InFlag); 1791199989Srdivacky if (!Res) 1792202375Srdivacky Res = SelectARMCMOVSoImmOp(N, TrueVal, FalseVal, 1793199989Srdivacky ARMCC::getOppositeCondition(CCVal), CCR, InFlag); 1794199989Srdivacky if (Res) 1795199989Srdivacky return Res; 1796199989Srdivacky } 1797199989Srdivacky } 1798199989Srdivacky 1799199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1800199989Srdivacky // Emits: (MOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1801199989Srdivacky // Pattern complexity = 6 cost = 1 size = 0 1802199989Srdivacky // 1803199989Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1804199989Srdivacky // Emits: (tMOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1805199989Srdivacky // Pattern complexity = 6 cost = 11 size = 0 1806199989Srdivacky // 1807199989Srdivacky // Also FCPYScc and FCPYDcc. 1808199989Srdivacky SDValue Tmp2 = CurDAG->getTargetConstant(CCVal, MVT::i32); 1809199989Srdivacky SDValue Ops[] = { FalseVal, TrueVal, Tmp2, CCR, InFlag }; 1810199989Srdivacky unsigned Opc = 0; 1811199989Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1812199989Srdivacky default: assert(false && "Illegal conditional move type!"); 1813199989Srdivacky break; 1814199989Srdivacky case MVT::i32: 1815199989Srdivacky Opc = Subtarget->isThumb() 1816199989Srdivacky ? (Subtarget->hasThumb2() ? ARM::t2MOVCCr : ARM::tMOVCCr_pseudo) 1817199989Srdivacky : ARM::MOVCCr; 1818199989Srdivacky break; 1819199989Srdivacky case MVT::f32: 1820199989Srdivacky Opc = ARM::VMOVScc; 1821199989Srdivacky break; 1822199989Srdivacky case MVT::f64: 1823199989Srdivacky Opc = ARM::VMOVDcc; 1824199989Srdivacky break; 1825199989Srdivacky } 1826202375Srdivacky return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5); 1827199989Srdivacky} 1828199989Srdivacky 1829208599SrdivackySDNode *ARMDAGToDAGISel::SelectConcatVector(SDNode *N) { 1830208599Srdivacky // The only time a CONCAT_VECTORS operation can have legal types is when 1831208599Srdivacky // two 64-bit vectors are concatenated to a 128-bit vector. 1832208599Srdivacky EVT VT = N->getValueType(0); 1833208599Srdivacky if (!VT.is128BitVector() || N->getNumOperands() != 2) 1834208599Srdivacky llvm_unreachable("unexpected CONCAT_VECTORS"); 1835208599Srdivacky DebugLoc dl = N->getDebugLoc(); 1836208599Srdivacky SDValue V0 = N->getOperand(0); 1837208599Srdivacky SDValue V1 = N->getOperand(1); 1838208599Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32); 1839208599Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32); 1840208599Srdivacky const SDValue Ops[] = { V0, SubReg0, V1, SubReg1 }; 1841208599Srdivacky return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 4); 1842208599Srdivacky} 1843208599Srdivacky 1844202375SrdivackySDNode *ARMDAGToDAGISel::Select(SDNode *N) { 1845193323Sed DebugLoc dl = N->getDebugLoc(); 1846193323Sed 1847193323Sed if (N->isMachineOpcode()) 1848193323Sed return NULL; // Already selected. 1849193323Sed 1850193323Sed switch (N->getOpcode()) { 1851193323Sed default: break; 1852193323Sed case ISD::Constant: { 1853193323Sed unsigned Val = cast<ConstantSDNode>(N)->getZExtValue(); 1854193323Sed bool UseCP = true; 1855198090Srdivacky if (Subtarget->hasThumb2()) 1856198090Srdivacky // Thumb2-aware targets have the MOVT instruction, so all immediates can 1857198090Srdivacky // be done with MOV + MOVT, at worst. 1858198090Srdivacky UseCP = 0; 1859198090Srdivacky else { 1860198090Srdivacky if (Subtarget->isThumb()) { 1861194710Sed UseCP = (Val > 255 && // MOV 1862194710Sed ~Val > 255 && // MOV + MVN 1863194710Sed !ARM_AM::isThumbImmShiftedVal(Val)); // MOV + LSL 1864198090Srdivacky } else 1865198090Srdivacky UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV 1866198090Srdivacky ARM_AM::getSOImmVal(~Val) == -1 && // MVN 1867198090Srdivacky !ARM_AM::isSOImmTwoPartVal(Val)); // two instrs. 1868198090Srdivacky } 1869198090Srdivacky 1870193323Sed if (UseCP) { 1871193323Sed SDValue CPIdx = 1872198090Srdivacky CurDAG->getTargetConstantPool(ConstantInt::get( 1873198090Srdivacky Type::getInt32Ty(*CurDAG->getContext()), Val), 1874193323Sed TLI.getPointerTy()); 1875193323Sed 1876193323Sed SDNode *ResNode; 1877198090Srdivacky if (Subtarget->isThumb1Only()) { 1878207618Srdivacky SDValue Pred = getAL(CurDAG); 1879198090Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1880198090Srdivacky SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() }; 1881198090Srdivacky ResNode = CurDAG->getMachineNode(ARM::tLDRcp, dl, MVT::i32, MVT::Other, 1882198090Srdivacky Ops, 4); 1883198090Srdivacky } else { 1884193323Sed SDValue Ops[] = { 1885198090Srdivacky CPIdx, 1886193323Sed CurDAG->getRegister(0, MVT::i32), 1887193323Sed CurDAG->getTargetConstant(0, MVT::i32), 1888193323Sed getAL(CurDAG), 1889193323Sed CurDAG->getRegister(0, MVT::i32), 1890193323Sed CurDAG->getEntryNode() 1891193323Sed }; 1892198090Srdivacky ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other, 1893198090Srdivacky Ops, 6); 1894193323Sed } 1895202375Srdivacky ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0)); 1896193323Sed return NULL; 1897193323Sed } 1898198090Srdivacky 1899193323Sed // Other cases are autogenerated. 1900193323Sed break; 1901193323Sed } 1902193323Sed case ISD::FrameIndex: { 1903193323Sed // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm. 1904193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 1905193323Sed SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 1906198090Srdivacky if (Subtarget->isThumb1Only()) { 1907193323Sed return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI, 1908193323Sed CurDAG->getTargetConstant(0, MVT::i32)); 1909193323Sed } else { 1910198090Srdivacky unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ? 1911198090Srdivacky ARM::t2ADDri : ARM::ADDri); 1912193323Sed SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32), 1913198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1914198090Srdivacky CurDAG->getRegister(0, MVT::i32) }; 1915198090Srdivacky return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); 1916193323Sed } 1917193323Sed } 1918198090Srdivacky case ISD::SRL: 1919207618Srdivacky if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false)) 1920198090Srdivacky return I; 1921193323Sed break; 1922198090Srdivacky case ISD::SRA: 1923207618Srdivacky if (SDNode *I = SelectV6T2BitfieldExtractOp(N, true)) 1924198090Srdivacky return I; 1925198090Srdivacky break; 1926193323Sed case ISD::MUL: 1927198090Srdivacky if (Subtarget->isThumb1Only()) 1928193323Sed break; 1929202375Srdivacky if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) { 1930193323Sed unsigned RHSV = C->getZExtValue(); 1931193323Sed if (!RHSV) break; 1932193323Sed if (isPowerOf2_32(RHSV-1)) { // 2^n+1? 1933198090Srdivacky unsigned ShImm = Log2_32(RHSV-1); 1934198090Srdivacky if (ShImm >= 32) 1935198090Srdivacky break; 1936202375Srdivacky SDValue V = N->getOperand(0); 1937198090Srdivacky ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); 1938198090Srdivacky SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); 1939198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1940198090Srdivacky if (Subtarget->isThumb()) { 1941198090Srdivacky SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1942198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops, 6); 1943198090Srdivacky } else { 1944198090Srdivacky SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1945198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 7); 1946198090Srdivacky } 1947193323Sed } 1948193323Sed if (isPowerOf2_32(RHSV+1)) { // 2^n-1? 1949198090Srdivacky unsigned ShImm = Log2_32(RHSV+1); 1950198090Srdivacky if (ShImm >= 32) 1951198090Srdivacky break; 1952202375Srdivacky SDValue V = N->getOperand(0); 1953198090Srdivacky ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); 1954198090Srdivacky SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); 1955198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1956198090Srdivacky if (Subtarget->isThumb()) { 1957198090Srdivacky SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0 }; 1958198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops, 5); 1959198090Srdivacky } else { 1960198090Srdivacky SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1961198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 7); 1962198090Srdivacky } 1963193323Sed } 1964193323Sed } 1965193323Sed break; 1966198396Srdivacky case ISD::AND: { 1967207618Srdivacky // Check for unsigned bitfield extract 1968207618Srdivacky if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false)) 1969207618Srdivacky return I; 1970207618Srdivacky 1971198396Srdivacky // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits 1972198396Srdivacky // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits 1973198396Srdivacky // are entirely contributed by c2 and lower 16-bits are entirely contributed 1974198396Srdivacky // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)). 1975198396Srdivacky // Select it to: "movt x, ((c1 & 0xffff) >> 16) 1976202375Srdivacky EVT VT = N->getValueType(0); 1977198396Srdivacky if (VT != MVT::i32) 1978198396Srdivacky break; 1979198396Srdivacky unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2()) 1980198396Srdivacky ? ARM::t2MOVTi16 1981198396Srdivacky : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0); 1982198396Srdivacky if (!Opc) 1983198396Srdivacky break; 1984202375Srdivacky SDValue N0 = N->getOperand(0), N1 = N->getOperand(1); 1985198396Srdivacky ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); 1986198396Srdivacky if (!N1C) 1987198396Srdivacky break; 1988198396Srdivacky if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) { 1989198396Srdivacky SDValue N2 = N0.getOperand(1); 1990198396Srdivacky ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2); 1991198396Srdivacky if (!N2C) 1992198396Srdivacky break; 1993198396Srdivacky unsigned N1CVal = N1C->getZExtValue(); 1994198396Srdivacky unsigned N2CVal = N2C->getZExtValue(); 1995198396Srdivacky if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) && 1996198396Srdivacky (N1CVal & 0xffffU) == 0xffffU && 1997198396Srdivacky (N2CVal & 0xffffU) == 0x0U) { 1998198396Srdivacky SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16, 1999198396Srdivacky MVT::i32); 2000198396Srdivacky SDValue Ops[] = { N0.getOperand(0), Imm16, 2001198396Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; 2002198396Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, Ops, 4); 2003198396Srdivacky } 2004198396Srdivacky } 2005198396Srdivacky break; 2006198396Srdivacky } 2007199481Srdivacky case ARMISD::VMOVRRD: 2008199481Srdivacky return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32, 2009202375Srdivacky N->getOperand(0), getAL(CurDAG), 2010198090Srdivacky CurDAG->getRegister(0, MVT::i32)); 2011193323Sed case ISD::UMUL_LOHI: { 2012198090Srdivacky if (Subtarget->isThumb1Only()) 2013198090Srdivacky break; 2014198090Srdivacky if (Subtarget->isThumb()) { 2015202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 2016193323Sed getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 2017193323Sed CurDAG->getRegister(0, MVT::i32) }; 2018198090Srdivacky return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops,4); 2019198090Srdivacky } else { 2020202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 2021198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 2022198090Srdivacky CurDAG->getRegister(0, MVT::i32) }; 2023198090Srdivacky return CurDAG->getMachineNode(ARM::UMULL, dl, MVT::i32, MVT::i32, Ops, 5); 2024198090Srdivacky } 2025193323Sed } 2026193323Sed case ISD::SMUL_LOHI: { 2027198090Srdivacky if (Subtarget->isThumb1Only()) 2028198090Srdivacky break; 2029198090Srdivacky if (Subtarget->isThumb()) { 2030202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 2031198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; 2032198090Srdivacky return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops,4); 2033198090Srdivacky } else { 2034202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 2035193323Sed getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 2036193323Sed CurDAG->getRegister(0, MVT::i32) }; 2037198090Srdivacky return CurDAG->getMachineNode(ARM::SMULL, dl, MVT::i32, MVT::i32, Ops, 5); 2038198090Srdivacky } 2039193323Sed } 2040193323Sed case ISD::LOAD: { 2041195340Sed SDNode *ResNode = 0; 2042198090Srdivacky if (Subtarget->isThumb() && Subtarget->hasThumb2()) 2043202375Srdivacky ResNode = SelectT2IndexedLoad(N); 2044195340Sed else 2045202375Srdivacky ResNode = SelectARMIndexedLoad(N); 2046195340Sed if (ResNode) 2047195340Sed return ResNode; 2048206083Srdivacky 2049206083Srdivacky // VLDMQ must be custom-selected for "v2f64 load" to set the AM5Opc value. 2050206083Srdivacky if (Subtarget->hasVFP2() && 2051206083Srdivacky N->getValueType(0).getSimpleVT().SimpleTy == MVT::v2f64) { 2052206083Srdivacky SDValue Chain = N->getOperand(0); 2053206083Srdivacky SDValue AM5Opc = 2054206083Srdivacky CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::ia, 4), MVT::i32); 2055207618Srdivacky SDValue Pred = getAL(CurDAG); 2056206083Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 2057206083Srdivacky SDValue Ops[] = { N->getOperand(1), AM5Opc, Pred, PredReg, Chain }; 2058208599Srdivacky MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 2059208599Srdivacky MemOp[0] = cast<MemSDNode>(N)->getMemOperand(); 2060208599Srdivacky SDNode *Ret = CurDAG->getMachineNode(ARM::VLDMQ, dl, 2061208599Srdivacky MVT::v2f64, MVT::Other, Ops, 5); 2062208599Srdivacky cast<MachineSDNode>(Ret)->setMemRefs(MemOp, MemOp + 1); 2063208599Srdivacky return Ret; 2064206083Srdivacky } 2065193323Sed // Other cases are autogenerated. 2066193323Sed break; 2067193323Sed } 2068206083Srdivacky case ISD::STORE: { 2069206083Srdivacky // VSTMQ must be custom-selected for "v2f64 store" to set the AM5Opc value. 2070206083Srdivacky if (Subtarget->hasVFP2() && 2071206083Srdivacky N->getOperand(1).getValueType().getSimpleVT().SimpleTy == MVT::v2f64) { 2072206083Srdivacky SDValue Chain = N->getOperand(0); 2073206083Srdivacky SDValue AM5Opc = 2074206083Srdivacky CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::ia, 4), MVT::i32); 2075207618Srdivacky SDValue Pred = getAL(CurDAG); 2076206083Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 2077206083Srdivacky SDValue Ops[] = { N->getOperand(1), N->getOperand(2), 2078206083Srdivacky AM5Opc, Pred, PredReg, Chain }; 2079208599Srdivacky MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 2080208599Srdivacky MemOp[0] = cast<MemSDNode>(N)->getMemOperand(); 2081208599Srdivacky SDNode *Ret = CurDAG->getMachineNode(ARM::VSTMQ, dl, MVT::Other, Ops, 6); 2082208599Srdivacky cast<MachineSDNode>(Ret)->setMemRefs(MemOp, MemOp + 1); 2083208599Srdivacky return Ret; 2084206083Srdivacky } 2085206083Srdivacky // Other cases are autogenerated. 2086206083Srdivacky break; 2087206083Srdivacky } 2088193323Sed case ARMISD::BRCOND: { 2089193323Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 2090193323Sed // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc) 2091193323Sed // Pattern complexity = 6 cost = 1 size = 0 2092193323Sed 2093193323Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 2094193323Sed // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc) 2095193323Sed // Pattern complexity = 6 cost = 1 size = 0 2096193323Sed 2097195340Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 2098195340Sed // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc) 2099195340Sed // Pattern complexity = 6 cost = 1 size = 0 2100195340Sed 2101198090Srdivacky unsigned Opc = Subtarget->isThumb() ? 2102195340Sed ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc; 2103202375Srdivacky SDValue Chain = N->getOperand(0); 2104202375Srdivacky SDValue N1 = N->getOperand(1); 2105202375Srdivacky SDValue N2 = N->getOperand(2); 2106202375Srdivacky SDValue N3 = N->getOperand(3); 2107202375Srdivacky SDValue InFlag = N->getOperand(4); 2108193323Sed assert(N1.getOpcode() == ISD::BasicBlock); 2109193323Sed assert(N2.getOpcode() == ISD::Constant); 2110193323Sed assert(N3.getOpcode() == ISD::Register); 2111193323Sed 2112193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 2113193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 2114193323Sed MVT::i32); 2115193323Sed SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag }; 2116198090Srdivacky SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other, 2117198090Srdivacky MVT::Flag, Ops, 5); 2118193323Sed Chain = SDValue(ResNode, 0); 2119202375Srdivacky if (N->getNumValues() == 2) { 2120193323Sed InFlag = SDValue(ResNode, 1); 2121202375Srdivacky ReplaceUses(SDValue(N, 1), InFlag); 2122193323Sed } 2123202375Srdivacky ReplaceUses(SDValue(N, 0), 2124199511Srdivacky SDValue(Chain.getNode(), Chain.getResNo())); 2125193323Sed return NULL; 2126193323Sed } 2127199989Srdivacky case ARMISD::CMOV: 2128202375Srdivacky return SelectCMOVOp(N); 2129193323Sed case ARMISD::CNEG: { 2130202375Srdivacky EVT VT = N->getValueType(0); 2131202375Srdivacky SDValue N0 = N->getOperand(0); 2132202375Srdivacky SDValue N1 = N->getOperand(1); 2133202375Srdivacky SDValue N2 = N->getOperand(2); 2134202375Srdivacky SDValue N3 = N->getOperand(3); 2135202375Srdivacky SDValue InFlag = N->getOperand(4); 2136193323Sed assert(N2.getOpcode() == ISD::Constant); 2137193323Sed assert(N3.getOpcode() == ISD::Register); 2138193323Sed 2139193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 2140193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 2141193323Sed MVT::i32); 2142193323Sed SDValue Ops[] = { N0, N1, Tmp2, N3, InFlag }; 2143193323Sed unsigned Opc = 0; 2144198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 2145193323Sed default: assert(false && "Illegal conditional move type!"); 2146193323Sed break; 2147193323Sed case MVT::f32: 2148199481Srdivacky Opc = ARM::VNEGScc; 2149193323Sed break; 2150193323Sed case MVT::f64: 2151199481Srdivacky Opc = ARM::VNEGDcc; 2152193323Sed break; 2153193323Sed } 2154202375Srdivacky return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5); 2155193323Sed } 2156193323Sed 2157198090Srdivacky case ARMISD::VZIP: { 2158198090Srdivacky unsigned Opc = 0; 2159198090Srdivacky EVT VT = N->getValueType(0); 2160198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 2161198090Srdivacky default: return NULL; 2162198090Srdivacky case MVT::v8i8: Opc = ARM::VZIPd8; break; 2163198090Srdivacky case MVT::v4i16: Opc = ARM::VZIPd16; break; 2164198090Srdivacky case MVT::v2f32: 2165198090Srdivacky case MVT::v2i32: Opc = ARM::VZIPd32; break; 2166198090Srdivacky case MVT::v16i8: Opc = ARM::VZIPq8; break; 2167198090Srdivacky case MVT::v8i16: Opc = ARM::VZIPq16; break; 2168198090Srdivacky case MVT::v4f32: 2169198090Srdivacky case MVT::v4i32: Opc = ARM::VZIPq32; break; 2170193323Sed } 2171207618Srdivacky SDValue Pred = getAL(CurDAG); 2172199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 2173199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 2174199989Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); 2175198090Srdivacky } 2176198090Srdivacky case ARMISD::VUZP: { 2177198090Srdivacky unsigned Opc = 0; 2178198090Srdivacky EVT VT = N->getValueType(0); 2179198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 2180198090Srdivacky default: return NULL; 2181198090Srdivacky case MVT::v8i8: Opc = ARM::VUZPd8; break; 2182198090Srdivacky case MVT::v4i16: Opc = ARM::VUZPd16; break; 2183198090Srdivacky case MVT::v2f32: 2184198090Srdivacky case MVT::v2i32: Opc = ARM::VUZPd32; break; 2185198090Srdivacky case MVT::v16i8: Opc = ARM::VUZPq8; break; 2186198090Srdivacky case MVT::v8i16: Opc = ARM::VUZPq16; break; 2187198090Srdivacky case MVT::v4f32: 2188198090Srdivacky case MVT::v4i32: Opc = ARM::VUZPq32; break; 2189193323Sed } 2190207618Srdivacky SDValue Pred = getAL(CurDAG); 2191199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 2192199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 2193199989Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); 2194198090Srdivacky } 2195198090Srdivacky case ARMISD::VTRN: { 2196198090Srdivacky unsigned Opc = 0; 2197198090Srdivacky EVT VT = N->getValueType(0); 2198198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 2199198090Srdivacky default: return NULL; 2200198090Srdivacky case MVT::v8i8: Opc = ARM::VTRNd8; break; 2201198090Srdivacky case MVT::v4i16: Opc = ARM::VTRNd16; break; 2202198090Srdivacky case MVT::v2f32: 2203198090Srdivacky case MVT::v2i32: Opc = ARM::VTRNd32; break; 2204198090Srdivacky case MVT::v16i8: Opc = ARM::VTRNq8; break; 2205198090Srdivacky case MVT::v8i16: Opc = ARM::VTRNq16; break; 2206198090Srdivacky case MVT::v4f32: 2207198090Srdivacky case MVT::v4i32: Opc = ARM::VTRNq32; break; 2208193323Sed } 2209207618Srdivacky SDValue Pred = getAL(CurDAG); 2210199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 2211199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 2212199989Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); 2213193323Sed } 2214194710Sed 2215198090Srdivacky case ISD::INTRINSIC_VOID: 2216198090Srdivacky case ISD::INTRINSIC_W_CHAIN: { 2217198090Srdivacky unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue(); 2218198090Srdivacky switch (IntNo) { 2219198090Srdivacky default: 2220198090Srdivacky break; 2221194710Sed 2222206083Srdivacky case Intrinsic::arm_neon_vld1: { 2223206083Srdivacky unsigned DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16, 2224206083Srdivacky ARM::VLD1d32, ARM::VLD1d64 }; 2225206083Srdivacky unsigned QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16, 2226206083Srdivacky ARM::VLD1q32, ARM::VLD1q64 }; 2227206083Srdivacky return SelectVLD(N, 1, DOpcodes, QOpcodes, 0); 2228206083Srdivacky } 2229206083Srdivacky 2230198090Srdivacky case Intrinsic::arm_neon_vld2: { 2231198090Srdivacky unsigned DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16, 2232206083Srdivacky ARM::VLD2d32, ARM::VLD1q64 }; 2233198090Srdivacky unsigned QOpcodes[] = { ARM::VLD2q8, ARM::VLD2q16, ARM::VLD2q32 }; 2234202375Srdivacky return SelectVLD(N, 2, DOpcodes, QOpcodes, 0); 2235198090Srdivacky } 2236194710Sed 2237198090Srdivacky case Intrinsic::arm_neon_vld3: { 2238198090Srdivacky unsigned DOpcodes[] = { ARM::VLD3d8, ARM::VLD3d16, 2239206083Srdivacky ARM::VLD3d32, ARM::VLD1d64T }; 2240205407Srdivacky unsigned QOpcodes0[] = { ARM::VLD3q8_UPD, 2241205407Srdivacky ARM::VLD3q16_UPD, 2242205407Srdivacky ARM::VLD3q32_UPD }; 2243205407Srdivacky unsigned QOpcodes1[] = { ARM::VLD3q8odd_UPD, 2244205407Srdivacky ARM::VLD3q16odd_UPD, 2245205407Srdivacky ARM::VLD3q32odd_UPD }; 2246202375Srdivacky return SelectVLD(N, 3, DOpcodes, QOpcodes0, QOpcodes1); 2247198090Srdivacky } 2248198090Srdivacky 2249198090Srdivacky case Intrinsic::arm_neon_vld4: { 2250198090Srdivacky unsigned DOpcodes[] = { ARM::VLD4d8, ARM::VLD4d16, 2251206083Srdivacky ARM::VLD4d32, ARM::VLD1d64Q }; 2252205407Srdivacky unsigned QOpcodes0[] = { ARM::VLD4q8_UPD, 2253205407Srdivacky ARM::VLD4q16_UPD, 2254205407Srdivacky ARM::VLD4q32_UPD }; 2255205407Srdivacky unsigned QOpcodes1[] = { ARM::VLD4q8odd_UPD, 2256205407Srdivacky ARM::VLD4q16odd_UPD, 2257205407Srdivacky ARM::VLD4q32odd_UPD }; 2258202375Srdivacky return SelectVLD(N, 4, DOpcodes, QOpcodes0, QOpcodes1); 2259198090Srdivacky } 2260198090Srdivacky 2261198090Srdivacky case Intrinsic::arm_neon_vld2lane: { 2262198090Srdivacky unsigned DOpcodes[] = { ARM::VLD2LNd8, ARM::VLD2LNd16, ARM::VLD2LNd32 }; 2263205407Srdivacky unsigned QOpcodes0[] = { ARM::VLD2LNq16, ARM::VLD2LNq32 }; 2264205407Srdivacky unsigned QOpcodes1[] = { ARM::VLD2LNq16odd, ARM::VLD2LNq32odd }; 2265202375Srdivacky return SelectVLDSTLane(N, true, 2, DOpcodes, QOpcodes0, QOpcodes1); 2266198090Srdivacky } 2267198090Srdivacky 2268198090Srdivacky case Intrinsic::arm_neon_vld3lane: { 2269198090Srdivacky unsigned DOpcodes[] = { ARM::VLD3LNd8, ARM::VLD3LNd16, ARM::VLD3LNd32 }; 2270205407Srdivacky unsigned QOpcodes0[] = { ARM::VLD3LNq16, ARM::VLD3LNq32 }; 2271205407Srdivacky unsigned QOpcodes1[] = { ARM::VLD3LNq16odd, ARM::VLD3LNq32odd }; 2272202375Srdivacky return SelectVLDSTLane(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1); 2273198090Srdivacky } 2274198090Srdivacky 2275198090Srdivacky case Intrinsic::arm_neon_vld4lane: { 2276198090Srdivacky unsigned DOpcodes[] = { ARM::VLD4LNd8, ARM::VLD4LNd16, ARM::VLD4LNd32 }; 2277205407Srdivacky unsigned QOpcodes0[] = { ARM::VLD4LNq16, ARM::VLD4LNq32 }; 2278205407Srdivacky unsigned QOpcodes1[] = { ARM::VLD4LNq16odd, ARM::VLD4LNq32odd }; 2279202375Srdivacky return SelectVLDSTLane(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1); 2280198090Srdivacky } 2281198090Srdivacky 2282206083Srdivacky case Intrinsic::arm_neon_vst1: { 2283206083Srdivacky unsigned DOpcodes[] = { ARM::VST1d8, ARM::VST1d16, 2284206083Srdivacky ARM::VST1d32, ARM::VST1d64 }; 2285206083Srdivacky unsigned QOpcodes[] = { ARM::VST1q8, ARM::VST1q16, 2286206083Srdivacky ARM::VST1q32, ARM::VST1q64 }; 2287206083Srdivacky return SelectVST(N, 1, DOpcodes, QOpcodes, 0); 2288206083Srdivacky } 2289206083Srdivacky 2290198090Srdivacky case Intrinsic::arm_neon_vst2: { 2291198113Srdivacky unsigned DOpcodes[] = { ARM::VST2d8, ARM::VST2d16, 2292206083Srdivacky ARM::VST2d32, ARM::VST1q64 }; 2293198113Srdivacky unsigned QOpcodes[] = { ARM::VST2q8, ARM::VST2q16, ARM::VST2q32 }; 2294202375Srdivacky return SelectVST(N, 2, DOpcodes, QOpcodes, 0); 2295198090Srdivacky } 2296194710Sed 2297198090Srdivacky case Intrinsic::arm_neon_vst3: { 2298198113Srdivacky unsigned DOpcodes[] = { ARM::VST3d8, ARM::VST3d16, 2299206083Srdivacky ARM::VST3d32, ARM::VST1d64T }; 2300205407Srdivacky unsigned QOpcodes0[] = { ARM::VST3q8_UPD, 2301205407Srdivacky ARM::VST3q16_UPD, 2302205407Srdivacky ARM::VST3q32_UPD }; 2303205407Srdivacky unsigned QOpcodes1[] = { ARM::VST3q8odd_UPD, 2304205407Srdivacky ARM::VST3q16odd_UPD, 2305205407Srdivacky ARM::VST3q32odd_UPD }; 2306202375Srdivacky return SelectVST(N, 3, DOpcodes, QOpcodes0, QOpcodes1); 2307194710Sed } 2308194710Sed 2309198090Srdivacky case Intrinsic::arm_neon_vst4: { 2310198113Srdivacky unsigned DOpcodes[] = { ARM::VST4d8, ARM::VST4d16, 2311206083Srdivacky ARM::VST4d32, ARM::VST1d64Q }; 2312205407Srdivacky unsigned QOpcodes0[] = { ARM::VST4q8_UPD, 2313205407Srdivacky ARM::VST4q16_UPD, 2314205407Srdivacky ARM::VST4q32_UPD }; 2315205407Srdivacky unsigned QOpcodes1[] = { ARM::VST4q8odd_UPD, 2316205407Srdivacky ARM::VST4q16odd_UPD, 2317205407Srdivacky ARM::VST4q32odd_UPD }; 2318202375Srdivacky return SelectVST(N, 4, DOpcodes, QOpcodes0, QOpcodes1); 2319198090Srdivacky } 2320198090Srdivacky 2321198090Srdivacky case Intrinsic::arm_neon_vst2lane: { 2322198090Srdivacky unsigned DOpcodes[] = { ARM::VST2LNd8, ARM::VST2LNd16, ARM::VST2LNd32 }; 2323205407Srdivacky unsigned QOpcodes0[] = { ARM::VST2LNq16, ARM::VST2LNq32 }; 2324205407Srdivacky unsigned QOpcodes1[] = { ARM::VST2LNq16odd, ARM::VST2LNq32odd }; 2325202375Srdivacky return SelectVLDSTLane(N, false, 2, DOpcodes, QOpcodes0, QOpcodes1); 2326198090Srdivacky } 2327198090Srdivacky 2328198090Srdivacky case Intrinsic::arm_neon_vst3lane: { 2329198090Srdivacky unsigned DOpcodes[] = { ARM::VST3LNd8, ARM::VST3LNd16, ARM::VST3LNd32 }; 2330205407Srdivacky unsigned QOpcodes0[] = { ARM::VST3LNq16, ARM::VST3LNq32 }; 2331205407Srdivacky unsigned QOpcodes1[] = { ARM::VST3LNq16odd, ARM::VST3LNq32odd }; 2332202375Srdivacky return SelectVLDSTLane(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1); 2333198090Srdivacky } 2334198090Srdivacky 2335198090Srdivacky case Intrinsic::arm_neon_vst4lane: { 2336198090Srdivacky unsigned DOpcodes[] = { ARM::VST4LNd8, ARM::VST4LNd16, ARM::VST4LNd32 }; 2337205407Srdivacky unsigned QOpcodes0[] = { ARM::VST4LNq16, ARM::VST4LNq32 }; 2338205407Srdivacky unsigned QOpcodes1[] = { ARM::VST4LNq16odd, ARM::VST4LNq32odd }; 2339202375Srdivacky return SelectVLDSTLane(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1); 2340198090Srdivacky } 2341198090Srdivacky } 2342208599Srdivacky break; 2343194710Sed } 2344208599Srdivacky 2345208599Srdivacky case ISD::CONCAT_VECTORS: 2346208599Srdivacky return SelectConcatVector(N); 2347194710Sed } 2348194710Sed 2349202375Srdivacky return SelectCode(N); 2350193323Sed} 2351193323Sed 2352193323Sedbool ARMDAGToDAGISel:: 2353193323SedSelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, 2354193323Sed std::vector<SDValue> &OutOps) { 2355193323Sed assert(ConstraintCode == 'm' && "unexpected asm memory constraint"); 2356198090Srdivacky // Require the address to be in a register. That is safe for all ARM 2357198090Srdivacky // variants and it is hard to do anything much smarter without knowing 2358198090Srdivacky // how the operand is used. 2359198090Srdivacky OutOps.push_back(Op); 2360193323Sed return false; 2361193323Sed} 2362193323Sed 2363193323Sed/// createARMISelDag - This pass converts a legalized DAG into a 2364193323Sed/// ARM-specific DAG, ready for instruction scheduling. 2365193323Sed/// 2366198090SrdivackyFunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM, 2367198090Srdivacky CodeGenOpt::Level OptLevel) { 2368198090Srdivacky return new ARMDAGToDAGISel(TM, OptLevel); 2369193323Sed} 2370208599Srdivacky 2371208599Srdivacky/// ModelWithRegSequence - Return true if isel should use REG_SEQUENCE to model 2372208599Srdivacky/// operations involving sub-registers. 2373208599Srdivackybool llvm::ModelWithRegSequence() { 2374208599Srdivacky return UseRegSeq; 2375208599Srdivacky} 2376