ARMISelDAGToDAG.cpp revision 205407
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 "ARMISelLowering.h"
17193323Sed#include "ARMTargetMachine.h"
18193323Sed#include "llvm/CallingConv.h"
19193323Sed#include "llvm/Constants.h"
20193323Sed#include "llvm/DerivedTypes.h"
21193323Sed#include "llvm/Function.h"
22193323Sed#include "llvm/Intrinsics.h"
23198090Srdivacky#include "llvm/LLVMContext.h"
24193323Sed#include "llvm/CodeGen/MachineFrameInfo.h"
25193323Sed#include "llvm/CodeGen/MachineFunction.h"
26193323Sed#include "llvm/CodeGen/MachineInstrBuilder.h"
27193323Sed#include "llvm/CodeGen/SelectionDAG.h"
28193323Sed#include "llvm/CodeGen/SelectionDAGISel.h"
29193323Sed#include "llvm/Target/TargetLowering.h"
30193323Sed#include "llvm/Target/TargetOptions.h"
31193323Sed#include "llvm/Support/Compiler.h"
32193323Sed#include "llvm/Support/Debug.h"
33198090Srdivacky#include "llvm/Support/ErrorHandling.h"
34198090Srdivacky#include "llvm/Support/raw_ostream.h"
35198090Srdivacky
36193323Sedusing namespace llvm;
37193323Sed
38193323Sed//===--------------------------------------------------------------------===//
39193323Sed/// ARMDAGToDAGISel - ARM specific code to select ARM machine
40193323Sed/// instructions for SelectionDAG operations.
41193323Sed///
42193323Sednamespace {
43193323Sedclass ARMDAGToDAGISel : public SelectionDAGISel {
44195098Sed  ARMBaseTargetMachine &TM;
45193323Sed
46193323Sed  /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
47193323Sed  /// make the right decision when generating code for different targets.
48193323Sed  const ARMSubtarget *Subtarget;
49193323Sed
50193323Sedpublic:
51198090Srdivacky  explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm,
52198090Srdivacky                           CodeGenOpt::Level OptLevel)
53198090Srdivacky    : SelectionDAGISel(tm, OptLevel), TM(tm),
54193323Sed    Subtarget(&TM.getSubtarget<ARMSubtarget>()) {
55193323Sed  }
56193323Sed
57193323Sed  virtual const char *getPassName() const {
58193323Sed    return "ARM Instruction Selection";
59194612Sed  }
60194612Sed
61198090Srdivacky  /// getI32Imm - Return a target constant of type i32 with the specified
62198090Srdivacky  /// value.
63194612Sed  inline SDValue getI32Imm(unsigned Imm) {
64194612Sed    return CurDAG->getTargetConstant(Imm, MVT::i32);
65194612Sed  }
66194612Sed
67202375Srdivacky  SDNode *Select(SDNode *N);
68203954Srdivacky
69202375Srdivacky  bool SelectShifterOperandReg(SDNode *Op, SDValue N, SDValue &A,
70195340Sed                               SDValue &B, SDValue &C);
71202375Srdivacky  bool SelectAddrMode2(SDNode *Op, SDValue N, SDValue &Base,
72193323Sed                       SDValue &Offset, SDValue &Opc);
73202375Srdivacky  bool SelectAddrMode2Offset(SDNode *Op, SDValue N,
74193323Sed                             SDValue &Offset, SDValue &Opc);
75202375Srdivacky  bool SelectAddrMode3(SDNode *Op, SDValue N, SDValue &Base,
76193323Sed                       SDValue &Offset, SDValue &Opc);
77202375Srdivacky  bool SelectAddrMode3Offset(SDNode *Op, SDValue N,
78193323Sed                             SDValue &Offset, SDValue &Opc);
79202375Srdivacky  bool SelectAddrMode4(SDNode *Op, SDValue N, SDValue &Addr,
80198090Srdivacky                       SDValue &Mode);
81202375Srdivacky  bool SelectAddrMode5(SDNode *Op, SDValue N, SDValue &Base,
82193323Sed                       SDValue &Offset);
83205407Srdivacky  bool SelectAddrMode6(SDNode *Op, SDValue N, SDValue &Addr, SDValue &Align);
84193323Sed
85202375Srdivacky  bool SelectAddrModePC(SDNode *Op, SDValue N, SDValue &Offset,
86195340Sed                        SDValue &Label);
87193323Sed
88202375Srdivacky  bool SelectThumbAddrModeRR(SDNode *Op, SDValue N, SDValue &Base,
89193323Sed                             SDValue &Offset);
90202375Srdivacky  bool SelectThumbAddrModeRI5(SDNode *Op, SDValue N, unsigned Scale,
91193323Sed                              SDValue &Base, SDValue &OffImm,
92193323Sed                              SDValue &Offset);
93202375Srdivacky  bool SelectThumbAddrModeS1(SDNode *Op, SDValue N, SDValue &Base,
94193323Sed                             SDValue &OffImm, SDValue &Offset);
95202375Srdivacky  bool SelectThumbAddrModeS2(SDNode *Op, SDValue N, SDValue &Base,
96193323Sed                             SDValue &OffImm, SDValue &Offset);
97202375Srdivacky  bool SelectThumbAddrModeS4(SDNode *Op, SDValue N, SDValue &Base,
98193323Sed                             SDValue &OffImm, SDValue &Offset);
99202375Srdivacky  bool SelectThumbAddrModeSP(SDNode *Op, SDValue N, SDValue &Base,
100193323Sed                             SDValue &OffImm);
101193323Sed
102202375Srdivacky  bool SelectT2ShifterOperandReg(SDNode *Op, SDValue N,
103195098Sed                                 SDValue &BaseReg, SDValue &Opc);
104202375Srdivacky  bool SelectT2AddrModeImm12(SDNode *Op, SDValue N, SDValue &Base,
105195340Sed                             SDValue &OffImm);
106202375Srdivacky  bool SelectT2AddrModeImm8(SDNode *Op, SDValue N, SDValue &Base,
107195340Sed                            SDValue &OffImm);
108202375Srdivacky  bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
109195340Sed                                 SDValue &OffImm);
110202375Srdivacky  bool SelectT2AddrModeImm8s4(SDNode *Op, SDValue N, SDValue &Base,
111195340Sed                              SDValue &OffImm);
112202375Srdivacky  bool SelectT2AddrModeSoReg(SDNode *Op, SDValue N, SDValue &Base,
113195340Sed                             SDValue &OffReg, SDValue &ShImm);
114195340Sed
115193323Sed  // Include the pieces autogenerated from the target description.
116193323Sed#include "ARMGenDAGISel.inc"
117193323Sed
118193323Sedprivate:
119195340Sed  /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for
120195340Sed  /// ARM.
121202375Srdivacky  SDNode *SelectARMIndexedLoad(SDNode *N);
122202375Srdivacky  SDNode *SelectT2IndexedLoad(SDNode *N);
123195340Sed
124198090Srdivacky  /// SelectDYN_ALLOC - Select dynamic alloc for Thumb.
125202375Srdivacky  SDNode *SelectDYN_ALLOC(SDNode *N);
126195340Sed
127198090Srdivacky  /// SelectVLD - Select NEON load intrinsics.  NumVecs should
128198090Srdivacky  /// be 2, 3 or 4.  The opcode arrays specify the instructions used for
129198090Srdivacky  /// loads of D registers and even subregs and odd subregs of Q registers.
130198090Srdivacky  /// For NumVecs == 2, QOpcodes1 is not used.
131202375Srdivacky  SDNode *SelectVLD(SDNode *N, unsigned NumVecs, unsigned *DOpcodes,
132198090Srdivacky                    unsigned *QOpcodes0, unsigned *QOpcodes1);
133198090Srdivacky
134198113Srdivacky  /// SelectVST - Select NEON store intrinsics.  NumVecs should
135198113Srdivacky  /// be 2, 3 or 4.  The opcode arrays specify the instructions used for
136198113Srdivacky  /// stores of D registers and even subregs and odd subregs of Q registers.
137198113Srdivacky  /// For NumVecs == 2, QOpcodes1 is not used.
138202375Srdivacky  SDNode *SelectVST(SDNode *N, unsigned NumVecs, unsigned *DOpcodes,
139198113Srdivacky                    unsigned *QOpcodes0, unsigned *QOpcodes1);
140198113Srdivacky
141198090Srdivacky  /// SelectVLDSTLane - Select NEON load/store lane intrinsics.  NumVecs should
142198090Srdivacky  /// be 2, 3 or 4.  The opcode arrays specify the instructions used for
143198090Srdivacky  /// load/store of D registers and even subregs and odd subregs of Q registers.
144202375Srdivacky  SDNode *SelectVLDSTLane(SDNode *N, bool IsLoad, unsigned NumVecs,
145198090Srdivacky                          unsigned *DOpcodes, unsigned *QOpcodes0,
146198090Srdivacky                          unsigned *QOpcodes1);
147198090Srdivacky
148198090Srdivacky  /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM.
149202375Srdivacky  SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, unsigned Opc);
150198090Srdivacky
151199989Srdivacky  /// SelectCMOVOp - Select CMOV instructions for ARM.
152202375Srdivacky  SDNode *SelectCMOVOp(SDNode *N);
153202375Srdivacky  SDNode *SelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
154199989Srdivacky                              ARMCC::CondCodes CCVal, SDValue CCR,
155199989Srdivacky                              SDValue InFlag);
156202375Srdivacky  SDNode *SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
157199989Srdivacky                               ARMCC::CondCodes CCVal, SDValue CCR,
158199989Srdivacky                               SDValue InFlag);
159202375Srdivacky  SDNode *SelectT2CMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
160199989Srdivacky                              ARMCC::CondCodes CCVal, SDValue CCR,
161199989Srdivacky                              SDValue InFlag);
162202375Srdivacky  SDNode *SelectARMCMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
163199989Srdivacky                               ARMCC::CondCodes CCVal, SDValue CCR,
164199989Srdivacky                               SDValue InFlag);
165199989Srdivacky
166195340Sed  /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
167195340Sed  /// inline asm expressions.
168195340Sed  virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
169195340Sed                                            char ConstraintCode,
170195340Sed                                            std::vector<SDValue> &OutOps);
171198090Srdivacky
172198090Srdivacky  /// PairDRegs - Insert a pair of double registers into an implicit def to
173198090Srdivacky  /// form a quad register.
174198090Srdivacky  SDNode *PairDRegs(EVT VT, SDValue V0, SDValue V1);
175193323Sed};
176193323Sed}
177193323Sed
178198090Srdivacky/// isInt32Immediate - This method tests to see if the node is a 32-bit constant
179198090Srdivacky/// operand. If so Imm will receive the 32-bit value.
180198090Srdivackystatic bool isInt32Immediate(SDNode *N, unsigned &Imm) {
181198090Srdivacky  if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) {
182198090Srdivacky    Imm = cast<ConstantSDNode>(N)->getZExtValue();
183198090Srdivacky    return true;
184198090Srdivacky  }
185198090Srdivacky  return false;
186198090Srdivacky}
187198090Srdivacky
188198090Srdivacky// isInt32Immediate - This method tests to see if a constant operand.
189198090Srdivacky// If so Imm will receive the 32 bit value.
190198090Srdivackystatic bool isInt32Immediate(SDValue N, unsigned &Imm) {
191198090Srdivacky  return isInt32Immediate(N.getNode(), Imm);
192198090Srdivacky}
193198090Srdivacky
194198090Srdivacky// isOpcWithIntImmediate - This method tests to see if the node is a specific
195198090Srdivacky// opcode and that it has a immediate integer right operand.
196198090Srdivacky// If so Imm will receive the 32 bit value.
197198090Srdivackystatic bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
198198090Srdivacky  return N->getOpcode() == Opc &&
199198090Srdivacky         isInt32Immediate(N->getOperand(1).getNode(), Imm);
200198090Srdivacky}
201198090Srdivacky
202198090Srdivacky
203202375Srdivackybool ARMDAGToDAGISel::SelectShifterOperandReg(SDNode *Op,
204195340Sed                                              SDValue N,
205195340Sed                                              SDValue &BaseReg,
206195340Sed                                              SDValue &ShReg,
207195340Sed                                              SDValue &Opc) {
208195340Sed  ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N);
209195340Sed
210195340Sed  // Don't match base register only case. That is matched to a separate
211195340Sed  // lower complexity pattern with explicit register operand.
212195340Sed  if (ShOpcVal == ARM_AM::no_shift) return false;
213198090Srdivacky
214195340Sed  BaseReg = N.getOperand(0);
215195340Sed  unsigned ShImmVal = 0;
216195340Sed  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
217195340Sed    ShReg = CurDAG->getRegister(0, MVT::i32);
218195340Sed    ShImmVal = RHS->getZExtValue() & 31;
219195340Sed  } else {
220195340Sed    ShReg = N.getOperand(1);
221195340Sed  }
222195340Sed  Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
223195340Sed                                  MVT::i32);
224195340Sed  return true;
225195340Sed}
226195340Sed
227202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode2(SDNode *Op, SDValue N,
228193323Sed                                      SDValue &Base, SDValue &Offset,
229193323Sed                                      SDValue &Opc) {
230193323Sed  if (N.getOpcode() == ISD::MUL) {
231193323Sed    if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
232193323Sed      // X * [3,5,9] -> X + X * [2,4,8] etc.
233193323Sed      int RHSC = (int)RHS->getZExtValue();
234193323Sed      if (RHSC & 1) {
235193323Sed        RHSC = RHSC & ~1;
236193323Sed        ARM_AM::AddrOpc AddSub = ARM_AM::add;
237193323Sed        if (RHSC < 0) {
238193323Sed          AddSub = ARM_AM::sub;
239193323Sed          RHSC = - RHSC;
240193323Sed        }
241193323Sed        if (isPowerOf2_32(RHSC)) {
242193323Sed          unsigned ShAmt = Log2_32(RHSC);
243193323Sed          Base = Offset = N.getOperand(0);
244193323Sed          Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
245193323Sed                                                            ARM_AM::lsl),
246193323Sed                                          MVT::i32);
247193323Sed          return true;
248193323Sed        }
249193323Sed      }
250193323Sed    }
251193323Sed  }
252193323Sed
253193323Sed  if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) {
254193323Sed    Base = N;
255193323Sed    if (N.getOpcode() == ISD::FrameIndex) {
256193323Sed      int FI = cast<FrameIndexSDNode>(N)->getIndex();
257193323Sed      Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
258199989Srdivacky    } else if (N.getOpcode() == ARMISD::Wrapper &&
259199989Srdivacky               !(Subtarget->useMovt() &&
260199989Srdivacky                 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
261193323Sed      Base = N.getOperand(0);
262193323Sed    }
263193323Sed    Offset = CurDAG->getRegister(0, MVT::i32);
264193323Sed    Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
265193323Sed                                                      ARM_AM::no_shift),
266193323Sed                                    MVT::i32);
267193323Sed    return true;
268193323Sed  }
269198090Srdivacky
270193323Sed  // Match simple R +/- imm12 operands.
271193323Sed  if (N.getOpcode() == ISD::ADD)
272193323Sed    if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
273193323Sed      int RHSC = (int)RHS->getZExtValue();
274193323Sed      if ((RHSC >= 0 && RHSC < 0x1000) ||
275193323Sed          (RHSC < 0 && RHSC > -0x1000)) { // 12 bits.
276193323Sed        Base = N.getOperand(0);
277193323Sed        if (Base.getOpcode() == ISD::FrameIndex) {
278193323Sed          int FI = cast<FrameIndexSDNode>(Base)->getIndex();
279193323Sed          Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
280193323Sed        }
281193323Sed        Offset = CurDAG->getRegister(0, MVT::i32);
282193323Sed
283193323Sed        ARM_AM::AddrOpc AddSub = ARM_AM::add;
284193323Sed        if (RHSC < 0) {
285193323Sed          AddSub = ARM_AM::sub;
286193323Sed          RHSC = - RHSC;
287193323Sed        }
288193323Sed        Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC,
289193323Sed                                                          ARM_AM::no_shift),
290193323Sed                                        MVT::i32);
291193323Sed        return true;
292193323Sed      }
293193323Sed    }
294198090Srdivacky
295198892Srdivacky  // Otherwise this is R +/- [possibly shifted] R.
296193323Sed  ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::ADD ? ARM_AM::add:ARM_AM::sub;
297193323Sed  ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1));
298193323Sed  unsigned ShAmt = 0;
299198090Srdivacky
300193323Sed  Base   = N.getOperand(0);
301193323Sed  Offset = N.getOperand(1);
302198090Srdivacky
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 fold
305193323Sed    // it.
306193323Sed    if (ConstantSDNode *Sh =
307193323Sed           dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
308193323Sed      ShAmt = Sh->getZExtValue();
309193323Sed      Offset = N.getOperand(1).getOperand(0);
310193323Sed    } else {
311193323Sed      ShOpcVal = ARM_AM::no_shift;
312193323Sed    }
313193323Sed  }
314198090Srdivacky
315193323Sed  // Try matching (R shl C) + (R).
316193323Sed  if (N.getOpcode() == ISD::ADD && ShOpcVal == ARM_AM::no_shift) {
317193323Sed    ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0));
318193323Sed    if (ShOpcVal != ARM_AM::no_shift) {
319193323Sed      // Check to see if the RHS of the shift is a constant, if not, we can't
320193323Sed      // fold it.
321193323Sed      if (ConstantSDNode *Sh =
322193323Sed          dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
323193323Sed        ShAmt = Sh->getZExtValue();
324193323Sed        Offset = N.getOperand(0).getOperand(0);
325193323Sed        Base = N.getOperand(1);
326193323Sed      } else {
327193323Sed        ShOpcVal = ARM_AM::no_shift;
328193323Sed      }
329193323Sed    }
330193323Sed  }
331198090Srdivacky
332193323Sed  Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
333193323Sed                                  MVT::i32);
334193323Sed  return true;
335193323Sed}
336193323Sed
337202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode2Offset(SDNode *Op, SDValue N,
338193323Sed                                            SDValue &Offset, SDValue &Opc) {
339202375Srdivacky  unsigned Opcode = Op->getOpcode();
340193323Sed  ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
341193323Sed    ? cast<LoadSDNode>(Op)->getAddressingMode()
342193323Sed    : cast<StoreSDNode>(Op)->getAddressingMode();
343193323Sed  ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
344193323Sed    ? ARM_AM::add : ARM_AM::sub;
345193323Sed  if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) {
346193323Sed    int Val = (int)C->getZExtValue();
347193323Sed    if (Val >= 0 && Val < 0x1000) { // 12 bits.
348193323Sed      Offset = CurDAG->getRegister(0, MVT::i32);
349193323Sed      Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
350193323Sed                                                        ARM_AM::no_shift),
351193323Sed                                      MVT::i32);
352193323Sed      return true;
353193323Sed    }
354193323Sed  }
355193323Sed
356193323Sed  Offset = N;
357193323Sed  ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N);
358193323Sed  unsigned ShAmt = 0;
359193323Sed  if (ShOpcVal != ARM_AM::no_shift) {
360193323Sed    // Check to see if the RHS of the shift is a constant, if not, we can't fold
361193323Sed    // it.
362193323Sed    if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
363193323Sed      ShAmt = Sh->getZExtValue();
364193323Sed      Offset = N.getOperand(0);
365193323Sed    } else {
366193323Sed      ShOpcVal = ARM_AM::no_shift;
367193323Sed    }
368193323Sed  }
369193323Sed
370193323Sed  Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
371193323Sed                                  MVT::i32);
372193323Sed  return true;
373193323Sed}
374193323Sed
375193323Sed
376202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode3(SDNode *Op, SDValue N,
377193323Sed                                      SDValue &Base, SDValue &Offset,
378193323Sed                                      SDValue &Opc) {
379193323Sed  if (N.getOpcode() == ISD::SUB) {
380193323Sed    // X - C  is canonicalize to X + -C, no need to handle it here.
381193323Sed    Base = N.getOperand(0);
382193323Sed    Offset = N.getOperand(1);
383193323Sed    Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32);
384193323Sed    return true;
385193323Sed  }
386198090Srdivacky
387193323Sed  if (N.getOpcode() != ISD::ADD) {
388193323Sed    Base = N;
389193323Sed    if (N.getOpcode() == ISD::FrameIndex) {
390193323Sed      int FI = cast<FrameIndexSDNode>(N)->getIndex();
391193323Sed      Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
392193323Sed    }
393193323Sed    Offset = CurDAG->getRegister(0, MVT::i32);
394193323Sed    Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32);
395193323Sed    return true;
396193323Sed  }
397198090Srdivacky
398193323Sed  // If the RHS is +/- imm8, fold into addr mode.
399193323Sed  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
400193323Sed    int RHSC = (int)RHS->getZExtValue();
401193323Sed    if ((RHSC >= 0 && RHSC < 256) ||
402193323Sed        (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed.
403193323Sed      Base = N.getOperand(0);
404193323Sed      if (Base.getOpcode() == ISD::FrameIndex) {
405193323Sed        int FI = cast<FrameIndexSDNode>(Base)->getIndex();
406193323Sed        Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
407193323Sed      }
408193323Sed      Offset = CurDAG->getRegister(0, MVT::i32);
409193323Sed
410193323Sed      ARM_AM::AddrOpc AddSub = ARM_AM::add;
411193323Sed      if (RHSC < 0) {
412193323Sed        AddSub = ARM_AM::sub;
413193323Sed        RHSC = - RHSC;
414193323Sed      }
415193323Sed      Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32);
416193323Sed      return true;
417193323Sed    }
418193323Sed  }
419198090Srdivacky
420193323Sed  Base = N.getOperand(0);
421193323Sed  Offset = N.getOperand(1);
422193323Sed  Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32);
423193323Sed  return true;
424193323Sed}
425193323Sed
426202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
427193323Sed                                            SDValue &Offset, SDValue &Opc) {
428202375Srdivacky  unsigned Opcode = Op->getOpcode();
429193323Sed  ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
430193323Sed    ? cast<LoadSDNode>(Op)->getAddressingMode()
431193323Sed    : cast<StoreSDNode>(Op)->getAddressingMode();
432193323Sed  ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
433193323Sed    ? ARM_AM::add : ARM_AM::sub;
434193323Sed  if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) {
435193323Sed    int Val = (int)C->getZExtValue();
436193323Sed    if (Val >= 0 && Val < 256) {
437193323Sed      Offset = CurDAG->getRegister(0, MVT::i32);
438193323Sed      Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32);
439193323Sed      return true;
440193323Sed    }
441193323Sed  }
442193323Sed
443193323Sed  Offset = N;
444193323Sed  Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32);
445193323Sed  return true;
446193323Sed}
447193323Sed
448202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode4(SDNode *Op, SDValue N,
449198090Srdivacky                                      SDValue &Addr, SDValue &Mode) {
450198090Srdivacky  Addr = N;
451198090Srdivacky  Mode = CurDAG->getTargetConstant(0, MVT::i32);
452198090Srdivacky  return true;
453198090Srdivacky}
454193323Sed
455202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode5(SDNode *Op, SDValue N,
456193323Sed                                      SDValue &Base, SDValue &Offset) {
457193323Sed  if (N.getOpcode() != ISD::ADD) {
458193323Sed    Base = N;
459193323Sed    if (N.getOpcode() == ISD::FrameIndex) {
460193323Sed      int FI = cast<FrameIndexSDNode>(N)->getIndex();
461193323Sed      Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
462199989Srdivacky    } else if (N.getOpcode() == ARMISD::Wrapper &&
463199989Srdivacky               !(Subtarget->useMovt() &&
464199989Srdivacky                 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
465193323Sed      Base = N.getOperand(0);
466193323Sed    }
467193323Sed    Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
468193323Sed                                       MVT::i32);
469193323Sed    return true;
470193323Sed  }
471198090Srdivacky
472193323Sed  // If the RHS is +/- imm8, fold into addr mode.
473193323Sed  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
474193323Sed    int RHSC = (int)RHS->getZExtValue();
475193323Sed    if ((RHSC & 3) == 0) {  // The constant is implicitly multiplied by 4.
476193323Sed      RHSC >>= 2;
477193323Sed      if ((RHSC >= 0 && RHSC < 256) ||
478193323Sed          (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed.
479193323Sed        Base = N.getOperand(0);
480193323Sed        if (Base.getOpcode() == ISD::FrameIndex) {
481193323Sed          int FI = cast<FrameIndexSDNode>(Base)->getIndex();
482193323Sed          Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
483193323Sed        }
484193323Sed
485193323Sed        ARM_AM::AddrOpc AddSub = ARM_AM::add;
486193323Sed        if (RHSC < 0) {
487193323Sed          AddSub = ARM_AM::sub;
488193323Sed          RHSC = - RHSC;
489193323Sed        }
490193323Sed        Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
491193323Sed                                           MVT::i32);
492193323Sed        return true;
493193323Sed      }
494193323Sed    }
495193323Sed  }
496198090Srdivacky
497193323Sed  Base = N;
498193323Sed  Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
499193323Sed                                     MVT::i32);
500193323Sed  return true;
501193323Sed}
502193323Sed
503202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Op, SDValue N,
504205407Srdivacky                                      SDValue &Addr, SDValue &Align) {
505195340Sed  Addr = N;
506199481Srdivacky  // Default to no alignment.
507199481Srdivacky  Align = CurDAG->getTargetConstant(0, MVT::i32);
508195340Sed  return true;
509195340Sed}
510195340Sed
511202375Srdivackybool ARMDAGToDAGISel::SelectAddrModePC(SDNode *Op, SDValue N,
512198090Srdivacky                                       SDValue &Offset, SDValue &Label) {
513193323Sed  if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
514193323Sed    Offset = N.getOperand(0);
515193323Sed    SDValue N1 = N.getOperand(1);
516193323Sed    Label  = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
517193323Sed                                       MVT::i32);
518193323Sed    return true;
519193323Sed  }
520193323Sed  return false;
521193323Sed}
522193323Sed
523202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDNode *Op, SDValue N,
524193323Sed                                            SDValue &Base, SDValue &Offset){
525193323Sed  // FIXME dl should come from the parent load or store, not the address
526202375Srdivacky  DebugLoc dl = Op->getDebugLoc();
527193323Sed  if (N.getOpcode() != ISD::ADD) {
528198090Srdivacky    ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
529198090Srdivacky    if (!NC || NC->getZExtValue() != 0)
530198090Srdivacky      return false;
531198090Srdivacky
532198090Srdivacky    Base = Offset = N;
533193323Sed    return true;
534193323Sed  }
535193323Sed
536193323Sed  Base = N.getOperand(0);
537193323Sed  Offset = N.getOperand(1);
538193323Sed  return true;
539193323Sed}
540193323Sed
541193323Sedbool
542202375SrdivackyARMDAGToDAGISel::SelectThumbAddrModeRI5(SDNode *Op, SDValue N,
543193323Sed                                        unsigned Scale, SDValue &Base,
544193323Sed                                        SDValue &OffImm, SDValue &Offset) {
545193323Sed  if (Scale == 4) {
546193323Sed    SDValue TmpBase, TmpOffImm;
547193323Sed    if (SelectThumbAddrModeSP(Op, N, TmpBase, TmpOffImm))
548193323Sed      return false;  // We want to select tLDRspi / tSTRspi instead.
549193323Sed    if (N.getOpcode() == ARMISD::Wrapper &&
550193323Sed        N.getOperand(0).getOpcode() == ISD::TargetConstantPool)
551193323Sed      return false;  // We want to select tLDRpci instead.
552193323Sed  }
553193323Sed
554193323Sed  if (N.getOpcode() != ISD::ADD) {
555199989Srdivacky    if (N.getOpcode() == ARMISD::Wrapper &&
556199989Srdivacky        !(Subtarget->useMovt() &&
557199989Srdivacky          N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
558199989Srdivacky      Base = N.getOperand(0);
559199989Srdivacky    } else
560199989Srdivacky      Base = N;
561199989Srdivacky
562193323Sed    Offset = CurDAG->getRegister(0, MVT::i32);
563193323Sed    OffImm = CurDAG->getTargetConstant(0, MVT::i32);
564193323Sed    return true;
565193323Sed  }
566193323Sed
567193323Sed  // Thumb does not have [sp, r] address mode.
568193323Sed  RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
569193323Sed  RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1));
570193323Sed  if ((LHSR && LHSR->getReg() == ARM::SP) ||
571193323Sed      (RHSR && RHSR->getReg() == ARM::SP)) {
572193323Sed    Base = N;
573193323Sed    Offset = CurDAG->getRegister(0, MVT::i32);
574193323Sed    OffImm = CurDAG->getTargetConstant(0, MVT::i32);
575193323Sed    return true;
576193323Sed  }
577193323Sed
578193323Sed  // If the RHS is + imm5 * scale, fold into addr mode.
579193323Sed  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
580193323Sed    int RHSC = (int)RHS->getZExtValue();
581193323Sed    if ((RHSC & (Scale-1)) == 0) {  // The constant is implicitly multiplied.
582193323Sed      RHSC /= Scale;
583193323Sed      if (RHSC >= 0 && RHSC < 32) {
584193323Sed        Base = N.getOperand(0);
585193323Sed        Offset = CurDAG->getRegister(0, MVT::i32);
586193323Sed        OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
587193323Sed        return true;
588193323Sed      }
589193323Sed    }
590193323Sed  }
591193323Sed
592193323Sed  Base = N.getOperand(0);
593193323Sed  Offset = N.getOperand(1);
594193323Sed  OffImm = CurDAG->getTargetConstant(0, MVT::i32);
595193323Sed  return true;
596193323Sed}
597193323Sed
598202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeS1(SDNode *Op, SDValue N,
599193323Sed                                            SDValue &Base, SDValue &OffImm,
600193323Sed                                            SDValue &Offset) {
601193323Sed  return SelectThumbAddrModeRI5(Op, N, 1, Base, OffImm, Offset);
602193323Sed}
603193323Sed
604202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeS2(SDNode *Op, SDValue N,
605193323Sed                                            SDValue &Base, SDValue &OffImm,
606193323Sed                                            SDValue &Offset) {
607193323Sed  return SelectThumbAddrModeRI5(Op, N, 2, Base, OffImm, Offset);
608193323Sed}
609193323Sed
610202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeS4(SDNode *Op, SDValue N,
611193323Sed                                            SDValue &Base, SDValue &OffImm,
612193323Sed                                            SDValue &Offset) {
613193323Sed  return SelectThumbAddrModeRI5(Op, N, 4, Base, OffImm, Offset);
614193323Sed}
615193323Sed
616202375Srdivackybool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDNode *Op, SDValue N,
617193323Sed                                           SDValue &Base, SDValue &OffImm) {
618193323Sed  if (N.getOpcode() == ISD::FrameIndex) {
619193323Sed    int FI = cast<FrameIndexSDNode>(N)->getIndex();
620193323Sed    Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
621193323Sed    OffImm = CurDAG->getTargetConstant(0, MVT::i32);
622193323Sed    return true;
623193323Sed  }
624193323Sed
625193323Sed  if (N.getOpcode() != ISD::ADD)
626193323Sed    return false;
627193323Sed
628193323Sed  RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
629193323Sed  if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
630193323Sed      (LHSR && LHSR->getReg() == ARM::SP)) {
631193323Sed    // If the RHS is + imm8 * scale, fold into addr mode.
632193323Sed    if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
633193323Sed      int RHSC = (int)RHS->getZExtValue();
634193323Sed      if ((RHSC & 3) == 0) {  // The constant is implicitly multiplied.
635193323Sed        RHSC >>= 2;
636193323Sed        if (RHSC >= 0 && RHSC < 256) {
637193323Sed          Base = N.getOperand(0);
638193323Sed          if (Base.getOpcode() == ISD::FrameIndex) {
639193323Sed            int FI = cast<FrameIndexSDNode>(Base)->getIndex();
640193323Sed            Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
641193323Sed          }
642193323Sed          OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
643193323Sed          return true;
644193323Sed        }
645193323Sed      }
646193323Sed    }
647193323Sed  }
648198090Srdivacky
649193323Sed  return false;
650193323Sed}
651193323Sed
652202375Srdivackybool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDNode *Op, SDValue N,
653195098Sed                                                SDValue &BaseReg,
654195098Sed                                                SDValue &Opc) {
655195098Sed  ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N);
656195098Sed
657195098Sed  // Don't match base register only case. That is matched to a separate
658195098Sed  // lower complexity pattern with explicit register operand.
659195098Sed  if (ShOpcVal == ARM_AM::no_shift) return false;
660195098Sed
661195098Sed  BaseReg = N.getOperand(0);
662195098Sed  unsigned ShImmVal = 0;
663195098Sed  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
664195098Sed    ShImmVal = RHS->getZExtValue() & 31;
665195098Sed    Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal));
666195098Sed    return true;
667195098Sed  }
668195098Sed
669195098Sed  return false;
670195098Sed}
671195098Sed
672202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDNode *Op, SDValue N,
673195340Sed                                            SDValue &Base, SDValue &OffImm) {
674195340Sed  // Match simple R + imm12 operands.
675195340Sed
676198090Srdivacky  // Base only.
677198090Srdivacky  if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) {
678198090Srdivacky    if (N.getOpcode() == ISD::FrameIndex) {
679198090Srdivacky      // Match frame index...
680198090Srdivacky      int FI = cast<FrameIndexSDNode>(N)->getIndex();
681198090Srdivacky      Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
682198090Srdivacky      OffImm  = CurDAG->getTargetConstant(0, MVT::i32);
683198090Srdivacky      return true;
684199989Srdivacky    } else if (N.getOpcode() == ARMISD::Wrapper &&
685199989Srdivacky               !(Subtarget->useMovt() &&
686199989Srdivacky                 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
687198090Srdivacky      Base = N.getOperand(0);
688198090Srdivacky      if (Base.getOpcode() == ISD::TargetConstantPool)
689198090Srdivacky        return false;  // We want to select t2LDRpci instead.
690198090Srdivacky    } else
691198090Srdivacky      Base = N;
692198090Srdivacky    OffImm  = CurDAG->getTargetConstant(0, MVT::i32);
693198090Srdivacky    return true;
694198090Srdivacky  }
695198090Srdivacky
696195340Sed  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
697198090Srdivacky    if (SelectT2AddrModeImm8(Op, N, Base, OffImm))
698198090Srdivacky      // Let t2LDRi8 handle (R - imm8).
699198090Srdivacky      return false;
700198090Srdivacky
701195340Sed    int RHSC = (int)RHS->getZExtValue();
702198090Srdivacky    if (N.getOpcode() == ISD::SUB)
703198090Srdivacky      RHSC = -RHSC;
704198090Srdivacky
705198090Srdivacky    if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
706195340Sed      Base   = N.getOperand(0);
707198090Srdivacky      if (Base.getOpcode() == ISD::FrameIndex) {
708198090Srdivacky        int FI = cast<FrameIndexSDNode>(Base)->getIndex();
709198090Srdivacky        Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
710198090Srdivacky      }
711195340Sed      OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
712195340Sed      return true;
713195340Sed    }
714195340Sed  }
715195340Sed
716198090Srdivacky  // Base only.
717198090Srdivacky  Base = N;
718198090Srdivacky  OffImm  = CurDAG->getTargetConstant(0, MVT::i32);
719198090Srdivacky  return true;
720195340Sed}
721195340Sed
722202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDNode *Op, SDValue N,
723195340Sed                                           SDValue &Base, SDValue &OffImm) {
724198090Srdivacky  // Match simple R - imm8 operands.
725198090Srdivacky  if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::SUB) {
726195340Sed    if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
727198090Srdivacky      int RHSC = (int)RHS->getSExtValue();
728198090Srdivacky      if (N.getOpcode() == ISD::SUB)
729198090Srdivacky        RHSC = -RHSC;
730198090Srdivacky
731198090Srdivacky      if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
732198090Srdivacky        Base = N.getOperand(0);
733198090Srdivacky        if (Base.getOpcode() == ISD::FrameIndex) {
734198090Srdivacky          int FI = cast<FrameIndexSDNode>(Base)->getIndex();
735198090Srdivacky          Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
736198090Srdivacky        }
737195340Sed        OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
738195340Sed        return true;
739195340Sed      }
740195340Sed    }
741195340Sed  }
742195340Sed
743195340Sed  return false;
744195340Sed}
745195340Sed
746202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
747195340Sed                                                 SDValue &OffImm){
748202375Srdivacky  unsigned Opcode = Op->getOpcode();
749195340Sed  ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
750195340Sed    ? cast<LoadSDNode>(Op)->getAddressingMode()
751195340Sed    : cast<StoreSDNode>(Op)->getAddressingMode();
752195340Sed  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N)) {
753195340Sed    int RHSC = (int)RHS->getZExtValue();
754195340Sed    if (RHSC >= 0 && RHSC < 0x100) { // 8 bits.
755198090Srdivacky      OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC))
756195340Sed        ? CurDAG->getTargetConstant(RHSC, MVT::i32)
757195340Sed        : CurDAG->getTargetConstant(-RHSC, MVT::i32);
758195340Sed      return true;
759195340Sed    }
760195340Sed  }
761195340Sed
762195340Sed  return false;
763195340Sed}
764195340Sed
765202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm8s4(SDNode *Op, SDValue N,
766195340Sed                                             SDValue &Base, SDValue &OffImm) {
767195340Sed  if (N.getOpcode() == ISD::ADD) {
768195340Sed    if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
769195340Sed      int RHSC = (int)RHS->getZExtValue();
770198090Srdivacky      if (((RHSC & 0x3) == 0) &&
771198090Srdivacky          ((RHSC >= 0 && RHSC < 0x400) || (RHSC < 0 && RHSC > -0x400))) { // 8 bits.
772195340Sed        Base   = N.getOperand(0);
773195340Sed        OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
774195340Sed        return true;
775195340Sed      }
776195340Sed    }
777195340Sed  } else if (N.getOpcode() == ISD::SUB) {
778195340Sed    if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
779195340Sed      int RHSC = (int)RHS->getZExtValue();
780195340Sed      if (((RHSC & 0x3) == 0) && (RHSC >= 0 && RHSC < 0x400)) { // 8 bits.
781195340Sed        Base   = N.getOperand(0);
782195340Sed        OffImm = CurDAG->getTargetConstant(-RHSC, MVT::i32);
783195340Sed        return true;
784195340Sed      }
785195340Sed    }
786195340Sed  }
787195340Sed
788195340Sed  return false;
789195340Sed}
790195340Sed
791202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDNode *Op, SDValue N,
792195340Sed                                            SDValue &Base,
793195340Sed                                            SDValue &OffReg, SDValue &ShImm) {
794198090Srdivacky  // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
795198090Srdivacky  if (N.getOpcode() != ISD::ADD)
796198090Srdivacky    return false;
797198090Srdivacky
798198090Srdivacky  // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
799198090Srdivacky  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
800198090Srdivacky    int RHSC = (int)RHS->getZExtValue();
801198090Srdivacky    if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
802198090Srdivacky      return false;
803198090Srdivacky    else if (RHSC < 0 && RHSC >= -255) // 8 bits
804198090Srdivacky      return false;
805195340Sed  }
806195340Sed
807195340Sed  // Look for (R + R) or (R + (R << [1,2,3])).
808195340Sed  unsigned ShAmt = 0;
809195340Sed  Base   = N.getOperand(0);
810195340Sed  OffReg = N.getOperand(1);
811195340Sed
812195340Sed  // Swap if it is ((R << c) + R).
813195340Sed  ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg);
814195340Sed  if (ShOpcVal != ARM_AM::lsl) {
815195340Sed    ShOpcVal = ARM_AM::getShiftOpcForNode(Base);
816195340Sed    if (ShOpcVal == ARM_AM::lsl)
817195340Sed      std::swap(Base, OffReg);
818198090Srdivacky  }
819198090Srdivacky
820195340Sed  if (ShOpcVal == ARM_AM::lsl) {
821195340Sed    // Check to see if the RHS of the shift is a constant, if not, we can't fold
822195340Sed    // it.
823195340Sed    if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
824195340Sed      ShAmt = Sh->getZExtValue();
825195340Sed      if (ShAmt >= 4) {
826195340Sed        ShAmt = 0;
827195340Sed        ShOpcVal = ARM_AM::no_shift;
828195340Sed      } else
829195340Sed        OffReg = OffReg.getOperand(0);
830195340Sed    } else {
831195340Sed      ShOpcVal = ARM_AM::no_shift;
832195340Sed    }
833198090Srdivacky  }
834198090Srdivacky
835195340Sed  ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32);
836195340Sed
837195340Sed  return true;
838195340Sed}
839195340Sed
840195340Sed//===--------------------------------------------------------------------===//
841195340Sed
842193323Sed/// getAL - Returns a ARMCC::AL immediate node.
843193323Sedstatic inline SDValue getAL(SelectionDAG *CurDAG) {
844193323Sed  return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32);
845193323Sed}
846193323Sed
847202375SrdivackySDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) {
848202375Srdivacky  LoadSDNode *LD = cast<LoadSDNode>(N);
849195340Sed  ISD::MemIndexedMode AM = LD->getAddressingMode();
850195340Sed  if (AM == ISD::UNINDEXED)
851195340Sed    return NULL;
852193323Sed
853198090Srdivacky  EVT LoadedVT = LD->getMemoryVT();
854195340Sed  SDValue Offset, AMOpc;
855195340Sed  bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
856195340Sed  unsigned Opcode = 0;
857195340Sed  bool Match = false;
858195340Sed  if (LoadedVT == MVT::i32 &&
859202375Srdivacky      SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) {
860195340Sed    Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST;
861195340Sed    Match = true;
862195340Sed  } else if (LoadedVT == MVT::i16 &&
863202375Srdivacky             SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
864195340Sed    Match = true;
865195340Sed    Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
866195340Sed      ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
867195340Sed      : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
868195340Sed  } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
869195340Sed    if (LD->getExtensionType() == ISD::SEXTLOAD) {
870202375Srdivacky      if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
871195340Sed        Match = true;
872195340Sed        Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
873195340Sed      }
874195340Sed    } else {
875202375Srdivacky      if (SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) {
876195340Sed        Match = true;
877195340Sed        Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST;
878195340Sed      }
879195340Sed    }
880195340Sed  }
881195340Sed
882195340Sed  if (Match) {
883195340Sed    SDValue Chain = LD->getChain();
884195340Sed    SDValue Base = LD->getBasePtr();
885195340Sed    SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG),
886195340Sed                     CurDAG->getRegister(0, MVT::i32), Chain };
887202375Srdivacky    return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, MVT::i32,
888198090Srdivacky                                  MVT::Other, Ops, 6);
889195340Sed  }
890195340Sed
891195340Sed  return NULL;
892195340Sed}
893195340Sed
894202375SrdivackySDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) {
895202375Srdivacky  LoadSDNode *LD = cast<LoadSDNode>(N);
896195340Sed  ISD::MemIndexedMode AM = LD->getAddressingMode();
897195340Sed  if (AM == ISD::UNINDEXED)
898195340Sed    return NULL;
899195340Sed
900198090Srdivacky  EVT LoadedVT = LD->getMemoryVT();
901195340Sed  bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD;
902195340Sed  SDValue Offset;
903195340Sed  bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
904195340Sed  unsigned Opcode = 0;
905195340Sed  bool Match = false;
906202375Srdivacky  if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) {
907198090Srdivacky    switch (LoadedVT.getSimpleVT().SimpleTy) {
908195340Sed    case MVT::i32:
909195340Sed      Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
910195340Sed      break;
911195340Sed    case MVT::i16:
912195340Sed      if (isSExtLd)
913195340Sed        Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
914195340Sed      else
915195340Sed        Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
916195340Sed      break;
917195340Sed    case MVT::i8:
918195340Sed    case MVT::i1:
919195340Sed      if (isSExtLd)
920195340Sed        Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
921195340Sed      else
922195340Sed        Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
923195340Sed      break;
924195340Sed    default:
925195340Sed      return NULL;
926195340Sed    }
927195340Sed    Match = true;
928195340Sed  }
929195340Sed
930195340Sed  if (Match) {
931195340Sed    SDValue Chain = LD->getChain();
932195340Sed    SDValue Base = LD->getBasePtr();
933195340Sed    SDValue Ops[]= { Base, Offset, getAL(CurDAG),
934195340Sed                     CurDAG->getRegister(0, MVT::i32), Chain };
935202375Srdivacky    return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, MVT::i32,
936198090Srdivacky                                  MVT::Other, Ops, 5);
937195340Sed  }
938195340Sed
939195340Sed  return NULL;
940195340Sed}
941195340Sed
942202375SrdivackySDNode *ARMDAGToDAGISel::SelectDYN_ALLOC(SDNode *N) {
943198090Srdivacky  DebugLoc dl = N->getDebugLoc();
944202375Srdivacky  EVT VT = N->getValueType(0);
945202375Srdivacky  SDValue Chain = N->getOperand(0);
946202375Srdivacky  SDValue Size = N->getOperand(1);
947202375Srdivacky  SDValue Align = N->getOperand(2);
948198090Srdivacky  SDValue SP = CurDAG->getRegister(ARM::SP, MVT::i32);
949198090Srdivacky  int32_t AlignVal = cast<ConstantSDNode>(Align)->getSExtValue();
950198090Srdivacky  if (AlignVal < 0)
951198090Srdivacky    // We need to align the stack. Use Thumb1 tAND which is the only thumb
952198090Srdivacky    // instruction that can read and write SP. This matches to a pseudo
953198090Srdivacky    // instruction that has a chain to ensure the result is written back to
954198090Srdivacky    // the stack pointer.
955198090Srdivacky    SP = SDValue(CurDAG->getMachineNode(ARM::tANDsp, dl, VT, SP, Align), 0);
956195340Sed
957198090Srdivacky  bool isC = isa<ConstantSDNode>(Size);
958198090Srdivacky  uint32_t C = isC ? cast<ConstantSDNode>(Size)->getZExtValue() : ~0UL;
959198090Srdivacky  // Handle the most common case for both Thumb1 and Thumb2:
960198090Srdivacky  // tSUBspi - immediate is between 0 ... 508 inclusive.
961198090Srdivacky  if (C <= 508 && ((C & 3) == 0))
962198090Srdivacky    // FIXME: tSUBspi encode scale 4 implicitly.
963198090Srdivacky    return CurDAG->SelectNodeTo(N, ARM::tSUBspi_, VT, MVT::Other, SP,
964198090Srdivacky                                CurDAG->getTargetConstant(C/4, MVT::i32),
965198090Srdivacky                                Chain);
966198090Srdivacky
967198090Srdivacky  if (Subtarget->isThumb1Only()) {
968198090Srdivacky    // Use tADDspr since Thumb1 does not have a sub r, sp, r. ARMISelLowering
969198090Srdivacky    // should have negated the size operand already. FIXME: We can't insert
970198090Srdivacky    // new target independent node at this stage so we are forced to negate
971198090Srdivacky    // it earlier. Is there a better solution?
972198090Srdivacky    return CurDAG->SelectNodeTo(N, ARM::tADDspr_, VT, MVT::Other, SP, Size,
973198090Srdivacky                                Chain);
974198090Srdivacky  } else if (Subtarget->isThumb2()) {
975198090Srdivacky    if (isC && Predicate_t2_so_imm(Size.getNode())) {
976198090Srdivacky      // t2SUBrSPi
977198090Srdivacky      SDValue Ops[] = { SP, CurDAG->getTargetConstant(C, MVT::i32), Chain };
978198090Srdivacky      return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPi_, VT, MVT::Other, Ops, 3);
979198090Srdivacky    } else if (isC && Predicate_imm0_4095(Size.getNode())) {
980198090Srdivacky      // t2SUBrSPi12
981198090Srdivacky      SDValue Ops[] = { SP, CurDAG->getTargetConstant(C, MVT::i32), Chain };
982198090Srdivacky      return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPi12_, VT, MVT::Other, Ops, 3);
983198090Srdivacky    } else {
984198090Srdivacky      // t2SUBrSPs
985198090Srdivacky      SDValue Ops[] = { SP, Size,
986198090Srdivacky                        getI32Imm(ARM_AM::getSORegOpc(ARM_AM::lsl,0)), Chain };
987198090Srdivacky      return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPs_, VT, MVT::Other, Ops, 4);
988198090Srdivacky    }
989198090Srdivacky  }
990198090Srdivacky
991198090Srdivacky  // FIXME: Add ADD / SUB sp instructions for ARM.
992198090Srdivacky  return 0;
993198090Srdivacky}
994198090Srdivacky
995198090Srdivacky/// PairDRegs - Insert a pair of double registers into an implicit def to
996198090Srdivacky/// form a quad register.
997198090SrdivackySDNode *ARMDAGToDAGISel::PairDRegs(EVT VT, SDValue V0, SDValue V1) {
998198090Srdivacky  DebugLoc dl = V0.getNode()->getDebugLoc();
999198090Srdivacky  SDValue Undef =
1000203954Srdivacky    SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0);
1001198090Srdivacky  SDValue SubReg0 = CurDAG->getTargetConstant(ARM::DSUBREG_0, MVT::i32);
1002198090Srdivacky  SDValue SubReg1 = CurDAG->getTargetConstant(ARM::DSUBREG_1, MVT::i32);
1003203954Srdivacky  SDNode *Pair = CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, dl,
1004198090Srdivacky                                        VT, Undef, V0, SubReg0);
1005203954Srdivacky  return CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, dl,
1006198090Srdivacky                                VT, SDValue(Pair, 0), V1, SubReg1);
1007198090Srdivacky}
1008198090Srdivacky
1009198090Srdivacky/// GetNEONSubregVT - Given a type for a 128-bit NEON vector, return the type
1010198090Srdivacky/// for a 64-bit subregister of the vector.
1011198090Srdivackystatic EVT GetNEONSubregVT(EVT VT) {
1012198090Srdivacky  switch (VT.getSimpleVT().SimpleTy) {
1013198090Srdivacky  default: llvm_unreachable("unhandled NEON type");
1014198090Srdivacky  case MVT::v16i8: return MVT::v8i8;
1015198090Srdivacky  case MVT::v8i16: return MVT::v4i16;
1016198090Srdivacky  case MVT::v4f32: return MVT::v2f32;
1017198090Srdivacky  case MVT::v4i32: return MVT::v2i32;
1018198090Srdivacky  case MVT::v2i64: return MVT::v1i64;
1019198090Srdivacky  }
1020198090Srdivacky}
1021198090Srdivacky
1022202375SrdivackySDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, unsigned NumVecs,
1023198090Srdivacky                                   unsigned *DOpcodes, unsigned *QOpcodes0,
1024198090Srdivacky                                   unsigned *QOpcodes1) {
1025198090Srdivacky  assert(NumVecs >=2 && NumVecs <= 4 && "VLD NumVecs out-of-range");
1026198090Srdivacky  DebugLoc dl = N->getDebugLoc();
1027198090Srdivacky
1028205407Srdivacky  SDValue MemAddr, Align;
1029205407Srdivacky  if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, Align))
1030198090Srdivacky    return NULL;
1031198090Srdivacky
1032198090Srdivacky  SDValue Chain = N->getOperand(0);
1033198090Srdivacky  EVT VT = N->getValueType(0);
1034198090Srdivacky  bool is64BitVector = VT.is64BitVector();
1035198090Srdivacky
1036198090Srdivacky  unsigned OpcodeIndex;
1037198090Srdivacky  switch (VT.getSimpleVT().SimpleTy) {
1038198090Srdivacky  default: llvm_unreachable("unhandled vld type");
1039198090Srdivacky    // Double-register operations:
1040198090Srdivacky  case MVT::v8i8:  OpcodeIndex = 0; break;
1041198090Srdivacky  case MVT::v4i16: OpcodeIndex = 1; break;
1042198090Srdivacky  case MVT::v2f32:
1043198090Srdivacky  case MVT::v2i32: OpcodeIndex = 2; break;
1044198090Srdivacky  case MVT::v1i64: OpcodeIndex = 3; break;
1045198090Srdivacky    // Quad-register operations:
1046198090Srdivacky  case MVT::v16i8: OpcodeIndex = 0; break;
1047198090Srdivacky  case MVT::v8i16: OpcodeIndex = 1; break;
1048198090Srdivacky  case MVT::v4f32:
1049198090Srdivacky  case MVT::v4i32: OpcodeIndex = 2; break;
1050198090Srdivacky  }
1051198090Srdivacky
1052199989Srdivacky  SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32);
1053205407Srdivacky  SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
1054198090Srdivacky  if (is64BitVector) {
1055198090Srdivacky    unsigned Opc = DOpcodes[OpcodeIndex];
1056205407Srdivacky    const SDValue Ops[] = { MemAddr, Align, Pred, Reg0, Chain };
1057198090Srdivacky    std::vector<EVT> ResTys(NumVecs, VT);
1058198090Srdivacky    ResTys.push_back(MVT::Other);
1059205407Srdivacky    return CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 5);
1060198090Srdivacky  }
1061198090Srdivacky
1062198090Srdivacky  EVT RegVT = GetNEONSubregVT(VT);
1063198090Srdivacky  if (NumVecs == 2) {
1064198090Srdivacky    // Quad registers are directly supported for VLD2,
1065198090Srdivacky    // loading 2 pairs of D regs.
1066198090Srdivacky    unsigned Opc = QOpcodes0[OpcodeIndex];
1067205407Srdivacky    const SDValue Ops[] = { MemAddr, Align, Pred, Reg0, Chain };
1068198090Srdivacky    std::vector<EVT> ResTys(4, VT);
1069198090Srdivacky    ResTys.push_back(MVT::Other);
1070205407Srdivacky    SDNode *VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 5);
1071198090Srdivacky    Chain = SDValue(VLd, 4);
1072198090Srdivacky
1073198090Srdivacky    // Combine the even and odd subregs to produce the result.
1074198090Srdivacky    for (unsigned Vec = 0; Vec < NumVecs; ++Vec) {
1075198090Srdivacky      SDNode *Q = PairDRegs(VT, SDValue(VLd, 2*Vec), SDValue(VLd, 2*Vec+1));
1076198090Srdivacky      ReplaceUses(SDValue(N, Vec), SDValue(Q, 0));
1077198090Srdivacky    }
1078198090Srdivacky  } else {
1079198090Srdivacky    // Otherwise, quad registers are loaded with two separate instructions,
1080198090Srdivacky    // where one loads the even registers and the other loads the odd registers.
1081198090Srdivacky
1082198090Srdivacky    std::vector<EVT> ResTys(NumVecs, RegVT);
1083198090Srdivacky    ResTys.push_back(MemAddr.getValueType());
1084198090Srdivacky    ResTys.push_back(MVT::Other);
1085198090Srdivacky
1086198113Srdivacky    // Load the even subregs.
1087198090Srdivacky    unsigned Opc = QOpcodes0[OpcodeIndex];
1088205407Srdivacky    const SDValue OpsA[] = { MemAddr, Align, Reg0, Pred, Reg0, Chain };
1089205407Srdivacky    SDNode *VLdA = CurDAG->getMachineNode(Opc, dl, ResTys, OpsA, 6);
1090198090Srdivacky    Chain = SDValue(VLdA, NumVecs+1);
1091198090Srdivacky
1092198113Srdivacky    // Load the odd subregs.
1093198090Srdivacky    Opc = QOpcodes1[OpcodeIndex];
1094205407Srdivacky    const SDValue OpsB[] = { SDValue(VLdA, NumVecs),
1095205407Srdivacky                             Align, Reg0, Pred, Reg0, Chain };
1096205407Srdivacky    SDNode *VLdB = CurDAG->getMachineNode(Opc, dl, ResTys, OpsB, 6);
1097198090Srdivacky    Chain = SDValue(VLdB, NumVecs+1);
1098198090Srdivacky
1099198090Srdivacky    // Combine the even and odd subregs to produce the result.
1100198090Srdivacky    for (unsigned Vec = 0; Vec < NumVecs; ++Vec) {
1101198090Srdivacky      SDNode *Q = PairDRegs(VT, SDValue(VLdA, Vec), SDValue(VLdB, Vec));
1102198090Srdivacky      ReplaceUses(SDValue(N, Vec), SDValue(Q, 0));
1103198090Srdivacky    }
1104198090Srdivacky  }
1105198090Srdivacky  ReplaceUses(SDValue(N, NumVecs), Chain);
1106198090Srdivacky  return NULL;
1107198090Srdivacky}
1108198090Srdivacky
1109202375SrdivackySDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, unsigned NumVecs,
1110198113Srdivacky                                   unsigned *DOpcodes, unsigned *QOpcodes0,
1111198113Srdivacky                                   unsigned *QOpcodes1) {
1112198113Srdivacky  assert(NumVecs >=2 && NumVecs <= 4 && "VST NumVecs out-of-range");
1113198113Srdivacky  DebugLoc dl = N->getDebugLoc();
1114198113Srdivacky
1115205407Srdivacky  SDValue MemAddr, Align;
1116205407Srdivacky  if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, Align))
1117198113Srdivacky    return NULL;
1118198113Srdivacky
1119198113Srdivacky  SDValue Chain = N->getOperand(0);
1120198113Srdivacky  EVT VT = N->getOperand(3).getValueType();
1121198113Srdivacky  bool is64BitVector = VT.is64BitVector();
1122198113Srdivacky
1123198113Srdivacky  unsigned OpcodeIndex;
1124198113Srdivacky  switch (VT.getSimpleVT().SimpleTy) {
1125198113Srdivacky  default: llvm_unreachable("unhandled vst type");
1126198113Srdivacky    // Double-register operations:
1127198113Srdivacky  case MVT::v8i8:  OpcodeIndex = 0; break;
1128198113Srdivacky  case MVT::v4i16: OpcodeIndex = 1; break;
1129198113Srdivacky  case MVT::v2f32:
1130198113Srdivacky  case MVT::v2i32: OpcodeIndex = 2; break;
1131198113Srdivacky  case MVT::v1i64: OpcodeIndex = 3; break;
1132198113Srdivacky    // Quad-register operations:
1133198113Srdivacky  case MVT::v16i8: OpcodeIndex = 0; break;
1134198113Srdivacky  case MVT::v8i16: OpcodeIndex = 1; break;
1135198113Srdivacky  case MVT::v4f32:
1136198113Srdivacky  case MVT::v4i32: OpcodeIndex = 2; break;
1137198113Srdivacky  }
1138198113Srdivacky
1139199989Srdivacky  SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32);
1140205407Srdivacky  SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
1141199989Srdivacky
1142205407Srdivacky  SmallVector<SDValue, 10> Ops;
1143198113Srdivacky  Ops.push_back(MemAddr);
1144199481Srdivacky  Ops.push_back(Align);
1145198113Srdivacky
1146198113Srdivacky  if (is64BitVector) {
1147198113Srdivacky    unsigned Opc = DOpcodes[OpcodeIndex];
1148198113Srdivacky    for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1149198113Srdivacky      Ops.push_back(N->getOperand(Vec+3));
1150199989Srdivacky    Ops.push_back(Pred);
1151205407Srdivacky    Ops.push_back(Reg0); // predicate register
1152198113Srdivacky    Ops.push_back(Chain);
1153205407Srdivacky    return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+5);
1154198113Srdivacky  }
1155198113Srdivacky
1156198113Srdivacky  EVT RegVT = GetNEONSubregVT(VT);
1157198113Srdivacky  if (NumVecs == 2) {
1158198113Srdivacky    // Quad registers are directly supported for VST2,
1159198113Srdivacky    // storing 2 pairs of D regs.
1160198113Srdivacky    unsigned Opc = QOpcodes0[OpcodeIndex];
1161198113Srdivacky    for (unsigned Vec = 0; Vec < NumVecs; ++Vec) {
1162198113Srdivacky      Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT,
1163198113Srdivacky                                                   N->getOperand(Vec+3)));
1164198113Srdivacky      Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT,
1165198113Srdivacky                                                   N->getOperand(Vec+3)));
1166198113Srdivacky    }
1167199989Srdivacky    Ops.push_back(Pred);
1168205407Srdivacky    Ops.push_back(Reg0); // predicate register
1169198113Srdivacky    Ops.push_back(Chain);
1170205407Srdivacky    return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), 9);
1171198113Srdivacky  }
1172198113Srdivacky
1173198113Srdivacky  // Otherwise, quad registers are stored with two separate instructions,
1174198113Srdivacky  // where one stores the even registers and the other stores the odd registers.
1175198113Srdivacky
1176205407Srdivacky  Ops.push_back(Reg0); // post-access address offset
1177198113Srdivacky
1178198113Srdivacky  // Store the even subregs.
1179198113Srdivacky  for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1180198113Srdivacky    Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT,
1181198113Srdivacky                                                 N->getOperand(Vec+3)));
1182199989Srdivacky  Ops.push_back(Pred);
1183205407Srdivacky  Ops.push_back(Reg0); // predicate register
1184198113Srdivacky  Ops.push_back(Chain);
1185198113Srdivacky  unsigned Opc = QOpcodes0[OpcodeIndex];
1186198113Srdivacky  SDNode *VStA = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(),
1187205407Srdivacky                                        MVT::Other, Ops.data(), NumVecs+6);
1188198113Srdivacky  Chain = SDValue(VStA, 1);
1189198113Srdivacky
1190198113Srdivacky  // Store the odd subregs.
1191198113Srdivacky  Ops[0] = SDValue(VStA, 0); // MemAddr
1192198113Srdivacky  for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1193205407Srdivacky    Ops[Vec+3] = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT,
1194198113Srdivacky                                                N->getOperand(Vec+3));
1195205407Srdivacky  Ops[NumVecs+5] = Chain;
1196198113Srdivacky  Opc = QOpcodes1[OpcodeIndex];
1197198113Srdivacky  SDNode *VStB = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(),
1198205407Srdivacky                                        MVT::Other, Ops.data(), NumVecs+6);
1199198113Srdivacky  Chain = SDValue(VStB, 1);
1200198113Srdivacky  ReplaceUses(SDValue(N, 0), Chain);
1201198113Srdivacky  return NULL;
1202198113Srdivacky}
1203198113Srdivacky
1204202375SrdivackySDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad,
1205198090Srdivacky                                         unsigned NumVecs, unsigned *DOpcodes,
1206198090Srdivacky                                         unsigned *QOpcodes0,
1207198090Srdivacky                                         unsigned *QOpcodes1) {
1208198090Srdivacky  assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range");
1209198090Srdivacky  DebugLoc dl = N->getDebugLoc();
1210198090Srdivacky
1211205407Srdivacky  SDValue MemAddr, Align;
1212205407Srdivacky  if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, Align))
1213198090Srdivacky    return NULL;
1214198090Srdivacky
1215198090Srdivacky  SDValue Chain = N->getOperand(0);
1216198090Srdivacky  unsigned Lane =
1217198090Srdivacky    cast<ConstantSDNode>(N->getOperand(NumVecs+3))->getZExtValue();
1218198090Srdivacky  EVT VT = IsLoad ? N->getValueType(0) : N->getOperand(3).getValueType();
1219198090Srdivacky  bool is64BitVector = VT.is64BitVector();
1220198090Srdivacky
1221198090Srdivacky  // Quad registers are handled by load/store of subregs. Find the subreg info.
1222198090Srdivacky  unsigned NumElts = 0;
1223198090Srdivacky  int SubregIdx = 0;
1224198090Srdivacky  EVT RegVT = VT;
1225198090Srdivacky  if (!is64BitVector) {
1226198090Srdivacky    RegVT = GetNEONSubregVT(VT);
1227198090Srdivacky    NumElts = RegVT.getVectorNumElements();
1228198090Srdivacky    SubregIdx = (Lane < NumElts) ? ARM::DSUBREG_0 : ARM::DSUBREG_1;
1229198090Srdivacky  }
1230198090Srdivacky
1231198090Srdivacky  unsigned OpcodeIndex;
1232198090Srdivacky  switch (VT.getSimpleVT().SimpleTy) {
1233198090Srdivacky  default: llvm_unreachable("unhandled vld/vst lane type");
1234198090Srdivacky    // Double-register operations:
1235198090Srdivacky  case MVT::v8i8:  OpcodeIndex = 0; break;
1236198090Srdivacky  case MVT::v4i16: OpcodeIndex = 1; break;
1237198090Srdivacky  case MVT::v2f32:
1238198090Srdivacky  case MVT::v2i32: OpcodeIndex = 2; break;
1239198090Srdivacky    // Quad-register operations:
1240198090Srdivacky  case MVT::v8i16: OpcodeIndex = 0; break;
1241198090Srdivacky  case MVT::v4f32:
1242198090Srdivacky  case MVT::v4i32: OpcodeIndex = 1; break;
1243198090Srdivacky  }
1244198090Srdivacky
1245199989Srdivacky  SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32);
1246205407Srdivacky  SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
1247199989Srdivacky
1248205407Srdivacky  SmallVector<SDValue, 10> Ops;
1249198090Srdivacky  Ops.push_back(MemAddr);
1250199481Srdivacky  Ops.push_back(Align);
1251198090Srdivacky
1252198090Srdivacky  unsigned Opc = 0;
1253198090Srdivacky  if (is64BitVector) {
1254198090Srdivacky    Opc = DOpcodes[OpcodeIndex];
1255198090Srdivacky    for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1256198090Srdivacky      Ops.push_back(N->getOperand(Vec+3));
1257198090Srdivacky  } else {
1258198090Srdivacky    // Check if this is loading the even or odd subreg of a Q register.
1259198090Srdivacky    if (Lane < NumElts) {
1260198090Srdivacky      Opc = QOpcodes0[OpcodeIndex];
1261198090Srdivacky    } else {
1262198090Srdivacky      Lane -= NumElts;
1263198090Srdivacky      Opc = QOpcodes1[OpcodeIndex];
1264198090Srdivacky    }
1265198090Srdivacky    // Extract the subregs of the input vector.
1266198090Srdivacky    for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1267198090Srdivacky      Ops.push_back(CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT,
1268198090Srdivacky                                                   N->getOperand(Vec+3)));
1269198090Srdivacky  }
1270198090Srdivacky  Ops.push_back(getI32Imm(Lane));
1271199989Srdivacky  Ops.push_back(Pred);
1272205407Srdivacky  Ops.push_back(Reg0);
1273198090Srdivacky  Ops.push_back(Chain);
1274198090Srdivacky
1275198090Srdivacky  if (!IsLoad)
1276205407Srdivacky    return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+6);
1277198090Srdivacky
1278198090Srdivacky  std::vector<EVT> ResTys(NumVecs, RegVT);
1279198090Srdivacky  ResTys.push_back(MVT::Other);
1280198090Srdivacky  SDNode *VLdLn =
1281205407Srdivacky    CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), NumVecs+6);
1282198090Srdivacky  // For a 64-bit vector load to D registers, nothing more needs to be done.
1283198090Srdivacky  if (is64BitVector)
1284198090Srdivacky    return VLdLn;
1285198090Srdivacky
1286198090Srdivacky  // For 128-bit vectors, take the 64-bit results of the load and insert them
1287198090Srdivacky  // as subregs into the result.
1288198090Srdivacky  for (unsigned Vec = 0; Vec < NumVecs; ++Vec) {
1289198090Srdivacky    SDValue QuadVec = CurDAG->getTargetInsertSubreg(SubregIdx, dl, VT,
1290198090Srdivacky                                                    N->getOperand(Vec+3),
1291198090Srdivacky                                                    SDValue(VLdLn, Vec));
1292198090Srdivacky    ReplaceUses(SDValue(N, Vec), QuadVec);
1293198090Srdivacky  }
1294198090Srdivacky
1295198090Srdivacky  Chain = SDValue(VLdLn, NumVecs);
1296198090Srdivacky  ReplaceUses(SDValue(N, NumVecs), Chain);
1297198090Srdivacky  return NULL;
1298198090Srdivacky}
1299198090Srdivacky
1300202375SrdivackySDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N,
1301198090Srdivacky                                                     unsigned Opc) {
1302198090Srdivacky  if (!Subtarget->hasV6T2Ops())
1303198090Srdivacky    return NULL;
1304198090Srdivacky
1305198090Srdivacky  unsigned Shl_imm = 0;
1306202375Srdivacky  if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
1307198090Srdivacky    assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
1308198090Srdivacky    unsigned Srl_imm = 0;
1309202375Srdivacky    if (isInt32Immediate(N->getOperand(1), Srl_imm)) {
1310198090Srdivacky      assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
1311198090Srdivacky      unsigned Width = 32 - Srl_imm;
1312198090Srdivacky      int LSB = Srl_imm - Shl_imm;
1313198396Srdivacky      if (LSB < 0)
1314198090Srdivacky        return NULL;
1315198090Srdivacky      SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
1316202375Srdivacky      SDValue Ops[] = { N->getOperand(0).getOperand(0),
1317198090Srdivacky                        CurDAG->getTargetConstant(LSB, MVT::i32),
1318198090Srdivacky                        CurDAG->getTargetConstant(Width, MVT::i32),
1319198090Srdivacky                        getAL(CurDAG), Reg0 };
1320202375Srdivacky      return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
1321198090Srdivacky    }
1322198090Srdivacky  }
1323198090Srdivacky  return NULL;
1324198090Srdivacky}
1325198090Srdivacky
1326199989SrdivackySDNode *ARMDAGToDAGISel::
1327202375SrdivackySelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
1328199989Srdivacky                    ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
1329199989Srdivacky  SDValue CPTmp0;
1330199989Srdivacky  SDValue CPTmp1;
1331202375Srdivacky  if (SelectT2ShifterOperandReg(N, TrueVal, CPTmp0, CPTmp1)) {
1332199989Srdivacky    unsigned SOVal = cast<ConstantSDNode>(CPTmp1)->getZExtValue();
1333199989Srdivacky    unsigned SOShOp = ARM_AM::getSORegShOp(SOVal);
1334199989Srdivacky    unsigned Opc = 0;
1335199989Srdivacky    switch (SOShOp) {
1336199989Srdivacky    case ARM_AM::lsl: Opc = ARM::t2MOVCClsl; break;
1337199989Srdivacky    case ARM_AM::lsr: Opc = ARM::t2MOVCClsr; break;
1338199989Srdivacky    case ARM_AM::asr: Opc = ARM::t2MOVCCasr; break;
1339199989Srdivacky    case ARM_AM::ror: Opc = ARM::t2MOVCCror; break;
1340199989Srdivacky    default:
1341199989Srdivacky      llvm_unreachable("Unknown so_reg opcode!");
1342199989Srdivacky      break;
1343199989Srdivacky    }
1344199989Srdivacky    SDValue SOShImm =
1345199989Srdivacky      CurDAG->getTargetConstant(ARM_AM::getSORegOffset(SOVal), MVT::i32);
1346199989Srdivacky    SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
1347199989Srdivacky    SDValue Ops[] = { FalseVal, CPTmp0, SOShImm, CC, CCR, InFlag };
1348202375Srdivacky    return CurDAG->SelectNodeTo(N, Opc, MVT::i32,Ops, 6);
1349199989Srdivacky  }
1350199989Srdivacky  return 0;
1351199989Srdivacky}
1352199989Srdivacky
1353199989SrdivackySDNode *ARMDAGToDAGISel::
1354202375SrdivackySelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
1355199989Srdivacky                     ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
1356199989Srdivacky  SDValue CPTmp0;
1357199989Srdivacky  SDValue CPTmp1;
1358199989Srdivacky  SDValue CPTmp2;
1359202375Srdivacky  if (SelectShifterOperandReg(N, TrueVal, CPTmp0, CPTmp1, CPTmp2)) {
1360199989Srdivacky    SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
1361199989Srdivacky    SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, InFlag };
1362202375Srdivacky    return CurDAG->SelectNodeTo(N, ARM::MOVCCs, MVT::i32, Ops, 7);
1363199989Srdivacky  }
1364199989Srdivacky  return 0;
1365199989Srdivacky}
1366199989Srdivacky
1367199989SrdivackySDNode *ARMDAGToDAGISel::
1368202375SrdivackySelectT2CMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
1369199989Srdivacky                    ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
1370199989Srdivacky  ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal);
1371199989Srdivacky  if (!T)
1372199989Srdivacky    return 0;
1373199989Srdivacky
1374199989Srdivacky  if (Predicate_t2_so_imm(TrueVal.getNode())) {
1375199989Srdivacky    SDValue True = CurDAG->getTargetConstant(T->getZExtValue(), MVT::i32);
1376199989Srdivacky    SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
1377199989Srdivacky    SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag };
1378202375Srdivacky    return CurDAG->SelectNodeTo(N,
1379199989Srdivacky                                ARM::t2MOVCCi, MVT::i32, Ops, 5);
1380199989Srdivacky  }
1381199989Srdivacky  return 0;
1382199989Srdivacky}
1383199989Srdivacky
1384199989SrdivackySDNode *ARMDAGToDAGISel::
1385202375SrdivackySelectARMCMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
1386199989Srdivacky                     ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
1387199989Srdivacky  ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal);
1388199989Srdivacky  if (!T)
1389199989Srdivacky    return 0;
1390199989Srdivacky
1391199989Srdivacky  if (Predicate_so_imm(TrueVal.getNode())) {
1392199989Srdivacky    SDValue True = CurDAG->getTargetConstant(T->getZExtValue(), MVT::i32);
1393199989Srdivacky    SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
1394199989Srdivacky    SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag };
1395202375Srdivacky    return CurDAG->SelectNodeTo(N,
1396199989Srdivacky                                ARM::MOVCCi, MVT::i32, Ops, 5);
1397199989Srdivacky  }
1398199989Srdivacky  return 0;
1399199989Srdivacky}
1400199989Srdivacky
1401202375SrdivackySDNode *ARMDAGToDAGISel::SelectCMOVOp(SDNode *N) {
1402202375Srdivacky  EVT VT = N->getValueType(0);
1403202375Srdivacky  SDValue FalseVal = N->getOperand(0);
1404202375Srdivacky  SDValue TrueVal  = N->getOperand(1);
1405202375Srdivacky  SDValue CC = N->getOperand(2);
1406202375Srdivacky  SDValue CCR = N->getOperand(3);
1407202375Srdivacky  SDValue InFlag = N->getOperand(4);
1408199989Srdivacky  assert(CC.getOpcode() == ISD::Constant);
1409199989Srdivacky  assert(CCR.getOpcode() == ISD::Register);
1410199989Srdivacky  ARMCC::CondCodes CCVal =
1411199989Srdivacky    (ARMCC::CondCodes)cast<ConstantSDNode>(CC)->getZExtValue();
1412199989Srdivacky
1413199989Srdivacky  if (!Subtarget->isThumb1Only() && VT == MVT::i32) {
1414199989Srdivacky    // Pattern: (ARMcmov:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc)
1415199989Srdivacky    // Emits: (MOVCCs:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc)
1416199989Srdivacky    // Pattern complexity = 18  cost = 1  size = 0
1417199989Srdivacky    SDValue CPTmp0;
1418199989Srdivacky    SDValue CPTmp1;
1419199989Srdivacky    SDValue CPTmp2;
1420199989Srdivacky    if (Subtarget->isThumb()) {
1421202375Srdivacky      SDNode *Res = SelectT2CMOVShiftOp(N, FalseVal, TrueVal,
1422199989Srdivacky                                        CCVal, CCR, InFlag);
1423199989Srdivacky      if (!Res)
1424202375Srdivacky        Res = SelectT2CMOVShiftOp(N, TrueVal, FalseVal,
1425199989Srdivacky                               ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
1426199989Srdivacky      if (Res)
1427199989Srdivacky        return Res;
1428199989Srdivacky    } else {
1429202375Srdivacky      SDNode *Res = SelectARMCMOVShiftOp(N, FalseVal, TrueVal,
1430199989Srdivacky                                         CCVal, CCR, InFlag);
1431199989Srdivacky      if (!Res)
1432202375Srdivacky        Res = SelectARMCMOVShiftOp(N, TrueVal, FalseVal,
1433199989Srdivacky                               ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
1434199989Srdivacky      if (Res)
1435199989Srdivacky        return Res;
1436199989Srdivacky    }
1437199989Srdivacky
1438199989Srdivacky    // Pattern: (ARMcmov:i32 GPR:i32:$false,
1439199989Srdivacky    //             (imm:i32)<<P:Predicate_so_imm>>:$true,
1440199989Srdivacky    //             (imm:i32):$cc)
1441199989Srdivacky    // Emits: (MOVCCi:i32 GPR:i32:$false,
1442199989Srdivacky    //           (so_imm:i32 (imm:i32):$true), (imm:i32):$cc)
1443199989Srdivacky    // Pattern complexity = 10  cost = 1  size = 0
1444199989Srdivacky    if (Subtarget->isThumb()) {
1445202375Srdivacky      SDNode *Res = SelectT2CMOVSoImmOp(N, FalseVal, TrueVal,
1446199989Srdivacky                                        CCVal, CCR, InFlag);
1447199989Srdivacky      if (!Res)
1448202375Srdivacky        Res = SelectT2CMOVSoImmOp(N, TrueVal, FalseVal,
1449199989Srdivacky                               ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
1450199989Srdivacky      if (Res)
1451199989Srdivacky        return Res;
1452199989Srdivacky    } else {
1453202375Srdivacky      SDNode *Res = SelectARMCMOVSoImmOp(N, FalseVal, TrueVal,
1454199989Srdivacky                                         CCVal, CCR, InFlag);
1455199989Srdivacky      if (!Res)
1456202375Srdivacky        Res = SelectARMCMOVSoImmOp(N, TrueVal, FalseVal,
1457199989Srdivacky                               ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
1458199989Srdivacky      if (Res)
1459199989Srdivacky        return Res;
1460199989Srdivacky    }
1461199989Srdivacky  }
1462199989Srdivacky
1463199989Srdivacky  // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
1464199989Srdivacky  // Emits: (MOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
1465199989Srdivacky  // Pattern complexity = 6  cost = 1  size = 0
1466199989Srdivacky  //
1467199989Srdivacky  // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
1468199989Srdivacky  // Emits: (tMOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
1469199989Srdivacky  // Pattern complexity = 6  cost = 11  size = 0
1470199989Srdivacky  //
1471199989Srdivacky  // Also FCPYScc and FCPYDcc.
1472199989Srdivacky  SDValue Tmp2 = CurDAG->getTargetConstant(CCVal, MVT::i32);
1473199989Srdivacky  SDValue Ops[] = { FalseVal, TrueVal, Tmp2, CCR, InFlag };
1474199989Srdivacky  unsigned Opc = 0;
1475199989Srdivacky  switch (VT.getSimpleVT().SimpleTy) {
1476199989Srdivacky  default: assert(false && "Illegal conditional move type!");
1477199989Srdivacky    break;
1478199989Srdivacky  case MVT::i32:
1479199989Srdivacky    Opc = Subtarget->isThumb()
1480199989Srdivacky      ? (Subtarget->hasThumb2() ? ARM::t2MOVCCr : ARM::tMOVCCr_pseudo)
1481199989Srdivacky      : ARM::MOVCCr;
1482199989Srdivacky    break;
1483199989Srdivacky  case MVT::f32:
1484199989Srdivacky    Opc = ARM::VMOVScc;
1485199989Srdivacky    break;
1486199989Srdivacky  case MVT::f64:
1487199989Srdivacky    Opc = ARM::VMOVDcc;
1488199989Srdivacky    break;
1489199989Srdivacky  }
1490202375Srdivacky  return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5);
1491199989Srdivacky}
1492199989Srdivacky
1493202375SrdivackySDNode *ARMDAGToDAGISel::Select(SDNode *N) {
1494193323Sed  DebugLoc dl = N->getDebugLoc();
1495193323Sed
1496193323Sed  if (N->isMachineOpcode())
1497193323Sed    return NULL;   // Already selected.
1498193323Sed
1499193323Sed  switch (N->getOpcode()) {
1500193323Sed  default: break;
1501193323Sed  case ISD::Constant: {
1502193323Sed    unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
1503193323Sed    bool UseCP = true;
1504198090Srdivacky    if (Subtarget->hasThumb2())
1505198090Srdivacky      // Thumb2-aware targets have the MOVT instruction, so all immediates can
1506198090Srdivacky      // be done with MOV + MOVT, at worst.
1507198090Srdivacky      UseCP = 0;
1508198090Srdivacky    else {
1509198090Srdivacky      if (Subtarget->isThumb()) {
1510194710Sed        UseCP = (Val > 255 &&                          // MOV
1511194710Sed                 ~Val > 255 &&                         // MOV + MVN
1512194710Sed                 !ARM_AM::isThumbImmShiftedVal(Val));  // MOV + LSL
1513198090Srdivacky      } else
1514198090Srdivacky        UseCP = (ARM_AM::getSOImmVal(Val) == -1 &&     // MOV
1515198090Srdivacky                 ARM_AM::getSOImmVal(~Val) == -1 &&    // MVN
1516198090Srdivacky                 !ARM_AM::isSOImmTwoPartVal(Val));     // two instrs.
1517198090Srdivacky    }
1518198090Srdivacky
1519193323Sed    if (UseCP) {
1520193323Sed      SDValue CPIdx =
1521198090Srdivacky        CurDAG->getTargetConstantPool(ConstantInt::get(
1522198090Srdivacky                                  Type::getInt32Ty(*CurDAG->getContext()), Val),
1523193323Sed                                      TLI.getPointerTy());
1524193323Sed
1525193323Sed      SDNode *ResNode;
1526198090Srdivacky      if (Subtarget->isThumb1Only()) {
1527199989Srdivacky        SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32);
1528198090Srdivacky        SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
1529198090Srdivacky        SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
1530198090Srdivacky        ResNode = CurDAG->getMachineNode(ARM::tLDRcp, dl, MVT::i32, MVT::Other,
1531198090Srdivacky                                         Ops, 4);
1532198090Srdivacky      } else {
1533193323Sed        SDValue Ops[] = {
1534198090Srdivacky          CPIdx,
1535193323Sed          CurDAG->getRegister(0, MVT::i32),
1536193323Sed          CurDAG->getTargetConstant(0, MVT::i32),
1537193323Sed          getAL(CurDAG),
1538193323Sed          CurDAG->getRegister(0, MVT::i32),
1539193323Sed          CurDAG->getEntryNode()
1540193323Sed        };
1541198090Srdivacky        ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
1542198090Srdivacky                                       Ops, 6);
1543193323Sed      }
1544202375Srdivacky      ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
1545193323Sed      return NULL;
1546193323Sed    }
1547198090Srdivacky
1548193323Sed    // Other cases are autogenerated.
1549193323Sed    break;
1550193323Sed  }
1551193323Sed  case ISD::FrameIndex: {
1552193323Sed    // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
1553193323Sed    int FI = cast<FrameIndexSDNode>(N)->getIndex();
1554193323Sed    SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
1555198090Srdivacky    if (Subtarget->isThumb1Only()) {
1556193323Sed      return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI,
1557193323Sed                                  CurDAG->getTargetConstant(0, MVT::i32));
1558193323Sed    } else {
1559198090Srdivacky      unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
1560198090Srdivacky                      ARM::t2ADDri : ARM::ADDri);
1561193323Sed      SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32),
1562198090Srdivacky                        getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
1563198090Srdivacky                        CurDAG->getRegister(0, MVT::i32) };
1564198090Srdivacky      return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
1565193323Sed    }
1566193323Sed  }
1567198090Srdivacky  case ARMISD::DYN_ALLOC:
1568202375Srdivacky    return SelectDYN_ALLOC(N);
1569198090Srdivacky  case ISD::SRL:
1570202375Srdivacky    if (SDNode *I = SelectV6T2BitfieldExtractOp(N,
1571198090Srdivacky                      Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX))
1572198090Srdivacky      return I;
1573193323Sed    break;
1574198090Srdivacky  case ISD::SRA:
1575202375Srdivacky    if (SDNode *I = SelectV6T2BitfieldExtractOp(N,
1576198090Srdivacky                      Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX))
1577198090Srdivacky      return I;
1578198090Srdivacky    break;
1579193323Sed  case ISD::MUL:
1580198090Srdivacky    if (Subtarget->isThumb1Only())
1581193323Sed      break;
1582202375Srdivacky    if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
1583193323Sed      unsigned RHSV = C->getZExtValue();
1584193323Sed      if (!RHSV) break;
1585193323Sed      if (isPowerOf2_32(RHSV-1)) {  // 2^n+1?
1586198090Srdivacky        unsigned ShImm = Log2_32(RHSV-1);
1587198090Srdivacky        if (ShImm >= 32)
1588198090Srdivacky          break;
1589202375Srdivacky        SDValue V = N->getOperand(0);
1590198090Srdivacky        ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
1591198090Srdivacky        SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32);
1592198090Srdivacky        SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
1593198090Srdivacky        if (Subtarget->isThumb()) {
1594198090Srdivacky          SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
1595198090Srdivacky          return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops, 6);
1596198090Srdivacky        } else {
1597198090Srdivacky          SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
1598198090Srdivacky          return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 7);
1599198090Srdivacky        }
1600193323Sed      }
1601193323Sed      if (isPowerOf2_32(RHSV+1)) {  // 2^n-1?
1602198090Srdivacky        unsigned ShImm = Log2_32(RHSV+1);
1603198090Srdivacky        if (ShImm >= 32)
1604198090Srdivacky          break;
1605202375Srdivacky        SDValue V = N->getOperand(0);
1606198090Srdivacky        ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
1607198090Srdivacky        SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32);
1608198090Srdivacky        SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
1609198090Srdivacky        if (Subtarget->isThumb()) {
1610198090Srdivacky          SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0 };
1611198090Srdivacky          return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops, 5);
1612198090Srdivacky        } else {
1613198090Srdivacky          SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
1614198090Srdivacky          return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 7);
1615198090Srdivacky        }
1616193323Sed      }
1617193323Sed    }
1618193323Sed    break;
1619198396Srdivacky  case ISD::AND: {
1620198396Srdivacky    // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
1621198396Srdivacky    // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
1622198396Srdivacky    // are entirely contributed by c2 and lower 16-bits are entirely contributed
1623198396Srdivacky    // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)).
1624198396Srdivacky    // Select it to: "movt x, ((c1 & 0xffff) >> 16)
1625202375Srdivacky    EVT VT = N->getValueType(0);
1626198396Srdivacky    if (VT != MVT::i32)
1627198396Srdivacky      break;
1628198396Srdivacky    unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
1629198396Srdivacky      ? ARM::t2MOVTi16
1630198396Srdivacky      : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
1631198396Srdivacky    if (!Opc)
1632198396Srdivacky      break;
1633202375Srdivacky    SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
1634198396Srdivacky    ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
1635198396Srdivacky    if (!N1C)
1636198396Srdivacky      break;
1637198396Srdivacky    if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {
1638198396Srdivacky      SDValue N2 = N0.getOperand(1);
1639198396Srdivacky      ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
1640198396Srdivacky      if (!N2C)
1641198396Srdivacky        break;
1642198396Srdivacky      unsigned N1CVal = N1C->getZExtValue();
1643198396Srdivacky      unsigned N2CVal = N2C->getZExtValue();
1644198396Srdivacky      if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
1645198396Srdivacky          (N1CVal & 0xffffU) == 0xffffU &&
1646198396Srdivacky          (N2CVal & 0xffffU) == 0x0U) {
1647198396Srdivacky        SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
1648198396Srdivacky                                                  MVT::i32);
1649198396Srdivacky        SDValue Ops[] = { N0.getOperand(0), Imm16,
1650198396Srdivacky                          getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
1651198396Srdivacky        return CurDAG->getMachineNode(Opc, dl, VT, Ops, 4);
1652198396Srdivacky      }
1653198396Srdivacky    }
1654198396Srdivacky    break;
1655198396Srdivacky  }
1656199481Srdivacky  case ARMISD::VMOVRRD:
1657199481Srdivacky    return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32,
1658202375Srdivacky                                  N->getOperand(0), getAL(CurDAG),
1659198090Srdivacky                                  CurDAG->getRegister(0, MVT::i32));
1660193323Sed  case ISD::UMUL_LOHI: {
1661198090Srdivacky    if (Subtarget->isThumb1Only())
1662198090Srdivacky      break;
1663198090Srdivacky    if (Subtarget->isThumb()) {
1664202375Srdivacky      SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
1665193323Sed                        getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
1666193323Sed                        CurDAG->getRegister(0, MVT::i32) };
1667198090Srdivacky      return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops,4);
1668198090Srdivacky    } else {
1669202375Srdivacky      SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
1670198090Srdivacky                        getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
1671198090Srdivacky                        CurDAG->getRegister(0, MVT::i32) };
1672198090Srdivacky      return CurDAG->getMachineNode(ARM::UMULL, dl, MVT::i32, MVT::i32, Ops, 5);
1673198090Srdivacky    }
1674193323Sed  }
1675193323Sed  case ISD::SMUL_LOHI: {
1676198090Srdivacky    if (Subtarget->isThumb1Only())
1677198090Srdivacky      break;
1678198090Srdivacky    if (Subtarget->isThumb()) {
1679202375Srdivacky      SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
1680198090Srdivacky                        getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
1681198090Srdivacky      return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops,4);
1682198090Srdivacky    } else {
1683202375Srdivacky      SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
1684193323Sed                        getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
1685193323Sed                        CurDAG->getRegister(0, MVT::i32) };
1686198090Srdivacky      return CurDAG->getMachineNode(ARM::SMULL, dl, MVT::i32, MVT::i32, Ops, 5);
1687198090Srdivacky    }
1688193323Sed  }
1689193323Sed  case ISD::LOAD: {
1690195340Sed    SDNode *ResNode = 0;
1691198090Srdivacky    if (Subtarget->isThumb() && Subtarget->hasThumb2())
1692202375Srdivacky      ResNode = SelectT2IndexedLoad(N);
1693195340Sed    else
1694202375Srdivacky      ResNode = SelectARMIndexedLoad(N);
1695195340Sed    if (ResNode)
1696195340Sed      return ResNode;
1697193323Sed    // Other cases are autogenerated.
1698193323Sed    break;
1699193323Sed  }
1700193323Sed  case ARMISD::BRCOND: {
1701193323Sed    // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
1702193323Sed    // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
1703193323Sed    // Pattern complexity = 6  cost = 1  size = 0
1704193323Sed
1705193323Sed    // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
1706193323Sed    // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
1707193323Sed    // Pattern complexity = 6  cost = 1  size = 0
1708193323Sed
1709195340Sed    // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
1710195340Sed    // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
1711195340Sed    // Pattern complexity = 6  cost = 1  size = 0
1712195340Sed
1713198090Srdivacky    unsigned Opc = Subtarget->isThumb() ?
1714195340Sed      ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
1715202375Srdivacky    SDValue Chain = N->getOperand(0);
1716202375Srdivacky    SDValue N1 = N->getOperand(1);
1717202375Srdivacky    SDValue N2 = N->getOperand(2);
1718202375Srdivacky    SDValue N3 = N->getOperand(3);
1719202375Srdivacky    SDValue InFlag = N->getOperand(4);
1720193323Sed    assert(N1.getOpcode() == ISD::BasicBlock);
1721193323Sed    assert(N2.getOpcode() == ISD::Constant);
1722193323Sed    assert(N3.getOpcode() == ISD::Register);
1723193323Sed
1724193323Sed    SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
1725193323Sed                               cast<ConstantSDNode>(N2)->getZExtValue()),
1726193323Sed                               MVT::i32);
1727193323Sed    SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
1728198090Srdivacky    SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
1729198090Srdivacky                                             MVT::Flag, Ops, 5);
1730193323Sed    Chain = SDValue(ResNode, 0);
1731202375Srdivacky    if (N->getNumValues() == 2) {
1732193323Sed      InFlag = SDValue(ResNode, 1);
1733202375Srdivacky      ReplaceUses(SDValue(N, 1), InFlag);
1734193323Sed    }
1735202375Srdivacky    ReplaceUses(SDValue(N, 0),
1736199511Srdivacky                SDValue(Chain.getNode(), Chain.getResNo()));
1737193323Sed    return NULL;
1738193323Sed  }
1739199989Srdivacky  case ARMISD::CMOV:
1740202375Srdivacky    return SelectCMOVOp(N);
1741193323Sed  case ARMISD::CNEG: {
1742202375Srdivacky    EVT VT = N->getValueType(0);
1743202375Srdivacky    SDValue N0 = N->getOperand(0);
1744202375Srdivacky    SDValue N1 = N->getOperand(1);
1745202375Srdivacky    SDValue N2 = N->getOperand(2);
1746202375Srdivacky    SDValue N3 = N->getOperand(3);
1747202375Srdivacky    SDValue InFlag = N->getOperand(4);
1748193323Sed    assert(N2.getOpcode() == ISD::Constant);
1749193323Sed    assert(N3.getOpcode() == ISD::Register);
1750193323Sed
1751193323Sed    SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
1752193323Sed                               cast<ConstantSDNode>(N2)->getZExtValue()),
1753193323Sed                               MVT::i32);
1754193323Sed    SDValue Ops[] = { N0, N1, Tmp2, N3, InFlag };
1755193323Sed    unsigned Opc = 0;
1756198090Srdivacky    switch (VT.getSimpleVT().SimpleTy) {
1757193323Sed    default: assert(false && "Illegal conditional move type!");
1758193323Sed      break;
1759193323Sed    case MVT::f32:
1760199481Srdivacky      Opc = ARM::VNEGScc;
1761193323Sed      break;
1762193323Sed    case MVT::f64:
1763199481Srdivacky      Opc = ARM::VNEGDcc;
1764193323Sed      break;
1765193323Sed    }
1766202375Srdivacky    return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5);
1767193323Sed  }
1768193323Sed
1769198090Srdivacky  case ARMISD::VZIP: {
1770198090Srdivacky    unsigned Opc = 0;
1771198090Srdivacky    EVT VT = N->getValueType(0);
1772198090Srdivacky    switch (VT.getSimpleVT().SimpleTy) {
1773198090Srdivacky    default: return NULL;
1774198090Srdivacky    case MVT::v8i8:  Opc = ARM::VZIPd8; break;
1775198090Srdivacky    case MVT::v4i16: Opc = ARM::VZIPd16; break;
1776198090Srdivacky    case MVT::v2f32:
1777198090Srdivacky    case MVT::v2i32: Opc = ARM::VZIPd32; break;
1778198090Srdivacky    case MVT::v16i8: Opc = ARM::VZIPq8; break;
1779198090Srdivacky    case MVT::v8i16: Opc = ARM::VZIPq16; break;
1780198090Srdivacky    case MVT::v4f32:
1781198090Srdivacky    case MVT::v4i32: Opc = ARM::VZIPq32; break;
1782193323Sed    }
1783199989Srdivacky    SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32);
1784199989Srdivacky    SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
1785199989Srdivacky    SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
1786199989Srdivacky    return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4);
1787198090Srdivacky  }
1788198090Srdivacky  case ARMISD::VUZP: {
1789198090Srdivacky    unsigned Opc = 0;
1790198090Srdivacky    EVT VT = N->getValueType(0);
1791198090Srdivacky    switch (VT.getSimpleVT().SimpleTy) {
1792198090Srdivacky    default: return NULL;
1793198090Srdivacky    case MVT::v8i8:  Opc = ARM::VUZPd8; break;
1794198090Srdivacky    case MVT::v4i16: Opc = ARM::VUZPd16; break;
1795198090Srdivacky    case MVT::v2f32:
1796198090Srdivacky    case MVT::v2i32: Opc = ARM::VUZPd32; break;
1797198090Srdivacky    case MVT::v16i8: Opc = ARM::VUZPq8; break;
1798198090Srdivacky    case MVT::v8i16: Opc = ARM::VUZPq16; break;
1799198090Srdivacky    case MVT::v4f32:
1800198090Srdivacky    case MVT::v4i32: Opc = ARM::VUZPq32; break;
1801193323Sed    }
1802199989Srdivacky    SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32);
1803199989Srdivacky    SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
1804199989Srdivacky    SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
1805199989Srdivacky    return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4);
1806198090Srdivacky  }
1807198090Srdivacky  case ARMISD::VTRN: {
1808198090Srdivacky    unsigned Opc = 0;
1809198090Srdivacky    EVT VT = N->getValueType(0);
1810198090Srdivacky    switch (VT.getSimpleVT().SimpleTy) {
1811198090Srdivacky    default: return NULL;
1812198090Srdivacky    case MVT::v8i8:  Opc = ARM::VTRNd8; break;
1813198090Srdivacky    case MVT::v4i16: Opc = ARM::VTRNd16; break;
1814198090Srdivacky    case MVT::v2f32:
1815198090Srdivacky    case MVT::v2i32: Opc = ARM::VTRNd32; break;
1816198090Srdivacky    case MVT::v16i8: Opc = ARM::VTRNq8; break;
1817198090Srdivacky    case MVT::v8i16: Opc = ARM::VTRNq16; break;
1818198090Srdivacky    case MVT::v4f32:
1819198090Srdivacky    case MVT::v4i32: Opc = ARM::VTRNq32; break;
1820193323Sed    }
1821199989Srdivacky    SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32);
1822199989Srdivacky    SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
1823199989Srdivacky    SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
1824199989Srdivacky    return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4);
1825193323Sed  }
1826194710Sed
1827198090Srdivacky  case ISD::INTRINSIC_VOID:
1828198090Srdivacky  case ISD::INTRINSIC_W_CHAIN: {
1829198090Srdivacky    unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
1830198090Srdivacky    switch (IntNo) {
1831198090Srdivacky    default:
1832198090Srdivacky      break;
1833194710Sed
1834198090Srdivacky    case Intrinsic::arm_neon_vld2: {
1835198090Srdivacky      unsigned DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
1836198090Srdivacky                              ARM::VLD2d32, ARM::VLD2d64 };
1837198090Srdivacky      unsigned QOpcodes[] = { ARM::VLD2q8, ARM::VLD2q16, ARM::VLD2q32 };
1838202375Srdivacky      return SelectVLD(N, 2, DOpcodes, QOpcodes, 0);
1839198090Srdivacky    }
1840194710Sed
1841198090Srdivacky    case Intrinsic::arm_neon_vld3: {
1842198090Srdivacky      unsigned DOpcodes[] = { ARM::VLD3d8, ARM::VLD3d16,
1843198090Srdivacky                              ARM::VLD3d32, ARM::VLD3d64 };
1844205407Srdivacky      unsigned QOpcodes0[] = { ARM::VLD3q8_UPD,
1845205407Srdivacky                               ARM::VLD3q16_UPD,
1846205407Srdivacky                               ARM::VLD3q32_UPD };
1847205407Srdivacky      unsigned QOpcodes1[] = { ARM::VLD3q8odd_UPD,
1848205407Srdivacky                               ARM::VLD3q16odd_UPD,
1849205407Srdivacky                               ARM::VLD3q32odd_UPD };
1850202375Srdivacky      return SelectVLD(N, 3, DOpcodes, QOpcodes0, QOpcodes1);
1851198090Srdivacky    }
1852198090Srdivacky
1853198090Srdivacky    case Intrinsic::arm_neon_vld4: {
1854198090Srdivacky      unsigned DOpcodes[] = { ARM::VLD4d8, ARM::VLD4d16,
1855198090Srdivacky                              ARM::VLD4d32, ARM::VLD4d64 };
1856205407Srdivacky      unsigned QOpcodes0[] = { ARM::VLD4q8_UPD,
1857205407Srdivacky                               ARM::VLD4q16_UPD,
1858205407Srdivacky                               ARM::VLD4q32_UPD };
1859205407Srdivacky      unsigned QOpcodes1[] = { ARM::VLD4q8odd_UPD,
1860205407Srdivacky                               ARM::VLD4q16odd_UPD,
1861205407Srdivacky                               ARM::VLD4q32odd_UPD };
1862202375Srdivacky      return SelectVLD(N, 4, DOpcodes, QOpcodes0, QOpcodes1);
1863198090Srdivacky    }
1864198090Srdivacky
1865198090Srdivacky    case Intrinsic::arm_neon_vld2lane: {
1866198090Srdivacky      unsigned DOpcodes[] = { ARM::VLD2LNd8, ARM::VLD2LNd16, ARM::VLD2LNd32 };
1867205407Srdivacky      unsigned QOpcodes0[] = { ARM::VLD2LNq16, ARM::VLD2LNq32 };
1868205407Srdivacky      unsigned QOpcodes1[] = { ARM::VLD2LNq16odd, ARM::VLD2LNq32odd };
1869202375Srdivacky      return SelectVLDSTLane(N, true, 2, DOpcodes, QOpcodes0, QOpcodes1);
1870198090Srdivacky    }
1871198090Srdivacky
1872198090Srdivacky    case Intrinsic::arm_neon_vld3lane: {
1873198090Srdivacky      unsigned DOpcodes[] = { ARM::VLD3LNd8, ARM::VLD3LNd16, ARM::VLD3LNd32 };
1874205407Srdivacky      unsigned QOpcodes0[] = { ARM::VLD3LNq16, ARM::VLD3LNq32 };
1875205407Srdivacky      unsigned QOpcodes1[] = { ARM::VLD3LNq16odd, ARM::VLD3LNq32odd };
1876202375Srdivacky      return SelectVLDSTLane(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
1877198090Srdivacky    }
1878198090Srdivacky
1879198090Srdivacky    case Intrinsic::arm_neon_vld4lane: {
1880198090Srdivacky      unsigned DOpcodes[] = { ARM::VLD4LNd8, ARM::VLD4LNd16, ARM::VLD4LNd32 };
1881205407Srdivacky      unsigned QOpcodes0[] = { ARM::VLD4LNq16, ARM::VLD4LNq32 };
1882205407Srdivacky      unsigned QOpcodes1[] = { ARM::VLD4LNq16odd, ARM::VLD4LNq32odd };
1883202375Srdivacky      return SelectVLDSTLane(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
1884198090Srdivacky    }
1885198090Srdivacky
1886198090Srdivacky    case Intrinsic::arm_neon_vst2: {
1887198113Srdivacky      unsigned DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
1888198113Srdivacky                              ARM::VST2d32, ARM::VST2d64 };
1889198113Srdivacky      unsigned QOpcodes[] = { ARM::VST2q8, ARM::VST2q16, ARM::VST2q32 };
1890202375Srdivacky      return SelectVST(N, 2, DOpcodes, QOpcodes, 0);
1891198090Srdivacky    }
1892194710Sed
1893198090Srdivacky    case Intrinsic::arm_neon_vst3: {
1894198113Srdivacky      unsigned DOpcodes[] = { ARM::VST3d8, ARM::VST3d16,
1895198113Srdivacky                              ARM::VST3d32, ARM::VST3d64 };
1896205407Srdivacky      unsigned QOpcodes0[] = { ARM::VST3q8_UPD,
1897205407Srdivacky                               ARM::VST3q16_UPD,
1898205407Srdivacky                               ARM::VST3q32_UPD };
1899205407Srdivacky      unsigned QOpcodes1[] = { ARM::VST3q8odd_UPD,
1900205407Srdivacky                               ARM::VST3q16odd_UPD,
1901205407Srdivacky                               ARM::VST3q32odd_UPD };
1902202375Srdivacky      return SelectVST(N, 3, DOpcodes, QOpcodes0, QOpcodes1);
1903194710Sed    }
1904194710Sed
1905198090Srdivacky    case Intrinsic::arm_neon_vst4: {
1906198113Srdivacky      unsigned DOpcodes[] = { ARM::VST4d8, ARM::VST4d16,
1907198113Srdivacky                              ARM::VST4d32, ARM::VST4d64 };
1908205407Srdivacky      unsigned QOpcodes0[] = { ARM::VST4q8_UPD,
1909205407Srdivacky                               ARM::VST4q16_UPD,
1910205407Srdivacky                               ARM::VST4q32_UPD };
1911205407Srdivacky      unsigned QOpcodes1[] = { ARM::VST4q8odd_UPD,
1912205407Srdivacky                               ARM::VST4q16odd_UPD,
1913205407Srdivacky                               ARM::VST4q32odd_UPD };
1914202375Srdivacky      return SelectVST(N, 4, DOpcodes, QOpcodes0, QOpcodes1);
1915198090Srdivacky    }
1916198090Srdivacky
1917198090Srdivacky    case Intrinsic::arm_neon_vst2lane: {
1918198090Srdivacky      unsigned DOpcodes[] = { ARM::VST2LNd8, ARM::VST2LNd16, ARM::VST2LNd32 };
1919205407Srdivacky      unsigned QOpcodes0[] = { ARM::VST2LNq16, ARM::VST2LNq32 };
1920205407Srdivacky      unsigned QOpcodes1[] = { ARM::VST2LNq16odd, ARM::VST2LNq32odd };
1921202375Srdivacky      return SelectVLDSTLane(N, false, 2, DOpcodes, QOpcodes0, QOpcodes1);
1922198090Srdivacky    }
1923198090Srdivacky
1924198090Srdivacky    case Intrinsic::arm_neon_vst3lane: {
1925198090Srdivacky      unsigned DOpcodes[] = { ARM::VST3LNd8, ARM::VST3LNd16, ARM::VST3LNd32 };
1926205407Srdivacky      unsigned QOpcodes0[] = { ARM::VST3LNq16, ARM::VST3LNq32 };
1927205407Srdivacky      unsigned QOpcodes1[] = { ARM::VST3LNq16odd, ARM::VST3LNq32odd };
1928202375Srdivacky      return SelectVLDSTLane(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
1929198090Srdivacky    }
1930198090Srdivacky
1931198090Srdivacky    case Intrinsic::arm_neon_vst4lane: {
1932198090Srdivacky      unsigned DOpcodes[] = { ARM::VST4LNd8, ARM::VST4LNd16, ARM::VST4LNd32 };
1933205407Srdivacky      unsigned QOpcodes0[] = { ARM::VST4LNq16, ARM::VST4LNq32 };
1934205407Srdivacky      unsigned QOpcodes1[] = { ARM::VST4LNq16odd, ARM::VST4LNq32odd };
1935202375Srdivacky      return SelectVLDSTLane(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
1936198090Srdivacky    }
1937198090Srdivacky    }
1938194710Sed  }
1939194710Sed  }
1940194710Sed
1941202375Srdivacky  return SelectCode(N);
1942193323Sed}
1943193323Sed
1944193323Sedbool ARMDAGToDAGISel::
1945193323SedSelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
1946193323Sed                             std::vector<SDValue> &OutOps) {
1947193323Sed  assert(ConstraintCode == 'm' && "unexpected asm memory constraint");
1948198090Srdivacky  // Require the address to be in a register.  That is safe for all ARM
1949198090Srdivacky  // variants and it is hard to do anything much smarter without knowing
1950198090Srdivacky  // how the operand is used.
1951198090Srdivacky  OutOps.push_back(Op);
1952193323Sed  return false;
1953193323Sed}
1954193323Sed
1955193323Sed/// createARMISelDag - This pass converts a legalized DAG into a
1956193323Sed/// ARM-specific DAG, ready for instruction scheduling.
1957193323Sed///
1958198090SrdivackyFunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
1959198090Srdivacky                                     CodeGenOpt::Level OptLevel) {
1960198090Srdivacky  return new ARMDAGToDAGISel(TM, OptLevel);
1961193323Sed}
1962