xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===-- AArch64ISelDAGToDAG.cpp - A dag to dag inst selector for AArch64 --===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // This file defines an instruction selector for the AArch64 target.
10*0b57cec5SDimitry Andric //
11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
12*0b57cec5SDimitry Andric 
13*0b57cec5SDimitry Andric #include "AArch64TargetMachine.h"
14*0b57cec5SDimitry Andric #include "MCTargetDesc/AArch64AddressingModes.h"
15*0b57cec5SDimitry Andric #include "llvm/ADT/APSInt.h"
16*0b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAGISel.h"
17*0b57cec5SDimitry Andric #include "llvm/IR/Function.h" // To access function attributes.
18*0b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
19*0b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h"
20*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
21*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
22*0b57cec5SDimitry Andric #include "llvm/Support/KnownBits.h"
23*0b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
24*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
25*0b57cec5SDimitry Andric 
26*0b57cec5SDimitry Andric using namespace llvm;
27*0b57cec5SDimitry Andric 
28*0b57cec5SDimitry Andric #define DEBUG_TYPE "aarch64-isel"
29*0b57cec5SDimitry Andric 
30*0b57cec5SDimitry Andric //===--------------------------------------------------------------------===//
31*0b57cec5SDimitry Andric /// AArch64DAGToDAGISel - AArch64 specific code to select AArch64 machine
32*0b57cec5SDimitry Andric /// instructions for SelectionDAG operations.
33*0b57cec5SDimitry Andric ///
34*0b57cec5SDimitry Andric namespace {
35*0b57cec5SDimitry Andric 
36*0b57cec5SDimitry Andric class AArch64DAGToDAGISel : public SelectionDAGISel {
37*0b57cec5SDimitry Andric 
38*0b57cec5SDimitry Andric   /// Subtarget - Keep a pointer to the AArch64Subtarget around so that we can
39*0b57cec5SDimitry Andric   /// make the right decision when generating code for different targets.
40*0b57cec5SDimitry Andric   const AArch64Subtarget *Subtarget;
41*0b57cec5SDimitry Andric 
42*0b57cec5SDimitry Andric   bool ForCodeSize;
43*0b57cec5SDimitry Andric 
44*0b57cec5SDimitry Andric public:
45*0b57cec5SDimitry Andric   explicit AArch64DAGToDAGISel(AArch64TargetMachine &tm,
46*0b57cec5SDimitry Andric                                CodeGenOpt::Level OptLevel)
47*0b57cec5SDimitry Andric       : SelectionDAGISel(tm, OptLevel), Subtarget(nullptr),
48*0b57cec5SDimitry Andric         ForCodeSize(false) {}
49*0b57cec5SDimitry Andric 
50*0b57cec5SDimitry Andric   StringRef getPassName() const override {
51*0b57cec5SDimitry Andric     return "AArch64 Instruction Selection";
52*0b57cec5SDimitry Andric   }
53*0b57cec5SDimitry Andric 
54*0b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override {
55*0b57cec5SDimitry Andric     ForCodeSize = MF.getFunction().hasOptSize();
56*0b57cec5SDimitry Andric     Subtarget = &MF.getSubtarget<AArch64Subtarget>();
57*0b57cec5SDimitry Andric     return SelectionDAGISel::runOnMachineFunction(MF);
58*0b57cec5SDimitry Andric   }
59*0b57cec5SDimitry Andric 
60*0b57cec5SDimitry Andric   void Select(SDNode *Node) override;
61*0b57cec5SDimitry Andric 
62*0b57cec5SDimitry Andric   /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
63*0b57cec5SDimitry Andric   /// inline asm expressions.
64*0b57cec5SDimitry Andric   bool SelectInlineAsmMemoryOperand(const SDValue &Op,
65*0b57cec5SDimitry Andric                                     unsigned ConstraintID,
66*0b57cec5SDimitry Andric                                     std::vector<SDValue> &OutOps) override;
67*0b57cec5SDimitry Andric 
68*0b57cec5SDimitry Andric   bool tryMLAV64LaneV128(SDNode *N);
69*0b57cec5SDimitry Andric   bool tryMULLV64LaneV128(unsigned IntNo, SDNode *N);
70*0b57cec5SDimitry Andric   bool SelectArithExtendedRegister(SDValue N, SDValue &Reg, SDValue &Shift);
71*0b57cec5SDimitry Andric   bool SelectArithImmed(SDValue N, SDValue &Val, SDValue &Shift);
72*0b57cec5SDimitry Andric   bool SelectNegArithImmed(SDValue N, SDValue &Val, SDValue &Shift);
73*0b57cec5SDimitry Andric   bool SelectArithShiftedRegister(SDValue N, SDValue &Reg, SDValue &Shift) {
74*0b57cec5SDimitry Andric     return SelectShiftedRegister(N, false, Reg, Shift);
75*0b57cec5SDimitry Andric   }
76*0b57cec5SDimitry Andric   bool SelectLogicalShiftedRegister(SDValue N, SDValue &Reg, SDValue &Shift) {
77*0b57cec5SDimitry Andric     return SelectShiftedRegister(N, true, Reg, Shift);
78*0b57cec5SDimitry Andric   }
79*0b57cec5SDimitry Andric   bool SelectAddrModeIndexed7S8(SDValue N, SDValue &Base, SDValue &OffImm) {
80*0b57cec5SDimitry Andric     return SelectAddrModeIndexed7S(N, 1, Base, OffImm);
81*0b57cec5SDimitry Andric   }
82*0b57cec5SDimitry Andric   bool SelectAddrModeIndexed7S16(SDValue N, SDValue &Base, SDValue &OffImm) {
83*0b57cec5SDimitry Andric     return SelectAddrModeIndexed7S(N, 2, Base, OffImm);
84*0b57cec5SDimitry Andric   }
85*0b57cec5SDimitry Andric   bool SelectAddrModeIndexed7S32(SDValue N, SDValue &Base, SDValue &OffImm) {
86*0b57cec5SDimitry Andric     return SelectAddrModeIndexed7S(N, 4, Base, OffImm);
87*0b57cec5SDimitry Andric   }
88*0b57cec5SDimitry Andric   bool SelectAddrModeIndexed7S64(SDValue N, SDValue &Base, SDValue &OffImm) {
89*0b57cec5SDimitry Andric     return SelectAddrModeIndexed7S(N, 8, Base, OffImm);
90*0b57cec5SDimitry Andric   }
91*0b57cec5SDimitry Andric   bool SelectAddrModeIndexed7S128(SDValue N, SDValue &Base, SDValue &OffImm) {
92*0b57cec5SDimitry Andric     return SelectAddrModeIndexed7S(N, 16, Base, OffImm);
93*0b57cec5SDimitry Andric   }
94*0b57cec5SDimitry Andric   bool SelectAddrModeIndexedS9S128(SDValue N, SDValue &Base, SDValue &OffImm) {
95*0b57cec5SDimitry Andric     return SelectAddrModeIndexedBitWidth(N, true, 9, 16, Base, OffImm);
96*0b57cec5SDimitry Andric   }
97*0b57cec5SDimitry Andric   bool SelectAddrModeIndexedU6S128(SDValue N, SDValue &Base, SDValue &OffImm) {
98*0b57cec5SDimitry Andric     return SelectAddrModeIndexedBitWidth(N, false, 6, 16, Base, OffImm);
99*0b57cec5SDimitry Andric   }
100*0b57cec5SDimitry Andric   bool SelectAddrModeIndexed8(SDValue N, SDValue &Base, SDValue &OffImm) {
101*0b57cec5SDimitry Andric     return SelectAddrModeIndexed(N, 1, Base, OffImm);
102*0b57cec5SDimitry Andric   }
103*0b57cec5SDimitry Andric   bool SelectAddrModeIndexed16(SDValue N, SDValue &Base, SDValue &OffImm) {
104*0b57cec5SDimitry Andric     return SelectAddrModeIndexed(N, 2, Base, OffImm);
105*0b57cec5SDimitry Andric   }
106*0b57cec5SDimitry Andric   bool SelectAddrModeIndexed32(SDValue N, SDValue &Base, SDValue &OffImm) {
107*0b57cec5SDimitry Andric     return SelectAddrModeIndexed(N, 4, Base, OffImm);
108*0b57cec5SDimitry Andric   }
109*0b57cec5SDimitry Andric   bool SelectAddrModeIndexed64(SDValue N, SDValue &Base, SDValue &OffImm) {
110*0b57cec5SDimitry Andric     return SelectAddrModeIndexed(N, 8, Base, OffImm);
111*0b57cec5SDimitry Andric   }
112*0b57cec5SDimitry Andric   bool SelectAddrModeIndexed128(SDValue N, SDValue &Base, SDValue &OffImm) {
113*0b57cec5SDimitry Andric     return SelectAddrModeIndexed(N, 16, Base, OffImm);
114*0b57cec5SDimitry Andric   }
115*0b57cec5SDimitry Andric   bool SelectAddrModeUnscaled8(SDValue N, SDValue &Base, SDValue &OffImm) {
116*0b57cec5SDimitry Andric     return SelectAddrModeUnscaled(N, 1, Base, OffImm);
117*0b57cec5SDimitry Andric   }
118*0b57cec5SDimitry Andric   bool SelectAddrModeUnscaled16(SDValue N, SDValue &Base, SDValue &OffImm) {
119*0b57cec5SDimitry Andric     return SelectAddrModeUnscaled(N, 2, Base, OffImm);
120*0b57cec5SDimitry Andric   }
121*0b57cec5SDimitry Andric   bool SelectAddrModeUnscaled32(SDValue N, SDValue &Base, SDValue &OffImm) {
122*0b57cec5SDimitry Andric     return SelectAddrModeUnscaled(N, 4, Base, OffImm);
123*0b57cec5SDimitry Andric   }
124*0b57cec5SDimitry Andric   bool SelectAddrModeUnscaled64(SDValue N, SDValue &Base, SDValue &OffImm) {
125*0b57cec5SDimitry Andric     return SelectAddrModeUnscaled(N, 8, Base, OffImm);
126*0b57cec5SDimitry Andric   }
127*0b57cec5SDimitry Andric   bool SelectAddrModeUnscaled128(SDValue N, SDValue &Base, SDValue &OffImm) {
128*0b57cec5SDimitry Andric     return SelectAddrModeUnscaled(N, 16, Base, OffImm);
129*0b57cec5SDimitry Andric   }
130*0b57cec5SDimitry Andric 
131*0b57cec5SDimitry Andric   template<int Width>
132*0b57cec5SDimitry Andric   bool SelectAddrModeWRO(SDValue N, SDValue &Base, SDValue &Offset,
133*0b57cec5SDimitry Andric                          SDValue &SignExtend, SDValue &DoShift) {
134*0b57cec5SDimitry Andric     return SelectAddrModeWRO(N, Width / 8, Base, Offset, SignExtend, DoShift);
135*0b57cec5SDimitry Andric   }
136*0b57cec5SDimitry Andric 
137*0b57cec5SDimitry Andric   template<int Width>
138*0b57cec5SDimitry Andric   bool SelectAddrModeXRO(SDValue N, SDValue &Base, SDValue &Offset,
139*0b57cec5SDimitry Andric                          SDValue &SignExtend, SDValue &DoShift) {
140*0b57cec5SDimitry Andric     return SelectAddrModeXRO(N, Width / 8, Base, Offset, SignExtend, DoShift);
141*0b57cec5SDimitry Andric   }
142*0b57cec5SDimitry Andric 
143*0b57cec5SDimitry Andric 
144*0b57cec5SDimitry Andric   /// Form sequences of consecutive 64/128-bit registers for use in NEON
145*0b57cec5SDimitry Andric   /// instructions making use of a vector-list (e.g. ldN, tbl). Vecs must have
146*0b57cec5SDimitry Andric   /// between 1 and 4 elements. If it contains a single element that is returned
147*0b57cec5SDimitry Andric   /// unchanged; otherwise a REG_SEQUENCE value is returned.
148*0b57cec5SDimitry Andric   SDValue createDTuple(ArrayRef<SDValue> Vecs);
149*0b57cec5SDimitry Andric   SDValue createQTuple(ArrayRef<SDValue> Vecs);
150*0b57cec5SDimitry Andric 
151*0b57cec5SDimitry Andric   /// Generic helper for the createDTuple/createQTuple
152*0b57cec5SDimitry Andric   /// functions. Those should almost always be called instead.
153*0b57cec5SDimitry Andric   SDValue createTuple(ArrayRef<SDValue> Vecs, const unsigned RegClassIDs[],
154*0b57cec5SDimitry Andric                       const unsigned SubRegs[]);
155*0b57cec5SDimitry Andric 
156*0b57cec5SDimitry Andric   void SelectTable(SDNode *N, unsigned NumVecs, unsigned Opc, bool isExt);
157*0b57cec5SDimitry Andric 
158*0b57cec5SDimitry Andric   bool tryIndexedLoad(SDNode *N);
159*0b57cec5SDimitry Andric 
160*0b57cec5SDimitry Andric   bool trySelectStackSlotTagP(SDNode *N);
161*0b57cec5SDimitry Andric   void SelectTagP(SDNode *N);
162*0b57cec5SDimitry Andric 
163*0b57cec5SDimitry Andric   void SelectLoad(SDNode *N, unsigned NumVecs, unsigned Opc,
164*0b57cec5SDimitry Andric                      unsigned SubRegIdx);
165*0b57cec5SDimitry Andric   void SelectPostLoad(SDNode *N, unsigned NumVecs, unsigned Opc,
166*0b57cec5SDimitry Andric                          unsigned SubRegIdx);
167*0b57cec5SDimitry Andric   void SelectLoadLane(SDNode *N, unsigned NumVecs, unsigned Opc);
168*0b57cec5SDimitry Andric   void SelectPostLoadLane(SDNode *N, unsigned NumVecs, unsigned Opc);
169*0b57cec5SDimitry Andric 
170*0b57cec5SDimitry Andric   void SelectStore(SDNode *N, unsigned NumVecs, unsigned Opc);
171*0b57cec5SDimitry Andric   void SelectPostStore(SDNode *N, unsigned NumVecs, unsigned Opc);
172*0b57cec5SDimitry Andric   void SelectStoreLane(SDNode *N, unsigned NumVecs, unsigned Opc);
173*0b57cec5SDimitry Andric   void SelectPostStoreLane(SDNode *N, unsigned NumVecs, unsigned Opc);
174*0b57cec5SDimitry Andric 
175*0b57cec5SDimitry Andric   bool tryBitfieldExtractOp(SDNode *N);
176*0b57cec5SDimitry Andric   bool tryBitfieldExtractOpFromSExt(SDNode *N);
177*0b57cec5SDimitry Andric   bool tryBitfieldInsertOp(SDNode *N);
178*0b57cec5SDimitry Andric   bool tryBitfieldInsertInZeroOp(SDNode *N);
179*0b57cec5SDimitry Andric   bool tryShiftAmountMod(SDNode *N);
180*0b57cec5SDimitry Andric 
181*0b57cec5SDimitry Andric   bool tryReadRegister(SDNode *N);
182*0b57cec5SDimitry Andric   bool tryWriteRegister(SDNode *N);
183*0b57cec5SDimitry Andric 
184*0b57cec5SDimitry Andric // Include the pieces autogenerated from the target description.
185*0b57cec5SDimitry Andric #include "AArch64GenDAGISel.inc"
186*0b57cec5SDimitry Andric 
187*0b57cec5SDimitry Andric private:
188*0b57cec5SDimitry Andric   bool SelectShiftedRegister(SDValue N, bool AllowROR, SDValue &Reg,
189*0b57cec5SDimitry Andric                              SDValue &Shift);
190*0b57cec5SDimitry Andric   bool SelectAddrModeIndexed7S(SDValue N, unsigned Size, SDValue &Base,
191*0b57cec5SDimitry Andric                                SDValue &OffImm) {
192*0b57cec5SDimitry Andric     return SelectAddrModeIndexedBitWidth(N, true, 7, Size, Base, OffImm);
193*0b57cec5SDimitry Andric   }
194*0b57cec5SDimitry Andric   bool SelectAddrModeIndexedBitWidth(SDValue N, bool IsSignedImm, unsigned BW,
195*0b57cec5SDimitry Andric                                      unsigned Size, SDValue &Base,
196*0b57cec5SDimitry Andric                                      SDValue &OffImm);
197*0b57cec5SDimitry Andric   bool SelectAddrModeIndexed(SDValue N, unsigned Size, SDValue &Base,
198*0b57cec5SDimitry Andric                              SDValue &OffImm);
199*0b57cec5SDimitry Andric   bool SelectAddrModeUnscaled(SDValue N, unsigned Size, SDValue &Base,
200*0b57cec5SDimitry Andric                               SDValue &OffImm);
201*0b57cec5SDimitry Andric   bool SelectAddrModeWRO(SDValue N, unsigned Size, SDValue &Base,
202*0b57cec5SDimitry Andric                          SDValue &Offset, SDValue &SignExtend,
203*0b57cec5SDimitry Andric                          SDValue &DoShift);
204*0b57cec5SDimitry Andric   bool SelectAddrModeXRO(SDValue N, unsigned Size, SDValue &Base,
205*0b57cec5SDimitry Andric                          SDValue &Offset, SDValue &SignExtend,
206*0b57cec5SDimitry Andric                          SDValue &DoShift);
207*0b57cec5SDimitry Andric   bool isWorthFolding(SDValue V) const;
208*0b57cec5SDimitry Andric   bool SelectExtendedSHL(SDValue N, unsigned Size, bool WantExtend,
209*0b57cec5SDimitry Andric                          SDValue &Offset, SDValue &SignExtend);
210*0b57cec5SDimitry Andric 
211*0b57cec5SDimitry Andric   template<unsigned RegWidth>
212*0b57cec5SDimitry Andric   bool SelectCVTFixedPosOperand(SDValue N, SDValue &FixedPos) {
213*0b57cec5SDimitry Andric     return SelectCVTFixedPosOperand(N, FixedPos, RegWidth);
214*0b57cec5SDimitry Andric   }
215*0b57cec5SDimitry Andric 
216*0b57cec5SDimitry Andric   bool SelectCVTFixedPosOperand(SDValue N, SDValue &FixedPos, unsigned Width);
217*0b57cec5SDimitry Andric 
218*0b57cec5SDimitry Andric   bool SelectCMP_SWAP(SDNode *N);
219*0b57cec5SDimitry Andric 
220*0b57cec5SDimitry Andric };
221*0b57cec5SDimitry Andric } // end anonymous namespace
222*0b57cec5SDimitry Andric 
223*0b57cec5SDimitry Andric /// isIntImmediate - This method tests to see if the node is a constant
224*0b57cec5SDimitry Andric /// operand. If so Imm will receive the 32-bit value.
225*0b57cec5SDimitry Andric static bool isIntImmediate(const SDNode *N, uint64_t &Imm) {
226*0b57cec5SDimitry Andric   if (const ConstantSDNode *C = dyn_cast<const ConstantSDNode>(N)) {
227*0b57cec5SDimitry Andric     Imm = C->getZExtValue();
228*0b57cec5SDimitry Andric     return true;
229*0b57cec5SDimitry Andric   }
230*0b57cec5SDimitry Andric   return false;
231*0b57cec5SDimitry Andric }
232*0b57cec5SDimitry Andric 
233*0b57cec5SDimitry Andric // isIntImmediate - This method tests to see if a constant operand.
234*0b57cec5SDimitry Andric // If so Imm will receive the value.
235*0b57cec5SDimitry Andric static bool isIntImmediate(SDValue N, uint64_t &Imm) {
236*0b57cec5SDimitry Andric   return isIntImmediate(N.getNode(), Imm);
237*0b57cec5SDimitry Andric }
238*0b57cec5SDimitry Andric 
239*0b57cec5SDimitry Andric // isOpcWithIntImmediate - This method tests to see if the node is a specific
240*0b57cec5SDimitry Andric // opcode and that it has a immediate integer right operand.
241*0b57cec5SDimitry Andric // If so Imm will receive the 32 bit value.
242*0b57cec5SDimitry Andric static bool isOpcWithIntImmediate(const SDNode *N, unsigned Opc,
243*0b57cec5SDimitry Andric                                   uint64_t &Imm) {
244*0b57cec5SDimitry Andric   return N->getOpcode() == Opc &&
245*0b57cec5SDimitry Andric          isIntImmediate(N->getOperand(1).getNode(), Imm);
246*0b57cec5SDimitry Andric }
247*0b57cec5SDimitry Andric 
248*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::SelectInlineAsmMemoryOperand(
249*0b57cec5SDimitry Andric     const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) {
250*0b57cec5SDimitry Andric   switch(ConstraintID) {
251*0b57cec5SDimitry Andric   default:
252*0b57cec5SDimitry Andric     llvm_unreachable("Unexpected asm memory constraint");
253*0b57cec5SDimitry Andric   case InlineAsm::Constraint_i:
254*0b57cec5SDimitry Andric   case InlineAsm::Constraint_m:
255*0b57cec5SDimitry Andric   case InlineAsm::Constraint_Q:
256*0b57cec5SDimitry Andric     // We need to make sure that this one operand does not end up in XZR, thus
257*0b57cec5SDimitry Andric     // require the address to be in a PointerRegClass register.
258*0b57cec5SDimitry Andric     const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo();
259*0b57cec5SDimitry Andric     const TargetRegisterClass *TRC = TRI->getPointerRegClass(*MF);
260*0b57cec5SDimitry Andric     SDLoc dl(Op);
261*0b57cec5SDimitry Andric     SDValue RC = CurDAG->getTargetConstant(TRC->getID(), dl, MVT::i64);
262*0b57cec5SDimitry Andric     SDValue NewOp =
263*0b57cec5SDimitry Andric         SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
264*0b57cec5SDimitry Andric                                        dl, Op.getValueType(),
265*0b57cec5SDimitry Andric                                        Op, RC), 0);
266*0b57cec5SDimitry Andric     OutOps.push_back(NewOp);
267*0b57cec5SDimitry Andric     return false;
268*0b57cec5SDimitry Andric   }
269*0b57cec5SDimitry Andric   return true;
270*0b57cec5SDimitry Andric }
271*0b57cec5SDimitry Andric 
272*0b57cec5SDimitry Andric /// SelectArithImmed - Select an immediate value that can be represented as
273*0b57cec5SDimitry Andric /// a 12-bit value shifted left by either 0 or 12.  If so, return true with
274*0b57cec5SDimitry Andric /// Val set to the 12-bit value and Shift set to the shifter operand.
275*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::SelectArithImmed(SDValue N, SDValue &Val,
276*0b57cec5SDimitry Andric                                            SDValue &Shift) {
277*0b57cec5SDimitry Andric   // This function is called from the addsub_shifted_imm ComplexPattern,
278*0b57cec5SDimitry Andric   // which lists [imm] as the list of opcode it's interested in, however
279*0b57cec5SDimitry Andric   // we still need to check whether the operand is actually an immediate
280*0b57cec5SDimitry Andric   // here because the ComplexPattern opcode list is only used in
281*0b57cec5SDimitry Andric   // root-level opcode matching.
282*0b57cec5SDimitry Andric   if (!isa<ConstantSDNode>(N.getNode()))
283*0b57cec5SDimitry Andric     return false;
284*0b57cec5SDimitry Andric 
285*0b57cec5SDimitry Andric   uint64_t Immed = cast<ConstantSDNode>(N.getNode())->getZExtValue();
286*0b57cec5SDimitry Andric   unsigned ShiftAmt;
287*0b57cec5SDimitry Andric 
288*0b57cec5SDimitry Andric   if (Immed >> 12 == 0) {
289*0b57cec5SDimitry Andric     ShiftAmt = 0;
290*0b57cec5SDimitry Andric   } else if ((Immed & 0xfff) == 0 && Immed >> 24 == 0) {
291*0b57cec5SDimitry Andric     ShiftAmt = 12;
292*0b57cec5SDimitry Andric     Immed = Immed >> 12;
293*0b57cec5SDimitry Andric   } else
294*0b57cec5SDimitry Andric     return false;
295*0b57cec5SDimitry Andric 
296*0b57cec5SDimitry Andric   unsigned ShVal = AArch64_AM::getShifterImm(AArch64_AM::LSL, ShiftAmt);
297*0b57cec5SDimitry Andric   SDLoc dl(N);
298*0b57cec5SDimitry Andric   Val = CurDAG->getTargetConstant(Immed, dl, MVT::i32);
299*0b57cec5SDimitry Andric   Shift = CurDAG->getTargetConstant(ShVal, dl, MVT::i32);
300*0b57cec5SDimitry Andric   return true;
301*0b57cec5SDimitry Andric }
302*0b57cec5SDimitry Andric 
303*0b57cec5SDimitry Andric /// SelectNegArithImmed - As above, but negates the value before trying to
304*0b57cec5SDimitry Andric /// select it.
305*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::SelectNegArithImmed(SDValue N, SDValue &Val,
306*0b57cec5SDimitry Andric                                               SDValue &Shift) {
307*0b57cec5SDimitry Andric   // This function is called from the addsub_shifted_imm ComplexPattern,
308*0b57cec5SDimitry Andric   // which lists [imm] as the list of opcode it's interested in, however
309*0b57cec5SDimitry Andric   // we still need to check whether the operand is actually an immediate
310*0b57cec5SDimitry Andric   // here because the ComplexPattern opcode list is only used in
311*0b57cec5SDimitry Andric   // root-level opcode matching.
312*0b57cec5SDimitry Andric   if (!isa<ConstantSDNode>(N.getNode()))
313*0b57cec5SDimitry Andric     return false;
314*0b57cec5SDimitry Andric 
315*0b57cec5SDimitry Andric   // The immediate operand must be a 24-bit zero-extended immediate.
316*0b57cec5SDimitry Andric   uint64_t Immed = cast<ConstantSDNode>(N.getNode())->getZExtValue();
317*0b57cec5SDimitry Andric 
318*0b57cec5SDimitry Andric   // This negation is almost always valid, but "cmp wN, #0" and "cmn wN, #0"
319*0b57cec5SDimitry Andric   // have the opposite effect on the C flag, so this pattern mustn't match under
320*0b57cec5SDimitry Andric   // those circumstances.
321*0b57cec5SDimitry Andric   if (Immed == 0)
322*0b57cec5SDimitry Andric     return false;
323*0b57cec5SDimitry Andric 
324*0b57cec5SDimitry Andric   if (N.getValueType() == MVT::i32)
325*0b57cec5SDimitry Andric     Immed = ~((uint32_t)Immed) + 1;
326*0b57cec5SDimitry Andric   else
327*0b57cec5SDimitry Andric     Immed = ~Immed + 1ULL;
328*0b57cec5SDimitry Andric   if (Immed & 0xFFFFFFFFFF000000ULL)
329*0b57cec5SDimitry Andric     return false;
330*0b57cec5SDimitry Andric 
331*0b57cec5SDimitry Andric   Immed &= 0xFFFFFFULL;
332*0b57cec5SDimitry Andric   return SelectArithImmed(CurDAG->getConstant(Immed, SDLoc(N), MVT::i32), Val,
333*0b57cec5SDimitry Andric                           Shift);
334*0b57cec5SDimitry Andric }
335*0b57cec5SDimitry Andric 
336*0b57cec5SDimitry Andric /// getShiftTypeForNode - Translate a shift node to the corresponding
337*0b57cec5SDimitry Andric /// ShiftType value.
338*0b57cec5SDimitry Andric static AArch64_AM::ShiftExtendType getShiftTypeForNode(SDValue N) {
339*0b57cec5SDimitry Andric   switch (N.getOpcode()) {
340*0b57cec5SDimitry Andric   default:
341*0b57cec5SDimitry Andric     return AArch64_AM::InvalidShiftExtend;
342*0b57cec5SDimitry Andric   case ISD::SHL:
343*0b57cec5SDimitry Andric     return AArch64_AM::LSL;
344*0b57cec5SDimitry Andric   case ISD::SRL:
345*0b57cec5SDimitry Andric     return AArch64_AM::LSR;
346*0b57cec5SDimitry Andric   case ISD::SRA:
347*0b57cec5SDimitry Andric     return AArch64_AM::ASR;
348*0b57cec5SDimitry Andric   case ISD::ROTR:
349*0b57cec5SDimitry Andric     return AArch64_AM::ROR;
350*0b57cec5SDimitry Andric   }
351*0b57cec5SDimitry Andric }
352*0b57cec5SDimitry Andric 
353*0b57cec5SDimitry Andric /// Determine whether it is worth it to fold SHL into the addressing
354*0b57cec5SDimitry Andric /// mode.
355*0b57cec5SDimitry Andric static bool isWorthFoldingSHL(SDValue V) {
356*0b57cec5SDimitry Andric   assert(V.getOpcode() == ISD::SHL && "invalid opcode");
357*0b57cec5SDimitry Andric   // It is worth folding logical shift of up to three places.
358*0b57cec5SDimitry Andric   auto *CSD = dyn_cast<ConstantSDNode>(V.getOperand(1));
359*0b57cec5SDimitry Andric   if (!CSD)
360*0b57cec5SDimitry Andric     return false;
361*0b57cec5SDimitry Andric   unsigned ShiftVal = CSD->getZExtValue();
362*0b57cec5SDimitry Andric   if (ShiftVal > 3)
363*0b57cec5SDimitry Andric     return false;
364*0b57cec5SDimitry Andric 
365*0b57cec5SDimitry Andric   // Check if this particular node is reused in any non-memory related
366*0b57cec5SDimitry Andric   // operation.  If yes, do not try to fold this node into the address
367*0b57cec5SDimitry Andric   // computation, since the computation will be kept.
368*0b57cec5SDimitry Andric   const SDNode *Node = V.getNode();
369*0b57cec5SDimitry Andric   for (SDNode *UI : Node->uses())
370*0b57cec5SDimitry Andric     if (!isa<MemSDNode>(*UI))
371*0b57cec5SDimitry Andric       for (SDNode *UII : UI->uses())
372*0b57cec5SDimitry Andric         if (!isa<MemSDNode>(*UII))
373*0b57cec5SDimitry Andric           return false;
374*0b57cec5SDimitry Andric   return true;
375*0b57cec5SDimitry Andric }
376*0b57cec5SDimitry Andric 
377*0b57cec5SDimitry Andric /// Determine whether it is worth to fold V into an extended register.
378*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::isWorthFolding(SDValue V) const {
379*0b57cec5SDimitry Andric   // Trivial if we are optimizing for code size or if there is only
380*0b57cec5SDimitry Andric   // one use of the value.
381*0b57cec5SDimitry Andric   if (ForCodeSize || V.hasOneUse())
382*0b57cec5SDimitry Andric     return true;
383*0b57cec5SDimitry Andric   // If a subtarget has a fastpath LSL we can fold a logical shift into
384*0b57cec5SDimitry Andric   // the addressing mode and save a cycle.
385*0b57cec5SDimitry Andric   if (Subtarget->hasLSLFast() && V.getOpcode() == ISD::SHL &&
386*0b57cec5SDimitry Andric       isWorthFoldingSHL(V))
387*0b57cec5SDimitry Andric     return true;
388*0b57cec5SDimitry Andric   if (Subtarget->hasLSLFast() && V.getOpcode() == ISD::ADD) {
389*0b57cec5SDimitry Andric     const SDValue LHS = V.getOperand(0);
390*0b57cec5SDimitry Andric     const SDValue RHS = V.getOperand(1);
391*0b57cec5SDimitry Andric     if (LHS.getOpcode() == ISD::SHL && isWorthFoldingSHL(LHS))
392*0b57cec5SDimitry Andric       return true;
393*0b57cec5SDimitry Andric     if (RHS.getOpcode() == ISD::SHL && isWorthFoldingSHL(RHS))
394*0b57cec5SDimitry Andric       return true;
395*0b57cec5SDimitry Andric   }
396*0b57cec5SDimitry Andric 
397*0b57cec5SDimitry Andric   // It hurts otherwise, since the value will be reused.
398*0b57cec5SDimitry Andric   return false;
399*0b57cec5SDimitry Andric }
400*0b57cec5SDimitry Andric 
401*0b57cec5SDimitry Andric /// SelectShiftedRegister - Select a "shifted register" operand.  If the value
402*0b57cec5SDimitry Andric /// is not shifted, set the Shift operand to default of "LSL 0".  The logical
403*0b57cec5SDimitry Andric /// instructions allow the shifted register to be rotated, but the arithmetic
404*0b57cec5SDimitry Andric /// instructions do not.  The AllowROR parameter specifies whether ROR is
405*0b57cec5SDimitry Andric /// supported.
406*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::SelectShiftedRegister(SDValue N, bool AllowROR,
407*0b57cec5SDimitry Andric                                                 SDValue &Reg, SDValue &Shift) {
408*0b57cec5SDimitry Andric   AArch64_AM::ShiftExtendType ShType = getShiftTypeForNode(N);
409*0b57cec5SDimitry Andric   if (ShType == AArch64_AM::InvalidShiftExtend)
410*0b57cec5SDimitry Andric     return false;
411*0b57cec5SDimitry Andric   if (!AllowROR && ShType == AArch64_AM::ROR)
412*0b57cec5SDimitry Andric     return false;
413*0b57cec5SDimitry Andric 
414*0b57cec5SDimitry Andric   if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
415*0b57cec5SDimitry Andric     unsigned BitSize = N.getValueSizeInBits();
416*0b57cec5SDimitry Andric     unsigned Val = RHS->getZExtValue() & (BitSize - 1);
417*0b57cec5SDimitry Andric     unsigned ShVal = AArch64_AM::getShifterImm(ShType, Val);
418*0b57cec5SDimitry Andric 
419*0b57cec5SDimitry Andric     Reg = N.getOperand(0);
420*0b57cec5SDimitry Andric     Shift = CurDAG->getTargetConstant(ShVal, SDLoc(N), MVT::i32);
421*0b57cec5SDimitry Andric     return isWorthFolding(N);
422*0b57cec5SDimitry Andric   }
423*0b57cec5SDimitry Andric 
424*0b57cec5SDimitry Andric   return false;
425*0b57cec5SDimitry Andric }
426*0b57cec5SDimitry Andric 
427*0b57cec5SDimitry Andric /// getExtendTypeForNode - Translate an extend node to the corresponding
428*0b57cec5SDimitry Andric /// ExtendType value.
429*0b57cec5SDimitry Andric static AArch64_AM::ShiftExtendType
430*0b57cec5SDimitry Andric getExtendTypeForNode(SDValue N, bool IsLoadStore = false) {
431*0b57cec5SDimitry Andric   if (N.getOpcode() == ISD::SIGN_EXTEND ||
432*0b57cec5SDimitry Andric       N.getOpcode() == ISD::SIGN_EXTEND_INREG) {
433*0b57cec5SDimitry Andric     EVT SrcVT;
434*0b57cec5SDimitry Andric     if (N.getOpcode() == ISD::SIGN_EXTEND_INREG)
435*0b57cec5SDimitry Andric       SrcVT = cast<VTSDNode>(N.getOperand(1))->getVT();
436*0b57cec5SDimitry Andric     else
437*0b57cec5SDimitry Andric       SrcVT = N.getOperand(0).getValueType();
438*0b57cec5SDimitry Andric 
439*0b57cec5SDimitry Andric     if (!IsLoadStore && SrcVT == MVT::i8)
440*0b57cec5SDimitry Andric       return AArch64_AM::SXTB;
441*0b57cec5SDimitry Andric     else if (!IsLoadStore && SrcVT == MVT::i16)
442*0b57cec5SDimitry Andric       return AArch64_AM::SXTH;
443*0b57cec5SDimitry Andric     else if (SrcVT == MVT::i32)
444*0b57cec5SDimitry Andric       return AArch64_AM::SXTW;
445*0b57cec5SDimitry Andric     assert(SrcVT != MVT::i64 && "extend from 64-bits?");
446*0b57cec5SDimitry Andric 
447*0b57cec5SDimitry Andric     return AArch64_AM::InvalidShiftExtend;
448*0b57cec5SDimitry Andric   } else if (N.getOpcode() == ISD::ZERO_EXTEND ||
449*0b57cec5SDimitry Andric              N.getOpcode() == ISD::ANY_EXTEND) {
450*0b57cec5SDimitry Andric     EVT SrcVT = N.getOperand(0).getValueType();
451*0b57cec5SDimitry Andric     if (!IsLoadStore && SrcVT == MVT::i8)
452*0b57cec5SDimitry Andric       return AArch64_AM::UXTB;
453*0b57cec5SDimitry Andric     else if (!IsLoadStore && SrcVT == MVT::i16)
454*0b57cec5SDimitry Andric       return AArch64_AM::UXTH;
455*0b57cec5SDimitry Andric     else if (SrcVT == MVT::i32)
456*0b57cec5SDimitry Andric       return AArch64_AM::UXTW;
457*0b57cec5SDimitry Andric     assert(SrcVT != MVT::i64 && "extend from 64-bits?");
458*0b57cec5SDimitry Andric 
459*0b57cec5SDimitry Andric     return AArch64_AM::InvalidShiftExtend;
460*0b57cec5SDimitry Andric   } else if (N.getOpcode() == ISD::AND) {
461*0b57cec5SDimitry Andric     ConstantSDNode *CSD = dyn_cast<ConstantSDNode>(N.getOperand(1));
462*0b57cec5SDimitry Andric     if (!CSD)
463*0b57cec5SDimitry Andric       return AArch64_AM::InvalidShiftExtend;
464*0b57cec5SDimitry Andric     uint64_t AndMask = CSD->getZExtValue();
465*0b57cec5SDimitry Andric 
466*0b57cec5SDimitry Andric     switch (AndMask) {
467*0b57cec5SDimitry Andric     default:
468*0b57cec5SDimitry Andric       return AArch64_AM::InvalidShiftExtend;
469*0b57cec5SDimitry Andric     case 0xFF:
470*0b57cec5SDimitry Andric       return !IsLoadStore ? AArch64_AM::UXTB : AArch64_AM::InvalidShiftExtend;
471*0b57cec5SDimitry Andric     case 0xFFFF:
472*0b57cec5SDimitry Andric       return !IsLoadStore ? AArch64_AM::UXTH : AArch64_AM::InvalidShiftExtend;
473*0b57cec5SDimitry Andric     case 0xFFFFFFFF:
474*0b57cec5SDimitry Andric       return AArch64_AM::UXTW;
475*0b57cec5SDimitry Andric     }
476*0b57cec5SDimitry Andric   }
477*0b57cec5SDimitry Andric 
478*0b57cec5SDimitry Andric   return AArch64_AM::InvalidShiftExtend;
479*0b57cec5SDimitry Andric }
480*0b57cec5SDimitry Andric 
481*0b57cec5SDimitry Andric // Helper for SelectMLAV64LaneV128 - Recognize high lane extracts.
482*0b57cec5SDimitry Andric static bool checkHighLaneIndex(SDNode *DL, SDValue &LaneOp, int &LaneIdx) {
483*0b57cec5SDimitry Andric   if (DL->getOpcode() != AArch64ISD::DUPLANE16 &&
484*0b57cec5SDimitry Andric       DL->getOpcode() != AArch64ISD::DUPLANE32)
485*0b57cec5SDimitry Andric     return false;
486*0b57cec5SDimitry Andric 
487*0b57cec5SDimitry Andric   SDValue SV = DL->getOperand(0);
488*0b57cec5SDimitry Andric   if (SV.getOpcode() != ISD::INSERT_SUBVECTOR)
489*0b57cec5SDimitry Andric     return false;
490*0b57cec5SDimitry Andric 
491*0b57cec5SDimitry Andric   SDValue EV = SV.getOperand(1);
492*0b57cec5SDimitry Andric   if (EV.getOpcode() != ISD::EXTRACT_SUBVECTOR)
493*0b57cec5SDimitry Andric     return false;
494*0b57cec5SDimitry Andric 
495*0b57cec5SDimitry Andric   ConstantSDNode *DLidx = cast<ConstantSDNode>(DL->getOperand(1).getNode());
496*0b57cec5SDimitry Andric   ConstantSDNode *EVidx = cast<ConstantSDNode>(EV.getOperand(1).getNode());
497*0b57cec5SDimitry Andric   LaneIdx = DLidx->getSExtValue() + EVidx->getSExtValue();
498*0b57cec5SDimitry Andric   LaneOp = EV.getOperand(0);
499*0b57cec5SDimitry Andric 
500*0b57cec5SDimitry Andric   return true;
501*0b57cec5SDimitry Andric }
502*0b57cec5SDimitry Andric 
503*0b57cec5SDimitry Andric // Helper for SelectOpcV64LaneV128 - Recognize operations where one operand is a
504*0b57cec5SDimitry Andric // high lane extract.
505*0b57cec5SDimitry Andric static bool checkV64LaneV128(SDValue Op0, SDValue Op1, SDValue &StdOp,
506*0b57cec5SDimitry Andric                              SDValue &LaneOp, int &LaneIdx) {
507*0b57cec5SDimitry Andric 
508*0b57cec5SDimitry Andric   if (!checkHighLaneIndex(Op0.getNode(), LaneOp, LaneIdx)) {
509*0b57cec5SDimitry Andric     std::swap(Op0, Op1);
510*0b57cec5SDimitry Andric     if (!checkHighLaneIndex(Op0.getNode(), LaneOp, LaneIdx))
511*0b57cec5SDimitry Andric       return false;
512*0b57cec5SDimitry Andric   }
513*0b57cec5SDimitry Andric   StdOp = Op1;
514*0b57cec5SDimitry Andric   return true;
515*0b57cec5SDimitry Andric }
516*0b57cec5SDimitry Andric 
517*0b57cec5SDimitry Andric /// SelectMLAV64LaneV128 - AArch64 supports vector MLAs where one multiplicand
518*0b57cec5SDimitry Andric /// is a lane in the upper half of a 128-bit vector.  Recognize and select this
519*0b57cec5SDimitry Andric /// so that we don't emit unnecessary lane extracts.
520*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::tryMLAV64LaneV128(SDNode *N) {
521*0b57cec5SDimitry Andric   SDLoc dl(N);
522*0b57cec5SDimitry Andric   SDValue Op0 = N->getOperand(0);
523*0b57cec5SDimitry Andric   SDValue Op1 = N->getOperand(1);
524*0b57cec5SDimitry Andric   SDValue MLAOp1;   // Will hold ordinary multiplicand for MLA.
525*0b57cec5SDimitry Andric   SDValue MLAOp2;   // Will hold lane-accessed multiplicand for MLA.
526*0b57cec5SDimitry Andric   int LaneIdx = -1; // Will hold the lane index.
527*0b57cec5SDimitry Andric 
528*0b57cec5SDimitry Andric   if (Op1.getOpcode() != ISD::MUL ||
529*0b57cec5SDimitry Andric       !checkV64LaneV128(Op1.getOperand(0), Op1.getOperand(1), MLAOp1, MLAOp2,
530*0b57cec5SDimitry Andric                         LaneIdx)) {
531*0b57cec5SDimitry Andric     std::swap(Op0, Op1);
532*0b57cec5SDimitry Andric     if (Op1.getOpcode() != ISD::MUL ||
533*0b57cec5SDimitry Andric         !checkV64LaneV128(Op1.getOperand(0), Op1.getOperand(1), MLAOp1, MLAOp2,
534*0b57cec5SDimitry Andric                           LaneIdx))
535*0b57cec5SDimitry Andric       return false;
536*0b57cec5SDimitry Andric   }
537*0b57cec5SDimitry Andric 
538*0b57cec5SDimitry Andric   SDValue LaneIdxVal = CurDAG->getTargetConstant(LaneIdx, dl, MVT::i64);
539*0b57cec5SDimitry Andric 
540*0b57cec5SDimitry Andric   SDValue Ops[] = { Op0, MLAOp1, MLAOp2, LaneIdxVal };
541*0b57cec5SDimitry Andric 
542*0b57cec5SDimitry Andric   unsigned MLAOpc = ~0U;
543*0b57cec5SDimitry Andric 
544*0b57cec5SDimitry Andric   switch (N->getSimpleValueType(0).SimpleTy) {
545*0b57cec5SDimitry Andric   default:
546*0b57cec5SDimitry Andric     llvm_unreachable("Unrecognized MLA.");
547*0b57cec5SDimitry Andric   case MVT::v4i16:
548*0b57cec5SDimitry Andric     MLAOpc = AArch64::MLAv4i16_indexed;
549*0b57cec5SDimitry Andric     break;
550*0b57cec5SDimitry Andric   case MVT::v8i16:
551*0b57cec5SDimitry Andric     MLAOpc = AArch64::MLAv8i16_indexed;
552*0b57cec5SDimitry Andric     break;
553*0b57cec5SDimitry Andric   case MVT::v2i32:
554*0b57cec5SDimitry Andric     MLAOpc = AArch64::MLAv2i32_indexed;
555*0b57cec5SDimitry Andric     break;
556*0b57cec5SDimitry Andric   case MVT::v4i32:
557*0b57cec5SDimitry Andric     MLAOpc = AArch64::MLAv4i32_indexed;
558*0b57cec5SDimitry Andric     break;
559*0b57cec5SDimitry Andric   }
560*0b57cec5SDimitry Andric 
561*0b57cec5SDimitry Andric   ReplaceNode(N, CurDAG->getMachineNode(MLAOpc, dl, N->getValueType(0), Ops));
562*0b57cec5SDimitry Andric   return true;
563*0b57cec5SDimitry Andric }
564*0b57cec5SDimitry Andric 
565*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::tryMULLV64LaneV128(unsigned IntNo, SDNode *N) {
566*0b57cec5SDimitry Andric   SDLoc dl(N);
567*0b57cec5SDimitry Andric   SDValue SMULLOp0;
568*0b57cec5SDimitry Andric   SDValue SMULLOp1;
569*0b57cec5SDimitry Andric   int LaneIdx;
570*0b57cec5SDimitry Andric 
571*0b57cec5SDimitry Andric   if (!checkV64LaneV128(N->getOperand(1), N->getOperand(2), SMULLOp0, SMULLOp1,
572*0b57cec5SDimitry Andric                         LaneIdx))
573*0b57cec5SDimitry Andric     return false;
574*0b57cec5SDimitry Andric 
575*0b57cec5SDimitry Andric   SDValue LaneIdxVal = CurDAG->getTargetConstant(LaneIdx, dl, MVT::i64);
576*0b57cec5SDimitry Andric 
577*0b57cec5SDimitry Andric   SDValue Ops[] = { SMULLOp0, SMULLOp1, LaneIdxVal };
578*0b57cec5SDimitry Andric 
579*0b57cec5SDimitry Andric   unsigned SMULLOpc = ~0U;
580*0b57cec5SDimitry Andric 
581*0b57cec5SDimitry Andric   if (IntNo == Intrinsic::aarch64_neon_smull) {
582*0b57cec5SDimitry Andric     switch (N->getSimpleValueType(0).SimpleTy) {
583*0b57cec5SDimitry Andric     default:
584*0b57cec5SDimitry Andric       llvm_unreachable("Unrecognized SMULL.");
585*0b57cec5SDimitry Andric     case MVT::v4i32:
586*0b57cec5SDimitry Andric       SMULLOpc = AArch64::SMULLv4i16_indexed;
587*0b57cec5SDimitry Andric       break;
588*0b57cec5SDimitry Andric     case MVT::v2i64:
589*0b57cec5SDimitry Andric       SMULLOpc = AArch64::SMULLv2i32_indexed;
590*0b57cec5SDimitry Andric       break;
591*0b57cec5SDimitry Andric     }
592*0b57cec5SDimitry Andric   } else if (IntNo == Intrinsic::aarch64_neon_umull) {
593*0b57cec5SDimitry Andric     switch (N->getSimpleValueType(0).SimpleTy) {
594*0b57cec5SDimitry Andric     default:
595*0b57cec5SDimitry Andric       llvm_unreachable("Unrecognized SMULL.");
596*0b57cec5SDimitry Andric     case MVT::v4i32:
597*0b57cec5SDimitry Andric       SMULLOpc = AArch64::UMULLv4i16_indexed;
598*0b57cec5SDimitry Andric       break;
599*0b57cec5SDimitry Andric     case MVT::v2i64:
600*0b57cec5SDimitry Andric       SMULLOpc = AArch64::UMULLv2i32_indexed;
601*0b57cec5SDimitry Andric       break;
602*0b57cec5SDimitry Andric     }
603*0b57cec5SDimitry Andric   } else
604*0b57cec5SDimitry Andric     llvm_unreachable("Unrecognized intrinsic.");
605*0b57cec5SDimitry Andric 
606*0b57cec5SDimitry Andric   ReplaceNode(N, CurDAG->getMachineNode(SMULLOpc, dl, N->getValueType(0), Ops));
607*0b57cec5SDimitry Andric   return true;
608*0b57cec5SDimitry Andric }
609*0b57cec5SDimitry Andric 
610*0b57cec5SDimitry Andric /// Instructions that accept extend modifiers like UXTW expect the register
611*0b57cec5SDimitry Andric /// being extended to be a GPR32, but the incoming DAG might be acting on a
612*0b57cec5SDimitry Andric /// GPR64 (either via SEXT_INREG or AND). Extract the appropriate low bits if
613*0b57cec5SDimitry Andric /// this is the case.
614*0b57cec5SDimitry Andric static SDValue narrowIfNeeded(SelectionDAG *CurDAG, SDValue N) {
615*0b57cec5SDimitry Andric   if (N.getValueType() == MVT::i32)
616*0b57cec5SDimitry Andric     return N;
617*0b57cec5SDimitry Andric 
618*0b57cec5SDimitry Andric   SDLoc dl(N);
619*0b57cec5SDimitry Andric   SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32);
620*0b57cec5SDimitry Andric   MachineSDNode *Node = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
621*0b57cec5SDimitry Andric                                                dl, MVT::i32, N, SubReg);
622*0b57cec5SDimitry Andric   return SDValue(Node, 0);
623*0b57cec5SDimitry Andric }
624*0b57cec5SDimitry Andric 
625*0b57cec5SDimitry Andric 
626*0b57cec5SDimitry Andric /// SelectArithExtendedRegister - Select a "extended register" operand.  This
627*0b57cec5SDimitry Andric /// operand folds in an extend followed by an optional left shift.
628*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::SelectArithExtendedRegister(SDValue N, SDValue &Reg,
629*0b57cec5SDimitry Andric                                                       SDValue &Shift) {
630*0b57cec5SDimitry Andric   unsigned ShiftVal = 0;
631*0b57cec5SDimitry Andric   AArch64_AM::ShiftExtendType Ext;
632*0b57cec5SDimitry Andric 
633*0b57cec5SDimitry Andric   if (N.getOpcode() == ISD::SHL) {
634*0b57cec5SDimitry Andric     ConstantSDNode *CSD = dyn_cast<ConstantSDNode>(N.getOperand(1));
635*0b57cec5SDimitry Andric     if (!CSD)
636*0b57cec5SDimitry Andric       return false;
637*0b57cec5SDimitry Andric     ShiftVal = CSD->getZExtValue();
638*0b57cec5SDimitry Andric     if (ShiftVal > 4)
639*0b57cec5SDimitry Andric       return false;
640*0b57cec5SDimitry Andric 
641*0b57cec5SDimitry Andric     Ext = getExtendTypeForNode(N.getOperand(0));
642*0b57cec5SDimitry Andric     if (Ext == AArch64_AM::InvalidShiftExtend)
643*0b57cec5SDimitry Andric       return false;
644*0b57cec5SDimitry Andric 
645*0b57cec5SDimitry Andric     Reg = N.getOperand(0).getOperand(0);
646*0b57cec5SDimitry Andric   } else {
647*0b57cec5SDimitry Andric     Ext = getExtendTypeForNode(N);
648*0b57cec5SDimitry Andric     if (Ext == AArch64_AM::InvalidShiftExtend)
649*0b57cec5SDimitry Andric       return false;
650*0b57cec5SDimitry Andric 
651*0b57cec5SDimitry Andric     Reg = N.getOperand(0);
652*0b57cec5SDimitry Andric 
653*0b57cec5SDimitry Andric     // Don't match if free 32-bit -> 64-bit zext can be used instead.
654*0b57cec5SDimitry Andric     if (Ext == AArch64_AM::UXTW &&
655*0b57cec5SDimitry Andric         Reg->getValueType(0).getSizeInBits() == 32 && isDef32(*Reg.getNode()))
656*0b57cec5SDimitry Andric       return false;
657*0b57cec5SDimitry Andric   }
658*0b57cec5SDimitry Andric 
659*0b57cec5SDimitry Andric   // AArch64 mandates that the RHS of the operation must use the smallest
660*0b57cec5SDimitry Andric   // register class that could contain the size being extended from.  Thus,
661*0b57cec5SDimitry Andric   // if we're folding a (sext i8), we need the RHS to be a GPR32, even though
662*0b57cec5SDimitry Andric   // there might not be an actual 32-bit value in the program.  We can
663*0b57cec5SDimitry Andric   // (harmlessly) synthesize one by injected an EXTRACT_SUBREG here.
664*0b57cec5SDimitry Andric   assert(Ext != AArch64_AM::UXTX && Ext != AArch64_AM::SXTX);
665*0b57cec5SDimitry Andric   Reg = narrowIfNeeded(CurDAG, Reg);
666*0b57cec5SDimitry Andric   Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(N),
667*0b57cec5SDimitry Andric                                     MVT::i32);
668*0b57cec5SDimitry Andric   return isWorthFolding(N);
669*0b57cec5SDimitry Andric }
670*0b57cec5SDimitry Andric 
671*0b57cec5SDimitry Andric /// If there's a use of this ADDlow that's not itself a load/store then we'll
672*0b57cec5SDimitry Andric /// need to create a real ADD instruction from it anyway and there's no point in
673*0b57cec5SDimitry Andric /// folding it into the mem op. Theoretically, it shouldn't matter, but there's
674*0b57cec5SDimitry Andric /// a single pseudo-instruction for an ADRP/ADD pair so over-aggressive folding
675*0b57cec5SDimitry Andric /// leads to duplicated ADRP instructions.
676*0b57cec5SDimitry Andric static bool isWorthFoldingADDlow(SDValue N) {
677*0b57cec5SDimitry Andric   for (auto Use : N->uses()) {
678*0b57cec5SDimitry Andric     if (Use->getOpcode() != ISD::LOAD && Use->getOpcode() != ISD::STORE &&
679*0b57cec5SDimitry Andric         Use->getOpcode() != ISD::ATOMIC_LOAD &&
680*0b57cec5SDimitry Andric         Use->getOpcode() != ISD::ATOMIC_STORE)
681*0b57cec5SDimitry Andric       return false;
682*0b57cec5SDimitry Andric 
683*0b57cec5SDimitry Andric     // ldar and stlr have much more restrictive addressing modes (just a
684*0b57cec5SDimitry Andric     // register).
685*0b57cec5SDimitry Andric     if (isStrongerThanMonotonic(cast<MemSDNode>(Use)->getOrdering()))
686*0b57cec5SDimitry Andric       return false;
687*0b57cec5SDimitry Andric   }
688*0b57cec5SDimitry Andric 
689*0b57cec5SDimitry Andric   return true;
690*0b57cec5SDimitry Andric }
691*0b57cec5SDimitry Andric 
692*0b57cec5SDimitry Andric /// SelectAddrModeIndexedBitWidth - Select a "register plus scaled (un)signed BW-bit
693*0b57cec5SDimitry Andric /// immediate" address.  The "Size" argument is the size in bytes of the memory
694*0b57cec5SDimitry Andric /// reference, which determines the scale.
695*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::SelectAddrModeIndexedBitWidth(SDValue N, bool IsSignedImm,
696*0b57cec5SDimitry Andric                                                         unsigned BW, unsigned Size,
697*0b57cec5SDimitry Andric                                                         SDValue &Base,
698*0b57cec5SDimitry Andric                                                         SDValue &OffImm) {
699*0b57cec5SDimitry Andric   SDLoc dl(N);
700*0b57cec5SDimitry Andric   const DataLayout &DL = CurDAG->getDataLayout();
701*0b57cec5SDimitry Andric   const TargetLowering *TLI = getTargetLowering();
702*0b57cec5SDimitry Andric   if (N.getOpcode() == ISD::FrameIndex) {
703*0b57cec5SDimitry Andric     int FI = cast<FrameIndexSDNode>(N)->getIndex();
704*0b57cec5SDimitry Andric     Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL));
705*0b57cec5SDimitry Andric     OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
706*0b57cec5SDimitry Andric     return true;
707*0b57cec5SDimitry Andric   }
708*0b57cec5SDimitry Andric 
709*0b57cec5SDimitry Andric   // As opposed to the (12-bit) Indexed addressing mode below, the 7/9-bit signed
710*0b57cec5SDimitry Andric   // selected here doesn't support labels/immediates, only base+offset.
711*0b57cec5SDimitry Andric   if (CurDAG->isBaseWithConstantOffset(N)) {
712*0b57cec5SDimitry Andric     if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
713*0b57cec5SDimitry Andric       if (IsSignedImm) {
714*0b57cec5SDimitry Andric         int64_t RHSC = RHS->getSExtValue();
715*0b57cec5SDimitry Andric         unsigned Scale = Log2_32(Size);
716*0b57cec5SDimitry Andric         int64_t Range = 0x1LL << (BW - 1);
717*0b57cec5SDimitry Andric 
718*0b57cec5SDimitry Andric         if ((RHSC & (Size - 1)) == 0 && RHSC >= -(Range << Scale) &&
719*0b57cec5SDimitry Andric             RHSC < (Range << Scale)) {
720*0b57cec5SDimitry Andric           Base = N.getOperand(0);
721*0b57cec5SDimitry Andric           if (Base.getOpcode() == ISD::FrameIndex) {
722*0b57cec5SDimitry Andric             int FI = cast<FrameIndexSDNode>(Base)->getIndex();
723*0b57cec5SDimitry Andric             Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL));
724*0b57cec5SDimitry Andric           }
725*0b57cec5SDimitry Andric           OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
726*0b57cec5SDimitry Andric           return true;
727*0b57cec5SDimitry Andric         }
728*0b57cec5SDimitry Andric       } else {
729*0b57cec5SDimitry Andric         // unsigned Immediate
730*0b57cec5SDimitry Andric         uint64_t RHSC = RHS->getZExtValue();
731*0b57cec5SDimitry Andric         unsigned Scale = Log2_32(Size);
732*0b57cec5SDimitry Andric         uint64_t Range = 0x1ULL << BW;
733*0b57cec5SDimitry Andric 
734*0b57cec5SDimitry Andric         if ((RHSC & (Size - 1)) == 0 && RHSC < (Range << Scale)) {
735*0b57cec5SDimitry Andric           Base = N.getOperand(0);
736*0b57cec5SDimitry Andric           if (Base.getOpcode() == ISD::FrameIndex) {
737*0b57cec5SDimitry Andric             int FI = cast<FrameIndexSDNode>(Base)->getIndex();
738*0b57cec5SDimitry Andric             Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL));
739*0b57cec5SDimitry Andric           }
740*0b57cec5SDimitry Andric           OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
741*0b57cec5SDimitry Andric           return true;
742*0b57cec5SDimitry Andric         }
743*0b57cec5SDimitry Andric       }
744*0b57cec5SDimitry Andric     }
745*0b57cec5SDimitry Andric   }
746*0b57cec5SDimitry Andric   // Base only. The address will be materialized into a register before
747*0b57cec5SDimitry Andric   // the memory is accessed.
748*0b57cec5SDimitry Andric   //    add x0, Xbase, #offset
749*0b57cec5SDimitry Andric   //    stp x1, x2, [x0]
750*0b57cec5SDimitry Andric   Base = N;
751*0b57cec5SDimitry Andric   OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
752*0b57cec5SDimitry Andric   return true;
753*0b57cec5SDimitry Andric }
754*0b57cec5SDimitry Andric 
755*0b57cec5SDimitry Andric /// SelectAddrModeIndexed - Select a "register plus scaled unsigned 12-bit
756*0b57cec5SDimitry Andric /// immediate" address.  The "Size" argument is the size in bytes of the memory
757*0b57cec5SDimitry Andric /// reference, which determines the scale.
758*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::SelectAddrModeIndexed(SDValue N, unsigned Size,
759*0b57cec5SDimitry Andric                                               SDValue &Base, SDValue &OffImm) {
760*0b57cec5SDimitry Andric   SDLoc dl(N);
761*0b57cec5SDimitry Andric   const DataLayout &DL = CurDAG->getDataLayout();
762*0b57cec5SDimitry Andric   const TargetLowering *TLI = getTargetLowering();
763*0b57cec5SDimitry Andric   if (N.getOpcode() == ISD::FrameIndex) {
764*0b57cec5SDimitry Andric     int FI = cast<FrameIndexSDNode>(N)->getIndex();
765*0b57cec5SDimitry Andric     Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL));
766*0b57cec5SDimitry Andric     OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
767*0b57cec5SDimitry Andric     return true;
768*0b57cec5SDimitry Andric   }
769*0b57cec5SDimitry Andric 
770*0b57cec5SDimitry Andric   if (N.getOpcode() == AArch64ISD::ADDlow && isWorthFoldingADDlow(N)) {
771*0b57cec5SDimitry Andric     GlobalAddressSDNode *GAN =
772*0b57cec5SDimitry Andric         dyn_cast<GlobalAddressSDNode>(N.getOperand(1).getNode());
773*0b57cec5SDimitry Andric     Base = N.getOperand(0);
774*0b57cec5SDimitry Andric     OffImm = N.getOperand(1);
775*0b57cec5SDimitry Andric     if (!GAN)
776*0b57cec5SDimitry Andric       return true;
777*0b57cec5SDimitry Andric 
778*0b57cec5SDimitry Andric     if (GAN->getOffset() % Size == 0) {
779*0b57cec5SDimitry Andric       const GlobalValue *GV = GAN->getGlobal();
780*0b57cec5SDimitry Andric       unsigned Alignment = GV->getAlignment();
781*0b57cec5SDimitry Andric       Type *Ty = GV->getValueType();
782*0b57cec5SDimitry Andric       if (Alignment == 0 && Ty->isSized())
783*0b57cec5SDimitry Andric         Alignment = DL.getABITypeAlignment(Ty);
784*0b57cec5SDimitry Andric 
785*0b57cec5SDimitry Andric       if (Alignment >= Size)
786*0b57cec5SDimitry Andric         return true;
787*0b57cec5SDimitry Andric     }
788*0b57cec5SDimitry Andric   }
789*0b57cec5SDimitry Andric 
790*0b57cec5SDimitry Andric   if (CurDAG->isBaseWithConstantOffset(N)) {
791*0b57cec5SDimitry Andric     if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
792*0b57cec5SDimitry Andric       int64_t RHSC = (int64_t)RHS->getZExtValue();
793*0b57cec5SDimitry Andric       unsigned Scale = Log2_32(Size);
794*0b57cec5SDimitry Andric       if ((RHSC & (Size - 1)) == 0 && RHSC >= 0 && RHSC < (0x1000 << Scale)) {
795*0b57cec5SDimitry Andric         Base = N.getOperand(0);
796*0b57cec5SDimitry Andric         if (Base.getOpcode() == ISD::FrameIndex) {
797*0b57cec5SDimitry Andric           int FI = cast<FrameIndexSDNode>(Base)->getIndex();
798*0b57cec5SDimitry Andric           Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL));
799*0b57cec5SDimitry Andric         }
800*0b57cec5SDimitry Andric         OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
801*0b57cec5SDimitry Andric         return true;
802*0b57cec5SDimitry Andric       }
803*0b57cec5SDimitry Andric     }
804*0b57cec5SDimitry Andric   }
805*0b57cec5SDimitry Andric 
806*0b57cec5SDimitry Andric   // Before falling back to our general case, check if the unscaled
807*0b57cec5SDimitry Andric   // instructions can handle this. If so, that's preferable.
808*0b57cec5SDimitry Andric   if (SelectAddrModeUnscaled(N, Size, Base, OffImm))
809*0b57cec5SDimitry Andric     return false;
810*0b57cec5SDimitry Andric 
811*0b57cec5SDimitry Andric   // Base only. The address will be materialized into a register before
812*0b57cec5SDimitry Andric   // the memory is accessed.
813*0b57cec5SDimitry Andric   //    add x0, Xbase, #offset
814*0b57cec5SDimitry Andric   //    ldr x0, [x0]
815*0b57cec5SDimitry Andric   Base = N;
816*0b57cec5SDimitry Andric   OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
817*0b57cec5SDimitry Andric   return true;
818*0b57cec5SDimitry Andric }
819*0b57cec5SDimitry Andric 
820*0b57cec5SDimitry Andric /// SelectAddrModeUnscaled - Select a "register plus unscaled signed 9-bit
821*0b57cec5SDimitry Andric /// immediate" address.  This should only match when there is an offset that
822*0b57cec5SDimitry Andric /// is not valid for a scaled immediate addressing mode.  The "Size" argument
823*0b57cec5SDimitry Andric /// is the size in bytes of the memory reference, which is needed here to know
824*0b57cec5SDimitry Andric /// what is valid for a scaled immediate.
825*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::SelectAddrModeUnscaled(SDValue N, unsigned Size,
826*0b57cec5SDimitry Andric                                                  SDValue &Base,
827*0b57cec5SDimitry Andric                                                  SDValue &OffImm) {
828*0b57cec5SDimitry Andric   if (!CurDAG->isBaseWithConstantOffset(N))
829*0b57cec5SDimitry Andric     return false;
830*0b57cec5SDimitry Andric   if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
831*0b57cec5SDimitry Andric     int64_t RHSC = RHS->getSExtValue();
832*0b57cec5SDimitry Andric     // If the offset is valid as a scaled immediate, don't match here.
833*0b57cec5SDimitry Andric     if ((RHSC & (Size - 1)) == 0 && RHSC >= 0 &&
834*0b57cec5SDimitry Andric         RHSC < (0x1000 << Log2_32(Size)))
835*0b57cec5SDimitry Andric       return false;
836*0b57cec5SDimitry Andric     if (RHSC >= -256 && RHSC < 256) {
837*0b57cec5SDimitry Andric       Base = N.getOperand(0);
838*0b57cec5SDimitry Andric       if (Base.getOpcode() == ISD::FrameIndex) {
839*0b57cec5SDimitry Andric         int FI = cast<FrameIndexSDNode>(Base)->getIndex();
840*0b57cec5SDimitry Andric         const TargetLowering *TLI = getTargetLowering();
841*0b57cec5SDimitry Andric         Base = CurDAG->getTargetFrameIndex(
842*0b57cec5SDimitry Andric             FI, TLI->getPointerTy(CurDAG->getDataLayout()));
843*0b57cec5SDimitry Andric       }
844*0b57cec5SDimitry Andric       OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i64);
845*0b57cec5SDimitry Andric       return true;
846*0b57cec5SDimitry Andric     }
847*0b57cec5SDimitry Andric   }
848*0b57cec5SDimitry Andric   return false;
849*0b57cec5SDimitry Andric }
850*0b57cec5SDimitry Andric 
851*0b57cec5SDimitry Andric static SDValue Widen(SelectionDAG *CurDAG, SDValue N) {
852*0b57cec5SDimitry Andric   SDLoc dl(N);
853*0b57cec5SDimitry Andric   SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32);
854*0b57cec5SDimitry Andric   SDValue ImpDef = SDValue(
855*0b57cec5SDimitry Andric       CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::i64), 0);
856*0b57cec5SDimitry Andric   MachineSDNode *Node = CurDAG->getMachineNode(
857*0b57cec5SDimitry Andric       TargetOpcode::INSERT_SUBREG, dl, MVT::i64, ImpDef, N, SubReg);
858*0b57cec5SDimitry Andric   return SDValue(Node, 0);
859*0b57cec5SDimitry Andric }
860*0b57cec5SDimitry Andric 
861*0b57cec5SDimitry Andric /// Check if the given SHL node (\p N), can be used to form an
862*0b57cec5SDimitry Andric /// extended register for an addressing mode.
863*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::SelectExtendedSHL(SDValue N, unsigned Size,
864*0b57cec5SDimitry Andric                                             bool WantExtend, SDValue &Offset,
865*0b57cec5SDimitry Andric                                             SDValue &SignExtend) {
866*0b57cec5SDimitry Andric   assert(N.getOpcode() == ISD::SHL && "Invalid opcode.");
867*0b57cec5SDimitry Andric   ConstantSDNode *CSD = dyn_cast<ConstantSDNode>(N.getOperand(1));
868*0b57cec5SDimitry Andric   if (!CSD || (CSD->getZExtValue() & 0x7) != CSD->getZExtValue())
869*0b57cec5SDimitry Andric     return false;
870*0b57cec5SDimitry Andric 
871*0b57cec5SDimitry Andric   SDLoc dl(N);
872*0b57cec5SDimitry Andric   if (WantExtend) {
873*0b57cec5SDimitry Andric     AArch64_AM::ShiftExtendType Ext =
874*0b57cec5SDimitry Andric         getExtendTypeForNode(N.getOperand(0), true);
875*0b57cec5SDimitry Andric     if (Ext == AArch64_AM::InvalidShiftExtend)
876*0b57cec5SDimitry Andric       return false;
877*0b57cec5SDimitry Andric 
878*0b57cec5SDimitry Andric     Offset = narrowIfNeeded(CurDAG, N.getOperand(0).getOperand(0));
879*0b57cec5SDimitry Andric     SignExtend = CurDAG->getTargetConstant(Ext == AArch64_AM::SXTW, dl,
880*0b57cec5SDimitry Andric                                            MVT::i32);
881*0b57cec5SDimitry Andric   } else {
882*0b57cec5SDimitry Andric     Offset = N.getOperand(0);
883*0b57cec5SDimitry Andric     SignExtend = CurDAG->getTargetConstant(0, dl, MVT::i32);
884*0b57cec5SDimitry Andric   }
885*0b57cec5SDimitry Andric 
886*0b57cec5SDimitry Andric   unsigned LegalShiftVal = Log2_32(Size);
887*0b57cec5SDimitry Andric   unsigned ShiftVal = CSD->getZExtValue();
888*0b57cec5SDimitry Andric 
889*0b57cec5SDimitry Andric   if (ShiftVal != 0 && ShiftVal != LegalShiftVal)
890*0b57cec5SDimitry Andric     return false;
891*0b57cec5SDimitry Andric 
892*0b57cec5SDimitry Andric   return isWorthFolding(N);
893*0b57cec5SDimitry Andric }
894*0b57cec5SDimitry Andric 
895*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::SelectAddrModeWRO(SDValue N, unsigned Size,
896*0b57cec5SDimitry Andric                                             SDValue &Base, SDValue &Offset,
897*0b57cec5SDimitry Andric                                             SDValue &SignExtend,
898*0b57cec5SDimitry Andric                                             SDValue &DoShift) {
899*0b57cec5SDimitry Andric   if (N.getOpcode() != ISD::ADD)
900*0b57cec5SDimitry Andric     return false;
901*0b57cec5SDimitry Andric   SDValue LHS = N.getOperand(0);
902*0b57cec5SDimitry Andric   SDValue RHS = N.getOperand(1);
903*0b57cec5SDimitry Andric   SDLoc dl(N);
904*0b57cec5SDimitry Andric 
905*0b57cec5SDimitry Andric   // We don't want to match immediate adds here, because they are better lowered
906*0b57cec5SDimitry Andric   // to the register-immediate addressing modes.
907*0b57cec5SDimitry Andric   if (isa<ConstantSDNode>(LHS) || isa<ConstantSDNode>(RHS))
908*0b57cec5SDimitry Andric     return false;
909*0b57cec5SDimitry Andric 
910*0b57cec5SDimitry Andric   // Check if this particular node is reused in any non-memory related
911*0b57cec5SDimitry Andric   // operation.  If yes, do not try to fold this node into the address
912*0b57cec5SDimitry Andric   // computation, since the computation will be kept.
913*0b57cec5SDimitry Andric   const SDNode *Node = N.getNode();
914*0b57cec5SDimitry Andric   for (SDNode *UI : Node->uses()) {
915*0b57cec5SDimitry Andric     if (!isa<MemSDNode>(*UI))
916*0b57cec5SDimitry Andric       return false;
917*0b57cec5SDimitry Andric   }
918*0b57cec5SDimitry Andric 
919*0b57cec5SDimitry Andric   // Remember if it is worth folding N when it produces extended register.
920*0b57cec5SDimitry Andric   bool IsExtendedRegisterWorthFolding = isWorthFolding(N);
921*0b57cec5SDimitry Andric 
922*0b57cec5SDimitry Andric   // Try to match a shifted extend on the RHS.
923*0b57cec5SDimitry Andric   if (IsExtendedRegisterWorthFolding && RHS.getOpcode() == ISD::SHL &&
924*0b57cec5SDimitry Andric       SelectExtendedSHL(RHS, Size, true, Offset, SignExtend)) {
925*0b57cec5SDimitry Andric     Base = LHS;
926*0b57cec5SDimitry Andric     DoShift = CurDAG->getTargetConstant(true, dl, MVT::i32);
927*0b57cec5SDimitry Andric     return true;
928*0b57cec5SDimitry Andric   }
929*0b57cec5SDimitry Andric 
930*0b57cec5SDimitry Andric   // Try to match a shifted extend on the LHS.
931*0b57cec5SDimitry Andric   if (IsExtendedRegisterWorthFolding && LHS.getOpcode() == ISD::SHL &&
932*0b57cec5SDimitry Andric       SelectExtendedSHL(LHS, Size, true, Offset, SignExtend)) {
933*0b57cec5SDimitry Andric     Base = RHS;
934*0b57cec5SDimitry Andric     DoShift = CurDAG->getTargetConstant(true, dl, MVT::i32);
935*0b57cec5SDimitry Andric     return true;
936*0b57cec5SDimitry Andric   }
937*0b57cec5SDimitry Andric 
938*0b57cec5SDimitry Andric   // There was no shift, whatever else we find.
939*0b57cec5SDimitry Andric   DoShift = CurDAG->getTargetConstant(false, dl, MVT::i32);
940*0b57cec5SDimitry Andric 
941*0b57cec5SDimitry Andric   AArch64_AM::ShiftExtendType Ext = AArch64_AM::InvalidShiftExtend;
942*0b57cec5SDimitry Andric   // Try to match an unshifted extend on the LHS.
943*0b57cec5SDimitry Andric   if (IsExtendedRegisterWorthFolding &&
944*0b57cec5SDimitry Andric       (Ext = getExtendTypeForNode(LHS, true)) !=
945*0b57cec5SDimitry Andric           AArch64_AM::InvalidShiftExtend) {
946*0b57cec5SDimitry Andric     Base = RHS;
947*0b57cec5SDimitry Andric     Offset = narrowIfNeeded(CurDAG, LHS.getOperand(0));
948*0b57cec5SDimitry Andric     SignExtend = CurDAG->getTargetConstant(Ext == AArch64_AM::SXTW, dl,
949*0b57cec5SDimitry Andric                                            MVT::i32);
950*0b57cec5SDimitry Andric     if (isWorthFolding(LHS))
951*0b57cec5SDimitry Andric       return true;
952*0b57cec5SDimitry Andric   }
953*0b57cec5SDimitry Andric 
954*0b57cec5SDimitry Andric   // Try to match an unshifted extend on the RHS.
955*0b57cec5SDimitry Andric   if (IsExtendedRegisterWorthFolding &&
956*0b57cec5SDimitry Andric       (Ext = getExtendTypeForNode(RHS, true)) !=
957*0b57cec5SDimitry Andric           AArch64_AM::InvalidShiftExtend) {
958*0b57cec5SDimitry Andric     Base = LHS;
959*0b57cec5SDimitry Andric     Offset = narrowIfNeeded(CurDAG, RHS.getOperand(0));
960*0b57cec5SDimitry Andric     SignExtend = CurDAG->getTargetConstant(Ext == AArch64_AM::SXTW, dl,
961*0b57cec5SDimitry Andric                                            MVT::i32);
962*0b57cec5SDimitry Andric     if (isWorthFolding(RHS))
963*0b57cec5SDimitry Andric       return true;
964*0b57cec5SDimitry Andric   }
965*0b57cec5SDimitry Andric 
966*0b57cec5SDimitry Andric   return false;
967*0b57cec5SDimitry Andric }
968*0b57cec5SDimitry Andric 
969*0b57cec5SDimitry Andric // Check if the given immediate is preferred by ADD. If an immediate can be
970*0b57cec5SDimitry Andric // encoded in an ADD, or it can be encoded in an "ADD LSL #12" and can not be
971*0b57cec5SDimitry Andric // encoded by one MOVZ, return true.
972*0b57cec5SDimitry Andric static bool isPreferredADD(int64_t ImmOff) {
973*0b57cec5SDimitry Andric   // Constant in [0x0, 0xfff] can be encoded in ADD.
974*0b57cec5SDimitry Andric   if ((ImmOff & 0xfffffffffffff000LL) == 0x0LL)
975*0b57cec5SDimitry Andric     return true;
976*0b57cec5SDimitry Andric   // Check if it can be encoded in an "ADD LSL #12".
977*0b57cec5SDimitry Andric   if ((ImmOff & 0xffffffffff000fffLL) == 0x0LL)
978*0b57cec5SDimitry Andric     // As a single MOVZ is faster than a "ADD of LSL #12", ignore such constant.
979*0b57cec5SDimitry Andric     return (ImmOff & 0xffffffffff00ffffLL) != 0x0LL &&
980*0b57cec5SDimitry Andric            (ImmOff & 0xffffffffffff0fffLL) != 0x0LL;
981*0b57cec5SDimitry Andric   return false;
982*0b57cec5SDimitry Andric }
983*0b57cec5SDimitry Andric 
984*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::SelectAddrModeXRO(SDValue N, unsigned Size,
985*0b57cec5SDimitry Andric                                             SDValue &Base, SDValue &Offset,
986*0b57cec5SDimitry Andric                                             SDValue &SignExtend,
987*0b57cec5SDimitry Andric                                             SDValue &DoShift) {
988*0b57cec5SDimitry Andric   if (N.getOpcode() != ISD::ADD)
989*0b57cec5SDimitry Andric     return false;
990*0b57cec5SDimitry Andric   SDValue LHS = N.getOperand(0);
991*0b57cec5SDimitry Andric   SDValue RHS = N.getOperand(1);
992*0b57cec5SDimitry Andric   SDLoc DL(N);
993*0b57cec5SDimitry Andric 
994*0b57cec5SDimitry Andric   // Check if this particular node is reused in any non-memory related
995*0b57cec5SDimitry Andric   // operation.  If yes, do not try to fold this node into the address
996*0b57cec5SDimitry Andric   // computation, since the computation will be kept.
997*0b57cec5SDimitry Andric   const SDNode *Node = N.getNode();
998*0b57cec5SDimitry Andric   for (SDNode *UI : Node->uses()) {
999*0b57cec5SDimitry Andric     if (!isa<MemSDNode>(*UI))
1000*0b57cec5SDimitry Andric       return false;
1001*0b57cec5SDimitry Andric   }
1002*0b57cec5SDimitry Andric 
1003*0b57cec5SDimitry Andric   // Watch out if RHS is a wide immediate, it can not be selected into
1004*0b57cec5SDimitry Andric   // [BaseReg+Imm] addressing mode. Also it may not be able to be encoded into
1005*0b57cec5SDimitry Andric   // ADD/SUB. Instead it will use [BaseReg + 0] address mode and generate
1006*0b57cec5SDimitry Andric   // instructions like:
1007*0b57cec5SDimitry Andric   //     MOV  X0, WideImmediate
1008*0b57cec5SDimitry Andric   //     ADD  X1, BaseReg, X0
1009*0b57cec5SDimitry Andric   //     LDR  X2, [X1, 0]
1010*0b57cec5SDimitry Andric   // For such situation, using [BaseReg, XReg] addressing mode can save one
1011*0b57cec5SDimitry Andric   // ADD/SUB:
1012*0b57cec5SDimitry Andric   //     MOV  X0, WideImmediate
1013*0b57cec5SDimitry Andric   //     LDR  X2, [BaseReg, X0]
1014*0b57cec5SDimitry Andric   if (isa<ConstantSDNode>(RHS)) {
1015*0b57cec5SDimitry Andric     int64_t ImmOff = (int64_t)cast<ConstantSDNode>(RHS)->getZExtValue();
1016*0b57cec5SDimitry Andric     unsigned Scale = Log2_32(Size);
1017*0b57cec5SDimitry Andric     // Skip the immediate can be selected by load/store addressing mode.
1018*0b57cec5SDimitry Andric     // Also skip the immediate can be encoded by a single ADD (SUB is also
1019*0b57cec5SDimitry Andric     // checked by using -ImmOff).
1020*0b57cec5SDimitry Andric     if ((ImmOff % Size == 0 && ImmOff >= 0 && ImmOff < (0x1000 << Scale)) ||
1021*0b57cec5SDimitry Andric         isPreferredADD(ImmOff) || isPreferredADD(-ImmOff))
1022*0b57cec5SDimitry Andric       return false;
1023*0b57cec5SDimitry Andric 
1024*0b57cec5SDimitry Andric     SDValue Ops[] = { RHS };
1025*0b57cec5SDimitry Andric     SDNode *MOVI =
1026*0b57cec5SDimitry Andric         CurDAG->getMachineNode(AArch64::MOVi64imm, DL, MVT::i64, Ops);
1027*0b57cec5SDimitry Andric     SDValue MOVIV = SDValue(MOVI, 0);
1028*0b57cec5SDimitry Andric     // This ADD of two X register will be selected into [Reg+Reg] mode.
1029*0b57cec5SDimitry Andric     N = CurDAG->getNode(ISD::ADD, DL, MVT::i64, LHS, MOVIV);
1030*0b57cec5SDimitry Andric   }
1031*0b57cec5SDimitry Andric 
1032*0b57cec5SDimitry Andric   // Remember if it is worth folding N when it produces extended register.
1033*0b57cec5SDimitry Andric   bool IsExtendedRegisterWorthFolding = isWorthFolding(N);
1034*0b57cec5SDimitry Andric 
1035*0b57cec5SDimitry Andric   // Try to match a shifted extend on the RHS.
1036*0b57cec5SDimitry Andric   if (IsExtendedRegisterWorthFolding && RHS.getOpcode() == ISD::SHL &&
1037*0b57cec5SDimitry Andric       SelectExtendedSHL(RHS, Size, false, Offset, SignExtend)) {
1038*0b57cec5SDimitry Andric     Base = LHS;
1039*0b57cec5SDimitry Andric     DoShift = CurDAG->getTargetConstant(true, DL, MVT::i32);
1040*0b57cec5SDimitry Andric     return true;
1041*0b57cec5SDimitry Andric   }
1042*0b57cec5SDimitry Andric 
1043*0b57cec5SDimitry Andric   // Try to match a shifted extend on the LHS.
1044*0b57cec5SDimitry Andric   if (IsExtendedRegisterWorthFolding && LHS.getOpcode() == ISD::SHL &&
1045*0b57cec5SDimitry Andric       SelectExtendedSHL(LHS, Size, false, Offset, SignExtend)) {
1046*0b57cec5SDimitry Andric     Base = RHS;
1047*0b57cec5SDimitry Andric     DoShift = CurDAG->getTargetConstant(true, DL, MVT::i32);
1048*0b57cec5SDimitry Andric     return true;
1049*0b57cec5SDimitry Andric   }
1050*0b57cec5SDimitry Andric 
1051*0b57cec5SDimitry Andric   // Match any non-shifted, non-extend, non-immediate add expression.
1052*0b57cec5SDimitry Andric   Base = LHS;
1053*0b57cec5SDimitry Andric   Offset = RHS;
1054*0b57cec5SDimitry Andric   SignExtend = CurDAG->getTargetConstant(false, DL, MVT::i32);
1055*0b57cec5SDimitry Andric   DoShift = CurDAG->getTargetConstant(false, DL, MVT::i32);
1056*0b57cec5SDimitry Andric   // Reg1 + Reg2 is free: no check needed.
1057*0b57cec5SDimitry Andric   return true;
1058*0b57cec5SDimitry Andric }
1059*0b57cec5SDimitry Andric 
1060*0b57cec5SDimitry Andric SDValue AArch64DAGToDAGISel::createDTuple(ArrayRef<SDValue> Regs) {
1061*0b57cec5SDimitry Andric   static const unsigned RegClassIDs[] = {
1062*0b57cec5SDimitry Andric       AArch64::DDRegClassID, AArch64::DDDRegClassID, AArch64::DDDDRegClassID};
1063*0b57cec5SDimitry Andric   static const unsigned SubRegs[] = {AArch64::dsub0, AArch64::dsub1,
1064*0b57cec5SDimitry Andric                                      AArch64::dsub2, AArch64::dsub3};
1065*0b57cec5SDimitry Andric 
1066*0b57cec5SDimitry Andric   return createTuple(Regs, RegClassIDs, SubRegs);
1067*0b57cec5SDimitry Andric }
1068*0b57cec5SDimitry Andric 
1069*0b57cec5SDimitry Andric SDValue AArch64DAGToDAGISel::createQTuple(ArrayRef<SDValue> Regs) {
1070*0b57cec5SDimitry Andric   static const unsigned RegClassIDs[] = {
1071*0b57cec5SDimitry Andric       AArch64::QQRegClassID, AArch64::QQQRegClassID, AArch64::QQQQRegClassID};
1072*0b57cec5SDimitry Andric   static const unsigned SubRegs[] = {AArch64::qsub0, AArch64::qsub1,
1073*0b57cec5SDimitry Andric                                      AArch64::qsub2, AArch64::qsub3};
1074*0b57cec5SDimitry Andric 
1075*0b57cec5SDimitry Andric   return createTuple(Regs, RegClassIDs, SubRegs);
1076*0b57cec5SDimitry Andric }
1077*0b57cec5SDimitry Andric 
1078*0b57cec5SDimitry Andric SDValue AArch64DAGToDAGISel::createTuple(ArrayRef<SDValue> Regs,
1079*0b57cec5SDimitry Andric                                          const unsigned RegClassIDs[],
1080*0b57cec5SDimitry Andric                                          const unsigned SubRegs[]) {
1081*0b57cec5SDimitry Andric   // There's no special register-class for a vector-list of 1 element: it's just
1082*0b57cec5SDimitry Andric   // a vector.
1083*0b57cec5SDimitry Andric   if (Regs.size() == 1)
1084*0b57cec5SDimitry Andric     return Regs[0];
1085*0b57cec5SDimitry Andric 
1086*0b57cec5SDimitry Andric   assert(Regs.size() >= 2 && Regs.size() <= 4);
1087*0b57cec5SDimitry Andric 
1088*0b57cec5SDimitry Andric   SDLoc DL(Regs[0]);
1089*0b57cec5SDimitry Andric 
1090*0b57cec5SDimitry Andric   SmallVector<SDValue, 4> Ops;
1091*0b57cec5SDimitry Andric 
1092*0b57cec5SDimitry Andric   // First operand of REG_SEQUENCE is the desired RegClass.
1093*0b57cec5SDimitry Andric   Ops.push_back(
1094*0b57cec5SDimitry Andric       CurDAG->getTargetConstant(RegClassIDs[Regs.size() - 2], DL, MVT::i32));
1095*0b57cec5SDimitry Andric 
1096*0b57cec5SDimitry Andric   // Then we get pairs of source & subregister-position for the components.
1097*0b57cec5SDimitry Andric   for (unsigned i = 0; i < Regs.size(); ++i) {
1098*0b57cec5SDimitry Andric     Ops.push_back(Regs[i]);
1099*0b57cec5SDimitry Andric     Ops.push_back(CurDAG->getTargetConstant(SubRegs[i], DL, MVT::i32));
1100*0b57cec5SDimitry Andric   }
1101*0b57cec5SDimitry Andric 
1102*0b57cec5SDimitry Andric   SDNode *N =
1103*0b57cec5SDimitry Andric       CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL, MVT::Untyped, Ops);
1104*0b57cec5SDimitry Andric   return SDValue(N, 0);
1105*0b57cec5SDimitry Andric }
1106*0b57cec5SDimitry Andric 
1107*0b57cec5SDimitry Andric void AArch64DAGToDAGISel::SelectTable(SDNode *N, unsigned NumVecs, unsigned Opc,
1108*0b57cec5SDimitry Andric                                       bool isExt) {
1109*0b57cec5SDimitry Andric   SDLoc dl(N);
1110*0b57cec5SDimitry Andric   EVT VT = N->getValueType(0);
1111*0b57cec5SDimitry Andric 
1112*0b57cec5SDimitry Andric   unsigned ExtOff = isExt;
1113*0b57cec5SDimitry Andric 
1114*0b57cec5SDimitry Andric   // Form a REG_SEQUENCE to force register allocation.
1115*0b57cec5SDimitry Andric   unsigned Vec0Off = ExtOff + 1;
1116*0b57cec5SDimitry Andric   SmallVector<SDValue, 4> Regs(N->op_begin() + Vec0Off,
1117*0b57cec5SDimitry Andric                                N->op_begin() + Vec0Off + NumVecs);
1118*0b57cec5SDimitry Andric   SDValue RegSeq = createQTuple(Regs);
1119*0b57cec5SDimitry Andric 
1120*0b57cec5SDimitry Andric   SmallVector<SDValue, 6> Ops;
1121*0b57cec5SDimitry Andric   if (isExt)
1122*0b57cec5SDimitry Andric     Ops.push_back(N->getOperand(1));
1123*0b57cec5SDimitry Andric   Ops.push_back(RegSeq);
1124*0b57cec5SDimitry Andric   Ops.push_back(N->getOperand(NumVecs + ExtOff + 1));
1125*0b57cec5SDimitry Andric   ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops));
1126*0b57cec5SDimitry Andric }
1127*0b57cec5SDimitry Andric 
1128*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::tryIndexedLoad(SDNode *N) {
1129*0b57cec5SDimitry Andric   LoadSDNode *LD = cast<LoadSDNode>(N);
1130*0b57cec5SDimitry Andric   if (LD->isUnindexed())
1131*0b57cec5SDimitry Andric     return false;
1132*0b57cec5SDimitry Andric   EVT VT = LD->getMemoryVT();
1133*0b57cec5SDimitry Andric   EVT DstVT = N->getValueType(0);
1134*0b57cec5SDimitry Andric   ISD::MemIndexedMode AM = LD->getAddressingMode();
1135*0b57cec5SDimitry Andric   bool IsPre = AM == ISD::PRE_INC || AM == ISD::PRE_DEC;
1136*0b57cec5SDimitry Andric 
1137*0b57cec5SDimitry Andric   // We're not doing validity checking here. That was done when checking
1138*0b57cec5SDimitry Andric   // if we should mark the load as indexed or not. We're just selecting
1139*0b57cec5SDimitry Andric   // the right instruction.
1140*0b57cec5SDimitry Andric   unsigned Opcode = 0;
1141*0b57cec5SDimitry Andric 
1142*0b57cec5SDimitry Andric   ISD::LoadExtType ExtType = LD->getExtensionType();
1143*0b57cec5SDimitry Andric   bool InsertTo64 = false;
1144*0b57cec5SDimitry Andric   if (VT == MVT::i64)
1145*0b57cec5SDimitry Andric     Opcode = IsPre ? AArch64::LDRXpre : AArch64::LDRXpost;
1146*0b57cec5SDimitry Andric   else if (VT == MVT::i32) {
1147*0b57cec5SDimitry Andric     if (ExtType == ISD::NON_EXTLOAD)
1148*0b57cec5SDimitry Andric       Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1149*0b57cec5SDimitry Andric     else if (ExtType == ISD::SEXTLOAD)
1150*0b57cec5SDimitry Andric       Opcode = IsPre ? AArch64::LDRSWpre : AArch64::LDRSWpost;
1151*0b57cec5SDimitry Andric     else {
1152*0b57cec5SDimitry Andric       Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1153*0b57cec5SDimitry Andric       InsertTo64 = true;
1154*0b57cec5SDimitry Andric       // The result of the load is only i32. It's the subreg_to_reg that makes
1155*0b57cec5SDimitry Andric       // it into an i64.
1156*0b57cec5SDimitry Andric       DstVT = MVT::i32;
1157*0b57cec5SDimitry Andric     }
1158*0b57cec5SDimitry Andric   } else if (VT == MVT::i16) {
1159*0b57cec5SDimitry Andric     if (ExtType == ISD::SEXTLOAD) {
1160*0b57cec5SDimitry Andric       if (DstVT == MVT::i64)
1161*0b57cec5SDimitry Andric         Opcode = IsPre ? AArch64::LDRSHXpre : AArch64::LDRSHXpost;
1162*0b57cec5SDimitry Andric       else
1163*0b57cec5SDimitry Andric         Opcode = IsPre ? AArch64::LDRSHWpre : AArch64::LDRSHWpost;
1164*0b57cec5SDimitry Andric     } else {
1165*0b57cec5SDimitry Andric       Opcode = IsPre ? AArch64::LDRHHpre : AArch64::LDRHHpost;
1166*0b57cec5SDimitry Andric       InsertTo64 = DstVT == MVT::i64;
1167*0b57cec5SDimitry Andric       // The result of the load is only i32. It's the subreg_to_reg that makes
1168*0b57cec5SDimitry Andric       // it into an i64.
1169*0b57cec5SDimitry Andric       DstVT = MVT::i32;
1170*0b57cec5SDimitry Andric     }
1171*0b57cec5SDimitry Andric   } else if (VT == MVT::i8) {
1172*0b57cec5SDimitry Andric     if (ExtType == ISD::SEXTLOAD) {
1173*0b57cec5SDimitry Andric       if (DstVT == MVT::i64)
1174*0b57cec5SDimitry Andric         Opcode = IsPre ? AArch64::LDRSBXpre : AArch64::LDRSBXpost;
1175*0b57cec5SDimitry Andric       else
1176*0b57cec5SDimitry Andric         Opcode = IsPre ? AArch64::LDRSBWpre : AArch64::LDRSBWpost;
1177*0b57cec5SDimitry Andric     } else {
1178*0b57cec5SDimitry Andric       Opcode = IsPre ? AArch64::LDRBBpre : AArch64::LDRBBpost;
1179*0b57cec5SDimitry Andric       InsertTo64 = DstVT == MVT::i64;
1180*0b57cec5SDimitry Andric       // The result of the load is only i32. It's the subreg_to_reg that makes
1181*0b57cec5SDimitry Andric       // it into an i64.
1182*0b57cec5SDimitry Andric       DstVT = MVT::i32;
1183*0b57cec5SDimitry Andric     }
1184*0b57cec5SDimitry Andric   } else if (VT == MVT::f16) {
1185*0b57cec5SDimitry Andric     Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1186*0b57cec5SDimitry Andric   } else if (VT == MVT::f32) {
1187*0b57cec5SDimitry Andric     Opcode = IsPre ? AArch64::LDRSpre : AArch64::LDRSpost;
1188*0b57cec5SDimitry Andric   } else if (VT == MVT::f64 || VT.is64BitVector()) {
1189*0b57cec5SDimitry Andric     Opcode = IsPre ? AArch64::LDRDpre : AArch64::LDRDpost;
1190*0b57cec5SDimitry Andric   } else if (VT.is128BitVector()) {
1191*0b57cec5SDimitry Andric     Opcode = IsPre ? AArch64::LDRQpre : AArch64::LDRQpost;
1192*0b57cec5SDimitry Andric   } else
1193*0b57cec5SDimitry Andric     return false;
1194*0b57cec5SDimitry Andric   SDValue Chain = LD->getChain();
1195*0b57cec5SDimitry Andric   SDValue Base = LD->getBasePtr();
1196*0b57cec5SDimitry Andric   ConstantSDNode *OffsetOp = cast<ConstantSDNode>(LD->getOffset());
1197*0b57cec5SDimitry Andric   int OffsetVal = (int)OffsetOp->getZExtValue();
1198*0b57cec5SDimitry Andric   SDLoc dl(N);
1199*0b57cec5SDimitry Andric   SDValue Offset = CurDAG->getTargetConstant(OffsetVal, dl, MVT::i64);
1200*0b57cec5SDimitry Andric   SDValue Ops[] = { Base, Offset, Chain };
1201*0b57cec5SDimitry Andric   SDNode *Res = CurDAG->getMachineNode(Opcode, dl, MVT::i64, DstVT,
1202*0b57cec5SDimitry Andric                                        MVT::Other, Ops);
1203*0b57cec5SDimitry Andric   // Either way, we're replacing the node, so tell the caller that.
1204*0b57cec5SDimitry Andric   SDValue LoadedVal = SDValue(Res, 1);
1205*0b57cec5SDimitry Andric   if (InsertTo64) {
1206*0b57cec5SDimitry Andric     SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32);
1207*0b57cec5SDimitry Andric     LoadedVal =
1208*0b57cec5SDimitry Andric         SDValue(CurDAG->getMachineNode(
1209*0b57cec5SDimitry Andric                     AArch64::SUBREG_TO_REG, dl, MVT::i64,
1210*0b57cec5SDimitry Andric                     CurDAG->getTargetConstant(0, dl, MVT::i64), LoadedVal,
1211*0b57cec5SDimitry Andric                     SubReg),
1212*0b57cec5SDimitry Andric                 0);
1213*0b57cec5SDimitry Andric   }
1214*0b57cec5SDimitry Andric 
1215*0b57cec5SDimitry Andric   ReplaceUses(SDValue(N, 0), LoadedVal);
1216*0b57cec5SDimitry Andric   ReplaceUses(SDValue(N, 1), SDValue(Res, 0));
1217*0b57cec5SDimitry Andric   ReplaceUses(SDValue(N, 2), SDValue(Res, 2));
1218*0b57cec5SDimitry Andric   CurDAG->RemoveDeadNode(N);
1219*0b57cec5SDimitry Andric   return true;
1220*0b57cec5SDimitry Andric }
1221*0b57cec5SDimitry Andric 
1222*0b57cec5SDimitry Andric void AArch64DAGToDAGISel::SelectLoad(SDNode *N, unsigned NumVecs, unsigned Opc,
1223*0b57cec5SDimitry Andric                                      unsigned SubRegIdx) {
1224*0b57cec5SDimitry Andric   SDLoc dl(N);
1225*0b57cec5SDimitry Andric   EVT VT = N->getValueType(0);
1226*0b57cec5SDimitry Andric   SDValue Chain = N->getOperand(0);
1227*0b57cec5SDimitry Andric 
1228*0b57cec5SDimitry Andric   SDValue Ops[] = {N->getOperand(2), // Mem operand;
1229*0b57cec5SDimitry Andric                    Chain};
1230*0b57cec5SDimitry Andric 
1231*0b57cec5SDimitry Andric   const EVT ResTys[] = {MVT::Untyped, MVT::Other};
1232*0b57cec5SDimitry Andric 
1233*0b57cec5SDimitry Andric   SDNode *Ld = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
1234*0b57cec5SDimitry Andric   SDValue SuperReg = SDValue(Ld, 0);
1235*0b57cec5SDimitry Andric   for (unsigned i = 0; i < NumVecs; ++i)
1236*0b57cec5SDimitry Andric     ReplaceUses(SDValue(N, i),
1237*0b57cec5SDimitry Andric         CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
1238*0b57cec5SDimitry Andric 
1239*0b57cec5SDimitry Andric   ReplaceUses(SDValue(N, NumVecs), SDValue(Ld, 1));
1240*0b57cec5SDimitry Andric 
1241*0b57cec5SDimitry Andric   // Transfer memoperands.
1242*0b57cec5SDimitry Andric   MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1243*0b57cec5SDimitry Andric   CurDAG->setNodeMemRefs(cast<MachineSDNode>(Ld), {MemOp});
1244*0b57cec5SDimitry Andric 
1245*0b57cec5SDimitry Andric   CurDAG->RemoveDeadNode(N);
1246*0b57cec5SDimitry Andric }
1247*0b57cec5SDimitry Andric 
1248*0b57cec5SDimitry Andric void AArch64DAGToDAGISel::SelectPostLoad(SDNode *N, unsigned NumVecs,
1249*0b57cec5SDimitry Andric                                          unsigned Opc, unsigned SubRegIdx) {
1250*0b57cec5SDimitry Andric   SDLoc dl(N);
1251*0b57cec5SDimitry Andric   EVT VT = N->getValueType(0);
1252*0b57cec5SDimitry Andric   SDValue Chain = N->getOperand(0);
1253*0b57cec5SDimitry Andric 
1254*0b57cec5SDimitry Andric   SDValue Ops[] = {N->getOperand(1), // Mem operand
1255*0b57cec5SDimitry Andric                    N->getOperand(2), // Incremental
1256*0b57cec5SDimitry Andric                    Chain};
1257*0b57cec5SDimitry Andric 
1258*0b57cec5SDimitry Andric   const EVT ResTys[] = {MVT::i64, // Type of the write back register
1259*0b57cec5SDimitry Andric                         MVT::Untyped, MVT::Other};
1260*0b57cec5SDimitry Andric 
1261*0b57cec5SDimitry Andric   SDNode *Ld = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
1262*0b57cec5SDimitry Andric 
1263*0b57cec5SDimitry Andric   // Update uses of write back register
1264*0b57cec5SDimitry Andric   ReplaceUses(SDValue(N, NumVecs), SDValue(Ld, 0));
1265*0b57cec5SDimitry Andric 
1266*0b57cec5SDimitry Andric   // Update uses of vector list
1267*0b57cec5SDimitry Andric   SDValue SuperReg = SDValue(Ld, 1);
1268*0b57cec5SDimitry Andric   if (NumVecs == 1)
1269*0b57cec5SDimitry Andric     ReplaceUses(SDValue(N, 0), SuperReg);
1270*0b57cec5SDimitry Andric   else
1271*0b57cec5SDimitry Andric     for (unsigned i = 0; i < NumVecs; ++i)
1272*0b57cec5SDimitry Andric       ReplaceUses(SDValue(N, i),
1273*0b57cec5SDimitry Andric           CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
1274*0b57cec5SDimitry Andric 
1275*0b57cec5SDimitry Andric   // Update the chain
1276*0b57cec5SDimitry Andric   ReplaceUses(SDValue(N, NumVecs + 1), SDValue(Ld, 2));
1277*0b57cec5SDimitry Andric   CurDAG->RemoveDeadNode(N);
1278*0b57cec5SDimitry Andric }
1279*0b57cec5SDimitry Andric 
1280*0b57cec5SDimitry Andric void AArch64DAGToDAGISel::SelectStore(SDNode *N, unsigned NumVecs,
1281*0b57cec5SDimitry Andric                                       unsigned Opc) {
1282*0b57cec5SDimitry Andric   SDLoc dl(N);
1283*0b57cec5SDimitry Andric   EVT VT = N->getOperand(2)->getValueType(0);
1284*0b57cec5SDimitry Andric 
1285*0b57cec5SDimitry Andric   // Form a REG_SEQUENCE to force register allocation.
1286*0b57cec5SDimitry Andric   bool Is128Bit = VT.getSizeInBits() == 128;
1287*0b57cec5SDimitry Andric   SmallVector<SDValue, 4> Regs(N->op_begin() + 2, N->op_begin() + 2 + NumVecs);
1288*0b57cec5SDimitry Andric   SDValue RegSeq = Is128Bit ? createQTuple(Regs) : createDTuple(Regs);
1289*0b57cec5SDimitry Andric 
1290*0b57cec5SDimitry Andric   SDValue Ops[] = {RegSeq, N->getOperand(NumVecs + 2), N->getOperand(0)};
1291*0b57cec5SDimitry Andric   SDNode *St = CurDAG->getMachineNode(Opc, dl, N->getValueType(0), Ops);
1292*0b57cec5SDimitry Andric 
1293*0b57cec5SDimitry Andric   // Transfer memoperands.
1294*0b57cec5SDimitry Andric   MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1295*0b57cec5SDimitry Andric   CurDAG->setNodeMemRefs(cast<MachineSDNode>(St), {MemOp});
1296*0b57cec5SDimitry Andric 
1297*0b57cec5SDimitry Andric   ReplaceNode(N, St);
1298*0b57cec5SDimitry Andric }
1299*0b57cec5SDimitry Andric 
1300*0b57cec5SDimitry Andric void AArch64DAGToDAGISel::SelectPostStore(SDNode *N, unsigned NumVecs,
1301*0b57cec5SDimitry Andric                                           unsigned Opc) {
1302*0b57cec5SDimitry Andric   SDLoc dl(N);
1303*0b57cec5SDimitry Andric   EVT VT = N->getOperand(2)->getValueType(0);
1304*0b57cec5SDimitry Andric   const EVT ResTys[] = {MVT::i64,    // Type of the write back register
1305*0b57cec5SDimitry Andric                         MVT::Other}; // Type for the Chain
1306*0b57cec5SDimitry Andric 
1307*0b57cec5SDimitry Andric   // Form a REG_SEQUENCE to force register allocation.
1308*0b57cec5SDimitry Andric   bool Is128Bit = VT.getSizeInBits() == 128;
1309*0b57cec5SDimitry Andric   SmallVector<SDValue, 4> Regs(N->op_begin() + 1, N->op_begin() + 1 + NumVecs);
1310*0b57cec5SDimitry Andric   SDValue RegSeq = Is128Bit ? createQTuple(Regs) : createDTuple(Regs);
1311*0b57cec5SDimitry Andric 
1312*0b57cec5SDimitry Andric   SDValue Ops[] = {RegSeq,
1313*0b57cec5SDimitry Andric                    N->getOperand(NumVecs + 1), // base register
1314*0b57cec5SDimitry Andric                    N->getOperand(NumVecs + 2), // Incremental
1315*0b57cec5SDimitry Andric                    N->getOperand(0)};          // Chain
1316*0b57cec5SDimitry Andric   SDNode *St = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
1317*0b57cec5SDimitry Andric 
1318*0b57cec5SDimitry Andric   ReplaceNode(N, St);
1319*0b57cec5SDimitry Andric }
1320*0b57cec5SDimitry Andric 
1321*0b57cec5SDimitry Andric namespace {
1322*0b57cec5SDimitry Andric /// WidenVector - Given a value in the V64 register class, produce the
1323*0b57cec5SDimitry Andric /// equivalent value in the V128 register class.
1324*0b57cec5SDimitry Andric class WidenVector {
1325*0b57cec5SDimitry Andric   SelectionDAG &DAG;
1326*0b57cec5SDimitry Andric 
1327*0b57cec5SDimitry Andric public:
1328*0b57cec5SDimitry Andric   WidenVector(SelectionDAG &DAG) : DAG(DAG) {}
1329*0b57cec5SDimitry Andric 
1330*0b57cec5SDimitry Andric   SDValue operator()(SDValue V64Reg) {
1331*0b57cec5SDimitry Andric     EVT VT = V64Reg.getValueType();
1332*0b57cec5SDimitry Andric     unsigned NarrowSize = VT.getVectorNumElements();
1333*0b57cec5SDimitry Andric     MVT EltTy = VT.getVectorElementType().getSimpleVT();
1334*0b57cec5SDimitry Andric     MVT WideTy = MVT::getVectorVT(EltTy, 2 * NarrowSize);
1335*0b57cec5SDimitry Andric     SDLoc DL(V64Reg);
1336*0b57cec5SDimitry Andric 
1337*0b57cec5SDimitry Andric     SDValue Undef =
1338*0b57cec5SDimitry Andric         SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, WideTy), 0);
1339*0b57cec5SDimitry Andric     return DAG.getTargetInsertSubreg(AArch64::dsub, DL, WideTy, Undef, V64Reg);
1340*0b57cec5SDimitry Andric   }
1341*0b57cec5SDimitry Andric };
1342*0b57cec5SDimitry Andric } // namespace
1343*0b57cec5SDimitry Andric 
1344*0b57cec5SDimitry Andric /// NarrowVector - Given a value in the V128 register class, produce the
1345*0b57cec5SDimitry Andric /// equivalent value in the V64 register class.
1346*0b57cec5SDimitry Andric static SDValue NarrowVector(SDValue V128Reg, SelectionDAG &DAG) {
1347*0b57cec5SDimitry Andric   EVT VT = V128Reg.getValueType();
1348*0b57cec5SDimitry Andric   unsigned WideSize = VT.getVectorNumElements();
1349*0b57cec5SDimitry Andric   MVT EltTy = VT.getVectorElementType().getSimpleVT();
1350*0b57cec5SDimitry Andric   MVT NarrowTy = MVT::getVectorVT(EltTy, WideSize / 2);
1351*0b57cec5SDimitry Andric 
1352*0b57cec5SDimitry Andric   return DAG.getTargetExtractSubreg(AArch64::dsub, SDLoc(V128Reg), NarrowTy,
1353*0b57cec5SDimitry Andric                                     V128Reg);
1354*0b57cec5SDimitry Andric }
1355*0b57cec5SDimitry Andric 
1356*0b57cec5SDimitry Andric void AArch64DAGToDAGISel::SelectLoadLane(SDNode *N, unsigned NumVecs,
1357*0b57cec5SDimitry Andric                                          unsigned Opc) {
1358*0b57cec5SDimitry Andric   SDLoc dl(N);
1359*0b57cec5SDimitry Andric   EVT VT = N->getValueType(0);
1360*0b57cec5SDimitry Andric   bool Narrow = VT.getSizeInBits() == 64;
1361*0b57cec5SDimitry Andric 
1362*0b57cec5SDimitry Andric   // Form a REG_SEQUENCE to force register allocation.
1363*0b57cec5SDimitry Andric   SmallVector<SDValue, 4> Regs(N->op_begin() + 2, N->op_begin() + 2 + NumVecs);
1364*0b57cec5SDimitry Andric 
1365*0b57cec5SDimitry Andric   if (Narrow)
1366*0b57cec5SDimitry Andric     transform(Regs, Regs.begin(),
1367*0b57cec5SDimitry Andric                    WidenVector(*CurDAG));
1368*0b57cec5SDimitry Andric 
1369*0b57cec5SDimitry Andric   SDValue RegSeq = createQTuple(Regs);
1370*0b57cec5SDimitry Andric 
1371*0b57cec5SDimitry Andric   const EVT ResTys[] = {MVT::Untyped, MVT::Other};
1372*0b57cec5SDimitry Andric 
1373*0b57cec5SDimitry Andric   unsigned LaneNo =
1374*0b57cec5SDimitry Andric       cast<ConstantSDNode>(N->getOperand(NumVecs + 2))->getZExtValue();
1375*0b57cec5SDimitry Andric 
1376*0b57cec5SDimitry Andric   SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
1377*0b57cec5SDimitry Andric                    N->getOperand(NumVecs + 3), N->getOperand(0)};
1378*0b57cec5SDimitry Andric   SDNode *Ld = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
1379*0b57cec5SDimitry Andric   SDValue SuperReg = SDValue(Ld, 0);
1380*0b57cec5SDimitry Andric 
1381*0b57cec5SDimitry Andric   EVT WideVT = RegSeq.getOperand(1)->getValueType(0);
1382*0b57cec5SDimitry Andric   static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
1383*0b57cec5SDimitry Andric                                     AArch64::qsub2, AArch64::qsub3 };
1384*0b57cec5SDimitry Andric   for (unsigned i = 0; i < NumVecs; ++i) {
1385*0b57cec5SDimitry Andric     SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT, SuperReg);
1386*0b57cec5SDimitry Andric     if (Narrow)
1387*0b57cec5SDimitry Andric       NV = NarrowVector(NV, *CurDAG);
1388*0b57cec5SDimitry Andric     ReplaceUses(SDValue(N, i), NV);
1389*0b57cec5SDimitry Andric   }
1390*0b57cec5SDimitry Andric 
1391*0b57cec5SDimitry Andric   ReplaceUses(SDValue(N, NumVecs), SDValue(Ld, 1));
1392*0b57cec5SDimitry Andric   CurDAG->RemoveDeadNode(N);
1393*0b57cec5SDimitry Andric }
1394*0b57cec5SDimitry Andric 
1395*0b57cec5SDimitry Andric void AArch64DAGToDAGISel::SelectPostLoadLane(SDNode *N, unsigned NumVecs,
1396*0b57cec5SDimitry Andric                                              unsigned Opc) {
1397*0b57cec5SDimitry Andric   SDLoc dl(N);
1398*0b57cec5SDimitry Andric   EVT VT = N->getValueType(0);
1399*0b57cec5SDimitry Andric   bool Narrow = VT.getSizeInBits() == 64;
1400*0b57cec5SDimitry Andric 
1401*0b57cec5SDimitry Andric   // Form a REG_SEQUENCE to force register allocation.
1402*0b57cec5SDimitry Andric   SmallVector<SDValue, 4> Regs(N->op_begin() + 1, N->op_begin() + 1 + NumVecs);
1403*0b57cec5SDimitry Andric 
1404*0b57cec5SDimitry Andric   if (Narrow)
1405*0b57cec5SDimitry Andric     transform(Regs, Regs.begin(),
1406*0b57cec5SDimitry Andric                    WidenVector(*CurDAG));
1407*0b57cec5SDimitry Andric 
1408*0b57cec5SDimitry Andric   SDValue RegSeq = createQTuple(Regs);
1409*0b57cec5SDimitry Andric 
1410*0b57cec5SDimitry Andric   const EVT ResTys[] = {MVT::i64, // Type of the write back register
1411*0b57cec5SDimitry Andric                         RegSeq->getValueType(0), MVT::Other};
1412*0b57cec5SDimitry Andric 
1413*0b57cec5SDimitry Andric   unsigned LaneNo =
1414*0b57cec5SDimitry Andric       cast<ConstantSDNode>(N->getOperand(NumVecs + 1))->getZExtValue();
1415*0b57cec5SDimitry Andric 
1416*0b57cec5SDimitry Andric   SDValue Ops[] = {RegSeq,
1417*0b57cec5SDimitry Andric                    CurDAG->getTargetConstant(LaneNo, dl,
1418*0b57cec5SDimitry Andric                                              MVT::i64),         // Lane Number
1419*0b57cec5SDimitry Andric                    N->getOperand(NumVecs + 2),                  // Base register
1420*0b57cec5SDimitry Andric                    N->getOperand(NumVecs + 3),                  // Incremental
1421*0b57cec5SDimitry Andric                    N->getOperand(0)};
1422*0b57cec5SDimitry Andric   SDNode *Ld = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
1423*0b57cec5SDimitry Andric 
1424*0b57cec5SDimitry Andric   // Update uses of the write back register
1425*0b57cec5SDimitry Andric   ReplaceUses(SDValue(N, NumVecs), SDValue(Ld, 0));
1426*0b57cec5SDimitry Andric 
1427*0b57cec5SDimitry Andric   // Update uses of the vector list
1428*0b57cec5SDimitry Andric   SDValue SuperReg = SDValue(Ld, 1);
1429*0b57cec5SDimitry Andric   if (NumVecs == 1) {
1430*0b57cec5SDimitry Andric     ReplaceUses(SDValue(N, 0),
1431*0b57cec5SDimitry Andric                 Narrow ? NarrowVector(SuperReg, *CurDAG) : SuperReg);
1432*0b57cec5SDimitry Andric   } else {
1433*0b57cec5SDimitry Andric     EVT WideVT = RegSeq.getOperand(1)->getValueType(0);
1434*0b57cec5SDimitry Andric     static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
1435*0b57cec5SDimitry Andric                                       AArch64::qsub2, AArch64::qsub3 };
1436*0b57cec5SDimitry Andric     for (unsigned i = 0; i < NumVecs; ++i) {
1437*0b57cec5SDimitry Andric       SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT,
1438*0b57cec5SDimitry Andric                                                   SuperReg);
1439*0b57cec5SDimitry Andric       if (Narrow)
1440*0b57cec5SDimitry Andric         NV = NarrowVector(NV, *CurDAG);
1441*0b57cec5SDimitry Andric       ReplaceUses(SDValue(N, i), NV);
1442*0b57cec5SDimitry Andric     }
1443*0b57cec5SDimitry Andric   }
1444*0b57cec5SDimitry Andric 
1445*0b57cec5SDimitry Andric   // Update the Chain
1446*0b57cec5SDimitry Andric   ReplaceUses(SDValue(N, NumVecs + 1), SDValue(Ld, 2));
1447*0b57cec5SDimitry Andric   CurDAG->RemoveDeadNode(N);
1448*0b57cec5SDimitry Andric }
1449*0b57cec5SDimitry Andric 
1450*0b57cec5SDimitry Andric void AArch64DAGToDAGISel::SelectStoreLane(SDNode *N, unsigned NumVecs,
1451*0b57cec5SDimitry Andric                                           unsigned Opc) {
1452*0b57cec5SDimitry Andric   SDLoc dl(N);
1453*0b57cec5SDimitry Andric   EVT VT = N->getOperand(2)->getValueType(0);
1454*0b57cec5SDimitry Andric   bool Narrow = VT.getSizeInBits() == 64;
1455*0b57cec5SDimitry Andric 
1456*0b57cec5SDimitry Andric   // Form a REG_SEQUENCE to force register allocation.
1457*0b57cec5SDimitry Andric   SmallVector<SDValue, 4> Regs(N->op_begin() + 2, N->op_begin() + 2 + NumVecs);
1458*0b57cec5SDimitry Andric 
1459*0b57cec5SDimitry Andric   if (Narrow)
1460*0b57cec5SDimitry Andric     transform(Regs, Regs.begin(),
1461*0b57cec5SDimitry Andric                    WidenVector(*CurDAG));
1462*0b57cec5SDimitry Andric 
1463*0b57cec5SDimitry Andric   SDValue RegSeq = createQTuple(Regs);
1464*0b57cec5SDimitry Andric 
1465*0b57cec5SDimitry Andric   unsigned LaneNo =
1466*0b57cec5SDimitry Andric       cast<ConstantSDNode>(N->getOperand(NumVecs + 2))->getZExtValue();
1467*0b57cec5SDimitry Andric 
1468*0b57cec5SDimitry Andric   SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
1469*0b57cec5SDimitry Andric                    N->getOperand(NumVecs + 3), N->getOperand(0)};
1470*0b57cec5SDimitry Andric   SDNode *St = CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops);
1471*0b57cec5SDimitry Andric 
1472*0b57cec5SDimitry Andric   // Transfer memoperands.
1473*0b57cec5SDimitry Andric   MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1474*0b57cec5SDimitry Andric   CurDAG->setNodeMemRefs(cast<MachineSDNode>(St), {MemOp});
1475*0b57cec5SDimitry Andric 
1476*0b57cec5SDimitry Andric   ReplaceNode(N, St);
1477*0b57cec5SDimitry Andric }
1478*0b57cec5SDimitry Andric 
1479*0b57cec5SDimitry Andric void AArch64DAGToDAGISel::SelectPostStoreLane(SDNode *N, unsigned NumVecs,
1480*0b57cec5SDimitry Andric                                               unsigned Opc) {
1481*0b57cec5SDimitry Andric   SDLoc dl(N);
1482*0b57cec5SDimitry Andric   EVT VT = N->getOperand(2)->getValueType(0);
1483*0b57cec5SDimitry Andric   bool Narrow = VT.getSizeInBits() == 64;
1484*0b57cec5SDimitry Andric 
1485*0b57cec5SDimitry Andric   // Form a REG_SEQUENCE to force register allocation.
1486*0b57cec5SDimitry Andric   SmallVector<SDValue, 4> Regs(N->op_begin() + 1, N->op_begin() + 1 + NumVecs);
1487*0b57cec5SDimitry Andric 
1488*0b57cec5SDimitry Andric   if (Narrow)
1489*0b57cec5SDimitry Andric     transform(Regs, Regs.begin(),
1490*0b57cec5SDimitry Andric                    WidenVector(*CurDAG));
1491*0b57cec5SDimitry Andric 
1492*0b57cec5SDimitry Andric   SDValue RegSeq = createQTuple(Regs);
1493*0b57cec5SDimitry Andric 
1494*0b57cec5SDimitry Andric   const EVT ResTys[] = {MVT::i64, // Type of the write back register
1495*0b57cec5SDimitry Andric                         MVT::Other};
1496*0b57cec5SDimitry Andric 
1497*0b57cec5SDimitry Andric   unsigned LaneNo =
1498*0b57cec5SDimitry Andric       cast<ConstantSDNode>(N->getOperand(NumVecs + 1))->getZExtValue();
1499*0b57cec5SDimitry Andric 
1500*0b57cec5SDimitry Andric   SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
1501*0b57cec5SDimitry Andric                    N->getOperand(NumVecs + 2), // Base Register
1502*0b57cec5SDimitry Andric                    N->getOperand(NumVecs + 3), // Incremental
1503*0b57cec5SDimitry Andric                    N->getOperand(0)};
1504*0b57cec5SDimitry Andric   SDNode *St = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
1505*0b57cec5SDimitry Andric 
1506*0b57cec5SDimitry Andric   // Transfer memoperands.
1507*0b57cec5SDimitry Andric   MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1508*0b57cec5SDimitry Andric   CurDAG->setNodeMemRefs(cast<MachineSDNode>(St), {MemOp});
1509*0b57cec5SDimitry Andric 
1510*0b57cec5SDimitry Andric   ReplaceNode(N, St);
1511*0b57cec5SDimitry Andric }
1512*0b57cec5SDimitry Andric 
1513*0b57cec5SDimitry Andric static bool isBitfieldExtractOpFromAnd(SelectionDAG *CurDAG, SDNode *N,
1514*0b57cec5SDimitry Andric                                        unsigned &Opc, SDValue &Opd0,
1515*0b57cec5SDimitry Andric                                        unsigned &LSB, unsigned &MSB,
1516*0b57cec5SDimitry Andric                                        unsigned NumberOfIgnoredLowBits,
1517*0b57cec5SDimitry Andric                                        bool BiggerPattern) {
1518*0b57cec5SDimitry Andric   assert(N->getOpcode() == ISD::AND &&
1519*0b57cec5SDimitry Andric          "N must be a AND operation to call this function");
1520*0b57cec5SDimitry Andric 
1521*0b57cec5SDimitry Andric   EVT VT = N->getValueType(0);
1522*0b57cec5SDimitry Andric 
1523*0b57cec5SDimitry Andric   // Here we can test the type of VT and return false when the type does not
1524*0b57cec5SDimitry Andric   // match, but since it is done prior to that call in the current context
1525*0b57cec5SDimitry Andric   // we turned that into an assert to avoid redundant code.
1526*0b57cec5SDimitry Andric   assert((VT == MVT::i32 || VT == MVT::i64) &&
1527*0b57cec5SDimitry Andric          "Type checking must have been done before calling this function");
1528*0b57cec5SDimitry Andric 
1529*0b57cec5SDimitry Andric   // FIXME: simplify-demanded-bits in DAGCombine will probably have
1530*0b57cec5SDimitry Andric   // changed the AND node to a 32-bit mask operation. We'll have to
1531*0b57cec5SDimitry Andric   // undo that as part of the transform here if we want to catch all
1532*0b57cec5SDimitry Andric   // the opportunities.
1533*0b57cec5SDimitry Andric   // Currently the NumberOfIgnoredLowBits argument helps to recover
1534*0b57cec5SDimitry Andric   // form these situations when matching bigger pattern (bitfield insert).
1535*0b57cec5SDimitry Andric 
1536*0b57cec5SDimitry Andric   // For unsigned extracts, check for a shift right and mask
1537*0b57cec5SDimitry Andric   uint64_t AndImm = 0;
1538*0b57cec5SDimitry Andric   if (!isOpcWithIntImmediate(N, ISD::AND, AndImm))
1539*0b57cec5SDimitry Andric     return false;
1540*0b57cec5SDimitry Andric 
1541*0b57cec5SDimitry Andric   const SDNode *Op0 = N->getOperand(0).getNode();
1542*0b57cec5SDimitry Andric 
1543*0b57cec5SDimitry Andric   // Because of simplify-demanded-bits in DAGCombine, the mask may have been
1544*0b57cec5SDimitry Andric   // simplified. Try to undo that
1545*0b57cec5SDimitry Andric   AndImm |= maskTrailingOnes<uint64_t>(NumberOfIgnoredLowBits);
1546*0b57cec5SDimitry Andric 
1547*0b57cec5SDimitry Andric   // The immediate is a mask of the low bits iff imm & (imm+1) == 0
1548*0b57cec5SDimitry Andric   if (AndImm & (AndImm + 1))
1549*0b57cec5SDimitry Andric     return false;
1550*0b57cec5SDimitry Andric 
1551*0b57cec5SDimitry Andric   bool ClampMSB = false;
1552*0b57cec5SDimitry Andric   uint64_t SrlImm = 0;
1553*0b57cec5SDimitry Andric   // Handle the SRL + ANY_EXTEND case.
1554*0b57cec5SDimitry Andric   if (VT == MVT::i64 && Op0->getOpcode() == ISD::ANY_EXTEND &&
1555*0b57cec5SDimitry Andric       isOpcWithIntImmediate(Op0->getOperand(0).getNode(), ISD::SRL, SrlImm)) {
1556*0b57cec5SDimitry Andric     // Extend the incoming operand of the SRL to 64-bit.
1557*0b57cec5SDimitry Andric     Opd0 = Widen(CurDAG, Op0->getOperand(0).getOperand(0));
1558*0b57cec5SDimitry Andric     // Make sure to clamp the MSB so that we preserve the semantics of the
1559*0b57cec5SDimitry Andric     // original operations.
1560*0b57cec5SDimitry Andric     ClampMSB = true;
1561*0b57cec5SDimitry Andric   } else if (VT == MVT::i32 && Op0->getOpcode() == ISD::TRUNCATE &&
1562*0b57cec5SDimitry Andric              isOpcWithIntImmediate(Op0->getOperand(0).getNode(), ISD::SRL,
1563*0b57cec5SDimitry Andric                                    SrlImm)) {
1564*0b57cec5SDimitry Andric     // If the shift result was truncated, we can still combine them.
1565*0b57cec5SDimitry Andric     Opd0 = Op0->getOperand(0).getOperand(0);
1566*0b57cec5SDimitry Andric 
1567*0b57cec5SDimitry Andric     // Use the type of SRL node.
1568*0b57cec5SDimitry Andric     VT = Opd0->getValueType(0);
1569*0b57cec5SDimitry Andric   } else if (isOpcWithIntImmediate(Op0, ISD::SRL, SrlImm)) {
1570*0b57cec5SDimitry Andric     Opd0 = Op0->getOperand(0);
1571*0b57cec5SDimitry Andric   } else if (BiggerPattern) {
1572*0b57cec5SDimitry Andric     // Let's pretend a 0 shift right has been performed.
1573*0b57cec5SDimitry Andric     // The resulting code will be at least as good as the original one
1574*0b57cec5SDimitry Andric     // plus it may expose more opportunities for bitfield insert pattern.
1575*0b57cec5SDimitry Andric     // FIXME: Currently we limit this to the bigger pattern, because
1576*0b57cec5SDimitry Andric     // some optimizations expect AND and not UBFM.
1577*0b57cec5SDimitry Andric     Opd0 = N->getOperand(0);
1578*0b57cec5SDimitry Andric   } else
1579*0b57cec5SDimitry Andric     return false;
1580*0b57cec5SDimitry Andric 
1581*0b57cec5SDimitry Andric   // Bail out on large immediates. This happens when no proper
1582*0b57cec5SDimitry Andric   // combining/constant folding was performed.
1583*0b57cec5SDimitry Andric   if (!BiggerPattern && (SrlImm <= 0 || SrlImm >= VT.getSizeInBits())) {
1584*0b57cec5SDimitry Andric     LLVM_DEBUG(
1585*0b57cec5SDimitry Andric         (dbgs() << N
1586*0b57cec5SDimitry Andric                 << ": Found large shift immediate, this should not happen\n"));
1587*0b57cec5SDimitry Andric     return false;
1588*0b57cec5SDimitry Andric   }
1589*0b57cec5SDimitry Andric 
1590*0b57cec5SDimitry Andric   LSB = SrlImm;
1591*0b57cec5SDimitry Andric   MSB = SrlImm + (VT == MVT::i32 ? countTrailingOnes<uint32_t>(AndImm)
1592*0b57cec5SDimitry Andric                                  : countTrailingOnes<uint64_t>(AndImm)) -
1593*0b57cec5SDimitry Andric         1;
1594*0b57cec5SDimitry Andric   if (ClampMSB)
1595*0b57cec5SDimitry Andric     // Since we're moving the extend before the right shift operation, we need
1596*0b57cec5SDimitry Andric     // to clamp the MSB to make sure we don't shift in undefined bits instead of
1597*0b57cec5SDimitry Andric     // the zeros which would get shifted in with the original right shift
1598*0b57cec5SDimitry Andric     // operation.
1599*0b57cec5SDimitry Andric     MSB = MSB > 31 ? 31 : MSB;
1600*0b57cec5SDimitry Andric 
1601*0b57cec5SDimitry Andric   Opc = VT == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
1602*0b57cec5SDimitry Andric   return true;
1603*0b57cec5SDimitry Andric }
1604*0b57cec5SDimitry Andric 
1605*0b57cec5SDimitry Andric static bool isBitfieldExtractOpFromSExtInReg(SDNode *N, unsigned &Opc,
1606*0b57cec5SDimitry Andric                                              SDValue &Opd0, unsigned &Immr,
1607*0b57cec5SDimitry Andric                                              unsigned &Imms) {
1608*0b57cec5SDimitry Andric   assert(N->getOpcode() == ISD::SIGN_EXTEND_INREG);
1609*0b57cec5SDimitry Andric 
1610*0b57cec5SDimitry Andric   EVT VT = N->getValueType(0);
1611*0b57cec5SDimitry Andric   unsigned BitWidth = VT.getSizeInBits();
1612*0b57cec5SDimitry Andric   assert((VT == MVT::i32 || VT == MVT::i64) &&
1613*0b57cec5SDimitry Andric          "Type checking must have been done before calling this function");
1614*0b57cec5SDimitry Andric 
1615*0b57cec5SDimitry Andric   SDValue Op = N->getOperand(0);
1616*0b57cec5SDimitry Andric   if (Op->getOpcode() == ISD::TRUNCATE) {
1617*0b57cec5SDimitry Andric     Op = Op->getOperand(0);
1618*0b57cec5SDimitry Andric     VT = Op->getValueType(0);
1619*0b57cec5SDimitry Andric     BitWidth = VT.getSizeInBits();
1620*0b57cec5SDimitry Andric   }
1621*0b57cec5SDimitry Andric 
1622*0b57cec5SDimitry Andric   uint64_t ShiftImm;
1623*0b57cec5SDimitry Andric   if (!isOpcWithIntImmediate(Op.getNode(), ISD::SRL, ShiftImm) &&
1624*0b57cec5SDimitry Andric       !isOpcWithIntImmediate(Op.getNode(), ISD::SRA, ShiftImm))
1625*0b57cec5SDimitry Andric     return false;
1626*0b57cec5SDimitry Andric 
1627*0b57cec5SDimitry Andric   unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits();
1628*0b57cec5SDimitry Andric   if (ShiftImm + Width > BitWidth)
1629*0b57cec5SDimitry Andric     return false;
1630*0b57cec5SDimitry Andric 
1631*0b57cec5SDimitry Andric   Opc = (VT == MVT::i32) ? AArch64::SBFMWri : AArch64::SBFMXri;
1632*0b57cec5SDimitry Andric   Opd0 = Op.getOperand(0);
1633*0b57cec5SDimitry Andric   Immr = ShiftImm;
1634*0b57cec5SDimitry Andric   Imms = ShiftImm + Width - 1;
1635*0b57cec5SDimitry Andric   return true;
1636*0b57cec5SDimitry Andric }
1637*0b57cec5SDimitry Andric 
1638*0b57cec5SDimitry Andric static bool isSeveralBitsExtractOpFromShr(SDNode *N, unsigned &Opc,
1639*0b57cec5SDimitry Andric                                           SDValue &Opd0, unsigned &LSB,
1640*0b57cec5SDimitry Andric                                           unsigned &MSB) {
1641*0b57cec5SDimitry Andric   // We are looking for the following pattern which basically extracts several
1642*0b57cec5SDimitry Andric   // continuous bits from the source value and places it from the LSB of the
1643*0b57cec5SDimitry Andric   // destination value, all other bits of the destination value or set to zero:
1644*0b57cec5SDimitry Andric   //
1645*0b57cec5SDimitry Andric   // Value2 = AND Value, MaskImm
1646*0b57cec5SDimitry Andric   // SRL Value2, ShiftImm
1647*0b57cec5SDimitry Andric   //
1648*0b57cec5SDimitry Andric   // with MaskImm >> ShiftImm to search for the bit width.
1649*0b57cec5SDimitry Andric   //
1650*0b57cec5SDimitry Andric   // This gets selected into a single UBFM:
1651*0b57cec5SDimitry Andric   //
1652*0b57cec5SDimitry Andric   // UBFM Value, ShiftImm, BitWide + SrlImm -1
1653*0b57cec5SDimitry Andric   //
1654*0b57cec5SDimitry Andric 
1655*0b57cec5SDimitry Andric   if (N->getOpcode() != ISD::SRL)
1656*0b57cec5SDimitry Andric     return false;
1657*0b57cec5SDimitry Andric 
1658*0b57cec5SDimitry Andric   uint64_t AndMask = 0;
1659*0b57cec5SDimitry Andric   if (!isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::AND, AndMask))
1660*0b57cec5SDimitry Andric     return false;
1661*0b57cec5SDimitry Andric 
1662*0b57cec5SDimitry Andric   Opd0 = N->getOperand(0).getOperand(0);
1663*0b57cec5SDimitry Andric 
1664*0b57cec5SDimitry Andric   uint64_t SrlImm = 0;
1665*0b57cec5SDimitry Andric   if (!isIntImmediate(N->getOperand(1), SrlImm))
1666*0b57cec5SDimitry Andric     return false;
1667*0b57cec5SDimitry Andric 
1668*0b57cec5SDimitry Andric   // Check whether we really have several bits extract here.
1669*0b57cec5SDimitry Andric   unsigned BitWide = 64 - countLeadingOnes(~(AndMask >> SrlImm));
1670*0b57cec5SDimitry Andric   if (BitWide && isMask_64(AndMask >> SrlImm)) {
1671*0b57cec5SDimitry Andric     if (N->getValueType(0) == MVT::i32)
1672*0b57cec5SDimitry Andric       Opc = AArch64::UBFMWri;
1673*0b57cec5SDimitry Andric     else
1674*0b57cec5SDimitry Andric       Opc = AArch64::UBFMXri;
1675*0b57cec5SDimitry Andric 
1676*0b57cec5SDimitry Andric     LSB = SrlImm;
1677*0b57cec5SDimitry Andric     MSB = BitWide + SrlImm - 1;
1678*0b57cec5SDimitry Andric     return true;
1679*0b57cec5SDimitry Andric   }
1680*0b57cec5SDimitry Andric 
1681*0b57cec5SDimitry Andric   return false;
1682*0b57cec5SDimitry Andric }
1683*0b57cec5SDimitry Andric 
1684*0b57cec5SDimitry Andric static bool isBitfieldExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0,
1685*0b57cec5SDimitry Andric                                        unsigned &Immr, unsigned &Imms,
1686*0b57cec5SDimitry Andric                                        bool BiggerPattern) {
1687*0b57cec5SDimitry Andric   assert((N->getOpcode() == ISD::SRA || N->getOpcode() == ISD::SRL) &&
1688*0b57cec5SDimitry Andric          "N must be a SHR/SRA operation to call this function");
1689*0b57cec5SDimitry Andric 
1690*0b57cec5SDimitry Andric   EVT VT = N->getValueType(0);
1691*0b57cec5SDimitry Andric 
1692*0b57cec5SDimitry Andric   // Here we can test the type of VT and return false when the type does not
1693*0b57cec5SDimitry Andric   // match, but since it is done prior to that call in the current context
1694*0b57cec5SDimitry Andric   // we turned that into an assert to avoid redundant code.
1695*0b57cec5SDimitry Andric   assert((VT == MVT::i32 || VT == MVT::i64) &&
1696*0b57cec5SDimitry Andric          "Type checking must have been done before calling this function");
1697*0b57cec5SDimitry Andric 
1698*0b57cec5SDimitry Andric   // Check for AND + SRL doing several bits extract.
1699*0b57cec5SDimitry Andric   if (isSeveralBitsExtractOpFromShr(N, Opc, Opd0, Immr, Imms))
1700*0b57cec5SDimitry Andric     return true;
1701*0b57cec5SDimitry Andric 
1702*0b57cec5SDimitry Andric   // We're looking for a shift of a shift.
1703*0b57cec5SDimitry Andric   uint64_t ShlImm = 0;
1704*0b57cec5SDimitry Andric   uint64_t TruncBits = 0;
1705*0b57cec5SDimitry Andric   if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, ShlImm)) {
1706*0b57cec5SDimitry Andric     Opd0 = N->getOperand(0).getOperand(0);
1707*0b57cec5SDimitry Andric   } else if (VT == MVT::i32 && N->getOpcode() == ISD::SRL &&
1708*0b57cec5SDimitry Andric              N->getOperand(0).getNode()->getOpcode() == ISD::TRUNCATE) {
1709*0b57cec5SDimitry Andric     // We are looking for a shift of truncate. Truncate from i64 to i32 could
1710*0b57cec5SDimitry Andric     // be considered as setting high 32 bits as zero. Our strategy here is to
1711*0b57cec5SDimitry Andric     // always generate 64bit UBFM. This consistency will help the CSE pass
1712*0b57cec5SDimitry Andric     // later find more redundancy.
1713*0b57cec5SDimitry Andric     Opd0 = N->getOperand(0).getOperand(0);
1714*0b57cec5SDimitry Andric     TruncBits = Opd0->getValueType(0).getSizeInBits() - VT.getSizeInBits();
1715*0b57cec5SDimitry Andric     VT = Opd0.getValueType();
1716*0b57cec5SDimitry Andric     assert(VT == MVT::i64 && "the promoted type should be i64");
1717*0b57cec5SDimitry Andric   } else if (BiggerPattern) {
1718*0b57cec5SDimitry Andric     // Let's pretend a 0 shift left has been performed.
1719*0b57cec5SDimitry Andric     // FIXME: Currently we limit this to the bigger pattern case,
1720*0b57cec5SDimitry Andric     // because some optimizations expect AND and not UBFM
1721*0b57cec5SDimitry Andric     Opd0 = N->getOperand(0);
1722*0b57cec5SDimitry Andric   } else
1723*0b57cec5SDimitry Andric     return false;
1724*0b57cec5SDimitry Andric 
1725*0b57cec5SDimitry Andric   // Missing combines/constant folding may have left us with strange
1726*0b57cec5SDimitry Andric   // constants.
1727*0b57cec5SDimitry Andric   if (ShlImm >= VT.getSizeInBits()) {
1728*0b57cec5SDimitry Andric     LLVM_DEBUG(
1729*0b57cec5SDimitry Andric         (dbgs() << N
1730*0b57cec5SDimitry Andric                 << ": Found large shift immediate, this should not happen\n"));
1731*0b57cec5SDimitry Andric     return false;
1732*0b57cec5SDimitry Andric   }
1733*0b57cec5SDimitry Andric 
1734*0b57cec5SDimitry Andric   uint64_t SrlImm = 0;
1735*0b57cec5SDimitry Andric   if (!isIntImmediate(N->getOperand(1), SrlImm))
1736*0b57cec5SDimitry Andric     return false;
1737*0b57cec5SDimitry Andric 
1738*0b57cec5SDimitry Andric   assert(SrlImm > 0 && SrlImm < VT.getSizeInBits() &&
1739*0b57cec5SDimitry Andric          "bad amount in shift node!");
1740*0b57cec5SDimitry Andric   int immr = SrlImm - ShlImm;
1741*0b57cec5SDimitry Andric   Immr = immr < 0 ? immr + VT.getSizeInBits() : immr;
1742*0b57cec5SDimitry Andric   Imms = VT.getSizeInBits() - ShlImm - TruncBits - 1;
1743*0b57cec5SDimitry Andric   // SRA requires a signed extraction
1744*0b57cec5SDimitry Andric   if (VT == MVT::i32)
1745*0b57cec5SDimitry Andric     Opc = N->getOpcode() == ISD::SRA ? AArch64::SBFMWri : AArch64::UBFMWri;
1746*0b57cec5SDimitry Andric   else
1747*0b57cec5SDimitry Andric     Opc = N->getOpcode() == ISD::SRA ? AArch64::SBFMXri : AArch64::UBFMXri;
1748*0b57cec5SDimitry Andric   return true;
1749*0b57cec5SDimitry Andric }
1750*0b57cec5SDimitry Andric 
1751*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::tryBitfieldExtractOpFromSExt(SDNode *N) {
1752*0b57cec5SDimitry Andric   assert(N->getOpcode() == ISD::SIGN_EXTEND);
1753*0b57cec5SDimitry Andric 
1754*0b57cec5SDimitry Andric   EVT VT = N->getValueType(0);
1755*0b57cec5SDimitry Andric   EVT NarrowVT = N->getOperand(0)->getValueType(0);
1756*0b57cec5SDimitry Andric   if (VT != MVT::i64 || NarrowVT != MVT::i32)
1757*0b57cec5SDimitry Andric     return false;
1758*0b57cec5SDimitry Andric 
1759*0b57cec5SDimitry Andric   uint64_t ShiftImm;
1760*0b57cec5SDimitry Andric   SDValue Op = N->getOperand(0);
1761*0b57cec5SDimitry Andric   if (!isOpcWithIntImmediate(Op.getNode(), ISD::SRA, ShiftImm))
1762*0b57cec5SDimitry Andric     return false;
1763*0b57cec5SDimitry Andric 
1764*0b57cec5SDimitry Andric   SDLoc dl(N);
1765*0b57cec5SDimitry Andric   // Extend the incoming operand of the shift to 64-bits.
1766*0b57cec5SDimitry Andric   SDValue Opd0 = Widen(CurDAG, Op.getOperand(0));
1767*0b57cec5SDimitry Andric   unsigned Immr = ShiftImm;
1768*0b57cec5SDimitry Andric   unsigned Imms = NarrowVT.getSizeInBits() - 1;
1769*0b57cec5SDimitry Andric   SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
1770*0b57cec5SDimitry Andric                    CurDAG->getTargetConstant(Imms, dl, VT)};
1771*0b57cec5SDimitry Andric   CurDAG->SelectNodeTo(N, AArch64::SBFMXri, VT, Ops);
1772*0b57cec5SDimitry Andric   return true;
1773*0b57cec5SDimitry Andric }
1774*0b57cec5SDimitry Andric 
1775*0b57cec5SDimitry Andric static bool isBitfieldExtractOp(SelectionDAG *CurDAG, SDNode *N, unsigned &Opc,
1776*0b57cec5SDimitry Andric                                 SDValue &Opd0, unsigned &Immr, unsigned &Imms,
1777*0b57cec5SDimitry Andric                                 unsigned NumberOfIgnoredLowBits = 0,
1778*0b57cec5SDimitry Andric                                 bool BiggerPattern = false) {
1779*0b57cec5SDimitry Andric   if (N->getValueType(0) != MVT::i32 && N->getValueType(0) != MVT::i64)
1780*0b57cec5SDimitry Andric     return false;
1781*0b57cec5SDimitry Andric 
1782*0b57cec5SDimitry Andric   switch (N->getOpcode()) {
1783*0b57cec5SDimitry Andric   default:
1784*0b57cec5SDimitry Andric     if (!N->isMachineOpcode())
1785*0b57cec5SDimitry Andric       return false;
1786*0b57cec5SDimitry Andric     break;
1787*0b57cec5SDimitry Andric   case ISD::AND:
1788*0b57cec5SDimitry Andric     return isBitfieldExtractOpFromAnd(CurDAG, N, Opc, Opd0, Immr, Imms,
1789*0b57cec5SDimitry Andric                                       NumberOfIgnoredLowBits, BiggerPattern);
1790*0b57cec5SDimitry Andric   case ISD::SRL:
1791*0b57cec5SDimitry Andric   case ISD::SRA:
1792*0b57cec5SDimitry Andric     return isBitfieldExtractOpFromShr(N, Opc, Opd0, Immr, Imms, BiggerPattern);
1793*0b57cec5SDimitry Andric 
1794*0b57cec5SDimitry Andric   case ISD::SIGN_EXTEND_INREG:
1795*0b57cec5SDimitry Andric     return isBitfieldExtractOpFromSExtInReg(N, Opc, Opd0, Immr, Imms);
1796*0b57cec5SDimitry Andric   }
1797*0b57cec5SDimitry Andric 
1798*0b57cec5SDimitry Andric   unsigned NOpc = N->getMachineOpcode();
1799*0b57cec5SDimitry Andric   switch (NOpc) {
1800*0b57cec5SDimitry Andric   default:
1801*0b57cec5SDimitry Andric     return false;
1802*0b57cec5SDimitry Andric   case AArch64::SBFMWri:
1803*0b57cec5SDimitry Andric   case AArch64::UBFMWri:
1804*0b57cec5SDimitry Andric   case AArch64::SBFMXri:
1805*0b57cec5SDimitry Andric   case AArch64::UBFMXri:
1806*0b57cec5SDimitry Andric     Opc = NOpc;
1807*0b57cec5SDimitry Andric     Opd0 = N->getOperand(0);
1808*0b57cec5SDimitry Andric     Immr = cast<ConstantSDNode>(N->getOperand(1).getNode())->getZExtValue();
1809*0b57cec5SDimitry Andric     Imms = cast<ConstantSDNode>(N->getOperand(2).getNode())->getZExtValue();
1810*0b57cec5SDimitry Andric     return true;
1811*0b57cec5SDimitry Andric   }
1812*0b57cec5SDimitry Andric   // Unreachable
1813*0b57cec5SDimitry Andric   return false;
1814*0b57cec5SDimitry Andric }
1815*0b57cec5SDimitry Andric 
1816*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::tryBitfieldExtractOp(SDNode *N) {
1817*0b57cec5SDimitry Andric   unsigned Opc, Immr, Imms;
1818*0b57cec5SDimitry Andric   SDValue Opd0;
1819*0b57cec5SDimitry Andric   if (!isBitfieldExtractOp(CurDAG, N, Opc, Opd0, Immr, Imms))
1820*0b57cec5SDimitry Andric     return false;
1821*0b57cec5SDimitry Andric 
1822*0b57cec5SDimitry Andric   EVT VT = N->getValueType(0);
1823*0b57cec5SDimitry Andric   SDLoc dl(N);
1824*0b57cec5SDimitry Andric 
1825*0b57cec5SDimitry Andric   // If the bit extract operation is 64bit but the original type is 32bit, we
1826*0b57cec5SDimitry Andric   // need to add one EXTRACT_SUBREG.
1827*0b57cec5SDimitry Andric   if ((Opc == AArch64::SBFMXri || Opc == AArch64::UBFMXri) && VT == MVT::i32) {
1828*0b57cec5SDimitry Andric     SDValue Ops64[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, MVT::i64),
1829*0b57cec5SDimitry Andric                        CurDAG->getTargetConstant(Imms, dl, MVT::i64)};
1830*0b57cec5SDimitry Andric 
1831*0b57cec5SDimitry Andric     SDNode *BFM = CurDAG->getMachineNode(Opc, dl, MVT::i64, Ops64);
1832*0b57cec5SDimitry Andric     SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32);
1833*0b57cec5SDimitry Andric     ReplaceNode(N, CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl,
1834*0b57cec5SDimitry Andric                                           MVT::i32, SDValue(BFM, 0), SubReg));
1835*0b57cec5SDimitry Andric     return true;
1836*0b57cec5SDimitry Andric   }
1837*0b57cec5SDimitry Andric 
1838*0b57cec5SDimitry Andric   SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
1839*0b57cec5SDimitry Andric                    CurDAG->getTargetConstant(Imms, dl, VT)};
1840*0b57cec5SDimitry Andric   CurDAG->SelectNodeTo(N, Opc, VT, Ops);
1841*0b57cec5SDimitry Andric   return true;
1842*0b57cec5SDimitry Andric }
1843*0b57cec5SDimitry Andric 
1844*0b57cec5SDimitry Andric /// Does DstMask form a complementary pair with the mask provided by
1845*0b57cec5SDimitry Andric /// BitsToBeInserted, suitable for use in a BFI instruction. Roughly speaking,
1846*0b57cec5SDimitry Andric /// this asks whether DstMask zeroes precisely those bits that will be set by
1847*0b57cec5SDimitry Andric /// the other half.
1848*0b57cec5SDimitry Andric static bool isBitfieldDstMask(uint64_t DstMask, const APInt &BitsToBeInserted,
1849*0b57cec5SDimitry Andric                               unsigned NumberOfIgnoredHighBits, EVT VT) {
1850*0b57cec5SDimitry Andric   assert((VT == MVT::i32 || VT == MVT::i64) &&
1851*0b57cec5SDimitry Andric          "i32 or i64 mask type expected!");
1852*0b57cec5SDimitry Andric   unsigned BitWidth = VT.getSizeInBits() - NumberOfIgnoredHighBits;
1853*0b57cec5SDimitry Andric 
1854*0b57cec5SDimitry Andric   APInt SignificantDstMask = APInt(BitWidth, DstMask);
1855*0b57cec5SDimitry Andric   APInt SignificantBitsToBeInserted = BitsToBeInserted.zextOrTrunc(BitWidth);
1856*0b57cec5SDimitry Andric 
1857*0b57cec5SDimitry Andric   return (SignificantDstMask & SignificantBitsToBeInserted) == 0 &&
1858*0b57cec5SDimitry Andric          (SignificantDstMask | SignificantBitsToBeInserted).isAllOnesValue();
1859*0b57cec5SDimitry Andric }
1860*0b57cec5SDimitry Andric 
1861*0b57cec5SDimitry Andric // Look for bits that will be useful for later uses.
1862*0b57cec5SDimitry Andric // A bit is consider useless as soon as it is dropped and never used
1863*0b57cec5SDimitry Andric // before it as been dropped.
1864*0b57cec5SDimitry Andric // E.g., looking for useful bit of x
1865*0b57cec5SDimitry Andric // 1. y = x & 0x7
1866*0b57cec5SDimitry Andric // 2. z = y >> 2
1867*0b57cec5SDimitry Andric // After #1, x useful bits are 0x7, then the useful bits of x, live through
1868*0b57cec5SDimitry Andric // y.
1869*0b57cec5SDimitry Andric // After #2, the useful bits of x are 0x4.
1870*0b57cec5SDimitry Andric // However, if x is used on an unpredicatable instruction, then all its bits
1871*0b57cec5SDimitry Andric // are useful.
1872*0b57cec5SDimitry Andric // E.g.
1873*0b57cec5SDimitry Andric // 1. y = x & 0x7
1874*0b57cec5SDimitry Andric // 2. z = y >> 2
1875*0b57cec5SDimitry Andric // 3. str x, [@x]
1876*0b57cec5SDimitry Andric static void getUsefulBits(SDValue Op, APInt &UsefulBits, unsigned Depth = 0);
1877*0b57cec5SDimitry Andric 
1878*0b57cec5SDimitry Andric static void getUsefulBitsFromAndWithImmediate(SDValue Op, APInt &UsefulBits,
1879*0b57cec5SDimitry Andric                                               unsigned Depth) {
1880*0b57cec5SDimitry Andric   uint64_t Imm =
1881*0b57cec5SDimitry Andric       cast<const ConstantSDNode>(Op.getOperand(1).getNode())->getZExtValue();
1882*0b57cec5SDimitry Andric   Imm = AArch64_AM::decodeLogicalImmediate(Imm, UsefulBits.getBitWidth());
1883*0b57cec5SDimitry Andric   UsefulBits &= APInt(UsefulBits.getBitWidth(), Imm);
1884*0b57cec5SDimitry Andric   getUsefulBits(Op, UsefulBits, Depth + 1);
1885*0b57cec5SDimitry Andric }
1886*0b57cec5SDimitry Andric 
1887*0b57cec5SDimitry Andric static void getUsefulBitsFromBitfieldMoveOpd(SDValue Op, APInt &UsefulBits,
1888*0b57cec5SDimitry Andric                                              uint64_t Imm, uint64_t MSB,
1889*0b57cec5SDimitry Andric                                              unsigned Depth) {
1890*0b57cec5SDimitry Andric   // inherit the bitwidth value
1891*0b57cec5SDimitry Andric   APInt OpUsefulBits(UsefulBits);
1892*0b57cec5SDimitry Andric   OpUsefulBits = 1;
1893*0b57cec5SDimitry Andric 
1894*0b57cec5SDimitry Andric   if (MSB >= Imm) {
1895*0b57cec5SDimitry Andric     OpUsefulBits <<= MSB - Imm + 1;
1896*0b57cec5SDimitry Andric     --OpUsefulBits;
1897*0b57cec5SDimitry Andric     // The interesting part will be in the lower part of the result
1898*0b57cec5SDimitry Andric     getUsefulBits(Op, OpUsefulBits, Depth + 1);
1899*0b57cec5SDimitry Andric     // The interesting part was starting at Imm in the argument
1900*0b57cec5SDimitry Andric     OpUsefulBits <<= Imm;
1901*0b57cec5SDimitry Andric   } else {
1902*0b57cec5SDimitry Andric     OpUsefulBits <<= MSB + 1;
1903*0b57cec5SDimitry Andric     --OpUsefulBits;
1904*0b57cec5SDimitry Andric     // The interesting part will be shifted in the result
1905*0b57cec5SDimitry Andric     OpUsefulBits <<= OpUsefulBits.getBitWidth() - Imm;
1906*0b57cec5SDimitry Andric     getUsefulBits(Op, OpUsefulBits, Depth + 1);
1907*0b57cec5SDimitry Andric     // The interesting part was at zero in the argument
1908*0b57cec5SDimitry Andric     OpUsefulBits.lshrInPlace(OpUsefulBits.getBitWidth() - Imm);
1909*0b57cec5SDimitry Andric   }
1910*0b57cec5SDimitry Andric 
1911*0b57cec5SDimitry Andric   UsefulBits &= OpUsefulBits;
1912*0b57cec5SDimitry Andric }
1913*0b57cec5SDimitry Andric 
1914*0b57cec5SDimitry Andric static void getUsefulBitsFromUBFM(SDValue Op, APInt &UsefulBits,
1915*0b57cec5SDimitry Andric                                   unsigned Depth) {
1916*0b57cec5SDimitry Andric   uint64_t Imm =
1917*0b57cec5SDimitry Andric       cast<const ConstantSDNode>(Op.getOperand(1).getNode())->getZExtValue();
1918*0b57cec5SDimitry Andric   uint64_t MSB =
1919*0b57cec5SDimitry Andric       cast<const ConstantSDNode>(Op.getOperand(2).getNode())->getZExtValue();
1920*0b57cec5SDimitry Andric 
1921*0b57cec5SDimitry Andric   getUsefulBitsFromBitfieldMoveOpd(Op, UsefulBits, Imm, MSB, Depth);
1922*0b57cec5SDimitry Andric }
1923*0b57cec5SDimitry Andric 
1924*0b57cec5SDimitry Andric static void getUsefulBitsFromOrWithShiftedReg(SDValue Op, APInt &UsefulBits,
1925*0b57cec5SDimitry Andric                                               unsigned Depth) {
1926*0b57cec5SDimitry Andric   uint64_t ShiftTypeAndValue =
1927*0b57cec5SDimitry Andric       cast<const ConstantSDNode>(Op.getOperand(2).getNode())->getZExtValue();
1928*0b57cec5SDimitry Andric   APInt Mask(UsefulBits);
1929*0b57cec5SDimitry Andric   Mask.clearAllBits();
1930*0b57cec5SDimitry Andric   Mask.flipAllBits();
1931*0b57cec5SDimitry Andric 
1932*0b57cec5SDimitry Andric   if (AArch64_AM::getShiftType(ShiftTypeAndValue) == AArch64_AM::LSL) {
1933*0b57cec5SDimitry Andric     // Shift Left
1934*0b57cec5SDimitry Andric     uint64_t ShiftAmt = AArch64_AM::getShiftValue(ShiftTypeAndValue);
1935*0b57cec5SDimitry Andric     Mask <<= ShiftAmt;
1936*0b57cec5SDimitry Andric     getUsefulBits(Op, Mask, Depth + 1);
1937*0b57cec5SDimitry Andric     Mask.lshrInPlace(ShiftAmt);
1938*0b57cec5SDimitry Andric   } else if (AArch64_AM::getShiftType(ShiftTypeAndValue) == AArch64_AM::LSR) {
1939*0b57cec5SDimitry Andric     // Shift Right
1940*0b57cec5SDimitry Andric     // We do not handle AArch64_AM::ASR, because the sign will change the
1941*0b57cec5SDimitry Andric     // number of useful bits
1942*0b57cec5SDimitry Andric     uint64_t ShiftAmt = AArch64_AM::getShiftValue(ShiftTypeAndValue);
1943*0b57cec5SDimitry Andric     Mask.lshrInPlace(ShiftAmt);
1944*0b57cec5SDimitry Andric     getUsefulBits(Op, Mask, Depth + 1);
1945*0b57cec5SDimitry Andric     Mask <<= ShiftAmt;
1946*0b57cec5SDimitry Andric   } else
1947*0b57cec5SDimitry Andric     return;
1948*0b57cec5SDimitry Andric 
1949*0b57cec5SDimitry Andric   UsefulBits &= Mask;
1950*0b57cec5SDimitry Andric }
1951*0b57cec5SDimitry Andric 
1952*0b57cec5SDimitry Andric static void getUsefulBitsFromBFM(SDValue Op, SDValue Orig, APInt &UsefulBits,
1953*0b57cec5SDimitry Andric                                  unsigned Depth) {
1954*0b57cec5SDimitry Andric   uint64_t Imm =
1955*0b57cec5SDimitry Andric       cast<const ConstantSDNode>(Op.getOperand(2).getNode())->getZExtValue();
1956*0b57cec5SDimitry Andric   uint64_t MSB =
1957*0b57cec5SDimitry Andric       cast<const ConstantSDNode>(Op.getOperand(3).getNode())->getZExtValue();
1958*0b57cec5SDimitry Andric 
1959*0b57cec5SDimitry Andric   APInt OpUsefulBits(UsefulBits);
1960*0b57cec5SDimitry Andric   OpUsefulBits = 1;
1961*0b57cec5SDimitry Andric 
1962*0b57cec5SDimitry Andric   APInt ResultUsefulBits(UsefulBits.getBitWidth(), 0);
1963*0b57cec5SDimitry Andric   ResultUsefulBits.flipAllBits();
1964*0b57cec5SDimitry Andric   APInt Mask(UsefulBits.getBitWidth(), 0);
1965*0b57cec5SDimitry Andric 
1966*0b57cec5SDimitry Andric   getUsefulBits(Op, ResultUsefulBits, Depth + 1);
1967*0b57cec5SDimitry Andric 
1968*0b57cec5SDimitry Andric   if (MSB >= Imm) {
1969*0b57cec5SDimitry Andric     // The instruction is a BFXIL.
1970*0b57cec5SDimitry Andric     uint64_t Width = MSB - Imm + 1;
1971*0b57cec5SDimitry Andric     uint64_t LSB = Imm;
1972*0b57cec5SDimitry Andric 
1973*0b57cec5SDimitry Andric     OpUsefulBits <<= Width;
1974*0b57cec5SDimitry Andric     --OpUsefulBits;
1975*0b57cec5SDimitry Andric 
1976*0b57cec5SDimitry Andric     if (Op.getOperand(1) == Orig) {
1977*0b57cec5SDimitry Andric       // Copy the low bits from the result to bits starting from LSB.
1978*0b57cec5SDimitry Andric       Mask = ResultUsefulBits & OpUsefulBits;
1979*0b57cec5SDimitry Andric       Mask <<= LSB;
1980*0b57cec5SDimitry Andric     }
1981*0b57cec5SDimitry Andric 
1982*0b57cec5SDimitry Andric     if (Op.getOperand(0) == Orig)
1983*0b57cec5SDimitry Andric       // Bits starting from LSB in the input contribute to the result.
1984*0b57cec5SDimitry Andric       Mask |= (ResultUsefulBits & ~OpUsefulBits);
1985*0b57cec5SDimitry Andric   } else {
1986*0b57cec5SDimitry Andric     // The instruction is a BFI.
1987*0b57cec5SDimitry Andric     uint64_t Width = MSB + 1;
1988*0b57cec5SDimitry Andric     uint64_t LSB = UsefulBits.getBitWidth() - Imm;
1989*0b57cec5SDimitry Andric 
1990*0b57cec5SDimitry Andric     OpUsefulBits <<= Width;
1991*0b57cec5SDimitry Andric     --OpUsefulBits;
1992*0b57cec5SDimitry Andric     OpUsefulBits <<= LSB;
1993*0b57cec5SDimitry Andric 
1994*0b57cec5SDimitry Andric     if (Op.getOperand(1) == Orig) {
1995*0b57cec5SDimitry Andric       // Copy the bits from the result to the zero bits.
1996*0b57cec5SDimitry Andric       Mask = ResultUsefulBits & OpUsefulBits;
1997*0b57cec5SDimitry Andric       Mask.lshrInPlace(LSB);
1998*0b57cec5SDimitry Andric     }
1999*0b57cec5SDimitry Andric 
2000*0b57cec5SDimitry Andric     if (Op.getOperand(0) == Orig)
2001*0b57cec5SDimitry Andric       Mask |= (ResultUsefulBits & ~OpUsefulBits);
2002*0b57cec5SDimitry Andric   }
2003*0b57cec5SDimitry Andric 
2004*0b57cec5SDimitry Andric   UsefulBits &= Mask;
2005*0b57cec5SDimitry Andric }
2006*0b57cec5SDimitry Andric 
2007*0b57cec5SDimitry Andric static void getUsefulBitsForUse(SDNode *UserNode, APInt &UsefulBits,
2008*0b57cec5SDimitry Andric                                 SDValue Orig, unsigned Depth) {
2009*0b57cec5SDimitry Andric 
2010*0b57cec5SDimitry Andric   // Users of this node should have already been instruction selected
2011*0b57cec5SDimitry Andric   // FIXME: Can we turn that into an assert?
2012*0b57cec5SDimitry Andric   if (!UserNode->isMachineOpcode())
2013*0b57cec5SDimitry Andric     return;
2014*0b57cec5SDimitry Andric 
2015*0b57cec5SDimitry Andric   switch (UserNode->getMachineOpcode()) {
2016*0b57cec5SDimitry Andric   default:
2017*0b57cec5SDimitry Andric     return;
2018*0b57cec5SDimitry Andric   case AArch64::ANDSWri:
2019*0b57cec5SDimitry Andric   case AArch64::ANDSXri:
2020*0b57cec5SDimitry Andric   case AArch64::ANDWri:
2021*0b57cec5SDimitry Andric   case AArch64::ANDXri:
2022*0b57cec5SDimitry Andric     // We increment Depth only when we call the getUsefulBits
2023*0b57cec5SDimitry Andric     return getUsefulBitsFromAndWithImmediate(SDValue(UserNode, 0), UsefulBits,
2024*0b57cec5SDimitry Andric                                              Depth);
2025*0b57cec5SDimitry Andric   case AArch64::UBFMWri:
2026*0b57cec5SDimitry Andric   case AArch64::UBFMXri:
2027*0b57cec5SDimitry Andric     return getUsefulBitsFromUBFM(SDValue(UserNode, 0), UsefulBits, Depth);
2028*0b57cec5SDimitry Andric 
2029*0b57cec5SDimitry Andric   case AArch64::ORRWrs:
2030*0b57cec5SDimitry Andric   case AArch64::ORRXrs:
2031*0b57cec5SDimitry Andric     if (UserNode->getOperand(1) != Orig)
2032*0b57cec5SDimitry Andric       return;
2033*0b57cec5SDimitry Andric     return getUsefulBitsFromOrWithShiftedReg(SDValue(UserNode, 0), UsefulBits,
2034*0b57cec5SDimitry Andric                                              Depth);
2035*0b57cec5SDimitry Andric   case AArch64::BFMWri:
2036*0b57cec5SDimitry Andric   case AArch64::BFMXri:
2037*0b57cec5SDimitry Andric     return getUsefulBitsFromBFM(SDValue(UserNode, 0), Orig, UsefulBits, Depth);
2038*0b57cec5SDimitry Andric 
2039*0b57cec5SDimitry Andric   case AArch64::STRBBui:
2040*0b57cec5SDimitry Andric   case AArch64::STURBBi:
2041*0b57cec5SDimitry Andric     if (UserNode->getOperand(0) != Orig)
2042*0b57cec5SDimitry Andric       return;
2043*0b57cec5SDimitry Andric     UsefulBits &= APInt(UsefulBits.getBitWidth(), 0xff);
2044*0b57cec5SDimitry Andric     return;
2045*0b57cec5SDimitry Andric 
2046*0b57cec5SDimitry Andric   case AArch64::STRHHui:
2047*0b57cec5SDimitry Andric   case AArch64::STURHHi:
2048*0b57cec5SDimitry Andric     if (UserNode->getOperand(0) != Orig)
2049*0b57cec5SDimitry Andric       return;
2050*0b57cec5SDimitry Andric     UsefulBits &= APInt(UsefulBits.getBitWidth(), 0xffff);
2051*0b57cec5SDimitry Andric     return;
2052*0b57cec5SDimitry Andric   }
2053*0b57cec5SDimitry Andric }
2054*0b57cec5SDimitry Andric 
2055*0b57cec5SDimitry Andric static void getUsefulBits(SDValue Op, APInt &UsefulBits, unsigned Depth) {
2056*0b57cec5SDimitry Andric   if (Depth >= 6)
2057*0b57cec5SDimitry Andric     return;
2058*0b57cec5SDimitry Andric   // Initialize UsefulBits
2059*0b57cec5SDimitry Andric   if (!Depth) {
2060*0b57cec5SDimitry Andric     unsigned Bitwidth = Op.getScalarValueSizeInBits();
2061*0b57cec5SDimitry Andric     // At the beginning, assume every produced bits is useful
2062*0b57cec5SDimitry Andric     UsefulBits = APInt(Bitwidth, 0);
2063*0b57cec5SDimitry Andric     UsefulBits.flipAllBits();
2064*0b57cec5SDimitry Andric   }
2065*0b57cec5SDimitry Andric   APInt UsersUsefulBits(UsefulBits.getBitWidth(), 0);
2066*0b57cec5SDimitry Andric 
2067*0b57cec5SDimitry Andric   for (SDNode *Node : Op.getNode()->uses()) {
2068*0b57cec5SDimitry Andric     // A use cannot produce useful bits
2069*0b57cec5SDimitry Andric     APInt UsefulBitsForUse = APInt(UsefulBits);
2070*0b57cec5SDimitry Andric     getUsefulBitsForUse(Node, UsefulBitsForUse, Op, Depth);
2071*0b57cec5SDimitry Andric     UsersUsefulBits |= UsefulBitsForUse;
2072*0b57cec5SDimitry Andric   }
2073*0b57cec5SDimitry Andric   // UsefulBits contains the produced bits that are meaningful for the
2074*0b57cec5SDimitry Andric   // current definition, thus a user cannot make a bit meaningful at
2075*0b57cec5SDimitry Andric   // this point
2076*0b57cec5SDimitry Andric   UsefulBits &= UsersUsefulBits;
2077*0b57cec5SDimitry Andric }
2078*0b57cec5SDimitry Andric 
2079*0b57cec5SDimitry Andric /// Create a machine node performing a notional SHL of Op by ShlAmount. If
2080*0b57cec5SDimitry Andric /// ShlAmount is negative, do a (logical) right-shift instead. If ShlAmount is
2081*0b57cec5SDimitry Andric /// 0, return Op unchanged.
2082*0b57cec5SDimitry Andric static SDValue getLeftShift(SelectionDAG *CurDAG, SDValue Op, int ShlAmount) {
2083*0b57cec5SDimitry Andric   if (ShlAmount == 0)
2084*0b57cec5SDimitry Andric     return Op;
2085*0b57cec5SDimitry Andric 
2086*0b57cec5SDimitry Andric   EVT VT = Op.getValueType();
2087*0b57cec5SDimitry Andric   SDLoc dl(Op);
2088*0b57cec5SDimitry Andric   unsigned BitWidth = VT.getSizeInBits();
2089*0b57cec5SDimitry Andric   unsigned UBFMOpc = BitWidth == 32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2090*0b57cec5SDimitry Andric 
2091*0b57cec5SDimitry Andric   SDNode *ShiftNode;
2092*0b57cec5SDimitry Andric   if (ShlAmount > 0) {
2093*0b57cec5SDimitry Andric     // LSL wD, wN, #Amt == UBFM wD, wN, #32-Amt, #31-Amt
2094*0b57cec5SDimitry Andric     ShiftNode = CurDAG->getMachineNode(
2095*0b57cec5SDimitry Andric         UBFMOpc, dl, VT, Op,
2096*0b57cec5SDimitry Andric         CurDAG->getTargetConstant(BitWidth - ShlAmount, dl, VT),
2097*0b57cec5SDimitry Andric         CurDAG->getTargetConstant(BitWidth - 1 - ShlAmount, dl, VT));
2098*0b57cec5SDimitry Andric   } else {
2099*0b57cec5SDimitry Andric     // LSR wD, wN, #Amt == UBFM wD, wN, #Amt, #32-1
2100*0b57cec5SDimitry Andric     assert(ShlAmount < 0 && "expected right shift");
2101*0b57cec5SDimitry Andric     int ShrAmount = -ShlAmount;
2102*0b57cec5SDimitry Andric     ShiftNode = CurDAG->getMachineNode(
2103*0b57cec5SDimitry Andric         UBFMOpc, dl, VT, Op, CurDAG->getTargetConstant(ShrAmount, dl, VT),
2104*0b57cec5SDimitry Andric         CurDAG->getTargetConstant(BitWidth - 1, dl, VT));
2105*0b57cec5SDimitry Andric   }
2106*0b57cec5SDimitry Andric 
2107*0b57cec5SDimitry Andric   return SDValue(ShiftNode, 0);
2108*0b57cec5SDimitry Andric }
2109*0b57cec5SDimitry Andric 
2110*0b57cec5SDimitry Andric /// Does this tree qualify as an attempt to move a bitfield into position,
2111*0b57cec5SDimitry Andric /// essentially "(and (shl VAL, N), Mask)".
2112*0b57cec5SDimitry Andric static bool isBitfieldPositioningOp(SelectionDAG *CurDAG, SDValue Op,
2113*0b57cec5SDimitry Andric                                     bool BiggerPattern,
2114*0b57cec5SDimitry Andric                                     SDValue &Src, int &ShiftAmount,
2115*0b57cec5SDimitry Andric                                     int &MaskWidth) {
2116*0b57cec5SDimitry Andric   EVT VT = Op.getValueType();
2117*0b57cec5SDimitry Andric   unsigned BitWidth = VT.getSizeInBits();
2118*0b57cec5SDimitry Andric   (void)BitWidth;
2119*0b57cec5SDimitry Andric   assert(BitWidth == 32 || BitWidth == 64);
2120*0b57cec5SDimitry Andric 
2121*0b57cec5SDimitry Andric   KnownBits Known = CurDAG->computeKnownBits(Op);
2122*0b57cec5SDimitry Andric 
2123*0b57cec5SDimitry Andric   // Non-zero in the sense that they're not provably zero, which is the key
2124*0b57cec5SDimitry Andric   // point if we want to use this value
2125*0b57cec5SDimitry Andric   uint64_t NonZeroBits = (~Known.Zero).getZExtValue();
2126*0b57cec5SDimitry Andric 
2127*0b57cec5SDimitry Andric   // Discard a constant AND mask if present. It's safe because the node will
2128*0b57cec5SDimitry Andric   // already have been factored into the computeKnownBits calculation above.
2129*0b57cec5SDimitry Andric   uint64_t AndImm;
2130*0b57cec5SDimitry Andric   if (isOpcWithIntImmediate(Op.getNode(), ISD::AND, AndImm)) {
2131*0b57cec5SDimitry Andric     assert((~APInt(BitWidth, AndImm) & ~Known.Zero) == 0);
2132*0b57cec5SDimitry Andric     Op = Op.getOperand(0);
2133*0b57cec5SDimitry Andric   }
2134*0b57cec5SDimitry Andric 
2135*0b57cec5SDimitry Andric   // Don't match if the SHL has more than one use, since then we'll end up
2136*0b57cec5SDimitry Andric   // generating SHL+UBFIZ instead of just keeping SHL+AND.
2137*0b57cec5SDimitry Andric   if (!BiggerPattern && !Op.hasOneUse())
2138*0b57cec5SDimitry Andric     return false;
2139*0b57cec5SDimitry Andric 
2140*0b57cec5SDimitry Andric   uint64_t ShlImm;
2141*0b57cec5SDimitry Andric   if (!isOpcWithIntImmediate(Op.getNode(), ISD::SHL, ShlImm))
2142*0b57cec5SDimitry Andric     return false;
2143*0b57cec5SDimitry Andric   Op = Op.getOperand(0);
2144*0b57cec5SDimitry Andric 
2145*0b57cec5SDimitry Andric   if (!isShiftedMask_64(NonZeroBits))
2146*0b57cec5SDimitry Andric     return false;
2147*0b57cec5SDimitry Andric 
2148*0b57cec5SDimitry Andric   ShiftAmount = countTrailingZeros(NonZeroBits);
2149*0b57cec5SDimitry Andric   MaskWidth = countTrailingOnes(NonZeroBits >> ShiftAmount);
2150*0b57cec5SDimitry Andric 
2151*0b57cec5SDimitry Andric   // BFI encompasses sufficiently many nodes that it's worth inserting an extra
2152*0b57cec5SDimitry Andric   // LSL/LSR if the mask in NonZeroBits doesn't quite match up with the ISD::SHL
2153*0b57cec5SDimitry Andric   // amount.  BiggerPattern is true when this pattern is being matched for BFI,
2154*0b57cec5SDimitry Andric   // BiggerPattern is false when this pattern is being matched for UBFIZ, in
2155*0b57cec5SDimitry Andric   // which case it is not profitable to insert an extra shift.
2156*0b57cec5SDimitry Andric   if (ShlImm - ShiftAmount != 0 && !BiggerPattern)
2157*0b57cec5SDimitry Andric     return false;
2158*0b57cec5SDimitry Andric   Src = getLeftShift(CurDAG, Op, ShlImm - ShiftAmount);
2159*0b57cec5SDimitry Andric 
2160*0b57cec5SDimitry Andric   return true;
2161*0b57cec5SDimitry Andric }
2162*0b57cec5SDimitry Andric 
2163*0b57cec5SDimitry Andric static bool isShiftedMask(uint64_t Mask, EVT VT) {
2164*0b57cec5SDimitry Andric   assert(VT == MVT::i32 || VT == MVT::i64);
2165*0b57cec5SDimitry Andric   if (VT == MVT::i32)
2166*0b57cec5SDimitry Andric     return isShiftedMask_32(Mask);
2167*0b57cec5SDimitry Andric   return isShiftedMask_64(Mask);
2168*0b57cec5SDimitry Andric }
2169*0b57cec5SDimitry Andric 
2170*0b57cec5SDimitry Andric // Generate a BFI/BFXIL from 'or (and X, MaskImm), OrImm' iff the value being
2171*0b57cec5SDimitry Andric // inserted only sets known zero bits.
2172*0b57cec5SDimitry Andric static bool tryBitfieldInsertOpFromOrAndImm(SDNode *N, SelectionDAG *CurDAG) {
2173*0b57cec5SDimitry Andric   assert(N->getOpcode() == ISD::OR && "Expect a OR operation");
2174*0b57cec5SDimitry Andric 
2175*0b57cec5SDimitry Andric   EVT VT = N->getValueType(0);
2176*0b57cec5SDimitry Andric   if (VT != MVT::i32 && VT != MVT::i64)
2177*0b57cec5SDimitry Andric     return false;
2178*0b57cec5SDimitry Andric 
2179*0b57cec5SDimitry Andric   unsigned BitWidth = VT.getSizeInBits();
2180*0b57cec5SDimitry Andric 
2181*0b57cec5SDimitry Andric   uint64_t OrImm;
2182*0b57cec5SDimitry Andric   if (!isOpcWithIntImmediate(N, ISD::OR, OrImm))
2183*0b57cec5SDimitry Andric     return false;
2184*0b57cec5SDimitry Andric 
2185*0b57cec5SDimitry Andric   // Skip this transformation if the ORR immediate can be encoded in the ORR.
2186*0b57cec5SDimitry Andric   // Otherwise, we'll trade an AND+ORR for ORR+BFI/BFXIL, which is most likely
2187*0b57cec5SDimitry Andric   // performance neutral.
2188*0b57cec5SDimitry Andric   if (AArch64_AM::isLogicalImmediate(OrImm, BitWidth))
2189*0b57cec5SDimitry Andric     return false;
2190*0b57cec5SDimitry Andric 
2191*0b57cec5SDimitry Andric   uint64_t MaskImm;
2192*0b57cec5SDimitry Andric   SDValue And = N->getOperand(0);
2193*0b57cec5SDimitry Andric   // Must be a single use AND with an immediate operand.
2194*0b57cec5SDimitry Andric   if (!And.hasOneUse() ||
2195*0b57cec5SDimitry Andric       !isOpcWithIntImmediate(And.getNode(), ISD::AND, MaskImm))
2196*0b57cec5SDimitry Andric     return false;
2197*0b57cec5SDimitry Andric 
2198*0b57cec5SDimitry Andric   // Compute the Known Zero for the AND as this allows us to catch more general
2199*0b57cec5SDimitry Andric   // cases than just looking for AND with imm.
2200*0b57cec5SDimitry Andric   KnownBits Known = CurDAG->computeKnownBits(And);
2201*0b57cec5SDimitry Andric 
2202*0b57cec5SDimitry Andric   // Non-zero in the sense that they're not provably zero, which is the key
2203*0b57cec5SDimitry Andric   // point if we want to use this value.
2204*0b57cec5SDimitry Andric   uint64_t NotKnownZero = (~Known.Zero).getZExtValue();
2205*0b57cec5SDimitry Andric 
2206*0b57cec5SDimitry Andric   // The KnownZero mask must be a shifted mask (e.g., 1110..011, 11100..00).
2207*0b57cec5SDimitry Andric   if (!isShiftedMask(Known.Zero.getZExtValue(), VT))
2208*0b57cec5SDimitry Andric     return false;
2209*0b57cec5SDimitry Andric 
2210*0b57cec5SDimitry Andric   // The bits being inserted must only set those bits that are known to be zero.
2211*0b57cec5SDimitry Andric   if ((OrImm & NotKnownZero) != 0) {
2212*0b57cec5SDimitry Andric     // FIXME:  It's okay if the OrImm sets NotKnownZero bits to 1, but we don't
2213*0b57cec5SDimitry Andric     // currently handle this case.
2214*0b57cec5SDimitry Andric     return false;
2215*0b57cec5SDimitry Andric   }
2216*0b57cec5SDimitry Andric 
2217*0b57cec5SDimitry Andric   // BFI/BFXIL dst, src, #lsb, #width.
2218*0b57cec5SDimitry Andric   int LSB = countTrailingOnes(NotKnownZero);
2219*0b57cec5SDimitry Andric   int Width = BitWidth - APInt(BitWidth, NotKnownZero).countPopulation();
2220*0b57cec5SDimitry Andric 
2221*0b57cec5SDimitry Andric   // BFI/BFXIL is an alias of BFM, so translate to BFM operands.
2222*0b57cec5SDimitry Andric   unsigned ImmR = (BitWidth - LSB) % BitWidth;
2223*0b57cec5SDimitry Andric   unsigned ImmS = Width - 1;
2224*0b57cec5SDimitry Andric 
2225*0b57cec5SDimitry Andric   // If we're creating a BFI instruction avoid cases where we need more
2226*0b57cec5SDimitry Andric   // instructions to materialize the BFI constant as compared to the original
2227*0b57cec5SDimitry Andric   // ORR.  A BFXIL will use the same constant as the original ORR, so the code
2228*0b57cec5SDimitry Andric   // should be no worse in this case.
2229*0b57cec5SDimitry Andric   bool IsBFI = LSB != 0;
2230*0b57cec5SDimitry Andric   uint64_t BFIImm = OrImm >> LSB;
2231*0b57cec5SDimitry Andric   if (IsBFI && !AArch64_AM::isLogicalImmediate(BFIImm, BitWidth)) {
2232*0b57cec5SDimitry Andric     // We have a BFI instruction and we know the constant can't be materialized
2233*0b57cec5SDimitry Andric     // with a ORR-immediate with the zero register.
2234*0b57cec5SDimitry Andric     unsigned OrChunks = 0, BFIChunks = 0;
2235*0b57cec5SDimitry Andric     for (unsigned Shift = 0; Shift < BitWidth; Shift += 16) {
2236*0b57cec5SDimitry Andric       if (((OrImm >> Shift) & 0xFFFF) != 0)
2237*0b57cec5SDimitry Andric         ++OrChunks;
2238*0b57cec5SDimitry Andric       if (((BFIImm >> Shift) & 0xFFFF) != 0)
2239*0b57cec5SDimitry Andric         ++BFIChunks;
2240*0b57cec5SDimitry Andric     }
2241*0b57cec5SDimitry Andric     if (BFIChunks > OrChunks)
2242*0b57cec5SDimitry Andric       return false;
2243*0b57cec5SDimitry Andric   }
2244*0b57cec5SDimitry Andric 
2245*0b57cec5SDimitry Andric   // Materialize the constant to be inserted.
2246*0b57cec5SDimitry Andric   SDLoc DL(N);
2247*0b57cec5SDimitry Andric   unsigned MOVIOpc = VT == MVT::i32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
2248*0b57cec5SDimitry Andric   SDNode *MOVI = CurDAG->getMachineNode(
2249*0b57cec5SDimitry Andric       MOVIOpc, DL, VT, CurDAG->getTargetConstant(BFIImm, DL, VT));
2250*0b57cec5SDimitry Andric 
2251*0b57cec5SDimitry Andric   // Create the BFI/BFXIL instruction.
2252*0b57cec5SDimitry Andric   SDValue Ops[] = {And.getOperand(0), SDValue(MOVI, 0),
2253*0b57cec5SDimitry Andric                    CurDAG->getTargetConstant(ImmR, DL, VT),
2254*0b57cec5SDimitry Andric                    CurDAG->getTargetConstant(ImmS, DL, VT)};
2255*0b57cec5SDimitry Andric   unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
2256*0b57cec5SDimitry Andric   CurDAG->SelectNodeTo(N, Opc, VT, Ops);
2257*0b57cec5SDimitry Andric   return true;
2258*0b57cec5SDimitry Andric }
2259*0b57cec5SDimitry Andric 
2260*0b57cec5SDimitry Andric static bool tryBitfieldInsertOpFromOr(SDNode *N, const APInt &UsefulBits,
2261*0b57cec5SDimitry Andric                                       SelectionDAG *CurDAG) {
2262*0b57cec5SDimitry Andric   assert(N->getOpcode() == ISD::OR && "Expect a OR operation");
2263*0b57cec5SDimitry Andric 
2264*0b57cec5SDimitry Andric   EVT VT = N->getValueType(0);
2265*0b57cec5SDimitry Andric   if (VT != MVT::i32 && VT != MVT::i64)
2266*0b57cec5SDimitry Andric     return false;
2267*0b57cec5SDimitry Andric 
2268*0b57cec5SDimitry Andric   unsigned BitWidth = VT.getSizeInBits();
2269*0b57cec5SDimitry Andric 
2270*0b57cec5SDimitry Andric   // Because of simplify-demanded-bits in DAGCombine, involved masks may not
2271*0b57cec5SDimitry Andric   // have the expected shape. Try to undo that.
2272*0b57cec5SDimitry Andric 
2273*0b57cec5SDimitry Andric   unsigned NumberOfIgnoredLowBits = UsefulBits.countTrailingZeros();
2274*0b57cec5SDimitry Andric   unsigned NumberOfIgnoredHighBits = UsefulBits.countLeadingZeros();
2275*0b57cec5SDimitry Andric 
2276*0b57cec5SDimitry Andric   // Given a OR operation, check if we have the following pattern
2277*0b57cec5SDimitry Andric   // ubfm c, b, imm, imm2 (or something that does the same jobs, see
2278*0b57cec5SDimitry Andric   //                       isBitfieldExtractOp)
2279*0b57cec5SDimitry Andric   // d = e & mask2 ; where mask is a binary sequence of 1..10..0 and
2280*0b57cec5SDimitry Andric   //                 countTrailingZeros(mask2) == imm2 - imm + 1
2281*0b57cec5SDimitry Andric   // f = d | c
2282*0b57cec5SDimitry Andric   // if yes, replace the OR instruction with:
2283*0b57cec5SDimitry Andric   // f = BFM Opd0, Opd1, LSB, MSB ; where LSB = imm, and MSB = imm2
2284*0b57cec5SDimitry Andric 
2285*0b57cec5SDimitry Andric   // OR is commutative, check all combinations of operand order and values of
2286*0b57cec5SDimitry Andric   // BiggerPattern, i.e.
2287*0b57cec5SDimitry Andric   //     Opd0, Opd1, BiggerPattern=false
2288*0b57cec5SDimitry Andric   //     Opd1, Opd0, BiggerPattern=false
2289*0b57cec5SDimitry Andric   //     Opd0, Opd1, BiggerPattern=true
2290*0b57cec5SDimitry Andric   //     Opd1, Opd0, BiggerPattern=true
2291*0b57cec5SDimitry Andric   // Several of these combinations may match, so check with BiggerPattern=false
2292*0b57cec5SDimitry Andric   // first since that will produce better results by matching more instructions
2293*0b57cec5SDimitry Andric   // and/or inserting fewer extra instructions.
2294*0b57cec5SDimitry Andric   for (int I = 0; I < 4; ++I) {
2295*0b57cec5SDimitry Andric 
2296*0b57cec5SDimitry Andric     SDValue Dst, Src;
2297*0b57cec5SDimitry Andric     unsigned ImmR, ImmS;
2298*0b57cec5SDimitry Andric     bool BiggerPattern = I / 2;
2299*0b57cec5SDimitry Andric     SDValue OrOpd0Val = N->getOperand(I % 2);
2300*0b57cec5SDimitry Andric     SDNode *OrOpd0 = OrOpd0Val.getNode();
2301*0b57cec5SDimitry Andric     SDValue OrOpd1Val = N->getOperand((I + 1) % 2);
2302*0b57cec5SDimitry Andric     SDNode *OrOpd1 = OrOpd1Val.getNode();
2303*0b57cec5SDimitry Andric 
2304*0b57cec5SDimitry Andric     unsigned BFXOpc;
2305*0b57cec5SDimitry Andric     int DstLSB, Width;
2306*0b57cec5SDimitry Andric     if (isBitfieldExtractOp(CurDAG, OrOpd0, BFXOpc, Src, ImmR, ImmS,
2307*0b57cec5SDimitry Andric                             NumberOfIgnoredLowBits, BiggerPattern)) {
2308*0b57cec5SDimitry Andric       // Check that the returned opcode is compatible with the pattern,
2309*0b57cec5SDimitry Andric       // i.e., same type and zero extended (U and not S)
2310*0b57cec5SDimitry Andric       if ((BFXOpc != AArch64::UBFMXri && VT == MVT::i64) ||
2311*0b57cec5SDimitry Andric           (BFXOpc != AArch64::UBFMWri && VT == MVT::i32))
2312*0b57cec5SDimitry Andric         continue;
2313*0b57cec5SDimitry Andric 
2314*0b57cec5SDimitry Andric       // Compute the width of the bitfield insertion
2315*0b57cec5SDimitry Andric       DstLSB = 0;
2316*0b57cec5SDimitry Andric       Width = ImmS - ImmR + 1;
2317*0b57cec5SDimitry Andric       // FIXME: This constraint is to catch bitfield insertion we may
2318*0b57cec5SDimitry Andric       // want to widen the pattern if we want to grab general bitfied
2319*0b57cec5SDimitry Andric       // move case
2320*0b57cec5SDimitry Andric       if (Width <= 0)
2321*0b57cec5SDimitry Andric         continue;
2322*0b57cec5SDimitry Andric 
2323*0b57cec5SDimitry Andric       // If the mask on the insertee is correct, we have a BFXIL operation. We
2324*0b57cec5SDimitry Andric       // can share the ImmR and ImmS values from the already-computed UBFM.
2325*0b57cec5SDimitry Andric     } else if (isBitfieldPositioningOp(CurDAG, OrOpd0Val,
2326*0b57cec5SDimitry Andric                                        BiggerPattern,
2327*0b57cec5SDimitry Andric                                        Src, DstLSB, Width)) {
2328*0b57cec5SDimitry Andric       ImmR = (BitWidth - DstLSB) % BitWidth;
2329*0b57cec5SDimitry Andric       ImmS = Width - 1;
2330*0b57cec5SDimitry Andric     } else
2331*0b57cec5SDimitry Andric       continue;
2332*0b57cec5SDimitry Andric 
2333*0b57cec5SDimitry Andric     // Check the second part of the pattern
2334*0b57cec5SDimitry Andric     EVT VT = OrOpd1Val.getValueType();
2335*0b57cec5SDimitry Andric     assert((VT == MVT::i32 || VT == MVT::i64) && "unexpected OR operand");
2336*0b57cec5SDimitry Andric 
2337*0b57cec5SDimitry Andric     // Compute the Known Zero for the candidate of the first operand.
2338*0b57cec5SDimitry Andric     // This allows to catch more general case than just looking for
2339*0b57cec5SDimitry Andric     // AND with imm. Indeed, simplify-demanded-bits may have removed
2340*0b57cec5SDimitry Andric     // the AND instruction because it proves it was useless.
2341*0b57cec5SDimitry Andric     KnownBits Known = CurDAG->computeKnownBits(OrOpd1Val);
2342*0b57cec5SDimitry Andric 
2343*0b57cec5SDimitry Andric     // Check if there is enough room for the second operand to appear
2344*0b57cec5SDimitry Andric     // in the first one
2345*0b57cec5SDimitry Andric     APInt BitsToBeInserted =
2346*0b57cec5SDimitry Andric         APInt::getBitsSet(Known.getBitWidth(), DstLSB, DstLSB + Width);
2347*0b57cec5SDimitry Andric 
2348*0b57cec5SDimitry Andric     if ((BitsToBeInserted & ~Known.Zero) != 0)
2349*0b57cec5SDimitry Andric       continue;
2350*0b57cec5SDimitry Andric 
2351*0b57cec5SDimitry Andric     // Set the first operand
2352*0b57cec5SDimitry Andric     uint64_t Imm;
2353*0b57cec5SDimitry Andric     if (isOpcWithIntImmediate(OrOpd1, ISD::AND, Imm) &&
2354*0b57cec5SDimitry Andric         isBitfieldDstMask(Imm, BitsToBeInserted, NumberOfIgnoredHighBits, VT))
2355*0b57cec5SDimitry Andric       // In that case, we can eliminate the AND
2356*0b57cec5SDimitry Andric       Dst = OrOpd1->getOperand(0);
2357*0b57cec5SDimitry Andric     else
2358*0b57cec5SDimitry Andric       // Maybe the AND has been removed by simplify-demanded-bits
2359*0b57cec5SDimitry Andric       // or is useful because it discards more bits
2360*0b57cec5SDimitry Andric       Dst = OrOpd1Val;
2361*0b57cec5SDimitry Andric 
2362*0b57cec5SDimitry Andric     // both parts match
2363*0b57cec5SDimitry Andric     SDLoc DL(N);
2364*0b57cec5SDimitry Andric     SDValue Ops[] = {Dst, Src, CurDAG->getTargetConstant(ImmR, DL, VT),
2365*0b57cec5SDimitry Andric                      CurDAG->getTargetConstant(ImmS, DL, VT)};
2366*0b57cec5SDimitry Andric     unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
2367*0b57cec5SDimitry Andric     CurDAG->SelectNodeTo(N, Opc, VT, Ops);
2368*0b57cec5SDimitry Andric     return true;
2369*0b57cec5SDimitry Andric   }
2370*0b57cec5SDimitry Andric 
2371*0b57cec5SDimitry Andric   // Generate a BFXIL from 'or (and X, Mask0Imm), (and Y, Mask1Imm)' iff
2372*0b57cec5SDimitry Andric   // Mask0Imm and ~Mask1Imm are equivalent and one of the MaskImms is a shifted
2373*0b57cec5SDimitry Andric   // mask (e.g., 0x000ffff0).
2374*0b57cec5SDimitry Andric   uint64_t Mask0Imm, Mask1Imm;
2375*0b57cec5SDimitry Andric   SDValue And0 = N->getOperand(0);
2376*0b57cec5SDimitry Andric   SDValue And1 = N->getOperand(1);
2377*0b57cec5SDimitry Andric   if (And0.hasOneUse() && And1.hasOneUse() &&
2378*0b57cec5SDimitry Andric       isOpcWithIntImmediate(And0.getNode(), ISD::AND, Mask0Imm) &&
2379*0b57cec5SDimitry Andric       isOpcWithIntImmediate(And1.getNode(), ISD::AND, Mask1Imm) &&
2380*0b57cec5SDimitry Andric       APInt(BitWidth, Mask0Imm) == ~APInt(BitWidth, Mask1Imm) &&
2381*0b57cec5SDimitry Andric       (isShiftedMask(Mask0Imm, VT) || isShiftedMask(Mask1Imm, VT))) {
2382*0b57cec5SDimitry Andric 
2383*0b57cec5SDimitry Andric     // ORR is commutative, so canonicalize to the form 'or (and X, Mask0Imm),
2384*0b57cec5SDimitry Andric     // (and Y, Mask1Imm)' where Mask1Imm is the shifted mask masking off the
2385*0b57cec5SDimitry Andric     // bits to be inserted.
2386*0b57cec5SDimitry Andric     if (isShiftedMask(Mask0Imm, VT)) {
2387*0b57cec5SDimitry Andric       std::swap(And0, And1);
2388*0b57cec5SDimitry Andric       std::swap(Mask0Imm, Mask1Imm);
2389*0b57cec5SDimitry Andric     }
2390*0b57cec5SDimitry Andric 
2391*0b57cec5SDimitry Andric     SDValue Src = And1->getOperand(0);
2392*0b57cec5SDimitry Andric     SDValue Dst = And0->getOperand(0);
2393*0b57cec5SDimitry Andric     unsigned LSB = countTrailingZeros(Mask1Imm);
2394*0b57cec5SDimitry Andric     int Width = BitWidth - APInt(BitWidth, Mask0Imm).countPopulation();
2395*0b57cec5SDimitry Andric 
2396*0b57cec5SDimitry Andric     // The BFXIL inserts the low-order bits from a source register, so right
2397*0b57cec5SDimitry Andric     // shift the needed bits into place.
2398*0b57cec5SDimitry Andric     SDLoc DL(N);
2399*0b57cec5SDimitry Andric     unsigned ShiftOpc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
2400*0b57cec5SDimitry Andric     SDNode *LSR = CurDAG->getMachineNode(
2401*0b57cec5SDimitry Andric         ShiftOpc, DL, VT, Src, CurDAG->getTargetConstant(LSB, DL, VT),
2402*0b57cec5SDimitry Andric         CurDAG->getTargetConstant(BitWidth - 1, DL, VT));
2403*0b57cec5SDimitry Andric 
2404*0b57cec5SDimitry Andric     // BFXIL is an alias of BFM, so translate to BFM operands.
2405*0b57cec5SDimitry Andric     unsigned ImmR = (BitWidth - LSB) % BitWidth;
2406*0b57cec5SDimitry Andric     unsigned ImmS = Width - 1;
2407*0b57cec5SDimitry Andric 
2408*0b57cec5SDimitry Andric     // Create the BFXIL instruction.
2409*0b57cec5SDimitry Andric     SDValue Ops[] = {Dst, SDValue(LSR, 0),
2410*0b57cec5SDimitry Andric                      CurDAG->getTargetConstant(ImmR, DL, VT),
2411*0b57cec5SDimitry Andric                      CurDAG->getTargetConstant(ImmS, DL, VT)};
2412*0b57cec5SDimitry Andric     unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
2413*0b57cec5SDimitry Andric     CurDAG->SelectNodeTo(N, Opc, VT, Ops);
2414*0b57cec5SDimitry Andric     return true;
2415*0b57cec5SDimitry Andric   }
2416*0b57cec5SDimitry Andric 
2417*0b57cec5SDimitry Andric   return false;
2418*0b57cec5SDimitry Andric }
2419*0b57cec5SDimitry Andric 
2420*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::tryBitfieldInsertOp(SDNode *N) {
2421*0b57cec5SDimitry Andric   if (N->getOpcode() != ISD::OR)
2422*0b57cec5SDimitry Andric     return false;
2423*0b57cec5SDimitry Andric 
2424*0b57cec5SDimitry Andric   APInt NUsefulBits;
2425*0b57cec5SDimitry Andric   getUsefulBits(SDValue(N, 0), NUsefulBits);
2426*0b57cec5SDimitry Andric 
2427*0b57cec5SDimitry Andric   // If all bits are not useful, just return UNDEF.
2428*0b57cec5SDimitry Andric   if (!NUsefulBits) {
2429*0b57cec5SDimitry Andric     CurDAG->SelectNodeTo(N, TargetOpcode::IMPLICIT_DEF, N->getValueType(0));
2430*0b57cec5SDimitry Andric     return true;
2431*0b57cec5SDimitry Andric   }
2432*0b57cec5SDimitry Andric 
2433*0b57cec5SDimitry Andric   if (tryBitfieldInsertOpFromOr(N, NUsefulBits, CurDAG))
2434*0b57cec5SDimitry Andric     return true;
2435*0b57cec5SDimitry Andric 
2436*0b57cec5SDimitry Andric   return tryBitfieldInsertOpFromOrAndImm(N, CurDAG);
2437*0b57cec5SDimitry Andric }
2438*0b57cec5SDimitry Andric 
2439*0b57cec5SDimitry Andric /// SelectBitfieldInsertInZeroOp - Match a UBFIZ instruction that is the
2440*0b57cec5SDimitry Andric /// equivalent of a left shift by a constant amount followed by an and masking
2441*0b57cec5SDimitry Andric /// out a contiguous set of bits.
2442*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::tryBitfieldInsertInZeroOp(SDNode *N) {
2443*0b57cec5SDimitry Andric   if (N->getOpcode() != ISD::AND)
2444*0b57cec5SDimitry Andric     return false;
2445*0b57cec5SDimitry Andric 
2446*0b57cec5SDimitry Andric   EVT VT = N->getValueType(0);
2447*0b57cec5SDimitry Andric   if (VT != MVT::i32 && VT != MVT::i64)
2448*0b57cec5SDimitry Andric     return false;
2449*0b57cec5SDimitry Andric 
2450*0b57cec5SDimitry Andric   SDValue Op0;
2451*0b57cec5SDimitry Andric   int DstLSB, Width;
2452*0b57cec5SDimitry Andric   if (!isBitfieldPositioningOp(CurDAG, SDValue(N, 0), /*BiggerPattern=*/false,
2453*0b57cec5SDimitry Andric                                Op0, DstLSB, Width))
2454*0b57cec5SDimitry Andric     return false;
2455*0b57cec5SDimitry Andric 
2456*0b57cec5SDimitry Andric   // ImmR is the rotate right amount.
2457*0b57cec5SDimitry Andric   unsigned ImmR = (VT.getSizeInBits() - DstLSB) % VT.getSizeInBits();
2458*0b57cec5SDimitry Andric   // ImmS is the most significant bit of the source to be moved.
2459*0b57cec5SDimitry Andric   unsigned ImmS = Width - 1;
2460*0b57cec5SDimitry Andric 
2461*0b57cec5SDimitry Andric   SDLoc DL(N);
2462*0b57cec5SDimitry Andric   SDValue Ops[] = {Op0, CurDAG->getTargetConstant(ImmR, DL, VT),
2463*0b57cec5SDimitry Andric                    CurDAG->getTargetConstant(ImmS, DL, VT)};
2464*0b57cec5SDimitry Andric   unsigned Opc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
2465*0b57cec5SDimitry Andric   CurDAG->SelectNodeTo(N, Opc, VT, Ops);
2466*0b57cec5SDimitry Andric   return true;
2467*0b57cec5SDimitry Andric }
2468*0b57cec5SDimitry Andric 
2469*0b57cec5SDimitry Andric /// tryShiftAmountMod - Take advantage of built-in mod of shift amount in
2470*0b57cec5SDimitry Andric /// variable shift/rotate instructions.
2471*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::tryShiftAmountMod(SDNode *N) {
2472*0b57cec5SDimitry Andric   EVT VT = N->getValueType(0);
2473*0b57cec5SDimitry Andric 
2474*0b57cec5SDimitry Andric   unsigned Opc;
2475*0b57cec5SDimitry Andric   switch (N->getOpcode()) {
2476*0b57cec5SDimitry Andric   case ISD::ROTR:
2477*0b57cec5SDimitry Andric     Opc = (VT == MVT::i32) ? AArch64::RORVWr : AArch64::RORVXr;
2478*0b57cec5SDimitry Andric     break;
2479*0b57cec5SDimitry Andric   case ISD::SHL:
2480*0b57cec5SDimitry Andric     Opc = (VT == MVT::i32) ? AArch64::LSLVWr : AArch64::LSLVXr;
2481*0b57cec5SDimitry Andric     break;
2482*0b57cec5SDimitry Andric   case ISD::SRL:
2483*0b57cec5SDimitry Andric     Opc = (VT == MVT::i32) ? AArch64::LSRVWr : AArch64::LSRVXr;
2484*0b57cec5SDimitry Andric     break;
2485*0b57cec5SDimitry Andric   case ISD::SRA:
2486*0b57cec5SDimitry Andric     Opc = (VT == MVT::i32) ? AArch64::ASRVWr : AArch64::ASRVXr;
2487*0b57cec5SDimitry Andric     break;
2488*0b57cec5SDimitry Andric   default:
2489*0b57cec5SDimitry Andric     return false;
2490*0b57cec5SDimitry Andric   }
2491*0b57cec5SDimitry Andric 
2492*0b57cec5SDimitry Andric   uint64_t Size;
2493*0b57cec5SDimitry Andric   uint64_t Bits;
2494*0b57cec5SDimitry Andric   if (VT == MVT::i32) {
2495*0b57cec5SDimitry Andric     Bits = 5;
2496*0b57cec5SDimitry Andric     Size = 32;
2497*0b57cec5SDimitry Andric   } else if (VT == MVT::i64) {
2498*0b57cec5SDimitry Andric     Bits = 6;
2499*0b57cec5SDimitry Andric     Size = 64;
2500*0b57cec5SDimitry Andric   } else
2501*0b57cec5SDimitry Andric     return false;
2502*0b57cec5SDimitry Andric 
2503*0b57cec5SDimitry Andric   SDValue ShiftAmt = N->getOperand(1);
2504*0b57cec5SDimitry Andric   SDLoc DL(N);
2505*0b57cec5SDimitry Andric   SDValue NewShiftAmt;
2506*0b57cec5SDimitry Andric 
2507*0b57cec5SDimitry Andric   // Skip over an extend of the shift amount.
2508*0b57cec5SDimitry Andric   if (ShiftAmt->getOpcode() == ISD::ZERO_EXTEND ||
2509*0b57cec5SDimitry Andric       ShiftAmt->getOpcode() == ISD::ANY_EXTEND)
2510*0b57cec5SDimitry Andric     ShiftAmt = ShiftAmt->getOperand(0);
2511*0b57cec5SDimitry Andric 
2512*0b57cec5SDimitry Andric   if (ShiftAmt->getOpcode() == ISD::ADD || ShiftAmt->getOpcode() == ISD::SUB) {
2513*0b57cec5SDimitry Andric     SDValue Add0 = ShiftAmt->getOperand(0);
2514*0b57cec5SDimitry Andric     SDValue Add1 = ShiftAmt->getOperand(1);
2515*0b57cec5SDimitry Andric     uint64_t Add0Imm;
2516*0b57cec5SDimitry Andric     uint64_t Add1Imm;
2517*0b57cec5SDimitry Andric     // If we are shifting by X+/-N where N == 0 mod Size, then just shift by X
2518*0b57cec5SDimitry Andric     // to avoid the ADD/SUB.
2519*0b57cec5SDimitry Andric     if (isIntImmediate(Add1, Add1Imm) && (Add1Imm % Size == 0))
2520*0b57cec5SDimitry Andric       NewShiftAmt = Add0;
2521*0b57cec5SDimitry Andric     // If we are shifting by N-X where N == 0 mod Size, then just shift by -X to
2522*0b57cec5SDimitry Andric     // generate a NEG instead of a SUB of a constant.
2523*0b57cec5SDimitry Andric     else if (ShiftAmt->getOpcode() == ISD::SUB &&
2524*0b57cec5SDimitry Andric              isIntImmediate(Add0, Add0Imm) && Add0Imm != 0 &&
2525*0b57cec5SDimitry Andric              (Add0Imm % Size == 0)) {
2526*0b57cec5SDimitry Andric       unsigned NegOpc;
2527*0b57cec5SDimitry Andric       unsigned ZeroReg;
2528*0b57cec5SDimitry Andric       EVT SubVT = ShiftAmt->getValueType(0);
2529*0b57cec5SDimitry Andric       if (SubVT == MVT::i32) {
2530*0b57cec5SDimitry Andric         NegOpc = AArch64::SUBWrr;
2531*0b57cec5SDimitry Andric         ZeroReg = AArch64::WZR;
2532*0b57cec5SDimitry Andric       } else {
2533*0b57cec5SDimitry Andric         assert(SubVT == MVT::i64);
2534*0b57cec5SDimitry Andric         NegOpc = AArch64::SUBXrr;
2535*0b57cec5SDimitry Andric         ZeroReg = AArch64::XZR;
2536*0b57cec5SDimitry Andric       }
2537*0b57cec5SDimitry Andric       SDValue Zero =
2538*0b57cec5SDimitry Andric           CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, ZeroReg, SubVT);
2539*0b57cec5SDimitry Andric       MachineSDNode *Neg =
2540*0b57cec5SDimitry Andric           CurDAG->getMachineNode(NegOpc, DL, SubVT, Zero, Add1);
2541*0b57cec5SDimitry Andric       NewShiftAmt = SDValue(Neg, 0);
2542*0b57cec5SDimitry Andric     } else
2543*0b57cec5SDimitry Andric       return false;
2544*0b57cec5SDimitry Andric   } else {
2545*0b57cec5SDimitry Andric     // If the shift amount is masked with an AND, check that the mask covers the
2546*0b57cec5SDimitry Andric     // bits that are implicitly ANDed off by the above opcodes and if so, skip
2547*0b57cec5SDimitry Andric     // the AND.
2548*0b57cec5SDimitry Andric     uint64_t MaskImm;
2549*0b57cec5SDimitry Andric     if (!isOpcWithIntImmediate(ShiftAmt.getNode(), ISD::AND, MaskImm))
2550*0b57cec5SDimitry Andric       return false;
2551*0b57cec5SDimitry Andric 
2552*0b57cec5SDimitry Andric     if (countTrailingOnes(MaskImm) < Bits)
2553*0b57cec5SDimitry Andric       return false;
2554*0b57cec5SDimitry Andric 
2555*0b57cec5SDimitry Andric     NewShiftAmt = ShiftAmt->getOperand(0);
2556*0b57cec5SDimitry Andric   }
2557*0b57cec5SDimitry Andric 
2558*0b57cec5SDimitry Andric   // Narrow/widen the shift amount to match the size of the shift operation.
2559*0b57cec5SDimitry Andric   if (VT == MVT::i32)
2560*0b57cec5SDimitry Andric     NewShiftAmt = narrowIfNeeded(CurDAG, NewShiftAmt);
2561*0b57cec5SDimitry Andric   else if (VT == MVT::i64 && NewShiftAmt->getValueType(0) == MVT::i32) {
2562*0b57cec5SDimitry Andric     SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, DL, MVT::i32);
2563*0b57cec5SDimitry Andric     MachineSDNode *Ext = CurDAG->getMachineNode(
2564*0b57cec5SDimitry Andric         AArch64::SUBREG_TO_REG, DL, VT,
2565*0b57cec5SDimitry Andric         CurDAG->getTargetConstant(0, DL, MVT::i64), NewShiftAmt, SubReg);
2566*0b57cec5SDimitry Andric     NewShiftAmt = SDValue(Ext, 0);
2567*0b57cec5SDimitry Andric   }
2568*0b57cec5SDimitry Andric 
2569*0b57cec5SDimitry Andric   SDValue Ops[] = {N->getOperand(0), NewShiftAmt};
2570*0b57cec5SDimitry Andric   CurDAG->SelectNodeTo(N, Opc, VT, Ops);
2571*0b57cec5SDimitry Andric   return true;
2572*0b57cec5SDimitry Andric }
2573*0b57cec5SDimitry Andric 
2574*0b57cec5SDimitry Andric bool
2575*0b57cec5SDimitry Andric AArch64DAGToDAGISel::SelectCVTFixedPosOperand(SDValue N, SDValue &FixedPos,
2576*0b57cec5SDimitry Andric                                               unsigned RegWidth) {
2577*0b57cec5SDimitry Andric   APFloat FVal(0.0);
2578*0b57cec5SDimitry Andric   if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N))
2579*0b57cec5SDimitry Andric     FVal = CN->getValueAPF();
2580*0b57cec5SDimitry Andric   else if (LoadSDNode *LN = dyn_cast<LoadSDNode>(N)) {
2581*0b57cec5SDimitry Andric     // Some otherwise illegal constants are allowed in this case.
2582*0b57cec5SDimitry Andric     if (LN->getOperand(1).getOpcode() != AArch64ISD::ADDlow ||
2583*0b57cec5SDimitry Andric         !isa<ConstantPoolSDNode>(LN->getOperand(1)->getOperand(1)))
2584*0b57cec5SDimitry Andric       return false;
2585*0b57cec5SDimitry Andric 
2586*0b57cec5SDimitry Andric     ConstantPoolSDNode *CN =
2587*0b57cec5SDimitry Andric         dyn_cast<ConstantPoolSDNode>(LN->getOperand(1)->getOperand(1));
2588*0b57cec5SDimitry Andric     FVal = cast<ConstantFP>(CN->getConstVal())->getValueAPF();
2589*0b57cec5SDimitry Andric   } else
2590*0b57cec5SDimitry Andric     return false;
2591*0b57cec5SDimitry Andric 
2592*0b57cec5SDimitry Andric   // An FCVT[SU] instruction performs: convertToInt(Val * 2^fbits) where fbits
2593*0b57cec5SDimitry Andric   // is between 1 and 32 for a destination w-register, or 1 and 64 for an
2594*0b57cec5SDimitry Andric   // x-register.
2595*0b57cec5SDimitry Andric   //
2596*0b57cec5SDimitry Andric   // By this stage, we've detected (fp_to_[su]int (fmul Val, THIS_NODE)) so we
2597*0b57cec5SDimitry Andric   // want THIS_NODE to be 2^fbits. This is much easier to deal with using
2598*0b57cec5SDimitry Andric   // integers.
2599*0b57cec5SDimitry Andric   bool IsExact;
2600*0b57cec5SDimitry Andric 
2601*0b57cec5SDimitry Andric   // fbits is between 1 and 64 in the worst-case, which means the fmul
2602*0b57cec5SDimitry Andric   // could have 2^64 as an actual operand. Need 65 bits of precision.
2603*0b57cec5SDimitry Andric   APSInt IntVal(65, true);
2604*0b57cec5SDimitry Andric   FVal.convertToInteger(IntVal, APFloat::rmTowardZero, &IsExact);
2605*0b57cec5SDimitry Andric 
2606*0b57cec5SDimitry Andric   // N.b. isPowerOf2 also checks for > 0.
2607*0b57cec5SDimitry Andric   if (!IsExact || !IntVal.isPowerOf2()) return false;
2608*0b57cec5SDimitry Andric   unsigned FBits = IntVal.logBase2();
2609*0b57cec5SDimitry Andric 
2610*0b57cec5SDimitry Andric   // Checks above should have guaranteed that we haven't lost information in
2611*0b57cec5SDimitry Andric   // finding FBits, but it must still be in range.
2612*0b57cec5SDimitry Andric   if (FBits == 0 || FBits > RegWidth) return false;
2613*0b57cec5SDimitry Andric 
2614*0b57cec5SDimitry Andric   FixedPos = CurDAG->getTargetConstant(FBits, SDLoc(N), MVT::i32);
2615*0b57cec5SDimitry Andric   return true;
2616*0b57cec5SDimitry Andric }
2617*0b57cec5SDimitry Andric 
2618*0b57cec5SDimitry Andric // Inspects a register string of the form o0:op1:CRn:CRm:op2 gets the fields
2619*0b57cec5SDimitry Andric // of the string and obtains the integer values from them and combines these
2620*0b57cec5SDimitry Andric // into a single value to be used in the MRS/MSR instruction.
2621*0b57cec5SDimitry Andric static int getIntOperandFromRegisterString(StringRef RegString) {
2622*0b57cec5SDimitry Andric   SmallVector<StringRef, 5> Fields;
2623*0b57cec5SDimitry Andric   RegString.split(Fields, ':');
2624*0b57cec5SDimitry Andric 
2625*0b57cec5SDimitry Andric   if (Fields.size() == 1)
2626*0b57cec5SDimitry Andric     return -1;
2627*0b57cec5SDimitry Andric 
2628*0b57cec5SDimitry Andric   assert(Fields.size() == 5
2629*0b57cec5SDimitry Andric             && "Invalid number of fields in read register string");
2630*0b57cec5SDimitry Andric 
2631*0b57cec5SDimitry Andric   SmallVector<int, 5> Ops;
2632*0b57cec5SDimitry Andric   bool AllIntFields = true;
2633*0b57cec5SDimitry Andric 
2634*0b57cec5SDimitry Andric   for (StringRef Field : Fields) {
2635*0b57cec5SDimitry Andric     unsigned IntField;
2636*0b57cec5SDimitry Andric     AllIntFields &= !Field.getAsInteger(10, IntField);
2637*0b57cec5SDimitry Andric     Ops.push_back(IntField);
2638*0b57cec5SDimitry Andric   }
2639*0b57cec5SDimitry Andric 
2640*0b57cec5SDimitry Andric   assert(AllIntFields &&
2641*0b57cec5SDimitry Andric           "Unexpected non-integer value in special register string.");
2642*0b57cec5SDimitry Andric 
2643*0b57cec5SDimitry Andric   // Need to combine the integer fields of the string into a single value
2644*0b57cec5SDimitry Andric   // based on the bit encoding of MRS/MSR instruction.
2645*0b57cec5SDimitry Andric   return (Ops[0] << 14) | (Ops[1] << 11) | (Ops[2] << 7) |
2646*0b57cec5SDimitry Andric          (Ops[3] << 3) | (Ops[4]);
2647*0b57cec5SDimitry Andric }
2648*0b57cec5SDimitry Andric 
2649*0b57cec5SDimitry Andric // Lower the read_register intrinsic to an MRS instruction node if the special
2650*0b57cec5SDimitry Andric // register string argument is either of the form detailed in the ALCE (the
2651*0b57cec5SDimitry Andric // form described in getIntOperandsFromRegsterString) or is a named register
2652*0b57cec5SDimitry Andric // known by the MRS SysReg mapper.
2653*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::tryReadRegister(SDNode *N) {
2654*0b57cec5SDimitry Andric   const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
2655*0b57cec5SDimitry Andric   const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
2656*0b57cec5SDimitry Andric   SDLoc DL(N);
2657*0b57cec5SDimitry Andric 
2658*0b57cec5SDimitry Andric   int Reg = getIntOperandFromRegisterString(RegString->getString());
2659*0b57cec5SDimitry Andric   if (Reg != -1) {
2660*0b57cec5SDimitry Andric     ReplaceNode(N, CurDAG->getMachineNode(
2661*0b57cec5SDimitry Andric                        AArch64::MRS, DL, N->getSimpleValueType(0), MVT::Other,
2662*0b57cec5SDimitry Andric                        CurDAG->getTargetConstant(Reg, DL, MVT::i32),
2663*0b57cec5SDimitry Andric                        N->getOperand(0)));
2664*0b57cec5SDimitry Andric     return true;
2665*0b57cec5SDimitry Andric   }
2666*0b57cec5SDimitry Andric 
2667*0b57cec5SDimitry Andric   // Use the sysreg mapper to map the remaining possible strings to the
2668*0b57cec5SDimitry Andric   // value for the register to be used for the instruction operand.
2669*0b57cec5SDimitry Andric   auto TheReg = AArch64SysReg::lookupSysRegByName(RegString->getString());
2670*0b57cec5SDimitry Andric   if (TheReg && TheReg->Readable &&
2671*0b57cec5SDimitry Andric       TheReg->haveFeatures(Subtarget->getFeatureBits()))
2672*0b57cec5SDimitry Andric     Reg = TheReg->Encoding;
2673*0b57cec5SDimitry Andric   else
2674*0b57cec5SDimitry Andric     Reg = AArch64SysReg::parseGenericRegister(RegString->getString());
2675*0b57cec5SDimitry Andric 
2676*0b57cec5SDimitry Andric   if (Reg != -1) {
2677*0b57cec5SDimitry Andric     ReplaceNode(N, CurDAG->getMachineNode(
2678*0b57cec5SDimitry Andric                        AArch64::MRS, DL, N->getSimpleValueType(0), MVT::Other,
2679*0b57cec5SDimitry Andric                        CurDAG->getTargetConstant(Reg, DL, MVT::i32),
2680*0b57cec5SDimitry Andric                        N->getOperand(0)));
2681*0b57cec5SDimitry Andric     return true;
2682*0b57cec5SDimitry Andric   }
2683*0b57cec5SDimitry Andric 
2684*0b57cec5SDimitry Andric   if (RegString->getString() == "pc") {
2685*0b57cec5SDimitry Andric     ReplaceNode(N, CurDAG->getMachineNode(
2686*0b57cec5SDimitry Andric                        AArch64::ADR, DL, N->getSimpleValueType(0), MVT::Other,
2687*0b57cec5SDimitry Andric                        CurDAG->getTargetConstant(0, DL, MVT::i32),
2688*0b57cec5SDimitry Andric                        N->getOperand(0)));
2689*0b57cec5SDimitry Andric     return true;
2690*0b57cec5SDimitry Andric   }
2691*0b57cec5SDimitry Andric 
2692*0b57cec5SDimitry Andric   return false;
2693*0b57cec5SDimitry Andric }
2694*0b57cec5SDimitry Andric 
2695*0b57cec5SDimitry Andric // Lower the write_register intrinsic to an MSR instruction node if the special
2696*0b57cec5SDimitry Andric // register string argument is either of the form detailed in the ALCE (the
2697*0b57cec5SDimitry Andric // form described in getIntOperandsFromRegsterString) or is a named register
2698*0b57cec5SDimitry Andric // known by the MSR SysReg mapper.
2699*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::tryWriteRegister(SDNode *N) {
2700*0b57cec5SDimitry Andric   const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
2701*0b57cec5SDimitry Andric   const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
2702*0b57cec5SDimitry Andric   SDLoc DL(N);
2703*0b57cec5SDimitry Andric 
2704*0b57cec5SDimitry Andric   int Reg = getIntOperandFromRegisterString(RegString->getString());
2705*0b57cec5SDimitry Andric   if (Reg != -1) {
2706*0b57cec5SDimitry Andric     ReplaceNode(
2707*0b57cec5SDimitry Andric         N, CurDAG->getMachineNode(AArch64::MSR, DL, MVT::Other,
2708*0b57cec5SDimitry Andric                                   CurDAG->getTargetConstant(Reg, DL, MVT::i32),
2709*0b57cec5SDimitry Andric                                   N->getOperand(2), N->getOperand(0)));
2710*0b57cec5SDimitry Andric     return true;
2711*0b57cec5SDimitry Andric   }
2712*0b57cec5SDimitry Andric 
2713*0b57cec5SDimitry Andric   // Check if the register was one of those allowed as the pstatefield value in
2714*0b57cec5SDimitry Andric   // the MSR (immediate) instruction. To accept the values allowed in the
2715*0b57cec5SDimitry Andric   // pstatefield for the MSR (immediate) instruction, we also require that an
2716*0b57cec5SDimitry Andric   // immediate value has been provided as an argument, we know that this is
2717*0b57cec5SDimitry Andric   // the case as it has been ensured by semantic checking.
2718*0b57cec5SDimitry Andric   auto PMapper = AArch64PState::lookupPStateByName(RegString->getString());
2719*0b57cec5SDimitry Andric   if (PMapper) {
2720*0b57cec5SDimitry Andric     assert (isa<ConstantSDNode>(N->getOperand(2))
2721*0b57cec5SDimitry Andric               && "Expected a constant integer expression.");
2722*0b57cec5SDimitry Andric     unsigned Reg = PMapper->Encoding;
2723*0b57cec5SDimitry Andric     uint64_t Immed = cast<ConstantSDNode>(N->getOperand(2))->getZExtValue();
2724*0b57cec5SDimitry Andric     unsigned State;
2725*0b57cec5SDimitry Andric     if (Reg == AArch64PState::PAN || Reg == AArch64PState::UAO || Reg == AArch64PState::SSBS) {
2726*0b57cec5SDimitry Andric       assert(Immed < 2 && "Bad imm");
2727*0b57cec5SDimitry Andric       State = AArch64::MSRpstateImm1;
2728*0b57cec5SDimitry Andric     } else {
2729*0b57cec5SDimitry Andric       assert(Immed < 16 && "Bad imm");
2730*0b57cec5SDimitry Andric       State = AArch64::MSRpstateImm4;
2731*0b57cec5SDimitry Andric     }
2732*0b57cec5SDimitry Andric     ReplaceNode(N, CurDAG->getMachineNode(
2733*0b57cec5SDimitry Andric                        State, DL, MVT::Other,
2734*0b57cec5SDimitry Andric                        CurDAG->getTargetConstant(Reg, DL, MVT::i32),
2735*0b57cec5SDimitry Andric                        CurDAG->getTargetConstant(Immed, DL, MVT::i16),
2736*0b57cec5SDimitry Andric                        N->getOperand(0)));
2737*0b57cec5SDimitry Andric     return true;
2738*0b57cec5SDimitry Andric   }
2739*0b57cec5SDimitry Andric 
2740*0b57cec5SDimitry Andric   // Use the sysreg mapper to attempt to map the remaining possible strings
2741*0b57cec5SDimitry Andric   // to the value for the register to be used for the MSR (register)
2742*0b57cec5SDimitry Andric   // instruction operand.
2743*0b57cec5SDimitry Andric   auto TheReg = AArch64SysReg::lookupSysRegByName(RegString->getString());
2744*0b57cec5SDimitry Andric   if (TheReg && TheReg->Writeable &&
2745*0b57cec5SDimitry Andric       TheReg->haveFeatures(Subtarget->getFeatureBits()))
2746*0b57cec5SDimitry Andric     Reg = TheReg->Encoding;
2747*0b57cec5SDimitry Andric   else
2748*0b57cec5SDimitry Andric     Reg = AArch64SysReg::parseGenericRegister(RegString->getString());
2749*0b57cec5SDimitry Andric   if (Reg != -1) {
2750*0b57cec5SDimitry Andric     ReplaceNode(N, CurDAG->getMachineNode(
2751*0b57cec5SDimitry Andric                        AArch64::MSR, DL, MVT::Other,
2752*0b57cec5SDimitry Andric                        CurDAG->getTargetConstant(Reg, DL, MVT::i32),
2753*0b57cec5SDimitry Andric                        N->getOperand(2), N->getOperand(0)));
2754*0b57cec5SDimitry Andric     return true;
2755*0b57cec5SDimitry Andric   }
2756*0b57cec5SDimitry Andric 
2757*0b57cec5SDimitry Andric   return false;
2758*0b57cec5SDimitry Andric }
2759*0b57cec5SDimitry Andric 
2760*0b57cec5SDimitry Andric /// We've got special pseudo-instructions for these
2761*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::SelectCMP_SWAP(SDNode *N) {
2762*0b57cec5SDimitry Andric   unsigned Opcode;
2763*0b57cec5SDimitry Andric   EVT MemTy = cast<MemSDNode>(N)->getMemoryVT();
2764*0b57cec5SDimitry Andric 
2765*0b57cec5SDimitry Andric   // Leave IR for LSE if subtarget supports it.
2766*0b57cec5SDimitry Andric   if (Subtarget->hasLSE()) return false;
2767*0b57cec5SDimitry Andric 
2768*0b57cec5SDimitry Andric   if (MemTy == MVT::i8)
2769*0b57cec5SDimitry Andric     Opcode = AArch64::CMP_SWAP_8;
2770*0b57cec5SDimitry Andric   else if (MemTy == MVT::i16)
2771*0b57cec5SDimitry Andric     Opcode = AArch64::CMP_SWAP_16;
2772*0b57cec5SDimitry Andric   else if (MemTy == MVT::i32)
2773*0b57cec5SDimitry Andric     Opcode = AArch64::CMP_SWAP_32;
2774*0b57cec5SDimitry Andric   else if (MemTy == MVT::i64)
2775*0b57cec5SDimitry Andric     Opcode = AArch64::CMP_SWAP_64;
2776*0b57cec5SDimitry Andric   else
2777*0b57cec5SDimitry Andric     llvm_unreachable("Unknown AtomicCmpSwap type");
2778*0b57cec5SDimitry Andric 
2779*0b57cec5SDimitry Andric   MVT RegTy = MemTy == MVT::i64 ? MVT::i64 : MVT::i32;
2780*0b57cec5SDimitry Andric   SDValue Ops[] = {N->getOperand(1), N->getOperand(2), N->getOperand(3),
2781*0b57cec5SDimitry Andric                    N->getOperand(0)};
2782*0b57cec5SDimitry Andric   SDNode *CmpSwap = CurDAG->getMachineNode(
2783*0b57cec5SDimitry Andric       Opcode, SDLoc(N),
2784*0b57cec5SDimitry Andric       CurDAG->getVTList(RegTy, MVT::i32, MVT::Other), Ops);
2785*0b57cec5SDimitry Andric 
2786*0b57cec5SDimitry Andric   MachineMemOperand *MemOp = cast<MemSDNode>(N)->getMemOperand();
2787*0b57cec5SDimitry Andric   CurDAG->setNodeMemRefs(cast<MachineSDNode>(CmpSwap), {MemOp});
2788*0b57cec5SDimitry Andric 
2789*0b57cec5SDimitry Andric   ReplaceUses(SDValue(N, 0), SDValue(CmpSwap, 0));
2790*0b57cec5SDimitry Andric   ReplaceUses(SDValue(N, 1), SDValue(CmpSwap, 2));
2791*0b57cec5SDimitry Andric   CurDAG->RemoveDeadNode(N);
2792*0b57cec5SDimitry Andric 
2793*0b57cec5SDimitry Andric   return true;
2794*0b57cec5SDimitry Andric }
2795*0b57cec5SDimitry Andric 
2796*0b57cec5SDimitry Andric bool AArch64DAGToDAGISel::trySelectStackSlotTagP(SDNode *N) {
2797*0b57cec5SDimitry Andric   // tagp(FrameIndex, IRGstack, tag_offset):
2798*0b57cec5SDimitry Andric   // since the offset between FrameIndex and IRGstack is a compile-time
2799*0b57cec5SDimitry Andric   // constant, this can be lowered to a single ADDG instruction.
2800*0b57cec5SDimitry Andric   if (!(isa<FrameIndexSDNode>(N->getOperand(1)))) {
2801*0b57cec5SDimitry Andric     return false;
2802*0b57cec5SDimitry Andric   }
2803*0b57cec5SDimitry Andric 
2804*0b57cec5SDimitry Andric   SDValue IRG_SP = N->getOperand(2);
2805*0b57cec5SDimitry Andric   if (IRG_SP->getOpcode() != ISD::INTRINSIC_W_CHAIN ||
2806*0b57cec5SDimitry Andric       cast<ConstantSDNode>(IRG_SP->getOperand(1))->getZExtValue() !=
2807*0b57cec5SDimitry Andric           Intrinsic::aarch64_irg_sp) {
2808*0b57cec5SDimitry Andric     return false;
2809*0b57cec5SDimitry Andric   }
2810*0b57cec5SDimitry Andric 
2811*0b57cec5SDimitry Andric   const TargetLowering *TLI = getTargetLowering();
2812*0b57cec5SDimitry Andric   SDLoc DL(N);
2813*0b57cec5SDimitry Andric   int FI = cast<FrameIndexSDNode>(N->getOperand(1))->getIndex();
2814*0b57cec5SDimitry Andric   SDValue FiOp = CurDAG->getTargetFrameIndex(
2815*0b57cec5SDimitry Andric       FI, TLI->getPointerTy(CurDAG->getDataLayout()));
2816*0b57cec5SDimitry Andric   int TagOffset = cast<ConstantSDNode>(N->getOperand(3))->getZExtValue();
2817*0b57cec5SDimitry Andric 
2818*0b57cec5SDimitry Andric   SDNode *Out = CurDAG->getMachineNode(
2819*0b57cec5SDimitry Andric       AArch64::TAGPstack, DL, MVT::i64,
2820*0b57cec5SDimitry Andric       {FiOp, CurDAG->getTargetConstant(0, DL, MVT::i64), N->getOperand(2),
2821*0b57cec5SDimitry Andric        CurDAG->getTargetConstant(TagOffset, DL, MVT::i64)});
2822*0b57cec5SDimitry Andric   ReplaceNode(N, Out);
2823*0b57cec5SDimitry Andric   return true;
2824*0b57cec5SDimitry Andric }
2825*0b57cec5SDimitry Andric 
2826*0b57cec5SDimitry Andric void AArch64DAGToDAGISel::SelectTagP(SDNode *N) {
2827*0b57cec5SDimitry Andric   assert(isa<ConstantSDNode>(N->getOperand(3)) &&
2828*0b57cec5SDimitry Andric          "llvm.aarch64.tagp third argument must be an immediate");
2829*0b57cec5SDimitry Andric   if (trySelectStackSlotTagP(N))
2830*0b57cec5SDimitry Andric     return;
2831*0b57cec5SDimitry Andric   // FIXME: above applies in any case when offset between Op1 and Op2 is a
2832*0b57cec5SDimitry Andric   // compile-time constant, not just for stack allocations.
2833*0b57cec5SDimitry Andric 
2834*0b57cec5SDimitry Andric   // General case for unrelated pointers in Op1 and Op2.
2835*0b57cec5SDimitry Andric   SDLoc DL(N);
2836*0b57cec5SDimitry Andric   int TagOffset = cast<ConstantSDNode>(N->getOperand(3))->getZExtValue();
2837*0b57cec5SDimitry Andric   SDNode *N1 = CurDAG->getMachineNode(AArch64::SUBP, DL, MVT::i64,
2838*0b57cec5SDimitry Andric                                       {N->getOperand(1), N->getOperand(2)});
2839*0b57cec5SDimitry Andric   SDNode *N2 = CurDAG->getMachineNode(AArch64::ADDXrr, DL, MVT::i64,
2840*0b57cec5SDimitry Andric                                       {SDValue(N1, 0), N->getOperand(2)});
2841*0b57cec5SDimitry Andric   SDNode *N3 = CurDAG->getMachineNode(
2842*0b57cec5SDimitry Andric       AArch64::ADDG, DL, MVT::i64,
2843*0b57cec5SDimitry Andric       {SDValue(N2, 0), CurDAG->getTargetConstant(0, DL, MVT::i64),
2844*0b57cec5SDimitry Andric        CurDAG->getTargetConstant(TagOffset, DL, MVT::i64)});
2845*0b57cec5SDimitry Andric   ReplaceNode(N, N3);
2846*0b57cec5SDimitry Andric }
2847*0b57cec5SDimitry Andric 
2848*0b57cec5SDimitry Andric void AArch64DAGToDAGISel::Select(SDNode *Node) {
2849*0b57cec5SDimitry Andric   // If we have a custom node, we already have selected!
2850*0b57cec5SDimitry Andric   if (Node->isMachineOpcode()) {
2851*0b57cec5SDimitry Andric     LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
2852*0b57cec5SDimitry Andric     Node->setNodeId(-1);
2853*0b57cec5SDimitry Andric     return;
2854*0b57cec5SDimitry Andric   }
2855*0b57cec5SDimitry Andric 
2856*0b57cec5SDimitry Andric   // Few custom selection stuff.
2857*0b57cec5SDimitry Andric   EVT VT = Node->getValueType(0);
2858*0b57cec5SDimitry Andric 
2859*0b57cec5SDimitry Andric   switch (Node->getOpcode()) {
2860*0b57cec5SDimitry Andric   default:
2861*0b57cec5SDimitry Andric     break;
2862*0b57cec5SDimitry Andric 
2863*0b57cec5SDimitry Andric   case ISD::ATOMIC_CMP_SWAP:
2864*0b57cec5SDimitry Andric     if (SelectCMP_SWAP(Node))
2865*0b57cec5SDimitry Andric       return;
2866*0b57cec5SDimitry Andric     break;
2867*0b57cec5SDimitry Andric 
2868*0b57cec5SDimitry Andric   case ISD::READ_REGISTER:
2869*0b57cec5SDimitry Andric     if (tryReadRegister(Node))
2870*0b57cec5SDimitry Andric       return;
2871*0b57cec5SDimitry Andric     break;
2872*0b57cec5SDimitry Andric 
2873*0b57cec5SDimitry Andric   case ISD::WRITE_REGISTER:
2874*0b57cec5SDimitry Andric     if (tryWriteRegister(Node))
2875*0b57cec5SDimitry Andric       return;
2876*0b57cec5SDimitry Andric     break;
2877*0b57cec5SDimitry Andric 
2878*0b57cec5SDimitry Andric   case ISD::ADD:
2879*0b57cec5SDimitry Andric     if (tryMLAV64LaneV128(Node))
2880*0b57cec5SDimitry Andric       return;
2881*0b57cec5SDimitry Andric     break;
2882*0b57cec5SDimitry Andric 
2883*0b57cec5SDimitry Andric   case ISD::LOAD: {
2884*0b57cec5SDimitry Andric     // Try to select as an indexed load. Fall through to normal processing
2885*0b57cec5SDimitry Andric     // if we can't.
2886*0b57cec5SDimitry Andric     if (tryIndexedLoad(Node))
2887*0b57cec5SDimitry Andric       return;
2888*0b57cec5SDimitry Andric     break;
2889*0b57cec5SDimitry Andric   }
2890*0b57cec5SDimitry Andric 
2891*0b57cec5SDimitry Andric   case ISD::SRL:
2892*0b57cec5SDimitry Andric   case ISD::AND:
2893*0b57cec5SDimitry Andric   case ISD::SRA:
2894*0b57cec5SDimitry Andric   case ISD::SIGN_EXTEND_INREG:
2895*0b57cec5SDimitry Andric     if (tryBitfieldExtractOp(Node))
2896*0b57cec5SDimitry Andric       return;
2897*0b57cec5SDimitry Andric     if (tryBitfieldInsertInZeroOp(Node))
2898*0b57cec5SDimitry Andric       return;
2899*0b57cec5SDimitry Andric     LLVM_FALLTHROUGH;
2900*0b57cec5SDimitry Andric   case ISD::ROTR:
2901*0b57cec5SDimitry Andric   case ISD::SHL:
2902*0b57cec5SDimitry Andric     if (tryShiftAmountMod(Node))
2903*0b57cec5SDimitry Andric       return;
2904*0b57cec5SDimitry Andric     break;
2905*0b57cec5SDimitry Andric 
2906*0b57cec5SDimitry Andric   case ISD::SIGN_EXTEND:
2907*0b57cec5SDimitry Andric     if (tryBitfieldExtractOpFromSExt(Node))
2908*0b57cec5SDimitry Andric       return;
2909*0b57cec5SDimitry Andric     break;
2910*0b57cec5SDimitry Andric 
2911*0b57cec5SDimitry Andric   case ISD::OR:
2912*0b57cec5SDimitry Andric     if (tryBitfieldInsertOp(Node))
2913*0b57cec5SDimitry Andric       return;
2914*0b57cec5SDimitry Andric     break;
2915*0b57cec5SDimitry Andric 
2916*0b57cec5SDimitry Andric   case ISD::EXTRACT_VECTOR_ELT: {
2917*0b57cec5SDimitry Andric     // Extracting lane zero is a special case where we can just use a plain
2918*0b57cec5SDimitry Andric     // EXTRACT_SUBREG instruction, which will become FMOV. This is easier for
2919*0b57cec5SDimitry Andric     // the rest of the compiler, especially the register allocator and copyi
2920*0b57cec5SDimitry Andric     // propagation, to reason about, so is preferred when it's possible to
2921*0b57cec5SDimitry Andric     // use it.
2922*0b57cec5SDimitry Andric     ConstantSDNode *LaneNode = cast<ConstantSDNode>(Node->getOperand(1));
2923*0b57cec5SDimitry Andric     // Bail and use the default Select() for non-zero lanes.
2924*0b57cec5SDimitry Andric     if (LaneNode->getZExtValue() != 0)
2925*0b57cec5SDimitry Andric       break;
2926*0b57cec5SDimitry Andric     // If the element type is not the same as the result type, likewise
2927*0b57cec5SDimitry Andric     // bail and use the default Select(), as there's more to do than just
2928*0b57cec5SDimitry Andric     // a cross-class COPY. This catches extracts of i8 and i16 elements
2929*0b57cec5SDimitry Andric     // since they will need an explicit zext.
2930*0b57cec5SDimitry Andric     if (VT != Node->getOperand(0).getValueType().getVectorElementType())
2931*0b57cec5SDimitry Andric       break;
2932*0b57cec5SDimitry Andric     unsigned SubReg;
2933*0b57cec5SDimitry Andric     switch (Node->getOperand(0)
2934*0b57cec5SDimitry Andric                 .getValueType()
2935*0b57cec5SDimitry Andric                 .getVectorElementType()
2936*0b57cec5SDimitry Andric                 .getSizeInBits()) {
2937*0b57cec5SDimitry Andric     default:
2938*0b57cec5SDimitry Andric       llvm_unreachable("Unexpected vector element type!");
2939*0b57cec5SDimitry Andric     case 64:
2940*0b57cec5SDimitry Andric       SubReg = AArch64::dsub;
2941*0b57cec5SDimitry Andric       break;
2942*0b57cec5SDimitry Andric     case 32:
2943*0b57cec5SDimitry Andric       SubReg = AArch64::ssub;
2944*0b57cec5SDimitry Andric       break;
2945*0b57cec5SDimitry Andric     case 16:
2946*0b57cec5SDimitry Andric       SubReg = AArch64::hsub;
2947*0b57cec5SDimitry Andric       break;
2948*0b57cec5SDimitry Andric     case 8:
2949*0b57cec5SDimitry Andric       llvm_unreachable("unexpected zext-requiring extract element!");
2950*0b57cec5SDimitry Andric     }
2951*0b57cec5SDimitry Andric     SDValue Extract = CurDAG->getTargetExtractSubreg(SubReg, SDLoc(Node), VT,
2952*0b57cec5SDimitry Andric                                                      Node->getOperand(0));
2953*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "ISEL: Custom selection!\n=> ");
2954*0b57cec5SDimitry Andric     LLVM_DEBUG(Extract->dumpr(CurDAG));
2955*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "\n");
2956*0b57cec5SDimitry Andric     ReplaceNode(Node, Extract.getNode());
2957*0b57cec5SDimitry Andric     return;
2958*0b57cec5SDimitry Andric   }
2959*0b57cec5SDimitry Andric   case ISD::Constant: {
2960*0b57cec5SDimitry Andric     // Materialize zero constants as copies from WZR/XZR.  This allows
2961*0b57cec5SDimitry Andric     // the coalescer to propagate these into other instructions.
2962*0b57cec5SDimitry Andric     ConstantSDNode *ConstNode = cast<ConstantSDNode>(Node);
2963*0b57cec5SDimitry Andric     if (ConstNode->isNullValue()) {
2964*0b57cec5SDimitry Andric       if (VT == MVT::i32) {
2965*0b57cec5SDimitry Andric         SDValue New = CurDAG->getCopyFromReg(
2966*0b57cec5SDimitry Andric             CurDAG->getEntryNode(), SDLoc(Node), AArch64::WZR, MVT::i32);
2967*0b57cec5SDimitry Andric         ReplaceNode(Node, New.getNode());
2968*0b57cec5SDimitry Andric         return;
2969*0b57cec5SDimitry Andric       } else if (VT == MVT::i64) {
2970*0b57cec5SDimitry Andric         SDValue New = CurDAG->getCopyFromReg(
2971*0b57cec5SDimitry Andric             CurDAG->getEntryNode(), SDLoc(Node), AArch64::XZR, MVT::i64);
2972*0b57cec5SDimitry Andric         ReplaceNode(Node, New.getNode());
2973*0b57cec5SDimitry Andric         return;
2974*0b57cec5SDimitry Andric       }
2975*0b57cec5SDimitry Andric     }
2976*0b57cec5SDimitry Andric     break;
2977*0b57cec5SDimitry Andric   }
2978*0b57cec5SDimitry Andric 
2979*0b57cec5SDimitry Andric   case ISD::FrameIndex: {
2980*0b57cec5SDimitry Andric     // Selects to ADDXri FI, 0 which in turn will become ADDXri SP, imm.
2981*0b57cec5SDimitry Andric     int FI = cast<FrameIndexSDNode>(Node)->getIndex();
2982*0b57cec5SDimitry Andric     unsigned Shifter = AArch64_AM::getShifterImm(AArch64_AM::LSL, 0);
2983*0b57cec5SDimitry Andric     const TargetLowering *TLI = getTargetLowering();
2984*0b57cec5SDimitry Andric     SDValue TFI = CurDAG->getTargetFrameIndex(
2985*0b57cec5SDimitry Andric         FI, TLI->getPointerTy(CurDAG->getDataLayout()));
2986*0b57cec5SDimitry Andric     SDLoc DL(Node);
2987*0b57cec5SDimitry Andric     SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, DL, MVT::i32),
2988*0b57cec5SDimitry Andric                       CurDAG->getTargetConstant(Shifter, DL, MVT::i32) };
2989*0b57cec5SDimitry Andric     CurDAG->SelectNodeTo(Node, AArch64::ADDXri, MVT::i64, Ops);
2990*0b57cec5SDimitry Andric     return;
2991*0b57cec5SDimitry Andric   }
2992*0b57cec5SDimitry Andric   case ISD::INTRINSIC_W_CHAIN: {
2993*0b57cec5SDimitry Andric     unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
2994*0b57cec5SDimitry Andric     switch (IntNo) {
2995*0b57cec5SDimitry Andric     default:
2996*0b57cec5SDimitry Andric       break;
2997*0b57cec5SDimitry Andric     case Intrinsic::aarch64_ldaxp:
2998*0b57cec5SDimitry Andric     case Intrinsic::aarch64_ldxp: {
2999*0b57cec5SDimitry Andric       unsigned Op =
3000*0b57cec5SDimitry Andric           IntNo == Intrinsic::aarch64_ldaxp ? AArch64::LDAXPX : AArch64::LDXPX;
3001*0b57cec5SDimitry Andric       SDValue MemAddr = Node->getOperand(2);
3002*0b57cec5SDimitry Andric       SDLoc DL(Node);
3003*0b57cec5SDimitry Andric       SDValue Chain = Node->getOperand(0);
3004*0b57cec5SDimitry Andric 
3005*0b57cec5SDimitry Andric       SDNode *Ld = CurDAG->getMachineNode(Op, DL, MVT::i64, MVT::i64,
3006*0b57cec5SDimitry Andric                                           MVT::Other, MemAddr, Chain);
3007*0b57cec5SDimitry Andric 
3008*0b57cec5SDimitry Andric       // Transfer memoperands.
3009*0b57cec5SDimitry Andric       MachineMemOperand *MemOp =
3010*0b57cec5SDimitry Andric           cast<MemIntrinsicSDNode>(Node)->getMemOperand();
3011*0b57cec5SDimitry Andric       CurDAG->setNodeMemRefs(cast<MachineSDNode>(Ld), {MemOp});
3012*0b57cec5SDimitry Andric       ReplaceNode(Node, Ld);
3013*0b57cec5SDimitry Andric       return;
3014*0b57cec5SDimitry Andric     }
3015*0b57cec5SDimitry Andric     case Intrinsic::aarch64_stlxp:
3016*0b57cec5SDimitry Andric     case Intrinsic::aarch64_stxp: {
3017*0b57cec5SDimitry Andric       unsigned Op =
3018*0b57cec5SDimitry Andric           IntNo == Intrinsic::aarch64_stlxp ? AArch64::STLXPX : AArch64::STXPX;
3019*0b57cec5SDimitry Andric       SDLoc DL(Node);
3020*0b57cec5SDimitry Andric       SDValue Chain = Node->getOperand(0);
3021*0b57cec5SDimitry Andric       SDValue ValLo = Node->getOperand(2);
3022*0b57cec5SDimitry Andric       SDValue ValHi = Node->getOperand(3);
3023*0b57cec5SDimitry Andric       SDValue MemAddr = Node->getOperand(4);
3024*0b57cec5SDimitry Andric 
3025*0b57cec5SDimitry Andric       // Place arguments in the right order.
3026*0b57cec5SDimitry Andric       SDValue Ops[] = {ValLo, ValHi, MemAddr, Chain};
3027*0b57cec5SDimitry Andric 
3028*0b57cec5SDimitry Andric       SDNode *St = CurDAG->getMachineNode(Op, DL, MVT::i32, MVT::Other, Ops);
3029*0b57cec5SDimitry Andric       // Transfer memoperands.
3030*0b57cec5SDimitry Andric       MachineMemOperand *MemOp =
3031*0b57cec5SDimitry Andric           cast<MemIntrinsicSDNode>(Node)->getMemOperand();
3032*0b57cec5SDimitry Andric       CurDAG->setNodeMemRefs(cast<MachineSDNode>(St), {MemOp});
3033*0b57cec5SDimitry Andric 
3034*0b57cec5SDimitry Andric       ReplaceNode(Node, St);
3035*0b57cec5SDimitry Andric       return;
3036*0b57cec5SDimitry Andric     }
3037*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_ld1x2:
3038*0b57cec5SDimitry Andric       if (VT == MVT::v8i8) {
3039*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD1Twov8b, AArch64::dsub0);
3040*0b57cec5SDimitry Andric         return;
3041*0b57cec5SDimitry Andric       } else if (VT == MVT::v16i8) {
3042*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD1Twov16b, AArch64::qsub0);
3043*0b57cec5SDimitry Andric         return;
3044*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3045*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD1Twov4h, AArch64::dsub0);
3046*0b57cec5SDimitry Andric         return;
3047*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3048*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD1Twov8h, AArch64::qsub0);
3049*0b57cec5SDimitry Andric         return;
3050*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3051*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD1Twov2s, AArch64::dsub0);
3052*0b57cec5SDimitry Andric         return;
3053*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3054*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD1Twov4s, AArch64::qsub0);
3055*0b57cec5SDimitry Andric         return;
3056*0b57cec5SDimitry Andric       } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3057*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
3058*0b57cec5SDimitry Andric         return;
3059*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3060*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD1Twov2d, AArch64::qsub0);
3061*0b57cec5SDimitry Andric         return;
3062*0b57cec5SDimitry Andric       }
3063*0b57cec5SDimitry Andric       break;
3064*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_ld1x3:
3065*0b57cec5SDimitry Andric       if (VT == MVT::v8i8) {
3066*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD1Threev8b, AArch64::dsub0);
3067*0b57cec5SDimitry Andric         return;
3068*0b57cec5SDimitry Andric       } else if (VT == MVT::v16i8) {
3069*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD1Threev16b, AArch64::qsub0);
3070*0b57cec5SDimitry Andric         return;
3071*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3072*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD1Threev4h, AArch64::dsub0);
3073*0b57cec5SDimitry Andric         return;
3074*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3075*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD1Threev8h, AArch64::qsub0);
3076*0b57cec5SDimitry Andric         return;
3077*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3078*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD1Threev2s, AArch64::dsub0);
3079*0b57cec5SDimitry Andric         return;
3080*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3081*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD1Threev4s, AArch64::qsub0);
3082*0b57cec5SDimitry Andric         return;
3083*0b57cec5SDimitry Andric       } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3084*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
3085*0b57cec5SDimitry Andric         return;
3086*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3087*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD1Threev2d, AArch64::qsub0);
3088*0b57cec5SDimitry Andric         return;
3089*0b57cec5SDimitry Andric       }
3090*0b57cec5SDimitry Andric       break;
3091*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_ld1x4:
3092*0b57cec5SDimitry Andric       if (VT == MVT::v8i8) {
3093*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD1Fourv8b, AArch64::dsub0);
3094*0b57cec5SDimitry Andric         return;
3095*0b57cec5SDimitry Andric       } else if (VT == MVT::v16i8) {
3096*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD1Fourv16b, AArch64::qsub0);
3097*0b57cec5SDimitry Andric         return;
3098*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3099*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD1Fourv4h, AArch64::dsub0);
3100*0b57cec5SDimitry Andric         return;
3101*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3102*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD1Fourv8h, AArch64::qsub0);
3103*0b57cec5SDimitry Andric         return;
3104*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3105*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD1Fourv2s, AArch64::dsub0);
3106*0b57cec5SDimitry Andric         return;
3107*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3108*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD1Fourv4s, AArch64::qsub0);
3109*0b57cec5SDimitry Andric         return;
3110*0b57cec5SDimitry Andric       } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3111*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
3112*0b57cec5SDimitry Andric         return;
3113*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3114*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD1Fourv2d, AArch64::qsub0);
3115*0b57cec5SDimitry Andric         return;
3116*0b57cec5SDimitry Andric       }
3117*0b57cec5SDimitry Andric       break;
3118*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_ld2:
3119*0b57cec5SDimitry Andric       if (VT == MVT::v8i8) {
3120*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD2Twov8b, AArch64::dsub0);
3121*0b57cec5SDimitry Andric         return;
3122*0b57cec5SDimitry Andric       } else if (VT == MVT::v16i8) {
3123*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD2Twov16b, AArch64::qsub0);
3124*0b57cec5SDimitry Andric         return;
3125*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3126*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD2Twov4h, AArch64::dsub0);
3127*0b57cec5SDimitry Andric         return;
3128*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3129*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD2Twov8h, AArch64::qsub0);
3130*0b57cec5SDimitry Andric         return;
3131*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3132*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD2Twov2s, AArch64::dsub0);
3133*0b57cec5SDimitry Andric         return;
3134*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3135*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD2Twov4s, AArch64::qsub0);
3136*0b57cec5SDimitry Andric         return;
3137*0b57cec5SDimitry Andric       } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3138*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
3139*0b57cec5SDimitry Andric         return;
3140*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3141*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD2Twov2d, AArch64::qsub0);
3142*0b57cec5SDimitry Andric         return;
3143*0b57cec5SDimitry Andric       }
3144*0b57cec5SDimitry Andric       break;
3145*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_ld3:
3146*0b57cec5SDimitry Andric       if (VT == MVT::v8i8) {
3147*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD3Threev8b, AArch64::dsub0);
3148*0b57cec5SDimitry Andric         return;
3149*0b57cec5SDimitry Andric       } else if (VT == MVT::v16i8) {
3150*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD3Threev16b, AArch64::qsub0);
3151*0b57cec5SDimitry Andric         return;
3152*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3153*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD3Threev4h, AArch64::dsub0);
3154*0b57cec5SDimitry Andric         return;
3155*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3156*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD3Threev8h, AArch64::qsub0);
3157*0b57cec5SDimitry Andric         return;
3158*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3159*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD3Threev2s, AArch64::dsub0);
3160*0b57cec5SDimitry Andric         return;
3161*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3162*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD3Threev4s, AArch64::qsub0);
3163*0b57cec5SDimitry Andric         return;
3164*0b57cec5SDimitry Andric       } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3165*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
3166*0b57cec5SDimitry Andric         return;
3167*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3168*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD3Threev2d, AArch64::qsub0);
3169*0b57cec5SDimitry Andric         return;
3170*0b57cec5SDimitry Andric       }
3171*0b57cec5SDimitry Andric       break;
3172*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_ld4:
3173*0b57cec5SDimitry Andric       if (VT == MVT::v8i8) {
3174*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD4Fourv8b, AArch64::dsub0);
3175*0b57cec5SDimitry Andric         return;
3176*0b57cec5SDimitry Andric       } else if (VT == MVT::v16i8) {
3177*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD4Fourv16b, AArch64::qsub0);
3178*0b57cec5SDimitry Andric         return;
3179*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3180*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD4Fourv4h, AArch64::dsub0);
3181*0b57cec5SDimitry Andric         return;
3182*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3183*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD4Fourv8h, AArch64::qsub0);
3184*0b57cec5SDimitry Andric         return;
3185*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3186*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD4Fourv2s, AArch64::dsub0);
3187*0b57cec5SDimitry Andric         return;
3188*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3189*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD4Fourv4s, AArch64::qsub0);
3190*0b57cec5SDimitry Andric         return;
3191*0b57cec5SDimitry Andric       } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3192*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
3193*0b57cec5SDimitry Andric         return;
3194*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3195*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD4Fourv2d, AArch64::qsub0);
3196*0b57cec5SDimitry Andric         return;
3197*0b57cec5SDimitry Andric       }
3198*0b57cec5SDimitry Andric       break;
3199*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_ld2r:
3200*0b57cec5SDimitry Andric       if (VT == MVT::v8i8) {
3201*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD2Rv8b, AArch64::dsub0);
3202*0b57cec5SDimitry Andric         return;
3203*0b57cec5SDimitry Andric       } else if (VT == MVT::v16i8) {
3204*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD2Rv16b, AArch64::qsub0);
3205*0b57cec5SDimitry Andric         return;
3206*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3207*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD2Rv4h, AArch64::dsub0);
3208*0b57cec5SDimitry Andric         return;
3209*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3210*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD2Rv8h, AArch64::qsub0);
3211*0b57cec5SDimitry Andric         return;
3212*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3213*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD2Rv2s, AArch64::dsub0);
3214*0b57cec5SDimitry Andric         return;
3215*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3216*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD2Rv4s, AArch64::qsub0);
3217*0b57cec5SDimitry Andric         return;
3218*0b57cec5SDimitry Andric       } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3219*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD2Rv1d, AArch64::dsub0);
3220*0b57cec5SDimitry Andric         return;
3221*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3222*0b57cec5SDimitry Andric         SelectLoad(Node, 2, AArch64::LD2Rv2d, AArch64::qsub0);
3223*0b57cec5SDimitry Andric         return;
3224*0b57cec5SDimitry Andric       }
3225*0b57cec5SDimitry Andric       break;
3226*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_ld3r:
3227*0b57cec5SDimitry Andric       if (VT == MVT::v8i8) {
3228*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD3Rv8b, AArch64::dsub0);
3229*0b57cec5SDimitry Andric         return;
3230*0b57cec5SDimitry Andric       } else if (VT == MVT::v16i8) {
3231*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD3Rv16b, AArch64::qsub0);
3232*0b57cec5SDimitry Andric         return;
3233*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3234*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD3Rv4h, AArch64::dsub0);
3235*0b57cec5SDimitry Andric         return;
3236*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3237*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD3Rv8h, AArch64::qsub0);
3238*0b57cec5SDimitry Andric         return;
3239*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3240*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD3Rv2s, AArch64::dsub0);
3241*0b57cec5SDimitry Andric         return;
3242*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3243*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD3Rv4s, AArch64::qsub0);
3244*0b57cec5SDimitry Andric         return;
3245*0b57cec5SDimitry Andric       } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3246*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD3Rv1d, AArch64::dsub0);
3247*0b57cec5SDimitry Andric         return;
3248*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3249*0b57cec5SDimitry Andric         SelectLoad(Node, 3, AArch64::LD3Rv2d, AArch64::qsub0);
3250*0b57cec5SDimitry Andric         return;
3251*0b57cec5SDimitry Andric       }
3252*0b57cec5SDimitry Andric       break;
3253*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_ld4r:
3254*0b57cec5SDimitry Andric       if (VT == MVT::v8i8) {
3255*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD4Rv8b, AArch64::dsub0);
3256*0b57cec5SDimitry Andric         return;
3257*0b57cec5SDimitry Andric       } else if (VT == MVT::v16i8) {
3258*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD4Rv16b, AArch64::qsub0);
3259*0b57cec5SDimitry Andric         return;
3260*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3261*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD4Rv4h, AArch64::dsub0);
3262*0b57cec5SDimitry Andric         return;
3263*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3264*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD4Rv8h, AArch64::qsub0);
3265*0b57cec5SDimitry Andric         return;
3266*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3267*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD4Rv2s, AArch64::dsub0);
3268*0b57cec5SDimitry Andric         return;
3269*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3270*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD4Rv4s, AArch64::qsub0);
3271*0b57cec5SDimitry Andric         return;
3272*0b57cec5SDimitry Andric       } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3273*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD4Rv1d, AArch64::dsub0);
3274*0b57cec5SDimitry Andric         return;
3275*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3276*0b57cec5SDimitry Andric         SelectLoad(Node, 4, AArch64::LD4Rv2d, AArch64::qsub0);
3277*0b57cec5SDimitry Andric         return;
3278*0b57cec5SDimitry Andric       }
3279*0b57cec5SDimitry Andric       break;
3280*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_ld2lane:
3281*0b57cec5SDimitry Andric       if (VT == MVT::v16i8 || VT == MVT::v8i8) {
3282*0b57cec5SDimitry Andric         SelectLoadLane(Node, 2, AArch64::LD2i8);
3283*0b57cec5SDimitry Andric         return;
3284*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
3285*0b57cec5SDimitry Andric                  VT == MVT::v8f16) {
3286*0b57cec5SDimitry Andric         SelectLoadLane(Node, 2, AArch64::LD2i16);
3287*0b57cec5SDimitry Andric         return;
3288*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
3289*0b57cec5SDimitry Andric                  VT == MVT::v2f32) {
3290*0b57cec5SDimitry Andric         SelectLoadLane(Node, 2, AArch64::LD2i32);
3291*0b57cec5SDimitry Andric         return;
3292*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
3293*0b57cec5SDimitry Andric                  VT == MVT::v1f64) {
3294*0b57cec5SDimitry Andric         SelectLoadLane(Node, 2, AArch64::LD2i64);
3295*0b57cec5SDimitry Andric         return;
3296*0b57cec5SDimitry Andric       }
3297*0b57cec5SDimitry Andric       break;
3298*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_ld3lane:
3299*0b57cec5SDimitry Andric       if (VT == MVT::v16i8 || VT == MVT::v8i8) {
3300*0b57cec5SDimitry Andric         SelectLoadLane(Node, 3, AArch64::LD3i8);
3301*0b57cec5SDimitry Andric         return;
3302*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
3303*0b57cec5SDimitry Andric                  VT == MVT::v8f16) {
3304*0b57cec5SDimitry Andric         SelectLoadLane(Node, 3, AArch64::LD3i16);
3305*0b57cec5SDimitry Andric         return;
3306*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
3307*0b57cec5SDimitry Andric                  VT == MVT::v2f32) {
3308*0b57cec5SDimitry Andric         SelectLoadLane(Node, 3, AArch64::LD3i32);
3309*0b57cec5SDimitry Andric         return;
3310*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
3311*0b57cec5SDimitry Andric                  VT == MVT::v1f64) {
3312*0b57cec5SDimitry Andric         SelectLoadLane(Node, 3, AArch64::LD3i64);
3313*0b57cec5SDimitry Andric         return;
3314*0b57cec5SDimitry Andric       }
3315*0b57cec5SDimitry Andric       break;
3316*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_ld4lane:
3317*0b57cec5SDimitry Andric       if (VT == MVT::v16i8 || VT == MVT::v8i8) {
3318*0b57cec5SDimitry Andric         SelectLoadLane(Node, 4, AArch64::LD4i8);
3319*0b57cec5SDimitry Andric         return;
3320*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
3321*0b57cec5SDimitry Andric                  VT == MVT::v8f16) {
3322*0b57cec5SDimitry Andric         SelectLoadLane(Node, 4, AArch64::LD4i16);
3323*0b57cec5SDimitry Andric         return;
3324*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
3325*0b57cec5SDimitry Andric                  VT == MVT::v2f32) {
3326*0b57cec5SDimitry Andric         SelectLoadLane(Node, 4, AArch64::LD4i32);
3327*0b57cec5SDimitry Andric         return;
3328*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
3329*0b57cec5SDimitry Andric                  VT == MVT::v1f64) {
3330*0b57cec5SDimitry Andric         SelectLoadLane(Node, 4, AArch64::LD4i64);
3331*0b57cec5SDimitry Andric         return;
3332*0b57cec5SDimitry Andric       }
3333*0b57cec5SDimitry Andric       break;
3334*0b57cec5SDimitry Andric     }
3335*0b57cec5SDimitry Andric   } break;
3336*0b57cec5SDimitry Andric   case ISD::INTRINSIC_WO_CHAIN: {
3337*0b57cec5SDimitry Andric     unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(0))->getZExtValue();
3338*0b57cec5SDimitry Andric     switch (IntNo) {
3339*0b57cec5SDimitry Andric     default:
3340*0b57cec5SDimitry Andric       break;
3341*0b57cec5SDimitry Andric     case Intrinsic::aarch64_tagp:
3342*0b57cec5SDimitry Andric       SelectTagP(Node);
3343*0b57cec5SDimitry Andric       return;
3344*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_tbl2:
3345*0b57cec5SDimitry Andric       SelectTable(Node, 2,
3346*0b57cec5SDimitry Andric                   VT == MVT::v8i8 ? AArch64::TBLv8i8Two : AArch64::TBLv16i8Two,
3347*0b57cec5SDimitry Andric                   false);
3348*0b57cec5SDimitry Andric       return;
3349*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_tbl3:
3350*0b57cec5SDimitry Andric       SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBLv8i8Three
3351*0b57cec5SDimitry Andric                                            : AArch64::TBLv16i8Three,
3352*0b57cec5SDimitry Andric                   false);
3353*0b57cec5SDimitry Andric       return;
3354*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_tbl4:
3355*0b57cec5SDimitry Andric       SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBLv8i8Four
3356*0b57cec5SDimitry Andric                                            : AArch64::TBLv16i8Four,
3357*0b57cec5SDimitry Andric                   false);
3358*0b57cec5SDimitry Andric       return;
3359*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_tbx2:
3360*0b57cec5SDimitry Andric       SelectTable(Node, 2,
3361*0b57cec5SDimitry Andric                   VT == MVT::v8i8 ? AArch64::TBXv8i8Two : AArch64::TBXv16i8Two,
3362*0b57cec5SDimitry Andric                   true);
3363*0b57cec5SDimitry Andric       return;
3364*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_tbx3:
3365*0b57cec5SDimitry Andric       SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBXv8i8Three
3366*0b57cec5SDimitry Andric                                            : AArch64::TBXv16i8Three,
3367*0b57cec5SDimitry Andric                   true);
3368*0b57cec5SDimitry Andric       return;
3369*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_tbx4:
3370*0b57cec5SDimitry Andric       SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBXv8i8Four
3371*0b57cec5SDimitry Andric                                            : AArch64::TBXv16i8Four,
3372*0b57cec5SDimitry Andric                   true);
3373*0b57cec5SDimitry Andric       return;
3374*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_smull:
3375*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_umull:
3376*0b57cec5SDimitry Andric       if (tryMULLV64LaneV128(IntNo, Node))
3377*0b57cec5SDimitry Andric         return;
3378*0b57cec5SDimitry Andric       break;
3379*0b57cec5SDimitry Andric     }
3380*0b57cec5SDimitry Andric     break;
3381*0b57cec5SDimitry Andric   }
3382*0b57cec5SDimitry Andric   case ISD::INTRINSIC_VOID: {
3383*0b57cec5SDimitry Andric     unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
3384*0b57cec5SDimitry Andric     if (Node->getNumOperands() >= 3)
3385*0b57cec5SDimitry Andric       VT = Node->getOperand(2)->getValueType(0);
3386*0b57cec5SDimitry Andric     switch (IntNo) {
3387*0b57cec5SDimitry Andric     default:
3388*0b57cec5SDimitry Andric       break;
3389*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_st1x2: {
3390*0b57cec5SDimitry Andric       if (VT == MVT::v8i8) {
3391*0b57cec5SDimitry Andric         SelectStore(Node, 2, AArch64::ST1Twov8b);
3392*0b57cec5SDimitry Andric         return;
3393*0b57cec5SDimitry Andric       } else if (VT == MVT::v16i8) {
3394*0b57cec5SDimitry Andric         SelectStore(Node, 2, AArch64::ST1Twov16b);
3395*0b57cec5SDimitry Andric         return;
3396*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3397*0b57cec5SDimitry Andric         SelectStore(Node, 2, AArch64::ST1Twov4h);
3398*0b57cec5SDimitry Andric         return;
3399*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3400*0b57cec5SDimitry Andric         SelectStore(Node, 2, AArch64::ST1Twov8h);
3401*0b57cec5SDimitry Andric         return;
3402*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3403*0b57cec5SDimitry Andric         SelectStore(Node, 2, AArch64::ST1Twov2s);
3404*0b57cec5SDimitry Andric         return;
3405*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3406*0b57cec5SDimitry Andric         SelectStore(Node, 2, AArch64::ST1Twov4s);
3407*0b57cec5SDimitry Andric         return;
3408*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3409*0b57cec5SDimitry Andric         SelectStore(Node, 2, AArch64::ST1Twov2d);
3410*0b57cec5SDimitry Andric         return;
3411*0b57cec5SDimitry Andric       } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3412*0b57cec5SDimitry Andric         SelectStore(Node, 2, AArch64::ST1Twov1d);
3413*0b57cec5SDimitry Andric         return;
3414*0b57cec5SDimitry Andric       }
3415*0b57cec5SDimitry Andric       break;
3416*0b57cec5SDimitry Andric     }
3417*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_st1x3: {
3418*0b57cec5SDimitry Andric       if (VT == MVT::v8i8) {
3419*0b57cec5SDimitry Andric         SelectStore(Node, 3, AArch64::ST1Threev8b);
3420*0b57cec5SDimitry Andric         return;
3421*0b57cec5SDimitry Andric       } else if (VT == MVT::v16i8) {
3422*0b57cec5SDimitry Andric         SelectStore(Node, 3, AArch64::ST1Threev16b);
3423*0b57cec5SDimitry Andric         return;
3424*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3425*0b57cec5SDimitry Andric         SelectStore(Node, 3, AArch64::ST1Threev4h);
3426*0b57cec5SDimitry Andric         return;
3427*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3428*0b57cec5SDimitry Andric         SelectStore(Node, 3, AArch64::ST1Threev8h);
3429*0b57cec5SDimitry Andric         return;
3430*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3431*0b57cec5SDimitry Andric         SelectStore(Node, 3, AArch64::ST1Threev2s);
3432*0b57cec5SDimitry Andric         return;
3433*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3434*0b57cec5SDimitry Andric         SelectStore(Node, 3, AArch64::ST1Threev4s);
3435*0b57cec5SDimitry Andric         return;
3436*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3437*0b57cec5SDimitry Andric         SelectStore(Node, 3, AArch64::ST1Threev2d);
3438*0b57cec5SDimitry Andric         return;
3439*0b57cec5SDimitry Andric       } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3440*0b57cec5SDimitry Andric         SelectStore(Node, 3, AArch64::ST1Threev1d);
3441*0b57cec5SDimitry Andric         return;
3442*0b57cec5SDimitry Andric       }
3443*0b57cec5SDimitry Andric       break;
3444*0b57cec5SDimitry Andric     }
3445*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_st1x4: {
3446*0b57cec5SDimitry Andric       if (VT == MVT::v8i8) {
3447*0b57cec5SDimitry Andric         SelectStore(Node, 4, AArch64::ST1Fourv8b);
3448*0b57cec5SDimitry Andric         return;
3449*0b57cec5SDimitry Andric       } else if (VT == MVT::v16i8) {
3450*0b57cec5SDimitry Andric         SelectStore(Node, 4, AArch64::ST1Fourv16b);
3451*0b57cec5SDimitry Andric         return;
3452*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3453*0b57cec5SDimitry Andric         SelectStore(Node, 4, AArch64::ST1Fourv4h);
3454*0b57cec5SDimitry Andric         return;
3455*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3456*0b57cec5SDimitry Andric         SelectStore(Node, 4, AArch64::ST1Fourv8h);
3457*0b57cec5SDimitry Andric         return;
3458*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3459*0b57cec5SDimitry Andric         SelectStore(Node, 4, AArch64::ST1Fourv2s);
3460*0b57cec5SDimitry Andric         return;
3461*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3462*0b57cec5SDimitry Andric         SelectStore(Node, 4, AArch64::ST1Fourv4s);
3463*0b57cec5SDimitry Andric         return;
3464*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3465*0b57cec5SDimitry Andric         SelectStore(Node, 4, AArch64::ST1Fourv2d);
3466*0b57cec5SDimitry Andric         return;
3467*0b57cec5SDimitry Andric       } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3468*0b57cec5SDimitry Andric         SelectStore(Node, 4, AArch64::ST1Fourv1d);
3469*0b57cec5SDimitry Andric         return;
3470*0b57cec5SDimitry Andric       }
3471*0b57cec5SDimitry Andric       break;
3472*0b57cec5SDimitry Andric     }
3473*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_st2: {
3474*0b57cec5SDimitry Andric       if (VT == MVT::v8i8) {
3475*0b57cec5SDimitry Andric         SelectStore(Node, 2, AArch64::ST2Twov8b);
3476*0b57cec5SDimitry Andric         return;
3477*0b57cec5SDimitry Andric       } else if (VT == MVT::v16i8) {
3478*0b57cec5SDimitry Andric         SelectStore(Node, 2, AArch64::ST2Twov16b);
3479*0b57cec5SDimitry Andric         return;
3480*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3481*0b57cec5SDimitry Andric         SelectStore(Node, 2, AArch64::ST2Twov4h);
3482*0b57cec5SDimitry Andric         return;
3483*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3484*0b57cec5SDimitry Andric         SelectStore(Node, 2, AArch64::ST2Twov8h);
3485*0b57cec5SDimitry Andric         return;
3486*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3487*0b57cec5SDimitry Andric         SelectStore(Node, 2, AArch64::ST2Twov2s);
3488*0b57cec5SDimitry Andric         return;
3489*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3490*0b57cec5SDimitry Andric         SelectStore(Node, 2, AArch64::ST2Twov4s);
3491*0b57cec5SDimitry Andric         return;
3492*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3493*0b57cec5SDimitry Andric         SelectStore(Node, 2, AArch64::ST2Twov2d);
3494*0b57cec5SDimitry Andric         return;
3495*0b57cec5SDimitry Andric       } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3496*0b57cec5SDimitry Andric         SelectStore(Node, 2, AArch64::ST1Twov1d);
3497*0b57cec5SDimitry Andric         return;
3498*0b57cec5SDimitry Andric       }
3499*0b57cec5SDimitry Andric       break;
3500*0b57cec5SDimitry Andric     }
3501*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_st3: {
3502*0b57cec5SDimitry Andric       if (VT == MVT::v8i8) {
3503*0b57cec5SDimitry Andric         SelectStore(Node, 3, AArch64::ST3Threev8b);
3504*0b57cec5SDimitry Andric         return;
3505*0b57cec5SDimitry Andric       } else if (VT == MVT::v16i8) {
3506*0b57cec5SDimitry Andric         SelectStore(Node, 3, AArch64::ST3Threev16b);
3507*0b57cec5SDimitry Andric         return;
3508*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3509*0b57cec5SDimitry Andric         SelectStore(Node, 3, AArch64::ST3Threev4h);
3510*0b57cec5SDimitry Andric         return;
3511*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3512*0b57cec5SDimitry Andric         SelectStore(Node, 3, AArch64::ST3Threev8h);
3513*0b57cec5SDimitry Andric         return;
3514*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3515*0b57cec5SDimitry Andric         SelectStore(Node, 3, AArch64::ST3Threev2s);
3516*0b57cec5SDimitry Andric         return;
3517*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3518*0b57cec5SDimitry Andric         SelectStore(Node, 3, AArch64::ST3Threev4s);
3519*0b57cec5SDimitry Andric         return;
3520*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3521*0b57cec5SDimitry Andric         SelectStore(Node, 3, AArch64::ST3Threev2d);
3522*0b57cec5SDimitry Andric         return;
3523*0b57cec5SDimitry Andric       } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3524*0b57cec5SDimitry Andric         SelectStore(Node, 3, AArch64::ST1Threev1d);
3525*0b57cec5SDimitry Andric         return;
3526*0b57cec5SDimitry Andric       }
3527*0b57cec5SDimitry Andric       break;
3528*0b57cec5SDimitry Andric     }
3529*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_st4: {
3530*0b57cec5SDimitry Andric       if (VT == MVT::v8i8) {
3531*0b57cec5SDimitry Andric         SelectStore(Node, 4, AArch64::ST4Fourv8b);
3532*0b57cec5SDimitry Andric         return;
3533*0b57cec5SDimitry Andric       } else if (VT == MVT::v16i8) {
3534*0b57cec5SDimitry Andric         SelectStore(Node, 4, AArch64::ST4Fourv16b);
3535*0b57cec5SDimitry Andric         return;
3536*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3537*0b57cec5SDimitry Andric         SelectStore(Node, 4, AArch64::ST4Fourv4h);
3538*0b57cec5SDimitry Andric         return;
3539*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3540*0b57cec5SDimitry Andric         SelectStore(Node, 4, AArch64::ST4Fourv8h);
3541*0b57cec5SDimitry Andric         return;
3542*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3543*0b57cec5SDimitry Andric         SelectStore(Node, 4, AArch64::ST4Fourv2s);
3544*0b57cec5SDimitry Andric         return;
3545*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3546*0b57cec5SDimitry Andric         SelectStore(Node, 4, AArch64::ST4Fourv4s);
3547*0b57cec5SDimitry Andric         return;
3548*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3549*0b57cec5SDimitry Andric         SelectStore(Node, 4, AArch64::ST4Fourv2d);
3550*0b57cec5SDimitry Andric         return;
3551*0b57cec5SDimitry Andric       } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3552*0b57cec5SDimitry Andric         SelectStore(Node, 4, AArch64::ST1Fourv1d);
3553*0b57cec5SDimitry Andric         return;
3554*0b57cec5SDimitry Andric       }
3555*0b57cec5SDimitry Andric       break;
3556*0b57cec5SDimitry Andric     }
3557*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_st2lane: {
3558*0b57cec5SDimitry Andric       if (VT == MVT::v16i8 || VT == MVT::v8i8) {
3559*0b57cec5SDimitry Andric         SelectStoreLane(Node, 2, AArch64::ST2i8);
3560*0b57cec5SDimitry Andric         return;
3561*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
3562*0b57cec5SDimitry Andric                  VT == MVT::v8f16) {
3563*0b57cec5SDimitry Andric         SelectStoreLane(Node, 2, AArch64::ST2i16);
3564*0b57cec5SDimitry Andric         return;
3565*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
3566*0b57cec5SDimitry Andric                  VT == MVT::v2f32) {
3567*0b57cec5SDimitry Andric         SelectStoreLane(Node, 2, AArch64::ST2i32);
3568*0b57cec5SDimitry Andric         return;
3569*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
3570*0b57cec5SDimitry Andric                  VT == MVT::v1f64) {
3571*0b57cec5SDimitry Andric         SelectStoreLane(Node, 2, AArch64::ST2i64);
3572*0b57cec5SDimitry Andric         return;
3573*0b57cec5SDimitry Andric       }
3574*0b57cec5SDimitry Andric       break;
3575*0b57cec5SDimitry Andric     }
3576*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_st3lane: {
3577*0b57cec5SDimitry Andric       if (VT == MVT::v16i8 || VT == MVT::v8i8) {
3578*0b57cec5SDimitry Andric         SelectStoreLane(Node, 3, AArch64::ST3i8);
3579*0b57cec5SDimitry Andric         return;
3580*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
3581*0b57cec5SDimitry Andric                  VT == MVT::v8f16) {
3582*0b57cec5SDimitry Andric         SelectStoreLane(Node, 3, AArch64::ST3i16);
3583*0b57cec5SDimitry Andric         return;
3584*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
3585*0b57cec5SDimitry Andric                  VT == MVT::v2f32) {
3586*0b57cec5SDimitry Andric         SelectStoreLane(Node, 3, AArch64::ST3i32);
3587*0b57cec5SDimitry Andric         return;
3588*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
3589*0b57cec5SDimitry Andric                  VT == MVT::v1f64) {
3590*0b57cec5SDimitry Andric         SelectStoreLane(Node, 3, AArch64::ST3i64);
3591*0b57cec5SDimitry Andric         return;
3592*0b57cec5SDimitry Andric       }
3593*0b57cec5SDimitry Andric       break;
3594*0b57cec5SDimitry Andric     }
3595*0b57cec5SDimitry Andric     case Intrinsic::aarch64_neon_st4lane: {
3596*0b57cec5SDimitry Andric       if (VT == MVT::v16i8 || VT == MVT::v8i8) {
3597*0b57cec5SDimitry Andric         SelectStoreLane(Node, 4, AArch64::ST4i8);
3598*0b57cec5SDimitry Andric         return;
3599*0b57cec5SDimitry Andric       } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
3600*0b57cec5SDimitry Andric                  VT == MVT::v8f16) {
3601*0b57cec5SDimitry Andric         SelectStoreLane(Node, 4, AArch64::ST4i16);
3602*0b57cec5SDimitry Andric         return;
3603*0b57cec5SDimitry Andric       } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
3604*0b57cec5SDimitry Andric                  VT == MVT::v2f32) {
3605*0b57cec5SDimitry Andric         SelectStoreLane(Node, 4, AArch64::ST4i32);
3606*0b57cec5SDimitry Andric         return;
3607*0b57cec5SDimitry Andric       } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
3608*0b57cec5SDimitry Andric                  VT == MVT::v1f64) {
3609*0b57cec5SDimitry Andric         SelectStoreLane(Node, 4, AArch64::ST4i64);
3610*0b57cec5SDimitry Andric         return;
3611*0b57cec5SDimitry Andric       }
3612*0b57cec5SDimitry Andric       break;
3613*0b57cec5SDimitry Andric     }
3614*0b57cec5SDimitry Andric     }
3615*0b57cec5SDimitry Andric     break;
3616*0b57cec5SDimitry Andric   }
3617*0b57cec5SDimitry Andric   case AArch64ISD::LD2post: {
3618*0b57cec5SDimitry Andric     if (VT == MVT::v8i8) {
3619*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD2Twov8b_POST, AArch64::dsub0);
3620*0b57cec5SDimitry Andric       return;
3621*0b57cec5SDimitry Andric     } else if (VT == MVT::v16i8) {
3622*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD2Twov16b_POST, AArch64::qsub0);
3623*0b57cec5SDimitry Andric       return;
3624*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3625*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD2Twov4h_POST, AArch64::dsub0);
3626*0b57cec5SDimitry Andric       return;
3627*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3628*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD2Twov8h_POST, AArch64::qsub0);
3629*0b57cec5SDimitry Andric       return;
3630*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3631*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD2Twov2s_POST, AArch64::dsub0);
3632*0b57cec5SDimitry Andric       return;
3633*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3634*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD2Twov4s_POST, AArch64::qsub0);
3635*0b57cec5SDimitry Andric       return;
3636*0b57cec5SDimitry Andric     } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3637*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
3638*0b57cec5SDimitry Andric       return;
3639*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3640*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD2Twov2d_POST, AArch64::qsub0);
3641*0b57cec5SDimitry Andric       return;
3642*0b57cec5SDimitry Andric     }
3643*0b57cec5SDimitry Andric     break;
3644*0b57cec5SDimitry Andric   }
3645*0b57cec5SDimitry Andric   case AArch64ISD::LD3post: {
3646*0b57cec5SDimitry Andric     if (VT == MVT::v8i8) {
3647*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD3Threev8b_POST, AArch64::dsub0);
3648*0b57cec5SDimitry Andric       return;
3649*0b57cec5SDimitry Andric     } else if (VT == MVT::v16i8) {
3650*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD3Threev16b_POST, AArch64::qsub0);
3651*0b57cec5SDimitry Andric       return;
3652*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3653*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD3Threev4h_POST, AArch64::dsub0);
3654*0b57cec5SDimitry Andric       return;
3655*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3656*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD3Threev8h_POST, AArch64::qsub0);
3657*0b57cec5SDimitry Andric       return;
3658*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3659*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD3Threev2s_POST, AArch64::dsub0);
3660*0b57cec5SDimitry Andric       return;
3661*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3662*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD3Threev4s_POST, AArch64::qsub0);
3663*0b57cec5SDimitry Andric       return;
3664*0b57cec5SDimitry Andric     } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3665*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
3666*0b57cec5SDimitry Andric       return;
3667*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3668*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD3Threev2d_POST, AArch64::qsub0);
3669*0b57cec5SDimitry Andric       return;
3670*0b57cec5SDimitry Andric     }
3671*0b57cec5SDimitry Andric     break;
3672*0b57cec5SDimitry Andric   }
3673*0b57cec5SDimitry Andric   case AArch64ISD::LD4post: {
3674*0b57cec5SDimitry Andric     if (VT == MVT::v8i8) {
3675*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD4Fourv8b_POST, AArch64::dsub0);
3676*0b57cec5SDimitry Andric       return;
3677*0b57cec5SDimitry Andric     } else if (VT == MVT::v16i8) {
3678*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD4Fourv16b_POST, AArch64::qsub0);
3679*0b57cec5SDimitry Andric       return;
3680*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3681*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD4Fourv4h_POST, AArch64::dsub0);
3682*0b57cec5SDimitry Andric       return;
3683*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3684*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD4Fourv8h_POST, AArch64::qsub0);
3685*0b57cec5SDimitry Andric       return;
3686*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3687*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD4Fourv2s_POST, AArch64::dsub0);
3688*0b57cec5SDimitry Andric       return;
3689*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3690*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD4Fourv4s_POST, AArch64::qsub0);
3691*0b57cec5SDimitry Andric       return;
3692*0b57cec5SDimitry Andric     } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3693*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
3694*0b57cec5SDimitry Andric       return;
3695*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3696*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD4Fourv2d_POST, AArch64::qsub0);
3697*0b57cec5SDimitry Andric       return;
3698*0b57cec5SDimitry Andric     }
3699*0b57cec5SDimitry Andric     break;
3700*0b57cec5SDimitry Andric   }
3701*0b57cec5SDimitry Andric   case AArch64ISD::LD1x2post: {
3702*0b57cec5SDimitry Andric     if (VT == MVT::v8i8) {
3703*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD1Twov8b_POST, AArch64::dsub0);
3704*0b57cec5SDimitry Andric       return;
3705*0b57cec5SDimitry Andric     } else if (VT == MVT::v16i8) {
3706*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD1Twov16b_POST, AArch64::qsub0);
3707*0b57cec5SDimitry Andric       return;
3708*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3709*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD1Twov4h_POST, AArch64::dsub0);
3710*0b57cec5SDimitry Andric       return;
3711*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3712*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD1Twov8h_POST, AArch64::qsub0);
3713*0b57cec5SDimitry Andric       return;
3714*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3715*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD1Twov2s_POST, AArch64::dsub0);
3716*0b57cec5SDimitry Andric       return;
3717*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3718*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD1Twov4s_POST, AArch64::qsub0);
3719*0b57cec5SDimitry Andric       return;
3720*0b57cec5SDimitry Andric     } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3721*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
3722*0b57cec5SDimitry Andric       return;
3723*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3724*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD1Twov2d_POST, AArch64::qsub0);
3725*0b57cec5SDimitry Andric       return;
3726*0b57cec5SDimitry Andric     }
3727*0b57cec5SDimitry Andric     break;
3728*0b57cec5SDimitry Andric   }
3729*0b57cec5SDimitry Andric   case AArch64ISD::LD1x3post: {
3730*0b57cec5SDimitry Andric     if (VT == MVT::v8i8) {
3731*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD1Threev8b_POST, AArch64::dsub0);
3732*0b57cec5SDimitry Andric       return;
3733*0b57cec5SDimitry Andric     } else if (VT == MVT::v16i8) {
3734*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD1Threev16b_POST, AArch64::qsub0);
3735*0b57cec5SDimitry Andric       return;
3736*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3737*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD1Threev4h_POST, AArch64::dsub0);
3738*0b57cec5SDimitry Andric       return;
3739*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3740*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD1Threev8h_POST, AArch64::qsub0);
3741*0b57cec5SDimitry Andric       return;
3742*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3743*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD1Threev2s_POST, AArch64::dsub0);
3744*0b57cec5SDimitry Andric       return;
3745*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3746*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD1Threev4s_POST, AArch64::qsub0);
3747*0b57cec5SDimitry Andric       return;
3748*0b57cec5SDimitry Andric     } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3749*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
3750*0b57cec5SDimitry Andric       return;
3751*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3752*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD1Threev2d_POST, AArch64::qsub0);
3753*0b57cec5SDimitry Andric       return;
3754*0b57cec5SDimitry Andric     }
3755*0b57cec5SDimitry Andric     break;
3756*0b57cec5SDimitry Andric   }
3757*0b57cec5SDimitry Andric   case AArch64ISD::LD1x4post: {
3758*0b57cec5SDimitry Andric     if (VT == MVT::v8i8) {
3759*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD1Fourv8b_POST, AArch64::dsub0);
3760*0b57cec5SDimitry Andric       return;
3761*0b57cec5SDimitry Andric     } else if (VT == MVT::v16i8) {
3762*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD1Fourv16b_POST, AArch64::qsub0);
3763*0b57cec5SDimitry Andric       return;
3764*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3765*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD1Fourv4h_POST, AArch64::dsub0);
3766*0b57cec5SDimitry Andric       return;
3767*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3768*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD1Fourv8h_POST, AArch64::qsub0);
3769*0b57cec5SDimitry Andric       return;
3770*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3771*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD1Fourv2s_POST, AArch64::dsub0);
3772*0b57cec5SDimitry Andric       return;
3773*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3774*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD1Fourv4s_POST, AArch64::qsub0);
3775*0b57cec5SDimitry Andric       return;
3776*0b57cec5SDimitry Andric     } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3777*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
3778*0b57cec5SDimitry Andric       return;
3779*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3780*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD1Fourv2d_POST, AArch64::qsub0);
3781*0b57cec5SDimitry Andric       return;
3782*0b57cec5SDimitry Andric     }
3783*0b57cec5SDimitry Andric     break;
3784*0b57cec5SDimitry Andric   }
3785*0b57cec5SDimitry Andric   case AArch64ISD::LD1DUPpost: {
3786*0b57cec5SDimitry Andric     if (VT == MVT::v8i8) {
3787*0b57cec5SDimitry Andric       SelectPostLoad(Node, 1, AArch64::LD1Rv8b_POST, AArch64::dsub0);
3788*0b57cec5SDimitry Andric       return;
3789*0b57cec5SDimitry Andric     } else if (VT == MVT::v16i8) {
3790*0b57cec5SDimitry Andric       SelectPostLoad(Node, 1, AArch64::LD1Rv16b_POST, AArch64::qsub0);
3791*0b57cec5SDimitry Andric       return;
3792*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3793*0b57cec5SDimitry Andric       SelectPostLoad(Node, 1, AArch64::LD1Rv4h_POST, AArch64::dsub0);
3794*0b57cec5SDimitry Andric       return;
3795*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3796*0b57cec5SDimitry Andric       SelectPostLoad(Node, 1, AArch64::LD1Rv8h_POST, AArch64::qsub0);
3797*0b57cec5SDimitry Andric       return;
3798*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3799*0b57cec5SDimitry Andric       SelectPostLoad(Node, 1, AArch64::LD1Rv2s_POST, AArch64::dsub0);
3800*0b57cec5SDimitry Andric       return;
3801*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3802*0b57cec5SDimitry Andric       SelectPostLoad(Node, 1, AArch64::LD1Rv4s_POST, AArch64::qsub0);
3803*0b57cec5SDimitry Andric       return;
3804*0b57cec5SDimitry Andric     } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3805*0b57cec5SDimitry Andric       SelectPostLoad(Node, 1, AArch64::LD1Rv1d_POST, AArch64::dsub0);
3806*0b57cec5SDimitry Andric       return;
3807*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3808*0b57cec5SDimitry Andric       SelectPostLoad(Node, 1, AArch64::LD1Rv2d_POST, AArch64::qsub0);
3809*0b57cec5SDimitry Andric       return;
3810*0b57cec5SDimitry Andric     }
3811*0b57cec5SDimitry Andric     break;
3812*0b57cec5SDimitry Andric   }
3813*0b57cec5SDimitry Andric   case AArch64ISD::LD2DUPpost: {
3814*0b57cec5SDimitry Andric     if (VT == MVT::v8i8) {
3815*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD2Rv8b_POST, AArch64::dsub0);
3816*0b57cec5SDimitry Andric       return;
3817*0b57cec5SDimitry Andric     } else if (VT == MVT::v16i8) {
3818*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD2Rv16b_POST, AArch64::qsub0);
3819*0b57cec5SDimitry Andric       return;
3820*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3821*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD2Rv4h_POST, AArch64::dsub0);
3822*0b57cec5SDimitry Andric       return;
3823*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3824*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD2Rv8h_POST, AArch64::qsub0);
3825*0b57cec5SDimitry Andric       return;
3826*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3827*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD2Rv2s_POST, AArch64::dsub0);
3828*0b57cec5SDimitry Andric       return;
3829*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3830*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD2Rv4s_POST, AArch64::qsub0);
3831*0b57cec5SDimitry Andric       return;
3832*0b57cec5SDimitry Andric     } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3833*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD2Rv1d_POST, AArch64::dsub0);
3834*0b57cec5SDimitry Andric       return;
3835*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3836*0b57cec5SDimitry Andric       SelectPostLoad(Node, 2, AArch64::LD2Rv2d_POST, AArch64::qsub0);
3837*0b57cec5SDimitry Andric       return;
3838*0b57cec5SDimitry Andric     }
3839*0b57cec5SDimitry Andric     break;
3840*0b57cec5SDimitry Andric   }
3841*0b57cec5SDimitry Andric   case AArch64ISD::LD3DUPpost: {
3842*0b57cec5SDimitry Andric     if (VT == MVT::v8i8) {
3843*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD3Rv8b_POST, AArch64::dsub0);
3844*0b57cec5SDimitry Andric       return;
3845*0b57cec5SDimitry Andric     } else if (VT == MVT::v16i8) {
3846*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD3Rv16b_POST, AArch64::qsub0);
3847*0b57cec5SDimitry Andric       return;
3848*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3849*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD3Rv4h_POST, AArch64::dsub0);
3850*0b57cec5SDimitry Andric       return;
3851*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3852*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD3Rv8h_POST, AArch64::qsub0);
3853*0b57cec5SDimitry Andric       return;
3854*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3855*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD3Rv2s_POST, AArch64::dsub0);
3856*0b57cec5SDimitry Andric       return;
3857*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3858*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD3Rv4s_POST, AArch64::qsub0);
3859*0b57cec5SDimitry Andric       return;
3860*0b57cec5SDimitry Andric     } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3861*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD3Rv1d_POST, AArch64::dsub0);
3862*0b57cec5SDimitry Andric       return;
3863*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3864*0b57cec5SDimitry Andric       SelectPostLoad(Node, 3, AArch64::LD3Rv2d_POST, AArch64::qsub0);
3865*0b57cec5SDimitry Andric       return;
3866*0b57cec5SDimitry Andric     }
3867*0b57cec5SDimitry Andric     break;
3868*0b57cec5SDimitry Andric   }
3869*0b57cec5SDimitry Andric   case AArch64ISD::LD4DUPpost: {
3870*0b57cec5SDimitry Andric     if (VT == MVT::v8i8) {
3871*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD4Rv8b_POST, AArch64::dsub0);
3872*0b57cec5SDimitry Andric       return;
3873*0b57cec5SDimitry Andric     } else if (VT == MVT::v16i8) {
3874*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD4Rv16b_POST, AArch64::qsub0);
3875*0b57cec5SDimitry Andric       return;
3876*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3877*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD4Rv4h_POST, AArch64::dsub0);
3878*0b57cec5SDimitry Andric       return;
3879*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3880*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD4Rv8h_POST, AArch64::qsub0);
3881*0b57cec5SDimitry Andric       return;
3882*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3883*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD4Rv2s_POST, AArch64::dsub0);
3884*0b57cec5SDimitry Andric       return;
3885*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3886*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD4Rv4s_POST, AArch64::qsub0);
3887*0b57cec5SDimitry Andric       return;
3888*0b57cec5SDimitry Andric     } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3889*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD4Rv1d_POST, AArch64::dsub0);
3890*0b57cec5SDimitry Andric       return;
3891*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3892*0b57cec5SDimitry Andric       SelectPostLoad(Node, 4, AArch64::LD4Rv2d_POST, AArch64::qsub0);
3893*0b57cec5SDimitry Andric       return;
3894*0b57cec5SDimitry Andric     }
3895*0b57cec5SDimitry Andric     break;
3896*0b57cec5SDimitry Andric   }
3897*0b57cec5SDimitry Andric   case AArch64ISD::LD1LANEpost: {
3898*0b57cec5SDimitry Andric     if (VT == MVT::v16i8 || VT == MVT::v8i8) {
3899*0b57cec5SDimitry Andric       SelectPostLoadLane(Node, 1, AArch64::LD1i8_POST);
3900*0b57cec5SDimitry Andric       return;
3901*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
3902*0b57cec5SDimitry Andric                VT == MVT::v8f16) {
3903*0b57cec5SDimitry Andric       SelectPostLoadLane(Node, 1, AArch64::LD1i16_POST);
3904*0b57cec5SDimitry Andric       return;
3905*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
3906*0b57cec5SDimitry Andric                VT == MVT::v2f32) {
3907*0b57cec5SDimitry Andric       SelectPostLoadLane(Node, 1, AArch64::LD1i32_POST);
3908*0b57cec5SDimitry Andric       return;
3909*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
3910*0b57cec5SDimitry Andric                VT == MVT::v1f64) {
3911*0b57cec5SDimitry Andric       SelectPostLoadLane(Node, 1, AArch64::LD1i64_POST);
3912*0b57cec5SDimitry Andric       return;
3913*0b57cec5SDimitry Andric     }
3914*0b57cec5SDimitry Andric     break;
3915*0b57cec5SDimitry Andric   }
3916*0b57cec5SDimitry Andric   case AArch64ISD::LD2LANEpost: {
3917*0b57cec5SDimitry Andric     if (VT == MVT::v16i8 || VT == MVT::v8i8) {
3918*0b57cec5SDimitry Andric       SelectPostLoadLane(Node, 2, AArch64::LD2i8_POST);
3919*0b57cec5SDimitry Andric       return;
3920*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
3921*0b57cec5SDimitry Andric                VT == MVT::v8f16) {
3922*0b57cec5SDimitry Andric       SelectPostLoadLane(Node, 2, AArch64::LD2i16_POST);
3923*0b57cec5SDimitry Andric       return;
3924*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
3925*0b57cec5SDimitry Andric                VT == MVT::v2f32) {
3926*0b57cec5SDimitry Andric       SelectPostLoadLane(Node, 2, AArch64::LD2i32_POST);
3927*0b57cec5SDimitry Andric       return;
3928*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
3929*0b57cec5SDimitry Andric                VT == MVT::v1f64) {
3930*0b57cec5SDimitry Andric       SelectPostLoadLane(Node, 2, AArch64::LD2i64_POST);
3931*0b57cec5SDimitry Andric       return;
3932*0b57cec5SDimitry Andric     }
3933*0b57cec5SDimitry Andric     break;
3934*0b57cec5SDimitry Andric   }
3935*0b57cec5SDimitry Andric   case AArch64ISD::LD3LANEpost: {
3936*0b57cec5SDimitry Andric     if (VT == MVT::v16i8 || VT == MVT::v8i8) {
3937*0b57cec5SDimitry Andric       SelectPostLoadLane(Node, 3, AArch64::LD3i8_POST);
3938*0b57cec5SDimitry Andric       return;
3939*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
3940*0b57cec5SDimitry Andric                VT == MVT::v8f16) {
3941*0b57cec5SDimitry Andric       SelectPostLoadLane(Node, 3, AArch64::LD3i16_POST);
3942*0b57cec5SDimitry Andric       return;
3943*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
3944*0b57cec5SDimitry Andric                VT == MVT::v2f32) {
3945*0b57cec5SDimitry Andric       SelectPostLoadLane(Node, 3, AArch64::LD3i32_POST);
3946*0b57cec5SDimitry Andric       return;
3947*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
3948*0b57cec5SDimitry Andric                VT == MVT::v1f64) {
3949*0b57cec5SDimitry Andric       SelectPostLoadLane(Node, 3, AArch64::LD3i64_POST);
3950*0b57cec5SDimitry Andric       return;
3951*0b57cec5SDimitry Andric     }
3952*0b57cec5SDimitry Andric     break;
3953*0b57cec5SDimitry Andric   }
3954*0b57cec5SDimitry Andric   case AArch64ISD::LD4LANEpost: {
3955*0b57cec5SDimitry Andric     if (VT == MVT::v16i8 || VT == MVT::v8i8) {
3956*0b57cec5SDimitry Andric       SelectPostLoadLane(Node, 4, AArch64::LD4i8_POST);
3957*0b57cec5SDimitry Andric       return;
3958*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
3959*0b57cec5SDimitry Andric                VT == MVT::v8f16) {
3960*0b57cec5SDimitry Andric       SelectPostLoadLane(Node, 4, AArch64::LD4i16_POST);
3961*0b57cec5SDimitry Andric       return;
3962*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
3963*0b57cec5SDimitry Andric                VT == MVT::v2f32) {
3964*0b57cec5SDimitry Andric       SelectPostLoadLane(Node, 4, AArch64::LD4i32_POST);
3965*0b57cec5SDimitry Andric       return;
3966*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
3967*0b57cec5SDimitry Andric                VT == MVT::v1f64) {
3968*0b57cec5SDimitry Andric       SelectPostLoadLane(Node, 4, AArch64::LD4i64_POST);
3969*0b57cec5SDimitry Andric       return;
3970*0b57cec5SDimitry Andric     }
3971*0b57cec5SDimitry Andric     break;
3972*0b57cec5SDimitry Andric   }
3973*0b57cec5SDimitry Andric   case AArch64ISD::ST2post: {
3974*0b57cec5SDimitry Andric     VT = Node->getOperand(1).getValueType();
3975*0b57cec5SDimitry Andric     if (VT == MVT::v8i8) {
3976*0b57cec5SDimitry Andric       SelectPostStore(Node, 2, AArch64::ST2Twov8b_POST);
3977*0b57cec5SDimitry Andric       return;
3978*0b57cec5SDimitry Andric     } else if (VT == MVT::v16i8) {
3979*0b57cec5SDimitry Andric       SelectPostStore(Node, 2, AArch64::ST2Twov16b_POST);
3980*0b57cec5SDimitry Andric       return;
3981*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
3982*0b57cec5SDimitry Andric       SelectPostStore(Node, 2, AArch64::ST2Twov4h_POST);
3983*0b57cec5SDimitry Andric       return;
3984*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
3985*0b57cec5SDimitry Andric       SelectPostStore(Node, 2, AArch64::ST2Twov8h_POST);
3986*0b57cec5SDimitry Andric       return;
3987*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
3988*0b57cec5SDimitry Andric       SelectPostStore(Node, 2, AArch64::ST2Twov2s_POST);
3989*0b57cec5SDimitry Andric       return;
3990*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
3991*0b57cec5SDimitry Andric       SelectPostStore(Node, 2, AArch64::ST2Twov4s_POST);
3992*0b57cec5SDimitry Andric       return;
3993*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
3994*0b57cec5SDimitry Andric       SelectPostStore(Node, 2, AArch64::ST2Twov2d_POST);
3995*0b57cec5SDimitry Andric       return;
3996*0b57cec5SDimitry Andric     } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
3997*0b57cec5SDimitry Andric       SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
3998*0b57cec5SDimitry Andric       return;
3999*0b57cec5SDimitry Andric     }
4000*0b57cec5SDimitry Andric     break;
4001*0b57cec5SDimitry Andric   }
4002*0b57cec5SDimitry Andric   case AArch64ISD::ST3post: {
4003*0b57cec5SDimitry Andric     VT = Node->getOperand(1).getValueType();
4004*0b57cec5SDimitry Andric     if (VT == MVT::v8i8) {
4005*0b57cec5SDimitry Andric       SelectPostStore(Node, 3, AArch64::ST3Threev8b_POST);
4006*0b57cec5SDimitry Andric       return;
4007*0b57cec5SDimitry Andric     } else if (VT == MVT::v16i8) {
4008*0b57cec5SDimitry Andric       SelectPostStore(Node, 3, AArch64::ST3Threev16b_POST);
4009*0b57cec5SDimitry Andric       return;
4010*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
4011*0b57cec5SDimitry Andric       SelectPostStore(Node, 3, AArch64::ST3Threev4h_POST);
4012*0b57cec5SDimitry Andric       return;
4013*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
4014*0b57cec5SDimitry Andric       SelectPostStore(Node, 3, AArch64::ST3Threev8h_POST);
4015*0b57cec5SDimitry Andric       return;
4016*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
4017*0b57cec5SDimitry Andric       SelectPostStore(Node, 3, AArch64::ST3Threev2s_POST);
4018*0b57cec5SDimitry Andric       return;
4019*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
4020*0b57cec5SDimitry Andric       SelectPostStore(Node, 3, AArch64::ST3Threev4s_POST);
4021*0b57cec5SDimitry Andric       return;
4022*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
4023*0b57cec5SDimitry Andric       SelectPostStore(Node, 3, AArch64::ST3Threev2d_POST);
4024*0b57cec5SDimitry Andric       return;
4025*0b57cec5SDimitry Andric     } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
4026*0b57cec5SDimitry Andric       SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
4027*0b57cec5SDimitry Andric       return;
4028*0b57cec5SDimitry Andric     }
4029*0b57cec5SDimitry Andric     break;
4030*0b57cec5SDimitry Andric   }
4031*0b57cec5SDimitry Andric   case AArch64ISD::ST4post: {
4032*0b57cec5SDimitry Andric     VT = Node->getOperand(1).getValueType();
4033*0b57cec5SDimitry Andric     if (VT == MVT::v8i8) {
4034*0b57cec5SDimitry Andric       SelectPostStore(Node, 4, AArch64::ST4Fourv8b_POST);
4035*0b57cec5SDimitry Andric       return;
4036*0b57cec5SDimitry Andric     } else if (VT == MVT::v16i8) {
4037*0b57cec5SDimitry Andric       SelectPostStore(Node, 4, AArch64::ST4Fourv16b_POST);
4038*0b57cec5SDimitry Andric       return;
4039*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
4040*0b57cec5SDimitry Andric       SelectPostStore(Node, 4, AArch64::ST4Fourv4h_POST);
4041*0b57cec5SDimitry Andric       return;
4042*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
4043*0b57cec5SDimitry Andric       SelectPostStore(Node, 4, AArch64::ST4Fourv8h_POST);
4044*0b57cec5SDimitry Andric       return;
4045*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
4046*0b57cec5SDimitry Andric       SelectPostStore(Node, 4, AArch64::ST4Fourv2s_POST);
4047*0b57cec5SDimitry Andric       return;
4048*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
4049*0b57cec5SDimitry Andric       SelectPostStore(Node, 4, AArch64::ST4Fourv4s_POST);
4050*0b57cec5SDimitry Andric       return;
4051*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
4052*0b57cec5SDimitry Andric       SelectPostStore(Node, 4, AArch64::ST4Fourv2d_POST);
4053*0b57cec5SDimitry Andric       return;
4054*0b57cec5SDimitry Andric     } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
4055*0b57cec5SDimitry Andric       SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
4056*0b57cec5SDimitry Andric       return;
4057*0b57cec5SDimitry Andric     }
4058*0b57cec5SDimitry Andric     break;
4059*0b57cec5SDimitry Andric   }
4060*0b57cec5SDimitry Andric   case AArch64ISD::ST1x2post: {
4061*0b57cec5SDimitry Andric     VT = Node->getOperand(1).getValueType();
4062*0b57cec5SDimitry Andric     if (VT == MVT::v8i8) {
4063*0b57cec5SDimitry Andric       SelectPostStore(Node, 2, AArch64::ST1Twov8b_POST);
4064*0b57cec5SDimitry Andric       return;
4065*0b57cec5SDimitry Andric     } else if (VT == MVT::v16i8) {
4066*0b57cec5SDimitry Andric       SelectPostStore(Node, 2, AArch64::ST1Twov16b_POST);
4067*0b57cec5SDimitry Andric       return;
4068*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
4069*0b57cec5SDimitry Andric       SelectPostStore(Node, 2, AArch64::ST1Twov4h_POST);
4070*0b57cec5SDimitry Andric       return;
4071*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
4072*0b57cec5SDimitry Andric       SelectPostStore(Node, 2, AArch64::ST1Twov8h_POST);
4073*0b57cec5SDimitry Andric       return;
4074*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
4075*0b57cec5SDimitry Andric       SelectPostStore(Node, 2, AArch64::ST1Twov2s_POST);
4076*0b57cec5SDimitry Andric       return;
4077*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
4078*0b57cec5SDimitry Andric       SelectPostStore(Node, 2, AArch64::ST1Twov4s_POST);
4079*0b57cec5SDimitry Andric       return;
4080*0b57cec5SDimitry Andric     } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
4081*0b57cec5SDimitry Andric       SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
4082*0b57cec5SDimitry Andric       return;
4083*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
4084*0b57cec5SDimitry Andric       SelectPostStore(Node, 2, AArch64::ST1Twov2d_POST);
4085*0b57cec5SDimitry Andric       return;
4086*0b57cec5SDimitry Andric     }
4087*0b57cec5SDimitry Andric     break;
4088*0b57cec5SDimitry Andric   }
4089*0b57cec5SDimitry Andric   case AArch64ISD::ST1x3post: {
4090*0b57cec5SDimitry Andric     VT = Node->getOperand(1).getValueType();
4091*0b57cec5SDimitry Andric     if (VT == MVT::v8i8) {
4092*0b57cec5SDimitry Andric       SelectPostStore(Node, 3, AArch64::ST1Threev8b_POST);
4093*0b57cec5SDimitry Andric       return;
4094*0b57cec5SDimitry Andric     } else if (VT == MVT::v16i8) {
4095*0b57cec5SDimitry Andric       SelectPostStore(Node, 3, AArch64::ST1Threev16b_POST);
4096*0b57cec5SDimitry Andric       return;
4097*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
4098*0b57cec5SDimitry Andric       SelectPostStore(Node, 3, AArch64::ST1Threev4h_POST);
4099*0b57cec5SDimitry Andric       return;
4100*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
4101*0b57cec5SDimitry Andric       SelectPostStore(Node, 3, AArch64::ST1Threev8h_POST);
4102*0b57cec5SDimitry Andric       return;
4103*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
4104*0b57cec5SDimitry Andric       SelectPostStore(Node, 3, AArch64::ST1Threev2s_POST);
4105*0b57cec5SDimitry Andric       return;
4106*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
4107*0b57cec5SDimitry Andric       SelectPostStore(Node, 3, AArch64::ST1Threev4s_POST);
4108*0b57cec5SDimitry Andric       return;
4109*0b57cec5SDimitry Andric     } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
4110*0b57cec5SDimitry Andric       SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
4111*0b57cec5SDimitry Andric       return;
4112*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
4113*0b57cec5SDimitry Andric       SelectPostStore(Node, 3, AArch64::ST1Threev2d_POST);
4114*0b57cec5SDimitry Andric       return;
4115*0b57cec5SDimitry Andric     }
4116*0b57cec5SDimitry Andric     break;
4117*0b57cec5SDimitry Andric   }
4118*0b57cec5SDimitry Andric   case AArch64ISD::ST1x4post: {
4119*0b57cec5SDimitry Andric     VT = Node->getOperand(1).getValueType();
4120*0b57cec5SDimitry Andric     if (VT == MVT::v8i8) {
4121*0b57cec5SDimitry Andric       SelectPostStore(Node, 4, AArch64::ST1Fourv8b_POST);
4122*0b57cec5SDimitry Andric       return;
4123*0b57cec5SDimitry Andric     } else if (VT == MVT::v16i8) {
4124*0b57cec5SDimitry Andric       SelectPostStore(Node, 4, AArch64::ST1Fourv16b_POST);
4125*0b57cec5SDimitry Andric       return;
4126*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i16 || VT == MVT::v4f16) {
4127*0b57cec5SDimitry Andric       SelectPostStore(Node, 4, AArch64::ST1Fourv4h_POST);
4128*0b57cec5SDimitry Andric       return;
4129*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v8f16) {
4130*0b57cec5SDimitry Andric       SelectPostStore(Node, 4, AArch64::ST1Fourv8h_POST);
4131*0b57cec5SDimitry Andric       return;
4132*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
4133*0b57cec5SDimitry Andric       SelectPostStore(Node, 4, AArch64::ST1Fourv2s_POST);
4134*0b57cec5SDimitry Andric       return;
4135*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
4136*0b57cec5SDimitry Andric       SelectPostStore(Node, 4, AArch64::ST1Fourv4s_POST);
4137*0b57cec5SDimitry Andric       return;
4138*0b57cec5SDimitry Andric     } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
4139*0b57cec5SDimitry Andric       SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
4140*0b57cec5SDimitry Andric       return;
4141*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
4142*0b57cec5SDimitry Andric       SelectPostStore(Node, 4, AArch64::ST1Fourv2d_POST);
4143*0b57cec5SDimitry Andric       return;
4144*0b57cec5SDimitry Andric     }
4145*0b57cec5SDimitry Andric     break;
4146*0b57cec5SDimitry Andric   }
4147*0b57cec5SDimitry Andric   case AArch64ISD::ST2LANEpost: {
4148*0b57cec5SDimitry Andric     VT = Node->getOperand(1).getValueType();
4149*0b57cec5SDimitry Andric     if (VT == MVT::v16i8 || VT == MVT::v8i8) {
4150*0b57cec5SDimitry Andric       SelectPostStoreLane(Node, 2, AArch64::ST2i8_POST);
4151*0b57cec5SDimitry Andric       return;
4152*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
4153*0b57cec5SDimitry Andric                VT == MVT::v8f16) {
4154*0b57cec5SDimitry Andric       SelectPostStoreLane(Node, 2, AArch64::ST2i16_POST);
4155*0b57cec5SDimitry Andric       return;
4156*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
4157*0b57cec5SDimitry Andric                VT == MVT::v2f32) {
4158*0b57cec5SDimitry Andric       SelectPostStoreLane(Node, 2, AArch64::ST2i32_POST);
4159*0b57cec5SDimitry Andric       return;
4160*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
4161*0b57cec5SDimitry Andric                VT == MVT::v1f64) {
4162*0b57cec5SDimitry Andric       SelectPostStoreLane(Node, 2, AArch64::ST2i64_POST);
4163*0b57cec5SDimitry Andric       return;
4164*0b57cec5SDimitry Andric     }
4165*0b57cec5SDimitry Andric     break;
4166*0b57cec5SDimitry Andric   }
4167*0b57cec5SDimitry Andric   case AArch64ISD::ST3LANEpost: {
4168*0b57cec5SDimitry Andric     VT = Node->getOperand(1).getValueType();
4169*0b57cec5SDimitry Andric     if (VT == MVT::v16i8 || VT == MVT::v8i8) {
4170*0b57cec5SDimitry Andric       SelectPostStoreLane(Node, 3, AArch64::ST3i8_POST);
4171*0b57cec5SDimitry Andric       return;
4172*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
4173*0b57cec5SDimitry Andric                VT == MVT::v8f16) {
4174*0b57cec5SDimitry Andric       SelectPostStoreLane(Node, 3, AArch64::ST3i16_POST);
4175*0b57cec5SDimitry Andric       return;
4176*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
4177*0b57cec5SDimitry Andric                VT == MVT::v2f32) {
4178*0b57cec5SDimitry Andric       SelectPostStoreLane(Node, 3, AArch64::ST3i32_POST);
4179*0b57cec5SDimitry Andric       return;
4180*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
4181*0b57cec5SDimitry Andric                VT == MVT::v1f64) {
4182*0b57cec5SDimitry Andric       SelectPostStoreLane(Node, 3, AArch64::ST3i64_POST);
4183*0b57cec5SDimitry Andric       return;
4184*0b57cec5SDimitry Andric     }
4185*0b57cec5SDimitry Andric     break;
4186*0b57cec5SDimitry Andric   }
4187*0b57cec5SDimitry Andric   case AArch64ISD::ST4LANEpost: {
4188*0b57cec5SDimitry Andric     VT = Node->getOperand(1).getValueType();
4189*0b57cec5SDimitry Andric     if (VT == MVT::v16i8 || VT == MVT::v8i8) {
4190*0b57cec5SDimitry Andric       SelectPostStoreLane(Node, 4, AArch64::ST4i8_POST);
4191*0b57cec5SDimitry Andric       return;
4192*0b57cec5SDimitry Andric     } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
4193*0b57cec5SDimitry Andric                VT == MVT::v8f16) {
4194*0b57cec5SDimitry Andric       SelectPostStoreLane(Node, 4, AArch64::ST4i16_POST);
4195*0b57cec5SDimitry Andric       return;
4196*0b57cec5SDimitry Andric     } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
4197*0b57cec5SDimitry Andric                VT == MVT::v2f32) {
4198*0b57cec5SDimitry Andric       SelectPostStoreLane(Node, 4, AArch64::ST4i32_POST);
4199*0b57cec5SDimitry Andric       return;
4200*0b57cec5SDimitry Andric     } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
4201*0b57cec5SDimitry Andric                VT == MVT::v1f64) {
4202*0b57cec5SDimitry Andric       SelectPostStoreLane(Node, 4, AArch64::ST4i64_POST);
4203*0b57cec5SDimitry Andric       return;
4204*0b57cec5SDimitry Andric     }
4205*0b57cec5SDimitry Andric     break;
4206*0b57cec5SDimitry Andric   }
4207*0b57cec5SDimitry Andric   }
4208*0b57cec5SDimitry Andric 
4209*0b57cec5SDimitry Andric   // Select the default instruction
4210*0b57cec5SDimitry Andric   SelectCode(Node);
4211*0b57cec5SDimitry Andric }
4212*0b57cec5SDimitry Andric 
4213*0b57cec5SDimitry Andric /// createAArch64ISelDag - This pass converts a legalized DAG into a
4214*0b57cec5SDimitry Andric /// AArch64-specific DAG, ready for instruction scheduling.
4215*0b57cec5SDimitry Andric FunctionPass *llvm::createAArch64ISelDag(AArch64TargetMachine &TM,
4216*0b57cec5SDimitry Andric                                          CodeGenOpt::Level OptLevel) {
4217*0b57cec5SDimitry Andric   return new AArch64DAGToDAGISel(TM, OptLevel);
4218*0b57cec5SDimitry Andric }
4219