ARMISelDAGToDAG.cpp revision 198090
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 "ARMConstantPoolValue.h" 17193323Sed#include "ARMISelLowering.h" 18193323Sed#include "ARMTargetMachine.h" 19193323Sed#include "llvm/CallingConv.h" 20193323Sed#include "llvm/Constants.h" 21193323Sed#include "llvm/DerivedTypes.h" 22193323Sed#include "llvm/Function.h" 23193323Sed#include "llvm/Intrinsics.h" 24198090Srdivacky#include "llvm/LLVMContext.h" 25193323Sed#include "llvm/CodeGen/MachineFrameInfo.h" 26193323Sed#include "llvm/CodeGen/MachineFunction.h" 27193323Sed#include "llvm/CodeGen/MachineInstrBuilder.h" 28193323Sed#include "llvm/CodeGen/SelectionDAG.h" 29193323Sed#include "llvm/CodeGen/SelectionDAGISel.h" 30193323Sed#include "llvm/Target/TargetLowering.h" 31193323Sed#include "llvm/Target/TargetOptions.h" 32193323Sed#include "llvm/Support/Compiler.h" 33193323Sed#include "llvm/Support/Debug.h" 34198090Srdivacky#include "llvm/Support/ErrorHandling.h" 35198090Srdivacky#include "llvm/Support/raw_ostream.h" 36198090Srdivacky 37193323Sedusing namespace llvm; 38193323Sed 39193323Sed//===--------------------------------------------------------------------===// 40193323Sed/// ARMDAGToDAGISel - ARM specific code to select ARM machine 41193323Sed/// instructions for SelectionDAG operations. 42193323Sed/// 43193323Sednamespace { 44193323Sedclass ARMDAGToDAGISel : public SelectionDAGISel { 45195098Sed ARMBaseTargetMachine &TM; 46193323Sed 47193323Sed /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can 48193323Sed /// make the right decision when generating code for different targets. 49193323Sed const ARMSubtarget *Subtarget; 50193323Sed 51193323Sedpublic: 52198090Srdivacky explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm, 53198090Srdivacky CodeGenOpt::Level OptLevel) 54198090Srdivacky : SelectionDAGISel(tm, OptLevel), TM(tm), 55193323Sed Subtarget(&TM.getSubtarget<ARMSubtarget>()) { 56193323Sed } 57193323Sed 58193323Sed virtual const char *getPassName() const { 59193323Sed return "ARM Instruction Selection"; 60194612Sed } 61194612Sed 62198090Srdivacky /// getI32Imm - Return a target constant of type i32 with the specified 63198090Srdivacky /// value. 64194612Sed inline SDValue getI32Imm(unsigned Imm) { 65194612Sed return CurDAG->getTargetConstant(Imm, MVT::i32); 66194612Sed } 67194612Sed 68193323Sed SDNode *Select(SDValue Op); 69193323Sed virtual void InstructionSelect(); 70195340Sed bool SelectShifterOperandReg(SDValue Op, SDValue N, SDValue &A, 71195340Sed SDValue &B, SDValue &C); 72193323Sed bool SelectAddrMode2(SDValue Op, SDValue N, SDValue &Base, 73193323Sed SDValue &Offset, SDValue &Opc); 74193323Sed bool SelectAddrMode2Offset(SDValue Op, SDValue N, 75193323Sed SDValue &Offset, SDValue &Opc); 76193323Sed bool SelectAddrMode3(SDValue Op, SDValue N, SDValue &Base, 77193323Sed SDValue &Offset, SDValue &Opc); 78193323Sed bool SelectAddrMode3Offset(SDValue Op, SDValue N, 79193323Sed SDValue &Offset, SDValue &Opc); 80198090Srdivacky bool SelectAddrMode4(SDValue Op, SDValue N, SDValue &Addr, 81198090Srdivacky SDValue &Mode); 82193323Sed bool SelectAddrMode5(SDValue Op, SDValue N, SDValue &Base, 83193323Sed SDValue &Offset); 84195340Sed bool SelectAddrMode6(SDValue Op, SDValue N, SDValue &Addr, SDValue &Update, 85195340Sed SDValue &Opc); 86193323Sed 87193323Sed bool SelectAddrModePC(SDValue Op, SDValue N, SDValue &Offset, 88195340Sed SDValue &Label); 89193323Sed 90193323Sed bool SelectThumbAddrModeRR(SDValue Op, SDValue N, SDValue &Base, 91193323Sed SDValue &Offset); 92193323Sed bool SelectThumbAddrModeRI5(SDValue Op, SDValue N, unsigned Scale, 93193323Sed SDValue &Base, SDValue &OffImm, 94193323Sed SDValue &Offset); 95193323Sed bool SelectThumbAddrModeS1(SDValue Op, SDValue N, SDValue &Base, 96193323Sed SDValue &OffImm, SDValue &Offset); 97193323Sed bool SelectThumbAddrModeS2(SDValue Op, SDValue N, SDValue &Base, 98193323Sed SDValue &OffImm, SDValue &Offset); 99193323Sed bool SelectThumbAddrModeS4(SDValue Op, SDValue N, SDValue &Base, 100193323Sed SDValue &OffImm, SDValue &Offset); 101193323Sed bool SelectThumbAddrModeSP(SDValue Op, SDValue N, SDValue &Base, 102193323Sed SDValue &OffImm); 103193323Sed 104195098Sed bool SelectT2ShifterOperandReg(SDValue Op, SDValue N, 105195098Sed SDValue &BaseReg, SDValue &Opc); 106195340Sed bool SelectT2AddrModeImm12(SDValue Op, SDValue N, SDValue &Base, 107195340Sed SDValue &OffImm); 108195340Sed bool SelectT2AddrModeImm8(SDValue Op, SDValue N, SDValue &Base, 109195340Sed SDValue &OffImm); 110195340Sed bool SelectT2AddrModeImm8Offset(SDValue Op, SDValue N, 111195340Sed SDValue &OffImm); 112195340Sed bool SelectT2AddrModeImm8s4(SDValue Op, SDValue N, SDValue &Base, 113195340Sed SDValue &OffImm); 114195340Sed bool SelectT2AddrModeSoReg(SDValue Op, SDValue N, SDValue &Base, 115195340Sed SDValue &OffReg, SDValue &ShImm); 116195340Sed 117193323Sed // Include the pieces autogenerated from the target description. 118193323Sed#include "ARMGenDAGISel.inc" 119193323Sed 120193323Sedprivate: 121195340Sed /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for 122195340Sed /// ARM. 123195340Sed SDNode *SelectARMIndexedLoad(SDValue Op); 124195340Sed SDNode *SelectT2IndexedLoad(SDValue Op); 125195340Sed 126198090Srdivacky /// SelectDYN_ALLOC - Select dynamic alloc for Thumb. 127198090Srdivacky SDNode *SelectDYN_ALLOC(SDValue Op); 128195340Sed 129198090Srdivacky /// SelectVLD - Select NEON load intrinsics. NumVecs should 130198090Srdivacky /// be 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. 132198090Srdivacky /// For NumVecs == 2, QOpcodes1 is not used. 133198090Srdivacky SDNode *SelectVLD(SDValue Op, unsigned NumVecs, unsigned *DOpcodes, 134198090Srdivacky unsigned *QOpcodes0, unsigned *QOpcodes1); 135198090Srdivacky 136198090Srdivacky /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should 137198090Srdivacky /// be 2, 3 or 4. The opcode arrays specify the instructions used for 138198090Srdivacky /// load/store of D registers and even subregs and odd subregs of Q registers. 139198090Srdivacky SDNode *SelectVLDSTLane(SDValue Op, bool IsLoad, unsigned NumVecs, 140198090Srdivacky unsigned *DOpcodes, unsigned *QOpcodes0, 141198090Srdivacky unsigned *QOpcodes1); 142198090Srdivacky 143198090Srdivacky /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM. 144198090Srdivacky SDNode *SelectV6T2BitfieldExtractOp(SDValue Op, unsigned Opc); 145198090Srdivacky 146195340Sed /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for 147195340Sed /// inline asm expressions. 148195340Sed virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, 149195340Sed char ConstraintCode, 150195340Sed std::vector<SDValue> &OutOps); 151198090Srdivacky 152198090Srdivacky /// PairDRegs - Insert a pair of double registers into an implicit def to 153198090Srdivacky /// form a quad register. 154198090Srdivacky SDNode *PairDRegs(EVT VT, SDValue V0, SDValue V1); 155193323Sed}; 156193323Sed} 157193323Sed 158198090Srdivacky/// isInt32Immediate - This method tests to see if the node is a 32-bit constant 159198090Srdivacky/// operand. If so Imm will receive the 32-bit value. 160198090Srdivackystatic bool isInt32Immediate(SDNode *N, unsigned &Imm) { 161198090Srdivacky if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) { 162198090Srdivacky Imm = cast<ConstantSDNode>(N)->getZExtValue(); 163198090Srdivacky return true; 164198090Srdivacky } 165198090Srdivacky return false; 166198090Srdivacky} 167198090Srdivacky 168198090Srdivacky// isInt32Immediate - This method tests to see if a constant operand. 169198090Srdivacky// If so Imm will receive the 32 bit value. 170198090Srdivackystatic bool isInt32Immediate(SDValue N, unsigned &Imm) { 171198090Srdivacky return isInt32Immediate(N.getNode(), Imm); 172198090Srdivacky} 173198090Srdivacky 174198090Srdivacky// isOpcWithIntImmediate - This method tests to see if the node is a specific 175198090Srdivacky// opcode and that it has a immediate integer right operand. 176198090Srdivacky// If so Imm will receive the 32 bit value. 177198090Srdivackystatic bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) { 178198090Srdivacky return N->getOpcode() == Opc && 179198090Srdivacky isInt32Immediate(N->getOperand(1).getNode(), Imm); 180198090Srdivacky} 181198090Srdivacky 182198090Srdivacky 183193323Sedvoid ARMDAGToDAGISel::InstructionSelect() { 184193323Sed DEBUG(BB->dump()); 185193323Sed 186193323Sed SelectRoot(*CurDAG); 187193323Sed CurDAG->RemoveDeadNodes(); 188193323Sed} 189193323Sed 190195340Sedbool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue Op, 191195340Sed SDValue N, 192195340Sed SDValue &BaseReg, 193195340Sed SDValue &ShReg, 194195340Sed SDValue &Opc) { 195195340Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 196195340Sed 197195340Sed // Don't match base register only case. That is matched to a separate 198195340Sed // lower complexity pattern with explicit register operand. 199195340Sed if (ShOpcVal == ARM_AM::no_shift) return false; 200198090Srdivacky 201195340Sed BaseReg = N.getOperand(0); 202195340Sed unsigned ShImmVal = 0; 203195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 204195340Sed ShReg = CurDAG->getRegister(0, MVT::i32); 205195340Sed ShImmVal = RHS->getZExtValue() & 31; 206195340Sed } else { 207195340Sed ShReg = N.getOperand(1); 208195340Sed } 209195340Sed Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), 210195340Sed MVT::i32); 211195340Sed return true; 212195340Sed} 213195340Sed 214193323Sedbool ARMDAGToDAGISel::SelectAddrMode2(SDValue Op, SDValue N, 215193323Sed SDValue &Base, SDValue &Offset, 216193323Sed SDValue &Opc) { 217193323Sed if (N.getOpcode() == ISD::MUL) { 218193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 219193323Sed // X * [3,5,9] -> X + X * [2,4,8] etc. 220193323Sed int RHSC = (int)RHS->getZExtValue(); 221193323Sed if (RHSC & 1) { 222193323Sed RHSC = RHSC & ~1; 223193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 224193323Sed if (RHSC < 0) { 225193323Sed AddSub = ARM_AM::sub; 226193323Sed RHSC = - RHSC; 227193323Sed } 228193323Sed if (isPowerOf2_32(RHSC)) { 229193323Sed unsigned ShAmt = Log2_32(RHSC); 230193323Sed Base = Offset = N.getOperand(0); 231193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, 232193323Sed ARM_AM::lsl), 233193323Sed MVT::i32); 234193323Sed return true; 235193323Sed } 236193323Sed } 237193323Sed } 238193323Sed } 239193323Sed 240193323Sed if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) { 241193323Sed Base = N; 242193323Sed if (N.getOpcode() == ISD::FrameIndex) { 243193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 244193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 245193323Sed } else if (N.getOpcode() == ARMISD::Wrapper) { 246193323Sed Base = N.getOperand(0); 247193323Sed } 248193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 249193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, 250193323Sed ARM_AM::no_shift), 251193323Sed MVT::i32); 252193323Sed return true; 253193323Sed } 254198090Srdivacky 255193323Sed // Match simple R +/- imm12 operands. 256193323Sed if (N.getOpcode() == ISD::ADD) 257193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 258193323Sed int RHSC = (int)RHS->getZExtValue(); 259193323Sed if ((RHSC >= 0 && RHSC < 0x1000) || 260193323Sed (RHSC < 0 && RHSC > -0x1000)) { // 12 bits. 261193323Sed Base = N.getOperand(0); 262193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 263193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 264193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 265193323Sed } 266193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 267193323Sed 268193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 269193323Sed if (RHSC < 0) { 270193323Sed AddSub = ARM_AM::sub; 271193323Sed RHSC = - RHSC; 272193323Sed } 273193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC, 274193323Sed ARM_AM::no_shift), 275193323Sed MVT::i32); 276193323Sed return true; 277193323Sed } 278193323Sed } 279198090Srdivacky 280193323Sed // Otherwise this is R +/- [possibly shifted] R 281193323Sed ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::ADD ? ARM_AM::add:ARM_AM::sub; 282193323Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1)); 283193323Sed unsigned ShAmt = 0; 284198090Srdivacky 285193323Sed Base = N.getOperand(0); 286193323Sed Offset = N.getOperand(1); 287198090Srdivacky 288193323Sed if (ShOpcVal != ARM_AM::no_shift) { 289193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 290193323Sed // it. 291193323Sed if (ConstantSDNode *Sh = 292193323Sed dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) { 293193323Sed ShAmt = Sh->getZExtValue(); 294193323Sed Offset = N.getOperand(1).getOperand(0); 295193323Sed } else { 296193323Sed ShOpcVal = ARM_AM::no_shift; 297193323Sed } 298193323Sed } 299198090Srdivacky 300193323Sed // Try matching (R shl C) + (R). 301193323Sed if (N.getOpcode() == ISD::ADD && ShOpcVal == ARM_AM::no_shift) { 302193323Sed ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0)); 303193323Sed if (ShOpcVal != ARM_AM::no_shift) { 304193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't 305193323Sed // fold it. 306193323Sed if (ConstantSDNode *Sh = 307193323Sed dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) { 308193323Sed ShAmt = Sh->getZExtValue(); 309193323Sed Offset = N.getOperand(0).getOperand(0); 310193323Sed Base = N.getOperand(1); 311193323Sed } else { 312193323Sed ShOpcVal = ARM_AM::no_shift; 313193323Sed } 314193323Sed } 315193323Sed } 316198090Srdivacky 317193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 318193323Sed MVT::i32); 319193323Sed return true; 320193323Sed} 321193323Sed 322193323Sedbool ARMDAGToDAGISel::SelectAddrMode2Offset(SDValue Op, SDValue N, 323193323Sed SDValue &Offset, SDValue &Opc) { 324193323Sed unsigned Opcode = Op.getOpcode(); 325193323Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 326193323Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 327193323Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 328193323Sed ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 329193323Sed ? ARM_AM::add : ARM_AM::sub; 330193323Sed if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 331193323Sed int Val = (int)C->getZExtValue(); 332193323Sed if (Val >= 0 && Val < 0x1000) { // 12 bits. 333193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 334193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val, 335193323Sed ARM_AM::no_shift), 336193323Sed MVT::i32); 337193323Sed return true; 338193323Sed } 339193323Sed } 340193323Sed 341193323Sed Offset = N; 342193323Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 343193323Sed unsigned ShAmt = 0; 344193323Sed if (ShOpcVal != ARM_AM::no_shift) { 345193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 346193323Sed // it. 347193323Sed if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 348193323Sed ShAmt = Sh->getZExtValue(); 349193323Sed Offset = N.getOperand(0); 350193323Sed } else { 351193323Sed ShOpcVal = ARM_AM::no_shift; 352193323Sed } 353193323Sed } 354193323Sed 355193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 356193323Sed MVT::i32); 357193323Sed return true; 358193323Sed} 359193323Sed 360193323Sed 361193323Sedbool ARMDAGToDAGISel::SelectAddrMode3(SDValue Op, SDValue N, 362193323Sed SDValue &Base, SDValue &Offset, 363193323Sed SDValue &Opc) { 364193323Sed if (N.getOpcode() == ISD::SUB) { 365193323Sed // X - C is canonicalize to X + -C, no need to handle it here. 366193323Sed Base = N.getOperand(0); 367193323Sed Offset = N.getOperand(1); 368193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32); 369193323Sed return true; 370193323Sed } 371198090Srdivacky 372193323Sed if (N.getOpcode() != ISD::ADD) { 373193323Sed Base = N; 374193323Sed if (N.getOpcode() == ISD::FrameIndex) { 375193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 376193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 377193323Sed } 378193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 379193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32); 380193323Sed return true; 381193323Sed } 382198090Srdivacky 383193323Sed // If the RHS is +/- imm8, fold into addr mode. 384193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 385193323Sed int RHSC = (int)RHS->getZExtValue(); 386193323Sed if ((RHSC >= 0 && RHSC < 256) || 387193323Sed (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed. 388193323Sed Base = N.getOperand(0); 389193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 390193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 391193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 392193323Sed } 393193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 394193323Sed 395193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 396193323Sed if (RHSC < 0) { 397193323Sed AddSub = ARM_AM::sub; 398193323Sed RHSC = - RHSC; 399193323Sed } 400193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32); 401193323Sed return true; 402193323Sed } 403193323Sed } 404198090Srdivacky 405193323Sed Base = N.getOperand(0); 406193323Sed Offset = N.getOperand(1); 407193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32); 408193323Sed return true; 409193323Sed} 410193323Sed 411193323Sedbool ARMDAGToDAGISel::SelectAddrMode3Offset(SDValue Op, SDValue N, 412193323Sed SDValue &Offset, SDValue &Opc) { 413193323Sed unsigned Opcode = Op.getOpcode(); 414193323Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 415193323Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 416193323Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 417193323Sed ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 418193323Sed ? ARM_AM::add : ARM_AM::sub; 419193323Sed if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 420193323Sed int Val = (int)C->getZExtValue(); 421193323Sed if (Val >= 0 && Val < 256) { 422193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 423193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32); 424193323Sed return true; 425193323Sed } 426193323Sed } 427193323Sed 428193323Sed Offset = N; 429193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32); 430193323Sed return true; 431193323Sed} 432193323Sed 433198090Srdivackybool ARMDAGToDAGISel::SelectAddrMode4(SDValue Op, SDValue N, 434198090Srdivacky SDValue &Addr, SDValue &Mode) { 435198090Srdivacky Addr = N; 436198090Srdivacky Mode = CurDAG->getTargetConstant(0, MVT::i32); 437198090Srdivacky return true; 438198090Srdivacky} 439193323Sed 440193323Sedbool ARMDAGToDAGISel::SelectAddrMode5(SDValue Op, SDValue N, 441193323Sed SDValue &Base, SDValue &Offset) { 442193323Sed if (N.getOpcode() != ISD::ADD) { 443193323Sed Base = N; 444193323Sed if (N.getOpcode() == ISD::FrameIndex) { 445193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 446193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 447193323Sed } else if (N.getOpcode() == ARMISD::Wrapper) { 448193323Sed Base = N.getOperand(0); 449193323Sed } 450193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 451193323Sed MVT::i32); 452193323Sed return true; 453193323Sed } 454198090Srdivacky 455193323Sed // If the RHS is +/- imm8, fold into addr mode. 456193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 457193323Sed int RHSC = (int)RHS->getZExtValue(); 458193323Sed if ((RHSC & 3) == 0) { // The constant is implicitly multiplied by 4. 459193323Sed RHSC >>= 2; 460193323Sed if ((RHSC >= 0 && RHSC < 256) || 461193323Sed (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed. 462193323Sed Base = N.getOperand(0); 463193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 464193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 465193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 466193323Sed } 467193323Sed 468193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 469193323Sed if (RHSC < 0) { 470193323Sed AddSub = ARM_AM::sub; 471193323Sed RHSC = - RHSC; 472193323Sed } 473193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC), 474193323Sed MVT::i32); 475193323Sed return true; 476193323Sed } 477193323Sed } 478193323Sed } 479198090Srdivacky 480193323Sed Base = N; 481193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 482193323Sed MVT::i32); 483193323Sed return true; 484193323Sed} 485193323Sed 486195340Sedbool ARMDAGToDAGISel::SelectAddrMode6(SDValue Op, SDValue N, 487195340Sed SDValue &Addr, SDValue &Update, 488195340Sed SDValue &Opc) { 489195340Sed Addr = N; 490198090Srdivacky // Default to no writeback. 491195340Sed Update = CurDAG->getRegister(0, MVT::i32); 492195340Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(false), MVT::i32); 493195340Sed return true; 494195340Sed} 495195340Sed 496193323Sedbool ARMDAGToDAGISel::SelectAddrModePC(SDValue Op, SDValue N, 497198090Srdivacky SDValue &Offset, SDValue &Label) { 498193323Sed if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) { 499193323Sed Offset = N.getOperand(0); 500193323Sed SDValue N1 = N.getOperand(1); 501193323Sed Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(), 502193323Sed MVT::i32); 503193323Sed return true; 504193323Sed } 505193323Sed return false; 506193323Sed} 507193323Sed 508193323Sedbool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue Op, SDValue N, 509193323Sed SDValue &Base, SDValue &Offset){ 510193323Sed // FIXME dl should come from the parent load or store, not the address 511193323Sed DebugLoc dl = Op.getDebugLoc(); 512193323Sed if (N.getOpcode() != ISD::ADD) { 513198090Srdivacky ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N); 514198090Srdivacky if (!NC || NC->getZExtValue() != 0) 515198090Srdivacky return false; 516198090Srdivacky 517198090Srdivacky Base = Offset = N; 518193323Sed return true; 519193323Sed } 520193323Sed 521193323Sed Base = N.getOperand(0); 522193323Sed Offset = N.getOperand(1); 523193323Sed return true; 524193323Sed} 525193323Sed 526193323Sedbool 527193323SedARMDAGToDAGISel::SelectThumbAddrModeRI5(SDValue Op, SDValue N, 528193323Sed unsigned Scale, SDValue &Base, 529193323Sed SDValue &OffImm, SDValue &Offset) { 530193323Sed if (Scale == 4) { 531193323Sed SDValue TmpBase, TmpOffImm; 532193323Sed if (SelectThumbAddrModeSP(Op, N, TmpBase, TmpOffImm)) 533193323Sed return false; // We want to select tLDRspi / tSTRspi instead. 534193323Sed if (N.getOpcode() == ARMISD::Wrapper && 535193323Sed N.getOperand(0).getOpcode() == ISD::TargetConstantPool) 536193323Sed return false; // We want to select tLDRpci instead. 537193323Sed } 538193323Sed 539193323Sed if (N.getOpcode() != ISD::ADD) { 540193323Sed Base = (N.getOpcode() == ARMISD::Wrapper) ? N.getOperand(0) : N; 541193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 542193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 543193323Sed return true; 544193323Sed } 545193323Sed 546193323Sed // Thumb does not have [sp, r] address mode. 547193323Sed RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 548193323Sed RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1)); 549193323Sed if ((LHSR && LHSR->getReg() == ARM::SP) || 550193323Sed (RHSR && RHSR->getReg() == ARM::SP)) { 551193323Sed Base = N; 552193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 553193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 554193323Sed return true; 555193323Sed } 556193323Sed 557193323Sed // If the RHS is + imm5 * scale, fold into addr mode. 558193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 559193323Sed int RHSC = (int)RHS->getZExtValue(); 560193323Sed if ((RHSC & (Scale-1)) == 0) { // The constant is implicitly multiplied. 561193323Sed RHSC /= Scale; 562193323Sed if (RHSC >= 0 && RHSC < 32) { 563193323Sed Base = N.getOperand(0); 564193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 565193323Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 566193323Sed return true; 567193323Sed } 568193323Sed } 569193323Sed } 570193323Sed 571193323Sed Base = N.getOperand(0); 572193323Sed Offset = N.getOperand(1); 573193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 574193323Sed return true; 575193323Sed} 576193323Sed 577193323Sedbool ARMDAGToDAGISel::SelectThumbAddrModeS1(SDValue Op, SDValue N, 578193323Sed SDValue &Base, SDValue &OffImm, 579193323Sed SDValue &Offset) { 580193323Sed return SelectThumbAddrModeRI5(Op, N, 1, Base, OffImm, Offset); 581193323Sed} 582193323Sed 583193323Sedbool ARMDAGToDAGISel::SelectThumbAddrModeS2(SDValue Op, SDValue N, 584193323Sed SDValue &Base, SDValue &OffImm, 585193323Sed SDValue &Offset) { 586193323Sed return SelectThumbAddrModeRI5(Op, N, 2, Base, OffImm, Offset); 587193323Sed} 588193323Sed 589193323Sedbool ARMDAGToDAGISel::SelectThumbAddrModeS4(SDValue Op, SDValue N, 590193323Sed SDValue &Base, SDValue &OffImm, 591193323Sed SDValue &Offset) { 592193323Sed return SelectThumbAddrModeRI5(Op, N, 4, Base, OffImm, Offset); 593193323Sed} 594193323Sed 595193323Sedbool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue Op, SDValue N, 596193323Sed SDValue &Base, SDValue &OffImm) { 597193323Sed if (N.getOpcode() == ISD::FrameIndex) { 598193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 599193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 600193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 601193323Sed return true; 602193323Sed } 603193323Sed 604193323Sed if (N.getOpcode() != ISD::ADD) 605193323Sed return false; 606193323Sed 607193323Sed RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 608193323Sed if (N.getOperand(0).getOpcode() == ISD::FrameIndex || 609193323Sed (LHSR && LHSR->getReg() == ARM::SP)) { 610193323Sed // If the RHS is + imm8 * scale, fold into addr mode. 611193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 612193323Sed int RHSC = (int)RHS->getZExtValue(); 613193323Sed if ((RHSC & 3) == 0) { // The constant is implicitly multiplied. 614193323Sed RHSC >>= 2; 615193323Sed if (RHSC >= 0 && RHSC < 256) { 616193323Sed Base = N.getOperand(0); 617193323Sed if (Base.getOpcode() == ISD::FrameIndex) { 618193323Sed int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 619193323Sed Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 620193323Sed } 621193323Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 622193323Sed return true; 623193323Sed } 624193323Sed } 625193323Sed } 626193323Sed } 627198090Srdivacky 628193323Sed return false; 629193323Sed} 630193323Sed 631195098Sedbool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue Op, SDValue N, 632195098Sed SDValue &BaseReg, 633195098Sed SDValue &Opc) { 634195098Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 635195098Sed 636195098Sed // Don't match base register only case. That is matched to a separate 637195098Sed // lower complexity pattern with explicit register operand. 638195098Sed if (ShOpcVal == ARM_AM::no_shift) return false; 639195098Sed 640195098Sed BaseReg = N.getOperand(0); 641195098Sed unsigned ShImmVal = 0; 642195098Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 643195098Sed ShImmVal = RHS->getZExtValue() & 31; 644195098Sed Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal)); 645195098Sed return true; 646195098Sed } 647195098Sed 648195098Sed return false; 649195098Sed} 650195098Sed 651195340Sedbool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue Op, SDValue N, 652195340Sed SDValue &Base, SDValue &OffImm) { 653195340Sed // Match simple R + imm12 operands. 654195340Sed 655198090Srdivacky // Base only. 656198090Srdivacky if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) { 657198090Srdivacky if (N.getOpcode() == ISD::FrameIndex) { 658198090Srdivacky // Match frame index... 659198090Srdivacky int FI = cast<FrameIndexSDNode>(N)->getIndex(); 660198090Srdivacky Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 661198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 662198090Srdivacky return true; 663198090Srdivacky } else if (N.getOpcode() == ARMISD::Wrapper) { 664198090Srdivacky Base = N.getOperand(0); 665198090Srdivacky if (Base.getOpcode() == ISD::TargetConstantPool) 666198090Srdivacky return false; // We want to select t2LDRpci instead. 667198090Srdivacky } else 668198090Srdivacky Base = N; 669198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 670198090Srdivacky return true; 671198090Srdivacky } 672198090Srdivacky 673195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 674198090Srdivacky if (SelectT2AddrModeImm8(Op, N, Base, OffImm)) 675198090Srdivacky // Let t2LDRi8 handle (R - imm8). 676198090Srdivacky return false; 677198090Srdivacky 678195340Sed int RHSC = (int)RHS->getZExtValue(); 679198090Srdivacky if (N.getOpcode() == ISD::SUB) 680198090Srdivacky RHSC = -RHSC; 681198090Srdivacky 682198090Srdivacky if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned) 683195340Sed Base = N.getOperand(0); 684198090Srdivacky if (Base.getOpcode() == ISD::FrameIndex) { 685198090Srdivacky int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 686198090Srdivacky Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 687198090Srdivacky } 688195340Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 689195340Sed return true; 690195340Sed } 691195340Sed } 692195340Sed 693198090Srdivacky // Base only. 694198090Srdivacky Base = N; 695198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 696198090Srdivacky return true; 697195340Sed} 698195340Sed 699195340Sedbool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue Op, SDValue N, 700195340Sed SDValue &Base, SDValue &OffImm) { 701198090Srdivacky // Match simple R - imm8 operands. 702198090Srdivacky if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::SUB) { 703195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 704198090Srdivacky int RHSC = (int)RHS->getSExtValue(); 705198090Srdivacky if (N.getOpcode() == ISD::SUB) 706198090Srdivacky RHSC = -RHSC; 707198090Srdivacky 708198090Srdivacky if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative) 709198090Srdivacky Base = N.getOperand(0); 710198090Srdivacky if (Base.getOpcode() == ISD::FrameIndex) { 711198090Srdivacky int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 712198090Srdivacky Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 713198090Srdivacky } 714195340Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 715195340Sed return true; 716195340Sed } 717195340Sed } 718195340Sed } 719195340Sed 720195340Sed return false; 721195340Sed} 722195340Sed 723195340Sedbool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDValue Op, SDValue N, 724195340Sed SDValue &OffImm){ 725195340Sed unsigned Opcode = Op.getOpcode(); 726195340Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 727195340Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 728195340Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 729195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N)) { 730195340Sed int RHSC = (int)RHS->getZExtValue(); 731195340Sed if (RHSC >= 0 && RHSC < 0x100) { // 8 bits. 732198090Srdivacky OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC)) 733195340Sed ? CurDAG->getTargetConstant(RHSC, MVT::i32) 734195340Sed : CurDAG->getTargetConstant(-RHSC, MVT::i32); 735195340Sed return true; 736195340Sed } 737195340Sed } 738195340Sed 739195340Sed return false; 740195340Sed} 741195340Sed 742195340Sedbool ARMDAGToDAGISel::SelectT2AddrModeImm8s4(SDValue Op, SDValue N, 743195340Sed SDValue &Base, SDValue &OffImm) { 744195340Sed if (N.getOpcode() == ISD::ADD) { 745195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 746195340Sed int RHSC = (int)RHS->getZExtValue(); 747198090Srdivacky if (((RHSC & 0x3) == 0) && 748198090Srdivacky ((RHSC >= 0 && RHSC < 0x400) || (RHSC < 0 && RHSC > -0x400))) { // 8 bits. 749195340Sed Base = N.getOperand(0); 750195340Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 751195340Sed return true; 752195340Sed } 753195340Sed } 754195340Sed } else if (N.getOpcode() == ISD::SUB) { 755195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 756195340Sed int RHSC = (int)RHS->getZExtValue(); 757195340Sed if (((RHSC & 0x3) == 0) && (RHSC >= 0 && RHSC < 0x400)) { // 8 bits. 758195340Sed Base = N.getOperand(0); 759195340Sed OffImm = CurDAG->getTargetConstant(-RHSC, MVT::i32); 760195340Sed return true; 761195340Sed } 762195340Sed } 763195340Sed } 764195340Sed 765195340Sed return false; 766195340Sed} 767195340Sed 768195340Sedbool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue Op, SDValue N, 769195340Sed SDValue &Base, 770195340Sed SDValue &OffReg, SDValue &ShImm) { 771198090Srdivacky // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12. 772198090Srdivacky if (N.getOpcode() != ISD::ADD) 773198090Srdivacky return false; 774198090Srdivacky 775198090Srdivacky // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8. 776198090Srdivacky if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 777198090Srdivacky int RHSC = (int)RHS->getZExtValue(); 778198090Srdivacky if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned) 779198090Srdivacky return false; 780198090Srdivacky else if (RHSC < 0 && RHSC >= -255) // 8 bits 781198090Srdivacky return false; 782195340Sed } 783195340Sed 784195340Sed // Look for (R + R) or (R + (R << [1,2,3])). 785195340Sed unsigned ShAmt = 0; 786195340Sed Base = N.getOperand(0); 787195340Sed OffReg = N.getOperand(1); 788195340Sed 789195340Sed // Swap if it is ((R << c) + R). 790195340Sed ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg); 791195340Sed if (ShOpcVal != ARM_AM::lsl) { 792195340Sed ShOpcVal = ARM_AM::getShiftOpcForNode(Base); 793195340Sed if (ShOpcVal == ARM_AM::lsl) 794195340Sed std::swap(Base, OffReg); 795198090Srdivacky } 796198090Srdivacky 797195340Sed if (ShOpcVal == ARM_AM::lsl) { 798195340Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 799195340Sed // it. 800195340Sed if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) { 801195340Sed ShAmt = Sh->getZExtValue(); 802195340Sed if (ShAmt >= 4) { 803195340Sed ShAmt = 0; 804195340Sed ShOpcVal = ARM_AM::no_shift; 805195340Sed } else 806195340Sed OffReg = OffReg.getOperand(0); 807195340Sed } else { 808195340Sed ShOpcVal = ARM_AM::no_shift; 809195340Sed } 810198090Srdivacky } 811198090Srdivacky 812195340Sed ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32); 813195340Sed 814195340Sed return true; 815195340Sed} 816195340Sed 817195340Sed//===--------------------------------------------------------------------===// 818195340Sed 819193323Sed/// getAL - Returns a ARMCC::AL immediate node. 820193323Sedstatic inline SDValue getAL(SelectionDAG *CurDAG) { 821193323Sed return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32); 822193323Sed} 823193323Sed 824195340SedSDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDValue Op) { 825195340Sed LoadSDNode *LD = cast<LoadSDNode>(Op); 826195340Sed ISD::MemIndexedMode AM = LD->getAddressingMode(); 827195340Sed if (AM == ISD::UNINDEXED) 828195340Sed return NULL; 829193323Sed 830198090Srdivacky EVT LoadedVT = LD->getMemoryVT(); 831195340Sed SDValue Offset, AMOpc; 832195340Sed bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 833195340Sed unsigned Opcode = 0; 834195340Sed bool Match = false; 835195340Sed if (LoadedVT == MVT::i32 && 836195340Sed SelectAddrMode2Offset(Op, LD->getOffset(), Offset, AMOpc)) { 837195340Sed Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST; 838195340Sed Match = true; 839195340Sed } else if (LoadedVT == MVT::i16 && 840195340Sed SelectAddrMode3Offset(Op, LD->getOffset(), Offset, AMOpc)) { 841195340Sed Match = true; 842195340Sed Opcode = (LD->getExtensionType() == ISD::SEXTLOAD) 843195340Sed ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST) 844195340Sed : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST); 845195340Sed } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) { 846195340Sed if (LD->getExtensionType() == ISD::SEXTLOAD) { 847195340Sed if (SelectAddrMode3Offset(Op, LD->getOffset(), Offset, AMOpc)) { 848195340Sed Match = true; 849195340Sed Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST; 850195340Sed } 851195340Sed } else { 852195340Sed if (SelectAddrMode2Offset(Op, LD->getOffset(), Offset, AMOpc)) { 853195340Sed Match = true; 854195340Sed Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST; 855195340Sed } 856195340Sed } 857195340Sed } 858195340Sed 859195340Sed if (Match) { 860195340Sed SDValue Chain = LD->getChain(); 861195340Sed SDValue Base = LD->getBasePtr(); 862195340Sed SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG), 863195340Sed CurDAG->getRegister(0, MVT::i32), Chain }; 864198090Srdivacky return CurDAG->getMachineNode(Opcode, Op.getDebugLoc(), MVT::i32, MVT::i32, 865198090Srdivacky MVT::Other, Ops, 6); 866195340Sed } 867195340Sed 868195340Sed return NULL; 869195340Sed} 870195340Sed 871195340SedSDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDValue Op) { 872195340Sed LoadSDNode *LD = cast<LoadSDNode>(Op); 873195340Sed ISD::MemIndexedMode AM = LD->getAddressingMode(); 874195340Sed if (AM == ISD::UNINDEXED) 875195340Sed return NULL; 876195340Sed 877198090Srdivacky EVT LoadedVT = LD->getMemoryVT(); 878195340Sed bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD; 879195340Sed SDValue Offset; 880195340Sed bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 881195340Sed unsigned Opcode = 0; 882195340Sed bool Match = false; 883195340Sed if (SelectT2AddrModeImm8Offset(Op, LD->getOffset(), Offset)) { 884198090Srdivacky switch (LoadedVT.getSimpleVT().SimpleTy) { 885195340Sed case MVT::i32: 886195340Sed Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST; 887195340Sed break; 888195340Sed case MVT::i16: 889195340Sed if (isSExtLd) 890195340Sed Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST; 891195340Sed else 892195340Sed Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST; 893195340Sed break; 894195340Sed case MVT::i8: 895195340Sed case MVT::i1: 896195340Sed if (isSExtLd) 897195340Sed Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST; 898195340Sed else 899195340Sed Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST; 900195340Sed break; 901195340Sed default: 902195340Sed return NULL; 903195340Sed } 904195340Sed Match = true; 905195340Sed } 906195340Sed 907195340Sed if (Match) { 908195340Sed SDValue Chain = LD->getChain(); 909195340Sed SDValue Base = LD->getBasePtr(); 910195340Sed SDValue Ops[]= { Base, Offset, getAL(CurDAG), 911195340Sed CurDAG->getRegister(0, MVT::i32), Chain }; 912198090Srdivacky return CurDAG->getMachineNode(Opcode, Op.getDebugLoc(), MVT::i32, MVT::i32, 913198090Srdivacky MVT::Other, Ops, 5); 914195340Sed } 915195340Sed 916195340Sed return NULL; 917195340Sed} 918195340Sed 919198090SrdivackySDNode *ARMDAGToDAGISel::SelectDYN_ALLOC(SDValue Op) { 920198090Srdivacky SDNode *N = Op.getNode(); 921198090Srdivacky DebugLoc dl = N->getDebugLoc(); 922198090Srdivacky EVT VT = Op.getValueType(); 923198090Srdivacky SDValue Chain = Op.getOperand(0); 924198090Srdivacky SDValue Size = Op.getOperand(1); 925198090Srdivacky SDValue Align = Op.getOperand(2); 926198090Srdivacky SDValue SP = CurDAG->getRegister(ARM::SP, MVT::i32); 927198090Srdivacky int32_t AlignVal = cast<ConstantSDNode>(Align)->getSExtValue(); 928198090Srdivacky if (AlignVal < 0) 929198090Srdivacky // We need to align the stack. Use Thumb1 tAND which is the only thumb 930198090Srdivacky // instruction that can read and write SP. This matches to a pseudo 931198090Srdivacky // instruction that has a chain to ensure the result is written back to 932198090Srdivacky // the stack pointer. 933198090Srdivacky SP = SDValue(CurDAG->getMachineNode(ARM::tANDsp, dl, VT, SP, Align), 0); 934195340Sed 935198090Srdivacky bool isC = isa<ConstantSDNode>(Size); 936198090Srdivacky uint32_t C = isC ? cast<ConstantSDNode>(Size)->getZExtValue() : ~0UL; 937198090Srdivacky // Handle the most common case for both Thumb1 and Thumb2: 938198090Srdivacky // tSUBspi - immediate is between 0 ... 508 inclusive. 939198090Srdivacky if (C <= 508 && ((C & 3) == 0)) 940198090Srdivacky // FIXME: tSUBspi encode scale 4 implicitly. 941198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::tSUBspi_, VT, MVT::Other, SP, 942198090Srdivacky CurDAG->getTargetConstant(C/4, MVT::i32), 943198090Srdivacky Chain); 944198090Srdivacky 945198090Srdivacky if (Subtarget->isThumb1Only()) { 946198090Srdivacky // Use tADDspr since Thumb1 does not have a sub r, sp, r. ARMISelLowering 947198090Srdivacky // should have negated the size operand already. FIXME: We can't insert 948198090Srdivacky // new target independent node at this stage so we are forced to negate 949198090Srdivacky // it earlier. Is there a better solution? 950198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::tADDspr_, VT, MVT::Other, SP, Size, 951198090Srdivacky Chain); 952198090Srdivacky } else if (Subtarget->isThumb2()) { 953198090Srdivacky if (isC && Predicate_t2_so_imm(Size.getNode())) { 954198090Srdivacky // t2SUBrSPi 955198090Srdivacky SDValue Ops[] = { SP, CurDAG->getTargetConstant(C, MVT::i32), Chain }; 956198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPi_, VT, MVT::Other, Ops, 3); 957198090Srdivacky } else if (isC && Predicate_imm0_4095(Size.getNode())) { 958198090Srdivacky // t2SUBrSPi12 959198090Srdivacky SDValue Ops[] = { SP, CurDAG->getTargetConstant(C, MVT::i32), Chain }; 960198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPi12_, VT, MVT::Other, Ops, 3); 961198090Srdivacky } else { 962198090Srdivacky // t2SUBrSPs 963198090Srdivacky SDValue Ops[] = { SP, Size, 964198090Srdivacky getI32Imm(ARM_AM::getSORegOpc(ARM_AM::lsl,0)), Chain }; 965198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPs_, VT, MVT::Other, Ops, 4); 966198090Srdivacky } 967198090Srdivacky } 968198090Srdivacky 969198090Srdivacky // FIXME: Add ADD / SUB sp instructions for ARM. 970198090Srdivacky return 0; 971198090Srdivacky} 972198090Srdivacky 973198090Srdivacky/// PairDRegs - Insert a pair of double registers into an implicit def to 974198090Srdivacky/// form a quad register. 975198090SrdivackySDNode *ARMDAGToDAGISel::PairDRegs(EVT VT, SDValue V0, SDValue V1) { 976198090Srdivacky DebugLoc dl = V0.getNode()->getDebugLoc(); 977198090Srdivacky SDValue Undef = 978198090Srdivacky SDValue(CurDAG->getMachineNode(TargetInstrInfo::IMPLICIT_DEF, dl, VT), 0); 979198090Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::DSUBREG_0, MVT::i32); 980198090Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::DSUBREG_1, MVT::i32); 981198090Srdivacky SDNode *Pair = CurDAG->getMachineNode(TargetInstrInfo::INSERT_SUBREG, dl, 982198090Srdivacky VT, Undef, V0, SubReg0); 983198090Srdivacky return CurDAG->getMachineNode(TargetInstrInfo::INSERT_SUBREG, dl, 984198090Srdivacky VT, SDValue(Pair, 0), V1, SubReg1); 985198090Srdivacky} 986198090Srdivacky 987198090Srdivacky/// GetNEONSubregVT - Given a type for a 128-bit NEON vector, return the type 988198090Srdivacky/// for a 64-bit subregister of the vector. 989198090Srdivackystatic EVT GetNEONSubregVT(EVT VT) { 990198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 991198090Srdivacky default: llvm_unreachable("unhandled NEON type"); 992198090Srdivacky case MVT::v16i8: return MVT::v8i8; 993198090Srdivacky case MVT::v8i16: return MVT::v4i16; 994198090Srdivacky case MVT::v4f32: return MVT::v2f32; 995198090Srdivacky case MVT::v4i32: return MVT::v2i32; 996198090Srdivacky case MVT::v2i64: return MVT::v1i64; 997198090Srdivacky } 998198090Srdivacky} 999198090Srdivacky 1000198090SrdivackySDNode *ARMDAGToDAGISel::SelectVLD(SDValue Op, unsigned NumVecs, 1001198090Srdivacky unsigned *DOpcodes, unsigned *QOpcodes0, 1002198090Srdivacky unsigned *QOpcodes1) { 1003198090Srdivacky assert(NumVecs >=2 && NumVecs <= 4 && "VLD NumVecs out-of-range"); 1004198090Srdivacky SDNode *N = Op.getNode(); 1005198090Srdivacky DebugLoc dl = N->getDebugLoc(); 1006198090Srdivacky 1007198090Srdivacky SDValue MemAddr, MemUpdate, MemOpc; 1008198090Srdivacky if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc)) 1009198090Srdivacky return NULL; 1010198090Srdivacky 1011198090Srdivacky SDValue Chain = N->getOperand(0); 1012198090Srdivacky EVT VT = N->getValueType(0); 1013198090Srdivacky bool is64BitVector = VT.is64BitVector(); 1014198090Srdivacky 1015198090Srdivacky unsigned OpcodeIndex; 1016198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1017198090Srdivacky default: llvm_unreachable("unhandled vld type"); 1018198090Srdivacky // Double-register operations: 1019198090Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1020198090Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1021198090Srdivacky case MVT::v2f32: 1022198090Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1023198090Srdivacky case MVT::v1i64: OpcodeIndex = 3; break; 1024198090Srdivacky // Quad-register operations: 1025198090Srdivacky case MVT::v16i8: OpcodeIndex = 0; break; 1026198090Srdivacky case MVT::v8i16: OpcodeIndex = 1; break; 1027198090Srdivacky case MVT::v4f32: 1028198090Srdivacky case MVT::v4i32: OpcodeIndex = 2; break; 1029198090Srdivacky } 1030198090Srdivacky 1031198090Srdivacky if (is64BitVector) { 1032198090Srdivacky unsigned Opc = DOpcodes[OpcodeIndex]; 1033198090Srdivacky const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, Chain }; 1034198090Srdivacky std::vector<EVT> ResTys(NumVecs, VT); 1035198090Srdivacky ResTys.push_back(MVT::Other); 1036198090Srdivacky return CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 4); 1037198090Srdivacky } 1038198090Srdivacky 1039198090Srdivacky EVT RegVT = GetNEONSubregVT(VT); 1040198090Srdivacky if (NumVecs == 2) { 1041198090Srdivacky // Quad registers are directly supported for VLD2, 1042198090Srdivacky // loading 2 pairs of D regs. 1043198090Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1044198090Srdivacky const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, Chain }; 1045198090Srdivacky std::vector<EVT> ResTys(4, VT); 1046198090Srdivacky ResTys.push_back(MVT::Other); 1047198090Srdivacky SDNode *VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 4); 1048198090Srdivacky Chain = SDValue(VLd, 4); 1049198090Srdivacky 1050198090Srdivacky // Combine the even and odd subregs to produce the result. 1051198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1052198090Srdivacky SDNode *Q = PairDRegs(VT, SDValue(VLd, 2*Vec), SDValue(VLd, 2*Vec+1)); 1053198090Srdivacky ReplaceUses(SDValue(N, Vec), SDValue(Q, 0)); 1054198090Srdivacky } 1055198090Srdivacky } else { 1056198090Srdivacky // Otherwise, quad registers are loaded with two separate instructions, 1057198090Srdivacky // where one loads the even registers and the other loads the odd registers. 1058198090Srdivacky 1059198090Srdivacky // Enable writeback to the address register. 1060198090Srdivacky MemOpc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(true), MVT::i32); 1061198090Srdivacky 1062198090Srdivacky std::vector<EVT> ResTys(NumVecs, RegVT); 1063198090Srdivacky ResTys.push_back(MemAddr.getValueType()); 1064198090Srdivacky ResTys.push_back(MVT::Other); 1065198090Srdivacky 1066198090Srdivacky // Load the even subreg. 1067198090Srdivacky unsigned Opc = QOpcodes0[OpcodeIndex]; 1068198090Srdivacky const SDValue OpsA[] = { MemAddr, MemUpdate, MemOpc, Chain }; 1069198090Srdivacky SDNode *VLdA = CurDAG->getMachineNode(Opc, dl, ResTys, OpsA, 4); 1070198090Srdivacky Chain = SDValue(VLdA, NumVecs+1); 1071198090Srdivacky 1072198090Srdivacky // Load the odd subreg. 1073198090Srdivacky Opc = QOpcodes1[OpcodeIndex]; 1074198090Srdivacky const SDValue OpsB[] = { SDValue(VLdA, NumVecs), MemUpdate, MemOpc, Chain }; 1075198090Srdivacky SDNode *VLdB = CurDAG->getMachineNode(Opc, dl, ResTys, OpsB, 4); 1076198090Srdivacky Chain = SDValue(VLdB, NumVecs+1); 1077198090Srdivacky 1078198090Srdivacky // Combine the even and odd subregs to produce the result. 1079198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1080198090Srdivacky SDNode *Q = PairDRegs(VT, SDValue(VLdA, Vec), SDValue(VLdB, Vec)); 1081198090Srdivacky ReplaceUses(SDValue(N, Vec), SDValue(Q, 0)); 1082198090Srdivacky } 1083198090Srdivacky } 1084198090Srdivacky ReplaceUses(SDValue(N, NumVecs), Chain); 1085198090Srdivacky return NULL; 1086198090Srdivacky} 1087198090Srdivacky 1088198090SrdivackySDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDValue Op, bool IsLoad, 1089198090Srdivacky unsigned NumVecs, unsigned *DOpcodes, 1090198090Srdivacky unsigned *QOpcodes0, 1091198090Srdivacky unsigned *QOpcodes1) { 1092198090Srdivacky assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range"); 1093198090Srdivacky SDNode *N = Op.getNode(); 1094198090Srdivacky DebugLoc dl = N->getDebugLoc(); 1095198090Srdivacky 1096198090Srdivacky SDValue MemAddr, MemUpdate, MemOpc; 1097198090Srdivacky if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc)) 1098198090Srdivacky return NULL; 1099198090Srdivacky 1100198090Srdivacky SDValue Chain = N->getOperand(0); 1101198090Srdivacky unsigned Lane = 1102198090Srdivacky cast<ConstantSDNode>(N->getOperand(NumVecs+3))->getZExtValue(); 1103198090Srdivacky EVT VT = IsLoad ? N->getValueType(0) : N->getOperand(3).getValueType(); 1104198090Srdivacky bool is64BitVector = VT.is64BitVector(); 1105198090Srdivacky 1106198090Srdivacky // Quad registers are handled by load/store of subregs. Find the subreg info. 1107198090Srdivacky unsigned NumElts = 0; 1108198090Srdivacky int SubregIdx = 0; 1109198090Srdivacky EVT RegVT = VT; 1110198090Srdivacky if (!is64BitVector) { 1111198090Srdivacky RegVT = GetNEONSubregVT(VT); 1112198090Srdivacky NumElts = RegVT.getVectorNumElements(); 1113198090Srdivacky SubregIdx = (Lane < NumElts) ? ARM::DSUBREG_0 : ARM::DSUBREG_1; 1114198090Srdivacky } 1115198090Srdivacky 1116198090Srdivacky unsigned OpcodeIndex; 1117198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1118198090Srdivacky default: llvm_unreachable("unhandled vld/vst lane type"); 1119198090Srdivacky // Double-register operations: 1120198090Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1121198090Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1122198090Srdivacky case MVT::v2f32: 1123198090Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1124198090Srdivacky // Quad-register operations: 1125198090Srdivacky case MVT::v8i16: OpcodeIndex = 0; break; 1126198090Srdivacky case MVT::v4f32: 1127198090Srdivacky case MVT::v4i32: OpcodeIndex = 1; break; 1128198090Srdivacky } 1129198090Srdivacky 1130198090Srdivacky SmallVector<SDValue, 9> Ops; 1131198090Srdivacky Ops.push_back(MemAddr); 1132198090Srdivacky Ops.push_back(MemUpdate); 1133198090Srdivacky Ops.push_back(MemOpc); 1134198090Srdivacky 1135198090Srdivacky unsigned Opc = 0; 1136198090Srdivacky if (is64BitVector) { 1137198090Srdivacky Opc = DOpcodes[OpcodeIndex]; 1138198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1139198090Srdivacky Ops.push_back(N->getOperand(Vec+3)); 1140198090Srdivacky } else { 1141198090Srdivacky // Check if this is loading the even or odd subreg of a Q register. 1142198090Srdivacky if (Lane < NumElts) { 1143198090Srdivacky Opc = QOpcodes0[OpcodeIndex]; 1144198090Srdivacky } else { 1145198090Srdivacky Lane -= NumElts; 1146198090Srdivacky Opc = QOpcodes1[OpcodeIndex]; 1147198090Srdivacky } 1148198090Srdivacky // Extract the subregs of the input vector. 1149198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1150198090Srdivacky Ops.push_back(CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT, 1151198090Srdivacky N->getOperand(Vec+3))); 1152198090Srdivacky } 1153198090Srdivacky Ops.push_back(getI32Imm(Lane)); 1154198090Srdivacky Ops.push_back(Chain); 1155198090Srdivacky 1156198090Srdivacky if (!IsLoad) 1157198090Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+5); 1158198090Srdivacky 1159198090Srdivacky std::vector<EVT> ResTys(NumVecs, RegVT); 1160198090Srdivacky ResTys.push_back(MVT::Other); 1161198090Srdivacky SDNode *VLdLn = 1162198090Srdivacky CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), NumVecs+5); 1163198090Srdivacky // For a 64-bit vector load to D registers, nothing more needs to be done. 1164198090Srdivacky if (is64BitVector) 1165198090Srdivacky return VLdLn; 1166198090Srdivacky 1167198090Srdivacky // For 128-bit vectors, take the 64-bit results of the load and insert them 1168198090Srdivacky // as subregs into the result. 1169198090Srdivacky for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { 1170198090Srdivacky SDValue QuadVec = CurDAG->getTargetInsertSubreg(SubregIdx, dl, VT, 1171198090Srdivacky N->getOperand(Vec+3), 1172198090Srdivacky SDValue(VLdLn, Vec)); 1173198090Srdivacky ReplaceUses(SDValue(N, Vec), QuadVec); 1174198090Srdivacky } 1175198090Srdivacky 1176198090Srdivacky Chain = SDValue(VLdLn, NumVecs); 1177198090Srdivacky ReplaceUses(SDValue(N, NumVecs), Chain); 1178198090Srdivacky return NULL; 1179198090Srdivacky} 1180198090Srdivacky 1181198090SrdivackySDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDValue Op, 1182198090Srdivacky unsigned Opc) { 1183198090Srdivacky if (!Subtarget->hasV6T2Ops()) 1184198090Srdivacky return NULL; 1185198090Srdivacky 1186198090Srdivacky unsigned Shl_imm = 0; 1187198090Srdivacky if (isOpcWithIntImmediate(Op.getOperand(0).getNode(), ISD::SHL, Shl_imm)){ 1188198090Srdivacky assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!"); 1189198090Srdivacky unsigned Srl_imm = 0; 1190198090Srdivacky if (isInt32Immediate(Op.getOperand(1), Srl_imm)) { 1191198090Srdivacky assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); 1192198090Srdivacky unsigned Width = 32 - Srl_imm; 1193198090Srdivacky int LSB = Srl_imm - Shl_imm; 1194198090Srdivacky if ((LSB + Width) > 32) 1195198090Srdivacky return NULL; 1196198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1197198090Srdivacky SDValue Ops[] = { Op.getOperand(0).getOperand(0), 1198198090Srdivacky CurDAG->getTargetConstant(LSB, MVT::i32), 1199198090Srdivacky CurDAG->getTargetConstant(Width, MVT::i32), 1200198090Srdivacky getAL(CurDAG), Reg0 }; 1201198090Srdivacky return CurDAG->SelectNodeTo(Op.getNode(), Opc, MVT::i32, Ops, 5); 1202198090Srdivacky } 1203198090Srdivacky } 1204198090Srdivacky return NULL; 1205198090Srdivacky} 1206198090Srdivacky 1207193323SedSDNode *ARMDAGToDAGISel::Select(SDValue Op) { 1208193323Sed SDNode *N = Op.getNode(); 1209193323Sed DebugLoc dl = N->getDebugLoc(); 1210193323Sed 1211193323Sed if (N->isMachineOpcode()) 1212193323Sed return NULL; // Already selected. 1213193323Sed 1214193323Sed switch (N->getOpcode()) { 1215193323Sed default: break; 1216193323Sed case ISD::Constant: { 1217193323Sed unsigned Val = cast<ConstantSDNode>(N)->getZExtValue(); 1218193323Sed bool UseCP = true; 1219198090Srdivacky if (Subtarget->hasThumb2()) 1220198090Srdivacky // Thumb2-aware targets have the MOVT instruction, so all immediates can 1221198090Srdivacky // be done with MOV + MOVT, at worst. 1222198090Srdivacky UseCP = 0; 1223198090Srdivacky else { 1224198090Srdivacky if (Subtarget->isThumb()) { 1225194710Sed UseCP = (Val > 255 && // MOV 1226194710Sed ~Val > 255 && // MOV + MVN 1227194710Sed !ARM_AM::isThumbImmShiftedVal(Val)); // MOV + LSL 1228198090Srdivacky } else 1229198090Srdivacky UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV 1230198090Srdivacky ARM_AM::getSOImmVal(~Val) == -1 && // MVN 1231198090Srdivacky !ARM_AM::isSOImmTwoPartVal(Val)); // two instrs. 1232198090Srdivacky } 1233198090Srdivacky 1234193323Sed if (UseCP) { 1235193323Sed SDValue CPIdx = 1236198090Srdivacky CurDAG->getTargetConstantPool(ConstantInt::get( 1237198090Srdivacky Type::getInt32Ty(*CurDAG->getContext()), Val), 1238193323Sed TLI.getPointerTy()); 1239193323Sed 1240193323Sed SDNode *ResNode; 1241198090Srdivacky if (Subtarget->isThumb1Only()) { 1242198090Srdivacky SDValue Pred = CurDAG->getTargetConstant(0xEULL, MVT::i32); 1243198090Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 1244198090Srdivacky SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() }; 1245198090Srdivacky ResNode = CurDAG->getMachineNode(ARM::tLDRcp, dl, MVT::i32, MVT::Other, 1246198090Srdivacky Ops, 4); 1247198090Srdivacky } else { 1248193323Sed SDValue Ops[] = { 1249198090Srdivacky CPIdx, 1250193323Sed CurDAG->getRegister(0, MVT::i32), 1251193323Sed CurDAG->getTargetConstant(0, MVT::i32), 1252193323Sed getAL(CurDAG), 1253193323Sed CurDAG->getRegister(0, MVT::i32), 1254193323Sed CurDAG->getEntryNode() 1255193323Sed }; 1256198090Srdivacky ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other, 1257198090Srdivacky Ops, 6); 1258193323Sed } 1259193323Sed ReplaceUses(Op, SDValue(ResNode, 0)); 1260193323Sed return NULL; 1261193323Sed } 1262198090Srdivacky 1263193323Sed // Other cases are autogenerated. 1264193323Sed break; 1265193323Sed } 1266193323Sed case ISD::FrameIndex: { 1267193323Sed // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm. 1268193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 1269193323Sed SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 1270198090Srdivacky if (Subtarget->isThumb1Only()) { 1271193323Sed return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI, 1272193323Sed CurDAG->getTargetConstant(0, MVT::i32)); 1273193323Sed } else { 1274198090Srdivacky unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ? 1275198090Srdivacky ARM::t2ADDri : ARM::ADDri); 1276193323Sed SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32), 1277198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1278198090Srdivacky CurDAG->getRegister(0, MVT::i32) }; 1279198090Srdivacky return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); 1280193323Sed } 1281193323Sed } 1282198090Srdivacky case ARMISD::DYN_ALLOC: 1283198090Srdivacky return SelectDYN_ALLOC(Op); 1284198090Srdivacky case ISD::SRL: 1285198090Srdivacky if (SDNode *I = SelectV6T2BitfieldExtractOp(Op, 1286198090Srdivacky Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX)) 1287198090Srdivacky return I; 1288193323Sed break; 1289198090Srdivacky case ISD::SRA: 1290198090Srdivacky if (SDNode *I = SelectV6T2BitfieldExtractOp(Op, 1291198090Srdivacky Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)) 1292198090Srdivacky return I; 1293198090Srdivacky break; 1294193323Sed case ISD::MUL: 1295198090Srdivacky if (Subtarget->isThumb1Only()) 1296193323Sed break; 1297193323Sed if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) { 1298193323Sed unsigned RHSV = C->getZExtValue(); 1299193323Sed if (!RHSV) break; 1300193323Sed if (isPowerOf2_32(RHSV-1)) { // 2^n+1? 1301198090Srdivacky unsigned ShImm = Log2_32(RHSV-1); 1302198090Srdivacky if (ShImm >= 32) 1303198090Srdivacky break; 1304193323Sed SDValue V = Op.getOperand(0); 1305198090Srdivacky ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); 1306198090Srdivacky SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); 1307198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1308198090Srdivacky if (Subtarget->isThumb()) { 1309198090Srdivacky SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1310198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops, 6); 1311198090Srdivacky } else { 1312198090Srdivacky SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1313198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 7); 1314198090Srdivacky } 1315193323Sed } 1316193323Sed if (isPowerOf2_32(RHSV+1)) { // 2^n-1? 1317198090Srdivacky unsigned ShImm = Log2_32(RHSV+1); 1318198090Srdivacky if (ShImm >= 32) 1319198090Srdivacky break; 1320193323Sed SDValue V = Op.getOperand(0); 1321198090Srdivacky ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); 1322198090Srdivacky SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); 1323198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1324198090Srdivacky if (Subtarget->isThumb()) { 1325198090Srdivacky SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0 }; 1326198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops, 5); 1327198090Srdivacky } else { 1328198090Srdivacky SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 1329198090Srdivacky return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 7); 1330198090Srdivacky } 1331193323Sed } 1332193323Sed } 1333193323Sed break; 1334193323Sed case ARMISD::FMRRD: 1335198090Srdivacky return CurDAG->getMachineNode(ARM::FMRRD, dl, MVT::i32, MVT::i32, 1336198090Srdivacky Op.getOperand(0), getAL(CurDAG), 1337198090Srdivacky CurDAG->getRegister(0, MVT::i32)); 1338193323Sed case ISD::UMUL_LOHI: { 1339198090Srdivacky if (Subtarget->isThumb1Only()) 1340198090Srdivacky break; 1341198090Srdivacky if (Subtarget->isThumb()) { 1342198090Srdivacky SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), 1343193323Sed getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1344193323Sed CurDAG->getRegister(0, MVT::i32) }; 1345198090Srdivacky return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops,4); 1346198090Srdivacky } else { 1347198090Srdivacky SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), 1348198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1349198090Srdivacky CurDAG->getRegister(0, MVT::i32) }; 1350198090Srdivacky return CurDAG->getMachineNode(ARM::UMULL, dl, MVT::i32, MVT::i32, Ops, 5); 1351198090Srdivacky } 1352193323Sed } 1353193323Sed case ISD::SMUL_LOHI: { 1354198090Srdivacky if (Subtarget->isThumb1Only()) 1355198090Srdivacky break; 1356198090Srdivacky if (Subtarget->isThumb()) { 1357198090Srdivacky SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), 1358198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; 1359198090Srdivacky return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops,4); 1360198090Srdivacky } else { 1361198090Srdivacky SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), 1362193323Sed getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 1363193323Sed CurDAG->getRegister(0, MVT::i32) }; 1364198090Srdivacky return CurDAG->getMachineNode(ARM::SMULL, dl, MVT::i32, MVT::i32, Ops, 5); 1365198090Srdivacky } 1366193323Sed } 1367193323Sed case ISD::LOAD: { 1368195340Sed SDNode *ResNode = 0; 1369198090Srdivacky if (Subtarget->isThumb() && Subtarget->hasThumb2()) 1370195340Sed ResNode = SelectT2IndexedLoad(Op); 1371195340Sed else 1372195340Sed ResNode = SelectARMIndexedLoad(Op); 1373195340Sed if (ResNode) 1374195340Sed return ResNode; 1375193323Sed // Other cases are autogenerated. 1376193323Sed break; 1377193323Sed } 1378193323Sed case ARMISD::BRCOND: { 1379193323Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 1380193323Sed // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc) 1381193323Sed // Pattern complexity = 6 cost = 1 size = 0 1382193323Sed 1383193323Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 1384193323Sed // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc) 1385193323Sed // Pattern complexity = 6 cost = 1 size = 0 1386193323Sed 1387195340Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 1388195340Sed // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc) 1389195340Sed // Pattern complexity = 6 cost = 1 size = 0 1390195340Sed 1391198090Srdivacky unsigned Opc = Subtarget->isThumb() ? 1392195340Sed ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc; 1393193323Sed SDValue Chain = Op.getOperand(0); 1394193323Sed SDValue N1 = Op.getOperand(1); 1395193323Sed SDValue N2 = Op.getOperand(2); 1396193323Sed SDValue N3 = Op.getOperand(3); 1397193323Sed SDValue InFlag = Op.getOperand(4); 1398193323Sed assert(N1.getOpcode() == ISD::BasicBlock); 1399193323Sed assert(N2.getOpcode() == ISD::Constant); 1400193323Sed assert(N3.getOpcode() == ISD::Register); 1401193323Sed 1402193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 1403193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 1404193323Sed MVT::i32); 1405193323Sed SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag }; 1406198090Srdivacky SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other, 1407198090Srdivacky MVT::Flag, Ops, 5); 1408193323Sed Chain = SDValue(ResNode, 0); 1409193323Sed if (Op.getNode()->getNumValues() == 2) { 1410193323Sed InFlag = SDValue(ResNode, 1); 1411193323Sed ReplaceUses(SDValue(Op.getNode(), 1), InFlag); 1412193323Sed } 1413193323Sed ReplaceUses(SDValue(Op.getNode(), 0), SDValue(Chain.getNode(), Chain.getResNo())); 1414193323Sed return NULL; 1415193323Sed } 1416193323Sed case ARMISD::CMOV: { 1417198090Srdivacky EVT VT = Op.getValueType(); 1418193323Sed SDValue N0 = Op.getOperand(0); 1419193323Sed SDValue N1 = Op.getOperand(1); 1420193323Sed SDValue N2 = Op.getOperand(2); 1421193323Sed SDValue N3 = Op.getOperand(3); 1422193323Sed SDValue InFlag = Op.getOperand(4); 1423193323Sed assert(N2.getOpcode() == ISD::Constant); 1424193323Sed assert(N3.getOpcode() == ISD::Register); 1425193323Sed 1426198090Srdivacky if (!Subtarget->isThumb1Only() && VT == MVT::i32) { 1427198090Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) 1428198090Srdivacky // Emits: (MOVCCs:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) 1429198090Srdivacky // Pattern complexity = 18 cost = 1 size = 0 1430198090Srdivacky SDValue CPTmp0; 1431198090Srdivacky SDValue CPTmp1; 1432198090Srdivacky SDValue CPTmp2; 1433198090Srdivacky if (Subtarget->isThumb()) { 1434198090Srdivacky if (SelectT2ShifterOperandReg(Op, N1, CPTmp0, CPTmp1)) { 1435198090Srdivacky unsigned SOVal = cast<ConstantSDNode>(CPTmp1)->getZExtValue(); 1436198090Srdivacky unsigned SOShOp = ARM_AM::getSORegShOp(SOVal); 1437198090Srdivacky unsigned Opc = 0; 1438198090Srdivacky switch (SOShOp) { 1439198090Srdivacky case ARM_AM::lsl: Opc = ARM::t2MOVCClsl; break; 1440198090Srdivacky case ARM_AM::lsr: Opc = ARM::t2MOVCClsr; break; 1441198090Srdivacky case ARM_AM::asr: Opc = ARM::t2MOVCCasr; break; 1442198090Srdivacky case ARM_AM::ror: Opc = ARM::t2MOVCCror; break; 1443198090Srdivacky default: 1444198090Srdivacky llvm_unreachable("Unknown so_reg opcode!"); 1445198090Srdivacky break; 1446198090Srdivacky } 1447198090Srdivacky SDValue SOShImm = 1448198090Srdivacky CurDAG->getTargetConstant(ARM_AM::getSORegOffset(SOVal), MVT::i32); 1449198090Srdivacky SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 1450198090Srdivacky cast<ConstantSDNode>(N2)->getZExtValue()), 1451198090Srdivacky MVT::i32); 1452198090Srdivacky SDValue Ops[] = { N0, CPTmp0, SOShImm, Tmp2, N3, InFlag }; 1453198090Srdivacky return CurDAG->SelectNodeTo(Op.getNode(), Opc, MVT::i32,Ops, 6); 1454198090Srdivacky } 1455198090Srdivacky } else { 1456198090Srdivacky if (SelectShifterOperandReg(Op, N1, CPTmp0, CPTmp1, CPTmp2)) { 1457198090Srdivacky SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 1458198090Srdivacky cast<ConstantSDNode>(N2)->getZExtValue()), 1459198090Srdivacky MVT::i32); 1460198090Srdivacky SDValue Ops[] = { N0, CPTmp0, CPTmp1, CPTmp2, Tmp2, N3, InFlag }; 1461198090Srdivacky return CurDAG->SelectNodeTo(Op.getNode(), 1462198090Srdivacky ARM::MOVCCs, MVT::i32, Ops, 7); 1463198090Srdivacky } 1464198090Srdivacky } 1465193323Sed 1466198090Srdivacky // Pattern: (ARMcmov:i32 GPR:i32:$false, 1467198090Srdivacky // (imm:i32)<<P:Predicate_so_imm>>:$true, 1468198090Srdivacky // (imm:i32):$cc) 1469198090Srdivacky // Emits: (MOVCCi:i32 GPR:i32:$false, 1470198090Srdivacky // (so_imm:i32 (imm:i32):$true), (imm:i32):$cc) 1471198090Srdivacky // Pattern complexity = 10 cost = 1 size = 0 1472198090Srdivacky if (N3.getOpcode() == ISD::Constant) { 1473198090Srdivacky if (Subtarget->isThumb()) { 1474198090Srdivacky if (Predicate_t2_so_imm(N3.getNode())) { 1475198090Srdivacky SDValue Tmp1 = CurDAG->getTargetConstant(((unsigned) 1476198090Srdivacky cast<ConstantSDNode>(N1)->getZExtValue()), 1477198090Srdivacky MVT::i32); 1478198090Srdivacky SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 1479198090Srdivacky cast<ConstantSDNode>(N2)->getZExtValue()), 1480198090Srdivacky MVT::i32); 1481198090Srdivacky SDValue Ops[] = { N0, Tmp1, Tmp2, N3, InFlag }; 1482198090Srdivacky return CurDAG->SelectNodeTo(Op.getNode(), 1483198090Srdivacky ARM::t2MOVCCi, MVT::i32, Ops, 5); 1484198090Srdivacky } 1485198090Srdivacky } else { 1486198090Srdivacky if (Predicate_so_imm(N3.getNode())) { 1487198090Srdivacky SDValue Tmp1 = CurDAG->getTargetConstant(((unsigned) 1488198090Srdivacky cast<ConstantSDNode>(N1)->getZExtValue()), 1489198090Srdivacky MVT::i32); 1490198090Srdivacky SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 1491198090Srdivacky cast<ConstantSDNode>(N2)->getZExtValue()), 1492198090Srdivacky MVT::i32); 1493198090Srdivacky SDValue Ops[] = { N0, Tmp1, Tmp2, N3, InFlag }; 1494198090Srdivacky return CurDAG->SelectNodeTo(Op.getNode(), 1495198090Srdivacky ARM::MOVCCi, MVT::i32, Ops, 5); 1496198090Srdivacky } 1497198090Srdivacky } 1498198090Srdivacky } 1499193323Sed } 1500193323Sed 1501193323Sed // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1502193323Sed // Emits: (MOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1503193323Sed // Pattern complexity = 6 cost = 1 size = 0 1504193323Sed // 1505193323Sed // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1506193323Sed // Emits: (tMOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 1507193323Sed // Pattern complexity = 6 cost = 11 size = 0 1508193323Sed // 1509193323Sed // Also FCPYScc and FCPYDcc. 1510193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 1511193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 1512193323Sed MVT::i32); 1513193323Sed SDValue Ops[] = { N0, N1, Tmp2, N3, InFlag }; 1514193323Sed unsigned Opc = 0; 1515198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1516193323Sed default: assert(false && "Illegal conditional move type!"); 1517193323Sed break; 1518193323Sed case MVT::i32: 1519198090Srdivacky Opc = Subtarget->isThumb() 1520198090Srdivacky ? (Subtarget->hasThumb2() ? ARM::t2MOVCCr : ARM::tMOVCCr_pseudo) 1521198090Srdivacky : ARM::MOVCCr; 1522193323Sed break; 1523193323Sed case MVT::f32: 1524193323Sed Opc = ARM::FCPYScc; 1525193323Sed break; 1526193323Sed case MVT::f64: 1527193323Sed Opc = ARM::FCPYDcc; 1528198090Srdivacky break; 1529193323Sed } 1530193323Sed return CurDAG->SelectNodeTo(Op.getNode(), Opc, VT, Ops, 5); 1531193323Sed } 1532193323Sed case ARMISD::CNEG: { 1533198090Srdivacky EVT VT = Op.getValueType(); 1534193323Sed SDValue N0 = Op.getOperand(0); 1535193323Sed SDValue N1 = Op.getOperand(1); 1536193323Sed SDValue N2 = Op.getOperand(2); 1537193323Sed SDValue N3 = Op.getOperand(3); 1538193323Sed SDValue InFlag = Op.getOperand(4); 1539193323Sed assert(N2.getOpcode() == ISD::Constant); 1540193323Sed assert(N3.getOpcode() == ISD::Register); 1541193323Sed 1542193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 1543193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 1544193323Sed MVT::i32); 1545193323Sed SDValue Ops[] = { N0, N1, Tmp2, N3, InFlag }; 1546193323Sed unsigned Opc = 0; 1547198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1548193323Sed default: assert(false && "Illegal conditional move type!"); 1549193323Sed break; 1550193323Sed case MVT::f32: 1551193323Sed Opc = ARM::FNEGScc; 1552193323Sed break; 1553193323Sed case MVT::f64: 1554193323Sed Opc = ARM::FNEGDcc; 1555193323Sed break; 1556193323Sed } 1557193323Sed return CurDAG->SelectNodeTo(Op.getNode(), Opc, VT, Ops, 5); 1558193323Sed } 1559193323Sed 1560198090Srdivacky case ARMISD::VZIP: { 1561198090Srdivacky unsigned Opc = 0; 1562198090Srdivacky EVT VT = N->getValueType(0); 1563198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1564198090Srdivacky default: return NULL; 1565198090Srdivacky case MVT::v8i8: Opc = ARM::VZIPd8; break; 1566198090Srdivacky case MVT::v4i16: Opc = ARM::VZIPd16; break; 1567198090Srdivacky case MVT::v2f32: 1568198090Srdivacky case MVT::v2i32: Opc = ARM::VZIPd32; break; 1569198090Srdivacky case MVT::v16i8: Opc = ARM::VZIPq8; break; 1570198090Srdivacky case MVT::v8i16: Opc = ARM::VZIPq16; break; 1571198090Srdivacky case MVT::v4f32: 1572198090Srdivacky case MVT::v4i32: Opc = ARM::VZIPq32; break; 1573193323Sed } 1574198090Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, 1575198090Srdivacky N->getOperand(0), N->getOperand(1)); 1576198090Srdivacky } 1577198090Srdivacky case ARMISD::VUZP: { 1578198090Srdivacky unsigned Opc = 0; 1579198090Srdivacky EVT VT = N->getValueType(0); 1580198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1581198090Srdivacky default: return NULL; 1582198090Srdivacky case MVT::v8i8: Opc = ARM::VUZPd8; break; 1583198090Srdivacky case MVT::v4i16: Opc = ARM::VUZPd16; break; 1584198090Srdivacky case MVT::v2f32: 1585198090Srdivacky case MVT::v2i32: Opc = ARM::VUZPd32; break; 1586198090Srdivacky case MVT::v16i8: Opc = ARM::VUZPq8; break; 1587198090Srdivacky case MVT::v8i16: Opc = ARM::VUZPq16; break; 1588198090Srdivacky case MVT::v4f32: 1589198090Srdivacky case MVT::v4i32: Opc = ARM::VUZPq32; break; 1590193323Sed } 1591198090Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, 1592198090Srdivacky N->getOperand(0), N->getOperand(1)); 1593198090Srdivacky } 1594198090Srdivacky case ARMISD::VTRN: { 1595198090Srdivacky unsigned Opc = 0; 1596198090Srdivacky EVT VT = N->getValueType(0); 1597198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1598198090Srdivacky default: return NULL; 1599198090Srdivacky case MVT::v8i8: Opc = ARM::VTRNd8; break; 1600198090Srdivacky case MVT::v4i16: Opc = ARM::VTRNd16; break; 1601198090Srdivacky case MVT::v2f32: 1602198090Srdivacky case MVT::v2i32: Opc = ARM::VTRNd32; break; 1603198090Srdivacky case MVT::v16i8: Opc = ARM::VTRNq8; break; 1604198090Srdivacky case MVT::v8i16: Opc = ARM::VTRNq16; break; 1605198090Srdivacky case MVT::v4f32: 1606198090Srdivacky case MVT::v4i32: Opc = ARM::VTRNq32; break; 1607193323Sed } 1608198090Srdivacky return CurDAG->getMachineNode(Opc, dl, VT, VT, 1609198090Srdivacky N->getOperand(0), N->getOperand(1)); 1610193323Sed } 1611194710Sed 1612198090Srdivacky case ISD::INTRINSIC_VOID: 1613198090Srdivacky case ISD::INTRINSIC_W_CHAIN: { 1614198090Srdivacky unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue(); 1615198090Srdivacky EVT VT = N->getValueType(0); 1616198090Srdivacky unsigned Opc = 0; 1617193323Sed 1618198090Srdivacky switch (IntNo) { 1619198090Srdivacky default: 1620198090Srdivacky break; 1621194710Sed 1622198090Srdivacky case Intrinsic::arm_neon_vld2: { 1623198090Srdivacky unsigned DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16, 1624198090Srdivacky ARM::VLD2d32, ARM::VLD2d64 }; 1625198090Srdivacky unsigned QOpcodes[] = { ARM::VLD2q8, ARM::VLD2q16, ARM::VLD2q32 }; 1626198090Srdivacky return SelectVLD(Op, 2, DOpcodes, QOpcodes, 0); 1627198090Srdivacky } 1628194710Sed 1629198090Srdivacky case Intrinsic::arm_neon_vld3: { 1630198090Srdivacky unsigned DOpcodes[] = { ARM::VLD3d8, ARM::VLD3d16, 1631198090Srdivacky ARM::VLD3d32, ARM::VLD3d64 }; 1632198090Srdivacky unsigned QOpcodes0[] = { ARM::VLD3q8a, ARM::VLD3q16a, ARM::VLD3q32a }; 1633198090Srdivacky unsigned QOpcodes1[] = { ARM::VLD3q8b, ARM::VLD3q16b, ARM::VLD3q32b }; 1634198090Srdivacky return SelectVLD(Op, 3, DOpcodes, QOpcodes0, QOpcodes1); 1635198090Srdivacky } 1636198090Srdivacky 1637198090Srdivacky case Intrinsic::arm_neon_vld4: { 1638198090Srdivacky unsigned DOpcodes[] = { ARM::VLD4d8, ARM::VLD4d16, 1639198090Srdivacky ARM::VLD4d32, ARM::VLD4d64 }; 1640198090Srdivacky unsigned QOpcodes0[] = { ARM::VLD4q8a, ARM::VLD4q16a, ARM::VLD4q32a }; 1641198090Srdivacky unsigned QOpcodes1[] = { ARM::VLD4q8b, ARM::VLD4q16b, ARM::VLD4q32b }; 1642198090Srdivacky return SelectVLD(Op, 4, DOpcodes, QOpcodes0, QOpcodes1); 1643198090Srdivacky } 1644198090Srdivacky 1645198090Srdivacky case Intrinsic::arm_neon_vld2lane: { 1646198090Srdivacky unsigned DOpcodes[] = { ARM::VLD2LNd8, ARM::VLD2LNd16, ARM::VLD2LNd32 }; 1647198090Srdivacky unsigned QOpcodes0[] = { ARM::VLD2LNq16a, ARM::VLD2LNq32a }; 1648198090Srdivacky unsigned QOpcodes1[] = { ARM::VLD2LNq16b, ARM::VLD2LNq32b }; 1649198090Srdivacky return SelectVLDSTLane(Op, true, 2, DOpcodes, QOpcodes0, QOpcodes1); 1650198090Srdivacky } 1651198090Srdivacky 1652198090Srdivacky case Intrinsic::arm_neon_vld3lane: { 1653198090Srdivacky unsigned DOpcodes[] = { ARM::VLD3LNd8, ARM::VLD3LNd16, ARM::VLD3LNd32 }; 1654198090Srdivacky unsigned QOpcodes0[] = { ARM::VLD3LNq16a, ARM::VLD3LNq32a }; 1655198090Srdivacky unsigned QOpcodes1[] = { ARM::VLD3LNq16b, ARM::VLD3LNq32b }; 1656198090Srdivacky return SelectVLDSTLane(Op, true, 3, DOpcodes, QOpcodes0, QOpcodes1); 1657198090Srdivacky } 1658198090Srdivacky 1659198090Srdivacky case Intrinsic::arm_neon_vld4lane: { 1660198090Srdivacky unsigned DOpcodes[] = { ARM::VLD4LNd8, ARM::VLD4LNd16, ARM::VLD4LNd32 }; 1661198090Srdivacky unsigned QOpcodes0[] = { ARM::VLD4LNq16a, ARM::VLD4LNq32a }; 1662198090Srdivacky unsigned QOpcodes1[] = { ARM::VLD4LNq16b, ARM::VLD4LNq32b }; 1663198090Srdivacky return SelectVLDSTLane(Op, true, 4, DOpcodes, QOpcodes0, QOpcodes1); 1664198090Srdivacky } 1665198090Srdivacky 1666198090Srdivacky case Intrinsic::arm_neon_vst2: { 1667198090Srdivacky SDValue MemAddr, MemUpdate, MemOpc; 1668198090Srdivacky if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc)) 1669198090Srdivacky return NULL; 1670198090Srdivacky SDValue Chain = N->getOperand(0); 1671198090Srdivacky VT = N->getOperand(3).getValueType(); 1672198090Srdivacky if (VT.is64BitVector()) { 1673198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1674198090Srdivacky default: llvm_unreachable("unhandled vst2 type"); 1675198090Srdivacky case MVT::v8i8: Opc = ARM::VST2d8; break; 1676198090Srdivacky case MVT::v4i16: Opc = ARM::VST2d16; break; 1677198090Srdivacky case MVT::v2f32: 1678198090Srdivacky case MVT::v2i32: Opc = ARM::VST2d32; break; 1679198090Srdivacky case MVT::v1i64: Opc = ARM::VST2d64; break; 1680198090Srdivacky } 1681198090Srdivacky const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, 1682198090Srdivacky N->getOperand(3), N->getOperand(4), Chain }; 1683198090Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops, 6); 1684194710Sed } 1685198090Srdivacky // Quad registers are stored as pairs of double registers. 1686198090Srdivacky EVT RegVT; 1687198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1688198090Srdivacky default: llvm_unreachable("unhandled vst2 type"); 1689198090Srdivacky case MVT::v16i8: Opc = ARM::VST2q8; RegVT = MVT::v8i8; break; 1690198090Srdivacky case MVT::v8i16: Opc = ARM::VST2q16; RegVT = MVT::v4i16; break; 1691198090Srdivacky case MVT::v4f32: Opc = ARM::VST2q32; RegVT = MVT::v2f32; break; 1692198090Srdivacky case MVT::v4i32: Opc = ARM::VST2q32; RegVT = MVT::v2i32; break; 1693198090Srdivacky } 1694198090Srdivacky SDValue D0 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT, 1695198090Srdivacky N->getOperand(3)); 1696198090Srdivacky SDValue D1 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT, 1697198090Srdivacky N->getOperand(3)); 1698198090Srdivacky SDValue D2 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT, 1699198090Srdivacky N->getOperand(4)); 1700198090Srdivacky SDValue D3 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT, 1701198090Srdivacky N->getOperand(4)); 1702198090Srdivacky const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, 1703198090Srdivacky D0, D1, D2, D3, Chain }; 1704198090Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops, 8); 1705198090Srdivacky } 1706194710Sed 1707198090Srdivacky case Intrinsic::arm_neon_vst3: { 1708198090Srdivacky SDValue MemAddr, MemUpdate, MemOpc; 1709198090Srdivacky if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc)) 1710198090Srdivacky return NULL; 1711198090Srdivacky SDValue Chain = N->getOperand(0); 1712198090Srdivacky VT = N->getOperand(3).getValueType(); 1713198090Srdivacky if (VT.is64BitVector()) { 1714198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1715198090Srdivacky default: llvm_unreachable("unhandled vst3 type"); 1716198090Srdivacky case MVT::v8i8: Opc = ARM::VST3d8; break; 1717198090Srdivacky case MVT::v4i16: Opc = ARM::VST3d16; break; 1718198090Srdivacky case MVT::v2f32: 1719198090Srdivacky case MVT::v2i32: Opc = ARM::VST3d32; break; 1720198090Srdivacky case MVT::v1i64: Opc = ARM::VST3d64; break; 1721198090Srdivacky } 1722198090Srdivacky const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, 1723198090Srdivacky N->getOperand(3), N->getOperand(4), 1724198090Srdivacky N->getOperand(5), Chain }; 1725198090Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops, 7); 1726198090Srdivacky } 1727198090Srdivacky // Quad registers are stored with two separate instructions, where one 1728198090Srdivacky // stores the even registers and the other stores the odd registers. 1729198090Srdivacky EVT RegVT; 1730198090Srdivacky unsigned Opc2 = 0; 1731198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1732198090Srdivacky default: llvm_unreachable("unhandled vst3 type"); 1733198090Srdivacky case MVT::v16i8: 1734198090Srdivacky Opc = ARM::VST3q8a; Opc2 = ARM::VST3q8b; RegVT = MVT::v8i8; break; 1735198090Srdivacky case MVT::v8i16: 1736198090Srdivacky Opc = ARM::VST3q16a; Opc2 = ARM::VST3q16b; RegVT = MVT::v4i16; break; 1737198090Srdivacky case MVT::v4f32: 1738198090Srdivacky Opc = ARM::VST3q32a; Opc2 = ARM::VST3q32b; RegVT = MVT::v2f32; break; 1739198090Srdivacky case MVT::v4i32: 1740198090Srdivacky Opc = ARM::VST3q32a; Opc2 = ARM::VST3q32b; RegVT = MVT::v2i32; break; 1741198090Srdivacky } 1742198090Srdivacky // Enable writeback to the address register. 1743198090Srdivacky MemOpc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(true), MVT::i32); 1744198090Srdivacky 1745198090Srdivacky SDValue D0 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT, 1746198090Srdivacky N->getOperand(3)); 1747198090Srdivacky SDValue D2 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT, 1748198090Srdivacky N->getOperand(4)); 1749198090Srdivacky SDValue D4 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT, 1750198090Srdivacky N->getOperand(5)); 1751198090Srdivacky const SDValue OpsA[] = { MemAddr, MemUpdate, MemOpc, D0, D2, D4, Chain }; 1752198090Srdivacky SDNode *VStA = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(), 1753198090Srdivacky MVT::Other, OpsA, 7); 1754198090Srdivacky Chain = SDValue(VStA, 1); 1755198090Srdivacky 1756198090Srdivacky SDValue D1 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT, 1757198090Srdivacky N->getOperand(3)); 1758198090Srdivacky SDValue D3 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT, 1759198090Srdivacky N->getOperand(4)); 1760198090Srdivacky SDValue D5 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT, 1761198090Srdivacky N->getOperand(5)); 1762198090Srdivacky MemAddr = SDValue(VStA, 0); 1763198090Srdivacky const SDValue OpsB[] = { MemAddr, MemUpdate, MemOpc, D1, D3, D5, Chain }; 1764198090Srdivacky SDNode *VStB = CurDAG->getMachineNode(Opc2, dl, MemAddr.getValueType(), 1765198090Srdivacky MVT::Other, OpsB, 7); 1766198090Srdivacky Chain = SDValue(VStB, 1); 1767198090Srdivacky ReplaceUses(SDValue(N, 0), Chain); 1768198090Srdivacky return NULL; 1769194710Sed } 1770194710Sed 1771198090Srdivacky case Intrinsic::arm_neon_vst4: { 1772198090Srdivacky SDValue MemAddr, MemUpdate, MemOpc; 1773198090Srdivacky if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc)) 1774198090Srdivacky return NULL; 1775198090Srdivacky SDValue Chain = N->getOperand(0); 1776198090Srdivacky VT = N->getOperand(3).getValueType(); 1777198090Srdivacky if (VT.is64BitVector()) { 1778198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1779198090Srdivacky default: llvm_unreachable("unhandled vst4 type"); 1780198090Srdivacky case MVT::v8i8: Opc = ARM::VST4d8; break; 1781198090Srdivacky case MVT::v4i16: Opc = ARM::VST4d16; break; 1782198090Srdivacky case MVT::v2f32: 1783198090Srdivacky case MVT::v2i32: Opc = ARM::VST4d32; break; 1784198090Srdivacky case MVT::v1i64: Opc = ARM::VST4d64; break; 1785198090Srdivacky } 1786198090Srdivacky const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, 1787198090Srdivacky N->getOperand(3), N->getOperand(4), 1788198090Srdivacky N->getOperand(5), N->getOperand(6), Chain }; 1789198090Srdivacky return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops, 8); 1790198090Srdivacky } 1791198090Srdivacky // Quad registers are stored with two separate instructions, where one 1792198090Srdivacky // stores the even registers and the other stores the odd registers. 1793198090Srdivacky EVT RegVT; 1794198090Srdivacky unsigned Opc2 = 0; 1795198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1796198090Srdivacky default: llvm_unreachable("unhandled vst4 type"); 1797198090Srdivacky case MVT::v16i8: 1798198090Srdivacky Opc = ARM::VST4q8a; Opc2 = ARM::VST4q8b; RegVT = MVT::v8i8; break; 1799198090Srdivacky case MVT::v8i16: 1800198090Srdivacky Opc = ARM::VST4q16a; Opc2 = ARM::VST4q16b; RegVT = MVT::v4i16; break; 1801198090Srdivacky case MVT::v4f32: 1802198090Srdivacky Opc = ARM::VST4q32a; Opc2 = ARM::VST4q32b; RegVT = MVT::v2f32; break; 1803198090Srdivacky case MVT::v4i32: 1804198090Srdivacky Opc = ARM::VST4q32a; Opc2 = ARM::VST4q32b; RegVT = MVT::v2i32; break; 1805198090Srdivacky } 1806198090Srdivacky // Enable writeback to the address register. 1807198090Srdivacky MemOpc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(true), MVT::i32); 1808198090Srdivacky 1809198090Srdivacky SDValue D0 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT, 1810198090Srdivacky N->getOperand(3)); 1811198090Srdivacky SDValue D2 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT, 1812198090Srdivacky N->getOperand(4)); 1813198090Srdivacky SDValue D4 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT, 1814198090Srdivacky N->getOperand(5)); 1815198090Srdivacky SDValue D6 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT, 1816198090Srdivacky N->getOperand(6)); 1817198090Srdivacky const SDValue OpsA[] = { MemAddr, MemUpdate, MemOpc, 1818198090Srdivacky D0, D2, D4, D6, Chain }; 1819198090Srdivacky SDNode *VStA = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(), 1820198090Srdivacky MVT::Other, OpsA, 8); 1821198090Srdivacky Chain = SDValue(VStA, 1); 1822198090Srdivacky 1823198090Srdivacky SDValue D1 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT, 1824198090Srdivacky N->getOperand(3)); 1825198090Srdivacky SDValue D3 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT, 1826198090Srdivacky N->getOperand(4)); 1827198090Srdivacky SDValue D5 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT, 1828198090Srdivacky N->getOperand(5)); 1829198090Srdivacky SDValue D7 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT, 1830198090Srdivacky N->getOperand(6)); 1831198090Srdivacky MemAddr = SDValue(VStA, 0); 1832198090Srdivacky const SDValue OpsB[] = { MemAddr, MemUpdate, MemOpc, 1833198090Srdivacky D1, D3, D5, D7, Chain }; 1834198090Srdivacky SDNode *VStB = CurDAG->getMachineNode(Opc2, dl, MemAddr.getValueType(), 1835198090Srdivacky MVT::Other, OpsB, 8); 1836198090Srdivacky Chain = SDValue(VStB, 1); 1837198090Srdivacky ReplaceUses(SDValue(N, 0), Chain); 1838198090Srdivacky return NULL; 1839198090Srdivacky } 1840198090Srdivacky 1841198090Srdivacky case Intrinsic::arm_neon_vst2lane: { 1842198090Srdivacky unsigned DOpcodes[] = { ARM::VST2LNd8, ARM::VST2LNd16, ARM::VST2LNd32 }; 1843198090Srdivacky unsigned QOpcodes0[] = { ARM::VST2LNq16a, ARM::VST2LNq32a }; 1844198090Srdivacky unsigned QOpcodes1[] = { ARM::VST2LNq16b, ARM::VST2LNq32b }; 1845198090Srdivacky return SelectVLDSTLane(Op, false, 2, DOpcodes, QOpcodes0, QOpcodes1); 1846198090Srdivacky } 1847198090Srdivacky 1848198090Srdivacky case Intrinsic::arm_neon_vst3lane: { 1849198090Srdivacky unsigned DOpcodes[] = { ARM::VST3LNd8, ARM::VST3LNd16, ARM::VST3LNd32 }; 1850198090Srdivacky unsigned QOpcodes0[] = { ARM::VST3LNq16a, ARM::VST3LNq32a }; 1851198090Srdivacky unsigned QOpcodes1[] = { ARM::VST3LNq16b, ARM::VST3LNq32b }; 1852198090Srdivacky return SelectVLDSTLane(Op, false, 3, DOpcodes, QOpcodes0, QOpcodes1); 1853198090Srdivacky } 1854198090Srdivacky 1855198090Srdivacky case Intrinsic::arm_neon_vst4lane: { 1856198090Srdivacky unsigned DOpcodes[] = { ARM::VST4LNd8, ARM::VST4LNd16, ARM::VST4LNd32 }; 1857198090Srdivacky unsigned QOpcodes0[] = { ARM::VST4LNq16a, ARM::VST4LNq32a }; 1858198090Srdivacky unsigned QOpcodes1[] = { ARM::VST4LNq16b, ARM::VST4LNq32b }; 1859198090Srdivacky return SelectVLDSTLane(Op, false, 4, DOpcodes, QOpcodes0, QOpcodes1); 1860198090Srdivacky } 1861198090Srdivacky } 1862194710Sed } 1863194710Sed } 1864194710Sed 1865193323Sed return SelectCode(Op); 1866193323Sed} 1867193323Sed 1868193323Sedbool ARMDAGToDAGISel:: 1869193323SedSelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, 1870193323Sed std::vector<SDValue> &OutOps) { 1871193323Sed assert(ConstraintCode == 'm' && "unexpected asm memory constraint"); 1872198090Srdivacky // Require the address to be in a register. That is safe for all ARM 1873198090Srdivacky // variants and it is hard to do anything much smarter without knowing 1874198090Srdivacky // how the operand is used. 1875198090Srdivacky OutOps.push_back(Op); 1876193323Sed return false; 1877193323Sed} 1878193323Sed 1879193323Sed/// createARMISelDag - This pass converts a legalized DAG into a 1880193323Sed/// ARM-specific DAG, ready for instruction scheduling. 1881193323Sed/// 1882198090SrdivackyFunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM, 1883198090Srdivacky CodeGenOpt::Level OptLevel) { 1884198090Srdivacky return new ARMDAGToDAGISel(TM, OptLevel); 1885193323Sed} 1886