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