1259698Sdim//===-- AArch64InstrNEON.td - NEON support for AArch64 -----*- tablegen -*-===//
2259698Sdim//
3259698Sdim//                     The LLVM Compiler Infrastructure
4259698Sdim//
5259698Sdim// This file is distributed under the University of Illinois Open Source
6259698Sdim// License. See LICENSE.TXT for details.
7259698Sdim//
8259698Sdim//===----------------------------------------------------------------------===//
9259698Sdim//
10259698Sdim// This file describes the AArch64 NEON instruction set.
11259698Sdim//
12259698Sdim//===----------------------------------------------------------------------===//
13259698Sdim
14259698Sdim//===----------------------------------------------------------------------===//
15259698Sdim// NEON-specific DAG Nodes.
16259698Sdim//===----------------------------------------------------------------------===//
17259698Sdimdef Neon_bsl       : SDNode<"AArch64ISD::NEON_BSL", SDTypeProfile<1, 3,
18259698Sdim                      [SDTCisVec<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
19259698Sdim                      SDTCisSameAs<0, 3>]>>;
20259698Sdim
21259698Sdim// (outs Result), (ins Imm, OpCmode)
22259698Sdimdef SDT_Neon_movi : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVT<1, i32>]>;
23259698Sdim
24259698Sdimdef Neon_movi     : SDNode<"AArch64ISD::NEON_MOVIMM", SDT_Neon_movi>;
25259698Sdim
26259698Sdimdef Neon_mvni     : SDNode<"AArch64ISD::NEON_MVNIMM", SDT_Neon_movi>;
27259698Sdim
28259698Sdim// (outs Result), (ins Imm)
29259698Sdimdef Neon_fmovi : SDNode<"AArch64ISD::NEON_FMOVIMM", SDTypeProfile<1, 1,
30259698Sdim                        [SDTCisVec<0>, SDTCisVT<1, i32>]>>;
31259698Sdim
32259698Sdim// (outs Result), (ins LHS, RHS, CondCode)
33259698Sdimdef Neon_cmp : SDNode<"AArch64ISD::NEON_CMP", SDTypeProfile<1, 3,
34259698Sdim                 [SDTCisVec<0>,  SDTCisSameAs<1, 2>]>>;
35259698Sdim
36259698Sdim// (outs Result), (ins LHS, 0/0.0 constant, CondCode)
37259698Sdimdef Neon_cmpz : SDNode<"AArch64ISD::NEON_CMPZ", SDTypeProfile<1, 3,
38259698Sdim                 [SDTCisVec<0>,  SDTCisVec<1>]>>;
39259698Sdim
40259698Sdim// (outs Result), (ins LHS, RHS)
41259698Sdimdef Neon_tst : SDNode<"AArch64ISD::NEON_TST", SDTypeProfile<1, 2,
42259698Sdim                 [SDTCisVec<0>,  SDTCisSameAs<1, 2>]>>;
43259698Sdim
44259698Sdimdef SDTARMVSH : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0, 1>,
45259698Sdim                                     SDTCisVT<2, i32>]>;
46259698Sdimdef Neon_sqrshlImm   : SDNode<"AArch64ISD::NEON_QSHLs", SDTARMVSH>;
47259698Sdimdef Neon_uqrshlImm   : SDNode<"AArch64ISD::NEON_QSHLu", SDTARMVSH>;
48259698Sdim
49259698Sdimdef SDTPERMUTE : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0, 1>,
50259698Sdim                               SDTCisSameAs<0, 2>]>;
51259698Sdimdef Neon_uzp1    : SDNode<"AArch64ISD::NEON_UZP1", SDTPERMUTE>;
52259698Sdimdef Neon_uzp2    : SDNode<"AArch64ISD::NEON_UZP2", SDTPERMUTE>;
53259698Sdimdef Neon_zip1    : SDNode<"AArch64ISD::NEON_ZIP1", SDTPERMUTE>;
54259698Sdimdef Neon_zip2    : SDNode<"AArch64ISD::NEON_ZIP2", SDTPERMUTE>;
55259698Sdimdef Neon_trn1    : SDNode<"AArch64ISD::NEON_TRN1", SDTPERMUTE>;
56259698Sdimdef Neon_trn2    : SDNode<"AArch64ISD::NEON_TRN2", SDTPERMUTE>;
57259698Sdim
58259698Sdimdef SDTVSHUF : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisSameAs<0, 1>]>;
59259698Sdimdef Neon_rev64    : SDNode<"AArch64ISD::NEON_REV64", SDTVSHUF>;
60259698Sdimdef Neon_rev32    : SDNode<"AArch64ISD::NEON_REV32", SDTVSHUF>;
61259698Sdimdef Neon_rev16    : SDNode<"AArch64ISD::NEON_REV16", SDTVSHUF>;
62259698Sdimdef Neon_vdup : SDNode<"AArch64ISD::NEON_VDUP", SDTypeProfile<1, 1,
63259698Sdim                       [SDTCisVec<0>]>>;
64259698Sdimdef Neon_vduplane : SDNode<"AArch64ISD::NEON_VDUPLANE", SDTypeProfile<1, 2,
65259698Sdim                           [SDTCisVec<0>, SDTCisVec<1>, SDTCisVT<2, i64>]>>;
66259698Sdimdef Neon_vextract : SDNode<"AArch64ISD::NEON_VEXTRACT", SDTypeProfile<1, 3,
67259698Sdim                           [SDTCisVec<0>,  SDTCisSameAs<0, 1>,
68259698Sdim                           SDTCisSameAs<0, 2>, SDTCisVT<3, i64>]>>;
69259698Sdim
70259698Sdimdef SDT_assertext : SDTypeProfile<1, 1,
71259698Sdim  [SDTCisInt<0>, SDTCisInt<1>, SDTCisSameAs<1, 0>]>;
72259698Sdimdef assertsext : SDNode<"ISD::AssertSext", SDT_assertext>;
73259698Sdimdef assertzext : SDNode<"ISD::AssertZext", SDT_assertext>;
74259698Sdim
75259698Sdim//===----------------------------------------------------------------------===//
76259698Sdim// Multiclasses
77259698Sdim//===----------------------------------------------------------------------===//
78259698Sdim
79259698Sdimmulticlass NeonI_3VSame_B_sizes<bit u, bits<2> size,  bits<5> opcode,
80259698Sdim                                string asmop, SDPatternOperator opnode8B,
81259698Sdim                                SDPatternOperator opnode16B,
82259698Sdim                                bit Commutable = 0> {
83259698Sdim  let isCommutable = Commutable in {
84259698Sdim    def _8B :  NeonI_3VSame<0b0, u, size, opcode,
85259698Sdim               (outs VPR64:$Rd), (ins VPR64:$Rn, VPR64:$Rm),
86259698Sdim               asmop # "\t$Rd.8b, $Rn.8b, $Rm.8b",
87259698Sdim               [(set (v8i8 VPR64:$Rd),
88259698Sdim                  (v8i8 (opnode8B (v8i8 VPR64:$Rn), (v8i8 VPR64:$Rm))))],
89259698Sdim               NoItinerary>;
90259698Sdim
91259698Sdim    def _16B : NeonI_3VSame<0b1, u, size, opcode,
92259698Sdim               (outs VPR128:$Rd), (ins VPR128:$Rn, VPR128:$Rm),
93259698Sdim               asmop # "\t$Rd.16b, $Rn.16b, $Rm.16b",
94259698Sdim               [(set (v16i8 VPR128:$Rd),
95259698Sdim                  (v16i8 (opnode16B (v16i8 VPR128:$Rn), (v16i8 VPR128:$Rm))))],
96259698Sdim               NoItinerary>;
97259698Sdim  }
98259698Sdim
99259698Sdim}
100259698Sdim
101259698Sdimmulticlass NeonI_3VSame_HS_sizes<bit u, bits<5> opcode,
102259698Sdim                                  string asmop, SDPatternOperator opnode,
103259698Sdim                                  bit Commutable = 0> {
104259698Sdim  let isCommutable = Commutable in {
105259698Sdim    def _4H : NeonI_3VSame<0b0, u, 0b01, opcode,
106259698Sdim              (outs VPR64:$Rd), (ins VPR64:$Rn, VPR64:$Rm),
107259698Sdim              asmop # "\t$Rd.4h, $Rn.4h, $Rm.4h",
108259698Sdim              [(set (v4i16 VPR64:$Rd),
109259698Sdim                 (v4i16 (opnode (v4i16 VPR64:$Rn), (v4i16 VPR64:$Rm))))],
110259698Sdim              NoItinerary>;
111259698Sdim
112259698Sdim    def _8H : NeonI_3VSame<0b1, u, 0b01, opcode,
113259698Sdim              (outs VPR128:$Rd), (ins VPR128:$Rn, VPR128:$Rm),
114259698Sdim              asmop # "\t$Rd.8h, $Rn.8h, $Rm.8h",
115259698Sdim              [(set (v8i16 VPR128:$Rd),
116259698Sdim                 (v8i16 (opnode (v8i16 VPR128:$Rn), (v8i16 VPR128:$Rm))))],
117259698Sdim              NoItinerary>;
118259698Sdim
119259698Sdim    def _2S : NeonI_3VSame<0b0, u, 0b10, opcode,
120259698Sdim              (outs VPR64:$Rd), (ins VPR64:$Rn, VPR64:$Rm),
121259698Sdim              asmop # "\t$Rd.2s, $Rn.2s, $Rm.2s",
122259698Sdim              [(set (v2i32 VPR64:$Rd),
123259698Sdim                 (v2i32 (opnode (v2i32 VPR64:$Rn), (v2i32 VPR64:$Rm))))],
124259698Sdim              NoItinerary>;
125259698Sdim
126259698Sdim    def _4S : NeonI_3VSame<0b1, u, 0b10, opcode,
127259698Sdim              (outs VPR128:$Rd), (ins VPR128:$Rn, VPR128:$Rm),
128259698Sdim              asmop # "\t$Rd.4s, $Rn.4s, $Rm.4s",
129259698Sdim              [(set (v4i32 VPR128:$Rd),
130259698Sdim                 (v4i32 (opnode (v4i32 VPR128:$Rn), (v4i32 VPR128:$Rm))))],
131259698Sdim              NoItinerary>;
132259698Sdim  }
133259698Sdim}
134259698Sdimmulticlass NeonI_3VSame_BHS_sizes<bit u, bits<5> opcode,
135259698Sdim                                  string asmop, SDPatternOperator opnode,
136259698Sdim                                  bit Commutable = 0>
137259698Sdim   : NeonI_3VSame_HS_sizes<u, opcode,  asmop, opnode, Commutable> {
138259698Sdim  let isCommutable = Commutable in {
139259698Sdim    def _8B :  NeonI_3VSame<0b0, u, 0b00, opcode,
140259698Sdim               (outs VPR64:$Rd), (ins VPR64:$Rn, VPR64:$Rm),
141259698Sdim               asmop # "\t$Rd.8b, $Rn.8b, $Rm.8b",
142259698Sdim               [(set (v8i8 VPR64:$Rd),
143259698Sdim                  (v8i8 (opnode (v8i8 VPR64:$Rn), (v8i8 VPR64:$Rm))))],
144259698Sdim               NoItinerary>;
145259698Sdim
146259698Sdim    def _16B : NeonI_3VSame<0b1, u, 0b00, opcode,
147259698Sdim               (outs VPR128:$Rd), (ins VPR128:$Rn, VPR128:$Rm),
148259698Sdim               asmop # "\t$Rd.16b, $Rn.16b, $Rm.16b",
149259698Sdim               [(set (v16i8 VPR128:$Rd),
150259698Sdim                  (v16i8 (opnode (v16i8 VPR128:$Rn), (v16i8 VPR128:$Rm))))],
151259698Sdim               NoItinerary>;
152259698Sdim  }
153259698Sdim}
154259698Sdim
155259698Sdimmulticlass NeonI_3VSame_BHSD_sizes<bit u, bits<5> opcode,
156259698Sdim                                   string asmop, SDPatternOperator opnode,
157259698Sdim                                   bit Commutable = 0>
158259698Sdim   : NeonI_3VSame_BHS_sizes<u, opcode,  asmop, opnode, Commutable> {
159259698Sdim  let isCommutable = Commutable in {
160259698Sdim    def _2D : NeonI_3VSame<0b1, u, 0b11, opcode,
161259698Sdim              (outs VPR128:$Rd), (ins VPR128:$Rn, VPR128:$Rm),
162259698Sdim              asmop # "\t$Rd.2d, $Rn.2d, $Rm.2d",
163259698Sdim              [(set (v2i64 VPR128:$Rd),
164259698Sdim                 (v2i64 (opnode (v2i64 VPR128:$Rn), (v2i64 VPR128:$Rm))))],
165259698Sdim              NoItinerary>;
166259698Sdim  }
167259698Sdim}
168259698Sdim
169259698Sdim// Multiclass NeonI_3VSame_SD_sizes: Operand types are floating point types,
170259698Sdim// but Result types can be integer or floating point types.
171259698Sdimmulticlass NeonI_3VSame_SD_sizes<bit u, bit size, bits<5> opcode,
172259698Sdim                                 string asmop, SDPatternOperator opnode2S,
173259698Sdim                                 SDPatternOperator opnode4S,
174259698Sdim                                 SDPatternOperator opnode2D,
175259698Sdim                                 ValueType ResTy2S, ValueType ResTy4S,
176259698Sdim                                 ValueType ResTy2D, bit Commutable = 0> {
177259698Sdim  let isCommutable = Commutable in {
178259698Sdim    def _2S : NeonI_3VSame<0b0, u, {size, 0b0}, opcode,
179259698Sdim              (outs VPR64:$Rd), (ins VPR64:$Rn, VPR64:$Rm),
180259698Sdim              asmop # "\t$Rd.2s, $Rn.2s, $Rm.2s",
181259698Sdim              [(set (ResTy2S VPR64:$Rd),
182259698Sdim                 (ResTy2S (opnode2S (v2f32 VPR64:$Rn), (v2f32 VPR64:$Rm))))],
183259698Sdim              NoItinerary>;
184259698Sdim
185259698Sdim    def _4S : NeonI_3VSame<0b1, u, {size, 0b0}, opcode,
186259698Sdim              (outs VPR128:$Rd), (ins VPR128:$Rn, VPR128:$Rm),
187259698Sdim              asmop # "\t$Rd.4s, $Rn.4s, $Rm.4s",
188259698Sdim              [(set (ResTy4S VPR128:$Rd),
189259698Sdim                 (ResTy4S (opnode4S (v4f32 VPR128:$Rn), (v4f32 VPR128:$Rm))))],
190259698Sdim              NoItinerary>;
191259698Sdim
192259698Sdim    def _2D : NeonI_3VSame<0b1, u, {size, 0b1}, opcode,
193259698Sdim              (outs VPR128:$Rd), (ins VPR128:$Rn, VPR128:$Rm),
194259698Sdim              asmop # "\t$Rd.2d, $Rn.2d, $Rm.2d",
195259698Sdim              [(set (ResTy2D VPR128:$Rd),
196259698Sdim                 (ResTy2D (opnode2D (v2f64 VPR128:$Rn), (v2f64 VPR128:$Rm))))],
197259698Sdim               NoItinerary>;
198259698Sdim  }
199259698Sdim}
200259698Sdim
201259698Sdim//===----------------------------------------------------------------------===//
202259698Sdim// Instruction Definitions
203259698Sdim//===----------------------------------------------------------------------===//
204259698Sdim
205259698Sdim// Vector Arithmetic Instructions
206259698Sdim
207259698Sdim// Vector Add (Integer and Floating-Point)
208259698Sdim
209259698Sdimdefm ADDvvv :  NeonI_3VSame_BHSD_sizes<0b0, 0b10000, "add", add, 1>;
210259698Sdimdefm FADDvvv : NeonI_3VSame_SD_sizes<0b0, 0b0, 0b11010, "fadd", fadd, fadd, fadd,
211259698Sdim                                     v2f32, v4f32, v2f64, 1>;
212259698Sdim
213259698Sdim// Vector Sub (Integer and Floating-Point)
214259698Sdim
215259698Sdimdefm SUBvvv :  NeonI_3VSame_BHSD_sizes<0b1, 0b10000, "sub", sub, 0>;
216259698Sdimdefm FSUBvvv : NeonI_3VSame_SD_sizes<0b0, 0b1, 0b11010, "fsub", fsub, fsub, fsub,
217259698Sdim                                     v2f32, v4f32, v2f64, 0>;
218259698Sdim
219259698Sdim// Vector Multiply (Integer and Floating-Point)
220259698Sdim
221259698Sdimdefm MULvvv :  NeonI_3VSame_BHS_sizes<0b0, 0b10011, "mul", mul, 1>;
222259698Sdimdefm FMULvvv : NeonI_3VSame_SD_sizes<0b1, 0b0, 0b11011, "fmul", fmul, fmul, fmul,
223259698Sdim                                     v2f32, v4f32, v2f64, 1>;
224259698Sdim
225259698Sdim// Vector Multiply (Polynomial)
226259698Sdim
227259698Sdimdefm PMULvvv : NeonI_3VSame_B_sizes<0b1, 0b00, 0b10011, "pmul",
228259698Sdim                                    int_arm_neon_vmulp, int_arm_neon_vmulp, 1>;
229259698Sdim
230259698Sdim// Vector Multiply-accumulate and Multiply-subtract (Integer)
231259698Sdim
232259698Sdim// class NeonI_3VSame_Constraint_impl: NeonI_3VSame with no data type and
233259698Sdim// two operands constraints.
234259698Sdimclass NeonI_3VSame_Constraint_impl<string asmop, string asmlane,
235259698Sdim  RegisterOperand VPRC, ValueType OpTy, bit q, bit u, bits<2> size,
236259698Sdim  bits<5> opcode, SDPatternOperator opnode>
237259698Sdim  : NeonI_3VSame<q, u, size, opcode,
238259698Sdim    (outs VPRC:$Rd), (ins VPRC:$src, VPRC:$Rn, VPRC:$Rm),
239259698Sdim    asmop # "\t$Rd" # asmlane # ", $Rn" # asmlane # ", $Rm" # asmlane,
240259698Sdim    [(set (OpTy VPRC:$Rd),
241259698Sdim       (OpTy (opnode (OpTy VPRC:$src), (OpTy VPRC:$Rn), (OpTy VPRC:$Rm))))],
242259698Sdim    NoItinerary> {
243259698Sdim  let Constraints = "$src = $Rd";
244259698Sdim}
245259698Sdim
246259698Sdimdef Neon_mla : PatFrag<(ops node:$Ra, node:$Rn, node:$Rm),
247259698Sdim                       (add node:$Ra, (mul node:$Rn, node:$Rm))>;
248259698Sdim
249259698Sdimdef Neon_mls : PatFrag<(ops node:$Ra, node:$Rn, node:$Rm),
250259698Sdim                       (sub node:$Ra, (mul node:$Rn, node:$Rm))>;
251259698Sdim
252259698Sdim
253259698Sdimdef MLAvvv_8B:  NeonI_3VSame_Constraint_impl<"mla", ".8b",  VPR64,  v8i8,
254259698Sdim                                             0b0, 0b0, 0b00, 0b10010, Neon_mla>;
255259698Sdimdef MLAvvv_16B: NeonI_3VSame_Constraint_impl<"mla", ".16b", VPR128, v16i8,
256259698Sdim                                             0b1, 0b0, 0b00, 0b10010, Neon_mla>;
257259698Sdimdef MLAvvv_4H:  NeonI_3VSame_Constraint_impl<"mla", ".4h",  VPR64,  v4i16,
258259698Sdim                                             0b0, 0b0, 0b01, 0b10010, Neon_mla>;
259259698Sdimdef MLAvvv_8H:  NeonI_3VSame_Constraint_impl<"mla", ".8h",  VPR128, v8i16,
260259698Sdim                                             0b1, 0b0, 0b01, 0b10010, Neon_mla>;
261259698Sdimdef MLAvvv_2S:  NeonI_3VSame_Constraint_impl<"mla", ".2s",  VPR64,  v2i32,
262259698Sdim                                             0b0, 0b0, 0b10, 0b10010, Neon_mla>;
263259698Sdimdef MLAvvv_4S:  NeonI_3VSame_Constraint_impl<"mla", ".4s",  VPR128, v4i32,
264259698Sdim                                             0b1, 0b0, 0b10, 0b10010, Neon_mla>;
265259698Sdim
266259698Sdimdef MLSvvv_8B:  NeonI_3VSame_Constraint_impl<"mls", ".8b",  VPR64,  v8i8,
267259698Sdim                                             0b0, 0b1, 0b00, 0b10010, Neon_mls>;
268259698Sdimdef MLSvvv_16B: NeonI_3VSame_Constraint_impl<"mls", ".16b", VPR128, v16i8,
269259698Sdim                                             0b1, 0b1, 0b00, 0b10010, Neon_mls>;
270259698Sdimdef MLSvvv_4H:  NeonI_3VSame_Constraint_impl<"mls", ".4h",  VPR64,  v4i16,
271259698Sdim                                             0b0, 0b1, 0b01, 0b10010, Neon_mls>;
272259698Sdimdef MLSvvv_8H:  NeonI_3VSame_Constraint_impl<"mls", ".8h",  VPR128, v8i16,
273259698Sdim                                             0b1, 0b1, 0b01, 0b10010, Neon_mls>;
274259698Sdimdef MLSvvv_2S:  NeonI_3VSame_Constraint_impl<"mls", ".2s",  VPR64,  v2i32,
275259698Sdim                                             0b0, 0b1, 0b10, 0b10010, Neon_mls>;
276259698Sdimdef MLSvvv_4S:  NeonI_3VSame_Constraint_impl<"mls", ".4s",  VPR128, v4i32,
277259698Sdim                                             0b1, 0b1, 0b10, 0b10010, Neon_mls>;
278259698Sdim
279259698Sdim// Vector Multiply-accumulate and Multiply-subtract (Floating Point)
280259698Sdim
281259698Sdimdef Neon_fmla : PatFrag<(ops node:$Ra, node:$Rn, node:$Rm),
282259698Sdim                        (fadd node:$Ra, (fmul node:$Rn, node:$Rm))>;
283259698Sdim
284259698Sdimdef Neon_fmls : PatFrag<(ops node:$Ra, node:$Rn, node:$Rm),
285259698Sdim                        (fsub node:$Ra, (fmul node:$Rn, node:$Rm))>;
286259698Sdim
287259698Sdimlet Predicates = [HasNEON, UseFusedMAC] in {
288259698Sdimdef FMLAvvv_2S: NeonI_3VSame_Constraint_impl<"fmla", ".2s",  VPR64,  v2f32,
289259698Sdim                                             0b0, 0b0, 0b00, 0b11001, Neon_fmla>;
290259698Sdimdef FMLAvvv_4S: NeonI_3VSame_Constraint_impl<"fmla", ".4s",  VPR128, v4f32,
291259698Sdim                                             0b1, 0b0, 0b00, 0b11001, Neon_fmla>;
292259698Sdimdef FMLAvvv_2D: NeonI_3VSame_Constraint_impl<"fmla", ".2d",  VPR128, v2f64,
293259698Sdim                                             0b1, 0b0, 0b01, 0b11001, Neon_fmla>;
294259698Sdim
295259698Sdimdef FMLSvvv_2S: NeonI_3VSame_Constraint_impl<"fmls", ".2s",  VPR64,  v2f32,
296259698Sdim                                              0b0, 0b0, 0b10, 0b11001, Neon_fmls>;
297259698Sdimdef FMLSvvv_4S: NeonI_3VSame_Constraint_impl<"fmls", ".4s",  VPR128, v4f32,
298259698Sdim                                             0b1, 0b0, 0b10, 0b11001, Neon_fmls>;
299259698Sdimdef FMLSvvv_2D: NeonI_3VSame_Constraint_impl<"fmls", ".2d",  VPR128, v2f64,
300259698Sdim                                             0b1, 0b0, 0b11, 0b11001, Neon_fmls>;
301259698Sdim}
302259698Sdim
303259698Sdim// We're also allowed to match the fma instruction regardless of compile
304259698Sdim// options.
305259698Sdimdef : Pat<(v2f32 (fma VPR64:$Rn, VPR64:$Rm, VPR64:$Ra)),
306259698Sdim          (FMLAvvv_2S VPR64:$Ra, VPR64:$Rn, VPR64:$Rm)>;
307259698Sdimdef : Pat<(v4f32 (fma VPR128:$Rn, VPR128:$Rm, VPR128:$Ra)),
308259698Sdim          (FMLAvvv_4S VPR128:$Ra, VPR128:$Rn, VPR128:$Rm)>;
309259698Sdimdef : Pat<(v2f64 (fma VPR128:$Rn, VPR128:$Rm, VPR128:$Ra)),
310259698Sdim          (FMLAvvv_2D VPR128:$Ra, VPR128:$Rn, VPR128:$Rm)>;
311259698Sdim
312259698Sdimdef : Pat<(v2f32 (fma (fneg VPR64:$Rn), VPR64:$Rm, VPR64:$Ra)),
313259698Sdim          (FMLSvvv_2S VPR64:$Ra, VPR64:$Rn, VPR64:$Rm)>;
314259698Sdimdef : Pat<(v4f32 (fma (fneg VPR128:$Rn), VPR128:$Rm, VPR128:$Ra)),
315259698Sdim          (FMLSvvv_4S VPR128:$Ra, VPR128:$Rn, VPR128:$Rm)>;
316259698Sdimdef : Pat<(v2f64 (fma (fneg VPR128:$Rn), VPR128:$Rm, VPR128:$Ra)),
317259698Sdim          (FMLSvvv_2D VPR128:$Ra, VPR128:$Rn, VPR128:$Rm)>;
318259698Sdim
319259698Sdim// Vector Divide (Floating-Point)
320259698Sdim
321259698Sdimdefm FDIVvvv : NeonI_3VSame_SD_sizes<0b1, 0b0, 0b11111, "fdiv", fdiv, fdiv, fdiv,
322259698Sdim                                     v2f32, v4f32, v2f64, 0>;
323259698Sdim
324259698Sdim// Vector Bitwise Operations
325259698Sdim
326259698Sdim// Vector Bitwise AND
327259698Sdim
328259698Sdimdefm ANDvvv : NeonI_3VSame_B_sizes<0b0, 0b00, 0b00011, "and", and, and, 1>;
329259698Sdim
330259698Sdim// Vector Bitwise Exclusive OR
331259698Sdim
332259698Sdimdefm EORvvv : NeonI_3VSame_B_sizes<0b1, 0b00, 0b00011, "eor", xor, xor, 1>;
333259698Sdim
334259698Sdim// Vector Bitwise OR
335259698Sdim
336259698Sdimdefm ORRvvv : NeonI_3VSame_B_sizes<0b0, 0b10, 0b00011, "orr", or, or, 1>;
337259698Sdim
338259698Sdim// ORR disassembled as MOV if Vn==Vm
339259698Sdim
340259698Sdim// Vector Move - register
341259698Sdim// Alias for ORR if Vn=Vm.
342259698Sdim// FIXME: This is actually the preferred syntax but TableGen can't deal with
343259698Sdim// custom printing of aliases.
344259698Sdimdef : NeonInstAlias<"mov $Rd.8b, $Rn.8b",
345259698Sdim                    (ORRvvv_8B VPR64:$Rd, VPR64:$Rn, VPR64:$Rn), 0>;
346259698Sdimdef : NeonInstAlias<"mov $Rd.16b, $Rn.16b",
347259698Sdim                    (ORRvvv_16B VPR128:$Rd, VPR128:$Rn, VPR128:$Rn), 0>;
348259698Sdim
349259698Sdim// The MOVI instruction takes two immediate operands.  The first is the
350259698Sdim// immediate encoding, while the second is the cmode.  A cmode of 14, or
351259698Sdim// 0b1110, produces a MOVI operation, rather than a MVNI, ORR, or BIC.
352259698Sdimdef Neon_AllZero : PatFrag<(ops), (Neon_movi (i32 0), (i32 14))>;
353259698Sdimdef Neon_AllOne : PatFrag<(ops), (Neon_movi (i32 255), (i32 14))>;
354259698Sdim
355259698Sdimdef Neon_not8B  : PatFrag<(ops node:$in),
356259698Sdim                          (xor node:$in, (bitconvert (v8i8 Neon_AllOne)))>;
357259698Sdimdef Neon_not16B : PatFrag<(ops node:$in),
358259698Sdim                          (xor node:$in, (bitconvert (v16i8 Neon_AllOne)))>;
359259698Sdim
360259698Sdimdef Neon_orn8B : PatFrag<(ops node:$Rn, node:$Rm),
361259698Sdim                         (or node:$Rn, (Neon_not8B node:$Rm))>;
362259698Sdim
363259698Sdimdef Neon_orn16B : PatFrag<(ops node:$Rn, node:$Rm),
364259698Sdim                          (or node:$Rn, (Neon_not16B node:$Rm))>;
365259698Sdim
366259698Sdimdef Neon_bic8B : PatFrag<(ops node:$Rn, node:$Rm),
367259698Sdim                         (and node:$Rn, (Neon_not8B node:$Rm))>;
368259698Sdim
369259698Sdimdef Neon_bic16B : PatFrag<(ops node:$Rn, node:$Rm),
370259698Sdim                          (and node:$Rn, (Neon_not16B node:$Rm))>;
371259698Sdim
372259698Sdim
373259698Sdim// Vector Bitwise OR NOT - register
374259698Sdim
375259698Sdimdefm ORNvvv : NeonI_3VSame_B_sizes<0b0, 0b11, 0b00011, "orn",
376259698Sdim                                   Neon_orn8B, Neon_orn16B, 0>;
377259698Sdim
378259698Sdim// Vector Bitwise Bit Clear (AND NOT) - register
379259698Sdim
380259698Sdimdefm BICvvv : NeonI_3VSame_B_sizes<0b0, 0b01, 0b00011, "bic",
381259698Sdim                                   Neon_bic8B, Neon_bic16B, 0>;
382259698Sdim
383259698Sdimmulticlass Neon_bitwise2V_patterns<SDPatternOperator opnode8B,
384259698Sdim                                   SDPatternOperator opnode16B,
385259698Sdim                                   Instruction INST8B,
386259698Sdim                                   Instruction INST16B> {
387259698Sdim  def : Pat<(v2i32 (opnode8B VPR64:$Rn, VPR64:$Rm)),
388259698Sdim            (INST8B VPR64:$Rn, VPR64:$Rm)>;
389259698Sdim  def : Pat<(v4i16 (opnode8B VPR64:$Rn, VPR64:$Rm)),
390259698Sdim            (INST8B VPR64:$Rn, VPR64:$Rm)>;
391259698Sdim  def : Pat<(v1i64 (opnode8B VPR64:$Rn, VPR64:$Rm)),
392259698Sdim            (INST8B VPR64:$Rn, VPR64:$Rm)>;
393259698Sdim  def : Pat<(v4i32 (opnode16B VPR128:$Rn, VPR128:$Rm)),
394259698Sdim            (INST16B VPR128:$Rn, VPR128:$Rm)>;
395259698Sdim  def : Pat<(v8i16 (opnode16B VPR128:$Rn, VPR128:$Rm)),
396259698Sdim            (INST16B VPR128:$Rn, VPR128:$Rm)>;
397259698Sdim  def : Pat<(v2i64 (opnode16B VPR128:$Rn, VPR128:$Rm)),
398259698Sdim            (INST16B VPR128:$Rn, VPR128:$Rm)>;
399259698Sdim}
400259698Sdim
401259698Sdim// Additional patterns for bitwise instructions AND, EOR, ORR, BIC, ORN
402259698Sdimdefm : Neon_bitwise2V_patterns<and, and, ANDvvv_8B, ANDvvv_16B>;
403259698Sdimdefm : Neon_bitwise2V_patterns<or,  or,  ORRvvv_8B, ORRvvv_16B>;
404259698Sdimdefm : Neon_bitwise2V_patterns<xor, xor, EORvvv_8B, EORvvv_16B>;
405259698Sdimdefm : Neon_bitwise2V_patterns<Neon_bic8B, Neon_bic16B, BICvvv_8B, BICvvv_16B>;
406259698Sdimdefm : Neon_bitwise2V_patterns<Neon_orn8B, Neon_orn16B, ORNvvv_8B, ORNvvv_16B>;
407259698Sdim
408259698Sdim//   Vector Bitwise Select
409259698Sdimdef BSLvvv_8B  : NeonI_3VSame_Constraint_impl<"bsl", ".8b",  VPR64, v8i8,
410259698Sdim                                              0b0, 0b1, 0b01, 0b00011, Neon_bsl>;
411259698Sdim
412259698Sdimdef BSLvvv_16B : NeonI_3VSame_Constraint_impl<"bsl", ".16b", VPR128, v16i8,
413259698Sdim                                              0b1, 0b1, 0b01, 0b00011, Neon_bsl>;
414259698Sdim
415259698Sdimmulticlass Neon_bitwise3V_patterns<SDPatternOperator opnode,
416259698Sdim                                   Instruction INST8B,
417259698Sdim                                   Instruction INST16B> {
418259698Sdim  // Disassociate type from instruction definition
419259698Sdim  def : Pat<(v2i32 (opnode VPR64:$src,VPR64:$Rn, VPR64:$Rm)),
420259698Sdim            (INST8B VPR64:$src, VPR64:$Rn, VPR64:$Rm)>;
421259698Sdim  def : Pat<(v4i16 (opnode VPR64:$src, VPR64:$Rn, VPR64:$Rm)),
422259698Sdim            (INST8B VPR64:$src, VPR64:$Rn, VPR64:$Rm)>;
423259698Sdim  def : Pat<(v1i64 (opnode VPR64:$src, VPR64:$Rn, VPR64:$Rm)),
424259698Sdim            (INST8B VPR64:$src, VPR64:$Rn, VPR64:$Rm)>;
425259698Sdim  def : Pat<(v4i32 (opnode VPR128:$src, VPR128:$Rn, VPR128:$Rm)),
426259698Sdim            (INST16B VPR128:$src, VPR128:$Rn, VPR128:$Rm)>;
427259698Sdim  def : Pat<(v8i16 (opnode VPR128:$src, VPR128:$Rn, VPR128:$Rm)),
428259698Sdim            (INST16B VPR128:$src, VPR128:$Rn, VPR128:$Rm)>;
429259698Sdim  def : Pat<(v2i64 (opnode VPR128:$src, VPR128:$Rn, VPR128:$Rm)),
430259698Sdim            (INST16B VPR128:$src, VPR128:$Rn, VPR128:$Rm)>;
431259698Sdim
432259698Sdim  // Allow to match BSL instruction pattern with non-constant operand
433259698Sdim  def : Pat<(v8i8 (or (and VPR64:$Rn, VPR64:$Rd),
434259698Sdim                    (and VPR64:$Rm, (Neon_not8B VPR64:$Rd)))),
435259698Sdim          (INST8B VPR64:$Rd, VPR64:$Rn, VPR64:$Rm)>;
436259698Sdim  def : Pat<(v4i16 (or (and VPR64:$Rn, VPR64:$Rd),
437259698Sdim                     (and VPR64:$Rm, (Neon_not8B VPR64:$Rd)))),
438259698Sdim          (INST8B VPR64:$Rd, VPR64:$Rn, VPR64:$Rm)>;
439259698Sdim  def : Pat<(v2i32 (or (and VPR64:$Rn, VPR64:$Rd),
440259698Sdim                     (and VPR64:$Rm, (Neon_not8B VPR64:$Rd)))),
441259698Sdim          (INST8B VPR64:$Rd, VPR64:$Rn, VPR64:$Rm)>;
442259698Sdim  def : Pat<(v1i64 (or (and VPR64:$Rn, VPR64:$Rd),
443259698Sdim                     (and VPR64:$Rm, (Neon_not8B VPR64:$Rd)))),
444259698Sdim          (INST8B VPR64:$Rd, VPR64:$Rn, VPR64:$Rm)>;
445259698Sdim  def : Pat<(v16i8 (or (and VPR128:$Rn, VPR128:$Rd),
446259698Sdim                     (and VPR128:$Rm, (Neon_not16B VPR128:$Rd)))),
447259698Sdim          (INST16B VPR128:$Rd, VPR128:$Rn, VPR128:$Rm)>;
448259698Sdim  def : Pat<(v8i16 (or (and VPR128:$Rn, VPR128:$Rd),
449259698Sdim                     (and VPR128:$Rm, (Neon_not16B VPR128:$Rd)))),
450259698Sdim          (INST16B VPR128:$Rd, VPR128:$Rn, VPR128:$Rm)>;
451259698Sdim  def : Pat<(v4i32 (or (and VPR128:$Rn, VPR128:$Rd),
452259698Sdim                     (and VPR128:$Rm, (Neon_not16B VPR128:$Rd)))),
453259698Sdim          (INST16B VPR128:$Rd, VPR128:$Rn, VPR128:$Rm)>;
454259698Sdim  def : Pat<(v2i64 (or (and VPR128:$Rn, VPR128:$Rd),
455259698Sdim                     (and VPR128:$Rm, (Neon_not16B VPR128:$Rd)))),
456259698Sdim          (INST16B VPR128:$Rd, VPR128:$Rn, VPR128:$Rm)>;
457259698Sdim
458259698Sdim  // Allow to match llvm.arm.* intrinsics.
459259698Sdim  def : Pat<(v8i8 (int_arm_neon_vbsl (v8i8 VPR64:$src),
460259698Sdim                    (v8i8 VPR64:$Rn), (v8i8 VPR64:$Rm))),
461259698Sdim            (INST8B VPR64:$src, VPR64:$Rn, VPR64:$Rm)>;
462259698Sdim  def : Pat<(v4i16 (int_arm_neon_vbsl (v4i16 VPR64:$src),
463259698Sdim                    (v4i16 VPR64:$Rn), (v4i16 VPR64:$Rm))),
464259698Sdim            (INST8B VPR64:$src, VPR64:$Rn, VPR64:$Rm)>;
465259698Sdim  def : Pat<(v2i32 (int_arm_neon_vbsl (v2i32 VPR64:$src),
466259698Sdim                    (v2i32 VPR64:$Rn), (v2i32 VPR64:$Rm))),
467259698Sdim            (INST8B VPR64:$src, VPR64:$Rn, VPR64:$Rm)>;
468259698Sdim  def : Pat<(v1i64 (int_arm_neon_vbsl (v1i64 VPR64:$src),
469259698Sdim                    (v1i64 VPR64:$Rn), (v1i64 VPR64:$Rm))),
470259698Sdim            (INST8B VPR64:$src, VPR64:$Rn, VPR64:$Rm)>;
471259698Sdim  def : Pat<(v2f32 (int_arm_neon_vbsl (v2f32 VPR64:$src),
472259698Sdim                    (v2f32 VPR64:$Rn), (v2f32 VPR64:$Rm))),
473259698Sdim            (INST8B VPR64:$src, VPR64:$Rn, VPR64:$Rm)>;
474259698Sdim  def : Pat<(v1f64 (int_arm_neon_vbsl (v1f64 VPR64:$src),
475259698Sdim                    (v1f64 VPR64:$Rn), (v1f64 VPR64:$Rm))),
476259698Sdim            (INST8B VPR64:$src, VPR64:$Rn, VPR64:$Rm)>;
477259698Sdim  def : Pat<(v16i8 (int_arm_neon_vbsl (v16i8 VPR128:$src),
478259698Sdim                    (v16i8 VPR128:$Rn), (v16i8 VPR128:$Rm))),
479259698Sdim            (INST16B VPR128:$src, VPR128:$Rn, VPR128:$Rm)>;
480259698Sdim  def : Pat<(v8i16 (int_arm_neon_vbsl (v8i16 VPR128:$src),
481259698Sdim                    (v8i16 VPR128:$Rn), (v8i16 VPR128:$Rm))),
482259698Sdim            (INST16B VPR128:$src, VPR128:$Rn, VPR128:$Rm)>;
483259698Sdim  def : Pat<(v4i32 (int_arm_neon_vbsl (v4i32 VPR128:$src),
484259698Sdim                    (v4i32 VPR128:$Rn), (v4i32 VPR128:$Rm))),
485259698Sdim            (INST16B VPR128:$src, VPR128:$Rn, VPR128:$Rm)>;
486259698Sdim  def : Pat<(v2i64 (int_arm_neon_vbsl (v2i64 VPR128:$src),
487259698Sdim                    (v2i64 VPR128:$Rn), (v2i64 VPR128:$Rm))),
488259698Sdim            (INST16B VPR128:$src, VPR128:$Rn, VPR128:$Rm)>;
489259698Sdim  def : Pat<(v4f32 (int_arm_neon_vbsl (v4f32 VPR128:$src),
490259698Sdim                    (v4f32 VPR128:$Rn), (v4f32 VPR128:$Rm))),
491259698Sdim            (INST16B VPR128:$src, VPR128:$Rn, VPR128:$Rm)>;
492259698Sdim  def : Pat<(v2f64 (int_arm_neon_vbsl (v2f64 VPR128:$src),
493259698Sdim                    (v2f64 VPR128:$Rn), (v2f64 VPR128:$Rm))),
494259698Sdim            (INST16B VPR128:$src, VPR128:$Rn, VPR128:$Rm)>;
495259698Sdim}
496259698Sdim
497259698Sdim// Additional patterns for bitwise instruction BSL
498259698Sdimdefm: Neon_bitwise3V_patterns<Neon_bsl, BSLvvv_8B, BSLvvv_16B>;
499259698Sdim
500259698Sdimdef Neon_NoBSLop : PatFrag<(ops node:$src, node:$Rn, node:$Rm),
501259698Sdim                           (Neon_bsl node:$src, node:$Rn, node:$Rm),
502259698Sdim                           [{ (void)N; return false; }]>;
503259698Sdim
504259698Sdim// Vector Bitwise Insert if True
505259698Sdim
506259698Sdimdef BITvvv_8B  : NeonI_3VSame_Constraint_impl<"bit", ".8b", VPR64,   v8i8,
507259698Sdim                   0b0, 0b1, 0b10, 0b00011, Neon_NoBSLop>;
508259698Sdimdef BITvvv_16B : NeonI_3VSame_Constraint_impl<"bit", ".16b", VPR128, v16i8,
509259698Sdim                   0b1, 0b1, 0b10, 0b00011, Neon_NoBSLop>;
510259698Sdim
511259698Sdim// Vector Bitwise Insert if False
512259698Sdim
513259698Sdimdef BIFvvv_8B  : NeonI_3VSame_Constraint_impl<"bif", ".8b", VPR64,  v8i8,
514259698Sdim                                0b0, 0b1, 0b11, 0b00011, Neon_NoBSLop>;
515259698Sdimdef BIFvvv_16B : NeonI_3VSame_Constraint_impl<"bif", ".16b", VPR128, v16i8,
516259698Sdim                                0b1, 0b1, 0b11, 0b00011, Neon_NoBSLop>;
517259698Sdim
518259698Sdim// Vector Absolute Difference and Accumulate (Signed, Unsigned)
519259698Sdim
520259698Sdimdef Neon_uaba : PatFrag<(ops node:$Ra, node:$Rn, node:$Rm),
521259698Sdim                       (add node:$Ra, (int_arm_neon_vabdu node:$Rn, node:$Rm))>;
522259698Sdimdef Neon_saba : PatFrag<(ops node:$Ra, node:$Rn, node:$Rm),
523259698Sdim                       (add node:$Ra, (int_arm_neon_vabds node:$Rn, node:$Rm))>;
524259698Sdim
525259698Sdim// Vector Absolute Difference and Accumulate (Unsigned)
526259698Sdimdef UABAvvv_8B :  NeonI_3VSame_Constraint_impl<"uaba", ".8b",  VPR64,  v8i8,
527259698Sdim                    0b0, 0b1, 0b00, 0b01111, Neon_uaba>;
528259698Sdimdef UABAvvv_16B : NeonI_3VSame_Constraint_impl<"uaba", ".16b", VPR128, v16i8,
529259698Sdim                    0b1, 0b1, 0b00, 0b01111, Neon_uaba>;
530259698Sdimdef UABAvvv_4H :  NeonI_3VSame_Constraint_impl<"uaba", ".4h",  VPR64,  v4i16,
531259698Sdim                    0b0, 0b1, 0b01, 0b01111, Neon_uaba>;
532259698Sdimdef UABAvvv_8H :  NeonI_3VSame_Constraint_impl<"uaba", ".8h",  VPR128, v8i16,
533259698Sdim                    0b1, 0b1, 0b01, 0b01111, Neon_uaba>;
534259698Sdimdef UABAvvv_2S :  NeonI_3VSame_Constraint_impl<"uaba", ".2s",  VPR64,  v2i32,
535259698Sdim                    0b0, 0b1, 0b10, 0b01111, Neon_uaba>;
536259698Sdimdef UABAvvv_4S :  NeonI_3VSame_Constraint_impl<"uaba", ".4s",  VPR128, v4i32,
537259698Sdim                    0b1, 0b1, 0b10, 0b01111, Neon_uaba>;
538259698Sdim
539259698Sdim// Vector Absolute Difference and Accumulate (Signed)
540259698Sdimdef SABAvvv_8B :  NeonI_3VSame_Constraint_impl<"saba", ".8b",  VPR64,  v8i8,
541259698Sdim                    0b0, 0b0, 0b00, 0b01111, Neon_saba>;
542259698Sdimdef SABAvvv_16B : NeonI_3VSame_Constraint_impl<"saba", ".16b", VPR128, v16i8,
543259698Sdim                    0b1, 0b0, 0b00, 0b01111, Neon_saba>;
544259698Sdimdef SABAvvv_4H :  NeonI_3VSame_Constraint_impl<"saba", ".4h",  VPR64,  v4i16,
545259698Sdim                    0b0, 0b0, 0b01, 0b01111, Neon_saba>;
546259698Sdimdef SABAvvv_8H :  NeonI_3VSame_Constraint_impl<"saba", ".8h",  VPR128, v8i16,
547259698Sdim                    0b1, 0b0, 0b01, 0b01111, Neon_saba>;
548259698Sdimdef SABAvvv_2S :  NeonI_3VSame_Constraint_impl<"saba", ".2s",  VPR64,  v2i32,
549259698Sdim                    0b0, 0b0, 0b10, 0b01111, Neon_saba>;
550259698Sdimdef SABAvvv_4S :  NeonI_3VSame_Constraint_impl<"saba", ".4s",  VPR128, v4i32,
551259698Sdim                    0b1, 0b0, 0b10, 0b01111, Neon_saba>;
552259698Sdim
553259698Sdim
554259698Sdim// Vector Absolute Difference (Signed, Unsigned)
555259698Sdimdefm UABDvvv : NeonI_3VSame_BHS_sizes<0b1, 0b01110, "uabd", int_arm_neon_vabdu, 0>;
556259698Sdimdefm SABDvvv : NeonI_3VSame_BHS_sizes<0b0, 0b01110, "sabd", int_arm_neon_vabds, 0>;
557259698Sdim
558259698Sdim// Vector Absolute Difference (Floating Point)
559259698Sdimdefm FABDvvv: NeonI_3VSame_SD_sizes<0b1, 0b1, 0b11010, "fabd",
560259698Sdim                                    int_arm_neon_vabds, int_arm_neon_vabds,
561259698Sdim                                    int_arm_neon_vabds, v2f32, v4f32, v2f64, 0>;
562259698Sdim
563259698Sdim// Vector Reciprocal Step (Floating Point)
564259698Sdimdefm FRECPSvvv : NeonI_3VSame_SD_sizes<0b0, 0b0, 0b11111, "frecps",
565259698Sdim                                       int_arm_neon_vrecps, int_arm_neon_vrecps,
566259698Sdim                                       int_arm_neon_vrecps,
567259698Sdim                                       v2f32, v4f32, v2f64, 0>;
568259698Sdim
569259698Sdim// Vector Reciprocal Square Root Step (Floating Point)
570259698Sdimdefm FRSQRTSvvv : NeonI_3VSame_SD_sizes<0b0, 0b1, 0b11111, "frsqrts",
571259698Sdim                                        int_arm_neon_vrsqrts,
572259698Sdim                                        int_arm_neon_vrsqrts,
573259698Sdim                                        int_arm_neon_vrsqrts,
574259698Sdim                                        v2f32, v4f32, v2f64, 0>;
575259698Sdim
576259698Sdim// Vector Comparisons
577259698Sdim
578259698Sdimdef Neon_cmeq : PatFrag<(ops node:$lhs, node:$rhs),
579259698Sdim                        (Neon_cmp node:$lhs, node:$rhs, SETEQ)>;
580259698Sdimdef Neon_cmphs : PatFrag<(ops node:$lhs, node:$rhs),
581259698Sdim                         (Neon_cmp node:$lhs, node:$rhs, SETUGE)>;
582259698Sdimdef Neon_cmge : PatFrag<(ops node:$lhs, node:$rhs),
583259698Sdim                        (Neon_cmp node:$lhs, node:$rhs, SETGE)>;
584259698Sdimdef Neon_cmhi : PatFrag<(ops node:$lhs, node:$rhs),
585259698Sdim                        (Neon_cmp node:$lhs, node:$rhs, SETUGT)>;
586259698Sdimdef Neon_cmgt : PatFrag<(ops node:$lhs, node:$rhs),
587259698Sdim                        (Neon_cmp node:$lhs, node:$rhs, SETGT)>;
588259698Sdim
589259698Sdim// NeonI_compare_aliases class: swaps register operands to implement
590259698Sdim// comparison aliases, e.g., CMLE is alias for CMGE with operands reversed.
591259698Sdimclass NeonI_compare_aliases<string asmop, string asmlane,
592259698Sdim                            Instruction inst, RegisterOperand VPRC>
593259698Sdim  : NeonInstAlias<asmop # "\t$Rd" # asmlane #", $Rn" # asmlane #
594259698Sdim                    ", $Rm" # asmlane,
595259698Sdim                  (inst VPRC:$Rd, VPRC:$Rm, VPRC:$Rn), 0b0>;
596259698Sdim
597259698Sdim// Vector Comparisons (Integer)
598259698Sdim
599259698Sdim// Vector Compare Mask Equal (Integer)
600259698Sdimlet isCommutable =1 in {
601259698Sdimdefm CMEQvvv : NeonI_3VSame_BHSD_sizes<0b1, 0b10001, "cmeq", Neon_cmeq, 0>;
602259698Sdim}
603259698Sdim
604259698Sdim// Vector Compare Mask Higher or Same (Unsigned Integer)
605259698Sdimdefm CMHSvvv : NeonI_3VSame_BHSD_sizes<0b1, 0b00111, "cmhs", Neon_cmphs, 0>;
606259698Sdim
607259698Sdim// Vector Compare Mask Greater Than or Equal (Integer)
608259698Sdimdefm CMGEvvv : NeonI_3VSame_BHSD_sizes<0b0, 0b00111, "cmge", Neon_cmge, 0>;
609259698Sdim
610259698Sdim// Vector Compare Mask Higher (Unsigned Integer)
611259698Sdimdefm CMHIvvv : NeonI_3VSame_BHSD_sizes<0b1, 0b00110, "cmhi", Neon_cmhi, 0>;
612259698Sdim
613259698Sdim// Vector Compare Mask Greater Than (Integer)
614259698Sdimdefm CMGTvvv : NeonI_3VSame_BHSD_sizes<0b0, 0b00110, "cmgt", Neon_cmgt, 0>;
615259698Sdim
616259698Sdim// Vector Compare Mask Bitwise Test (Integer)
617259698Sdimdefm CMTSTvvv:  NeonI_3VSame_BHSD_sizes<0b0, 0b10001, "cmtst", Neon_tst, 0>;
618259698Sdim
619259698Sdim// Vector Compare Mask Less or Same (Unsigned Integer)
620259698Sdim// CMLS is alias for CMHS with operands reversed.
621259698Sdimdef CMLSvvv_8B  : NeonI_compare_aliases<"cmls", ".8b",  CMHSvvv_8B,  VPR64>;
622259698Sdimdef CMLSvvv_16B : NeonI_compare_aliases<"cmls", ".16b", CMHSvvv_16B, VPR128>;
623259698Sdimdef CMLSvvv_4H  : NeonI_compare_aliases<"cmls", ".4h",  CMHSvvv_4H,  VPR64>;
624259698Sdimdef CMLSvvv_8H  : NeonI_compare_aliases<"cmls", ".8h",  CMHSvvv_8H,  VPR128>;
625259698Sdimdef CMLSvvv_2S  : NeonI_compare_aliases<"cmls", ".2s",  CMHSvvv_2S,  VPR64>;
626259698Sdimdef CMLSvvv_4S  : NeonI_compare_aliases<"cmls", ".4s",  CMHSvvv_4S,  VPR128>;
627259698Sdimdef CMLSvvv_2D  : NeonI_compare_aliases<"cmls", ".2d",  CMHSvvv_2D,  VPR128>;
628259698Sdim
629259698Sdim// Vector Compare Mask Less Than or Equal (Integer)
630259698Sdim// CMLE is alias for CMGE with operands reversed.
631259698Sdimdef CMLEvvv_8B  : NeonI_compare_aliases<"cmle", ".8b",  CMGEvvv_8B,  VPR64>;
632259698Sdimdef CMLEvvv_16B : NeonI_compare_aliases<"cmle", ".16b", CMGEvvv_16B, VPR128>;
633259698Sdimdef CMLEvvv_4H  : NeonI_compare_aliases<"cmle", ".4h",  CMGEvvv_4H,  VPR64>;
634259698Sdimdef CMLEvvv_8H  : NeonI_compare_aliases<"cmle", ".8h",  CMGEvvv_8H,  VPR128>;
635259698Sdimdef CMLEvvv_2S  : NeonI_compare_aliases<"cmle", ".2s",  CMGEvvv_2S,  VPR64>;
636259698Sdimdef CMLEvvv_4S  : NeonI_compare_aliases<"cmle", ".4s",  CMGEvvv_4S,  VPR128>;
637259698Sdimdef CMLEvvv_2D  : NeonI_compare_aliases<"cmle", ".2d",  CMGEvvv_2D,  VPR128>;
638259698Sdim
639259698Sdim// Vector Compare Mask Lower (Unsigned Integer)
640259698Sdim// CMLO is alias for CMHI with operands reversed.
641259698Sdimdef CMLOvvv_8B  : NeonI_compare_aliases<"cmlo", ".8b",  CMHIvvv_8B,  VPR64>;
642259698Sdimdef CMLOvvv_16B : NeonI_compare_aliases<"cmlo", ".16b", CMHIvvv_16B, VPR128>;
643259698Sdimdef CMLOvvv_4H  : NeonI_compare_aliases<"cmlo", ".4h",  CMHIvvv_4H,  VPR64>;
644259698Sdimdef CMLOvvv_8H  : NeonI_compare_aliases<"cmlo", ".8h",  CMHIvvv_8H,  VPR128>;
645259698Sdimdef CMLOvvv_2S  : NeonI_compare_aliases<"cmlo", ".2s",  CMHIvvv_2S,  VPR64>;
646259698Sdimdef CMLOvvv_4S  : NeonI_compare_aliases<"cmlo", ".4s",  CMHIvvv_4S,  VPR128>;
647259698Sdimdef CMLOvvv_2D  : NeonI_compare_aliases<"cmlo", ".2d",  CMHIvvv_2D,  VPR128>;
648259698Sdim
649259698Sdim// Vector Compare Mask Less Than (Integer)
650259698Sdim// CMLT is alias for CMGT with operands reversed.
651259698Sdimdef CMLTvvv_8B  : NeonI_compare_aliases<"cmlt", ".8b",  CMGTvvv_8B,  VPR64>;
652259698Sdimdef CMLTvvv_16B : NeonI_compare_aliases<"cmlt", ".16b", CMGTvvv_16B, VPR128>;
653259698Sdimdef CMLTvvv_4H  : NeonI_compare_aliases<"cmlt", ".4h",  CMGTvvv_4H,  VPR64>;
654259698Sdimdef CMLTvvv_8H  : NeonI_compare_aliases<"cmlt", ".8h",  CMGTvvv_8H,  VPR128>;
655259698Sdimdef CMLTvvv_2S  : NeonI_compare_aliases<"cmlt", ".2s",  CMGTvvv_2S,  VPR64>;
656259698Sdimdef CMLTvvv_4S  : NeonI_compare_aliases<"cmlt", ".4s",  CMGTvvv_4S,  VPR128>;
657259698Sdimdef CMLTvvv_2D  : NeonI_compare_aliases<"cmlt", ".2d",  CMGTvvv_2D,  VPR128>;
658259698Sdim
659259698Sdim
660259698Sdimdef neon_uimm0_asmoperand : AsmOperandClass
661259698Sdim{
662259698Sdim  let Name = "UImm0";
663259698Sdim  let PredicateMethod = "isUImm<0>";
664259698Sdim  let RenderMethod = "addImmOperands";
665259698Sdim}
666259698Sdim
667259698Sdimdef neon_uimm0 : Operand<i32>, ImmLeaf<i32, [{return Imm == 0;}]> {
668259698Sdim  let ParserMatchClass = neon_uimm0_asmoperand;
669259698Sdim  let PrintMethod = "printNeonUImm0Operand";
670259698Sdim
671259698Sdim}
672259698Sdim
673259698Sdimmulticlass NeonI_cmpz_sizes<bit u, bits<5> opcode, string asmop, CondCode CC>
674259698Sdim{
675259698Sdim  def _8B :  NeonI_2VMisc<0b0, u, 0b00, opcode,
676259698Sdim             (outs VPR64:$Rd), (ins VPR64:$Rn, neon_uimm0:$Imm),
677259698Sdim             asmop # "\t$Rd.8b, $Rn.8b, $Imm",
678259698Sdim             [(set (v8i8 VPR64:$Rd),
679259698Sdim                (v8i8 (Neon_cmpz (v8i8 VPR64:$Rn), (i32 imm:$Imm), CC)))],
680259698Sdim             NoItinerary>;
681259698Sdim
682259698Sdim  def _16B : NeonI_2VMisc<0b1, u, 0b00, opcode,
683259698Sdim             (outs VPR128:$Rd), (ins VPR128:$Rn, neon_uimm0:$Imm),
684259698Sdim             asmop # "\t$Rd.16b, $Rn.16b, $Imm",
685259698Sdim             [(set (v16i8 VPR128:$Rd),
686259698Sdim                (v16i8 (Neon_cmpz (v16i8 VPR128:$Rn), (i32 imm:$Imm), CC)))],
687259698Sdim             NoItinerary>;
688259698Sdim
689259698Sdim  def _4H : NeonI_2VMisc<0b0, u, 0b01, opcode,
690259698Sdim            (outs VPR64:$Rd), (ins VPR64:$Rn, neon_uimm0:$Imm),
691259698Sdim            asmop # "\t$Rd.4h, $Rn.4h, $Imm",
692259698Sdim            [(set (v4i16 VPR64:$Rd),
693259698Sdim               (v4i16 (Neon_cmpz (v4i16 VPR64:$Rn), (i32 imm:$Imm), CC)))],
694259698Sdim            NoItinerary>;
695259698Sdim
696259698Sdim  def _8H : NeonI_2VMisc<0b1, u, 0b01, opcode,
697259698Sdim            (outs VPR128:$Rd), (ins VPR128:$Rn, neon_uimm0:$Imm),
698259698Sdim            asmop # "\t$Rd.8h, $Rn.8h, $Imm",
699259698Sdim            [(set (v8i16 VPR128:$Rd),
700259698Sdim               (v8i16 (Neon_cmpz (v8i16 VPR128:$Rn), (i32 imm:$Imm), CC)))],
701259698Sdim            NoItinerary>;
702259698Sdim
703259698Sdim  def _2S : NeonI_2VMisc<0b0, u, 0b10, opcode,
704259698Sdim            (outs VPR64:$Rd), (ins VPR64:$Rn, neon_uimm0:$Imm),
705259698Sdim            asmop # "\t$Rd.2s, $Rn.2s, $Imm",
706259698Sdim            [(set (v2i32 VPR64:$Rd),
707259698Sdim               (v2i32 (Neon_cmpz (v2i32 VPR64:$Rn), (i32 imm:$Imm), CC)))],
708259698Sdim            NoItinerary>;
709259698Sdim
710259698Sdim  def _4S : NeonI_2VMisc<0b1, u, 0b10, opcode,
711259698Sdim            (outs VPR128:$Rd), (ins VPR128:$Rn, neon_uimm0:$Imm),
712259698Sdim            asmop # "\t$Rd.4s, $Rn.4s, $Imm",
713259698Sdim            [(set (v4i32 VPR128:$Rd),
714259698Sdim               (v4i32 (Neon_cmpz (v4i32 VPR128:$Rn), (i32 imm:$Imm), CC)))],
715259698Sdim            NoItinerary>;
716259698Sdim
717259698Sdim  def _2D : NeonI_2VMisc<0b1, u, 0b11, opcode,
718259698Sdim            (outs VPR128:$Rd), (ins VPR128:$Rn, neon_uimm0:$Imm),
719259698Sdim            asmop # "\t$Rd.2d, $Rn.2d, $Imm",
720259698Sdim            [(set (v2i64 VPR128:$Rd),
721259698Sdim               (v2i64 (Neon_cmpz (v2i64 VPR128:$Rn), (i32 imm:$Imm), CC)))],
722259698Sdim            NoItinerary>;
723259698Sdim}
724259698Sdim
725259698Sdim// Vector Compare Mask Equal to Zero (Integer)
726259698Sdimdefm CMEQvvi : NeonI_cmpz_sizes<0b0, 0b01001, "cmeq", SETEQ>;
727259698Sdim
728259698Sdim// Vector Compare Mask Greater Than or Equal to Zero (Signed Integer)
729259698Sdimdefm CMGEvvi : NeonI_cmpz_sizes<0b1, 0b01000, "cmge", SETGE>;
730259698Sdim
731259698Sdim// Vector Compare Mask Greater Than Zero (Signed Integer)
732259698Sdimdefm CMGTvvi : NeonI_cmpz_sizes<0b0, 0b01000, "cmgt", SETGT>;
733259698Sdim
734259698Sdim// Vector Compare Mask Less Than or Equal To Zero (Signed Integer)
735259698Sdimdefm CMLEvvi : NeonI_cmpz_sizes<0b1, 0b01001, "cmle", SETLE>;
736259698Sdim
737259698Sdim// Vector Compare Mask Less Than Zero (Signed Integer)
738259698Sdimdefm CMLTvvi : NeonI_cmpz_sizes<0b0, 0b01010, "cmlt", SETLT>;
739259698Sdim
740259698Sdim// Vector Comparisons (Floating Point)
741259698Sdim
742259698Sdim// Vector Compare Mask Equal (Floating Point)
743259698Sdimlet isCommutable =1 in {
744259698Sdimdefm FCMEQvvv : NeonI_3VSame_SD_sizes<0b0, 0b0, 0b11100, "fcmeq", Neon_cmeq,
745259698Sdim                                      Neon_cmeq, Neon_cmeq,
746259698Sdim                                      v2i32, v4i32, v2i64, 0>;
747259698Sdim}
748259698Sdim
749259698Sdim// Vector Compare Mask Greater Than Or Equal (Floating Point)
750259698Sdimdefm FCMGEvvv : NeonI_3VSame_SD_sizes<0b1, 0b0, 0b11100, "fcmge", Neon_cmge,
751259698Sdim                                      Neon_cmge, Neon_cmge,
752259698Sdim                                      v2i32, v4i32, v2i64, 0>;
753259698Sdim
754259698Sdim// Vector Compare Mask Greater Than (Floating Point)
755259698Sdimdefm FCMGTvvv : NeonI_3VSame_SD_sizes<0b1, 0b1, 0b11100, "fcmgt", Neon_cmgt,
756259698Sdim                                      Neon_cmgt, Neon_cmgt,
757259698Sdim                                      v2i32, v4i32, v2i64, 0>;
758259698Sdim
759259698Sdim// Vector Compare Mask Less Than Or Equal (Floating Point)
760259698Sdim// FCMLE is alias for FCMGE with operands reversed.
761259698Sdimdef FCMLEvvv_2S  : NeonI_compare_aliases<"fcmle", ".2s",  FCMGEvvv_2S,  VPR64>;
762259698Sdimdef FCMLEvvv_4S  : NeonI_compare_aliases<"fcmle", ".4s",  FCMGEvvv_4S,  VPR128>;
763259698Sdimdef FCMLEvvv_2D  : NeonI_compare_aliases<"fcmle", ".2d",  FCMGEvvv_2D,  VPR128>;
764259698Sdim
765259698Sdim// Vector Compare Mask Less Than (Floating Point)
766259698Sdim// FCMLT is alias for FCMGT with operands reversed.
767259698Sdimdef FCMLTvvv_2S  : NeonI_compare_aliases<"fcmlt", ".2s",  FCMGTvvv_2S,  VPR64>;
768259698Sdimdef FCMLTvvv_4S  : NeonI_compare_aliases<"fcmlt", ".4s",  FCMGTvvv_4S,  VPR128>;
769259698Sdimdef FCMLTvvv_2D  : NeonI_compare_aliases<"fcmlt", ".2d",  FCMGTvvv_2D,  VPR128>;
770259698Sdim
771259698Sdim
772259698Sdimmulticlass NeonI_fpcmpz_sizes<bit u, bit size, bits<5> opcode,
773259698Sdim                              string asmop, CondCode CC>
774259698Sdim{
775259698Sdim  def _2S : NeonI_2VMisc<0b0, u, {size, 0b0}, opcode,
776259698Sdim            (outs VPR64:$Rd), (ins VPR64:$Rn, fpz32:$FPImm),
777259698Sdim            asmop # "\t$Rd.2s, $Rn.2s, $FPImm",
778259698Sdim            [(set (v2i32 VPR64:$Rd),
779259698Sdim               (v2i32 (Neon_cmpz (v2f32 VPR64:$Rn), (f32 fpimm:$FPImm), CC)))],
780259698Sdim            NoItinerary>;
781259698Sdim
782259698Sdim  def _4S : NeonI_2VMisc<0b1, u, {size, 0b0}, opcode,
783259698Sdim            (outs VPR128:$Rd), (ins VPR128:$Rn, fpz32:$FPImm),
784259698Sdim            asmop # "\t$Rd.4s, $Rn.4s, $FPImm",
785259698Sdim            [(set (v4i32 VPR128:$Rd),
786259698Sdim               (v4i32 (Neon_cmpz (v4f32 VPR128:$Rn), (f32 fpimm:$FPImm), CC)))],
787259698Sdim            NoItinerary>;
788259698Sdim
789259698Sdim  def _2D : NeonI_2VMisc<0b1, u, {size, 0b1}, opcode,
790259698Sdim            (outs VPR128:$Rd), (ins VPR128:$Rn, fpz32:$FPImm),
791259698Sdim            asmop # "\t$Rd.2d, $Rn.2d, $FPImm",
792259698Sdim            [(set (v2i64 VPR128:$Rd),
793259698Sdim               (v2i64 (Neon_cmpz (v2f64 VPR128:$Rn), (f32 fpimm:$FPImm), CC)))],
794259698Sdim            NoItinerary>;
795259698Sdim}
796259698Sdim
797259698Sdim// Vector Compare Mask Equal to Zero (Floating Point)
798259698Sdimdefm FCMEQvvi : NeonI_fpcmpz_sizes<0b0, 0b1, 0b01101, "fcmeq", SETEQ>;
799259698Sdim
800259698Sdim// Vector Compare Mask Greater Than or Equal to Zero (Floating Point)
801259698Sdimdefm FCMGEvvi : NeonI_fpcmpz_sizes<0b1, 0b1, 0b01100, "fcmge", SETGE>;
802259698Sdim
803259698Sdim// Vector Compare Mask Greater Than Zero (Floating Point)
804259698Sdimdefm FCMGTvvi : NeonI_fpcmpz_sizes<0b0, 0b1, 0b01100, "fcmgt", SETGT>;
805259698Sdim
806259698Sdim// Vector Compare Mask Less Than or Equal To Zero (Floating Point)
807259698Sdimdefm FCMLEvvi : NeonI_fpcmpz_sizes<0b1, 0b1, 0b01101, "fcmle", SETLE>;
808259698Sdim
809259698Sdim// Vector Compare Mask Less Than Zero (Floating Point)
810259698Sdimdefm FCMLTvvi : NeonI_fpcmpz_sizes<0b0, 0b1, 0b01110, "fcmlt", SETLT>;
811259698Sdim
812259698Sdim// Vector Absolute Comparisons (Floating Point)
813259698Sdim
814259698Sdim// Vector Absolute Compare Mask Greater Than Or Equal (Floating Point)
815259698Sdimdefm FACGEvvv : NeonI_3VSame_SD_sizes<0b1, 0b0, 0b11101, "facge",
816259698Sdim                                      int_arm_neon_vacged, int_arm_neon_vacgeq,
817259698Sdim                                      int_aarch64_neon_vacgeq,
818259698Sdim                                      v2i32, v4i32, v2i64, 0>;
819259698Sdim
820259698Sdim// Vector Absolute Compare Mask Greater Than (Floating Point)
821259698Sdimdefm FACGTvvv : NeonI_3VSame_SD_sizes<0b1, 0b1, 0b11101, "facgt",
822259698Sdim                                      int_arm_neon_vacgtd, int_arm_neon_vacgtq,
823259698Sdim                                      int_aarch64_neon_vacgtq,
824259698Sdim                                      v2i32, v4i32, v2i64, 0>;
825259698Sdim
826259698Sdim// Vector Absolute Compare Mask Less Than Or Equal (Floating Point)
827259698Sdim// FACLE is alias for FACGE with operands reversed.
828259698Sdimdef FACLEvvv_2S  : NeonI_compare_aliases<"facle", ".2s",  FACGEvvv_2S,  VPR64>;
829259698Sdimdef FACLEvvv_4S  : NeonI_compare_aliases<"facle", ".4s",  FACGEvvv_4S,  VPR128>;
830259698Sdimdef FACLEvvv_2D  : NeonI_compare_aliases<"facle", ".2d",  FACGEvvv_2D,  VPR128>;
831259698Sdim
832259698Sdim// Vector Absolute Compare Mask Less Than (Floating Point)
833259698Sdim// FACLT is alias for FACGT with operands reversed.
834259698Sdimdef FACLTvvv_2S  : NeonI_compare_aliases<"faclt", ".2s",  FACGTvvv_2S,  VPR64>;
835259698Sdimdef FACLTvvv_4S  : NeonI_compare_aliases<"faclt", ".4s",  FACGTvvv_4S,  VPR128>;
836259698Sdimdef FACLTvvv_2D  : NeonI_compare_aliases<"faclt", ".2d",  FACGTvvv_2D,  VPR128>;
837259698Sdim
838259698Sdim// Vector halving add (Integer Signed, Unsigned)
839259698Sdimdefm SHADDvvv :  NeonI_3VSame_BHS_sizes<0b0, 0b00000, "shadd",
840259698Sdim                                        int_arm_neon_vhadds, 1>;
841259698Sdimdefm UHADDvvv :  NeonI_3VSame_BHS_sizes<0b1, 0b00000, "uhadd",
842259698Sdim                                        int_arm_neon_vhaddu, 1>;
843259698Sdim
844259698Sdim// Vector halving sub (Integer Signed, Unsigned)
845259698Sdimdefm SHSUBvvv :  NeonI_3VSame_BHS_sizes<0b0, 0b00100, "shsub",
846259698Sdim                                        int_arm_neon_vhsubs, 0>;
847259698Sdimdefm UHSUBvvv :  NeonI_3VSame_BHS_sizes<0b1, 0b00100, "uhsub",
848259698Sdim                                        int_arm_neon_vhsubu, 0>;
849259698Sdim
850259698Sdim// Vector rouding halving add (Integer Signed, Unsigned)
851259698Sdimdefm SRHADDvvv :  NeonI_3VSame_BHS_sizes<0b0, 0b00010, "srhadd",
852259698Sdim                                         int_arm_neon_vrhadds, 1>;
853259698Sdimdefm URHADDvvv :  NeonI_3VSame_BHS_sizes<0b1, 0b00010, "urhadd",
854259698Sdim                                         int_arm_neon_vrhaddu, 1>;
855259698Sdim
856259698Sdim// Vector Saturating add (Integer Signed, Unsigned)
857259698Sdimdefm SQADDvvv :  NeonI_3VSame_BHSD_sizes<0b0, 0b00001, "sqadd",
858259698Sdim                   int_arm_neon_vqadds, 1>;
859259698Sdimdefm UQADDvvv :  NeonI_3VSame_BHSD_sizes<0b1, 0b00001, "uqadd",
860259698Sdim                   int_arm_neon_vqaddu, 1>;
861259698Sdim
862259698Sdim// Vector Saturating sub (Integer Signed, Unsigned)
863259698Sdimdefm SQSUBvvv :  NeonI_3VSame_BHSD_sizes<0b0, 0b00101, "sqsub",
864259698Sdim                   int_arm_neon_vqsubs, 1>;
865259698Sdimdefm UQSUBvvv :  NeonI_3VSame_BHSD_sizes<0b1, 0b00101, "uqsub",
866259698Sdim                   int_arm_neon_vqsubu, 1>;
867259698Sdim
868259698Sdim// Vector Shift Left (Signed and Unsigned Integer)
869259698Sdimdefm SSHLvvv : NeonI_3VSame_BHSD_sizes<0b0, 0b01000, "sshl",
870259698Sdim                 int_arm_neon_vshifts, 1>;
871259698Sdimdefm USHLvvv : NeonI_3VSame_BHSD_sizes<0b1, 0b01000, "ushl",
872259698Sdim                 int_arm_neon_vshiftu, 1>;
873259698Sdim
874259698Sdim// Vector Saturating Shift Left (Signed and Unsigned Integer)
875259698Sdimdefm SQSHLvvv : NeonI_3VSame_BHSD_sizes<0b0, 0b01001, "sqshl",
876259698Sdim                  int_arm_neon_vqshifts, 1>;
877259698Sdimdefm UQSHLvvv : NeonI_3VSame_BHSD_sizes<0b1, 0b01001, "uqshl",
878259698Sdim                  int_arm_neon_vqshiftu, 1>;
879259698Sdim
880259698Sdim// Vector Rouding Shift Left (Signed and Unsigned Integer)
881259698Sdimdefm SRSHLvvv : NeonI_3VSame_BHSD_sizes<0b0, 0b01010, "srshl",
882259698Sdim                  int_arm_neon_vrshifts, 1>;
883259698Sdimdefm URSHLvvv : NeonI_3VSame_BHSD_sizes<0b1, 0b01010, "urshl",
884259698Sdim                  int_arm_neon_vrshiftu, 1>;
885259698Sdim
886259698Sdim// Vector Saturating Rouding Shift Left (Signed and Unsigned Integer)
887259698Sdimdefm SQRSHLvvv : NeonI_3VSame_BHSD_sizes<0b0, 0b01011, "sqrshl",
888259698Sdim                   int_arm_neon_vqrshifts, 1>;
889259698Sdimdefm UQRSHLvvv : NeonI_3VSame_BHSD_sizes<0b1, 0b01011, "uqrshl",
890259698Sdim                   int_arm_neon_vqrshiftu, 1>;
891259698Sdim
892259698Sdim// Vector Maximum (Signed and Unsigned Integer)
893259698Sdimdefm SMAXvvv : NeonI_3VSame_BHS_sizes<0b0, 0b01100, "smax", int_arm_neon_vmaxs, 1>;
894259698Sdimdefm UMAXvvv : NeonI_3VSame_BHS_sizes<0b1, 0b01100, "umax", int_arm_neon_vmaxu, 1>;
895259698Sdim
896259698Sdim// Vector Minimum (Signed and Unsigned Integer)
897259698Sdimdefm SMINvvv : NeonI_3VSame_BHS_sizes<0b0, 0b01101, "smin", int_arm_neon_vmins, 1>;
898259698Sdimdefm UMINvvv : NeonI_3VSame_BHS_sizes<0b1, 0b01101, "umin", int_arm_neon_vminu, 1>;
899259698Sdim
900259698Sdim// Vector Maximum (Floating Point)
901259698Sdimdefm FMAXvvv : NeonI_3VSame_SD_sizes<0b0, 0b0, 0b11110, "fmax",
902259698Sdim                                     int_arm_neon_vmaxs, int_arm_neon_vmaxs,
903259698Sdim                                     int_arm_neon_vmaxs, v2f32, v4f32, v2f64, 1>;
904259698Sdim
905259698Sdim// Vector Minimum (Floating Point)
906259698Sdimdefm FMINvvv : NeonI_3VSame_SD_sizes<0b0, 0b1, 0b11110, "fmin",
907259698Sdim                                     int_arm_neon_vmins, int_arm_neon_vmins,
908259698Sdim                                     int_arm_neon_vmins, v2f32, v4f32, v2f64, 1>;
909259698Sdim
910259698Sdim// Vector maxNum (Floating Point) -  prefer a number over a quiet NaN)
911259698Sdimdefm FMAXNMvvv : NeonI_3VSame_SD_sizes<0b0, 0b0, 0b11000, "fmaxnm",
912259698Sdim                                       int_aarch64_neon_vmaxnm,
913259698Sdim                                       int_aarch64_neon_vmaxnm,
914259698Sdim                                       int_aarch64_neon_vmaxnm,
915259698Sdim                                       v2f32, v4f32, v2f64, 1>;
916259698Sdim
917259698Sdim// Vector minNum (Floating Point) - prefer a number over a quiet NaN)
918259698Sdimdefm FMINNMvvv : NeonI_3VSame_SD_sizes<0b0, 0b1, 0b11000, "fminnm",
919259698Sdim                                       int_aarch64_neon_vminnm,
920259698Sdim                                       int_aarch64_neon_vminnm,
921259698Sdim                                       int_aarch64_neon_vminnm,
922259698Sdim                                       v2f32, v4f32, v2f64, 1>;
923259698Sdim
924259698Sdim// Vector Maximum Pairwise (Signed and Unsigned Integer)
925259698Sdimdefm SMAXPvvv : NeonI_3VSame_BHS_sizes<0b0, 0b10100, "smaxp", int_arm_neon_vpmaxs, 1>;
926259698Sdimdefm UMAXPvvv : NeonI_3VSame_BHS_sizes<0b1, 0b10100, "umaxp", int_arm_neon_vpmaxu, 1>;
927259698Sdim
928259698Sdim// Vector Minimum Pairwise (Signed and Unsigned Integer)
929259698Sdimdefm SMINPvvv : NeonI_3VSame_BHS_sizes<0b0, 0b10101, "sminp", int_arm_neon_vpmins, 1>;
930259698Sdimdefm UMINPvvv : NeonI_3VSame_BHS_sizes<0b1, 0b10101, "uminp", int_arm_neon_vpminu, 1>;
931259698Sdim
932259698Sdim// Vector Maximum Pairwise (Floating Point)
933259698Sdimdefm FMAXPvvv : NeonI_3VSame_SD_sizes<0b1, 0b0, 0b11110, "fmaxp",
934259698Sdim                                     int_arm_neon_vpmaxs, int_arm_neon_vpmaxs,
935259698Sdim                                     int_arm_neon_vpmaxs, v2f32, v4f32, v2f64, 1>;
936259698Sdim
937259698Sdim// Vector Minimum Pairwise (Floating Point)
938259698Sdimdefm FMINPvvv : NeonI_3VSame_SD_sizes<0b1, 0b1, 0b11110, "fminp",
939259698Sdim                                     int_arm_neon_vpmins, int_arm_neon_vpmins,
940259698Sdim                                     int_arm_neon_vpmins, v2f32, v4f32, v2f64, 1>;
941259698Sdim
942259698Sdim// Vector maxNum Pairwise (Floating Point) -  prefer a number over a quiet NaN)
943259698Sdimdefm FMAXNMPvvv : NeonI_3VSame_SD_sizes<0b1, 0b0, 0b11000, "fmaxnmp",
944259698Sdim                                       int_aarch64_neon_vpmaxnm,
945259698Sdim                                       int_aarch64_neon_vpmaxnm,
946259698Sdim                                       int_aarch64_neon_vpmaxnm,
947259698Sdim                                       v2f32, v4f32, v2f64, 1>;
948259698Sdim
949259698Sdim// Vector minNum Pairwise (Floating Point) -  prefer a number over a quiet NaN)
950259698Sdimdefm FMINNMPvvv : NeonI_3VSame_SD_sizes<0b1, 0b1, 0b11000, "fminnmp",
951259698Sdim                                       int_aarch64_neon_vpminnm,
952259698Sdim                                       int_aarch64_neon_vpminnm,
953259698Sdim                                       int_aarch64_neon_vpminnm,
954259698Sdim                                       v2f32, v4f32, v2f64, 1>;
955259698Sdim
956259698Sdim// Vector Addition Pairwise (Integer)
957259698Sdimdefm ADDP : NeonI_3VSame_BHSD_sizes<0b0, 0b10111, "addp", int_arm_neon_vpadd, 1>;
958259698Sdim
959259698Sdim// Vector Addition Pairwise (Floating Point)
960259698Sdimdefm FADDP : NeonI_3VSame_SD_sizes<0b1, 0b0, 0b11010, "faddp",
961259698Sdim                                       int_arm_neon_vpadd,
962259698Sdim                                       int_arm_neon_vpadd,
963259698Sdim                                       int_arm_neon_vpadd,
964259698Sdim                                       v2f32, v4f32, v2f64, 1>;
965259698Sdim
966259698Sdim// Vector Saturating Doubling Multiply High
967259698Sdimdefm SQDMULHvvv : NeonI_3VSame_HS_sizes<0b0, 0b10110, "sqdmulh",
968259698Sdim                    int_arm_neon_vqdmulh, 1>;
969259698Sdim
970259698Sdim// Vector Saturating Rouding Doubling Multiply High
971259698Sdimdefm SQRDMULHvvv : NeonI_3VSame_HS_sizes<0b1, 0b10110, "sqrdmulh",
972259698Sdim                     int_arm_neon_vqrdmulh, 1>;
973259698Sdim
974259698Sdim// Vector Multiply Extended (Floating Point)
975259698Sdimdefm FMULXvvv : NeonI_3VSame_SD_sizes<0b0, 0b0, 0b11011, "fmulx",
976259698Sdim                                      int_aarch64_neon_vmulx,
977259698Sdim                                      int_aarch64_neon_vmulx,
978259698Sdim                                      int_aarch64_neon_vmulx,
979259698Sdim                                      v2f32, v4f32, v2f64, 1>;
980259698Sdim
981259698Sdim// Vector Immediate Instructions
982259698Sdim
983259698Sdimmulticlass neon_mov_imm_shift_asmoperands<string PREFIX>
984259698Sdim{
985259698Sdim  def _asmoperand : AsmOperandClass
986259698Sdim    {
987259698Sdim      let Name = "NeonMovImmShift" # PREFIX;
988259698Sdim      let RenderMethod = "addNeonMovImmShift" # PREFIX # "Operands";
989259698Sdim      let PredicateMethod = "isNeonMovImmShift" # PREFIX;
990259698Sdim    }
991259698Sdim}
992259698Sdim
993259698Sdim// Definition of vector immediates shift operands
994259698Sdim
995259698Sdim// The selectable use-cases extract the shift operation
996259698Sdim// information from the OpCmode fields encoded in the immediate.
997259698Sdimdef neon_mod_shift_imm_XFORM : SDNodeXForm<imm, [{
998259698Sdim  uint64_t OpCmode = N->getZExtValue();
999259698Sdim  unsigned ShiftImm;
1000259698Sdim  unsigned ShiftOnesIn;
1001259698Sdim  unsigned HasShift =
1002259698Sdim    A64Imms::decodeNeonModShiftImm(OpCmode, ShiftImm, ShiftOnesIn);
1003259698Sdim  if (!HasShift) return SDValue();
1004259698Sdim  return CurDAG->getTargetConstant(ShiftImm, MVT::i32);
1005259698Sdim}]>;
1006259698Sdim
1007259698Sdim// Vector immediates shift operands which accept LSL and MSL
1008259698Sdim// shift operators with shift value in the range of 0, 8, 16, 24 (LSL),
1009259698Sdim// or 0, 8 (LSLH) or 8, 16 (MSL).
1010259698Sdimdefm neon_mov_imm_LSL : neon_mov_imm_shift_asmoperands<"LSL">;
1011259698Sdimdefm neon_mov_imm_MSL : neon_mov_imm_shift_asmoperands<"MSL">;
1012259698Sdim// LSLH restricts shift amount to  0, 8 out of 0, 8, 16, 24
1013259698Sdimdefm neon_mov_imm_LSLH : neon_mov_imm_shift_asmoperands<"LSLH">;
1014259698Sdim
1015259698Sdimmulticlass neon_mov_imm_shift_operands<string PREFIX,
1016259698Sdim                                       string HALF, string ISHALF, code pred>
1017259698Sdim{
1018259698Sdim   def _operand : Operand<i32>, ImmLeaf<i32, pred, neon_mod_shift_imm_XFORM>
1019259698Sdim    {
1020259698Sdim      let PrintMethod =
1021259698Sdim        "printNeonMovImmShiftOperand<A64SE::" # PREFIX # ", " # ISHALF # ">";
1022259698Sdim      let DecoderMethod =
1023259698Sdim        "DecodeNeonMovImmShiftOperand<A64SE::" # PREFIX # ", " # ISHALF # ">";
1024259698Sdim      let ParserMatchClass =
1025259698Sdim        !cast<AsmOperandClass>("neon_mov_imm_" # PREFIX # HALF # "_asmoperand");
1026259698Sdim    }
1027259698Sdim}
1028259698Sdim
1029259698Sdimdefm neon_mov_imm_LSL  : neon_mov_imm_shift_operands<"LSL", "", "false", [{
1030259698Sdim  unsigned ShiftImm;
1031259698Sdim  unsigned ShiftOnesIn;
1032259698Sdim  unsigned HasShift =
1033259698Sdim    A64Imms::decodeNeonModShiftImm(Imm, ShiftImm, ShiftOnesIn);
1034259698Sdim  return (HasShift && !ShiftOnesIn);
1035259698Sdim}]>;
1036259698Sdim
1037259698Sdimdefm neon_mov_imm_MSL  : neon_mov_imm_shift_operands<"MSL", "", "false", [{
1038259698Sdim  unsigned ShiftImm;
1039259698Sdim  unsigned ShiftOnesIn;
1040259698Sdim  unsigned HasShift =
1041259698Sdim    A64Imms::decodeNeonModShiftImm(Imm, ShiftImm, ShiftOnesIn);
1042259698Sdim  return (HasShift && ShiftOnesIn);
1043259698Sdim}]>;
1044259698Sdim
1045259698Sdimdefm neon_mov_imm_LSLH  : neon_mov_imm_shift_operands<"LSL", "H", "true", [{
1046259698Sdim  unsigned ShiftImm;
1047259698Sdim  unsigned ShiftOnesIn;
1048259698Sdim  unsigned HasShift =
1049259698Sdim    A64Imms::decodeNeonModShiftImm(Imm, ShiftImm, ShiftOnesIn);
1050259698Sdim  return (HasShift && !ShiftOnesIn);
1051259698Sdim}]>;
1052259698Sdim
1053259698Sdimdef neon_uimm1_asmoperand : AsmOperandClass
1054259698Sdim{
1055259698Sdim  let Name = "UImm1";
1056259698Sdim  let PredicateMethod = "isUImm<1>";
1057259698Sdim  let RenderMethod = "addImmOperands";
1058259698Sdim}
1059259698Sdim
1060259698Sdimdef neon_uimm2_asmoperand : AsmOperandClass
1061259698Sdim{
1062259698Sdim  let Name = "UImm2";
1063259698Sdim  let PredicateMethod = "isUImm<2>";
1064259698Sdim  let RenderMethod = "addImmOperands";
1065259698Sdim}
1066259698Sdim
1067259698Sdimdef neon_uimm8_asmoperand : AsmOperandClass
1068259698Sdim{
1069259698Sdim  let Name = "UImm8";
1070259698Sdim  let PredicateMethod = "isUImm<8>";
1071259698Sdim  let RenderMethod = "addImmOperands";
1072259698Sdim}
1073259698Sdim
1074259698Sdimdef neon_uimm8 : Operand<i32>, ImmLeaf<i32, [{(void)Imm; return true;}]> {
1075259698Sdim  let ParserMatchClass = neon_uimm8_asmoperand;
1076259698Sdim  let PrintMethod = "printUImmHexOperand";
1077259698Sdim}
1078259698Sdim
1079259698Sdimdef neon_uimm64_mask_asmoperand : AsmOperandClass
1080259698Sdim{
1081259698Sdim  let Name = "NeonUImm64Mask";
1082259698Sdim  let PredicateMethod = "isNeonUImm64Mask";
1083259698Sdim  let RenderMethod = "addNeonUImm64MaskOperands";
1084259698Sdim}
1085259698Sdim
1086259698Sdim// MCOperand for 64-bit bytemask with each byte having only the
1087259698Sdim// value 0x00 and 0xff is encoded as an unsigned 8-bit value
1088259698Sdimdef neon_uimm64_mask : Operand<i32>, ImmLeaf<i32, [{(void)Imm; return true;}]> {
1089259698Sdim  let ParserMatchClass = neon_uimm64_mask_asmoperand;
1090259698Sdim  let PrintMethod = "printNeonUImm64MaskOperand";
1091259698Sdim}
1092259698Sdim
1093259698Sdimmulticlass NeonI_mov_imm_lsl_sizes<string asmop, bit op,
1094259698Sdim                                   SDPatternOperator opnode>
1095259698Sdim{
1096259698Sdim    // shift zeros, per word
1097259698Sdim    def _2S  : NeonI_1VModImm<0b0, op,
1098259698Sdim                              (outs VPR64:$Rd),
1099259698Sdim                              (ins neon_uimm8:$Imm,
1100259698Sdim                                neon_mov_imm_LSL_operand:$Simm),
1101259698Sdim                              !strconcat(asmop, "\t$Rd.2s, $Imm$Simm"),
1102259698Sdim                              [(set (v2i32 VPR64:$Rd),
1103259698Sdim                                 (v2i32 (opnode (timm:$Imm),
1104259698Sdim                                   (neon_mov_imm_LSL_operand:$Simm))))],
1105259698Sdim                              NoItinerary> {
1106259698Sdim       bits<2> Simm;
1107259698Sdim       let cmode = {0b0, Simm{1}, Simm{0}, 0b0};
1108259698Sdim     }
1109259698Sdim
1110259698Sdim    def _4S  : NeonI_1VModImm<0b1, op,
1111259698Sdim                              (outs VPR128:$Rd),
1112259698Sdim                              (ins neon_uimm8:$Imm,
1113259698Sdim                                neon_mov_imm_LSL_operand:$Simm),
1114259698Sdim                              !strconcat(asmop, "\t$Rd.4s, $Imm$Simm"),
1115259698Sdim                              [(set (v4i32 VPR128:$Rd),
1116259698Sdim                                 (v4i32 (opnode (timm:$Imm),
1117259698Sdim                                   (neon_mov_imm_LSL_operand:$Simm))))],
1118259698Sdim                              NoItinerary> {
1119259698Sdim      bits<2> Simm;
1120259698Sdim      let cmode = {0b0, Simm{1}, Simm{0}, 0b0};
1121259698Sdim    }
1122259698Sdim
1123259698Sdim    // shift zeros, per halfword
1124259698Sdim    def _4H  : NeonI_1VModImm<0b0, op,
1125259698Sdim                              (outs VPR64:$Rd),
1126259698Sdim                              (ins neon_uimm8:$Imm,
1127259698Sdim                                neon_mov_imm_LSLH_operand:$Simm),
1128259698Sdim                              !strconcat(asmop, "\t$Rd.4h, $Imm$Simm"),
1129259698Sdim                              [(set (v4i16 VPR64:$Rd),
1130259698Sdim                                 (v4i16 (opnode (timm:$Imm),
1131259698Sdim                                   (neon_mov_imm_LSLH_operand:$Simm))))],
1132259698Sdim                              NoItinerary> {
1133259698Sdim      bit  Simm;
1134259698Sdim      let cmode = {0b1, 0b0, Simm, 0b0};
1135259698Sdim    }
1136259698Sdim
1137259698Sdim    def _8H  : NeonI_1VModImm<0b1, op,
1138259698Sdim                              (outs VPR128:$Rd),
1139259698Sdim                              (ins neon_uimm8:$Imm,
1140259698Sdim                                neon_mov_imm_LSLH_operand:$Simm),
1141259698Sdim                              !strconcat(asmop, "\t$Rd.8h, $Imm$Simm"),
1142259698Sdim                              [(set (v8i16 VPR128:$Rd),
1143259698Sdim                                 (v8i16 (opnode (timm:$Imm),
1144259698Sdim                                   (neon_mov_imm_LSLH_operand:$Simm))))],
1145259698Sdim                              NoItinerary> {
1146259698Sdim      bit Simm;
1147259698Sdim      let cmode = {0b1, 0b0, Simm, 0b0};
1148259698Sdim     }
1149259698Sdim}
1150259698Sdim
1151259698Sdimmulticlass NeonI_mov_imm_with_constraint_lsl_sizes<string asmop, bit op,
1152259698Sdim                                                   SDPatternOperator opnode,
1153259698Sdim                                                   SDPatternOperator neonopnode>
1154259698Sdim{
1155259698Sdim  let Constraints = "$src = $Rd" in {
1156259698Sdim    // shift zeros, per word
1157259698Sdim    def _2S  : NeonI_1VModImm<0b0, op,
1158259698Sdim                 (outs VPR64:$Rd),
1159259698Sdim                 (ins VPR64:$src, neon_uimm8:$Imm,
1160259698Sdim                   neon_mov_imm_LSL_operand:$Simm),
1161259698Sdim                 !strconcat(asmop, "\t$Rd.2s, $Imm$Simm"),
1162259698Sdim                 [(set (v2i32 VPR64:$Rd),
1163259698Sdim                    (v2i32 (opnode (v2i32 VPR64:$src),
1164259698Sdim                      (v2i32 (bitconvert (v2i32 (neonopnode timm:$Imm,
1165259698Sdim                        neon_mov_imm_LSL_operand:$Simm)))))))],
1166259698Sdim                 NoItinerary> {
1167259698Sdim      bits<2> Simm;
1168259698Sdim      let cmode = {0b0, Simm{1}, Simm{0}, 0b1};
1169259698Sdim    }
1170259698Sdim
1171259698Sdim    def _4S  : NeonI_1VModImm<0b1, op,
1172259698Sdim                 (outs VPR128:$Rd),
1173259698Sdim                 (ins VPR128:$src, neon_uimm8:$Imm,
1174259698Sdim                   neon_mov_imm_LSL_operand:$Simm),
1175259698Sdim                 !strconcat(asmop, "\t$Rd.4s, $Imm$Simm"),
1176259698Sdim                 [(set (v4i32 VPR128:$Rd),
1177259698Sdim                    (v4i32 (opnode (v4i32 VPR128:$src),
1178259698Sdim                      (v4i32 (bitconvert (v4i32 (neonopnode timm:$Imm,
1179259698Sdim                        neon_mov_imm_LSL_operand:$Simm)))))))],
1180259698Sdim                 NoItinerary> {
1181259698Sdim      bits<2> Simm;
1182259698Sdim      let cmode = {0b0, Simm{1}, Simm{0}, 0b1};
1183259698Sdim    }
1184259698Sdim
1185259698Sdim    // shift zeros, per halfword
1186259698Sdim    def _4H  : NeonI_1VModImm<0b0, op,
1187259698Sdim                 (outs VPR64:$Rd),
1188259698Sdim                 (ins VPR64:$src, neon_uimm8:$Imm,
1189259698Sdim                   neon_mov_imm_LSLH_operand:$Simm),
1190259698Sdim                 !strconcat(asmop, "\t$Rd.4h, $Imm$Simm"),
1191259698Sdim                 [(set (v4i16 VPR64:$Rd),
1192259698Sdim                    (v4i16 (opnode (v4i16 VPR64:$src),
1193259698Sdim                       (v4i16 (bitconvert (v4i16 (neonopnode timm:$Imm,
1194259698Sdim                          neon_mov_imm_LSL_operand:$Simm)))))))],
1195259698Sdim                 NoItinerary> {
1196259698Sdim      bit  Simm;
1197259698Sdim      let cmode = {0b1, 0b0, Simm, 0b1};
1198259698Sdim    }
1199259698Sdim
1200259698Sdim    def _8H  : NeonI_1VModImm<0b1, op,
1201259698Sdim                 (outs VPR128:$Rd),
1202259698Sdim                 (ins VPR128:$src, neon_uimm8:$Imm,
1203259698Sdim                   neon_mov_imm_LSLH_operand:$Simm),
1204259698Sdim                 !strconcat(asmop, "\t$Rd.8h, $Imm$Simm"),
1205259698Sdim                 [(set (v8i16 VPR128:$Rd),
1206259698Sdim                    (v8i16 (opnode (v8i16 VPR128:$src),
1207259698Sdim                      (v8i16 (bitconvert (v8i16 (neonopnode timm:$Imm,
1208259698Sdim                        neon_mov_imm_LSL_operand:$Simm)))))))],
1209259698Sdim                 NoItinerary> {
1210259698Sdim      bit Simm;
1211259698Sdim      let cmode = {0b1, 0b0, Simm, 0b1};
1212259698Sdim    }
1213259698Sdim  }
1214259698Sdim}
1215259698Sdim
1216259698Sdimmulticlass NeonI_mov_imm_msl_sizes<string asmop, bit op,
1217259698Sdim                                   SDPatternOperator opnode>
1218259698Sdim{
1219259698Sdim    // shift ones, per word
1220259698Sdim    def _2S  : NeonI_1VModImm<0b0, op,
1221259698Sdim                             (outs VPR64:$Rd),
1222259698Sdim                             (ins neon_uimm8:$Imm,
1223259698Sdim                               neon_mov_imm_MSL_operand:$Simm),
1224259698Sdim                             !strconcat(asmop, "\t$Rd.2s, $Imm$Simm"),
1225259698Sdim                              [(set (v2i32 VPR64:$Rd),
1226259698Sdim                                 (v2i32 (opnode (timm:$Imm),
1227259698Sdim                                   (neon_mov_imm_MSL_operand:$Simm))))],
1228259698Sdim                             NoItinerary> {
1229259698Sdim       bit Simm;
1230259698Sdim       let cmode = {0b1, 0b1, 0b0, Simm};
1231259698Sdim     }
1232259698Sdim
1233259698Sdim   def _4S  : NeonI_1VModImm<0b1, op,
1234259698Sdim                              (outs VPR128:$Rd),
1235259698Sdim                              (ins neon_uimm8:$Imm,
1236259698Sdim                                neon_mov_imm_MSL_operand:$Simm),
1237259698Sdim                              !strconcat(asmop, "\t$Rd.4s, $Imm$Simm"),
1238259698Sdim                              [(set (v4i32 VPR128:$Rd),
1239259698Sdim                                 (v4i32 (opnode (timm:$Imm),
1240259698Sdim                                   (neon_mov_imm_MSL_operand:$Simm))))],
1241259698Sdim                              NoItinerary> {
1242259698Sdim     bit Simm;
1243259698Sdim     let cmode = {0b1, 0b1, 0b0, Simm};
1244259698Sdim   }
1245259698Sdim}
1246259698Sdim
1247259698Sdim// Vector Move Immediate Shifted
1248259698Sdimlet isReMaterializable = 1 in {
1249259698Sdimdefm MOVIvi_lsl : NeonI_mov_imm_lsl_sizes<"movi", 0b0, Neon_movi>;
1250259698Sdim}
1251259698Sdim
1252259698Sdim// Vector Move Inverted Immediate Shifted
1253259698Sdimlet isReMaterializable = 1 in {
1254259698Sdimdefm MVNIvi_lsl : NeonI_mov_imm_lsl_sizes<"mvni", 0b1, Neon_mvni>;
1255259698Sdim}
1256259698Sdim
1257259698Sdim// Vector Bitwise Bit Clear (AND NOT) - immediate
1258259698Sdimlet isReMaterializable = 1 in {
1259259698Sdimdefm BICvi_lsl : NeonI_mov_imm_with_constraint_lsl_sizes<"bic", 0b1,
1260259698Sdim                                                         and, Neon_mvni>;
1261259698Sdim}
1262259698Sdim
1263259698Sdim// Vector Bitwise OR - immedidate
1264259698Sdim
1265259698Sdimlet isReMaterializable = 1 in {
1266259698Sdimdefm ORRvi_lsl   : NeonI_mov_imm_with_constraint_lsl_sizes<"orr", 0b0,
1267259698Sdim                                                           or, Neon_movi>;
1268259698Sdim}
1269259698Sdim
1270259698Sdim// Additional patterns for Vector Bitwise Bit Clear (AND NOT) - immedidate
1271259698Sdim// LowerBUILD_VECTOR favors lowering MOVI over MVNI.
1272259698Sdim// BIC immediate instructions selection requires additional patterns to
1273259698Sdim// transform Neon_movi operands into BIC immediate operands
1274259698Sdim
1275259698Sdimdef neon_mov_imm_LSLH_transform_XFORM : SDNodeXForm<imm, [{
1276259698Sdim  uint64_t OpCmode = N->getZExtValue();
1277259698Sdim  unsigned ShiftImm;
1278259698Sdim  unsigned ShiftOnesIn;
1279259698Sdim  (void)A64Imms::decodeNeonModShiftImm(OpCmode, ShiftImm, ShiftOnesIn);
1280259698Sdim  // LSLH restricts shift amount to  0, 8 which are encoded as 0 and 1
1281259698Sdim  // Transform encoded shift amount 0 to 1 and 1 to 0.
1282259698Sdim  return CurDAG->getTargetConstant(!ShiftImm, MVT::i32);
1283259698Sdim}]>;
1284259698Sdim
1285259698Sdimdef neon_mov_imm_LSLH_transform_operand
1286259698Sdim  : ImmLeaf<i32, [{
1287259698Sdim    unsigned ShiftImm;
1288259698Sdim    unsigned ShiftOnesIn;
1289259698Sdim    unsigned HasShift =
1290259698Sdim      A64Imms::decodeNeonModShiftImm(Imm, ShiftImm, ShiftOnesIn);
1291259698Sdim    return (HasShift && !ShiftOnesIn); }],
1292259698Sdim  neon_mov_imm_LSLH_transform_XFORM>;
1293259698Sdim
1294259698Sdim// Transform (and A, (4h Neon_movi 0xff)) -> BIC 4h (A, 0x00, LSL 8)
1295259698Sdim// Transform (and A, (4h Neon_movi 0xff LSL #8)) -> BIC 4h (A, 0x00)
1296259698Sdimdef : Pat<(v4i16 (and VPR64:$src,
1297259698Sdim            (v4i16 (Neon_movi 255, neon_mov_imm_LSLH_transform_operand:$Simm)))),
1298259698Sdim          (BICvi_lsl_4H VPR64:$src, 0,
1299259698Sdim            neon_mov_imm_LSLH_transform_operand:$Simm)>;
1300259698Sdim
1301259698Sdim// Transform (and A, (8h Neon_movi 8h 0xff)) -> BIC 8h (A, 0x00, LSL 8)
1302259698Sdim// Transform (and A, (8h Neon_movi 0xff LSL #8)) -> BIC 8h (A, 0x00)
1303259698Sdimdef : Pat<(v8i16 (and VPR128:$src,
1304259698Sdim            (v8i16 (Neon_movi 255, neon_mov_imm_LSLH_transform_operand:$Simm)))),
1305259698Sdim          (BICvi_lsl_8H VPR128:$src, 0,
1306259698Sdim            neon_mov_imm_LSLH_transform_operand:$Simm)>;
1307259698Sdim
1308259698Sdim
1309259698Sdimmulticlass Neon_bitwiseVi_patterns<SDPatternOperator opnode,
1310259698Sdim                                   SDPatternOperator neonopnode,
1311259698Sdim                                   Instruction INST4H,
1312259698Sdim                                   Instruction INST8H> {
1313259698Sdim  def : Pat<(v8i8 (opnode VPR64:$src,
1314259698Sdim                    (bitconvert(v4i16 (neonopnode timm:$Imm,
1315259698Sdim                      neon_mov_imm_LSLH_operand:$Simm))))),
1316259698Sdim            (INST4H VPR64:$src, neon_uimm8:$Imm,
1317259698Sdim              neon_mov_imm_LSLH_operand:$Simm)>;
1318259698Sdim  def : Pat<(v1i64 (opnode VPR64:$src,
1319259698Sdim                  (bitconvert(v4i16 (neonopnode timm:$Imm,
1320259698Sdim                    neon_mov_imm_LSLH_operand:$Simm))))),
1321259698Sdim          (INST4H VPR64:$src, neon_uimm8:$Imm,
1322259698Sdim            neon_mov_imm_LSLH_operand:$Simm)>;
1323259698Sdim
1324259698Sdim  def : Pat<(v16i8 (opnode VPR128:$src,
1325259698Sdim                   (bitconvert(v8i16 (neonopnode timm:$Imm,
1326259698Sdim                     neon_mov_imm_LSLH_operand:$Simm))))),
1327259698Sdim          (INST8H VPR128:$src, neon_uimm8:$Imm,
1328259698Sdim            neon_mov_imm_LSLH_operand:$Simm)>;
1329259698Sdim  def : Pat<(v4i32 (opnode VPR128:$src,
1330259698Sdim                   (bitconvert(v8i16 (neonopnode timm:$Imm,
1331259698Sdim                     neon_mov_imm_LSLH_operand:$Simm))))),
1332259698Sdim          (INST8H VPR128:$src, neon_uimm8:$Imm,
1333259698Sdim            neon_mov_imm_LSLH_operand:$Simm)>;
1334259698Sdim  def : Pat<(v2i64 (opnode VPR128:$src,
1335259698Sdim                   (bitconvert(v8i16 (neonopnode timm:$Imm,
1336259698Sdim                     neon_mov_imm_LSLH_operand:$Simm))))),
1337259698Sdim          (INST8H VPR128:$src, neon_uimm8:$Imm,
1338259698Sdim            neon_mov_imm_LSLH_operand:$Simm)>;
1339259698Sdim}
1340259698Sdim
1341259698Sdim// Additional patterns for Vector Vector Bitwise Bit Clear (AND NOT) - immediate
1342259698Sdimdefm : Neon_bitwiseVi_patterns<or, Neon_mvni, BICvi_lsl_4H, BICvi_lsl_8H>;
1343259698Sdim
1344259698Sdim// Additional patterns for Vector Bitwise OR - immedidate
1345259698Sdimdefm : Neon_bitwiseVi_patterns<or, Neon_movi, ORRvi_lsl_4H, ORRvi_lsl_8H>;
1346259698Sdim
1347259698Sdim
1348259698Sdim// Vector Move Immediate Masked
1349259698Sdimlet isReMaterializable = 1 in {
1350259698Sdimdefm MOVIvi_msl : NeonI_mov_imm_msl_sizes<"movi", 0b0, Neon_movi>;
1351259698Sdim}
1352259698Sdim
1353259698Sdim// Vector Move Inverted Immediate Masked
1354259698Sdimlet isReMaterializable = 1 in {
1355259698Sdimdefm MVNIvi_msl : NeonI_mov_imm_msl_sizes<"mvni", 0b1, Neon_mvni>;
1356259698Sdim}
1357259698Sdim
1358259698Sdimclass NeonI_mov_imm_lsl_aliases<string asmop, string asmlane,
1359259698Sdim                                Instruction inst, RegisterOperand VPRC>
1360259698Sdim  : NeonInstAlias<!strconcat(asmop, "\t$Rd," # asmlane # ", $Imm"),
1361259698Sdim                        (inst VPRC:$Rd, neon_uimm8:$Imm,  0), 0b0>;
1362259698Sdim
1363259698Sdim// Aliases for Vector Move Immediate Shifted
1364259698Sdimdef : NeonI_mov_imm_lsl_aliases<"movi", ".2s", MOVIvi_lsl_2S, VPR64>;
1365259698Sdimdef : NeonI_mov_imm_lsl_aliases<"movi", ".4s", MOVIvi_lsl_4S, VPR128>;
1366259698Sdimdef : NeonI_mov_imm_lsl_aliases<"movi", ".4h", MOVIvi_lsl_4H, VPR64>;
1367259698Sdimdef : NeonI_mov_imm_lsl_aliases<"movi", ".8h", MOVIvi_lsl_8H, VPR128>;
1368259698Sdim
1369259698Sdim// Aliases for Vector Move Inverted Immediate Shifted
1370259698Sdimdef : NeonI_mov_imm_lsl_aliases<"mvni", ".2s", MVNIvi_lsl_2S, VPR64>;
1371259698Sdimdef : NeonI_mov_imm_lsl_aliases<"mvni", ".4s", MVNIvi_lsl_4S, VPR128>;
1372259698Sdimdef : NeonI_mov_imm_lsl_aliases<"mvni", ".4h", MVNIvi_lsl_4H, VPR64>;
1373259698Sdimdef : NeonI_mov_imm_lsl_aliases<"mvni", ".8h", MVNIvi_lsl_8H, VPR128>;
1374259698Sdim
1375259698Sdim// Aliases for Vector Bitwise Bit Clear (AND NOT) - immediate
1376259698Sdimdef : NeonI_mov_imm_lsl_aliases<"bic", ".2s", BICvi_lsl_2S, VPR64>;
1377259698Sdimdef : NeonI_mov_imm_lsl_aliases<"bic", ".4s", BICvi_lsl_4S, VPR128>;
1378259698Sdimdef : NeonI_mov_imm_lsl_aliases<"bic", ".4h", BICvi_lsl_4H, VPR64>;
1379259698Sdimdef : NeonI_mov_imm_lsl_aliases<"bic", ".8h", BICvi_lsl_8H, VPR128>;
1380259698Sdim
1381259698Sdim// Aliases for Vector Bitwise OR - immedidate
1382259698Sdimdef : NeonI_mov_imm_lsl_aliases<"orr", ".2s", ORRvi_lsl_2S, VPR64>;
1383259698Sdimdef : NeonI_mov_imm_lsl_aliases<"orr", ".4s", ORRvi_lsl_4S, VPR128>;
1384259698Sdimdef : NeonI_mov_imm_lsl_aliases<"orr", ".4h", ORRvi_lsl_4H, VPR64>;
1385259698Sdimdef : NeonI_mov_imm_lsl_aliases<"orr", ".8h", ORRvi_lsl_8H, VPR128>;
1386259698Sdim
1387259698Sdim//  Vector Move Immediate - per byte
1388259698Sdimlet isReMaterializable = 1 in {
1389259698Sdimdef MOVIvi_8B : NeonI_1VModImm<0b0, 0b0,
1390259698Sdim                               (outs VPR64:$Rd), (ins neon_uimm8:$Imm),
1391259698Sdim                               "movi\t$Rd.8b, $Imm",
1392259698Sdim                               [(set (v8i8 VPR64:$Rd),
1393259698Sdim                                  (v8i8 (Neon_movi (timm:$Imm), (i32 imm))))],
1394259698Sdim                                NoItinerary> {
1395259698Sdim  let cmode = 0b1110;
1396259698Sdim}
1397259698Sdim
1398259698Sdimdef MOVIvi_16B : NeonI_1VModImm<0b1, 0b0,
1399259698Sdim                                (outs VPR128:$Rd), (ins neon_uimm8:$Imm),
1400259698Sdim                                "movi\t$Rd.16b, $Imm",
1401259698Sdim                                [(set (v16i8 VPR128:$Rd),
1402259698Sdim                                   (v16i8 (Neon_movi (timm:$Imm), (i32 imm))))],
1403259698Sdim                                 NoItinerary> {
1404259698Sdim  let cmode = 0b1110;
1405259698Sdim}
1406259698Sdim}
1407259698Sdim
1408259698Sdim// Vector Move Immediate - bytemask, per double word
1409259698Sdimlet isReMaterializable = 1 in {
1410259698Sdimdef MOVIvi_2D : NeonI_1VModImm<0b1, 0b1,
1411259698Sdim                               (outs VPR128:$Rd), (ins neon_uimm64_mask:$Imm),
1412259698Sdim                               "movi\t $Rd.2d, $Imm",
1413259698Sdim                               [(set (v2i64 VPR128:$Rd),
1414259698Sdim                                  (v2i64 (Neon_movi (timm:$Imm), (i32 imm))))],
1415259698Sdim                               NoItinerary> {
1416259698Sdim  let cmode = 0b1110;
1417259698Sdim}
1418259698Sdim}
1419259698Sdim
1420259698Sdim// Vector Move Immediate - bytemask, one doubleword
1421259698Sdim
1422259698Sdimlet isReMaterializable = 1 in {
1423259698Sdimdef MOVIdi : NeonI_1VModImm<0b0, 0b1,
1424259698Sdim                           (outs FPR64:$Rd), (ins neon_uimm64_mask:$Imm),
1425259698Sdim                           "movi\t $Rd, $Imm",
1426259698Sdim                           [(set (v1i64 FPR64:$Rd),
1427259698Sdim                             (v1i64 (Neon_movi (timm:$Imm), (i32 imm))))],
1428259698Sdim                           NoItinerary> {
1429259698Sdim  let cmode = 0b1110;
1430259698Sdim}
1431259698Sdim}
1432259698Sdim
1433259698Sdim// Vector Floating Point Move Immediate
1434259698Sdim
1435259698Sdimclass NeonI_FMOV_impl<string asmlane, RegisterOperand VPRC, ValueType OpTy,
1436259698Sdim                      Operand immOpType, bit q, bit op>
1437259698Sdim  : NeonI_1VModImm<q, op,
1438259698Sdim                   (outs VPRC:$Rd), (ins immOpType:$Imm),
1439259698Sdim                   "fmov\t$Rd" # asmlane # ", $Imm",
1440259698Sdim                   [(set (OpTy VPRC:$Rd),
1441259698Sdim                      (OpTy (Neon_fmovi (timm:$Imm))))],
1442259698Sdim                   NoItinerary> {
1443259698Sdim     let cmode = 0b1111;
1444259698Sdim   }
1445259698Sdim
1446259698Sdimlet isReMaterializable = 1 in {
1447259698Sdimdef FMOVvi_2S : NeonI_FMOV_impl<".2s", VPR64,  v2f32, fmov32_operand, 0b0, 0b0>;
1448259698Sdimdef FMOVvi_4S : NeonI_FMOV_impl<".4s", VPR128, v4f32, fmov32_operand, 0b1, 0b0>;
1449259698Sdimdef FMOVvi_2D : NeonI_FMOV_impl<".2d", VPR128, v2f64, fmov64_operand, 0b1, 0b1>;
1450259698Sdim}
1451259698Sdim
1452259698Sdim// Vector Shift (Immediate)
1453259698Sdim// Immediate in [0, 63]
1454259698Sdimdef imm0_63 : Operand<i32> {
1455259698Sdim  let ParserMatchClass = uimm6_asmoperand;
1456259698Sdim}
1457259698Sdim
1458259698Sdim// Shift Right/Left Immediate - The immh:immb field of these shifts are encoded
1459259698Sdim// as follows:
1460259698Sdim//
1461259698Sdim//    Offset    Encoding
1462259698Sdim//     8        immh:immb<6:3> = '0001xxx', <imm> is encoded in immh:immb<2:0>
1463259698Sdim//     16       immh:immb<6:4> = '001xxxx', <imm> is encoded in immh:immb<3:0>
1464259698Sdim//     32       immh:immb<6:5> = '01xxxxx', <imm> is encoded in immh:immb<4:0>
1465259698Sdim//     64       immh:immb<6>   = '1xxxxxx', <imm> is encoded in immh:immb<5:0>
1466259698Sdim//
1467259698Sdim// The shift right immediate amount, in the range 1 to element bits, is computed
1468259698Sdim// as Offset - UInt(immh:immb).  The shift left immediate amount, in the range 0
1469259698Sdim// to element bits - 1, is computed as UInt(immh:immb) - Offset.
1470259698Sdim
1471259698Sdimclass shr_imm_asmoperands<string OFFSET> : AsmOperandClass {
1472259698Sdim  let Name = "ShrImm" # OFFSET;
1473259698Sdim  let RenderMethod = "addImmOperands";
1474259698Sdim  let DiagnosticType = "ShrImm" # OFFSET;
1475259698Sdim}
1476259698Sdim
1477259698Sdimclass shr_imm<string OFFSET> : Operand<i32> {
1478259698Sdim  let EncoderMethod = "getShiftRightImm" # OFFSET;
1479259698Sdim  let DecoderMethod = "DecodeShiftRightImm" # OFFSET;
1480259698Sdim  let ParserMatchClass =
1481259698Sdim    !cast<AsmOperandClass>("shr_imm" # OFFSET # "_asmoperand");
1482259698Sdim}
1483259698Sdim
1484259698Sdimdef shr_imm8_asmoperand : shr_imm_asmoperands<"8">;
1485259698Sdimdef shr_imm16_asmoperand : shr_imm_asmoperands<"16">;
1486259698Sdimdef shr_imm32_asmoperand : shr_imm_asmoperands<"32">;
1487259698Sdimdef shr_imm64_asmoperand : shr_imm_asmoperands<"64">;
1488259698Sdim
1489259698Sdimdef shr_imm8 : shr_imm<"8">, ImmLeaf<i32, [{return Imm > 0 && Imm <= 8;}]>;
1490259698Sdimdef shr_imm16 : shr_imm<"16">, ImmLeaf<i32, [{return Imm > 0 && Imm <= 16;}]>;
1491259698Sdimdef shr_imm32 : shr_imm<"32">, ImmLeaf<i32, [{return Imm > 0 && Imm <= 32;}]>;
1492259698Sdimdef shr_imm64 : shr_imm<"64">, ImmLeaf<i32, [{return Imm > 0 && Imm <= 64;}]>;
1493259698Sdim
1494259698Sdimclass shl_imm_asmoperands<string OFFSET> : AsmOperandClass {
1495259698Sdim  let Name = "ShlImm" # OFFSET;
1496259698Sdim  let RenderMethod = "addImmOperands";
1497259698Sdim  let DiagnosticType = "ShlImm" # OFFSET;
1498259698Sdim}
1499259698Sdim
1500259698Sdimclass shl_imm<string OFFSET> : Operand<i32> {
1501259698Sdim  let EncoderMethod = "getShiftLeftImm" # OFFSET;
1502259698Sdim  let DecoderMethod = "DecodeShiftLeftImm" # OFFSET;
1503259698Sdim  let ParserMatchClass =
1504259698Sdim    !cast<AsmOperandClass>("shl_imm" # OFFSET # "_asmoperand");
1505259698Sdim}
1506259698Sdim
1507259698Sdimdef shl_imm8_asmoperand : shl_imm_asmoperands<"8">;
1508259698Sdimdef shl_imm16_asmoperand : shl_imm_asmoperands<"16">;
1509259698Sdimdef shl_imm32_asmoperand : shl_imm_asmoperands<"32">;
1510259698Sdimdef shl_imm64_asmoperand : shl_imm_asmoperands<"64">;
1511259698Sdim
1512259698Sdimdef shl_imm8 : shl_imm<"8">, ImmLeaf<i32, [{return Imm >= 0 && Imm < 8;}]>;
1513259698Sdimdef shl_imm16 : shl_imm<"16">, ImmLeaf<i32, [{return Imm >= 0 && Imm < 16;}]>;
1514259698Sdimdef shl_imm32 : shl_imm<"32">, ImmLeaf<i32, [{return Imm >= 0 && Imm < 32;}]>;
1515259698Sdimdef shl_imm64 : shl_imm<"64">, ImmLeaf<i32, [{return Imm >= 0 && Imm < 64;}]>;
1516259698Sdim
1517259698Sdimclass N2VShift<bit q, bit u, bits<5> opcode, string asmop, string T,
1518259698Sdim               RegisterOperand VPRC, ValueType Ty, Operand ImmTy, SDNode OpNode>
1519259698Sdim  : NeonI_2VShiftImm<q, u, opcode,
1520259698Sdim                     (outs VPRC:$Rd), (ins VPRC:$Rn, ImmTy:$Imm),
1521259698Sdim                     asmop # "\t$Rd." # T # ", $Rn." # T # ", $Imm",
1522259698Sdim                     [(set (Ty VPRC:$Rd),
1523259698Sdim                        (Ty (OpNode (Ty VPRC:$Rn),
1524259698Sdim                          (Ty (Neon_vdup (i32 ImmTy:$Imm))))))],
1525259698Sdim                     NoItinerary>;
1526259698Sdim
1527259698Sdimmulticlass NeonI_N2VShL<bit u, bits<5> opcode, string asmop> {
1528259698Sdim  // 64-bit vector types.
1529259698Sdim  def _8B : N2VShift<0b0, u, opcode, asmop, "8b", VPR64, v8i8, shl_imm8, shl> {
1530259698Sdim    let Inst{22-19} = 0b0001;  // immh:immb = 0001xxx
1531259698Sdim  }
1532259698Sdim
1533259698Sdim  def _4H : N2VShift<0b0, u, opcode, asmop, "4h", VPR64, v4i16, shl_imm16, shl> {
1534259698Sdim    let Inst{22-20} = 0b001;   // immh:immb = 001xxxx
1535259698Sdim  }
1536259698Sdim
1537259698Sdim  def _2S : N2VShift<0b0, u, opcode, asmop, "2s", VPR64, v2i32, shl_imm32, shl> {
1538259698Sdim    let Inst{22-21} = 0b01;    // immh:immb = 01xxxxx
1539259698Sdim  }
1540259698Sdim
1541259698Sdim  // 128-bit vector types.
1542259698Sdim  def _16B : N2VShift<0b1, u, opcode, asmop, "16b", VPR128, v16i8, shl_imm8, shl> {
1543259698Sdim    let Inst{22-19} = 0b0001;  // immh:immb = 0001xxx
1544259698Sdim  }
1545259698Sdim
1546259698Sdim  def _8H : N2VShift<0b1, u, opcode, asmop, "8h", VPR128, v8i16, shl_imm16, shl> {
1547259698Sdim    let Inst{22-20} = 0b001;   // immh:immb = 001xxxx
1548259698Sdim  }
1549259698Sdim
1550259698Sdim  def _4S : N2VShift<0b1, u, opcode, asmop, "4s", VPR128, v4i32, shl_imm32, shl> {
1551259698Sdim    let Inst{22-21} = 0b01;    // immh:immb = 01xxxxx
1552259698Sdim  }
1553259698Sdim
1554259698Sdim  def _2D : N2VShift<0b1, u, opcode, asmop, "2d", VPR128, v2i64, shl_imm64, shl> {
1555259698Sdim    let Inst{22} = 0b1;        // immh:immb = 1xxxxxx
1556259698Sdim  }
1557259698Sdim}
1558259698Sdim
1559259698Sdimmulticlass NeonI_N2VShR<bit u, bits<5> opcode, string asmop, SDNode OpNode> {
1560259698Sdim  def _8B : N2VShift<0b0, u, opcode, asmop, "8b", VPR64, v8i8, shr_imm8,
1561259698Sdim                     OpNode> {
1562259698Sdim    let Inst{22-19} = 0b0001;
1563259698Sdim  }
1564259698Sdim
1565259698Sdim  def _4H : N2VShift<0b0, u, opcode, asmop, "4h", VPR64, v4i16, shr_imm16,
1566259698Sdim                     OpNode> {
1567259698Sdim    let Inst{22-20} = 0b001;
1568259698Sdim  }
1569259698Sdim
1570259698Sdim  def _2S : N2VShift<0b0, u, opcode, asmop, "2s", VPR64, v2i32, shr_imm32,
1571259698Sdim                     OpNode> {
1572259698Sdim     let Inst{22-21} = 0b01;
1573259698Sdim  }
1574259698Sdim
1575259698Sdim  def _16B : N2VShift<0b1, u, opcode, asmop, "16b", VPR128, v16i8, shr_imm8,
1576259698Sdim                      OpNode> {
1577259698Sdim                      let Inst{22-19} = 0b0001;
1578259698Sdim                    }
1579259698Sdim
1580259698Sdim  def _8H : N2VShift<0b1, u, opcode, asmop, "8h", VPR128, v8i16, shr_imm16,
1581259698Sdim                     OpNode> {
1582259698Sdim                     let Inst{22-20} = 0b001;
1583259698Sdim                    }
1584259698Sdim
1585259698Sdim  def _4S : N2VShift<0b1, u, opcode, asmop, "4s", VPR128, v4i32, shr_imm32,
1586259698Sdim                     OpNode> {
1587259698Sdim                      let Inst{22-21} = 0b01;
1588259698Sdim                    }
1589259698Sdim
1590259698Sdim  def _2D : N2VShift<0b1, u, opcode, asmop, "2d", VPR128, v2i64, shr_imm64,
1591259698Sdim                     OpNode> {
1592259698Sdim                      let Inst{22} = 0b1;
1593259698Sdim                    }
1594259698Sdim}
1595259698Sdim
1596259698Sdim// Shift left
1597259698Sdimdefm SHLvvi : NeonI_N2VShL<0b0, 0b01010, "shl">;
1598259698Sdim
1599259698Sdim// Shift right
1600259698Sdimdefm SSHRvvi : NeonI_N2VShR<0b0, 0b00000, "sshr", sra>;
1601259698Sdimdefm USHRvvi : NeonI_N2VShR<0b1, 0b00000, "ushr", srl>;
1602259698Sdim
1603259698Sdimdef Neon_High16B : PatFrag<(ops node:$in),
1604259698Sdim                           (extract_subvector (v16i8 node:$in), (iPTR 8))>;
1605259698Sdimdef Neon_High8H  : PatFrag<(ops node:$in),
1606259698Sdim                           (extract_subvector (v8i16 node:$in), (iPTR 4))>;
1607259698Sdimdef Neon_High4S  : PatFrag<(ops node:$in),
1608259698Sdim                           (extract_subvector (v4i32 node:$in), (iPTR 2))>;
1609259698Sdimdef Neon_High2D  : PatFrag<(ops node:$in),
1610259698Sdim                           (extract_subvector (v2i64 node:$in), (iPTR 1))>;
1611259698Sdimdef Neon_High4float : PatFrag<(ops node:$in),
1612259698Sdim                               (extract_subvector (v4f32 node:$in), (iPTR 2))>;
1613259698Sdimdef Neon_High2double : PatFrag<(ops node:$in),
1614259698Sdim                               (extract_subvector (v2f64 node:$in), (iPTR 1))>;
1615259698Sdim
1616259698Sdimdef Neon_Low16B : PatFrag<(ops node:$in),
1617259698Sdim                          (v8i8 (extract_subvector (v16i8 node:$in),
1618259698Sdim                                                   (iPTR 0)))>;
1619259698Sdimdef Neon_Low8H : PatFrag<(ops node:$in),
1620259698Sdim                         (v4i16 (extract_subvector (v8i16 node:$in),
1621259698Sdim                                                   (iPTR 0)))>;
1622259698Sdimdef Neon_Low4S : PatFrag<(ops node:$in),
1623259698Sdim                         (v2i32 (extract_subvector (v4i32 node:$in),
1624259698Sdim                                                   (iPTR 0)))>;
1625259698Sdimdef Neon_Low2D : PatFrag<(ops node:$in),
1626259698Sdim                         (v1i64 (extract_subvector (v2i64 node:$in),
1627259698Sdim                                                   (iPTR 0)))>;
1628259698Sdimdef Neon_Low4float : PatFrag<(ops node:$in),
1629259698Sdim                             (v2f32 (extract_subvector (v4f32 node:$in),
1630259698Sdim                                                       (iPTR 0)))>;
1631259698Sdimdef Neon_Low2double : PatFrag<(ops node:$in),
1632259698Sdim                              (v1f64 (extract_subvector (v2f64 node:$in),
1633259698Sdim                                                        (iPTR 0)))>;
1634259698Sdim
1635259698Sdimclass N2VShiftLong<bit q, bit u, bits<5> opcode, string asmop, string DestT,
1636259698Sdim                   string SrcT, ValueType DestTy, ValueType SrcTy,
1637259698Sdim                   Operand ImmTy, SDPatternOperator ExtOp>
1638259698Sdim  : NeonI_2VShiftImm<q, u, opcode, (outs VPR128:$Rd),
1639259698Sdim                     (ins VPR64:$Rn, ImmTy:$Imm),
1640259698Sdim                     asmop # "\t$Rd." # DestT # ", $Rn." # SrcT # ", $Imm",
1641259698Sdim                     [(set (DestTy VPR128:$Rd),
1642259698Sdim                        (DestTy (shl
1643259698Sdim                          (DestTy (ExtOp (SrcTy VPR64:$Rn))),
1644259698Sdim                            (DestTy (Neon_vdup (i32 ImmTy:$Imm))))))],
1645259698Sdim                     NoItinerary>;
1646259698Sdim
1647259698Sdimclass N2VShiftLongHigh<bit q, bit u, bits<5> opcode, string asmop, string DestT,
1648259698Sdim                       string SrcT, ValueType DestTy, ValueType SrcTy,
1649259698Sdim                       int StartIndex, Operand ImmTy,
1650259698Sdim                       SDPatternOperator ExtOp, PatFrag getTop>
1651259698Sdim  : NeonI_2VShiftImm<q, u, opcode, (outs VPR128:$Rd),
1652259698Sdim                     (ins VPR128:$Rn, ImmTy:$Imm),
1653259698Sdim                     asmop # "2\t$Rd." # DestT # ", $Rn." # SrcT # ", $Imm",
1654259698Sdim                     [(set (DestTy VPR128:$Rd),
1655259698Sdim                        (DestTy (shl
1656259698Sdim                          (DestTy (ExtOp
1657259698Sdim                            (SrcTy (getTop VPR128:$Rn)))),
1658259698Sdim                              (DestTy (Neon_vdup (i32 ImmTy:$Imm))))))],
1659259698Sdim                     NoItinerary>;
1660259698Sdim
1661259698Sdimmulticlass NeonI_N2VShLL<string prefix, bit u, bits<5> opcode, string asmop,
1662259698Sdim                         SDNode ExtOp> {
1663259698Sdim  // 64-bit vector types.
1664259698Sdim  def _8B : N2VShiftLong<0b0, u, opcode, asmop, "8h", "8b", v8i16, v8i8,
1665259698Sdim                         shl_imm8, ExtOp> {
1666259698Sdim    let Inst{22-19} = 0b0001;  // immh:immb = 0001xxx
1667259698Sdim  }
1668259698Sdim
1669259698Sdim  def _4H : N2VShiftLong<0b0, u, opcode, asmop, "4s", "4h", v4i32, v4i16,
1670259698Sdim                         shl_imm16, ExtOp> {
1671259698Sdim    let Inst{22-20} = 0b001;   // immh:immb = 001xxxx
1672259698Sdim  }
1673259698Sdim
1674259698Sdim  def _2S : N2VShiftLong<0b0, u, opcode, asmop, "2d", "2s", v2i64, v2i32,
1675259698Sdim                         shl_imm32, ExtOp> {
1676259698Sdim    let Inst{22-21} = 0b01;    // immh:immb = 01xxxxx
1677259698Sdim  }
1678259698Sdim
1679259698Sdim  // 128-bit vector types
1680259698Sdim  def _16B : N2VShiftLongHigh<0b1, u, opcode, asmop, "8h", "16b", v8i16, v8i8,
1681259698Sdim                              8, shl_imm8, ExtOp, Neon_High16B> {
1682259698Sdim    let Inst{22-19} = 0b0001;  // immh:immb = 0001xxx
1683259698Sdim  }
1684259698Sdim
1685259698Sdim  def _8H : N2VShiftLongHigh<0b1, u, opcode, asmop, "4s", "8h", v4i32, v4i16,
1686259698Sdim                             4, shl_imm16, ExtOp, Neon_High8H> {
1687259698Sdim    let Inst{22-20} = 0b001;   // immh:immb = 001xxxx
1688259698Sdim  }
1689259698Sdim
1690259698Sdim  def _4S : N2VShiftLongHigh<0b1, u, opcode, asmop, "2d", "4s", v2i64, v2i32,
1691259698Sdim                             2, shl_imm32, ExtOp, Neon_High4S> {
1692259698Sdim    let Inst{22-21} = 0b01;    // immh:immb = 01xxxxx
1693259698Sdim  }
1694259698Sdim
1695259698Sdim  // Use other patterns to match when the immediate is 0.
1696259698Sdim  def : Pat<(v8i16 (ExtOp (v8i8 VPR64:$Rn))),
1697259698Sdim            (!cast<Instruction>(prefix # "_8B") VPR64:$Rn, 0)>;
1698259698Sdim
1699259698Sdim  def : Pat<(v4i32 (ExtOp (v4i16 VPR64:$Rn))),
1700259698Sdim            (!cast<Instruction>(prefix # "_4H") VPR64:$Rn, 0)>;
1701259698Sdim
1702259698Sdim  def : Pat<(v2i64 (ExtOp (v2i32 VPR64:$Rn))),
1703259698Sdim            (!cast<Instruction>(prefix # "_2S") VPR64:$Rn, 0)>;
1704259698Sdim
1705259698Sdim  def : Pat<(v8i16 (ExtOp (v8i8 (Neon_High16B VPR128:$Rn)))),
1706259698Sdim            (!cast<Instruction>(prefix # "_16B") VPR128:$Rn, 0)>;
1707259698Sdim
1708259698Sdim  def : Pat<(v4i32 (ExtOp (v4i16 (Neon_High8H VPR128:$Rn)))),
1709259698Sdim            (!cast<Instruction>(prefix # "_8H") VPR128:$Rn, 0)>;
1710259698Sdim
1711259698Sdim  def : Pat<(v2i64 (ExtOp (v2i32 (Neon_High4S VPR128:$Rn)))),
1712259698Sdim            (!cast<Instruction>(prefix # "_4S") VPR128:$Rn, 0)>;
1713259698Sdim}
1714259698Sdim
1715259698Sdim// Shift left long
1716259698Sdimdefm SSHLLvvi : NeonI_N2VShLL<"SSHLLvvi", 0b0, 0b10100, "sshll", sext>;
1717259698Sdimdefm USHLLvvi : NeonI_N2VShLL<"USHLLvvi", 0b1, 0b10100, "ushll", zext>;
1718259698Sdim
1719259698Sdim// Rounding/Saturating shift
1720259698Sdimclass N2VShift_RQ<bit q, bit u, bits<5> opcode, string asmop, string T,
1721259698Sdim                  RegisterOperand VPRC, ValueType Ty, Operand ImmTy,
1722259698Sdim                  SDPatternOperator OpNode>
1723259698Sdim  : NeonI_2VShiftImm<q, u, opcode,
1724259698Sdim                     (outs VPRC:$Rd), (ins VPRC:$Rn, ImmTy:$Imm),
1725259698Sdim                     asmop # "\t$Rd." # T # ", $Rn." # T # ", $Imm",
1726259698Sdim                     [(set (Ty VPRC:$Rd), (Ty (OpNode (Ty VPRC:$Rn),
1727259698Sdim                        (i32 ImmTy:$Imm))))],
1728259698Sdim                     NoItinerary>;
1729259698Sdim
1730259698Sdim// shift right (vector by immediate)
1731259698Sdimmulticlass NeonI_N2VShR_RQ<bit u, bits<5> opcode, string asmop,
1732259698Sdim                           SDPatternOperator OpNode> {
1733259698Sdim  def _8B  : N2VShift_RQ<0b0, u, opcode, asmop, "8b", VPR64, v8i8, shr_imm8,
1734259698Sdim                         OpNode> {
1735259698Sdim    let Inst{22-19} = 0b0001;
1736259698Sdim  }
1737259698Sdim
1738259698Sdim  def _4H  : N2VShift_RQ<0b0, u, opcode, asmop, "4h", VPR64, v4i16, shr_imm16,
1739259698Sdim                         OpNode> {
1740259698Sdim    let Inst{22-20} = 0b001;
1741259698Sdim  }
1742259698Sdim
1743259698Sdim  def _2S  : N2VShift_RQ<0b0, u, opcode, asmop, "2s", VPR64, v2i32, shr_imm32,
1744259698Sdim                         OpNode> {
1745259698Sdim    let Inst{22-21} = 0b01;
1746259698Sdim  }
1747259698Sdim
1748259698Sdim  def _16B : N2VShift_RQ<0b1, u, opcode, asmop, "16b", VPR128, v16i8, shr_imm8,
1749259698Sdim                         OpNode> {
1750259698Sdim    let Inst{22-19} = 0b0001;
1751259698Sdim  }
1752259698Sdim
1753259698Sdim  def _8H : N2VShift_RQ<0b1, u, opcode, asmop, "8h", VPR128, v8i16, shr_imm16,
1754259698Sdim                        OpNode> {
1755259698Sdim    let Inst{22-20} = 0b001;
1756259698Sdim  }
1757259698Sdim
1758259698Sdim  def _4S : N2VShift_RQ<0b1, u, opcode, asmop, "4s", VPR128, v4i32, shr_imm32,
1759259698Sdim                        OpNode> {
1760259698Sdim    let Inst{22-21} = 0b01;
1761259698Sdim  }
1762259698Sdim
1763259698Sdim  def _2D : N2VShift_RQ<0b1, u, opcode, asmop, "2d", VPR128, v2i64, shr_imm64,
1764259698Sdim                        OpNode> {
1765259698Sdim    let Inst{22} = 0b1;
1766259698Sdim  }
1767259698Sdim}
1768259698Sdim
1769259698Sdimmulticlass NeonI_N2VShL_Q<bit u, bits<5> opcode, string asmop,
1770259698Sdim                          SDPatternOperator OpNode> {
1771259698Sdim  // 64-bit vector types.
1772259698Sdim  def _8B : N2VShift_RQ<0b0, u, opcode, asmop, "8b", VPR64, v8i8, shl_imm8,
1773259698Sdim                        OpNode> {
1774259698Sdim    let Inst{22-19} = 0b0001;
1775259698Sdim  }
1776259698Sdim
1777259698Sdim  def _4H : N2VShift_RQ<0b0, u, opcode, asmop, "4h", VPR64, v4i16, shl_imm16,
1778259698Sdim                        OpNode> {
1779259698Sdim    let Inst{22-20} = 0b001;
1780259698Sdim  }
1781259698Sdim
1782259698Sdim  def _2S : N2VShift_RQ<0b0, u, opcode, asmop, "2s", VPR64, v2i32, shl_imm32,
1783259698Sdim                        OpNode> {
1784259698Sdim    let Inst{22-21} = 0b01;
1785259698Sdim  }
1786259698Sdim
1787259698Sdim  // 128-bit vector types.
1788259698Sdim  def _16B : N2VShift_RQ<0b1, u, opcode, asmop, "16b", VPR128, v16i8, shl_imm8,
1789259698Sdim                         OpNode> {
1790259698Sdim    let Inst{22-19} = 0b0001;
1791259698Sdim  }
1792259698Sdim
1793259698Sdim  def _8H : N2VShift_RQ<0b1, u, opcode, asmop, "8h", VPR128, v8i16, shl_imm16,
1794259698Sdim                        OpNode> {
1795259698Sdim    let Inst{22-20} = 0b001;
1796259698Sdim  }
1797259698Sdim
1798259698Sdim  def _4S : N2VShift_RQ<0b1, u, opcode, asmop, "4s", VPR128, v4i32, shl_imm32,
1799259698Sdim                        OpNode> {
1800259698Sdim    let Inst{22-21} = 0b01;
1801259698Sdim  }
1802259698Sdim
1803259698Sdim  def _2D : N2VShift_RQ<0b1, u, opcode, asmop, "2d", VPR128, v2i64, shl_imm64,
1804259698Sdim                        OpNode> {
1805259698Sdim    let Inst{22} = 0b1;
1806259698Sdim  }
1807259698Sdim}
1808259698Sdim
1809259698Sdim// Rounding shift right
1810259698Sdimdefm SRSHRvvi : NeonI_N2VShR_RQ<0b0, 0b00100, "srshr",
1811259698Sdim                                int_aarch64_neon_vsrshr>;
1812259698Sdimdefm URSHRvvi : NeonI_N2VShR_RQ<0b1, 0b00100, "urshr",
1813259698Sdim                                int_aarch64_neon_vurshr>;
1814259698Sdim
1815259698Sdim// Saturating shift left unsigned
1816259698Sdimdefm SQSHLUvvi : NeonI_N2VShL_Q<0b1, 0b01100, "sqshlu", int_aarch64_neon_vsqshlu>;
1817259698Sdim
1818259698Sdim// Saturating shift left
1819259698Sdimdefm SQSHLvvi : NeonI_N2VShL_Q<0b0, 0b01110, "sqshl", Neon_sqrshlImm>;
1820259698Sdimdefm UQSHLvvi : NeonI_N2VShL_Q<0b1, 0b01110, "uqshl", Neon_uqrshlImm>;
1821259698Sdim
1822259698Sdimclass N2VShiftAdd<bit q, bit u, bits<5> opcode, string asmop, string T,
1823259698Sdim                  RegisterOperand VPRC, ValueType Ty, Operand ImmTy,
1824259698Sdim                  SDNode OpNode>
1825259698Sdim  : NeonI_2VShiftImm<q, u, opcode,
1826259698Sdim           (outs VPRC:$Rd), (ins VPRC:$src, VPRC:$Rn, ImmTy:$Imm),
1827259698Sdim           asmop # "\t$Rd." # T # ", $Rn." # T # ", $Imm",
1828259698Sdim           [(set (Ty VPRC:$Rd), (Ty (add (Ty VPRC:$src),
1829259698Sdim              (Ty (OpNode (Ty VPRC:$Rn),
1830259698Sdim                (Ty (Neon_vdup (i32 ImmTy:$Imm))))))))],
1831259698Sdim           NoItinerary> {
1832259698Sdim  let Constraints = "$src = $Rd";
1833259698Sdim}
1834259698Sdim
1835259698Sdim// Shift Right accumulate
1836259698Sdimmulticlass NeonI_N2VShRAdd<bit u, bits<5> opcode, string asmop, SDNode OpNode> {
1837259698Sdim  def _8B : N2VShiftAdd<0b0, u, opcode, asmop, "8b", VPR64, v8i8, shr_imm8,
1838259698Sdim                        OpNode> {
1839259698Sdim    let Inst{22-19} = 0b0001;
1840259698Sdim  }
1841259698Sdim
1842259698Sdim  def _4H : N2VShiftAdd<0b0, u, opcode, asmop, "4h", VPR64, v4i16, shr_imm16,
1843259698Sdim                        OpNode> {
1844259698Sdim    let Inst{22-20} = 0b001;
1845259698Sdim  }
1846259698Sdim
1847259698Sdim  def _2S : N2VShiftAdd<0b0, u, opcode, asmop, "2s", VPR64, v2i32, shr_imm32,
1848259698Sdim                        OpNode> {
1849259698Sdim    let Inst{22-21} = 0b01;
1850259698Sdim  }
1851259698Sdim
1852259698Sdim  def _16B : N2VShiftAdd<0b1, u, opcode, asmop, "16b", VPR128, v16i8, shr_imm8,
1853259698Sdim                         OpNode> {
1854259698Sdim    let Inst{22-19} = 0b0001;
1855259698Sdim  }
1856259698Sdim
1857259698Sdim  def _8H : N2VShiftAdd<0b1, u, opcode, asmop, "8h", VPR128, v8i16, shr_imm16,
1858259698Sdim                        OpNode> {
1859259698Sdim    let Inst{22-20} = 0b001;
1860259698Sdim  }
1861259698Sdim
1862259698Sdim  def _4S : N2VShiftAdd<0b1, u, opcode, asmop, "4s", VPR128, v4i32, shr_imm32,
1863259698Sdim                        OpNode> {
1864259698Sdim    let Inst{22-21} = 0b01;
1865259698Sdim  }
1866259698Sdim
1867259698Sdim  def _2D : N2VShiftAdd<0b1, u, opcode, asmop, "2d", VPR128, v2i64, shr_imm64,
1868259698Sdim                        OpNode> {
1869259698Sdim    let Inst{22} = 0b1;
1870259698Sdim  }
1871259698Sdim}
1872259698Sdim
1873259698Sdim// Shift right and accumulate
1874259698Sdimdefm SSRAvvi    : NeonI_N2VShRAdd<0, 0b00010, "ssra", sra>;
1875259698Sdimdefm USRAvvi    : NeonI_N2VShRAdd<1, 0b00010, "usra", srl>;
1876259698Sdim
1877259698Sdim// Rounding shift accumulate
1878259698Sdimclass N2VShiftAdd_R<bit q, bit u, bits<5> opcode, string asmop, string T,
1879259698Sdim                    RegisterOperand VPRC, ValueType Ty, Operand ImmTy,
1880259698Sdim                    SDPatternOperator OpNode>
1881259698Sdim  : NeonI_2VShiftImm<q, u, opcode,
1882259698Sdim                     (outs VPRC:$Rd), (ins VPRC:$src, VPRC:$Rn, ImmTy:$Imm),
1883259698Sdim                     asmop # "\t$Rd." # T # ", $Rn." # T # ", $Imm",
1884259698Sdim                     [(set (Ty VPRC:$Rd), (Ty (add (Ty VPRC:$src),
1885259698Sdim                        (Ty (OpNode (Ty VPRC:$Rn), (i32 ImmTy:$Imm))))))],
1886259698Sdim                     NoItinerary> {
1887259698Sdim  let Constraints = "$src = $Rd";
1888259698Sdim}
1889259698Sdim
1890259698Sdimmulticlass NeonI_N2VShRAdd_R<bit u, bits<5> opcode, string asmop,
1891259698Sdim                             SDPatternOperator OpNode> {
1892259698Sdim  def _8B : N2VShiftAdd_R<0b0, u, opcode, asmop, "8b", VPR64, v8i8, shr_imm8,
1893259698Sdim                          OpNode> {
1894259698Sdim    let Inst{22-19} = 0b0001;
1895259698Sdim  }
1896259698Sdim
1897259698Sdim  def _4H : N2VShiftAdd_R<0b0, u, opcode, asmop, "4h", VPR64, v4i16, shr_imm16,
1898259698Sdim                          OpNode> {
1899259698Sdim    let Inst{22-20} = 0b001;
1900259698Sdim  }
1901259698Sdim
1902259698Sdim  def _2S : N2VShiftAdd_R<0b0, u, opcode, asmop, "2s", VPR64, v2i32, shr_imm32,
1903259698Sdim                          OpNode> {
1904259698Sdim    let Inst{22-21} = 0b01;
1905259698Sdim  }
1906259698Sdim
1907259698Sdim  def _16B : N2VShiftAdd_R<0b1, u, opcode, asmop, "16b", VPR128, v16i8, shr_imm8,
1908259698Sdim                           OpNode> {
1909259698Sdim    let Inst{22-19} = 0b0001;
1910259698Sdim  }
1911259698Sdim
1912259698Sdim  def _8H : N2VShiftAdd_R<0b1, u, opcode, asmop, "8h", VPR128, v8i16, shr_imm16,
1913259698Sdim                          OpNode> {
1914259698Sdim    let Inst{22-20} = 0b001;
1915259698Sdim  }
1916259698Sdim
1917259698Sdim  def _4S : N2VShiftAdd_R<0b1, u, opcode, asmop, "4s", VPR128, v4i32, shr_imm32,
1918259698Sdim                          OpNode> {
1919259698Sdim    let Inst{22-21} = 0b01;
1920259698Sdim  }
1921259698Sdim
1922259698Sdim  def _2D : N2VShiftAdd_R<0b1, u, opcode, asmop, "2d", VPR128, v2i64, shr_imm64,
1923259698Sdim                          OpNode> {
1924259698Sdim    let Inst{22} = 0b1;
1925259698Sdim  }
1926259698Sdim}
1927259698Sdim
1928259698Sdim// Rounding shift right and accumulate
1929259698Sdimdefm SRSRAvvi : NeonI_N2VShRAdd_R<0, 0b00110, "srsra", int_aarch64_neon_vsrshr>;
1930259698Sdimdefm URSRAvvi : NeonI_N2VShRAdd_R<1, 0b00110, "ursra", int_aarch64_neon_vurshr>;
1931259698Sdim
1932259698Sdim// Shift insert by immediate
1933259698Sdimclass N2VShiftIns<bit q, bit u, bits<5> opcode, string asmop, string T,
1934259698Sdim                  RegisterOperand VPRC, ValueType Ty, Operand ImmTy,
1935259698Sdim                  SDPatternOperator OpNode>
1936259698Sdim    : NeonI_2VShiftImm<q, u, opcode,
1937259698Sdim           (outs VPRC:$Rd), (ins VPRC:$src, VPRC:$Rn, ImmTy:$Imm),
1938259698Sdim           asmop # "\t$Rd." # T # ", $Rn." # T # ", $Imm",
1939259698Sdim           [(set (Ty VPRC:$Rd), (Ty (OpNode (Ty VPRC:$src), (Ty VPRC:$Rn),
1940259698Sdim             (i32 ImmTy:$Imm))))],
1941259698Sdim           NoItinerary> {
1942259698Sdim  let Constraints = "$src = $Rd";
1943259698Sdim}
1944259698Sdim
1945259698Sdim// shift left insert (vector by immediate)
1946259698Sdimmulticlass NeonI_N2VShLIns<bit u, bits<5> opcode, string asmop> {
1947259698Sdim  def _8B : N2VShiftIns<0b0, u, opcode, asmop, "8b", VPR64, v8i8, shl_imm8,
1948259698Sdim                        int_aarch64_neon_vsli> {
1949259698Sdim    let Inst{22-19} = 0b0001;
1950259698Sdim  }
1951259698Sdim
1952259698Sdim  def _4H : N2VShiftIns<0b0, u, opcode, asmop, "4h", VPR64, v4i16, shl_imm16,
1953259698Sdim                        int_aarch64_neon_vsli> {
1954259698Sdim    let Inst{22-20} = 0b001;
1955259698Sdim  }
1956259698Sdim
1957259698Sdim  def _2S : N2VShiftIns<0b0, u, opcode, asmop, "2s", VPR64, v2i32, shl_imm32,
1958259698Sdim                        int_aarch64_neon_vsli> {
1959259698Sdim    let Inst{22-21} = 0b01;
1960259698Sdim  }
1961259698Sdim
1962259698Sdim    // 128-bit vector types
1963259698Sdim  def _16B : N2VShiftIns<0b1, u, opcode, asmop, "16b", VPR128, v16i8, shl_imm8,
1964259698Sdim                         int_aarch64_neon_vsli> {
1965259698Sdim    let Inst{22-19} = 0b0001;
1966259698Sdim  }
1967259698Sdim
1968259698Sdim  def _8H : N2VShiftIns<0b1, u, opcode, asmop, "8h", VPR128, v8i16, shl_imm16,
1969259698Sdim                        int_aarch64_neon_vsli> {
1970259698Sdim    let Inst{22-20} = 0b001;
1971259698Sdim  }
1972259698Sdim
1973259698Sdim  def _4S : N2VShiftIns<0b1, u, opcode, asmop, "4s", VPR128, v4i32, shl_imm32,
1974259698Sdim                        int_aarch64_neon_vsli> {
1975259698Sdim    let Inst{22-21} = 0b01;
1976259698Sdim  }
1977259698Sdim
1978259698Sdim  def _2D : N2VShiftIns<0b1, u, opcode, asmop, "2d", VPR128, v2i64, shl_imm64,
1979259698Sdim                        int_aarch64_neon_vsli> {
1980259698Sdim    let Inst{22} = 0b1;
1981259698Sdim  }
1982259698Sdim}
1983259698Sdim
1984259698Sdim// shift right insert (vector by immediate)
1985259698Sdimmulticlass NeonI_N2VShRIns<bit u, bits<5> opcode, string asmop> {
1986259698Sdim    // 64-bit vector types.
1987259698Sdim  def _8B : N2VShiftIns<0b0, u, opcode, asmop, "8b", VPR64, v8i8, shr_imm8,
1988259698Sdim                        int_aarch64_neon_vsri> {
1989259698Sdim    let Inst{22-19} = 0b0001;
1990259698Sdim  }
1991259698Sdim
1992259698Sdim  def _4H : N2VShiftIns<0b0, u, opcode, asmop, "4h", VPR64, v4i16, shr_imm16,
1993259698Sdim                        int_aarch64_neon_vsri> {
1994259698Sdim    let Inst{22-20} = 0b001;
1995259698Sdim  }
1996259698Sdim
1997259698Sdim  def _2S : N2VShiftIns<0b0, u, opcode, asmop, "2s", VPR64, v2i32, shr_imm32,
1998259698Sdim                        int_aarch64_neon_vsri> {
1999259698Sdim    let Inst{22-21} = 0b01;
2000259698Sdim  }
2001259698Sdim
2002259698Sdim    // 128-bit vector types
2003259698Sdim  def _16B : N2VShiftIns<0b1, u, opcode, asmop, "16b", VPR128, v16i8, shr_imm8,
2004259698Sdim                         int_aarch64_neon_vsri> {
2005259698Sdim    let Inst{22-19} = 0b0001;
2006259698Sdim  }
2007259698Sdim
2008259698Sdim  def _8H : N2VShiftIns<0b1, u, opcode, asmop, "8h", VPR128, v8i16, shr_imm16,
2009259698Sdim                        int_aarch64_neon_vsri> {
2010259698Sdim    let Inst{22-20} = 0b001;
2011259698Sdim  }
2012259698Sdim
2013259698Sdim  def _4S : N2VShiftIns<0b1, u, opcode, asmop, "4s", VPR128, v4i32, shr_imm32,
2014259698Sdim                        int_aarch64_neon_vsri> {
2015259698Sdim    let Inst{22-21} = 0b01;
2016259698Sdim  }
2017259698Sdim
2018259698Sdim  def _2D : N2VShiftIns<0b1, u, opcode, asmop, "2d", VPR128, v2i64, shr_imm64,
2019259698Sdim                        int_aarch64_neon_vsri> {
2020259698Sdim    let Inst{22} = 0b1;
2021259698Sdim  }
2022259698Sdim}
2023259698Sdim
2024259698Sdim// Shift left and insert
2025259698Sdimdefm SLIvvi   : NeonI_N2VShLIns<0b1, 0b01010, "sli">;
2026259698Sdim
2027259698Sdim// Shift right and insert
2028259698Sdimdefm SRIvvi   : NeonI_N2VShRIns<0b1, 0b01000, "sri">;
2029259698Sdim
2030259698Sdimclass N2VShR_Narrow<bit q, bit u, bits<5> opcode, string asmop, string DestT,
2031259698Sdim                    string SrcT, Operand ImmTy>
2032259698Sdim  : NeonI_2VShiftImm<q, u, opcode,
2033259698Sdim                     (outs VPR64:$Rd), (ins VPR128:$Rn, ImmTy:$Imm),
2034259698Sdim                     asmop # "\t$Rd." # DestT # ", $Rn." # SrcT # ", $Imm",
2035259698Sdim                     [], NoItinerary>;
2036259698Sdim
2037259698Sdimclass N2VShR_Narrow_Hi<bit q, bit u, bits<5> opcode, string asmop, string DestT,
2038259698Sdim                       string SrcT, Operand ImmTy>
2039259698Sdim  : NeonI_2VShiftImm<q, u, opcode, (outs VPR128:$Rd),
2040259698Sdim                     (ins VPR128:$src, VPR128:$Rn, ImmTy:$Imm),
2041259698Sdim                     asmop # "\t$Rd." # DestT # ", $Rn." # SrcT # ", $Imm",
2042259698Sdim                     [], NoItinerary> {
2043259698Sdim  let Constraints = "$src = $Rd";
2044259698Sdim}
2045259698Sdim
2046259698Sdim// left long shift by immediate
2047259698Sdimmulticlass NeonI_N2VShR_Narrow<bit u, bits<5> opcode, string asmop> {
2048259698Sdim  def _8B : N2VShR_Narrow<0b0, u, opcode, asmop, "8b", "8h", shr_imm8> {
2049259698Sdim    let Inst{22-19} = 0b0001;
2050259698Sdim  }
2051259698Sdim
2052259698Sdim  def _4H : N2VShR_Narrow<0b0, u, opcode, asmop, "4h", "4s", shr_imm16> {
2053259698Sdim    let Inst{22-20} = 0b001;
2054259698Sdim  }
2055259698Sdim
2056259698Sdim  def _2S : N2VShR_Narrow<0b0, u, opcode, asmop, "2s", "2d", shr_imm32> {
2057259698Sdim    let Inst{22-21} = 0b01;
2058259698Sdim  }
2059259698Sdim
2060259698Sdim  // Shift Narrow High
2061259698Sdim  def _16B : N2VShR_Narrow_Hi<0b1, u, opcode, asmop # "2", "16b", "8h",
2062259698Sdim                              shr_imm8> {
2063259698Sdim    let Inst{22-19} = 0b0001;
2064259698Sdim  }
2065259698Sdim
2066259698Sdim  def _8H : N2VShR_Narrow_Hi<0b1, u, opcode, asmop # "2", "8h", "4s",
2067259698Sdim                             shr_imm16> {
2068259698Sdim    let Inst{22-20} = 0b001;
2069259698Sdim  }
2070259698Sdim
2071259698Sdim  def _4S : N2VShR_Narrow_Hi<0b1, u, opcode, asmop # "2", "4s", "2d",
2072259698Sdim                             shr_imm32> {
2073259698Sdim    let Inst{22-21} = 0b01;
2074259698Sdim  }
2075259698Sdim}
2076259698Sdim
2077259698Sdim// Shift right narrow
2078259698Sdimdefm SHRNvvi : NeonI_N2VShR_Narrow<0b0, 0b10000, "shrn">;
2079259698Sdim
2080259698Sdim// Shift right narrow (prefix Q is saturating, prefix R is rounding)
2081259698Sdimdefm QSHRUNvvi :NeonI_N2VShR_Narrow<0b1, 0b10000, "sqshrun">;
2082259698Sdimdefm RSHRNvvi : NeonI_N2VShR_Narrow<0b0, 0b10001, "rshrn">;
2083259698Sdimdefm QRSHRUNvvi : NeonI_N2VShR_Narrow<0b1, 0b10001, "sqrshrun">;
2084259698Sdimdefm SQSHRNvvi : NeonI_N2VShR_Narrow<0b0, 0b10010, "sqshrn">;
2085259698Sdimdefm UQSHRNvvi : NeonI_N2VShR_Narrow<0b1, 0b10010, "uqshrn">;
2086259698Sdimdefm SQRSHRNvvi : NeonI_N2VShR_Narrow<0b0, 0b10011, "sqrshrn">;
2087259698Sdimdefm UQRSHRNvvi : NeonI_N2VShR_Narrow<0b1, 0b10011, "uqrshrn">;
2088259698Sdim
2089259698Sdimdef Neon_combine_2D : PatFrag<(ops node:$Rm, node:$Rn),
2090259698Sdim                              (v2i64 (concat_vectors (v1i64 node:$Rm),
2091259698Sdim                                                     (v1i64 node:$Rn)))>;
2092259698Sdimdef Neon_combine_8H : PatFrag<(ops node:$Rm, node:$Rn),
2093259698Sdim                              (v8i16 (concat_vectors (v4i16 node:$Rm),
2094259698Sdim                                                     (v4i16 node:$Rn)))>;
2095259698Sdimdef Neon_combine_4S : PatFrag<(ops node:$Rm, node:$Rn),
2096259698Sdim                              (v4i32 (concat_vectors (v2i32 node:$Rm),
2097259698Sdim                                                     (v2i32 node:$Rn)))>;
2098259698Sdimdef Neon_combine_4f : PatFrag<(ops node:$Rm, node:$Rn),
2099259698Sdim                              (v4f32 (concat_vectors (v2f32 node:$Rm),
2100259698Sdim                                                     (v2f32 node:$Rn)))>;
2101259698Sdimdef Neon_combine_2d : PatFrag<(ops node:$Rm, node:$Rn),
2102259698Sdim                              (v2f64 (concat_vectors (v1f64 node:$Rm),
2103259698Sdim                                                     (v1f64 node:$Rn)))>;
2104259698Sdim
2105259698Sdimdef Neon_lshrImm8H : PatFrag<(ops node:$lhs, node:$rhs),
2106259698Sdim                             (v8i16 (srl (v8i16 node:$lhs),
2107259698Sdim                               (v8i16 (Neon_vdup (i32 node:$rhs)))))>;
2108259698Sdimdef Neon_lshrImm4S : PatFrag<(ops node:$lhs, node:$rhs),
2109259698Sdim                             (v4i32 (srl (v4i32 node:$lhs),
2110259698Sdim                               (v4i32 (Neon_vdup (i32 node:$rhs)))))>;
2111259698Sdimdef Neon_lshrImm2D : PatFrag<(ops node:$lhs, node:$rhs),
2112259698Sdim                             (v2i64 (srl (v2i64 node:$lhs),
2113259698Sdim                               (v2i64 (Neon_vdup (i32 node:$rhs)))))>;
2114259698Sdimdef Neon_ashrImm8H : PatFrag<(ops node:$lhs, node:$rhs),
2115259698Sdim                             (v8i16 (sra (v8i16 node:$lhs),
2116259698Sdim                               (v8i16 (Neon_vdup (i32 node:$rhs)))))>;
2117259698Sdimdef Neon_ashrImm4S : PatFrag<(ops node:$lhs, node:$rhs),
2118259698Sdim                             (v4i32 (sra (v4i32 node:$lhs),
2119259698Sdim                               (v4i32 (Neon_vdup (i32 node:$rhs)))))>;
2120259698Sdimdef Neon_ashrImm2D : PatFrag<(ops node:$lhs, node:$rhs),
2121259698Sdim                             (v2i64 (sra (v2i64 node:$lhs),
2122259698Sdim                               (v2i64 (Neon_vdup (i32 node:$rhs)))))>;
2123259698Sdim
2124259698Sdim// Normal shift right narrow is matched by IR (srl/sra, trunc, concat_vectors)
2125259698Sdimmulticlass Neon_shiftNarrow_patterns<string shr> {
2126259698Sdim  def : Pat<(v8i8 (trunc (!cast<PatFrag>("Neon_" # shr # "Imm8H") VPR128:$Rn,
2127259698Sdim              (i32 shr_imm8:$Imm)))),
2128259698Sdim            (SHRNvvi_8B VPR128:$Rn, imm:$Imm)>;
2129259698Sdim  def : Pat<(v4i16 (trunc (!cast<PatFrag>("Neon_" # shr # "Imm4S") VPR128:$Rn,
2130259698Sdim              (i32 shr_imm16:$Imm)))),
2131259698Sdim            (SHRNvvi_4H VPR128:$Rn, imm:$Imm)>;
2132259698Sdim  def : Pat<(v2i32 (trunc (!cast<PatFrag>("Neon_" # shr # "Imm2D") VPR128:$Rn,
2133259698Sdim              (i32 shr_imm32:$Imm)))),
2134259698Sdim            (SHRNvvi_2S VPR128:$Rn, imm:$Imm)>;
2135259698Sdim
2136259698Sdim  def : Pat<(Neon_combine_2D (v1i64 VPR64:$src), (v1i64 (bitconvert
2137259698Sdim              (v8i8 (trunc (!cast<PatFrag>("Neon_" # shr # "Imm8H")
2138259698Sdim                VPR128:$Rn, (i32 shr_imm8:$Imm))))))),
2139259698Sdim            (SHRNvvi_16B (v2i64 (SUBREG_TO_REG (i64 0), VPR64:$src, sub_64)),
2140259698Sdim                         VPR128:$Rn, imm:$Imm)>;
2141259698Sdim  def : Pat<(Neon_combine_2D (v1i64 VPR64:$src), (v1i64 (bitconvert
2142259698Sdim              (v4i16 (trunc (!cast<PatFrag>("Neon_" # shr # "Imm4S")
2143259698Sdim                VPR128:$Rn, (i32 shr_imm16:$Imm))))))),
2144259698Sdim            (SHRNvvi_8H (SUBREG_TO_REG (i64 0), VPR64:$src, sub_64),
2145259698Sdim                        VPR128:$Rn, imm:$Imm)>;
2146259698Sdim  def : Pat<(Neon_combine_2D (v1i64 VPR64:$src), (v1i64 (bitconvert
2147259698Sdim              (v2i32 (trunc (!cast<PatFrag>("Neon_" # shr # "Imm2D")
2148259698Sdim                VPR128:$Rn, (i32 shr_imm32:$Imm))))))),
2149259698Sdim            (SHRNvvi_4S (SUBREG_TO_REG (i64 0), VPR64:$src, sub_64),
2150259698Sdim                        VPR128:$Rn, imm:$Imm)>;
2151259698Sdim}
2152259698Sdim
2153259698Sdimmulticlass Neon_shiftNarrow_QR_patterns<SDPatternOperator op, string prefix> {
2154259698Sdim  def : Pat<(v8i8 (op (v8i16 VPR128:$Rn), shr_imm8:$Imm)),
2155259698Sdim            (!cast<Instruction>(prefix # "_8B") VPR128:$Rn, imm:$Imm)>;
2156259698Sdim  def : Pat<(v4i16 (op (v4i32 VPR128:$Rn), shr_imm16:$Imm)),
2157259698Sdim            (!cast<Instruction>(prefix # "_4H") VPR128:$Rn, imm:$Imm)>;
2158259698Sdim  def : Pat<(v2i32 (op (v2i64 VPR128:$Rn), shr_imm32:$Imm)),
2159259698Sdim            (!cast<Instruction>(prefix # "_2S") VPR128:$Rn, imm:$Imm)>;
2160259698Sdim
2161259698Sdim  def : Pat<(Neon_combine_2D (v1i64 VPR64:$src),
2162259698Sdim                (v1i64 (bitconvert (v8i8
2163259698Sdim                    (op (v8i16 VPR128:$Rn), shr_imm8:$Imm))))),
2164259698Sdim            (!cast<Instruction>(prefix # "_16B")
2165259698Sdim                (SUBREG_TO_REG (i64 0), VPR64:$src, sub_64),
2166259698Sdim                VPR128:$Rn, imm:$Imm)>;
2167259698Sdim  def : Pat<(Neon_combine_2D (v1i64 VPR64:$src),
2168259698Sdim                (v1i64 (bitconvert (v4i16
2169259698Sdim                    (op (v4i32 VPR128:$Rn), shr_imm16:$Imm))))),
2170259698Sdim            (!cast<Instruction>(prefix # "_8H")
2171259698Sdim                (SUBREG_TO_REG (i64 0), VPR64:$src, sub_64),
2172259698Sdim                VPR128:$Rn, imm:$Imm)>;
2173259698Sdim  def : Pat<(Neon_combine_2D (v1i64 VPR64:$src),
2174259698Sdim                (v1i64 (bitconvert (v2i32
2175259698Sdim                    (op (v2i64 VPR128:$Rn), shr_imm32:$Imm))))),
2176259698Sdim            (!cast<Instruction>(prefix # "_4S")
2177259698Sdim                  (SUBREG_TO_REG (i64 0), VPR64:$src, sub_64),
2178259698Sdim                  VPR128:$Rn, imm:$Imm)>;
2179259698Sdim}
2180259698Sdim
2181259698Sdimdefm : Neon_shiftNarrow_patterns<"lshr">;
2182259698Sdimdefm : Neon_shiftNarrow_patterns<"ashr">;
2183259698Sdim
2184259698Sdimdefm : Neon_shiftNarrow_QR_patterns<int_aarch64_neon_vsqshrun, "QSHRUNvvi">;
2185259698Sdimdefm : Neon_shiftNarrow_QR_patterns<int_aarch64_neon_vrshrn, "RSHRNvvi">;
2186259698Sdimdefm : Neon_shiftNarrow_QR_patterns<int_aarch64_neon_vsqrshrun, "QRSHRUNvvi">;
2187259698Sdimdefm : Neon_shiftNarrow_QR_patterns<int_aarch64_neon_vsqshrn, "SQSHRNvvi">;
2188259698Sdimdefm : Neon_shiftNarrow_QR_patterns<int_aarch64_neon_vuqshrn, "UQSHRNvvi">;
2189259698Sdimdefm : Neon_shiftNarrow_QR_patterns<int_aarch64_neon_vsqrshrn, "SQRSHRNvvi">;
2190259698Sdimdefm : Neon_shiftNarrow_QR_patterns<int_aarch64_neon_vuqrshrn, "UQRSHRNvvi">;
2191259698Sdim
2192259698Sdim// Convert fix-point and float-pointing
2193259698Sdimclass N2VCvt_Fx<bit q, bit u, bits<5> opcode, string asmop, string T,
2194259698Sdim                RegisterOperand VPRC, ValueType DestTy, ValueType SrcTy,
2195259698Sdim                Operand ImmTy, SDPatternOperator IntOp>
2196259698Sdim  : NeonI_2VShiftImm<q, u, opcode,
2197259698Sdim                     (outs VPRC:$Rd), (ins VPRC:$Rn, ImmTy:$Imm),
2198259698Sdim                     asmop # "\t$Rd." # T # ", $Rn." # T # ", $Imm",
2199259698Sdim                     [(set (DestTy VPRC:$Rd), (DestTy (IntOp (SrcTy VPRC:$Rn),
2200259698Sdim                       (i32 ImmTy:$Imm))))],
2201259698Sdim                     NoItinerary>;
2202259698Sdim
2203259698Sdimmulticlass NeonI_N2VCvt_Fx2fp<bit u, bits<5> opcode, string asmop,
2204259698Sdim                              SDPatternOperator IntOp> {
2205259698Sdim  def _2S : N2VCvt_Fx<0, u, opcode, asmop, "2s", VPR64, v2f32, v2i32,
2206259698Sdim                      shr_imm32, IntOp> {
2207259698Sdim    let Inst{22-21} = 0b01;
2208259698Sdim  }
2209259698Sdim
2210259698Sdim  def _4S : N2VCvt_Fx<1, u, opcode, asmop, "4s", VPR128, v4f32, v4i32,
2211259698Sdim                      shr_imm32, IntOp> {
2212259698Sdim    let Inst{22-21} = 0b01;
2213259698Sdim  }
2214259698Sdim
2215259698Sdim  def _2D : N2VCvt_Fx<1, u, opcode, asmop, "2d", VPR128, v2f64, v2i64,
2216259698Sdim                      shr_imm64, IntOp> {
2217259698Sdim    let Inst{22} = 0b1;
2218259698Sdim  }
2219259698Sdim}
2220259698Sdim
2221259698Sdimmulticlass NeonI_N2VCvt_Fp2fx<bit u, bits<5> opcode, string asmop,
2222259698Sdim                              SDPatternOperator IntOp> {
2223259698Sdim  def _2S : N2VCvt_Fx<0, u, opcode, asmop, "2s", VPR64, v2i32, v2f32,
2224259698Sdim                      shr_imm32, IntOp> {
2225259698Sdim    let Inst{22-21} = 0b01;
2226259698Sdim  }
2227259698Sdim
2228259698Sdim  def _4S : N2VCvt_Fx<1, u, opcode, asmop, "4s", VPR128, v4i32, v4f32,
2229259698Sdim                      shr_imm32, IntOp> {
2230259698Sdim    let Inst{22-21} = 0b01;
2231259698Sdim  }
2232259698Sdim
2233259698Sdim  def _2D : N2VCvt_Fx<1, u, opcode, asmop, "2d", VPR128, v2i64, v2f64,
2234259698Sdim                      shr_imm64, IntOp> {
2235259698Sdim    let Inst{22} = 0b1;
2236259698Sdim  }
2237259698Sdim}
2238259698Sdim
2239259698Sdim// Convert fixed-point to floating-point
2240259698Sdimdefm VCVTxs2f : NeonI_N2VCvt_Fx2fp<0, 0b11100, "scvtf",
2241259698Sdim                                   int_arm_neon_vcvtfxs2fp>;
2242259698Sdimdefm VCVTxu2f : NeonI_N2VCvt_Fx2fp<1, 0b11100, "ucvtf",
2243259698Sdim                                   int_arm_neon_vcvtfxu2fp>;
2244259698Sdim
2245259698Sdim// Convert floating-point to fixed-point
2246259698Sdimdefm VCVTf2xs : NeonI_N2VCvt_Fp2fx<0, 0b11111, "fcvtzs",
2247259698Sdim                                   int_arm_neon_vcvtfp2fxs>;
2248259698Sdimdefm VCVTf2xu : NeonI_N2VCvt_Fp2fx<1, 0b11111, "fcvtzu",
2249259698Sdim                                   int_arm_neon_vcvtfp2fxu>;
2250259698Sdim
2251259698Sdimmulticlass Neon_sshll2_0<SDNode ext>
2252259698Sdim{
2253259698Sdim  def _v8i8  : PatFrag<(ops node:$Rn),
2254259698Sdim                       (v8i16 (ext (v8i8 (Neon_High16B node:$Rn))))>;
2255259698Sdim  def _v4i16 : PatFrag<(ops node:$Rn),
2256259698Sdim                       (v4i32 (ext (v4i16 (Neon_High8H node:$Rn))))>;
2257259698Sdim  def _v2i32 : PatFrag<(ops node:$Rn),
2258259698Sdim                       (v2i64 (ext (v2i32 (Neon_High4S node:$Rn))))>;
2259259698Sdim}
2260259698Sdim
2261259698Sdimdefm NI_sext_high : Neon_sshll2_0<sext>;
2262259698Sdimdefm NI_zext_high : Neon_sshll2_0<zext>;
2263259698Sdim
2264259698Sdim
2265259698Sdim//===----------------------------------------------------------------------===//
2266259698Sdim// Multiclasses for NeonI_Across
2267259698Sdim//===----------------------------------------------------------------------===//
2268259698Sdim
2269259698Sdim// Variant 1
2270259698Sdim
2271259698Sdimmulticlass NeonI_2VAcross_1<bit u, bits<5> opcode,
2272259698Sdim                            string asmop, SDPatternOperator opnode>
2273259698Sdim{
2274259698Sdim    def _1h8b:  NeonI_2VAcross<0b0, u, 0b00, opcode,
2275259698Sdim                (outs FPR16:$Rd), (ins VPR64:$Rn),
2276259698Sdim                asmop # "\t$Rd, $Rn.8b",
2277259698Sdim                [(set (v1i16 FPR16:$Rd),
2278259698Sdim                    (v1i16 (opnode (v8i8 VPR64:$Rn))))],
2279259698Sdim                NoItinerary>;
2280259698Sdim
2281259698Sdim    def _1h16b: NeonI_2VAcross<0b1, u, 0b00, opcode,
2282259698Sdim                (outs FPR16:$Rd), (ins VPR128:$Rn),
2283259698Sdim                asmop # "\t$Rd, $Rn.16b",
2284259698Sdim                [(set (v1i16 FPR16:$Rd),
2285259698Sdim                    (v1i16 (opnode (v16i8 VPR128:$Rn))))],
2286259698Sdim                NoItinerary>;
2287259698Sdim
2288259698Sdim    def _1s4h:  NeonI_2VAcross<0b0, u, 0b01, opcode,
2289259698Sdim                (outs FPR32:$Rd), (ins VPR64:$Rn),
2290259698Sdim                asmop # "\t$Rd, $Rn.4h",
2291259698Sdim                [(set (v1i32 FPR32:$Rd),
2292259698Sdim                    (v1i32 (opnode (v4i16 VPR64:$Rn))))],
2293259698Sdim                NoItinerary>;
2294259698Sdim
2295259698Sdim    def _1s8h:  NeonI_2VAcross<0b1, u, 0b01, opcode,
2296259698Sdim                (outs FPR32:$Rd), (ins VPR128:$Rn),
2297259698Sdim                asmop # "\t$Rd, $Rn.8h",
2298259698Sdim                [(set (v1i32 FPR32:$Rd),
2299259698Sdim                    (v1i32 (opnode (v8i16 VPR128:$Rn))))],
2300259698Sdim                NoItinerary>;
2301259698Sdim
2302259698Sdim    // _1d2s doesn't exist!
2303259698Sdim
2304259698Sdim    def _1d4s:  NeonI_2VAcross<0b1, u, 0b10, opcode,
2305259698Sdim                (outs FPR64:$Rd), (ins VPR128:$Rn),
2306259698Sdim                asmop # "\t$Rd, $Rn.4s",
2307259698Sdim                [(set (v1i64 FPR64:$Rd),
2308259698Sdim                    (v1i64 (opnode (v4i32 VPR128:$Rn))))],
2309259698Sdim                NoItinerary>;
2310259698Sdim}
2311259698Sdim
2312259698Sdimdefm SADDLV : NeonI_2VAcross_1<0b0, 0b00011, "saddlv", int_aarch64_neon_saddlv>;
2313259698Sdimdefm UADDLV : NeonI_2VAcross_1<0b1, 0b00011, "uaddlv", int_aarch64_neon_uaddlv>;
2314259698Sdim
2315259698Sdim// Variant 2
2316259698Sdim
2317259698Sdimmulticlass NeonI_2VAcross_2<bit u, bits<5> opcode,
2318259698Sdim                            string asmop, SDPatternOperator opnode>
2319259698Sdim{
2320259698Sdim    def _1b8b:  NeonI_2VAcross<0b0, u, 0b00, opcode,
2321259698Sdim                (outs FPR8:$Rd), (ins VPR64:$Rn),
2322259698Sdim                asmop # "\t$Rd, $Rn.8b",
2323259698Sdim                [(set (v1i8 FPR8:$Rd),
2324259698Sdim                    (v1i8 (opnode (v8i8 VPR64:$Rn))))],
2325259698Sdim                NoItinerary>;
2326259698Sdim
2327259698Sdim    def _1b16b: NeonI_2VAcross<0b1, u, 0b00, opcode,
2328259698Sdim                (outs FPR8:$Rd), (ins VPR128:$Rn),
2329259698Sdim                asmop # "\t$Rd, $Rn.16b",
2330259698Sdim                [(set (v1i8 FPR8:$Rd),
2331259698Sdim                    (v1i8 (opnode (v16i8 VPR128:$Rn))))],
2332259698Sdim                NoItinerary>;
2333259698Sdim
2334259698Sdim    def _1h4h:  NeonI_2VAcross<0b0, u, 0b01, opcode,
2335259698Sdim                (outs FPR16:$Rd), (ins VPR64:$Rn),
2336259698Sdim                asmop # "\t$Rd, $Rn.4h",
2337259698Sdim                [(set (v1i16 FPR16:$Rd),
2338259698Sdim                    (v1i16 (opnode (v4i16 VPR64:$Rn))))],
2339259698Sdim                NoItinerary>;
2340259698Sdim
2341259698Sdim    def _1h8h:  NeonI_2VAcross<0b1, u, 0b01, opcode,
2342259698Sdim                (outs FPR16:$Rd), (ins VPR128:$Rn),
2343259698Sdim                asmop # "\t$Rd, $Rn.8h",
2344259698Sdim                [(set (v1i16 FPR16:$Rd),
2345259698Sdim                    (v1i16 (opnode (v8i16 VPR128:$Rn))))],
2346259698Sdim                NoItinerary>;
2347259698Sdim
2348259698Sdim    // _1s2s doesn't exist!
2349259698Sdim
2350259698Sdim    def _1s4s:  NeonI_2VAcross<0b1, u, 0b10, opcode,
2351259698Sdim                (outs FPR32:$Rd), (ins VPR128:$Rn),
2352259698Sdim                asmop # "\t$Rd, $Rn.4s",
2353259698Sdim                [(set (v1i32 FPR32:$Rd),
2354259698Sdim                    (v1i32 (opnode (v4i32 VPR128:$Rn))))],
2355259698Sdim                NoItinerary>;
2356259698Sdim}
2357259698Sdim
2358259698Sdimdefm SMAXV : NeonI_2VAcross_2<0b0, 0b01010, "smaxv", int_aarch64_neon_smaxv>;
2359259698Sdimdefm UMAXV : NeonI_2VAcross_2<0b1, 0b01010, "umaxv", int_aarch64_neon_umaxv>;
2360259698Sdim
2361259698Sdimdefm SMINV : NeonI_2VAcross_2<0b0, 0b11010, "sminv", int_aarch64_neon_sminv>;
2362259698Sdimdefm UMINV : NeonI_2VAcross_2<0b1, 0b11010, "uminv", int_aarch64_neon_uminv>;
2363259698Sdim
2364259698Sdimdefm ADDV : NeonI_2VAcross_2<0b0, 0b11011, "addv", int_aarch64_neon_vaddv>;
2365259698Sdim
2366259698Sdim// Variant 3
2367259698Sdim
2368259698Sdimmulticlass NeonI_2VAcross_3<bit u, bits<5> opcode, bits<2> size,
2369259698Sdim                            string asmop, SDPatternOperator opnode> {
2370259698Sdim    def _1s4s:  NeonI_2VAcross<0b1, u, size, opcode,
2371259698Sdim                (outs FPR32:$Rd), (ins VPR128:$Rn),
2372259698Sdim                asmop # "\t$Rd, $Rn.4s",
2373259698Sdim                [(set (v1f32 FPR32:$Rd),
2374259698Sdim                    (v1f32 (opnode (v4f32 VPR128:$Rn))))],
2375259698Sdim                NoItinerary>;
2376259698Sdim}
2377259698Sdim
2378259698Sdimdefm FMAXNMV : NeonI_2VAcross_3<0b1, 0b01100, 0b00, "fmaxnmv",
2379259698Sdim                                int_aarch64_neon_vmaxnmv>;
2380259698Sdimdefm FMINNMV : NeonI_2VAcross_3<0b1, 0b01100, 0b10, "fminnmv",
2381259698Sdim                                int_aarch64_neon_vminnmv>;
2382259698Sdim
2383259698Sdimdefm FMAXV : NeonI_2VAcross_3<0b1, 0b01111, 0b00, "fmaxv",
2384259698Sdim                              int_aarch64_neon_vmaxv>;
2385259698Sdimdefm FMINV : NeonI_2VAcross_3<0b1, 0b01111, 0b10, "fminv",
2386259698Sdim                              int_aarch64_neon_vminv>;
2387259698Sdim
2388259698Sdim// The followings are for instruction class (Perm)
2389259698Sdim
2390259698Sdimclass NeonI_Permute<bit q, bits<2> size, bits<3> opcode,
2391259698Sdim                    string asmop, RegisterOperand OpVPR, string OpS,
2392259698Sdim                    SDPatternOperator opnode, ValueType Ty>
2393259698Sdim  : NeonI_Perm<q, size, opcode,
2394259698Sdim               (outs OpVPR:$Rd), (ins OpVPR:$Rn, OpVPR:$Rm),
2395259698Sdim               asmop # "\t$Rd." # OpS # ", $Rn." # OpS # ", $Rm." # OpS,
2396259698Sdim               [(set (Ty OpVPR:$Rd),
2397259698Sdim                  (Ty (opnode (Ty OpVPR:$Rn), (Ty OpVPR:$Rm))))],
2398259698Sdim               NoItinerary>;
2399259698Sdim
2400259698Sdimmulticlass NeonI_Perm_pat<bits<3> opcode, string asmop,
2401259698Sdim                          SDPatternOperator opnode> {
2402259698Sdim  def _8b  : NeonI_Permute<0b0, 0b00, opcode, asmop,
2403259698Sdim                           VPR64, "8b", opnode, v8i8>;
2404259698Sdim  def _16b : NeonI_Permute<0b1, 0b00, opcode, asmop,
2405259698Sdim                           VPR128, "16b",opnode, v16i8>;
2406259698Sdim  def _4h  : NeonI_Permute<0b0, 0b01, opcode, asmop,
2407259698Sdim                           VPR64, "4h", opnode, v4i16>;
2408259698Sdim  def _8h  : NeonI_Permute<0b1, 0b01, opcode, asmop,
2409259698Sdim                           VPR128, "8h", opnode, v8i16>;
2410259698Sdim  def _2s  : NeonI_Permute<0b0, 0b10, opcode, asmop,
2411259698Sdim                           VPR64, "2s", opnode, v2i32>;
2412259698Sdim  def _4s  : NeonI_Permute<0b1, 0b10, opcode, asmop,
2413259698Sdim                           VPR128, "4s", opnode, v4i32>;
2414259698Sdim  def _2d  : NeonI_Permute<0b1, 0b11, opcode, asmop,
2415259698Sdim                           VPR128, "2d", opnode, v2i64>;
2416259698Sdim}
2417259698Sdim
2418259698Sdimdefm UZP1vvv : NeonI_Perm_pat<0b001, "uzp1", Neon_uzp1>;
2419259698Sdimdefm TRN1vvv : NeonI_Perm_pat<0b010, "trn1", Neon_trn1>;
2420259698Sdimdefm ZIP1vvv : NeonI_Perm_pat<0b011, "zip1", Neon_zip1>;
2421259698Sdimdefm UZP2vvv : NeonI_Perm_pat<0b101, "uzp2", Neon_uzp2>;
2422259698Sdimdefm TRN2vvv : NeonI_Perm_pat<0b110, "trn2", Neon_trn2>;
2423259698Sdimdefm ZIP2vvv : NeonI_Perm_pat<0b111, "zip2", Neon_zip2>;
2424259698Sdim
2425259698Sdimmulticlass NeonI_Perm_float_pat<string INS, SDPatternOperator opnode> {
2426259698Sdim  def : Pat<(v2f32 (opnode (v2f32 VPR64:$Rn), (v2f32 VPR64:$Rm))),
2427259698Sdim            (!cast<Instruction>(INS # "_2s") VPR64:$Rn, VPR64:$Rm)>;
2428259698Sdim
2429259698Sdim  def : Pat<(v4f32 (opnode (v4f32 VPR128:$Rn), (v4f32 VPR128:$Rm))),
2430259698Sdim            (!cast<Instruction>(INS # "_4s") VPR128:$Rn, VPR128:$Rm)>;
2431259698Sdim
2432259698Sdim  def : Pat<(v2f64 (opnode (v2f64 VPR128:$Rn), (v2f64 VPR128:$Rm))),
2433259698Sdim            (!cast<Instruction>(INS # "_2d") VPR128:$Rn, VPR128:$Rm)>;
2434259698Sdim}
2435259698Sdim
2436259698Sdimdefm : NeonI_Perm_float_pat<"UZP1vvv", Neon_uzp1>;
2437259698Sdimdefm : NeonI_Perm_float_pat<"UZP2vvv", Neon_uzp2>;
2438259698Sdimdefm : NeonI_Perm_float_pat<"ZIP1vvv", Neon_zip1>;
2439259698Sdimdefm : NeonI_Perm_float_pat<"ZIP2vvv", Neon_zip2>;
2440259698Sdimdefm : NeonI_Perm_float_pat<"TRN1vvv", Neon_trn1>;
2441259698Sdimdefm : NeonI_Perm_float_pat<"TRN2vvv", Neon_trn2>;
2442259698Sdim
2443259698Sdim// The followings are for instruction class (3V Diff)
2444259698Sdim
2445259698Sdim// normal long/long2 pattern
2446259698Sdimclass NeonI_3VDL<bit q, bit u, bits<2> size, bits<4> opcode,
2447259698Sdim                 string asmop, string ResS, string OpS,
2448259698Sdim                 SDPatternOperator opnode, SDPatternOperator ext,
2449259698Sdim                 RegisterOperand OpVPR,
2450259698Sdim                 ValueType ResTy, ValueType OpTy>
2451259698Sdim  : NeonI_3VDiff<q, u, size, opcode,
2452259698Sdim                 (outs VPR128:$Rd), (ins OpVPR:$Rn, OpVPR:$Rm),
2453259698Sdim                 asmop # "\t$Rd." # ResS # ", $Rn." # OpS # ", $Rm." # OpS,
2454259698Sdim                 [(set (ResTy VPR128:$Rd),
2455259698Sdim                    (ResTy (opnode (ResTy (ext (OpTy OpVPR:$Rn))),
2456259698Sdim                                   (ResTy (ext (OpTy OpVPR:$Rm))))))],
2457259698Sdim                 NoItinerary>;
2458259698Sdim
2459259698Sdimmulticlass NeonI_3VDL_s<bit u, bits<4> opcode,
2460259698Sdim                        string asmop, SDPatternOperator opnode,
2461259698Sdim                        bit Commutable = 0> {
2462259698Sdim  let isCommutable = Commutable in {
2463259698Sdim    def _8h8b : NeonI_3VDL<0b0, u, 0b00, opcode, asmop, "8h", "8b",
2464259698Sdim                           opnode, sext, VPR64, v8i16, v8i8>;
2465259698Sdim    def _4s4h : NeonI_3VDL<0b0, u, 0b01, opcode, asmop, "4s", "4h",
2466259698Sdim                           opnode, sext, VPR64, v4i32, v4i16>;
2467259698Sdim    def _2d2s : NeonI_3VDL<0b0, u, 0b10, opcode, asmop, "2d", "2s",
2468259698Sdim                           opnode, sext, VPR64, v2i64, v2i32>;
2469259698Sdim  }
2470259698Sdim}
2471259698Sdim
2472259698Sdimmulticlass NeonI_3VDL2_s<bit u, bits<4> opcode, string asmop,
2473259698Sdim                         SDPatternOperator opnode, bit Commutable = 0> {
2474259698Sdim  let isCommutable = Commutable in {
2475259698Sdim    def _8h16b : NeonI_3VDL<0b1, u, 0b00, opcode, asmop, "8h", "16b",
2476259698Sdim                            opnode, NI_sext_high_v8i8, VPR128, v8i16, v16i8>;
2477259698Sdim    def _4s8h  : NeonI_3VDL<0b1, u, 0b01, opcode, asmop, "4s", "8h",
2478259698Sdim                            opnode, NI_sext_high_v4i16, VPR128, v4i32, v8i16>;
2479259698Sdim    def _2d4s  : NeonI_3VDL<0b1, u, 0b10, opcode, asmop, "2d", "4s",
2480259698Sdim                            opnode, NI_sext_high_v2i32, VPR128, v2i64, v4i32>;
2481259698Sdim  }
2482259698Sdim}
2483259698Sdim
2484259698Sdimmulticlass NeonI_3VDL_u<bit u, bits<4> opcode, string asmop,
2485259698Sdim                        SDPatternOperator opnode, bit Commutable = 0> {
2486259698Sdim  let isCommutable = Commutable in {
2487259698Sdim    def _8h8b : NeonI_3VDL<0b0, u, 0b00, opcode, asmop, "8h", "8b",
2488259698Sdim                           opnode, zext, VPR64, v8i16, v8i8>;
2489259698Sdim    def _4s4h : NeonI_3VDL<0b0, u, 0b01, opcode, asmop, "4s", "4h",
2490259698Sdim                           opnode, zext, VPR64, v4i32, v4i16>;
2491259698Sdim    def _2d2s : NeonI_3VDL<0b0, u, 0b10, opcode, asmop, "2d", "2s",
2492259698Sdim                           opnode, zext, VPR64, v2i64, v2i32>;
2493259698Sdim  }
2494259698Sdim}
2495259698Sdim
2496259698Sdimmulticlass NeonI_3VDL2_u<bit u, bits<4> opcode, string asmop,
2497259698Sdim                         SDPatternOperator opnode, bit Commutable = 0> {
2498259698Sdim  let isCommutable = Commutable in {
2499259698Sdim    def _8h16b : NeonI_3VDL<0b1, u, 0b00, opcode, asmop, "8h", "16b",
2500259698Sdim                            opnode, NI_zext_high_v8i8, VPR128, v8i16, v16i8>;
2501259698Sdim    def _4s8h : NeonI_3VDL<0b1, u, 0b01, opcode, asmop, "4s", "8h",
2502259698Sdim                           opnode, NI_zext_high_v4i16, VPR128, v4i32, v8i16>;
2503259698Sdim    def _2d4s : NeonI_3VDL<0b1, u, 0b10, opcode, asmop, "2d", "4s",
2504259698Sdim                           opnode, NI_zext_high_v2i32, VPR128, v2i64, v4i32>;
2505259698Sdim  }
2506259698Sdim}
2507259698Sdim
2508259698Sdimdefm SADDLvvv :  NeonI_3VDL_s<0b0, 0b0000, "saddl", add, 1>;
2509259698Sdimdefm UADDLvvv :  NeonI_3VDL_u<0b1, 0b0000, "uaddl", add, 1>;
2510259698Sdim
2511259698Sdimdefm SADDL2vvv :  NeonI_3VDL2_s<0b0, 0b0000, "saddl2", add, 1>;
2512259698Sdimdefm UADDL2vvv :  NeonI_3VDL2_u<0b1, 0b0000, "uaddl2", add, 1>;
2513259698Sdim
2514259698Sdimdefm SSUBLvvv :  NeonI_3VDL_s<0b0, 0b0010, "ssubl", sub, 0>;
2515259698Sdimdefm USUBLvvv :  NeonI_3VDL_u<0b1, 0b0010, "usubl", sub, 0>;
2516259698Sdim
2517259698Sdimdefm SSUBL2vvv :  NeonI_3VDL2_s<0b0, 0b0010, "ssubl2", sub, 0>;
2518259698Sdimdefm USUBL2vvv :  NeonI_3VDL2_u<0b1, 0b0010, "usubl2", sub, 0>;
2519259698Sdim
2520259698Sdim// normal wide/wide2 pattern
2521259698Sdimclass NeonI_3VDW<bit q, bit u, bits<2> size, bits<4> opcode,
2522259698Sdim                 string asmop, string ResS, string OpS,
2523259698Sdim                 SDPatternOperator opnode, SDPatternOperator ext,
2524259698Sdim                 RegisterOperand OpVPR,
2525259698Sdim                 ValueType ResTy, ValueType OpTy>
2526259698Sdim  : NeonI_3VDiff<q, u, size, opcode,
2527259698Sdim                 (outs VPR128:$Rd), (ins VPR128:$Rn, OpVPR:$Rm),
2528259698Sdim                 asmop # "\t$Rd." # ResS # ", $Rn." # ResS # ", $Rm." # OpS,
2529259698Sdim                 [(set (ResTy VPR128:$Rd),
2530259698Sdim                    (ResTy (opnode (ResTy VPR128:$Rn),
2531259698Sdim                                   (ResTy (ext (OpTy OpVPR:$Rm))))))],
2532259698Sdim                 NoItinerary>;
2533259698Sdim
2534259698Sdimmulticlass NeonI_3VDW_s<bit u, bits<4> opcode, string asmop,
2535259698Sdim                        SDPatternOperator opnode> {
2536259698Sdim  def _8h8b : NeonI_3VDW<0b0, u, 0b00, opcode, asmop, "8h", "8b",
2537259698Sdim                         opnode, sext, VPR64, v8i16, v8i8>;
2538259698Sdim  def _4s4h : NeonI_3VDW<0b0, u, 0b01, opcode, asmop, "4s", "4h",
2539259698Sdim                         opnode, sext, VPR64, v4i32, v4i16>;
2540259698Sdim  def _2d2s : NeonI_3VDW<0b0, u, 0b10, opcode, asmop, "2d", "2s",
2541259698Sdim                         opnode, sext, VPR64, v2i64, v2i32>;
2542259698Sdim}
2543259698Sdim
2544259698Sdimdefm SADDWvvv :  NeonI_3VDW_s<0b0, 0b0001, "saddw", add>;
2545259698Sdimdefm SSUBWvvv :  NeonI_3VDW_s<0b0, 0b0011, "ssubw", sub>;
2546259698Sdim
2547259698Sdimmulticlass NeonI_3VDW2_s<bit u, bits<4> opcode, string asmop,
2548259698Sdim                         SDPatternOperator opnode> {
2549259698Sdim  def _8h16b : NeonI_3VDW<0b1, u, 0b00, opcode, asmop, "8h", "16b",
2550259698Sdim                          opnode, NI_sext_high_v8i8, VPR128, v8i16, v16i8>;
2551259698Sdim  def _4s8h  : NeonI_3VDW<0b1, u, 0b01, opcode, asmop, "4s", "8h",
2552259698Sdim                          opnode, NI_sext_high_v4i16, VPR128, v4i32, v8i16>;
2553259698Sdim  def _2d4s  : NeonI_3VDW<0b1, u, 0b10, opcode, asmop, "2d", "4s",
2554259698Sdim                          opnode, NI_sext_high_v2i32, VPR128, v2i64, v4i32>;
2555259698Sdim}
2556259698Sdim
2557259698Sdimdefm SADDW2vvv :  NeonI_3VDW2_s<0b0, 0b0001, "saddw2", add>;
2558259698Sdimdefm SSUBW2vvv :  NeonI_3VDW2_s<0b0, 0b0011, "ssubw2", sub>;
2559259698Sdim
2560259698Sdimmulticlass NeonI_3VDW_u<bit u, bits<4> opcode, string asmop,
2561259698Sdim                        SDPatternOperator opnode> {
2562259698Sdim  def _8h8b : NeonI_3VDW<0b0, u, 0b00, opcode, asmop, "8h", "8b",
2563259698Sdim                         opnode, zext, VPR64, v8i16, v8i8>;
2564259698Sdim  def _4s4h : NeonI_3VDW<0b0, u, 0b01, opcode, asmop, "4s", "4h",
2565259698Sdim                         opnode, zext, VPR64, v4i32, v4i16>;
2566259698Sdim  def _2d2s : NeonI_3VDW<0b0, u, 0b10, opcode, asmop, "2d", "2s",
2567259698Sdim                         opnode, zext, VPR64, v2i64, v2i32>;
2568259698Sdim}
2569259698Sdim
2570259698Sdimdefm UADDWvvv :  NeonI_3VDW_u<0b1, 0b0001, "uaddw", add>;
2571259698Sdimdefm USUBWvvv :  NeonI_3VDW_u<0b1, 0b0011, "usubw", sub>;
2572259698Sdim
2573259698Sdimmulticlass NeonI_3VDW2_u<bit u, bits<4> opcode, string asmop,
2574259698Sdim                         SDPatternOperator opnode> {
2575259698Sdim  def _8h16b : NeonI_3VDW<0b1, u, 0b00, opcode, asmop, "8h", "16b",
2576259698Sdim                          opnode, NI_zext_high_v8i8, VPR128, v8i16, v16i8>;
2577259698Sdim  def _4s8h : NeonI_3VDW<0b1, u, 0b01, opcode, asmop, "4s", "8h",
2578259698Sdim                         opnode, NI_zext_high_v4i16, VPR128, v4i32, v8i16>;
2579259698Sdim  def _2d4s : NeonI_3VDW<0b1, u, 0b10, opcode, asmop, "2d", "4s",
2580259698Sdim                         opnode, NI_zext_high_v2i32, VPR128, v2i64, v4i32>;
2581259698Sdim}
2582259698Sdim
2583259698Sdimdefm UADDW2vvv :  NeonI_3VDW2_u<0b1, 0b0001, "uaddw2", add>;
2584259698Sdimdefm USUBW2vvv :  NeonI_3VDW2_u<0b1, 0b0011, "usubw2", sub>;
2585259698Sdim
2586259698Sdim// Get the high half part of the vector element.
2587259698Sdimmulticlass NeonI_get_high {
2588259698Sdim  def _8h : PatFrag<(ops node:$Rn),
2589259698Sdim                    (v8i8 (trunc (v8i16 (srl (v8i16 node:$Rn),
2590259698Sdim                                             (v8i16 (Neon_vdup (i32 8)))))))>;
2591259698Sdim  def _4s : PatFrag<(ops node:$Rn),
2592259698Sdim                    (v4i16 (trunc (v4i32 (srl (v4i32 node:$Rn),
2593259698Sdim                                              (v4i32 (Neon_vdup (i32 16)))))))>;
2594259698Sdim  def _2d : PatFrag<(ops node:$Rn),
2595259698Sdim                    (v2i32 (trunc (v2i64 (srl (v2i64 node:$Rn),
2596259698Sdim                                              (v2i64 (Neon_vdup (i32 32)))))))>;
2597259698Sdim}
2598259698Sdim
2599259698Sdimdefm NI_get_hi : NeonI_get_high;
2600259698Sdim
2601259698Sdim// pattern for addhn/subhn with 2 operands
2602259698Sdimclass NeonI_3VDN_addhn_2Op<bit q, bit u, bits<2> size, bits<4> opcode,
2603259698Sdim                           string asmop, string ResS, string OpS,
2604259698Sdim                           SDPatternOperator opnode, SDPatternOperator get_hi,
2605259698Sdim                           ValueType ResTy, ValueType OpTy>
2606259698Sdim  : NeonI_3VDiff<q, u, size, opcode,
2607259698Sdim                 (outs VPR64:$Rd), (ins VPR128:$Rn, VPR128:$Rm),
2608259698Sdim                 asmop # "\t$Rd." # ResS # ", $Rn." # OpS # ", $Rm." # OpS,
2609259698Sdim                 [(set (ResTy VPR64:$Rd),
2610259698Sdim                    (ResTy (get_hi
2611259698Sdim                      (OpTy (opnode (OpTy VPR128:$Rn),
2612259698Sdim                                    (OpTy VPR128:$Rm))))))],
2613259698Sdim                 NoItinerary>;
2614259698Sdim
2615259698Sdimmulticlass NeonI_3VDN_addhn_2Op<bit u, bits<4> opcode, string asmop,
2616259698Sdim                                SDPatternOperator opnode, bit Commutable = 0> {
2617259698Sdim  let isCommutable = Commutable in {
2618259698Sdim    def _8b8h : NeonI_3VDN_addhn_2Op<0b0, u, 0b00, opcode, asmop, "8b", "8h",
2619259698Sdim                                     opnode, NI_get_hi_8h, v8i8, v8i16>;
2620259698Sdim    def _4h4s : NeonI_3VDN_addhn_2Op<0b0, u, 0b01, opcode, asmop, "4h", "4s",
2621259698Sdim                                     opnode, NI_get_hi_4s, v4i16, v4i32>;
2622259698Sdim    def _2s2d : NeonI_3VDN_addhn_2Op<0b0, u, 0b10, opcode, asmop, "2s", "2d",
2623259698Sdim                                     opnode, NI_get_hi_2d, v2i32, v2i64>;
2624259698Sdim  }
2625259698Sdim}
2626259698Sdim
2627259698Sdimdefm ADDHNvvv  : NeonI_3VDN_addhn_2Op<0b0, 0b0100, "addhn", add, 1>;
2628259698Sdimdefm SUBHNvvv  : NeonI_3VDN_addhn_2Op<0b0, 0b0110, "subhn", sub, 0>;
2629259698Sdim
2630259698Sdim// pattern for operation with 2 operands
2631259698Sdimclass NeonI_3VD_2Op<bit q, bit u, bits<2> size, bits<4> opcode,
2632259698Sdim                    string asmop, string ResS, string OpS,
2633259698Sdim                    SDPatternOperator opnode,
2634259698Sdim                    RegisterOperand ResVPR, RegisterOperand OpVPR,
2635259698Sdim                    ValueType ResTy, ValueType OpTy>
2636259698Sdim  : NeonI_3VDiff<q, u, size, opcode,
2637259698Sdim                 (outs ResVPR:$Rd), (ins OpVPR:$Rn, OpVPR:$Rm),
2638259698Sdim                 asmop # "\t$Rd." # ResS # ", $Rn." # OpS # ", $Rm." # OpS,
2639259698Sdim                 [(set (ResTy ResVPR:$Rd),
2640259698Sdim                    (ResTy (opnode (OpTy OpVPR:$Rn), (OpTy OpVPR:$Rm))))],
2641259698Sdim                 NoItinerary>;
2642259698Sdim
2643259698Sdim// normal narrow pattern
2644259698Sdimmulticlass NeonI_3VDN_2Op<bit u, bits<4> opcode, string asmop,
2645259698Sdim                          SDPatternOperator opnode, bit Commutable = 0> {
2646259698Sdim  let isCommutable = Commutable in {
2647259698Sdim    def _8b8h : NeonI_3VD_2Op<0b0, u, 0b00, opcode, asmop, "8b", "8h",
2648259698Sdim                              opnode, VPR64, VPR128, v8i8, v8i16>;
2649259698Sdim    def _4h4s : NeonI_3VD_2Op<0b0, u, 0b01, opcode, asmop, "4h", "4s",
2650259698Sdim                              opnode, VPR64, VPR128, v4i16, v4i32>;
2651259698Sdim    def _2s2d : NeonI_3VD_2Op<0b0, u, 0b10, opcode, asmop, "2s", "2d",
2652259698Sdim                              opnode, VPR64, VPR128, v2i32, v2i64>;
2653259698Sdim  }
2654259698Sdim}
2655259698Sdim
2656259698Sdimdefm RADDHNvvv : NeonI_3VDN_2Op<0b1, 0b0100, "raddhn", int_arm_neon_vraddhn, 1>;
2657259698Sdimdefm RSUBHNvvv : NeonI_3VDN_2Op<0b1, 0b0110, "rsubhn", int_arm_neon_vrsubhn, 0>;
2658259698Sdim
2659259698Sdim// pattern for acle intrinsic with 3 operands
2660259698Sdimclass NeonI_3VDN_3Op<bit q, bit u, bits<2> size, bits<4> opcode,
2661259698Sdim                     string asmop, string ResS, string OpS>
2662259698Sdim  : NeonI_3VDiff<q, u, size, opcode,
2663259698Sdim                 (outs VPR128:$Rd), (ins VPR128:$src, VPR128:$Rn, VPR128:$Rm),
2664259698Sdim                 asmop # "\t$Rd." # ResS # ", $Rn." # OpS # ", $Rm." # OpS,
2665259698Sdim                 [], NoItinerary> {
2666259698Sdim  let Constraints = "$src = $Rd";
2667259698Sdim  let neverHasSideEffects = 1;
2668259698Sdim}
2669259698Sdim
2670259698Sdimmulticlass NeonI_3VDN_3Op_v1<bit u, bits<4> opcode, string asmop> {
2671259698Sdim  def _16b8h : NeonI_3VDN_3Op<0b1, u, 0b00, opcode, asmop, "16b", "8h">;
2672259698Sdim  def _8h4s : NeonI_3VDN_3Op<0b1, u, 0b01, opcode, asmop, "8h", "4s">;
2673259698Sdim  def _4s2d : NeonI_3VDN_3Op<0b1, u, 0b10, opcode, asmop, "4s", "2d">;
2674259698Sdim}
2675259698Sdim
2676259698Sdimdefm ADDHN2vvv  : NeonI_3VDN_3Op_v1<0b0, 0b0100, "addhn2">;
2677259698Sdimdefm SUBHN2vvv  : NeonI_3VDN_3Op_v1<0b0, 0b0110, "subhn2">;
2678259698Sdim
2679259698Sdimdefm RADDHN2vvv : NeonI_3VDN_3Op_v1<0b1, 0b0100, "raddhn2">;
2680259698Sdimdefm RSUBHN2vvv : NeonI_3VDN_3Op_v1<0b1, 0b0110, "rsubhn2">;
2681259698Sdim
2682259698Sdim// Patterns have to be separate because there's a SUBREG_TO_REG in the output
2683259698Sdim// part.
2684259698Sdimclass NarrowHighHalfPat<Instruction INST, ValueType DstTy, ValueType SrcTy,
2685259698Sdim                        SDPatternOperator coreop>
2686259698Sdim  : Pat<(Neon_combine_2D (v1i64 VPR64:$src),
2687259698Sdim                      (v1i64 (bitconvert (DstTy (coreop (SrcTy VPR128:$Rn),
2688259698Sdim                                                        (SrcTy VPR128:$Rm)))))),
2689259698Sdim        (INST (SUBREG_TO_REG (i64 0), VPR64:$src, sub_64),
2690259698Sdim              VPR128:$Rn, VPR128:$Rm)>;
2691259698Sdim
2692259698Sdim// addhn2 patterns
2693259698Sdimdef : NarrowHighHalfPat<ADDHN2vvv_16b8h, v8i8,  v8i16,
2694259698Sdim          BinOpFrag<(NI_get_hi_8h (add node:$LHS, node:$RHS))>>;
2695259698Sdimdef : NarrowHighHalfPat<ADDHN2vvv_8h4s,  v4i16, v4i32,
2696259698Sdim          BinOpFrag<(NI_get_hi_4s (add node:$LHS, node:$RHS))>>;
2697259698Sdimdef : NarrowHighHalfPat<ADDHN2vvv_4s2d,  v2i32, v2i64,
2698259698Sdim          BinOpFrag<(NI_get_hi_2d (add node:$LHS, node:$RHS))>>;
2699259698Sdim
2700259698Sdim// subhn2 patterns
2701259698Sdimdef : NarrowHighHalfPat<SUBHN2vvv_16b8h, v8i8,  v8i16,
2702259698Sdim          BinOpFrag<(NI_get_hi_8h (sub node:$LHS, node:$RHS))>>;
2703259698Sdimdef : NarrowHighHalfPat<SUBHN2vvv_8h4s,  v4i16, v4i32,
2704259698Sdim          BinOpFrag<(NI_get_hi_4s (sub node:$LHS, node:$RHS))>>;
2705259698Sdimdef : NarrowHighHalfPat<SUBHN2vvv_4s2d,  v2i32, v2i64,
2706259698Sdim          BinOpFrag<(NI_get_hi_2d (sub node:$LHS, node:$RHS))>>;
2707259698Sdim
2708259698Sdim// raddhn2 patterns
2709259698Sdimdef : NarrowHighHalfPat<RADDHN2vvv_16b8h, v8i8,  v8i16, int_arm_neon_vraddhn>;
2710259698Sdimdef : NarrowHighHalfPat<RADDHN2vvv_8h4s,  v4i16, v4i32, int_arm_neon_vraddhn>;
2711259698Sdimdef : NarrowHighHalfPat<RADDHN2vvv_4s2d,  v2i32, v2i64, int_arm_neon_vraddhn>;
2712259698Sdim
2713259698Sdim// rsubhn2 patterns
2714259698Sdimdef : NarrowHighHalfPat<RSUBHN2vvv_16b8h, v8i8,  v8i16, int_arm_neon_vrsubhn>;
2715259698Sdimdef : NarrowHighHalfPat<RSUBHN2vvv_8h4s,  v4i16, v4i32, int_arm_neon_vrsubhn>;
2716259698Sdimdef : NarrowHighHalfPat<RSUBHN2vvv_4s2d,  v2i32, v2i64, int_arm_neon_vrsubhn>;
2717259698Sdim
2718259698Sdim// pattern that need to extend result
2719259698Sdimclass NeonI_3VDL_Ext<bit q, bit u, bits<2> size, bits<4> opcode,
2720259698Sdim                     string asmop, string ResS, string OpS,
2721259698Sdim                     SDPatternOperator opnode,
2722259698Sdim                     RegisterOperand OpVPR,
2723259698Sdim                     ValueType ResTy, ValueType OpTy, ValueType OpSTy>
2724259698Sdim  : NeonI_3VDiff<q, u, size, opcode,
2725259698Sdim                 (outs VPR128:$Rd), (ins OpVPR:$Rn, OpVPR:$Rm),
2726259698Sdim                 asmop # "\t$Rd." # ResS # ", $Rn." # OpS # ", $Rm." # OpS,
2727259698Sdim                 [(set (ResTy VPR128:$Rd),
2728259698Sdim                    (ResTy (zext (OpSTy (opnode (OpTy OpVPR:$Rn),
2729259698Sdim                                                (OpTy OpVPR:$Rm))))))],
2730259698Sdim                 NoItinerary>;
2731259698Sdim
2732259698Sdimmulticlass NeonI_3VDL_zext<bit u, bits<4> opcode, string asmop,
2733259698Sdim                           SDPatternOperator opnode, bit Commutable = 0> {
2734259698Sdim  let isCommutable = Commutable in {
2735259698Sdim    def _8h8b : NeonI_3VDL_Ext<0b0, u, 0b00, opcode, asmop, "8h", "8b",
2736259698Sdim                               opnode, VPR64, v8i16, v8i8, v8i8>;
2737259698Sdim    def _4s4h : NeonI_3VDL_Ext<0b0, u, 0b01, opcode, asmop, "4s", "4h",
2738259698Sdim                               opnode, VPR64, v4i32, v4i16, v4i16>;
2739259698Sdim    def _2d2s : NeonI_3VDL_Ext<0b0, u, 0b10, opcode, asmop, "2d", "2s",
2740259698Sdim                               opnode, VPR64, v2i64, v2i32, v2i32>;
2741259698Sdim  }
2742259698Sdim}
2743259698Sdim
2744259698Sdimdefm SABDLvvv : NeonI_3VDL_zext<0b0, 0b0111, "sabdl", int_arm_neon_vabds, 1>;
2745259698Sdimdefm UABDLvvv : NeonI_3VDL_zext<0b1, 0b0111, "uabdl", int_arm_neon_vabdu, 1>;
2746259698Sdim
2747259698Sdimmulticlass NeonI_Op_High<SDPatternOperator op> {
2748259698Sdim  def _16B : PatFrag<(ops node:$Rn, node:$Rm),
2749259698Sdim                     (op (v8i8 (Neon_High16B node:$Rn)),
2750259698Sdim                         (v8i8 (Neon_High16B node:$Rm)))>;
2751259698Sdim  def _8H  : PatFrag<(ops node:$Rn, node:$Rm),
2752259698Sdim                     (op (v4i16 (Neon_High8H node:$Rn)),
2753259698Sdim                         (v4i16 (Neon_High8H node:$Rm)))>;
2754259698Sdim  def _4S  : PatFrag<(ops node:$Rn, node:$Rm),
2755259698Sdim                     (op (v2i32 (Neon_High4S node:$Rn)),
2756259698Sdim                         (v2i32 (Neon_High4S node:$Rm)))>;
2757259698Sdim}
2758259698Sdim
2759259698Sdimdefm NI_sabdl_hi : NeonI_Op_High<int_arm_neon_vabds>;
2760259698Sdimdefm NI_uabdl_hi : NeonI_Op_High<int_arm_neon_vabdu>;
2761259698Sdimdefm NI_smull_hi : NeonI_Op_High<int_arm_neon_vmulls>;
2762259698Sdimdefm NI_umull_hi : NeonI_Op_High<int_arm_neon_vmullu>;
2763259698Sdimdefm NI_qdmull_hi : NeonI_Op_High<int_arm_neon_vqdmull>;
2764259698Sdimdefm NI_pmull_hi : NeonI_Op_High<int_arm_neon_vmullp>;
2765259698Sdim
2766259698Sdimmulticlass NeonI_3VDL_Abd_u<bit u, bits<4> opcode, string asmop, string opnode,
2767259698Sdim                            bit Commutable = 0> {
2768259698Sdim  let isCommutable = Commutable in {
2769259698Sdim    def _8h8b  : NeonI_3VDL_Ext<0b1, u, 0b00, opcode, asmop, "8h", "16b",
2770259698Sdim                                !cast<PatFrag>(opnode # "_16B"),
2771259698Sdim                                VPR128, v8i16, v16i8, v8i8>;
2772259698Sdim    def _4s4h  : NeonI_3VDL_Ext<0b1, u, 0b01, opcode, asmop, "4s", "8h",
2773259698Sdim                                !cast<PatFrag>(opnode # "_8H"),
2774259698Sdim                                VPR128, v4i32, v8i16, v4i16>;
2775259698Sdim    def _2d2s  : NeonI_3VDL_Ext<0b1, u, 0b10, opcode, asmop, "2d", "4s",
2776259698Sdim                                !cast<PatFrag>(opnode # "_4S"),
2777259698Sdim                                VPR128, v2i64, v4i32, v2i32>;
2778259698Sdim  }
2779259698Sdim}
2780259698Sdim
2781259698Sdimdefm SABDL2vvv : NeonI_3VDL_Abd_u<0b0, 0b0111, "sabdl2", "NI_sabdl_hi", 1>;
2782259698Sdimdefm UABDL2vvv : NeonI_3VDL_Abd_u<0b1, 0b0111, "uabdl2", "NI_uabdl_hi", 1>;
2783259698Sdim
2784259698Sdim// For pattern that need two operators being chained.
2785259698Sdimclass NeonI_3VDL_Aba<bit q, bit u, bits<2> size, bits<4> opcode,
2786259698Sdim                     string asmop, string ResS, string OpS,
2787259698Sdim                     SDPatternOperator opnode, SDPatternOperator subop,
2788259698Sdim                     RegisterOperand OpVPR,
2789259698Sdim                     ValueType ResTy, ValueType OpTy, ValueType OpSTy>
2790259698Sdim  : NeonI_3VDiff<q, u, size, opcode,
2791259698Sdim                 (outs VPR128:$Rd), (ins VPR128:$src, OpVPR:$Rn, OpVPR:$Rm),
2792259698Sdim                 asmop # "\t$Rd." # ResS # ", $Rn." # OpS # ", $Rm." # OpS,
2793259698Sdim                 [(set (ResTy VPR128:$Rd),
2794259698Sdim                    (ResTy (opnode
2795259698Sdim                      (ResTy VPR128:$src),
2796259698Sdim                      (ResTy (zext (OpSTy (subop (OpTy OpVPR:$Rn),
2797259698Sdim                                                 (OpTy OpVPR:$Rm))))))))],
2798259698Sdim                 NoItinerary> {
2799259698Sdim  let Constraints = "$src = $Rd";
2800259698Sdim}
2801259698Sdim
2802259698Sdimmulticlass NeonI_3VDL_Aba_v1<bit u, bits<4> opcode, string asmop,
2803259698Sdim                             SDPatternOperator opnode, SDPatternOperator subop>{
2804259698Sdim  def _8h8b : NeonI_3VDL_Aba<0b0, u, 0b00, opcode, asmop, "8h", "8b",
2805259698Sdim                             opnode, subop, VPR64, v8i16, v8i8, v8i8>;
2806259698Sdim  def _4s4h : NeonI_3VDL_Aba<0b0, u, 0b01, opcode, asmop, "4s", "4h",
2807259698Sdim                             opnode, subop, VPR64, v4i32, v4i16, v4i16>;
2808259698Sdim  def _2d2s : NeonI_3VDL_Aba<0b0, u, 0b10, opcode, asmop, "2d", "2s",
2809259698Sdim                             opnode, subop, VPR64, v2i64, v2i32, v2i32>;
2810259698Sdim}
2811259698Sdim
2812259698Sdimdefm SABALvvv :  NeonI_3VDL_Aba_v1<0b0, 0b0101, "sabal",
2813259698Sdim                                   add, int_arm_neon_vabds>;
2814259698Sdimdefm UABALvvv :  NeonI_3VDL_Aba_v1<0b1, 0b0101, "uabal",
2815259698Sdim                                   add, int_arm_neon_vabdu>;
2816259698Sdim
2817259698Sdimmulticlass NeonI_3VDL2_Aba_v1<bit u, bits<4> opcode, string asmop,
2818259698Sdim                              SDPatternOperator opnode, string subop> {
2819259698Sdim  def _8h8b : NeonI_3VDL_Aba<0b1, u, 0b00, opcode, asmop, "8h", "16b",
2820259698Sdim                             opnode, !cast<PatFrag>(subop # "_16B"),
2821259698Sdim                             VPR128, v8i16, v16i8, v8i8>;
2822259698Sdim  def _4s4h : NeonI_3VDL_Aba<0b1, u, 0b01, opcode, asmop, "4s", "8h",
2823259698Sdim                             opnode, !cast<PatFrag>(subop # "_8H"),
2824259698Sdim                             VPR128, v4i32, v8i16, v4i16>;
2825259698Sdim  def _2d2s : NeonI_3VDL_Aba<0b1, u, 0b10, opcode, asmop, "2d", "4s",
2826259698Sdim                             opnode, !cast<PatFrag>(subop # "_4S"),
2827259698Sdim                             VPR128, v2i64, v4i32, v2i32>;
2828259698Sdim}
2829259698Sdim
2830259698Sdimdefm SABAL2vvv :  NeonI_3VDL2_Aba_v1<0b0, 0b0101, "sabal2", add,
2831259698Sdim                                     "NI_sabdl_hi">;
2832259698Sdimdefm UABAL2vvv :  NeonI_3VDL2_Aba_v1<0b1, 0b0101, "uabal2", add,
2833259698Sdim                                     "NI_uabdl_hi">;
2834259698Sdim
2835259698Sdim// Long pattern with 2 operands
2836259698Sdimmulticlass NeonI_3VDL_2Op<bit u, bits<4> opcode, string asmop,
2837259698Sdim                          SDPatternOperator opnode, bit Commutable = 0> {
2838259698Sdim  let isCommutable = Commutable in {
2839259698Sdim    def _8h8b : NeonI_3VD_2Op<0b0, u, 0b00, opcode, asmop, "8h", "8b",
2840259698Sdim                              opnode, VPR128, VPR64, v8i16, v8i8>;
2841259698Sdim    def _4s4h : NeonI_3VD_2Op<0b0, u, 0b01, opcode, asmop, "4s", "4h",
2842259698Sdim                              opnode, VPR128, VPR64, v4i32, v4i16>;
2843259698Sdim    def _2d2s : NeonI_3VD_2Op<0b0, u, 0b10, opcode, asmop, "2d", "2s",
2844259698Sdim                              opnode, VPR128, VPR64, v2i64, v2i32>;
2845259698Sdim  }
2846259698Sdim}
2847259698Sdim
2848259698Sdimdefm SMULLvvv :  NeonI_3VDL_2Op<0b0, 0b1100, "smull", int_arm_neon_vmulls, 1>;
2849259698Sdimdefm UMULLvvv :  NeonI_3VDL_2Op<0b1, 0b1100, "umull", int_arm_neon_vmullu, 1>;
2850259698Sdim
2851259698Sdimclass NeonI_3VDL2_2Op_mull<bit q, bit u, bits<2> size, bits<4> opcode,
2852259698Sdim                           string asmop, string ResS, string OpS,
2853259698Sdim                           SDPatternOperator opnode,
2854259698Sdim                           ValueType ResTy, ValueType OpTy>
2855259698Sdim  : NeonI_3VDiff<q, u, size, opcode,
2856259698Sdim                 (outs VPR128:$Rd), (ins VPR128:$Rn, VPR128:$Rm),
2857259698Sdim                 asmop # "\t$Rd." # ResS # ", $Rn." # OpS # ", $Rm." # OpS,
2858259698Sdim                 [(set (ResTy VPR128:$Rd),
2859259698Sdim                    (ResTy (opnode (OpTy VPR128:$Rn), (OpTy VPR128:$Rm))))],
2860259698Sdim                 NoItinerary>;
2861259698Sdim
2862259698Sdimmulticlass NeonI_3VDL2_2Op_mull_v1<bit u, bits<4> opcode, string asmop,
2863259698Sdim                                   string opnode, bit Commutable = 0> {
2864259698Sdim  let isCommutable = Commutable in {
2865259698Sdim    def _8h16b : NeonI_3VDL2_2Op_mull<0b1, u, 0b00, opcode, asmop, "8h", "16b",
2866259698Sdim                                      !cast<PatFrag>(opnode # "_16B"),
2867259698Sdim                                      v8i16, v16i8>;
2868259698Sdim    def _4s8h : NeonI_3VDL2_2Op_mull<0b1, u, 0b01, opcode, asmop, "4s", "8h",
2869259698Sdim                                     !cast<PatFrag>(opnode # "_8H"),
2870259698Sdim                                     v4i32, v8i16>;
2871259698Sdim    def _2d4s : NeonI_3VDL2_2Op_mull<0b1, u, 0b10, opcode, asmop, "2d", "4s",
2872259698Sdim                                     !cast<PatFrag>(opnode # "_4S"),
2873259698Sdim                                     v2i64, v4i32>;
2874259698Sdim  }
2875259698Sdim}
2876259698Sdim
2877259698Sdimdefm SMULL2vvv : NeonI_3VDL2_2Op_mull_v1<0b0, 0b1100, "smull2",
2878259698Sdim                                         "NI_smull_hi", 1>;
2879259698Sdimdefm UMULL2vvv : NeonI_3VDL2_2Op_mull_v1<0b1, 0b1100, "umull2",
2880259698Sdim                                         "NI_umull_hi", 1>;
2881259698Sdim
2882259698Sdim// Long pattern with 3 operands
2883259698Sdimclass NeonI_3VDL_3Op<bit q, bit u, bits<2> size, bits<4> opcode,
2884259698Sdim                     string asmop, string ResS, string OpS,
2885259698Sdim                     SDPatternOperator opnode,
2886259698Sdim                     ValueType ResTy, ValueType OpTy>
2887259698Sdim  : NeonI_3VDiff<q, u, size, opcode,
2888259698Sdim                 (outs VPR128:$Rd), (ins VPR128:$src, VPR64:$Rn, VPR64:$Rm),
2889259698Sdim                 asmop # "\t$Rd." # ResS # ", $Rn." # OpS # ", $Rm." # OpS,
2890259698Sdim                 [(set (ResTy VPR128:$Rd),
2891259698Sdim                    (ResTy (opnode
2892259698Sdim                      (ResTy VPR128:$src),
2893259698Sdim                      (OpTy VPR64:$Rn), (OpTy VPR64:$Rm))))],
2894259698Sdim               NoItinerary> {
2895259698Sdim  let Constraints = "$src = $Rd";
2896259698Sdim}
2897259698Sdim
2898259698Sdimmulticlass NeonI_3VDL_3Op_v1<bit u, bits<4> opcode, string asmop,
2899259698Sdim                             SDPatternOperator opnode> {
2900259698Sdim  def _8h8b : NeonI_3VDL_3Op<0b0, u, 0b00, opcode, asmop, "8h", "8b",
2901259698Sdim                             opnode, v8i16, v8i8>;
2902259698Sdim  def _4s4h : NeonI_3VDL_3Op<0b0, u, 0b01, opcode, asmop, "4s", "4h",
2903259698Sdim                             opnode, v4i32, v4i16>;
2904259698Sdim  def _2d2s : NeonI_3VDL_3Op<0b0, u, 0b10, opcode, asmop, "2d", "2s",
2905259698Sdim                             opnode, v2i64, v2i32>;
2906259698Sdim}
2907259698Sdim
2908259698Sdimdef Neon_smlal : PatFrag<(ops node:$Rd, node:$Rn, node:$Rm),
2909259698Sdim                         (add node:$Rd,
2910259698Sdim                            (int_arm_neon_vmulls node:$Rn, node:$Rm))>;
2911259698Sdim
2912259698Sdimdef Neon_umlal : PatFrag<(ops node:$Rd, node:$Rn, node:$Rm),
2913259698Sdim                         (add node:$Rd,
2914259698Sdim                            (int_arm_neon_vmullu node:$Rn, node:$Rm))>;
2915259698Sdim
2916259698Sdimdef Neon_smlsl : PatFrag<(ops node:$Rd, node:$Rn, node:$Rm),
2917259698Sdim                         (sub node:$Rd,
2918259698Sdim                            (int_arm_neon_vmulls node:$Rn, node:$Rm))>;
2919259698Sdim
2920259698Sdimdef Neon_umlsl : PatFrag<(ops node:$Rd, node:$Rn, node:$Rm),
2921259698Sdim                         (sub node:$Rd,
2922259698Sdim                            (int_arm_neon_vmullu node:$Rn, node:$Rm))>;
2923259698Sdim
2924259698Sdimdefm SMLALvvv :  NeonI_3VDL_3Op_v1<0b0, 0b1000, "smlal", Neon_smlal>;
2925259698Sdimdefm UMLALvvv :  NeonI_3VDL_3Op_v1<0b1, 0b1000, "umlal", Neon_umlal>;
2926259698Sdim
2927259698Sdimdefm SMLSLvvv :  NeonI_3VDL_3Op_v1<0b0, 0b1010, "smlsl", Neon_smlsl>;
2928259698Sdimdefm UMLSLvvv :  NeonI_3VDL_3Op_v1<0b1, 0b1010, "umlsl", Neon_umlsl>;
2929259698Sdim
2930259698Sdimclass NeonI_3VDL2_3Op_mlas<bit q, bit u, bits<2> size, bits<4> opcode,
2931259698Sdim                           string asmop, string ResS, string OpS,
2932259698Sdim                           SDPatternOperator subop, SDPatternOperator opnode,
2933259698Sdim                           RegisterOperand OpVPR,
2934259698Sdim                           ValueType ResTy, ValueType OpTy>
2935259698Sdim  : NeonI_3VDiff<q, u, size, opcode,
2936259698Sdim               (outs VPR128:$Rd), (ins VPR128:$src, OpVPR:$Rn, OpVPR:$Rm),
2937259698Sdim               asmop # "\t$Rd." # ResS # ", $Rn." # OpS # ", $Rm." # OpS,
2938259698Sdim               [(set (ResTy VPR128:$Rd),
2939259698Sdim                  (ResTy (subop
2940259698Sdim                    (ResTy VPR128:$src),
2941259698Sdim                    (ResTy (opnode (OpTy OpVPR:$Rn), (OpTy OpVPR:$Rm))))))],
2942259698Sdim               NoItinerary> {
2943259698Sdim  let Constraints = "$src = $Rd";
2944259698Sdim}
2945259698Sdim
2946259698Sdimmulticlass NeonI_3VDL2_3Op_mlas_v1<bit u, bits<4> opcode, string asmop,
2947259698Sdim                                   SDPatternOperator subop, string opnode> {
2948259698Sdim  def _8h16b : NeonI_3VDL2_3Op_mlas<0b1, u, 0b00, opcode, asmop, "8h", "16b",
2949259698Sdim                                    subop, !cast<PatFrag>(opnode # "_16B"),
2950259698Sdim                                    VPR128, v8i16, v16i8>;
2951259698Sdim  def _4s8h : NeonI_3VDL2_3Op_mlas<0b1, u, 0b01, opcode, asmop, "4s", "8h",
2952259698Sdim                                   subop, !cast<PatFrag>(opnode # "_8H"),
2953259698Sdim                                   VPR128, v4i32, v8i16>;
2954259698Sdim  def _2d4s : NeonI_3VDL2_3Op_mlas<0b1, u, 0b10, opcode, asmop, "2d", "4s",
2955259698Sdim                                   subop, !cast<PatFrag>(opnode # "_4S"),
2956259698Sdim                                   VPR128, v2i64, v4i32>;
2957259698Sdim}
2958259698Sdim
2959259698Sdimdefm SMLAL2vvv :  NeonI_3VDL2_3Op_mlas_v1<0b0, 0b1000, "smlal2",
2960259698Sdim                                          add, "NI_smull_hi">;
2961259698Sdimdefm UMLAL2vvv :  NeonI_3VDL2_3Op_mlas_v1<0b1, 0b1000, "umlal2",
2962259698Sdim                                          add, "NI_umull_hi">;
2963259698Sdim
2964259698Sdimdefm SMLSL2vvv :  NeonI_3VDL2_3Op_mlas_v1<0b0, 0b1010, "smlsl2",
2965259698Sdim                                          sub, "NI_smull_hi">;
2966259698Sdimdefm UMLSL2vvv :  NeonI_3VDL2_3Op_mlas_v1<0b1, 0b1010, "umlsl2",
2967259698Sdim                                          sub, "NI_umull_hi">;
2968259698Sdim
2969259698Sdimmulticlass NeonI_3VDL_qdmlal_3Op_v2<bit u, bits<4> opcode, string asmop,
2970259698Sdim                                    SDPatternOperator opnode> {
2971259698Sdim  def _4s4h : NeonI_3VDL2_3Op_mlas<0b0, u, 0b01, opcode, asmop, "4s", "4h",
2972259698Sdim                                   opnode, int_arm_neon_vqdmull,
2973259698Sdim                                   VPR64, v4i32, v4i16>;
2974259698Sdim  def _2d2s : NeonI_3VDL2_3Op_mlas<0b0, u, 0b10, opcode, asmop, "2d", "2s",
2975259698Sdim                                   opnode, int_arm_neon_vqdmull,
2976259698Sdim                                   VPR64, v2i64, v2i32>;
2977259698Sdim}
2978259698Sdim
2979259698Sdimdefm SQDMLALvvv : NeonI_3VDL_qdmlal_3Op_v2<0b0, 0b1001, "sqdmlal",
2980259698Sdim                                           int_arm_neon_vqadds>;
2981259698Sdimdefm SQDMLSLvvv : NeonI_3VDL_qdmlal_3Op_v2<0b0, 0b1011, "sqdmlsl",
2982259698Sdim                                           int_arm_neon_vqsubs>;
2983259698Sdim
2984259698Sdimmulticlass NeonI_3VDL_v2<bit u, bits<4> opcode, string asmop,
2985259698Sdim                         SDPatternOperator opnode, bit Commutable = 0> {
2986259698Sdim  let isCommutable = Commutable in {
2987259698Sdim    def _4s4h : NeonI_3VD_2Op<0b0, u, 0b01, opcode, asmop, "4s", "4h",
2988259698Sdim                              opnode, VPR128, VPR64, v4i32, v4i16>;
2989259698Sdim    def _2d2s : NeonI_3VD_2Op<0b0, u, 0b10, opcode, asmop, "2d", "2s",
2990259698Sdim                              opnode, VPR128, VPR64, v2i64, v2i32>;
2991259698Sdim  }
2992259698Sdim}
2993259698Sdim
2994259698Sdimdefm SQDMULLvvv : NeonI_3VDL_v2<0b0, 0b1101, "sqdmull",
2995259698Sdim                                int_arm_neon_vqdmull, 1>;
2996259698Sdim
2997259698Sdimmulticlass NeonI_3VDL2_2Op_mull_v2<bit u, bits<4> opcode, string asmop,
2998259698Sdim                                   string opnode, bit Commutable = 0> {
2999259698Sdim  let isCommutable = Commutable in {
3000259698Sdim    def _4s8h : NeonI_3VDL2_2Op_mull<0b1, u, 0b01, opcode, asmop, "4s", "8h",
3001259698Sdim                                     !cast<PatFrag>(opnode # "_8H"),
3002259698Sdim                                     v4i32, v8i16>;
3003259698Sdim    def _2d4s : NeonI_3VDL2_2Op_mull<0b1, u, 0b10, opcode, asmop, "2d", "4s",
3004259698Sdim                                     !cast<PatFrag>(opnode # "_4S"),
3005259698Sdim                                     v2i64, v4i32>;
3006259698Sdim  }
3007259698Sdim}
3008259698Sdim
3009259698Sdimdefm SQDMULL2vvv : NeonI_3VDL2_2Op_mull_v2<0b0, 0b1101, "sqdmull2",
3010259698Sdim                                           "NI_qdmull_hi", 1>;
3011259698Sdim
3012259698Sdimmulticlass NeonI_3VDL2_3Op_qdmlal_v2<bit u, bits<4> opcode, string asmop,
3013259698Sdim                                     SDPatternOperator opnode> {
3014259698Sdim  def _4s8h : NeonI_3VDL2_3Op_mlas<0b1, u, 0b01, opcode, asmop, "4s", "8h",
3015259698Sdim                                   opnode, NI_qdmull_hi_8H,
3016259698Sdim                                   VPR128, v4i32, v8i16>;
3017259698Sdim  def _2d4s : NeonI_3VDL2_3Op_mlas<0b1, u, 0b10, opcode, asmop, "2d", "4s",
3018259698Sdim                                   opnode, NI_qdmull_hi_4S,
3019259698Sdim                                   VPR128, v2i64, v4i32>;
3020259698Sdim}
3021259698Sdim
3022259698Sdimdefm SQDMLAL2vvv : NeonI_3VDL2_3Op_qdmlal_v2<0b0, 0b1001, "sqdmlal2",
3023259698Sdim                                             int_arm_neon_vqadds>;
3024259698Sdimdefm SQDMLSL2vvv : NeonI_3VDL2_3Op_qdmlal_v2<0b0, 0b1011, "sqdmlsl2",
3025259698Sdim                                             int_arm_neon_vqsubs>;
3026259698Sdim
3027259698Sdimmulticlass NeonI_3VDL_v3<bit u, bits<4> opcode, string asmop,
3028259698Sdim                         SDPatternOperator opnode, bit Commutable = 0> {
3029259698Sdim  let isCommutable = Commutable in {
3030259698Sdim    def _8h8b : NeonI_3VD_2Op<0b0, u, 0b00, opcode, asmop, "8h", "8b",
3031259698Sdim                              opnode, VPR128, VPR64, v8i16, v8i8>;
3032259698Sdim
3033259698Sdim    def _1q1d : NeonI_3VDiff<0b0, u, 0b11, opcode,
3034259698Sdim                             (outs VPR128:$Rd), (ins VPR64:$Rn, VPR64:$Rm),
3035259698Sdim                             asmop # "\t$Rd.1q, $Rn.1d, $Rm.1d",
3036259698Sdim                             [], NoItinerary>;
3037259698Sdim  }
3038259698Sdim}
3039259698Sdim
3040259698Sdimdefm PMULLvvv : NeonI_3VDL_v3<0b0, 0b1110, "pmull", int_arm_neon_vmullp, 1>;
3041259698Sdim
3042259698Sdimmulticlass NeonI_3VDL2_2Op_mull_v3<bit u, bits<4> opcode, string asmop,
3043259698Sdim                                   string opnode, bit Commutable = 0> {
3044259698Sdim  let isCommutable = Commutable in {
3045259698Sdim    def _8h16b : NeonI_3VDL2_2Op_mull<0b1, u, 0b00, opcode, asmop, "8h", "16b",
3046259698Sdim                                      !cast<PatFrag>(opnode # "_16B"),
3047259698Sdim                                      v8i16, v16i8>;
3048259698Sdim
3049259698Sdim    def _1q2d : NeonI_3VDiff<0b1, u, 0b11, opcode,
3050259698Sdim                             (outs VPR128:$Rd), (ins VPR128:$Rn, VPR128:$Rm),
3051259698Sdim                             asmop # "\t$Rd.1q, $Rn.2d, $Rm.2d",
3052259698Sdim                             [], NoItinerary>;
3053259698Sdim  }
3054259698Sdim}
3055259698Sdim
3056259698Sdimdefm PMULL2vvv : NeonI_3VDL2_2Op_mull_v3<0b0, 0b1110, "pmull2", "NI_pmull_hi",
3057259698Sdim                                         1>;
3058259698Sdim
3059259698Sdim// End of implementation for instruction class (3V Diff)
3060259698Sdim
3061259698Sdim// The followings are vector load/store multiple N-element structure
3062259698Sdim// (class SIMD lselem).
3063259698Sdim
3064259698Sdim// ld1:         load multiple 1-element structure to 1/2/3/4 registers.
3065259698Sdim// ld2/ld3/ld4: load multiple N-element structure to N registers (N = 2, 3, 4).
3066259698Sdim//              The structure consists of a sequence of sets of N values.
3067259698Sdim//              The first element of the structure is placed in the first lane
3068259698Sdim//              of the first first vector, the second element in the first lane
3069259698Sdim//              of the second vector, and so on.
3070259698Sdim// E.g. LD1_3V_2S will load 32-bit elements {A, B, C, D, E, F} sequentially into
3071259698Sdim// the three 64-bit vectors list {BA, DC, FE}.
3072259698Sdim// E.g. LD3_2S will load 32-bit elements {A, B, C, D, E, F} into the three
3073259698Sdim// 64-bit vectors list {DA, EB, FC}.
3074259698Sdim// Store instructions store multiple structure to N registers like load.
3075259698Sdim
3076259698Sdim
3077259698Sdimclass NeonI_LDVList<bit q, bits<4> opcode, bits<2> size,
3078259698Sdim                    RegisterOperand VecList, string asmop>
3079259698Sdim  : NeonI_LdStMult<q, 1, opcode, size,
3080259698Sdim                 (outs VecList:$Rt), (ins GPR64xsp:$Rn),
3081259698Sdim                 asmop # "\t$Rt, [$Rn]",
3082259698Sdim                 [],
3083259698Sdim                 NoItinerary> {
3084259698Sdim  let mayLoad = 1;
3085259698Sdim  let neverHasSideEffects = 1;
3086259698Sdim}
3087259698Sdim
3088259698Sdimmulticlass LDVList_BHSD<bits<4> opcode, string List, string asmop> {
3089259698Sdim  def _8B : NeonI_LDVList<0, opcode, 0b00,
3090259698Sdim                          !cast<RegisterOperand>(List # "8B_operand"), asmop>;
3091259698Sdim
3092259698Sdim  def _4H : NeonI_LDVList<0, opcode, 0b01,
3093259698Sdim                          !cast<RegisterOperand>(List # "4H_operand"), asmop>;
3094259698Sdim
3095259698Sdim  def _2S : NeonI_LDVList<0, opcode, 0b10,
3096259698Sdim                          !cast<RegisterOperand>(List # "2S_operand"), asmop>;
3097259698Sdim
3098259698Sdim  def _16B : NeonI_LDVList<1, opcode, 0b00,
3099259698Sdim                           !cast<RegisterOperand>(List # "16B_operand"), asmop>;
3100259698Sdim
3101259698Sdim  def _8H : NeonI_LDVList<1, opcode, 0b01,
3102259698Sdim                          !cast<RegisterOperand>(List # "8H_operand"), asmop>;
3103259698Sdim
3104259698Sdim  def _4S : NeonI_LDVList<1, opcode, 0b10,
3105259698Sdim                          !cast<RegisterOperand>(List # "4S_operand"), asmop>;
3106259698Sdim
3107259698Sdim  def _2D : NeonI_LDVList<1, opcode, 0b11,
3108259698Sdim                          !cast<RegisterOperand>(List # "2D_operand"), asmop>;
3109259698Sdim}
3110259698Sdim
3111259698Sdim// Load multiple N-element structure to N consecutive registers (N = 1,2,3,4)
3112259698Sdimdefm LD1 : LDVList_BHSD<0b0111, "VOne", "ld1">;
3113259698Sdimdef LD1_1D : NeonI_LDVList<0, 0b0111, 0b11, VOne1D_operand, "ld1">;
3114259698Sdim
3115259698Sdimdefm LD2 : LDVList_BHSD<0b1000, "VPair", "ld2">;
3116259698Sdim
3117259698Sdimdefm LD3 : LDVList_BHSD<0b0100, "VTriple", "ld3">;
3118259698Sdim
3119259698Sdimdefm LD4 : LDVList_BHSD<0b0000, "VQuad", "ld4">;
3120259698Sdim
3121259698Sdim// Load multiple 1-element structure to N consecutive registers (N = 2,3,4)
3122259698Sdimdefm LD1x2 : LDVList_BHSD<0b1010, "VPair", "ld1">;
3123259698Sdimdef LD1x2_1D : NeonI_LDVList<0, 0b1010, 0b11, VPair1D_operand, "ld1">;
3124259698Sdim
3125259698Sdimdefm LD1x3 : LDVList_BHSD<0b0110, "VTriple", "ld1">;
3126259698Sdimdef LD1x3_1D : NeonI_LDVList<0, 0b0110, 0b11, VTriple1D_operand, "ld1">;
3127259698Sdim
3128259698Sdimdefm LD1x4 : LDVList_BHSD<0b0010, "VQuad", "ld1">;
3129259698Sdimdef LD1x4_1D : NeonI_LDVList<0, 0b0010, 0b11, VQuad1D_operand, "ld1">;
3130259698Sdim
3131259698Sdimclass NeonI_STVList<bit q, bits<4> opcode, bits<2> size,
3132259698Sdim                    RegisterOperand VecList, string asmop>
3133259698Sdim  : NeonI_LdStMult<q, 0, opcode, size,
3134259698Sdim                 (outs), (ins GPR64xsp:$Rn, VecList:$Rt),
3135259698Sdim                 asmop # "\t$Rt, [$Rn]",
3136259698Sdim                 [],
3137259698Sdim                 NoItinerary> {
3138259698Sdim  let mayStore = 1;
3139259698Sdim  let neverHasSideEffects = 1;
3140259698Sdim}
3141259698Sdim
3142259698Sdimmulticlass STVList_BHSD<bits<4> opcode, string List, string asmop> {
3143259698Sdim  def _8B : NeonI_STVList<0, opcode, 0b00,
3144259698Sdim                          !cast<RegisterOperand>(List # "8B_operand"), asmop>;
3145259698Sdim
3146259698Sdim  def _4H : NeonI_STVList<0, opcode, 0b01,
3147259698Sdim                          !cast<RegisterOperand>(List # "4H_operand"), asmop>;
3148259698Sdim
3149259698Sdim  def _2S : NeonI_STVList<0, opcode, 0b10,
3150259698Sdim                          !cast<RegisterOperand>(List # "2S_operand"), asmop>;
3151259698Sdim
3152259698Sdim  def _16B : NeonI_STVList<1, opcode, 0b00,
3153259698Sdim                           !cast<RegisterOperand>(List # "16B_operand"), asmop>;
3154259698Sdim
3155259698Sdim  def _8H : NeonI_STVList<1, opcode, 0b01,
3156259698Sdim                          !cast<RegisterOperand>(List # "8H_operand"), asmop>;
3157259698Sdim
3158259698Sdim  def _4S : NeonI_STVList<1, opcode, 0b10,
3159259698Sdim                          !cast<RegisterOperand>(List # "4S_operand"), asmop>;
3160259698Sdim
3161259698Sdim  def _2D : NeonI_STVList<1, opcode, 0b11,
3162259698Sdim                          !cast<RegisterOperand>(List # "2D_operand"), asmop>;
3163259698Sdim}
3164259698Sdim
3165259698Sdim// Store multiple N-element structures from N registers (N = 1,2,3,4)
3166259698Sdimdefm ST1 : STVList_BHSD<0b0111, "VOne", "st1">;
3167259698Sdimdef ST1_1D : NeonI_STVList<0, 0b0111, 0b11, VOne1D_operand, "st1">;
3168259698Sdim
3169259698Sdimdefm ST2 : STVList_BHSD<0b1000, "VPair", "st2">;
3170259698Sdim
3171259698Sdimdefm ST3 : STVList_BHSD<0b0100, "VTriple", "st3">;
3172259698Sdim
3173259698Sdimdefm ST4 : STVList_BHSD<0b0000, "VQuad", "st4">;
3174259698Sdim
3175259698Sdim// Store multiple 1-element structures from N consecutive registers (N = 2,3,4)
3176259698Sdimdefm ST1x2 : STVList_BHSD<0b1010, "VPair", "st1">;
3177259698Sdimdef ST1x2_1D : NeonI_STVList<0, 0b1010, 0b11, VPair1D_operand, "st1">;
3178259698Sdim
3179259698Sdimdefm ST1x3 : STVList_BHSD<0b0110, "VTriple", "st1">;
3180259698Sdimdef ST1x3_1D : NeonI_STVList<0, 0b0110, 0b11, VTriple1D_operand, "st1">;
3181259698Sdim
3182259698Sdimdefm ST1x4 : STVList_BHSD<0b0010, "VQuad", "st1">;
3183259698Sdimdef ST1x4_1D : NeonI_STVList<0, 0b0010, 0b11, VQuad1D_operand, "st1">;
3184259698Sdim
3185259698Sdimdef : Pat<(v2f64 (load GPR64xsp:$addr)), (LD1_2D GPR64xsp:$addr)>;
3186259698Sdimdef : Pat<(v2i64 (load GPR64xsp:$addr)), (LD1_2D GPR64xsp:$addr)>;
3187259698Sdim
3188259698Sdimdef : Pat<(v4f32 (load GPR64xsp:$addr)), (LD1_4S GPR64xsp:$addr)>;
3189259698Sdimdef : Pat<(v4i32 (load GPR64xsp:$addr)), (LD1_4S GPR64xsp:$addr)>;
3190259698Sdim
3191259698Sdimdef : Pat<(v8i16 (load GPR64xsp:$addr)), (LD1_8H GPR64xsp:$addr)>;
3192259698Sdimdef : Pat<(v16i8 (load GPR64xsp:$addr)), (LD1_16B GPR64xsp:$addr)>;
3193259698Sdim
3194259698Sdimdef : Pat<(v1f64 (load GPR64xsp:$addr)), (LD1_1D GPR64xsp:$addr)>;
3195259698Sdimdef : Pat<(v1i64 (load GPR64xsp:$addr)), (LD1_1D GPR64xsp:$addr)>;
3196259698Sdim
3197259698Sdimdef : Pat<(v2f32 (load GPR64xsp:$addr)), (LD1_2S GPR64xsp:$addr)>;
3198259698Sdimdef : Pat<(v2i32 (load GPR64xsp:$addr)), (LD1_2S GPR64xsp:$addr)>;
3199259698Sdim
3200259698Sdimdef : Pat<(v4i16 (load GPR64xsp:$addr)), (LD1_4H GPR64xsp:$addr)>;
3201259698Sdimdef : Pat<(v8i8 (load GPR64xsp:$addr)), (LD1_8B GPR64xsp:$addr)>;
3202259698Sdim
3203259698Sdimdef : Pat<(store (v2i64 VPR128:$value), GPR64xsp:$addr),
3204259698Sdim          (ST1_2D GPR64xsp:$addr, VPR128:$value)>;
3205259698Sdimdef : Pat<(store (v2f64 VPR128:$value), GPR64xsp:$addr),
3206259698Sdim          (ST1_2D GPR64xsp:$addr, VPR128:$value)>;
3207259698Sdim
3208259698Sdimdef : Pat<(store (v4i32 VPR128:$value), GPR64xsp:$addr),
3209259698Sdim          (ST1_4S GPR64xsp:$addr, VPR128:$value)>;
3210259698Sdimdef : Pat<(store (v4f32 VPR128:$value), GPR64xsp:$addr),
3211259698Sdim          (ST1_4S GPR64xsp:$addr, VPR128:$value)>;
3212259698Sdim
3213259698Sdimdef : Pat<(store (v8i16 VPR128:$value), GPR64xsp:$addr),
3214259698Sdim          (ST1_8H GPR64xsp:$addr, VPR128:$value)>;
3215259698Sdimdef : Pat<(store (v16i8 VPR128:$value), GPR64xsp:$addr),
3216259698Sdim          (ST1_16B GPR64xsp:$addr, VPR128:$value)>;
3217259698Sdim
3218259698Sdimdef : Pat<(store (v1i64 VPR64:$value), GPR64xsp:$addr),
3219259698Sdim          (ST1_1D GPR64xsp:$addr, VPR64:$value)>;
3220259698Sdimdef : Pat<(store (v1f64 VPR64:$value), GPR64xsp:$addr),
3221259698Sdim          (ST1_1D GPR64xsp:$addr, VPR64:$value)>;
3222259698Sdim
3223259698Sdimdef : Pat<(store (v2i32 VPR64:$value), GPR64xsp:$addr),
3224259698Sdim          (ST1_2S GPR64xsp:$addr, VPR64:$value)>;
3225259698Sdimdef : Pat<(store (v2f32 VPR64:$value), GPR64xsp:$addr),
3226259698Sdim          (ST1_2S GPR64xsp:$addr, VPR64:$value)>;
3227259698Sdim
3228259698Sdimdef : Pat<(store (v4i16 VPR64:$value), GPR64xsp:$addr),
3229259698Sdim          (ST1_4H GPR64xsp:$addr, VPR64:$value)>;
3230259698Sdimdef : Pat<(store (v8i8 VPR64:$value), GPR64xsp:$addr),
3231259698Sdim          (ST1_8B GPR64xsp:$addr, VPR64:$value)>;
3232259698Sdim
3233259698Sdim// End of vector load/store multiple N-element structure(class SIMD lselem)
3234259698Sdim
3235259698Sdim// The followings are post-index vector load/store multiple N-element
3236259698Sdim// structure(class SIMD lselem-post)
3237259698Sdimdef exact1_asmoperand : AsmOperandClass {
3238259698Sdim  let Name = "Exact1";
3239259698Sdim  let PredicateMethod = "isExactImm<1>";
3240259698Sdim  let RenderMethod = "addImmOperands";
3241259698Sdim}
3242259698Sdimdef uimm_exact1 : Operand<i32>, ImmLeaf<i32, [{return Imm == 1;}]> {
3243259698Sdim  let ParserMatchClass = exact1_asmoperand;
3244259698Sdim}
3245259698Sdim
3246259698Sdimdef exact2_asmoperand : AsmOperandClass {
3247259698Sdim  let Name = "Exact2";
3248259698Sdim  let PredicateMethod = "isExactImm<2>";
3249259698Sdim  let RenderMethod = "addImmOperands";
3250259698Sdim}
3251259698Sdimdef uimm_exact2 : Operand<i32>, ImmLeaf<i32, [{return Imm == 2;}]> {
3252259698Sdim  let ParserMatchClass = exact2_asmoperand;
3253259698Sdim}
3254259698Sdim
3255259698Sdimdef exact3_asmoperand : AsmOperandClass {
3256259698Sdim  let Name = "Exact3";
3257259698Sdim  let PredicateMethod = "isExactImm<3>";
3258259698Sdim  let RenderMethod = "addImmOperands";
3259259698Sdim}
3260259698Sdimdef uimm_exact3 : Operand<i32>, ImmLeaf<i32, [{return Imm == 3;}]> {
3261259698Sdim  let ParserMatchClass = exact3_asmoperand;
3262259698Sdim}
3263259698Sdim
3264259698Sdimdef exact4_asmoperand : AsmOperandClass {
3265259698Sdim  let Name = "Exact4";
3266259698Sdim  let PredicateMethod = "isExactImm<4>";
3267259698Sdim  let RenderMethod = "addImmOperands";
3268259698Sdim}
3269259698Sdimdef uimm_exact4 : Operand<i32>, ImmLeaf<i32, [{return Imm == 4;}]> {
3270259698Sdim  let ParserMatchClass = exact4_asmoperand;
3271259698Sdim}
3272259698Sdim
3273259698Sdimdef exact6_asmoperand : AsmOperandClass {
3274259698Sdim  let Name = "Exact6";
3275259698Sdim  let PredicateMethod = "isExactImm<6>";
3276259698Sdim  let RenderMethod = "addImmOperands";
3277259698Sdim}
3278259698Sdimdef uimm_exact6 : Operand<i32>, ImmLeaf<i32, [{return Imm == 6;}]> {
3279259698Sdim  let ParserMatchClass = exact6_asmoperand;
3280259698Sdim}
3281259698Sdim
3282259698Sdimdef exact8_asmoperand : AsmOperandClass {
3283259698Sdim  let Name = "Exact8";
3284259698Sdim  let PredicateMethod = "isExactImm<8>";
3285259698Sdim  let RenderMethod = "addImmOperands";
3286259698Sdim}
3287259698Sdimdef uimm_exact8 : Operand<i32>, ImmLeaf<i32, [{return Imm == 8;}]> {
3288259698Sdim  let ParserMatchClass = exact8_asmoperand;
3289259698Sdim}
3290259698Sdim
3291259698Sdimdef exact12_asmoperand : AsmOperandClass {
3292259698Sdim  let Name = "Exact12";
3293259698Sdim  let PredicateMethod = "isExactImm<12>";
3294259698Sdim  let RenderMethod = "addImmOperands";
3295259698Sdim}
3296259698Sdimdef uimm_exact12 : Operand<i32>, ImmLeaf<i32, [{return Imm == 12;}]> {
3297259698Sdim  let ParserMatchClass = exact12_asmoperand;
3298259698Sdim}
3299259698Sdim
3300259698Sdimdef exact16_asmoperand : AsmOperandClass {
3301259698Sdim  let Name = "Exact16";
3302259698Sdim  let PredicateMethod = "isExactImm<16>";
3303259698Sdim  let RenderMethod = "addImmOperands";
3304259698Sdim}
3305259698Sdimdef uimm_exact16 : Operand<i32>, ImmLeaf<i32, [{return Imm == 16;}]> {
3306259698Sdim  let ParserMatchClass = exact16_asmoperand;
3307259698Sdim}
3308259698Sdim
3309259698Sdimdef exact24_asmoperand : AsmOperandClass {
3310259698Sdim  let Name = "Exact24";
3311259698Sdim  let PredicateMethod = "isExactImm<24>";
3312259698Sdim  let RenderMethod = "addImmOperands";
3313259698Sdim}
3314259698Sdimdef uimm_exact24 : Operand<i32>, ImmLeaf<i32, [{return Imm == 24;}]> {
3315259698Sdim  let ParserMatchClass = exact24_asmoperand;
3316259698Sdim}
3317259698Sdim
3318259698Sdimdef exact32_asmoperand : AsmOperandClass {
3319259698Sdim  let Name = "Exact32";
3320259698Sdim  let PredicateMethod = "isExactImm<32>";
3321259698Sdim  let RenderMethod = "addImmOperands";
3322259698Sdim}
3323259698Sdimdef uimm_exact32 : Operand<i32>, ImmLeaf<i32, [{return Imm == 32;}]> {
3324259698Sdim  let ParserMatchClass = exact32_asmoperand;
3325259698Sdim}
3326259698Sdim
3327259698Sdimdef exact48_asmoperand : AsmOperandClass {
3328259698Sdim  let Name = "Exact48";
3329259698Sdim  let PredicateMethod = "isExactImm<48>";
3330259698Sdim  let RenderMethod = "addImmOperands";
3331259698Sdim}
3332259698Sdimdef uimm_exact48 : Operand<i32>, ImmLeaf<i32, [{return Imm == 48;}]> {
3333259698Sdim  let ParserMatchClass = exact48_asmoperand;
3334259698Sdim}
3335259698Sdim
3336259698Sdimdef exact64_asmoperand : AsmOperandClass {
3337259698Sdim  let Name = "Exact64";
3338259698Sdim  let PredicateMethod = "isExactImm<64>";
3339259698Sdim  let RenderMethod = "addImmOperands";
3340259698Sdim}
3341259698Sdimdef uimm_exact64 : Operand<i32>, ImmLeaf<i32, [{return Imm == 64;}]> {
3342259698Sdim  let ParserMatchClass = exact64_asmoperand;
3343259698Sdim}
3344259698Sdim
3345259698Sdimmulticlass NeonI_LDWB_VList<bit q, bits<4> opcode, bits<2> size,
3346259698Sdim                           RegisterOperand VecList, Operand ImmTy,
3347259698Sdim                           string asmop> {
3348259698Sdim  let Constraints = "$Rn = $wb", mayLoad = 1, neverHasSideEffects = 1,
3349259698Sdim      DecoderMethod = "DecodeVLDSTPostInstruction" in {
3350259698Sdim    def _fixed : NeonI_LdStMult_Post<q, 1, opcode, size,
3351259698Sdim                     (outs VecList:$Rt, GPR64xsp:$wb),
3352259698Sdim                     (ins GPR64xsp:$Rn, ImmTy:$amt),
3353259698Sdim                     asmop # "\t$Rt, [$Rn], $amt",
3354259698Sdim                     [],
3355259698Sdim                     NoItinerary> {
3356259698Sdim      let Rm = 0b11111;
3357259698Sdim    }
3358259698Sdim
3359259698Sdim    def _register : NeonI_LdStMult_Post<q, 1, opcode, size,
3360259698Sdim                        (outs VecList:$Rt, GPR64xsp:$wb),
3361259698Sdim                        (ins GPR64xsp:$Rn, GPR64noxzr:$Rm),
3362259698Sdim                        asmop # "\t$Rt, [$Rn], $Rm",
3363259698Sdim                        [],
3364259698Sdim                        NoItinerary>;
3365259698Sdim  }
3366259698Sdim}
3367259698Sdim
3368259698Sdimmulticlass LDWB_VList_BHSD<bits<4> opcode, string List, Operand ImmTy,
3369259698Sdim    Operand ImmTy2, string asmop> {
3370259698Sdim  defm _8B : NeonI_LDWB_VList<0, opcode, 0b00,
3371259698Sdim                              !cast<RegisterOperand>(List # "8B_operand"),
3372259698Sdim                              ImmTy, asmop>;
3373259698Sdim
3374259698Sdim  defm _4H : NeonI_LDWB_VList<0, opcode, 0b01,
3375259698Sdim                              !cast<RegisterOperand>(List # "4H_operand"),
3376259698Sdim                              ImmTy, asmop>;
3377259698Sdim
3378259698Sdim  defm _2S : NeonI_LDWB_VList<0, opcode, 0b10,
3379259698Sdim                              !cast<RegisterOperand>(List # "2S_operand"),
3380259698Sdim                              ImmTy, asmop>;
3381259698Sdim
3382259698Sdim  defm _16B : NeonI_LDWB_VList<1, opcode, 0b00,
3383259698Sdim                               !cast<RegisterOperand>(List # "16B_operand"),
3384259698Sdim                               ImmTy2, asmop>;
3385259698Sdim
3386259698Sdim  defm _8H : NeonI_LDWB_VList<1, opcode, 0b01,
3387259698Sdim                              !cast<RegisterOperand>(List # "8H_operand"),
3388259698Sdim                              ImmTy2, asmop>;
3389259698Sdim
3390259698Sdim  defm _4S : NeonI_LDWB_VList<1, opcode, 0b10,
3391259698Sdim                              !cast<RegisterOperand>(List # "4S_operand"),
3392259698Sdim                              ImmTy2, asmop>;
3393259698Sdim
3394259698Sdim  defm _2D : NeonI_LDWB_VList<1, opcode, 0b11,
3395259698Sdim                              !cast<RegisterOperand>(List # "2D_operand"),
3396259698Sdim                              ImmTy2, asmop>;
3397259698Sdim}
3398259698Sdim
3399259698Sdim// Post-index load multiple N-element structures from N registers (N = 1,2,3,4)
3400259698Sdimdefm LD1WB : LDWB_VList_BHSD<0b0111, "VOne", uimm_exact8, uimm_exact16, "ld1">;
3401259698Sdimdefm LD1WB_1D : NeonI_LDWB_VList<0, 0b0111, 0b11, VOne1D_operand, uimm_exact8,
3402259698Sdim                                 "ld1">;
3403259698Sdim
3404259698Sdimdefm LD2WB : LDWB_VList_BHSD<0b1000, "VPair", uimm_exact16, uimm_exact32, "ld2">;
3405259698Sdim
3406259698Sdimdefm LD3WB : LDWB_VList_BHSD<0b0100, "VTriple", uimm_exact24, uimm_exact48,
3407259698Sdim                             "ld3">;
3408259698Sdim
3409259698Sdimdefm LD4WB : LDWB_VList_BHSD<0b0000, "VQuad", uimm_exact32, uimm_exact64, "ld4">;
3410259698Sdim
3411259698Sdim// Post-index load multiple 1-element structures from N consecutive registers
3412259698Sdim// (N = 2,3,4)
3413259698Sdimdefm LD1x2WB : LDWB_VList_BHSD<0b1010, "VPair", uimm_exact16, uimm_exact32,
3414259698Sdim                               "ld1">;
3415259698Sdimdefm LD1x2WB_1D : NeonI_LDWB_VList<0, 0b1010, 0b11, VPair1D_operand,
3416259698Sdim                                   uimm_exact16, "ld1">;
3417259698Sdim
3418259698Sdimdefm LD1x3WB : LDWB_VList_BHSD<0b0110, "VTriple", uimm_exact24, uimm_exact48,
3419259698Sdim                               "ld1">;
3420259698Sdimdefm LD1x3WB_1D : NeonI_LDWB_VList<0, 0b0110, 0b11, VTriple1D_operand,
3421259698Sdim                                   uimm_exact24, "ld1">;
3422259698Sdim
3423259698Sdimdefm LD1x4WB : LDWB_VList_BHSD<0b0010, "VQuad", uimm_exact32, uimm_exact64,
3424259698Sdim                                "ld1">;
3425259698Sdimdefm LD1x4WB_1D : NeonI_LDWB_VList<0, 0b0010, 0b11, VQuad1D_operand,
3426259698Sdim                                   uimm_exact32, "ld1">;
3427259698Sdim
3428259698Sdimmulticlass NeonI_STWB_VList<bit q, bits<4> opcode, bits<2> size,
3429259698Sdim                            RegisterOperand VecList, Operand ImmTy,
3430259698Sdim                            string asmop> {
3431259698Sdim  let Constraints = "$Rn = $wb", mayStore = 1, neverHasSideEffects = 1,
3432259698Sdim      DecoderMethod = "DecodeVLDSTPostInstruction" in {
3433259698Sdim    def _fixed : NeonI_LdStMult_Post<q, 0, opcode, size,
3434259698Sdim                     (outs GPR64xsp:$wb),
3435259698Sdim                     (ins GPR64xsp:$Rn, ImmTy:$amt, VecList:$Rt),
3436259698Sdim                     asmop # "\t$Rt, [$Rn], $amt",
3437259698Sdim                     [],
3438259698Sdim                     NoItinerary> {
3439259698Sdim      let Rm = 0b11111;
3440259698Sdim    }
3441259698Sdim
3442259698Sdim    def _register : NeonI_LdStMult_Post<q, 0, opcode, size,
3443259698Sdim                      (outs GPR64xsp:$wb),
3444259698Sdim                      (ins GPR64xsp:$Rn, GPR64noxzr:$Rm, VecList:$Rt),
3445259698Sdim                      asmop # "\t$Rt, [$Rn], $Rm",
3446259698Sdim                      [],
3447259698Sdim                      NoItinerary>;
3448259698Sdim  }
3449259698Sdim}
3450259698Sdim
3451259698Sdimmulticlass STWB_VList_BHSD<bits<4> opcode, string List, Operand ImmTy,
3452259698Sdim                           Operand ImmTy2, string asmop> {
3453259698Sdim  defm _8B : NeonI_STWB_VList<0, opcode, 0b00,
3454259698Sdim                 !cast<RegisterOperand>(List # "8B_operand"), ImmTy, asmop>;
3455259698Sdim
3456259698Sdim  defm _4H : NeonI_STWB_VList<0, opcode, 0b01,
3457259698Sdim                              !cast<RegisterOperand>(List # "4H_operand"),
3458259698Sdim                              ImmTy, asmop>;
3459259698Sdim
3460259698Sdim  defm _2S : NeonI_STWB_VList<0, opcode, 0b10,
3461259698Sdim                              !cast<RegisterOperand>(List # "2S_operand"),
3462259698Sdim                              ImmTy, asmop>;
3463259698Sdim
3464259698Sdim  defm _16B : NeonI_STWB_VList<1, opcode, 0b00,
3465259698Sdim                               !cast<RegisterOperand>(List # "16B_operand"),
3466259698Sdim                               ImmTy2, asmop>;
3467259698Sdim
3468259698Sdim  defm _8H : NeonI_STWB_VList<1, opcode, 0b01,
3469259698Sdim                              !cast<RegisterOperand>(List # "8H_operand"),
3470259698Sdim                              ImmTy2, asmop>;
3471259698Sdim
3472259698Sdim  defm _4S : NeonI_STWB_VList<1, opcode, 0b10,
3473259698Sdim                              !cast<RegisterOperand>(List # "4S_operand"),
3474259698Sdim                              ImmTy2, asmop>;
3475259698Sdim
3476259698Sdim  defm _2D : NeonI_STWB_VList<1, opcode, 0b11,
3477259698Sdim                              !cast<RegisterOperand>(List # "2D_operand"),
3478259698Sdim                              ImmTy2, asmop>;
3479259698Sdim}
3480259698Sdim
3481259698Sdim// Post-index load multiple N-element structures from N registers (N = 1,2,3,4)
3482259698Sdimdefm ST1WB : STWB_VList_BHSD<0b0111, "VOne", uimm_exact8, uimm_exact16, "st1">;
3483259698Sdimdefm ST1WB_1D : NeonI_STWB_VList<0, 0b0111, 0b11, VOne1D_operand, uimm_exact8,
3484259698Sdim                                 "st1">;
3485259698Sdim
3486259698Sdimdefm ST2WB : STWB_VList_BHSD<0b1000, "VPair", uimm_exact16, uimm_exact32, "st2">;
3487259698Sdim
3488259698Sdimdefm ST3WB : STWB_VList_BHSD<0b0100, "VTriple", uimm_exact24, uimm_exact48,
3489259698Sdim                             "st3">;
3490259698Sdim
3491259698Sdimdefm ST4WB : STWB_VList_BHSD<0b0000, "VQuad", uimm_exact32, uimm_exact64, "st4">;
3492259698Sdim
3493259698Sdim// Post-index load multiple 1-element structures from N consecutive registers
3494259698Sdim// (N = 2,3,4)
3495259698Sdimdefm ST1x2WB : STWB_VList_BHSD<0b1010, "VPair", uimm_exact16, uimm_exact32,
3496259698Sdim                               "st1">;
3497259698Sdimdefm ST1x2WB_1D : NeonI_STWB_VList<0, 0b1010, 0b11, VPair1D_operand,
3498259698Sdim                                   uimm_exact16, "st1">;
3499259698Sdim
3500259698Sdimdefm ST1x3WB : STWB_VList_BHSD<0b0110, "VTriple", uimm_exact24, uimm_exact48,
3501259698Sdim                               "st1">;
3502259698Sdimdefm ST1x3WB_1D : NeonI_STWB_VList<0, 0b0110, 0b11, VTriple1D_operand,
3503259698Sdim                                   uimm_exact24, "st1">;
3504259698Sdim
3505259698Sdimdefm ST1x4WB : STWB_VList_BHSD<0b0010, "VQuad", uimm_exact32, uimm_exact64,
3506259698Sdim                               "st1">;
3507259698Sdimdefm ST1x4WB_1D : NeonI_STWB_VList<0, 0b0010, 0b11, VQuad1D_operand,
3508259698Sdim                                   uimm_exact32, "st1">;
3509259698Sdim
3510259698Sdim// End of post-index vector load/store multiple N-element structure
3511259698Sdim// (class SIMD lselem-post)
3512259698Sdim
3513259698Sdim// The followings are vector load/store single N-element structure
3514259698Sdim// (class SIMD lsone).
3515259698Sdimdef neon_uimm0_bare : Operand<i64>,
3516259698Sdim                        ImmLeaf<i64, [{return Imm == 0;}]> {
3517259698Sdim  let ParserMatchClass = neon_uimm0_asmoperand;
3518259698Sdim  let PrintMethod = "printUImmBareOperand";
3519259698Sdim}
3520259698Sdim
3521259698Sdimdef neon_uimm1_bare : Operand<i64>,
3522259698Sdim                        ImmLeaf<i64, [{return Imm < 2;}]> {
3523259698Sdim  let ParserMatchClass = neon_uimm1_asmoperand;
3524259698Sdim  let PrintMethod = "printUImmBareOperand";
3525259698Sdim}
3526259698Sdim
3527259698Sdimdef neon_uimm2_bare : Operand<i64>,
3528259698Sdim                        ImmLeaf<i64, [{return Imm < 4;}]> {
3529259698Sdim  let ParserMatchClass = neon_uimm2_asmoperand;
3530259698Sdim  let PrintMethod = "printUImmBareOperand";
3531259698Sdim}
3532259698Sdim
3533259698Sdimdef neon_uimm3_bare : Operand<i64>,
3534259698Sdim                        ImmLeaf<i64, [{return Imm < 8;}]> {
3535259698Sdim  let ParserMatchClass = uimm3_asmoperand;
3536259698Sdim  let PrintMethod = "printUImmBareOperand";
3537259698Sdim}
3538259698Sdim
3539259698Sdimdef neon_uimm4_bare : Operand<i64>,
3540259698Sdim                        ImmLeaf<i64, [{return Imm < 16;}]> {
3541259698Sdim  let ParserMatchClass = uimm4_asmoperand;
3542259698Sdim  let PrintMethod = "printUImmBareOperand";
3543259698Sdim}
3544259698Sdim
3545259698Sdimclass NeonI_LDN_Dup<bit q, bit r, bits<3> opcode, bits<2> size,
3546259698Sdim                    RegisterOperand VecList, string asmop>
3547259698Sdim    : NeonI_LdOne_Dup<q, r, opcode, size,
3548259698Sdim                      (outs VecList:$Rt), (ins GPR64xsp:$Rn),
3549259698Sdim                      asmop # "\t$Rt, [$Rn]",
3550259698Sdim                      [],
3551259698Sdim                      NoItinerary> {
3552259698Sdim  let mayLoad = 1;
3553259698Sdim  let neverHasSideEffects = 1;
3554259698Sdim}
3555259698Sdim
3556259698Sdimmulticlass LDN_Dup_BHSD<bit r, bits<3> opcode, string List, string asmop> {
3557259698Sdim  def _8B : NeonI_LDN_Dup<0, r, opcode, 0b00,
3558259698Sdim                          !cast<RegisterOperand>(List # "8B_operand"), asmop>;
3559259698Sdim
3560259698Sdim  def _4H : NeonI_LDN_Dup<0, r, opcode, 0b01,
3561259698Sdim                          !cast<RegisterOperand>(List # "4H_operand"), asmop>;
3562259698Sdim
3563259698Sdim  def _2S : NeonI_LDN_Dup<0, r, opcode, 0b10,
3564259698Sdim                          !cast<RegisterOperand>(List # "2S_operand"), asmop>;
3565259698Sdim
3566259698Sdim  def _1D : NeonI_LDN_Dup<0, r, opcode, 0b11,
3567259698Sdim                          !cast<RegisterOperand>(List # "1D_operand"), asmop>;
3568259698Sdim
3569259698Sdim  def _16B : NeonI_LDN_Dup<1, r, opcode, 0b00,
3570259698Sdim                           !cast<RegisterOperand>(List # "16B_operand"), asmop>;
3571259698Sdim
3572259698Sdim  def _8H : NeonI_LDN_Dup<1, r, opcode, 0b01,
3573259698Sdim                          !cast<RegisterOperand>(List # "8H_operand"), asmop>;
3574259698Sdim
3575259698Sdim  def _4S : NeonI_LDN_Dup<1, r, opcode, 0b10,
3576259698Sdim                          !cast<RegisterOperand>(List # "4S_operand"), asmop>;
3577259698Sdim
3578259698Sdim  def _2D : NeonI_LDN_Dup<1, r, opcode, 0b11,
3579259698Sdim                          !cast<RegisterOperand>(List # "2D_operand"), asmop>;
3580259698Sdim}
3581259698Sdim
3582259698Sdim// Load single 1-element structure to all lanes of 1 register
3583259698Sdimdefm LD1R : LDN_Dup_BHSD<0b0, 0b110, "VOne", "ld1r">;
3584259698Sdim
3585259698Sdim// Load single N-element structure to all lanes of N consecutive
3586259698Sdim// registers (N = 2,3,4)
3587259698Sdimdefm LD2R : LDN_Dup_BHSD<0b1, 0b110, "VPair", "ld2r">;
3588259698Sdimdefm LD3R : LDN_Dup_BHSD<0b0, 0b111, "VTriple", "ld3r">;
3589259698Sdimdefm LD4R : LDN_Dup_BHSD<0b1, 0b111, "VQuad", "ld4r">;
3590259698Sdim
3591259698Sdim
3592259698Sdimclass LD1R_pattern <ValueType VTy, ValueType DTy, PatFrag LoadOp,
3593259698Sdim                    Instruction INST>
3594259698Sdim    : Pat<(VTy (Neon_vdup (DTy (LoadOp GPR64xsp:$Rn)))),
3595259698Sdim          (VTy (INST GPR64xsp:$Rn))>;
3596259698Sdim
3597259698Sdim// Match all LD1R instructions
3598259698Sdimdef : LD1R_pattern<v8i8, i32, extloadi8, LD1R_8B>;
3599259698Sdim
3600259698Sdimdef : LD1R_pattern<v16i8, i32, extloadi8, LD1R_16B>;
3601259698Sdim
3602259698Sdimdef : LD1R_pattern<v4i16, i32, extloadi16, LD1R_4H>;
3603259698Sdim
3604259698Sdimdef : LD1R_pattern<v8i16, i32, extloadi16, LD1R_8H>;
3605259698Sdim
3606259698Sdimdef : LD1R_pattern<v2i32, i32, load, LD1R_2S>;
3607259698Sdimdef : LD1R_pattern<v2f32, f32, load, LD1R_2S>;
3608259698Sdim
3609259698Sdimdef : LD1R_pattern<v4i32, i32, load, LD1R_4S>;
3610259698Sdimdef : LD1R_pattern<v4f32, f32, load, LD1R_4S>;
3611259698Sdim
3612259698Sdimdef : LD1R_pattern<v1i64, i64, load, LD1R_1D>;
3613259698Sdimdef : LD1R_pattern<v1f64, f64, load, LD1R_1D>;
3614259698Sdim
3615259698Sdimdef : LD1R_pattern<v2i64, i64, load, LD1R_2D>;
3616259698Sdimdef : LD1R_pattern<v2f64, f64, load, LD1R_2D>;
3617259698Sdim
3618259698Sdim
3619259698Sdimmulticlass VectorList_Bare_BHSD<string PREFIX, int Count,
3620259698Sdim                                RegisterClass RegList> {
3621259698Sdim  defm B : VectorList_operands<PREFIX, "B", Count, RegList>;
3622259698Sdim  defm H : VectorList_operands<PREFIX, "H", Count, RegList>;
3623259698Sdim  defm S : VectorList_operands<PREFIX, "S", Count, RegList>;
3624259698Sdim  defm D : VectorList_operands<PREFIX, "D", Count, RegList>;
3625259698Sdim}
3626259698Sdim
3627259698Sdim// Special vector list operand of 128-bit vectors with bare layout.
3628259698Sdim// i.e. only show ".b", ".h", ".s", ".d"
3629259698Sdimdefm VOne : VectorList_Bare_BHSD<"VOne", 1, FPR128>;
3630259698Sdimdefm VPair : VectorList_Bare_BHSD<"VPair", 2, QPair>;
3631259698Sdimdefm VTriple : VectorList_Bare_BHSD<"VTriple", 3, QTriple>;
3632259698Sdimdefm VQuad : VectorList_Bare_BHSD<"VQuad", 4, QQuad>;
3633259698Sdim
3634259698Sdimclass NeonI_LDN_Lane<bit r, bits<2> op2_1, bit op0, RegisterOperand VList,
3635259698Sdim                     Operand ImmOp, string asmop>
3636259698Sdim    : NeonI_LdStOne_Lane<1, r, op2_1, op0,
3637259698Sdim                         (outs VList:$Rt),
3638259698Sdim                         (ins GPR64xsp:$Rn, VList:$src, ImmOp:$lane),
3639259698Sdim                         asmop # "\t$Rt[$lane], [$Rn]",
3640259698Sdim                         [],
3641259698Sdim                         NoItinerary> {
3642259698Sdim  let mayLoad = 1;
3643259698Sdim  let neverHasSideEffects = 1;
3644259698Sdim  let hasExtraDefRegAllocReq = 1;
3645259698Sdim  let Constraints = "$src = $Rt";
3646259698Sdim}
3647259698Sdim
3648259698Sdimmulticlass LDN_Lane_BHSD<bit r, bit op0, string List, string asmop> {
3649259698Sdim  def _B : NeonI_LDN_Lane<r, 0b00, op0,
3650259698Sdim                          !cast<RegisterOperand>(List # "B_operand"),
3651259698Sdim                          neon_uimm4_bare, asmop> {
3652259698Sdim    let Inst{12-10} = lane{2-0};
3653259698Sdim    let Inst{30} = lane{3};
3654259698Sdim  }
3655259698Sdim
3656259698Sdim  def _H : NeonI_LDN_Lane<r, 0b01, op0,
3657259698Sdim                          !cast<RegisterOperand>(List # "H_operand"),
3658259698Sdim                          neon_uimm3_bare, asmop> {
3659259698Sdim    let Inst{12-10} = {lane{1}, lane{0}, 0b0};
3660259698Sdim    let Inst{30} = lane{2};
3661259698Sdim  }
3662259698Sdim
3663259698Sdim  def _S : NeonI_LDN_Lane<r, 0b10, op0,
3664259698Sdim                          !cast<RegisterOperand>(List # "S_operand"),
3665259698Sdim                          neon_uimm2_bare, asmop> {
3666259698Sdim    let Inst{12-10} = {lane{0}, 0b0, 0b0};
3667259698Sdim    let Inst{30} = lane{1};
3668259698Sdim  }
3669259698Sdim
3670259698Sdim  def _D : NeonI_LDN_Lane<r, 0b10, op0,
3671259698Sdim                          !cast<RegisterOperand>(List # "D_operand"),
3672259698Sdim                          neon_uimm1_bare, asmop> {
3673259698Sdim    let Inst{12-10} = 0b001;
3674259698Sdim    let Inst{30} = lane{0};
3675259698Sdim  }
3676259698Sdim}
3677259698Sdim
3678259698Sdim// Load single 1-element structure to one lane of 1 register.
3679259698Sdimdefm LD1LN : LDN_Lane_BHSD<0b0, 0b0, "VOne", "ld1">;
3680259698Sdim
3681259698Sdim// Load single N-element structure to one lane of N consecutive registers
3682259698Sdim// (N = 2,3,4)
3683259698Sdimdefm LD2LN : LDN_Lane_BHSD<0b1, 0b0, "VPair", "ld2">;
3684259698Sdimdefm LD3LN : LDN_Lane_BHSD<0b0, 0b1, "VTriple", "ld3">;
3685259698Sdimdefm LD4LN : LDN_Lane_BHSD<0b1, 0b1, "VQuad", "ld4">;
3686259698Sdim
3687259698Sdimmulticlass LD1LN_patterns<ValueType VTy, ValueType VTy2, ValueType DTy,
3688259698Sdim                          Operand ImmOp, Operand ImmOp2, PatFrag LoadOp,
3689259698Sdim                          Instruction INST> {
3690259698Sdim  def : Pat<(VTy (vector_insert (VTy VPR64:$src),
3691259698Sdim                     (DTy (LoadOp GPR64xsp:$Rn)), (ImmOp:$lane))),
3692259698Sdim            (VTy (EXTRACT_SUBREG
3693259698Sdim                     (INST GPR64xsp:$Rn,
3694259698Sdim                           (SUBREG_TO_REG (i64 0), VPR64:$src, sub_64),
3695259698Sdim                           ImmOp:$lane),
3696259698Sdim                     sub_64))>;
3697259698Sdim
3698259698Sdim  def : Pat<(VTy2 (vector_insert (VTy2 VPR128:$src),
3699259698Sdim                      (DTy (LoadOp GPR64xsp:$Rn)), (ImmOp2:$lane))),
3700259698Sdim            (VTy2 (INST GPR64xsp:$Rn, VPR128:$src, ImmOp2:$lane))>;
3701259698Sdim}
3702259698Sdim
3703259698Sdim// Match all LD1LN instructions
3704259698Sdimdefm : LD1LN_patterns<v8i8, v16i8, i32, neon_uimm3_bare, neon_uimm4_bare,
3705259698Sdim                      extloadi8, LD1LN_B>;
3706259698Sdim
3707259698Sdimdefm : LD1LN_patterns<v4i16, v8i16, i32, neon_uimm2_bare, neon_uimm3_bare,
3708259698Sdim                      extloadi16, LD1LN_H>;
3709259698Sdim
3710259698Sdimdefm : LD1LN_patterns<v2i32, v4i32, i32, neon_uimm1_bare, neon_uimm2_bare,
3711259698Sdim                      load, LD1LN_S>;
3712259698Sdimdefm : LD1LN_patterns<v2f32, v4f32, f32, neon_uimm1_bare, neon_uimm2_bare,
3713259698Sdim                      load, LD1LN_S>;
3714259698Sdim
3715259698Sdimdefm : LD1LN_patterns<v1i64, v2i64, i64, neon_uimm0_bare, neon_uimm1_bare,
3716259698Sdim                      load, LD1LN_D>;
3717259698Sdimdefm : LD1LN_patterns<v1f64, v2f64, f64, neon_uimm0_bare, neon_uimm1_bare,
3718259698Sdim                      load, LD1LN_D>;
3719259698Sdim
3720259698Sdimclass NeonI_STN_Lane<bit r, bits<2> op2_1, bit op0, RegisterOperand VList,
3721259698Sdim                     Operand ImmOp, string asmop>
3722259698Sdim    : NeonI_LdStOne_Lane<0, r, op2_1, op0,
3723259698Sdim                         (outs), (ins GPR64xsp:$Rn, VList:$Rt, ImmOp:$lane),
3724259698Sdim                         asmop # "\t$Rt[$lane], [$Rn]",
3725259698Sdim                         [],
3726259698Sdim                         NoItinerary> {
3727259698Sdim  let mayStore = 1;
3728259698Sdim  let neverHasSideEffects = 1;
3729259698Sdim  let hasExtraDefRegAllocReq = 1;
3730259698Sdim}
3731259698Sdim
3732259698Sdimmulticlass STN_Lane_BHSD<bit r, bit op0, string List, string asmop> {
3733259698Sdim  def _B : NeonI_STN_Lane<r, 0b00, op0,
3734259698Sdim                          !cast<RegisterOperand>(List # "B_operand"),
3735259698Sdim                          neon_uimm4_bare, asmop> {
3736259698Sdim    let Inst{12-10} = lane{2-0};
3737259698Sdim    let Inst{30} = lane{3};
3738259698Sdim  }
3739259698Sdim
3740259698Sdim  def _H : NeonI_STN_Lane<r, 0b01, op0,
3741259698Sdim                          !cast<RegisterOperand>(List # "H_operand"),
3742259698Sdim                          neon_uimm3_bare, asmop> {
3743259698Sdim    let Inst{12-10} = {lane{1}, lane{0}, 0b0};
3744259698Sdim    let Inst{30} = lane{2};
3745259698Sdim  }
3746259698Sdim
3747259698Sdim  def _S : NeonI_STN_Lane<r, 0b10, op0,
3748259698Sdim                          !cast<RegisterOperand>(List # "S_operand"),
3749259698Sdim                           neon_uimm2_bare, asmop> {
3750259698Sdim    let Inst{12-10} = {lane{0}, 0b0, 0b0};
3751259698Sdim    let Inst{30} = lane{1};
3752259698Sdim  }
3753259698Sdim
3754259698Sdim  def _D : NeonI_STN_Lane<r, 0b10, op0,
3755259698Sdim                          !cast<RegisterOperand>(List # "D_operand"),
3756259698Sdim                          neon_uimm1_bare, asmop>{
3757259698Sdim    let Inst{12-10} = 0b001;
3758259698Sdim    let Inst{30} = lane{0};
3759259698Sdim  }
3760259698Sdim}
3761259698Sdim
3762259698Sdim// Store single 1-element structure from one lane of 1 register.
3763259698Sdimdefm ST1LN : STN_Lane_BHSD<0b0, 0b0, "VOne", "st1">;
3764259698Sdim
3765259698Sdim// Store single N-element structure from one lane of N consecutive registers
3766259698Sdim// (N = 2,3,4)
3767259698Sdimdefm ST2LN : STN_Lane_BHSD<0b1, 0b0, "VPair", "st2">;
3768259698Sdimdefm ST3LN : STN_Lane_BHSD<0b0, 0b1, "VTriple", "st3">;
3769259698Sdimdefm ST4LN : STN_Lane_BHSD<0b1, 0b1, "VQuad", "st4">;
3770259698Sdim
3771259698Sdimmulticlass ST1LN_patterns<ValueType VTy, ValueType VTy2, ValueType DTy,
3772259698Sdim                          Operand ImmOp, Operand ImmOp2, PatFrag StoreOp,
3773259698Sdim                          Instruction INST> {
3774259698Sdim  def : Pat<(StoreOp (DTy (vector_extract (VTy VPR64:$Rt), ImmOp:$lane)),
3775259698Sdim                     GPR64xsp:$Rn),
3776259698Sdim            (INST GPR64xsp:$Rn,
3777259698Sdim                  (SUBREG_TO_REG (i64 0), VPR64:$Rt, sub_64),
3778259698Sdim                  ImmOp:$lane)>;
3779259698Sdim
3780259698Sdim  def : Pat<(StoreOp (DTy (vector_extract (VTy2 VPR128:$Rt), ImmOp2:$lane)),
3781259698Sdim                     GPR64xsp:$Rn),
3782259698Sdim            (INST GPR64xsp:$Rn, VPR128:$Rt, ImmOp2:$lane)>;
3783259698Sdim}
3784259698Sdim
3785259698Sdim// Match all ST1LN instructions
3786259698Sdimdefm : ST1LN_patterns<v8i8, v16i8, i32, neon_uimm3_bare, neon_uimm4_bare,
3787259698Sdim                      truncstorei8, ST1LN_B>;
3788259698Sdim
3789259698Sdimdefm : ST1LN_patterns<v4i16, v8i16, i32, neon_uimm2_bare, neon_uimm3_bare,
3790259698Sdim                      truncstorei16, ST1LN_H>;
3791259698Sdim
3792259698Sdimdefm : ST1LN_patterns<v2i32, v4i32, i32, neon_uimm1_bare, neon_uimm2_bare,
3793259698Sdim                      store, ST1LN_S>;
3794259698Sdimdefm : ST1LN_patterns<v2f32, v4f32, f32, neon_uimm1_bare, neon_uimm2_bare,
3795259698Sdim                      store, ST1LN_S>;
3796259698Sdim
3797259698Sdimdefm : ST1LN_patterns<v1i64, v2i64, i64, neon_uimm0_bare, neon_uimm1_bare,
3798259698Sdim                      store, ST1LN_D>;
3799259698Sdimdefm : ST1LN_patterns<v1f64, v2f64, f64, neon_uimm0_bare, neon_uimm1_bare,
3800259698Sdim                      store, ST1LN_D>;
3801259698Sdim
3802259698Sdim// End of vector load/store single N-element structure (class SIMD lsone).
3803259698Sdim
3804259698Sdim
3805259698Sdim// The following are post-index load/store single N-element instructions
3806259698Sdim// (class SIMD lsone-post)
3807259698Sdim
3808259698Sdimmulticlass NeonI_LDN_WB_Dup<bit q, bit r, bits<3> opcode, bits<2> size,
3809259698Sdim                            RegisterOperand VecList, Operand ImmTy,
3810259698Sdim                            string asmop> {
3811259698Sdim  let mayLoad = 1, neverHasSideEffects = 1, Constraints = "$wb = $Rn",
3812259698Sdim  DecoderMethod = "DecodeVLDSTLanePostInstruction" in {
3813259698Sdim    def _fixed : NeonI_LdOne_Dup_Post<q, r, opcode, size,
3814259698Sdim                      (outs VecList:$Rt, GPR64xsp:$wb),
3815259698Sdim                      (ins GPR64xsp:$Rn, ImmTy:$amt),
3816259698Sdim                      asmop # "\t$Rt, [$Rn], $amt",
3817259698Sdim                      [],
3818259698Sdim                      NoItinerary> {
3819259698Sdim                        let Rm = 0b11111;
3820259698Sdim                      }
3821259698Sdim
3822259698Sdim    def _register : NeonI_LdOne_Dup_Post<q, r, opcode, size,
3823259698Sdim                      (outs VecList:$Rt, GPR64xsp:$wb),
3824259698Sdim                      (ins GPR64xsp:$Rn, GPR64noxzr:$Rm),
3825259698Sdim                      asmop # "\t$Rt, [$Rn], $Rm",
3826259698Sdim                      [],
3827259698Sdim                      NoItinerary>;
3828259698Sdim  }
3829259698Sdim}
3830259698Sdim
3831259698Sdimmulticlass LDWB_Dup_BHSD<bit r, bits<3> opcode, string List, string asmop,
3832259698Sdim                         Operand uimm_b, Operand uimm_h,
3833259698Sdim                         Operand uimm_s, Operand uimm_d> {
3834259698Sdim  defm _8B : NeonI_LDN_WB_Dup<0, r, opcode, 0b00,
3835259698Sdim                              !cast<RegisterOperand>(List # "8B_operand"),
3836259698Sdim                              uimm_b, asmop>;
3837259698Sdim
3838259698Sdim  defm _4H : NeonI_LDN_WB_Dup<0, r, opcode, 0b01,
3839259698Sdim                              !cast<RegisterOperand>(List # "4H_operand"),
3840259698Sdim                              uimm_h, asmop>;
3841259698Sdim
3842259698Sdim  defm _2S : NeonI_LDN_WB_Dup<0, r, opcode, 0b10,
3843259698Sdim                              !cast<RegisterOperand>(List # "2S_operand"),
3844259698Sdim                              uimm_s, asmop>;
3845259698Sdim
3846259698Sdim  defm _1D : NeonI_LDN_WB_Dup<0, r, opcode, 0b11,
3847259698Sdim                              !cast<RegisterOperand>(List # "1D_operand"),
3848259698Sdim                              uimm_d, asmop>;
3849259698Sdim
3850259698Sdim  defm _16B : NeonI_LDN_WB_Dup<1, r, opcode, 0b00,
3851259698Sdim                               !cast<RegisterOperand>(List # "16B_operand"),
3852259698Sdim                               uimm_b, asmop>;
3853259698Sdim
3854259698Sdim  defm _8H : NeonI_LDN_WB_Dup<1, r, opcode, 0b01,
3855259698Sdim                              !cast<RegisterOperand>(List # "8H_operand"),
3856259698Sdim                              uimm_h, asmop>;
3857259698Sdim
3858259698Sdim  defm _4S : NeonI_LDN_WB_Dup<1, r, opcode, 0b10,
3859259698Sdim                              !cast<RegisterOperand>(List # "4S_operand"),
3860259698Sdim                              uimm_s, asmop>;
3861259698Sdim
3862259698Sdim  defm _2D : NeonI_LDN_WB_Dup<1, r, opcode, 0b11,
3863259698Sdim                              !cast<RegisterOperand>(List # "2D_operand"),
3864259698Sdim                              uimm_d, asmop>;
3865259698Sdim}
3866259698Sdim
3867259698Sdim// Post-index load single 1-element structure to all lanes of 1 register
3868259698Sdimdefm LD1R_WB : LDWB_Dup_BHSD<0b0, 0b110, "VOne", "ld1r", uimm_exact1,
3869259698Sdim                             uimm_exact2, uimm_exact4, uimm_exact8>;
3870259698Sdim
3871259698Sdim// Post-index load single N-element structure to all lanes of N consecutive
3872259698Sdim// registers (N = 2,3,4)
3873259698Sdimdefm LD2R_WB : LDWB_Dup_BHSD<0b1, 0b110, "VPair", "ld2r", uimm_exact2,
3874259698Sdim                             uimm_exact4, uimm_exact8, uimm_exact16>;
3875259698Sdimdefm LD3R_WB : LDWB_Dup_BHSD<0b0, 0b111, "VTriple", "ld3r", uimm_exact3,
3876259698Sdim                             uimm_exact6, uimm_exact12, uimm_exact24>;
3877259698Sdimdefm LD4R_WB : LDWB_Dup_BHSD<0b1, 0b111, "VQuad", "ld4r", uimm_exact4,
3878259698Sdim                             uimm_exact8, uimm_exact16, uimm_exact32>;
3879259698Sdim
3880259698Sdimlet mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1,
3881259698Sdim    Constraints = "$Rn = $wb, $Rt = $src",
3882259698Sdim    DecoderMethod = "DecodeVLDSTLanePostInstruction" in {
3883259698Sdim  class LDN_WBFx_Lane<bit r, bits<2> op2_1, bit op0, RegisterOperand VList,
3884259698Sdim                                Operand ImmTy, Operand ImmOp, string asmop>
3885259698Sdim      : NeonI_LdStOne_Lane_Post<1, r, op2_1, op0,
3886259698Sdim                                (outs VList:$Rt, GPR64xsp:$wb),
3887259698Sdim                                (ins GPR64xsp:$Rn, ImmTy:$amt,
3888259698Sdim                                    VList:$src, ImmOp:$lane),
3889259698Sdim                                asmop # "\t$Rt[$lane], [$Rn], $amt",
3890259698Sdim                                [],
3891259698Sdim                                NoItinerary> {
3892259698Sdim    let Rm = 0b11111;
3893259698Sdim  }
3894259698Sdim
3895259698Sdim  class LDN_WBReg_Lane<bit r, bits<2> op2_1, bit op0, RegisterOperand VList,
3896259698Sdim                                 Operand ImmTy, Operand ImmOp, string asmop>
3897259698Sdim      : NeonI_LdStOne_Lane_Post<1, r, op2_1, op0,
3898259698Sdim                                (outs VList:$Rt, GPR64xsp:$wb),
3899259698Sdim                                (ins GPR64xsp:$Rn, GPR64noxzr:$Rm,
3900259698Sdim                                    VList:$src, ImmOp:$lane),
3901259698Sdim                                asmop # "\t$Rt[$lane], [$Rn], $Rm",
3902259698Sdim                                [],
3903259698Sdim                                NoItinerary>;
3904259698Sdim}
3905259698Sdim
3906259698Sdimmulticlass LD_Lane_WB_BHSD<bit r, bit op0, string List, string asmop,
3907259698Sdim                           Operand uimm_b, Operand uimm_h,
3908259698Sdim                           Operand uimm_s, Operand uimm_d> {
3909259698Sdim  def _B_fixed : LDN_WBFx_Lane<r, 0b00, op0,
3910259698Sdim                               !cast<RegisterOperand>(List # "B_operand"),
3911259698Sdim                               uimm_b, neon_uimm4_bare, asmop> {
3912259698Sdim    let Inst{12-10} = lane{2-0};
3913259698Sdim    let Inst{30} = lane{3};
3914259698Sdim  }
3915259698Sdim
3916259698Sdim  def _B_register : LDN_WBReg_Lane<r, 0b00, op0,
3917259698Sdim                                   !cast<RegisterOperand>(List # "B_operand"),
3918259698Sdim                                   uimm_b, neon_uimm4_bare, asmop> {
3919259698Sdim    let Inst{12-10} = lane{2-0};
3920259698Sdim    let Inst{30} = lane{3};
3921259698Sdim  }
3922259698Sdim
3923259698Sdim  def _H_fixed : LDN_WBFx_Lane<r, 0b01, op0,
3924259698Sdim                               !cast<RegisterOperand>(List # "H_operand"),
3925259698Sdim                               uimm_h, neon_uimm3_bare, asmop> {
3926259698Sdim    let Inst{12-10} = {lane{1}, lane{0}, 0b0};
3927259698Sdim    let Inst{30} = lane{2};
3928259698Sdim  }
3929259698Sdim
3930259698Sdim  def _H_register : LDN_WBReg_Lane<r, 0b01, op0,
3931259698Sdim                                   !cast<RegisterOperand>(List # "H_operand"),
3932259698Sdim                                   uimm_h, neon_uimm3_bare, asmop> {
3933259698Sdim    let Inst{12-10} = {lane{1}, lane{0}, 0b0};
3934259698Sdim    let Inst{30} = lane{2};
3935259698Sdim  }
3936259698Sdim
3937259698Sdim  def _S_fixed : LDN_WBFx_Lane<r, 0b10, op0,
3938259698Sdim                               !cast<RegisterOperand>(List # "S_operand"),
3939259698Sdim                               uimm_s, neon_uimm2_bare, asmop> {
3940259698Sdim    let Inst{12-10} = {lane{0}, 0b0, 0b0};
3941259698Sdim    let Inst{30} = lane{1};
3942259698Sdim  }
3943259698Sdim
3944259698Sdim  def _S_register : LDN_WBReg_Lane<r, 0b10, op0,
3945259698Sdim                                   !cast<RegisterOperand>(List # "S_operand"),
3946259698Sdim                                   uimm_s, neon_uimm2_bare, asmop> {
3947259698Sdim    let Inst{12-10} = {lane{0}, 0b0, 0b0};
3948259698Sdim    let Inst{30} = lane{1};
3949259698Sdim  }
3950259698Sdim
3951259698Sdim  def _D_fixed : LDN_WBFx_Lane<r, 0b10, op0,
3952259698Sdim                               !cast<RegisterOperand>(List # "D_operand"),
3953259698Sdim                               uimm_d, neon_uimm1_bare, asmop> {
3954259698Sdim    let Inst{12-10} = 0b001;
3955259698Sdim    let Inst{30} = lane{0};
3956259698Sdim  }
3957259698Sdim
3958259698Sdim  def _D_register : LDN_WBReg_Lane<r, 0b10, op0,
3959259698Sdim                                   !cast<RegisterOperand>(List # "D_operand"),
3960259698Sdim                                   uimm_d, neon_uimm1_bare, asmop> {
3961259698Sdim    let Inst{12-10} = 0b001;
3962259698Sdim    let Inst{30} = lane{0};
3963259698Sdim  }
3964259698Sdim}
3965259698Sdim
3966259698Sdim// Post-index load single 1-element structure to one lane of 1 register.
3967259698Sdimdefm LD1LN_WB : LD_Lane_WB_BHSD<0b0, 0b0, "VOne", "ld1", uimm_exact1,
3968259698Sdim                                uimm_exact2, uimm_exact4, uimm_exact8>;
3969259698Sdim
3970259698Sdim// Post-index load single N-element structure to one lane of N consecutive
3971259698Sdim// registers
3972259698Sdim// (N = 2,3,4)
3973259698Sdimdefm LD2LN_WB : LD_Lane_WB_BHSD<0b1, 0b0, "VPair", "ld2", uimm_exact2,
3974259698Sdim                                uimm_exact4, uimm_exact8, uimm_exact16>;
3975259698Sdimdefm LD3LN_WB : LD_Lane_WB_BHSD<0b0, 0b1, "VTriple", "ld3", uimm_exact3,
3976259698Sdim                                uimm_exact6, uimm_exact12, uimm_exact24>;
3977259698Sdimdefm LD4LN_WB : LD_Lane_WB_BHSD<0b1, 0b1, "VQuad", "ld4", uimm_exact4,
3978259698Sdim                                uimm_exact8, uimm_exact16, uimm_exact32>;
3979259698Sdim
3980259698Sdimlet mayStore = 1, neverHasSideEffects = 1,
3981259698Sdim    hasExtraDefRegAllocReq = 1, Constraints = "$Rn = $wb",
3982259698Sdim    DecoderMethod = "DecodeVLDSTLanePostInstruction" in {
3983259698Sdim  class STN_WBFx_Lane<bit r, bits<2> op2_1, bit op0, RegisterOperand VList,
3984259698Sdim                      Operand ImmTy, Operand ImmOp, string asmop>
3985259698Sdim      : NeonI_LdStOne_Lane_Post<0, r, op2_1, op0,
3986259698Sdim                                (outs GPR64xsp:$wb),
3987259698Sdim                                (ins GPR64xsp:$Rn, ImmTy:$amt,
3988259698Sdim                                    VList:$Rt, ImmOp:$lane),
3989259698Sdim                                asmop # "\t$Rt[$lane], [$Rn], $amt",
3990259698Sdim                                [],
3991259698Sdim                                NoItinerary> {
3992259698Sdim    let Rm = 0b11111;
3993259698Sdim  }
3994259698Sdim
3995259698Sdim  class STN_WBReg_Lane<bit r, bits<2> op2_1, bit op0, RegisterOperand VList,
3996259698Sdim                       Operand ImmTy, Operand ImmOp, string asmop>
3997259698Sdim      : NeonI_LdStOne_Lane_Post<0, r, op2_1, op0,
3998259698Sdim                                (outs GPR64xsp:$wb),
3999259698Sdim                                (ins GPR64xsp:$Rn, GPR64noxzr:$Rm, VList:$Rt,
4000259698Sdim                                    ImmOp:$lane),
4001259698Sdim                                asmop # "\t$Rt[$lane], [$Rn], $Rm",
4002259698Sdim                                [],
4003259698Sdim                                NoItinerary>;
4004259698Sdim}
4005259698Sdim
4006259698Sdimmulticlass ST_Lane_WB_BHSD<bit r, bit op0, string List, string asmop,
4007259698Sdim                           Operand uimm_b, Operand uimm_h,
4008259698Sdim                           Operand uimm_s, Operand uimm_d> {
4009259698Sdim  def _B_fixed : STN_WBFx_Lane<r, 0b00, op0,
4010259698Sdim                               !cast<RegisterOperand>(List # "B_operand"),
4011259698Sdim                               uimm_b, neon_uimm4_bare, asmop> {
4012259698Sdim    let Inst{12-10} = lane{2-0};
4013259698Sdim    let Inst{30} = lane{3};
4014259698Sdim  }
4015259698Sdim
4016259698Sdim  def _B_register : STN_WBReg_Lane<r, 0b00, op0,
4017259698Sdim                                   !cast<RegisterOperand>(List # "B_operand"),
4018259698Sdim                                   uimm_b, neon_uimm4_bare, asmop> {
4019259698Sdim    let Inst{12-10} = lane{2-0};
4020259698Sdim    let Inst{30} = lane{3};
4021259698Sdim  }
4022259698Sdim
4023259698Sdim  def _H_fixed : STN_WBFx_Lane<r, 0b01, op0,
4024259698Sdim                               !cast<RegisterOperand>(List # "H_operand"),
4025259698Sdim                               uimm_h, neon_uimm3_bare, asmop> {
4026259698Sdim    let Inst{12-10} = {lane{1}, lane{0}, 0b0};
4027259698Sdim    let Inst{30} = lane{2};
4028259698Sdim  }
4029259698Sdim
4030259698Sdim  def _H_register : STN_WBReg_Lane<r, 0b01, op0,
4031259698Sdim                                   !cast<RegisterOperand>(List # "H_operand"),
4032259698Sdim                                   uimm_h, neon_uimm3_bare, asmop> {
4033259698Sdim    let Inst{12-10} = {lane{1}, lane{0}, 0b0};
4034259698Sdim    let Inst{30} = lane{2};
4035259698Sdim  }
4036259698Sdim
4037259698Sdim  def _S_fixed : STN_WBFx_Lane<r, 0b10, op0,
4038259698Sdim                               !cast<RegisterOperand>(List # "S_operand"),
4039259698Sdim                               uimm_s, neon_uimm2_bare, asmop> {
4040259698Sdim    let Inst{12-10} = {lane{0}, 0b0, 0b0};
4041259698Sdim    let Inst{30} = lane{1};
4042259698Sdim  }
4043259698Sdim
4044259698Sdim  def _S_register : STN_WBReg_Lane<r, 0b10, op0,
4045259698Sdim                                   !cast<RegisterOperand>(List # "S_operand"),
4046259698Sdim                                   uimm_s, neon_uimm2_bare, asmop> {
4047259698Sdim    let Inst{12-10} = {lane{0}, 0b0, 0b0};
4048259698Sdim    let Inst{30} = lane{1};
4049259698Sdim  }
4050259698Sdim
4051259698Sdim  def _D_fixed : STN_WBFx_Lane<r, 0b10, op0,
4052259698Sdim                               !cast<RegisterOperand>(List # "D_operand"),
4053259698Sdim                               uimm_d, neon_uimm1_bare, asmop> {
4054259698Sdim    let Inst{12-10} = 0b001;
4055259698Sdim    let Inst{30} = lane{0};
4056259698Sdim  }
4057259698Sdim
4058259698Sdim  def _D_register : STN_WBReg_Lane<r, 0b10, op0,
4059259698Sdim                                   !cast<RegisterOperand>(List # "D_operand"),
4060259698Sdim                                   uimm_d, neon_uimm1_bare, asmop> {
4061259698Sdim    let Inst{12-10} = 0b001;
4062259698Sdim    let Inst{30} = lane{0};
4063259698Sdim  }
4064259698Sdim}
4065259698Sdim
4066259698Sdim// Post-index store single 1-element structure from one lane of 1 register.
4067259698Sdimdefm ST1LN_WB : ST_Lane_WB_BHSD<0b0, 0b0, "VOne", "st1", uimm_exact1,
4068259698Sdim                                uimm_exact2, uimm_exact4, uimm_exact8>;
4069259698Sdim
4070259698Sdim// Post-index store single N-element structure from one lane of N consecutive
4071259698Sdim// registers (N = 2,3,4)
4072259698Sdimdefm ST2LN_WB : ST_Lane_WB_BHSD<0b1, 0b0, "VPair", "st2", uimm_exact2,
4073259698Sdim                                uimm_exact4, uimm_exact8, uimm_exact16>;
4074259698Sdimdefm ST3LN_WB : ST_Lane_WB_BHSD<0b0, 0b1, "VTriple", "st3", uimm_exact3,
4075259698Sdim                                uimm_exact6, uimm_exact12, uimm_exact24>;
4076259698Sdimdefm ST4LN_WB : ST_Lane_WB_BHSD<0b1, 0b1, "VQuad", "st4", uimm_exact4,
4077259698Sdim                                uimm_exact8, uimm_exact16, uimm_exact32>;
4078259698Sdim
4079259698Sdim// End of post-index load/store single N-element instructions
4080259698Sdim// (class SIMD lsone-post)
4081259698Sdim
4082259698Sdim// Neon Scalar instructions implementation
4083259698Sdim// Scalar Three Same
4084259698Sdim
4085259698Sdimclass NeonI_Scalar3Same_size<bit u, bits<2> size, bits<5> opcode, string asmop,
4086259698Sdim                             RegisterClass FPRC>
4087259698Sdim  : NeonI_Scalar3Same<u, size, opcode,
4088259698Sdim                      (outs FPRC:$Rd), (ins FPRC:$Rn, FPRC:$Rm),
4089259698Sdim                      !strconcat(asmop, "\t$Rd, $Rn, $Rm"),
4090259698Sdim                      [],
4091259698Sdim                      NoItinerary>;
4092259698Sdim
4093259698Sdimclass NeonI_Scalar3Same_D_size<bit u, bits<5> opcode, string asmop>
4094259698Sdim  : NeonI_Scalar3Same_size<u, 0b11, opcode, asmop, FPR64>;
4095259698Sdim
4096259698Sdimmulticlass NeonI_Scalar3Same_HS_sizes<bit u, bits<5> opcode, string asmop,
4097259698Sdim                                      bit Commutable = 0> {
4098259698Sdim  let isCommutable = Commutable in {
4099259698Sdim    def hhh : NeonI_Scalar3Same_size<u, 0b01, opcode, asmop, FPR16>;
4100259698Sdim    def sss : NeonI_Scalar3Same_size<u, 0b10, opcode, asmop, FPR32>;
4101259698Sdim  }
4102259698Sdim}
4103259698Sdim
4104259698Sdimmulticlass NeonI_Scalar3Same_SD_sizes<bit u, bit size_high, bits<5> opcode,
4105259698Sdim                                      string asmop, bit Commutable = 0> {
4106259698Sdim  let isCommutable = Commutable in {
4107259698Sdim    def sss : NeonI_Scalar3Same_size<u, {size_high, 0b0}, opcode, asmop, FPR32>;
4108259698Sdim    def ddd : NeonI_Scalar3Same_size<u, {size_high, 0b1}, opcode, asmop, FPR64>;
4109259698Sdim  }
4110259698Sdim}
4111259698Sdim
4112259698Sdimmulticlass NeonI_Scalar3Same_BHSD_sizes<bit u, bits<5> opcode,
4113259698Sdim                                        string asmop, bit Commutable = 0> {
4114259698Sdim  let isCommutable = Commutable in {
4115259698Sdim    def bbb : NeonI_Scalar3Same_size<u, 0b00, opcode, asmop, FPR8>;
4116259698Sdim    def hhh : NeonI_Scalar3Same_size<u, 0b01, opcode, asmop, FPR16>;
4117259698Sdim    def sss : NeonI_Scalar3Same_size<u, 0b10, opcode, asmop, FPR32>;
4118259698Sdim    def ddd : NeonI_Scalar3Same_size<u, 0b11, opcode, asmop, FPR64>;
4119259698Sdim  }
4120259698Sdim}
4121259698Sdim
4122259698Sdimmulticlass Neon_Scalar3Same_D_size_patterns<SDPatternOperator opnode,
4123259698Sdim                                            Instruction INSTD> {
4124259698Sdim  def : Pat<(v1i64 (opnode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm))),
4125259698Sdim            (INSTD FPR64:$Rn, FPR64:$Rm)>;
4126259698Sdim}
4127259698Sdim
4128259698Sdimmulticlass Neon_Scalar3Same_BHSD_size_patterns<SDPatternOperator opnode,
4129259698Sdim                                               Instruction INSTB,
4130259698Sdim                                               Instruction INSTH,
4131259698Sdim                                               Instruction INSTS,
4132259698Sdim                                               Instruction INSTD>
4133259698Sdim  : Neon_Scalar3Same_D_size_patterns<opnode, INSTD> {
4134259698Sdim  def: Pat<(v1i8 (opnode (v1i8 FPR8:$Rn), (v1i8 FPR8:$Rm))),
4135259698Sdim           (INSTB FPR8:$Rn, FPR8:$Rm)>;
4136259698Sdim
4137259698Sdim  def: Pat<(v1i16 (opnode (v1i16 FPR16:$Rn), (v1i16 FPR16:$Rm))),
4138259698Sdim           (INSTH FPR16:$Rn, FPR16:$Rm)>;
4139259698Sdim
4140259698Sdim  def: Pat<(v1i32 (opnode (v1i32 FPR32:$Rn), (v1i32 FPR32:$Rm))),
4141259698Sdim           (INSTS FPR32:$Rn, FPR32:$Rm)>;
4142259698Sdim}
4143259698Sdim
4144259698Sdimclass Neon_Scalar3Same_cmp_D_size_patterns<SDPatternOperator opnode,
4145259698Sdim                                           Instruction INSTD>
4146259698Sdim  : Pat<(v1i64 (opnode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm))),
4147259698Sdim        (INSTD FPR64:$Rn, FPR64:$Rm)>;
4148259698Sdim
4149259698Sdimmulticlass Neon_Scalar3Same_HS_size_patterns<SDPatternOperator opnode,
4150259698Sdim                                             Instruction INSTH,
4151259698Sdim                                             Instruction INSTS> {
4152259698Sdim  def : Pat<(v1i16 (opnode (v1i16 FPR16:$Rn), (v1i16 FPR16:$Rm))),
4153259698Sdim            (INSTH FPR16:$Rn, FPR16:$Rm)>;
4154259698Sdim  def : Pat<(v1i32 (opnode (v1i32 FPR32:$Rn), (v1i32 FPR32:$Rm))),
4155259698Sdim            (INSTS FPR32:$Rn, FPR32:$Rm)>;
4156259698Sdim}
4157259698Sdim
4158259698Sdimmulticlass Neon_Scalar3Same_SD_size_patterns<SDPatternOperator opnode,
4159259698Sdim                                             Instruction INSTS,
4160259698Sdim                                             Instruction INSTD> {
4161259698Sdim  def : Pat<(v1f32 (opnode (v1f32 FPR32:$Rn), (v1f32 FPR32:$Rm))),
4162259698Sdim            (INSTS FPR32:$Rn, FPR32:$Rm)>;
4163259698Sdim  def : Pat<(v1f64 (opnode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
4164259698Sdim            (INSTD FPR64:$Rn, FPR64:$Rm)>;
4165259698Sdim}
4166259698Sdim
4167259698Sdimmulticlass Neon_Scalar3Same_cmp_SD_size_patterns<SDPatternOperator opnode,
4168259698Sdim                                                 Instruction INSTS,
4169259698Sdim                                                 Instruction INSTD> {
4170259698Sdim  def : Pat<(v1i32 (opnode (v1f32 FPR32:$Rn), (v1f32 FPR32:$Rm))),
4171259698Sdim            (INSTS FPR32:$Rn, FPR32:$Rm)>;
4172259698Sdim  def : Pat<(v1i64 (opnode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
4173259698Sdim            (INSTD FPR64:$Rn, FPR64:$Rm)>;
4174259698Sdim}
4175259698Sdim
4176259698Sdimclass Neon_Scalar3Same_cmp_V1_D_size_patterns<CondCode CC,
4177259698Sdim                                              Instruction INSTD>
4178259698Sdim  : Pat<(v1i64 (Neon_cmp (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm), CC)),
4179259698Sdim        (INSTD FPR64:$Rn, FPR64:$Rm)>;
4180259698Sdim
4181259698Sdim// Scalar Three Different
4182259698Sdim
4183259698Sdimclass NeonI_Scalar3Diff_size<bit u, bits<2> size, bits<4> opcode, string asmop,
4184259698Sdim                             RegisterClass FPRCD, RegisterClass FPRCS>
4185259698Sdim  : NeonI_Scalar3Diff<u, size, opcode,
4186259698Sdim                      (outs FPRCD:$Rd), (ins FPRCS:$Rn, FPRCS:$Rm),
4187259698Sdim                      !strconcat(asmop, "\t$Rd, $Rn, $Rm"),
4188259698Sdim                      [],
4189259698Sdim                      NoItinerary>;
4190259698Sdim
4191259698Sdimmulticlass NeonI_Scalar3Diff_HS_size<bit u, bits<4> opcode, string asmop> {
4192259698Sdim  def shh : NeonI_Scalar3Diff_size<u, 0b01, opcode, asmop, FPR32, FPR16>;
4193259698Sdim  def dss : NeonI_Scalar3Diff_size<u, 0b10, opcode, asmop, FPR64, FPR32>;
4194259698Sdim}
4195259698Sdim
4196259698Sdimmulticlass NeonI_Scalar3Diff_ml_HS_size<bit u, bits<4> opcode, string asmop> {
4197259698Sdim  let Constraints = "$Src = $Rd" in {
4198259698Sdim    def shh : NeonI_Scalar3Diff<u, 0b01, opcode,
4199259698Sdim                       (outs FPR32:$Rd), (ins FPR32:$Src, FPR16:$Rn, FPR16:$Rm),
4200259698Sdim                       !strconcat(asmop, "\t$Rd, $Rn, $Rm"),
4201259698Sdim                       [],
4202259698Sdim                       NoItinerary>;
4203259698Sdim    def dss : NeonI_Scalar3Diff<u, 0b10, opcode,
4204259698Sdim                       (outs FPR64:$Rd), (ins FPR64:$Src, FPR32:$Rn, FPR32:$Rm),
4205259698Sdim                       !strconcat(asmop, "\t$Rd, $Rn, $Rm"),
4206259698Sdim                       [],
4207259698Sdim                       NoItinerary>;
4208259698Sdim  }
4209259698Sdim}
4210259698Sdim
4211259698Sdimmulticlass Neon_Scalar3Diff_HS_size_patterns<SDPatternOperator opnode,
4212259698Sdim                                             Instruction INSTH,
4213259698Sdim                                             Instruction INSTS> {
4214259698Sdim  def : Pat<(v1i32 (opnode (v1i16 FPR16:$Rn), (v1i16 FPR16:$Rm))),
4215259698Sdim            (INSTH FPR16:$Rn, FPR16:$Rm)>;
4216259698Sdim  def : Pat<(v1i64 (opnode (v1i32 FPR32:$Rn), (v1i32 FPR32:$Rm))),
4217259698Sdim            (INSTS FPR32:$Rn, FPR32:$Rm)>;
4218259698Sdim}
4219259698Sdim
4220259698Sdimmulticlass Neon_Scalar3Diff_ml_HS_size_patterns<SDPatternOperator opnode,
4221259698Sdim                                             Instruction INSTH,
4222259698Sdim                                             Instruction INSTS> {
4223259698Sdim  def : Pat<(v1i32 (opnode (v1i32 FPR32:$Src), (v1i16 FPR16:$Rn), (v1i16 FPR16:$Rm))),
4224259698Sdim            (INSTH FPR32:$Src, FPR16:$Rn, FPR16:$Rm)>;
4225259698Sdim  def : Pat<(v1i64 (opnode (v1i64 FPR64:$Src), (v1i32 FPR32:$Rn), (v1i32 FPR32:$Rm))),
4226259698Sdim            (INSTS FPR64:$Src, FPR32:$Rn, FPR32:$Rm)>;
4227259698Sdim}
4228259698Sdim
4229259698Sdim// Scalar Two Registers Miscellaneous
4230259698Sdim
4231259698Sdimclass NeonI_Scalar2SameMisc_size<bit u, bits<2> size, bits<5> opcode, string asmop,
4232259698Sdim                             RegisterClass FPRCD, RegisterClass FPRCS>
4233259698Sdim  : NeonI_Scalar2SameMisc<u, size, opcode,
4234259698Sdim                          (outs FPRCD:$Rd), (ins FPRCS:$Rn),
4235259698Sdim                          !strconcat(asmop, "\t$Rd, $Rn"),
4236259698Sdim                          [],
4237259698Sdim                          NoItinerary>;
4238259698Sdim
4239259698Sdimmulticlass NeonI_Scalar2SameMisc_SD_size<bit u, bit size_high, bits<5> opcode,
4240259698Sdim                                         string asmop> {
4241259698Sdim  def ss : NeonI_Scalar2SameMisc_size<u, {size_high, 0b0}, opcode, asmop, FPR32,
4242259698Sdim                                      FPR32>;
4243259698Sdim  def dd : NeonI_Scalar2SameMisc_size<u, {size_high, 0b1}, opcode, asmop, FPR64,
4244259698Sdim                                      FPR64>;
4245259698Sdim}
4246259698Sdim
4247259698Sdimmulticlass NeonI_Scalar2SameMisc_D_size<bit u, bits<5> opcode, string asmop> {
4248259698Sdim  def dd : NeonI_Scalar2SameMisc_size<u, 0b11, opcode, asmop, FPR64, FPR64>;
4249259698Sdim}
4250259698Sdim
4251259698Sdimmulticlass NeonI_Scalar2SameMisc_BHSD_size<bit u, bits<5> opcode, string asmop>
4252259698Sdim  : NeonI_Scalar2SameMisc_D_size<u, opcode, asmop> {
4253259698Sdim  def bb : NeonI_Scalar2SameMisc_size<u, 0b00, opcode, asmop, FPR8, FPR8>;
4254259698Sdim  def hh : NeonI_Scalar2SameMisc_size<u, 0b01, opcode, asmop, FPR16, FPR16>;
4255259698Sdim  def ss : NeonI_Scalar2SameMisc_size<u, 0b10, opcode, asmop, FPR32, FPR32>;
4256259698Sdim}
4257259698Sdim
4258259698Sdimclass NeonI_Scalar2SameMisc_fcvtxn_D_size<bit u, bits<5> opcode, string asmop>
4259259698Sdim  : NeonI_Scalar2SameMisc_size<u, 0b01, opcode, asmop, FPR32, FPR64>;
4260259698Sdim
4261259698Sdimmulticlass NeonI_Scalar2SameMisc_narrow_HSD_size<bit u, bits<5> opcode,
4262259698Sdim                                                 string asmop> {
4263259698Sdim  def bh : NeonI_Scalar2SameMisc_size<u, 0b00, opcode, asmop, FPR8, FPR16>;
4264259698Sdim  def hs : NeonI_Scalar2SameMisc_size<u, 0b01, opcode, asmop, FPR16, FPR32>;
4265259698Sdim  def sd : NeonI_Scalar2SameMisc_size<u, 0b10, opcode, asmop, FPR32, FPR64>;
4266259698Sdim}
4267259698Sdim
4268259698Sdimclass NeonI_Scalar2SameMisc_accum_size<bit u, bits<2> size, bits<5> opcode,
4269259698Sdim                                       string asmop, RegisterClass FPRC>
4270259698Sdim  : NeonI_Scalar2SameMisc<u, size, opcode,
4271259698Sdim                          (outs FPRC:$Rd), (ins FPRC:$Src, FPRC:$Rn),
4272259698Sdim                          !strconcat(asmop, "\t$Rd, $Rn"),
4273259698Sdim                          [],
4274259698Sdim                          NoItinerary>;
4275259698Sdim
4276259698Sdimmulticlass NeonI_Scalar2SameMisc_accum_BHSD_size<bit u, bits<5> opcode,
4277259698Sdim                                                 string asmop> {
4278259698Sdim
4279259698Sdim  let Constraints = "$Src = $Rd" in {
4280259698Sdim    def bb : NeonI_Scalar2SameMisc_accum_size<u, 0b00, opcode, asmop, FPR8>;
4281259698Sdim    def hh : NeonI_Scalar2SameMisc_accum_size<u, 0b01, opcode, asmop, FPR16>;
4282259698Sdim    def ss : NeonI_Scalar2SameMisc_accum_size<u, 0b10, opcode, asmop, FPR32>;
4283259698Sdim    def dd : NeonI_Scalar2SameMisc_accum_size<u, 0b11, opcode, asmop, FPR64>;
4284259698Sdim  }
4285259698Sdim}
4286259698Sdim
4287259698Sdimclass Neon_Scalar2SameMisc_fcvtxn_D_size_patterns<SDPatternOperator opnode,
4288259698Sdim                                                  Instruction INSTD>
4289259698Sdim  : Pat<(v1f32 (opnode (v1f64 FPR64:$Rn))),
4290259698Sdim        (INSTD FPR64:$Rn)>;
4291259698Sdim
4292259698Sdimmulticlass Neon_Scalar2SameMisc_fcvt_SD_size_patterns<SDPatternOperator opnode,
4293259698Sdim                                                      Instruction INSTS,
4294259698Sdim                                                      Instruction INSTD> {
4295259698Sdim  def : Pat<(v1i32 (opnode (v1f32 FPR32:$Rn))),
4296259698Sdim            (INSTS FPR32:$Rn)>;
4297259698Sdim  def : Pat<(v1i64 (opnode (v1f64 FPR64:$Rn))),
4298259698Sdim            (INSTD FPR64:$Rn)>;
4299259698Sdim}
4300259698Sdim
4301259698Sdimmulticlass Neon_Scalar2SameMisc_cvt_SD_size_patterns<SDPatternOperator Sopnode,
4302259698Sdim                                                     SDPatternOperator Dopnode,
4303259698Sdim                                                     Instruction INSTS,
4304259698Sdim                                                     Instruction INSTD> {
4305259698Sdim  def : Pat<(f32 (Sopnode (v1i32 FPR32:$Rn))),
4306259698Sdim            (INSTS FPR32:$Rn)>;
4307259698Sdim  def : Pat<(f64 (Dopnode (v1i64 FPR64:$Rn))),
4308259698Sdim            (INSTD FPR64:$Rn)>;
4309259698Sdim}
4310259698Sdim
4311259698Sdimmulticlass Neon_Scalar2SameMisc_SD_size_patterns<SDPatternOperator opnode,
4312259698Sdim                                                 Instruction INSTS,
4313259698Sdim                                                 Instruction INSTD> {
4314259698Sdim  def : Pat<(v1f32 (opnode (v1f32 FPR32:$Rn))),
4315259698Sdim            (INSTS FPR32:$Rn)>;
4316259698Sdim  def : Pat<(v1f64 (opnode (v1f64 FPR64:$Rn))),
4317259698Sdim            (INSTD FPR64:$Rn)>;
4318259698Sdim}
4319259698Sdim
4320259698Sdimclass NeonI_Scalar2SameMisc_cmpz_D_size<bit u, bits<5> opcode, string asmop>
4321259698Sdim  : NeonI_Scalar2SameMisc<u, 0b11, opcode,
4322259698Sdim                          (outs FPR64:$Rd), (ins FPR64:$Rn, neon_uimm0:$Imm),
4323259698Sdim                          !strconcat(asmop, "\t$Rd, $Rn, $Imm"),
4324259698Sdim                          [],
4325259698Sdim                          NoItinerary>;
4326259698Sdim
4327259698Sdimmulticlass NeonI_Scalar2SameMisc_cmpz_SD_size<bit u, bits<5> opcode,
4328259698Sdim                                              string asmop> {
4329259698Sdim  def ssi : NeonI_Scalar2SameMisc<u, 0b10, opcode,
4330259698Sdim                           (outs FPR32:$Rd), (ins FPR32:$Rn, fpz32:$FPImm),
4331259698Sdim                           !strconcat(asmop, "\t$Rd, $Rn, $FPImm"),
4332259698Sdim                           [],
4333259698Sdim                           NoItinerary>;
4334259698Sdim  def ddi : NeonI_Scalar2SameMisc<u, 0b11, opcode,
4335259698Sdim                           (outs FPR64:$Rd), (ins FPR64:$Rn, fpz32:$FPImm),
4336259698Sdim                           !strconcat(asmop, "\t$Rd, $Rn, $FPImm"),
4337259698Sdim                           [],
4338259698Sdim                           NoItinerary>;
4339259698Sdim}
4340259698Sdim
4341259698Sdimclass Neon_Scalar2SameMisc_cmpz_D_size_patterns<SDPatternOperator opnode,
4342259698Sdim                                                Instruction INSTD>
4343259698Sdim  : Pat<(v1i64 (opnode (v1i64 FPR64:$Rn),
4344259698Sdim                       (v1i64 (bitconvert (v8i8 Neon_AllZero))))),
4345259698Sdim        (INSTD FPR64:$Rn, 0)>;
4346259698Sdim
4347259698Sdimclass Neon_Scalar2SameMisc_cmpz_D_V1_size_patterns<CondCode CC,
4348259698Sdim                                                   Instruction INSTD>
4349259698Sdim  : Pat<(v1i64 (Neon_cmpz (v1i64 FPR64:$Rn),
4350259698Sdim                          (i32 neon_uimm0:$Imm), CC)),
4351259698Sdim        (INSTD FPR64:$Rn, neon_uimm0:$Imm)>;
4352259698Sdim
4353259698Sdimmulticlass Neon_Scalar2SameMisc_cmpz_SD_size_patterns<SDPatternOperator opnode,
4354259698Sdim                                                      Instruction INSTS,
4355259698Sdim                                                      Instruction INSTD> {
4356259698Sdim  def : Pat<(v1i32 (opnode (v1f32 FPR32:$Rn),
4357259698Sdim                           (v1f32 (scalar_to_vector (f32 fpz32:$FPImm))))),
4358259698Sdim            (INSTS FPR32:$Rn, fpz32:$FPImm)>;
4359259698Sdim  def : Pat<(v1i64 (opnode (v1f64 FPR64:$Rn),
4360259698Sdim                           (v1f32 (scalar_to_vector (f32 fpz32:$FPImm))))),
4361259698Sdim            (INSTD FPR64:$Rn, fpz32:$FPImm)>;
4362259698Sdim}
4363259698Sdim
4364259698Sdimmulticlass Neon_Scalar2SameMisc_D_size_patterns<SDPatternOperator opnode,
4365259698Sdim                                                Instruction INSTD> {
4366259698Sdim  def : Pat<(v1i64 (opnode (v1i64 FPR64:$Rn))),
4367259698Sdim            (INSTD FPR64:$Rn)>;
4368259698Sdim}
4369259698Sdim
4370259698Sdimmulticlass Neon_Scalar2SameMisc_BHSD_size_patterns<SDPatternOperator opnode,
4371259698Sdim                                                   Instruction INSTB,
4372259698Sdim                                                   Instruction INSTH,
4373259698Sdim                                                   Instruction INSTS,
4374259698Sdim                                                   Instruction INSTD>
4375259698Sdim  : Neon_Scalar2SameMisc_D_size_patterns<opnode, INSTD> {
4376259698Sdim  def : Pat<(v1i8 (opnode (v1i8 FPR8:$Rn))),
4377259698Sdim            (INSTB FPR8:$Rn)>;
4378259698Sdim  def : Pat<(v1i16 (opnode (v1i16 FPR16:$Rn))),
4379259698Sdim            (INSTH FPR16:$Rn)>;
4380259698Sdim  def : Pat<(v1i32 (opnode (v1i32 FPR32:$Rn))),
4381259698Sdim            (INSTS FPR32:$Rn)>;
4382259698Sdim}
4383259698Sdim
4384259698Sdimmulticlass Neon_Scalar2SameMisc_narrow_HSD_size_patterns<
4385259698Sdim                                                       SDPatternOperator opnode,
4386259698Sdim                                                       Instruction INSTH,
4387259698Sdim                                                       Instruction INSTS,
4388259698Sdim                                                       Instruction INSTD> {
4389259698Sdim  def : Pat<(v1i8 (opnode (v1i16 FPR16:$Rn))),
4390259698Sdim            (INSTH FPR16:$Rn)>;
4391259698Sdim  def : Pat<(v1i16 (opnode (v1i32 FPR32:$Rn))),
4392259698Sdim            (INSTS FPR32:$Rn)>;
4393259698Sdim  def : Pat<(v1i32 (opnode (v1i64 FPR64:$Rn))),
4394259698Sdim            (INSTD FPR64:$Rn)>;
4395259698Sdim
4396259698Sdim}
4397259698Sdim
4398259698Sdimmulticlass Neon_Scalar2SameMisc_accum_BHSD_size_patterns<
4399259698Sdim                                                       SDPatternOperator opnode,
4400259698Sdim                                                       Instruction INSTB,
4401259698Sdim                                                       Instruction INSTH,
4402259698Sdim                                                       Instruction INSTS,
4403259698Sdim                                                       Instruction INSTD> {
4404259698Sdim  def : Pat<(v1i8 (opnode (v1i8 FPR8:$Src), (v1i8 FPR8:$Rn))),
4405259698Sdim            (INSTB FPR8:$Src, FPR8:$Rn)>;
4406259698Sdim  def : Pat<(v1i16 (opnode (v1i16 FPR16:$Src), (v1i16 FPR16:$Rn))),
4407259698Sdim            (INSTH FPR16:$Src, FPR16:$Rn)>;
4408259698Sdim  def : Pat<(v1i32 (opnode (v1i32 FPR32:$Src), (v1i32 FPR32:$Rn))),
4409259698Sdim            (INSTS FPR32:$Src, FPR32:$Rn)>;
4410259698Sdim  def : Pat<(v1i64 (opnode (v1i64 FPR64:$Src), (v1i64 FPR64:$Rn))),
4411259698Sdim            (INSTD FPR64:$Src, FPR64:$Rn)>;
4412259698Sdim}
4413259698Sdim
4414259698Sdim// Scalar Shift By Immediate
4415259698Sdim
4416259698Sdimclass NeonI_ScalarShiftImm_size<bit u, bits<5> opcode, string asmop,
4417259698Sdim                                RegisterClass FPRC, Operand ImmTy>
4418259698Sdim  : NeonI_ScalarShiftImm<u, opcode,
4419259698Sdim                         (outs FPRC:$Rd), (ins FPRC:$Rn, ImmTy:$Imm),
4420259698Sdim                         !strconcat(asmop, "\t$Rd, $Rn, $Imm"),
4421259698Sdim                         [], NoItinerary>;
4422259698Sdim
4423259698Sdimmulticlass NeonI_ScalarShiftRightImm_D_size<bit u, bits<5> opcode,
4424259698Sdim                                            string asmop> {
4425259698Sdim  def ddi : NeonI_ScalarShiftImm_size<u, opcode, asmop, FPR64, shr_imm64> {
4426259698Sdim    bits<6> Imm;
4427259698Sdim    let Inst{22} = 0b1; // immh:immb = 1xxxxxx
4428259698Sdim    let Inst{21-16} = Imm;
4429259698Sdim  }
4430259698Sdim}
4431259698Sdim
4432259698Sdimmulticlass NeonI_ScalarShiftRightImm_BHSD_size<bit u, bits<5> opcode,
4433259698Sdim                                               string asmop>
4434259698Sdim  : NeonI_ScalarShiftRightImm_D_size<u, opcode, asmop> {
4435259698Sdim  def bbi : NeonI_ScalarShiftImm_size<u, opcode, asmop, FPR8, shr_imm8> {
4436259698Sdim    bits<3> Imm;
4437259698Sdim    let Inst{22-19} = 0b0001; // immh:immb = 0001xxx
4438259698Sdim    let Inst{18-16} = Imm;
4439259698Sdim  }
4440259698Sdim  def hhi : NeonI_ScalarShiftImm_size<u, opcode, asmop, FPR16, shr_imm16> {
4441259698Sdim    bits<4> Imm;
4442259698Sdim    let Inst{22-20} = 0b001; // immh:immb = 001xxxx
4443259698Sdim    let Inst{19-16} = Imm;
4444259698Sdim  }
4445259698Sdim  def ssi : NeonI_ScalarShiftImm_size<u, opcode, asmop, FPR32, shr_imm32> {
4446259698Sdim    bits<5> Imm;
4447259698Sdim    let Inst{22-21} = 0b01; // immh:immb = 01xxxxx
4448259698Sdim    let Inst{20-16} = Imm;
4449259698Sdim  }
4450259698Sdim}
4451259698Sdim
4452259698Sdimmulticlass NeonI_ScalarShiftLeftImm_D_size<bit u, bits<5> opcode,
4453259698Sdim                                            string asmop> {
4454259698Sdim  def ddi : NeonI_ScalarShiftImm_size<u, opcode, asmop, FPR64, shl_imm64> {
4455259698Sdim    bits<6> Imm;
4456259698Sdim    let Inst{22} = 0b1; // immh:immb = 1xxxxxx
4457259698Sdim    let Inst{21-16} = Imm;
4458259698Sdim  }
4459259698Sdim}
4460259698Sdim
4461259698Sdimmulticlass NeonI_ScalarShiftLeftImm_BHSD_size<bit u, bits<5> opcode,
4462259698Sdim                                              string asmop>
4463259698Sdim  : NeonI_ScalarShiftLeftImm_D_size<u, opcode, asmop> {
4464259698Sdim  def bbi : NeonI_ScalarShiftImm_size<u, opcode, asmop, FPR8, shl_imm8> {
4465259698Sdim    bits<3> Imm;
4466259698Sdim    let Inst{22-19} = 0b0001; // immh:immb = 0001xxx
4467259698Sdim    let Inst{18-16} = Imm;
4468259698Sdim  }
4469259698Sdim  def hhi : NeonI_ScalarShiftImm_size<u, opcode, asmop, FPR16, shl_imm16> {
4470259698Sdim    bits<4> Imm;
4471259698Sdim    let Inst{22-20} = 0b001; // immh:immb = 001xxxx
4472259698Sdim    let Inst{19-16} = Imm;
4473259698Sdim  }
4474259698Sdim  def ssi : NeonI_ScalarShiftImm_size<u, opcode, asmop, FPR32, shl_imm32> {
4475259698Sdim    bits<5> Imm;
4476259698Sdim    let Inst{22-21} = 0b01; // immh:immb = 01xxxxx
4477259698Sdim    let Inst{20-16} = Imm;
4478259698Sdim  }
4479259698Sdim}
4480259698Sdim
4481259698Sdimclass NeonI_ScalarShiftRightImm_accum_D_size<bit u, bits<5> opcode, string asmop>
4482259698Sdim  : NeonI_ScalarShiftImm<u, opcode,
4483259698Sdim                         (outs FPR64:$Rd),
4484259698Sdim                         (ins FPR64:$Src, FPR64:$Rn, shr_imm64:$Imm),
4485259698Sdim                         !strconcat(asmop, "\t$Rd, $Rn, $Imm"),
4486259698Sdim                         [], NoItinerary> {
4487259698Sdim    bits<6> Imm;
4488259698Sdim    let Inst{22} = 0b1; // immh:immb = 1xxxxxx
4489259698Sdim    let Inst{21-16} = Imm;
4490259698Sdim    let Constraints = "$Src = $Rd";
4491259698Sdim}
4492259698Sdim
4493259698Sdimclass NeonI_ScalarShiftLeftImm_accum_D_size<bit u, bits<5> opcode, string asmop>
4494259698Sdim  : NeonI_ScalarShiftImm<u, opcode,
4495259698Sdim                         (outs FPR64:$Rd),
4496259698Sdim                         (ins FPR64:$Src, FPR64:$Rn, shl_imm64:$Imm),
4497259698Sdim                         !strconcat(asmop, "\t$Rd, $Rn, $Imm"),
4498259698Sdim                         [], NoItinerary> {
4499259698Sdim    bits<6> Imm;
4500259698Sdim    let Inst{22} = 0b1; // immh:immb = 1xxxxxx
4501259698Sdim    let Inst{21-16} = Imm;
4502259698Sdim    let Constraints = "$Src = $Rd";
4503259698Sdim}
4504259698Sdim
4505259698Sdimclass NeonI_ScalarShiftImm_narrow_size<bit u, bits<5> opcode, string asmop,
4506259698Sdim                                       RegisterClass FPRCD, RegisterClass FPRCS,
4507259698Sdim                                       Operand ImmTy>
4508259698Sdim  : NeonI_ScalarShiftImm<u, opcode,
4509259698Sdim                         (outs FPRCD:$Rd), (ins FPRCS:$Rn, ImmTy:$Imm),
4510259698Sdim                         !strconcat(asmop, "\t$Rd, $Rn, $Imm"),
4511259698Sdim                         [], NoItinerary>;
4512259698Sdim
4513259698Sdimmulticlass NeonI_ScalarShiftImm_narrow_HSD_size<bit u, bits<5> opcode,
4514259698Sdim                                                string asmop> {
4515259698Sdim  def bhi : NeonI_ScalarShiftImm_narrow_size<u, opcode, asmop, FPR8, FPR16,
4516259698Sdim                                             shr_imm8> {
4517259698Sdim    bits<3> Imm;
4518259698Sdim    let Inst{22-19} = 0b0001; // immh:immb = 0001xxx
4519259698Sdim    let Inst{18-16} = Imm;
4520259698Sdim  }
4521259698Sdim  def hsi : NeonI_ScalarShiftImm_narrow_size<u, opcode, asmop, FPR16, FPR32,
4522259698Sdim                                             shr_imm16> {
4523259698Sdim    bits<4> Imm;
4524259698Sdim    let Inst{22-20} = 0b001; // immh:immb = 001xxxx
4525259698Sdim    let Inst{19-16} = Imm;
4526259698Sdim  }
4527259698Sdim  def sdi : NeonI_ScalarShiftImm_narrow_size<u, opcode, asmop, FPR32, FPR64,
4528259698Sdim                                             shr_imm32> {
4529259698Sdim    bits<5> Imm;
4530259698Sdim    let Inst{22-21} = 0b01; // immh:immb = 01xxxxx
4531259698Sdim    let Inst{20-16} = Imm;
4532259698Sdim  }
4533259698Sdim}
4534259698Sdim
4535259698Sdimmulticlass NeonI_ScalarShiftImm_cvt_SD_size<bit u, bits<5> opcode, string asmop> {
4536259698Sdim  def ssi : NeonI_ScalarShiftImm_size<u, opcode, asmop, FPR32, shr_imm32> {
4537259698Sdim    bits<5> Imm;
4538259698Sdim    let Inst{22-21} = 0b01; // immh:immb = 01xxxxx
4539259698Sdim    let Inst{20-16} = Imm;
4540259698Sdim  }
4541259698Sdim  def ddi : NeonI_ScalarShiftImm_size<u, opcode, asmop, FPR64, shr_imm64> {
4542259698Sdim    bits<6> Imm;
4543259698Sdim    let Inst{22} = 0b1; // immh:immb = 1xxxxxx
4544259698Sdim    let Inst{21-16} = Imm;
4545259698Sdim  }
4546259698Sdim}
4547259698Sdim
4548259698Sdimmulticlass Neon_ScalarShiftRImm_D_size_patterns<SDPatternOperator opnode,
4549259698Sdim                                               Instruction INSTD> {
4550259698Sdim  def ddi : Pat<(v1i64 (opnode (v1i64 FPR64:$Rn), (i32 shr_imm64:$Imm))),
4551259698Sdim                (INSTD FPR64:$Rn, imm:$Imm)>;
4552259698Sdim}
4553259698Sdim
4554259698Sdimmulticlass Neon_ScalarShiftLImm_D_size_patterns<SDPatternOperator opnode,
4555259698Sdim                                               Instruction INSTD> {
4556259698Sdim  def ddi : Pat<(v1i64 (opnode (v1i64 FPR64:$Rn), (i32 shl_imm64:$Imm))),
4557259698Sdim                (INSTD FPR64:$Rn, imm:$Imm)>;
4558259698Sdim}
4559259698Sdim
4560259698Sdimclass Neon_ScalarShiftImm_arm_D_size_patterns<SDPatternOperator opnode,
4561259698Sdim                                              Instruction INSTD>
4562259698Sdim  : Pat<(v1i64 (opnode (v1i64 FPR64:$Rn),
4563259698Sdim            (v1i64 (Neon_vdup (i32 shr_imm64:$Imm))))),
4564259698Sdim        (INSTD FPR64:$Rn, imm:$Imm)>;
4565259698Sdim
4566259698Sdimmulticlass Neon_ScalarShiftLImm_BHSD_size_patterns<SDPatternOperator opnode,
4567259698Sdim                                                   Instruction INSTB,
4568259698Sdim                                                   Instruction INSTH,
4569259698Sdim                                                   Instruction INSTS,
4570259698Sdim                                                   Instruction INSTD>
4571259698Sdim  : Neon_ScalarShiftLImm_D_size_patterns<opnode, INSTD> {
4572259698Sdim  def bbi : Pat<(v1i8 (opnode (v1i8 FPR8:$Rn), (i32 shl_imm8:$Imm))),
4573259698Sdim                (INSTB FPR8:$Rn, imm:$Imm)>;
4574259698Sdim  def hhi : Pat<(v1i16 (opnode (v1i16 FPR16:$Rn), (i32 shl_imm16:$Imm))),
4575259698Sdim                (INSTH FPR16:$Rn, imm:$Imm)>;
4576259698Sdim  def ssi : Pat<(v1i32 (opnode (v1i32 FPR32:$Rn), (i32 shl_imm32:$Imm))),
4577259698Sdim                (INSTS FPR32:$Rn, imm:$Imm)>;
4578259698Sdim}
4579259698Sdim
4580259698Sdimclass Neon_ScalarShiftLImm_accum_D_size_patterns<SDPatternOperator opnode,
4581259698Sdim                                                Instruction INSTD>
4582259698Sdim  : Pat<(v1i64 (opnode (v1i64 FPR64:$Src), (v1i64 FPR64:$Rn),
4583259698Sdim            (i32 shl_imm64:$Imm))),
4584259698Sdim        (INSTD FPR64:$Src, FPR64:$Rn, imm:$Imm)>;
4585259698Sdim
4586259698Sdimclass Neon_ScalarShiftRImm_accum_D_size_patterns<SDPatternOperator opnode,
4587259698Sdim                                                Instruction INSTD>
4588259698Sdim  : Pat<(v1i64 (opnode (v1i64 FPR64:$Src), (v1i64 FPR64:$Rn),
4589259698Sdim            (i32 shr_imm64:$Imm))),
4590259698Sdim        (INSTD FPR64:$Src, FPR64:$Rn, imm:$Imm)>;
4591259698Sdim
4592259698Sdimmulticlass Neon_ScalarShiftImm_narrow_HSD_size_patterns<
4593259698Sdim                                                       SDPatternOperator opnode,
4594259698Sdim                                                       Instruction INSTH,
4595259698Sdim                                                       Instruction INSTS,
4596259698Sdim                                                       Instruction INSTD> {
4597259698Sdim  def bhi : Pat<(v1i8 (opnode (v1i16 FPR16:$Rn), (i32 shr_imm16:$Imm))),
4598259698Sdim                (INSTH FPR16:$Rn, imm:$Imm)>;
4599259698Sdim  def hsi : Pat<(v1i16 (opnode (v1i32 FPR32:$Rn), (i32 shr_imm32:$Imm))),
4600259698Sdim                (INSTS FPR32:$Rn, imm:$Imm)>;
4601259698Sdim  def sdi : Pat<(v1i32 (opnode (v1i64 FPR64:$Rn), (i32 shr_imm64:$Imm))),
4602259698Sdim                (INSTD FPR64:$Rn, imm:$Imm)>;
4603259698Sdim}
4604259698Sdim
4605259698Sdimmulticlass Neon_ScalarShiftImm_scvtf_SD_size_patterns<SDPatternOperator Sopnode,
4606259698Sdim                                                      SDPatternOperator Dopnode,
4607259698Sdim                                                      Instruction INSTS,
4608259698Sdim                                                      Instruction INSTD> {
4609259698Sdim  def ssi : Pat<(f32 (Sopnode (v1i32 FPR32:$Rn), (i32 shr_imm32:$Imm))),
4610259698Sdim                (INSTS FPR32:$Rn, imm:$Imm)>;
4611259698Sdim  def ddi : Pat<(f64 (Dopnode (v1i64 FPR64:$Rn), (i32 shr_imm64:$Imm))),
4612259698Sdim                (INSTD FPR64:$Rn, imm:$Imm)>;
4613259698Sdim}
4614259698Sdim
4615259698Sdimmulticlass Neon_ScalarShiftImm_fcvts_SD_size_patterns<SDPatternOperator Sopnode,
4616259698Sdim                                                      SDPatternOperator Dopnode,
4617259698Sdim                                                      Instruction INSTS,
4618259698Sdim                                                      Instruction INSTD> {
4619259698Sdim  def ssi : Pat<(v1i32 (Sopnode (v1f32 FPR32:$Rn), (i32 shr_imm32:$Imm))),
4620259698Sdim                (INSTS FPR32:$Rn, imm:$Imm)>;
4621259698Sdim  def ddi : Pat<(v1i64 (Dopnode (v1f64 FPR64:$Rn), (i32 shr_imm64:$Imm))),
4622259698Sdim                (INSTD FPR64:$Rn, imm:$Imm)>;
4623259698Sdim}
4624259698Sdim
4625259698Sdim// Scalar Signed Shift Right (Immediate)
4626259698Sdimdefm SSHR : NeonI_ScalarShiftRightImm_D_size<0b0, 0b00000, "sshr">;
4627259698Sdimdefm : Neon_ScalarShiftRImm_D_size_patterns<int_aarch64_neon_vshrds_n, SSHRddi>;
4628259698Sdim// Pattern to match llvm.arm.* intrinsic.
4629259698Sdimdef : Neon_ScalarShiftImm_arm_D_size_patterns<sra, SSHRddi>;
4630259698Sdim
4631259698Sdim// Scalar Unsigned Shift Right (Immediate)
4632259698Sdimdefm USHR : NeonI_ScalarShiftRightImm_D_size<0b1, 0b00000, "ushr">;
4633259698Sdimdefm : Neon_ScalarShiftRImm_D_size_patterns<int_aarch64_neon_vshrdu_n, USHRddi>;
4634259698Sdim// Pattern to match llvm.arm.* intrinsic.
4635259698Sdimdef : Neon_ScalarShiftImm_arm_D_size_patterns<srl, USHRddi>;
4636259698Sdim
4637259698Sdim// Scalar Signed Rounding Shift Right (Immediate)
4638259698Sdimdefm SRSHR : NeonI_ScalarShiftRightImm_D_size<0b0, 0b00100, "srshr">;
4639259698Sdimdefm : Neon_ScalarShiftRImm_D_size_patterns<int_aarch64_neon_vsrshr, SRSHRddi>;
4640259698Sdim
4641259698Sdim// Scalar Unigned Rounding Shift Right (Immediate)
4642259698Sdimdefm URSHR : NeonI_ScalarShiftRightImm_D_size<0b1, 0b00100, "urshr">;
4643259698Sdimdefm : Neon_ScalarShiftRImm_D_size_patterns<int_aarch64_neon_vurshr, URSHRddi>;
4644259698Sdim
4645259698Sdim// Scalar Signed Shift Right and Accumulate (Immediate)
4646259698Sdimdef SSRA : NeonI_ScalarShiftRightImm_accum_D_size<0b0, 0b00010, "ssra">;
4647259698Sdimdef : Neon_ScalarShiftRImm_accum_D_size_patterns
4648259698Sdim          <int_aarch64_neon_vsrads_n, SSRA>;
4649259698Sdim
4650259698Sdim// Scalar Unsigned Shift Right and Accumulate (Immediate)
4651259698Sdimdef USRA : NeonI_ScalarShiftRightImm_accum_D_size<0b1, 0b00010, "usra">;
4652259698Sdimdef : Neon_ScalarShiftRImm_accum_D_size_patterns
4653259698Sdim          <int_aarch64_neon_vsradu_n, USRA>;
4654259698Sdim
4655259698Sdim// Scalar Signed Rounding Shift Right and Accumulate (Immediate)
4656259698Sdimdef SRSRA : NeonI_ScalarShiftRightImm_accum_D_size<0b0, 0b00110, "srsra">;
4657259698Sdimdef : Neon_ScalarShiftRImm_accum_D_size_patterns
4658259698Sdim          <int_aarch64_neon_vrsrads_n, SRSRA>;
4659259698Sdim
4660259698Sdim// Scalar Unsigned Rounding Shift Right and Accumulate (Immediate)
4661259698Sdimdef URSRA : NeonI_ScalarShiftRightImm_accum_D_size<0b1, 0b00110, "ursra">;
4662259698Sdimdef : Neon_ScalarShiftRImm_accum_D_size_patterns
4663259698Sdim          <int_aarch64_neon_vrsradu_n, URSRA>;
4664259698Sdim
4665259698Sdim// Scalar Shift Left (Immediate)
4666259698Sdimdefm SHL : NeonI_ScalarShiftLeftImm_D_size<0b0, 0b01010, "shl">;
4667259698Sdimdefm : Neon_ScalarShiftLImm_D_size_patterns<int_aarch64_neon_vshld_n, SHLddi>;
4668259698Sdim// Pattern to match llvm.arm.* intrinsic.
4669259698Sdimdef : Neon_ScalarShiftImm_arm_D_size_patterns<shl, SHLddi>;
4670259698Sdim
4671259698Sdim// Signed Saturating Shift Left (Immediate)
4672259698Sdimdefm SQSHL : NeonI_ScalarShiftLeftImm_BHSD_size<0b0, 0b01110, "sqshl">;
4673259698Sdimdefm : Neon_ScalarShiftLImm_BHSD_size_patterns<int_aarch64_neon_vqshls_n,
4674259698Sdim                                               SQSHLbbi, SQSHLhhi,
4675259698Sdim                                               SQSHLssi, SQSHLddi>;
4676259698Sdim// Pattern to match llvm.arm.* intrinsic.
4677259698Sdimdefm : Neon_ScalarShiftLImm_D_size_patterns<Neon_sqrshlImm, SQSHLddi>;
4678259698Sdim
4679259698Sdim// Unsigned Saturating Shift Left (Immediate)
4680259698Sdimdefm UQSHL : NeonI_ScalarShiftLeftImm_BHSD_size<0b1, 0b01110, "uqshl">;
4681259698Sdimdefm : Neon_ScalarShiftLImm_BHSD_size_patterns<int_aarch64_neon_vqshlu_n,
4682259698Sdim                                               UQSHLbbi, UQSHLhhi,
4683259698Sdim                                               UQSHLssi, UQSHLddi>;
4684259698Sdim// Pattern to match llvm.arm.* intrinsic.
4685259698Sdimdefm : Neon_ScalarShiftLImm_D_size_patterns<Neon_uqrshlImm, UQSHLddi>;
4686259698Sdim
4687259698Sdim// Signed Saturating Shift Left Unsigned (Immediate)
4688259698Sdimdefm SQSHLU : NeonI_ScalarShiftLeftImm_BHSD_size<0b1, 0b01100, "sqshlu">;
4689259698Sdimdefm : Neon_ScalarShiftLImm_BHSD_size_patterns<int_aarch64_neon_vsqshlu,
4690259698Sdim                                               SQSHLUbbi, SQSHLUhhi,
4691259698Sdim                                               SQSHLUssi, SQSHLUddi>;
4692259698Sdim
4693259698Sdim// Shift Right And Insert (Immediate)
4694259698Sdimdef SRI : NeonI_ScalarShiftRightImm_accum_D_size<0b1, 0b01000, "sri">;
4695259698Sdimdef : Neon_ScalarShiftRImm_accum_D_size_patterns
4696259698Sdim          <int_aarch64_neon_vsri, SRI>;
4697259698Sdim
4698259698Sdim// Shift Left And Insert (Immediate)
4699259698Sdimdef SLI : NeonI_ScalarShiftLeftImm_accum_D_size<0b1, 0b01010, "sli">;
4700259698Sdimdef : Neon_ScalarShiftLImm_accum_D_size_patterns
4701259698Sdim          <int_aarch64_neon_vsli, SLI>;
4702259698Sdim
4703259698Sdim// Signed Saturating Shift Right Narrow (Immediate)
4704259698Sdimdefm SQSHRN : NeonI_ScalarShiftImm_narrow_HSD_size<0b0, 0b10010, "sqshrn">;
4705259698Sdimdefm : Neon_ScalarShiftImm_narrow_HSD_size_patterns<int_aarch64_neon_vsqshrn,
4706259698Sdim                                                    SQSHRNbhi, SQSHRNhsi,
4707259698Sdim                                                    SQSHRNsdi>;
4708259698Sdim
4709259698Sdim// Unsigned Saturating Shift Right Narrow (Immediate)
4710259698Sdimdefm UQSHRN : NeonI_ScalarShiftImm_narrow_HSD_size<0b1, 0b10010, "uqshrn">;
4711259698Sdimdefm : Neon_ScalarShiftImm_narrow_HSD_size_patterns<int_aarch64_neon_vuqshrn,
4712259698Sdim                                                    UQSHRNbhi, UQSHRNhsi,
4713259698Sdim                                                    UQSHRNsdi>;
4714259698Sdim
4715259698Sdim// Signed Saturating Rounded Shift Right Narrow (Immediate)
4716259698Sdimdefm SQRSHRN : NeonI_ScalarShiftImm_narrow_HSD_size<0b0, 0b10011, "sqrshrn">;
4717259698Sdimdefm : Neon_ScalarShiftImm_narrow_HSD_size_patterns<int_aarch64_neon_vsqrshrn,
4718259698Sdim                                                    SQRSHRNbhi, SQRSHRNhsi,
4719259698Sdim                                                    SQRSHRNsdi>;
4720259698Sdim
4721259698Sdim// Unsigned Saturating Rounded Shift Right Narrow (Immediate)
4722259698Sdimdefm UQRSHRN : NeonI_ScalarShiftImm_narrow_HSD_size<0b1, 0b10011, "uqrshrn">;
4723259698Sdimdefm : Neon_ScalarShiftImm_narrow_HSD_size_patterns<int_aarch64_neon_vuqrshrn,
4724259698Sdim                                                    UQRSHRNbhi, UQRSHRNhsi,
4725259698Sdim                                                    UQRSHRNsdi>;
4726259698Sdim
4727259698Sdim// Signed Saturating Shift Right Unsigned Narrow (Immediate)
4728259698Sdimdefm SQSHRUN : NeonI_ScalarShiftImm_narrow_HSD_size<0b1, 0b10000, "sqshrun">;
4729259698Sdimdefm : Neon_ScalarShiftImm_narrow_HSD_size_patterns<int_aarch64_neon_vsqshrun,
4730259698Sdim                                                    SQSHRUNbhi, SQSHRUNhsi,
4731259698Sdim                                                    SQSHRUNsdi>;
4732259698Sdim
4733259698Sdim// Signed Saturating Rounded Shift Right Unsigned Narrow (Immediate)
4734259698Sdimdefm SQRSHRUN : NeonI_ScalarShiftImm_narrow_HSD_size<0b1, 0b10001, "sqrshrun">;
4735259698Sdimdefm : Neon_ScalarShiftImm_narrow_HSD_size_patterns<int_aarch64_neon_vsqrshrun,
4736259698Sdim                                                    SQRSHRUNbhi, SQRSHRUNhsi,
4737259698Sdim                                                    SQRSHRUNsdi>;
4738259698Sdim
4739259698Sdim// Scalar Signed Fixed-point Convert To Floating-Point (Immediate)
4740259698Sdimdefm SCVTF_N : NeonI_ScalarShiftImm_cvt_SD_size<0b0, 0b11100, "scvtf">;
4741259698Sdimdefm : Neon_ScalarShiftImm_scvtf_SD_size_patterns<int_aarch64_neon_vcvtf32_n_s32,
4742259698Sdim                                                  int_aarch64_neon_vcvtf64_n_s64,
4743259698Sdim                                                  SCVTF_Nssi, SCVTF_Nddi>;
4744259698Sdim
4745259698Sdim// Scalar Unsigned Fixed-point Convert To Floating-Point (Immediate)
4746259698Sdimdefm UCVTF_N : NeonI_ScalarShiftImm_cvt_SD_size<0b1, 0b11100, "ucvtf">;
4747259698Sdimdefm : Neon_ScalarShiftImm_scvtf_SD_size_patterns<int_aarch64_neon_vcvtf32_n_u32,
4748259698Sdim                                                  int_aarch64_neon_vcvtf64_n_u64,
4749259698Sdim                                                  UCVTF_Nssi, UCVTF_Nddi>;
4750259698Sdim
4751259698Sdim// Scalar Floating-point Convert To Signed Fixed-point (Immediate)
4752259698Sdimdefm FCVTZS_N : NeonI_ScalarShiftImm_cvt_SD_size<0b0, 0b11111, "fcvtzs">;
4753259698Sdimdefm : Neon_ScalarShiftImm_fcvts_SD_size_patterns<int_aarch64_neon_vcvts_n_s32_f32,
4754259698Sdim                                                  int_aarch64_neon_vcvtd_n_s64_f64,
4755259698Sdim                                                  FCVTZS_Nssi, FCVTZS_Nddi>;
4756259698Sdim
4757259698Sdim// Scalar Floating-point Convert To Unsigned Fixed-point (Immediate)
4758259698Sdimdefm FCVTZU_N : NeonI_ScalarShiftImm_cvt_SD_size<0b1, 0b11111, "fcvtzu">;
4759259698Sdimdefm : Neon_ScalarShiftImm_fcvts_SD_size_patterns<int_aarch64_neon_vcvts_n_u32_f32,
4760259698Sdim                                                  int_aarch64_neon_vcvtd_n_u64_f64,
4761259698Sdim                                                  FCVTZU_Nssi, FCVTZU_Nddi>;
4762259698Sdim
4763259698Sdim// Patterns For Convert Instructions Between v1f64 and v1i64
4764259698Sdimclass Neon_ScalarShiftImm_cvtf_v1f64_pattern<SDPatternOperator opnode,
4765259698Sdim                                             Instruction INST>
4766259698Sdim    : Pat<(v1f64 (opnode (v1i64 FPR64:$Rn), (i32 shr_imm64:$Imm))),
4767259698Sdim          (INST FPR64:$Rn, imm:$Imm)>;
4768259698Sdim
4769259698Sdimclass Neon_ScalarShiftImm_fcvt_v1f64_pattern<SDPatternOperator opnode,
4770259698Sdim                                             Instruction INST>
4771259698Sdim    : Pat<(v1i64 (opnode (v1f64 FPR64:$Rn), (i32 shr_imm64:$Imm))),
4772259698Sdim          (INST FPR64:$Rn, imm:$Imm)>;
4773259698Sdim
4774259698Sdimdef : Neon_ScalarShiftImm_cvtf_v1f64_pattern<int_arm_neon_vcvtfxs2fp,
4775259698Sdim                                             SCVTF_Nddi>;
4776259698Sdim
4777259698Sdimdef : Neon_ScalarShiftImm_cvtf_v1f64_pattern<int_arm_neon_vcvtfxu2fp,
4778259698Sdim                                             UCVTF_Nddi>;
4779259698Sdim
4780259698Sdimdef : Neon_ScalarShiftImm_fcvt_v1f64_pattern<int_arm_neon_vcvtfp2fxs,
4781259698Sdim                                             FCVTZS_Nddi>;
4782259698Sdim
4783259698Sdimdef : Neon_ScalarShiftImm_fcvt_v1f64_pattern<int_arm_neon_vcvtfp2fxu,
4784259698Sdim                                             FCVTZU_Nddi>;
4785259698Sdim
4786259698Sdim// Scalar Integer Add
4787259698Sdimlet isCommutable = 1 in {
4788259698Sdimdef ADDddd : NeonI_Scalar3Same_D_size<0b0, 0b10000, "add">;
4789259698Sdim}
4790259698Sdim
4791259698Sdim// Scalar Integer Sub
4792259698Sdimdef SUBddd : NeonI_Scalar3Same_D_size<0b1, 0b10000, "sub">;
4793259698Sdim
4794259698Sdim// Pattern for Scalar Integer Add and Sub with D register only
4795259698Sdimdefm : Neon_Scalar3Same_D_size_patterns<add, ADDddd>;
4796259698Sdimdefm : Neon_Scalar3Same_D_size_patterns<sub, SUBddd>;
4797259698Sdim
4798259698Sdim// Patterns to match llvm.aarch64.* intrinsic for Scalar Add, Sub
4799259698Sdimdefm : Neon_Scalar3Same_D_size_patterns<int_aarch64_neon_vaddds, ADDddd>;
4800259698Sdimdefm : Neon_Scalar3Same_D_size_patterns<int_aarch64_neon_vadddu, ADDddd>;
4801259698Sdimdefm : Neon_Scalar3Same_D_size_patterns<int_aarch64_neon_vsubds, SUBddd>;
4802259698Sdimdefm : Neon_Scalar3Same_D_size_patterns<int_aarch64_neon_vsubdu, SUBddd>;
4803259698Sdim
4804259698Sdim// Scalar Integer Saturating Add (Signed, Unsigned)
4805259698Sdimdefm SQADD : NeonI_Scalar3Same_BHSD_sizes<0b0, 0b00001, "sqadd", 1>;
4806259698Sdimdefm UQADD : NeonI_Scalar3Same_BHSD_sizes<0b1, 0b00001, "uqadd", 1>;
4807259698Sdim
4808259698Sdim// Scalar Integer Saturating Sub (Signed, Unsigned)
4809259698Sdimdefm SQSUB : NeonI_Scalar3Same_BHSD_sizes<0b0, 0b00101, "sqsub", 0>;
4810259698Sdimdefm UQSUB : NeonI_Scalar3Same_BHSD_sizes<0b1, 0b00101, "uqsub", 0>;
4811259698Sdim
4812259698Sdim
4813259698Sdim// Patterns to match llvm.aarch64.* intrinsic for
4814259698Sdim// Scalar Integer Saturating Add, Sub  (Signed, Unsigned)
4815259698Sdimdefm : Neon_Scalar3Same_BHSD_size_patterns<int_arm_neon_vqadds, SQADDbbb,
4816259698Sdim                                           SQADDhhh, SQADDsss, SQADDddd>;
4817259698Sdimdefm : Neon_Scalar3Same_BHSD_size_patterns<int_arm_neon_vqaddu, UQADDbbb,
4818259698Sdim                                           UQADDhhh, UQADDsss, UQADDddd>;
4819259698Sdimdefm : Neon_Scalar3Same_BHSD_size_patterns<int_arm_neon_vqsubs, SQSUBbbb,
4820259698Sdim                                           SQSUBhhh, SQSUBsss, SQSUBddd>;
4821259698Sdimdefm : Neon_Scalar3Same_BHSD_size_patterns<int_arm_neon_vqsubu, UQSUBbbb,
4822259698Sdim                                           UQSUBhhh, UQSUBsss, UQSUBddd>;
4823259698Sdim
4824259698Sdim// Scalar Integer Saturating Doubling Multiply Half High
4825259698Sdimdefm SQDMULH : NeonI_Scalar3Same_HS_sizes<0b0, 0b10110, "sqdmulh", 1>;
4826259698Sdim
4827259698Sdim// Scalar Integer Saturating Rounding Doubling Multiply Half High
4828259698Sdimdefm SQRDMULH : NeonI_Scalar3Same_HS_sizes<0b1, 0b10110, "sqrdmulh", 1>;
4829259698Sdim
4830259698Sdim// Patterns to match llvm.arm.* intrinsic for
4831259698Sdim// Scalar Integer Saturating Doubling Multiply Half High and
4832259698Sdim// Scalar Integer Saturating Rounding Doubling Multiply Half High
4833259698Sdimdefm : Neon_Scalar3Same_HS_size_patterns<int_arm_neon_vqdmulh, SQDMULHhhh,
4834259698Sdim                                                               SQDMULHsss>;
4835259698Sdimdefm : Neon_Scalar3Same_HS_size_patterns<int_arm_neon_vqrdmulh, SQRDMULHhhh,
4836259698Sdim                                                                SQRDMULHsss>;
4837259698Sdim
4838259698Sdim// Scalar Floating-point Multiply Extended
4839259698Sdimdefm FMULX : NeonI_Scalar3Same_SD_sizes<0b0, 0b0, 0b11011, "fmulx", 1>;
4840259698Sdim
4841259698Sdim// Scalar Floating-point Reciprocal Step
4842259698Sdimdefm FRECPS : NeonI_Scalar3Same_SD_sizes<0b0, 0b0, 0b11111, "frecps", 0>;
4843259698Sdim
4844259698Sdim// Scalar Floating-point Reciprocal Square Root Step
4845259698Sdimdefm FRSQRTS : NeonI_Scalar3Same_SD_sizes<0b0, 0b1, 0b11111, "frsqrts", 0>;
4846259698Sdim
4847259698Sdim// Patterns to match llvm.arm.* intrinsic for
4848259698Sdim// Scalar Floating-point Reciprocal Step and
4849259698Sdim// Scalar Floating-point Reciprocal Square Root Step
4850259698Sdimdefm : Neon_Scalar3Same_SD_size_patterns<int_arm_neon_vrecps, FRECPSsss,
4851259698Sdim                                                              FRECPSddd>;
4852259698Sdimdefm : Neon_Scalar3Same_SD_size_patterns<int_arm_neon_vrsqrts, FRSQRTSsss,
4853259698Sdim                                                               FRSQRTSddd>;
4854259698Sdim
4855259698Sdimdef : Pat<(v1f64 (fsqrt (v1f64 FPR64:$Rn))), (FSQRTdd FPR64:$Rn)>;
4856259698Sdim
4857259698Sdim// Patterns to match llvm.aarch64.* intrinsic for
4858259698Sdim// Scalar Floating-point Multiply Extended,
4859259698Sdimmulticlass Neon_Scalar3Same_MULX_SD_size_patterns<SDPatternOperator opnode,
4860259698Sdim                                                  Instruction INSTS,
4861259698Sdim                                                  Instruction INSTD> {
4862259698Sdim  def : Pat<(f32 (opnode (f32 FPR32:$Rn), (f32 FPR32:$Rm))),
4863259698Sdim            (INSTS FPR32:$Rn, FPR32:$Rm)>;
4864259698Sdim  def : Pat<(f64 (opnode (f64 FPR64:$Rn), (f64 FPR64:$Rm))),
4865259698Sdim            (INSTD FPR64:$Rn, FPR64:$Rm)>;
4866259698Sdim}
4867259698Sdim
4868259698Sdimdefm : Neon_Scalar3Same_MULX_SD_size_patterns<int_aarch64_neon_vmulx,
4869259698Sdim                                              FMULXsss,FMULXddd>;
4870259698Sdim
4871259698Sdim// Scalar Integer Shift Left (Signed, Unsigned)
4872259698Sdimdef SSHLddd : NeonI_Scalar3Same_D_size<0b0, 0b01000, "sshl">;
4873259698Sdimdef USHLddd : NeonI_Scalar3Same_D_size<0b1, 0b01000, "ushl">;
4874259698Sdim
4875259698Sdim// Patterns to match llvm.arm.* intrinsic for
4876259698Sdim// Scalar Integer Shift Left (Signed, Unsigned)
4877259698Sdimdefm : Neon_Scalar3Same_D_size_patterns<int_arm_neon_vshifts, SSHLddd>;
4878259698Sdimdefm : Neon_Scalar3Same_D_size_patterns<int_arm_neon_vshiftu, USHLddd>;
4879259698Sdim
4880259698Sdim// Patterns to match llvm.aarch64.* intrinsic for
4881259698Sdim// Scalar Integer Shift Left (Signed, Unsigned)
4882259698Sdimdefm : Neon_Scalar3Same_D_size_patterns<int_aarch64_neon_vshlds, SSHLddd>;
4883259698Sdimdefm : Neon_Scalar3Same_D_size_patterns<int_aarch64_neon_vshldu, USHLddd>;
4884259698Sdim
4885259698Sdim// Scalar Integer Saturating Shift Left (Signed, Unsigned)
4886259698Sdimdefm SQSHL: NeonI_Scalar3Same_BHSD_sizes<0b0, 0b01001, "sqshl", 0>;
4887259698Sdimdefm UQSHL: NeonI_Scalar3Same_BHSD_sizes<0b1, 0b01001, "uqshl", 0>;
4888259698Sdim
4889259698Sdim// Patterns to match llvm.aarch64.* intrinsic for
4890259698Sdim// Scalar  Integer Saturating Shift Letf (Signed, Unsigned)
4891259698Sdimdefm : Neon_Scalar3Same_BHSD_size_patterns<int_aarch64_neon_vqshls, SQSHLbbb,
4892259698Sdim                                           SQSHLhhh, SQSHLsss, SQSHLddd>;
4893259698Sdimdefm : Neon_Scalar3Same_BHSD_size_patterns<int_aarch64_neon_vqshlu, UQSHLbbb,
4894259698Sdim                                           UQSHLhhh, UQSHLsss, UQSHLddd>;
4895259698Sdim
4896259698Sdim// Patterns to match llvm.arm.* intrinsic for
4897259698Sdim// Scalar  Integer Saturating Shift Letf (Signed, Unsigned)
4898259698Sdimdefm : Neon_Scalar3Same_D_size_patterns<int_arm_neon_vqshifts, SQSHLddd>;
4899259698Sdimdefm : Neon_Scalar3Same_D_size_patterns<int_arm_neon_vqshiftu, UQSHLddd>;
4900259698Sdim
4901259698Sdim// Scalar Integer Rounding Shift Left (Signed, Unsigned)
4902259698Sdimdef SRSHLddd: NeonI_Scalar3Same_D_size<0b0, 0b01010, "srshl">;
4903259698Sdimdef URSHLddd: NeonI_Scalar3Same_D_size<0b1, 0b01010, "urshl">;
4904259698Sdim
4905259698Sdim// Patterns to match llvm.aarch64.* intrinsic for
4906259698Sdim// Scalar Integer Rounding Shift Left (Signed, Unsigned)
4907259698Sdimdefm : Neon_Scalar3Same_D_size_patterns<int_aarch64_neon_vrshlds, SRSHLddd>;
4908259698Sdimdefm : Neon_Scalar3Same_D_size_patterns<int_aarch64_neon_vrshldu, URSHLddd>;
4909259698Sdim
4910259698Sdim// Patterns to match llvm.arm.* intrinsic for
4911259698Sdim// Scalar Integer Rounding Shift Left (Signed, Unsigned)
4912259698Sdimdefm : Neon_Scalar3Same_D_size_patterns<int_arm_neon_vrshifts, SRSHLddd>;
4913259698Sdimdefm : Neon_Scalar3Same_D_size_patterns<int_arm_neon_vrshiftu, URSHLddd>;
4914259698Sdim
4915259698Sdim// Scalar Integer Saturating Rounding Shift Left (Signed, Unsigned)
4916259698Sdimdefm SQRSHL: NeonI_Scalar3Same_BHSD_sizes<0b0, 0b01011, "sqrshl", 0>;
4917259698Sdimdefm UQRSHL: NeonI_Scalar3Same_BHSD_sizes<0b1, 0b01011, "uqrshl", 0>;
4918259698Sdim
4919259698Sdim// Patterns to match llvm.aarch64.* intrinsic for
4920259698Sdim// Scalar Integer Saturating Rounding Shift Left (Signed, Unsigned)
4921259698Sdimdefm : Neon_Scalar3Same_BHSD_size_patterns<int_aarch64_neon_vqrshls, SQRSHLbbb,
4922259698Sdim                                           SQRSHLhhh, SQRSHLsss, SQRSHLddd>;
4923259698Sdimdefm : Neon_Scalar3Same_BHSD_size_patterns<int_aarch64_neon_vqrshlu, UQRSHLbbb,
4924259698Sdim                                           UQRSHLhhh, UQRSHLsss, UQRSHLddd>;
4925259698Sdim
4926259698Sdim// Patterns to match llvm.arm.* intrinsic for
4927259698Sdim// Scalar Integer Saturating Rounding Shift Left (Signed, Unsigned)
4928259698Sdimdefm : Neon_Scalar3Same_D_size_patterns<int_arm_neon_vqrshifts, SQRSHLddd>;
4929259698Sdimdefm : Neon_Scalar3Same_D_size_patterns<int_arm_neon_vqrshiftu, UQRSHLddd>;
4930259698Sdim
4931259698Sdim// Signed Saturating Doubling Multiply-Add Long
4932259698Sdimdefm SQDMLAL : NeonI_Scalar3Diff_ml_HS_size<0b0, 0b1001, "sqdmlal">;
4933259698Sdimdefm : Neon_Scalar3Diff_ml_HS_size_patterns<int_aarch64_neon_vqdmlal,
4934259698Sdim                                            SQDMLALshh, SQDMLALdss>;
4935259698Sdim
4936259698Sdim// Signed Saturating Doubling Multiply-Subtract Long
4937259698Sdimdefm SQDMLSL : NeonI_Scalar3Diff_ml_HS_size<0b0, 0b1011, "sqdmlsl">;
4938259698Sdimdefm : Neon_Scalar3Diff_ml_HS_size_patterns<int_aarch64_neon_vqdmlsl,
4939259698Sdim                                            SQDMLSLshh, SQDMLSLdss>;
4940259698Sdim
4941259698Sdim// Signed Saturating Doubling Multiply Long
4942259698Sdimdefm SQDMULL : NeonI_Scalar3Diff_HS_size<0b0, 0b1101, "sqdmull">;
4943259698Sdimdefm : Neon_Scalar3Diff_HS_size_patterns<int_arm_neon_vqdmull,
4944259698Sdim                                         SQDMULLshh, SQDMULLdss>;
4945259698Sdim
4946259698Sdim// Scalar Signed Integer Convert To Floating-point
4947259698Sdimdefm SCVTF  : NeonI_Scalar2SameMisc_SD_size<0b0, 0b0, 0b11101, "scvtf">;
4948259698Sdimdefm : Neon_Scalar2SameMisc_cvt_SD_size_patterns<int_aarch64_neon_vcvtf32_s32,
4949259698Sdim                                                 int_aarch64_neon_vcvtf64_s64,
4950259698Sdim                                                 SCVTFss, SCVTFdd>;
4951259698Sdim
4952259698Sdim// Scalar Unsigned Integer Convert To Floating-point
4953259698Sdimdefm UCVTF  : NeonI_Scalar2SameMisc_SD_size<0b1, 0b0, 0b11101, "ucvtf">;
4954259698Sdimdefm : Neon_Scalar2SameMisc_cvt_SD_size_patterns<int_aarch64_neon_vcvtf32_u32,
4955259698Sdim                                                 int_aarch64_neon_vcvtf64_u64,
4956259698Sdim                                                 UCVTFss, UCVTFdd>;
4957259698Sdim
4958259698Sdim// Scalar Floating-point Converts
4959259698Sdimdef FCVTXN : NeonI_Scalar2SameMisc_fcvtxn_D_size<0b1, 0b10110, "fcvtxn">;
4960259698Sdimdef : Neon_Scalar2SameMisc_fcvtxn_D_size_patterns<int_aarch64_neon_fcvtxn,
4961259698Sdim                                                  FCVTXN>;
4962259698Sdim
4963259698Sdimdefm FCVTNS : NeonI_Scalar2SameMisc_SD_size<0b0, 0b0, 0b11010, "fcvtns">;
4964259698Sdimdefm : Neon_Scalar2SameMisc_fcvt_SD_size_patterns<int_aarch64_neon_fcvtns,
4965259698Sdim                                                  FCVTNSss, FCVTNSdd>;
4966259698Sdim
4967259698Sdimdefm FCVTNU : NeonI_Scalar2SameMisc_SD_size<0b1, 0b0, 0b11010, "fcvtnu">;
4968259698Sdimdefm : Neon_Scalar2SameMisc_fcvt_SD_size_patterns<int_aarch64_neon_fcvtnu,
4969259698Sdim                                                  FCVTNUss, FCVTNUdd>;
4970259698Sdim
4971259698Sdimdefm FCVTMS : NeonI_Scalar2SameMisc_SD_size<0b0, 0b0, 0b11011, "fcvtms">;
4972259698Sdimdefm : Neon_Scalar2SameMisc_fcvt_SD_size_patterns<int_aarch64_neon_fcvtms,
4973259698Sdim                                                  FCVTMSss, FCVTMSdd>;
4974259698Sdim
4975259698Sdimdefm FCVTMU : NeonI_Scalar2SameMisc_SD_size<0b1, 0b0, 0b11011, "fcvtmu">;
4976259698Sdimdefm : Neon_Scalar2SameMisc_fcvt_SD_size_patterns<int_aarch64_neon_fcvtmu,
4977259698Sdim                                                  FCVTMUss, FCVTMUdd>;
4978259698Sdim
4979259698Sdimdefm FCVTAS : NeonI_Scalar2SameMisc_SD_size<0b0, 0b0, 0b11100, "fcvtas">;
4980259698Sdimdefm : Neon_Scalar2SameMisc_fcvt_SD_size_patterns<int_aarch64_neon_fcvtas,
4981259698Sdim                                                  FCVTASss, FCVTASdd>;
4982259698Sdim
4983259698Sdimdefm FCVTAU : NeonI_Scalar2SameMisc_SD_size<0b1, 0b0, 0b11100, "fcvtau">;
4984259698Sdimdefm : Neon_Scalar2SameMisc_fcvt_SD_size_patterns<int_aarch64_neon_fcvtau,
4985259698Sdim                                                  FCVTAUss, FCVTAUdd>;
4986259698Sdim
4987259698Sdimdefm FCVTPS : NeonI_Scalar2SameMisc_SD_size<0b0, 0b1, 0b11010, "fcvtps">;
4988259698Sdimdefm : Neon_Scalar2SameMisc_fcvt_SD_size_patterns<int_aarch64_neon_fcvtps,
4989259698Sdim                                                  FCVTPSss, FCVTPSdd>;
4990259698Sdim
4991259698Sdimdefm FCVTPU : NeonI_Scalar2SameMisc_SD_size<0b1, 0b1, 0b11010, "fcvtpu">;
4992259698Sdimdefm : Neon_Scalar2SameMisc_fcvt_SD_size_patterns<int_aarch64_neon_fcvtpu,
4993259698Sdim                                                  FCVTPUss, FCVTPUdd>;
4994259698Sdim
4995259698Sdimdefm FCVTZS : NeonI_Scalar2SameMisc_SD_size<0b0, 0b1, 0b11011, "fcvtzs">;
4996259698Sdimdefm : Neon_Scalar2SameMisc_fcvt_SD_size_patterns<int_aarch64_neon_fcvtzs,
4997259698Sdim                                                  FCVTZSss, FCVTZSdd>;
4998259698Sdim
4999259698Sdimdefm FCVTZU : NeonI_Scalar2SameMisc_SD_size<0b1, 0b1, 0b11011, "fcvtzu">;
5000259698Sdimdefm : Neon_Scalar2SameMisc_fcvt_SD_size_patterns<int_aarch64_neon_fcvtzu,
5001259698Sdim                                                  FCVTZUss, FCVTZUdd>;
5002259698Sdim
5003259698Sdim// Patterns For Convert Instructions Between v1f64 and v1i64
5004259698Sdimclass Neon_Scalar2SameMisc_cvtf_v1f64_pattern<SDPatternOperator opnode,
5005259698Sdim                                              Instruction INST>
5006259698Sdim    : Pat<(v1f64 (opnode (v1i64 FPR64:$Rn))), (INST FPR64:$Rn)>;
5007259698Sdim
5008259698Sdimclass Neon_Scalar2SameMisc_fcvt_v1f64_pattern<SDPatternOperator opnode,
5009259698Sdim                                              Instruction INST>
5010259698Sdim    : Pat<(v1i64 (opnode (v1f64 FPR64:$Rn))), (INST FPR64:$Rn)>;
5011259698Sdim
5012259698Sdimdef : Neon_Scalar2SameMisc_cvtf_v1f64_pattern<sint_to_fp, SCVTFdd>;
5013259698Sdimdef : Neon_Scalar2SameMisc_cvtf_v1f64_pattern<uint_to_fp, UCVTFdd>;
5014259698Sdim
5015259698Sdimdef : Neon_Scalar2SameMisc_fcvt_v1f64_pattern<fp_to_sint, FCVTZSdd>;
5016259698Sdimdef : Neon_Scalar2SameMisc_fcvt_v1f64_pattern<fp_to_uint, FCVTZUdd>;
5017259698Sdim
5018259698Sdim// Scalar Floating-point Reciprocal Estimate
5019259698Sdimdefm FRECPE : NeonI_Scalar2SameMisc_SD_size<0b0, 0b1, 0b11101, "frecpe">;
5020259698Sdimdefm : Neon_Scalar2SameMisc_SD_size_patterns<int_arm_neon_vrecpe,
5021259698Sdim                                             FRECPEss, FRECPEdd>;
5022259698Sdim
5023259698Sdim// Scalar Floating-point Reciprocal Exponent
5024259698Sdimdefm FRECPX : NeonI_Scalar2SameMisc_SD_size<0b0, 0b1, 0b11111, "frecpx">;
5025259698Sdimdefm : Neon_Scalar2SameMisc_SD_size_patterns<int_aarch64_neon_vrecpx,
5026259698Sdim                                             FRECPXss, FRECPXdd>;
5027259698Sdim
5028259698Sdim// Scalar Floating-point Reciprocal Square Root Estimate
5029259698Sdimdefm FRSQRTE: NeonI_Scalar2SameMisc_SD_size<0b1, 0b1, 0b11101, "frsqrte">;
5030259698Sdimdefm : Neon_Scalar2SameMisc_SD_size_patterns<int_arm_neon_vrsqrte,
5031259698Sdim                                             FRSQRTEss, FRSQRTEdd>;
5032259698Sdim
5033259698Sdim// Scalar Floating-point Round
5034259698Sdimclass Neon_ScalarFloatRound_pattern<SDPatternOperator opnode, Instruction INST>
5035259698Sdim    : Pat<(v1f64 (opnode (v1f64 FPR64:$Rn))), (INST FPR64:$Rn)>;
5036259698Sdim
5037259698Sdimdef : Neon_ScalarFloatRound_pattern<fceil, FRINTPdd>;
5038259698Sdimdef : Neon_ScalarFloatRound_pattern<ffloor, FRINTMdd>;
5039259698Sdimdef : Neon_ScalarFloatRound_pattern<ftrunc, FRINTZdd>;
5040259698Sdimdef : Neon_ScalarFloatRound_pattern<frint, FRINTXdd>;
5041259698Sdimdef : Neon_ScalarFloatRound_pattern<fnearbyint, FRINTIdd>;
5042259698Sdimdef : Neon_ScalarFloatRound_pattern<frnd, FRINTAdd>;
5043259698Sdimdef : Neon_ScalarFloatRound_pattern<int_aarch64_neon_frintn, FRINTNdd>;
5044259698Sdim
5045259698Sdim// Scalar Integer Compare
5046259698Sdim
5047259698Sdim// Scalar Compare Bitwise Equal
5048259698Sdimdef CMEQddd: NeonI_Scalar3Same_D_size<0b1, 0b10001, "cmeq">;
5049259698Sdimdef : Neon_Scalar3Same_cmp_D_size_patterns<int_aarch64_neon_vceq, CMEQddd>;
5050259698Sdim
5051259698Sdimclass Neon_Scalar3Same_cmp_D_size_v1_patterns<SDPatternOperator opnode,
5052259698Sdim                                              Instruction INSTD,
5053259698Sdim                                              CondCode CC>
5054259698Sdim  : Pat<(v1i64 (opnode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm), CC)),
5055259698Sdim        (INSTD FPR64:$Rn, FPR64:$Rm)>;
5056259698Sdim
5057259698Sdimdef : Neon_Scalar3Same_cmp_D_size_v1_patterns<Neon_cmp, CMEQddd, SETEQ>;
5058259698Sdim
5059259698Sdim// Scalar Compare Signed Greather Than Or Equal
5060259698Sdimdef CMGEddd: NeonI_Scalar3Same_D_size<0b0, 0b00111, "cmge">;
5061259698Sdimdef : Neon_Scalar3Same_cmp_D_size_patterns<int_aarch64_neon_vcge, CMGEddd>;
5062259698Sdimdef : Neon_Scalar3Same_cmp_D_size_v1_patterns<Neon_cmp, CMGEddd, SETGE>;
5063259698Sdim
5064259698Sdim// Scalar Compare Unsigned Higher Or Same
5065259698Sdimdef CMHSddd: NeonI_Scalar3Same_D_size<0b1, 0b00111, "cmhs">;
5066259698Sdimdef : Neon_Scalar3Same_cmp_D_size_patterns<int_aarch64_neon_vchs, CMHSddd>;
5067259698Sdimdef : Neon_Scalar3Same_cmp_D_size_v1_patterns<Neon_cmp, CMHSddd, SETUGE>;
5068259698Sdim
5069259698Sdim// Scalar Compare Unsigned Higher
5070259698Sdimdef CMHIddd: NeonI_Scalar3Same_D_size<0b1, 0b00110, "cmhi">;
5071259698Sdimdef : Neon_Scalar3Same_cmp_D_size_patterns<int_aarch64_neon_vchi, CMHIddd>;
5072259698Sdimdef : Neon_Scalar3Same_cmp_D_size_v1_patterns<Neon_cmp, CMHIddd, SETUGT>;
5073259698Sdim
5074259698Sdim// Scalar Compare Signed Greater Than
5075259698Sdimdef CMGTddd: NeonI_Scalar3Same_D_size<0b0, 0b00110, "cmgt">;
5076259698Sdimdef : Neon_Scalar3Same_cmp_D_size_patterns<int_aarch64_neon_vcgt, CMGTddd>;
5077259698Sdimdef : Neon_Scalar3Same_cmp_D_size_v1_patterns<Neon_cmp, CMGTddd, SETGT>;
5078259698Sdim
5079259698Sdim// Scalar Compare Bitwise Test Bits
5080259698Sdimdef CMTSTddd: NeonI_Scalar3Same_D_size<0b0, 0b10001, "cmtst">;
5081259698Sdimdef : Neon_Scalar3Same_cmp_D_size_patterns<int_aarch64_neon_vtstd, CMTSTddd>;
5082259698Sdimdef : Neon_Scalar3Same_cmp_D_size_patterns<Neon_tst, CMTSTddd>;
5083259698Sdim
5084259698Sdim// Scalar Compare Bitwise Equal To Zero
5085259698Sdimdef CMEQddi: NeonI_Scalar2SameMisc_cmpz_D_size<0b0, 0b01001, "cmeq">;
5086259698Sdimdef : Neon_Scalar2SameMisc_cmpz_D_size_patterns<int_aarch64_neon_vceq,
5087259698Sdim                                                CMEQddi>;
5088259698Sdimdef : Neon_Scalar2SameMisc_cmpz_D_V1_size_patterns<SETEQ, CMEQddi>;
5089259698Sdim
5090259698Sdim// Scalar Compare Signed Greather Than Or Equal To Zero
5091259698Sdimdef CMGEddi: NeonI_Scalar2SameMisc_cmpz_D_size<0b1, 0b01000, "cmge">;
5092259698Sdimdef : Neon_Scalar2SameMisc_cmpz_D_size_patterns<int_aarch64_neon_vcge,
5093259698Sdim                                                CMGEddi>;
5094259698Sdimdef : Neon_Scalar2SameMisc_cmpz_D_V1_size_patterns<SETGE, CMGEddi>;
5095259698Sdim
5096259698Sdim// Scalar Compare Signed Greater Than Zero
5097259698Sdimdef CMGTddi: NeonI_Scalar2SameMisc_cmpz_D_size<0b0, 0b01000, "cmgt">;
5098259698Sdimdef : Neon_Scalar2SameMisc_cmpz_D_size_patterns<int_aarch64_neon_vcgt,
5099259698Sdim                                                CMGTddi>;
5100259698Sdimdef : Neon_Scalar2SameMisc_cmpz_D_V1_size_patterns<SETGT, CMGTddi>;
5101259698Sdim
5102259698Sdim// Scalar Compare Signed Less Than Or Equal To Zero
5103259698Sdimdef CMLEddi: NeonI_Scalar2SameMisc_cmpz_D_size<0b1, 0b01001, "cmle">;
5104259698Sdimdef : Neon_Scalar2SameMisc_cmpz_D_size_patterns<int_aarch64_neon_vclez,
5105259698Sdim                                                CMLEddi>;
5106259698Sdimdef : Neon_Scalar2SameMisc_cmpz_D_V1_size_patterns<SETLE, CMLEddi>;
5107259698Sdim
5108259698Sdim// Scalar Compare Less Than Zero
5109259698Sdimdef CMLTddi: NeonI_Scalar2SameMisc_cmpz_D_size<0b0, 0b01010, "cmlt">;
5110259698Sdimdef : Neon_Scalar2SameMisc_cmpz_D_size_patterns<int_aarch64_neon_vcltz,
5111259698Sdim                                                CMLTddi>;
5112259698Sdimdef : Neon_Scalar2SameMisc_cmpz_D_V1_size_patterns<SETLT, CMLTddi>;
5113259698Sdim
5114259698Sdim// Scalar Floating-point Compare
5115259698Sdim
5116259698Sdim// Scalar Floating-point Compare Mask Equal
5117259698Sdimdefm FCMEQ: NeonI_Scalar3Same_SD_sizes<0b0, 0b0, 0b11100, "fcmeq">;
5118259698Sdimdefm : Neon_Scalar3Same_cmp_SD_size_patterns<int_aarch64_neon_vceq,
5119259698Sdim                                             FCMEQsss, FCMEQddd>;
5120259698Sdimdef : Neon_Scalar3Same_cmp_V1_D_size_patterns<SETEQ, FCMEQddd>;
5121259698Sdim
5122259698Sdim// Scalar Floating-point Compare Mask Equal To Zero
5123259698Sdimdefm FCMEQZ: NeonI_Scalar2SameMisc_cmpz_SD_size<0b0, 0b01101, "fcmeq">;
5124259698Sdimdefm : Neon_Scalar2SameMisc_cmpz_SD_size_patterns<int_aarch64_neon_vceq,
5125259698Sdim                                                  FCMEQZssi, FCMEQZddi>;
5126259698Sdimdef : Pat<(v1i64 (Neon_cmpz (v1f64 FPR64:$Rn), (f32 fpz32:$FPImm), SETEQ)),
5127259698Sdim          (FCMEQZddi FPR64:$Rn, fpz32:$FPImm)>;
5128259698Sdim
5129259698Sdim// Scalar Floating-point Compare Mask Greater Than Or Equal
5130259698Sdimdefm FCMGE: NeonI_Scalar3Same_SD_sizes<0b1, 0b0, 0b11100, "fcmge">;
5131259698Sdimdefm : Neon_Scalar3Same_cmp_SD_size_patterns<int_aarch64_neon_vcge,
5132259698Sdim                                             FCMGEsss, FCMGEddd>;
5133259698Sdimdef : Neon_Scalar3Same_cmp_V1_D_size_patterns<SETGE, FCMGEddd>;
5134259698Sdim
5135259698Sdim// Scalar Floating-point Compare Mask Greater Than Or Equal To Zero
5136259698Sdimdefm FCMGEZ: NeonI_Scalar2SameMisc_cmpz_SD_size<0b1, 0b01100, "fcmge">;
5137259698Sdimdefm : Neon_Scalar2SameMisc_cmpz_SD_size_patterns<int_aarch64_neon_vcge,
5138259698Sdim                                                  FCMGEZssi, FCMGEZddi>;
5139259698Sdim
5140259698Sdim// Scalar Floating-point Compare Mask Greather Than
5141259698Sdimdefm FCMGT: NeonI_Scalar3Same_SD_sizes<0b1, 0b1, 0b11100, "fcmgt">;
5142259698Sdimdefm : Neon_Scalar3Same_cmp_SD_size_patterns<int_aarch64_neon_vcgt,
5143259698Sdim                                             FCMGTsss, FCMGTddd>;
5144259698Sdimdef : Neon_Scalar3Same_cmp_V1_D_size_patterns<SETGT, FCMGTddd>;
5145259698Sdim
5146259698Sdim// Scalar Floating-point Compare Mask Greather Than Zero
5147259698Sdimdefm FCMGTZ: NeonI_Scalar2SameMisc_cmpz_SD_size<0b0, 0b01100, "fcmgt">;
5148259698Sdimdefm : Neon_Scalar2SameMisc_cmpz_SD_size_patterns<int_aarch64_neon_vcgt,
5149259698Sdim                                                  FCMGTZssi, FCMGTZddi>;
5150259698Sdim
5151259698Sdim// Scalar Floating-point Compare Mask Less Than Or Equal To Zero
5152259698Sdimdefm FCMLEZ: NeonI_Scalar2SameMisc_cmpz_SD_size<0b1, 0b01101, "fcmle">;
5153259698Sdimdefm : Neon_Scalar2SameMisc_cmpz_SD_size_patterns<int_aarch64_neon_vclez,
5154259698Sdim                                                  FCMLEZssi, FCMLEZddi>;
5155259698Sdim
5156259698Sdim// Scalar Floating-point Compare Mask Less Than Zero
5157259698Sdimdefm FCMLTZ: NeonI_Scalar2SameMisc_cmpz_SD_size<0b0, 0b01110, "fcmlt">;
5158259698Sdimdefm : Neon_Scalar2SameMisc_cmpz_SD_size_patterns<int_aarch64_neon_vcltz,
5159259698Sdim                                                  FCMLTZssi, FCMLTZddi>;
5160259698Sdim
5161259698Sdim// Scalar Floating-point Absolute Compare Mask Greater Than Or Equal
5162259698Sdimdefm FACGE: NeonI_Scalar3Same_SD_sizes<0b1, 0b0, 0b11101, "facge">;
5163259698Sdimdefm : Neon_Scalar3Same_cmp_SD_size_patterns<int_aarch64_neon_vcage,
5164259698Sdim                                             FACGEsss, FACGEddd>;
5165259698Sdim
5166259698Sdim// Scalar Floating-point Absolute Compare Mask Greater Than
5167259698Sdimdefm FACGT: NeonI_Scalar3Same_SD_sizes<0b1, 0b1, 0b11101, "facgt">;
5168259698Sdimdefm : Neon_Scalar3Same_cmp_SD_size_patterns<int_aarch64_neon_vcagt,
5169259698Sdim                                             FACGTsss, FACGTddd>;
5170259698Sdim
5171259698Sdim// Scakar Floating-point Absolute Difference
5172259698Sdimdefm FABD: NeonI_Scalar3Same_SD_sizes<0b1, 0b1, 0b11010, "fabd">;
5173259698Sdimdefm : Neon_Scalar3Same_SD_size_patterns<int_aarch64_neon_vabd,
5174259698Sdim                                         FABDsss, FABDddd>;
5175259698Sdim
5176259698Sdim// Scalar Absolute Value
5177259698Sdimdefm ABS : NeonI_Scalar2SameMisc_D_size<0b0, 0b01011, "abs">;
5178259698Sdimdefm : Neon_Scalar2SameMisc_D_size_patterns<int_aarch64_neon_vabs, ABSdd>;
5179259698Sdim
5180259698Sdim// Scalar Signed Saturating Absolute Value
5181259698Sdimdefm SQABS : NeonI_Scalar2SameMisc_BHSD_size<0b0, 0b00111, "sqabs">;
5182259698Sdimdefm : Neon_Scalar2SameMisc_BHSD_size_patterns<int_arm_neon_vqabs,
5183259698Sdim                                               SQABSbb, SQABShh, SQABSss, SQABSdd>;
5184259698Sdim
5185259698Sdim// Scalar Negate
5186259698Sdimdefm NEG : NeonI_Scalar2SameMisc_D_size<0b1, 0b01011, "neg">;
5187259698Sdimdefm : Neon_Scalar2SameMisc_D_size_patterns<int_aarch64_neon_vneg, NEGdd>;
5188259698Sdim
5189259698Sdim// Scalar Signed Saturating Negate
5190259698Sdimdefm SQNEG : NeonI_Scalar2SameMisc_BHSD_size<0b1, 0b00111, "sqneg">;
5191259698Sdimdefm : Neon_Scalar2SameMisc_BHSD_size_patterns<int_arm_neon_vqneg,
5192259698Sdim                                               SQNEGbb, SQNEGhh, SQNEGss, SQNEGdd>;
5193259698Sdim
5194259698Sdim// Scalar Signed Saturating Accumulated of Unsigned Value
5195259698Sdimdefm SUQADD : NeonI_Scalar2SameMisc_accum_BHSD_size<0b0, 0b00011, "suqadd">;
5196259698Sdimdefm : Neon_Scalar2SameMisc_accum_BHSD_size_patterns<int_aarch64_neon_vuqadd,
5197259698Sdim                                                     SUQADDbb, SUQADDhh,
5198259698Sdim                                                     SUQADDss, SUQADDdd>;
5199259698Sdim
5200259698Sdim// Scalar Unsigned Saturating Accumulated of Signed Value
5201259698Sdimdefm USQADD : NeonI_Scalar2SameMisc_accum_BHSD_size<0b1, 0b00011, "usqadd">;
5202259698Sdimdefm : Neon_Scalar2SameMisc_accum_BHSD_size_patterns<int_aarch64_neon_vsqadd,
5203259698Sdim                                                     USQADDbb, USQADDhh,
5204259698Sdim                                                     USQADDss, USQADDdd>;
5205259698Sdim
5206259698Sdimdef : Pat<(v1i64 (int_aarch64_neon_suqadd (v1i64 FPR64:$Src),
5207259698Sdim                                          (v1i64 FPR64:$Rn))),
5208259698Sdim          (SUQADDdd FPR64:$Src, FPR64:$Rn)>;
5209259698Sdim
5210259698Sdimdef : Pat<(v1i64 (int_aarch64_neon_usqadd (v1i64 FPR64:$Src),
5211259698Sdim                                          (v1i64 FPR64:$Rn))),
5212259698Sdim          (USQADDdd FPR64:$Src, FPR64:$Rn)>;
5213259698Sdim
5214259698Sdimdef : Pat<(v1i64 (int_arm_neon_vabs (v1i64 FPR64:$Rn))),
5215259698Sdim          (ABSdd FPR64:$Rn)>;
5216259698Sdim
5217259698Sdimdef : Pat<(v1i64 (int_arm_neon_vqabs (v1i64 FPR64:$Rn))),
5218259698Sdim          (SQABSdd FPR64:$Rn)>;
5219259698Sdim
5220259698Sdimdef : Pat<(v1i64 (int_arm_neon_vqneg (v1i64 FPR64:$Rn))),
5221259698Sdim          (SQNEGdd FPR64:$Rn)>;
5222259698Sdim
5223259698Sdimdef : Pat<(v1i64 (sub (v1i64 (bitconvert (v8i8 Neon_AllZero))),
5224259698Sdim                      (v1i64 FPR64:$Rn))),
5225259698Sdim          (NEGdd FPR64:$Rn)>;
5226259698Sdim
5227259698Sdim// Scalar Signed Saturating Extract Unsigned Narrow
5228259698Sdimdefm SQXTUN : NeonI_Scalar2SameMisc_narrow_HSD_size<0b1, 0b10010, "sqxtun">;
5229259698Sdimdefm : Neon_Scalar2SameMisc_narrow_HSD_size_patterns<int_arm_neon_vqmovnsu,
5230259698Sdim                                                     SQXTUNbh, SQXTUNhs,
5231259698Sdim                                                     SQXTUNsd>;
5232259698Sdim
5233259698Sdim// Scalar Signed Saturating Extract Narrow
5234259698Sdimdefm SQXTN  : NeonI_Scalar2SameMisc_narrow_HSD_size<0b0, 0b10100, "sqxtn">;
5235259698Sdimdefm : Neon_Scalar2SameMisc_narrow_HSD_size_patterns<int_arm_neon_vqmovns,
5236259698Sdim                                                     SQXTNbh, SQXTNhs,
5237259698Sdim                                                     SQXTNsd>;
5238259698Sdim
5239259698Sdim// Scalar Unsigned Saturating Extract Narrow
5240259698Sdimdefm UQXTN  : NeonI_Scalar2SameMisc_narrow_HSD_size<0b1, 0b10100, "uqxtn">;
5241259698Sdimdefm : Neon_Scalar2SameMisc_narrow_HSD_size_patterns<int_arm_neon_vqmovnu,
5242259698Sdim                                                     UQXTNbh, UQXTNhs,
5243259698Sdim                                                     UQXTNsd>;
5244259698Sdim
5245259698Sdim// Scalar Reduce Pairwise
5246259698Sdim
5247259698Sdimmulticlass NeonI_ScalarPair_D_sizes<bit u, bit size, bits<5> opcode,
5248259698Sdim                                     string asmop, bit Commutable = 0> {
5249259698Sdim  let isCommutable = Commutable in {
5250259698Sdim    def _D_2D : NeonI_ScalarPair<u, {size, 0b1}, opcode,
5251259698Sdim                                (outs FPR64:$Rd), (ins VPR128:$Rn),
5252259698Sdim                                !strconcat(asmop, "\t$Rd, $Rn.2d"),
5253259698Sdim                                [],
5254259698Sdim                                NoItinerary>;
5255259698Sdim  }
5256259698Sdim}
5257259698Sdim
5258259698Sdimmulticlass NeonI_ScalarPair_SD_sizes<bit u, bit size, bits<5> opcode,
5259259698Sdim                                     string asmop, bit Commutable = 0>
5260259698Sdim  : NeonI_ScalarPair_D_sizes<u, size, opcode, asmop, Commutable> {
5261259698Sdim  let isCommutable = Commutable in {
5262259698Sdim    def _S_2S : NeonI_ScalarPair<u, {size, 0b0}, opcode,
5263259698Sdim                                (outs FPR32:$Rd), (ins VPR64:$Rn),
5264259698Sdim                                !strconcat(asmop, "\t$Rd, $Rn.2s"),
5265259698Sdim                                [],
5266259698Sdim                                NoItinerary>;
5267259698Sdim  }
5268259698Sdim}
5269259698Sdim
5270259698Sdim// Scalar Reduce Addition Pairwise (Integer) with
5271259698Sdim// Pattern to match llvm.arm.* intrinsic
5272259698Sdimdefm ADDPvv : NeonI_ScalarPair_D_sizes<0b0, 0b1, 0b11011, "addp", 0>;
5273259698Sdim
5274259698Sdim// Pattern to match llvm.aarch64.* intrinsic for
5275259698Sdim// Scalar Reduce Addition Pairwise (Integer)
5276259698Sdimdef : Pat<(v1i64 (int_aarch64_neon_vpadd (v2i64 VPR128:$Rn))),
5277259698Sdim          (ADDPvv_D_2D VPR128:$Rn)>;
5278259698Sdimdef : Pat<(v1i64 (int_aarch64_neon_vaddv (v2i64 VPR128:$Rn))),
5279259698Sdim          (ADDPvv_D_2D VPR128:$Rn)>;
5280259698Sdim
5281259698Sdim// Scalar Reduce Addition Pairwise (Floating Point)
5282259698Sdimdefm FADDPvv : NeonI_ScalarPair_SD_sizes<0b1, 0b0, 0b01101, "faddp", 0>;
5283259698Sdim
5284259698Sdim// Scalar Reduce Maximum Pairwise (Floating Point)
5285259698Sdimdefm FMAXPvv : NeonI_ScalarPair_SD_sizes<0b1, 0b0, 0b01111, "fmaxp", 0>;
5286259698Sdim
5287259698Sdim// Scalar Reduce Minimum Pairwise (Floating Point)
5288259698Sdimdefm FMINPvv : NeonI_ScalarPair_SD_sizes<0b1, 0b1, 0b01111, "fminp", 0>;
5289259698Sdim
5290259698Sdim// Scalar Reduce maxNum Pairwise (Floating Point)
5291259698Sdimdefm FMAXNMPvv : NeonI_ScalarPair_SD_sizes<0b1, 0b0, 0b01100, "fmaxnmp", 0>;
5292259698Sdim
5293259698Sdim// Scalar Reduce minNum Pairwise (Floating Point)
5294259698Sdimdefm FMINNMPvv : NeonI_ScalarPair_SD_sizes<0b1, 0b1, 0b01100, "fminnmp", 0>;
5295259698Sdim
5296259698Sdimmulticlass Neon_ScalarPair_SD_size_patterns<SDPatternOperator opnodeS,
5297259698Sdim                                            SDPatternOperator opnodeD,
5298259698Sdim                                            Instruction INSTS,
5299259698Sdim                                            Instruction INSTD> {
5300259698Sdim  def : Pat<(v1f32 (opnodeS (v2f32 VPR64:$Rn))),
5301259698Sdim            (INSTS VPR64:$Rn)>;
5302259698Sdim  def : Pat<(v1f64 (opnodeD (v2f64 VPR128:$Rn))),
5303259698Sdim            (INSTD VPR128:$Rn)>;
5304259698Sdim}
5305259698Sdim
5306259698Sdim// Patterns to match llvm.aarch64.* intrinsic for
5307259698Sdim// Scalar Reduce Add, Max, Min, MaxiNum, MinNum Pairwise (Floating Point)
5308259698Sdimdefm : Neon_ScalarPair_SD_size_patterns<int_aarch64_neon_vpfadd,
5309259698Sdim  int_aarch64_neon_vpfaddq, FADDPvv_S_2S, FADDPvv_D_2D>;
5310259698Sdim
5311259698Sdimdefm : Neon_ScalarPair_SD_size_patterns<int_aarch64_neon_vpmax,
5312259698Sdim  int_aarch64_neon_vpmaxq, FMAXPvv_S_2S, FMAXPvv_D_2D>;
5313259698Sdim
5314259698Sdimdefm : Neon_ScalarPair_SD_size_patterns<int_aarch64_neon_vpmin,
5315259698Sdim  int_aarch64_neon_vpminq, FMINPvv_S_2S, FMINPvv_D_2D>;
5316259698Sdim
5317259698Sdimdefm : Neon_ScalarPair_SD_size_patterns<int_aarch64_neon_vpfmaxnm,
5318259698Sdim  int_aarch64_neon_vpfmaxnmq, FMAXNMPvv_S_2S, FMAXNMPvv_D_2D>;
5319259698Sdim
5320259698Sdimdefm : Neon_ScalarPair_SD_size_patterns<int_aarch64_neon_vpfminnm,
5321259698Sdim  int_aarch64_neon_vpfminnmq, FMINNMPvv_S_2S, FMINNMPvv_D_2D>;
5322259698Sdim
5323259698Sdimdefm : Neon_ScalarPair_SD_size_patterns<int_aarch64_neon_vaddv,
5324259698Sdim    int_aarch64_neon_vaddv, FADDPvv_S_2S, FADDPvv_D_2D>;
5325259698Sdim
5326259698Sdimdef : Pat<(v1f32 (int_aarch64_neon_vaddv (v4f32 VPR128:$Rn))),
5327259698Sdim          (FADDPvv_S_2S (v2f32
5328259698Sdim               (EXTRACT_SUBREG
5329259698Sdim                   (v4f32 (FADDP_4S (v4f32 VPR128:$Rn), (v4f32 VPR128:$Rn))),
5330259698Sdim                   sub_64)))>;
5331259698Sdim
5332259698Sdimdefm : Neon_ScalarPair_SD_size_patterns<int_aarch64_neon_vmaxv,
5333259698Sdim    int_aarch64_neon_vmaxv, FMAXPvv_S_2S, FMAXPvv_D_2D>;
5334259698Sdim
5335259698Sdimdefm : Neon_ScalarPair_SD_size_patterns<int_aarch64_neon_vminv,
5336259698Sdim    int_aarch64_neon_vminv, FMINPvv_S_2S, FMINPvv_D_2D>;
5337259698Sdim
5338259698Sdimdefm : Neon_ScalarPair_SD_size_patterns<int_aarch64_neon_vmaxnmv,
5339259698Sdim    int_aarch64_neon_vmaxnmv, FMAXNMPvv_S_2S, FMAXNMPvv_D_2D>;
5340259698Sdim
5341259698Sdimdefm : Neon_ScalarPair_SD_size_patterns<int_aarch64_neon_vminnmv,
5342259698Sdim    int_aarch64_neon_vminnmv, FMINNMPvv_S_2S, FMINNMPvv_D_2D>;
5343259698Sdim
5344259698Sdim// Scalar by element Arithmetic
5345259698Sdim
5346259698Sdimclass NeonI_ScalarXIndexedElemArith<string asmop, bits<4> opcode,
5347259698Sdim                                    string rmlane, bit u, bit szhi, bit szlo,
5348259698Sdim                                    RegisterClass ResFPR, RegisterClass OpFPR,
5349259698Sdim                                    RegisterOperand OpVPR, Operand OpImm>
5350259698Sdim  : NeonI_ScalarXIndexedElem<u, szhi, szlo, opcode,
5351259698Sdim                             (outs ResFPR:$Rd),
5352259698Sdim                             (ins OpFPR:$Rn, OpVPR:$MRm, OpImm:$Imm),
5353259698Sdim                             asmop # "\t$Rd, $Rn, $MRm" # rmlane # "[$Imm]",
5354259698Sdim                             [],
5355259698Sdim                             NoItinerary> {
5356259698Sdim  bits<3> Imm;
5357259698Sdim  bits<5> MRm;
5358259698Sdim}
5359259698Sdim
5360259698Sdimclass NeonI_ScalarXIndexedElemArith_Constraint_Impl<string asmop, bits<4> opcode,
5361259698Sdim                                                    string rmlane,
5362259698Sdim                                                    bit u, bit szhi, bit szlo,
5363259698Sdim                                                    RegisterClass ResFPR,
5364259698Sdim                                                    RegisterClass OpFPR,
5365259698Sdim                                                    RegisterOperand OpVPR,
5366259698Sdim                                                    Operand OpImm>
5367259698Sdim  : NeonI_ScalarXIndexedElem<u, szhi, szlo, opcode,
5368259698Sdim                             (outs ResFPR:$Rd),
5369259698Sdim                             (ins ResFPR:$src, OpFPR:$Rn, OpVPR:$MRm, OpImm:$Imm),
5370259698Sdim                             asmop # "\t$Rd, $Rn, $MRm" # rmlane # "[$Imm]",
5371259698Sdim                             [],
5372259698Sdim                             NoItinerary> {
5373259698Sdim  let Constraints = "$src = $Rd";
5374259698Sdim  bits<3> Imm;
5375259698Sdim  bits<5> MRm;
5376259698Sdim}
5377259698Sdim
5378259698Sdim// Scalar Floating Point  multiply (scalar, by element)
5379259698Sdimdef FMULssv_4S : NeonI_ScalarXIndexedElemArith<"fmul",
5380259698Sdim  0b1001, ".s", 0b0, 0b1, 0b0, FPR32, FPR32, VPR128, neon_uimm2_bare> {
5381259698Sdim  let Inst{11} = Imm{1}; // h
5382259698Sdim  let Inst{21} = Imm{0}; // l
5383259698Sdim  let Inst{20-16} = MRm;
5384259698Sdim}
5385259698Sdimdef FMULddv_2D : NeonI_ScalarXIndexedElemArith<"fmul",
5386259698Sdim  0b1001, ".d", 0b0, 0b1, 0b1, FPR64, FPR64, VPR128, neon_uimm1_bare> {
5387259698Sdim  let Inst{11} = Imm{0}; // h
5388259698Sdim  let Inst{21} = 0b0;    // l
5389259698Sdim  let Inst{20-16} = MRm;
5390259698Sdim}
5391259698Sdim
5392259698Sdim// Scalar Floating Point  multiply extended (scalar, by element)
5393259698Sdimdef FMULXssv_4S : NeonI_ScalarXIndexedElemArith<"fmulx",
5394259698Sdim  0b1001, ".s", 0b1, 0b1, 0b0, FPR32, FPR32, VPR128, neon_uimm2_bare> {
5395259698Sdim  let Inst{11} = Imm{1}; // h
5396259698Sdim  let Inst{21} = Imm{0}; // l
5397259698Sdim  let Inst{20-16} = MRm;
5398259698Sdim}
5399259698Sdimdef FMULXddv_2D : NeonI_ScalarXIndexedElemArith<"fmulx",
5400259698Sdim  0b1001, ".d", 0b1, 0b1, 0b1, FPR64, FPR64, VPR128, neon_uimm1_bare> {
5401259698Sdim  let Inst{11} = Imm{0}; // h
5402259698Sdim  let Inst{21} = 0b0;    // l
5403259698Sdim  let Inst{20-16} = MRm;
5404259698Sdim}
5405259698Sdim
5406259698Sdimmulticlass Neon_ScalarXIndexedElem_MUL_MULX_Patterns<
5407259698Sdim  SDPatternOperator opnode,
5408259698Sdim  Instruction INST,
5409259698Sdim  ValueType ResTy, RegisterClass FPRC, ValueType OpTy, Operand OpImm,
5410259698Sdim  ValueType OpNTy, ValueType ExTy, Operand OpNImm> {
5411259698Sdim
5412259698Sdim  def  : Pat<(ResTy (opnode (ResTy FPRC:$Rn),
5413259698Sdim               (ResTy (vector_extract (OpTy VPR128:$MRm), OpImm:$Imm)))),
5414259698Sdim             (ResTy (INST (ResTy FPRC:$Rn), (OpTy VPR128:$MRm), OpImm:$Imm))>;
5415259698Sdim
5416259698Sdim  def  : Pat<(ResTy (opnode (ResTy FPRC:$Rn),
5417259698Sdim               (ResTy (vector_extract (OpNTy VPR64:$MRm), OpNImm:$Imm)))),
5418259698Sdim             (ResTy (INST (ResTy FPRC:$Rn),
5419259698Sdim               (ExTy (SUBREG_TO_REG (i64 0), VPR64:$MRm, sub_64)),
5420259698Sdim               OpNImm:$Imm))>;
5421259698Sdim
5422259698Sdim  // swapped operands
5423259698Sdim  def  : Pat<(ResTy (opnode
5424259698Sdim               (ResTy (vector_extract (OpTy VPR128:$MRm), OpImm:$Imm)),
5425259698Sdim               (ResTy FPRC:$Rn))),
5426259698Sdim             (ResTy (INST (ResTy FPRC:$Rn), (OpTy VPR128:$MRm), OpImm:$Imm))>;
5427259698Sdim
5428259698Sdim  def  : Pat<(ResTy (opnode
5429259698Sdim               (ResTy (vector_extract (OpNTy VPR64:$MRm), OpNImm:$Imm)),
5430259698Sdim               (ResTy FPRC:$Rn))),
5431259698Sdim             (ResTy (INST (ResTy FPRC:$Rn),
5432259698Sdim               (ExTy (SUBREG_TO_REG (i64 0), VPR64:$MRm, sub_64)),
5433259698Sdim               OpNImm:$Imm))>;
5434259698Sdim}
5435259698Sdim
5436259698Sdim// Patterns for Scalar Floating Point  multiply (scalar, by element)
5437259698Sdimdefm : Neon_ScalarXIndexedElem_MUL_MULX_Patterns<fmul, FMULssv_4S,
5438259698Sdim  f32, FPR32, v4f32, neon_uimm2_bare, v2f32, v4f32, neon_uimm1_bare>;
5439259698Sdimdefm : Neon_ScalarXIndexedElem_MUL_MULX_Patterns<fmul, FMULddv_2D,
5440259698Sdim  f64, FPR64, v2f64, neon_uimm1_bare, v1f64, v2f64, neon_uimm0_bare>;
5441259698Sdim
5442259698Sdim// Patterns for Scalar Floating Point  multiply extended (scalar, by element)
5443259698Sdimdefm : Neon_ScalarXIndexedElem_MUL_MULX_Patterns<int_aarch64_neon_vmulx,
5444259698Sdim  FMULXssv_4S, f32, FPR32, v4f32, neon_uimm2_bare,
5445259698Sdim  v2f32, v4f32, neon_uimm1_bare>;
5446259698Sdimdefm : Neon_ScalarXIndexedElem_MUL_MULX_Patterns<int_aarch64_neon_vmulx,
5447259698Sdim  FMULXddv_2D, f64, FPR64, v2f64, neon_uimm1_bare,
5448259698Sdim  v1f64, v2f64, neon_uimm0_bare>;
5449259698Sdim
5450259698Sdim
5451259698Sdim// Scalar Floating Point fused multiply-add (scalar, by element)
5452259698Sdimdef FMLAssv_4S : NeonI_ScalarXIndexedElemArith_Constraint_Impl<"fmla",
5453259698Sdim  0b0001, ".s", 0b0, 0b1, 0b0, FPR32, FPR32, VPR128, neon_uimm2_bare> {
5454259698Sdim  let Inst{11} = Imm{1}; // h
5455259698Sdim  let Inst{21} = Imm{0}; // l
5456259698Sdim  let Inst{20-16} = MRm;
5457259698Sdim}
5458259698Sdimdef FMLAddv_2D : NeonI_ScalarXIndexedElemArith_Constraint_Impl<"fmla",
5459259698Sdim  0b0001, ".d", 0b0, 0b1, 0b1, FPR64, FPR64, VPR128, neon_uimm1_bare> {
5460259698Sdim  let Inst{11} = Imm{0}; // h
5461259698Sdim  let Inst{21} = 0b0;    // l
5462259698Sdim  let Inst{20-16} = MRm;
5463259698Sdim}
5464259698Sdim
5465259698Sdim// Scalar Floating Point fused multiply-subtract (scalar, by element)
5466259698Sdimdef FMLSssv_4S : NeonI_ScalarXIndexedElemArith_Constraint_Impl<"fmls",
5467259698Sdim  0b0101, ".s", 0b0, 0b1, 0b0, FPR32, FPR32, VPR128, neon_uimm2_bare> {
5468259698Sdim  let Inst{11} = Imm{1}; // h
5469259698Sdim  let Inst{21} = Imm{0}; // l
5470259698Sdim  let Inst{20-16} = MRm;
5471259698Sdim}
5472259698Sdimdef FMLSddv_2D : NeonI_ScalarXIndexedElemArith_Constraint_Impl<"fmls",
5473259698Sdim  0b0101, ".d", 0b0, 0b1, 0b1, FPR64, FPR64, VPR128, neon_uimm1_bare> {
5474259698Sdim  let Inst{11} = Imm{0}; // h
5475259698Sdim  let Inst{21} = 0b0;    // l
5476259698Sdim  let Inst{20-16} = MRm;
5477259698Sdim}
5478259698Sdim// We are allowed to match the fma instruction regardless of compile options.
5479259698Sdimmulticlass Neon_ScalarXIndexedElem_FMA_Patterns<
5480259698Sdim  Instruction FMLAI, Instruction FMLSI,
5481259698Sdim  ValueType ResTy, RegisterClass FPRC, ValueType OpTy, Operand OpImm,
5482259698Sdim  ValueType OpNTy, ValueType ExTy, Operand OpNImm> {
5483259698Sdim  // fmla
5484259698Sdim  def  : Pat<(ResTy (fma (ResTy FPRC:$Rn),
5485259698Sdim               (ResTy (vector_extract (OpTy VPR128:$MRm), OpImm:$Imm)),
5486259698Sdim               (ResTy FPRC:$Ra))),
5487259698Sdim             (ResTy (FMLAI (ResTy FPRC:$Ra),
5488259698Sdim               (ResTy FPRC:$Rn), (OpTy VPR128:$MRm), OpImm:$Imm))>;
5489259698Sdim
5490259698Sdim  def  : Pat<(ResTy (fma (ResTy FPRC:$Rn),
5491259698Sdim               (ResTy (vector_extract (OpNTy VPR64:$MRm), OpNImm:$Imm)),
5492259698Sdim               (ResTy FPRC:$Ra))),
5493259698Sdim             (ResTy (FMLAI (ResTy FPRC:$Ra),
5494259698Sdim               (ResTy FPRC:$Rn),
5495259698Sdim               (ExTy (SUBREG_TO_REG (i64 0), VPR64:$MRm, sub_64)),
5496259698Sdim               OpNImm:$Imm))>;
5497259698Sdim
5498259698Sdim  // swapped fmla operands
5499259698Sdim  def  : Pat<(ResTy (fma
5500259698Sdim               (ResTy (vector_extract (OpTy VPR128:$MRm), OpImm:$Imm)),
5501259698Sdim               (ResTy FPRC:$Rn),
5502259698Sdim               (ResTy FPRC:$Ra))),
5503259698Sdim             (ResTy (FMLAI (ResTy FPRC:$Ra),
5504259698Sdim               (ResTy FPRC:$Rn), (OpTy VPR128:$MRm), OpImm:$Imm))>;
5505259698Sdim
5506259698Sdim  def  : Pat<(ResTy (fma
5507259698Sdim               (ResTy (vector_extract (OpNTy VPR64:$MRm), OpNImm:$Imm)),
5508259698Sdim               (ResTy FPRC:$Rn),
5509259698Sdim               (ResTy FPRC:$Ra))),
5510259698Sdim             (ResTy (FMLAI (ResTy FPRC:$Ra),
5511259698Sdim               (ResTy FPRC:$Rn),
5512259698Sdim               (ExTy (SUBREG_TO_REG (i64 0), VPR64:$MRm, sub_64)),
5513259698Sdim               OpNImm:$Imm))>;
5514259698Sdim
5515259698Sdim  // fmls
5516259698Sdim  def  : Pat<(ResTy (fma (ResTy FPRC:$Rn),
5517259698Sdim               (fneg (ResTy (vector_extract (OpTy VPR128:$MRm), OpImm:$Imm))),
5518259698Sdim               (ResTy FPRC:$Ra))),
5519259698Sdim             (ResTy (FMLSI (ResTy FPRC:$Ra),
5520259698Sdim               (ResTy FPRC:$Rn), (OpTy VPR128:$MRm), OpImm:$Imm))>;
5521259698Sdim
5522259698Sdim  def  : Pat<(ResTy (fma (ResTy FPRC:$Rn),
5523259698Sdim               (fneg (ResTy (vector_extract (OpNTy VPR64:$MRm), OpNImm:$Imm))),
5524259698Sdim               (ResTy FPRC:$Ra))),
5525259698Sdim             (ResTy (FMLSI (ResTy FPRC:$Ra),
5526259698Sdim               (ResTy FPRC:$Rn),
5527259698Sdim               (ExTy (SUBREG_TO_REG (i64 0), VPR64:$MRm, sub_64)),
5528259698Sdim               OpNImm:$Imm))>;
5529259698Sdim
5530259698Sdim  // swapped fmls operands
5531259698Sdim  def  : Pat<(ResTy (fma
5532259698Sdim               (fneg (ResTy (vector_extract (OpTy VPR128:$MRm), OpImm:$Imm))),
5533259698Sdim               (ResTy FPRC:$Rn),
5534259698Sdim               (ResTy FPRC:$Ra))),
5535259698Sdim             (ResTy (FMLSI (ResTy FPRC:$Ra),
5536259698Sdim               (ResTy FPRC:$Rn), (OpTy VPR128:$MRm), OpImm:$Imm))>;
5537259698Sdim
5538259698Sdim  def  : Pat<(ResTy (fma
5539259698Sdim               (fneg (ResTy (vector_extract (OpNTy VPR64:$MRm), OpNImm:$Imm))),
5540259698Sdim               (ResTy FPRC:$Rn),
5541259698Sdim               (ResTy FPRC:$Ra))),
5542259698Sdim             (ResTy (FMLSI (ResTy FPRC:$Ra),
5543259698Sdim               (ResTy FPRC:$Rn),
5544259698Sdim               (ExTy (SUBREG_TO_REG (i64 0), VPR64:$MRm, sub_64)),
5545259698Sdim               OpNImm:$Imm))>;
5546259698Sdim}
5547259698Sdim
5548259698Sdim// Scalar Floating Point fused multiply-add and
5549259698Sdim// multiply-subtract (scalar, by element)
5550259698Sdimdefm : Neon_ScalarXIndexedElem_FMA_Patterns<FMLAssv_4S, FMLSssv_4S,
5551259698Sdim  f32, FPR32, v4f32, neon_uimm2_bare, v2f32, v4f32, neon_uimm1_bare>;
5552259698Sdimdefm : Neon_ScalarXIndexedElem_FMA_Patterns<FMLAddv_2D, FMLSddv_2D,
5553259698Sdim  f64, FPR64, v2f64, neon_uimm1_bare, v1f64, v2f64, neon_uimm0_bare>;
5554259698Sdimdefm : Neon_ScalarXIndexedElem_FMA_Patterns<FMLAddv_2D, FMLSddv_2D,
5555259698Sdim  f64, FPR64, v2f64, neon_uimm1_bare, v1f64, v2f64, neon_uimm0_bare>;
5556259698Sdim
5557259698Sdim// Scalar Signed saturating doubling multiply long (scalar, by element)
5558259698Sdimdef SQDMULLshv_4H : NeonI_ScalarXIndexedElemArith<"sqdmull",
5559259698Sdim  0b1011, ".h", 0b0, 0b0, 0b1, FPR32, FPR16, VPR64Lo, neon_uimm2_bare> {
5560259698Sdim  let Inst{11} = 0b0; // h
5561259698Sdim  let Inst{21} = Imm{1}; // l
5562259698Sdim  let Inst{20} = Imm{0}; // m
5563259698Sdim  let Inst{19-16} = MRm{3-0};
5564259698Sdim}
5565259698Sdimdef SQDMULLshv_8H : NeonI_ScalarXIndexedElemArith<"sqdmull",
5566259698Sdim  0b1011, ".h", 0b0, 0b0, 0b1, FPR32, FPR16, VPR128Lo, neon_uimm3_bare> {
5567259698Sdim  let Inst{11} = Imm{2}; // h
5568259698Sdim  let Inst{21} = Imm{1}; // l
5569259698Sdim  let Inst{20} = Imm{0}; // m
5570259698Sdim  let Inst{19-16} = MRm{3-0};
5571259698Sdim}
5572259698Sdimdef SQDMULLdsv_2S : NeonI_ScalarXIndexedElemArith<"sqdmull",
5573259698Sdim  0b1011, ".s", 0b0, 0b1, 0b0, FPR64, FPR32, VPR64, neon_uimm1_bare> {
5574259698Sdim  let Inst{11} = 0b0;    // h
5575259698Sdim  let Inst{21} = Imm{0}; // l
5576259698Sdim  let Inst{20-16} = MRm;
5577259698Sdim}
5578259698Sdimdef SQDMULLdsv_4S : NeonI_ScalarXIndexedElemArith<"sqdmull",
5579259698Sdim  0b1011, ".s", 0b0, 0b1, 0b0, FPR64, FPR32, VPR128, neon_uimm2_bare> {
5580259698Sdim  let Inst{11} = Imm{1};    // h
5581259698Sdim  let Inst{21} = Imm{0};    // l
5582259698Sdim  let Inst{20-16} = MRm;
5583259698Sdim}
5584259698Sdim
5585259698Sdimmulticlass Neon_ScalarXIndexedElem_MUL_Patterns<
5586259698Sdim  SDPatternOperator opnode,
5587259698Sdim  Instruction INST,
5588259698Sdim  ValueType ResTy, RegisterClass FPRC,
5589259698Sdim  ValueType OpVTy, ValueType OpTy,
5590259698Sdim  ValueType VecOpTy, ValueType ExTy, RegisterOperand VPRC, Operand OpImm> {
5591259698Sdim
5592259698Sdim  def  : Pat<(ResTy (opnode (OpVTy FPRC:$Rn),
5593259698Sdim               (OpVTy (scalar_to_vector
5594259698Sdim                 (ExTy (vector_extract (VecOpTy VPRC:$MRm), OpImm:$Imm)))))),
5595259698Sdim             (ResTy (INST (OpVTy FPRC:$Rn), (VecOpTy VPRC:$MRm), OpImm:$Imm))>;
5596259698Sdim
5597259698Sdim  //swapped operands
5598259698Sdim  def  : Pat<(ResTy (opnode
5599259698Sdim               (OpVTy (scalar_to_vector
5600259698Sdim                 (ExTy (vector_extract (VecOpTy VPRC:$MRm), OpImm:$Imm)))),
5601259698Sdim                 (OpVTy FPRC:$Rn))),
5602259698Sdim             (ResTy (INST (OpVTy FPRC:$Rn), (VecOpTy VPRC:$MRm), OpImm:$Imm))>;
5603259698Sdim}
5604259698Sdim
5605259698Sdim
5606259698Sdim// Patterns for Scalar Signed saturating doubling
5607259698Sdim// multiply long (scalar, by element)
5608259698Sdimdefm : Neon_ScalarXIndexedElem_MUL_Patterns<int_arm_neon_vqdmull,
5609259698Sdim  SQDMULLshv_4H, v1i32, FPR16, v1i16, i16, v4i16,
5610259698Sdim  i32, VPR64Lo, neon_uimm2_bare>;
5611259698Sdimdefm : Neon_ScalarXIndexedElem_MUL_Patterns<int_arm_neon_vqdmull,
5612259698Sdim  SQDMULLshv_8H, v1i32, FPR16, v1i16, i16, v8i16,
5613259698Sdim  i32, VPR128Lo, neon_uimm3_bare>;
5614259698Sdimdefm : Neon_ScalarXIndexedElem_MUL_Patterns<int_arm_neon_vqdmull,
5615259698Sdim  SQDMULLdsv_2S, v1i64, FPR32, v1i32, i32, v2i32,
5616259698Sdim  i32, VPR64Lo, neon_uimm1_bare>;
5617259698Sdimdefm : Neon_ScalarXIndexedElem_MUL_Patterns<int_arm_neon_vqdmull,
5618259698Sdim  SQDMULLdsv_4S, v1i64, FPR32, v1i32, i32, v4i32,
5619259698Sdim  i32, VPR128Lo, neon_uimm2_bare>;
5620259698Sdim
5621259698Sdim// Scalar Signed saturating doubling multiply-add long (scalar, by element)
5622259698Sdimdef SQDMLALshv_4H : NeonI_ScalarXIndexedElemArith_Constraint_Impl<"sqdmlal",
5623259698Sdim  0b0011, ".h", 0b0, 0b0, 0b1, FPR32, FPR16, VPR64Lo, neon_uimm2_bare> {
5624259698Sdim  let Inst{11} = 0b0; // h
5625259698Sdim  let Inst{21} = Imm{1}; // l
5626259698Sdim  let Inst{20} = Imm{0}; // m
5627259698Sdim  let Inst{19-16} = MRm{3-0};
5628259698Sdim}
5629259698Sdimdef SQDMLALshv_8H : NeonI_ScalarXIndexedElemArith_Constraint_Impl<"sqdmlal",
5630259698Sdim  0b0011, ".h", 0b0, 0b0, 0b1, FPR32, FPR16, VPR128Lo, neon_uimm3_bare> {
5631259698Sdim  let Inst{11} = Imm{2}; // h
5632259698Sdim  let Inst{21} = Imm{1}; // l
5633259698Sdim  let Inst{20} = Imm{0}; // m
5634259698Sdim  let Inst{19-16} = MRm{3-0};
5635259698Sdim}
5636259698Sdimdef SQDMLALdsv_2S : NeonI_ScalarXIndexedElemArith_Constraint_Impl<"sqdmlal",
5637259698Sdim  0b0011, ".s", 0b0, 0b1, 0b0, FPR64, FPR32, VPR64, neon_uimm1_bare> {
5638259698Sdim  let Inst{11} = 0b0;    // h
5639259698Sdim  let Inst{21} = Imm{0}; // l
5640259698Sdim  let Inst{20-16} = MRm;
5641259698Sdim}
5642259698Sdimdef SQDMLALdsv_4S : NeonI_ScalarXIndexedElemArith_Constraint_Impl<"sqdmlal",
5643259698Sdim  0b0011, ".s", 0b0, 0b1, 0b0, FPR64, FPR32, VPR128, neon_uimm2_bare> {
5644259698Sdim  let Inst{11} = Imm{1};    // h
5645259698Sdim  let Inst{21} = Imm{0};    // l
5646259698Sdim  let Inst{20-16} = MRm;
5647259698Sdim}
5648259698Sdim
5649259698Sdim// Scalar Signed saturating doubling
5650259698Sdim// multiply-subtract long (scalar, by element)
5651259698Sdimdef SQDMLSLshv_4H : NeonI_ScalarXIndexedElemArith_Constraint_Impl<"sqdmlsl",
5652259698Sdim  0b0111, ".h", 0b0, 0b0, 0b1, FPR32, FPR16, VPR64Lo, neon_uimm2_bare> {
5653259698Sdim  let Inst{11} = 0b0; // h
5654259698Sdim  let Inst{21} = Imm{1}; // l
5655259698Sdim  let Inst{20} = Imm{0}; // m
5656259698Sdim  let Inst{19-16} = MRm{3-0};
5657259698Sdim}
5658259698Sdimdef SQDMLSLshv_8H : NeonI_ScalarXIndexedElemArith_Constraint_Impl<"sqdmlsl",
5659259698Sdim  0b0111, ".h", 0b0, 0b0, 0b1, FPR32, FPR16, VPR128Lo, neon_uimm3_bare> {
5660259698Sdim  let Inst{11} = Imm{2}; // h
5661259698Sdim  let Inst{21} = Imm{1}; // l
5662259698Sdim  let Inst{20} = Imm{0}; // m
5663259698Sdim  let Inst{19-16} = MRm{3-0};
5664259698Sdim}
5665259698Sdimdef SQDMLSLdsv_2S : NeonI_ScalarXIndexedElemArith_Constraint_Impl<"sqdmlsl",
5666259698Sdim  0b0111, ".s", 0b0, 0b1, 0b0, FPR64, FPR32, VPR64, neon_uimm1_bare> {
5667259698Sdim  let Inst{11} = 0b0;    // h
5668259698Sdim  let Inst{21} = Imm{0}; // l
5669259698Sdim  let Inst{20-16} = MRm;
5670259698Sdim}
5671259698Sdimdef SQDMLSLdsv_4S : NeonI_ScalarXIndexedElemArith_Constraint_Impl<"sqdmlsl",
5672259698Sdim  0b0111, ".s", 0b0, 0b1, 0b0, FPR64, FPR32, VPR128, neon_uimm2_bare> {
5673259698Sdim  let Inst{11} = Imm{1};    // h
5674259698Sdim  let Inst{21} = Imm{0};    // l
5675259698Sdim  let Inst{20-16} = MRm;
5676259698Sdim}
5677259698Sdim
5678259698Sdimmulticlass Neon_ScalarXIndexedElem_MLAL_Patterns<
5679259698Sdim  SDPatternOperator opnode,
5680259698Sdim  SDPatternOperator coreopnode,
5681259698Sdim  Instruction INST,
5682259698Sdim  ValueType ResTy, RegisterClass ResFPRC, RegisterClass FPRC,
5683259698Sdim  ValueType OpTy,
5684259698Sdim  ValueType OpVTy, ValueType ExTy, RegisterOperand VPRC, Operand OpImm> {
5685259698Sdim
5686259698Sdim  def  : Pat<(ResTy (opnode
5687259698Sdim               (ResTy ResFPRC:$Ra),
5688259698Sdim               (ResTy (coreopnode (OpTy FPRC:$Rn),
5689259698Sdim                 (OpTy (scalar_to_vector
5690259698Sdim                   (ExTy (vector_extract (OpVTy VPRC:$MRm), OpImm:$Imm)))))))),
5691259698Sdim             (ResTy (INST (ResTy ResFPRC:$Ra),
5692259698Sdim               (OpTy FPRC:$Rn), (OpVTy VPRC:$MRm), OpImm:$Imm))>;
5693259698Sdim
5694259698Sdim  // swapped operands
5695259698Sdim  def  : Pat<(ResTy (opnode
5696259698Sdim               (ResTy ResFPRC:$Ra),
5697259698Sdim               (ResTy (coreopnode
5698259698Sdim                 (OpTy (scalar_to_vector
5699259698Sdim                   (ExTy (vector_extract (OpVTy VPRC:$MRm), OpImm:$Imm)))),
5700259698Sdim                 (OpTy FPRC:$Rn))))),
5701259698Sdim             (ResTy (INST (ResTy ResFPRC:$Ra),
5702259698Sdim               (OpTy FPRC:$Rn), (OpVTy VPRC:$MRm), OpImm:$Imm))>;
5703259698Sdim}
5704259698Sdim
5705259698Sdim// Patterns for Scalar Signed saturating
5706259698Sdim// doubling multiply-add long (scalar, by element)
5707259698Sdimdefm : Neon_ScalarXIndexedElem_MLAL_Patterns<int_arm_neon_vqadds,
5708259698Sdim  int_arm_neon_vqdmull, SQDMLALshv_4H, v1i32, FPR32, FPR16, v1i16, v4i16,
5709259698Sdim  i32, VPR64Lo, neon_uimm2_bare>;
5710259698Sdimdefm : Neon_ScalarXIndexedElem_MLAL_Patterns<int_arm_neon_vqadds,
5711259698Sdim  int_arm_neon_vqdmull, SQDMLALshv_8H, v1i32, FPR32, FPR16, v1i16, v8i16,
5712259698Sdim  i32, VPR128Lo, neon_uimm3_bare>;
5713259698Sdimdefm : Neon_ScalarXIndexedElem_MLAL_Patterns<int_arm_neon_vqadds,
5714259698Sdim  int_arm_neon_vqdmull, SQDMLALdsv_2S, v1i64, FPR64, FPR32, v1i32, v2i32,
5715259698Sdim  i32, VPR64Lo, neon_uimm1_bare>;
5716259698Sdimdefm : Neon_ScalarXIndexedElem_MLAL_Patterns<int_arm_neon_vqadds,
5717259698Sdim  int_arm_neon_vqdmull, SQDMLALdsv_4S, v1i64, FPR64, FPR32, v1i32, v4i32,
5718259698Sdim  i32, VPR128Lo, neon_uimm2_bare>;
5719259698Sdim
5720259698Sdim// Patterns for Scalar Signed saturating
5721259698Sdim// doubling multiply-sub long (scalar, by element)
5722259698Sdimdefm : Neon_ScalarXIndexedElem_MLAL_Patterns<int_arm_neon_vqsubs,
5723259698Sdim  int_arm_neon_vqdmull, SQDMLSLshv_4H, v1i32, FPR32, FPR16, v1i16, v4i16,
5724259698Sdim  i32, VPR64Lo, neon_uimm2_bare>;
5725259698Sdimdefm : Neon_ScalarXIndexedElem_MLAL_Patterns<int_arm_neon_vqsubs,
5726259698Sdim  int_arm_neon_vqdmull, SQDMLSLshv_8H, v1i32, FPR32, FPR16, v1i16, v8i16,
5727259698Sdim  i32, VPR128Lo, neon_uimm3_bare>;
5728259698Sdimdefm : Neon_ScalarXIndexedElem_MLAL_Patterns<int_arm_neon_vqsubs,
5729259698Sdim  int_arm_neon_vqdmull, SQDMLSLdsv_2S, v1i64, FPR64, FPR32, v1i32, v2i32,
5730259698Sdim  i32, VPR64Lo, neon_uimm1_bare>;
5731259698Sdimdefm : Neon_ScalarXIndexedElem_MLAL_Patterns<int_arm_neon_vqsubs,
5732259698Sdim  int_arm_neon_vqdmull, SQDMLSLdsv_4S, v1i64, FPR64, FPR32, v1i32, v4i32,
5733259698Sdim  i32, VPR128Lo, neon_uimm2_bare>;
5734259698Sdim
5735259698Sdim// Scalar general arithmetic operation
5736259698Sdimclass Neon_Scalar_GeneralMath2D_pattern<SDPatternOperator opnode,
5737259698Sdim                                        Instruction INST> 
5738259698Sdim    : Pat<(v1f64 (opnode (v1f64 FPR64:$Rn))), (INST FPR64:$Rn)>;
5739259698Sdim
5740259698Sdimclass Neon_Scalar_GeneralMath3D_pattern<SDPatternOperator opnode,
5741259698Sdim                                        Instruction INST> 
5742259698Sdim    : Pat<(v1f64 (opnode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5743259698Sdim          (INST FPR64:$Rn, FPR64:$Rm)>;
5744259698Sdim
5745259698Sdimclass Neon_Scalar_GeneralMath4D_pattern<SDPatternOperator opnode,
5746259698Sdim                                        Instruction INST> 
5747259698Sdim    : Pat<(v1f64 (opnode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm),
5748259698Sdim              (v1f64 FPR64:$Ra))),
5749259698Sdim          (INST FPR64:$Rn, FPR64:$Rm, FPR64:$Ra)>;
5750259698Sdim
5751259698Sdimdef : Neon_Scalar_GeneralMath3D_pattern<fadd, FADDddd>;
5752259698Sdimdef : Neon_Scalar_GeneralMath3D_pattern<fmul, FMULddd>;
5753259698Sdimdef : Neon_Scalar_GeneralMath3D_pattern<fsub, FSUBddd>;
5754259698Sdimdef : Neon_Scalar_GeneralMath3D_pattern<fdiv, FDIVddd>;
5755259698Sdimdef : Neon_Scalar_GeneralMath3D_pattern<int_arm_neon_vabds, FABDddd>;
5756259698Sdimdef : Neon_Scalar_GeneralMath3D_pattern<int_arm_neon_vmaxs, FMAXddd>;
5757259698Sdimdef : Neon_Scalar_GeneralMath3D_pattern<int_arm_neon_vmins, FMINddd>;
5758259698Sdimdef : Neon_Scalar_GeneralMath3D_pattern<int_aarch64_neon_vmaxnm, FMAXNMddd>;
5759259698Sdimdef : Neon_Scalar_GeneralMath3D_pattern<int_aarch64_neon_vminnm, FMINNMddd>;
5760259698Sdim
5761259698Sdimdef : Neon_Scalar_GeneralMath2D_pattern<fabs, FABSdd>;
5762259698Sdimdef : Neon_Scalar_GeneralMath2D_pattern<fneg, FNEGdd>;
5763259698Sdim
5764259698Sdimdef : Neon_Scalar_GeneralMath4D_pattern<fma, FMADDdddd>;
5765259698Sdimdef : Neon_Scalar_GeneralMath4D_pattern<fmsub, FMSUBdddd>;
5766259698Sdim
5767259698Sdim// Scalar Signed saturating doubling multiply returning
5768259698Sdim// high half (scalar, by element)
5769259698Sdimdef SQDMULHhhv_4H : NeonI_ScalarXIndexedElemArith<"sqdmulh",
5770259698Sdim  0b1100, ".h", 0b0, 0b0, 0b1, FPR16, FPR16, VPR64Lo, neon_uimm2_bare> {
5771259698Sdim  let Inst{11} = 0b0; // h
5772259698Sdim  let Inst{21} = Imm{1}; // l
5773259698Sdim  let Inst{20} = Imm{0}; // m
5774259698Sdim  let Inst{19-16} = MRm{3-0};
5775259698Sdim}
5776259698Sdimdef SQDMULHhhv_8H : NeonI_ScalarXIndexedElemArith<"sqdmulh",
5777259698Sdim  0b1100, ".h", 0b0, 0b0, 0b1, FPR16, FPR16, VPR128Lo, neon_uimm3_bare> {
5778259698Sdim  let Inst{11} = Imm{2}; // h
5779259698Sdim  let Inst{21} = Imm{1}; // l
5780259698Sdim  let Inst{20} = Imm{0}; // m
5781259698Sdim  let Inst{19-16} = MRm{3-0};
5782259698Sdim}
5783259698Sdimdef SQDMULHssv_2S : NeonI_ScalarXIndexedElemArith<"sqdmulh",
5784259698Sdim  0b1100, ".s", 0b0, 0b1, 0b0, FPR32, FPR32, VPR64, neon_uimm1_bare> {
5785259698Sdim  let Inst{11} = 0b0;    // h
5786259698Sdim  let Inst{21} = Imm{0}; // l
5787259698Sdim  let Inst{20-16} = MRm;
5788259698Sdim}
5789259698Sdimdef SQDMULHssv_4S : NeonI_ScalarXIndexedElemArith<"sqdmulh",
5790259698Sdim  0b1100, ".s", 0b0, 0b1, 0b0, FPR32, FPR32, VPR128, neon_uimm2_bare> {
5791259698Sdim  let Inst{11} = Imm{1};    // h
5792259698Sdim  let Inst{21} = Imm{0};    // l
5793259698Sdim  let Inst{20-16} = MRm;
5794259698Sdim}
5795259698Sdim
5796259698Sdim// Patterns for Scalar Signed saturating doubling multiply returning
5797259698Sdim// high half (scalar, by element)
5798259698Sdimdefm : Neon_ScalarXIndexedElem_MUL_Patterns<int_arm_neon_vqdmulh,
5799259698Sdim  SQDMULHhhv_4H, v1i16, FPR16, v1i16, i16, v4i16,
5800259698Sdim  i32, VPR64Lo, neon_uimm2_bare>;
5801259698Sdimdefm : Neon_ScalarXIndexedElem_MUL_Patterns<int_arm_neon_vqdmulh,
5802259698Sdim  SQDMULHhhv_8H, v1i16, FPR16, v1i16, i16, v8i16,
5803259698Sdim  i32, VPR128Lo, neon_uimm3_bare>;
5804259698Sdimdefm : Neon_ScalarXIndexedElem_MUL_Patterns<int_arm_neon_vqdmulh,
5805259698Sdim  SQDMULHssv_2S, v1i32, FPR32, v1i32, i32, v2i32,
5806259698Sdim  i32, VPR64Lo, neon_uimm1_bare>;
5807259698Sdimdefm : Neon_ScalarXIndexedElem_MUL_Patterns<int_arm_neon_vqdmulh,
5808259698Sdim  SQDMULHssv_4S, v1i32, FPR32, v1i32, i32, v4i32,
5809259698Sdim  i32, VPR128Lo, neon_uimm2_bare>;
5810259698Sdim
5811259698Sdim// Scalar Signed saturating rounding doubling multiply
5812259698Sdim// returning high half (scalar, by element)
5813259698Sdimdef SQRDMULHhhv_4H : NeonI_ScalarXIndexedElemArith<"sqrdmulh",
5814259698Sdim  0b1101, ".h", 0b0, 0b0, 0b1, FPR16, FPR16, VPR64Lo, neon_uimm2_bare> {
5815259698Sdim  let Inst{11} = 0b0; // h
5816259698Sdim  let Inst{21} = Imm{1}; // l
5817259698Sdim  let Inst{20} = Imm{0}; // m
5818259698Sdim  let Inst{19-16} = MRm{3-0};
5819259698Sdim}
5820259698Sdimdef SQRDMULHhhv_8H : NeonI_ScalarXIndexedElemArith<"sqrdmulh",
5821259698Sdim  0b1101, ".h", 0b0, 0b0, 0b1, FPR16, FPR16, VPR128Lo, neon_uimm3_bare> {
5822259698Sdim  let Inst{11} = Imm{2}; // h
5823259698Sdim  let Inst{21} = Imm{1}; // l
5824259698Sdim  let Inst{20} = Imm{0}; // m
5825259698Sdim  let Inst{19-16} = MRm{3-0};
5826259698Sdim}
5827259698Sdimdef SQRDMULHssv_2S : NeonI_ScalarXIndexedElemArith<"sqrdmulh",
5828259698Sdim  0b1101, ".s", 0b0, 0b1, 0b0, FPR32, FPR32, VPR64, neon_uimm1_bare> {
5829259698Sdim  let Inst{11} = 0b0;    // h
5830259698Sdim  let Inst{21} = Imm{0}; // l
5831259698Sdim  let Inst{20-16} = MRm;
5832259698Sdim}
5833259698Sdimdef SQRDMULHssv_4S : NeonI_ScalarXIndexedElemArith<"sqrdmulh",
5834259698Sdim  0b1101, ".s", 0b0, 0b1, 0b0, FPR32, FPR32, VPR128, neon_uimm2_bare> {
5835259698Sdim  let Inst{11} = Imm{1};    // h
5836259698Sdim  let Inst{21} = Imm{0};    // l
5837259698Sdim  let Inst{20-16} = MRm;
5838259698Sdim}
5839259698Sdim
5840259698Sdimdefm : Neon_ScalarXIndexedElem_MUL_Patterns<int_arm_neon_vqrdmulh,
5841259698Sdim  SQRDMULHhhv_4H, v1i16, FPR16, v1i16, i16, v4i16, i32,
5842259698Sdim  VPR64Lo, neon_uimm2_bare>;
5843259698Sdimdefm : Neon_ScalarXIndexedElem_MUL_Patterns<int_arm_neon_vqrdmulh,
5844259698Sdim  SQRDMULHhhv_8H, v1i16, FPR16, v1i16, i16, v8i16, i32,
5845259698Sdim  VPR128Lo, neon_uimm3_bare>;
5846259698Sdimdefm : Neon_ScalarXIndexedElem_MUL_Patterns<int_arm_neon_vqrdmulh,
5847259698Sdim  SQRDMULHssv_2S, v1i32, FPR32, v1i32, i32, v2i32, i32,
5848259698Sdim  VPR64Lo, neon_uimm1_bare>;
5849259698Sdimdefm : Neon_ScalarXIndexedElem_MUL_Patterns<int_arm_neon_vqrdmulh,
5850259698Sdim  SQRDMULHssv_4S, v1i32, FPR32, v1i32, i32, v4i32, i32,
5851259698Sdim  VPR128Lo, neon_uimm2_bare>;
5852259698Sdim
5853259698Sdim// Scalar Copy - DUP element to scalar
5854259698Sdimclass NeonI_Scalar_DUP<string asmop, string asmlane,
5855259698Sdim                       RegisterClass ResRC, RegisterOperand VPRC,
5856259698Sdim                       Operand OpImm>
5857259698Sdim  : NeonI_ScalarCopy<(outs ResRC:$Rd), (ins VPRC:$Rn, OpImm:$Imm),
5858259698Sdim                     asmop # "\t$Rd, $Rn." # asmlane # "[$Imm]",
5859259698Sdim                     [],
5860259698Sdim                     NoItinerary> {
5861259698Sdim  bits<4> Imm;
5862259698Sdim}
5863259698Sdim
5864259698Sdimdef DUPbv_B : NeonI_Scalar_DUP<"dup", "b", FPR8, VPR128, neon_uimm4_bare> {
5865259698Sdim  let Inst{20-16} = {Imm{3}, Imm{2}, Imm{1}, Imm{0}, 0b1};
5866259698Sdim}
5867259698Sdimdef DUPhv_H : NeonI_Scalar_DUP<"dup", "h", FPR16, VPR128, neon_uimm3_bare> {
5868259698Sdim  let Inst{20-16} = {Imm{2}, Imm{1}, Imm{0}, 0b1, 0b0};
5869259698Sdim}
5870259698Sdimdef DUPsv_S : NeonI_Scalar_DUP<"dup", "s", FPR32, VPR128, neon_uimm2_bare> {
5871259698Sdim  let Inst{20-16} = {Imm{1}, Imm{0}, 0b1, 0b0, 0b0};
5872259698Sdim}
5873259698Sdimdef DUPdv_D : NeonI_Scalar_DUP<"dup", "d", FPR64, VPR128, neon_uimm1_bare> {
5874259698Sdim  let Inst{20-16} = {Imm, 0b1, 0b0, 0b0, 0b0};
5875259698Sdim}
5876259698Sdim
5877259698Sdimmulticlass NeonI_Scalar_DUP_Elt_pattern<Instruction DUPI, ValueType ResTy,
5878259698Sdim  ValueType OpTy, Operand OpImm,
5879259698Sdim  ValueType OpNTy, ValueType ExTy, Operand OpNImm> {
5880259698Sdim  def : Pat<(ResTy (vector_extract (OpTy VPR128:$Rn), OpImm:$Imm)),
5881259698Sdim            (ResTy (DUPI (OpTy VPR128:$Rn), OpImm:$Imm))>;
5882259698Sdim
5883259698Sdim  def : Pat<(ResTy (vector_extract (OpNTy VPR64:$Rn), OpNImm:$Imm)),
5884259698Sdim            (ResTy (DUPI
5885259698Sdim              (ExTy (SUBREG_TO_REG (i64 0), VPR64:$Rn, sub_64)),
5886259698Sdim                OpNImm:$Imm))>;
5887259698Sdim}
5888259698Sdim
5889259698Sdim// Patterns for vector extract of FP data using scalar DUP instructions
5890259698Sdimdefm : NeonI_Scalar_DUP_Elt_pattern<DUPsv_S, f32,
5891259698Sdim  v4f32, neon_uimm2_bare, v2f32, v4f32, neon_uimm1_bare>;
5892259698Sdimdefm : NeonI_Scalar_DUP_Elt_pattern<DUPdv_D, f64,
5893259698Sdim  v2f64, neon_uimm1_bare, v1f64, v2f64, neon_uimm0_bare>;
5894259698Sdim
5895259698Sdimmulticlass NeonI_Scalar_DUP_Ext_Vec_pattern<Instruction DUPI,
5896259698Sdim  ValueType ResTy, ValueType OpTy,Operand OpLImm,
5897259698Sdim  ValueType NOpTy, ValueType ExTy, Operand OpNImm> {
5898259698Sdim
5899259698Sdim  def : Pat<(ResTy (extract_subvector (OpTy VPR128:$Rn), OpLImm:$Imm)),
5900259698Sdim            (ResTy (DUPI VPR128:$Rn, OpLImm:$Imm))>;
5901259698Sdim
5902259698Sdim  def : Pat<(ResTy (extract_subvector (NOpTy VPR64:$Rn), OpNImm:$Imm)),
5903259698Sdim            (ResTy (DUPI
5904259698Sdim              (ExTy (SUBREG_TO_REG (i64 0), VPR64:$Rn, sub_64)),
5905259698Sdim                OpNImm:$Imm))>;
5906259698Sdim}
5907259698Sdim
5908259698Sdim// Patterns for extract subvectors of v1ix data using scalar DUP instructions.
5909259698Sdimdefm : NeonI_Scalar_DUP_Ext_Vec_pattern<DUPbv_B, v1i8, v16i8, neon_uimm4_bare,
5910259698Sdim                                        v8i8, v16i8, neon_uimm3_bare>;
5911259698Sdimdefm : NeonI_Scalar_DUP_Ext_Vec_pattern<DUPhv_H, v1i16, v8i16, neon_uimm3_bare,
5912259698Sdim                                        v4i16, v8i16, neon_uimm2_bare>;
5913259698Sdimdefm : NeonI_Scalar_DUP_Ext_Vec_pattern<DUPsv_S, v1i32, v4i32, neon_uimm2_bare,
5914259698Sdim                                        v2i32, v4i32, neon_uimm1_bare>;
5915259698Sdim
5916259698Sdimmulticlass NeonI_Scalar_DUP_Copy_pattern1<Instruction DUPI, ValueType ResTy,
5917259698Sdim                                          ValueType OpTy, ValueType ElemTy,
5918259698Sdim                                          Operand OpImm, ValueType OpNTy,
5919259698Sdim                                          ValueType ExTy, Operand OpNImm> {
5920259698Sdim
5921259698Sdim  def : Pat<(ResTy (vector_insert (ResTy undef),
5922259698Sdim              (ElemTy (vector_extract (OpTy VPR128:$Rn), OpImm:$Imm)),
5923259698Sdim              (neon_uimm0_bare:$Imm))),
5924259698Sdim            (ResTy (DUPI (OpTy VPR128:$Rn), OpImm:$Imm))>;
5925259698Sdim
5926259698Sdim  def : Pat<(ResTy (vector_insert (ResTy undef),
5927259698Sdim              (ElemTy (vector_extract (OpNTy VPR64:$Rn), OpNImm:$Imm)),
5928259698Sdim              (OpNImm:$Imm))),
5929259698Sdim            (ResTy (DUPI
5930259698Sdim              (ExTy (SUBREG_TO_REG (i64 0), VPR64:$Rn, sub_64)),
5931259698Sdim              OpNImm:$Imm))>;
5932259698Sdim}
5933259698Sdim
5934259698Sdimmulticlass NeonI_Scalar_DUP_Copy_pattern2<Instruction DUPI, ValueType ResTy,
5935259698Sdim                                          ValueType OpTy, ValueType ElemTy,
5936259698Sdim                                          Operand OpImm, ValueType OpNTy,
5937259698Sdim                                          ValueType ExTy, Operand OpNImm> {
5938259698Sdim
5939259698Sdim  def : Pat<(ResTy (scalar_to_vector
5940259698Sdim              (ElemTy (vector_extract (OpTy VPR128:$Rn), OpImm:$Imm)))),
5941259698Sdim            (ResTy (DUPI (OpTy VPR128:$Rn), OpImm:$Imm))>;
5942259698Sdim
5943259698Sdim  def : Pat<(ResTy (scalar_to_vector
5944259698Sdim              (ElemTy (vector_extract (OpNTy VPR64:$Rn), OpNImm:$Imm)))),
5945259698Sdim            (ResTy (DUPI
5946259698Sdim              (ExTy (SUBREG_TO_REG (i64 0), VPR64:$Rn, sub_64)),
5947259698Sdim              OpNImm:$Imm))>;
5948259698Sdim}
5949259698Sdim
5950259698Sdim// Patterns for vector copy to v1ix and v1fx vectors using scalar DUP
5951259698Sdim// instructions.
5952259698Sdimdefm : NeonI_Scalar_DUP_Copy_pattern1<DUPdv_D,
5953259698Sdim  v1i64, v2i64, i64, neon_uimm1_bare,
5954259698Sdim  v1i64, v2i64, neon_uimm0_bare>;
5955259698Sdimdefm : NeonI_Scalar_DUP_Copy_pattern1<DUPsv_S,
5956259698Sdim  v1i32, v4i32, i32, neon_uimm2_bare,
5957259698Sdim  v2i32, v4i32, neon_uimm1_bare>;
5958259698Sdimdefm : NeonI_Scalar_DUP_Copy_pattern1<DUPhv_H,
5959259698Sdim  v1i16, v8i16, i32, neon_uimm3_bare,
5960259698Sdim  v4i16, v8i16, neon_uimm2_bare>;
5961259698Sdimdefm : NeonI_Scalar_DUP_Copy_pattern1<DUPbv_B,
5962259698Sdim  v1i8, v16i8, i32, neon_uimm4_bare,
5963259698Sdim  v8i8, v16i8, neon_uimm3_bare>;
5964259698Sdimdefm : NeonI_Scalar_DUP_Copy_pattern1<DUPdv_D,
5965259698Sdim  v1f64, v2f64, f64, neon_uimm1_bare,
5966259698Sdim  v1f64, v2f64, neon_uimm0_bare>;
5967259698Sdimdefm : NeonI_Scalar_DUP_Copy_pattern1<DUPsv_S,
5968259698Sdim  v1f32, v4f32, f32, neon_uimm2_bare,
5969259698Sdim  v2f32, v4f32, neon_uimm1_bare>;
5970259698Sdimdefm : NeonI_Scalar_DUP_Copy_pattern2<DUPdv_D,
5971259698Sdim  v1i64, v2i64, i64, neon_uimm1_bare,
5972259698Sdim  v1i64, v2i64, neon_uimm0_bare>;
5973259698Sdimdefm : NeonI_Scalar_DUP_Copy_pattern2<DUPsv_S,
5974259698Sdim  v1i32, v4i32, i32, neon_uimm2_bare,
5975259698Sdim  v2i32, v4i32, neon_uimm1_bare>;
5976259698Sdimdefm : NeonI_Scalar_DUP_Copy_pattern2<DUPhv_H,
5977259698Sdim  v1i16, v8i16, i32, neon_uimm3_bare,
5978259698Sdim  v4i16, v8i16, neon_uimm2_bare>;
5979259698Sdimdefm : NeonI_Scalar_DUP_Copy_pattern2<DUPbv_B,
5980259698Sdim  v1i8, v16i8, i32, neon_uimm4_bare,
5981259698Sdim  v8i8, v16i8, neon_uimm3_bare>;
5982259698Sdimdefm : NeonI_Scalar_DUP_Copy_pattern2<DUPdv_D,
5983259698Sdim  v1f64, v2f64, f64, neon_uimm1_bare,
5984259698Sdim  v1f64, v2f64, neon_uimm0_bare>;
5985259698Sdimdefm : NeonI_Scalar_DUP_Copy_pattern2<DUPsv_S,
5986259698Sdim  v1f32, v4f32, f32, neon_uimm2_bare,
5987259698Sdim  v2f32, v4f32, neon_uimm1_bare>;
5988259698Sdim
5989259698Sdimmulticlass NeonI_Scalar_DUP_alias<string asmop, string asmlane,
5990259698Sdim                                  Instruction DUPI, Operand OpImm,
5991259698Sdim                                  RegisterClass ResRC> {
5992259698Sdim  def : NeonInstAlias<!strconcat(asmop, "$Rd, $Rn" # asmlane # "[$Imm]"),
5993259698Sdim          (DUPI ResRC:$Rd, VPR128:$Rn, OpImm:$Imm), 0b0>;
5994259698Sdim}
5995259698Sdim
5996259698Sdim// Aliases for Scalar copy - DUP element (scalar)
5997259698Sdim// FIXME: This is actually the preferred syntax but TableGen can't deal with
5998259698Sdim// custom printing of aliases.
5999259698Sdimdefm : NeonI_Scalar_DUP_alias<"mov", ".b", DUPbv_B, neon_uimm4_bare, FPR8>;
6000259698Sdimdefm : NeonI_Scalar_DUP_alias<"mov", ".h", DUPhv_H, neon_uimm3_bare, FPR16>;
6001259698Sdimdefm : NeonI_Scalar_DUP_alias<"mov", ".s", DUPsv_S, neon_uimm2_bare, FPR32>;
6002259698Sdimdefm : NeonI_Scalar_DUP_alias<"mov", ".d", DUPdv_D, neon_uimm1_bare, FPR64>;
6003259698Sdim
6004259698Sdimmulticlass NeonI_SDUP<PatFrag GetLow, PatFrag GetHigh, ValueType ResTy,
6005259698Sdim                      ValueType OpTy> {
6006259698Sdim  def : Pat<(ResTy (GetLow VPR128:$Rn)),
6007259698Sdim            (ResTy (EXTRACT_SUBREG (OpTy VPR128:$Rn), sub_64))>;
6008259698Sdim  def : Pat<(ResTy (GetHigh VPR128:$Rn)),
6009259698Sdim            (ResTy (DUPdv_D (OpTy VPR128:$Rn), 1))>;
6010259698Sdim}
6011259698Sdim
6012259698Sdimdefm : NeonI_SDUP<Neon_Low16B, Neon_High16B, v8i8, v16i8>;
6013259698Sdimdefm : NeonI_SDUP<Neon_Low8H, Neon_High8H, v4i16, v8i16>;
6014259698Sdimdefm : NeonI_SDUP<Neon_Low4S, Neon_High4S, v2i32, v4i32>;
6015259698Sdimdefm : NeonI_SDUP<Neon_Low2D, Neon_High2D, v1i64, v2i64>;
6016259698Sdimdefm : NeonI_SDUP<Neon_Low4float, Neon_High4float, v2f32, v4f32>;
6017259698Sdimdefm : NeonI_SDUP<Neon_Low2double, Neon_High2double, v1f64, v2f64>;
6018259698Sdim
6019259698Sdim//===----------------------------------------------------------------------===//
6020259698Sdim// Non-Instruction Patterns
6021259698Sdim//===----------------------------------------------------------------------===//
6022259698Sdim
6023259698Sdim// 64-bit vector bitcasts...
6024259698Sdim
6025259698Sdimdef : Pat<(v1i64 (bitconvert (v8i8  VPR64:$src))), (v1i64 VPR64:$src)>;
6026259698Sdimdef : Pat<(v2f32 (bitconvert (v8i8  VPR64:$src))), (v2f32 VPR64:$src)>;
6027259698Sdimdef : Pat<(v2i32 (bitconvert (v8i8  VPR64:$src))), (v2i32 VPR64:$src)>;
6028259698Sdimdef : Pat<(v4i16 (bitconvert (v8i8  VPR64:$src))), (v4i16 VPR64:$src)>;
6029259698Sdim
6030259698Sdimdef : Pat<(v1i64 (bitconvert (v4i16  VPR64:$src))), (v1i64 VPR64:$src)>;
6031259698Sdimdef : Pat<(v2i32 (bitconvert (v4i16  VPR64:$src))), (v2i32 VPR64:$src)>;
6032259698Sdimdef : Pat<(v2f32 (bitconvert (v4i16  VPR64:$src))), (v2f32 VPR64:$src)>;
6033259698Sdimdef : Pat<(v8i8  (bitconvert (v4i16  VPR64:$src))), (v8i8 VPR64:$src)>;
6034259698Sdim
6035259698Sdimdef : Pat<(v1i64 (bitconvert (v2i32  VPR64:$src))), (v1i64 VPR64:$src)>;
6036259698Sdimdef : Pat<(v2f32 (bitconvert (v2i32  VPR64:$src))), (v2f32 VPR64:$src)>;
6037259698Sdimdef : Pat<(v4i16 (bitconvert (v2i32  VPR64:$src))), (v4i16 VPR64:$src)>;
6038259698Sdimdef : Pat<(v8i8  (bitconvert (v2i32  VPR64:$src))), (v8i8 VPR64:$src)>;
6039259698Sdim
6040259698Sdimdef : Pat<(v1i64 (bitconvert (v2f32  VPR64:$src))), (v1i64 VPR64:$src)>;
6041259698Sdimdef : Pat<(v2i32 (bitconvert (v2f32  VPR64:$src))), (v2i32 VPR64:$src)>;
6042259698Sdimdef : Pat<(v4i16 (bitconvert (v2f32  VPR64:$src))), (v4i16 VPR64:$src)>;
6043259698Sdimdef : Pat<(v8i8  (bitconvert (v2f32  VPR64:$src))), (v8i8 VPR64:$src)>;
6044259698Sdim
6045259698Sdimdef : Pat<(v2f32 (bitconvert (v1i64  VPR64:$src))), (v2f32 VPR64:$src)>;
6046259698Sdimdef : Pat<(v2i32 (bitconvert (v1i64  VPR64:$src))), (v2i32 VPR64:$src)>;
6047259698Sdimdef : Pat<(v4i16 (bitconvert (v1i64  VPR64:$src))), (v4i16 VPR64:$src)>;
6048259698Sdimdef : Pat<(v8i8  (bitconvert (v1i64  VPR64:$src))), (v8i8 VPR64:$src)>;
6049259698Sdim
6050259698Sdim// ..and 128-bit vector bitcasts...
6051259698Sdim
6052259698Sdimdef : Pat<(v2f64 (bitconvert (v16i8  VPR128:$src))), (v2f64 VPR128:$src)>;
6053259698Sdimdef : Pat<(v2i64 (bitconvert (v16i8  VPR128:$src))), (v2i64 VPR128:$src)>;
6054259698Sdimdef : Pat<(v4f32 (bitconvert (v16i8  VPR128:$src))), (v4f32 VPR128:$src)>;
6055259698Sdimdef : Pat<(v4i32 (bitconvert (v16i8  VPR128:$src))), (v4i32 VPR128:$src)>;
6056259698Sdimdef : Pat<(v8i16 (bitconvert (v16i8  VPR128:$src))), (v8i16 VPR128:$src)>;
6057259698Sdim
6058259698Sdimdef : Pat<(v2f64 (bitconvert (v8i16  VPR128:$src))), (v2f64 VPR128:$src)>;
6059259698Sdimdef : Pat<(v2i64 (bitconvert (v8i16  VPR128:$src))), (v2i64 VPR128:$src)>;
6060259698Sdimdef : Pat<(v4i32 (bitconvert (v8i16  VPR128:$src))), (v4i32 VPR128:$src)>;
6061259698Sdimdef : Pat<(v4f32 (bitconvert (v8i16  VPR128:$src))), (v4f32 VPR128:$src)>;
6062259698Sdimdef : Pat<(v16i8 (bitconvert (v8i16  VPR128:$src))), (v16i8 VPR128:$src)>;
6063259698Sdim
6064259698Sdimdef : Pat<(v2f64 (bitconvert (v4i32  VPR128:$src))), (v2f64 VPR128:$src)>;
6065259698Sdimdef : Pat<(v2i64 (bitconvert (v4i32  VPR128:$src))), (v2i64 VPR128:$src)>;
6066259698Sdimdef : Pat<(v4f32 (bitconvert (v4i32  VPR128:$src))), (v4f32 VPR128:$src)>;
6067259698Sdimdef : Pat<(v8i16 (bitconvert (v4i32  VPR128:$src))), (v8i16 VPR128:$src)>;
6068259698Sdimdef : Pat<(v16i8 (bitconvert (v4i32  VPR128:$src))), (v16i8 VPR128:$src)>;
6069259698Sdim
6070259698Sdimdef : Pat<(v2f64 (bitconvert (v4f32  VPR128:$src))), (v2f64 VPR128:$src)>;
6071259698Sdimdef : Pat<(v2i64 (bitconvert (v4f32  VPR128:$src))), (v2i64 VPR128:$src)>;
6072259698Sdimdef : Pat<(v4i32 (bitconvert (v4f32  VPR128:$src))), (v4i32 VPR128:$src)>;
6073259698Sdimdef : Pat<(v8i16 (bitconvert (v4f32  VPR128:$src))), (v8i16 VPR128:$src)>;
6074259698Sdimdef : Pat<(v16i8 (bitconvert (v4f32  VPR128:$src))), (v16i8 VPR128:$src)>;
6075259698Sdim
6076259698Sdimdef : Pat<(v2f64 (bitconvert (v2i64  VPR128:$src))), (v2f64 VPR128:$src)>;
6077259698Sdimdef : Pat<(v4f32 (bitconvert (v2i64  VPR128:$src))), (v4f32 VPR128:$src)>;
6078259698Sdimdef : Pat<(v4i32 (bitconvert (v2i64  VPR128:$src))), (v4i32 VPR128:$src)>;
6079259698Sdimdef : Pat<(v8i16 (bitconvert (v2i64  VPR128:$src))), (v8i16 VPR128:$src)>;
6080259698Sdimdef : Pat<(v16i8 (bitconvert (v2i64  VPR128:$src))), (v16i8 VPR128:$src)>;
6081259698Sdim
6082259698Sdimdef : Pat<(v2i64 (bitconvert (v2f64  VPR128:$src))), (v2i64 VPR128:$src)>;
6083259698Sdimdef : Pat<(v4f32 (bitconvert (v2f64  VPR128:$src))), (v4f32 VPR128:$src)>;
6084259698Sdimdef : Pat<(v4i32 (bitconvert (v2f64  VPR128:$src))), (v4i32 VPR128:$src)>;
6085259698Sdimdef : Pat<(v8i16 (bitconvert (v2f64  VPR128:$src))), (v8i16 VPR128:$src)>;
6086259698Sdimdef : Pat<(v16i8 (bitconvert (v2f64  VPR128:$src))), (v16i8 VPR128:$src)>;
6087259698Sdim
6088259698Sdim// ...and scalar bitcasts...
6089259698Sdimdef : Pat<(f16 (bitconvert (v1i16  FPR16:$src))), (f16 FPR16:$src)>;
6090259698Sdimdef : Pat<(f32 (bitconvert (v1i32  FPR32:$src))), (f32 FPR32:$src)>;
6091259698Sdimdef : Pat<(f64 (bitconvert (v1i64  FPR64:$src))), (f64 FPR64:$src)>;
6092259698Sdimdef : Pat<(f32 (bitconvert (v1f32  FPR32:$src))), (f32 FPR32:$src)>;
6093259698Sdimdef : Pat<(f64 (bitconvert (v1f64  FPR64:$src))), (f64 FPR64:$src)>;
6094259698Sdim
6095259698Sdimdef : Pat<(i64 (bitconvert (v1i64  FPR64:$src))), (FMOVxd $src)>;
6096259698Sdimdef : Pat<(i64 (bitconvert (v1f64  FPR64:$src))), (FMOVxd $src)>;
6097259698Sdimdef : Pat<(i64 (bitconvert (v2i32  FPR64:$src))), (FMOVxd $src)>;
6098259698Sdimdef : Pat<(i64 (bitconvert (v2f32  FPR64:$src))), (FMOVxd $src)>;
6099259698Sdimdef : Pat<(i64 (bitconvert (v4i16  FPR64:$src))), (FMOVxd $src)>;
6100259698Sdimdef : Pat<(i64 (bitconvert (v8i8  FPR64:$src))), (FMOVxd $src)>;
6101259698Sdim
6102259698Sdimdef : Pat<(i32 (bitconvert (v1i32  FPR32:$src))), (FMOVws $src)>;
6103259698Sdim
6104259698Sdimdef : Pat<(v8i8  (bitconvert (v1i64  VPR64:$src))), (v8i8 VPR64:$src)>;
6105259698Sdimdef : Pat<(v4i16 (bitconvert (v1i64  VPR64:$src))), (v4i16 VPR64:$src)>;
6106259698Sdimdef : Pat<(v2i32 (bitconvert (v1i64  VPR64:$src))), (v2i32 VPR64:$src)>;
6107259698Sdim
6108259698Sdimdef : Pat<(f64   (bitconvert (v8i8  VPR64:$src))), (f64 VPR64:$src)>;
6109259698Sdimdef : Pat<(f64   (bitconvert (v4i16  VPR64:$src))), (f64 VPR64:$src)>;
6110259698Sdimdef : Pat<(f64   (bitconvert (v2i32  VPR64:$src))), (f64 VPR64:$src)>;
6111259698Sdimdef : Pat<(f64   (bitconvert (v2f32  VPR64:$src))), (f64 VPR64:$src)>;
6112259698Sdimdef : Pat<(f64   (bitconvert (v1i64  VPR64:$src))), (f64 VPR64:$src)>;
6113259698Sdim
6114259698Sdimdef : Pat<(f128  (bitconvert (v16i8  VPR128:$src))), (f128 VPR128:$src)>;
6115259698Sdimdef : Pat<(f128  (bitconvert (v8i16  VPR128:$src))), (f128 VPR128:$src)>;
6116259698Sdimdef : Pat<(f128  (bitconvert (v4i32  VPR128:$src))), (f128 VPR128:$src)>;
6117259698Sdimdef : Pat<(f128  (bitconvert (v2i64  VPR128:$src))), (f128 VPR128:$src)>;
6118259698Sdimdef : Pat<(f128  (bitconvert (v4f32  VPR128:$src))), (f128 VPR128:$src)>;
6119259698Sdimdef : Pat<(f128  (bitconvert (v2f64  VPR128:$src))), (f128 VPR128:$src)>;
6120259698Sdim
6121259698Sdimdef : Pat<(v1i16 (bitconvert (f16  FPR16:$src))), (v1i16 FPR16:$src)>;
6122259698Sdimdef : Pat<(v1i32 (bitconvert (f32  FPR32:$src))), (v1i32 FPR32:$src)>;
6123259698Sdimdef : Pat<(v1i64 (bitconvert (f64  FPR64:$src))), (v1i64 FPR64:$src)>;
6124259698Sdimdef : Pat<(v1f32 (bitconvert (f32  FPR32:$src))), (v1f32 FPR32:$src)>;
6125259698Sdimdef : Pat<(v1f64 (bitconvert (f64  FPR64:$src))), (v1f64 FPR64:$src)>;
6126259698Sdim
6127259698Sdimdef : Pat<(v1i64 (bitconvert (i64  GPR64:$src))), (FMOVdx $src)>;
6128259698Sdimdef : Pat<(v1f64 (bitconvert (i64  GPR64:$src))), (FMOVdx $src)>;
6129259698Sdimdef : Pat<(v2i32 (bitconvert (i64  GPR64:$src))), (FMOVdx $src)>;
6130259698Sdimdef : Pat<(v2f32 (bitconvert (i64  GPR64:$src))), (FMOVdx $src)>;
6131259698Sdimdef : Pat<(v4i16 (bitconvert (i64  GPR64:$src))), (FMOVdx $src)>;
6132259698Sdimdef : Pat<(v8i8 (bitconvert (i64  GPR64:$src))), (FMOVdx $src)>;
6133259698Sdim
6134259698Sdimdef : Pat<(v1i32 (bitconvert (i32  GPR32:$src))), (FMOVsw $src)>;
6135259698Sdim
6136259698Sdimdef : Pat<(v8i8   (bitconvert (f64   FPR64:$src))), (v8i8 FPR64:$src)>;
6137259698Sdimdef : Pat<(v4i16  (bitconvert (f64   FPR64:$src))), (v4i16 FPR64:$src)>;
6138259698Sdimdef : Pat<(v2i32  (bitconvert (f64   FPR64:$src))), (v2i32 FPR64:$src)>;
6139259698Sdimdef : Pat<(v2f32  (bitconvert (f64   FPR64:$src))), (v2f32 FPR64:$src)>;
6140259698Sdimdef : Pat<(v1i64  (bitconvert (f64   FPR64:$src))), (v1i64 FPR64:$src)>;
6141259698Sdim
6142259698Sdimdef : Pat<(v16i8  (bitconvert (f128   FPR128:$src))), (v16i8 FPR128:$src)>;
6143259698Sdimdef : Pat<(v8i16  (bitconvert (f128   FPR128:$src))), (v8i16 FPR128:$src)>;
6144259698Sdimdef : Pat<(v4i32  (bitconvert (f128   FPR128:$src))), (v4i32 FPR128:$src)>;
6145259698Sdimdef : Pat<(v2i64  (bitconvert (f128   FPR128:$src))), (v2i64 FPR128:$src)>;
6146259698Sdimdef : Pat<(v4f32  (bitconvert (f128   FPR128:$src))), (v4f32 FPR128:$src)>;
6147259698Sdimdef : Pat<(v2f64  (bitconvert (f128   FPR128:$src))), (v2f64 FPR128:$src)>;
6148259698Sdim
6149259698Sdim// Scalar Three Same
6150259698Sdim
6151259698Sdimdef neon_uimm3 : Operand<i64>,
6152259698Sdim                   ImmLeaf<i64, [{return Imm < 8;}]> {
6153259698Sdim  let ParserMatchClass = uimm3_asmoperand;
6154259698Sdim  let PrintMethod = "printUImmHexOperand";
6155259698Sdim}
6156259698Sdim
6157259698Sdimdef neon_uimm4 : Operand<i64>,
6158259698Sdim                   ImmLeaf<i64, [{return Imm < 16;}]> {
6159259698Sdim  let ParserMatchClass = uimm4_asmoperand;
6160259698Sdim  let PrintMethod = "printUImmHexOperand";
6161259698Sdim}
6162259698Sdim
6163259698Sdim// Bitwise Extract
6164259698Sdimclass NeonI_Extract<bit q, bits<2> op2, string asmop,
6165259698Sdim                    string OpS, RegisterOperand OpVPR, Operand OpImm>
6166259698Sdim  : NeonI_BitExtract<q, op2, (outs OpVPR:$Rd),
6167259698Sdim                     (ins OpVPR:$Rn, OpVPR:$Rm, OpImm:$Index),
6168259698Sdim                     asmop # "\t$Rd." # OpS # ", $Rn." # OpS #
6169259698Sdim                     ", $Rm." # OpS # ", $Index",
6170259698Sdim                     [],
6171259698Sdim                     NoItinerary>{
6172259698Sdim  bits<4> Index;
6173259698Sdim}
6174259698Sdim
6175259698Sdimdef EXTvvvi_8b : NeonI_Extract<0b0, 0b00, "ext", "8b",
6176259698Sdim                               VPR64, neon_uimm3> {
6177259698Sdim  let Inst{14-11} = {0b0, Index{2}, Index{1}, Index{0}};
6178259698Sdim}
6179259698Sdim
6180259698Sdimdef EXTvvvi_16b: NeonI_Extract<0b1, 0b00, "ext", "16b",
6181259698Sdim                               VPR128, neon_uimm4> {
6182259698Sdim  let Inst{14-11} = Index;
6183259698Sdim}
6184259698Sdim
6185259698Sdimclass NI_Extract<ValueType OpTy, RegisterOperand OpVPR, Instruction INST,
6186259698Sdim                 Operand OpImm>
6187259698Sdim  : Pat<(OpTy (Neon_vextract (OpTy OpVPR:$Rn), (OpTy OpVPR:$Rm),
6188259698Sdim                                 (i64 OpImm:$Imm))),
6189259698Sdim              (INST OpVPR:$Rn, OpVPR:$Rm, OpImm:$Imm)>;
6190259698Sdim
6191259698Sdimdef : NI_Extract<v8i8,  VPR64,  EXTvvvi_8b,  neon_uimm3>;
6192259698Sdimdef : NI_Extract<v4i16, VPR64,  EXTvvvi_8b,  neon_uimm3>;
6193259698Sdimdef : NI_Extract<v2i32, VPR64,  EXTvvvi_8b,  neon_uimm3>;
6194259698Sdimdef : NI_Extract<v1i64, VPR64,  EXTvvvi_8b,  neon_uimm3>;
6195259698Sdimdef : NI_Extract<v2f32, VPR64,  EXTvvvi_8b,  neon_uimm3>;
6196259698Sdimdef : NI_Extract<v1f64, VPR64,  EXTvvvi_8b,  neon_uimm3>;
6197259698Sdimdef : NI_Extract<v16i8, VPR128, EXTvvvi_16b, neon_uimm4>;
6198259698Sdimdef : NI_Extract<v8i16, VPR128, EXTvvvi_16b, neon_uimm4>;
6199259698Sdimdef : NI_Extract<v4i32, VPR128, EXTvvvi_16b, neon_uimm4>;
6200259698Sdimdef : NI_Extract<v2i64, VPR128, EXTvvvi_16b, neon_uimm4>;
6201259698Sdimdef : NI_Extract<v4f32, VPR128, EXTvvvi_16b, neon_uimm4>;
6202259698Sdimdef : NI_Extract<v2f64, VPR128, EXTvvvi_16b, neon_uimm4>;
6203259698Sdim
6204259698Sdim// Table lookup
6205259698Sdimclass NI_TBL<bit q, bits<2> op2, bits<2> len, bit op,
6206259698Sdim             string asmop, string OpS, RegisterOperand OpVPR,
6207259698Sdim             RegisterOperand VecList>
6208259698Sdim  : NeonI_TBL<q, op2, len, op,
6209259698Sdim              (outs OpVPR:$Rd), (ins VecList:$Rn, OpVPR:$Rm),
6210259698Sdim              asmop # "\t$Rd." # OpS # ", $Rn, $Rm." # OpS,
6211259698Sdim              [],
6212259698Sdim              NoItinerary>;
6213259698Sdim
6214259698Sdim// The vectors in look up table are always 16b
6215259698Sdimmulticlass NI_TBL_pat<bits<2> len, bit op, string asmop, string List> {
6216259698Sdim  def _8b  : NI_TBL<0, 0b00, len, op, asmop, "8b", VPR64,
6217259698Sdim                    !cast<RegisterOperand>(List # "16B_operand")>;
6218259698Sdim
6219259698Sdim  def _16b : NI_TBL<1, 0b00, len, op, asmop, "16b", VPR128,
6220259698Sdim                    !cast<RegisterOperand>(List # "16B_operand")>;
6221259698Sdim}
6222259698Sdim
6223259698Sdimdefm TBL1 : NI_TBL_pat<0b00, 0b0, "tbl", "VOne">;
6224259698Sdimdefm TBL2 : NI_TBL_pat<0b01, 0b0, "tbl", "VPair">;
6225259698Sdimdefm TBL3 : NI_TBL_pat<0b10, 0b0, "tbl", "VTriple">;
6226259698Sdimdefm TBL4 : NI_TBL_pat<0b11, 0b0, "tbl", "VQuad">;
6227259698Sdim
6228259698Sdim// Table lookup extention
6229259698Sdimclass NI_TBX<bit q, bits<2> op2, bits<2> len, bit op,
6230259698Sdim             string asmop, string OpS, RegisterOperand OpVPR,
6231259698Sdim             RegisterOperand VecList>
6232259698Sdim  : NeonI_TBL<q, op2, len, op,
6233259698Sdim              (outs OpVPR:$Rd), (ins OpVPR:$src, VecList:$Rn, OpVPR:$Rm),
6234259698Sdim              asmop # "\t$Rd." # OpS # ", $Rn, $Rm." # OpS,
6235259698Sdim              [],
6236259698Sdim              NoItinerary> {
6237259698Sdim  let Constraints = "$src = $Rd";
6238259698Sdim}
6239259698Sdim
6240259698Sdim// The vectors in look up table are always 16b
6241259698Sdimmulticlass NI_TBX_pat<bits<2> len, bit op, string asmop, string List> {
6242259698Sdim  def _8b  : NI_TBX<0, 0b00, len, op, asmop, "8b", VPR64,
6243259698Sdim                    !cast<RegisterOperand>(List # "16B_operand")>;
6244259698Sdim
6245259698Sdim  def _16b : NI_TBX<1, 0b00, len, op, asmop, "16b", VPR128,
6246259698Sdim                    !cast<RegisterOperand>(List # "16B_operand")>;
6247259698Sdim}
6248259698Sdim
6249259698Sdimdefm TBX1 : NI_TBX_pat<0b00, 0b1, "tbx", "VOne">;
6250259698Sdimdefm TBX2 : NI_TBX_pat<0b01, 0b1, "tbx", "VPair">;
6251259698Sdimdefm TBX3 : NI_TBX_pat<0b10, 0b1, "tbx", "VTriple">;
6252259698Sdimdefm TBX4 : NI_TBX_pat<0b11, 0b1, "tbx", "VQuad">;
6253259698Sdim
6254259698Sdimclass NeonI_INS_main<string asmop, string Res, ValueType ResTy,
6255259698Sdim                     RegisterClass OpGPR, ValueType OpTy, Operand OpImm>
6256259698Sdim  : NeonI_copy<0b1, 0b0, 0b0011,
6257259698Sdim               (outs VPR128:$Rd), (ins VPR128:$src, OpGPR:$Rn, OpImm:$Imm),
6258259698Sdim               asmop # "\t$Rd." # Res # "[$Imm], $Rn",
6259259698Sdim               [(set (ResTy VPR128:$Rd),
6260259698Sdim                 (ResTy (vector_insert
6261259698Sdim                   (ResTy VPR128:$src),
6262259698Sdim                   (OpTy OpGPR:$Rn),
6263259698Sdim                   (OpImm:$Imm))))],
6264259698Sdim               NoItinerary> {
6265259698Sdim  bits<4> Imm;
6266259698Sdim  let Constraints = "$src = $Rd";
6267259698Sdim}
6268259698Sdim
6269259698Sdim//Insert element (vector, from main)
6270259698Sdimdef INSbw : NeonI_INS_main<"ins", "b", v16i8, GPR32, i32,
6271259698Sdim                           neon_uimm4_bare> {
6272259698Sdim  let Inst{20-16} = {Imm{3}, Imm{2}, Imm{1}, Imm{0}, 0b1};
6273259698Sdim}
6274259698Sdimdef INShw : NeonI_INS_main<"ins", "h", v8i16, GPR32, i32,
6275259698Sdim                           neon_uimm3_bare> {
6276259698Sdim  let Inst{20-16} = {Imm{2}, Imm{1}, Imm{0}, 0b1, 0b0};
6277259698Sdim}
6278259698Sdimdef INSsw : NeonI_INS_main<"ins", "s", v4i32, GPR32, i32,
6279259698Sdim                           neon_uimm2_bare> {
6280259698Sdim  let Inst{20-16} = {Imm{1}, Imm{0}, 0b1, 0b0, 0b0};
6281259698Sdim}
6282259698Sdimdef INSdx : NeonI_INS_main<"ins", "d", v2i64, GPR64, i64,
6283259698Sdim                           neon_uimm1_bare> {
6284259698Sdim  let Inst{20-16} = {Imm, 0b1, 0b0, 0b0, 0b0};
6285259698Sdim}
6286259698Sdim
6287259698Sdimdef : NeonInstAlias<"mov $Rd.b[$Imm], $Rn",
6288259698Sdim                    (INSbw VPR128:$Rd, GPR32:$Rn, neon_uimm4_bare:$Imm), 0>;
6289259698Sdimdef : NeonInstAlias<"mov $Rd.h[$Imm], $Rn",
6290259698Sdim                    (INShw VPR128:$Rd, GPR32:$Rn, neon_uimm3_bare:$Imm), 0>;
6291259698Sdimdef : NeonInstAlias<"mov $Rd.s[$Imm], $Rn",
6292259698Sdim                    (INSsw VPR128:$Rd, GPR32:$Rn, neon_uimm2_bare:$Imm), 0>;
6293259698Sdimdef : NeonInstAlias<"mov $Rd.d[$Imm], $Rn",
6294259698Sdim                    (INSdx VPR128:$Rd, GPR64:$Rn, neon_uimm1_bare:$Imm), 0>;
6295259698Sdim
6296259698Sdimclass Neon_INS_main_pattern <ValueType ResTy,ValueType ExtResTy,
6297259698Sdim                             RegisterClass OpGPR, ValueType OpTy,
6298259698Sdim                             Operand OpImm, Instruction INS>
6299259698Sdim  : Pat<(ResTy (vector_insert
6300259698Sdim              (ResTy VPR64:$src),
6301259698Sdim              (OpTy OpGPR:$Rn),
6302259698Sdim              (OpImm:$Imm))),
6303259698Sdim        (ResTy (EXTRACT_SUBREG
6304259698Sdim          (ExtResTy (INS (ExtResTy (SUBREG_TO_REG (i64 0), VPR64:$src, sub_64)),
6305259698Sdim            OpGPR:$Rn, OpImm:$Imm)), sub_64))>;
6306259698Sdim
6307259698Sdimdef INSbw_pattern : Neon_INS_main_pattern<v8i8, v16i8, GPR32, i32,
6308259698Sdim                                          neon_uimm3_bare, INSbw>;
6309259698Sdimdef INShw_pattern : Neon_INS_main_pattern<v4i16, v8i16, GPR32, i32,
6310259698Sdim                                          neon_uimm2_bare, INShw>;
6311259698Sdimdef INSsw_pattern : Neon_INS_main_pattern<v2i32, v4i32, GPR32, i32,
6312259698Sdim                                          neon_uimm1_bare, INSsw>;
6313259698Sdimdef INSdx_pattern : Neon_INS_main_pattern<v1i64, v2i64, GPR64, i64,
6314259698Sdim                                          neon_uimm0_bare, INSdx>;
6315259698Sdim
6316259698Sdimclass NeonI_INS_element<string asmop, string Res, Operand ResImm>
6317259698Sdim  : NeonI_insert<0b1, 0b1,
6318259698Sdim                 (outs VPR128:$Rd), (ins VPR128:$src, VPR128:$Rn,
6319259698Sdim                 ResImm:$Immd, ResImm:$Immn),
6320259698Sdim                 asmop # "\t$Rd." # Res # "[$Immd], $Rn." # Res # "[$Immn]",
6321259698Sdim                 [],
6322259698Sdim                 NoItinerary> {
6323259698Sdim  let Constraints = "$src = $Rd";
6324259698Sdim  bits<4> Immd;
6325259698Sdim  bits<4> Immn;
6326259698Sdim}
6327259698Sdim
6328259698Sdim//Insert element (vector, from element)
6329259698Sdimdef INSELb : NeonI_INS_element<"ins", "b", neon_uimm4_bare> {
6330259698Sdim  let Inst{20-16} = {Immd{3}, Immd{2}, Immd{1}, Immd{0}, 0b1};
6331259698Sdim  let Inst{14-11} = {Immn{3}, Immn{2}, Immn{1}, Immn{0}};
6332259698Sdim}
6333259698Sdimdef INSELh : NeonI_INS_element<"ins", "h", neon_uimm3_bare> {
6334259698Sdim  let Inst{20-16} = {Immd{2}, Immd{1}, Immd{0}, 0b1, 0b0};
6335259698Sdim  let Inst{14-11} = {Immn{2}, Immn{1}, Immn{0}, 0b0};
6336259698Sdim  // bit 11 is unspecified, but should be set to zero.
6337259698Sdim}
6338259698Sdimdef INSELs : NeonI_INS_element<"ins", "s", neon_uimm2_bare> {
6339259698Sdim  let Inst{20-16} = {Immd{1}, Immd{0}, 0b1, 0b0, 0b0};
6340259698Sdim  let Inst{14-11} = {Immn{1}, Immn{0}, 0b0, 0b0};
6341259698Sdim  // bits 11-12 are unspecified, but should be set to zero.
6342259698Sdim}
6343259698Sdimdef INSELd : NeonI_INS_element<"ins", "d", neon_uimm1_bare> {
6344259698Sdim  let Inst{20-16} = {Immd, 0b1, 0b0, 0b0, 0b0};
6345259698Sdim  let Inst{14-11} = {Immn{0}, 0b0, 0b0, 0b0};
6346259698Sdim  // bits 11-13 are unspecified, but should be set to zero.
6347259698Sdim}
6348259698Sdim
6349259698Sdimdef : NeonInstAlias<"mov $Rd.b[$Immd], $Rn.b[$Immn]",
6350259698Sdim                    (INSELb VPR128:$Rd, VPR128:$Rn,
6351259698Sdim                      neon_uimm4_bare:$Immd, neon_uimm4_bare:$Immn), 0>;
6352259698Sdimdef : NeonInstAlias<"mov $Rd.h[$Immd], $Rn.h[$Immn]",
6353259698Sdim                    (INSELh VPR128:$Rd, VPR128:$Rn,
6354259698Sdim                      neon_uimm3_bare:$Immd, neon_uimm3_bare:$Immn), 0>;
6355259698Sdimdef : NeonInstAlias<"mov $Rd.s[$Immd], $Rn.s[$Immn]",
6356259698Sdim                    (INSELs VPR128:$Rd, VPR128:$Rn,
6357259698Sdim                      neon_uimm2_bare:$Immd, neon_uimm2_bare:$Immn), 0>;
6358259698Sdimdef : NeonInstAlias<"mov $Rd.d[$Immd], $Rn.d[$Immn]",
6359259698Sdim                    (INSELd VPR128:$Rd, VPR128:$Rn,
6360259698Sdim                      neon_uimm1_bare:$Immd, neon_uimm1_bare:$Immn), 0>;
6361259698Sdim
6362259698Sdimmulticlass Neon_INS_elt_pattern<ValueType ResTy, ValueType NaTy,
6363259698Sdim                                ValueType MidTy, Operand StImm, Operand NaImm,
6364259698Sdim                                Instruction INS> {
6365259698Sdimdef : Pat<(ResTy (vector_insert
6366259698Sdim            (ResTy VPR128:$src),
6367259698Sdim            (MidTy (vector_extract
6368259698Sdim              (ResTy VPR128:$Rn),
6369259698Sdim              (StImm:$Immn))),
6370259698Sdim            (StImm:$Immd))),
6371259698Sdim          (INS (ResTy VPR128:$src), (ResTy VPR128:$Rn),
6372259698Sdim              StImm:$Immd, StImm:$Immn)>;
6373259698Sdim
6374259698Sdimdef : Pat <(ResTy (vector_insert
6375259698Sdim             (ResTy VPR128:$src),
6376259698Sdim             (MidTy (vector_extract
6377259698Sdim               (NaTy VPR64:$Rn),
6378259698Sdim               (NaImm:$Immn))),
6379259698Sdim             (StImm:$Immd))),
6380259698Sdim           (INS (ResTy VPR128:$src),
6381259698Sdim             (ResTy (SUBREG_TO_REG (i64 0), (NaTy VPR64:$Rn), sub_64)),
6382259698Sdim             StImm:$Immd, NaImm:$Immn)>;
6383259698Sdim
6384259698Sdimdef : Pat <(NaTy (vector_insert
6385259698Sdim             (NaTy VPR64:$src),
6386259698Sdim             (MidTy (vector_extract
6387259698Sdim               (ResTy VPR128:$Rn),
6388259698Sdim               (StImm:$Immn))),
6389259698Sdim             (NaImm:$Immd))),
6390259698Sdim           (NaTy (EXTRACT_SUBREG
6391259698Sdim             (ResTy (INS
6392259698Sdim               (ResTy (SUBREG_TO_REG (i64 0), (NaTy VPR64:$src), sub_64)),
6393259698Sdim               (ResTy VPR128:$Rn),
6394259698Sdim               NaImm:$Immd, StImm:$Immn)),
6395259698Sdim             sub_64))>;
6396259698Sdim
6397259698Sdimdef : Pat <(NaTy (vector_insert
6398259698Sdim             (NaTy VPR64:$src),
6399259698Sdim             (MidTy (vector_extract
6400259698Sdim               (NaTy VPR64:$Rn),
6401259698Sdim               (NaImm:$Immn))),
6402259698Sdim             (NaImm:$Immd))),
6403259698Sdim           (NaTy (EXTRACT_SUBREG
6404259698Sdim             (ResTy (INS
6405259698Sdim               (ResTy (SUBREG_TO_REG (i64 0), (NaTy VPR64:$src), sub_64)),
6406259698Sdim               (ResTy (SUBREG_TO_REG (i64 0), (NaTy VPR64:$Rn), sub_64)),
6407259698Sdim               NaImm:$Immd, NaImm:$Immn)),
6408259698Sdim             sub_64))>;
6409259698Sdim}
6410259698Sdim
6411259698Sdimdefm : Neon_INS_elt_pattern<v4f32, v2f32, f32, neon_uimm2_bare,
6412259698Sdim                            neon_uimm1_bare, INSELs>;
6413259698Sdimdefm : Neon_INS_elt_pattern<v2f64, v1f64, f64, neon_uimm1_bare,
6414259698Sdim                            neon_uimm0_bare, INSELd>;
6415259698Sdimdefm : Neon_INS_elt_pattern<v16i8, v8i8, i32, neon_uimm4_bare,
6416259698Sdim                            neon_uimm3_bare, INSELb>;
6417259698Sdimdefm : Neon_INS_elt_pattern<v8i16, v4i16, i32, neon_uimm3_bare,
6418259698Sdim                            neon_uimm2_bare, INSELh>;
6419259698Sdimdefm : Neon_INS_elt_pattern<v4i32, v2i32, i32, neon_uimm2_bare,
6420259698Sdim                            neon_uimm1_bare, INSELs>;
6421259698Sdimdefm : Neon_INS_elt_pattern<v2i64, v1i64, i64, neon_uimm1_bare,
6422259698Sdim                            neon_uimm0_bare, INSELd>;
6423259698Sdim
6424259698Sdimmulticlass Neon_INS_elt_float_pattern<ValueType ResTy, ValueType NaTy,
6425259698Sdim                                      ValueType MidTy,
6426259698Sdim                                      RegisterClass OpFPR, Operand ResImm,
6427259698Sdim                                      SubRegIndex SubIndex, Instruction INS> {
6428259698Sdimdef : Pat <(ResTy (vector_insert
6429259698Sdim             (ResTy VPR128:$src),
6430259698Sdim             (MidTy OpFPR:$Rn),
6431259698Sdim             (ResImm:$Imm))),
6432259698Sdim           (INS (ResTy VPR128:$src),
6433259698Sdim             (ResTy (SUBREG_TO_REG (i64 0), OpFPR:$Rn, SubIndex)),
6434259698Sdim             ResImm:$Imm,
6435259698Sdim             (i64 0))>;
6436259698Sdim
6437259698Sdimdef : Pat <(NaTy (vector_insert
6438259698Sdim             (NaTy VPR64:$src),
6439259698Sdim             (MidTy OpFPR:$Rn),
6440259698Sdim             (ResImm:$Imm))),
6441259698Sdim           (NaTy (EXTRACT_SUBREG
6442259698Sdim             (ResTy (INS
6443259698Sdim               (ResTy (SUBREG_TO_REG (i64 0), (NaTy VPR64:$src), sub_64)),
6444259698Sdim               (ResTy (SUBREG_TO_REG (i64 0), (MidTy OpFPR:$Rn), SubIndex)),
6445259698Sdim               ResImm:$Imm,
6446259698Sdim               (i64 0))),
6447259698Sdim             sub_64))>;
6448259698Sdim}
6449259698Sdim
6450259698Sdimdefm : Neon_INS_elt_float_pattern<v4f32, v2f32, f32, FPR32, neon_uimm2_bare,
6451259698Sdim                                  sub_32, INSELs>;
6452259698Sdimdefm : Neon_INS_elt_float_pattern<v2f64, v1f64, f64, FPR64, neon_uimm1_bare,
6453259698Sdim                                  sub_64, INSELd>;
6454259698Sdim
6455259698Sdimclass NeonI_SMOV<string asmop, string Res, bit Q,
6456259698Sdim                 ValueType OpTy, ValueType eleTy,
6457259698Sdim                 Operand OpImm, RegisterClass ResGPR, ValueType ResTy>
6458259698Sdim  : NeonI_copy<Q, 0b0, 0b0101,
6459259698Sdim               (outs ResGPR:$Rd), (ins VPR128:$Rn, OpImm:$Imm),
6460259698Sdim               asmop # "\t$Rd, $Rn." # Res # "[$Imm]",
6461259698Sdim               [(set (ResTy ResGPR:$Rd),
6462259698Sdim                 (ResTy (sext_inreg
6463259698Sdim                   (ResTy (vector_extract
6464259698Sdim                     (OpTy VPR128:$Rn), (OpImm:$Imm))),
6465259698Sdim                   eleTy)))],
6466259698Sdim               NoItinerary> {
6467259698Sdim  bits<4> Imm;
6468259698Sdim}
6469259698Sdim
6470259698Sdim//Signed integer move (main, from element)
6471259698Sdimdef SMOVwb : NeonI_SMOV<"smov", "b", 0b0, v16i8, i8, neon_uimm4_bare,
6472259698Sdim                        GPR32, i32> {
6473259698Sdim  let Inst{20-16} = {Imm{3}, Imm{2}, Imm{1}, Imm{0}, 0b1};
6474259698Sdim}
6475259698Sdimdef SMOVwh : NeonI_SMOV<"smov", "h", 0b0, v8i16, i16, neon_uimm3_bare,
6476259698Sdim                        GPR32, i32> {
6477259698Sdim  let Inst{20-16} = {Imm{2}, Imm{1}, Imm{0}, 0b1, 0b0};
6478259698Sdim}
6479259698Sdimdef SMOVxb : NeonI_SMOV<"smov", "b", 0b1, v16i8, i8, neon_uimm4_bare,
6480259698Sdim                        GPR64, i64> {
6481259698Sdim  let Inst{20-16} = {Imm{3}, Imm{2}, Imm{1}, Imm{0}, 0b1};
6482259698Sdim}
6483259698Sdimdef SMOVxh : NeonI_SMOV<"smov", "h", 0b1, v8i16, i16, neon_uimm3_bare,
6484259698Sdim                        GPR64, i64> {
6485259698Sdim  let Inst{20-16} = {Imm{2}, Imm{1}, Imm{0}, 0b1, 0b0};
6486259698Sdim}
6487259698Sdimdef SMOVxs : NeonI_SMOV<"smov", "s", 0b1, v4i32, i32, neon_uimm2_bare,
6488259698Sdim                        GPR64, i64> {
6489259698Sdim  let Inst{20-16} = {Imm{1}, Imm{0}, 0b1, 0b0, 0b0};
6490259698Sdim}
6491259698Sdim
6492259698Sdimmulticlass Neon_SMOVx_pattern <ValueType StTy, ValueType NaTy,
6493259698Sdim                               ValueType eleTy, Operand StImm,  Operand NaImm,
6494259698Sdim                               Instruction SMOVI> {
6495259698Sdim  def : Pat<(i64 (sext_inreg
6496259698Sdim              (i64 (anyext
6497259698Sdim                (i32 (vector_extract
6498259698Sdim                  (StTy VPR128:$Rn), (StImm:$Imm))))),
6499259698Sdim              eleTy)),
6500259698Sdim            (SMOVI VPR128:$Rn, StImm:$Imm)>;
6501259698Sdim
6502259698Sdim  def : Pat<(i64 (sext
6503259698Sdim              (i32 (vector_extract
6504259698Sdim                (StTy VPR128:$Rn), (StImm:$Imm))))),
6505259698Sdim            (SMOVI VPR128:$Rn, StImm:$Imm)>;
6506259698Sdim
6507259698Sdim  def : Pat<(i64 (sext_inreg
6508259698Sdim              (i64 (vector_extract
6509259698Sdim                (NaTy VPR64:$Rn), (NaImm:$Imm))),
6510259698Sdim              eleTy)),
6511259698Sdim            (SMOVI (StTy (SUBREG_TO_REG (i64 0), VPR64:$Rn, sub_64)),
6512259698Sdim              NaImm:$Imm)>;
6513259698Sdim
6514259698Sdim  def : Pat<(i64 (sext_inreg
6515259698Sdim              (i64 (anyext
6516259698Sdim                (i32 (vector_extract
6517259698Sdim                  (NaTy VPR64:$Rn), (NaImm:$Imm))))),
6518259698Sdim              eleTy)),
6519259698Sdim            (SMOVI (StTy (SUBREG_TO_REG (i64 0), VPR64:$Rn, sub_64)),
6520259698Sdim              NaImm:$Imm)>;
6521259698Sdim
6522259698Sdim  def : Pat<(i64 (sext
6523259698Sdim              (i32 (vector_extract
6524259698Sdim                (NaTy VPR64:$Rn), (NaImm:$Imm))))),
6525259698Sdim            (SMOVI (StTy (SUBREG_TO_REG (i64 0), VPR64:$Rn, sub_64)),
6526259698Sdim              NaImm:$Imm)>;
6527259698Sdim}
6528259698Sdim
6529259698Sdimdefm : Neon_SMOVx_pattern<v16i8, v8i8, i8, neon_uimm4_bare,
6530259698Sdim                          neon_uimm3_bare, SMOVxb>;
6531259698Sdimdefm : Neon_SMOVx_pattern<v8i16, v4i16, i16, neon_uimm3_bare,
6532259698Sdim                          neon_uimm2_bare, SMOVxh>;
6533259698Sdimdefm : Neon_SMOVx_pattern<v4i32, v2i32, i32, neon_uimm2_bare,
6534259698Sdim                          neon_uimm1_bare, SMOVxs>;
6535259698Sdim
6536259698Sdimclass Neon_SMOVw_pattern <ValueType StTy, ValueType NaTy,
6537259698Sdim                          ValueType eleTy, Operand StImm,  Operand NaImm,
6538259698Sdim                          Instruction SMOVI>
6539259698Sdim  : Pat<(i32 (sext_inreg
6540259698Sdim          (i32 (vector_extract
6541259698Sdim            (NaTy VPR64:$Rn), (NaImm:$Imm))),
6542259698Sdim          eleTy)),
6543259698Sdim        (SMOVI (StTy (SUBREG_TO_REG (i64 0), VPR64:$Rn, sub_64)),
6544259698Sdim          NaImm:$Imm)>;
6545259698Sdim
6546259698Sdimdef : Neon_SMOVw_pattern<v16i8, v8i8, i8, neon_uimm4_bare,
6547259698Sdim                         neon_uimm3_bare, SMOVwb>;
6548259698Sdimdef : Neon_SMOVw_pattern<v8i16, v4i16, i16, neon_uimm3_bare,
6549259698Sdim                         neon_uimm2_bare, SMOVwh>;
6550259698Sdim
6551259698Sdimclass NeonI_UMOV<string asmop, string Res, bit Q,
6552259698Sdim                 ValueType OpTy, Operand OpImm,
6553259698Sdim                 RegisterClass ResGPR, ValueType ResTy>
6554259698Sdim  : NeonI_copy<Q, 0b0, 0b0111,
6555259698Sdim               (outs ResGPR:$Rd), (ins VPR128:$Rn, OpImm:$Imm),
6556259698Sdim               asmop # "\t$Rd, $Rn." # Res # "[$Imm]",
6557259698Sdim               [(set (ResTy ResGPR:$Rd),
6558259698Sdim                  (ResTy (vector_extract
6559259698Sdim                    (OpTy VPR128:$Rn), (OpImm:$Imm))))],
6560259698Sdim               NoItinerary> {
6561259698Sdim  bits<4> Imm;
6562259698Sdim}
6563259698Sdim
6564259698Sdim//Unsigned integer move (main, from element)
6565259698Sdimdef UMOVwb : NeonI_UMOV<"umov", "b", 0b0, v16i8, neon_uimm4_bare,
6566259698Sdim                         GPR32, i32> {
6567259698Sdim  let Inst{20-16} = {Imm{3}, Imm{2}, Imm{1}, Imm{0}, 0b1};
6568259698Sdim}
6569259698Sdimdef UMOVwh : NeonI_UMOV<"umov", "h", 0b0, v8i16, neon_uimm3_bare,
6570259698Sdim                         GPR32, i32> {
6571259698Sdim  let Inst{20-16} = {Imm{2}, Imm{1}, Imm{0}, 0b1, 0b0};
6572259698Sdim}
6573259698Sdimdef UMOVws : NeonI_UMOV<"umov", "s", 0b0, v4i32, neon_uimm2_bare,
6574259698Sdim                         GPR32, i32> {
6575259698Sdim  let Inst{20-16} = {Imm{1}, Imm{0}, 0b1, 0b0, 0b0};
6576259698Sdim}
6577259698Sdimdef UMOVxd : NeonI_UMOV<"umov", "d", 0b1, v2i64, neon_uimm1_bare,
6578259698Sdim                         GPR64, i64> {
6579259698Sdim  let Inst{20-16} = {Imm, 0b1, 0b0, 0b0, 0b0};
6580259698Sdim}
6581259698Sdim
6582259698Sdimdef : NeonInstAlias<"mov $Rd, $Rn.s[$Imm]",
6583259698Sdim                    (UMOVws GPR32:$Rd, VPR128:$Rn, neon_uimm2_bare:$Imm), 0>;
6584259698Sdimdef : NeonInstAlias<"mov $Rd, $Rn.d[$Imm]",
6585259698Sdim                    (UMOVxd GPR64:$Rd, VPR128:$Rn, neon_uimm1_bare:$Imm), 0>;
6586259698Sdim
6587259698Sdimclass Neon_UMOV_pattern <ValueType StTy, ValueType NaTy, ValueType ResTy,
6588259698Sdim                         Operand StImm,  Operand NaImm,
6589259698Sdim                         Instruction SMOVI>
6590259698Sdim  : Pat<(ResTy (vector_extract
6591259698Sdim          (NaTy VPR64:$Rn), NaImm:$Imm)),
6592259698Sdim        (SMOVI (StTy (SUBREG_TO_REG (i64 0), VPR64:$Rn, sub_64)),
6593259698Sdim          NaImm:$Imm)>;
6594259698Sdim
6595259698Sdimdef : Neon_UMOV_pattern<v16i8, v8i8, i32, neon_uimm4_bare,
6596259698Sdim                        neon_uimm3_bare, UMOVwb>;
6597259698Sdimdef : Neon_UMOV_pattern<v8i16, v4i16, i32, neon_uimm3_bare,
6598259698Sdim                        neon_uimm2_bare, UMOVwh>;
6599259698Sdimdef : Neon_UMOV_pattern<v4i32, v2i32, i32, neon_uimm2_bare,
6600259698Sdim                        neon_uimm1_bare, UMOVws>;
6601259698Sdim
6602259698Sdimdef : Pat<(i32 (and
6603259698Sdim            (i32 (vector_extract
6604259698Sdim              (v16i8 VPR128:$Rn), (neon_uimm4_bare:$Imm))),
6605259698Sdim            255)),
6606259698Sdim          (UMOVwb VPR128:$Rn, neon_uimm4_bare:$Imm)>;
6607259698Sdim
6608259698Sdimdef : Pat<(i32 (and
6609259698Sdim            (i32 (vector_extract
6610259698Sdim              (v8i16 VPR128:$Rn), (neon_uimm3_bare:$Imm))),
6611259698Sdim            65535)),
6612259698Sdim          (UMOVwh VPR128:$Rn, neon_uimm3_bare:$Imm)>;
6613259698Sdim
6614259698Sdimdef : Pat<(i64 (zext
6615259698Sdim            (i32 (vector_extract
6616259698Sdim              (v2i64 VPR128:$Rn), (neon_uimm1_bare:$Imm))))),
6617259698Sdim          (UMOVxd VPR128:$Rn, neon_uimm1_bare:$Imm)>;
6618259698Sdim
6619259698Sdimdef : Pat<(i32 (and
6620259698Sdim            (i32 (vector_extract
6621259698Sdim              (v8i8 VPR64:$Rn), (neon_uimm3_bare:$Imm))),
6622259698Sdim            255)),
6623259698Sdim          (UMOVwb (SUBREG_TO_REG (i64 0), VPR64:$Rn, sub_64),
6624259698Sdim            neon_uimm3_bare:$Imm)>;
6625259698Sdim
6626259698Sdimdef : Pat<(i32 (and
6627259698Sdim            (i32 (vector_extract
6628259698Sdim              (v4i16 VPR64:$Rn), (neon_uimm2_bare:$Imm))),
6629259698Sdim            65535)),
6630259698Sdim          (UMOVwh (SUBREG_TO_REG (i64 0), VPR64:$Rn, sub_64),
6631259698Sdim            neon_uimm2_bare:$Imm)>;
6632259698Sdim
6633259698Sdimdef : Pat<(i64 (zext
6634259698Sdim            (i32 (vector_extract
6635259698Sdim              (v1i64 VPR64:$Rn), (neon_uimm0_bare:$Imm))))),
6636259698Sdim          (UMOVxd (SUBREG_TO_REG (i64 0), VPR64:$Rn, sub_64),
6637259698Sdim            neon_uimm0_bare:$Imm)>;
6638259698Sdim
6639259698Sdim// Additional copy patterns for scalar types
6640259698Sdimdef : Pat<(i32 (vector_extract (v1i8 FPR8:$Rn), (i64 0))),
6641259698Sdim          (UMOVwb (v16i8
6642259698Sdim            (SUBREG_TO_REG (i64 0), FPR8:$Rn, sub_8)), (i64 0))>;
6643259698Sdim
6644259698Sdimdef : Pat<(i32 (vector_extract (v1i16 FPR16:$Rn), (i64 0))),
6645259698Sdim          (UMOVwh (v8i16
6646259698Sdim            (SUBREG_TO_REG (i64 0), FPR16:$Rn, sub_16)), (i64 0))>;
6647259698Sdim
6648259698Sdimdef : Pat<(i32 (vector_extract (v1i32 FPR32:$Rn), (i64 0))),
6649259698Sdim          (FMOVws FPR32:$Rn)>;
6650259698Sdim
6651259698Sdimdef : Pat<(i64 (vector_extract (v1i64 FPR64:$Rn), (i64 0))),
6652259698Sdim          (FMOVxd FPR64:$Rn)>;
6653259698Sdim
6654259698Sdimdef : Pat<(f64 (vector_extract (v1f64 FPR64:$Rn), (i64 0))),
6655259698Sdim          (f64 FPR64:$Rn)>;
6656259698Sdim
6657259698Sdimdef : Pat<(f32 (vector_extract (v1f32 FPR32:$Rn), (i64 0))),
6658259698Sdim          (f32 FPR32:$Rn)>;
6659259698Sdim
6660259698Sdimdef : Pat<(v1i8 (scalar_to_vector GPR32:$Rn)),
6661259698Sdim          (v1i8 (EXTRACT_SUBREG (v16i8
6662259698Sdim            (INSbw (v16i8 (IMPLICIT_DEF)), $Rn, (i64 0))),
6663259698Sdim            sub_8))>;
6664259698Sdim
6665259698Sdimdef : Pat<(v1i16 (scalar_to_vector GPR32:$Rn)),
6666259698Sdim          (v1i16 (EXTRACT_SUBREG (v8i16
6667259698Sdim            (INShw (v8i16 (IMPLICIT_DEF)), $Rn, (i64 0))),
6668259698Sdim            sub_16))>;
6669259698Sdim
6670259698Sdimdef : Pat<(v1i32 (scalar_to_vector GPR32:$src)),
6671259698Sdim          (FMOVsw $src)>;
6672259698Sdim
6673259698Sdimdef : Pat<(v1i64 (scalar_to_vector GPR64:$src)),
6674259698Sdim          (FMOVdx $src)>;
6675259698Sdim
6676259698Sdimdef : Pat<(v1f32 (scalar_to_vector (f32 FPR32:$Rn))),
6677259698Sdim          (v1f32 FPR32:$Rn)>;
6678259698Sdimdef : Pat<(v1f64 (scalar_to_vector (f64 FPR64:$Rn))),
6679259698Sdim          (v1f64 FPR64:$Rn)>;
6680259698Sdim
6681259698Sdimdef : Pat<(v1f64 (scalar_to_vector (f64 FPR64:$src))),
6682259698Sdim          (FMOVdd $src)>;
6683259698Sdim
6684259698Sdimdef : Pat<(v2f64 (scalar_to_vector (f64 FPR64:$src))),
6685259698Sdim          (INSERT_SUBREG (v2f64 (IMPLICIT_DEF)),
6686259698Sdim                         (f64 FPR64:$src), sub_64)>;
6687259698Sdim
6688259698Sdimclass NeonI_DUP_Elt<bit Q, string asmop, string rdlane,  string rnlane,
6689259698Sdim                    RegisterOperand ResVPR, Operand OpImm>
6690259698Sdim  : NeonI_copy<Q, 0b0, 0b0000, (outs ResVPR:$Rd),
6691259698Sdim               (ins VPR128:$Rn, OpImm:$Imm),
6692259698Sdim               asmop # "\t$Rd" # rdlane # ", $Rn" # rnlane # "[$Imm]",
6693259698Sdim               [],
6694259698Sdim               NoItinerary> {
6695259698Sdim  bits<4> Imm;
6696259698Sdim}
6697259698Sdim
6698259698Sdimdef DUPELT16b : NeonI_DUP_Elt<0b1, "dup", ".16b", ".b", VPR128,
6699259698Sdim                              neon_uimm4_bare> {
6700259698Sdim  let Inst{20-16} = {Imm{3}, Imm{2}, Imm{1}, Imm{0}, 0b1};
6701259698Sdim}
6702259698Sdim
6703259698Sdimdef DUPELT8h : NeonI_DUP_Elt<0b1, "dup", ".8h", ".h", VPR128,
6704259698Sdim                              neon_uimm3_bare> {
6705259698Sdim  let Inst{20-16} = {Imm{2}, Imm{1}, Imm{0}, 0b1, 0b0};
6706259698Sdim}
6707259698Sdim
6708259698Sdimdef DUPELT4s : NeonI_DUP_Elt<0b1, "dup", ".4s", ".s", VPR128,
6709259698Sdim                              neon_uimm2_bare> {
6710259698Sdim  let Inst{20-16} = {Imm{1}, Imm{0}, 0b1, 0b0, 0b0};
6711259698Sdim}
6712259698Sdim
6713259698Sdimdef DUPELT2d : NeonI_DUP_Elt<0b1, "dup", ".2d", ".d", VPR128,
6714259698Sdim                              neon_uimm1_bare> {
6715259698Sdim  let Inst{20-16} = {Imm, 0b1, 0b0, 0b0, 0b0};
6716259698Sdim}
6717259698Sdim
6718259698Sdimdef DUPELT8b : NeonI_DUP_Elt<0b0, "dup", ".8b", ".b", VPR64,
6719259698Sdim                              neon_uimm4_bare> {
6720259698Sdim  let Inst{20-16} = {Imm{3}, Imm{2}, Imm{1}, Imm{0}, 0b1};
6721259698Sdim}
6722259698Sdim
6723259698Sdimdef DUPELT4h : NeonI_DUP_Elt<0b0, "dup", ".4h", ".h", VPR64,
6724259698Sdim                              neon_uimm3_bare> {
6725259698Sdim  let Inst{20-16} = {Imm{2}, Imm{1}, Imm{0}, 0b1, 0b0};
6726259698Sdim}
6727259698Sdim
6728259698Sdimdef DUPELT2s : NeonI_DUP_Elt<0b0, "dup", ".2s", ".s", VPR64,
6729259698Sdim                              neon_uimm2_bare> {
6730259698Sdim  let Inst{20-16} = {Imm{1}, Imm{0}, 0b1, 0b0, 0b0};
6731259698Sdim}
6732259698Sdim
6733259698Sdimmulticlass NeonI_DUP_Elt_pattern<Instruction DUPELT, ValueType ResTy,
6734259698Sdim                                       ValueType OpTy,ValueType NaTy,
6735259698Sdim                                       ValueType ExTy, Operand OpLImm,
6736259698Sdim                                       Operand OpNImm> {
6737259698Sdimdef  : Pat<(ResTy (Neon_vduplane (OpTy VPR128:$Rn), OpLImm:$Imm)),
6738259698Sdim        (ResTy (DUPELT (OpTy VPR128:$Rn), OpLImm:$Imm))>;
6739259698Sdim
6740259698Sdimdef : Pat<(ResTy (Neon_vduplane
6741259698Sdim            (NaTy VPR64:$Rn), OpNImm:$Imm)),
6742259698Sdim          (ResTy (DUPELT
6743259698Sdim            (ExTy (SUBREG_TO_REG (i64 0), VPR64:$Rn, sub_64)), OpNImm:$Imm))>;
6744259698Sdim}
6745259698Sdimdefm : NeonI_DUP_Elt_pattern<DUPELT16b, v16i8, v16i8, v8i8, v16i8,
6746259698Sdim                             neon_uimm4_bare, neon_uimm3_bare>;
6747259698Sdimdefm : NeonI_DUP_Elt_pattern<DUPELT8b, v8i8, v16i8, v8i8, v16i8,
6748259698Sdim                             neon_uimm4_bare, neon_uimm3_bare>;
6749259698Sdimdefm : NeonI_DUP_Elt_pattern<DUPELT8h, v8i16, v8i16, v4i16, v8i16,
6750259698Sdim                             neon_uimm3_bare, neon_uimm2_bare>;
6751259698Sdimdefm : NeonI_DUP_Elt_pattern<DUPELT4h, v4i16, v8i16, v4i16, v8i16,
6752259698Sdim                             neon_uimm3_bare, neon_uimm2_bare>;
6753259698Sdimdefm : NeonI_DUP_Elt_pattern<DUPELT4s, v4i32, v4i32, v2i32, v4i32,
6754259698Sdim                             neon_uimm2_bare, neon_uimm1_bare>;
6755259698Sdimdefm : NeonI_DUP_Elt_pattern<DUPELT2s, v2i32, v4i32, v2i32, v4i32,
6756259698Sdim                             neon_uimm2_bare, neon_uimm1_bare>;
6757259698Sdimdefm : NeonI_DUP_Elt_pattern<DUPELT2d, v2i64, v2i64, v1i64, v2i64,
6758259698Sdim                             neon_uimm1_bare, neon_uimm0_bare>;
6759259698Sdimdefm : NeonI_DUP_Elt_pattern<DUPELT4s, v4f32, v4f32, v2f32, v4f32,
6760259698Sdim                             neon_uimm2_bare, neon_uimm1_bare>;
6761259698Sdimdefm : NeonI_DUP_Elt_pattern<DUPELT2s, v2f32, v4f32, v2f32, v4f32,
6762259698Sdim                             neon_uimm2_bare, neon_uimm1_bare>;
6763259698Sdimdefm : NeonI_DUP_Elt_pattern<DUPELT2d, v2f64, v2f64, v1f64, v2f64,
6764259698Sdim                             neon_uimm1_bare, neon_uimm0_bare>;
6765259698Sdim
6766259698Sdimdef : Pat<(v2f32 (Neon_vdup (f32 FPR32:$Rn))),
6767259698Sdim          (v2f32 (DUPELT2s
6768259698Sdim            (SUBREG_TO_REG (i64 0), FPR32:$Rn, sub_32),
6769259698Sdim            (i64 0)))>;
6770259698Sdimdef : Pat<(v4f32 (Neon_vdup (f32 FPR32:$Rn))),
6771259698Sdim          (v4f32 (DUPELT4s
6772259698Sdim            (SUBREG_TO_REG (i64 0), FPR32:$Rn, sub_32),
6773259698Sdim            (i64 0)))>;
6774259698Sdimdef : Pat<(v2f64 (Neon_vdup (f64 FPR64:$Rn))),
6775259698Sdim          (v2f64 (DUPELT2d
6776259698Sdim            (SUBREG_TO_REG (i64 0), FPR64:$Rn, sub_64),
6777259698Sdim            (i64 0)))>;
6778259698Sdim
6779259698Sdimclass NeonI_DUP<bit Q, string asmop, string rdlane,
6780259698Sdim                RegisterOperand ResVPR, ValueType ResTy,
6781259698Sdim                RegisterClass OpGPR, ValueType OpTy>
6782259698Sdim  : NeonI_copy<Q, 0b0, 0b0001, (outs ResVPR:$Rd), (ins OpGPR:$Rn),
6783259698Sdim               asmop # "\t$Rd" # rdlane # ", $Rn",
6784259698Sdim               [(set (ResTy ResVPR:$Rd),
6785259698Sdim                 (ResTy (Neon_vdup (OpTy OpGPR:$Rn))))],
6786259698Sdim               NoItinerary>;
6787259698Sdim
6788259698Sdimdef DUP16b : NeonI_DUP<0b1, "dup", ".16b", VPR128, v16i8, GPR32, i32> {
6789259698Sdim  let Inst{20-16} = 0b00001;
6790259698Sdim  // bits 17-20 are unspecified, but should be set to zero.
6791259698Sdim}
6792259698Sdim
6793259698Sdimdef DUP8h : NeonI_DUP<0b1, "dup", ".8h", VPR128, v8i16, GPR32, i32> {
6794259698Sdim  let Inst{20-16} = 0b00010;
6795259698Sdim  // bits 18-20 are unspecified, but should be set to zero.
6796259698Sdim}
6797259698Sdim
6798259698Sdimdef DUP4s : NeonI_DUP<0b1, "dup", ".4s", VPR128, v4i32, GPR32, i32> {
6799259698Sdim  let Inst{20-16} = 0b00100;
6800259698Sdim  // bits 19-20 are unspecified, but should be set to zero.
6801259698Sdim}
6802259698Sdim
6803259698Sdimdef DUP2d : NeonI_DUP<0b1, "dup", ".2d", VPR128, v2i64, GPR64, i64> {
6804259698Sdim  let Inst{20-16} = 0b01000;
6805259698Sdim  // bit 20 is unspecified, but should be set to zero.
6806259698Sdim}
6807259698Sdim
6808259698Sdimdef DUP8b : NeonI_DUP<0b0, "dup", ".8b", VPR64, v8i8, GPR32, i32> {
6809259698Sdim  let Inst{20-16} = 0b00001;
6810259698Sdim  // bits 17-20 are unspecified, but should be set to zero.
6811259698Sdim}
6812259698Sdim
6813259698Sdimdef DUP4h : NeonI_DUP<0b0, "dup", ".4h", VPR64, v4i16, GPR32, i32> {
6814259698Sdim  let Inst{20-16} = 0b00010;
6815259698Sdim  // bits 18-20 are unspecified, but should be set to zero.
6816259698Sdim}
6817259698Sdim
6818259698Sdimdef DUP2s : NeonI_DUP<0b0, "dup", ".2s", VPR64, v2i32, GPR32, i32> {
6819259698Sdim  let Inst{20-16} = 0b00100;
6820259698Sdim  // bits 19-20 are unspecified, but should be set to zero.
6821259698Sdim}
6822259698Sdim
6823259698Sdim// patterns for CONCAT_VECTORS
6824259698Sdimmulticlass Concat_Vector_Pattern<ValueType ResTy, ValueType OpTy> {
6825259698Sdimdef : Pat<(ResTy (concat_vectors (OpTy VPR64:$Rn), undef)),
6826259698Sdim          (SUBREG_TO_REG (i64 0), VPR64:$Rn, sub_64)>;
6827259698Sdimdef : Pat<(ResTy (concat_vectors (OpTy VPR64:$Rn), (OpTy VPR64:$Rm))),
6828259698Sdim          (INSELd
6829259698Sdim            (v2i64 (SUBREG_TO_REG (i64 0), VPR64:$Rn, sub_64)),
6830259698Sdim            (v2i64 (SUBREG_TO_REG (i64 0), VPR64:$Rm, sub_64)),
6831259698Sdim            (i64 1),
6832259698Sdim            (i64 0))>;
6833259698Sdimdef : Pat<(ResTy (concat_vectors (OpTy VPR64:$Rn), (OpTy VPR64:$Rn))),
6834259698Sdim          (DUPELT2d
6835259698Sdim            (v2i64 (SUBREG_TO_REG (i64 0), VPR64:$Rn, sub_64)),
6836259698Sdim            (i64 0))> ;
6837259698Sdim}
6838259698Sdim
6839259698Sdimdefm : Concat_Vector_Pattern<v16i8, v8i8>;
6840259698Sdimdefm : Concat_Vector_Pattern<v8i16, v4i16>;
6841259698Sdimdefm : Concat_Vector_Pattern<v4i32, v2i32>;
6842259698Sdimdefm : Concat_Vector_Pattern<v2i64, v1i64>;
6843259698Sdimdefm : Concat_Vector_Pattern<v4f32, v2f32>;
6844259698Sdimdefm : Concat_Vector_Pattern<v2f64, v1f64>;
6845259698Sdim
6846259698Sdim//patterns for EXTRACT_SUBVECTOR
6847259698Sdimdef : Pat<(v8i8 (extract_subvector (v16i8 VPR128:$Rn), (i64 0))),
6848259698Sdim          (v8i8 (EXTRACT_SUBREG VPR128:$Rn, sub_64))>;
6849259698Sdimdef : Pat<(v4i16 (extract_subvector (v8i16 VPR128:$Rn), (i64 0))),
6850259698Sdim          (v4i16 (EXTRACT_SUBREG VPR128:$Rn, sub_64))>;
6851259698Sdimdef : Pat<(v2i32 (extract_subvector (v4i32 VPR128:$Rn), (i64 0))),
6852259698Sdim          (v2i32 (EXTRACT_SUBREG VPR128:$Rn, sub_64))>;
6853259698Sdimdef : Pat<(v1i64 (extract_subvector (v2i64 VPR128:$Rn), (i64 0))),
6854259698Sdim          (v1i64 (EXTRACT_SUBREG VPR128:$Rn, sub_64))>;
6855259698Sdimdef : Pat<(v2f32 (extract_subvector (v4f32 VPR128:$Rn), (i64 0))),
6856259698Sdim          (v2f32 (EXTRACT_SUBREG VPR128:$Rn, sub_64))>;
6857259698Sdimdef : Pat<(v1f64 (extract_subvector (v2f64 VPR128:$Rn), (i64 0))),
6858259698Sdim          (v1f64 (EXTRACT_SUBREG VPR128:$Rn, sub_64))>;
6859259698Sdim
6860259698Sdim// The followings are for instruction class (3V Elem)
6861259698Sdim
6862259698Sdim// Variant 1
6863259698Sdim
6864259698Sdimclass NI_2VE<bit q, bit u, bits<2> size, bits<4> opcode,
6865259698Sdim             string asmop, string ResS, string OpS, string EleOpS,
6866259698Sdim             Operand OpImm, RegisterOperand ResVPR,
6867259698Sdim             RegisterOperand OpVPR, RegisterOperand EleOpVPR>
6868259698Sdim  : NeonI_2VElem<q, u, size, opcode,
6869259698Sdim                 (outs ResVPR:$Rd), (ins ResVPR:$src, OpVPR:$Rn,
6870259698Sdim                                         EleOpVPR:$Re, OpImm:$Index),
6871259698Sdim                 asmop # "\t$Rd." # ResS # ", $Rn." # OpS #
6872259698Sdim                 ", $Re." # EleOpS # "[$Index]",
6873259698Sdim                 [],
6874259698Sdim                 NoItinerary> {
6875259698Sdim  bits<3> Index;
6876259698Sdim  bits<5> Re;
6877259698Sdim
6878259698Sdim  let Constraints = "$src = $Rd";
6879259698Sdim}
6880259698Sdim
6881259698Sdimmulticlass NI_2VE_v1<bit u, bits<4> opcode, string asmop> {
6882259698Sdim  // vector register class for element is always 128-bit to cover the max index
6883259698Sdim  def _2s4s : NI_2VE<0b0, u, 0b10, opcode, asmop, "2s", "2s", "s",
6884259698Sdim                     neon_uimm2_bare, VPR64, VPR64, VPR128> {
6885259698Sdim    let Inst{11} = {Index{1}};
6886259698Sdim    let Inst{21} = {Index{0}};
6887259698Sdim    let Inst{20-16} = Re;
6888259698Sdim  }
6889259698Sdim
6890259698Sdim  def _4s4s : NI_2VE<0b1, u, 0b10, opcode, asmop, "4s", "4s", "s",
6891259698Sdim                     neon_uimm2_bare, VPR128, VPR128, VPR128> {
6892259698Sdim    let Inst{11} = {Index{1}};
6893259698Sdim    let Inst{21} = {Index{0}};
6894259698Sdim    let Inst{20-16} = Re;
6895259698Sdim  }
6896259698Sdim
6897259698Sdim  // Index operations on 16-bit(H) elements are restricted to using v0-v15.
6898259698Sdim  def _4h8h : NI_2VE<0b0, u, 0b01, opcode, asmop, "4h", "4h", "h",
6899259698Sdim                     neon_uimm3_bare, VPR64, VPR64, VPR128Lo> {
6900259698Sdim    let Inst{11} = {Index{2}};
6901259698Sdim    let Inst{21} = {Index{1}};
6902259698Sdim    let Inst{20} = {Index{0}};
6903259698Sdim    let Inst{19-16} = Re{3-0};
6904259698Sdim  }
6905259698Sdim
6906259698Sdim  def _8h8h : NI_2VE<0b1, u, 0b01, opcode, asmop, "8h", "8h", "h",
6907259698Sdim                     neon_uimm3_bare, VPR128, VPR128, VPR128Lo> {
6908259698Sdim    let Inst{11} = {Index{2}};
6909259698Sdim    let Inst{21} = {Index{1}};
6910259698Sdim    let Inst{20} = {Index{0}};
6911259698Sdim    let Inst{19-16} = Re{3-0};
6912259698Sdim  }
6913259698Sdim}
6914259698Sdim
6915259698Sdimdefm MLAvve : NI_2VE_v1<0b1, 0b0000, "mla">;
6916259698Sdimdefm MLSvve : NI_2VE_v1<0b1, 0b0100, "mls">;
6917259698Sdim
6918259698Sdim// Pattern for lane in 128-bit vector
6919259698Sdimclass NI_2VE_laneq<Instruction INST, Operand OpImm, SDPatternOperator op,
6920259698Sdim                   RegisterOperand ResVPR, RegisterOperand OpVPR,
6921259698Sdim                   RegisterOperand EleOpVPR, ValueType ResTy, ValueType OpTy,
6922259698Sdim                   ValueType EleOpTy>
6923259698Sdim  : Pat<(ResTy (op (ResTy ResVPR:$src), (OpTy OpVPR:$Rn),
6924259698Sdim          (OpTy (Neon_vduplane (EleOpTy EleOpVPR:$Re), (i64 OpImm:$Index))))),
6925259698Sdim        (INST ResVPR:$src, OpVPR:$Rn, EleOpVPR:$Re, OpImm:$Index)>;
6926259698Sdim
6927259698Sdim// Pattern for lane in 64-bit vector
6928259698Sdimclass NI_2VE_lane<Instruction INST, Operand OpImm, SDPatternOperator op,
6929259698Sdim                  RegisterOperand ResVPR, RegisterOperand OpVPR,
6930259698Sdim                  RegisterOperand EleOpVPR, ValueType ResTy, ValueType OpTy,
6931259698Sdim                  ValueType EleOpTy>
6932259698Sdim  : Pat<(ResTy (op (ResTy ResVPR:$src), (OpTy OpVPR:$Rn),
6933259698Sdim          (OpTy (Neon_vduplane (EleOpTy EleOpVPR:$Re), (i64 OpImm:$Index))))),
6934259698Sdim        (INST ResVPR:$src, OpVPR:$Rn,
6935259698Sdim          (SUBREG_TO_REG (i64 0), EleOpVPR:$Re, sub_64), OpImm:$Index)>;
6936259698Sdim
6937259698Sdimmulticlass NI_2VE_v1_pat<string subop, SDPatternOperator op>
6938259698Sdim{
6939259698Sdim  def : NI_2VE_laneq<!cast<Instruction>(subop # "_2s4s"), neon_uimm2_bare,
6940259698Sdim                     op, VPR64, VPR64, VPR128, v2i32, v2i32, v4i32>;
6941259698Sdim
6942259698Sdim  def : NI_2VE_laneq<!cast<Instruction>(subop # "_4s4s"), neon_uimm2_bare,
6943259698Sdim                     op, VPR128, VPR128, VPR128, v4i32, v4i32, v4i32>;
6944259698Sdim
6945259698Sdim  def : NI_2VE_laneq<!cast<Instruction>(subop # "_4h8h"), neon_uimm3_bare,
6946259698Sdim                     op, VPR64, VPR64, VPR128Lo, v4i16, v4i16, v8i16>;
6947259698Sdim
6948259698Sdim  def : NI_2VE_laneq<!cast<Instruction>(subop # "_8h8h"), neon_uimm3_bare,
6949259698Sdim                     op, VPR128, VPR128, VPR128Lo, v8i16, v8i16, v8i16>;
6950259698Sdim
6951259698Sdim  // Index can only be half of the max value for lane in 64-bit vector
6952259698Sdim
6953259698Sdim  def : NI_2VE_lane<!cast<Instruction>(subop # "_2s4s"), neon_uimm1_bare,
6954259698Sdim                    op, VPR64, VPR64, VPR64, v2i32, v2i32, v2i32>;
6955259698Sdim
6956259698Sdim  def : NI_2VE_lane<!cast<Instruction>(subop # "_4h8h"), neon_uimm2_bare,
6957259698Sdim                    op, VPR64, VPR64, VPR64Lo, v4i16, v4i16, v4i16>;
6958259698Sdim}
6959259698Sdim
6960259698Sdimdefm MLA_lane_v1 : NI_2VE_v1_pat<"MLAvve", Neon_mla>;
6961259698Sdimdefm MLS_lane_v1 : NI_2VE_v1_pat<"MLSvve", Neon_mls>;
6962259698Sdim
6963259698Sdimclass NI_2VE_2op<bit q, bit u, bits<2> size, bits<4> opcode,
6964259698Sdim                 string asmop, string ResS, string OpS, string EleOpS,
6965259698Sdim                 Operand OpImm, RegisterOperand ResVPR,
6966259698Sdim                 RegisterOperand OpVPR, RegisterOperand EleOpVPR>
6967259698Sdim  : NeonI_2VElem<q, u, size, opcode,
6968259698Sdim                 (outs ResVPR:$Rd), (ins OpVPR:$Rn,
6969259698Sdim                                         EleOpVPR:$Re, OpImm:$Index),
6970259698Sdim                 asmop # "\t$Rd." # ResS # ", $Rn." # OpS #
6971259698Sdim                 ", $Re." # EleOpS # "[$Index]",
6972259698Sdim                 [],
6973259698Sdim                 NoItinerary> {
6974259698Sdim  bits<3> Index;
6975259698Sdim  bits<5> Re;
6976259698Sdim}
6977259698Sdim
6978259698Sdimmulticlass NI_2VE_v1_2op<bit u, bits<4> opcode, string asmop> {
6979259698Sdim  // vector register class for element is always 128-bit to cover the max index
6980259698Sdim  def _2s4s : NI_2VE_2op<0b0, u, 0b10, opcode, asmop, "2s", "2s", "s",
6981259698Sdim                         neon_uimm2_bare, VPR64, VPR64, VPR128> {
6982259698Sdim    let Inst{11} = {Index{1}};
6983259698Sdim    let Inst{21} = {Index{0}};
6984259698Sdim    let Inst{20-16} = Re;
6985259698Sdim  }
6986259698Sdim
6987259698Sdim  def _4s4s : NI_2VE_2op<0b1, u, 0b10, opcode, asmop, "4s", "4s", "s",
6988259698Sdim                         neon_uimm2_bare, VPR128, VPR128, VPR128> {
6989259698Sdim    let Inst{11} = {Index{1}};
6990259698Sdim    let Inst{21} = {Index{0}};
6991259698Sdim    let Inst{20-16} = Re;
6992259698Sdim  }
6993259698Sdim
6994259698Sdim  // Index operations on 16-bit(H) elements are restricted to using v0-v15.
6995259698Sdim  def _4h8h : NI_2VE_2op<0b0, u, 0b01, opcode, asmop, "4h", "4h", "h",
6996259698Sdim                         neon_uimm3_bare, VPR64, VPR64, VPR128Lo> {
6997259698Sdim    let Inst{11} = {Index{2}};
6998259698Sdim    let Inst{21} = {Index{1}};
6999259698Sdim    let Inst{20} = {Index{0}};
7000259698Sdim    let Inst{19-16} = Re{3-0};
7001259698Sdim  }
7002259698Sdim
7003259698Sdim  def _8h8h : NI_2VE_2op<0b1, u, 0b01, opcode, asmop, "8h", "8h", "h",
7004259698Sdim                         neon_uimm3_bare, VPR128, VPR128, VPR128Lo> {
7005259698Sdim    let Inst{11} = {Index{2}};
7006259698Sdim    let Inst{21} = {Index{1}};
7007259698Sdim    let Inst{20} = {Index{0}};
7008259698Sdim    let Inst{19-16} = Re{3-0};
7009259698Sdim  }
7010259698Sdim}
7011259698Sdim
7012259698Sdimdefm MULve : NI_2VE_v1_2op<0b0, 0b1000, "mul">;
7013259698Sdimdefm SQDMULHve : NI_2VE_v1_2op<0b0, 0b1100, "sqdmulh">;
7014259698Sdimdefm SQRDMULHve : NI_2VE_v1_2op<0b0, 0b1101, "sqrdmulh">;
7015259698Sdim
7016259698Sdim// Pattern for lane in 128-bit vector
7017259698Sdimclass NI_2VE_mul_laneq<Instruction INST, Operand OpImm, SDPatternOperator op,
7018259698Sdim                       RegisterOperand OpVPR, RegisterOperand EleOpVPR,
7019259698Sdim                       ValueType ResTy, ValueType OpTy, ValueType EleOpTy>
7020259698Sdim  : Pat<(ResTy (op (OpTy OpVPR:$Rn),
7021259698Sdim          (OpTy (Neon_vduplane (EleOpTy EleOpVPR:$Re), (i64 OpImm:$Index))))),
7022259698Sdim        (INST OpVPR:$Rn, EleOpVPR:$Re, OpImm:$Index)>;
7023259698Sdim
7024259698Sdim// Pattern for lane in 64-bit vector
7025259698Sdimclass NI_2VE_mul_lane<Instruction INST, Operand OpImm, SDPatternOperator op,
7026259698Sdim                      RegisterOperand OpVPR, RegisterOperand EleOpVPR,
7027259698Sdim                      ValueType ResTy, ValueType OpTy, ValueType EleOpTy>
7028259698Sdim  : Pat<(ResTy (op (OpTy OpVPR:$Rn),
7029259698Sdim          (OpTy (Neon_vduplane (EleOpTy EleOpVPR:$Re), (i64 OpImm:$Index))))),
7030259698Sdim        (INST OpVPR:$Rn,
7031259698Sdim          (SUBREG_TO_REG (i64 0), EleOpVPR:$Re, sub_64), OpImm:$Index)>;
7032259698Sdim
7033259698Sdimmulticlass NI_2VE_mul_v1_pat<string subop, SDPatternOperator op> {
7034259698Sdim  def : NI_2VE_mul_laneq<!cast<Instruction>(subop # "_2s4s"), neon_uimm2_bare,
7035259698Sdim                         op, VPR64, VPR128, v2i32, v2i32, v4i32>;
7036259698Sdim
7037259698Sdim  def : NI_2VE_mul_laneq<!cast<Instruction>(subop # "_4s4s"), neon_uimm2_bare,
7038259698Sdim                         op, VPR128, VPR128, v4i32, v4i32, v4i32>;
7039259698Sdim
7040259698Sdim  def : NI_2VE_mul_laneq<!cast<Instruction>(subop # "_4h8h"), neon_uimm3_bare,
7041259698Sdim                         op, VPR64, VPR128Lo, v4i16, v4i16, v8i16>;
7042259698Sdim
7043259698Sdim  def : NI_2VE_mul_laneq<!cast<Instruction>(subop # "_8h8h"), neon_uimm3_bare,
7044259698Sdim                         op, VPR128, VPR128Lo, v8i16, v8i16, v8i16>;
7045259698Sdim
7046259698Sdim  // Index can only be half of the max value for lane in 64-bit vector
7047259698Sdim
7048259698Sdim  def : NI_2VE_mul_lane<!cast<Instruction>(subop # "_2s4s"), neon_uimm1_bare,
7049259698Sdim                        op, VPR64, VPR64, v2i32, v2i32, v2i32>;
7050259698Sdim
7051259698Sdim  def : NI_2VE_mul_lane<!cast<Instruction>(subop # "_4h8h"), neon_uimm2_bare,
7052259698Sdim                        op, VPR64, VPR64Lo, v4i16, v4i16, v4i16>;
7053259698Sdim}
7054259698Sdim
7055259698Sdimdefm MUL_lane_v1 : NI_2VE_mul_v1_pat<"MULve", mul>;
7056259698Sdimdefm SQDMULH_lane_v1 : NI_2VE_mul_v1_pat<"SQDMULHve", int_arm_neon_vqdmulh>;
7057259698Sdimdefm SQRDMULH_lane_v1 : NI_2VE_mul_v1_pat<"SQRDMULHve", int_arm_neon_vqrdmulh>;
7058259698Sdim
7059259698Sdim// Variant 2
7060259698Sdim
7061259698Sdimmulticlass NI_2VE_v2_2op<bit u, bits<4> opcode, string asmop> {
7062259698Sdim  // vector register class for element is always 128-bit to cover the max index
7063259698Sdim  def _2s4s : NI_2VE_2op<0b0, u, 0b10, opcode, asmop, "2s", "2s", "s",
7064259698Sdim                         neon_uimm2_bare, VPR64, VPR64, VPR128> {
7065259698Sdim    let Inst{11} = {Index{1}};
7066259698Sdim    let Inst{21} = {Index{0}};
7067259698Sdim    let Inst{20-16} = Re;
7068259698Sdim  }
7069259698Sdim
7070259698Sdim  def _4s4s : NI_2VE_2op<0b1, u, 0b10, opcode, asmop, "4s", "4s", "s",
7071259698Sdim                         neon_uimm2_bare, VPR128, VPR128, VPR128> {
7072259698Sdim    let Inst{11} = {Index{1}};
7073259698Sdim    let Inst{21} = {Index{0}};
7074259698Sdim    let Inst{20-16} = Re;
7075259698Sdim  }
7076259698Sdim
7077259698Sdim  // _1d2d doesn't exist!
7078259698Sdim
7079259698Sdim  def _2d2d : NI_2VE_2op<0b1, u, 0b11, opcode, asmop, "2d", "2d", "d",
7080259698Sdim                         neon_uimm1_bare, VPR128, VPR128, VPR128> {
7081259698Sdim    let Inst{11} = {Index{0}};
7082259698Sdim    let Inst{21} = 0b0;
7083259698Sdim    let Inst{20-16} = Re;
7084259698Sdim  }
7085259698Sdim}
7086259698Sdim
7087259698Sdimdefm FMULve : NI_2VE_v2_2op<0b0, 0b1001, "fmul">;
7088259698Sdimdefm FMULXve : NI_2VE_v2_2op<0b1, 0b1001, "fmulx">;
7089259698Sdim
7090259698Sdimclass NI_2VE_mul_lane_2d<Instruction INST, Operand OpImm, SDPatternOperator op,
7091259698Sdim                         RegisterOperand OpVPR, RegisterOperand EleOpVPR,
7092259698Sdim                         ValueType ResTy, ValueType OpTy, ValueType EleOpTy,
7093259698Sdim                         SDPatternOperator coreop>
7094259698Sdim  : Pat<(ResTy (op (OpTy OpVPR:$Rn),
7095259698Sdim          (OpTy (coreop (EleOpTy EleOpVPR:$Re), (EleOpTy EleOpVPR:$Re))))),
7096259698Sdim        (INST OpVPR:$Rn,
7097259698Sdim          (SUBREG_TO_REG (i64 0), EleOpVPR:$Re, sub_64), 0)>;
7098259698Sdim
7099259698Sdimmulticlass NI_2VE_mul_v2_pat<string subop, SDPatternOperator op> {
7100259698Sdim  def : NI_2VE_mul_laneq<!cast<Instruction>(subop # "_2s4s"), neon_uimm2_bare,
7101259698Sdim                         op, VPR64, VPR128, v2f32, v2f32, v4f32>;
7102259698Sdim
7103259698Sdim  def : NI_2VE_mul_laneq<!cast<Instruction>(subop # "_4s4s"), neon_uimm2_bare,
7104259698Sdim                         op, VPR128, VPR128, v4f32, v4f32, v4f32>;
7105259698Sdim
7106259698Sdim  def : NI_2VE_mul_laneq<!cast<Instruction>(subop # "_2d2d"), neon_uimm1_bare,
7107259698Sdim                         op, VPR128, VPR128, v2f64, v2f64, v2f64>;
7108259698Sdim
7109259698Sdim  // Index can only be half of the max value for lane in 64-bit vector
7110259698Sdim
7111259698Sdim  def : NI_2VE_mul_lane<!cast<Instruction>(subop # "_2s4s"), neon_uimm1_bare,
7112259698Sdim                        op, VPR64, VPR64, v2f32, v2f32, v2f32>;
7113259698Sdim
7114259698Sdim  def : NI_2VE_mul_lane_2d<!cast<Instruction>(subop # "_2d2d"), neon_uimm1_bare,
7115259698Sdim                           op, VPR128, VPR64, v2f64, v2f64, v1f64,
7116259698Sdim                           BinOpFrag<(Neon_combine_2d node:$LHS, node:$RHS)>>;
7117259698Sdim}
7118259698Sdim
7119259698Sdimdefm FMUL_lane_v2 : NI_2VE_mul_v2_pat<"FMULve", fmul>;
7120259698Sdimdefm FMULX_lane_v2 : NI_2VE_mul_v2_pat<"FMULXve", int_aarch64_neon_vmulx>;
7121259698Sdim
7122259698Sdimdef : Pat<(v2f32 (fmul (v2f32 (Neon_vdup (f32 FPR32:$Re))),
7123259698Sdim                       (v2f32 VPR64:$Rn))),
7124259698Sdim          (FMULve_2s4s VPR64:$Rn, (SUBREG_TO_REG (i32 0), $Re, sub_32), 0)>;
7125259698Sdim
7126259698Sdimdef : Pat<(v4f32 (fmul (v4f32 (Neon_vdup (f32 FPR32:$Re))),
7127259698Sdim                       (v4f32 VPR128:$Rn))),
7128259698Sdim          (FMULve_4s4s VPR128:$Rn, (SUBREG_TO_REG (i32 0), $Re, sub_32), 0)>;
7129259698Sdim
7130259698Sdimdef : Pat<(v2f64 (fmul (v2f64 (Neon_vdup (f64 FPR64:$Re))),
7131259698Sdim                       (v2f64 VPR128:$Rn))),
7132259698Sdim          (FMULve_2d2d VPR128:$Rn, (SUBREG_TO_REG (i64 0), $Re, sub_64), 0)>;
7133259698Sdim
7134259698Sdim// The followings are patterns using fma
7135259698Sdim// -ffp-contract=fast generates fma
7136259698Sdim
7137259698Sdimmulticlass NI_2VE_v2<bit u, bits<4> opcode, string asmop> {
7138259698Sdim  // vector register class for element is always 128-bit to cover the max index
7139259698Sdim  def _2s4s : NI_2VE<0b0, u, 0b10, opcode, asmop, "2s", "2s", "s",
7140259698Sdim                     neon_uimm2_bare, VPR64, VPR64, VPR128> {
7141259698Sdim    let Inst{11} = {Index{1}};
7142259698Sdim    let Inst{21} = {Index{0}};
7143259698Sdim    let Inst{20-16} = Re;
7144259698Sdim  }
7145259698Sdim
7146259698Sdim  def _4s4s : NI_2VE<0b1, u, 0b10, opcode, asmop, "4s", "4s", "s",
7147259698Sdim                     neon_uimm2_bare, VPR128, VPR128, VPR128> {
7148259698Sdim    let Inst{11} = {Index{1}};
7149259698Sdim    let Inst{21} = {Index{0}};
7150259698Sdim    let Inst{20-16} = Re;
7151259698Sdim  }
7152259698Sdim
7153259698Sdim  // _1d2d doesn't exist!
7154259698Sdim
7155259698Sdim  def _2d2d : NI_2VE<0b1, u, 0b11, opcode, asmop, "2d", "2d", "d",
7156259698Sdim                     neon_uimm1_bare, VPR128, VPR128, VPR128> {
7157259698Sdim    let Inst{11} = {Index{0}};
7158259698Sdim    let Inst{21} = 0b0;
7159259698Sdim    let Inst{20-16} = Re;
7160259698Sdim  }
7161259698Sdim}
7162259698Sdim
7163259698Sdimdefm FMLAvve : NI_2VE_v2<0b0, 0b0001, "fmla">;
7164259698Sdimdefm FMLSvve : NI_2VE_v2<0b0, 0b0101, "fmls">;
7165259698Sdim
7166259698Sdim// Pattern for lane in 128-bit vector
7167259698Sdimclass NI_2VEswap_laneq<Instruction INST, Operand OpImm, SDPatternOperator op,
7168259698Sdim                       RegisterOperand ResVPR, RegisterOperand OpVPR,
7169259698Sdim                       ValueType ResTy, ValueType OpTy,
7170259698Sdim                       SDPatternOperator coreop>
7171259698Sdim  : Pat<(ResTy (op (ResTy (coreop (OpTy OpVPR:$Re), (i64 OpImm:$Index))),
7172259698Sdim                   (ResTy ResVPR:$src), (ResTy ResVPR:$Rn))),
7173259698Sdim        (INST ResVPR:$src, ResVPR:$Rn, OpVPR:$Re, OpImm:$Index)>;
7174259698Sdim
7175259698Sdim// Pattern for lane 0
7176259698Sdimclass NI_2VEfma_lane0<Instruction INST, SDPatternOperator op,
7177259698Sdim                      RegisterOperand ResVPR, ValueType ResTy>
7178259698Sdim  : Pat<(ResTy (op (ResTy ResVPR:$Rn),
7179259698Sdim                   (ResTy (Neon_vdup (f32 FPR32:$Re))),
7180259698Sdim                   (ResTy ResVPR:$src))),
7181259698Sdim        (INST ResVPR:$src, ResVPR:$Rn,
7182259698Sdim              (SUBREG_TO_REG (i32 0), $Re, sub_32), 0)>;
7183259698Sdim
7184259698Sdim// Pattern for lane in 64-bit vector
7185259698Sdimclass NI_2VEswap_lane<Instruction INST, Operand OpImm, SDPatternOperator op,
7186259698Sdim                      RegisterOperand ResVPR, RegisterOperand OpVPR,
7187259698Sdim                      ValueType ResTy, ValueType OpTy,
7188259698Sdim                      SDPatternOperator coreop>
7189259698Sdim  : Pat<(ResTy (op (ResTy (coreop (OpTy OpVPR:$Re), (i64 OpImm:$Index))),
7190259698Sdim                   (ResTy ResVPR:$Rn), (ResTy ResVPR:$src))),
7191259698Sdim        (INST ResVPR:$src, ResVPR:$Rn,
7192259698Sdim          (SUBREG_TO_REG (i64 0), OpVPR:$Re, sub_64), OpImm:$Index)>;
7193259698Sdim
7194259698Sdim// Pattern for lane in 64-bit vector
7195259698Sdimclass NI_2VEswap_lane_2d2d<Instruction INST, Operand OpImm,
7196259698Sdim                           SDPatternOperator op,
7197259698Sdim                           RegisterOperand ResVPR, RegisterOperand OpVPR,
7198259698Sdim                           ValueType ResTy, ValueType OpTy,
7199259698Sdim                           SDPatternOperator coreop>
7200259698Sdim  : Pat<(ResTy (op (ResTy (coreop (OpTy OpVPR:$Re), (OpTy OpVPR:$Re))),
7201259698Sdim                   (ResTy ResVPR:$Rn), (ResTy ResVPR:$src))),
7202259698Sdim        (INST ResVPR:$src, ResVPR:$Rn,
7203259698Sdim          (SUBREG_TO_REG (i64 0), OpVPR:$Re, sub_64), 0)>;
7204259698Sdim
7205259698Sdim
7206259698Sdimmulticlass NI_2VE_fma_v2_pat<string subop, SDPatternOperator op> {
7207259698Sdim  def : NI_2VEswap_laneq<!cast<Instruction>(subop # "_2s4s"),
7208259698Sdim                         neon_uimm2_bare, op, VPR64, VPR128, v2f32, v4f32,
7209259698Sdim                         BinOpFrag<(Neon_vduplane node:$LHS, node:$RHS)>>;
7210259698Sdim
7211259698Sdim  def : NI_2VEfma_lane0<!cast<Instruction>(subop # "_2s4s"),
7212259698Sdim                        op, VPR64, v2f32>;
7213259698Sdim
7214259698Sdim  def : NI_2VEswap_laneq<!cast<Instruction>(subop # "_4s4s"),
7215259698Sdim                         neon_uimm2_bare, op, VPR128, VPR128, v4f32, v4f32,
7216259698Sdim                         BinOpFrag<(Neon_vduplane node:$LHS, node:$RHS)>>;
7217259698Sdim
7218259698Sdim  def : NI_2VEfma_lane0<!cast<Instruction>(subop # "_4s4s"),
7219259698Sdim                        op, VPR128, v4f32>;
7220259698Sdim
7221259698Sdim  def : NI_2VEswap_laneq<!cast<Instruction>(subop # "_2d2d"),
7222259698Sdim                         neon_uimm1_bare, op, VPR128, VPR128, v2f64, v2f64,
7223259698Sdim                         BinOpFrag<(Neon_vduplane node:$LHS, node:$RHS)>>;
7224259698Sdim
7225259698Sdim  // Index can only be half of the max value for lane in 64-bit vector
7226259698Sdim
7227259698Sdim  def : NI_2VEswap_lane<!cast<Instruction>(subop # "_2s4s"),
7228259698Sdim                        neon_uimm1_bare, op, VPR64, VPR64, v2f32, v2f32,
7229259698Sdim                        BinOpFrag<(Neon_vduplane node:$LHS, node:$RHS)>>;
7230259698Sdim
7231259698Sdim  def : NI_2VEswap_lane_2d2d<!cast<Instruction>(subop # "_2d2d"),
7232259698Sdim                             neon_uimm1_bare, op, VPR128, VPR64, v2f64, v1f64,
7233259698Sdim                             BinOpFrag<(Neon_combine_2d node:$LHS, node:$RHS)>>;
7234259698Sdim}
7235259698Sdim
7236259698Sdimdefm FMLA_lane_v2_s : NI_2VE_fma_v2_pat<"FMLAvve", fma>;
7237259698Sdim
7238259698Sdim// Pattern for lane 0
7239259698Sdimclass NI_2VEfms_lane0<Instruction INST, SDPatternOperator op,
7240259698Sdim                      RegisterOperand ResVPR, ValueType ResTy>
7241259698Sdim  : Pat<(ResTy (op (ResTy (fneg ResVPR:$Rn)),
7242259698Sdim                   (ResTy (Neon_vdup (f32 FPR32:$Re))),
7243259698Sdim                   (ResTy ResVPR:$src))),
7244259698Sdim        (INST ResVPR:$src, ResVPR:$Rn,
7245259698Sdim              (SUBREG_TO_REG (i32 0), $Re, sub_32), 0)>;
7246259698Sdim
7247259698Sdimmulticlass NI_2VE_fms_v2_pat<string subop, SDPatternOperator op>
7248259698Sdim{
7249259698Sdim  def : NI_2VEswap_laneq<!cast<Instruction>(subop # "_2s4s"),
7250259698Sdim                         neon_uimm2_bare, op, VPR64, VPR128, v2f32, v4f32,
7251259698Sdim                         BinOpFrag<(fneg (Neon_vduplane node:$LHS, node:$RHS))>>;
7252259698Sdim
7253259698Sdim  def : NI_2VEswap_laneq<!cast<Instruction>(subop # "_2s4s"),
7254259698Sdim                         neon_uimm2_bare, op, VPR64, VPR128, v2f32, v4f32,
7255259698Sdim                         BinOpFrag<(Neon_vduplane
7256259698Sdim                                     (fneg node:$LHS), node:$RHS)>>;
7257259698Sdim
7258259698Sdim  def : NI_2VEfms_lane0<!cast<Instruction>(subop # "_2s4s"),
7259259698Sdim                        op, VPR64, v2f32>;
7260259698Sdim
7261259698Sdim  def : NI_2VEswap_laneq<!cast<Instruction>(subop # "_4s4s"),
7262259698Sdim                         neon_uimm2_bare, op, VPR128, VPR128, v4f32, v4f32,
7263259698Sdim                         BinOpFrag<(fneg (Neon_vduplane
7264259698Sdim                                     node:$LHS, node:$RHS))>>;
7265259698Sdim
7266259698Sdim  def : NI_2VEswap_laneq<!cast<Instruction>(subop # "_4s4s"),
7267259698Sdim                         neon_uimm2_bare, op, VPR128, VPR128, v4f32, v4f32,
7268259698Sdim                         BinOpFrag<(Neon_vduplane
7269259698Sdim                                     (fneg node:$LHS), node:$RHS)>>;
7270259698Sdim
7271259698Sdim  def : NI_2VEfms_lane0<!cast<Instruction>(subop # "_4s4s"),
7272259698Sdim                        op, VPR128, v4f32>;
7273259698Sdim
7274259698Sdim  def : NI_2VEswap_laneq<!cast<Instruction>(subop # "_2d2d"),
7275259698Sdim                         neon_uimm1_bare, op, VPR128, VPR128, v2f64, v2f64,
7276259698Sdim                         BinOpFrag<(fneg (Neon_vduplane
7277259698Sdim                                     node:$LHS, node:$RHS))>>;
7278259698Sdim
7279259698Sdim  def : NI_2VEswap_laneq<!cast<Instruction>(subop # "_2d2d"),
7280259698Sdim                         neon_uimm1_bare, op, VPR128, VPR128, v2f64, v2f64,
7281259698Sdim                         BinOpFrag<(Neon_vduplane
7282259698Sdim                                     (fneg node:$LHS), node:$RHS)>>;
7283259698Sdim
7284259698Sdim  // Index can only be half of the max value for lane in 64-bit vector
7285259698Sdim
7286259698Sdim  def : NI_2VEswap_lane<!cast<Instruction>(subop # "_2s4s"),
7287259698Sdim                        neon_uimm1_bare, op, VPR64, VPR64, v2f32, v2f32,
7288259698Sdim                        BinOpFrag<(fneg (Neon_vduplane
7289259698Sdim                                    node:$LHS, node:$RHS))>>;
7290259698Sdim
7291259698Sdim  def : NI_2VEswap_lane<!cast<Instruction>(subop # "_2s4s"),
7292259698Sdim                        neon_uimm1_bare, op, VPR64, VPR64, v2f32, v2f32,
7293259698Sdim                        BinOpFrag<(Neon_vduplane
7294259698Sdim                                    (fneg node:$LHS), node:$RHS)>>;
7295259698Sdim
7296259698Sdim  def : NI_2VEswap_lane<!cast<Instruction>(subop # "_4s4s"),
7297259698Sdim                        neon_uimm1_bare, op, VPR128, VPR64, v4f32, v2f32,
7298259698Sdim                        BinOpFrag<(fneg (Neon_vduplane node:$LHS, node:$RHS))>>;
7299259698Sdim
7300259698Sdim  def : NI_2VEswap_lane<!cast<Instruction>(subop # "_4s4s"),
7301259698Sdim                        neon_uimm1_bare, op, VPR128, VPR64, v4f32, v2f32,
7302259698Sdim                        BinOpFrag<(Neon_vduplane (fneg node:$LHS), node:$RHS)>>;
7303259698Sdim
7304259698Sdim  def : NI_2VEswap_lane_2d2d<!cast<Instruction>(subop # "_2d2d"),
7305259698Sdim                             neon_uimm1_bare, op, VPR128, VPR64, v2f64, v1f64,
7306259698Sdim                             BinOpFrag<(fneg (Neon_combine_2d
7307259698Sdim                                         node:$LHS, node:$RHS))>>;
7308259698Sdim
7309259698Sdim  def : NI_2VEswap_lane_2d2d<!cast<Instruction>(subop # "_2d2d"),
7310259698Sdim                             neon_uimm1_bare, op, VPR128, VPR64, v2f64, v1f64,
7311259698Sdim                             BinOpFrag<(Neon_combine_2d
7312259698Sdim                                         (fneg node:$LHS), (fneg node:$RHS))>>;
7313259698Sdim}
7314259698Sdim
7315259698Sdimdefm FMLS_lane_v2_s : NI_2VE_fms_v2_pat<"FMLSvve", fma>;
7316259698Sdim
7317259698Sdim// Variant 3: Long type
7318259698Sdim// E.g. SMLAL : 4S/4H/H (v0-v15), 2D/2S/S
7319259698Sdim//      SMLAL2: 4S/8H/H (v0-v15), 2D/4S/S
7320259698Sdim
7321259698Sdimmulticlass NI_2VE_v3<bit u, bits<4> opcode, string asmop> {
7322259698Sdim  // vector register class for element is always 128-bit to cover the max index
7323259698Sdim  def _2d2s : NI_2VE<0b0, u, 0b10, opcode, asmop, "2d", "2s", "s",
7324259698Sdim                     neon_uimm2_bare, VPR128, VPR64, VPR128> {
7325259698Sdim    let Inst{11} = {Index{1}};
7326259698Sdim    let Inst{21} = {Index{0}};
7327259698Sdim    let Inst{20-16} = Re;
7328259698Sdim  }
7329259698Sdim
7330259698Sdim  def _2d4s : NI_2VE<0b1, u, 0b10, opcode, asmop # "2", "2d", "4s", "s",
7331259698Sdim                     neon_uimm2_bare, VPR128, VPR128, VPR128> {
7332259698Sdim    let Inst{11} = {Index{1}};
7333259698Sdim    let Inst{21} = {Index{0}};
7334259698Sdim    let Inst{20-16} = Re;
7335259698Sdim  }
7336259698Sdim
7337259698Sdim  // Index operations on 16-bit(H) elements are restricted to using v0-v15.
7338259698Sdim  def _4s8h : NI_2VE<0b1, u, 0b01, opcode, asmop # "2", "4s", "8h", "h",
7339259698Sdim                     neon_uimm3_bare, VPR128, VPR128, VPR128Lo> {
7340259698Sdim    let Inst{11} = {Index{2}};
7341259698Sdim    let Inst{21} = {Index{1}};
7342259698Sdim    let Inst{20} = {Index{0}};
7343259698Sdim    let Inst{19-16} = Re{3-0};
7344259698Sdim  }
7345259698Sdim
7346259698Sdim  def _4s4h : NI_2VE<0b0, u, 0b01, opcode, asmop, "4s", "4h", "h",
7347259698Sdim                     neon_uimm3_bare, VPR128, VPR64, VPR128Lo> {
7348259698Sdim    let Inst{11} = {Index{2}};
7349259698Sdim    let Inst{21} = {Index{1}};
7350259698Sdim    let Inst{20} = {Index{0}};
7351259698Sdim    let Inst{19-16} = Re{3-0};
7352259698Sdim  }
7353259698Sdim}
7354259698Sdim
7355259698Sdimdefm SMLALvve : NI_2VE_v3<0b0, 0b0010, "smlal">;
7356259698Sdimdefm UMLALvve : NI_2VE_v3<0b1, 0b0010, "umlal">;
7357259698Sdimdefm SMLSLvve : NI_2VE_v3<0b0, 0b0110, "smlsl">;
7358259698Sdimdefm UMLSLvve : NI_2VE_v3<0b1, 0b0110, "umlsl">;
7359259698Sdimdefm SQDMLALvve : NI_2VE_v3<0b0, 0b0011, "sqdmlal">;
7360259698Sdimdefm SQDMLSLvve : NI_2VE_v3<0b0, 0b0111, "sqdmlsl">;
7361259698Sdim
7362259698Sdimmulticlass NI_2VE_v3_2op<bit u, bits<4> opcode, string asmop> {
7363259698Sdim  // vector register class for element is always 128-bit to cover the max index
7364259698Sdim  def _2d2s : NI_2VE_2op<0b0, u, 0b10, opcode, asmop, "2d", "2s", "s",
7365259698Sdim                         neon_uimm2_bare, VPR128, VPR64, VPR128> {
7366259698Sdim    let Inst{11} = {Index{1}};
7367259698Sdim    let Inst{21} = {Index{0}};
7368259698Sdim    let Inst{20-16} = Re;
7369259698Sdim  }
7370259698Sdim
7371259698Sdim  def _2d4s : NI_2VE_2op<0b1, u, 0b10, opcode, asmop # "2", "2d", "4s", "s",
7372259698Sdim                         neon_uimm2_bare, VPR128, VPR128, VPR128> {
7373259698Sdim    let Inst{11} = {Index{1}};
7374259698Sdim    let Inst{21} = {Index{0}};
7375259698Sdim    let Inst{20-16} = Re;
7376259698Sdim  }
7377259698Sdim
7378259698Sdim  // Index operations on 16-bit(H) elements are restricted to using v0-v15.
7379259698Sdim  def _4s8h : NI_2VE_2op<0b1, u, 0b01, opcode, asmop # "2", "4s", "8h", "h",
7380259698Sdim                         neon_uimm3_bare, VPR128, VPR128, VPR128Lo> {
7381259698Sdim    let Inst{11} = {Index{2}};
7382259698Sdim    let Inst{21} = {Index{1}};
7383259698Sdim    let Inst{20} = {Index{0}};
7384259698Sdim    let Inst{19-16} = Re{3-0};
7385259698Sdim  }
7386259698Sdim
7387259698Sdim  def _4s4h : NI_2VE_2op<0b0, u, 0b01, opcode, asmop, "4s", "4h", "h",
7388259698Sdim                         neon_uimm3_bare, VPR128, VPR64, VPR128Lo> {
7389259698Sdim    let Inst{11} = {Index{2}};
7390259698Sdim    let Inst{21} = {Index{1}};
7391259698Sdim    let Inst{20} = {Index{0}};
7392259698Sdim    let Inst{19-16} = Re{3-0};
7393259698Sdim  }
7394259698Sdim}
7395259698Sdim
7396259698Sdimdefm SMULLve : NI_2VE_v3_2op<0b0, 0b1010, "smull">;
7397259698Sdimdefm UMULLve : NI_2VE_v3_2op<0b1, 0b1010, "umull">;
7398259698Sdimdefm SQDMULLve : NI_2VE_v3_2op<0b0, 0b1011, "sqdmull">;
7399259698Sdim
7400259698Sdimdef : Pat<(v1f64 (scalar_to_vector (f64 FPR64:$src))),
7401259698Sdim          (FMOVdd $src)>;
7402259698Sdimdef : Pat<(v1f32 (scalar_to_vector (f32 FPR32:$src))),
7403259698Sdim          (FMOVss $src)>;
7404259698Sdim
7405259698Sdim// Pattern for lane in 128-bit vector
7406259698Sdimclass NI_2VEL2_laneq<Instruction INST, Operand OpImm, SDPatternOperator op,
7407259698Sdim                     RegisterOperand EleOpVPR, ValueType ResTy,
7408259698Sdim                     ValueType OpTy, ValueType EleOpTy, ValueType HalfOpTy,
7409259698Sdim                     SDPatternOperator hiop>
7410259698Sdim  : Pat<(ResTy (op (ResTy VPR128:$src),
7411259698Sdim          (HalfOpTy (hiop (OpTy VPR128:$Rn))),
7412259698Sdim          (HalfOpTy (Neon_vduplane
7413259698Sdim                      (EleOpTy EleOpVPR:$Re), (i64 OpImm:$Index))))),
7414259698Sdim        (INST VPR128:$src, VPR128:$Rn, EleOpVPR:$Re, OpImm:$Index)>;
7415259698Sdim
7416259698Sdim// Pattern for lane in 64-bit vector
7417259698Sdimclass NI_2VEL2_lane<Instruction INST, Operand OpImm, SDPatternOperator op,
7418259698Sdim                    RegisterOperand EleOpVPR, ValueType ResTy,
7419259698Sdim                    ValueType OpTy, ValueType EleOpTy, ValueType HalfOpTy,
7420259698Sdim                    SDPatternOperator hiop>
7421259698Sdim  : Pat<(ResTy (op (ResTy VPR128:$src),
7422259698Sdim          (HalfOpTy (hiop (OpTy VPR128:$Rn))),
7423259698Sdim          (HalfOpTy (Neon_vduplane
7424259698Sdim                      (EleOpTy EleOpVPR:$Re), (i64 OpImm:$Index))))),
7425259698Sdim        (INST VPR128:$src, VPR128:$Rn,
7426259698Sdim          (SUBREG_TO_REG (i64 0), EleOpVPR:$Re, sub_64), OpImm:$Index)>;
7427259698Sdim
7428259698Sdimclass NI_2VEL2_lane0<Instruction INST, SDPatternOperator op,
7429259698Sdim                     ValueType ResTy, ValueType OpTy, ValueType HalfOpTy,
7430259698Sdim                     SDPatternOperator hiop, Instruction DupInst>
7431259698Sdim  : Pat<(ResTy (op (ResTy VPR128:$src),
7432259698Sdim          (HalfOpTy (hiop (OpTy VPR128:$Rn))),
7433259698Sdim          (HalfOpTy (Neon_vdup (i32 GPR32:$Re))))),
7434259698Sdim        (INST VPR128:$src, VPR128:$Rn, (DupInst $Re), 0)>;
7435259698Sdim
7436259698Sdimmulticlass NI_2VEL_v3_pat<string subop, SDPatternOperator op> {
7437259698Sdim  def : NI_2VE_laneq<!cast<Instruction>(subop # "_4s4h"), neon_uimm3_bare,
7438259698Sdim                     op, VPR128, VPR64, VPR128Lo, v4i32, v4i16, v8i16>;
7439259698Sdim
7440259698Sdim  def : NI_2VE_laneq<!cast<Instruction>(subop # "_2d2s"), neon_uimm2_bare,
7441259698Sdim                     op, VPR128, VPR64, VPR128, v2i64, v2i32, v4i32>;
7442259698Sdim
7443259698Sdim  def : NI_2VEL2_laneq<!cast<Instruction>(subop # "_4s8h"), neon_uimm3_bare,
7444259698Sdim                       op, VPR128Lo, v4i32, v8i16, v8i16, v4i16, Neon_High8H>;
7445259698Sdim
7446259698Sdim  def : NI_2VEL2_laneq<!cast<Instruction>(subop # "_2d4s"), neon_uimm2_bare,
7447259698Sdim                       op, VPR128, v2i64, v4i32, v4i32, v2i32, Neon_High4S>;
7448259698Sdim
7449259698Sdim  def : NI_2VEL2_lane0<!cast<Instruction>(subop # "_4s8h"),
7450259698Sdim                       op, v4i32, v8i16, v4i16, Neon_High8H, DUP8h>;
7451259698Sdim
7452259698Sdim  def : NI_2VEL2_lane0<!cast<Instruction>(subop # "_2d4s"),
7453259698Sdim                       op, v2i64, v4i32, v2i32, Neon_High4S, DUP4s>;
7454259698Sdim
7455259698Sdim  // Index can only be half of the max value for lane in 64-bit vector
7456259698Sdim
7457259698Sdim  def : NI_2VE_lane<!cast<Instruction>(subop # "_4s4h"), neon_uimm2_bare,
7458259698Sdim                    op, VPR128, VPR64, VPR64Lo, v4i32, v4i16, v4i16>;
7459259698Sdim
7460259698Sdim  def : NI_2VE_lane<!cast<Instruction>(subop # "_2d2s"), neon_uimm1_bare,
7461259698Sdim                    op, VPR128, VPR64, VPR64, v2i64, v2i32, v2i32>;
7462259698Sdim
7463259698Sdim  def : NI_2VEL2_lane<!cast<Instruction>(subop # "_4s8h"), neon_uimm2_bare,
7464259698Sdim                      op, VPR64Lo, v4i32, v8i16, v4i16, v4i16, Neon_High8H>;
7465259698Sdim
7466259698Sdim  def : NI_2VEL2_lane<!cast<Instruction>(subop # "_2d4s"), neon_uimm1_bare,
7467259698Sdim                      op, VPR64, v2i64, v4i32, v2i32, v2i32, Neon_High4S>;
7468259698Sdim}
7469259698Sdim
7470259698Sdimdefm SMLAL_lane_v3 : NI_2VEL_v3_pat<"SMLALvve", Neon_smlal>;
7471259698Sdimdefm UMLAL_lane_v3 : NI_2VEL_v3_pat<"UMLALvve", Neon_umlal>;
7472259698Sdimdefm SMLSL_lane_v3 : NI_2VEL_v3_pat<"SMLSLvve", Neon_smlsl>;
7473259698Sdimdefm UMLSL_lane_v3 : NI_2VEL_v3_pat<"UMLSLvve", Neon_umlsl>;
7474259698Sdim
7475259698Sdim// Pattern for lane in 128-bit vector
7476259698Sdimclass NI_2VEL2_mul_laneq<Instruction INST, Operand OpImm, SDPatternOperator op,
7477259698Sdim                         RegisterOperand EleOpVPR, ValueType ResTy,
7478259698Sdim                         ValueType OpTy, ValueType EleOpTy, ValueType HalfOpTy,
7479259698Sdim                         SDPatternOperator hiop>
7480259698Sdim  : Pat<(ResTy (op
7481259698Sdim          (HalfOpTy (hiop (OpTy VPR128:$Rn))),
7482259698Sdim          (HalfOpTy (Neon_vduplane
7483259698Sdim                      (EleOpTy EleOpVPR:$Re), (i64 OpImm:$Index))))),
7484259698Sdim        (INST VPR128:$Rn, EleOpVPR:$Re, OpImm:$Index)>;
7485259698Sdim
7486259698Sdim// Pattern for lane in 64-bit vector
7487259698Sdimclass NI_2VEL2_mul_lane<Instruction INST, Operand OpImm, SDPatternOperator op,
7488259698Sdim                        RegisterOperand EleOpVPR, ValueType ResTy,
7489259698Sdim                        ValueType OpTy, ValueType EleOpTy, ValueType HalfOpTy,
7490259698Sdim                        SDPatternOperator hiop>
7491259698Sdim  : Pat<(ResTy (op
7492259698Sdim          (HalfOpTy (hiop (OpTy VPR128:$Rn))),
7493259698Sdim          (HalfOpTy (Neon_vduplane
7494259698Sdim                      (EleOpTy EleOpVPR:$Re), (i64 OpImm:$Index))))),
7495259698Sdim        (INST VPR128:$Rn,
7496259698Sdim          (SUBREG_TO_REG (i64 0), EleOpVPR:$Re, sub_64), OpImm:$Index)>;
7497259698Sdim
7498259698Sdim// Pattern for fixed lane 0
7499259698Sdimclass NI_2VEL2_mul_lane0<Instruction INST, SDPatternOperator op,
7500259698Sdim                         ValueType ResTy, ValueType OpTy, ValueType HalfOpTy,
7501259698Sdim                         SDPatternOperator hiop, Instruction DupInst>
7502259698Sdim  : Pat<(ResTy (op
7503259698Sdim          (HalfOpTy (hiop (OpTy VPR128:$Rn))),
7504259698Sdim          (HalfOpTy (Neon_vdup (i32 GPR32:$Re))))),
7505259698Sdim        (INST VPR128:$Rn, (DupInst $Re), 0)>;
7506259698Sdim
7507259698Sdimmulticlass NI_2VEL_mul_v3_pat<string subop, SDPatternOperator op> {
7508259698Sdim  def : NI_2VE_mul_laneq<!cast<Instruction>(subop # "_4s4h"), neon_uimm3_bare,
7509259698Sdim                         op, VPR64, VPR128Lo, v4i32, v4i16, v8i16>;
7510259698Sdim
7511259698Sdim  def : NI_2VE_mul_laneq<!cast<Instruction>(subop # "_2d2s"), neon_uimm2_bare,
7512259698Sdim                         op, VPR64, VPR128, v2i64, v2i32, v4i32>;
7513259698Sdim
7514259698Sdim  def : NI_2VEL2_mul_laneq<!cast<Instruction>(subop # "_4s8h"), neon_uimm3_bare,
7515259698Sdim                         op, VPR128Lo, v4i32, v8i16, v8i16, v4i16, Neon_High8H>;
7516259698Sdim
7517259698Sdim  def : NI_2VEL2_mul_laneq<!cast<Instruction>(subop # "_2d4s"), neon_uimm2_bare,
7518259698Sdim                           op, VPR128, v2i64, v4i32, v4i32, v2i32, Neon_High4S>;
7519259698Sdim
7520259698Sdim  def : NI_2VEL2_mul_lane0<!cast<Instruction>(subop # "_4s8h"),
7521259698Sdim                           op, v4i32, v8i16, v4i16, Neon_High8H, DUP8h>;
7522259698Sdim
7523259698Sdim  def : NI_2VEL2_mul_lane0<!cast<Instruction>(subop # "_2d4s"),
7524259698Sdim                           op, v2i64, v4i32, v2i32, Neon_High4S, DUP4s>;
7525259698Sdim
7526259698Sdim  // Index can only be half of the max value for lane in 64-bit vector
7527259698Sdim
7528259698Sdim  def : NI_2VE_mul_lane<!cast<Instruction>(subop # "_4s4h"), neon_uimm2_bare,
7529259698Sdim                        op, VPR64, VPR64Lo, v4i32, v4i16, v4i16>;
7530259698Sdim
7531259698Sdim  def : NI_2VE_mul_lane<!cast<Instruction>(subop # "_2d2s"), neon_uimm1_bare,
7532259698Sdim                        op, VPR64, VPR64, v2i64, v2i32, v2i32>;
7533259698Sdim
7534259698Sdim  def : NI_2VEL2_mul_lane<!cast<Instruction>(subop # "_4s8h"), neon_uimm2_bare,
7535259698Sdim                          op, VPR64Lo, v4i32, v8i16, v4i16, v4i16, Neon_High8H>;
7536259698Sdim
7537259698Sdim  def : NI_2VEL2_mul_lane<!cast<Instruction>(subop # "_2d4s"), neon_uimm1_bare,
7538259698Sdim                          op, VPR64, v2i64, v4i32, v2i32, v2i32, Neon_High4S>;
7539259698Sdim}
7540259698Sdim
7541259698Sdimdefm SMULL_lane_v3 : NI_2VEL_mul_v3_pat<"SMULLve", int_arm_neon_vmulls>;
7542259698Sdimdefm UMULL_lane_v3 : NI_2VEL_mul_v3_pat<"UMULLve", int_arm_neon_vmullu>;
7543259698Sdimdefm SQDMULL_lane_v3 : NI_2VEL_mul_v3_pat<"SQDMULLve", int_arm_neon_vqdmull>;
7544259698Sdim
7545259698Sdimmulticlass NI_qdma<SDPatternOperator op> {
7546259698Sdim  def _4s : PatFrag<(ops node:$Ra, node:$Rn, node:$Rm),
7547259698Sdim                    (op node:$Ra,
7548259698Sdim                      (v4i32 (int_arm_neon_vqdmull node:$Rn, node:$Rm)))>;
7549259698Sdim
7550259698Sdim  def _2d : PatFrag<(ops node:$Ra, node:$Rn, node:$Rm),
7551259698Sdim                    (op node:$Ra,
7552259698Sdim                      (v2i64 (int_arm_neon_vqdmull node:$Rn, node:$Rm)))>;
7553259698Sdim}
7554259698Sdim
7555259698Sdimdefm Neon_qdmlal : NI_qdma<int_arm_neon_vqadds>;
7556259698Sdimdefm Neon_qdmlsl : NI_qdma<int_arm_neon_vqsubs>;
7557259698Sdim
7558259698Sdimmulticlass NI_2VEL_v3_qdma_pat<string subop, string op> {
7559259698Sdim  def : NI_2VE_laneq<!cast<Instruction>(subop # "_4s4h"), neon_uimm3_bare,
7560259698Sdim                     !cast<PatFrag>(op # "_4s"), VPR128, VPR64, VPR128Lo,
7561259698Sdim                     v4i32, v4i16, v8i16>;
7562259698Sdim
7563259698Sdim  def : NI_2VE_laneq<!cast<Instruction>(subop # "_2d2s"), neon_uimm2_bare,
7564259698Sdim                     !cast<PatFrag>(op # "_2d"), VPR128, VPR64, VPR128,
7565259698Sdim                     v2i64, v2i32, v4i32>;
7566259698Sdim
7567259698Sdim  def : NI_2VEL2_laneq<!cast<Instruction>(subop # "_4s8h"), neon_uimm3_bare,
7568259698Sdim                       !cast<PatFrag>(op # "_4s"), VPR128Lo,
7569259698Sdim                       v4i32, v8i16, v8i16, v4i16, Neon_High8H>;
7570259698Sdim
7571259698Sdim  def : NI_2VEL2_laneq<!cast<Instruction>(subop # "_2d4s"), neon_uimm2_bare,
7572259698Sdim                       !cast<PatFrag>(op # "_2d"), VPR128,
7573259698Sdim                       v2i64, v4i32, v4i32, v2i32, Neon_High4S>;
7574259698Sdim
7575259698Sdim  def : NI_2VEL2_lane0<!cast<Instruction>(subop # "_4s8h"),
7576259698Sdim                       !cast<PatFrag>(op # "_4s"),
7577259698Sdim                       v4i32, v8i16, v4i16, Neon_High8H, DUP8h>;
7578259698Sdim
7579259698Sdim  def : NI_2VEL2_lane0<!cast<Instruction>(subop # "_2d4s"),
7580259698Sdim                       !cast<PatFrag>(op # "_2d"),
7581259698Sdim                       v2i64, v4i32, v2i32, Neon_High4S, DUP4s>;
7582259698Sdim
7583259698Sdim  // Index can only be half of the max value for lane in 64-bit vector
7584259698Sdim
7585259698Sdim  def : NI_2VE_lane<!cast<Instruction>(subop # "_4s4h"), neon_uimm2_bare,
7586259698Sdim                    !cast<PatFrag>(op # "_4s"), VPR128, VPR64, VPR64Lo,
7587259698Sdim                    v4i32, v4i16, v4i16>;
7588259698Sdim
7589259698Sdim  def : NI_2VE_lane<!cast<Instruction>(subop # "_2d2s"), neon_uimm1_bare,
7590259698Sdim                    !cast<PatFrag>(op # "_2d"), VPR128, VPR64, VPR64,
7591259698Sdim                    v2i64, v2i32, v2i32>;
7592259698Sdim
7593259698Sdim  def : NI_2VEL2_lane<!cast<Instruction>(subop # "_4s8h"), neon_uimm2_bare,
7594259698Sdim                      !cast<PatFrag>(op # "_4s"), VPR64Lo,
7595259698Sdim                      v4i32, v8i16, v4i16, v4i16, Neon_High8H>;
7596259698Sdim
7597259698Sdim  def : NI_2VEL2_lane<!cast<Instruction>(subop # "_2d4s"), neon_uimm1_bare,
7598259698Sdim                      !cast<PatFrag>(op # "_2d"), VPR64,
7599259698Sdim                      v2i64, v4i32, v2i32, v2i32, Neon_High4S>;
7600259698Sdim}
7601259698Sdim
7602259698Sdimdefm SQDMLAL_lane_v3 : NI_2VEL_v3_qdma_pat<"SQDMLALvve", "Neon_qdmlal">;
7603259698Sdimdefm SQDMLSL_lane_v3 : NI_2VEL_v3_qdma_pat<"SQDMLSLvve", "Neon_qdmlsl">;
7604259698Sdim
7605259698Sdim// End of implementation for instruction class (3V Elem)
7606259698Sdim
7607259698Sdimclass NeonI_REV<string asmop, string Res, bits<2> size, bit Q, bit U,
7608259698Sdim                bits<5> opcode, RegisterOperand ResVPR, ValueType ResTy,
7609259698Sdim                SDPatternOperator Neon_Rev>
7610259698Sdim  : NeonI_2VMisc<Q, U, size, opcode,
7611259698Sdim               (outs ResVPR:$Rd), (ins ResVPR:$Rn),
7612259698Sdim               asmop # "\t$Rd." # Res # ", $Rn." # Res,
7613259698Sdim               [(set (ResTy ResVPR:$Rd),
7614259698Sdim                  (ResTy (Neon_Rev (ResTy ResVPR:$Rn))))],
7615259698Sdim               NoItinerary> ;
7616259698Sdim
7617259698Sdimdef REV64_16b : NeonI_REV<"rev64", "16b", 0b00, 0b1, 0b0, 0b00000, VPR128,
7618259698Sdim                          v16i8, Neon_rev64>;
7619259698Sdimdef REV64_8h : NeonI_REV<"rev64", "8h", 0b01, 0b1, 0b0, 0b00000, VPR128,
7620259698Sdim                         v8i16, Neon_rev64>;
7621259698Sdimdef REV64_4s : NeonI_REV<"rev64", "4s", 0b10, 0b1, 0b0, 0b00000, VPR128,
7622259698Sdim                         v4i32, Neon_rev64>;
7623259698Sdimdef REV64_8b : NeonI_REV<"rev64", "8b", 0b00, 0b0, 0b0, 0b00000, VPR64,
7624259698Sdim                         v8i8, Neon_rev64>;
7625259698Sdimdef REV64_4h : NeonI_REV<"rev64", "4h", 0b01, 0b0, 0b0, 0b00000, VPR64,
7626259698Sdim                         v4i16, Neon_rev64>;
7627259698Sdimdef REV64_2s : NeonI_REV<"rev64", "2s", 0b10, 0b0, 0b0, 0b00000, VPR64,
7628259698Sdim                         v2i32, Neon_rev64>;
7629259698Sdim
7630259698Sdimdef : Pat<(v4f32 (Neon_rev64 (v4f32 VPR128:$Rn))), (REV64_4s VPR128:$Rn)>;
7631259698Sdimdef : Pat<(v2f32 (Neon_rev64 (v2f32 VPR64:$Rn))), (REV64_2s VPR64:$Rn)>;
7632259698Sdim
7633259698Sdimdef REV32_16b : NeonI_REV<"rev32", "16b", 0b00, 0b1, 0b1, 0b00000, VPR128,
7634259698Sdim                          v16i8, Neon_rev32>;
7635259698Sdimdef REV32_8h : NeonI_REV<"rev32", "8h", 0b01, 0b1, 0b1, 0b00000, VPR128,
7636259698Sdim                          v8i16, Neon_rev32>;
7637259698Sdimdef REV32_8b : NeonI_REV<"rev32", "8b", 0b00, 0b0, 0b1, 0b00000, VPR64,
7638259698Sdim                         v8i8, Neon_rev32>;
7639259698Sdimdef REV32_4h : NeonI_REV<"rev32", "4h", 0b01, 0b0, 0b1, 0b00000, VPR64,
7640259698Sdim                         v4i16, Neon_rev32>;
7641259698Sdim
7642259698Sdimdef REV16_16b : NeonI_REV<"rev16", "16b", 0b00, 0b1, 0b0, 0b00001, VPR128,
7643259698Sdim                          v16i8, Neon_rev16>;
7644259698Sdimdef REV16_8b : NeonI_REV<"rev16", "8b", 0b00, 0b0, 0b0, 0b00001, VPR64,
7645259698Sdim                         v8i8, Neon_rev16>;
7646259698Sdim
7647259698Sdimmulticlass NeonI_PairwiseAdd<string asmop, bit U, bits<5> opcode,
7648259698Sdim                             SDPatternOperator Neon_Padd> {
7649259698Sdim  def 16b8h : NeonI_2VMisc<0b1, U, 0b00, opcode,
7650259698Sdim                           (outs VPR128:$Rd), (ins VPR128:$Rn),
7651259698Sdim                           asmop # "\t$Rd.8h, $Rn.16b",
7652259698Sdim                           [(set (v8i16 VPR128:$Rd),
7653259698Sdim                              (v8i16 (Neon_Padd (v16i8 VPR128:$Rn))))],
7654259698Sdim                           NoItinerary>;
7655259698Sdim
7656259698Sdim  def 8b4h : NeonI_2VMisc<0b0, U, 0b00, opcode,
7657259698Sdim                          (outs VPR64:$Rd), (ins VPR64:$Rn),
7658259698Sdim                          asmop # "\t$Rd.4h, $Rn.8b",
7659259698Sdim                          [(set (v4i16 VPR64:$Rd),
7660259698Sdim                             (v4i16 (Neon_Padd (v8i8 VPR64:$Rn))))],
7661259698Sdim                          NoItinerary>;
7662259698Sdim
7663259698Sdim  def 8h4s : NeonI_2VMisc<0b1, U, 0b01, opcode,
7664259698Sdim                           (outs VPR128:$Rd), (ins VPR128:$Rn),
7665259698Sdim                           asmop # "\t$Rd.4s, $Rn.8h",
7666259698Sdim                           [(set (v4i32 VPR128:$Rd),
7667259698Sdim                              (v4i32 (Neon_Padd (v8i16 VPR128:$Rn))))],
7668259698Sdim                           NoItinerary>;
7669259698Sdim
7670259698Sdim  def 4h2s : NeonI_2VMisc<0b0, U, 0b01, opcode,
7671259698Sdim                          (outs VPR64:$Rd), (ins VPR64:$Rn),
7672259698Sdim                          asmop # "\t$Rd.2s, $Rn.4h",
7673259698Sdim                          [(set (v2i32 VPR64:$Rd),
7674259698Sdim                             (v2i32 (Neon_Padd (v4i16 VPR64:$Rn))))],
7675259698Sdim                          NoItinerary>;
7676259698Sdim
7677259698Sdim  def 4s2d : NeonI_2VMisc<0b1, U, 0b10, opcode,
7678259698Sdim                           (outs VPR128:$Rd), (ins VPR128:$Rn),
7679259698Sdim                           asmop # "\t$Rd.2d, $Rn.4s",
7680259698Sdim                           [(set (v2i64 VPR128:$Rd),
7681259698Sdim                              (v2i64 (Neon_Padd (v4i32 VPR128:$Rn))))],
7682259698Sdim                           NoItinerary>;
7683259698Sdim
7684259698Sdim  def 2s1d : NeonI_2VMisc<0b0, U, 0b10, opcode,
7685259698Sdim                          (outs VPR64:$Rd), (ins VPR64:$Rn),
7686259698Sdim                          asmop # "\t$Rd.1d, $Rn.2s",
7687259698Sdim                          [(set (v1i64 VPR64:$Rd),
7688259698Sdim                             (v1i64 (Neon_Padd (v2i32 VPR64:$Rn))))],
7689259698Sdim                          NoItinerary>;
7690259698Sdim}
7691259698Sdim
7692259698Sdimdefm SADDLP : NeonI_PairwiseAdd<"saddlp", 0b0, 0b00010,
7693259698Sdim                                int_arm_neon_vpaddls>;
7694259698Sdimdefm UADDLP : NeonI_PairwiseAdd<"uaddlp", 0b1, 0b00010,
7695259698Sdim                                int_arm_neon_vpaddlu>;
7696259698Sdim
7697259698Sdimmulticlass NeonI_PairwiseAddAcc<string asmop, bit U, bits<5> opcode,
7698259698Sdim                             SDPatternOperator Neon_Padd> {
7699259698Sdim  let Constraints = "$src = $Rd" in {
7700259698Sdim    def 16b8h : NeonI_2VMisc<0b1, U, 0b00, opcode,
7701259698Sdim                             (outs VPR128:$Rd), (ins VPR128:$src, VPR128:$Rn),
7702259698Sdim                             asmop # "\t$Rd.8h, $Rn.16b",
7703259698Sdim                             [(set (v8i16 VPR128:$Rd),
7704259698Sdim                                (v8i16 (Neon_Padd
7705259698Sdim                                  (v8i16 VPR128:$src), (v16i8 VPR128:$Rn))))],
7706259698Sdim                             NoItinerary>;
7707259698Sdim
7708259698Sdim    def 8b4h : NeonI_2VMisc<0b0, U, 0b00, opcode,
7709259698Sdim                            (outs VPR64:$Rd), (ins VPR64:$src, VPR64:$Rn),
7710259698Sdim                            asmop # "\t$Rd.4h, $Rn.8b",
7711259698Sdim                            [(set (v4i16 VPR64:$Rd),
7712259698Sdim                               (v4i16 (Neon_Padd
7713259698Sdim                                 (v4i16 VPR64:$src), (v8i8 VPR64:$Rn))))],
7714259698Sdim                            NoItinerary>;
7715259698Sdim
7716259698Sdim    def 8h4s : NeonI_2VMisc<0b1, U, 0b01, opcode,
7717259698Sdim                            (outs VPR128:$Rd), (ins VPR128:$src, VPR128:$Rn),
7718259698Sdim                            asmop # "\t$Rd.4s, $Rn.8h",
7719259698Sdim                            [(set (v4i32 VPR128:$Rd),
7720259698Sdim                               (v4i32 (Neon_Padd
7721259698Sdim                                 (v4i32 VPR128:$src), (v8i16 VPR128:$Rn))))],
7722259698Sdim                            NoItinerary>;
7723259698Sdim
7724259698Sdim    def 4h2s : NeonI_2VMisc<0b0, U, 0b01, opcode,
7725259698Sdim                            (outs VPR64:$Rd), (ins VPR64:$src, VPR64:$Rn),
7726259698Sdim                            asmop # "\t$Rd.2s, $Rn.4h",
7727259698Sdim                            [(set (v2i32 VPR64:$Rd),
7728259698Sdim                               (v2i32 (Neon_Padd
7729259698Sdim                                 (v2i32 VPR64:$src), (v4i16 VPR64:$Rn))))],
7730259698Sdim                            NoItinerary>;
7731259698Sdim
7732259698Sdim    def 4s2d : NeonI_2VMisc<0b1, U, 0b10, opcode,
7733259698Sdim                            (outs VPR128:$Rd), (ins VPR128:$src, VPR128:$Rn),
7734259698Sdim                            asmop # "\t$Rd.2d, $Rn.4s",
7735259698Sdim                            [(set (v2i64 VPR128:$Rd),
7736259698Sdim                               (v2i64 (Neon_Padd
7737259698Sdim                                 (v2i64 VPR128:$src), (v4i32 VPR128:$Rn))))],
7738259698Sdim                            NoItinerary>;
7739259698Sdim
7740259698Sdim    def 2s1d : NeonI_2VMisc<0b0, U, 0b10, opcode,
7741259698Sdim                            (outs VPR64:$Rd), (ins VPR64:$src, VPR64:$Rn),
7742259698Sdim                            asmop # "\t$Rd.1d, $Rn.2s",
7743259698Sdim                            [(set (v1i64 VPR64:$Rd),
7744259698Sdim                               (v1i64 (Neon_Padd
7745259698Sdim                                 (v1i64 VPR64:$src), (v2i32 VPR64:$Rn))))],
7746259698Sdim                            NoItinerary>;
7747259698Sdim  }
7748259698Sdim}
7749259698Sdim
7750259698Sdimdefm SADALP : NeonI_PairwiseAddAcc<"sadalp", 0b0, 0b00110,
7751259698Sdim                                   int_arm_neon_vpadals>;
7752259698Sdimdefm UADALP : NeonI_PairwiseAddAcc<"uadalp", 0b1, 0b00110,
7753259698Sdim                                   int_arm_neon_vpadalu>;
7754259698Sdim
7755259698Sdimmulticlass NeonI_2VMisc_BHSDsize_1Arg<string asmop, bit U, bits<5> opcode> {
7756259698Sdim  def 16b : NeonI_2VMisc<0b1, U, 0b00, opcode,
7757259698Sdim                         (outs VPR128:$Rd), (ins VPR128:$Rn),
7758259698Sdim                         asmop # "\t$Rd.16b, $Rn.16b",
7759259698Sdim                         [], NoItinerary>;
7760259698Sdim
7761259698Sdim  def 8h : NeonI_2VMisc<0b1, U, 0b01, opcode,
7762259698Sdim                        (outs VPR128:$Rd), (ins VPR128:$Rn),
7763259698Sdim                        asmop # "\t$Rd.8h, $Rn.8h",
7764259698Sdim                        [], NoItinerary>;
7765259698Sdim
7766259698Sdim  def 4s : NeonI_2VMisc<0b1, U, 0b10, opcode,
7767259698Sdim                        (outs VPR128:$Rd), (ins VPR128:$Rn),
7768259698Sdim                        asmop # "\t$Rd.4s, $Rn.4s",
7769259698Sdim                        [], NoItinerary>;
7770259698Sdim
7771259698Sdim  def 2d : NeonI_2VMisc<0b1, U, 0b11, opcode,
7772259698Sdim                        (outs VPR128:$Rd), (ins VPR128:$Rn),
7773259698Sdim                        asmop # "\t$Rd.2d, $Rn.2d",
7774259698Sdim                        [], NoItinerary>;
7775259698Sdim
7776259698Sdim  def 8b : NeonI_2VMisc<0b0, U, 0b00, opcode,
7777259698Sdim                         (outs VPR64:$Rd), (ins VPR64:$Rn),
7778259698Sdim                         asmop # "\t$Rd.8b, $Rn.8b",
7779259698Sdim                         [], NoItinerary>;
7780259698Sdim
7781259698Sdim  def 4h : NeonI_2VMisc<0b0, U, 0b01, opcode,
7782259698Sdim                        (outs VPR64:$Rd), (ins VPR64:$Rn),
7783259698Sdim                        asmop # "\t$Rd.4h, $Rn.4h",
7784259698Sdim                        [], NoItinerary>;
7785259698Sdim
7786259698Sdim  def 2s : NeonI_2VMisc<0b0, U, 0b10, opcode,
7787259698Sdim                        (outs VPR64:$Rd), (ins VPR64:$Rn),
7788259698Sdim                        asmop # "\t$Rd.2s, $Rn.2s",
7789259698Sdim                        [], NoItinerary>;
7790259698Sdim}
7791259698Sdim
7792259698Sdimdefm SQABS : NeonI_2VMisc_BHSDsize_1Arg<"sqabs", 0b0, 0b00111>;
7793259698Sdimdefm SQNEG : NeonI_2VMisc_BHSDsize_1Arg<"sqneg", 0b1, 0b00111>;
7794259698Sdimdefm ABS : NeonI_2VMisc_BHSDsize_1Arg<"abs", 0b0, 0b01011>;
7795259698Sdimdefm NEG : NeonI_2VMisc_BHSDsize_1Arg<"neg", 0b1, 0b01011>;
7796259698Sdim
7797259698Sdimmulticlass NeonI_2VMisc_BHSD_1Arg_Pattern<string Prefix,
7798259698Sdim                                          SDPatternOperator Neon_Op> {
7799259698Sdim  def : Pat<(v16i8 (Neon_Op (v16i8 VPR128:$Rn))),
7800259698Sdim            (v16i8 (!cast<Instruction>(Prefix # 16b) (v16i8 VPR128:$Rn)))>;
7801259698Sdim
7802259698Sdim  def : Pat<(v8i16 (Neon_Op (v8i16 VPR128:$Rn))),
7803259698Sdim            (v8i16 (!cast<Instruction>(Prefix # 8h) (v8i16 VPR128:$Rn)))>;
7804259698Sdim
7805259698Sdim  def : Pat<(v4i32 (Neon_Op (v4i32 VPR128:$Rn))),
7806259698Sdim            (v4i32 (!cast<Instruction>(Prefix # 4s) (v4i32 VPR128:$Rn)))>;
7807259698Sdim
7808259698Sdim  def : Pat<(v2i64 (Neon_Op (v2i64 VPR128:$Rn))),
7809259698Sdim            (v2i64 (!cast<Instruction>(Prefix # 2d) (v2i64 VPR128:$Rn)))>;
7810259698Sdim
7811259698Sdim  def : Pat<(v8i8 (Neon_Op (v8i8 VPR64:$Rn))),
7812259698Sdim            (v8i8 (!cast<Instruction>(Prefix # 8b) (v8i8 VPR64:$Rn)))>;
7813259698Sdim
7814259698Sdim  def : Pat<(v4i16 (Neon_Op (v4i16 VPR64:$Rn))),
7815259698Sdim            (v4i16 (!cast<Instruction>(Prefix # 4h) (v4i16 VPR64:$Rn)))>;
7816259698Sdim
7817259698Sdim  def : Pat<(v2i32 (Neon_Op (v2i32 VPR64:$Rn))),
7818259698Sdim            (v2i32 (!cast<Instruction>(Prefix # 2s) (v2i32 VPR64:$Rn)))>;
7819259698Sdim}
7820259698Sdim
7821259698Sdimdefm : NeonI_2VMisc_BHSD_1Arg_Pattern<"SQABS", int_arm_neon_vqabs>;
7822259698Sdimdefm : NeonI_2VMisc_BHSD_1Arg_Pattern<"SQNEG", int_arm_neon_vqneg>;
7823259698Sdimdefm : NeonI_2VMisc_BHSD_1Arg_Pattern<"ABS", int_arm_neon_vabs>;
7824259698Sdim
7825259698Sdimdef : Pat<(v16i8 (sub
7826259698Sdim            (v16i8 Neon_AllZero),
7827259698Sdim            (v16i8 VPR128:$Rn))),
7828259698Sdim          (v16i8 (NEG16b (v16i8 VPR128:$Rn)))>;
7829259698Sdimdef : Pat<(v8i8 (sub
7830259698Sdim            (v8i8 Neon_AllZero),
7831259698Sdim            (v8i8 VPR64:$Rn))),
7832259698Sdim          (v8i8 (NEG8b (v8i8 VPR64:$Rn)))>;
7833259698Sdimdef : Pat<(v8i16 (sub
7834259698Sdim            (v8i16 (bitconvert (v16i8 Neon_AllZero))),
7835259698Sdim            (v8i16 VPR128:$Rn))),
7836259698Sdim          (v8i16 (NEG8h (v8i16 VPR128:$Rn)))>;
7837259698Sdimdef : Pat<(v4i16 (sub
7838259698Sdim            (v4i16 (bitconvert (v8i8 Neon_AllZero))),
7839259698Sdim            (v4i16 VPR64:$Rn))),
7840259698Sdim          (v4i16 (NEG4h (v4i16 VPR64:$Rn)))>;
7841259698Sdimdef : Pat<(v4i32 (sub
7842259698Sdim            (v4i32 (bitconvert (v16i8 Neon_AllZero))),
7843259698Sdim            (v4i32 VPR128:$Rn))),
7844259698Sdim          (v4i32 (NEG4s (v4i32 VPR128:$Rn)))>;
7845259698Sdimdef : Pat<(v2i32 (sub
7846259698Sdim            (v2i32 (bitconvert (v8i8 Neon_AllZero))),
7847259698Sdim            (v2i32 VPR64:$Rn))),
7848259698Sdim          (v2i32 (NEG2s (v2i32 VPR64:$Rn)))>;
7849259698Sdimdef : Pat<(v2i64 (sub
7850259698Sdim            (v2i64 (bitconvert (v16i8 Neon_AllZero))),
7851259698Sdim            (v2i64 VPR128:$Rn))),
7852259698Sdim          (v2i64 (NEG2d (v2i64 VPR128:$Rn)))>;
7853259698Sdim
7854259698Sdimmulticlass NeonI_2VMisc_BHSDsize_2Args<string asmop, bit U, bits<5> opcode> {
7855259698Sdim  let Constraints = "$src = $Rd" in {
7856259698Sdim    def 16b : NeonI_2VMisc<0b1, U, 0b00, opcode,
7857259698Sdim                           (outs VPR128:$Rd), (ins VPR128:$src, VPR128:$Rn),
7858259698Sdim                           asmop # "\t$Rd.16b, $Rn.16b",
7859259698Sdim                           [], NoItinerary>;
7860259698Sdim
7861259698Sdim    def 8h : NeonI_2VMisc<0b1, U, 0b01, opcode,
7862259698Sdim                          (outs VPR128:$Rd), (ins VPR128:$src, VPR128:$Rn),
7863259698Sdim                          asmop # "\t$Rd.8h, $Rn.8h",
7864259698Sdim                          [], NoItinerary>;
7865259698Sdim
7866259698Sdim    def 4s : NeonI_2VMisc<0b1, U, 0b10, opcode,
7867259698Sdim                          (outs VPR128:$Rd), (ins VPR128:$src, VPR128:$Rn),
7868259698Sdim                          asmop # "\t$Rd.4s, $Rn.4s",
7869259698Sdim                          [], NoItinerary>;
7870259698Sdim
7871259698Sdim    def 2d : NeonI_2VMisc<0b1, U, 0b11, opcode,
7872259698Sdim                          (outs VPR128:$Rd), (ins VPR128:$src, VPR128:$Rn),
7873259698Sdim                          asmop # "\t$Rd.2d, $Rn.2d",
7874259698Sdim                          [], NoItinerary>;
7875259698Sdim
7876259698Sdim    def 8b : NeonI_2VMisc<0b0, U, 0b00, opcode,
7877259698Sdim                          (outs VPR64:$Rd), (ins VPR64:$src, VPR64:$Rn),
7878259698Sdim                          asmop # "\t$Rd.8b, $Rn.8b",
7879259698Sdim                          [], NoItinerary>;
7880259698Sdim
7881259698Sdim    def 4h : NeonI_2VMisc<0b0, U, 0b01, opcode,
7882259698Sdim                          (outs VPR64:$Rd), (ins VPR64:$src, VPR64:$Rn),
7883259698Sdim                          asmop # "\t$Rd.4h, $Rn.4h",
7884259698Sdim                          [], NoItinerary>;
7885259698Sdim
7886259698Sdim    def 2s : NeonI_2VMisc<0b0, U, 0b10, opcode,
7887259698Sdim                          (outs VPR64:$Rd), (ins VPR64:$src, VPR64:$Rn),
7888259698Sdim                          asmop # "\t$Rd.2s, $Rn.2s",
7889259698Sdim                          [], NoItinerary>;
7890259698Sdim  }
7891259698Sdim}
7892259698Sdim
7893259698Sdimdefm SUQADD : NeonI_2VMisc_BHSDsize_2Args<"suqadd", 0b0, 0b00011>;
7894259698Sdimdefm USQADD : NeonI_2VMisc_BHSDsize_2Args<"usqadd", 0b1, 0b00011>;
7895259698Sdim
7896259698Sdimmulticlass NeonI_2VMisc_BHSD_2Args_Pattern<string Prefix,
7897259698Sdim                                           SDPatternOperator Neon_Op> {
7898259698Sdim  def : Pat<(v16i8 (Neon_Op (v16i8 VPR128:$src), (v16i8 VPR128:$Rn))),
7899259698Sdim            (v16i8 (!cast<Instruction>(Prefix # 16b)
7900259698Sdim              (v16i8 VPR128:$src), (v16i8 VPR128:$Rn)))>;
7901259698Sdim
7902259698Sdim  def : Pat<(v8i16 (Neon_Op (v8i16 VPR128:$src), (v8i16 VPR128:$Rn))),
7903259698Sdim            (v8i16 (!cast<Instruction>(Prefix # 8h)
7904259698Sdim              (v8i16 VPR128:$src), (v8i16 VPR128:$Rn)))>;
7905259698Sdim
7906259698Sdim  def : Pat<(v4i32 (Neon_Op (v4i32 VPR128:$src), (v4i32 VPR128:$Rn))),
7907259698Sdim            (v4i32 (!cast<Instruction>(Prefix # 4s)
7908259698Sdim              (v4i32 VPR128:$src), (v4i32 VPR128:$Rn)))>;
7909259698Sdim
7910259698Sdim  def : Pat<(v2i64 (Neon_Op (v2i64 VPR128:$src), (v2i64 VPR128:$Rn))),
7911259698Sdim            (v2i64 (!cast<Instruction>(Prefix # 2d)
7912259698Sdim              (v2i64 VPR128:$src), (v2i64 VPR128:$Rn)))>;
7913259698Sdim
7914259698Sdim  def : Pat<(v8i8 (Neon_Op (v8i8 VPR64:$src), (v8i8 VPR64:$Rn))),
7915259698Sdim            (v8i8 (!cast<Instruction>(Prefix # 8b)
7916259698Sdim              (v8i8 VPR64:$src), (v8i8 VPR64:$Rn)))>;
7917259698Sdim
7918259698Sdim  def : Pat<(v4i16 (Neon_Op (v4i16 VPR64:$src), (v4i16 VPR64:$Rn))),
7919259698Sdim            (v4i16 (!cast<Instruction>(Prefix # 4h)
7920259698Sdim              (v4i16 VPR64:$src), (v4i16 VPR64:$Rn)))>;
7921259698Sdim
7922259698Sdim  def : Pat<(v2i32 (Neon_Op (v2i32 VPR64:$src), (v2i32 VPR64:$Rn))),
7923259698Sdim            (v2i32 (!cast<Instruction>(Prefix # 2s)
7924259698Sdim              (v2i32 VPR64:$src), (v2i32 VPR64:$Rn)))>;
7925259698Sdim}
7926259698Sdim
7927259698Sdimdefm : NeonI_2VMisc_BHSD_2Args_Pattern<"SUQADD", int_aarch64_neon_suqadd>;
7928259698Sdimdefm : NeonI_2VMisc_BHSD_2Args_Pattern<"USQADD", int_aarch64_neon_usqadd>;
7929259698Sdim
7930259698Sdimmulticlass NeonI_2VMisc_BHSsizes<string asmop, bit U,
7931259698Sdim                          SDPatternOperator Neon_Op> {
7932259698Sdim  def 16b : NeonI_2VMisc<0b1, U, 0b00, 0b00100,
7933259698Sdim                         (outs VPR128:$Rd), (ins VPR128:$Rn),
7934259698Sdim                         asmop # "\t$Rd.16b, $Rn.16b",
7935259698Sdim                         [(set (v16i8 VPR128:$Rd),
7936259698Sdim                            (v16i8 (Neon_Op (v16i8 VPR128:$Rn))))],
7937259698Sdim                         NoItinerary>;
7938259698Sdim
7939259698Sdim  def 8h : NeonI_2VMisc<0b1, U, 0b01, 0b00100,
7940259698Sdim                        (outs VPR128:$Rd), (ins VPR128:$Rn),
7941259698Sdim                        asmop # "\t$Rd.8h, $Rn.8h",
7942259698Sdim                        [(set (v8i16 VPR128:$Rd),
7943259698Sdim                           (v8i16 (Neon_Op (v8i16 VPR128:$Rn))))],
7944259698Sdim                        NoItinerary>;
7945259698Sdim
7946259698Sdim  def 4s : NeonI_2VMisc<0b1, U, 0b10, 0b00100,
7947259698Sdim                        (outs VPR128:$Rd), (ins VPR128:$Rn),
7948259698Sdim                        asmop # "\t$Rd.4s, $Rn.4s",
7949259698Sdim                        [(set (v4i32 VPR128:$Rd),
7950259698Sdim                           (v4i32 (Neon_Op (v4i32 VPR128:$Rn))))],
7951259698Sdim                        NoItinerary>;
7952259698Sdim
7953259698Sdim  def 8b : NeonI_2VMisc<0b0, U, 0b00, 0b00100,
7954259698Sdim                        (outs VPR64:$Rd), (ins VPR64:$Rn),
7955259698Sdim                        asmop # "\t$Rd.8b, $Rn.8b",
7956259698Sdim                        [(set (v8i8 VPR64:$Rd),
7957259698Sdim                           (v8i8 (Neon_Op (v8i8 VPR64:$Rn))))],
7958259698Sdim                        NoItinerary>;
7959259698Sdim
7960259698Sdim  def 4h : NeonI_2VMisc<0b0, U, 0b01, 0b00100,
7961259698Sdim                        (outs VPR64:$Rd), (ins VPR64:$Rn),
7962259698Sdim                        asmop # "\t$Rd.4h, $Rn.4h",
7963259698Sdim                        [(set (v4i16 VPR64:$Rd),
7964259698Sdim                           (v4i16 (Neon_Op (v4i16 VPR64:$Rn))))],
7965259698Sdim                        NoItinerary>;
7966259698Sdim
7967259698Sdim  def 2s : NeonI_2VMisc<0b0, U, 0b10, 0b00100,
7968259698Sdim                        (outs VPR64:$Rd), (ins VPR64:$Rn),
7969259698Sdim                        asmop # "\t$Rd.2s, $Rn.2s",
7970259698Sdim                        [(set (v2i32 VPR64:$Rd),
7971259698Sdim                           (v2i32 (Neon_Op (v2i32 VPR64:$Rn))))],
7972259698Sdim                        NoItinerary>;
7973259698Sdim}
7974259698Sdim
7975259698Sdimdefm CLS : NeonI_2VMisc_BHSsizes<"cls", 0b0, int_arm_neon_vcls>;
7976259698Sdimdefm CLZ : NeonI_2VMisc_BHSsizes<"clz", 0b1, ctlz>;
7977259698Sdim
7978259698Sdimmulticlass NeonI_2VMisc_Bsize<string asmop, bit U, bits<2> size,
7979259698Sdim                              bits<5> Opcode> {
7980259698Sdim  def 16b : NeonI_2VMisc<0b1, U, size, Opcode,
7981259698Sdim                         (outs VPR128:$Rd), (ins VPR128:$Rn),
7982259698Sdim                         asmop # "\t$Rd.16b, $Rn.16b",
7983259698Sdim                         [], NoItinerary>;
7984259698Sdim
7985259698Sdim  def 8b : NeonI_2VMisc<0b0, U, size, Opcode,
7986259698Sdim                        (outs VPR64:$Rd), (ins VPR64:$Rn),
7987259698Sdim                        asmop # "\t$Rd.8b, $Rn.8b",
7988259698Sdim                        [], NoItinerary>;
7989259698Sdim}
7990259698Sdim
7991259698Sdimdefm CNT : NeonI_2VMisc_Bsize<"cnt", 0b0, 0b00, 0b00101>;
7992259698Sdimdefm NOT : NeonI_2VMisc_Bsize<"not", 0b1, 0b00, 0b00101>;
7993259698Sdimdefm RBIT : NeonI_2VMisc_Bsize<"rbit", 0b1, 0b01, 0b00101>;
7994259698Sdim
7995259698Sdimdef : NeonInstAlias<"mvn $Rd.16b, $Rn.16b",
7996259698Sdim                    (NOT16b VPR128:$Rd, VPR128:$Rn), 0>;
7997259698Sdimdef : NeonInstAlias<"mvn $Rd.8b, $Rn.8b",
7998259698Sdim                    (NOT8b VPR64:$Rd, VPR64:$Rn), 0>;
7999259698Sdim
8000259698Sdimdef : Pat<(v16i8 (ctpop (v16i8 VPR128:$Rn))),
8001259698Sdim          (v16i8 (CNT16b (v16i8 VPR128:$Rn)))>;
8002259698Sdimdef : Pat<(v8i8 (ctpop (v8i8 VPR64:$Rn))),
8003259698Sdim          (v8i8 (CNT8b (v8i8 VPR64:$Rn)))>;
8004259698Sdim
8005259698Sdimdef : Pat<(v16i8 (xor
8006259698Sdim            (v16i8 VPR128:$Rn),
8007259698Sdim            (v16i8 Neon_AllOne))),
8008259698Sdim          (v16i8 (NOT16b (v16i8 VPR128:$Rn)))>;
8009259698Sdimdef : Pat<(v8i8 (xor
8010259698Sdim            (v8i8 VPR64:$Rn),
8011259698Sdim            (v8i8 Neon_AllOne))),
8012259698Sdim          (v8i8 (NOT8b (v8i8 VPR64:$Rn)))>;
8013259698Sdimdef : Pat<(v8i16 (xor
8014259698Sdim            (v8i16 VPR128:$Rn),
8015259698Sdim            (v8i16 (bitconvert (v16i8 Neon_AllOne))))),
8016259698Sdim          (NOT16b VPR128:$Rn)>;
8017259698Sdimdef : Pat<(v4i16 (xor
8018259698Sdim            (v4i16 VPR64:$Rn),
8019259698Sdim            (v4i16 (bitconvert (v8i8 Neon_AllOne))))),
8020259698Sdim          (NOT8b VPR64:$Rn)>;
8021259698Sdimdef : Pat<(v4i32 (xor
8022259698Sdim            (v4i32 VPR128:$Rn),
8023259698Sdim            (v4i32 (bitconvert (v16i8 Neon_AllOne))))),
8024259698Sdim          (NOT16b VPR128:$Rn)>;
8025259698Sdimdef : Pat<(v2i32 (xor
8026259698Sdim            (v2i32 VPR64:$Rn),
8027259698Sdim            (v2i32 (bitconvert (v8i8 Neon_AllOne))))),
8028259698Sdim          (NOT8b VPR64:$Rn)>;
8029259698Sdimdef : Pat<(v2i64 (xor
8030259698Sdim            (v2i64 VPR128:$Rn),
8031259698Sdim            (v2i64 (bitconvert (v16i8 Neon_AllOne))))),
8032259698Sdim          (NOT16b VPR128:$Rn)>;
8033259698Sdim
8034259698Sdimdef : Pat<(v16i8 (int_aarch64_neon_rbit (v16i8 VPR128:$Rn))),
8035259698Sdim          (v16i8 (RBIT16b (v16i8 VPR128:$Rn)))>;
8036259698Sdimdef : Pat<(v8i8 (int_aarch64_neon_rbit (v8i8 VPR64:$Rn))),
8037259698Sdim          (v8i8 (RBIT8b (v8i8 VPR64:$Rn)))>;
8038259698Sdim
8039259698Sdimmulticlass NeonI_2VMisc_SDsizes<string asmop, bit U, bits<5> opcode,
8040259698Sdim                                SDPatternOperator Neon_Op> {
8041259698Sdim  def 4s : NeonI_2VMisc<0b1, U, 0b10, opcode,
8042259698Sdim                        (outs VPR128:$Rd), (ins VPR128:$Rn),
8043259698Sdim                        asmop # "\t$Rd.4s, $Rn.4s",
8044259698Sdim                        [(set (v4f32 VPR128:$Rd),
8045259698Sdim                           (v4f32 (Neon_Op (v4f32 VPR128:$Rn))))],
8046259698Sdim                        NoItinerary>;
8047259698Sdim
8048259698Sdim  def 2d : NeonI_2VMisc<0b1, U, 0b11, opcode,
8049259698Sdim                        (outs VPR128:$Rd), (ins VPR128:$Rn),
8050259698Sdim                        asmop # "\t$Rd.2d, $Rn.2d",
8051259698Sdim                        [(set (v2f64 VPR128:$Rd),
8052259698Sdim                           (v2f64 (Neon_Op (v2f64 VPR128:$Rn))))],
8053259698Sdim                        NoItinerary>;
8054259698Sdim
8055259698Sdim  def 2s : NeonI_2VMisc<0b0, U, 0b10, opcode,
8056259698Sdim                        (outs VPR64:$Rd), (ins VPR64:$Rn),
8057259698Sdim                        asmop # "\t$Rd.2s, $Rn.2s",
8058259698Sdim                        [(set (v2f32 VPR64:$Rd),
8059259698Sdim                           (v2f32 (Neon_Op (v2f32 VPR64:$Rn))))],
8060259698Sdim                        NoItinerary>;
8061259698Sdim}
8062259698Sdim
8063259698Sdimdefm FABS : NeonI_2VMisc_SDsizes<"fabs", 0b0, 0b01111, fabs>;
8064259698Sdimdefm FNEG : NeonI_2VMisc_SDsizes<"fneg", 0b1, 0b01111, fneg>;
8065259698Sdim
8066259698Sdimmulticlass NeonI_2VMisc_HSD_Narrow<string asmop, bit U, bits<5> opcode> {
8067259698Sdim  def 8h8b : NeonI_2VMisc<0b0, U, 0b00, opcode,
8068259698Sdim                          (outs VPR64:$Rd), (ins VPR128:$Rn),
8069259698Sdim                          asmop # "\t$Rd.8b, $Rn.8h",
8070259698Sdim                          [], NoItinerary>;
8071259698Sdim
8072259698Sdim  def 4s4h : NeonI_2VMisc<0b0, U, 0b01, opcode,
8073259698Sdim                          (outs VPR64:$Rd), (ins VPR128:$Rn),
8074259698Sdim                          asmop # "\t$Rd.4h, $Rn.4s",
8075259698Sdim                          [], NoItinerary>;
8076259698Sdim
8077259698Sdim  def 2d2s : NeonI_2VMisc<0b0, U, 0b10, opcode,
8078259698Sdim                          (outs VPR64:$Rd), (ins VPR128:$Rn),
8079259698Sdim                          asmop # "\t$Rd.2s, $Rn.2d",
8080259698Sdim                          [], NoItinerary>;
8081259698Sdim
8082259698Sdim  let Constraints = "$Rd = $src" in {
8083259698Sdim    def 8h16b : NeonI_2VMisc<0b1, U, 0b00, opcode,
8084259698Sdim                             (outs VPR128:$Rd), (ins VPR128:$src, VPR128:$Rn),
8085259698Sdim                             asmop # "2\t$Rd.16b, $Rn.8h",
8086259698Sdim                             [], NoItinerary>;
8087259698Sdim
8088259698Sdim    def 4s8h : NeonI_2VMisc<0b1, U, 0b01, opcode,
8089259698Sdim                            (outs VPR128:$Rd), (ins VPR128:$src, VPR128:$Rn),
8090259698Sdim                            asmop # "2\t$Rd.8h, $Rn.4s",
8091259698Sdim                            [], NoItinerary>;
8092259698Sdim
8093259698Sdim    def 2d4s : NeonI_2VMisc<0b1, U, 0b10, opcode,
8094259698Sdim                            (outs VPR128:$Rd), (ins VPR128:$src, VPR128:$Rn),
8095259698Sdim                            asmop # "2\t$Rd.4s, $Rn.2d",
8096259698Sdim                            [], NoItinerary>;
8097259698Sdim  }
8098259698Sdim}
8099259698Sdim
8100259698Sdimdefm XTN : NeonI_2VMisc_HSD_Narrow<"xtn", 0b0, 0b10010>;
8101259698Sdimdefm SQXTUN : NeonI_2VMisc_HSD_Narrow<"sqxtun", 0b1, 0b10010>;
8102259698Sdimdefm SQXTN : NeonI_2VMisc_HSD_Narrow<"sqxtn", 0b0, 0b10100>;
8103259698Sdimdefm UQXTN : NeonI_2VMisc_HSD_Narrow<"uqxtn", 0b1, 0b10100>;
8104259698Sdim
8105259698Sdimmulticlass NeonI_2VMisc_Narrow_Patterns<string Prefix,
8106259698Sdim                                        SDPatternOperator Neon_Op> {
8107259698Sdim  def : Pat<(v8i8 (Neon_Op (v8i16 VPR128:$Rn))),
8108259698Sdim            (v8i8 (!cast<Instruction>(Prefix # 8h8b) (v8i16 VPR128:$Rn)))>;
8109259698Sdim
8110259698Sdim  def : Pat<(v4i16 (Neon_Op (v4i32 VPR128:$Rn))),
8111259698Sdim            (v4i16 (!cast<Instruction>(Prefix # 4s4h) (v4i32 VPR128:$Rn)))>;
8112259698Sdim
8113259698Sdim  def : Pat<(v2i32 (Neon_Op (v2i64 VPR128:$Rn))),
8114259698Sdim            (v2i32 (!cast<Instruction>(Prefix # 2d2s) (v2i64 VPR128:$Rn)))>;
8115259698Sdim
8116259698Sdim  def : Pat<(v16i8 (concat_vectors
8117259698Sdim              (v8i8 VPR64:$src),
8118259698Sdim              (v8i8 (Neon_Op (v8i16 VPR128:$Rn))))),
8119259698Sdim            (!cast<Instruction>(Prefix # 8h16b)
8120259698Sdim              (SUBREG_TO_REG (i32 0), VPR64:$src, sub_64),
8121259698Sdim              VPR128:$Rn)>;
8122259698Sdim
8123259698Sdim  def : Pat<(v8i16 (concat_vectors
8124259698Sdim              (v4i16 VPR64:$src),
8125259698Sdim              (v4i16 (Neon_Op (v4i32 VPR128:$Rn))))),
8126259698Sdim            (!cast<Instruction>(Prefix # 4s8h)
8127259698Sdim              (SUBREG_TO_REG (i32 0), VPR64:$src, sub_64),
8128259698Sdim              VPR128:$Rn)>;
8129259698Sdim
8130259698Sdim  def : Pat<(v4i32 (concat_vectors
8131259698Sdim              (v2i32 VPR64:$src),
8132259698Sdim              (v2i32 (Neon_Op (v2i64 VPR128:$Rn))))),
8133259698Sdim            (!cast<Instruction>(Prefix # 2d4s)
8134259698Sdim              (SUBREG_TO_REG (i32 0), VPR64:$src, sub_64),
8135259698Sdim              VPR128:$Rn)>;
8136259698Sdim}
8137259698Sdim
8138259698Sdimdefm : NeonI_2VMisc_Narrow_Patterns<"XTN", trunc>;
8139259698Sdimdefm : NeonI_2VMisc_Narrow_Patterns<"SQXTUN", int_arm_neon_vqmovnsu>;
8140259698Sdimdefm : NeonI_2VMisc_Narrow_Patterns<"SQXTN", int_arm_neon_vqmovns>;
8141259698Sdimdefm : NeonI_2VMisc_Narrow_Patterns<"UQXTN", int_arm_neon_vqmovnu>;
8142259698Sdim
8143259698Sdimmulticlass NeonI_2VMisc_SHIFT<string asmop, bit U, bits<5> opcode> {
8144259698Sdim  let DecoderMethod = "DecodeSHLLInstruction" in {
8145259698Sdim    def 8b8h : NeonI_2VMisc<0b0, U, 0b00, opcode,
8146259698Sdim                            (outs VPR128:$Rd),
8147259698Sdim                            (ins VPR64:$Rn, uimm_exact8:$Imm),
8148259698Sdim                            asmop # "\t$Rd.8h, $Rn.8b, $Imm",
8149259698Sdim                            [], NoItinerary>;
8150259698Sdim
8151259698Sdim    def 4h4s : NeonI_2VMisc<0b0, U, 0b01, opcode,
8152259698Sdim                            (outs VPR128:$Rd),
8153259698Sdim                            (ins VPR64:$Rn, uimm_exact16:$Imm),
8154259698Sdim                            asmop # "\t$Rd.4s, $Rn.4h, $Imm",
8155259698Sdim                            [], NoItinerary>;
8156259698Sdim
8157259698Sdim    def 2s2d : NeonI_2VMisc<0b0, U, 0b10, opcode,
8158259698Sdim                            (outs VPR128:$Rd),
8159259698Sdim                            (ins VPR64:$Rn, uimm_exact32:$Imm),
8160259698Sdim                            asmop # "\t$Rd.2d, $Rn.2s, $Imm",
8161259698Sdim                            [], NoItinerary>;
8162259698Sdim
8163259698Sdim    def 16b8h : NeonI_2VMisc<0b1, U, 0b00, opcode,
8164259698Sdim                            (outs VPR128:$Rd),
8165259698Sdim                            (ins VPR128:$Rn, uimm_exact8:$Imm),
8166259698Sdim                            asmop # "2\t$Rd.8h, $Rn.16b, $Imm",
8167259698Sdim                            [], NoItinerary>;
8168259698Sdim
8169259698Sdim    def 8h4s : NeonI_2VMisc<0b1, U, 0b01, opcode,
8170259698Sdim                            (outs VPR128:$Rd),
8171259698Sdim                            (ins VPR128:$Rn, uimm_exact16:$Imm),
8172259698Sdim                            asmop # "2\t$Rd.4s, $Rn.8h, $Imm",
8173259698Sdim                            [], NoItinerary>;
8174259698Sdim
8175259698Sdim    def 4s2d : NeonI_2VMisc<0b1, U, 0b10, opcode,
8176259698Sdim                            (outs VPR128:$Rd),
8177259698Sdim                            (ins VPR128:$Rn, uimm_exact32:$Imm),
8178259698Sdim                            asmop # "2\t$Rd.2d, $Rn.4s, $Imm",
8179259698Sdim                            [], NoItinerary>;
8180259698Sdim  }
8181259698Sdim}
8182259698Sdim
8183259698Sdimdefm SHLL : NeonI_2VMisc_SHIFT<"shll", 0b1, 0b10011>;
8184259698Sdim
8185259698Sdimclass NeonI_SHLL_Patterns<ValueType OpTy, ValueType DesTy,
8186259698Sdim                          SDPatternOperator ExtOp, Operand Neon_Imm,
8187259698Sdim                          string suffix>
8188259698Sdim  : Pat<(DesTy (shl
8189259698Sdim          (DesTy (ExtOp (OpTy VPR64:$Rn))),
8190259698Sdim            (DesTy (Neon_vdup
8191259698Sdim              (i32 Neon_Imm:$Imm))))),
8192259698Sdim        (!cast<Instruction>("SHLL" # suffix) VPR64:$Rn, Neon_Imm:$Imm)>;
8193259698Sdim
8194259698Sdimclass NeonI_SHLL_High_Patterns<ValueType OpTy, ValueType DesTy,
8195259698Sdim                               SDPatternOperator ExtOp, Operand Neon_Imm,
8196259698Sdim                               string suffix, PatFrag GetHigh>
8197259698Sdim  : Pat<(DesTy (shl
8198259698Sdim          (DesTy (ExtOp
8199259698Sdim            (OpTy (GetHigh VPR128:$Rn)))),
8200259698Sdim              (DesTy (Neon_vdup
8201259698Sdim                (i32 Neon_Imm:$Imm))))),
8202259698Sdim        (!cast<Instruction>("SHLL" # suffix) VPR128:$Rn, Neon_Imm:$Imm)>;
8203259698Sdim
8204259698Sdimdef : NeonI_SHLL_Patterns<v8i8, v8i16, zext, uimm_exact8, "8b8h">;
8205259698Sdimdef : NeonI_SHLL_Patterns<v8i8, v8i16, sext, uimm_exact8, "8b8h">;
8206259698Sdimdef : NeonI_SHLL_Patterns<v4i16, v4i32, zext, uimm_exact16, "4h4s">;
8207259698Sdimdef : NeonI_SHLL_Patterns<v4i16, v4i32, sext, uimm_exact16, "4h4s">;
8208259698Sdimdef : NeonI_SHLL_Patterns<v2i32, v2i64, zext, uimm_exact32, "2s2d">;
8209259698Sdimdef : NeonI_SHLL_Patterns<v2i32, v2i64, sext, uimm_exact32, "2s2d">;
8210259698Sdimdef : NeonI_SHLL_High_Patterns<v8i8, v8i16, zext, uimm_exact8, "16b8h",
8211259698Sdim                               Neon_High16B>;
8212259698Sdimdef : NeonI_SHLL_High_Patterns<v8i8, v8i16, sext, uimm_exact8, "16b8h",
8213259698Sdim                               Neon_High16B>;
8214259698Sdimdef : NeonI_SHLL_High_Patterns<v4i16, v4i32, zext, uimm_exact16, "8h4s",
8215259698Sdim                               Neon_High8H>;
8216259698Sdimdef : NeonI_SHLL_High_Patterns<v4i16, v4i32, sext, uimm_exact16, "8h4s",
8217259698Sdim                               Neon_High8H>;
8218259698Sdimdef : NeonI_SHLL_High_Patterns<v2i32, v2i64, zext, uimm_exact32, "4s2d",
8219259698Sdim                               Neon_High4S>;
8220259698Sdimdef : NeonI_SHLL_High_Patterns<v2i32, v2i64, sext, uimm_exact32, "4s2d",
8221259698Sdim                               Neon_High4S>;
8222259698Sdim
8223259698Sdimmulticlass NeonI_2VMisc_SD_Narrow<string asmop, bit U, bits<5> opcode> {
8224259698Sdim  def 4s4h : NeonI_2VMisc<0b0, U, 0b00, opcode,
8225259698Sdim                          (outs VPR64:$Rd), (ins VPR128:$Rn),
8226259698Sdim                          asmop # "\t$Rd.4h, $Rn.4s",
8227259698Sdim                          [], NoItinerary>;
8228259698Sdim
8229259698Sdim  def 2d2s : NeonI_2VMisc<0b0, U, 0b01, opcode,
8230259698Sdim                          (outs VPR64:$Rd), (ins VPR128:$Rn),
8231259698Sdim                          asmop # "\t$Rd.2s, $Rn.2d",
8232259698Sdim                          [], NoItinerary>;
8233259698Sdim
8234259698Sdim  let Constraints = "$src = $Rd" in {
8235259698Sdim    def 4s8h : NeonI_2VMisc<0b1, U, 0b00, opcode,
8236259698Sdim                            (outs VPR128:$Rd), (ins VPR128:$src, VPR128:$Rn),
8237259698Sdim                            asmop # "2\t$Rd.8h, $Rn.4s",
8238259698Sdim                            [], NoItinerary>;
8239259698Sdim
8240259698Sdim    def 2d4s : NeonI_2VMisc<0b1, U, 0b01, opcode,
8241259698Sdim                            (outs VPR128:$Rd), (ins VPR128:$src, VPR128:$Rn),
8242259698Sdim                            asmop # "2\t$Rd.4s, $Rn.2d",
8243259698Sdim                            [], NoItinerary>;
8244259698Sdim  }
8245259698Sdim}
8246259698Sdim
8247259698Sdimdefm FCVTN : NeonI_2VMisc_SD_Narrow<"fcvtn", 0b0, 0b10110>;
8248259698Sdim
8249259698Sdimmulticlass NeonI_2VMisc_Narrow_Pattern<string prefix,
8250259698Sdim                                       SDPatternOperator f32_to_f16_Op,
8251259698Sdim                                       SDPatternOperator f64_to_f32_Op> {
8252259698Sdim
8253259698Sdim  def : Pat<(v4i16 (f32_to_f16_Op (v4f32 VPR128:$Rn))),
8254259698Sdim              (!cast<Instruction>(prefix # "4s4h") (v4f32 VPR128:$Rn))>;
8255259698Sdim
8256259698Sdim  def : Pat<(v8i16 (concat_vectors
8257259698Sdim                (v4i16 VPR64:$src),
8258259698Sdim                (v4i16 (f32_to_f16_Op (v4f32 VPR128:$Rn))))),
8259259698Sdim                  (!cast<Instruction>(prefix # "4s8h")
8260259698Sdim                    (v4f32 (SUBREG_TO_REG (i32 0), VPR64:$src, sub_64)),
8261259698Sdim                    (v4f32 VPR128:$Rn))>;
8262259698Sdim
8263259698Sdim  def : Pat<(v2f32 (f64_to_f32_Op (v2f64 VPR128:$Rn))),
8264259698Sdim            (!cast<Instruction>(prefix # "2d2s") (v2f64 VPR128:$Rn))>;
8265259698Sdim
8266259698Sdim  def : Pat<(v4f32 (concat_vectors
8267259698Sdim              (v2f32 VPR64:$src),
8268259698Sdim              (v2f32 (f64_to_f32_Op (v2f64 VPR128:$Rn))))),
8269259698Sdim                (!cast<Instruction>(prefix # "2d4s")
8270259698Sdim                  (v4f32 (SUBREG_TO_REG (i32 0), VPR64:$src, sub_64)),
8271259698Sdim                  (v2f64 VPR128:$Rn))>;
8272259698Sdim}
8273259698Sdim
8274259698Sdimdefm : NeonI_2VMisc_Narrow_Pattern<"FCVTN", int_arm_neon_vcvtfp2hf, fround>;
8275259698Sdim
8276259698Sdimmulticlass NeonI_2VMisc_D_Narrow<string asmop, string prefix, bit U,
8277259698Sdim                                 bits<5> opcode> {
8278259698Sdim  def 2d2s : NeonI_2VMisc<0b0, U, 0b01, opcode,
8279259698Sdim                          (outs VPR64:$Rd), (ins VPR128:$Rn),
8280259698Sdim                          asmop # "\t$Rd.2s, $Rn.2d",
8281259698Sdim                          [], NoItinerary>;
8282259698Sdim
8283259698Sdim  def 2d4s : NeonI_2VMisc<0b1, U, 0b01, opcode,
8284259698Sdim                          (outs VPR128:$Rd), (ins VPR128:$src, VPR128:$Rn),
8285259698Sdim                          asmop # "2\t$Rd.4s, $Rn.2d",
8286259698Sdim                          [], NoItinerary> {
8287259698Sdim    let Constraints = "$src = $Rd";
8288259698Sdim  }
8289259698Sdim
8290259698Sdim  def : Pat<(v2f32 (int_aarch64_neon_fcvtxn (v2f64 VPR128:$Rn))),
8291259698Sdim            (!cast<Instruction>(prefix # "2d2s") VPR128:$Rn)>;
8292259698Sdim
8293259698Sdim  def : Pat<(v4f32 (concat_vectors
8294259698Sdim              (v2f32 VPR64:$src),
8295259698Sdim              (v2f32 (int_aarch64_neon_fcvtxn (v2f64 VPR128:$Rn))))),
8296259698Sdim            (!cast<Instruction>(prefix # "2d4s")
8297259698Sdim               (v4f32 (SUBREG_TO_REG (i32 0), VPR64:$src, sub_64)),
8298259698Sdim               VPR128:$Rn)>;
8299259698Sdim}
8300259698Sdim
8301259698Sdimdefm FCVTXN : NeonI_2VMisc_D_Narrow<"fcvtxn","FCVTXN", 0b1, 0b10110>;
8302259698Sdim
8303259698Sdimdef Neon_High4Float : PatFrag<(ops node:$in),
8304259698Sdim                              (extract_subvector (v4f32 node:$in), (iPTR 2))>;
8305259698Sdim
8306259698Sdimmulticlass NeonI_2VMisc_HS_Extend<string asmop, bit U, bits<5> opcode> {
8307259698Sdim  def 4h4s : NeonI_2VMisc<0b0, U, 0b00, opcode,
8308259698Sdim                          (outs VPR128:$Rd), (ins VPR64:$Rn),
8309259698Sdim                          asmop # "\t$Rd.4s, $Rn.4h",
8310259698Sdim                          [], NoItinerary>;
8311259698Sdim
8312259698Sdim  def 2s2d : NeonI_2VMisc<0b0, U, 0b01, opcode,
8313259698Sdim                          (outs VPR128:$Rd), (ins VPR64:$Rn),
8314259698Sdim                          asmop # "\t$Rd.2d, $Rn.2s",
8315259698Sdim                          [], NoItinerary>;
8316259698Sdim
8317259698Sdim  def 8h4s : NeonI_2VMisc<0b1, U, 0b00, opcode,
8318259698Sdim                          (outs VPR128:$Rd), (ins VPR128:$Rn),
8319259698Sdim                          asmop # "2\t$Rd.4s, $Rn.8h",
8320259698Sdim                          [], NoItinerary>;
8321259698Sdim
8322259698Sdim  def 4s2d : NeonI_2VMisc<0b1, U, 0b01, opcode,
8323259698Sdim                          (outs VPR128:$Rd), (ins VPR128:$Rn),
8324259698Sdim                          asmop # "2\t$Rd.2d, $Rn.4s",
8325259698Sdim                          [], NoItinerary>;
8326259698Sdim}
8327259698Sdim
8328259698Sdimdefm FCVTL : NeonI_2VMisc_HS_Extend<"fcvtl", 0b0, 0b10111>;
8329259698Sdim
8330259698Sdimmulticlass NeonI_2VMisc_Extend_Pattern<string prefix> {
8331259698Sdim  def : Pat<(v4f32 (int_arm_neon_vcvthf2fp (v4i16 VPR64:$Rn))),
8332259698Sdim            (!cast<Instruction>(prefix # "4h4s") VPR64:$Rn)>;
8333259698Sdim
8334259698Sdim  def : Pat<(v4f32 (int_arm_neon_vcvthf2fp
8335259698Sdim              (v4i16 (Neon_High8H
8336259698Sdim                (v8i16 VPR128:$Rn))))),
8337259698Sdim            (!cast<Instruction>(prefix # "8h4s") VPR128:$Rn)>;
8338259698Sdim
8339259698Sdim  def : Pat<(v2f64 (fextend (v2f32 VPR64:$Rn))),
8340259698Sdim            (!cast<Instruction>(prefix # "2s2d") VPR64:$Rn)>;
8341259698Sdim
8342259698Sdim  def : Pat<(v2f64 (fextend
8343259698Sdim              (v2f32 (Neon_High4Float
8344259698Sdim                (v4f32 VPR128:$Rn))))),
8345259698Sdim            (!cast<Instruction>(prefix # "4s2d") VPR128:$Rn)>;
8346259698Sdim}
8347259698Sdim
8348259698Sdimdefm : NeonI_2VMisc_Extend_Pattern<"FCVTL">;
8349259698Sdim
8350259698Sdimmulticlass NeonI_2VMisc_SD_Conv<string asmop, bit Size, bit U, bits<5> opcode,
8351259698Sdim                                ValueType ResTy4s, ValueType OpTy4s,
8352259698Sdim                                ValueType ResTy2d, ValueType OpTy2d,
8353259698Sdim                                ValueType ResTy2s, ValueType OpTy2s,
8354259698Sdim                                SDPatternOperator Neon_Op> {
8355259698Sdim
8356259698Sdim  def 4s : NeonI_2VMisc<0b1, U, {Size, 0b0}, opcode,
8357259698Sdim                        (outs VPR128:$Rd), (ins VPR128:$Rn),
8358259698Sdim                        asmop # "\t$Rd.4s, $Rn.4s",
8359259698Sdim                        [(set (ResTy4s VPR128:$Rd),
8360259698Sdim                           (ResTy4s (Neon_Op (OpTy4s VPR128:$Rn))))],
8361259698Sdim                        NoItinerary>;
8362259698Sdim
8363259698Sdim  def 2d : NeonI_2VMisc<0b1, U, {Size, 0b1}, opcode,
8364259698Sdim                        (outs VPR128:$Rd), (ins VPR128:$Rn),
8365259698Sdim                        asmop # "\t$Rd.2d, $Rn.2d",
8366259698Sdim                        [(set (ResTy2d VPR128:$Rd),
8367259698Sdim                           (ResTy2d (Neon_Op (OpTy2d VPR128:$Rn))))],
8368259698Sdim                        NoItinerary>;
8369259698Sdim
8370259698Sdim  def 2s : NeonI_2VMisc<0b0, U, {Size, 0b0}, opcode,
8371259698Sdim                        (outs VPR64:$Rd), (ins VPR64:$Rn),
8372259698Sdim                        asmop # "\t$Rd.2s, $Rn.2s",
8373259698Sdim                        [(set (ResTy2s VPR64:$Rd),
8374259698Sdim                           (ResTy2s (Neon_Op (OpTy2s VPR64:$Rn))))],
8375259698Sdim                        NoItinerary>;
8376259698Sdim}
8377259698Sdim
8378259698Sdimmulticlass NeonI_2VMisc_fp_to_int<string asmop, bit Size, bit U,
8379259698Sdim                                  bits<5> opcode, SDPatternOperator Neon_Op> {
8380259698Sdim  defm _ : NeonI_2VMisc_SD_Conv<asmop, Size, U, opcode, v4i32, v4f32, v2i64,
8381259698Sdim                                v2f64, v2i32, v2f32, Neon_Op>;
8382259698Sdim}
8383259698Sdim
8384259698Sdimdefm FCVTNS : NeonI_2VMisc_fp_to_int<"fcvtns", 0b0, 0b0, 0b11010,
8385259698Sdim                                     int_aarch64_neon_fcvtns>;
8386259698Sdimdefm FCVTNU : NeonI_2VMisc_fp_to_int<"fcvtnu", 0b0, 0b1, 0b11010,
8387259698Sdim                                     int_aarch64_neon_fcvtnu>;
8388259698Sdimdefm FCVTPS : NeonI_2VMisc_fp_to_int<"fcvtps", 0b1, 0b0, 0b11010,
8389259698Sdim                                     int_aarch64_neon_fcvtps>;
8390259698Sdimdefm FCVTPU : NeonI_2VMisc_fp_to_int<"fcvtpu", 0b1, 0b1, 0b11010,
8391259698Sdim                                     int_aarch64_neon_fcvtpu>;
8392259698Sdimdefm FCVTMS : NeonI_2VMisc_fp_to_int<"fcvtms", 0b0, 0b0, 0b11011,
8393259698Sdim                                     int_aarch64_neon_fcvtms>;
8394259698Sdimdefm FCVTMU : NeonI_2VMisc_fp_to_int<"fcvtmu", 0b0, 0b1, 0b11011,
8395259698Sdim                                     int_aarch64_neon_fcvtmu>;
8396259698Sdimdefm FCVTZS : NeonI_2VMisc_fp_to_int<"fcvtzs", 0b1, 0b0, 0b11011, fp_to_sint>;
8397259698Sdimdefm FCVTZU : NeonI_2VMisc_fp_to_int<"fcvtzu", 0b1, 0b1, 0b11011, fp_to_uint>;
8398259698Sdimdefm FCVTAS : NeonI_2VMisc_fp_to_int<"fcvtas", 0b0, 0b0, 0b11100,
8399259698Sdim                                     int_aarch64_neon_fcvtas>;
8400259698Sdimdefm FCVTAU : NeonI_2VMisc_fp_to_int<"fcvtau", 0b0, 0b1, 0b11100,
8401259698Sdim                                     int_aarch64_neon_fcvtau>;
8402259698Sdim
8403259698Sdimmulticlass NeonI_2VMisc_int_to_fp<string asmop, bit Size, bit U,
8404259698Sdim                                  bits<5> opcode, SDPatternOperator Neon_Op> {
8405259698Sdim  defm _ : NeonI_2VMisc_SD_Conv<asmop, Size, U, opcode, v4f32, v4i32, v2f64,
8406259698Sdim                                v2i64, v2f32, v2i32, Neon_Op>;
8407259698Sdim}
8408259698Sdim
8409259698Sdimdefm SCVTF : NeonI_2VMisc_int_to_fp<"scvtf", 0b0, 0b0, 0b11101, sint_to_fp>;
8410259698Sdimdefm UCVTF : NeonI_2VMisc_int_to_fp<"ucvtf", 0b0, 0b1, 0b11101, uint_to_fp>;
8411259698Sdim
8412259698Sdimmulticlass NeonI_2VMisc_fp_to_fp<string asmop, bit Size, bit U,
8413259698Sdim                                 bits<5> opcode, SDPatternOperator Neon_Op> {
8414259698Sdim  defm _ : NeonI_2VMisc_SD_Conv<asmop, Size, U, opcode, v4f32, v4f32, v2f64,
8415259698Sdim                                v2f64, v2f32, v2f32, Neon_Op>;
8416259698Sdim}
8417259698Sdim
8418259698Sdimdefm FRINTN : NeonI_2VMisc_fp_to_fp<"frintn", 0b0, 0b0, 0b11000,
8419259698Sdim                                     int_aarch64_neon_frintn>;
8420259698Sdimdefm FRINTA : NeonI_2VMisc_fp_to_fp<"frinta", 0b0, 0b1, 0b11000, frnd>;
8421259698Sdimdefm FRINTP : NeonI_2VMisc_fp_to_fp<"frintp", 0b1, 0b0, 0b11000, fceil>;
8422259698Sdimdefm FRINTM : NeonI_2VMisc_fp_to_fp<"frintm", 0b0, 0b0, 0b11001, ffloor>;
8423259698Sdimdefm FRINTX : NeonI_2VMisc_fp_to_fp<"frintx", 0b0, 0b1, 0b11001, frint>;
8424259698Sdimdefm FRINTZ : NeonI_2VMisc_fp_to_fp<"frintz", 0b1, 0b0, 0b11001, ftrunc>;
8425259698Sdimdefm FRINTI : NeonI_2VMisc_fp_to_fp<"frinti", 0b1, 0b1, 0b11001, fnearbyint>;
8426259698Sdimdefm FRECPE : NeonI_2VMisc_fp_to_fp<"frecpe", 0b1, 0b0, 0b11101,
8427259698Sdim                                    int_arm_neon_vrecpe>;
8428259698Sdimdefm FRSQRTE : NeonI_2VMisc_fp_to_fp<"frsqrte", 0b1, 0b1, 0b11101,
8429259698Sdim                                     int_arm_neon_vrsqrte>;
8430259698Sdimdefm FSQRT : NeonI_2VMisc_fp_to_fp<"fsqrt", 0b1, 0b1, 0b11111, fsqrt>;
8431259698Sdim
8432259698Sdimmulticlass NeonI_2VMisc_S_Conv<string asmop, bit Size, bit U,
8433259698Sdim                               bits<5> opcode, SDPatternOperator Neon_Op> {
8434259698Sdim  def 4s : NeonI_2VMisc<0b1, U, {Size, 0b0}, opcode,
8435259698Sdim                        (outs VPR128:$Rd), (ins VPR128:$Rn),
8436259698Sdim                        asmop # "\t$Rd.4s, $Rn.4s",
8437259698Sdim                        [(set (v4i32 VPR128:$Rd),
8438259698Sdim                           (v4i32 (Neon_Op (v4i32 VPR128:$Rn))))],
8439259698Sdim                        NoItinerary>;
8440259698Sdim
8441259698Sdim  def 2s : NeonI_2VMisc<0b0, U, {Size, 0b0}, opcode,
8442259698Sdim                        (outs VPR64:$Rd), (ins VPR64:$Rn),
8443259698Sdim                        asmop # "\t$Rd.2s, $Rn.2s",
8444259698Sdim                        [(set (v2i32 VPR64:$Rd),
8445259698Sdim                           (v2i32 (Neon_Op (v2i32 VPR64:$Rn))))],
8446259698Sdim                        NoItinerary>;
8447259698Sdim}
8448259698Sdim
8449259698Sdimdefm URECPE : NeonI_2VMisc_S_Conv<"urecpe", 0b1, 0b0, 0b11100,
8450259698Sdim                                  int_arm_neon_vrecpe>;
8451259698Sdimdefm URSQRTE : NeonI_2VMisc_S_Conv<"ursqrte", 0b1, 0b1, 0b11100,
8452259698Sdim                                   int_arm_neon_vrsqrte>;
8453259698Sdim
8454259698Sdim// Crypto Class
8455259698Sdimclass NeonI_Cryptoaes_2v<bits<2> size, bits<5> opcode,
8456259698Sdim                         string asmop, SDPatternOperator opnode>
8457259698Sdim  : NeonI_Crypto_AES<size, opcode,
8458259698Sdim                     (outs VPR128:$Rd), (ins VPR128:$src, VPR128:$Rn),
8459259698Sdim                     asmop # "\t$Rd.16b, $Rn.16b",
8460259698Sdim                     [(set (v16i8 VPR128:$Rd),
8461259698Sdim                        (v16i8 (opnode (v16i8 VPR128:$src),
8462259698Sdim                                       (v16i8 VPR128:$Rn))))],
8463259698Sdim                     NoItinerary>{
8464259698Sdim  let Constraints = "$src = $Rd";
8465259698Sdim  let Predicates = [HasNEON, HasCrypto];
8466259698Sdim}
8467259698Sdim
8468259698Sdimdef AESE : NeonI_Cryptoaes_2v<0b00, 0b00100, "aese", int_arm_neon_aese>;
8469259698Sdimdef AESD : NeonI_Cryptoaes_2v<0b00, 0b00101, "aesd", int_arm_neon_aesd>;
8470259698Sdim
8471259698Sdimclass NeonI_Cryptoaes<bits<2> size, bits<5> opcode,
8472259698Sdim                      string asmop, SDPatternOperator opnode>
8473259698Sdim  : NeonI_Crypto_AES<size, opcode,
8474259698Sdim                     (outs VPR128:$Rd), (ins VPR128:$Rn),
8475259698Sdim                     asmop # "\t$Rd.16b, $Rn.16b",
8476259698Sdim                     [(set (v16i8 VPR128:$Rd),
8477259698Sdim                        (v16i8 (opnode (v16i8 VPR128:$Rn))))],
8478259698Sdim                     NoItinerary>;
8479259698Sdim
8480259698Sdimdef AESMC : NeonI_Cryptoaes<0b00, 0b00110, "aesmc", int_arm_neon_aesmc>;
8481259698Sdimdef AESIMC : NeonI_Cryptoaes<0b00, 0b00111, "aesimc", int_arm_neon_aesimc>;
8482259698Sdim
8483259698Sdimclass NeonI_Cryptosha_vv<bits<2> size, bits<5> opcode,
8484259698Sdim                         string asmop, SDPatternOperator opnode>
8485259698Sdim  : NeonI_Crypto_SHA<size, opcode,
8486259698Sdim                     (outs VPR128:$Rd), (ins VPR128:$src, VPR128:$Rn),
8487259698Sdim                     asmop # "\t$Rd.4s, $Rn.4s",
8488259698Sdim                     [(set (v4i32 VPR128:$Rd),
8489259698Sdim                        (v4i32 (opnode (v4i32 VPR128:$src),
8490259698Sdim                                       (v4i32 VPR128:$Rn))))],
8491259698Sdim                     NoItinerary> {
8492259698Sdim  let Constraints = "$src = $Rd";
8493259698Sdim  let Predicates = [HasNEON, HasCrypto];
8494259698Sdim}
8495259698Sdim
8496259698Sdimdef SHA1SU1 : NeonI_Cryptosha_vv<0b00, 0b00001, "sha1su1",
8497259698Sdim                                 int_arm_neon_sha1su1>;
8498259698Sdimdef SHA256SU0 : NeonI_Cryptosha_vv<0b00, 0b00010, "sha256su0",
8499259698Sdim                                   int_arm_neon_sha256su0>;
8500259698Sdim
8501259698Sdimclass NeonI_Cryptosha_ss<bits<2> size, bits<5> opcode,
8502259698Sdim                         string asmop, SDPatternOperator opnode>
8503259698Sdim  : NeonI_Crypto_SHA<size, opcode,
8504259698Sdim                     (outs FPR32:$Rd), (ins FPR32:$Rn),
8505259698Sdim                     asmop # "\t$Rd, $Rn",
8506259698Sdim                     [(set (v1i32 FPR32:$Rd),
8507259698Sdim                        (v1i32 (opnode (v1i32 FPR32:$Rn))))],
8508259698Sdim                     NoItinerary> {
8509259698Sdim  let Predicates = [HasNEON, HasCrypto];
8510259698Sdim}
8511259698Sdim
8512259698Sdimdef SHA1H : NeonI_Cryptosha_ss<0b00, 0b00000, "sha1h", int_arm_neon_sha1h>;
8513259698Sdim
8514259698Sdimclass NeonI_Cryptosha3_vvv<bits<2> size, bits<3> opcode, string asmop,
8515259698Sdim                           SDPatternOperator opnode>
8516259698Sdim  : NeonI_Crypto_3VSHA<size, opcode,
8517259698Sdim                       (outs VPR128:$Rd),
8518259698Sdim                       (ins VPR128:$src, VPR128:$Rn, VPR128:$Rm),
8519259698Sdim                       asmop # "\t$Rd.4s, $Rn.4s, $Rm.4s",
8520259698Sdim                       [(set (v4i32 VPR128:$Rd),
8521259698Sdim                          (v4i32 (opnode (v4i32 VPR128:$src),
8522259698Sdim                                         (v4i32 VPR128:$Rn),
8523259698Sdim                                         (v4i32 VPR128:$Rm))))],
8524259698Sdim                       NoItinerary> {
8525259698Sdim  let Constraints = "$src = $Rd";
8526259698Sdim  let Predicates = [HasNEON, HasCrypto];
8527259698Sdim}
8528259698Sdim
8529259698Sdimdef SHA1SU0 : NeonI_Cryptosha3_vvv<0b00, 0b011, "sha1su0",
8530259698Sdim                                   int_arm_neon_sha1su0>;
8531259698Sdimdef SHA256SU1 : NeonI_Cryptosha3_vvv<0b00, 0b110, "sha256su1",
8532259698Sdim                                     int_arm_neon_sha256su1>;
8533259698Sdim
8534259698Sdimclass NeonI_Cryptosha3_qqv<bits<2> size, bits<3> opcode, string asmop,
8535259698Sdim                           SDPatternOperator opnode>
8536259698Sdim  : NeonI_Crypto_3VSHA<size, opcode,
8537259698Sdim                       (outs FPR128:$Rd),
8538259698Sdim                       (ins FPR128:$src, FPR128:$Rn, VPR128:$Rm),
8539259698Sdim                       asmop # "\t$Rd, $Rn, $Rm.4s",
8540259698Sdim                       [(set (v4i32 FPR128:$Rd),
8541259698Sdim                          (v4i32 (opnode (v4i32 FPR128:$src),
8542259698Sdim                                         (v4i32 FPR128:$Rn),
8543259698Sdim                                         (v4i32 VPR128:$Rm))))],
8544259698Sdim                       NoItinerary> {
8545259698Sdim  let Constraints = "$src = $Rd";
8546259698Sdim  let Predicates = [HasNEON, HasCrypto];
8547259698Sdim}
8548259698Sdim
8549259698Sdimdef SHA256H : NeonI_Cryptosha3_qqv<0b00, 0b100, "sha256h",
8550259698Sdim                                   int_arm_neon_sha256h>;
8551259698Sdimdef SHA256H2 : NeonI_Cryptosha3_qqv<0b00, 0b101, "sha256h2",
8552259698Sdim                                    int_arm_neon_sha256h2>;
8553259698Sdim
8554259698Sdimclass NeonI_Cryptosha3_qsv<bits<2> size, bits<3> opcode, string asmop,
8555259698Sdim                           SDPatternOperator opnode>
8556259698Sdim  : NeonI_Crypto_3VSHA<size, opcode,
8557259698Sdim                       (outs FPR128:$Rd),
8558259698Sdim                       (ins FPR128:$src, FPR32:$Rn, VPR128:$Rm),
8559259698Sdim                       asmop # "\t$Rd, $Rn, $Rm.4s",
8560259698Sdim                       [(set (v4i32 FPR128:$Rd),
8561259698Sdim                          (v4i32 (opnode (v4i32 FPR128:$src),
8562259698Sdim                                         (v1i32 FPR32:$Rn),
8563259698Sdim                                         (v4i32 VPR128:$Rm))))],
8564259698Sdim                       NoItinerary> {
8565259698Sdim  let Constraints = "$src = $Rd";
8566259698Sdim  let Predicates = [HasNEON, HasCrypto];
8567259698Sdim}
8568259698Sdim
8569259698Sdimdef SHA1C : NeonI_Cryptosha3_qsv<0b00, 0b000, "sha1c", int_aarch64_neon_sha1c>;
8570259698Sdimdef SHA1P : NeonI_Cryptosha3_qsv<0b00, 0b001, "sha1p", int_aarch64_neon_sha1p>;
8571259698Sdimdef SHA1M : NeonI_Cryptosha3_qsv<0b00, 0b010, "sha1m", int_aarch64_neon_sha1m>;
8572259698Sdim
8573259698Sdim//
8574259698Sdim// Patterns for handling half-precision values
8575259698Sdim//
8576259698Sdim
8577259698Sdim// Convert f16 value coming in as i16 value to f32
8578259698Sdimdef : Pat<(f32 (f16_to_f32 (i32 (and (i32 GPR32:$Rn), 65535)))),
8579259698Sdim          (FCVTsh (EXTRACT_SUBREG (FMOVsw GPR32:$Rn), sub_16))>;
8580259698Sdimdef : Pat<(f32 (f16_to_f32 (i32 (assertzext GPR32:$Rn)))),
8581259698Sdim          (FCVTsh (EXTRACT_SUBREG (FMOVsw GPR32:$Rn), sub_16))>;
8582259698Sdim
8583259698Sdimdef : Pat<(f32 (f16_to_f32 (i32 (assertzext (i32 (
8584259698Sdim            f32_to_f16 (f32 FPR32:$Rn))))))),
8585259698Sdim          (f32 FPR32:$Rn)>;
8586259698Sdim
8587259698Sdim// Patterns for vector extract of half-precision FP value in i16 storage type
8588259698Sdimdef : Pat<(f32 (f16_to_f32 ( i32 (and (i32 (vector_extract
8589259698Sdim            (v4i16 VPR64:$Rn), neon_uimm2_bare:$Imm)), 65535)))),
8590259698Sdim          (FCVTsh (f16 (DUPhv_H
8591259698Sdim            (v8i16 (SUBREG_TO_REG (i64 0), VPR64:$Rn, sub_64)),
8592259698Sdim            neon_uimm2_bare:$Imm)))>;
8593259698Sdim
8594259698Sdimdef : Pat<(f32 (f16_to_f32 ( i32 (and (i32 (vector_extract
8595259698Sdim            (v8i16 VPR128:$Rn), neon_uimm3_bare:$Imm)), 65535)))),
8596259698Sdim          (FCVTsh (f16 (DUPhv_H (v8i16 VPR128:$Rn), neon_uimm3_bare:$Imm)))>;
8597259698Sdim
8598259698Sdim// Patterns for vector insert of half-precision FP value 0 in i16 storage type
8599259698Sdimdef : Pat<(v8i16 (vector_insert (v8i16 VPR128:$Rn),
8600259698Sdim            (i32 (assertsext (i32 (fp_to_sint(f32 (f16_to_f32 (i32 0))))))),
8601259698Sdim            (neon_uimm3_bare:$Imm))),
8602259698Sdim          (v8i16 (INSELh (v8i16 VPR128:$Rn),
8603259698Sdim            (v8i16 (SUBREG_TO_REG (i64 0),
8604259698Sdim              (f16 (EXTRACT_SUBREG (f32 (FMOVsw (i32 WZR))), sub_16)),
8605259698Sdim              sub_16)),
8606259698Sdim            neon_uimm3_bare:$Imm, 0))>;
8607259698Sdim
8608259698Sdimdef : Pat<(v4i16 (vector_insert (v4i16 VPR64:$Rn),
8609259698Sdim            (i32 (assertsext (i32 (fp_to_sint(f32 (f16_to_f32 (i32 0))))))),
8610259698Sdim            (neon_uimm2_bare:$Imm))),
8611259698Sdim          (v4i16 (EXTRACT_SUBREG
8612259698Sdim            (v8i16 (INSELh
8613259698Sdim              (v8i16 (SUBREG_TO_REG (i64 0), VPR64:$Rn, sub_64)),
8614259698Sdim              (v8i16 (SUBREG_TO_REG (i64 0),
8615259698Sdim                (f16 (EXTRACT_SUBREG (f32 (FMOVsw (i32 WZR))), sub_16)),
8616259698Sdim                sub_16)),
8617259698Sdim              neon_uimm2_bare:$Imm, 0)),
8618259698Sdim            sub_64))>;
8619259698Sdim
8620259698Sdim// Patterns for vector insert of half-precision FP value in i16 storage type
8621259698Sdimdef : Pat<(v8i16 (vector_insert (v8i16 VPR128:$Rn),
8622259698Sdim            (i32 (assertsext (i32 (fp_to_sint
8623259698Sdim              (f32 (f16_to_f32 (i32 (and (i32 GPR32:$src), 65535)))))))),
8624259698Sdim            (neon_uimm3_bare:$Imm))),
8625259698Sdim          (v8i16 (INSELh (v8i16 VPR128:$Rn),
8626259698Sdim            (v8i16 (SUBREG_TO_REG (i64 0),
8627259698Sdim              (f16 (EXTRACT_SUBREG (f32 (FMOVsw (i32 GPR32:$src))), sub_16)),
8628259698Sdim              sub_16)),
8629259698Sdim            neon_uimm3_bare:$Imm, 0))>;
8630259698Sdim
8631259698Sdimdef : Pat<(v4i16 (vector_insert (v4i16 VPR64:$Rn),
8632259698Sdim            (i32 (assertsext (i32 (fp_to_sint
8633259698Sdim              (f32 (f16_to_f32 (i32 (and (i32 GPR32:$src), 65535)))))))),
8634259698Sdim            (neon_uimm2_bare:$Imm))),
8635259698Sdim          (v4i16 (EXTRACT_SUBREG
8636259698Sdim            (v8i16 (INSELh
8637259698Sdim              (v8i16 (SUBREG_TO_REG (i64 0), VPR64:$Rn, sub_64)),
8638259698Sdim              (v8i16 (SUBREG_TO_REG (i64 0),
8639259698Sdim                (f16 (EXTRACT_SUBREG (f32 (FMOVsw (i32 GPR32:$src))), sub_16)),
8640259698Sdim                sub_16)),
8641259698Sdim              neon_uimm2_bare:$Imm, 0)),
8642259698Sdim            sub_64))>;
8643259698Sdim
8644259698Sdimdef : Pat<(v8i16 (vector_insert (v8i16 VPR128:$Rn),
8645259698Sdim            (i32 (vector_extract (v8i16 VPR128:$src), neon_uimm3_bare:$Imm2)),
8646259698Sdim              (neon_uimm3_bare:$Imm1))),
8647259698Sdim          (v8i16 (INSELh (v8i16 VPR128:$Rn), (v8i16 VPR128:$src),
8648259698Sdim            neon_uimm3_bare:$Imm1, neon_uimm3_bare:$Imm2))>;
8649259698Sdim
8650259698Sdim// Patterns for vector copy of half-precision FP value in i16 storage type
8651259698Sdimdef : Pat<(v8i16 (vector_insert (v8i16 VPR128:$Rn),
8652259698Sdim            (i32 (assertsext (i32 (fp_to_sint(f32 (f16_to_f32 (i32 (and (i32
8653259698Sdim              (vector_extract (v8i16 VPR128:$src), neon_uimm3_bare:$Imm2)),
8654259698Sdim              65535)))))))),
8655259698Sdim            (neon_uimm3_bare:$Imm1))),
8656259698Sdim          (v8i16 (INSELh (v8i16 VPR128:$Rn), (v8i16 VPR128:$src),
8657259698Sdim            neon_uimm3_bare:$Imm1, neon_uimm3_bare:$Imm2))>;
8658259698Sdim
8659259698Sdimdef : Pat<(v4i16 (vector_insert (v4i16 VPR64:$Rn),
8660259698Sdim            (i32 (assertsext (i32 (fp_to_sint(f32 (f16_to_f32 (i32 (and (i32
8661259698Sdim              (vector_extract (v4i16 VPR64:$src), neon_uimm3_bare:$Imm2)),
8662259698Sdim              65535)))))))),
8663259698Sdim            (neon_uimm3_bare:$Imm1))),
8664259698Sdim          (v4i16 (EXTRACT_SUBREG
8665259698Sdim            (v8i16 (INSELh
8666259698Sdim              (v8i16 (SUBREG_TO_REG (i64 0), VPR64:$Rn, sub_64)),
8667259698Sdim              (v8i16 (SUBREG_TO_REG (i64 0), VPR64:$src, sub_64)),
8668259698Sdim              neon_uimm3_bare:$Imm1, neon_uimm3_bare:$Imm2)),
8669259698Sdim            sub_64))>;
8670259698Sdim
8671259698Sdim
8672