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