ARMISelDAGToDAG.cpp revision 280031
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"
15218893Sdim#include "ARMBaseInstrInfo.h"
16193323Sed#include "ARMTargetMachine.h"
17226633Sdim#include "MCTargetDesc/ARMAddressingModes.h"
18193323Sed#include "llvm/CodeGen/MachineFrameInfo.h"
19193323Sed#include "llvm/CodeGen/MachineFunction.h"
20193323Sed#include "llvm/CodeGen/MachineInstrBuilder.h"
21249423Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
22193323Sed#include "llvm/CodeGen/SelectionDAG.h"
23193323Sed#include "llvm/CodeGen/SelectionDAGISel.h"
24249423Sdim#include "llvm/IR/CallingConv.h"
25249423Sdim#include "llvm/IR/Constants.h"
26249423Sdim#include "llvm/IR/DerivedTypes.h"
27249423Sdim#include "llvm/IR/Function.h"
28249423Sdim#include "llvm/IR/Intrinsics.h"
29249423Sdim#include "llvm/IR/LLVMContext.h"
30207631Srdivacky#include "llvm/Support/CommandLine.h"
31193323Sed#include "llvm/Support/Compiler.h"
32193323Sed#include "llvm/Support/Debug.h"
33198090Srdivacky#include "llvm/Support/ErrorHandling.h"
34249423Sdim#include "llvm/Target/TargetLowering.h"
35249423Sdim#include "llvm/Target/TargetOptions.h"
36198090Srdivacky
37193323Sedusing namespace llvm;
38193323Sed
39276479Sdim#define DEBUG_TYPE "arm-isel"
40276479Sdim
41212904Sdimstatic cl::opt<bool>
42212904SdimDisableShifterOp("disable-shifter-op", cl::Hidden,
43212904Sdim  cl::desc("Disable isel of shifter-op"),
44212904Sdim  cl::init(false));
45212904Sdim
46218893Sdimstatic cl::opt<bool>
47218893SdimCheckVMLxHazard("check-vmlx-hazard", cl::Hidden,
48218893Sdim  cl::desc("Check fp vmla / vmls hazard at isel time"),
49221345Sdim  cl::init(true));
50218893Sdim
51193323Sed//===--------------------------------------------------------------------===//
52193323Sed/// ARMDAGToDAGISel - ARM specific code to select ARM machine
53193323Sed/// instructions for SelectionDAG operations.
54193323Sed///
55193323Sednamespace {
56218893Sdim
57218893Sdimenum AddrMode2Type {
58218893Sdim  AM2_BASE, // Simple AM2 (+-imm12)
59218893Sdim  AM2_SHOP  // Shifter-op AM2
60218893Sdim};
61218893Sdim
62193323Sedclass ARMDAGToDAGISel : public SelectionDAGISel {
63193323Sed  /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
64193323Sed  /// make the right decision when generating code for different targets.
65193323Sed  const ARMSubtarget *Subtarget;
66193323Sed
67193323Sedpublic:
68276479Sdim  explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm, CodeGenOpt::Level OptLevel)
69276479Sdim      : SelectionDAGISel(tm, OptLevel) {}
70276479Sdim
71276479Sdim  bool runOnMachineFunction(MachineFunction &MF) override {
72276479Sdim    // Reset the subtarget each time through.
73276479Sdim    Subtarget = &MF.getTarget().getSubtarget<ARMSubtarget>();
74276479Sdim    SelectionDAGISel::runOnMachineFunction(MF);
75276479Sdim    return true;
76193323Sed  }
77193323Sed
78276479Sdim  const char *getPassName() const override {
79193323Sed    return "ARM Instruction Selection";
80194612Sed  }
81194612Sed
82276479Sdim  void PreprocessISelDAG() override;
83249423Sdim
84198090Srdivacky  /// getI32Imm - Return a target constant of type i32 with the specified
85198090Srdivacky  /// value.
86194612Sed  inline SDValue getI32Imm(unsigned Imm) {
87194612Sed    return CurDAG->getTargetConstant(Imm, MVT::i32);
88194612Sed  }
89194612Sed
90276479Sdim  SDNode *Select(SDNode *N) override;
91203954Srdivacky
92218893Sdim
93218893Sdim  bool hasNoVMLxHazardUse(SDNode *N) const;
94218893Sdim  bool isShifterOpProfitable(const SDValue &Shift,
95218893Sdim                             ARM_AM::ShiftOpc ShOpcVal, unsigned ShAmt);
96226633Sdim  bool SelectRegShifterOperand(SDValue N, SDValue &A,
97221345Sdim                               SDValue &B, SDValue &C,
98221345Sdim                               bool CheckProfitability = true);
99226633Sdim  bool SelectImmShifterOperand(SDValue N, SDValue &A,
100226633Sdim                               SDValue &B, bool CheckProfitability = true);
101226633Sdim  bool SelectShiftRegShifterOperand(SDValue N, SDValue &A,
102221345Sdim                                    SDValue &B, SDValue &C) {
103221345Sdim    // Don't apply the profitability check
104226633Sdim    return SelectRegShifterOperand(N, A, B, C, false);
105221345Sdim  }
106226633Sdim  bool SelectShiftImmShifterOperand(SDValue N, SDValue &A,
107226633Sdim                                    SDValue &B) {
108226633Sdim    // Don't apply the profitability check
109226633Sdim    return SelectImmShifterOperand(N, A, B, false);
110226633Sdim  }
111221345Sdim
112218893Sdim  bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
113218893Sdim  bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc);
114218893Sdim
115218893Sdim  AddrMode2Type SelectAddrMode2Worker(SDValue N, SDValue &Base,
116218893Sdim                                      SDValue &Offset, SDValue &Opc);
117218893Sdim  bool SelectAddrMode2Base(SDValue N, SDValue &Base, SDValue &Offset,
118218893Sdim                           SDValue &Opc) {
119218893Sdim    return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_BASE;
120218893Sdim  }
121218893Sdim
122218893Sdim  bool SelectAddrMode2ShOp(SDValue N, SDValue &Base, SDValue &Offset,
123218893Sdim                           SDValue &Opc) {
124218893Sdim    return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_SHOP;
125218893Sdim  }
126218893Sdim
127218893Sdim  bool SelectAddrMode2(SDValue N, SDValue &Base, SDValue &Offset,
128218893Sdim                       SDValue &Opc) {
129218893Sdim    SelectAddrMode2Worker(N, Base, Offset, Opc);
130218893Sdim//    return SelectAddrMode2ShOp(N, Base, Offset, Opc);
131218893Sdim    // This always matches one way or another.
132218893Sdim    return true;
133218893Sdim  }
134218893Sdim
135261991Sdim  bool SelectCMOVPred(SDValue N, SDValue &Pred, SDValue &Reg) {
136261991Sdim    const ConstantSDNode *CN = cast<ConstantSDNode>(N);
137261991Sdim    Pred = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32);
138261991Sdim    Reg = CurDAG->getRegister(ARM::CPSR, MVT::i32);
139261991Sdim    return true;
140261991Sdim  }
141261991Sdim
142226633Sdim  bool SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
143193323Sed                             SDValue &Offset, SDValue &Opc);
144226633Sdim  bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
145226633Sdim                             SDValue &Offset, SDValue &Opc);
146226633Sdim  bool SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
147226633Sdim                             SDValue &Offset, SDValue &Opc);
148226633Sdim  bool SelectAddrOffsetNone(SDValue N, SDValue &Base);
149218893Sdim  bool SelectAddrMode3(SDValue N, SDValue &Base,
150193323Sed                       SDValue &Offset, SDValue &Opc);
151202375Srdivacky  bool SelectAddrMode3Offset(SDNode *Op, SDValue N,
152193323Sed                             SDValue &Offset, SDValue &Opc);
153218893Sdim  bool SelectAddrMode5(SDValue N, SDValue &Base,
154193323Sed                       SDValue &Offset);
155218893Sdim  bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align);
156219077Sdim  bool SelectAddrMode6Offset(SDNode *Op, SDValue N, SDValue &Offset);
157193323Sed
158218893Sdim  bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label);
159193323Sed
160218893Sdim  // Thumb Addressing Modes:
161218893Sdim  bool SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset);
162218893Sdim  bool SelectThumbAddrModeRI(SDValue N, SDValue &Base, SDValue &Offset,
163218893Sdim                             unsigned Scale);
164218893Sdim  bool SelectThumbAddrModeRI5S1(SDValue N, SDValue &Base, SDValue &Offset);
165218893Sdim  bool SelectThumbAddrModeRI5S2(SDValue N, SDValue &Base, SDValue &Offset);
166218893Sdim  bool SelectThumbAddrModeRI5S4(SDValue N, SDValue &Base, SDValue &Offset);
167218893Sdim  bool SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, SDValue &Base,
168218893Sdim                                SDValue &OffImm);
169218893Sdim  bool SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
170218893Sdim                                 SDValue &OffImm);
171218893Sdim  bool SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
172218893Sdim                                 SDValue &OffImm);
173218893Sdim  bool SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
174218893Sdim                                 SDValue &OffImm);
175218893Sdim  bool SelectThumbAddrModeSP(SDValue N, SDValue &Base, SDValue &OffImm);
176193323Sed
177218893Sdim  // Thumb 2 Addressing Modes:
178218893Sdim  bool SelectT2ShifterOperandReg(SDValue N,
179195098Sed                                 SDValue &BaseReg, SDValue &Opc);
180218893Sdim  bool SelectT2AddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
181218893Sdim  bool SelectT2AddrModeImm8(SDValue N, SDValue &Base,
182195340Sed                            SDValue &OffImm);
183202375Srdivacky  bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
184195340Sed                                 SDValue &OffImm);
185218893Sdim  bool SelectT2AddrModeSoReg(SDValue N, SDValue &Base,
186195340Sed                             SDValue &OffReg, SDValue &ShImm);
187261991Sdim  bool SelectT2AddrModeExclusive(SDValue N, SDValue &Base, SDValue &OffImm);
188195340Sed
189218893Sdim  inline bool is_so_imm(unsigned Imm) const {
190218893Sdim    return ARM_AM::getSOImmVal(Imm) != -1;
191218893Sdim  }
192218893Sdim
193218893Sdim  inline bool is_so_imm_not(unsigned Imm) const {
194218893Sdim    return ARM_AM::getSOImmVal(~Imm) != -1;
195218893Sdim  }
196218893Sdim
197218893Sdim  inline bool is_t2_so_imm(unsigned Imm) const {
198218893Sdim    return ARM_AM::getT2SOImmVal(Imm) != -1;
199218893Sdim  }
200218893Sdim
201218893Sdim  inline bool is_t2_so_imm_not(unsigned Imm) const {
202218893Sdim    return ARM_AM::getT2SOImmVal(~Imm) != -1;
203218893Sdim  }
204218893Sdim
205193323Sed  // Include the pieces autogenerated from the target description.
206193323Sed#include "ARMGenDAGISel.inc"
207193323Sed
208193323Sedprivate:
209195340Sed  /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for
210195340Sed  /// ARM.
211202375Srdivacky  SDNode *SelectARMIndexedLoad(SDNode *N);
212202375Srdivacky  SDNode *SelectT2IndexedLoad(SDNode *N);
213195340Sed
214206083Srdivacky  /// SelectVLD - Select NEON load intrinsics.  NumVecs should be
215206083Srdivacky  /// 1, 2, 3 or 4.  The opcode arrays specify the instructions used for
216198090Srdivacky  /// loads of D registers and even subregs and odd subregs of Q registers.
217206083Srdivacky  /// For NumVecs <= 2, QOpcodes1 is not used.
218218893Sdim  SDNode *SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
219239462Sdim                    const uint16_t *DOpcodes,
220239462Sdim                    const uint16_t *QOpcodes0, const uint16_t *QOpcodes1);
221198090Srdivacky
222198113Srdivacky  /// SelectVST - Select NEON store intrinsics.  NumVecs should
223206083Srdivacky  /// be 1, 2, 3 or 4.  The opcode arrays specify the instructions used for
224198113Srdivacky  /// stores of D registers and even subregs and odd subregs of Q registers.
225206083Srdivacky  /// For NumVecs <= 2, QOpcodes1 is not used.
226218893Sdim  SDNode *SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
227239462Sdim                    const uint16_t *DOpcodes,
228239462Sdim                    const uint16_t *QOpcodes0, const uint16_t *QOpcodes1);
229198113Srdivacky
230198090Srdivacky  /// SelectVLDSTLane - Select NEON load/store lane intrinsics.  NumVecs should
231198090Srdivacky  /// be 2, 3 or 4.  The opcode arrays specify the instructions used for
232218893Sdim  /// load/store of D registers and Q registers.
233218893Sdim  SDNode *SelectVLDSTLane(SDNode *N, bool IsLoad,
234218893Sdim                          bool isUpdating, unsigned NumVecs,
235239462Sdim                          const uint16_t *DOpcodes, const uint16_t *QOpcodes);
236198090Srdivacky
237218893Sdim  /// SelectVLDDup - Select NEON load-duplicate intrinsics.  NumVecs
238218893Sdim  /// should be 2, 3 or 4.  The opcode array specifies the instructions used
239218893Sdim  /// for loading D registers.  (Q registers are not supported.)
240218893Sdim  SDNode *SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
241239462Sdim                       const uint16_t *Opcodes);
242218893Sdim
243210299Sed  /// SelectVTBL - Select NEON VTBL and VTBX intrinsics.  NumVecs should be 2,
244210299Sed  /// 3 or 4.  These are custom-selected so that a REG_SEQUENCE can be
245210299Sed  /// generated to force the table registers to be consecutive.
246210299Sed  SDNode *SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs, unsigned Opc);
247210299Sed
248198090Srdivacky  /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM.
249207618Srdivacky  SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, bool isSigned);
250198090Srdivacky
251226633Sdim  // Select special operations if node forms integer ABS pattern
252226633Sdim  SDNode *SelectABSOp(SDNode *N);
253226633Sdim
254249423Sdim  SDNode *SelectInlineAsm(SDNode *N);
255249423Sdim
256208599Srdivacky  SDNode *SelectConcatVector(SDNode *N);
257208599Srdivacky
258195340Sed  /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
259195340Sed  /// inline asm expressions.
260276479Sdim  bool SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
261276479Sdim                                    std::vector<SDValue> &OutOps) override;
262198090Srdivacky
263249423Sdim  // Form pairs of consecutive R, S, D, or Q registers.
264249423Sdim  SDNode *createGPRPairNode(EVT VT, SDValue V0, SDValue V1);
265249423Sdim  SDNode *createSRegPairNode(EVT VT, SDValue V0, SDValue V1);
266249423Sdim  SDNode *createDRegPairNode(EVT VT, SDValue V0, SDValue V1);
267249423Sdim  SDNode *createQRegPairNode(EVT VT, SDValue V0, SDValue V1);
268208599Srdivacky
269210299Sed  // Form sequences of 4 consecutive S, D, or Q registers.
270249423Sdim  SDNode *createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
271249423Sdim  SDNode *createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
272249423Sdim  SDNode *createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
273208599Srdivacky
274218893Sdim  // Get the alignment operand for a NEON VLD or VST instruction.
275218893Sdim  SDValue GetVLDSTAlign(SDValue Align, unsigned NumVecs, bool is64BitVector);
276193323Sed};
277193323Sed}
278193323Sed
279198090Srdivacky/// isInt32Immediate - This method tests to see if the node is a 32-bit constant
280198090Srdivacky/// operand. If so Imm will receive the 32-bit value.
281198090Srdivackystatic bool isInt32Immediate(SDNode *N, unsigned &Imm) {
282198090Srdivacky  if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) {
283198090Srdivacky    Imm = cast<ConstantSDNode>(N)->getZExtValue();
284198090Srdivacky    return true;
285198090Srdivacky  }
286198090Srdivacky  return false;
287198090Srdivacky}
288198090Srdivacky
289198090Srdivacky// isInt32Immediate - This method tests to see if a constant operand.
290198090Srdivacky// If so Imm will receive the 32 bit value.
291198090Srdivackystatic bool isInt32Immediate(SDValue N, unsigned &Imm) {
292198090Srdivacky  return isInt32Immediate(N.getNode(), Imm);
293198090Srdivacky}
294198090Srdivacky
295198090Srdivacky// isOpcWithIntImmediate - This method tests to see if the node is a specific
296198090Srdivacky// opcode and that it has a immediate integer right operand.
297198090Srdivacky// If so Imm will receive the 32 bit value.
298198090Srdivackystatic bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
299198090Srdivacky  return N->getOpcode() == Opc &&
300198090Srdivacky         isInt32Immediate(N->getOperand(1).getNode(), Imm);
301198090Srdivacky}
302198090Srdivacky
303218893Sdim/// \brief Check whether a particular node is a constant value representable as
304243830Sdim/// (N * Scale) where (N in [\p RangeMin, \p RangeMax).
305218893Sdim///
306218893Sdim/// \param ScaledConstant [out] - On success, the pre-scaled constant value.
307226633Sdimstatic bool isScaledConstantInRange(SDValue Node, int Scale,
308218893Sdim                                    int RangeMin, int RangeMax,
309218893Sdim                                    int &ScaledConstant) {
310226633Sdim  assert(Scale > 0 && "Invalid scale!");
311198090Srdivacky
312218893Sdim  // Check that this is a constant.
313218893Sdim  const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Node);
314218893Sdim  if (!C)
315218893Sdim    return false;
316218893Sdim
317218893Sdim  ScaledConstant = (int) C->getZExtValue();
318218893Sdim  if ((ScaledConstant % Scale) != 0)
319218893Sdim    return false;
320218893Sdim
321218893Sdim  ScaledConstant /= Scale;
322218893Sdim  return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
323218893Sdim}
324218893Sdim
325249423Sdimvoid ARMDAGToDAGISel::PreprocessISelDAG() {
326249423Sdim  if (!Subtarget->hasV6T2Ops())
327249423Sdim    return;
328249423Sdim
329249423Sdim  bool isThumb2 = Subtarget->isThumb();
330249423Sdim  for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
331249423Sdim       E = CurDAG->allnodes_end(); I != E; ) {
332249423Sdim    SDNode *N = I++;  // Preincrement iterator to avoid invalidation issues.
333249423Sdim
334249423Sdim    if (N->getOpcode() != ISD::ADD)
335249423Sdim      continue;
336249423Sdim
337249423Sdim    // Look for (add X1, (and (srl X2, c1), c2)) where c2 is constant with
338249423Sdim    // leading zeros, followed by consecutive set bits, followed by 1 or 2
339249423Sdim    // trailing zeros, e.g. 1020.
340249423Sdim    // Transform the expression to
341249423Sdim    // (add X1, (shl (and (srl X2, c1), (c2>>tz)), tz)) where tz is the number
342249423Sdim    // of trailing zeros of c2. The left shift would be folded as an shifter
343249423Sdim    // operand of 'add' and the 'and' and 'srl' would become a bits extraction
344249423Sdim    // node (UBFX).
345249423Sdim
346249423Sdim    SDValue N0 = N->getOperand(0);
347249423Sdim    SDValue N1 = N->getOperand(1);
348249423Sdim    unsigned And_imm = 0;
349249423Sdim    if (!isOpcWithIntImmediate(N1.getNode(), ISD::AND, And_imm)) {
350249423Sdim      if (isOpcWithIntImmediate(N0.getNode(), ISD::AND, And_imm))
351249423Sdim        std::swap(N0, N1);
352249423Sdim    }
353249423Sdim    if (!And_imm)
354249423Sdim      continue;
355249423Sdim
356249423Sdim    // Check if the AND mask is an immediate of the form: 000.....1111111100
357261991Sdim    unsigned TZ = countTrailingZeros(And_imm);
358249423Sdim    if (TZ != 1 && TZ != 2)
359249423Sdim      // Be conservative here. Shifter operands aren't always free. e.g. On
360249423Sdim      // Swift, left shifter operand of 1 / 2 for free but others are not.
361249423Sdim      // e.g.
362249423Sdim      //  ubfx   r3, r1, #16, #8
363249423Sdim      //  ldr.w  r3, [r0, r3, lsl #2]
364249423Sdim      // vs.
365249423Sdim      //  mov.w  r9, #1020
366249423Sdim      //  and.w  r2, r9, r1, lsr #14
367249423Sdim      //  ldr    r2, [r0, r2]
368249423Sdim      continue;
369249423Sdim    And_imm >>= TZ;
370249423Sdim    if (And_imm & (And_imm + 1))
371249423Sdim      continue;
372249423Sdim
373249423Sdim    // Look for (and (srl X, c1), c2).
374249423Sdim    SDValue Srl = N1.getOperand(0);
375249423Sdim    unsigned Srl_imm = 0;
376249423Sdim    if (!isOpcWithIntImmediate(Srl.getNode(), ISD::SRL, Srl_imm) ||
377249423Sdim        (Srl_imm <= 2))
378249423Sdim      continue;
379249423Sdim
380249423Sdim    // Make sure first operand is not a shifter operand which would prevent
381249423Sdim    // folding of the left shift.
382249423Sdim    SDValue CPTmp0;
383249423Sdim    SDValue CPTmp1;
384249423Sdim    SDValue CPTmp2;
385249423Sdim    if (isThumb2) {
386249423Sdim      if (SelectT2ShifterOperandReg(N0, CPTmp0, CPTmp1))
387249423Sdim        continue;
388249423Sdim    } else {
389249423Sdim      if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) ||
390249423Sdim          SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2))
391249423Sdim        continue;
392249423Sdim    }
393249423Sdim
394249423Sdim    // Now make the transformation.
395261991Sdim    Srl = CurDAG->getNode(ISD::SRL, SDLoc(Srl), MVT::i32,
396249423Sdim                          Srl.getOperand(0),
397249423Sdim                          CurDAG->getConstant(Srl_imm+TZ, MVT::i32));
398261991Sdim    N1 = CurDAG->getNode(ISD::AND, SDLoc(N1), MVT::i32,
399249423Sdim                         Srl, CurDAG->getConstant(And_imm, MVT::i32));
400261991Sdim    N1 = CurDAG->getNode(ISD::SHL, SDLoc(N1), MVT::i32,
401249423Sdim                         N1, CurDAG->getConstant(TZ, MVT::i32));
402249423Sdim    CurDAG->UpdateNodeOperands(N, N0, N1);
403276479Sdim  }
404249423Sdim}
405249423Sdim
406218893Sdim/// hasNoVMLxHazardUse - Return true if it's desirable to select a FP MLA / MLS
407218893Sdim/// node. VFP / NEON fp VMLA / VMLS instructions have special RAW hazards (at
408218893Sdim/// least on current ARM implementations) which should be avoidded.
409218893Sdimbool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const {
410218893Sdim  if (OptLevel == CodeGenOpt::None)
411218893Sdim    return true;
412218893Sdim
413218893Sdim  if (!CheckVMLxHazard)
414218893Sdim    return true;
415218893Sdim
416276479Sdim  if (!Subtarget->isCortexA7() && !Subtarget->isCortexA8() &&
417276479Sdim      !Subtarget->isCortexA9() && !Subtarget->isSwift())
418218893Sdim    return true;
419218893Sdim
420218893Sdim  if (!N->hasOneUse())
421218893Sdim    return false;
422218893Sdim
423218893Sdim  SDNode *Use = *N->use_begin();
424218893Sdim  if (Use->getOpcode() == ISD::CopyToReg)
425218893Sdim    return true;
426218893Sdim  if (Use->isMachineOpcode()) {
427276479Sdim    const ARMBaseInstrInfo *TII = static_cast<const ARMBaseInstrInfo *>(
428280031Sdim        CurDAG->getSubtarget().getInstrInfo());
429261991Sdim
430224145Sdim    const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode());
431224145Sdim    if (MCID.mayStore())
432218893Sdim      return true;
433224145Sdim    unsigned Opcode = MCID.getOpcode();
434218893Sdim    if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
435218893Sdim      return true;
436218893Sdim    // vmlx feeding into another vmlx. We actually want to unfold
437218893Sdim    // the use later in the MLxExpansion pass. e.g.
438218893Sdim    // vmla
439218893Sdim    // vmla (stall 8 cycles)
440218893Sdim    //
441218893Sdim    // vmul (5 cycles)
442218893Sdim    // vadd (5 cycles)
443218893Sdim    // vmla
444218893Sdim    // This adds up to about 18 - 19 cycles.
445218893Sdim    //
446218893Sdim    // vmla
447218893Sdim    // vmul (stall 4 cycles)
448218893Sdim    // vadd adds up to about 14 cycles.
449218893Sdim    return TII->isFpMLxInstruction(Opcode);
450218893Sdim  }
451218893Sdim
452218893Sdim  return false;
453218893Sdim}
454218893Sdim
455218893Sdimbool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift,
456218893Sdim                                            ARM_AM::ShiftOpc ShOpcVal,
457218893Sdim                                            unsigned ShAmt) {
458243830Sdim  if (!Subtarget->isLikeA9() && !Subtarget->isSwift())
459218893Sdim    return true;
460218893Sdim  if (Shift.hasOneUse())
461218893Sdim    return true;
462218893Sdim  // R << 2 is free.
463243830Sdim  return ShOpcVal == ARM_AM::lsl &&
464243830Sdim         (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1));
465218893Sdim}
466218893Sdim
467226633Sdimbool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N,
468195340Sed                                              SDValue &BaseReg,
469226633Sdim                                              SDValue &Opc,
470226633Sdim                                              bool CheckProfitability) {
471226633Sdim  if (DisableShifterOp)
472226633Sdim    return false;
473226633Sdim
474226633Sdim  ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
475226633Sdim
476226633Sdim  // Don't match base register only case. That is matched to a separate
477226633Sdim  // lower complexity pattern with explicit register operand.
478226633Sdim  if (ShOpcVal == ARM_AM::no_shift) return false;
479226633Sdim
480226633Sdim  BaseReg = N.getOperand(0);
481226633Sdim  unsigned ShImmVal = 0;
482226633Sdim  ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
483226633Sdim  if (!RHS) return false;
484226633Sdim  ShImmVal = RHS->getZExtValue() & 31;
485226633Sdim  Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
486226633Sdim                                  MVT::i32);
487226633Sdim  return true;
488226633Sdim}
489226633Sdim
490226633Sdimbool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N,
491226633Sdim                                              SDValue &BaseReg,
492195340Sed                                              SDValue &ShReg,
493221345Sdim                                              SDValue &Opc,
494221345Sdim                                              bool CheckProfitability) {
495212904Sdim  if (DisableShifterOp)
496212904Sdim    return false;
497212904Sdim
498226633Sdim  ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
499195340Sed
500195340Sed  // Don't match base register only case. That is matched to a separate
501195340Sed  // lower complexity pattern with explicit register operand.
502195340Sed  if (ShOpcVal == ARM_AM::no_shift) return false;
503198090Srdivacky
504195340Sed  BaseReg = N.getOperand(0);
505195340Sed  unsigned ShImmVal = 0;
506226633Sdim  ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
507226633Sdim  if (RHS) return false;
508226633Sdim
509226633Sdim  ShReg = N.getOperand(1);
510226633Sdim  if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
511226633Sdim    return false;
512195340Sed  Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
513195340Sed                                  MVT::i32);
514195340Sed  return true;
515195340Sed}
516195340Sed
517226633Sdim
518218893Sdimbool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
519218893Sdim                                          SDValue &Base,
520218893Sdim                                          SDValue &OffImm) {
521218893Sdim  // Match simple R + imm12 operands.
522218893Sdim
523218893Sdim  // Base only.
524218893Sdim  if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
525218893Sdim      !CurDAG->isBaseWithConstantOffset(N)) {
526218893Sdim    if (N.getOpcode() == ISD::FrameIndex) {
527218893Sdim      // Match frame index.
528218893Sdim      int FI = cast<FrameIndexSDNode>(N)->getIndex();
529280031Sdim      Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
530218893Sdim      OffImm  = CurDAG->getTargetConstant(0, MVT::i32);
531218893Sdim      return true;
532218893Sdim    }
533221345Sdim
534218893Sdim    if (N.getOpcode() == ARMISD::Wrapper &&
535276479Sdim        N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) {
536218893Sdim      Base = N.getOperand(0);
537218893Sdim    } else
538218893Sdim      Base = N;
539218893Sdim    OffImm  = CurDAG->getTargetConstant(0, MVT::i32);
540218893Sdim    return true;
541218893Sdim  }
542218893Sdim
543218893Sdim  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
544280031Sdim    int RHSC = (int)RHS->getSExtValue();
545218893Sdim    if (N.getOpcode() == ISD::SUB)
546218893Sdim      RHSC = -RHSC;
547218893Sdim
548280031Sdim    if (RHSC > -0x1000 && RHSC < 0x1000) { // 12 bits
549218893Sdim      Base   = N.getOperand(0);
550218893Sdim      if (Base.getOpcode() == ISD::FrameIndex) {
551218893Sdim        int FI = cast<FrameIndexSDNode>(Base)->getIndex();
552280031Sdim        Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
553218893Sdim      }
554218893Sdim      OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
555218893Sdim      return true;
556218893Sdim    }
557218893Sdim  }
558218893Sdim
559218893Sdim  // Base only.
560218893Sdim  Base = N;
561218893Sdim  OffImm  = CurDAG->getTargetConstant(0, MVT::i32);
562218893Sdim  return true;
563218893Sdim}
564218893Sdim
565218893Sdim
566218893Sdim
567218893Sdimbool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
568193323Sed                                      SDValue &Opc) {
569218893Sdim  if (N.getOpcode() == ISD::MUL &&
570243830Sdim      ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) {
571193323Sed    if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
572193323Sed      // X * [3,5,9] -> X + X * [2,4,8] etc.
573193323Sed      int RHSC = (int)RHS->getZExtValue();
574193323Sed      if (RHSC & 1) {
575193323Sed        RHSC = RHSC & ~1;
576193323Sed        ARM_AM::AddrOpc AddSub = ARM_AM::add;
577193323Sed        if (RHSC < 0) {
578193323Sed          AddSub = ARM_AM::sub;
579193323Sed          RHSC = - RHSC;
580193323Sed        }
581193323Sed        if (isPowerOf2_32(RHSC)) {
582193323Sed          unsigned ShAmt = Log2_32(RHSC);
583193323Sed          Base = Offset = N.getOperand(0);
584193323Sed          Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
585193323Sed                                                            ARM_AM::lsl),
586193323Sed                                          MVT::i32);
587193323Sed          return true;
588193323Sed        }
589193323Sed      }
590193323Sed    }
591193323Sed  }
592193323Sed
593218893Sdim  if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
594218893Sdim      // ISD::OR that is equivalent to an ISD::ADD.
595218893Sdim      !CurDAG->isBaseWithConstantOffset(N))
596218893Sdim    return false;
597218893Sdim
598218893Sdim  // Leave simple R +/- imm12 operands for LDRi12
599218893Sdim  if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
600218893Sdim    int RHSC;
601218893Sdim    if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
602218893Sdim                                -0x1000+1, 0x1000, RHSC)) // 12 bits.
603218893Sdim      return false;
604218893Sdim  }
605218893Sdim
606218893Sdim  // Otherwise this is R +/- [possibly shifted] R.
607218893Sdim  ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add;
608226633Sdim  ARM_AM::ShiftOpc ShOpcVal =
609226633Sdim    ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
610218893Sdim  unsigned ShAmt = 0;
611218893Sdim
612218893Sdim  Base   = N.getOperand(0);
613218893Sdim  Offset = N.getOperand(1);
614218893Sdim
615218893Sdim  if (ShOpcVal != ARM_AM::no_shift) {
616218893Sdim    // Check to see if the RHS of the shift is a constant, if not, we can't fold
617218893Sdim    // it.
618218893Sdim    if (ConstantSDNode *Sh =
619218893Sdim           dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
620218893Sdim      ShAmt = Sh->getZExtValue();
621218893Sdim      if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
622218893Sdim        Offset = N.getOperand(1).getOperand(0);
623218893Sdim      else {
624218893Sdim        ShAmt = 0;
625218893Sdim        ShOpcVal = ARM_AM::no_shift;
626218893Sdim      }
627218893Sdim    } else {
628218893Sdim      ShOpcVal = ARM_AM::no_shift;
629218893Sdim    }
630218893Sdim  }
631218893Sdim
632218893Sdim  // Try matching (R shl C) + (R).
633218893Sdim  if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
634243830Sdim      !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
635243830Sdim        N.getOperand(0).hasOneUse())) {
636226633Sdim    ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
637218893Sdim    if (ShOpcVal != ARM_AM::no_shift) {
638218893Sdim      // Check to see if the RHS of the shift is a constant, if not, we can't
639218893Sdim      // fold it.
640218893Sdim      if (ConstantSDNode *Sh =
641218893Sdim          dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
642218893Sdim        ShAmt = Sh->getZExtValue();
643226633Sdim        if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
644218893Sdim          Offset = N.getOperand(0).getOperand(0);
645218893Sdim          Base = N.getOperand(1);
646218893Sdim        } else {
647218893Sdim          ShAmt = 0;
648218893Sdim          ShOpcVal = ARM_AM::no_shift;
649218893Sdim        }
650218893Sdim      } else {
651218893Sdim        ShOpcVal = ARM_AM::no_shift;
652218893Sdim      }
653218893Sdim    }
654218893Sdim  }
655218893Sdim
656218893Sdim  Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
657218893Sdim                                  MVT::i32);
658218893Sdim  return true;
659218893Sdim}
660218893Sdim
661218893Sdim
662218893Sdim//-----
663218893Sdim
664218893SdimAddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N,
665218893Sdim                                                     SDValue &Base,
666218893Sdim                                                     SDValue &Offset,
667218893Sdim                                                     SDValue &Opc) {
668218893Sdim  if (N.getOpcode() == ISD::MUL &&
669243830Sdim      (!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.hasOneUse())) {
670218893Sdim    if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
671218893Sdim      // X * [3,5,9] -> X + X * [2,4,8] etc.
672218893Sdim      int RHSC = (int)RHS->getZExtValue();
673218893Sdim      if (RHSC & 1) {
674218893Sdim        RHSC = RHSC & ~1;
675218893Sdim        ARM_AM::AddrOpc AddSub = ARM_AM::add;
676218893Sdim        if (RHSC < 0) {
677218893Sdim          AddSub = ARM_AM::sub;
678218893Sdim          RHSC = - RHSC;
679218893Sdim        }
680218893Sdim        if (isPowerOf2_32(RHSC)) {
681218893Sdim          unsigned ShAmt = Log2_32(RHSC);
682218893Sdim          Base = Offset = N.getOperand(0);
683218893Sdim          Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
684218893Sdim                                                            ARM_AM::lsl),
685218893Sdim                                          MVT::i32);
686218893Sdim          return AM2_SHOP;
687218893Sdim        }
688218893Sdim      }
689218893Sdim    }
690218893Sdim  }
691218893Sdim
692218893Sdim  if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
693218893Sdim      // ISD::OR that is equivalent to an ADD.
694218893Sdim      !CurDAG->isBaseWithConstantOffset(N)) {
695193323Sed    Base = N;
696193323Sed    if (N.getOpcode() == ISD::FrameIndex) {
697193323Sed      int FI = cast<FrameIndexSDNode>(N)->getIndex();
698280031Sdim      Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
699199989Srdivacky    } else if (N.getOpcode() == ARMISD::Wrapper &&
700276479Sdim               N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) {
701193323Sed      Base = N.getOperand(0);
702193323Sed    }
703193323Sed    Offset = CurDAG->getRegister(0, MVT::i32);
704193323Sed    Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
705193323Sed                                                      ARM_AM::no_shift),
706193323Sed                                    MVT::i32);
707218893Sdim    return AM2_BASE;
708193323Sed  }
709198090Srdivacky
710193323Sed  // Match simple R +/- imm12 operands.
711218893Sdim  if (N.getOpcode() != ISD::SUB) {
712218893Sdim    int RHSC;
713218893Sdim    if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
714218893Sdim                                -0x1000+1, 0x1000, RHSC)) { // 12 bits.
715218893Sdim      Base = N.getOperand(0);
716218893Sdim      if (Base.getOpcode() == ISD::FrameIndex) {
717218893Sdim        int FI = cast<FrameIndexSDNode>(Base)->getIndex();
718280031Sdim        Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
719218893Sdim      }
720218893Sdim      Offset = CurDAG->getRegister(0, MVT::i32);
721193323Sed
722218893Sdim      ARM_AM::AddrOpc AddSub = ARM_AM::add;
723218893Sdim      if (RHSC < 0) {
724218893Sdim        AddSub = ARM_AM::sub;
725218893Sdim        RHSC = - RHSC;
726193323Sed      }
727218893Sdim      Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC,
728218893Sdim                                                        ARM_AM::no_shift),
729218893Sdim                                      MVT::i32);
730218893Sdim      return AM2_BASE;
731193323Sed    }
732218893Sdim  }
733198090Srdivacky
734243830Sdim  if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.hasOneUse()) {
735218893Sdim    // Compute R +/- (R << N) and reuse it.
736218893Sdim    Base = N;
737218893Sdim    Offset = CurDAG->getRegister(0, MVT::i32);
738218893Sdim    Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
739218893Sdim                                                      ARM_AM::no_shift),
740218893Sdim                                    MVT::i32);
741218893Sdim    return AM2_BASE;
742218893Sdim  }
743218893Sdim
744198892Srdivacky  // Otherwise this is R +/- [possibly shifted] R.
745218893Sdim  ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub;
746226633Sdim  ARM_AM::ShiftOpc ShOpcVal =
747226633Sdim    ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
748193323Sed  unsigned ShAmt = 0;
749198090Srdivacky
750193323Sed  Base   = N.getOperand(0);
751193323Sed  Offset = N.getOperand(1);
752198090Srdivacky
753193323Sed  if (ShOpcVal != ARM_AM::no_shift) {
754193323Sed    // Check to see if the RHS of the shift is a constant, if not, we can't fold
755193323Sed    // it.
756193323Sed    if (ConstantSDNode *Sh =
757193323Sed           dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
758193323Sed      ShAmt = Sh->getZExtValue();
759218893Sdim      if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
760218893Sdim        Offset = N.getOperand(1).getOperand(0);
761218893Sdim      else {
762218893Sdim        ShAmt = 0;
763218893Sdim        ShOpcVal = ARM_AM::no_shift;
764218893Sdim      }
765193323Sed    } else {
766193323Sed      ShOpcVal = ARM_AM::no_shift;
767193323Sed    }
768193323Sed  }
769198090Srdivacky
770193323Sed  // Try matching (R shl C) + (R).
771218893Sdim  if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
772243830Sdim      !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
773243830Sdim        N.getOperand(0).hasOneUse())) {
774226633Sdim    ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
775193323Sed    if (ShOpcVal != ARM_AM::no_shift) {
776193323Sed      // Check to see if the RHS of the shift is a constant, if not, we can't
777193323Sed      // fold it.
778193323Sed      if (ConstantSDNode *Sh =
779193323Sed          dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
780193323Sed        ShAmt = Sh->getZExtValue();
781226633Sdim        if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
782218893Sdim          Offset = N.getOperand(0).getOperand(0);
783218893Sdim          Base = N.getOperand(1);
784218893Sdim        } else {
785218893Sdim          ShAmt = 0;
786218893Sdim          ShOpcVal = ARM_AM::no_shift;
787218893Sdim        }
788193323Sed      } else {
789193323Sed        ShOpcVal = ARM_AM::no_shift;
790193323Sed      }
791193323Sed    }
792193323Sed  }
793198090Srdivacky
794193323Sed  Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
795193323Sed                                  MVT::i32);
796218893Sdim  return AM2_SHOP;
797193323Sed}
798193323Sed
799226633Sdimbool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
800193323Sed                                            SDValue &Offset, SDValue &Opc) {
801202375Srdivacky  unsigned Opcode = Op->getOpcode();
802193323Sed  ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
803193323Sed    ? cast<LoadSDNode>(Op)->getAddressingMode()
804193323Sed    : cast<StoreSDNode>(Op)->getAddressingMode();
805193323Sed  ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
806193323Sed    ? ARM_AM::add : ARM_AM::sub;
807218893Sdim  int Val;
808226633Sdim  if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val))
809226633Sdim    return false;
810193323Sed
811193323Sed  Offset = N;
812226633Sdim  ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
813193323Sed  unsigned ShAmt = 0;
814193323Sed  if (ShOpcVal != ARM_AM::no_shift) {
815193323Sed    // Check to see if the RHS of the shift is a constant, if not, we can't fold
816193323Sed    // it.
817193323Sed    if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
818193323Sed      ShAmt = Sh->getZExtValue();
819218893Sdim      if (isShifterOpProfitable(N, ShOpcVal, ShAmt))
820218893Sdim        Offset = N.getOperand(0);
821218893Sdim      else {
822218893Sdim        ShAmt = 0;
823218893Sdim        ShOpcVal = ARM_AM::no_shift;
824218893Sdim      }
825193323Sed    } else {
826193323Sed      ShOpcVal = ARM_AM::no_shift;
827193323Sed    }
828193323Sed  }
829193323Sed
830193323Sed  Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
831193323Sed                                  MVT::i32);
832193323Sed  return true;
833193323Sed}
834193323Sed
835226633Sdimbool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
836226633Sdim                                            SDValue &Offset, SDValue &Opc) {
837226633Sdim  unsigned Opcode = Op->getOpcode();
838226633Sdim  ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
839226633Sdim    ? cast<LoadSDNode>(Op)->getAddressingMode()
840226633Sdim    : cast<StoreSDNode>(Op)->getAddressingMode();
841226633Sdim  ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
842226633Sdim    ? ARM_AM::add : ARM_AM::sub;
843226633Sdim  int Val;
844226633Sdim  if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
845226633Sdim    if (AddSub == ARM_AM::sub) Val *= -1;
846226633Sdim    Offset = CurDAG->getRegister(0, MVT::i32);
847226633Sdim    Opc = CurDAG->getTargetConstant(Val, MVT::i32);
848226633Sdim    return true;
849226633Sdim  }
850193323Sed
851226633Sdim  return false;
852226633Sdim}
853226633Sdim
854226633Sdim
855226633Sdimbool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
856226633Sdim                                            SDValue &Offset, SDValue &Opc) {
857226633Sdim  unsigned Opcode = Op->getOpcode();
858226633Sdim  ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
859226633Sdim    ? cast<LoadSDNode>(Op)->getAddressingMode()
860226633Sdim    : cast<StoreSDNode>(Op)->getAddressingMode();
861226633Sdim  ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
862226633Sdim    ? ARM_AM::add : ARM_AM::sub;
863226633Sdim  int Val;
864226633Sdim  if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
865226633Sdim    Offset = CurDAG->getRegister(0, MVT::i32);
866226633Sdim    Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
867226633Sdim                                                      ARM_AM::no_shift),
868226633Sdim                                    MVT::i32);
869226633Sdim    return true;
870226633Sdim  }
871226633Sdim
872226633Sdim  return false;
873226633Sdim}
874226633Sdim
875226633Sdimbool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) {
876226633Sdim  Base = N;
877226633Sdim  return true;
878226633Sdim}
879226633Sdim
880218893Sdimbool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
881193323Sed                                      SDValue &Base, SDValue &Offset,
882193323Sed                                      SDValue &Opc) {
883193323Sed  if (N.getOpcode() == ISD::SUB) {
884193323Sed    // X - C  is canonicalize to X + -C, no need to handle it here.
885193323Sed    Base = N.getOperand(0);
886193323Sed    Offset = N.getOperand(1);
887193323Sed    Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32);
888193323Sed    return true;
889193323Sed  }
890198090Srdivacky
891218893Sdim  if (!CurDAG->isBaseWithConstantOffset(N)) {
892193323Sed    Base = N;
893193323Sed    if (N.getOpcode() == ISD::FrameIndex) {
894193323Sed      int FI = cast<FrameIndexSDNode>(N)->getIndex();
895280031Sdim      Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
896193323Sed    }
897193323Sed    Offset = CurDAG->getRegister(0, MVT::i32);
898193323Sed    Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32);
899193323Sed    return true;
900193323Sed  }
901198090Srdivacky
902193323Sed  // If the RHS is +/- imm8, fold into addr mode.
903218893Sdim  int RHSC;
904218893Sdim  if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
905218893Sdim                              -256 + 1, 256, RHSC)) { // 8 bits.
906218893Sdim    Base = N.getOperand(0);
907218893Sdim    if (Base.getOpcode() == ISD::FrameIndex) {
908218893Sdim      int FI = cast<FrameIndexSDNode>(Base)->getIndex();
909280031Sdim      Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
910218893Sdim    }
911218893Sdim    Offset = CurDAG->getRegister(0, MVT::i32);
912193323Sed
913218893Sdim    ARM_AM::AddrOpc AddSub = ARM_AM::add;
914218893Sdim    if (RHSC < 0) {
915218893Sdim      AddSub = ARM_AM::sub;
916218893Sdim      RHSC = -RHSC;
917193323Sed    }
918218893Sdim    Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32);
919218893Sdim    return true;
920193323Sed  }
921198090Srdivacky
922193323Sed  Base = N.getOperand(0);
923193323Sed  Offset = N.getOperand(1);
924193323Sed  Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32);
925193323Sed  return true;
926193323Sed}
927193323Sed
928202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
929193323Sed                                            SDValue &Offset, SDValue &Opc) {
930202375Srdivacky  unsigned Opcode = Op->getOpcode();
931193323Sed  ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
932193323Sed    ? cast<LoadSDNode>(Op)->getAddressingMode()
933193323Sed    : cast<StoreSDNode>(Op)->getAddressingMode();
934193323Sed  ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
935193323Sed    ? ARM_AM::add : ARM_AM::sub;
936218893Sdim  int Val;
937218893Sdim  if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits.
938218893Sdim    Offset = CurDAG->getRegister(0, MVT::i32);
939218893Sdim    Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32);
940218893Sdim    return true;
941193323Sed  }
942193323Sed
943193323Sed  Offset = N;
944193323Sed  Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32);
945193323Sed  return true;
946193323Sed}
947193323Sed
948218893Sdimbool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
949193323Sed                                      SDValue &Base, SDValue &Offset) {
950218893Sdim  if (!CurDAG->isBaseWithConstantOffset(N)) {
951193323Sed    Base = N;
952193323Sed    if (N.getOpcode() == ISD::FrameIndex) {
953193323Sed      int FI = cast<FrameIndexSDNode>(N)->getIndex();
954280031Sdim      Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
955199989Srdivacky    } else if (N.getOpcode() == ARMISD::Wrapper &&
956276479Sdim               N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) {
957193323Sed      Base = N.getOperand(0);
958193323Sed    }
959193323Sed    Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
960193323Sed                                       MVT::i32);
961193323Sed    return true;
962193323Sed  }
963198090Srdivacky
964193323Sed  // If the RHS is +/- imm8, fold into addr mode.
965218893Sdim  int RHSC;
966218893Sdim  if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4,
967218893Sdim                              -256 + 1, 256, RHSC)) {
968218893Sdim    Base = N.getOperand(0);
969218893Sdim    if (Base.getOpcode() == ISD::FrameIndex) {
970218893Sdim      int FI = cast<FrameIndexSDNode>(Base)->getIndex();
971280031Sdim      Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
972218893Sdim    }
973193323Sed
974218893Sdim    ARM_AM::AddrOpc AddSub = ARM_AM::add;
975218893Sdim    if (RHSC < 0) {
976218893Sdim      AddSub = ARM_AM::sub;
977218893Sdim      RHSC = -RHSC;
978193323Sed    }
979218893Sdim    Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
980218893Sdim                                       MVT::i32);
981218893Sdim    return true;
982193323Sed  }
983198090Srdivacky
984193323Sed  Base = N;
985193323Sed  Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
986193323Sed                                     MVT::i32);
987193323Sed  return true;
988193323Sed}
989193323Sed
990218893Sdimbool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
991218893Sdim                                      SDValue &Align) {
992195340Sed  Addr = N;
993218893Sdim
994218893Sdim  unsigned Alignment = 0;
995218893Sdim  if (LSBaseSDNode *LSN = dyn_cast<LSBaseSDNode>(Parent)) {
996218893Sdim    // This case occurs only for VLD1-lane/dup and VST1-lane instructions.
997218893Sdim    // The maximum alignment is equal to the memory size being referenced.
998218893Sdim    unsigned LSNAlign = LSN->getAlignment();
999218893Sdim    unsigned MemSize = LSN->getMemoryVT().getSizeInBits() / 8;
1000234353Sdim    if (LSNAlign >= MemSize && MemSize > 1)
1001218893Sdim      Alignment = MemSize;
1002218893Sdim  } else {
1003218893Sdim    // All other uses of addrmode6 are for intrinsics.  For now just record
1004218893Sdim    // the raw alignment value; it will be refined later based on the legal
1005218893Sdim    // alignment operands for the intrinsic.
1006218893Sdim    Alignment = cast<MemIntrinsicSDNode>(Parent)->getAlignment();
1007218893Sdim  }
1008218893Sdim
1009218893Sdim  Align = CurDAG->getTargetConstant(Alignment, MVT::i32);
1010195340Sed  return true;
1011195340Sed}
1012195340Sed
1013219077Sdimbool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N,
1014219077Sdim                                            SDValue &Offset) {
1015219077Sdim  LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op);
1016219077Sdim  ISD::MemIndexedMode AM = LdSt->getAddressingMode();
1017219077Sdim  if (AM != ISD::POST_INC)
1018219077Sdim    return false;
1019219077Sdim  Offset = N;
1020219077Sdim  if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) {
1021219077Sdim    if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits())
1022219077Sdim      Offset = CurDAG->getRegister(0, MVT::i32);
1023219077Sdim  }
1024219077Sdim  return true;
1025219077Sdim}
1026219077Sdim
1027218893Sdimbool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
1028198090Srdivacky                                       SDValue &Offset, SDValue &Label) {
1029193323Sed  if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
1030193323Sed    Offset = N.getOperand(0);
1031193323Sed    SDValue N1 = N.getOperand(1);
1032218893Sdim    Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
1033218893Sdim                                      MVT::i32);
1034193323Sed    return true;
1035193323Sed  }
1036218893Sdim
1037193323Sed  return false;
1038193323Sed}
1039193323Sed
1040218893Sdim
1041218893Sdim//===----------------------------------------------------------------------===//
1042218893Sdim//                         Thumb Addressing Modes
1043218893Sdim//===----------------------------------------------------------------------===//
1044218893Sdim
1045218893Sdimbool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
1046193323Sed                                            SDValue &Base, SDValue &Offset){
1047218893Sdim  if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) {
1048198090Srdivacky    ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
1049210299Sed    if (!NC || !NC->isNullValue())
1050198090Srdivacky      return false;
1051198090Srdivacky
1052198090Srdivacky    Base = Offset = N;
1053193323Sed    return true;
1054193323Sed  }
1055193323Sed
1056193323Sed  Base = N.getOperand(0);
1057193323Sed  Offset = N.getOperand(1);
1058193323Sed  return true;
1059193323Sed}
1060193323Sed
1061193323Sedbool
1062218893SdimARMDAGToDAGISel::SelectThumbAddrModeRI(SDValue N, SDValue &Base,
1063218893Sdim                                       SDValue &Offset, unsigned Scale) {
1064193323Sed  if (Scale == 4) {
1065193323Sed    SDValue TmpBase, TmpOffImm;
1066218893Sdim    if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm))
1067193323Sed      return false;  // We want to select tLDRspi / tSTRspi instead.
1068218893Sdim
1069193323Sed    if (N.getOpcode() == ARMISD::Wrapper &&
1070193323Sed        N.getOperand(0).getOpcode() == ISD::TargetConstantPool)
1071193323Sed      return false;  // We want to select tLDRpci instead.
1072193323Sed  }
1073193323Sed
1074218893Sdim  if (!CurDAG->isBaseWithConstantOffset(N))
1075218893Sdim    return false;
1076218893Sdim
1077218893Sdim  // Thumb does not have [sp, r] address mode.
1078218893Sdim  RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
1079218893Sdim  RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1));
1080218893Sdim  if ((LHSR && LHSR->getReg() == ARM::SP) ||
1081218893Sdim      (RHSR && RHSR->getReg() == ARM::SP))
1082218893Sdim    return false;
1083218893Sdim
1084218893Sdim  // FIXME: Why do we explicitly check for a match here and then return false?
1085218893Sdim  // Presumably to allow something else to match, but shouldn't this be
1086218893Sdim  // documented?
1087218893Sdim  int RHSC;
1088218893Sdim  if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC))
1089218893Sdim    return false;
1090218893Sdim
1091218893Sdim  Base = N.getOperand(0);
1092218893Sdim  Offset = N.getOperand(1);
1093218893Sdim  return true;
1094218893Sdim}
1095218893Sdim
1096218893Sdimbool
1097218893SdimARMDAGToDAGISel::SelectThumbAddrModeRI5S1(SDValue N,
1098218893Sdim                                          SDValue &Base,
1099218893Sdim                                          SDValue &Offset) {
1100218893Sdim  return SelectThumbAddrModeRI(N, Base, Offset, 1);
1101218893Sdim}
1102218893Sdim
1103218893Sdimbool
1104218893SdimARMDAGToDAGISel::SelectThumbAddrModeRI5S2(SDValue N,
1105218893Sdim                                          SDValue &Base,
1106218893Sdim                                          SDValue &Offset) {
1107218893Sdim  return SelectThumbAddrModeRI(N, Base, Offset, 2);
1108218893Sdim}
1109218893Sdim
1110218893Sdimbool
1111218893SdimARMDAGToDAGISel::SelectThumbAddrModeRI5S4(SDValue N,
1112218893Sdim                                          SDValue &Base,
1113218893Sdim                                          SDValue &Offset) {
1114218893Sdim  return SelectThumbAddrModeRI(N, Base, Offset, 4);
1115218893Sdim}
1116218893Sdim
1117218893Sdimbool
1118218893SdimARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale,
1119218893Sdim                                          SDValue &Base, SDValue &OffImm) {
1120218893Sdim  if (Scale == 4) {
1121218893Sdim    SDValue TmpBase, TmpOffImm;
1122218893Sdim    if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm))
1123218893Sdim      return false;  // We want to select tLDRspi / tSTRspi instead.
1124218893Sdim
1125199989Srdivacky    if (N.getOpcode() == ARMISD::Wrapper &&
1126218893Sdim        N.getOperand(0).getOpcode() == ISD::TargetConstantPool)
1127218893Sdim      return false;  // We want to select tLDRpci instead.
1128218893Sdim  }
1129218893Sdim
1130218893Sdim  if (!CurDAG->isBaseWithConstantOffset(N)) {
1131218893Sdim    if (N.getOpcode() == ARMISD::Wrapper &&
1132276479Sdim        N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) {
1133199989Srdivacky      Base = N.getOperand(0);
1134218893Sdim    } else {
1135199989Srdivacky      Base = N;
1136218893Sdim    }
1137199989Srdivacky
1138193323Sed    OffImm = CurDAG->getTargetConstant(0, MVT::i32);
1139193323Sed    return true;
1140193323Sed  }
1141193323Sed
1142193323Sed  RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
1143193323Sed  RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1));
1144193323Sed  if ((LHSR && LHSR->getReg() == ARM::SP) ||
1145193323Sed      (RHSR && RHSR->getReg() == ARM::SP)) {
1146218893Sdim    ConstantSDNode *LHS = dyn_cast<ConstantSDNode>(N.getOperand(0));
1147218893Sdim    ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1148218893Sdim    unsigned LHSC = LHS ? LHS->getZExtValue() : 0;
1149218893Sdim    unsigned RHSC = RHS ? RHS->getZExtValue() : 0;
1150218893Sdim
1151218893Sdim    // Thumb does not have [sp, #imm5] address mode for non-zero imm5.
1152218893Sdim    if (LHSC != 0 || RHSC != 0) return false;
1153218893Sdim
1154193323Sed    Base = N;
1155193323Sed    OffImm = CurDAG->getTargetConstant(0, MVT::i32);
1156193323Sed    return true;
1157193323Sed  }
1158193323Sed
1159193323Sed  // If the RHS is + imm5 * scale, fold into addr mode.
1160218893Sdim  int RHSC;
1161218893Sdim  if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) {
1162218893Sdim    Base = N.getOperand(0);
1163218893Sdim    OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
1164218893Sdim    return true;
1165193323Sed  }
1166193323Sed
1167193323Sed  Base = N.getOperand(0);
1168193323Sed  OffImm = CurDAG->getTargetConstant(0, MVT::i32);
1169193323Sed  return true;
1170193323Sed}
1171193323Sed
1172218893Sdimbool
1173218893SdimARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
1174218893Sdim                                           SDValue &OffImm) {
1175218893Sdim  return SelectThumbAddrModeImm5S(N, 4, Base, OffImm);
1176193323Sed}
1177193323Sed
1178218893Sdimbool
1179218893SdimARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
1180218893Sdim                                           SDValue &OffImm) {
1181218893Sdim  return SelectThumbAddrModeImm5S(N, 2, Base, OffImm);
1182193323Sed}
1183193323Sed
1184218893Sdimbool
1185218893SdimARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
1186218893Sdim                                           SDValue &OffImm) {
1187218893Sdim  return SelectThumbAddrModeImm5S(N, 1, Base, OffImm);
1188193323Sed}
1189193323Sed
1190218893Sdimbool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N,
1191218893Sdim                                            SDValue &Base, SDValue &OffImm) {
1192193323Sed  if (N.getOpcode() == ISD::FrameIndex) {
1193193323Sed    int FI = cast<FrameIndexSDNode>(N)->getIndex();
1194280031Sdim    Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
1195193323Sed    OffImm = CurDAG->getTargetConstant(0, MVT::i32);
1196193323Sed    return true;
1197193323Sed  }
1198193323Sed
1199218893Sdim  if (!CurDAG->isBaseWithConstantOffset(N))
1200193323Sed    return false;
1201193323Sed
1202193323Sed  RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
1203193323Sed  if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
1204193323Sed      (LHSR && LHSR->getReg() == ARM::SP)) {
1205193323Sed    // If the RHS is + imm8 * scale, fold into addr mode.
1206218893Sdim    int RHSC;
1207218893Sdim    if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) {
1208218893Sdim      Base = N.getOperand(0);
1209218893Sdim      if (Base.getOpcode() == ISD::FrameIndex) {
1210218893Sdim        int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1211280031Sdim        Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
1212193323Sed      }
1213218893Sdim      OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
1214218893Sdim      return true;
1215193323Sed    }
1216193323Sed  }
1217198090Srdivacky
1218193323Sed  return false;
1219193323Sed}
1220193323Sed
1221218893Sdim
1222218893Sdim//===----------------------------------------------------------------------===//
1223218893Sdim//                        Thumb 2 Addressing Modes
1224218893Sdim//===----------------------------------------------------------------------===//
1225218893Sdim
1226218893Sdim
1227218893Sdimbool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue N, SDValue &BaseReg,
1228195098Sed                                                SDValue &Opc) {
1229212904Sdim  if (DisableShifterOp)
1230212904Sdim    return false;
1231212904Sdim
1232226633Sdim  ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
1233195098Sed
1234195098Sed  // Don't match base register only case. That is matched to a separate
1235195098Sed  // lower complexity pattern with explicit register operand.
1236195098Sed  if (ShOpcVal == ARM_AM::no_shift) return false;
1237195098Sed
1238195098Sed  BaseReg = N.getOperand(0);
1239195098Sed  unsigned ShImmVal = 0;
1240195098Sed  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1241195098Sed    ShImmVal = RHS->getZExtValue() & 31;
1242195098Sed    Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal));
1243195098Sed    return true;
1244195098Sed  }
1245195098Sed
1246195098Sed  return false;
1247195098Sed}
1248195098Sed
1249218893Sdimbool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N,
1250195340Sed                                            SDValue &Base, SDValue &OffImm) {
1251195340Sed  // Match simple R + imm12 operands.
1252195340Sed
1253198090Srdivacky  // Base only.
1254218893Sdim  if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1255218893Sdim      !CurDAG->isBaseWithConstantOffset(N)) {
1256198090Srdivacky    if (N.getOpcode() == ISD::FrameIndex) {
1257218893Sdim      // Match frame index.
1258198090Srdivacky      int FI = cast<FrameIndexSDNode>(N)->getIndex();
1259280031Sdim      Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
1260198090Srdivacky      OffImm  = CurDAG->getTargetConstant(0, MVT::i32);
1261198090Srdivacky      return true;
1262218893Sdim    }
1263221345Sdim
1264218893Sdim    if (N.getOpcode() == ARMISD::Wrapper &&
1265276479Sdim        N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) {
1266198090Srdivacky      Base = N.getOperand(0);
1267198090Srdivacky      if (Base.getOpcode() == ISD::TargetConstantPool)
1268198090Srdivacky        return false;  // We want to select t2LDRpci instead.
1269198090Srdivacky    } else
1270198090Srdivacky      Base = N;
1271198090Srdivacky    OffImm  = CurDAG->getTargetConstant(0, MVT::i32);
1272198090Srdivacky    return true;
1273198090Srdivacky  }
1274198090Srdivacky
1275195340Sed  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1276218893Sdim    if (SelectT2AddrModeImm8(N, Base, OffImm))
1277198090Srdivacky      // Let t2LDRi8 handle (R - imm8).
1278198090Srdivacky      return false;
1279198090Srdivacky
1280195340Sed    int RHSC = (int)RHS->getZExtValue();
1281198090Srdivacky    if (N.getOpcode() == ISD::SUB)
1282198090Srdivacky      RHSC = -RHSC;
1283198090Srdivacky
1284198090Srdivacky    if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
1285195340Sed      Base   = N.getOperand(0);
1286198090Srdivacky      if (Base.getOpcode() == ISD::FrameIndex) {
1287198090Srdivacky        int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1288280031Sdim        Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
1289198090Srdivacky      }
1290195340Sed      OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
1291195340Sed      return true;
1292195340Sed    }
1293195340Sed  }
1294195340Sed
1295198090Srdivacky  // Base only.
1296198090Srdivacky  Base = N;
1297198090Srdivacky  OffImm  = CurDAG->getTargetConstant(0, MVT::i32);
1298198090Srdivacky  return true;
1299195340Sed}
1300195340Sed
1301218893Sdimbool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N,
1302195340Sed                                           SDValue &Base, SDValue &OffImm) {
1303198090Srdivacky  // Match simple R - imm8 operands.
1304218893Sdim  if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1305218893Sdim      !CurDAG->isBaseWithConstantOffset(N))
1306218893Sdim    return false;
1307221345Sdim
1308218893Sdim  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1309218893Sdim    int RHSC = (int)RHS->getSExtValue();
1310218893Sdim    if (N.getOpcode() == ISD::SUB)
1311218893Sdim      RHSC = -RHSC;
1312198090Srdivacky
1313218893Sdim    if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
1314218893Sdim      Base = N.getOperand(0);
1315218893Sdim      if (Base.getOpcode() == ISD::FrameIndex) {
1316218893Sdim        int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1317280031Sdim        Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
1318195340Sed      }
1319218893Sdim      OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
1320218893Sdim      return true;
1321195340Sed    }
1322195340Sed  }
1323195340Sed
1324195340Sed  return false;
1325195340Sed}
1326195340Sed
1327202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
1328195340Sed                                                 SDValue &OffImm){
1329202375Srdivacky  unsigned Opcode = Op->getOpcode();
1330195340Sed  ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1331195340Sed    ? cast<LoadSDNode>(Op)->getAddressingMode()
1332195340Sed    : cast<StoreSDNode>(Op)->getAddressingMode();
1333218893Sdim  int RHSC;
1334218893Sdim  if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits.
1335218893Sdim    OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC))
1336218893Sdim      ? CurDAG->getTargetConstant(RHSC, MVT::i32)
1337218893Sdim      : CurDAG->getTargetConstant(-RHSC, MVT::i32);
1338218893Sdim    return true;
1339195340Sed  }
1340195340Sed
1341195340Sed  return false;
1342195340Sed}
1343195340Sed
1344218893Sdimbool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N,
1345195340Sed                                            SDValue &Base,
1346195340Sed                                            SDValue &OffReg, SDValue &ShImm) {
1347198090Srdivacky  // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
1348218893Sdim  if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N))
1349198090Srdivacky    return false;
1350198090Srdivacky
1351198090Srdivacky  // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
1352198090Srdivacky  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1353198090Srdivacky    int RHSC = (int)RHS->getZExtValue();
1354198090Srdivacky    if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
1355198090Srdivacky      return false;
1356198090Srdivacky    else if (RHSC < 0 && RHSC >= -255) // 8 bits
1357198090Srdivacky      return false;
1358195340Sed  }
1359195340Sed
1360195340Sed  // Look for (R + R) or (R + (R << [1,2,3])).
1361195340Sed  unsigned ShAmt = 0;
1362195340Sed  Base   = N.getOperand(0);
1363195340Sed  OffReg = N.getOperand(1);
1364195340Sed
1365195340Sed  // Swap if it is ((R << c) + R).
1366226633Sdim  ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode());
1367195340Sed  if (ShOpcVal != ARM_AM::lsl) {
1368226633Sdim    ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode());
1369195340Sed    if (ShOpcVal == ARM_AM::lsl)
1370195340Sed      std::swap(Base, OffReg);
1371198090Srdivacky  }
1372198090Srdivacky
1373195340Sed  if (ShOpcVal == ARM_AM::lsl) {
1374195340Sed    // Check to see if the RHS of the shift is a constant, if not, we can't fold
1375195340Sed    // it.
1376195340Sed    if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
1377195340Sed      ShAmt = Sh->getZExtValue();
1378218893Sdim      if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1379218893Sdim        OffReg = OffReg.getOperand(0);
1380218893Sdim      else {
1381195340Sed        ShAmt = 0;
1382218893Sdim      }
1383195340Sed    }
1384198090Srdivacky  }
1385198090Srdivacky
1386195340Sed  ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32);
1387195340Sed
1388195340Sed  return true;
1389195340Sed}
1390195340Sed
1391261991Sdimbool ARMDAGToDAGISel::SelectT2AddrModeExclusive(SDValue N, SDValue &Base,
1392261991Sdim                                                SDValue &OffImm) {
1393276479Sdim  // This *must* succeed since it's used for the irreplaceable ldrex and strex
1394261991Sdim  // instructions.
1395261991Sdim  Base = N;
1396261991Sdim  OffImm = CurDAG->getTargetConstant(0, MVT::i32);
1397261991Sdim
1398261991Sdim  if (N.getOpcode() != ISD::ADD || !CurDAG->isBaseWithConstantOffset(N))
1399261991Sdim    return true;
1400261991Sdim
1401261991Sdim  ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1402261991Sdim  if (!RHS)
1403261991Sdim    return true;
1404261991Sdim
1405261991Sdim  uint32_t RHSC = (int)RHS->getZExtValue();
1406261991Sdim  if (RHSC > 1020 || RHSC % 4 != 0)
1407261991Sdim    return true;
1408261991Sdim
1409261991Sdim  Base = N.getOperand(0);
1410261991Sdim  if (Base.getOpcode() == ISD::FrameIndex) {
1411261991Sdim    int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1412280031Sdim    Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
1413261991Sdim  }
1414261991Sdim
1415261991Sdim  OffImm = CurDAG->getTargetConstant(RHSC / 4, MVT::i32);
1416261991Sdim  return true;
1417261991Sdim}
1418261991Sdim
1419195340Sed//===--------------------------------------------------------------------===//
1420195340Sed
1421193323Sed/// getAL - Returns a ARMCC::AL immediate node.
1422193323Sedstatic inline SDValue getAL(SelectionDAG *CurDAG) {
1423193323Sed  return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32);
1424193323Sed}
1425193323Sed
1426202375SrdivackySDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) {
1427202375Srdivacky  LoadSDNode *LD = cast<LoadSDNode>(N);
1428195340Sed  ISD::MemIndexedMode AM = LD->getAddressingMode();
1429195340Sed  if (AM == ISD::UNINDEXED)
1430276479Sdim    return nullptr;
1431193323Sed
1432198090Srdivacky  EVT LoadedVT = LD->getMemoryVT();
1433195340Sed  SDValue Offset, AMOpc;
1434195340Sed  bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1435195340Sed  unsigned Opcode = 0;
1436195340Sed  bool Match = false;
1437226633Sdim  if (LoadedVT == MVT::i32 && isPre &&
1438226633Sdim      SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
1439226633Sdim    Opcode = ARM::LDR_PRE_IMM;
1440195340Sed    Match = true;
1441226633Sdim  } else if (LoadedVT == MVT::i32 && !isPre &&
1442226633Sdim      SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
1443226633Sdim    Opcode = ARM::LDR_POST_IMM;
1444226633Sdim    Match = true;
1445226633Sdim  } else if (LoadedVT == MVT::i32 &&
1446226633Sdim      SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
1447226633Sdim    Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
1448226633Sdim    Match = true;
1449226633Sdim
1450195340Sed  } else if (LoadedVT == MVT::i16 &&
1451202375Srdivacky             SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
1452195340Sed    Match = true;
1453195340Sed    Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
1454195340Sed      ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1455195340Sed      : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
1456195340Sed  } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
1457195340Sed    if (LD->getExtensionType() == ISD::SEXTLOAD) {
1458202375Srdivacky      if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
1459195340Sed        Match = true;
1460195340Sed        Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1461195340Sed      }
1462195340Sed    } else {
1463226633Sdim      if (isPre &&
1464226633Sdim          SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
1465195340Sed        Match = true;
1466226633Sdim        Opcode = ARM::LDRB_PRE_IMM;
1467226633Sdim      } else if (!isPre &&
1468226633Sdim                  SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
1469226633Sdim        Match = true;
1470226633Sdim        Opcode = ARM::LDRB_POST_IMM;
1471226633Sdim      } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
1472226633Sdim        Match = true;
1473226633Sdim        Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
1474195340Sed      }
1475195340Sed    }
1476195340Sed  }
1477195340Sed
1478195340Sed  if (Match) {
1479226633Sdim    if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1480226633Sdim      SDValue Chain = LD->getChain();
1481226633Sdim      SDValue Base = LD->getBasePtr();
1482226633Sdim      SDValue Ops[]= { Base, AMOpc, getAL(CurDAG),
1483226633Sdim                       CurDAG->getRegister(0, MVT::i32), Chain };
1484261991Sdim      return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
1485251662Sdim                                    MVT::i32, MVT::Other, Ops);
1486226633Sdim    } else {
1487226633Sdim      SDValue Chain = LD->getChain();
1488226633Sdim      SDValue Base = LD->getBasePtr();
1489226633Sdim      SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG),
1490226633Sdim                       CurDAG->getRegister(0, MVT::i32), Chain };
1491261991Sdim      return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
1492251662Sdim                                    MVT::i32, MVT::Other, Ops);
1493226633Sdim    }
1494195340Sed  }
1495195340Sed
1496276479Sdim  return nullptr;
1497195340Sed}
1498195340Sed
1499202375SrdivackySDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) {
1500202375Srdivacky  LoadSDNode *LD = cast<LoadSDNode>(N);
1501195340Sed  ISD::MemIndexedMode AM = LD->getAddressingMode();
1502195340Sed  if (AM == ISD::UNINDEXED)
1503276479Sdim    return nullptr;
1504195340Sed
1505198090Srdivacky  EVT LoadedVT = LD->getMemoryVT();
1506195340Sed  bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD;
1507195340Sed  SDValue Offset;
1508195340Sed  bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1509195340Sed  unsigned Opcode = 0;
1510195340Sed  bool Match = false;
1511202375Srdivacky  if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) {
1512198090Srdivacky    switch (LoadedVT.getSimpleVT().SimpleTy) {
1513195340Sed    case MVT::i32:
1514195340Sed      Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1515195340Sed      break;
1516195340Sed    case MVT::i16:
1517195340Sed      if (isSExtLd)
1518195340Sed        Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1519195340Sed      else
1520195340Sed        Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
1521195340Sed      break;
1522195340Sed    case MVT::i8:
1523195340Sed    case MVT::i1:
1524195340Sed      if (isSExtLd)
1525195340Sed        Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1526195340Sed      else
1527195340Sed        Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
1528195340Sed      break;
1529195340Sed    default:
1530276479Sdim      return nullptr;
1531195340Sed    }
1532195340Sed    Match = true;
1533195340Sed  }
1534195340Sed
1535195340Sed  if (Match) {
1536195340Sed    SDValue Chain = LD->getChain();
1537195340Sed    SDValue Base = LD->getBasePtr();
1538195340Sed    SDValue Ops[]= { Base, Offset, getAL(CurDAG),
1539195340Sed                     CurDAG->getRegister(0, MVT::i32), Chain };
1540261991Sdim    return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
1541251662Sdim                                  MVT::Other, Ops);
1542195340Sed  }
1543195340Sed
1544276479Sdim  return nullptr;
1545195340Sed}
1546195340Sed
1547249423Sdim/// \brief Form a GPRPair pseudo register from a pair of GPR regs.
1548249423SdimSDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) {
1549261991Sdim  SDLoc dl(V0.getNode());
1550224145Sdim  SDValue RegClass =
1551249423Sdim    CurDAG->getTargetConstant(ARM::GPRPairRegClassID, MVT::i32);
1552249423Sdim  SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, MVT::i32);
1553249423Sdim  SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, MVT::i32);
1554249423Sdim  const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1555251662Sdim  return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1556249423Sdim}
1557249423Sdim
1558249423Sdim/// \brief Form a D register from a pair of S registers.
1559249423SdimSDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) {
1560261991Sdim  SDLoc dl(V0.getNode());
1561249423Sdim  SDValue RegClass =
1562224145Sdim    CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, MVT::i32);
1563210299Sed  SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32);
1564210299Sed  SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32);
1565224145Sdim  const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1566251662Sdim  return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1567210299Sed}
1568210299Sed
1569249423Sdim/// \brief Form a quad register from a pair of D registers.
1570249423SdimSDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) {
1571261991Sdim  SDLoc dl(V0.getNode());
1572224145Sdim  SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, MVT::i32);
1573208599Srdivacky  SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32);
1574208599Srdivacky  SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32);
1575224145Sdim  const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1576251662Sdim  return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1577198090Srdivacky}
1578198090Srdivacky
1579249423Sdim/// \brief Form 4 consecutive D registers from a pair of Q registers.
1580249423SdimSDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT, SDValue V0, SDValue V1) {
1581261991Sdim  SDLoc dl(V0.getNode());
1582224145Sdim  SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, MVT::i32);
1583208599Srdivacky  SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32);
1584208599Srdivacky  SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32);
1585224145Sdim  const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1586251662Sdim  return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1587208599Srdivacky}
1588208599Srdivacky
1589249423Sdim/// \brief Form 4 consecutive S registers.
1590249423SdimSDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1,
1591210299Sed                                   SDValue V2, SDValue V3) {
1592261991Sdim  SDLoc dl(V0.getNode());
1593224145Sdim  SDValue RegClass =
1594224145Sdim    CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, MVT::i32);
1595210299Sed  SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32);
1596210299Sed  SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32);
1597210299Sed  SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, MVT::i32);
1598210299Sed  SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, MVT::i32);
1599224145Sdim  const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1600224145Sdim                                    V2, SubReg2, V3, SubReg3 };
1601251662Sdim  return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1602210299Sed}
1603210299Sed
1604249423Sdim/// \brief Form 4 consecutive D registers.
1605249423SdimSDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1,
1606208599Srdivacky                                   SDValue V2, SDValue V3) {
1607261991Sdim  SDLoc dl(V0.getNode());
1608224145Sdim  SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, MVT::i32);
1609208599Srdivacky  SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32);
1610208599Srdivacky  SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32);
1611208599Srdivacky  SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, MVT::i32);
1612208599Srdivacky  SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, MVT::i32);
1613224145Sdim  const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1614224145Sdim                                    V2, SubReg2, V3, SubReg3 };
1615251662Sdim  return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1616208599Srdivacky}
1617208599Srdivacky
1618249423Sdim/// \brief Form 4 consecutive Q registers.
1619249423SdimSDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1,
1620208599Srdivacky                                   SDValue V2, SDValue V3) {
1621261991Sdim  SDLoc dl(V0.getNode());
1622224145Sdim  SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, MVT::i32);
1623208599Srdivacky  SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32);
1624208599Srdivacky  SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32);
1625208599Srdivacky  SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, MVT::i32);
1626208599Srdivacky  SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, MVT::i32);
1627224145Sdim  const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1628224145Sdim                                    V2, SubReg2, V3, SubReg3 };
1629251662Sdim  return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1630208599Srdivacky}
1631208599Srdivacky
1632218893Sdim/// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand
1633218893Sdim/// of a NEON VLD or VST instruction.  The supported values depend on the
1634218893Sdim/// number of registers being loaded.
1635218893SdimSDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, unsigned NumVecs,
1636218893Sdim                                       bool is64BitVector) {
1637218893Sdim  unsigned NumRegs = NumVecs;
1638218893Sdim  if (!is64BitVector && NumVecs < 3)
1639218893Sdim    NumRegs *= 2;
1640208599Srdivacky
1641218893Sdim  unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
1642218893Sdim  if (Alignment >= 32 && NumRegs == 4)
1643218893Sdim    Alignment = 32;
1644218893Sdim  else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1645218893Sdim    Alignment = 16;
1646218893Sdim  else if (Alignment >= 8)
1647218893Sdim    Alignment = 8;
1648218893Sdim  else
1649218893Sdim    Alignment = 0;
1650218893Sdim
1651218893Sdim  return CurDAG->getTargetConstant(Alignment, MVT::i32);
1652198090Srdivacky}
1653198090Srdivacky
1654265925Sdimstatic bool isVLDfixed(unsigned Opc)
1655265925Sdim{
1656265925Sdim  switch (Opc) {
1657265925Sdim  default: return false;
1658265925Sdim  case ARM::VLD1d8wb_fixed : return true;
1659265925Sdim  case ARM::VLD1d16wb_fixed : return true;
1660265925Sdim  case ARM::VLD1d64Qwb_fixed : return true;
1661265925Sdim  case ARM::VLD1d32wb_fixed : return true;
1662265925Sdim  case ARM::VLD1d64wb_fixed : return true;
1663265925Sdim  case ARM::VLD1d64TPseudoWB_fixed : return true;
1664265925Sdim  case ARM::VLD1d64QPseudoWB_fixed : return true;
1665265925Sdim  case ARM::VLD1q8wb_fixed : return true;
1666265925Sdim  case ARM::VLD1q16wb_fixed : return true;
1667265925Sdim  case ARM::VLD1q32wb_fixed : return true;
1668265925Sdim  case ARM::VLD1q64wb_fixed : return true;
1669265925Sdim  case ARM::VLD2d8wb_fixed : return true;
1670265925Sdim  case ARM::VLD2d16wb_fixed : return true;
1671265925Sdim  case ARM::VLD2d32wb_fixed : return true;
1672265925Sdim  case ARM::VLD2q8PseudoWB_fixed : return true;
1673265925Sdim  case ARM::VLD2q16PseudoWB_fixed : return true;
1674265925Sdim  case ARM::VLD2q32PseudoWB_fixed : return true;
1675265925Sdim  case ARM::VLD2DUPd8wb_fixed : return true;
1676265925Sdim  case ARM::VLD2DUPd16wb_fixed : return true;
1677265925Sdim  case ARM::VLD2DUPd32wb_fixed : return true;
1678265925Sdim  }
1679265925Sdim}
1680265925Sdim
1681265925Sdimstatic bool isVSTfixed(unsigned Opc)
1682265925Sdim{
1683265925Sdim  switch (Opc) {
1684265925Sdim  default: return false;
1685265925Sdim  case ARM::VST1d8wb_fixed : return true;
1686265925Sdim  case ARM::VST1d16wb_fixed : return true;
1687265925Sdim  case ARM::VST1d32wb_fixed : return true;
1688265925Sdim  case ARM::VST1d64wb_fixed : return true;
1689276479Sdim  case ARM::VST1q8wb_fixed : return true;
1690276479Sdim  case ARM::VST1q16wb_fixed : return true;
1691276479Sdim  case ARM::VST1q32wb_fixed : return true;
1692276479Sdim  case ARM::VST1q64wb_fixed : return true;
1693265925Sdim  case ARM::VST1d64TPseudoWB_fixed : return true;
1694265925Sdim  case ARM::VST1d64QPseudoWB_fixed : return true;
1695265925Sdim  case ARM::VST2d8wb_fixed : return true;
1696265925Sdim  case ARM::VST2d16wb_fixed : return true;
1697265925Sdim  case ARM::VST2d32wb_fixed : return true;
1698265925Sdim  case ARM::VST2q8PseudoWB_fixed : return true;
1699265925Sdim  case ARM::VST2q16PseudoWB_fixed : return true;
1700265925Sdim  case ARM::VST2q32PseudoWB_fixed : return true;
1701265925Sdim  }
1702265925Sdim}
1703265925Sdim
1704234353Sdim// Get the register stride update opcode of a VLD/VST instruction that
1705234353Sdim// is otherwise equivalent to the given fixed stride updating instruction.
1706234353Sdimstatic unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) {
1707265925Sdim  assert((isVLDfixed(Opc) || isVSTfixed(Opc))
1708265925Sdim    && "Incorrect fixed stride updating instruction.");
1709234353Sdim  switch (Opc) {
1710234353Sdim  default: break;
1711234353Sdim  case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register;
1712234353Sdim  case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register;
1713234353Sdim  case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register;
1714234353Sdim  case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register;
1715234353Sdim  case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register;
1716234353Sdim  case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register;
1717234353Sdim  case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register;
1718234353Sdim  case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register;
1719265925Sdim  case ARM::VLD1d64Twb_fixed: return ARM::VLD1d64Twb_register;
1720265925Sdim  case ARM::VLD1d64Qwb_fixed: return ARM::VLD1d64Qwb_register;
1721265925Sdim  case ARM::VLD1d64TPseudoWB_fixed: return ARM::VLD1d64TPseudoWB_register;
1722265925Sdim  case ARM::VLD1d64QPseudoWB_fixed: return ARM::VLD1d64QPseudoWB_register;
1723234353Sdim
1724234353Sdim  case ARM::VST1d8wb_fixed: return ARM::VST1d8wb_register;
1725234353Sdim  case ARM::VST1d16wb_fixed: return ARM::VST1d16wb_register;
1726234353Sdim  case ARM::VST1d32wb_fixed: return ARM::VST1d32wb_register;
1727234353Sdim  case ARM::VST1d64wb_fixed: return ARM::VST1d64wb_register;
1728234353Sdim  case ARM::VST1q8wb_fixed: return ARM::VST1q8wb_register;
1729234353Sdim  case ARM::VST1q16wb_fixed: return ARM::VST1q16wb_register;
1730234353Sdim  case ARM::VST1q32wb_fixed: return ARM::VST1q32wb_register;
1731234353Sdim  case ARM::VST1q64wb_fixed: return ARM::VST1q64wb_register;
1732234353Sdim  case ARM::VST1d64TPseudoWB_fixed: return ARM::VST1d64TPseudoWB_register;
1733234353Sdim  case ARM::VST1d64QPseudoWB_fixed: return ARM::VST1d64QPseudoWB_register;
1734234353Sdim
1735234353Sdim  case ARM::VLD2d8wb_fixed: return ARM::VLD2d8wb_register;
1736234353Sdim  case ARM::VLD2d16wb_fixed: return ARM::VLD2d16wb_register;
1737234353Sdim  case ARM::VLD2d32wb_fixed: return ARM::VLD2d32wb_register;
1738234353Sdim  case ARM::VLD2q8PseudoWB_fixed: return ARM::VLD2q8PseudoWB_register;
1739234353Sdim  case ARM::VLD2q16PseudoWB_fixed: return ARM::VLD2q16PseudoWB_register;
1740234353Sdim  case ARM::VLD2q32PseudoWB_fixed: return ARM::VLD2q32PseudoWB_register;
1741234353Sdim
1742234353Sdim  case ARM::VST2d8wb_fixed: return ARM::VST2d8wb_register;
1743234353Sdim  case ARM::VST2d16wb_fixed: return ARM::VST2d16wb_register;
1744234353Sdim  case ARM::VST2d32wb_fixed: return ARM::VST2d32wb_register;
1745234353Sdim  case ARM::VST2q8PseudoWB_fixed: return ARM::VST2q8PseudoWB_register;
1746234353Sdim  case ARM::VST2q16PseudoWB_fixed: return ARM::VST2q16PseudoWB_register;
1747234353Sdim  case ARM::VST2q32PseudoWB_fixed: return ARM::VST2q32PseudoWB_register;
1748234353Sdim
1749234353Sdim  case ARM::VLD2DUPd8wb_fixed: return ARM::VLD2DUPd8wb_register;
1750234353Sdim  case ARM::VLD2DUPd16wb_fixed: return ARM::VLD2DUPd16wb_register;
1751234353Sdim  case ARM::VLD2DUPd32wb_fixed: return ARM::VLD2DUPd32wb_register;
1752234353Sdim  }
1753234353Sdim  return Opc; // If not one we handle, return it unchanged.
1754234353Sdim}
1755234353Sdim
1756218893SdimSDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
1757239462Sdim                                   const uint16_t *DOpcodes,
1758239462Sdim                                   const uint16_t *QOpcodes0,
1759239462Sdim                                   const uint16_t *QOpcodes1) {
1760206083Srdivacky  assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range");
1761261991Sdim  SDLoc dl(N);
1762198090Srdivacky
1763205407Srdivacky  SDValue MemAddr, Align;
1764218893Sdim  unsigned AddrOpIdx = isUpdating ? 1 : 2;
1765218893Sdim  if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
1766276479Sdim    return nullptr;
1767198090Srdivacky
1768198090Srdivacky  SDValue Chain = N->getOperand(0);
1769198090Srdivacky  EVT VT = N->getValueType(0);
1770198090Srdivacky  bool is64BitVector = VT.is64BitVector();
1771218893Sdim  Align = GetVLDSTAlign(Align, NumVecs, is64BitVector);
1772198090Srdivacky
1773198090Srdivacky  unsigned OpcodeIndex;
1774198090Srdivacky  switch (VT.getSimpleVT().SimpleTy) {
1775198090Srdivacky  default: llvm_unreachable("unhandled vld type");
1776198090Srdivacky    // Double-register operations:
1777198090Srdivacky  case MVT::v8i8:  OpcodeIndex = 0; break;
1778198090Srdivacky  case MVT::v4i16: OpcodeIndex = 1; break;
1779198090Srdivacky  case MVT::v2f32:
1780198090Srdivacky  case MVT::v2i32: OpcodeIndex = 2; break;
1781198090Srdivacky  case MVT::v1i64: OpcodeIndex = 3; break;
1782198090Srdivacky    // Quad-register operations:
1783198090Srdivacky  case MVT::v16i8: OpcodeIndex = 0; break;
1784198090Srdivacky  case MVT::v8i16: OpcodeIndex = 1; break;
1785198090Srdivacky  case MVT::v4f32:
1786198090Srdivacky  case MVT::v4i32: OpcodeIndex = 2; break;
1787280031Sdim  case MVT::v2f64:
1788206083Srdivacky  case MVT::v2i64: OpcodeIndex = 3;
1789206083Srdivacky    assert(NumVecs == 1 && "v2i64 type only supported for VLD1");
1790206083Srdivacky    break;
1791198090Srdivacky  }
1792198090Srdivacky
1793212904Sdim  EVT ResTy;
1794212904Sdim  if (NumVecs == 1)
1795212904Sdim    ResTy = VT;
1796212904Sdim  else {
1797212904Sdim    unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
1798212904Sdim    if (!is64BitVector)
1799212904Sdim      ResTyElts *= 2;
1800212904Sdim    ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts);
1801212904Sdim  }
1802218893Sdim  std::vector<EVT> ResTys;
1803218893Sdim  ResTys.push_back(ResTy);
1804218893Sdim  if (isUpdating)
1805218893Sdim    ResTys.push_back(MVT::i32);
1806218893Sdim  ResTys.push_back(MVT::Other);
1807212904Sdim
1808207618Srdivacky  SDValue Pred = getAL(CurDAG);
1809205407Srdivacky  SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
1810218893Sdim  SDNode *VLd;
1811218893Sdim  SmallVector<SDValue, 7> Ops;
1812208599Srdivacky
1813218893Sdim  // Double registers and VLD1/VLD2 quad registers are directly supported.
1814218893Sdim  if (is64BitVector || NumVecs <= 2) {
1815218893Sdim    unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1816218893Sdim                    QOpcodes0[OpcodeIndex]);
1817218893Sdim    Ops.push_back(MemAddr);
1818218893Sdim    Ops.push_back(Align);
1819218893Sdim    if (isUpdating) {
1820218893Sdim      SDValue Inc = N->getOperand(AddrOpIdx + 1);
1821234353Sdim      // FIXME: VLD1/VLD2 fixed increment doesn't need Reg0. Remove the reg0
1822234353Sdim      // case entirely when the rest are updated to that form, too.
1823265925Sdim      if ((NumVecs <= 2) && !isa<ConstantSDNode>(Inc.getNode()))
1824234353Sdim        Opc = getVLDSTRegisterUpdateOpcode(Opc);
1825265925Sdim      // FIXME: We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so
1826234353Sdim      // check for that explicitly too. Horribly hacky, but temporary.
1827265925Sdim      if ((NumVecs > 2 && !isVLDfixed(Opc)) ||
1828234353Sdim          !isa<ConstantSDNode>(Inc.getNode()))
1829234353Sdim        Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
1830208599Srdivacky    }
1831218893Sdim    Ops.push_back(Pred);
1832218893Sdim    Ops.push_back(Reg0);
1833218893Sdim    Ops.push_back(Chain);
1834251662Sdim    VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
1835198090Srdivacky
1836198090Srdivacky  } else {
1837198090Srdivacky    // Otherwise, quad registers are loaded with two separate instructions,
1838198090Srdivacky    // where one loads the even registers and the other loads the odd registers.
1839212904Sdim    EVT AddrTy = MemAddr.getValueType();
1840198090Srdivacky
1841218893Sdim    // Load the even subregs.  This is always an updating load, so that it
1842218893Sdim    // provides the address to the second load for the odd subregs.
1843212904Sdim    SDValue ImplDef =
1844212904Sdim      SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
1845212904Sdim    const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain };
1846218893Sdim    SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
1847251662Sdim                                          ResTy, AddrTy, MVT::Other, OpsA);
1848212904Sdim    Chain = SDValue(VLdA, 2);
1849198090Srdivacky
1850198113Srdivacky    // Load the odd subregs.
1851218893Sdim    Ops.push_back(SDValue(VLdA, 1));
1852218893Sdim    Ops.push_back(Align);
1853218893Sdim    if (isUpdating) {
1854218893Sdim      SDValue Inc = N->getOperand(AddrOpIdx + 1);
1855218893Sdim      assert(isa<ConstantSDNode>(Inc.getNode()) &&
1856218893Sdim             "only constant post-increment update allowed for VLD3/4");
1857218893Sdim      (void)Inc;
1858218893Sdim      Ops.push_back(Reg0);
1859218893Sdim    }
1860218893Sdim    Ops.push_back(SDValue(VLdA, 0));
1861218893Sdim    Ops.push_back(Pred);
1862218893Sdim    Ops.push_back(Reg0);
1863218893Sdim    Ops.push_back(Chain);
1864251662Sdim    VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, Ops);
1865212904Sdim  }
1866198090Srdivacky
1867221345Sdim  // Transfer memoperands.
1868221345Sdim  MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1869221345Sdim  MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1870221345Sdim  cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1);
1871221345Sdim
1872218893Sdim  if (NumVecs == 1)
1873218893Sdim    return VLd;
1874218893Sdim
1875218893Sdim  // Extract out the subregisters.
1876218893Sdim  SDValue SuperReg = SDValue(VLd, 0);
1877218893Sdim  assert(ARM::dsub_7 == ARM::dsub_0+7 &&
1878218893Sdim         ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering");
1879218893Sdim  unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
1880218893Sdim  for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1881218893Sdim    ReplaceUses(SDValue(N, Vec),
1882218893Sdim                CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
1883218893Sdim  ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1));
1884218893Sdim  if (isUpdating)
1885218893Sdim    ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2));
1886276479Sdim  return nullptr;
1887198090Srdivacky}
1888198090Srdivacky
1889218893SdimSDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
1890239462Sdim                                   const uint16_t *DOpcodes,
1891239462Sdim                                   const uint16_t *QOpcodes0,
1892239462Sdim                                   const uint16_t *QOpcodes1) {
1893210299Sed  assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range");
1894261991Sdim  SDLoc dl(N);
1895198113Srdivacky
1896205407Srdivacky  SDValue MemAddr, Align;
1897218893Sdim  unsigned AddrOpIdx = isUpdating ? 1 : 2;
1898218893Sdim  unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
1899218893Sdim  if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
1900276479Sdim    return nullptr;
1901198113Srdivacky
1902221345Sdim  MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1903221345Sdim  MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1904221345Sdim
1905198113Srdivacky  SDValue Chain = N->getOperand(0);
1906218893Sdim  EVT VT = N->getOperand(Vec0Idx).getValueType();
1907198113Srdivacky  bool is64BitVector = VT.is64BitVector();
1908218893Sdim  Align = GetVLDSTAlign(Align, NumVecs, is64BitVector);
1909198113Srdivacky
1910198113Srdivacky  unsigned OpcodeIndex;
1911198113Srdivacky  switch (VT.getSimpleVT().SimpleTy) {
1912198113Srdivacky  default: llvm_unreachable("unhandled vst type");
1913198113Srdivacky    // Double-register operations:
1914198113Srdivacky  case MVT::v8i8:  OpcodeIndex = 0; break;
1915198113Srdivacky  case MVT::v4i16: OpcodeIndex = 1; break;
1916198113Srdivacky  case MVT::v2f32:
1917198113Srdivacky  case MVT::v2i32: OpcodeIndex = 2; break;
1918198113Srdivacky  case MVT::v1i64: OpcodeIndex = 3; break;
1919198113Srdivacky    // Quad-register operations:
1920198113Srdivacky  case MVT::v16i8: OpcodeIndex = 0; break;
1921198113Srdivacky  case MVT::v8i16: OpcodeIndex = 1; break;
1922198113Srdivacky  case MVT::v4f32:
1923198113Srdivacky  case MVT::v4i32: OpcodeIndex = 2; break;
1924280031Sdim  case MVT::v2f64:
1925206083Srdivacky  case MVT::v2i64: OpcodeIndex = 3;
1926206083Srdivacky    assert(NumVecs == 1 && "v2i64 type only supported for VST1");
1927206083Srdivacky    break;
1928198113Srdivacky  }
1929198113Srdivacky
1930218893Sdim  std::vector<EVT> ResTys;
1931218893Sdim  if (isUpdating)
1932218893Sdim    ResTys.push_back(MVT::i32);
1933218893Sdim  ResTys.push_back(MVT::Other);
1934218893Sdim
1935207618Srdivacky  SDValue Pred = getAL(CurDAG);
1936205407Srdivacky  SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
1937212904Sdim  SmallVector<SDValue, 7> Ops;
1938198113Srdivacky
1939218893Sdim  // Double registers and VST1/VST2 quad registers are directly supported.
1940218893Sdim  if (is64BitVector || NumVecs <= 2) {
1941218893Sdim    SDValue SrcReg;
1942212904Sdim    if (NumVecs == 1) {
1943218893Sdim      SrcReg = N->getOperand(Vec0Idx);
1944218893Sdim    } else if (is64BitVector) {
1945208599Srdivacky      // Form a REG_SEQUENCE to force register allocation.
1946218893Sdim      SDValue V0 = N->getOperand(Vec0Idx + 0);
1947218893Sdim      SDValue V1 = N->getOperand(Vec0Idx + 1);
1948208599Srdivacky      if (NumVecs == 2)
1949249423Sdim        SrcReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
1950208599Srdivacky      else {
1951218893Sdim        SDValue V2 = N->getOperand(Vec0Idx + 2);
1952218893Sdim        // If it's a vst3, form a quad D-register and leave the last part as
1953208599Srdivacky        // an undef.
1954208599Srdivacky        SDValue V3 = (NumVecs == 3)
1955208599Srdivacky          ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
1956218893Sdim          : N->getOperand(Vec0Idx + 3);
1957249423Sdim        SrcReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
1958208599Srdivacky      }
1959212904Sdim    } else {
1960212904Sdim      // Form a QQ register.
1961218893Sdim      SDValue Q0 = N->getOperand(Vec0Idx);
1962218893Sdim      SDValue Q1 = N->getOperand(Vec0Idx + 1);
1963249423Sdim      SrcReg = SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0);
1964198113Srdivacky    }
1965218893Sdim
1966218893Sdim    unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1967218893Sdim                    QOpcodes0[OpcodeIndex]);
1968218893Sdim    Ops.push_back(MemAddr);
1969218893Sdim    Ops.push_back(Align);
1970218893Sdim    if (isUpdating) {
1971218893Sdim      SDValue Inc = N->getOperand(AddrOpIdx + 1);
1972234353Sdim      // FIXME: VST1/VST2 fixed increment doesn't need Reg0. Remove the reg0
1973234353Sdim      // case entirely when the rest are updated to that form, too.
1974234353Sdim      if (NumVecs <= 2 && !isa<ConstantSDNode>(Inc.getNode()))
1975234353Sdim        Opc = getVLDSTRegisterUpdateOpcode(Opc);
1976265925Sdim      // FIXME: We use a VST1 for v1i64 even if the pseudo says vld2/3/4, so
1977234353Sdim      // check for that explicitly too. Horribly hacky, but temporary.
1978265925Sdim      if  (!isa<ConstantSDNode>(Inc.getNode()))
1979265925Sdim        Ops.push_back(Inc);
1980265925Sdim      else if (NumVecs > 2 && !isVSTfixed(Opc))
1981265925Sdim        Ops.push_back(Reg0);
1982218893Sdim    }
1983218893Sdim    Ops.push_back(SrcReg);
1984212904Sdim    Ops.push_back(Pred);
1985218893Sdim    Ops.push_back(Reg0);
1986212904Sdim    Ops.push_back(Chain);
1987251662Sdim    SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
1988221345Sdim
1989221345Sdim    // Transfer memoperands.
1990221345Sdim    cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1);
1991221345Sdim
1992221345Sdim    return VSt;
1993198113Srdivacky  }
1994198113Srdivacky
1995198113Srdivacky  // Otherwise, quad registers are stored with two separate instructions,
1996198113Srdivacky  // where one stores the even registers and the other stores the odd registers.
1997198113Srdivacky
1998210299Sed  // Form the QQQQ REG_SEQUENCE.
1999218893Sdim  SDValue V0 = N->getOperand(Vec0Idx + 0);
2000218893Sdim  SDValue V1 = N->getOperand(Vec0Idx + 1);
2001218893Sdim  SDValue V2 = N->getOperand(Vec0Idx + 2);
2002212904Sdim  SDValue V3 = (NumVecs == 3)
2003212904Sdim    ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2004218893Sdim    : N->getOperand(Vec0Idx + 3);
2005249423Sdim  SDValue RegSeq = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
2006198113Srdivacky
2007218893Sdim  // Store the even D registers.  This is always an updating store, so that it
2008218893Sdim  // provides the address to the second store for the odd subregs.
2009218893Sdim  const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain };
2010218893Sdim  SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
2011218893Sdim                                        MemAddr.getValueType(),
2012251662Sdim                                        MVT::Other, OpsA);
2013221345Sdim  cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1);
2014218893Sdim  Chain = SDValue(VStA, 1);
2015218893Sdim
2016218893Sdim  // Store the odd D registers.
2017218893Sdim  Ops.push_back(SDValue(VStA, 0));
2018218893Sdim  Ops.push_back(Align);
2019218893Sdim  if (isUpdating) {
2020218893Sdim    SDValue Inc = N->getOperand(AddrOpIdx + 1);
2021218893Sdim    assert(isa<ConstantSDNode>(Inc.getNode()) &&
2022218893Sdim           "only constant post-increment update allowed for VST3/4");
2023218893Sdim    (void)Inc;
2024218893Sdim    Ops.push_back(Reg0);
2025218893Sdim  }
2026212904Sdim  Ops.push_back(RegSeq);
2027210299Sed  Ops.push_back(Pred);
2028218893Sdim  Ops.push_back(Reg0);
2029210299Sed  Ops.push_back(Chain);
2030221345Sdim  SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
2031251662Sdim                                        Ops);
2032221345Sdim  cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1);
2033221345Sdim  return VStB;
2034198113Srdivacky}
2035198113Srdivacky
2036202375SrdivackySDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad,
2037218893Sdim                                         bool isUpdating, unsigned NumVecs,
2038239462Sdim                                         const uint16_t *DOpcodes,
2039239462Sdim                                         const uint16_t *QOpcodes) {
2040198090Srdivacky  assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range");
2041261991Sdim  SDLoc dl(N);
2042198090Srdivacky
2043205407Srdivacky  SDValue MemAddr, Align;
2044218893Sdim  unsigned AddrOpIdx = isUpdating ? 1 : 2;
2045218893Sdim  unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
2046218893Sdim  if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
2047276479Sdim    return nullptr;
2048198090Srdivacky
2049221345Sdim  MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2050221345Sdim  MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2051221345Sdim
2052198090Srdivacky  SDValue Chain = N->getOperand(0);
2053198090Srdivacky  unsigned Lane =
2054218893Sdim    cast<ConstantSDNode>(N->getOperand(Vec0Idx + NumVecs))->getZExtValue();
2055218893Sdim  EVT VT = N->getOperand(Vec0Idx).getValueType();
2056198090Srdivacky  bool is64BitVector = VT.is64BitVector();
2057198090Srdivacky
2058218893Sdim  unsigned Alignment = 0;
2059218893Sdim  if (NumVecs != 3) {
2060218893Sdim    Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
2061218893Sdim    unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2062218893Sdim    if (Alignment > NumBytes)
2063218893Sdim      Alignment = NumBytes;
2064218893Sdim    if (Alignment < 8 && Alignment < NumBytes)
2065218893Sdim      Alignment = 0;
2066218893Sdim    // Alignment must be a power of two; make sure of that.
2067218893Sdim    Alignment = (Alignment & -Alignment);
2068218893Sdim    if (Alignment == 1)
2069218893Sdim      Alignment = 0;
2070198090Srdivacky  }
2071218893Sdim  Align = CurDAG->getTargetConstant(Alignment, MVT::i32);
2072198090Srdivacky
2073198090Srdivacky  unsigned OpcodeIndex;
2074198090Srdivacky  switch (VT.getSimpleVT().SimpleTy) {
2075198090Srdivacky  default: llvm_unreachable("unhandled vld/vst lane type");
2076198090Srdivacky    // Double-register operations:
2077198090Srdivacky  case MVT::v8i8:  OpcodeIndex = 0; break;
2078198090Srdivacky  case MVT::v4i16: OpcodeIndex = 1; break;
2079198090Srdivacky  case MVT::v2f32:
2080198090Srdivacky  case MVT::v2i32: OpcodeIndex = 2; break;
2081198090Srdivacky    // Quad-register operations:
2082198090Srdivacky  case MVT::v8i16: OpcodeIndex = 0; break;
2083198090Srdivacky  case MVT::v4f32:
2084198090Srdivacky  case MVT::v4i32: OpcodeIndex = 1; break;
2085198090Srdivacky  }
2086198090Srdivacky
2087218893Sdim  std::vector<EVT> ResTys;
2088218893Sdim  if (IsLoad) {
2089218893Sdim    unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2090218893Sdim    if (!is64BitVector)
2091218893Sdim      ResTyElts *= 2;
2092218893Sdim    ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(),
2093218893Sdim                                      MVT::i64, ResTyElts));
2094218893Sdim  }
2095218893Sdim  if (isUpdating)
2096218893Sdim    ResTys.push_back(MVT::i32);
2097218893Sdim  ResTys.push_back(MVT::Other);
2098218893Sdim
2099207618Srdivacky  SDValue Pred = getAL(CurDAG);
2100205407Srdivacky  SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2101199989Srdivacky
2102218893Sdim  SmallVector<SDValue, 8> Ops;
2103198090Srdivacky  Ops.push_back(MemAddr);
2104199481Srdivacky  Ops.push_back(Align);
2105218893Sdim  if (isUpdating) {
2106218893Sdim    SDValue Inc = N->getOperand(AddrOpIdx + 1);
2107218893Sdim    Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
2108218893Sdim  }
2109198090Srdivacky
2110218893Sdim  SDValue SuperReg;
2111218893Sdim  SDValue V0 = N->getOperand(Vec0Idx + 0);
2112218893Sdim  SDValue V1 = N->getOperand(Vec0Idx + 1);
2113218893Sdim  if (NumVecs == 2) {
2114218893Sdim    if (is64BitVector)
2115249423Sdim      SuperReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
2116218893Sdim    else
2117249423Sdim      SuperReg = SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0);
2118198090Srdivacky  } else {
2119218893Sdim    SDValue V2 = N->getOperand(Vec0Idx + 2);
2120218893Sdim    SDValue V3 = (NumVecs == 3)
2121218893Sdim      ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2122218893Sdim      : N->getOperand(Vec0Idx + 3);
2123218893Sdim    if (is64BitVector)
2124249423Sdim      SuperReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
2125218893Sdim    else
2126249423Sdim      SuperReg = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
2127198090Srdivacky  }
2128218893Sdim  Ops.push_back(SuperReg);
2129198090Srdivacky  Ops.push_back(getI32Imm(Lane));
2130199989Srdivacky  Ops.push_back(Pred);
2131205407Srdivacky  Ops.push_back(Reg0);
2132198090Srdivacky  Ops.push_back(Chain);
2133198090Srdivacky
2134218893Sdim  unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2135218893Sdim                                  QOpcodes[OpcodeIndex]);
2136251662Sdim  SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
2137221345Sdim  cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1);
2138198090Srdivacky  if (!IsLoad)
2139218893Sdim    return VLdLn;
2140198090Srdivacky
2141218893Sdim  // Extract the subregisters.
2142218893Sdim  SuperReg = SDValue(VLdLn, 0);
2143218893Sdim  assert(ARM::dsub_7 == ARM::dsub_0+7 &&
2144218893Sdim         ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering");
2145218893Sdim  unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
2146218893Sdim  for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2147218893Sdim    ReplaceUses(SDValue(N, Vec),
2148218893Sdim                CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2149218893Sdim  ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1));
2150218893Sdim  if (isUpdating)
2151218893Sdim    ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2));
2152276479Sdim  return nullptr;
2153218893Sdim}
2154208599Srdivacky
2155218893SdimSDNode *ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating,
2156239462Sdim                                      unsigned NumVecs,
2157239462Sdim                                      const uint16_t *Opcodes) {
2158218893Sdim  assert(NumVecs >=2 && NumVecs <= 4 && "VLDDup NumVecs out-of-range");
2159261991Sdim  SDLoc dl(N);
2160208599Srdivacky
2161218893Sdim  SDValue MemAddr, Align;
2162218893Sdim  if (!SelectAddrMode6(N, N->getOperand(1), MemAddr, Align))
2163276479Sdim    return nullptr;
2164218893Sdim
2165221345Sdim  MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2166221345Sdim  MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2167221345Sdim
2168218893Sdim  SDValue Chain = N->getOperand(0);
2169218893Sdim  EVT VT = N->getValueType(0);
2170218893Sdim
2171218893Sdim  unsigned Alignment = 0;
2172218893Sdim  if (NumVecs != 3) {
2173218893Sdim    Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
2174218893Sdim    unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2175218893Sdim    if (Alignment > NumBytes)
2176218893Sdim      Alignment = NumBytes;
2177218893Sdim    if (Alignment < 8 && Alignment < NumBytes)
2178218893Sdim      Alignment = 0;
2179218893Sdim    // Alignment must be a power of two; make sure of that.
2180218893Sdim    Alignment = (Alignment & -Alignment);
2181218893Sdim    if (Alignment == 1)
2182218893Sdim      Alignment = 0;
2183208599Srdivacky  }
2184218893Sdim  Align = CurDAG->getTargetConstant(Alignment, MVT::i32);
2185208599Srdivacky
2186218893Sdim  unsigned OpcodeIndex;
2187218893Sdim  switch (VT.getSimpleVT().SimpleTy) {
2188218893Sdim  default: llvm_unreachable("unhandled vld-dup type");
2189218893Sdim  case MVT::v8i8:  OpcodeIndex = 0; break;
2190218893Sdim  case MVT::v4i16: OpcodeIndex = 1; break;
2191218893Sdim  case MVT::v2f32:
2192218893Sdim  case MVT::v2i32: OpcodeIndex = 2; break;
2193218893Sdim  }
2194218893Sdim
2195218893Sdim  SDValue Pred = getAL(CurDAG);
2196218893Sdim  SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2197218893Sdim  SDValue SuperReg;
2198218893Sdim  unsigned Opc = Opcodes[OpcodeIndex];
2199218893Sdim  SmallVector<SDValue, 6> Ops;
2200218893Sdim  Ops.push_back(MemAddr);
2201218893Sdim  Ops.push_back(Align);
2202218893Sdim  if (isUpdating) {
2203234353Sdim    // fixed-stride update instructions don't have an explicit writeback
2204234353Sdim    // operand. It's implicit in the opcode itself.
2205218893Sdim    SDValue Inc = N->getOperand(2);
2206234353Sdim    if (!isa<ConstantSDNode>(Inc.getNode()))
2207234353Sdim      Ops.push_back(Inc);
2208234353Sdim    // FIXME: VLD3 and VLD4 haven't been updated to that form yet.
2209234353Sdim    else if (NumVecs > 2)
2210234353Sdim      Ops.push_back(Reg0);
2211218893Sdim  }
2212218893Sdim  Ops.push_back(Pred);
2213218893Sdim  Ops.push_back(Reg0);
2214218893Sdim  Ops.push_back(Chain);
2215218893Sdim
2216218893Sdim  unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2217218893Sdim  std::vector<EVT> ResTys;
2218221345Sdim  ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64,ResTyElts));
2219218893Sdim  if (isUpdating)
2220218893Sdim    ResTys.push_back(MVT::i32);
2221218893Sdim  ResTys.push_back(MVT::Other);
2222251662Sdim  SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
2223221345Sdim  cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1);
2224218893Sdim  SuperReg = SDValue(VLdDup, 0);
2225218893Sdim
2226218893Sdim  // Extract the subregisters.
2227210299Sed  assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering");
2228218893Sdim  unsigned SubIdx = ARM::dsub_0;
2229210299Sed  for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2230210299Sed    ReplaceUses(SDValue(N, Vec),
2231218893Sdim                CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
2232218893Sdim  ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1));
2233218893Sdim  if (isUpdating)
2234218893Sdim    ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2));
2235276479Sdim  return nullptr;
2236210299Sed}
2237198090Srdivacky
2238210299SedSDNode *ARMDAGToDAGISel::SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs,
2239210299Sed                                    unsigned Opc) {
2240210299Sed  assert(NumVecs >= 2 && NumVecs <= 4 && "VTBL NumVecs out-of-range");
2241261991Sdim  SDLoc dl(N);
2242210299Sed  EVT VT = N->getValueType(0);
2243210299Sed  unsigned FirstTblReg = IsExt ? 2 : 1;
2244210299Sed
2245210299Sed  // Form a REG_SEQUENCE to force register allocation.
2246210299Sed  SDValue RegSeq;
2247210299Sed  SDValue V0 = N->getOperand(FirstTblReg + 0);
2248210299Sed  SDValue V1 = N->getOperand(FirstTblReg + 1);
2249210299Sed  if (NumVecs == 2)
2250249423Sdim    RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
2251210299Sed  else {
2252210299Sed    SDValue V2 = N->getOperand(FirstTblReg + 2);
2253218893Sdim    // If it's a vtbl3, form a quad D-register and leave the last part as
2254210299Sed    // an undef.
2255210299Sed    SDValue V3 = (NumVecs == 3)
2256210299Sed      ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2257210299Sed      : N->getOperand(FirstTblReg + 3);
2258249423Sdim    RegSeq = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
2259198090Srdivacky  }
2260198090Srdivacky
2261210299Sed  SmallVector<SDValue, 6> Ops;
2262210299Sed  if (IsExt)
2263210299Sed    Ops.push_back(N->getOperand(1));
2264218893Sdim  Ops.push_back(RegSeq);
2265210299Sed  Ops.push_back(N->getOperand(FirstTblReg + NumVecs));
2266210299Sed  Ops.push_back(getAL(CurDAG)); // predicate
2267210299Sed  Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // predicate register
2268251662Sdim  return CurDAG->getMachineNode(Opc, dl, VT, Ops);
2269198090Srdivacky}
2270198090Srdivacky
2271202375SrdivackySDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N,
2272207618Srdivacky                                                     bool isSigned) {
2273198090Srdivacky  if (!Subtarget->hasV6T2Ops())
2274276479Sdim    return nullptr;
2275198090Srdivacky
2276249423Sdim  unsigned Opc = isSigned
2277249423Sdim    ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
2278207618Srdivacky    : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
2279207618Srdivacky
2280207618Srdivacky  // For unsigned extracts, check for a shift right and mask
2281207618Srdivacky  unsigned And_imm = 0;
2282207618Srdivacky  if (N->getOpcode() == ISD::AND) {
2283207618Srdivacky    if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) {
2284207618Srdivacky
2285207618Srdivacky      // The immediate is a mask of the low bits iff imm & (imm+1) == 0
2286207618Srdivacky      if (And_imm & (And_imm + 1))
2287276479Sdim        return nullptr;
2288207618Srdivacky
2289207618Srdivacky      unsigned Srl_imm = 0;
2290207618Srdivacky      if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL,
2291207618Srdivacky                                Srl_imm)) {
2292207618Srdivacky        assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2293207618Srdivacky
2294226633Sdim        // Note: The width operand is encoded as width-1.
2295226633Sdim        unsigned Width = CountTrailingOnes_32(And_imm) - 1;
2296207618Srdivacky        unsigned LSB = Srl_imm;
2297249423Sdim
2298207618Srdivacky        SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2299249423Sdim
2300249423Sdim        if ((LSB + Width + 1) == N->getValueType(0).getSizeInBits()) {
2301249423Sdim          // It's cheaper to use a right shift to extract the top bits.
2302249423Sdim          if (Subtarget->isThumb()) {
2303249423Sdim            Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri;
2304249423Sdim            SDValue Ops[] = { N->getOperand(0).getOperand(0),
2305249423Sdim                              CurDAG->getTargetConstant(LSB, MVT::i32),
2306249423Sdim                              getAL(CurDAG), Reg0, Reg0 };
2307276479Sdim            return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2308249423Sdim          }
2309249423Sdim
2310249423Sdim          // ARM models shift instructions as MOVsi with shifter operand.
2311249423Sdim          ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(ISD::SRL);
2312249423Sdim          SDValue ShOpc =
2313249423Sdim            CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, LSB),
2314249423Sdim                                      MVT::i32);
2315249423Sdim          SDValue Ops[] = { N->getOperand(0).getOperand(0), ShOpc,
2316249423Sdim                            getAL(CurDAG), Reg0, Reg0 };
2317276479Sdim          return CurDAG->SelectNodeTo(N, ARM::MOVsi, MVT::i32, Ops);
2318249423Sdim        }
2319249423Sdim
2320207618Srdivacky        SDValue Ops[] = { N->getOperand(0).getOperand(0),
2321207618Srdivacky                          CurDAG->getTargetConstant(LSB, MVT::i32),
2322207618Srdivacky                          CurDAG->getTargetConstant(Width, MVT::i32),
2323276479Sdim                          getAL(CurDAG), Reg0 };
2324276479Sdim        return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2325207618Srdivacky      }
2326207618Srdivacky    }
2327276479Sdim    return nullptr;
2328207618Srdivacky  }
2329207618Srdivacky
2330207618Srdivacky  // Otherwise, we're looking for a shift of a shift
2331198090Srdivacky  unsigned Shl_imm = 0;
2332202375Srdivacky  if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
2333198090Srdivacky    assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
2334198090Srdivacky    unsigned Srl_imm = 0;
2335202375Srdivacky    if (isInt32Immediate(N->getOperand(1), Srl_imm)) {
2336198090Srdivacky      assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2337226633Sdim      // Note: The width operand is encoded as width-1.
2338226633Sdim      unsigned Width = 32 - Srl_imm - 1;
2339198090Srdivacky      int LSB = Srl_imm - Shl_imm;
2340198396Srdivacky      if (LSB < 0)
2341276479Sdim        return nullptr;
2342198090Srdivacky      SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2343202375Srdivacky      SDValue Ops[] = { N->getOperand(0).getOperand(0),
2344198090Srdivacky                        CurDAG->getTargetConstant(LSB, MVT::i32),
2345198090Srdivacky                        CurDAG->getTargetConstant(Width, MVT::i32),
2346198090Srdivacky                        getAL(CurDAG), Reg0 };
2347276479Sdim      return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2348198090Srdivacky    }
2349198090Srdivacky  }
2350280031Sdim
2351280031Sdim  if (N->getOpcode() == ISD::SIGN_EXTEND_INREG) {
2352280031Sdim    unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits();
2353280031Sdim    unsigned LSB = 0;
2354280031Sdim    if (!isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, LSB) &&
2355280031Sdim        !isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRA, LSB))
2356280031Sdim      return nullptr;
2357280031Sdim
2358280031Sdim    if (LSB + Width > 32)
2359280031Sdim      return nullptr;
2360280031Sdim
2361280031Sdim    SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2362280031Sdim    SDValue Ops[] = { N->getOperand(0).getOperand(0),
2363280031Sdim                      CurDAG->getTargetConstant(LSB, MVT::i32),
2364280031Sdim                      CurDAG->getTargetConstant(Width - 1, MVT::i32),
2365280031Sdim                      getAL(CurDAG), Reg0 };
2366280031Sdim    return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2367280031Sdim  }
2368280031Sdim
2369276479Sdim  return nullptr;
2370198090Srdivacky}
2371198090Srdivacky
2372226633Sdim/// Target-specific DAG combining for ISD::XOR.
2373226633Sdim/// Target-independent combining lowers SELECT_CC nodes of the form
2374226633Sdim/// select_cc setg[ge] X,  0,  X, -X
2375226633Sdim/// select_cc setgt    X, -1,  X, -X
2376226633Sdim/// select_cc setl[te] X,  0, -X,  X
2377226633Sdim/// select_cc setlt    X,  1, -X,  X
2378226633Sdim/// which represent Integer ABS into:
2379226633Sdim/// Y = sra (X, size(X)-1); xor (add (X, Y), Y)
2380226633Sdim/// ARM instruction selection detects the latter and matches it to
2381226633Sdim/// ARM::ABS or ARM::t2ABS machine node.
2382226633SdimSDNode *ARMDAGToDAGISel::SelectABSOp(SDNode *N){
2383226633Sdim  SDValue XORSrc0 = N->getOperand(0);
2384226633Sdim  SDValue XORSrc1 = N->getOperand(1);
2385226633Sdim  EVT VT = N->getValueType(0);
2386226633Sdim
2387226633Sdim  if (Subtarget->isThumb1Only())
2388276479Sdim    return nullptr;
2389226633Sdim
2390239462Sdim  if (XORSrc0.getOpcode() != ISD::ADD || XORSrc1.getOpcode() != ISD::SRA)
2391276479Sdim    return nullptr;
2392226633Sdim
2393226633Sdim  SDValue ADDSrc0 = XORSrc0.getOperand(0);
2394226633Sdim  SDValue ADDSrc1 = XORSrc0.getOperand(1);
2395226633Sdim  SDValue SRASrc0 = XORSrc1.getOperand(0);
2396226633Sdim  SDValue SRASrc1 = XORSrc1.getOperand(1);
2397226633Sdim  ConstantSDNode *SRAConstant =  dyn_cast<ConstantSDNode>(SRASrc1);
2398226633Sdim  EVT XType = SRASrc0.getValueType();
2399226633Sdim  unsigned Size = XType.getSizeInBits() - 1;
2400226633Sdim
2401239462Sdim  if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 &&
2402276479Sdim      XType.isInteger() && SRAConstant != nullptr &&
2403226633Sdim      Size == SRAConstant->getZExtValue()) {
2404239462Sdim    unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS : ARM::ABS;
2405226633Sdim    return CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0);
2406226633Sdim  }
2407226633Sdim
2408276479Sdim  return nullptr;
2409226633Sdim}
2410226633Sdim
2411208599SrdivackySDNode *ARMDAGToDAGISel::SelectConcatVector(SDNode *N) {
2412208599Srdivacky  // The only time a CONCAT_VECTORS operation can have legal types is when
2413208599Srdivacky  // two 64-bit vectors are concatenated to a 128-bit vector.
2414208599Srdivacky  EVT VT = N->getValueType(0);
2415208599Srdivacky  if (!VT.is128BitVector() || N->getNumOperands() != 2)
2416208599Srdivacky    llvm_unreachable("unexpected CONCAT_VECTORS");
2417249423Sdim  return createDRegPairNode(VT, N->getOperand(0), N->getOperand(1));
2418208599Srdivacky}
2419208599Srdivacky
2420202375SrdivackySDNode *ARMDAGToDAGISel::Select(SDNode *N) {
2421261991Sdim  SDLoc dl(N);
2422193323Sed
2423255804Sdim  if (N->isMachineOpcode()) {
2424255804Sdim    N->setNodeId(-1);
2425276479Sdim    return nullptr;   // Already selected.
2426255804Sdim  }
2427193323Sed
2428193323Sed  switch (N->getOpcode()) {
2429193323Sed  default: break;
2430249423Sdim  case ISD::INLINEASM: {
2431249423Sdim    SDNode *ResNode = SelectInlineAsm(N);
2432249423Sdim    if (ResNode)
2433249423Sdim      return ResNode;
2434249423Sdim    break;
2435249423Sdim  }
2436226633Sdim  case ISD::XOR: {
2437226633Sdim    // Select special operations if XOR node forms integer ABS pattern
2438226633Sdim    SDNode *ResNode = SelectABSOp(N);
2439226633Sdim    if (ResNode)
2440226633Sdim      return ResNode;
2441226633Sdim    // Other cases are autogenerated.
2442226633Sdim    break;
2443226633Sdim  }
2444193323Sed  case ISD::Constant: {
2445193323Sed    unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
2446193323Sed    bool UseCP = true;
2447276479Sdim    if (Subtarget->useMovt(*MF))
2448198090Srdivacky      // Thumb2-aware targets have the MOVT instruction, so all immediates can
2449198090Srdivacky      // be done with MOV + MOVT, at worst.
2450276479Sdim      UseCP = false;
2451198090Srdivacky    else {
2452198090Srdivacky      if (Subtarget->isThumb()) {
2453276479Sdim        UseCP = (Val > 255 &&                                  // MOV
2454276479Sdim                 ~Val > 255 &&                                 // MOV + MVN
2455276479Sdim                 !ARM_AM::isThumbImmShiftedVal(Val) &&         // MOV + LSL
2456276479Sdim                 !(Subtarget->hasV6T2Ops() && Val <= 0xffff)); // MOVW
2457198090Srdivacky      } else
2458276479Sdim        UseCP = (ARM_AM::getSOImmVal(Val) == -1 &&             // MOV
2459276479Sdim                 ARM_AM::getSOImmVal(~Val) == -1 &&            // MVN
2460276479Sdim                 !ARM_AM::isSOImmTwoPartVal(Val) &&            // two instrs.
2461276479Sdim                 !(Subtarget->hasV6T2Ops() && Val <= 0xffff)); // MOVW
2462198090Srdivacky    }
2463198090Srdivacky
2464193323Sed    if (UseCP) {
2465280031Sdim      SDValue CPIdx = CurDAG->getTargetConstantPool(
2466280031Sdim          ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val),
2467280031Sdim          TLI->getPointerTy());
2468193323Sed
2469193323Sed      SDNode *ResNode;
2470276479Sdim      if (Subtarget->isThumb()) {
2471207618Srdivacky        SDValue Pred = getAL(CurDAG);
2472198090Srdivacky        SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2473198090Srdivacky        SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
2474218893Sdim        ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
2475251662Sdim                                         Ops);
2476198090Srdivacky      } else {
2477193323Sed        SDValue Ops[] = {
2478198090Srdivacky          CPIdx,
2479193323Sed          CurDAG->getTargetConstant(0, MVT::i32),
2480193323Sed          getAL(CurDAG),
2481193323Sed          CurDAG->getRegister(0, MVT::i32),
2482193323Sed          CurDAG->getEntryNode()
2483193323Sed        };
2484198090Srdivacky        ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
2485251662Sdim                                       Ops);
2486193323Sed      }
2487202375Srdivacky      ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
2488276479Sdim      return nullptr;
2489193323Sed    }
2490198090Srdivacky
2491193323Sed    // Other cases are autogenerated.
2492193323Sed    break;
2493193323Sed  }
2494193323Sed  case ISD::FrameIndex: {
2495193323Sed    // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
2496193323Sed    int FI = cast<FrameIndexSDNode>(N)->getIndex();
2497280031Sdim    SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
2498198090Srdivacky    if (Subtarget->isThumb1Only()) {
2499280031Sdim      return CurDAG->SelectNodeTo(N, ARM::tADDframe, MVT::i32, TFI,
2500280031Sdim                                  CurDAG->getTargetConstant(0, MVT::i32));
2501193323Sed    } else {
2502198090Srdivacky      unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
2503198090Srdivacky                      ARM::t2ADDri : ARM::ADDri);
2504193323Sed      SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32),
2505198090Srdivacky                        getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2506198090Srdivacky                        CurDAG->getRegister(0, MVT::i32) };
2507276479Sdim      return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2508193323Sed    }
2509193323Sed  }
2510198090Srdivacky  case ISD::SRL:
2511207618Srdivacky    if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
2512198090Srdivacky      return I;
2513193323Sed    break;
2514280031Sdim  case ISD::SIGN_EXTEND_INREG:
2515198090Srdivacky  case ISD::SRA:
2516207618Srdivacky    if (SDNode *I = SelectV6T2BitfieldExtractOp(N, true))
2517198090Srdivacky      return I;
2518198090Srdivacky    break;
2519193323Sed  case ISD::MUL:
2520198090Srdivacky    if (Subtarget->isThumb1Only())
2521193323Sed      break;
2522202375Srdivacky    if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
2523193323Sed      unsigned RHSV = C->getZExtValue();
2524193323Sed      if (!RHSV) break;
2525193323Sed      if (isPowerOf2_32(RHSV-1)) {  // 2^n+1?
2526198090Srdivacky        unsigned ShImm = Log2_32(RHSV-1);
2527198090Srdivacky        if (ShImm >= 32)
2528198090Srdivacky          break;
2529202375Srdivacky        SDValue V = N->getOperand(0);
2530198090Srdivacky        ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
2531198090Srdivacky        SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32);
2532198090Srdivacky        SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2533198090Srdivacky        if (Subtarget->isThumb()) {
2534198090Srdivacky          SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
2535276479Sdim          return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops);
2536198090Srdivacky        } else {
2537198090Srdivacky          SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
2538276479Sdim          return CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops);
2539198090Srdivacky        }
2540193323Sed      }
2541193323Sed      if (isPowerOf2_32(RHSV+1)) {  // 2^n-1?
2542198090Srdivacky        unsigned ShImm = Log2_32(RHSV+1);
2543198090Srdivacky        if (ShImm >= 32)
2544198090Srdivacky          break;
2545202375Srdivacky        SDValue V = N->getOperand(0);
2546198090Srdivacky        ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
2547198090Srdivacky        SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32);
2548198090Srdivacky        SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2549198090Srdivacky        if (Subtarget->isThumb()) {
2550210299Sed          SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
2551276479Sdim          return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops);
2552198090Srdivacky        } else {
2553198090Srdivacky          SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
2554276479Sdim          return CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops);
2555198090Srdivacky        }
2556193323Sed      }
2557193323Sed    }
2558193323Sed    break;
2559198396Srdivacky  case ISD::AND: {
2560207618Srdivacky    // Check for unsigned bitfield extract
2561207618Srdivacky    if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
2562207618Srdivacky      return I;
2563207618Srdivacky
2564198396Srdivacky    // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
2565198396Srdivacky    // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
2566198396Srdivacky    // are entirely contributed by c2 and lower 16-bits are entirely contributed
2567198396Srdivacky    // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)).
2568198396Srdivacky    // Select it to: "movt x, ((c1 & 0xffff) >> 16)
2569202375Srdivacky    EVT VT = N->getValueType(0);
2570198396Srdivacky    if (VT != MVT::i32)
2571198396Srdivacky      break;
2572198396Srdivacky    unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
2573198396Srdivacky      ? ARM::t2MOVTi16
2574198396Srdivacky      : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
2575198396Srdivacky    if (!Opc)
2576198396Srdivacky      break;
2577202375Srdivacky    SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
2578198396Srdivacky    ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
2579198396Srdivacky    if (!N1C)
2580198396Srdivacky      break;
2581198396Srdivacky    if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {
2582198396Srdivacky      SDValue N2 = N0.getOperand(1);
2583198396Srdivacky      ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
2584198396Srdivacky      if (!N2C)
2585198396Srdivacky        break;
2586198396Srdivacky      unsigned N1CVal = N1C->getZExtValue();
2587198396Srdivacky      unsigned N2CVal = N2C->getZExtValue();
2588198396Srdivacky      if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
2589198396Srdivacky          (N1CVal & 0xffffU) == 0xffffU &&
2590198396Srdivacky          (N2CVal & 0xffffU) == 0x0U) {
2591198396Srdivacky        SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
2592198396Srdivacky                                                  MVT::i32);
2593198396Srdivacky        SDValue Ops[] = { N0.getOperand(0), Imm16,
2594198396Srdivacky                          getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
2595251662Sdim        return CurDAG->getMachineNode(Opc, dl, VT, Ops);
2596198396Srdivacky      }
2597198396Srdivacky    }
2598198396Srdivacky    break;
2599198396Srdivacky  }
2600199481Srdivacky  case ARMISD::VMOVRRD:
2601199481Srdivacky    return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32,
2602202375Srdivacky                                  N->getOperand(0), getAL(CurDAG),
2603198090Srdivacky                                  CurDAG->getRegister(0, MVT::i32));
2604193323Sed  case ISD::UMUL_LOHI: {
2605198090Srdivacky    if (Subtarget->isThumb1Only())
2606198090Srdivacky      break;
2607198090Srdivacky    if (Subtarget->isThumb()) {
2608202375Srdivacky      SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
2609251662Sdim                        getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
2610251662Sdim      return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops);
2611198090Srdivacky    } else {
2612202375Srdivacky      SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
2613198090Srdivacky                        getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2614198090Srdivacky                        CurDAG->getRegister(0, MVT::i32) };
2615218893Sdim      return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2616218893Sdim                                    ARM::UMULL : ARM::UMULLv5,
2617251662Sdim                                    dl, MVT::i32, MVT::i32, Ops);
2618198090Srdivacky    }
2619193323Sed  }
2620193323Sed  case ISD::SMUL_LOHI: {
2621198090Srdivacky    if (Subtarget->isThumb1Only())
2622198090Srdivacky      break;
2623198090Srdivacky    if (Subtarget->isThumb()) {
2624202375Srdivacky      SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
2625198090Srdivacky                        getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
2626251662Sdim      return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops);
2627198090Srdivacky    } else {
2628202375Srdivacky      SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
2629193323Sed                        getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2630193323Sed                        CurDAG->getRegister(0, MVT::i32) };
2631218893Sdim      return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2632218893Sdim                                    ARM::SMULL : ARM::SMULLv5,
2633251662Sdim                                    dl, MVT::i32, MVT::i32, Ops);
2634198090Srdivacky    }
2635193323Sed  }
2636243830Sdim  case ARMISD::UMLAL:{
2637243830Sdim    if (Subtarget->isThumb()) {
2638243830Sdim      SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2639243830Sdim                        N->getOperand(3), getAL(CurDAG),
2640243830Sdim                        CurDAG->getRegister(0, MVT::i32)};
2641251662Sdim      return CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops);
2642243830Sdim    }else{
2643243830Sdim      SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2644243830Sdim                        N->getOperand(3), getAL(CurDAG),
2645243830Sdim                        CurDAG->getRegister(0, MVT::i32),
2646243830Sdim                        CurDAG->getRegister(0, MVT::i32) };
2647243830Sdim      return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2648243830Sdim                                      ARM::UMLAL : ARM::UMLALv5,
2649251662Sdim                                      dl, MVT::i32, MVT::i32, Ops);
2650243830Sdim    }
2651243830Sdim  }
2652243830Sdim  case ARMISD::SMLAL:{
2653243830Sdim    if (Subtarget->isThumb()) {
2654243830Sdim      SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2655243830Sdim                        N->getOperand(3), getAL(CurDAG),
2656243830Sdim                        CurDAG->getRegister(0, MVT::i32)};
2657251662Sdim      return CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops);
2658243830Sdim    }else{
2659243830Sdim      SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2660243830Sdim                        N->getOperand(3), getAL(CurDAG),
2661243830Sdim                        CurDAG->getRegister(0, MVT::i32),
2662243830Sdim                        CurDAG->getRegister(0, MVT::i32) };
2663243830Sdim      return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2664243830Sdim                                      ARM::SMLAL : ARM::SMLALv5,
2665251662Sdim                                      dl, MVT::i32, MVT::i32, Ops);
2666243830Sdim    }
2667243830Sdim  }
2668193323Sed  case ISD::LOAD: {
2669276479Sdim    SDNode *ResNode = nullptr;
2670198090Srdivacky    if (Subtarget->isThumb() && Subtarget->hasThumb2())
2671202375Srdivacky      ResNode = SelectT2IndexedLoad(N);
2672195340Sed    else
2673202375Srdivacky      ResNode = SelectARMIndexedLoad(N);
2674195340Sed    if (ResNode)
2675195340Sed      return ResNode;
2676193323Sed    // Other cases are autogenerated.
2677193323Sed    break;
2678193323Sed  }
2679193323Sed  case ARMISD::BRCOND: {
2680193323Sed    // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2681193323Sed    // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2682193323Sed    // Pattern complexity = 6  cost = 1  size = 0
2683193323Sed
2684193323Sed    // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2685193323Sed    // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
2686193323Sed    // Pattern complexity = 6  cost = 1  size = 0
2687193323Sed
2688195340Sed    // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2689195340Sed    // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2690195340Sed    // Pattern complexity = 6  cost = 1  size = 0
2691195340Sed
2692198090Srdivacky    unsigned Opc = Subtarget->isThumb() ?
2693195340Sed      ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
2694202375Srdivacky    SDValue Chain = N->getOperand(0);
2695202375Srdivacky    SDValue N1 = N->getOperand(1);
2696202375Srdivacky    SDValue N2 = N->getOperand(2);
2697202375Srdivacky    SDValue N3 = N->getOperand(3);
2698202375Srdivacky    SDValue InFlag = N->getOperand(4);
2699193323Sed    assert(N1.getOpcode() == ISD::BasicBlock);
2700193323Sed    assert(N2.getOpcode() == ISD::Constant);
2701193323Sed    assert(N3.getOpcode() == ISD::Register);
2702193323Sed
2703193323Sed    SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
2704193323Sed                               cast<ConstantSDNode>(N2)->getZExtValue()),
2705193323Sed                               MVT::i32);
2706193323Sed    SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
2707198090Srdivacky    SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
2708251662Sdim                                             MVT::Glue, Ops);
2709193323Sed    Chain = SDValue(ResNode, 0);
2710202375Srdivacky    if (N->getNumValues() == 2) {
2711193323Sed      InFlag = SDValue(ResNode, 1);
2712202375Srdivacky      ReplaceUses(SDValue(N, 1), InFlag);
2713193323Sed    }
2714202375Srdivacky    ReplaceUses(SDValue(N, 0),
2715199511Srdivacky                SDValue(Chain.getNode(), Chain.getResNo()));
2716276479Sdim    return nullptr;
2717193323Sed  }
2718198090Srdivacky  case ARMISD::VZIP: {
2719198090Srdivacky    unsigned Opc = 0;
2720198090Srdivacky    EVT VT = N->getValueType(0);
2721198090Srdivacky    switch (VT.getSimpleVT().SimpleTy) {
2722276479Sdim    default: return nullptr;
2723198090Srdivacky    case MVT::v8i8:  Opc = ARM::VZIPd8; break;
2724198090Srdivacky    case MVT::v4i16: Opc = ARM::VZIPd16; break;
2725198090Srdivacky    case MVT::v2f32:
2726234353Sdim    // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2727234353Sdim    case MVT::v2i32: Opc = ARM::VTRNd32; break;
2728198090Srdivacky    case MVT::v16i8: Opc = ARM::VZIPq8; break;
2729198090Srdivacky    case MVT::v8i16: Opc = ARM::VZIPq16; break;
2730198090Srdivacky    case MVT::v4f32:
2731198090Srdivacky    case MVT::v4i32: Opc = ARM::VZIPq32; break;
2732193323Sed    }
2733207618Srdivacky    SDValue Pred = getAL(CurDAG);
2734199989Srdivacky    SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2735199989Srdivacky    SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
2736251662Sdim    return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
2737198090Srdivacky  }
2738198090Srdivacky  case ARMISD::VUZP: {
2739198090Srdivacky    unsigned Opc = 0;
2740198090Srdivacky    EVT VT = N->getValueType(0);
2741198090Srdivacky    switch (VT.getSimpleVT().SimpleTy) {
2742276479Sdim    default: return nullptr;
2743198090Srdivacky    case MVT::v8i8:  Opc = ARM::VUZPd8; break;
2744198090Srdivacky    case MVT::v4i16: Opc = ARM::VUZPd16; break;
2745198090Srdivacky    case MVT::v2f32:
2746234353Sdim    // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2747234353Sdim    case MVT::v2i32: Opc = ARM::VTRNd32; break;
2748198090Srdivacky    case MVT::v16i8: Opc = ARM::VUZPq8; break;
2749198090Srdivacky    case MVT::v8i16: Opc = ARM::VUZPq16; break;
2750198090Srdivacky    case MVT::v4f32:
2751198090Srdivacky    case MVT::v4i32: Opc = ARM::VUZPq32; break;
2752193323Sed    }
2753207618Srdivacky    SDValue Pred = getAL(CurDAG);
2754199989Srdivacky    SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2755199989Srdivacky    SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
2756251662Sdim    return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
2757198090Srdivacky  }
2758198090Srdivacky  case ARMISD::VTRN: {
2759198090Srdivacky    unsigned Opc = 0;
2760198090Srdivacky    EVT VT = N->getValueType(0);
2761198090Srdivacky    switch (VT.getSimpleVT().SimpleTy) {
2762276479Sdim    default: return nullptr;
2763198090Srdivacky    case MVT::v8i8:  Opc = ARM::VTRNd8; break;
2764198090Srdivacky    case MVT::v4i16: Opc = ARM::VTRNd16; break;
2765198090Srdivacky    case MVT::v2f32:
2766198090Srdivacky    case MVT::v2i32: Opc = ARM::VTRNd32; break;
2767198090Srdivacky    case MVT::v16i8: Opc = ARM::VTRNq8; break;
2768198090Srdivacky    case MVT::v8i16: Opc = ARM::VTRNq16; break;
2769198090Srdivacky    case MVT::v4f32:
2770198090Srdivacky    case MVT::v4i32: Opc = ARM::VTRNq32; break;
2771193323Sed    }
2772207618Srdivacky    SDValue Pred = getAL(CurDAG);
2773199989Srdivacky    SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2774199989Srdivacky    SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
2775251662Sdim    return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
2776193323Sed  }
2777210299Sed  case ARMISD::BUILD_VECTOR: {
2778210299Sed    EVT VecVT = N->getValueType(0);
2779210299Sed    EVT EltVT = VecVT.getVectorElementType();
2780210299Sed    unsigned NumElts = VecVT.getVectorNumElements();
2781218893Sdim    if (EltVT == MVT::f64) {
2782210299Sed      assert(NumElts == 2 && "unexpected type for BUILD_VECTOR");
2783249423Sdim      return createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1));
2784210299Sed    }
2785218893Sdim    assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR");
2786210299Sed    if (NumElts == 2)
2787249423Sdim      return createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1));
2788210299Sed    assert(NumElts == 4 && "unexpected type for BUILD_VECTOR");
2789249423Sdim    return createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1),
2790210299Sed                     N->getOperand(2), N->getOperand(3));
2791210299Sed  }
2792194710Sed
2793218893Sdim  case ARMISD::VLD2DUP: {
2794239462Sdim    static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
2795239462Sdim                                        ARM::VLD2DUPd32 };
2796218893Sdim    return SelectVLDDup(N, false, 2, Opcodes);
2797218893Sdim  }
2798218893Sdim
2799218893Sdim  case ARMISD::VLD3DUP: {
2800239462Sdim    static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
2801239462Sdim                                        ARM::VLD3DUPd16Pseudo,
2802239462Sdim                                        ARM::VLD3DUPd32Pseudo };
2803218893Sdim    return SelectVLDDup(N, false, 3, Opcodes);
2804218893Sdim  }
2805218893Sdim
2806218893Sdim  case ARMISD::VLD4DUP: {
2807239462Sdim    static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
2808239462Sdim                                        ARM::VLD4DUPd16Pseudo,
2809239462Sdim                                        ARM::VLD4DUPd32Pseudo };
2810218893Sdim    return SelectVLDDup(N, false, 4, Opcodes);
2811218893Sdim  }
2812218893Sdim
2813218893Sdim  case ARMISD::VLD2DUP_UPD: {
2814239462Sdim    static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed,
2815239462Sdim                                        ARM::VLD2DUPd16wb_fixed,
2816239462Sdim                                        ARM::VLD2DUPd32wb_fixed };
2817218893Sdim    return SelectVLDDup(N, true, 2, Opcodes);
2818218893Sdim  }
2819218893Sdim
2820218893Sdim  case ARMISD::VLD3DUP_UPD: {
2821239462Sdim    static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
2822239462Sdim                                        ARM::VLD3DUPd16Pseudo_UPD,
2823239462Sdim                                        ARM::VLD3DUPd32Pseudo_UPD };
2824218893Sdim    return SelectVLDDup(N, true, 3, Opcodes);
2825218893Sdim  }
2826218893Sdim
2827218893Sdim  case ARMISD::VLD4DUP_UPD: {
2828239462Sdim    static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
2829239462Sdim                                        ARM::VLD4DUPd16Pseudo_UPD,
2830239462Sdim                                        ARM::VLD4DUPd32Pseudo_UPD };
2831218893Sdim    return SelectVLDDup(N, true, 4, Opcodes);
2832218893Sdim  }
2833218893Sdim
2834218893Sdim  case ARMISD::VLD1_UPD: {
2835239462Sdim    static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
2836239462Sdim                                         ARM::VLD1d16wb_fixed,
2837239462Sdim                                         ARM::VLD1d32wb_fixed,
2838239462Sdim                                         ARM::VLD1d64wb_fixed };
2839239462Sdim    static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
2840239462Sdim                                         ARM::VLD1q16wb_fixed,
2841239462Sdim                                         ARM::VLD1q32wb_fixed,
2842239462Sdim                                         ARM::VLD1q64wb_fixed };
2843276479Sdim    return SelectVLD(N, true, 1, DOpcodes, QOpcodes, nullptr);
2844218893Sdim  }
2845218893Sdim
2846218893Sdim  case ARMISD::VLD2_UPD: {
2847239462Sdim    static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed,
2848239462Sdim                                         ARM::VLD2d16wb_fixed,
2849239462Sdim                                         ARM::VLD2d32wb_fixed,
2850239462Sdim                                         ARM::VLD1q64wb_fixed};
2851239462Sdim    static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed,
2852239462Sdim                                         ARM::VLD2q16PseudoWB_fixed,
2853239462Sdim                                         ARM::VLD2q32PseudoWB_fixed };
2854276479Sdim    return SelectVLD(N, true, 2, DOpcodes, QOpcodes, nullptr);
2855218893Sdim  }
2856218893Sdim
2857218893Sdim  case ARMISD::VLD3_UPD: {
2858239462Sdim    static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
2859239462Sdim                                         ARM::VLD3d16Pseudo_UPD,
2860239462Sdim                                         ARM::VLD3d32Pseudo_UPD,
2861265925Sdim                                         ARM::VLD1d64TPseudoWB_fixed};
2862239462Sdim    static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
2863239462Sdim                                          ARM::VLD3q16Pseudo_UPD,
2864239462Sdim                                          ARM::VLD3q32Pseudo_UPD };
2865239462Sdim    static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
2866239462Sdim                                          ARM::VLD3q16oddPseudo_UPD,
2867239462Sdim                                          ARM::VLD3q32oddPseudo_UPD };
2868218893Sdim    return SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
2869218893Sdim  }
2870218893Sdim
2871218893Sdim  case ARMISD::VLD4_UPD: {
2872239462Sdim    static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD,
2873239462Sdim                                         ARM::VLD4d16Pseudo_UPD,
2874239462Sdim                                         ARM::VLD4d32Pseudo_UPD,
2875265925Sdim                                         ARM::VLD1d64QPseudoWB_fixed};
2876239462Sdim    static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
2877239462Sdim                                          ARM::VLD4q16Pseudo_UPD,
2878239462Sdim                                          ARM::VLD4q32Pseudo_UPD };
2879239462Sdim    static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD,
2880239462Sdim                                          ARM::VLD4q16oddPseudo_UPD,
2881239462Sdim                                          ARM::VLD4q32oddPseudo_UPD };
2882218893Sdim    return SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
2883218893Sdim  }
2884218893Sdim
2885218893Sdim  case ARMISD::VLD2LN_UPD: {
2886239462Sdim    static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
2887239462Sdim                                         ARM::VLD2LNd16Pseudo_UPD,
2888239462Sdim                                         ARM::VLD2LNd32Pseudo_UPD };
2889239462Sdim    static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
2890239462Sdim                                         ARM::VLD2LNq32Pseudo_UPD };
2891218893Sdim    return SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes);
2892218893Sdim  }
2893218893Sdim
2894218893Sdim  case ARMISD::VLD3LN_UPD: {
2895239462Sdim    static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
2896239462Sdim                                         ARM::VLD3LNd16Pseudo_UPD,
2897239462Sdim                                         ARM::VLD3LNd32Pseudo_UPD };
2898239462Sdim    static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
2899239462Sdim                                         ARM::VLD3LNq32Pseudo_UPD };
2900218893Sdim    return SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes);
2901218893Sdim  }
2902218893Sdim
2903218893Sdim  case ARMISD::VLD4LN_UPD: {
2904239462Sdim    static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
2905239462Sdim                                         ARM::VLD4LNd16Pseudo_UPD,
2906239462Sdim                                         ARM::VLD4LNd32Pseudo_UPD };
2907239462Sdim    static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
2908239462Sdim                                         ARM::VLD4LNq32Pseudo_UPD };
2909218893Sdim    return SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes);
2910218893Sdim  }
2911218893Sdim
2912218893Sdim  case ARMISD::VST1_UPD: {
2913239462Sdim    static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
2914239462Sdim                                         ARM::VST1d16wb_fixed,
2915239462Sdim                                         ARM::VST1d32wb_fixed,
2916239462Sdim                                         ARM::VST1d64wb_fixed };
2917239462Sdim    static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
2918239462Sdim                                         ARM::VST1q16wb_fixed,
2919239462Sdim                                         ARM::VST1q32wb_fixed,
2920239462Sdim                                         ARM::VST1q64wb_fixed };
2921276479Sdim    return SelectVST(N, true, 1, DOpcodes, QOpcodes, nullptr);
2922218893Sdim  }
2923218893Sdim
2924218893Sdim  case ARMISD::VST2_UPD: {
2925239462Sdim    static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed,
2926239462Sdim                                         ARM::VST2d16wb_fixed,
2927239462Sdim                                         ARM::VST2d32wb_fixed,
2928239462Sdim                                         ARM::VST1q64wb_fixed};
2929239462Sdim    static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed,
2930239462Sdim                                         ARM::VST2q16PseudoWB_fixed,
2931239462Sdim                                         ARM::VST2q32PseudoWB_fixed };
2932276479Sdim    return SelectVST(N, true, 2, DOpcodes, QOpcodes, nullptr);
2933218893Sdim  }
2934218893Sdim
2935218893Sdim  case ARMISD::VST3_UPD: {
2936239462Sdim    static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
2937239462Sdim                                         ARM::VST3d16Pseudo_UPD,
2938239462Sdim                                         ARM::VST3d32Pseudo_UPD,
2939239462Sdim                                         ARM::VST1d64TPseudoWB_fixed};
2940239462Sdim    static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
2941239462Sdim                                          ARM::VST3q16Pseudo_UPD,
2942239462Sdim                                          ARM::VST3q32Pseudo_UPD };
2943239462Sdim    static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
2944239462Sdim                                          ARM::VST3q16oddPseudo_UPD,
2945239462Sdim                                          ARM::VST3q32oddPseudo_UPD };
2946218893Sdim    return SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
2947218893Sdim  }
2948218893Sdim
2949218893Sdim  case ARMISD::VST4_UPD: {
2950239462Sdim    static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD,
2951239462Sdim                                         ARM::VST4d16Pseudo_UPD,
2952239462Sdim                                         ARM::VST4d32Pseudo_UPD,
2953239462Sdim                                         ARM::VST1d64QPseudoWB_fixed};
2954239462Sdim    static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
2955239462Sdim                                          ARM::VST4q16Pseudo_UPD,
2956239462Sdim                                          ARM::VST4q32Pseudo_UPD };
2957239462Sdim    static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD,
2958239462Sdim                                          ARM::VST4q16oddPseudo_UPD,
2959239462Sdim                                          ARM::VST4q32oddPseudo_UPD };
2960218893Sdim    return SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
2961218893Sdim  }
2962218893Sdim
2963218893Sdim  case ARMISD::VST2LN_UPD: {
2964239462Sdim    static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
2965239462Sdim                                         ARM::VST2LNd16Pseudo_UPD,
2966239462Sdim                                         ARM::VST2LNd32Pseudo_UPD };
2967239462Sdim    static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
2968239462Sdim                                         ARM::VST2LNq32Pseudo_UPD };
2969218893Sdim    return SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes);
2970218893Sdim  }
2971218893Sdim
2972218893Sdim  case ARMISD::VST3LN_UPD: {
2973239462Sdim    static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
2974239462Sdim                                         ARM::VST3LNd16Pseudo_UPD,
2975239462Sdim                                         ARM::VST3LNd32Pseudo_UPD };
2976239462Sdim    static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
2977239462Sdim                                         ARM::VST3LNq32Pseudo_UPD };
2978218893Sdim    return SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes);
2979218893Sdim  }
2980218893Sdim
2981218893Sdim  case ARMISD::VST4LN_UPD: {
2982239462Sdim    static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
2983239462Sdim                                         ARM::VST4LNd16Pseudo_UPD,
2984239462Sdim                                         ARM::VST4LNd32Pseudo_UPD };
2985239462Sdim    static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
2986239462Sdim                                         ARM::VST4LNq32Pseudo_UPD };
2987218893Sdim    return SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes);
2988218893Sdim  }
2989218893Sdim
2990198090Srdivacky  case ISD::INTRINSIC_VOID:
2991198090Srdivacky  case ISD::INTRINSIC_W_CHAIN: {
2992198090Srdivacky    unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
2993198090Srdivacky    switch (IntNo) {
2994198090Srdivacky    default:
2995198090Srdivacky      break;
2996194710Sed
2997276479Sdim    case Intrinsic::arm_ldaexd:
2998223017Sdim    case Intrinsic::arm_ldrexd: {
2999261991Sdim      SDLoc dl(N);
3000223017Sdim      SDValue Chain = N->getOperand(0);
3001276479Sdim      SDValue MemAddr = N->getOperand(2);
3002249423Sdim      bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3003223017Sdim
3004276479Sdim      bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
3005276479Sdim      unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
3006276479Sdim                                : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD);
3007276479Sdim
3008223017Sdim      // arm_ldrexd returns a i64 value in {i32, i32}
3009223017Sdim      std::vector<EVT> ResTys;
3010249423Sdim      if (isThumb) {
3011249423Sdim        ResTys.push_back(MVT::i32);
3012249423Sdim        ResTys.push_back(MVT::i32);
3013249423Sdim      } else
3014249423Sdim        ResTys.push_back(MVT::Untyped);
3015223017Sdim      ResTys.push_back(MVT::Other);
3016223017Sdim
3017249423Sdim      // Place arguments in the right order.
3018223017Sdim      SmallVector<SDValue, 7> Ops;
3019223017Sdim      Ops.push_back(MemAddr);
3020223017Sdim      Ops.push_back(getAL(CurDAG));
3021223017Sdim      Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3022223017Sdim      Ops.push_back(Chain);
3023251662Sdim      SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
3024223017Sdim      // Transfer memoperands.
3025223017Sdim      MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3026223017Sdim      MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3027223017Sdim      cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3028223017Sdim
3029223017Sdim      // Remap uses.
3030249423Sdim      SDValue OutChain = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1);
3031223017Sdim      if (!SDValue(N, 0).use_empty()) {
3032249423Sdim        SDValue Result;
3033249423Sdim        if (isThumb)
3034249423Sdim          Result = SDValue(Ld, 0);
3035249423Sdim        else {
3036249423Sdim          SDValue SubRegIdx = CurDAG->getTargetConstant(ARM::gsub_0, MVT::i32);
3037249423Sdim          SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
3038249423Sdim              dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
3039249423Sdim          Result = SDValue(ResNode,0);
3040249423Sdim        }
3041223017Sdim        ReplaceUses(SDValue(N, 0), Result);
3042223017Sdim      }
3043223017Sdim      if (!SDValue(N, 1).use_empty()) {
3044249423Sdim        SDValue Result;
3045249423Sdim        if (isThumb)
3046249423Sdim          Result = SDValue(Ld, 1);
3047249423Sdim        else {
3048249423Sdim          SDValue SubRegIdx = CurDAG->getTargetConstant(ARM::gsub_1, MVT::i32);
3049249423Sdim          SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
3050249423Sdim              dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
3051249423Sdim          Result = SDValue(ResNode,0);
3052249423Sdim        }
3053223017Sdim        ReplaceUses(SDValue(N, 1), Result);
3054223017Sdim      }
3055249423Sdim      ReplaceUses(SDValue(N, 2), OutChain);
3056276479Sdim      return nullptr;
3057223017Sdim    }
3058276479Sdim    case Intrinsic::arm_stlexd:
3059223017Sdim    case Intrinsic::arm_strexd: {
3060261991Sdim      SDLoc dl(N);
3061223017Sdim      SDValue Chain = N->getOperand(0);
3062223017Sdim      SDValue Val0 = N->getOperand(2);
3063223017Sdim      SDValue Val1 = N->getOperand(3);
3064223017Sdim      SDValue MemAddr = N->getOperand(4);
3065223017Sdim
3066223017Sdim      // Store exclusive double return a i32 value which is the return status
3067223017Sdim      // of the issued store.
3068249423Sdim      EVT ResTys[] = { MVT::i32, MVT::Other };
3069223017Sdim
3070249423Sdim      bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3071249423Sdim      // Place arguments in the right order.
3072223017Sdim      SmallVector<SDValue, 7> Ops;
3073249423Sdim      if (isThumb) {
3074249423Sdim        Ops.push_back(Val0);
3075249423Sdim        Ops.push_back(Val1);
3076249423Sdim      } else
3077249423Sdim        // arm_strexd uses GPRPair.
3078249423Sdim        Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0));
3079223017Sdim      Ops.push_back(MemAddr);
3080223017Sdim      Ops.push_back(getAL(CurDAG));
3081223017Sdim      Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3082223017Sdim      Ops.push_back(Chain);
3083223017Sdim
3084276479Sdim      bool IsRelease = IntNo == Intrinsic::arm_stlexd;
3085276479Sdim      unsigned NewOpc = isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
3086276479Sdim                                : (IsRelease ? ARM::STLEXD : ARM::STREXD);
3087223017Sdim
3088251662Sdim      SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
3089223017Sdim      // Transfer memoperands.
3090223017Sdim      MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3091223017Sdim      MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3092223017Sdim      cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3093223017Sdim
3094223017Sdim      return St;
3095223017Sdim    }
3096223017Sdim
3097206083Srdivacky    case Intrinsic::arm_neon_vld1: {
3098239462Sdim      static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3099239462Sdim                                           ARM::VLD1d32, ARM::VLD1d64 };
3100239462Sdim      static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3101239462Sdim                                           ARM::VLD1q32, ARM::VLD1q64};
3102276479Sdim      return SelectVLD(N, false, 1, DOpcodes, QOpcodes, nullptr);
3103206083Srdivacky    }
3104206083Srdivacky
3105198090Srdivacky    case Intrinsic::arm_neon_vld2: {
3106239462Sdim      static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3107239462Sdim                                           ARM::VLD2d32, ARM::VLD1q64 };
3108239462Sdim      static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3109239462Sdim                                           ARM::VLD2q32Pseudo };
3110276479Sdim      return SelectVLD(N, false, 2, DOpcodes, QOpcodes, nullptr);
3111198090Srdivacky    }
3112194710Sed
3113198090Srdivacky    case Intrinsic::arm_neon_vld3: {
3114239462Sdim      static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3115239462Sdim                                           ARM::VLD3d16Pseudo,
3116239462Sdim                                           ARM::VLD3d32Pseudo,
3117239462Sdim                                           ARM::VLD1d64TPseudo };
3118239462Sdim      static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3119239462Sdim                                            ARM::VLD3q16Pseudo_UPD,
3120239462Sdim                                            ARM::VLD3q32Pseudo_UPD };
3121239462Sdim      static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3122239462Sdim                                            ARM::VLD3q16oddPseudo,
3123239462Sdim                                            ARM::VLD3q32oddPseudo };
3124218893Sdim      return SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3125198090Srdivacky    }
3126198090Srdivacky
3127198090Srdivacky    case Intrinsic::arm_neon_vld4: {
3128239462Sdim      static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3129239462Sdim                                           ARM::VLD4d16Pseudo,
3130239462Sdim                                           ARM::VLD4d32Pseudo,
3131239462Sdim                                           ARM::VLD1d64QPseudo };
3132239462Sdim      static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3133239462Sdim                                            ARM::VLD4q16Pseudo_UPD,
3134239462Sdim                                            ARM::VLD4q32Pseudo_UPD };
3135239462Sdim      static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3136239462Sdim                                            ARM::VLD4q16oddPseudo,
3137239462Sdim                                            ARM::VLD4q32oddPseudo };
3138218893Sdim      return SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3139198090Srdivacky    }
3140198090Srdivacky
3141198090Srdivacky    case Intrinsic::arm_neon_vld2lane: {
3142239462Sdim      static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3143239462Sdim                                           ARM::VLD2LNd16Pseudo,
3144239462Sdim                                           ARM::VLD2LNd32Pseudo };
3145239462Sdim      static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3146239462Sdim                                           ARM::VLD2LNq32Pseudo };
3147218893Sdim      return SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes);
3148198090Srdivacky    }
3149198090Srdivacky
3150198090Srdivacky    case Intrinsic::arm_neon_vld3lane: {
3151239462Sdim      static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3152239462Sdim                                           ARM::VLD3LNd16Pseudo,
3153239462Sdim                                           ARM::VLD3LNd32Pseudo };
3154239462Sdim      static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3155239462Sdim                                           ARM::VLD3LNq32Pseudo };
3156218893Sdim      return SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes);
3157198090Srdivacky    }
3158198090Srdivacky
3159198090Srdivacky    case Intrinsic::arm_neon_vld4lane: {
3160239462Sdim      static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3161239462Sdim                                           ARM::VLD4LNd16Pseudo,
3162239462Sdim                                           ARM::VLD4LNd32Pseudo };
3163239462Sdim      static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3164239462Sdim                                           ARM::VLD4LNq32Pseudo };
3165218893Sdim      return SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes);
3166198090Srdivacky    }
3167198090Srdivacky
3168206083Srdivacky    case Intrinsic::arm_neon_vst1: {
3169239462Sdim      static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3170239462Sdim                                           ARM::VST1d32, ARM::VST1d64 };
3171239462Sdim      static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3172239462Sdim                                           ARM::VST1q32, ARM::VST1q64 };
3173276479Sdim      return SelectVST(N, false, 1, DOpcodes, QOpcodes, nullptr);
3174206083Srdivacky    }
3175206083Srdivacky
3176198090Srdivacky    case Intrinsic::arm_neon_vst2: {
3177239462Sdim      static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3178239462Sdim                                           ARM::VST2d32, ARM::VST1q64 };
3179239462Sdim      static uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3180239462Sdim                                     ARM::VST2q32Pseudo };
3181276479Sdim      return SelectVST(N, false, 2, DOpcodes, QOpcodes, nullptr);
3182198090Srdivacky    }
3183194710Sed
3184198090Srdivacky    case Intrinsic::arm_neon_vst3: {
3185239462Sdim      static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3186239462Sdim                                           ARM::VST3d16Pseudo,
3187239462Sdim                                           ARM::VST3d32Pseudo,
3188239462Sdim                                           ARM::VST1d64TPseudo };
3189239462Sdim      static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3190239462Sdim                                            ARM::VST3q16Pseudo_UPD,
3191239462Sdim                                            ARM::VST3q32Pseudo_UPD };
3192239462Sdim      static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3193239462Sdim                                            ARM::VST3q16oddPseudo,
3194239462Sdim                                            ARM::VST3q32oddPseudo };
3195218893Sdim      return SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3196194710Sed    }
3197194710Sed
3198198090Srdivacky    case Intrinsic::arm_neon_vst4: {
3199239462Sdim      static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3200239462Sdim                                           ARM::VST4d16Pseudo,
3201239462Sdim                                           ARM::VST4d32Pseudo,
3202239462Sdim                                           ARM::VST1d64QPseudo };
3203239462Sdim      static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3204239462Sdim                                            ARM::VST4q16Pseudo_UPD,
3205239462Sdim                                            ARM::VST4q32Pseudo_UPD };
3206239462Sdim      static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3207239462Sdim                                            ARM::VST4q16oddPseudo,
3208239462Sdim                                            ARM::VST4q32oddPseudo };
3209218893Sdim      return SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3210198090Srdivacky    }
3211198090Srdivacky
3212198090Srdivacky    case Intrinsic::arm_neon_vst2lane: {
3213239462Sdim      static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3214239462Sdim                                           ARM::VST2LNd16Pseudo,
3215239462Sdim                                           ARM::VST2LNd32Pseudo };
3216239462Sdim      static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3217239462Sdim                                           ARM::VST2LNq32Pseudo };
3218218893Sdim      return SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes);
3219198090Srdivacky    }
3220198090Srdivacky
3221198090Srdivacky    case Intrinsic::arm_neon_vst3lane: {
3222239462Sdim      static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3223239462Sdim                                           ARM::VST3LNd16Pseudo,
3224239462Sdim                                           ARM::VST3LNd32Pseudo };
3225239462Sdim      static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3226239462Sdim                                           ARM::VST3LNq32Pseudo };
3227218893Sdim      return SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes);
3228198090Srdivacky    }
3229198090Srdivacky
3230198090Srdivacky    case Intrinsic::arm_neon_vst4lane: {
3231239462Sdim      static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3232239462Sdim                                           ARM::VST4LNd16Pseudo,
3233239462Sdim                                           ARM::VST4LNd32Pseudo };
3234239462Sdim      static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3235239462Sdim                                           ARM::VST4LNq32Pseudo };
3236218893Sdim      return SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes);
3237198090Srdivacky    }
3238198090Srdivacky    }
3239208599Srdivacky    break;
3240194710Sed  }
3241208599Srdivacky
3242210299Sed  case ISD::INTRINSIC_WO_CHAIN: {
3243210299Sed    unsigned IntNo = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
3244210299Sed    switch (IntNo) {
3245210299Sed    default:
3246210299Sed      break;
3247210299Sed
3248210299Sed    case Intrinsic::arm_neon_vtbl2:
3249234353Sdim      return SelectVTBL(N, false, 2, ARM::VTBL2);
3250210299Sed    case Intrinsic::arm_neon_vtbl3:
3251218893Sdim      return SelectVTBL(N, false, 3, ARM::VTBL3Pseudo);
3252210299Sed    case Intrinsic::arm_neon_vtbl4:
3253218893Sdim      return SelectVTBL(N, false, 4, ARM::VTBL4Pseudo);
3254210299Sed
3255210299Sed    case Intrinsic::arm_neon_vtbx2:
3256234353Sdim      return SelectVTBL(N, true, 2, ARM::VTBX2);
3257210299Sed    case Intrinsic::arm_neon_vtbx3:
3258218893Sdim      return SelectVTBL(N, true, 3, ARM::VTBX3Pseudo);
3259210299Sed    case Intrinsic::arm_neon_vtbx4:
3260218893Sdim      return SelectVTBL(N, true, 4, ARM::VTBX4Pseudo);
3261210299Sed    }
3262210299Sed    break;
3263210299Sed  }
3264210299Sed
3265221345Sdim  case ARMISD::VTBL1: {
3266261991Sdim    SDLoc dl(N);
3267221345Sdim    EVT VT = N->getValueType(0);
3268221345Sdim    SmallVector<SDValue, 6> Ops;
3269221345Sdim
3270221345Sdim    Ops.push_back(N->getOperand(0));
3271221345Sdim    Ops.push_back(N->getOperand(1));
3272221345Sdim    Ops.push_back(getAL(CurDAG));                    // Predicate
3273221345Sdim    Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register
3274251662Sdim    return CurDAG->getMachineNode(ARM::VTBL1, dl, VT, Ops);
3275221345Sdim  }
3276221345Sdim  case ARMISD::VTBL2: {
3277261991Sdim    SDLoc dl(N);
3278221345Sdim    EVT VT = N->getValueType(0);
3279221345Sdim
3280221345Sdim    // Form a REG_SEQUENCE to force register allocation.
3281221345Sdim    SDValue V0 = N->getOperand(0);
3282221345Sdim    SDValue V1 = N->getOperand(1);
3283249423Sdim    SDValue RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
3284221345Sdim
3285221345Sdim    SmallVector<SDValue, 6> Ops;
3286221345Sdim    Ops.push_back(RegSeq);
3287221345Sdim    Ops.push_back(N->getOperand(2));
3288221345Sdim    Ops.push_back(getAL(CurDAG));                    // Predicate
3289221345Sdim    Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register
3290251662Sdim    return CurDAG->getMachineNode(ARM::VTBL2, dl, VT, Ops);
3291221345Sdim  }
3292221345Sdim
3293208599Srdivacky  case ISD::CONCAT_VECTORS:
3294208599Srdivacky    return SelectConcatVector(N);
3295194710Sed  }
3296194710Sed
3297202375Srdivacky  return SelectCode(N);
3298193323Sed}
3299193323Sed
3300249423SdimSDNode *ARMDAGToDAGISel::SelectInlineAsm(SDNode *N){
3301249423Sdim  std::vector<SDValue> AsmNodeOperands;
3302249423Sdim  unsigned Flag, Kind;
3303249423Sdim  bool Changed = false;
3304249423Sdim  unsigned NumOps = N->getNumOperands();
3305249423Sdim
3306249423Sdim  // Normally, i64 data is bounded to two arbitrary GRPs for "%r" constraint.
3307249423Sdim  // However, some instrstions (e.g. ldrexd/strexd in ARM mode) require
3308249423Sdim  // (even/even+1) GPRs and use %n and %Hn to refer to the individual regs
3309249423Sdim  // respectively. Since there is no constraint to explicitly specify a
3310261991Sdim  // reg pair, we use GPRPair reg class for "%r" for 64-bit data. For Thumb,
3311261991Sdim  // the 64-bit data may be referred by H, Q, R modifiers, so we still pack
3312261991Sdim  // them into a GPRPair.
3313249423Sdim
3314261991Sdim  SDLoc dl(N);
3315276479Sdim  SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1)
3316276479Sdim                                   : SDValue(nullptr,0);
3317249423Sdim
3318261991Sdim  SmallVector<bool, 8> OpChanged;
3319249423Sdim  // Glue node will be appended late.
3320261991Sdim  for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
3321249423Sdim    SDValue op = N->getOperand(i);
3322249423Sdim    AsmNodeOperands.push_back(op);
3323249423Sdim
3324249423Sdim    if (i < InlineAsm::Op_FirstOperand)
3325249423Sdim      continue;
3326249423Sdim
3327249423Sdim    if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) {
3328249423Sdim      Flag = C->getZExtValue();
3329249423Sdim      Kind = InlineAsm::getKind(Flag);
3330249423Sdim    }
3331249423Sdim    else
3332249423Sdim      continue;
3333249423Sdim
3334261991Sdim    // Immediate operands to inline asm in the SelectionDAG are modeled with
3335261991Sdim    // two operands. The first is a constant of value InlineAsm::Kind_Imm, and
3336261991Sdim    // the second is a constant with the value of the immediate. If we get here
3337261991Sdim    // and we have a Kind_Imm, skip the next operand, and continue.
3338261991Sdim    if (Kind == InlineAsm::Kind_Imm) {
3339261991Sdim      SDValue op = N->getOperand(++i);
3340261991Sdim      AsmNodeOperands.push_back(op);
3341261991Sdim      continue;
3342261991Sdim    }
3343261991Sdim
3344261991Sdim    unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag);
3345261991Sdim    if (NumRegs)
3346261991Sdim      OpChanged.push_back(false);
3347261991Sdim
3348261991Sdim    unsigned DefIdx = 0;
3349261991Sdim    bool IsTiedToChangedOp = false;
3350261991Sdim    // If it's a use that is tied with a previous def, it has no
3351261991Sdim    // reg class constraint.
3352261991Sdim    if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx))
3353261991Sdim      IsTiedToChangedOp = OpChanged[DefIdx];
3354261991Sdim
3355249423Sdim    if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef
3356249423Sdim        && Kind != InlineAsm::Kind_RegDefEarlyClobber)
3357249423Sdim      continue;
3358249423Sdim
3359249423Sdim    unsigned RC;
3360249423Sdim    bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC);
3361261991Sdim    if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
3362261991Sdim        || NumRegs != 2)
3363249423Sdim      continue;
3364249423Sdim
3365261991Sdim    assert((i+2 < NumOps) && "Invalid number of operands in inline asm");
3366249423Sdim    SDValue V0 = N->getOperand(i+1);
3367249423Sdim    SDValue V1 = N->getOperand(i+2);
3368249423Sdim    unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg();
3369249423Sdim    unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg();
3370249423Sdim    SDValue PairedReg;
3371249423Sdim    MachineRegisterInfo &MRI = MF->getRegInfo();
3372249423Sdim
3373249423Sdim    if (Kind == InlineAsm::Kind_RegDef ||
3374249423Sdim        Kind == InlineAsm::Kind_RegDefEarlyClobber) {
3375249423Sdim      // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to
3376249423Sdim      // the original GPRs.
3377249423Sdim
3378249423Sdim      unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
3379249423Sdim      PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
3380249423Sdim      SDValue Chain = SDValue(N,0);
3381249423Sdim
3382249423Sdim      SDNode *GU = N->getGluedUser();
3383249423Sdim      SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
3384249423Sdim                                               Chain.getValue(1));
3385249423Sdim
3386249423Sdim      // Extract values from a GPRPair reg and copy to the original GPR reg.
3387249423Sdim      SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
3388249423Sdim                                                    RegCopy);
3389249423Sdim      SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
3390249423Sdim                                                    RegCopy);
3391249423Sdim      SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
3392249423Sdim                                        RegCopy.getValue(1));
3393249423Sdim      SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1));
3394249423Sdim
3395249423Sdim      // Update the original glue user.
3396249423Sdim      std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1);
3397249423Sdim      Ops.push_back(T1.getValue(1));
3398276479Sdim      CurDAG->UpdateNodeOperands(GU, Ops);
3399249423Sdim    }
3400249423Sdim    else {
3401249423Sdim      // For Kind  == InlineAsm::Kind_RegUse, we first copy two GPRs into a
3402249423Sdim      // GPRPair and then pass the GPRPair to the inline asm.
3403249423Sdim      SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain];
3404249423Sdim
3405249423Sdim      // As REG_SEQ doesn't take RegisterSDNode, we copy them first.
3406249423Sdim      SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
3407249423Sdim                                          Chain.getValue(1));
3408249423Sdim      SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
3409249423Sdim                                          T0.getValue(1));
3410249423Sdim      SDValue Pair = SDValue(createGPRPairNode(MVT::Untyped, T0, T1), 0);
3411249423Sdim
3412249423Sdim      // Copy REG_SEQ into a GPRPair-typed VR and replace the original two
3413249423Sdim      // i32 VRs of inline asm with it.
3414249423Sdim      unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
3415249423Sdim      PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
3416249423Sdim      Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1));
3417249423Sdim
3418249423Sdim      AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
3419249423Sdim      Glue = Chain.getValue(1);
3420249423Sdim    }
3421249423Sdim
3422249423Sdim    Changed = true;
3423249423Sdim
3424249423Sdim    if(PairedReg.getNode()) {
3425261991Sdim      OpChanged[OpChanged.size() -1 ] = true;
3426249423Sdim      Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/);
3427261991Sdim      if (IsTiedToChangedOp)
3428261991Sdim        Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx);
3429261991Sdim      else
3430261991Sdim        Flag = InlineAsm::getFlagWordForRegClass(Flag, ARM::GPRPairRegClassID);
3431249423Sdim      // Replace the current flag.
3432249423Sdim      AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
3433249423Sdim          Flag, MVT::i32);
3434249423Sdim      // Add the new register node and skip the original two GPRs.
3435249423Sdim      AsmNodeOperands.push_back(PairedReg);
3436249423Sdim      // Skip the next two GPRs.
3437249423Sdim      i += 2;
3438249423Sdim    }
3439249423Sdim  }
3440249423Sdim
3441261991Sdim  if (Glue.getNode())
3442261991Sdim    AsmNodeOperands.push_back(Glue);
3443249423Sdim  if (!Changed)
3444276479Sdim    return nullptr;
3445249423Sdim
3446261991Sdim  SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N),
3447276479Sdim      CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
3448249423Sdim  New->setNodeId(-1);
3449249423Sdim  return New.getNode();
3450249423Sdim}
3451249423Sdim
3452249423Sdim
3453193323Sedbool ARMDAGToDAGISel::
3454193323SedSelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
3455193323Sed                             std::vector<SDValue> &OutOps) {
3456193323Sed  assert(ConstraintCode == 'm' && "unexpected asm memory constraint");
3457198090Srdivacky  // Require the address to be in a register.  That is safe for all ARM
3458198090Srdivacky  // variants and it is hard to do anything much smarter without knowing
3459198090Srdivacky  // how the operand is used.
3460198090Srdivacky  OutOps.push_back(Op);
3461193323Sed  return false;
3462193323Sed}
3463193323Sed
3464193323Sed/// createARMISelDag - This pass converts a legalized DAG into a
3465193323Sed/// ARM-specific DAG, ready for instruction scheduling.
3466193323Sed///
3467198090SrdivackyFunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
3468198090Srdivacky                                     CodeGenOpt::Level OptLevel) {
3469198090Srdivacky  return new ARMDAGToDAGISel(TM, OptLevel);
3470193323Sed}
3471