1//===-- ARMInstrMVE.td - MVE support for ARM ---------------*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file describes the ARM MVE instruction set.
10//
11//===----------------------------------------------------------------------===//
12
13class ExpandImmAsmOp<string shift> : AsmOperandClass {
14  let Name = !strconcat("ExpandImm", shift);
15  let PredicateMethod = !strconcat("isExpImm<", shift, ">");
16  let RenderMethod = "addImmOperands";
17}
18class InvertedExpandImmAsmOp<string shift, string size> : AsmOperandClass {
19  let Name = !strconcat("InvertedExpandImm", shift, "_", size);
20  let PredicateMethod = !strconcat("isInvertedExpImm<", shift, ",", size, ">");
21  let RenderMethod = "addImmOperands";
22}
23
24class ExpandImm<string shift> : Operand<i32> {
25  let ParserMatchClass = ExpandImmAsmOp<shift>;
26  let EncoderMethod = !strconcat("getExpandedImmOpValue<",shift,",false>");
27  let DecoderMethod = !strconcat("DecodeExpandedImmOperand<",shift,">");
28  let PrintMethod = "printExpandedImmOperand";
29}
30class InvertedExpandImm<string shift, string size> : Operand<i32> {
31  let ParserMatchClass = InvertedExpandImmAsmOp<shift, size>;
32  let EncoderMethod = !strconcat("getExpandedImmOpValue<",shift,",true>");
33  let PrintMethod = "printExpandedImmOperand";
34  // No decoder method needed, because this operand type is only used
35  // by aliases (VAND and VORN)
36}
37
38def expzero00 : ExpandImm<"0">;
39def expzero08 : ExpandImm<"8">;
40def expzero16 : ExpandImm<"16">;
41def expzero24 : ExpandImm<"24">;
42
43def expzero00inv16 : InvertedExpandImm<"0", "16">;
44def expzero08inv16 : InvertedExpandImm<"8", "16">;
45
46def expzero00inv32 : InvertedExpandImm<"0", "32">;
47def expzero08inv32 : InvertedExpandImm<"8", "32">;
48def expzero16inv32 : InvertedExpandImm<"16", "32">;
49def expzero24inv32 : InvertedExpandImm<"24", "32">;
50
51// VPT condition mask
52def vpt_mask : Operand<i32> {
53  let PrintMethod = "printVPTMask";
54  let ParserMatchClass = it_mask_asmoperand;
55  let EncoderMethod = "getVPTMaskOpValue";
56  let DecoderMethod = "DecodeVPTMaskOperand";
57}
58
59// VPT/VCMP restricted predicate for sign invariant types
60def pred_restricted_i_asmoperand : AsmOperandClass {
61  let Name = "CondCodeRestrictedI";
62  let RenderMethod = "addITCondCodeOperands";
63  let PredicateMethod = "isITCondCodeRestrictedI";
64  let ParserMethod = "parseITCondCode";
65  let DiagnosticString = "condition code for sign-independent integer "#
66                         "comparison must be EQ or NE";
67}
68
69// VPT/VCMP restricted predicate for signed types
70def pred_restricted_s_asmoperand : AsmOperandClass {
71  let Name = "CondCodeRestrictedS";
72  let RenderMethod = "addITCondCodeOperands";
73  let PredicateMethod = "isITCondCodeRestrictedS";
74  let ParserMethod = "parseITCondCode";
75  let DiagnosticString = "condition code for signed integer "#
76                         "comparison must be EQ, NE, LT, GT, LE or GE";
77}
78
79// VPT/VCMP restricted predicate for unsigned types
80def pred_restricted_u_asmoperand : AsmOperandClass {
81  let Name = "CondCodeRestrictedU";
82  let RenderMethod = "addITCondCodeOperands";
83  let PredicateMethod = "isITCondCodeRestrictedU";
84  let ParserMethod = "parseITCondCode";
85  let DiagnosticString = "condition code for unsigned integer "#
86                         "comparison must be EQ, NE, HS or HI";
87}
88
89// VPT/VCMP restricted predicate for floating point
90def pred_restricted_fp_asmoperand : AsmOperandClass {
91  let Name = "CondCodeRestrictedFP";
92  let RenderMethod = "addITCondCodeOperands";
93  let PredicateMethod = "isITCondCodeRestrictedFP";
94  let ParserMethod = "parseITCondCode";
95  let DiagnosticString = "condition code for floating-point "#
96                         "comparison must be EQ, NE, LT, GT, LE or GE";
97}
98
99class VCMPPredicateOperand : Operand<i32>;
100
101def pred_basic_i : VCMPPredicateOperand {
102  let PrintMethod = "printMandatoryRestrictedPredicateOperand";
103  let ParserMatchClass = pred_restricted_i_asmoperand;
104  let DecoderMethod = "DecodeRestrictedIPredicateOperand";
105  let EncoderMethod = "getRestrictedCondCodeOpValue";
106}
107
108def pred_basic_u : VCMPPredicateOperand {
109  let PrintMethod = "printMandatoryRestrictedPredicateOperand";
110  let ParserMatchClass = pred_restricted_u_asmoperand;
111  let DecoderMethod = "DecodeRestrictedUPredicateOperand";
112  let EncoderMethod = "getRestrictedCondCodeOpValue";
113}
114
115def pred_basic_s : VCMPPredicateOperand {
116  let PrintMethod = "printMandatoryRestrictedPredicateOperand";
117  let ParserMatchClass = pred_restricted_s_asmoperand;
118  let DecoderMethod = "DecodeRestrictedSPredicateOperand";
119  let EncoderMethod = "getRestrictedCondCodeOpValue";
120}
121
122def pred_basic_fp : VCMPPredicateOperand {
123  let PrintMethod = "printMandatoryRestrictedPredicateOperand";
124  let ParserMatchClass = pred_restricted_fp_asmoperand;
125  let DecoderMethod = "DecodeRestrictedFPPredicateOperand";
126  let EncoderMethod = "getRestrictedCondCodeOpValue";
127}
128
129// Register list operands for interleaving load/stores
130def VecList2QAsmOperand : AsmOperandClass {
131  let Name = "VecListTwoMQ";
132  let ParserMethod = "parseVectorList";
133  let RenderMethod = "addMVEVecListOperands";
134  let DiagnosticString = "operand must be a list of two consecutive "#
135                         "q-registers in range [q0,q7]";
136}
137
138def VecList2Q : RegisterOperand<QQPR, "printMVEVectorListTwoQ"> {
139  let ParserMatchClass = VecList2QAsmOperand;
140  let PrintMethod = "printMVEVectorList<2>";
141}
142
143def VecList4QAsmOperand : AsmOperandClass {
144  let Name = "VecListFourMQ";
145  let ParserMethod = "parseVectorList";
146  let RenderMethod = "addMVEVecListOperands";
147  let DiagnosticString = "operand must be a list of four consecutive "#
148                         "q-registers in range [q0,q7]";
149}
150
151def VecList4Q : RegisterOperand<QQQQPR, "printMVEVectorListFourQ"> {
152  let ParserMatchClass = VecList4QAsmOperand;
153  let PrintMethod = "printMVEVectorList<4>";
154}
155
156// taddrmode_imm7  := reg[r0-r7] +/- (imm7 << shift)
157class TMemImm7ShiftOffsetAsmOperand<int shift> : AsmOperandClass {
158  let Name = "TMemImm7Shift"#shift#"Offset";
159  let PredicateMethod = "isMemImm7ShiftedOffset<"#shift#",ARM::tGPRRegClassID>";
160  let RenderMethod = "addMemImmOffsetOperands";
161}
162
163class taddrmode_imm7<int shift> : MemOperand,
164    ComplexPattern<i32, 2, "SelectTAddrModeImm7<"#shift#">", []>  {
165  let ParserMatchClass = TMemImm7ShiftOffsetAsmOperand<shift>;
166  // They are printed the same way as the T2 imm8 version
167  let PrintMethod = "printT2AddrModeImm8Operand<false>";
168  // This can also be the same as the T2 version.
169  let EncoderMethod = "getT2AddrModeImmOpValue<7,"#shift#">";
170  let DecoderMethod = "DecodeTAddrModeImm7<"#shift#">";
171  let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
172}
173
174// t2addrmode_imm7  := reg +/- (imm7)
175class MemImm7ShiftOffsetAsmOperand<int shift> : AsmOperandClass {
176  let Name = "MemImm7Shift"#shift#"Offset";
177  let PredicateMethod = "isMemImm7ShiftedOffset<" # shift #
178                        ",ARM::GPRnopcRegClassID>";
179  let RenderMethod = "addMemImmOffsetOperands";
180}
181
182def MemImm7Shift0OffsetAsmOperand : MemImm7ShiftOffsetAsmOperand<0>;
183def MemImm7Shift1OffsetAsmOperand : MemImm7ShiftOffsetAsmOperand<1>;
184def MemImm7Shift2OffsetAsmOperand : MemImm7ShiftOffsetAsmOperand<2>;
185class T2AddrMode_Imm7<int shift> : MemOperand,
186      ComplexPattern<i32, 2, "SelectT2AddrModeImm7<"#shift#">", []> {
187  let EncoderMethod = "getT2AddrModeImmOpValue<7,"#shift#">";
188  let DecoderMethod = "DecodeT2AddrModeImm7<"#shift#", 0>";
189  let ParserMatchClass =
190    !cast<AsmOperandClass>("MemImm7Shift"#shift#"OffsetAsmOperand");
191  let MIOperandInfo = (ops GPRnopc:$base, i32imm:$offsimm);
192}
193
194class t2addrmode_imm7<int shift> : T2AddrMode_Imm7<shift> {
195  // They are printed the same way as the imm8 version
196  let PrintMethod = "printT2AddrModeImm8Operand<false>";
197}
198
199class MemImm7ShiftOffsetWBAsmOperand<int shift> : AsmOperandClass {
200  let Name = "MemImm7Shift"#shift#"OffsetWB";
201  let PredicateMethod = "isMemImm7ShiftedOffset<" # shift #
202                        ",ARM::rGPRRegClassID>";
203  let RenderMethod = "addMemImmOffsetOperands";
204}
205
206def MemImm7Shift0OffsetWBAsmOperand : MemImm7ShiftOffsetWBAsmOperand<0>;
207def MemImm7Shift1OffsetWBAsmOperand : MemImm7ShiftOffsetWBAsmOperand<1>;
208def MemImm7Shift2OffsetWBAsmOperand : MemImm7ShiftOffsetWBAsmOperand<2>;
209
210class t2addrmode_imm7_pre<int shift> : T2AddrMode_Imm7<shift> {
211  // They are printed the same way as the imm8 version
212  let PrintMethod = "printT2AddrModeImm8Operand<true>";
213  let ParserMatchClass =
214    !cast<AsmOperandClass>("MemImm7Shift"#shift#"OffsetWBAsmOperand");
215  let DecoderMethod = "DecodeT2AddrModeImm7<"#shift#", 1>";
216  let MIOperandInfo = (ops rGPR:$base, i32imm:$offsim);
217}
218
219class t2am_imm7shiftOffsetAsmOperand<int shift>
220  : AsmOperandClass { let Name = "Imm7Shift"#shift; }
221def t2am_imm7shift0OffsetAsmOperand : t2am_imm7shiftOffsetAsmOperand<0>;
222def t2am_imm7shift1OffsetAsmOperand : t2am_imm7shiftOffsetAsmOperand<1>;
223def t2am_imm7shift2OffsetAsmOperand : t2am_imm7shiftOffsetAsmOperand<2>;
224
225class t2am_imm7_offset<int shift> : MemOperand,
226      ComplexPattern<i32, 1, "SelectT2AddrModeImm7Offset<"#shift#">",
227                     [], [SDNPWantRoot]> {
228  // They are printed the same way as the imm8 version
229  let PrintMethod = "printT2AddrModeImm8OffsetOperand";
230  let ParserMatchClass =
231    !cast<AsmOperandClass>("t2am_imm7shift"#shift#"OffsetAsmOperand");
232  let EncoderMethod = "getT2ScaledImmOpValue<7,"#shift#">";
233  let DecoderMethod = "DecodeT2Imm7<"#shift#">";
234}
235
236// Operands for gather/scatter loads of the form [Rbase, Qoffsets]
237class MemRegRQOffsetAsmOperand<int shift> : AsmOperandClass {
238  let Name = "MemRegRQS"#shift#"Offset";
239  let PredicateMethod = "isMemRegRQOffset<"#shift#">";
240  let RenderMethod = "addMemRegRQOffsetOperands";
241}
242
243def MemRegRQS0OffsetAsmOperand : MemRegRQOffsetAsmOperand<0>;
244def MemRegRQS1OffsetAsmOperand : MemRegRQOffsetAsmOperand<1>;
245def MemRegRQS2OffsetAsmOperand : MemRegRQOffsetAsmOperand<2>;
246def MemRegRQS3OffsetAsmOperand : MemRegRQOffsetAsmOperand<3>;
247
248// mve_addr_rq_shift  := reg + vreg{ << UXTW #shift}
249class mve_addr_rq_shift<int shift> : MemOperand {
250  let EncoderMethod = "getMveAddrModeRQOpValue";
251  let PrintMethod = "printMveAddrModeRQOperand<"#shift#">";
252  let ParserMatchClass =
253    !cast<AsmOperandClass>("MemRegRQS"#shift#"OffsetAsmOperand");
254  let DecoderMethod = "DecodeMveAddrModeRQ";
255  let MIOperandInfo = (ops GPRnopc:$base, MQPR:$offsreg);
256}
257
258class MemRegQOffsetAsmOperand<int shift> : AsmOperandClass {
259  let Name = "MemRegQS"#shift#"Offset";
260  let PredicateMethod = "isMemRegQOffset<"#shift#">";
261  let RenderMethod = "addMemImmOffsetOperands";
262}
263
264def MemRegQS2OffsetAsmOperand : MemRegQOffsetAsmOperand<2>;
265def MemRegQS3OffsetAsmOperand : MemRegQOffsetAsmOperand<3>;
266
267// mve_addr_q_shift  := vreg {+ #imm7s2/4}
268class mve_addr_q_shift<int shift> : MemOperand {
269  let EncoderMethod = "getMveAddrModeQOpValue<"#shift#">";
270  // Can be printed same way as other reg + imm operands
271  let PrintMethod = "printT2AddrModeImm8Operand<false>";
272  let ParserMatchClass =
273    !cast<AsmOperandClass>("MemRegQS"#shift#"OffsetAsmOperand");
274  let DecoderMethod = "DecodeMveAddrModeQ<"#shift#">";
275  let MIOperandInfo = (ops MQPR:$base, i32imm:$imm);
276}
277
278// A family of classes wrapping up information about the vector types
279// used by MVE.
280class MVEVectorVTInfo<ValueType vec, ValueType pred, bits<2> size,
281                      string suffix, bit unsigned> {
282  // The LLVM ValueType representing the vector, so we can use it in
283  // ISel patterns.
284  ValueType Vec = vec;
285
286  // An LLVM ValueType representing a corresponding vector of
287  // predicate bits, for use in ISel patterns that handle an IR
288  // intrinsic describing the predicated form of the instruction.
289  //
290  // Usually, for a vector of N things, this will be vNi1. But for
291  // vectors of 2 values, we make an exception, and use v4i1 instead
292  // of v2i1. Rationale: MVE codegen doesn't support doing all the
293  // auxiliary operations on v2i1 (vector shuffles etc), and also,
294  // there's no MVE compare instruction that will _generate_ v2i1
295  // directly.
296  ValueType Pred = pred;
297
298  // The most common representation of the vector element size in MVE
299  // instruction encodings: a 2-bit value V representing an (8<<V)-bit
300  // vector element.
301  bits<2> Size = size;
302
303  // For vectors explicitly mentioning a signedness of integers: 0 for
304  // signed and 1 for unsigned. For anything else, undefined.
305  bit Unsigned = unsigned;
306
307  // The suffix used on the instruction in assembly language.
308  string Suffix = suffix;
309}
310
311// Integer vector types that don't treat signed and unsigned differently.
312def MVE_v16i8 : MVEVectorVTInfo<v16i8, v16i1, 0b00, "i8",  ?>;
313def MVE_v8i16 : MVEVectorVTInfo<v8i16, v8i1,  0b01, "i16", ?>;
314def MVE_v4i32 : MVEVectorVTInfo<v4i32, v4i1,  0b10, "i32", ?>;
315def MVE_v2i64 : MVEVectorVTInfo<v2i64, v4i1,  0b11, "i64", ?>;
316
317// Explicitly signed and unsigned integer vectors. They map to the
318// same set of LLVM ValueTypes as above, but are represented
319// differently in assembly and instruction encodings.
320def MVE_v16s8 : MVEVectorVTInfo<v16i8, v16i1, 0b00, "s8",  0b0>;
321def MVE_v8s16 : MVEVectorVTInfo<v8i16, v8i1,  0b01, "s16", 0b0>;
322def MVE_v4s32 : MVEVectorVTInfo<v4i32, v4i1,  0b10, "s32", 0b0>;
323def MVE_v2s64 : MVEVectorVTInfo<v2i64, v4i1,  0b11, "s64", 0b0>;
324def MVE_v16u8 : MVEVectorVTInfo<v16i8, v16i1, 0b00, "u8",  0b1>;
325def MVE_v8u16 : MVEVectorVTInfo<v8i16, v8i1,  0b01, "u16", 0b1>;
326def MVE_v4u32 : MVEVectorVTInfo<v4i32, v4i1,  0b10, "u32", 0b1>;
327def MVE_v2u64 : MVEVectorVTInfo<v2i64, v4i1,  0b11, "u64", 0b1>;
328
329// FP vector types.
330def MVE_v8f16 : MVEVectorVTInfo<v8f16, v8i1,  0b01, "f16", ?>;
331def MVE_v4f32 : MVEVectorVTInfo<v4f32, v4i1,  0b10, "f32", ?>;
332def MVE_v2f64 : MVEVectorVTInfo<v2f64, v4i1,  0b11, "f64", ?>;
333
334// --------- Start of base classes for the instructions themselves
335
336class MVE_MI<dag oops, dag iops, InstrItinClass itin, string asm,
337             string ops, string cstr, list<dag> pattern>
338  : Thumb2XI<oops, iops, AddrModeNone, 4, itin, !strconcat(asm, "\t", ops), cstr,
339             pattern>,
340    Requires<[HasMVEInt]> {
341  let D = MVEDomain;
342  let DecoderNamespace = "MVE";
343}
344
345// MVE_p is used for most predicated instructions, to add the cluster
346// of input operands that provides the VPT suffix (none, T or E) and
347// the input predicate register.
348class MVE_p<dag oops, dag iops, InstrItinClass itin, string iname,
349            string suffix, string ops, vpred_ops vpred, string cstr,
350            list<dag> pattern=[]>
351  : MVE_MI<oops, !con(iops, (ins vpred:$vp)), itin,
352           // If the instruction has a suffix, like vadd.f32, then the
353           // VPT predication suffix goes before the dot, so the full
354           // name has to be "vadd${vp}.f32".
355           !strconcat(iname, "${vp}",
356                      !if(!eq(suffix, ""), "", !strconcat(".", suffix))),
357           ops, !strconcat(cstr, vpred.vpred_constraint), pattern> {
358  let Inst{31-29} = 0b111;
359  let Inst{27-26} = 0b11;
360}
361
362class MVE_f<dag oops, dag iops, InstrItinClass itin, string iname,
363            string suffix, string ops, vpred_ops vpred, string cstr,
364            list<dag> pattern=[]>
365  : MVE_p<oops, iops, itin, iname, suffix, ops, vpred, cstr, pattern> {
366  let Predicates = [HasMVEFloat];
367}
368
369class MVE_MI_with_pred<dag oops, dag iops, InstrItinClass itin, string asm,
370                       string ops, string cstr, list<dag> pattern>
371  : Thumb2I<oops, iops, AddrModeNone, 4, itin, asm, !strconcat("\t", ops), cstr,
372             pattern>,
373    Requires<[HasV8_1MMainline, HasMVEInt]> {
374  let D = MVEDomain;
375  let DecoderNamespace = "MVE";
376}
377
378class MVE_VMOV_lane_base<dag oops, dag iops, InstrItinClass itin, string asm,
379                         string suffix, string ops, string cstr,
380                         list<dag> pattern>
381  : Thumb2I<oops, iops, AddrModeNone, 4, itin, asm,
382            !if(!eq(suffix, ""), "", "." # suffix) # "\t" # ops,
383            cstr, pattern>,
384    Requires<[HasV8_1MMainline, HasMVEInt]> {
385  let D = MVEDomain;
386  let DecoderNamespace = "MVE";
387}
388
389class MVE_ScalarShift<string iname, dag oops, dag iops, string asm, string cstr,
390            list<dag> pattern=[]>
391  : MVE_MI_with_pred<oops, iops, NoItinerary, iname, asm, cstr, pattern> {
392  let Inst{31-20} = 0b111010100101;
393  let Inst{8} = 0b1;
394
395}
396
397class MVE_ScalarShiftSingleReg<string iname, dag iops, string asm, string cstr,
398                    list<dag> pattern=[]>
399  : MVE_ScalarShift<iname, (outs rGPR:$RdaDest), iops, asm, cstr, pattern> {
400  bits<4> RdaDest;
401
402  let Inst{19-16} = RdaDest{3-0};
403}
404
405class MVE_ScalarShiftSRegImm<string iname, bits<2> op5_4, list<dag> pattern=[]>
406  : MVE_ScalarShiftSingleReg<iname, (ins rGPR:$RdaSrc, long_shift:$imm),
407                     "$RdaSrc, $imm", "$RdaDest = $RdaSrc", pattern> {
408  bits<5> imm;
409
410  let Inst{15} = 0b0;
411  let Inst{14-12} = imm{4-2};
412  let Inst{11-8} = 0b1111;
413  let Inst{7-6} = imm{1-0};
414  let Inst{5-4} = op5_4{1-0};
415  let Inst{3-0} = 0b1111;
416}
417
418def MVE_SQSHL : MVE_ScalarShiftSRegImm<"sqshl", 0b11>;
419def MVE_SRSHR : MVE_ScalarShiftSRegImm<"srshr", 0b10>;
420def MVE_UQSHL : MVE_ScalarShiftSRegImm<"uqshl", 0b00>;
421def MVE_URSHR : MVE_ScalarShiftSRegImm<"urshr", 0b01>;
422
423class MVE_ScalarShiftSRegReg<string iname, bits<2> op5_4, list<dag> pattern=[]>
424  : MVE_ScalarShiftSingleReg<iname, (ins rGPR:$RdaSrc, rGPR:$Rm),
425                     "$RdaSrc, $Rm", "$RdaDest = $RdaSrc", pattern> {
426  bits<4> Rm;
427
428  let Inst{15-12} = Rm{3-0};
429  let Inst{11-8} = 0b1111;
430  let Inst{7-6} = 0b00;
431  let Inst{5-4} = op5_4{1-0};
432  let Inst{3-0} = 0b1101;
433
434  let Unpredictable{8-6} = 0b111;
435}
436
437def MVE_SQRSHR : MVE_ScalarShiftSRegReg<"sqrshr", 0b10>;
438def MVE_UQRSHL : MVE_ScalarShiftSRegReg<"uqrshl", 0b00>;
439
440class MVE_ScalarShiftDoubleReg<string iname, dag iops, string asm,
441                               string cstr, list<dag> pattern=[]>
442  : MVE_ScalarShift<iname, (outs tGPREven:$RdaLo, tGPROdd:$RdaHi),
443                    iops, asm, cstr, pattern> {
444  bits<4> RdaLo;
445  bits<4> RdaHi;
446
447  let Inst{19-17} = RdaLo{3-1};
448  let Inst{11-9} = RdaHi{3-1};
449}
450
451class MVE_ScalarShiftDRegImm<string iname, bits<2> op5_4, bit op16,
452                             list<dag> pattern=[]>
453  : MVE_ScalarShiftDoubleReg<
454      iname, (ins tGPREven:$RdaLo_src, tGPROdd:$RdaHi_src, long_shift:$imm),
455      "$RdaLo, $RdaHi, $imm", "$RdaLo = $RdaLo_src,$RdaHi = $RdaHi_src",
456      pattern> {
457  bits<5> imm;
458
459  let Inst{16} = op16;
460  let Inst{15} = 0b0;
461  let Inst{14-12} = imm{4-2};
462  let Inst{7-6} = imm{1-0};
463  let Inst{5-4} = op5_4{1-0};
464  let Inst{3-0} = 0b1111;
465}
466
467class MVE_ScalarShiftDRegRegBase<string iname, dag iops, string asm,
468                                 bit op5, bit op16, list<dag> pattern=[]>
469  : MVE_ScalarShiftDoubleReg<
470     iname, iops, asm, "@earlyclobber $RdaHi,@earlyclobber $RdaLo,"
471                       "$RdaLo = $RdaLo_src,$RdaHi = $RdaHi_src",
472     pattern> {
473  bits<4> Rm;
474
475  let Inst{16} = op16;
476  let Inst{15-12} = Rm{3-0};
477  let Inst{6} = 0b0;
478  let Inst{5} = op5;
479  let Inst{4} = 0b0;
480  let Inst{3-0} = 0b1101;
481
482  // Custom decoder method because of the following overlapping encodings:
483  // ASRL and SQRSHR
484  // LSLL and UQRSHL
485  // SQRSHRL and SQRSHR
486  // UQRSHLL and UQRSHL
487  let DecoderMethod = "DecodeMVEOverlappingLongShift";
488}
489
490class MVE_ScalarShiftDRegReg<string iname, bit op5, list<dag> pattern=[]>
491  : MVE_ScalarShiftDRegRegBase<
492     iname, (ins tGPREven:$RdaLo_src, tGPROdd:$RdaHi_src, rGPR:$Rm),
493     "$RdaLo, $RdaHi, $Rm", op5, 0b0, pattern> {
494
495  let Inst{7} = 0b0;
496}
497
498class MVE_ScalarShiftDRegRegWithSat<string iname, bit op5, list<dag> pattern=[]>
499  : MVE_ScalarShiftDRegRegBase<
500     iname, (ins tGPREven:$RdaLo_src, tGPROdd:$RdaHi_src, rGPR:$Rm, saturateop:$sat),
501     "$RdaLo, $RdaHi, $sat, $Rm", op5, 0b1, pattern> {
502  bit sat;
503
504  let Inst{7} = sat;
505}
506
507def MVE_ASRLr   : MVE_ScalarShiftDRegReg<"asrl",    0b1,  [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
508                                        (ARMasrl tGPREven:$RdaLo_src,
509                                        tGPROdd:$RdaHi_src, rGPR:$Rm))]>;
510def MVE_ASRLi   : MVE_ScalarShiftDRegImm<"asrl",    0b10, ?, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
511                                        (ARMasrl tGPREven:$RdaLo_src,
512                                        tGPROdd:$RdaHi_src, (i32 long_shift:$imm)))]>;
513def MVE_LSLLr   : MVE_ScalarShiftDRegReg<"lsll",    0b0,  [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
514                                        (ARMlsll tGPREven:$RdaLo_src,
515                                        tGPROdd:$RdaHi_src, rGPR:$Rm))]>;
516def MVE_LSLLi   : MVE_ScalarShiftDRegImm<"lsll",    0b00, ?, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
517                                        (ARMlsll tGPREven:$RdaLo_src,
518                                        tGPROdd:$RdaHi_src, (i32 long_shift:$imm)))]>;
519def MVE_LSRL    : MVE_ScalarShiftDRegImm<"lsrl",    0b01, ?, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
520                                        (ARMlsrl tGPREven:$RdaLo_src,
521                                        tGPROdd:$RdaHi_src, (i32 long_shift:$imm)))]>;
522
523def MVE_SQRSHRL : MVE_ScalarShiftDRegRegWithSat<"sqrshrl", 0b1>;
524def MVE_SQSHLL  : MVE_ScalarShiftDRegImm<"sqshll",  0b11, 0b1>;
525def MVE_SRSHRL  : MVE_ScalarShiftDRegImm<"srshrl",  0b10, 0b1>;
526
527def MVE_UQRSHLL : MVE_ScalarShiftDRegRegWithSat<"uqrshll", 0b0>;
528def MVE_UQSHLL  : MVE_ScalarShiftDRegImm<"uqshll",  0b00, 0b1>;
529def MVE_URSHRL  : MVE_ScalarShiftDRegImm<"urshrl",  0b01, 0b1>;
530
531// start of mve_rDest instructions
532
533class MVE_rDest<dag oops, dag iops, InstrItinClass itin,
534                string iname, string suffix,
535                string ops, string cstr, list<dag> pattern=[]>
536// Always use vpred_n and not vpred_r: with the output register being
537// a GPR and not a vector register, there can't be any question of
538// what to put in its inactive lanes.
539  : MVE_p<oops, iops, itin, iname, suffix, ops, vpred_n, cstr, pattern> {
540
541  let Inst{25-23} = 0b101;
542  let Inst{11-9} = 0b111;
543  let Inst{4} = 0b0;
544}
545
546class MVE_VABAV<string suffix, bit U, bits<2> size, list<dag> pattern=[]>
547  : MVE_rDest<(outs rGPR:$Rda), (ins rGPR:$Rda_src, MQPR:$Qn, MQPR:$Qm),
548              NoItinerary, "vabav", suffix, "$Rda, $Qn, $Qm", "$Rda = $Rda_src",
549              pattern> {
550  bits<4> Qm;
551  bits<4> Qn;
552  bits<4> Rda;
553
554  let Inst{28} = U;
555  let Inst{22} = 0b0;
556  let Inst{21-20} = size{1-0};
557  let Inst{19-17} = Qn{2-0};
558  let Inst{16} = 0b0;
559  let Inst{15-12} = Rda{3-0};
560  let Inst{8} = 0b1;
561  let Inst{7} = Qn{3};
562  let Inst{6} = 0b0;
563  let Inst{5} = Qm{3};
564  let Inst{3-1} = Qm{2-0};
565  let Inst{0} = 0b1;
566}
567
568def MVE_VABAVs8  : MVE_VABAV<"s8", 0b0, 0b00>;
569def MVE_VABAVs16 : MVE_VABAV<"s16", 0b0, 0b01>;
570def MVE_VABAVs32 : MVE_VABAV<"s32", 0b0, 0b10>;
571def MVE_VABAVu8  : MVE_VABAV<"u8", 0b1, 0b00>;
572def MVE_VABAVu16 : MVE_VABAV<"u16", 0b1, 0b01>;
573def MVE_VABAVu32 : MVE_VABAV<"u32", 0b1, 0b10>;
574
575class MVE_VADDV<string iname, string suffix, dag iops, string cstr,
576              bit A, bit U, bits<2> size, list<dag> pattern=[]>
577  : MVE_rDest<(outs tGPREven:$Rda), iops, NoItinerary,
578              iname, suffix, "$Rda, $Qm", cstr, pattern> {
579  bits<3> Qm;
580  bits<4> Rda;
581
582  let Inst{28} = U;
583  let Inst{22-20} = 0b111;
584  let Inst{19-18} = size{1-0};
585  let Inst{17-16} = 0b01;
586  let Inst{15-13} = Rda{3-1};
587  let Inst{12} = 0b0;
588  let Inst{8-6} = 0b100;
589  let Inst{5} = A;
590  let Inst{3-1} = Qm{2-0};
591  let Inst{0} = 0b0;
592}
593
594multiclass MVE_VADDV_A<string suffix, bit U, bits<2> size,
595                       list<dag> pattern=[]> {
596  def acc    : MVE_VADDV<"vaddva", suffix,
597                         (ins tGPREven:$Rda_src, MQPR:$Qm), "$Rda = $Rda_src",
598                         0b1, U, size, pattern>;
599  def no_acc : MVE_VADDV<"vaddv", suffix,
600                         (ins MQPR:$Qm), "",
601                         0b0, U, size, pattern>;
602}
603
604defm MVE_VADDVs8  : MVE_VADDV_A<"s8",  0b0, 0b00>;
605defm MVE_VADDVs16 : MVE_VADDV_A<"s16", 0b0, 0b01>;
606defm MVE_VADDVs32 : MVE_VADDV_A<"s32", 0b0, 0b10>;
607defm MVE_VADDVu8  : MVE_VADDV_A<"u8",  0b1, 0b00>;
608defm MVE_VADDVu16 : MVE_VADDV_A<"u16", 0b1, 0b01>;
609defm MVE_VADDVu32 : MVE_VADDV_A<"u32", 0b1, 0b10>;
610
611let Predicates = [HasMVEInt] in {
612  def : Pat<(i32 (vecreduce_add (v4i32 MQPR:$src))), (i32 (MVE_VADDVu32no_acc $src))>;
613  def : Pat<(i32 (vecreduce_add (v8i16 MQPR:$src))), (i32 (MVE_VADDVu16no_acc $src))>;
614  def : Pat<(i32 (vecreduce_add (v16i8 MQPR:$src))), (i32 (MVE_VADDVu8no_acc $src))>;
615  def : Pat<(i32 (add (i32 (vecreduce_add (v4i32 MQPR:$src1))), (i32 tGPR:$src2))),
616            (i32 (MVE_VADDVu32acc $src2, $src1))>;
617  def : Pat<(i32 (add (i32 (vecreduce_add (v8i16 MQPR:$src1))), (i32 tGPR:$src2))),
618            (i32 (MVE_VADDVu16acc $src2, $src1))>;
619  def : Pat<(i32 (add (i32 (vecreduce_add (v16i8 MQPR:$src1))), (i32 tGPR:$src2))),
620            (i32 (MVE_VADDVu8acc $src2, $src1))>;
621
622}
623
624class MVE_VADDLV<string iname, string suffix, dag iops, string cstr,
625               bit A, bit U, list<dag> pattern=[]>
626  : MVE_rDest<(outs tGPREven:$RdaLo, tGPROdd:$RdaHi), iops, NoItinerary, iname,
627              suffix, "$RdaLo, $RdaHi, $Qm", cstr, pattern> {
628  bits<3> Qm;
629  bits<4> RdaLo;
630  bits<4> RdaHi;
631
632  let Inst{28} = U;
633  let Inst{22-20} = RdaHi{3-1};
634  let Inst{19-18} = 0b10;
635  let Inst{17-16} = 0b01;
636  let Inst{15-13} = RdaLo{3-1};
637  let Inst{12} = 0b0;
638  let Inst{8-6} = 0b100;
639  let Inst{5} = A;
640  let Inst{3-1} = Qm{2-0};
641  let Inst{0} = 0b0;
642}
643
644multiclass MVE_VADDLV_A<string suffix, bit U, list<dag> pattern=[]> {
645  def acc    : MVE_VADDLV<"vaddlva", suffix,
646                        (ins tGPREven:$RdaLo_src, tGPROdd:$RdaHi_src, MQPR:$Qm),
647                        "$RdaLo = $RdaLo_src,$RdaHi = $RdaHi_src",
648                        0b1, U, pattern>;
649  def no_acc : MVE_VADDLV<"vaddlv", suffix,
650                        (ins MQPR:$Qm), "",
651                        0b0, U, pattern>;
652}
653
654
655defm MVE_VADDLVs32 : MVE_VADDLV_A<"s32", 0b0>;
656defm MVE_VADDLVu32 : MVE_VADDLV_A<"u32", 0b1>;
657
658class MVE_VMINMAXNMV<string iname, string suffix, bit sz,
659                     bit bit_17, bit bit_7, list<dag> pattern=[]>
660  : MVE_rDest<(outs rGPR:$RdaDest), (ins rGPR:$RdaSrc, MQPR:$Qm),
661              NoItinerary, iname, suffix, "$RdaSrc, $Qm",
662              "$RdaDest = $RdaSrc", pattern> {
663  bits<3> Qm;
664  bits<4> RdaDest;
665
666  let Inst{28} = sz;
667  let Inst{22-20} = 0b110;
668  let Inst{19-18} = 0b11;
669  let Inst{17} = bit_17;
670  let Inst{16} = 0b0;
671  let Inst{15-12} = RdaDest{3-0};
672  let Inst{8} = 0b1;
673  let Inst{7} = bit_7;
674  let Inst{6-5} = 0b00;
675  let Inst{3-1} = Qm{2-0};
676  let Inst{0} = 0b0;
677
678  let Predicates = [HasMVEFloat];
679}
680
681multiclass MVE_VMINMAXNMV_fty<string iname, bit bit_7, list<dag> pattern=[]> {
682  def f32 : MVE_VMINMAXNMV<iname, "f32", 0b0, 0b1, bit_7, pattern>;
683  def f16 : MVE_VMINMAXNMV<iname, "f16", 0b1, 0b1, bit_7, pattern>;
684}
685
686defm MVE_VMINNMV : MVE_VMINMAXNMV_fty<"vminnmv", 0b1>;
687defm MVE_VMAXNMV : MVE_VMINMAXNMV_fty<"vmaxnmv", 0b0>;
688
689multiclass MVE_VMINMAXNMAV_fty<string iname, bit bit_7, list<dag> pattern=[]> {
690  def f32 : MVE_VMINMAXNMV<iname, "f32", 0b0, 0b0, bit_7, pattern>;
691  def f16 : MVE_VMINMAXNMV<iname, "f16", 0b1, 0b0, bit_7, pattern>;
692}
693
694defm MVE_VMINNMAV : MVE_VMINMAXNMAV_fty<"vminnmav", 0b1>;
695defm MVE_VMAXNMAV : MVE_VMINMAXNMAV_fty<"vmaxnmav", 0b0>;
696
697class MVE_VMINMAXV<string iname, string suffix, bit U, bits<2> size,
698                 bit bit_17, bit bit_7, list<dag> pattern=[]>
699  : MVE_rDest<(outs rGPR:$RdaDest), (ins rGPR:$RdaSrc, MQPR:$Qm), NoItinerary,
700              iname, suffix, "$RdaSrc, $Qm", "$RdaDest = $RdaSrc", pattern> {
701  bits<3> Qm;
702  bits<4> RdaDest;
703
704  let Inst{28} = U;
705  let Inst{22-20} = 0b110;
706  let Inst{19-18} = size{1-0};
707  let Inst{17} = bit_17;
708  let Inst{16} = 0b0;
709  let Inst{15-12} = RdaDest{3-0};
710  let Inst{8} = 0b1;
711  let Inst{7} = bit_7;
712  let Inst{6-5} = 0b00;
713  let Inst{3-1} = Qm{2-0};
714  let Inst{0} = 0b0;
715}
716
717multiclass MVE_VMINMAXV_p<string iname, bit bit_17, bit bit_7,
718                          MVEVectorVTInfo VTI, Intrinsic intr> {
719  def "": MVE_VMINMAXV<iname, VTI.Suffix, VTI.Unsigned, VTI.Size,
720                       bit_17, bit_7>;
721
722  let Predicates = [HasMVEInt] in
723  def _pat : Pat<(i32 (intr (i32 rGPR:$prev), (VTI.Vec MQPR:$vec))),
724                 (i32 (!cast<Instruction>(NAME)
725                           (i32 rGPR:$prev), (VTI.Vec MQPR:$vec)))>;
726}
727
728multiclass MVE_VMINMAXV_ty<string iname, bit bit_7,
729                           Intrinsic intr_s, Intrinsic intr_u> {
730  defm s8 : MVE_VMINMAXV_p<iname, 1, bit_7, MVE_v16s8, intr_s>;
731  defm s16: MVE_VMINMAXV_p<iname, 1, bit_7, MVE_v8s16, intr_s>;
732  defm s32: MVE_VMINMAXV_p<iname, 1, bit_7, MVE_v4s32, intr_s>;
733  defm u8 : MVE_VMINMAXV_p<iname, 1, bit_7, MVE_v16u8, intr_u>;
734  defm u16: MVE_VMINMAXV_p<iname, 1, bit_7, MVE_v8u16, intr_u>;
735  defm u32: MVE_VMINMAXV_p<iname, 1, bit_7, MVE_v4u32, intr_u>;
736}
737
738defm MVE_VMINV : MVE_VMINMAXV_ty<
739  "vminv", 0b1, int_arm_mve_minv_s, int_arm_mve_minv_u>;
740defm MVE_VMAXV : MVE_VMINMAXV_ty<
741  "vmaxv", 0b0, int_arm_mve_maxv_s, int_arm_mve_maxv_u>;
742
743let Predicates = [HasMVEInt] in {
744  def : Pat<(i32 (vecreduce_smax (v16i8 MQPR:$src))),
745            (i32 (MVE_VMAXVs8 (t2MVNi (i32 127)), $src))>;
746  def : Pat<(i32 (vecreduce_smax (v8i16 MQPR:$src))),
747            (i32 (MVE_VMAXVs16 (t2MOVi32imm (i32 -32768)), $src))>;
748  def : Pat<(i32 (vecreduce_smax (v4i32 MQPR:$src))),
749            (i32 (MVE_VMAXVs32 (t2MOVi (i32 -2147483648)), $src))>;
750  def : Pat<(i32 (vecreduce_umax (v16i8 MQPR:$src))),
751            (i32 (MVE_VMAXVu8 (t2MOVi (i32 0)), $src))>;
752  def : Pat<(i32 (vecreduce_umax (v8i16 MQPR:$src))),
753            (i32 (MVE_VMAXVu16 (t2MOVi (i32 0)), $src))>;
754  def : Pat<(i32 (vecreduce_umax (v4i32 MQPR:$src))),
755            (i32 (MVE_VMAXVu32 (t2MOVi (i32 0)), $src))>;
756
757  def : Pat<(i32 (vecreduce_smin (v16i8 MQPR:$src))),
758            (i32 (MVE_VMINVs8 (t2MOVi (i32 127)), $src))>;
759  def : Pat<(i32 (vecreduce_smin (v8i16 MQPR:$src))),
760            (i32 (MVE_VMINVs16 (t2MOVi16 (i32 32767)), $src))>;
761  def : Pat<(i32 (vecreduce_smin (v4i32 MQPR:$src))),
762            (i32 (MVE_VMINVs32 (t2MVNi (i32 -2147483648)), $src))>;
763  def : Pat<(i32 (vecreduce_umin (v16i8 MQPR:$src))),
764            (i32 (MVE_VMINVu8 (t2MOVi (i32 255)), $src))>;
765  def : Pat<(i32 (vecreduce_umin (v8i16 MQPR:$src))),
766            (i32 (MVE_VMINVu16 (t2MOVi16 (i32 65535)), $src))>;
767  def : Pat<(i32 (vecreduce_umin (v4i32 MQPR:$src))),
768            (i32 (MVE_VMINVu32 (t2MOVi (i32 4294967295)), $src))>;
769
770}
771
772multiclass MVE_VMINMAXAV_ty<string iname, bit bit_7, list<dag> pattern=[]> {
773  def s8  : MVE_VMINMAXV<iname, "s8",  0b0, 0b00, 0b0, bit_7>;
774  def s16 : MVE_VMINMAXV<iname, "s16", 0b0, 0b01, 0b0, bit_7>;
775  def s32 : MVE_VMINMAXV<iname, "s32", 0b0, 0b10, 0b0, bit_7>;
776}
777
778defm MVE_VMINAV : MVE_VMINMAXAV_ty<"vminav", 0b1>;
779defm MVE_VMAXAV : MVE_VMINMAXAV_ty<"vmaxav", 0b0>;
780
781class MVE_VMLAMLSDAV<string iname, string suffix, dag iops, string cstr,
782                   bit sz, bit bit_28, bit A, bit X, bit bit_8, bit bit_0,
783                   list<dag> pattern=[]>
784  : MVE_rDest<(outs tGPREven:$RdaDest), iops, NoItinerary, iname, suffix,
785              "$RdaDest, $Qn, $Qm", cstr, pattern> {
786  bits<4> RdaDest;
787  bits<3> Qm;
788  bits<3> Qn;
789
790  let Inst{28} = bit_28;
791  let Inst{22-20} = 0b111;
792  let Inst{19-17} = Qn{2-0};
793  let Inst{16} = sz;
794  let Inst{15-13} = RdaDest{3-1};
795  let Inst{12} = X;
796  let Inst{8} = bit_8;
797  let Inst{7-6} = 0b00;
798  let Inst{5} = A;
799  let Inst{3-1} = Qm{2-0};
800  let Inst{0} = bit_0;
801}
802
803multiclass MVE_VMLAMLSDAV_A<string iname, string x, string suffix,
804                            bit sz, bit bit_28, bit X, bit bit_8, bit bit_0,
805                            list<dag> pattern=[]> {
806  def ""#x#suffix : MVE_VMLAMLSDAV<iname # x, suffix,
807                                   (ins MQPR:$Qn, MQPR:$Qm), "",
808                                   sz, bit_28, 0b0, X, bit_8, bit_0, pattern>;
809  def "a"#x#suffix : MVE_VMLAMLSDAV<iname # "a" # x, suffix,
810                                    (ins tGPREven:$RdaSrc, MQPR:$Qn, MQPR:$Qm),
811                                    "$RdaDest = $RdaSrc",
812                                    sz, bit_28, 0b1, X, bit_8, bit_0, pattern>;
813}
814
815multiclass MVE_VMLAMLSDAV_AX<string iname, string suffix, bit sz, bit bit_28,
816                             bit bit_8, bit bit_0, list<dag> pattern=[]> {
817  defm "" : MVE_VMLAMLSDAV_A<iname, "", suffix, sz, bit_28,
818                             0b0, bit_8, bit_0, pattern>;
819  defm "" : MVE_VMLAMLSDAV_A<iname, "x", suffix, sz, bit_28,
820                             0b1, bit_8, bit_0, pattern>;
821}
822
823multiclass MVE_VMLADAV_multi<string suffix, bit sz, bit bit_8,
824                             list<dag> pattern=[]> {
825  defm "" : MVE_VMLAMLSDAV_AX<"vmladav", "s"#suffix,
826                              sz, 0b0, bit_8, 0b0, pattern>;
827  defm "" : MVE_VMLAMLSDAV_A<"vmladav", "", "u"#suffix,
828                             sz, 0b1, 0b0, bit_8, 0b0, pattern>;
829}
830
831multiclass MVE_VMLSDAV_multi<string suffix, bit sz, bit bit_28,
832                             list<dag> pattern=[]> {
833  defm "" : MVE_VMLAMLSDAV_AX<"vmlsdav", "s"#suffix,
834                              sz, bit_28, 0b0, 0b1, pattern>;
835}
836
837defm MVE_VMLADAV : MVE_VMLADAV_multi< "8", 0b0, 0b1>;
838defm MVE_VMLADAV : MVE_VMLADAV_multi<"16", 0b0, 0b0>;
839defm MVE_VMLADAV : MVE_VMLADAV_multi<"32", 0b1, 0b0>;
840
841defm MVE_VMLSDAV : MVE_VMLSDAV_multi< "8", 0b0, 0b1>;
842defm MVE_VMLSDAV : MVE_VMLSDAV_multi<"16", 0b0, 0b0>;
843defm MVE_VMLSDAV : MVE_VMLSDAV_multi<"32", 0b1, 0b0>;
844
845// vmlav aliases vmladav
846foreach acc = ["", "a"] in {
847  foreach suffix = ["s8", "s16", "s32", "u8", "u16", "u32"] in {
848    def : MVEInstAlias<"vmlav"#acc#"${vp}."#suffix#"\t$RdaDest, $Qn, $Qm",
849                       (!cast<Instruction>("MVE_VMLADAV"#acc#suffix)
850                        tGPREven:$RdaDest, MQPR:$Qn, MQPR:$Qm, vpred_n:$vp)>;
851  }
852}
853
854// Base class for VMLALDAV and VMLSLDAV, VRMLALDAVH, VRMLSLDAVH
855class MVE_VMLALDAVBase<string iname, string suffix, dag iops, string cstr,
856                       bit sz, bit bit_28, bit A, bit X, bit bit_8, bit bit_0,
857                       list<dag> pattern=[]>
858  : MVE_rDest<(outs tGPREven:$RdaLoDest, tGPROdd:$RdaHiDest), iops, NoItinerary,
859              iname, suffix, "$RdaLoDest, $RdaHiDest, $Qn, $Qm", cstr, pattern> {
860  bits<4> RdaLoDest;
861  bits<4> RdaHiDest;
862  bits<3> Qm;
863  bits<3> Qn;
864
865  let Inst{28} = bit_28;
866  let Inst{22-20} = RdaHiDest{3-1};
867  let Inst{19-17} = Qn{2-0};
868  let Inst{16} = sz;
869  let Inst{15-13} = RdaLoDest{3-1};
870  let Inst{12} = X;
871  let Inst{8} = bit_8;
872  let Inst{7-6} = 0b00;
873  let Inst{5} = A;
874  let Inst{3-1} = Qm{2-0};
875  let Inst{0} = bit_0;
876}
877
878multiclass MVE_VMLALDAVBase_A<string iname, string x, string suffix,
879                               bit sz, bit bit_28, bit X, bit bit_8, bit bit_0,
880                               list<dag> pattern=[]> {
881  def ""#x#suffix : MVE_VMLALDAVBase<
882     iname # x, suffix, (ins MQPR:$Qn, MQPR:$Qm), "",
883     sz, bit_28, 0b0, X, bit_8, bit_0, pattern>;
884  def "a"#x#suffix : MVE_VMLALDAVBase<
885     iname # "a" # x, suffix,
886     (ins tGPREven:$RdaLoSrc, tGPROdd:$RdaHiSrc, MQPR:$Qn, MQPR:$Qm),
887     "$RdaLoDest = $RdaLoSrc,$RdaHiDest = $RdaHiSrc",
888     sz, bit_28, 0b1, X, bit_8, bit_0, pattern>;
889}
890
891
892multiclass MVE_VMLALDAVBase_AX<string iname, string suffix, bit sz, bit bit_28,
893                               bit bit_8, bit bit_0, list<dag> pattern=[]> {
894  defm "" : MVE_VMLALDAVBase_A<iname, "", suffix, sz,
895                               bit_28, 0b0, bit_8, bit_0, pattern>;
896  defm "" : MVE_VMLALDAVBase_A<iname, "x", suffix, sz,
897                               bit_28, 0b1, bit_8, bit_0, pattern>;
898}
899
900multiclass MVE_VRMLALDAVH_multi<string suffix, list<dag> pattern=[]> {
901  defm "" : MVE_VMLALDAVBase_AX<"vrmlaldavh", "s"#suffix,
902                                0b0, 0b0, 0b1, 0b0, pattern>;
903  defm "" : MVE_VMLALDAVBase_A<"vrmlaldavh", "", "u"#suffix,
904                               0b0, 0b1, 0b0, 0b1, 0b0, pattern>;
905}
906
907defm MVE_VRMLALDAVH : MVE_VRMLALDAVH_multi<"32">;
908
909// vrmlalvh aliases for vrmlaldavh
910def : MVEInstAlias<"vrmlalvh${vp}.s32\t$RdaLo, $RdaHi, $Qn, $Qm",
911                  (MVE_VRMLALDAVHs32
912                   tGPREven:$RdaLo, tGPROdd:$RdaHi,
913                   MQPR:$Qn, MQPR:$Qm, vpred_n:$vp)>;
914def : MVEInstAlias<"vrmlalvha${vp}.s32\t$RdaLo, $RdaHi, $Qn, $Qm",
915                  (MVE_VRMLALDAVHas32
916                   tGPREven:$RdaLo, tGPROdd:$RdaHi,
917                   MQPR:$Qn, MQPR:$Qm, vpred_n:$vp)>;
918def : MVEInstAlias<"vrmlalvh${vp}.u32\t$RdaLo, $RdaHi, $Qn, $Qm",
919                  (MVE_VRMLALDAVHu32
920                   tGPREven:$RdaLo, tGPROdd:$RdaHi,
921                   MQPR:$Qn, MQPR:$Qm, vpred_n:$vp)>;
922def : MVEInstAlias<"vrmlalvha${vp}.u32\t$RdaLo, $RdaHi, $Qn, $Qm",
923                  (MVE_VRMLALDAVHau32
924                   tGPREven:$RdaLo, tGPROdd:$RdaHi,
925                   MQPR:$Qn, MQPR:$Qm, vpred_n:$vp)>;
926
927multiclass MVE_VMLALDAV_multi<string suffix, bit sz, list<dag> pattern=[]> {
928  defm "" : MVE_VMLALDAVBase_AX<"vmlaldav", "s"#suffix, sz, 0b0, 0b0, 0b0, pattern>;
929  defm "" : MVE_VMLALDAVBase_A<"vmlaldav", "", "u"#suffix,
930                               sz, 0b1, 0b0, 0b0, 0b0, pattern>;
931}
932
933defm MVE_VMLALDAV : MVE_VMLALDAV_multi<"16", 0b0>;
934defm MVE_VMLALDAV : MVE_VMLALDAV_multi<"32", 0b1>;
935
936// vmlalv aliases vmlaldav
937foreach acc = ["", "a"] in {
938  foreach suffix = ["s16", "s32", "u16", "u32"] in {
939    def : MVEInstAlias<"vmlalv" # acc # "${vp}." # suffix #
940                          "\t$RdaLoDest, $RdaHiDest, $Qn, $Qm",
941                       (!cast<Instruction>("MVE_VMLALDAV"#acc#suffix)
942                       tGPREven:$RdaLoDest, tGPROdd:$RdaHiDest,
943                       MQPR:$Qn, MQPR:$Qm, vpred_n:$vp)>;
944  }
945}
946
947multiclass MVE_VMLSLDAV_multi<string iname, string suffix, bit sz,
948                              bit bit_28, list<dag> pattern=[]> {
949  defm "" : MVE_VMLALDAVBase_AX<iname, suffix, sz, bit_28, 0b0, 0b1, pattern>;
950}
951
952defm MVE_VMLSLDAV   : MVE_VMLSLDAV_multi<"vmlsldav", "s16", 0b0, 0b0>;
953defm MVE_VMLSLDAV   : MVE_VMLSLDAV_multi<"vmlsldav", "s32", 0b1, 0b0>;
954defm MVE_VRMLSLDAVH : MVE_VMLSLDAV_multi<"vrmlsldavh", "s32", 0b0, 0b1>;
955
956// end of mve_rDest instructions
957
958// start of mve_comp instructions
959
960class MVE_comp<InstrItinClass itin, string iname, string suffix,
961               string cstr, list<dag> pattern=[]>
962  : MVE_p<(outs MQPR:$Qd), (ins MQPR:$Qn, MQPR:$Qm), itin, iname, suffix,
963           "$Qd, $Qn, $Qm", vpred_r, cstr, pattern> {
964  bits<4> Qd;
965  bits<4> Qn;
966  bits<4> Qm;
967
968  let Inst{22} = Qd{3};
969  let Inst{19-17} = Qn{2-0};
970  let Inst{16} = 0b0;
971  let Inst{15-13} = Qd{2-0};
972  let Inst{12} = 0b0;
973  let Inst{10-9} = 0b11;
974  let Inst{7} = Qn{3};
975  let Inst{5} = Qm{3};
976  let Inst{3-1} = Qm{2-0};
977  let Inst{0} = 0b0;
978}
979
980class MVE_VMINMAXNM<string iname, string suffix, bit sz, bit bit_21,
981                list<dag> pattern=[]>
982  : MVE_comp<NoItinerary, iname, suffix, "", pattern> {
983
984  let Inst{28} = 0b1;
985  let Inst{25-24} = 0b11;
986  let Inst{23} = 0b0;
987  let Inst{21} = bit_21;
988  let Inst{20} = sz;
989  let Inst{11} = 0b1;
990  let Inst{8} = 0b1;
991  let Inst{6} = 0b1;
992  let Inst{4} = 0b1;
993
994  let Predicates = [HasMVEFloat];
995}
996
997def MVE_VMAXNMf32 : MVE_VMINMAXNM<"vmaxnm", "f32", 0b0, 0b0>;
998def MVE_VMAXNMf16 : MVE_VMINMAXNM<"vmaxnm", "f16", 0b1, 0b0>;
999
1000let Predicates = [HasMVEFloat] in {
1001  def : Pat<(v4f32 (fmaxnum (v4f32 MQPR:$val1), (v4f32 MQPR:$val2))),
1002            (v4f32 (MVE_VMAXNMf32 (v4f32 MQPR:$val1), (v4f32 MQPR:$val2)))>;
1003  def : Pat<(v8f16 (fmaxnum (v8f16 MQPR:$val1), (v8f16 MQPR:$val2))),
1004            (v8f16 (MVE_VMAXNMf16 (v8f16 MQPR:$val1), (v8f16 MQPR:$val2)))>;
1005}
1006
1007def MVE_VMINNMf32 : MVE_VMINMAXNM<"vminnm", "f32", 0b0, 0b1>;
1008def MVE_VMINNMf16 : MVE_VMINMAXNM<"vminnm", "f16", 0b1, 0b1>;
1009
1010let Predicates = [HasMVEFloat] in {
1011  def : Pat<(v4f32 (fminnum (v4f32 MQPR:$val1), (v4f32 MQPR:$val2))),
1012            (v4f32 (MVE_VMINNMf32 (v4f32 MQPR:$val1), (v4f32 MQPR:$val2)))>;
1013  def : Pat<(v8f16 (fminnum (v8f16 MQPR:$val1), (v8f16 MQPR:$val2))),
1014            (v8f16 (MVE_VMINNMf16 (v8f16 MQPR:$val1), (v8f16 MQPR:$val2)))>;
1015}
1016
1017
1018class MVE_VMINMAX<string iname, string suffix, bit U, bits<2> size,
1019              bit bit_4, list<dag> pattern=[]>
1020  : MVE_comp<NoItinerary, iname, suffix, "", pattern> {
1021
1022  let Inst{28} = U;
1023  let Inst{25-24} = 0b11;
1024  let Inst{23} = 0b0;
1025  let Inst{21-20} = size{1-0};
1026  let Inst{11} = 0b0;
1027  let Inst{8} = 0b0;
1028  let Inst{6} = 0b1;
1029  let Inst{4} = bit_4;
1030}
1031
1032multiclass MVE_VMINMAX_all_sizes<string iname, bit bit_4> {
1033  def s8  : MVE_VMINMAX<iname, "s8",  0b0, 0b00, bit_4>;
1034  def s16 : MVE_VMINMAX<iname, "s16", 0b0, 0b01, bit_4>;
1035  def s32 : MVE_VMINMAX<iname, "s32", 0b0, 0b10, bit_4>;
1036  def u8  : MVE_VMINMAX<iname, "u8",  0b1, 0b00, bit_4>;
1037  def u16 : MVE_VMINMAX<iname, "u16", 0b1, 0b01, bit_4>;
1038  def u32 : MVE_VMINMAX<iname, "u32", 0b1, 0b10, bit_4>;
1039}
1040
1041defm MVE_VMAX : MVE_VMINMAX_all_sizes<"vmax", 0b0>;
1042defm MVE_VMIN : MVE_VMINMAX_all_sizes<"vmin", 0b1>;
1043
1044let Predicates = [HasMVEInt] in {
1045  def : Pat<(v16i8 (smin (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))),
1046            (v16i8 (MVE_VMINs8 (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>;
1047  def : Pat<(v8i16 (smin (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))),
1048            (v8i16 (MVE_VMINs16 (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>;
1049  def : Pat<(v4i32 (smin (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))),
1050            (v4i32 (MVE_VMINs32 (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>;
1051
1052  def : Pat<(v16i8 (smax (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))),
1053            (v16i8 (MVE_VMAXs8 (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>;
1054  def : Pat<(v8i16 (smax (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))),
1055            (v8i16 (MVE_VMAXs16 (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>;
1056  def : Pat<(v4i32 (smax (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))),
1057            (v4i32 (MVE_VMAXs32 (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>;
1058
1059  def : Pat<(v16i8 (umin (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))),
1060            (v16i8 (MVE_VMINu8 (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>;
1061  def : Pat<(v8i16 (umin (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))),
1062            (v8i16 (MVE_VMINu16 (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>;
1063  def : Pat<(v4i32 (umin (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))),
1064            (v4i32 (MVE_VMINu32 (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>;
1065
1066  def : Pat<(v16i8 (umax (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))),
1067            (v16i8 (MVE_VMAXu8 (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>;
1068  def : Pat<(v8i16 (umax (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))),
1069            (v8i16 (MVE_VMAXu16 (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>;
1070  def : Pat<(v4i32 (umax (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))),
1071            (v4i32 (MVE_VMAXu32 (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>;
1072}
1073
1074// end of mve_comp instructions
1075
1076// start of mve_bit instructions
1077
1078class MVE_bit_arith<dag oops, dag iops, string iname, string suffix,
1079                    string ops, string cstr, list<dag> pattern=[]>
1080  : MVE_p<oops, iops, NoItinerary, iname, suffix, ops, vpred_r, cstr, pattern> {
1081  bits<4> Qd;
1082  bits<4> Qm;
1083
1084  let Inst{22} = Qd{3};
1085  let Inst{15-13} = Qd{2-0};
1086  let Inst{5} = Qm{3};
1087  let Inst{3-1} = Qm{2-0};
1088}
1089
1090def MVE_VBIC : MVE_bit_arith<(outs MQPR:$Qd), (ins MQPR:$Qn, MQPR:$Qm),
1091                             "vbic", "", "$Qd, $Qn, $Qm", ""> {
1092  bits<4> Qn;
1093
1094  let Inst{28} = 0b0;
1095  let Inst{25-23} = 0b110;
1096  let Inst{21-20} = 0b01;
1097  let Inst{19-17} = Qn{2-0};
1098  let Inst{16} = 0b0;
1099  let Inst{12-8} = 0b00001;
1100  let Inst{7} = Qn{3};
1101  let Inst{6} = 0b1;
1102  let Inst{4} = 0b1;
1103  let Inst{0} = 0b0;
1104  let validForTailPredication = 1;
1105}
1106
1107class MVE_VREV<string iname, string suffix, bits<2> size, bits<2> bit_8_7, string cstr="">
1108  : MVE_bit_arith<(outs MQPR:$Qd), (ins MQPR:$Qm), iname,
1109                  suffix, "$Qd, $Qm", cstr> {
1110
1111  let Inst{28} = 0b1;
1112  let Inst{25-23} = 0b111;
1113  let Inst{21-20} = 0b11;
1114  let Inst{19-18} = size;
1115  let Inst{17-16} = 0b00;
1116  let Inst{12-9} = 0b0000;
1117  let Inst{8-7} = bit_8_7;
1118  let Inst{6} = 0b1;
1119  let Inst{4} = 0b0;
1120  let Inst{0} = 0b0;
1121}
1122
1123def MVE_VREV64_8  : MVE_VREV<"vrev64", "8", 0b00, 0b00, "@earlyclobber $Qd">;
1124def MVE_VREV64_16 : MVE_VREV<"vrev64", "16", 0b01, 0b00, "@earlyclobber $Qd">;
1125def MVE_VREV64_32 : MVE_VREV<"vrev64", "32", 0b10, 0b00, "@earlyclobber $Qd">;
1126
1127def MVE_VREV32_8  : MVE_VREV<"vrev32", "8", 0b00, 0b01>;
1128def MVE_VREV32_16 : MVE_VREV<"vrev32", "16", 0b01, 0b01>;
1129
1130def MVE_VREV16_8  : MVE_VREV<"vrev16", "8", 0b00, 0b10>;
1131
1132let Predicates = [HasMVEInt] in {
1133  def : Pat<(v8i16 (bswap (v8i16 MQPR:$src))),
1134            (v8i16 (MVE_VREV16_8 (v8i16 MQPR:$src)))>;
1135  def : Pat<(v4i32 (bswap (v4i32 MQPR:$src))),
1136            (v4i32 (MVE_VREV32_8 (v4i32 MQPR:$src)))>;
1137}
1138
1139let Predicates = [HasMVEInt] in {
1140  def : Pat<(v4i32 (ARMvrev64 (v4i32 MQPR:$src))),
1141            (v4i32 (MVE_VREV64_32 (v4i32 MQPR:$src)))>;
1142  def : Pat<(v8i16 (ARMvrev64 (v8i16 MQPR:$src))),
1143            (v8i16 (MVE_VREV64_16 (v8i16 MQPR:$src)))>;
1144  def : Pat<(v16i8 (ARMvrev64 (v16i8 MQPR:$src))),
1145            (v16i8 (MVE_VREV64_8  (v16i8 MQPR:$src)))>;
1146
1147  def : Pat<(v8i16 (ARMvrev32 (v8i16 MQPR:$src))),
1148            (v8i16 (MVE_VREV32_16 (v8i16 MQPR:$src)))>;
1149  def : Pat<(v16i8 (ARMvrev32 (v16i8 MQPR:$src))),
1150            (v16i8 (MVE_VREV32_8  (v16i8 MQPR:$src)))>;
1151
1152  def : Pat<(v16i8 (ARMvrev16 (v16i8 MQPR:$src))),
1153            (v16i8 (MVE_VREV16_8  (v16i8 MQPR:$src)))>;
1154
1155  def : Pat<(v4f32 (ARMvrev64 (v4f32 MQPR:$src))),
1156            (v4f32 (MVE_VREV64_32 (v4f32 MQPR:$src)))>;
1157  def : Pat<(v8f16 (ARMvrev64 (v8f16 MQPR:$src))),
1158            (v8f16 (MVE_VREV64_16 (v8f16 MQPR:$src)))>;
1159  def : Pat<(v8f16 (ARMvrev32 (v8f16 MQPR:$src))),
1160            (v8f16 (MVE_VREV32_16 (v8f16 MQPR:$src)))>;
1161}
1162
1163def MVE_VMVN : MVE_bit_arith<(outs MQPR:$Qd), (ins MQPR:$Qm),
1164                             "vmvn", "", "$Qd, $Qm", ""> {
1165  let Inst{28} = 0b1;
1166  let Inst{25-23} = 0b111;
1167  let Inst{21-16} = 0b110000;
1168  let Inst{12-6} = 0b0010111;
1169  let Inst{4} = 0b0;
1170  let Inst{0} = 0b0;
1171  let validForTailPredication = 1;
1172}
1173
1174let Predicates = [HasMVEInt] in {
1175  def : Pat<(v16i8 (vnotq  (v16i8 MQPR:$val1))),
1176            (v16i8 (MVE_VMVN (v16i8 MQPR:$val1)))>;
1177  def : Pat<(v8i16 (vnotq  (v8i16 MQPR:$val1))),
1178            (v8i16 (MVE_VMVN (v8i16 MQPR:$val1)))>;
1179  def : Pat<(v4i32 (vnotq  (v4i32 MQPR:$val1))),
1180            (v4i32 (MVE_VMVN (v4i32 MQPR:$val1)))>;
1181  def : Pat<(v2i64 (vnotq  (v2i64 MQPR:$val1))),
1182            (v2i64 (MVE_VMVN (v2i64 MQPR:$val1)))>;
1183}
1184
1185class MVE_bit_ops<string iname, bits<2> bit_21_20, bit bit_28>
1186  : MVE_bit_arith<(outs MQPR:$Qd), (ins MQPR:$Qn, MQPR:$Qm),
1187                  iname, "", "$Qd, $Qn, $Qm", ""> {
1188  bits<4> Qn;
1189
1190  let Inst{28} = bit_28;
1191  let Inst{25-23} = 0b110;
1192  let Inst{21-20} = bit_21_20;
1193  let Inst{19-17} = Qn{2-0};
1194  let Inst{16} = 0b0;
1195  let Inst{12-8} = 0b00001;
1196  let Inst{7} = Qn{3};
1197  let Inst{6} = 0b1;
1198  let Inst{4} = 0b1;
1199  let Inst{0} = 0b0;
1200  let validForTailPredication = 1;
1201}
1202
1203def MVE_VEOR : MVE_bit_ops<"veor", 0b00, 0b1>;
1204def MVE_VORN : MVE_bit_ops<"vorn", 0b11, 0b0>;
1205def MVE_VORR : MVE_bit_ops<"vorr", 0b10, 0b0>;
1206def MVE_VAND : MVE_bit_ops<"vand", 0b00, 0b0>;
1207
1208// add ignored suffixes as aliases
1209
1210foreach s=["s8", "s16", "s32", "u8", "u16", "u32", "i8", "i16", "i32", "f16", "f32"] in {
1211  def : MVEInstAlias<"vbic${vp}." # s # "\t$QdSrc, $QnSrc, $QmSrc",
1212        (MVE_VBIC MQPR:$QdSrc, MQPR:$QnSrc, MQPR:$QmSrc, vpred_r:$vp)>;
1213  def : MVEInstAlias<"veor${vp}." # s # "\t$QdSrc, $QnSrc, $QmSrc",
1214        (MVE_VEOR MQPR:$QdSrc, MQPR:$QnSrc, MQPR:$QmSrc, vpred_r:$vp)>;
1215  def : MVEInstAlias<"vorn${vp}." # s # "\t$QdSrc, $QnSrc, $QmSrc",
1216        (MVE_VORN MQPR:$QdSrc, MQPR:$QnSrc, MQPR:$QmSrc, vpred_r:$vp)>;
1217  def : MVEInstAlias<"vorr${vp}." # s # "\t$QdSrc, $QnSrc, $QmSrc",
1218        (MVE_VORR MQPR:$QdSrc, MQPR:$QnSrc, MQPR:$QmSrc, vpred_r:$vp)>;
1219  def : MVEInstAlias<"vand${vp}." # s # "\t$QdSrc, $QnSrc, $QmSrc",
1220        (MVE_VAND MQPR:$QdSrc, MQPR:$QnSrc, MQPR:$QmSrc, vpred_r:$vp)>;
1221}
1222
1223let Predicates = [HasMVEInt] in {
1224  def : Pat<(v16i8 (and (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))),
1225            (v16i8 (MVE_VAND (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>;
1226  def : Pat<(v8i16 (and (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))),
1227            (v8i16 (MVE_VAND (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>;
1228  def : Pat<(v4i32 (and (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))),
1229            (v4i32 (MVE_VAND (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>;
1230  def : Pat<(v2i64 (and (v2i64 MQPR:$val1), (v2i64 MQPR:$val2))),
1231            (v2i64 (MVE_VAND (v2i64 MQPR:$val1), (v2i64 MQPR:$val2)))>;
1232
1233  def : Pat<(v16i8 (or (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))),
1234            (v16i8 (MVE_VORR (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>;
1235  def : Pat<(v8i16 (or (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))),
1236            (v8i16 (MVE_VORR (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>;
1237  def : Pat<(v4i32 (or (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))),
1238            (v4i32 (MVE_VORR (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>;
1239  def : Pat<(v2i64 (or (v2i64 MQPR:$val1), (v2i64 MQPR:$val2))),
1240            (v2i64 (MVE_VORR (v2i64 MQPR:$val1), (v2i64 MQPR:$val2)))>;
1241
1242  def : Pat<(v16i8 (xor (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))),
1243            (v16i8 (MVE_VEOR (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>;
1244  def : Pat<(v8i16 (xor (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))),
1245            (v8i16 (MVE_VEOR (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>;
1246  def : Pat<(v4i32 (xor (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))),
1247            (v4i32 (MVE_VEOR (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>;
1248  def : Pat<(v2i64 (xor (v2i64 MQPR:$val1), (v2i64 MQPR:$val2))),
1249            (v2i64 (MVE_VEOR (v2i64 MQPR:$val1), (v2i64 MQPR:$val2)))>;
1250
1251  def : Pat<(v16i8 (and (v16i8 MQPR:$val1), (vnotq MQPR:$val2))),
1252            (v16i8 (MVE_VBIC (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>;
1253  def : Pat<(v8i16 (and (v8i16 MQPR:$val1), (vnotq MQPR:$val2))),
1254            (v8i16 (MVE_VBIC (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>;
1255  def : Pat<(v4i32 (and (v4i32 MQPR:$val1), (vnotq MQPR:$val2))),
1256            (v4i32 (MVE_VBIC (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>;
1257  def : Pat<(v2i64 (and (v2i64 MQPR:$val1), (vnotq MQPR:$val2))),
1258            (v2i64 (MVE_VBIC (v2i64 MQPR:$val1), (v2i64 MQPR:$val2)))>;
1259
1260  def : Pat<(v16i8 (or (v16i8 MQPR:$val1), (vnotq MQPR:$val2))),
1261            (v16i8 (MVE_VORN (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>;
1262  def : Pat<(v8i16 (or (v8i16 MQPR:$val1), (vnotq MQPR:$val2))),
1263            (v8i16 (MVE_VORN (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>;
1264  def : Pat<(v4i32 (or (v4i32 MQPR:$val1), (vnotq MQPR:$val2))),
1265            (v4i32 (MVE_VORN (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>;
1266  def : Pat<(v2i64 (or (v2i64 MQPR:$val1), (vnotq MQPR:$val2))),
1267            (v2i64 (MVE_VORN (v2i64 MQPR:$val1), (v2i64 MQPR:$val2)))>;
1268}
1269
1270class MVE_bit_cmode<string iname, string suffix, bits<4> cmode, dag inOps>
1271  : MVE_p<(outs MQPR:$Qd), inOps, NoItinerary,
1272          iname, suffix, "$Qd, $imm", vpred_n, "$Qd = $Qd_src"> {
1273  bits<8> imm;
1274  bits<4> Qd;
1275
1276  let Inst{28} = imm{7};
1277  let Inst{27-23} = 0b11111;
1278  let Inst{22} = Qd{3};
1279  let Inst{21-19} = 0b000;
1280  let Inst{18-16} = imm{6-4};
1281  let Inst{15-13} = Qd{2-0};
1282  let Inst{12} = 0b0;
1283  let Inst{11-8} = cmode;
1284  let Inst{7-6} = 0b01;
1285  let Inst{4} = 0b1;
1286  let Inst{3-0} = imm{3-0};
1287}
1288
1289class MVE_VORR<string suffix, bits<4> cmode, ExpandImm imm_type>
1290  : MVE_bit_cmode<"vorr", suffix, cmode, (ins MQPR:$Qd_src, imm_type:$imm)> {
1291  let Inst{5} = 0b0;
1292  let validForTailPredication = 1;
1293}
1294
1295def MVE_VORRIZ0v4i32  : MVE_VORR<"i32", 0b0001, expzero00>;
1296def MVE_VORRIZ0v8i16  : MVE_VORR<"i16", 0b1001, expzero00>;
1297def MVE_VORRIZ8v4i32  : MVE_VORR<"i32", 0b0011, expzero08>;
1298def MVE_VORRIZ8v8i16  : MVE_VORR<"i16", 0b1011, expzero08>;
1299def MVE_VORRIZ16v4i32 : MVE_VORR<"i32", 0b0101, expzero16>;
1300def MVE_VORRIZ24v4i32 : MVE_VORR<"i32", 0b0111, expzero24>;
1301
1302def MVE_VORNIZ0v4i32 : MVEAsmPseudo<"vorn${vp}.i32\t$Qd, $imm",
1303    (ins MQPR:$Qd_src, expzero00inv32:$imm, vpred_n:$vp), (outs MQPR:$Qd)>;
1304def MVE_VORNIZ0v8i16 : MVEAsmPseudo<"vorn${vp}.i16\t$Qd, $imm",
1305    (ins MQPR:$Qd_src, expzero00inv16:$imm, vpred_n:$vp), (outs MQPR:$Qd)>;
1306def MVE_VORNIZ8v4i32 : MVEAsmPseudo<"vorn${vp}.i32\t$Qd, $imm",
1307    (ins MQPR:$Qd_src, expzero08inv32:$imm, vpred_n:$vp), (outs MQPR:$Qd)>;
1308def MVE_VORNIZ8v8i16 : MVEAsmPseudo<"vorn${vp}.i16\t$Qd, $imm",
1309    (ins MQPR:$Qd_src, expzero08inv16:$imm, vpred_n:$vp), (outs MQPR:$Qd)>;
1310def MVE_VORNIZ16v4i32 : MVEAsmPseudo<"vorn${vp}.i32\t$Qd, $imm",
1311    (ins MQPR:$Qd_src, expzero16inv32:$imm, vpred_n:$vp), (outs MQPR:$Qd)>;
1312def MVE_VORNIZ24v4i32 : MVEAsmPseudo<"vorn${vp}.i32\t$Qd, $imm",
1313    (ins MQPR:$Qd_src, expzero24inv32:$imm, vpred_n:$vp), (outs MQPR:$Qd)>;
1314
1315def MVE_VMOV : MVEInstAlias<"vmov${vp}\t$Qd, $Qm",
1316    (MVE_VORR MQPR:$Qd, MQPR:$Qm, MQPR:$Qm, vpred_r:$vp)>;
1317
1318class MVE_VBIC<string suffix, bits<4> cmode, ExpandImm imm_type>
1319  : MVE_bit_cmode<"vbic", suffix, cmode, (ins MQPR:$Qd_src, imm_type:$imm)> {
1320  let Inst{5} = 0b1;
1321  let validForTailPredication = 1;
1322}
1323
1324def MVE_VBICIZ0v4i32  : MVE_VBIC<"i32", 0b0001, expzero00>;
1325def MVE_VBICIZ0v8i16  : MVE_VBIC<"i16", 0b1001, expzero00>;
1326def MVE_VBICIZ8v4i32  : MVE_VBIC<"i32", 0b0011, expzero08>;
1327def MVE_VBICIZ8v8i16  : MVE_VBIC<"i16", 0b1011, expzero08>;
1328def MVE_VBICIZ16v4i32 : MVE_VBIC<"i32", 0b0101, expzero16>;
1329def MVE_VBICIZ24v4i32 : MVE_VBIC<"i32", 0b0111, expzero24>;
1330
1331def MVE_VANDIZ0v4i32 : MVEAsmPseudo<"vand${vp}.i32\t$Qda, $imm",
1332    (ins MQPR:$Qda_src, expzero00inv32:$imm, vpred_n:$vp), (outs MQPR:$Qda)>;
1333def MVE_VANDIZ0v8i16 : MVEAsmPseudo<"vand${vp}.i16\t$Qda, $imm",
1334    (ins MQPR:$Qda_src, expzero00inv16:$imm, vpred_n:$vp), (outs MQPR:$Qda)>;
1335def MVE_VANDIZ8v4i32 : MVEAsmPseudo<"vand${vp}.i32\t$Qda, $imm",
1336    (ins MQPR:$Qda_src, expzero08inv32:$imm, vpred_n:$vp), (outs MQPR:$Qda)>;
1337def MVE_VANDIZ8v8i16 : MVEAsmPseudo<"vand${vp}.i16\t$Qda, $imm",
1338    (ins MQPR:$Qda_src, expzero08inv16:$imm, vpred_n:$vp), (outs MQPR:$Qda)>;
1339def MVE_VANDIZ16v4i32 : MVEAsmPseudo<"vand${vp}.i32\t$Qda, $imm",
1340    (ins MQPR:$Qda_src, expzero16inv32:$imm, vpred_n:$vp), (outs MQPR:$Qda)>;
1341def MVE_VANDIZ24v4i32 : MVEAsmPseudo<"vand${vp}.i32\t$Qda, $imm",
1342    (ins MQPR:$Qda_src, expzero24inv32:$imm, vpred_n:$vp), (outs MQPR:$Qda)>;
1343
1344class MVE_VMOV_lane_direction {
1345  bit bit_20;
1346  dag oops;
1347  dag iops;
1348  string ops;
1349  string cstr;
1350}
1351def MVE_VMOV_from_lane : MVE_VMOV_lane_direction {
1352  let bit_20 = 0b1;
1353  let oops = (outs rGPR:$Rt);
1354  let iops = (ins MQPR:$Qd);
1355  let ops = "$Rt, $Qd$Idx";
1356  let cstr = "";
1357}
1358def MVE_VMOV_to_lane : MVE_VMOV_lane_direction {
1359  let bit_20 = 0b0;
1360  let oops = (outs MQPR:$Qd);
1361  let iops = (ins MQPR:$Qd_src, rGPR:$Rt);
1362  let ops = "$Qd$Idx, $Rt";
1363  let cstr = "$Qd = $Qd_src";
1364}
1365
1366class MVE_VMOV_lane<string suffix, bit U, dag indexop,
1367                    MVE_VMOV_lane_direction dir>
1368  : MVE_VMOV_lane_base<dir.oops, !con(dir.iops, indexop), NoItinerary,
1369                       "vmov", suffix, dir.ops, dir.cstr, []> {
1370  bits<4> Qd;
1371  bits<4> Rt;
1372
1373  let Inst{31-24} = 0b11101110;
1374  let Inst{23} = U;
1375  let Inst{20} = dir.bit_20;
1376  let Inst{19-17} = Qd{2-0};
1377  let Inst{15-12} = Rt{3-0};
1378  let Inst{11-8} = 0b1011;
1379  let Inst{7} = Qd{3};
1380  let Inst{4-0} = 0b10000;
1381}
1382
1383class MVE_VMOV_lane_32<MVE_VMOV_lane_direction dir>
1384    : MVE_VMOV_lane<"32", 0b0, (ins MVEVectorIndex<4>:$Idx), dir> {
1385  bits<2> Idx;
1386  let Inst{22} = 0b0;
1387  let Inst{6-5} = 0b00;
1388  let Inst{16} = Idx{1};
1389  let Inst{21} = Idx{0};
1390
1391  let Predicates = [HasFPRegsV8_1M];
1392}
1393
1394class MVE_VMOV_lane_16<string suffix, bit U, MVE_VMOV_lane_direction dir>
1395  : MVE_VMOV_lane<suffix, U, (ins MVEVectorIndex<8>:$Idx), dir> {
1396  bits<3> Idx;
1397  let Inst{22} = 0b0;
1398  let Inst{5} = 0b1;
1399  let Inst{16} = Idx{2};
1400  let Inst{21} = Idx{1};
1401  let Inst{6} = Idx{0};
1402}
1403
1404class MVE_VMOV_lane_8<string suffix, bit U, MVE_VMOV_lane_direction dir>
1405  : MVE_VMOV_lane<suffix, U, (ins MVEVectorIndex<16>:$Idx), dir> {
1406  bits<4> Idx;
1407  let Inst{22} = 0b1;
1408  let Inst{16} = Idx{3};
1409  let Inst{21} = Idx{2};
1410  let Inst{6} = Idx{1};
1411  let Inst{5} = Idx{0};
1412}
1413
1414def MVE_VMOV_from_lane_32  : MVE_VMOV_lane_32<            MVE_VMOV_from_lane>;
1415def MVE_VMOV_to_lane_32    : MVE_VMOV_lane_32<            MVE_VMOV_to_lane>;
1416def MVE_VMOV_from_lane_s16 : MVE_VMOV_lane_16<"s16", 0b0, MVE_VMOV_from_lane>;
1417def MVE_VMOV_from_lane_u16 : MVE_VMOV_lane_16<"u16", 0b1, MVE_VMOV_from_lane>;
1418def MVE_VMOV_to_lane_16    : MVE_VMOV_lane_16< "16", 0b0, MVE_VMOV_to_lane>;
1419def MVE_VMOV_from_lane_s8  : MVE_VMOV_lane_8 < "s8", 0b0, MVE_VMOV_from_lane>;
1420def MVE_VMOV_from_lane_u8  : MVE_VMOV_lane_8 < "u8", 0b1, MVE_VMOV_from_lane>;
1421def MVE_VMOV_to_lane_8     : MVE_VMOV_lane_8 <  "8", 0b0, MVE_VMOV_to_lane>;
1422
1423let Predicates = [HasMVEInt] in {
1424  def : Pat<(extractelt (v2f64 MQPR:$src), imm:$lane),
1425            (f64 (EXTRACT_SUBREG MQPR:$src, (DSubReg_f64_reg imm:$lane)))>;
1426  def : Pat<(insertelt (v2f64 MQPR:$src1), DPR:$src2, imm:$lane),
1427            (INSERT_SUBREG (v2f64 (COPY_TO_REGCLASS MQPR:$src1, MQPR)), DPR:$src2, (DSubReg_f64_reg imm:$lane))>;
1428
1429  def : Pat<(extractelt (v4i32 MQPR:$src), imm:$lane),
1430            (COPY_TO_REGCLASS
1431              (i32 (EXTRACT_SUBREG MQPR:$src, (SSubReg_f32_reg imm:$lane))), rGPR)>;
1432  def : Pat<(insertelt (v4i32 MQPR:$src1), rGPR:$src2, imm:$lane),
1433            (MVE_VMOV_to_lane_32 MQPR:$src1, rGPR:$src2, imm:$lane)>;
1434
1435  def : Pat<(vector_insert (v16i8 MQPR:$src1), rGPR:$src2, imm:$lane),
1436            (MVE_VMOV_to_lane_8  MQPR:$src1, rGPR:$src2, imm:$lane)>;
1437  def : Pat<(vector_insert (v8i16 MQPR:$src1), rGPR:$src2, imm:$lane),
1438            (MVE_VMOV_to_lane_16 MQPR:$src1, rGPR:$src2, imm:$lane)>;
1439
1440  def : Pat<(ARMvgetlanes (v16i8 MQPR:$src), imm:$lane),
1441            (MVE_VMOV_from_lane_s8 MQPR:$src, imm:$lane)>;
1442  def : Pat<(ARMvgetlanes (v8i16 MQPR:$src), imm:$lane),
1443            (MVE_VMOV_from_lane_s16 MQPR:$src, imm:$lane)>;
1444  def : Pat<(ARMvgetlaneu (v16i8 MQPR:$src), imm:$lane),
1445            (MVE_VMOV_from_lane_u8 MQPR:$src, imm:$lane)>;
1446  def : Pat<(ARMvgetlaneu (v8i16 MQPR:$src), imm:$lane),
1447            (MVE_VMOV_from_lane_u16 MQPR:$src, imm:$lane)>;
1448
1449  def : Pat<(v16i8 (scalar_to_vector GPR:$src)),
1450            (MVE_VMOV_to_lane_8  (v16i8 (IMPLICIT_DEF)), rGPR:$src, (i32 0))>;
1451  def : Pat<(v8i16 (scalar_to_vector GPR:$src)),
1452            (MVE_VMOV_to_lane_16 (v8i16 (IMPLICIT_DEF)), rGPR:$src, (i32 0))>;
1453  def : Pat<(v4i32 (scalar_to_vector GPR:$src)),
1454            (MVE_VMOV_to_lane_32 (v4i32 (IMPLICIT_DEF)), rGPR:$src, (i32 0))>;
1455
1456  // Floating point patterns, still enabled under HasMVEInt
1457  def : Pat<(extractelt (v4f32 MQPR:$src), imm:$lane),
1458            (COPY_TO_REGCLASS (f32 (EXTRACT_SUBREG MQPR:$src, (SSubReg_f32_reg imm:$lane))), SPR)>;
1459  def : Pat<(insertelt (v4f32 MQPR:$src1), (f32 SPR:$src2), imm:$lane),
1460            (INSERT_SUBREG (v4f32 (COPY_TO_REGCLASS MQPR:$src1, MQPR)), SPR:$src2, (SSubReg_f32_reg imm:$lane))>;
1461
1462  def : Pat<(insertelt (v8f16 MQPR:$src1), HPR:$src2, imm:$lane),
1463            (MVE_VMOV_to_lane_16 MQPR:$src1, (COPY_TO_REGCLASS HPR:$src2, rGPR), imm:$lane)>;
1464  def : Pat<(extractelt (v8f16 MQPR:$src), imm_even:$lane),
1465            (EXTRACT_SUBREG MQPR:$src, (SSubReg_f16_reg imm_even:$lane))>;
1466  def : Pat<(extractelt (v8f16 MQPR:$src), imm_odd:$lane),
1467            (COPY_TO_REGCLASS
1468              (VMOVH (EXTRACT_SUBREG MQPR:$src, (SSubReg_f16_reg imm_odd:$lane))),
1469              HPR)>;
1470
1471  def : Pat<(v4f32 (scalar_to_vector SPR:$src)),
1472            (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), SPR:$src, ssub_0)>;
1473  def : Pat<(v4f32 (scalar_to_vector GPR:$src)),
1474            (MVE_VMOV_to_lane_32 (v4f32 (IMPLICIT_DEF)), rGPR:$src, (i32 0))>;
1475  def : Pat<(v8f16 (scalar_to_vector HPR:$src)),
1476            (INSERT_SUBREG (v8f16 (IMPLICIT_DEF)), HPR:$src, ssub_0)>;
1477  def : Pat<(v8f16 (scalar_to_vector GPR:$src)),
1478            (MVE_VMOV_to_lane_16 (v8f16 (IMPLICIT_DEF)), rGPR:$src, (i32 0))>;
1479}
1480
1481// end of mve_bit instructions
1482
1483// start of MVE Integer instructions
1484
1485class MVE_int<string iname, string suffix, bits<2> size, list<dag> pattern=[]>
1486  : MVE_p<(outs MQPR:$Qd), (ins MQPR:$Qn, MQPR:$Qm), NoItinerary,
1487          iname, suffix, "$Qd, $Qn, $Qm", vpred_r, "", pattern> {
1488  bits<4> Qd;
1489  bits<4> Qn;
1490  bits<4> Qm;
1491
1492  let Inst{22} = Qd{3};
1493  let Inst{21-20} = size;
1494  let Inst{19-17} = Qn{2-0};
1495  let Inst{15-13} = Qd{2-0};
1496  let Inst{7} = Qn{3};
1497  let Inst{6} = 0b1;
1498  let Inst{5} = Qm{3};
1499  let Inst{3-1} = Qm{2-0};
1500}
1501
1502class MVE_VMULt1<string suffix, bits<2> size, list<dag> pattern=[]>
1503  : MVE_int<"vmul", suffix, size, pattern> {
1504
1505  let Inst{28} = 0b0;
1506  let Inst{25-23} = 0b110;
1507  let Inst{16} = 0b0;
1508  let Inst{12-8} = 0b01001;
1509  let Inst{4} = 0b1;
1510  let Inst{0} = 0b0;
1511}
1512
1513def MVE_VMULt1i8  : MVE_VMULt1<"i8", 0b00>;
1514def MVE_VMULt1i16 : MVE_VMULt1<"i16", 0b01>;
1515def MVE_VMULt1i32 : MVE_VMULt1<"i32", 0b10>;
1516
1517let Predicates = [HasMVEInt] in {
1518  def : Pat<(v16i8 (mul (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))),
1519            (v16i8 (MVE_VMULt1i8 (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>;
1520  def : Pat<(v8i16 (mul (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))),
1521            (v8i16 (MVE_VMULt1i16 (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>;
1522  def : Pat<(v4i32 (mul (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))),
1523            (v4i32 (MVE_VMULt1i32 (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>;
1524}
1525
1526class MVE_VQxDMULH<string iname, string suffix, bits<2> size, bit rounding,
1527                  list<dag> pattern=[]>
1528  : MVE_int<iname, suffix, size, pattern> {
1529
1530  let Inst{28} = rounding;
1531  let Inst{25-23} = 0b110;
1532  let Inst{16} = 0b0;
1533  let Inst{12-8} = 0b01011;
1534  let Inst{4} = 0b0;
1535  let Inst{0} = 0b0;
1536}
1537
1538class MVE_VQDMULH<string suffix, bits<2> size, list<dag> pattern=[]>
1539  : MVE_VQxDMULH<"vqdmulh", suffix, size, 0b0, pattern>;
1540class MVE_VQRDMULH<string suffix, bits<2> size, list<dag> pattern=[]>
1541  : MVE_VQxDMULH<"vqrdmulh", suffix, size, 0b1, pattern>;
1542
1543def MVE_VQDMULHi8   : MVE_VQDMULH<"s8",  0b00>;
1544def MVE_VQDMULHi16  : MVE_VQDMULH<"s16", 0b01>;
1545def MVE_VQDMULHi32  : MVE_VQDMULH<"s32", 0b10>;
1546
1547def MVE_VQRDMULHi8  : MVE_VQRDMULH<"s8",  0b00>;
1548def MVE_VQRDMULHi16 : MVE_VQRDMULH<"s16", 0b01>;
1549def MVE_VQRDMULHi32 : MVE_VQRDMULH<"s32", 0b10>;
1550
1551class MVE_VADDSUB<string iname, string suffix, bits<2> size, bit subtract,
1552                    list<dag> pattern=[]>
1553  : MVE_int<iname, suffix, size, pattern> {
1554
1555  let Inst{28} = subtract;
1556  let Inst{25-23} = 0b110;
1557  let Inst{16} = 0b0;
1558  let Inst{12-8} = 0b01000;
1559  let Inst{4} = 0b0;
1560  let Inst{0} = 0b0;
1561  let validForTailPredication = 1;
1562}
1563
1564multiclass MVE_VADDSUB_m<string iname, MVEVectorVTInfo VTI, bit subtract,
1565                         SDNode unpred_op, Intrinsic pred_int> {
1566  def "" : MVE_VADDSUB<iname, VTI.Suffix, VTI.Size, subtract>;
1567
1568  let Predicates = [HasMVEInt] in {
1569    // Unpredicated add/subtract
1570    def : Pat<(VTI.Vec (unpred_op (VTI.Vec MQPR:$Qm), (VTI.Vec MQPR:$Qn))),
1571              (VTI.Vec (!cast<Instruction>(NAME)
1572                            (VTI.Vec MQPR:$Qm), (VTI.Vec MQPR:$Qn)))>;
1573
1574    // Predicated add/subtract
1575    def : Pat<(VTI.Vec (pred_int (VTI.Vec MQPR:$Qm), (VTI.Vec MQPR:$Qn),
1576                            (VTI.Pred VCCR:$mask), (VTI.Vec MQPR:$inactive))),
1577              (VTI.Vec (!cast<Instruction>(NAME)
1578                            (VTI.Vec MQPR:$Qm), (VTI.Vec MQPR:$Qn),
1579                            (i32 1), (VTI.Pred VCCR:$mask),
1580                            (VTI.Vec MQPR:$inactive)))>;
1581  }
1582}
1583
1584multiclass MVE_VADD<MVEVectorVTInfo VTI>
1585  : MVE_VADDSUB_m<"vadd", VTI, 0b0, add, int_arm_mve_add_predicated>;
1586multiclass MVE_VSUB<MVEVectorVTInfo VTI>
1587  : MVE_VADDSUB_m<"vsub", VTI, 0b1, sub, int_arm_mve_sub_predicated>;
1588
1589defm MVE_VADDi8  : MVE_VADD<MVE_v16i8>;
1590defm MVE_VADDi16 : MVE_VADD<MVE_v8i16>;
1591defm MVE_VADDi32 : MVE_VADD<MVE_v4i32>;
1592
1593defm MVE_VSUBi8  : MVE_VSUB<MVE_v16i8>;
1594defm MVE_VSUBi16 : MVE_VSUB<MVE_v8i16>;
1595defm MVE_VSUBi32 : MVE_VSUB<MVE_v4i32>;
1596
1597class MVE_VQADDSUB<string iname, string suffix, bit U, bit subtract,
1598                   bits<2> size, ValueType vt>
1599  : MVE_int<iname, suffix, size, []> {
1600
1601  let Inst{28} = U;
1602  let Inst{25-23} = 0b110;
1603  let Inst{16} = 0b0;
1604  let Inst{12-10} = 0b000;
1605  let Inst{9} = subtract;
1606  let Inst{8} = 0b0;
1607  let Inst{4} = 0b1;
1608  let Inst{0} = 0b0;
1609  let validForTailPredication = 1;
1610
1611  ValueType VT = vt;
1612}
1613
1614class MVE_VQADD<string suffix, bit U, bits<2> size, ValueType VT>
1615  : MVE_VQADDSUB<"vqadd", suffix, U, 0b0, size, VT>;
1616class MVE_VQSUB<string suffix, bit U, bits<2> size, ValueType VT>
1617  : MVE_VQADDSUB<"vqsub", suffix, U, 0b1, size, VT>;
1618
1619def MVE_VQADDs8  : MVE_VQADD<"s8",  0b0, 0b00, v16i8>;
1620def MVE_VQADDs16 : MVE_VQADD<"s16", 0b0, 0b01, v8i16>;
1621def MVE_VQADDs32 : MVE_VQADD<"s32", 0b0, 0b10, v4i32>;
1622def MVE_VQADDu8  : MVE_VQADD<"u8",  0b1, 0b00, v16i8>;
1623def MVE_VQADDu16 : MVE_VQADD<"u16", 0b1, 0b01, v8i16>;
1624def MVE_VQADDu32 : MVE_VQADD<"u32", 0b1, 0b10, v4i32>;
1625
1626def MVE_VQSUBs8  : MVE_VQSUB<"s8",  0b0, 0b00, v16i8>;
1627def MVE_VQSUBs16 : MVE_VQSUB<"s16", 0b0, 0b01, v8i16>;
1628def MVE_VQSUBs32 : MVE_VQSUB<"s32", 0b0, 0b10, v4i32>;
1629def MVE_VQSUBu8  : MVE_VQSUB<"u8",  0b1, 0b00, v16i8>;
1630def MVE_VQSUBu16 : MVE_VQSUB<"u16", 0b1, 0b01, v8i16>;
1631def MVE_VQSUBu32 : MVE_VQSUB<"u32", 0b1, 0b10, v4i32>;
1632
1633let Predicates = [HasMVEInt] in {
1634  foreach instr = [MVE_VQADDu8, MVE_VQADDu16, MVE_VQADDu32] in
1635    foreach VT = [instr.VT] in
1636      def : Pat<(VT (uaddsat (VT MQPR:$Qm), (VT MQPR:$Qn))),
1637                (VT (instr (VT MQPR:$Qm), (VT MQPR:$Qn)))>;
1638  foreach instr = [MVE_VQADDs8, MVE_VQADDs16, MVE_VQADDs32] in
1639    foreach VT = [instr.VT] in
1640      def : Pat<(VT (saddsat (VT MQPR:$Qm), (VT MQPR:$Qn))),
1641                (VT (instr (VT MQPR:$Qm), (VT MQPR:$Qn)))>;
1642  foreach instr = [MVE_VQSUBu8, MVE_VQSUBu16, MVE_VQSUBu32] in
1643    foreach VT = [instr.VT] in
1644      def : Pat<(VT (usubsat (VT MQPR:$Qm), (VT MQPR:$Qn))),
1645                (VT (instr (VT MQPR:$Qm), (VT MQPR:$Qn)))>;
1646  foreach instr = [MVE_VQSUBs8, MVE_VQSUBs16, MVE_VQSUBs32] in
1647    foreach VT = [instr.VT] in
1648      def : Pat<(VT (ssubsat (VT MQPR:$Qm), (VT MQPR:$Qn))),
1649                (VT (instr (VT MQPR:$Qm), (VT MQPR:$Qn)))>;
1650}
1651
1652
1653class MVE_VABD_int<string suffix, bit U, bits<2> size, list<dag> pattern=[]>
1654  : MVE_int<"vabd", suffix, size, pattern> {
1655
1656  let Inst{28} = U;
1657  let Inst{25-23} = 0b110;
1658  let Inst{16} = 0b0;
1659  let Inst{12-8} = 0b00111;
1660  let Inst{4} = 0b0;
1661  let Inst{0} = 0b0;
1662  let validForTailPredication = 1;
1663}
1664
1665def MVE_VABDs8  : MVE_VABD_int<"s8", 0b0, 0b00>;
1666def MVE_VABDs16 : MVE_VABD_int<"s16", 0b0, 0b01>;
1667def MVE_VABDs32 : MVE_VABD_int<"s32", 0b0, 0b10>;
1668def MVE_VABDu8  : MVE_VABD_int<"u8", 0b1, 0b00>;
1669def MVE_VABDu16 : MVE_VABD_int<"u16", 0b1, 0b01>;
1670def MVE_VABDu32 : MVE_VABD_int<"u32", 0b1, 0b10>;
1671
1672class MVE_VRHADD<string suffix, bit U, bits<2> size, list<dag> pattern=[]>
1673  : MVE_int<"vrhadd", suffix, size, pattern> {
1674
1675  let Inst{28} = U;
1676  let Inst{25-23} = 0b110;
1677  let Inst{16} = 0b0;
1678  let Inst{12-8} = 0b00001;
1679  let Inst{4} = 0b0;
1680  let Inst{0} = 0b0;
1681  let validForTailPredication = 1;
1682}
1683
1684def MVE_VRHADDs8  : MVE_VRHADD<"s8", 0b0, 0b00>;
1685def MVE_VRHADDs16 : MVE_VRHADD<"s16", 0b0, 0b01>;
1686def MVE_VRHADDs32 : MVE_VRHADD<"s32", 0b0, 0b10>;
1687def MVE_VRHADDu8  : MVE_VRHADD<"u8", 0b1, 0b00>;
1688def MVE_VRHADDu16 : MVE_VRHADD<"u16", 0b1, 0b01>;
1689def MVE_VRHADDu32 : MVE_VRHADD<"u32", 0b1, 0b10>;
1690
1691class MVE_VHADDSUB<string iname, string suffix, bit U, bit subtract,
1692                   bits<2> size, list<dag> pattern=[]>
1693  : MVE_int<iname, suffix, size, pattern> {
1694
1695  let Inst{28} = U;
1696  let Inst{25-23} = 0b110;
1697  let Inst{16} = 0b0;
1698  let Inst{12-10} = 0b000;
1699  let Inst{9} = subtract;
1700  let Inst{8} = 0b0;
1701  let Inst{4} = 0b0;
1702  let Inst{0} = 0b0;
1703  let validForTailPredication = 1;
1704}
1705
1706class MVE_VHADD<string suffix, bit U, bits<2> size,
1707              list<dag> pattern=[]>
1708  : MVE_VHADDSUB<"vhadd", suffix, U, 0b0, size, pattern>;
1709class MVE_VHSUB<string suffix, bit U, bits<2> size,
1710              list<dag> pattern=[]>
1711  : MVE_VHADDSUB<"vhsub", suffix, U, 0b1, size, pattern>;
1712
1713def MVE_VHADDs8  : MVE_VHADD<"s8",  0b0, 0b00>;
1714def MVE_VHADDs16 : MVE_VHADD<"s16", 0b0, 0b01>;
1715def MVE_VHADDs32 : MVE_VHADD<"s32", 0b0, 0b10>;
1716def MVE_VHADDu8  : MVE_VHADD<"u8",  0b1, 0b00>;
1717def MVE_VHADDu16 : MVE_VHADD<"u16", 0b1, 0b01>;
1718def MVE_VHADDu32 : MVE_VHADD<"u32", 0b1, 0b10>;
1719
1720def MVE_VHSUBs8  : MVE_VHSUB<"s8",  0b0, 0b00>;
1721def MVE_VHSUBs16 : MVE_VHSUB<"s16", 0b0, 0b01>;
1722def MVE_VHSUBs32 : MVE_VHSUB<"s32", 0b0, 0b10>;
1723def MVE_VHSUBu8  : MVE_VHSUB<"u8",  0b1, 0b00>;
1724def MVE_VHSUBu16 : MVE_VHSUB<"u16", 0b1, 0b01>;
1725def MVE_VHSUBu32 : MVE_VHSUB<"u32", 0b1, 0b10>;
1726
1727let Predicates = [HasMVEInt] in {
1728  def : Pat<(v16i8 (ARMvshrsImm
1729                     (v16i8 (add (v16i8 MQPR:$v1), (v16i8 MQPR:$v2))), 1)),
1730            (v16i8 (MVE_VHADDs8
1731                     (v16i8 MQPR:$v1), (v16i8 MQPR:$v2)))>;
1732  def : Pat<(v8i16 (ARMvshrsImm
1733                     (v8i16 (add (v8i16 MQPR:$v1), (v8i16 MQPR:$v2))), 1)),
1734            (v8i16 (MVE_VHADDs16
1735                     (v8i16 MQPR:$v1), (v8i16 MQPR:$v2)))>;
1736  def : Pat<(v4i32 (ARMvshrsImm
1737                     (v4i32 (add (v4i32 MQPR:$v1), (v4i32 MQPR:$v2))), 1)),
1738            (v4i32 (MVE_VHADDs32
1739                     (v4i32 MQPR:$v1), (v4i32 MQPR:$v2)))>;
1740
1741  def : Pat<(v16i8 (ARMvshruImm
1742                     (v16i8 (add (v16i8 MQPR:$v1), (v16i8 MQPR:$v2))), 1)),
1743            (v16i8 (MVE_VHADDu8
1744                     (v16i8 MQPR:$v1), (v16i8 MQPR:$v2)))>;
1745  def : Pat<(v8i16 (ARMvshruImm
1746                     (v8i16 (add (v8i16 MQPR:$v1), (v8i16 MQPR:$v2))), 1)),
1747            (v8i16 (MVE_VHADDu16
1748                     (v8i16 MQPR:$v1), (v8i16 MQPR:$v2)))>;
1749  def : Pat<(v4i32 (ARMvshruImm
1750                     (v4i32 (add (v4i32 MQPR:$v1), (v4i32 MQPR:$v2))), 1)),
1751            (v4i32 (MVE_VHADDu32
1752                     (v4i32 MQPR:$v1), (v4i32 MQPR:$v2)))>;
1753
1754  def : Pat<(v16i8 (ARMvshrsImm
1755                     (v16i8 (sub (v16i8 MQPR:$v1), (v16i8 MQPR:$v2))), 1)),
1756            (v16i8 (MVE_VHSUBs8
1757                     (v16i8 MQPR:$v1), (v16i8 MQPR:$v2)))>;
1758  def : Pat<(v8i16 (ARMvshrsImm
1759                     (v8i16 (sub (v8i16 MQPR:$v1), (v8i16 MQPR:$v2))), 1)),
1760            (v8i16 (MVE_VHSUBs16
1761                     (v8i16 MQPR:$v1), (v8i16 MQPR:$v2)))>;
1762  def : Pat<(v4i32 (ARMvshrsImm
1763                     (v4i32 (sub (v4i32 MQPR:$v1), (v4i32 MQPR:$v2))), 1)),
1764            (v4i32 (MVE_VHSUBs32
1765                     (v4i32 MQPR:$v1), (v4i32 MQPR:$v2)))>;
1766
1767  def : Pat<(v16i8 (ARMvshruImm
1768                     (v16i8 (sub (v16i8 MQPR:$v1), (v16i8 MQPR:$v2))), 1)),
1769            (v16i8 (MVE_VHSUBu8
1770                     (v16i8 MQPR:$v1), (v16i8 MQPR:$v2)))>;
1771  def : Pat<(v8i16 (ARMvshruImm
1772                     (v8i16 (sub (v8i16 MQPR:$v1), (v8i16 MQPR:$v2))), 1)),
1773            (v8i16 (MVE_VHSUBu16
1774                     (v8i16 MQPR:$v1), (v8i16 MQPR:$v2)))>;
1775  def : Pat<(v4i32 (ARMvshruImm
1776                     (v4i32 (sub (v4i32 MQPR:$v1), (v4i32 MQPR:$v2))), 1)),
1777            (v4i32 (MVE_VHSUBu32
1778                     (v4i32 MQPR:$v1), (v4i32 MQPR:$v2)))>;
1779}
1780
1781class MVE_VDUP<string suffix, bit B, bit E, list<dag> pattern=[]>
1782  : MVE_p<(outs MQPR:$Qd), (ins rGPR:$Rt), NoItinerary,
1783          "vdup", suffix, "$Qd, $Rt", vpred_r, "", pattern> {
1784  bits<4> Qd;
1785  bits<4> Rt;
1786
1787  let Inst{28} = 0b0;
1788  let Inst{25-23} = 0b101;
1789  let Inst{22} = B;
1790  let Inst{21-20} = 0b10;
1791  let Inst{19-17} = Qd{2-0};
1792  let Inst{16} = 0b0;
1793  let Inst{15-12} = Rt;
1794  let Inst{11-8} = 0b1011;
1795  let Inst{7} = Qd{3};
1796  let Inst{6} = 0b0;
1797  let Inst{5} = E;
1798  let Inst{4-0} = 0b10000;
1799  let validForTailPredication = 1;
1800}
1801
1802def MVE_VDUP32 : MVE_VDUP<"32", 0b0, 0b0>;
1803def MVE_VDUP16 : MVE_VDUP<"16", 0b0, 0b1>;
1804def MVE_VDUP8  : MVE_VDUP<"8",  0b1, 0b0>;
1805
1806let Predicates = [HasMVEInt] in {
1807  def : Pat<(v16i8 (ARMvdup (i32 rGPR:$elem))),
1808            (MVE_VDUP8  rGPR:$elem)>;
1809  def : Pat<(v8i16 (ARMvdup (i32 rGPR:$elem))),
1810            (MVE_VDUP16 rGPR:$elem)>;
1811  def : Pat<(v4i32 (ARMvdup (i32 rGPR:$elem))),
1812            (MVE_VDUP32 rGPR:$elem)>;
1813
1814  def : Pat<(v4i32 (ARMvduplane (v4i32 MQPR:$src), imm:$lane)),
1815            (MVE_VDUP32 (MVE_VMOV_from_lane_32 MQPR:$src, imm:$lane))>;
1816  // For the 16-bit and 8-bit vduplanes we don't care about the signedness
1817  // of the lane move operation as we only want the lowest 8/16 bits anyway.
1818  def : Pat<(v8i16 (ARMvduplane (v8i16 MQPR:$src), imm:$lane)),
1819            (MVE_VDUP16 (MVE_VMOV_from_lane_u16 MQPR:$src, imm:$lane))>;
1820  def : Pat<(v16i8 (ARMvduplane (v16i8 MQPR:$src), imm:$lane)),
1821            (MVE_VDUP8  (MVE_VMOV_from_lane_u8 MQPR:$src, imm:$lane))>;
1822
1823  def : Pat<(v4f32 (ARMvdup (f32 SPR:$elem))),
1824            (v4f32 (MVE_VDUP32 (i32 (COPY_TO_REGCLASS (f32 SPR:$elem), rGPR))))>;
1825  def : Pat<(v8f16 (ARMvdup (f16 HPR:$elem))),
1826            (v8f16 (MVE_VDUP16 (i32 (COPY_TO_REGCLASS (f16 HPR:$elem), rGPR))))>;
1827
1828  def : Pat<(v4f32 (ARMvduplane (v4f32 MQPR:$src), imm:$lane)),
1829            (MVE_VDUP32 (MVE_VMOV_from_lane_32 MQPR:$src, imm:$lane))>;
1830  def : Pat<(v8f16 (ARMvduplane (v8f16 MQPR:$src), imm:$lane)),
1831            (MVE_VDUP16 (MVE_VMOV_from_lane_u16 MQPR:$src, imm:$lane))>;
1832}
1833
1834
1835class MVEIntSingleSrc<string iname, string suffix, bits<2> size,
1836                         list<dag> pattern=[]>
1837  : MVE_p<(outs MQPR:$Qd), (ins MQPR:$Qm), NoItinerary,
1838          iname, suffix, "$Qd, $Qm", vpred_r, "", pattern> {
1839  bits<4> Qd;
1840  bits<4> Qm;
1841
1842  let Inst{22} = Qd{3};
1843  let Inst{19-18} = size{1-0};
1844  let Inst{15-13} = Qd{2-0};
1845  let Inst{5} = Qm{3};
1846  let Inst{3-1} = Qm{2-0};
1847}
1848
1849class MVE_VCLSCLZ<string iname, string suffix, bits<2> size,
1850                   bit count_zeroes, list<dag> pattern=[]>
1851  : MVEIntSingleSrc<iname, suffix, size, pattern> {
1852
1853  let Inst{28} = 0b1;
1854  let Inst{25-23} = 0b111;
1855  let Inst{21-20} = 0b11;
1856  let Inst{17-16} = 0b00;
1857  let Inst{12-8} = 0b00100;
1858  let Inst{7} = count_zeroes;
1859  let Inst{6} = 0b1;
1860  let Inst{4} = 0b0;
1861  let Inst{0} = 0b0;
1862  let validForTailPredication = 1;
1863}
1864
1865def MVE_VCLSs8  : MVE_VCLSCLZ<"vcls", "s8",  0b00, 0b0>;
1866def MVE_VCLSs16 : MVE_VCLSCLZ<"vcls", "s16", 0b01, 0b0>;
1867def MVE_VCLSs32 : MVE_VCLSCLZ<"vcls", "s32", 0b10, 0b0>;
1868
1869def MVE_VCLZs8  : MVE_VCLSCLZ<"vclz", "i8",  0b00, 0b1>;
1870def MVE_VCLZs16 : MVE_VCLSCLZ<"vclz", "i16", 0b01, 0b1>;
1871def MVE_VCLZs32 : MVE_VCLSCLZ<"vclz", "i32", 0b10, 0b1>;
1872
1873let Predicates = [HasMVEInt] in {
1874  def : Pat<(v16i8 ( ctlz (v16i8 MQPR:$val1))),
1875            (v16i8 ( MVE_VCLZs8 (v16i8 MQPR:$val1)))>;
1876  def : Pat<(v4i32 ( ctlz (v4i32 MQPR:$val1))),
1877            (v4i32 ( MVE_VCLZs32 (v4i32 MQPR:$val1)))>;
1878  def : Pat<(v8i16 ( ctlz (v8i16 MQPR:$val1))),
1879            (v8i16 ( MVE_VCLZs16 (v8i16 MQPR:$val1)))>;
1880}
1881
1882class MVE_VABSNEG_int<string iname, string suffix, bits<2> size, bit negate,
1883                      list<dag> pattern=[]>
1884  : MVEIntSingleSrc<iname, suffix, size, pattern> {
1885
1886  let Inst{28} = 0b1;
1887  let Inst{25-23} = 0b111;
1888  let Inst{21-20} = 0b11;
1889  let Inst{17-16} = 0b01;
1890  let Inst{12-8} = 0b00011;
1891  let Inst{7} = negate;
1892  let Inst{6} = 0b1;
1893  let Inst{4} = 0b0;
1894  let Inst{0} = 0b0;
1895  let validForTailPredication = 1;
1896}
1897
1898def MVE_VABSs8  : MVE_VABSNEG_int<"vabs", "s8",  0b00, 0b0>;
1899def MVE_VABSs16 : MVE_VABSNEG_int<"vabs", "s16", 0b01, 0b0>;
1900def MVE_VABSs32 : MVE_VABSNEG_int<"vabs", "s32", 0b10, 0b0>;
1901
1902let Predicates = [HasMVEInt] in {
1903  def : Pat<(v16i8 (abs (v16i8 MQPR:$v))),
1904            (v16i8 (MVE_VABSs8 $v))>;
1905  def : Pat<(v8i16 (abs (v8i16 MQPR:$v))),
1906            (v8i16 (MVE_VABSs16 $v))>;
1907  def : Pat<(v4i32 (abs (v4i32 MQPR:$v))),
1908            (v4i32 (MVE_VABSs32 $v))>;
1909}
1910
1911def MVE_VNEGs8  : MVE_VABSNEG_int<"vneg", "s8",  0b00, 0b1>;
1912def MVE_VNEGs16 : MVE_VABSNEG_int<"vneg", "s16", 0b01, 0b1>;
1913def MVE_VNEGs32 : MVE_VABSNEG_int<"vneg", "s32", 0b10, 0b1>;
1914
1915let Predicates = [HasMVEInt] in {
1916  def : Pat<(v16i8 (vnegq (v16i8 MQPR:$v))),
1917            (v16i8 (MVE_VNEGs8 $v))>;
1918  def : Pat<(v8i16 (vnegq (v8i16 MQPR:$v))),
1919            (v8i16 (MVE_VNEGs16 $v))>;
1920  def : Pat<(v4i32 (vnegq (v4i32 MQPR:$v))),
1921            (v4i32 (MVE_VNEGs32 $v))>;
1922}
1923
1924class MVE_VQABSNEG<string iname, string suffix, bits<2> size,
1925                   bit negate, list<dag> pattern=[]>
1926  : MVEIntSingleSrc<iname, suffix, size, pattern> {
1927
1928  let Inst{28} = 0b1;
1929  let Inst{25-23} = 0b111;
1930  let Inst{21-20} = 0b11;
1931  let Inst{17-16} = 0b00;
1932  let Inst{12-8} = 0b00111;
1933  let Inst{7} = negate;
1934  let Inst{6} = 0b1;
1935  let Inst{4} = 0b0;
1936  let Inst{0} = 0b0;
1937  let validForTailPredication = 1;
1938}
1939
1940def MVE_VQABSs8  : MVE_VQABSNEG<"vqabs", "s8",  0b00, 0b0>;
1941def MVE_VQABSs16 : MVE_VQABSNEG<"vqabs", "s16", 0b01, 0b0>;
1942def MVE_VQABSs32 : MVE_VQABSNEG<"vqabs", "s32", 0b10, 0b0>;
1943
1944def MVE_VQNEGs8  : MVE_VQABSNEG<"vqneg", "s8",  0b00, 0b1>;
1945def MVE_VQNEGs16 : MVE_VQABSNEG<"vqneg", "s16", 0b01, 0b1>;
1946def MVE_VQNEGs32 : MVE_VQABSNEG<"vqneg", "s32", 0b10, 0b1>;
1947
1948class MVE_mod_imm<string iname, string suffix, bits<4> cmode, bit op,
1949                  dag iops, list<dag> pattern=[]>
1950  : MVE_p<(outs MQPR:$Qd), iops, NoItinerary, iname, suffix, "$Qd, $imm",
1951          vpred_r, "", pattern> {
1952  bits<13> imm;
1953  bits<4> Qd;
1954
1955  let Inst{28} = imm{7};
1956  let Inst{25-23} = 0b111;
1957  let Inst{22} = Qd{3};
1958  let Inst{21-19} = 0b000;
1959  let Inst{18-16} = imm{6-4};
1960  let Inst{15-13} = Qd{2-0};
1961  let Inst{12} = 0b0;
1962  let Inst{11-8} = cmode{3-0};
1963  let Inst{7-6} = 0b01;
1964  let Inst{5} = op;
1965  let Inst{4} = 0b1;
1966  let Inst{3-0} = imm{3-0};
1967
1968  let DecoderMethod = "DecodeMVEModImmInstruction";
1969  let validForTailPredication = 1;
1970}
1971
1972let isReMaterializable = 1 in {
1973let isAsCheapAsAMove = 1 in {
1974def MVE_VMOVimmi8  : MVE_mod_imm<"vmov", "i8",  {1,1,1,0}, 0b0, (ins nImmSplatI8:$imm)>;
1975def MVE_VMOVimmi16 : MVE_mod_imm<"vmov", "i16", {1,0,?,0}, 0b0, (ins nImmSplatI16:$imm)> {
1976  let Inst{9} = imm{9};
1977}
1978def MVE_VMOVimmi32 : MVE_mod_imm<"vmov", "i32", {?,?,?,?}, 0b0, (ins nImmVMOVI32:$imm)> {
1979  let Inst{11-8} = imm{11-8};
1980}
1981def MVE_VMOVimmi64 : MVE_mod_imm<"vmov", "i64", {1,1,1,0}, 0b1, (ins nImmSplatI64:$imm)>;
1982def MVE_VMOVimmf32 : MVE_mod_imm<"vmov", "f32", {1,1,1,1}, 0b0, (ins nImmVMOVF32:$imm)>;
1983} // let isAsCheapAsAMove = 1
1984
1985def MVE_VMVNimmi16 : MVE_mod_imm<"vmvn", "i16", {1,0,?,0}, 0b1, (ins nImmSplatI16:$imm)> {
1986  let Inst{9} = imm{9};
1987}
1988def MVE_VMVNimmi32 : MVE_mod_imm<"vmvn", "i32", {?,?,?,?}, 0b1, (ins nImmVMOVI32:$imm)> {
1989  let Inst{11-8} = imm{11-8};
1990}
1991} // let isReMaterializable = 1
1992
1993let Predicates = [HasMVEInt] in {
1994  def : Pat<(v16i8 (ARMvmovImm timm:$simm)),
1995            (v16i8 (MVE_VMOVimmi8  nImmSplatI8:$simm))>;
1996  def : Pat<(v8i16 (ARMvmovImm timm:$simm)),
1997            (v8i16 (MVE_VMOVimmi16 nImmSplatI16:$simm))>;
1998  def : Pat<(v4i32 (ARMvmovImm timm:$simm)),
1999            (v4i32 (MVE_VMOVimmi32 nImmVMOVI32:$simm))>;
2000
2001  def : Pat<(v8i16 (ARMvmvnImm timm:$simm)),
2002            (v8i16 (MVE_VMVNimmi16 nImmSplatI16:$simm))>;
2003  def : Pat<(v4i32 (ARMvmvnImm timm:$simm)),
2004            (v4i32 (MVE_VMVNimmi32 nImmVMOVI32:$simm))>;
2005
2006  def : Pat<(v4f32 (ARMvmovFPImm timm:$simm)),
2007            (v4f32 (MVE_VMOVimmf32 nImmVMOVF32:$simm))>;
2008}
2009
2010class MVE_VMINMAXA<string iname, string suffix, bits<2> size,
2011                   bit bit_12, list<dag> pattern=[]>
2012  : MVE_p<(outs MQPR:$Qd), (ins MQPR:$Qd_src, MQPR:$Qm),
2013          NoItinerary, iname, suffix, "$Qd, $Qm", vpred_n, "$Qd = $Qd_src",
2014          pattern> {
2015  bits<4> Qd;
2016  bits<4> Qm;
2017
2018  let Inst{28} = 0b0;
2019  let Inst{25-23} = 0b100;
2020  let Inst{22} = Qd{3};
2021  let Inst{21-20} = 0b11;
2022  let Inst{19-18} = size;
2023  let Inst{17-16} = 0b11;
2024  let Inst{15-13} = Qd{2-0};
2025  let Inst{12} = bit_12;
2026  let Inst{11-6} = 0b111010;
2027  let Inst{5} = Qm{3};
2028  let Inst{4} = 0b0;
2029  let Inst{3-1} = Qm{2-0};
2030  let Inst{0} = 0b1;
2031}
2032
2033def MVE_VMAXAs8  : MVE_VMINMAXA<"vmaxa", "s8",  0b00, 0b0>;
2034def MVE_VMAXAs16 : MVE_VMINMAXA<"vmaxa", "s16", 0b01, 0b0>;
2035def MVE_VMAXAs32 : MVE_VMINMAXA<"vmaxa", "s32", 0b10, 0b0>;
2036
2037def MVE_VMINAs8  : MVE_VMINMAXA<"vmina", "s8",  0b00, 0b1>;
2038def MVE_VMINAs16 : MVE_VMINMAXA<"vmina", "s16", 0b01, 0b1>;
2039def MVE_VMINAs32 : MVE_VMINMAXA<"vmina", "s32", 0b10, 0b1>;
2040
2041// end of MVE Integer instructions
2042
2043// start of mve_imm_shift instructions
2044
2045def MVE_VSHLC : MVE_p<(outs rGPR:$RdmDest, MQPR:$Qd),
2046                      (ins MQPR:$QdSrc, rGPR:$RdmSrc, long_shift:$imm),
2047                      NoItinerary, "vshlc", "", "$QdSrc, $RdmSrc, $imm",
2048                      vpred_n, "$RdmDest = $RdmSrc,$Qd = $QdSrc"> {
2049  bits<5> imm;
2050  bits<4> Qd;
2051  bits<4> RdmDest;
2052
2053  let Inst{28} = 0b0;
2054  let Inst{25-23} = 0b101;
2055  let Inst{22} = Qd{3};
2056  let Inst{21} = 0b1;
2057  let Inst{20-16} = imm{4-0};
2058  let Inst{15-13} = Qd{2-0};
2059  let Inst{12-4} = 0b011111100;
2060  let Inst{3-0} = RdmDest{3-0};
2061}
2062
2063class MVE_shift_imm<dag oops, dag iops, string iname, string suffix,
2064                    string ops, vpred_ops vpred, string cstr,
2065                    list<dag> pattern=[]>
2066  : MVE_p<oops, iops, NoItinerary, iname, suffix, ops, vpred, cstr, pattern> {
2067  bits<4> Qd;
2068  bits<4> Qm;
2069
2070  let Inst{22} = Qd{3};
2071  let Inst{15-13} = Qd{2-0};
2072  let Inst{5} = Qm{3};
2073  let Inst{3-1} = Qm{2-0};
2074}
2075
2076class MVE_VMOVL<string iname, string suffix, bits<2> sz, bit U,
2077              list<dag> pattern=[]>
2078  : MVE_shift_imm<(outs MQPR:$Qd), (ins MQPR:$Qm),
2079                  iname, suffix, "$Qd, $Qm", vpred_r, "",
2080                  pattern> {
2081  let Inst{28} = U;
2082  let Inst{25-23} = 0b101;
2083  let Inst{21} = 0b1;
2084  let Inst{20-19} = sz{1-0};
2085  let Inst{18-16} = 0b000;
2086  let Inst{11-6} = 0b111101;
2087  let Inst{4} = 0b0;
2088  let Inst{0} = 0b0;
2089}
2090
2091multiclass MVE_VMOVL_shift_half<string iname, string suffix, bits<2> sz, bit U,
2092                                list<dag> pattern=[]> {
2093  def bh : MVE_VMOVL<!strconcat(iname, "b"), suffix, sz, U, pattern> {
2094    let Inst{12} = 0b0;
2095  }
2096  def th : MVE_VMOVL<!strconcat(iname, "t"), suffix, sz, U, pattern> {
2097    let Inst{12} = 0b1;
2098  }
2099}
2100
2101defm MVE_VMOVLs8 : MVE_VMOVL_shift_half<"vmovl", "s8", 0b01, 0b0>;
2102defm MVE_VMOVLu8 : MVE_VMOVL_shift_half<"vmovl", "u8", 0b01, 0b1>;
2103defm MVE_VMOVLs16 : MVE_VMOVL_shift_half<"vmovl", "s16", 0b10, 0b0>;
2104defm MVE_VMOVLu16 : MVE_VMOVL_shift_half<"vmovl", "u16", 0b10, 0b1>;
2105
2106let Predicates = [HasMVEInt] in {
2107  def : Pat<(sext_inreg (v4i32 MQPR:$src), v4i16),
2108            (MVE_VMOVLs16bh MQPR:$src)>;
2109  def : Pat<(sext_inreg (v8i16 MQPR:$src), v8i8),
2110            (MVE_VMOVLs8bh MQPR:$src)>;
2111  def : Pat<(sext_inreg (v4i32 MQPR:$src), v4i8),
2112            (MVE_VMOVLs16bh (MVE_VMOVLs8bh MQPR:$src))>;
2113
2114  // zext_inreg 16 -> 32
2115  def : Pat<(and (v4i32 MQPR:$src), (v4i32 (ARMvmovImm (i32 0xCFF)))),
2116            (MVE_VMOVLu16bh MQPR:$src)>;
2117  // zext_inreg 8 -> 16
2118  def : Pat<(and (v8i16 MQPR:$src), (v8i16 (ARMvmovImm (i32 0x8FF)))),
2119            (MVE_VMOVLu8bh MQPR:$src)>;
2120}
2121
2122
2123class MVE_VSHLL_imm<string iname, string suffix, bit U, bit th,
2124                    dag immops, list<dag> pattern=[]>
2125  : MVE_shift_imm<(outs MQPR:$Qd), !con((ins MQPR:$Qm), immops),
2126                  iname, suffix, "$Qd, $Qm, $imm", vpred_r, "", pattern> {
2127  let Inst{28} = U;
2128  let Inst{25-23} = 0b101;
2129  let Inst{21} = 0b1;
2130  let Inst{12} = th;
2131  let Inst{11-6} = 0b111101;
2132  let Inst{4} = 0b0;
2133  let Inst{0} = 0b0;
2134}
2135
2136// The immediate VSHLL instructions accept shift counts from 1 up to
2137// the lane width (8 or 16), but the full-width shifts have an
2138// entirely separate encoding, given below with 'lw' in the name.
2139
2140class MVE_VSHLL_imm8<string iname, string suffix,
2141                     bit U, bit th, list<dag> pattern=[]>
2142  : MVE_VSHLL_imm<iname, suffix, U, th, (ins mve_shift_imm1_7:$imm), pattern> {
2143  bits<3> imm;
2144  let Inst{20-19} = 0b01;
2145  let Inst{18-16} = imm;
2146}
2147
2148class MVE_VSHLL_imm16<string iname, string suffix,
2149                      bit U, bit th, list<dag> pattern=[]>
2150  : MVE_VSHLL_imm<iname, suffix, U, th, (ins mve_shift_imm1_15:$imm), pattern> {
2151  bits<4> imm;
2152  let Inst{20} = 0b1;
2153  let Inst{19-16} = imm;
2154}
2155
2156def MVE_VSHLL_imms8bh  : MVE_VSHLL_imm8 <"vshllb", "s8", 0b0, 0b0>;
2157def MVE_VSHLL_imms8th  : MVE_VSHLL_imm8 <"vshllt", "s8", 0b0, 0b1>;
2158def MVE_VSHLL_immu8bh  : MVE_VSHLL_imm8 <"vshllb", "u8", 0b1, 0b0>;
2159def MVE_VSHLL_immu8th  : MVE_VSHLL_imm8 <"vshllt", "u8", 0b1, 0b1>;
2160def MVE_VSHLL_imms16bh : MVE_VSHLL_imm16<"vshllb", "s16", 0b0, 0b0>;
2161def MVE_VSHLL_imms16th : MVE_VSHLL_imm16<"vshllt", "s16", 0b0, 0b1>;
2162def MVE_VSHLL_immu16bh : MVE_VSHLL_imm16<"vshllb", "u16", 0b1, 0b0>;
2163def MVE_VSHLL_immu16th : MVE_VSHLL_imm16<"vshllt", "u16", 0b1, 0b1>;
2164
2165class MVE_VSHLL_by_lane_width<string iname, string suffix, bits<2> size,
2166                              bit U, string ops, list<dag> pattern=[]>
2167  : MVE_shift_imm<(outs MQPR:$Qd), (ins MQPR:$Qm),
2168                  iname, suffix, ops, vpred_r, "", pattern> {
2169  let Inst{28} = U;
2170  let Inst{25-23} = 0b100;
2171  let Inst{21-20} = 0b11;
2172  let Inst{19-18} = size{1-0};
2173  let Inst{17-16} = 0b01;
2174  let Inst{11-6} = 0b111000;
2175  let Inst{4} = 0b0;
2176  let Inst{0} = 0b1;
2177}
2178
2179multiclass MVE_VSHLL_lw<string iname, string suffix, bits<2> sz, bit U,
2180                              string ops, list<dag> pattern=[]> {
2181  def bh : MVE_VSHLL_by_lane_width<iname#"b", suffix, sz, U, ops, pattern> {
2182    let Inst{12} = 0b0;
2183  }
2184  def th : MVE_VSHLL_by_lane_width<iname#"t", suffix, sz, U, ops, pattern> {
2185    let Inst{12} = 0b1;
2186  }
2187}
2188
2189defm MVE_VSHLL_lws8  : MVE_VSHLL_lw<"vshll", "s8",  0b00, 0b0, "$Qd, $Qm, #8">;
2190defm MVE_VSHLL_lws16 : MVE_VSHLL_lw<"vshll", "s16", 0b01, 0b0, "$Qd, $Qm, #16">;
2191defm MVE_VSHLL_lwu8  : MVE_VSHLL_lw<"vshll", "u8",  0b00, 0b1, "$Qd, $Qm, #8">;
2192defm MVE_VSHLL_lwu16 : MVE_VSHLL_lw<"vshll", "u16", 0b01, 0b1, "$Qd, $Qm, #16">;
2193
2194class MVE_VxSHRN<string iname, string suffix, bit bit_12, bit bit_28,
2195               dag immops, list<dag> pattern=[]>
2196  : MVE_shift_imm<(outs MQPR:$Qd), !con((ins MQPR:$QdSrc, MQPR:$Qm), immops),
2197                  iname, suffix, "$Qd, $Qm, $imm", vpred_n, "$Qd = $QdSrc",
2198                  pattern> {
2199  bits<5> imm;
2200
2201  let Inst{28} = bit_28;
2202  let Inst{25-23} = 0b101;
2203  let Inst{21} = 0b0;
2204  let Inst{20-16} = imm{4-0};
2205  let Inst{12} = bit_12;
2206  let Inst{11-6} = 0b111111;
2207  let Inst{4} = 0b0;
2208  let Inst{0} = 0b1;
2209}
2210
2211def MVE_VRSHRNi16bh : MVE_VxSHRN<
2212    "vrshrnb", "i16", 0b0, 0b1, (ins shr_imm8:$imm)> {
2213  let Inst{20-19} = 0b01;
2214}
2215def MVE_VRSHRNi16th : MVE_VxSHRN<
2216    "vrshrnt", "i16", 0b1, 0b1,(ins shr_imm8:$imm)> {
2217  let Inst{20-19} = 0b01;
2218}
2219def MVE_VRSHRNi32bh : MVE_VxSHRN<
2220    "vrshrnb", "i32", 0b0, 0b1, (ins shr_imm16:$imm)> {
2221  let Inst{20} = 0b1;
2222}
2223def MVE_VRSHRNi32th : MVE_VxSHRN<
2224    "vrshrnt", "i32", 0b1, 0b1, (ins shr_imm16:$imm)> {
2225  let Inst{20} = 0b1;
2226}
2227
2228def MVE_VSHRNi16bh : MVE_VxSHRN<
2229    "vshrnb", "i16", 0b0, 0b0, (ins shr_imm8:$imm)> {
2230  let Inst{20-19} = 0b01;
2231}
2232def MVE_VSHRNi16th : MVE_VxSHRN<
2233    "vshrnt", "i16", 0b1, 0b0, (ins shr_imm8:$imm)> {
2234  let Inst{20-19} = 0b01;
2235}
2236def MVE_VSHRNi32bh : MVE_VxSHRN<
2237    "vshrnb", "i32", 0b0, 0b0, (ins shr_imm16:$imm)> {
2238  let Inst{20} = 0b1;
2239}
2240def MVE_VSHRNi32th : MVE_VxSHRN<
2241    "vshrnt", "i32", 0b1, 0b0, (ins shr_imm16:$imm)> {
2242  let Inst{20} = 0b1;
2243}
2244
2245class MVE_VxQRSHRUN<string iname, string suffix, bit bit_28, bit bit_12, dag immops,
2246                 list<dag> pattern=[]>
2247  : MVE_shift_imm<(outs MQPR:$Qd), !con((ins MQPR:$QdSrc, MQPR:$Qm), immops),
2248                  iname, suffix, "$Qd, $Qm, $imm", vpred_n, "$Qd = $QdSrc",
2249                  pattern> {
2250  bits<5> imm;
2251
2252  let Inst{28} = bit_28;
2253  let Inst{25-23} = 0b101;
2254  let Inst{21} = 0b0;
2255  let Inst{20-16} = imm{4-0};
2256  let Inst{12} = bit_12;
2257  let Inst{11-6} = 0b111111;
2258  let Inst{4} = 0b0;
2259  let Inst{0} = 0b0;
2260}
2261
2262def MVE_VQRSHRUNs16bh : MVE_VxQRSHRUN<
2263    "vqrshrunb", "s16", 0b1, 0b0, (ins shr_imm8:$imm)> {
2264  let Inst{20-19} = 0b01;
2265}
2266def MVE_VQRSHRUNs16th : MVE_VxQRSHRUN<
2267    "vqrshrunt", "s16", 0b1, 0b1, (ins shr_imm8:$imm)> {
2268  let Inst{20-19} = 0b01;
2269}
2270def MVE_VQRSHRUNs32bh : MVE_VxQRSHRUN<
2271    "vqrshrunb", "s32", 0b1, 0b0, (ins shr_imm16:$imm)> {
2272  let Inst{20} = 0b1;
2273}
2274def MVE_VQRSHRUNs32th : MVE_VxQRSHRUN<
2275    "vqrshrunt", "s32", 0b1, 0b1, (ins shr_imm16:$imm)> {
2276  let Inst{20} = 0b1;
2277}
2278
2279def MVE_VQSHRUNs16bh : MVE_VxQRSHRUN<
2280    "vqshrunb", "s16", 0b0, 0b0, (ins shr_imm8:$imm)> {
2281  let Inst{20-19} = 0b01;
2282}
2283def MVE_VQSHRUNs16th : MVE_VxQRSHRUN<
2284    "vqshrunt", "s16", 0b0, 0b1, (ins shr_imm8:$imm)> {
2285  let Inst{20-19} = 0b01;
2286}
2287def MVE_VQSHRUNs32bh : MVE_VxQRSHRUN<
2288    "vqshrunb", "s32", 0b0, 0b0, (ins shr_imm16:$imm)> {
2289  let Inst{20} = 0b1;
2290}
2291def MVE_VQSHRUNs32th : MVE_VxQRSHRUN<
2292    "vqshrunt", "s32", 0b0, 0b1, (ins shr_imm16:$imm)> {
2293  let Inst{20} = 0b1;
2294}
2295
2296class MVE_VxQRSHRN<string iname, string suffix, bit bit_0, bit bit_12,
2297                   dag immops, list<dag> pattern=[]>
2298  : MVE_shift_imm<(outs MQPR:$Qd), !con((ins MQPR:$QdSrc, MQPR:$Qm), immops),
2299                  iname, suffix, "$Qd, $Qm, $imm", vpred_n, "$Qd = $QdSrc",
2300                  pattern> {
2301  bits<5> imm;
2302
2303  let Inst{25-23} = 0b101;
2304  let Inst{21} = 0b0;
2305  let Inst{20-16} = imm{4-0};
2306  let Inst{12} = bit_12;
2307  let Inst{11-6} = 0b111101;
2308  let Inst{4} = 0b0;
2309  let Inst{0} = bit_0;
2310}
2311
2312multiclass MVE_VxQRSHRN_types<string iname, bit bit_0, bit bit_12> {
2313  def s16 : MVE_VxQRSHRN<iname, "s16", bit_0, bit_12, (ins shr_imm8:$imm)> {
2314    let Inst{28} = 0b0;
2315    let Inst{20-19} = 0b01;
2316  }
2317  def u16 : MVE_VxQRSHRN<iname, "u16", bit_0, bit_12, (ins shr_imm8:$imm)> {
2318    let Inst{28} = 0b1;
2319    let Inst{20-19} = 0b01;
2320  }
2321  def s32 : MVE_VxQRSHRN<iname, "s32", bit_0, bit_12, (ins shr_imm16:$imm)> {
2322    let Inst{28} = 0b0;
2323    let Inst{20} = 0b1;
2324  }
2325  def u32 : MVE_VxQRSHRN<iname, "u32", bit_0, bit_12, (ins shr_imm16:$imm)> {
2326    let Inst{28} = 0b1;
2327    let Inst{20} = 0b1;
2328  }
2329}
2330
2331defm MVE_VQRSHRNbh : MVE_VxQRSHRN_types<"vqrshrnb", 0b1, 0b0>;
2332defm MVE_VQRSHRNth : MVE_VxQRSHRN_types<"vqrshrnt", 0b1, 0b1>;
2333defm MVE_VQSHRNbh  : MVE_VxQRSHRN_types<"vqshrnb", 0b0, 0b0>;
2334defm MVE_VQSHRNth  : MVE_VxQRSHRN_types<"vqshrnt", 0b0, 0b1>;
2335
2336// end of mve_imm_shift instructions
2337
2338// start of mve_shift instructions
2339
2340class MVE_shift_by_vec<string iname, string suffix, bit U,
2341                       bits<2> size, bit bit_4, bit bit_8>
2342  : MVE_p<(outs MQPR:$Qd), (ins MQPR:$Qm, MQPR:$Qn), NoItinerary,
2343           iname, suffix, "$Qd, $Qm, $Qn", vpred_r, "", []> {
2344  // Shift instructions which take a vector of shift counts
2345  bits<4> Qd;
2346  bits<4> Qm;
2347  bits<4> Qn;
2348
2349  let Inst{28} = U;
2350  let Inst{25-24} = 0b11;
2351  let Inst{23} = 0b0;
2352  let Inst{22} = Qd{3};
2353  let Inst{21-20} = size;
2354  let Inst{19-17} = Qn{2-0};
2355  let Inst{16} = 0b0;
2356  let Inst{15-13} = Qd{2-0};
2357  let Inst{12-9} = 0b0010;
2358  let Inst{8} = bit_8;
2359  let Inst{7} = Qn{3};
2360  let Inst{6} = 0b1;
2361  let Inst{5} = Qm{3};
2362  let Inst{4} = bit_4;
2363  let Inst{3-1} = Qm{2-0};
2364  let Inst{0} = 0b0;
2365  let validForTailPredication = 1;
2366}
2367
2368multiclass mve_shift_by_vec_multi<string iname, bit bit_4, bit bit_8> {
2369  def s8  : MVE_shift_by_vec<iname, "s8", 0b0, 0b00, bit_4, bit_8>;
2370  def s16 : MVE_shift_by_vec<iname, "s16", 0b0, 0b01, bit_4, bit_8>;
2371  def s32 : MVE_shift_by_vec<iname, "s32", 0b0, 0b10, bit_4, bit_8>;
2372  def u8  : MVE_shift_by_vec<iname, "u8", 0b1, 0b00, bit_4, bit_8>;
2373  def u16 : MVE_shift_by_vec<iname, "u16", 0b1, 0b01, bit_4, bit_8>;
2374  def u32 : MVE_shift_by_vec<iname, "u32", 0b1, 0b10, bit_4, bit_8>;
2375}
2376
2377defm MVE_VSHL_by_vec   : mve_shift_by_vec_multi<"vshl",   0b0, 0b0>;
2378defm MVE_VQSHL_by_vec  : mve_shift_by_vec_multi<"vqshl",  0b1, 0b0>;
2379defm MVE_VQRSHL_by_vec : mve_shift_by_vec_multi<"vqrshl", 0b1, 0b1>;
2380defm MVE_VRSHL_by_vec  : mve_shift_by_vec_multi<"vrshl",  0b0, 0b1>;
2381
2382let Predicates = [HasMVEInt] in {
2383  def : Pat<(v4i32 (ARMvshlu (v4i32 MQPR:$Qm), (v4i32 MQPR:$Qn))),
2384            (v4i32 (MVE_VSHL_by_vecu32 (v4i32 MQPR:$Qm), (v4i32 MQPR:$Qn)))>;
2385  def : Pat<(v8i16 (ARMvshlu (v8i16 MQPR:$Qm), (v8i16 MQPR:$Qn))),
2386            (v8i16 (MVE_VSHL_by_vecu16 (v8i16 MQPR:$Qm), (v8i16 MQPR:$Qn)))>;
2387  def : Pat<(v16i8 (ARMvshlu (v16i8 MQPR:$Qm), (v16i8 MQPR:$Qn))),
2388            (v16i8 (MVE_VSHL_by_vecu8 (v16i8 MQPR:$Qm), (v16i8 MQPR:$Qn)))>;
2389
2390  def : Pat<(v4i32 (ARMvshls (v4i32 MQPR:$Qm), (v4i32 MQPR:$Qn))),
2391            (v4i32 (MVE_VSHL_by_vecs32 (v4i32 MQPR:$Qm), (v4i32 MQPR:$Qn)))>;
2392  def : Pat<(v8i16 (ARMvshls (v8i16 MQPR:$Qm), (v8i16 MQPR:$Qn))),
2393            (v8i16 (MVE_VSHL_by_vecs16 (v8i16 MQPR:$Qm), (v8i16 MQPR:$Qn)))>;
2394  def : Pat<(v16i8 (ARMvshls (v16i8 MQPR:$Qm), (v16i8 MQPR:$Qn))),
2395            (v16i8 (MVE_VSHL_by_vecs8 (v16i8 MQPR:$Qm), (v16i8 MQPR:$Qn)))>;
2396}
2397
2398class MVE_shift_with_imm<string iname, string suffix, dag oops, dag iops,
2399                         string ops, vpred_ops vpred, string cstr,
2400                         list<dag> pattern=[]>
2401  : MVE_p<oops, iops, NoItinerary, iname, suffix, ops, vpred, cstr, pattern> {
2402  bits<4> Qd;
2403  bits<4> Qm;
2404
2405  let Inst{23} = 0b1;
2406  let Inst{22} = Qd{3};
2407  let Inst{15-13} = Qd{2-0};
2408  let Inst{12-11} = 0b00;
2409  let Inst{7-6} = 0b01;
2410  let Inst{5} = Qm{3};
2411  let Inst{4} = 0b1;
2412  let Inst{3-1} = Qm{2-0};
2413  let Inst{0} = 0b0;
2414  let validForTailPredication = 1;
2415}
2416
2417class MVE_VSxI_imm<string iname, string suffix, bit bit_8, dag imm>
2418  : MVE_shift_with_imm<iname, suffix, (outs MQPR:$Qd),
2419                       !con((ins MQPR:$Qd_src, MQPR:$Qm), imm),
2420                       "$Qd, $Qm, $imm", vpred_n, "$Qd = $Qd_src"> {
2421  bits<6> imm;
2422  let Inst{28} = 0b1;
2423  let Inst{25-24} = 0b11;
2424  let Inst{21-16} = imm;
2425  let Inst{10-9} = 0b10;
2426  let Inst{8} = bit_8;
2427  let validForTailPredication = 1;
2428}
2429
2430def MVE_VSRIimm8 : MVE_VSxI_imm<"vsri", "8", 0b0, (ins shr_imm8:$imm)> {
2431  let Inst{21-19} = 0b001;
2432}
2433
2434def MVE_VSRIimm16 : MVE_VSxI_imm<"vsri", "16", 0b0, (ins shr_imm16:$imm)> {
2435  let Inst{21-20} = 0b01;
2436}
2437
2438def MVE_VSRIimm32 : MVE_VSxI_imm<"vsri", "32", 0b0, (ins shr_imm32:$imm)> {
2439  let Inst{21} = 0b1;
2440}
2441
2442def MVE_VSLIimm8 : MVE_VSxI_imm<"vsli", "8", 0b1, (ins imm0_7:$imm)> {
2443  let Inst{21-19} = 0b001;
2444}
2445
2446def MVE_VSLIimm16 : MVE_VSxI_imm<"vsli", "16", 0b1, (ins imm0_15:$imm)> {
2447  let Inst{21-20} = 0b01;
2448}
2449
2450def MVE_VSLIimm32 : MVE_VSxI_imm<"vsli", "32", 0b1,(ins imm0_31:$imm)> {
2451  let Inst{21} = 0b1;
2452}
2453
2454class MVE_VQSHL_imm<string suffix, dag imm>
2455  : MVE_shift_with_imm<"vqshl", suffix, (outs MQPR:$Qd),
2456                       !con((ins MQPR:$Qm), imm), "$Qd, $Qm, $imm",
2457                       vpred_r, ""> {
2458  bits<6> imm;
2459
2460  let Inst{25-24} = 0b11;
2461  let Inst{21-16} = imm;
2462  let Inst{10-8} = 0b111;
2463}
2464
2465def MVE_VSLIimms8 : MVE_VQSHL_imm<"s8", (ins imm0_7:$imm)> {
2466  let Inst{28} = 0b0;
2467  let Inst{21-19} = 0b001;
2468}
2469
2470def MVE_VSLIimmu8 : MVE_VQSHL_imm<"u8", (ins imm0_7:$imm)> {
2471  let Inst{28} = 0b1;
2472  let Inst{21-19} = 0b001;
2473}
2474
2475def MVE_VSLIimms16 : MVE_VQSHL_imm<"s16", (ins imm0_15:$imm)> {
2476  let Inst{28} = 0b0;
2477  let Inst{21-20} = 0b01;
2478}
2479
2480def MVE_VSLIimmu16 : MVE_VQSHL_imm<"u16", (ins imm0_15:$imm)> {
2481  let Inst{28} = 0b1;
2482  let Inst{21-20} = 0b01;
2483}
2484
2485def MVE_VSLIimms32 : MVE_VQSHL_imm<"s32", (ins imm0_31:$imm)> {
2486  let Inst{28} = 0b0;
2487  let Inst{21} = 0b1;
2488}
2489
2490def MVE_VSLIimmu32 : MVE_VQSHL_imm<"u32", (ins imm0_31:$imm)> {
2491  let Inst{28} = 0b1;
2492  let Inst{21} = 0b1;
2493}
2494
2495class MVE_VQSHLU_imm<string suffix, dag imm>
2496  : MVE_shift_with_imm<"vqshlu", suffix, (outs MQPR:$Qd),
2497                       !con((ins MQPR:$Qm), imm), "$Qd, $Qm, $imm",
2498                       vpred_r, ""> {
2499  bits<6> imm;
2500
2501  let Inst{28} = 0b1;
2502  let Inst{25-24} = 0b11;
2503  let Inst{21-16} = imm;
2504  let Inst{10-8} = 0b110;
2505}
2506
2507def MVE_VQSHLU_imms8 : MVE_VQSHLU_imm<"s8", (ins imm0_7:$imm)> {
2508  let Inst{21-19} = 0b001;
2509}
2510
2511def MVE_VQSHLU_imms16 : MVE_VQSHLU_imm<"s16", (ins imm0_15:$imm)> {
2512  let Inst{21-20} = 0b01;
2513}
2514
2515def MVE_VQSHLU_imms32 : MVE_VQSHLU_imm<"s32", (ins imm0_31:$imm)> {
2516  let Inst{21} = 0b1;
2517}
2518
2519class MVE_VRSHR_imm<string suffix, dag imm>
2520  : MVE_shift_with_imm<"vrshr", suffix, (outs MQPR:$Qd),
2521                       !con((ins MQPR:$Qm), imm), "$Qd, $Qm, $imm",
2522                       vpred_r, ""> {
2523  bits<6> imm;
2524
2525  let Inst{25-24} = 0b11;
2526  let Inst{21-16} = imm;
2527  let Inst{10-8} = 0b010;
2528}
2529
2530def MVE_VRSHR_imms8 : MVE_VRSHR_imm<"s8", (ins shr_imm8:$imm)> {
2531  let Inst{28} = 0b0;
2532  let Inst{21-19} = 0b001;
2533}
2534
2535def MVE_VRSHR_immu8 : MVE_VRSHR_imm<"u8", (ins shr_imm8:$imm)> {
2536  let Inst{28} = 0b1;
2537  let Inst{21-19} = 0b001;
2538}
2539
2540def MVE_VRSHR_imms16 : MVE_VRSHR_imm<"s16", (ins shr_imm16:$imm)> {
2541  let Inst{28} = 0b0;
2542  let Inst{21-20} = 0b01;
2543}
2544
2545def MVE_VRSHR_immu16 : MVE_VRSHR_imm<"u16", (ins shr_imm16:$imm)> {
2546  let Inst{28} = 0b1;
2547  let Inst{21-20} = 0b01;
2548}
2549
2550def MVE_VRSHR_imms32 : MVE_VRSHR_imm<"s32", (ins shr_imm32:$imm)> {
2551  let Inst{28} = 0b0;
2552  let Inst{21} = 0b1;
2553}
2554
2555def MVE_VRSHR_immu32 : MVE_VRSHR_imm<"u32", (ins shr_imm32:$imm)> {
2556  let Inst{28} = 0b1;
2557  let Inst{21} = 0b1;
2558}
2559
2560class MVE_VSHR_imm<string suffix, dag imm>
2561  : MVE_shift_with_imm<"vshr", suffix, (outs MQPR:$Qd),
2562                       !con((ins MQPR:$Qm), imm), "$Qd, $Qm, $imm",
2563                       vpred_r, ""> {
2564  bits<6> imm;
2565
2566  let Inst{25-24} = 0b11;
2567  let Inst{21-16} = imm;
2568  let Inst{10-8} = 0b000;
2569}
2570
2571def MVE_VSHR_imms8 : MVE_VSHR_imm<"s8", (ins shr_imm8:$imm)> {
2572  let Inst{28} = 0b0;
2573  let Inst{21-19} = 0b001;
2574}
2575
2576def MVE_VSHR_immu8 : MVE_VSHR_imm<"u8", (ins shr_imm8:$imm)> {
2577  let Inst{28} = 0b1;
2578  let Inst{21-19} = 0b001;
2579}
2580
2581def MVE_VSHR_imms16 : MVE_VSHR_imm<"s16", (ins shr_imm16:$imm)> {
2582  let Inst{28} = 0b0;
2583  let Inst{21-20} = 0b01;
2584}
2585
2586def MVE_VSHR_immu16 : MVE_VSHR_imm<"u16", (ins shr_imm16:$imm)> {
2587  let Inst{28} = 0b1;
2588  let Inst{21-20} = 0b01;
2589}
2590
2591def MVE_VSHR_imms32 : MVE_VSHR_imm<"s32", (ins shr_imm32:$imm)> {
2592  let Inst{28} = 0b0;
2593  let Inst{21} = 0b1;
2594}
2595
2596def MVE_VSHR_immu32 : MVE_VSHR_imm<"u32", (ins shr_imm32:$imm)> {
2597  let Inst{28} = 0b1;
2598  let Inst{21} = 0b1;
2599}
2600
2601class MVE_VSHL_imm<string suffix, dag imm>
2602  : MVE_shift_with_imm<"vshl", suffix, (outs MQPR:$Qd),
2603                       !con((ins MQPR:$Qm), imm), "$Qd, $Qm, $imm",
2604                       vpred_r, ""> {
2605  bits<6> imm;
2606
2607  let Inst{28} = 0b0;
2608  let Inst{25-24} = 0b11;
2609  let Inst{21-16} = imm;
2610  let Inst{10-8} = 0b101;
2611}
2612
2613def MVE_VSHL_immi8 : MVE_VSHL_imm<"i8", (ins imm0_7:$imm)> {
2614  let Inst{21-19} = 0b001;
2615}
2616
2617def MVE_VSHL_immi16 : MVE_VSHL_imm<"i16", (ins imm0_15:$imm)> {
2618  let Inst{21-20} = 0b01;
2619}
2620
2621def MVE_VSHL_immi32 : MVE_VSHL_imm<"i32", (ins imm0_31:$imm)> {
2622  let Inst{21} = 0b1;
2623}
2624
2625let Predicates = [HasMVEInt] in {
2626  def : Pat<(v4i32 (ARMvshlImm (v4i32 MQPR:$src), imm0_31:$imm)),
2627            (v4i32 (MVE_VSHL_immi32 (v4i32 MQPR:$src), imm0_31:$imm))>;
2628  def : Pat<(v8i16 (ARMvshlImm (v8i16 MQPR:$src), imm0_15:$imm)),
2629            (v8i16 (MVE_VSHL_immi16 (v8i16 MQPR:$src), imm0_15:$imm))>;
2630  def : Pat<(v16i8 (ARMvshlImm (v16i8 MQPR:$src), imm0_7:$imm)),
2631            (v16i8 (MVE_VSHL_immi8 (v16i8 MQPR:$src), imm0_7:$imm))>;
2632
2633  def : Pat<(v4i32 (ARMvshruImm (v4i32 MQPR:$src), imm0_31:$imm)),
2634            (v4i32 (MVE_VSHR_immu32 (v4i32 MQPR:$src), imm0_31:$imm))>;
2635  def : Pat<(v8i16 (ARMvshruImm (v8i16 MQPR:$src), imm0_15:$imm)),
2636            (v8i16 (MVE_VSHR_immu16 (v8i16 MQPR:$src), imm0_15:$imm))>;
2637  def : Pat<(v16i8 (ARMvshruImm (v16i8 MQPR:$src), imm0_7:$imm)),
2638            (v16i8 (MVE_VSHR_immu8 (v16i8 MQPR:$src), imm0_7:$imm))>;
2639
2640  def : Pat<(v4i32 (ARMvshrsImm (v4i32 MQPR:$src), imm0_31:$imm)),
2641            (v4i32 (MVE_VSHR_imms32 (v4i32 MQPR:$src), imm0_31:$imm))>;
2642  def : Pat<(v8i16 (ARMvshrsImm (v8i16 MQPR:$src), imm0_15:$imm)),
2643            (v8i16 (MVE_VSHR_imms16 (v8i16 MQPR:$src), imm0_15:$imm))>;
2644  def : Pat<(v16i8 (ARMvshrsImm (v16i8 MQPR:$src), imm0_7:$imm)),
2645            (v16i8 (MVE_VSHR_imms8 (v16i8 MQPR:$src), imm0_7:$imm))>;
2646}
2647
2648// end of mve_shift instructions
2649
2650// start of MVE Floating Point instructions
2651
2652class MVE_float<string iname, string suffix, dag oops, dag iops, string ops,
2653                vpred_ops vpred, string cstr, list<dag> pattern=[]>
2654  : MVE_f<oops, iops, NoItinerary, iname, suffix, ops, vpred, cstr, pattern> {
2655  bits<4> Qm;
2656
2657  let Inst{12} = 0b0;
2658  let Inst{6} = 0b1;
2659  let Inst{5} = Qm{3};
2660  let Inst{3-1} = Qm{2-0};
2661  let Inst{0} = 0b0;
2662}
2663
2664class MVE_VRINT<string rmode, bits<3> op, string suffix, bits<2> size,
2665                list<dag> pattern=[]>
2666  : MVE_float<!strconcat("vrint", rmode), suffix, (outs MQPR:$Qd),
2667              (ins MQPR:$Qm), "$Qd, $Qm", vpred_r, "", pattern> {
2668  bits<4> Qd;
2669
2670  let Inst{28} = 0b1;
2671  let Inst{25-23} = 0b111;
2672  let Inst{22} = Qd{3};
2673  let Inst{21-20} = 0b11;
2674  let Inst{19-18} = size;
2675  let Inst{17-16} = 0b10;
2676  let Inst{15-13} = Qd{2-0};
2677  let Inst{11-10} = 0b01;
2678  let Inst{9-7} = op{2-0};
2679  let Inst{4} = 0b0;
2680  let validForTailPredication = 1;
2681
2682}
2683
2684multiclass MVE_VRINT_ops<string suffix, bits<2> size, list<dag> pattern=[]> {
2685  def N : MVE_VRINT<"n", 0b000, suffix, size, pattern>;
2686  def X : MVE_VRINT<"x", 0b001, suffix, size, pattern>;
2687  def A : MVE_VRINT<"a", 0b010, suffix, size, pattern>;
2688  def Z : MVE_VRINT<"z", 0b011, suffix, size, pattern>;
2689  def M : MVE_VRINT<"m", 0b101, suffix, size, pattern>;
2690  def P : MVE_VRINT<"p", 0b111, suffix, size, pattern>;
2691}
2692
2693defm MVE_VRINTf16 : MVE_VRINT_ops<"f16", 0b01>;
2694defm MVE_VRINTf32 : MVE_VRINT_ops<"f32", 0b10>;
2695
2696let Predicates = [HasMVEFloat] in {
2697  def : Pat<(v4f32 (frint (v4f32 MQPR:$val1))),
2698            (v4f32 (MVE_VRINTf32X (v4f32 MQPR:$val1)))>;
2699  def : Pat<(v8f16 (frint (v8f16 MQPR:$val1))),
2700            (v8f16 (MVE_VRINTf16X (v8f16 MQPR:$val1)))>;
2701  def : Pat<(v4f32 (fround (v4f32 MQPR:$val1))),
2702            (v4f32 (MVE_VRINTf32A (v4f32 MQPR:$val1)))>;
2703  def : Pat<(v8f16 (fround (v8f16 MQPR:$val1))),
2704            (v8f16 (MVE_VRINTf16A (v8f16 MQPR:$val1)))>;
2705  def : Pat<(v4f32 (ftrunc (v4f32 MQPR:$val1))),
2706            (v4f32 (MVE_VRINTf32Z (v4f32 MQPR:$val1)))>;
2707  def : Pat<(v8f16 (ftrunc (v8f16 MQPR:$val1))),
2708            (v8f16 (MVE_VRINTf16Z (v8f16 MQPR:$val1)))>;
2709  def : Pat<(v4f32 (ffloor (v4f32 MQPR:$val1))),
2710            (v4f32 (MVE_VRINTf32M (v4f32 MQPR:$val1)))>;
2711  def : Pat<(v8f16 (ffloor (v8f16 MQPR:$val1))),
2712            (v8f16 (MVE_VRINTf16M (v8f16 MQPR:$val1)))>;
2713  def : Pat<(v4f32 (fceil (v4f32 MQPR:$val1))),
2714            (v4f32 (MVE_VRINTf32P (v4f32 MQPR:$val1)))>;
2715  def : Pat<(v8f16 (fceil (v8f16 MQPR:$val1))),
2716            (v8f16 (MVE_VRINTf16P (v8f16 MQPR:$val1)))>;
2717}
2718
2719class MVEFloatArithNeon<string iname, string suffix, bit size,
2720                           dag oops, dag iops, string ops,
2721                           vpred_ops vpred, string cstr, list<dag> pattern=[]>
2722  : MVE_float<iname, suffix, oops, iops, ops, vpred, cstr, pattern> {
2723  let Inst{20} = size;
2724  let Inst{16} = 0b0;
2725}
2726
2727class MVE_VMUL_fp<string suffix, bit size, list<dag> pattern=[]>
2728  : MVEFloatArithNeon<"vmul", suffix, size, (outs MQPR:$Qd),
2729                      (ins MQPR:$Qn, MQPR:$Qm), "$Qd, $Qn, $Qm", vpred_r, "",
2730                      pattern> {
2731  bits<4> Qd;
2732  bits<4> Qn;
2733
2734  let Inst{28} = 0b1;
2735  let Inst{25-23} = 0b110;
2736  let Inst{22} = Qd{3};
2737  let Inst{21} = 0b0;
2738  let Inst{19-17} = Qn{2-0};
2739  let Inst{15-13} = Qd{2-0};
2740  let Inst{12-8} = 0b01101;
2741  let Inst{7} = Qn{3};
2742  let Inst{4} = 0b1;
2743  let validForTailPredication = 1;
2744}
2745
2746def MVE_VMULf32 : MVE_VMUL_fp<"f32", 0b0>;
2747def MVE_VMULf16 : MVE_VMUL_fp<"f16", 0b1>;
2748
2749let Predicates = [HasMVEFloat] in {
2750  def : Pat<(v4f32 (fmul (v4f32 MQPR:$val1), (v4f32 MQPR:$val2))),
2751            (v4f32 (MVE_VMULf32 (v4f32 MQPR:$val1), (v4f32 MQPR:$val2)))>;
2752  def : Pat<(v8f16 (fmul (v8f16 MQPR:$val1), (v8f16 MQPR:$val2))),
2753            (v8f16 (MVE_VMULf16 (v8f16 MQPR:$val1), (v8f16 MQPR:$val2)))>;
2754}
2755
2756class MVE_VCMLA<string suffix, bit size, list<dag> pattern=[]>
2757  : MVEFloatArithNeon<"vcmla", suffix, size, (outs MQPR:$Qd),
2758                         (ins MQPR:$Qd_src, MQPR:$Qn, MQPR:$Qm, complexrotateop:$rot),
2759                         "$Qd, $Qn, $Qm, $rot", vpred_n, "$Qd = $Qd_src", pattern> {
2760  bits<4> Qd;
2761  bits<4> Qn;
2762  bits<2> rot;
2763
2764  let Inst{28} = 0b1;
2765  let Inst{25} = 0b0;
2766  let Inst{24-23} = rot;
2767  let Inst{22} = Qd{3};
2768  let Inst{21} = 0b1;
2769  let Inst{19-17} = Qn{2-0};
2770  let Inst{15-13} = Qd{2-0};
2771  let Inst{12-8} = 0b01000;
2772  let Inst{7} = Qn{3};
2773  let Inst{4} = 0b0;
2774}
2775
2776def MVE_VCMLAf16 : MVE_VCMLA<"f16", 0b0>;
2777def MVE_VCMLAf32 : MVE_VCMLA<"f32", 0b1>;
2778
2779class MVE_VADDSUBFMA_fp<string iname, string suffix, bit size, bit bit_4,
2780                        bit bit_8, bit bit_21, dag iops=(ins),
2781                        vpred_ops vpred=vpred_r, string cstr="",
2782                        list<dag> pattern=[]>
2783  : MVEFloatArithNeon<iname, suffix, size, (outs MQPR:$Qd),
2784                      !con(iops, (ins MQPR:$Qn, MQPR:$Qm)), "$Qd, $Qn, $Qm",
2785                      vpred, cstr, pattern> {
2786  bits<4> Qd;
2787  bits<4> Qn;
2788
2789  let Inst{28} = 0b0;
2790  let Inst{25-23} = 0b110;
2791  let Inst{22} = Qd{3};
2792  let Inst{21} = bit_21;
2793  let Inst{19-17} = Qn{2-0};
2794  let Inst{15-13} = Qd{2-0};
2795  let Inst{11-9} = 0b110;
2796  let Inst{8} = bit_8;
2797  let Inst{7} = Qn{3};
2798  let Inst{4} = bit_4;
2799}
2800
2801def MVE_VFMAf32 : MVE_VADDSUBFMA_fp<"vfma", "f32", 0b0, 0b1, 0b0, 0b0,
2802    (ins MQPR:$Qd_src), vpred_n, "$Qd = $Qd_src">;
2803def MVE_VFMAf16 : MVE_VADDSUBFMA_fp<"vfma", "f16", 0b1, 0b1, 0b0, 0b0,
2804    (ins MQPR:$Qd_src), vpred_n, "$Qd = $Qd_src">;
2805
2806def MVE_VFMSf32 : MVE_VADDSUBFMA_fp<"vfms", "f32", 0b0, 0b1, 0b0, 0b1,
2807    (ins MQPR:$Qd_src), vpred_n, "$Qd = $Qd_src">;
2808def MVE_VFMSf16 : MVE_VADDSUBFMA_fp<"vfms", "f16", 0b1, 0b1, 0b0, 0b1,
2809    (ins MQPR:$Qd_src), vpred_n, "$Qd = $Qd_src">;
2810
2811let Predicates = [HasMVEFloat] in {
2812  def : Pat<(v8f16 (fma (v8f16 MQPR:$src1), (v8f16 MQPR:$src2), (v8f16 MQPR:$src3))),
2813            (v8f16 (MVE_VFMAf16 $src3, $src1, $src2))>;
2814  def : Pat<(v4f32 (fma (v4f32 MQPR:$src1), (v4f32 MQPR:$src2), (v4f32 MQPR:$src3))),
2815            (v4f32 (MVE_VFMAf32 $src3, $src1, $src2))>;
2816  def : Pat<(v8f16 (fma (fneg (v8f16 MQPR:$src1)), (v8f16 MQPR:$src2), (v8f16 MQPR:$src3))),
2817            (v8f16 (MVE_VFMSf16 $src3, $src1, $src2))>;
2818  def : Pat<(v4f32 (fma (fneg (v4f32 MQPR:$src1)), (v4f32 MQPR:$src2), (v4f32 MQPR:$src3))),
2819            (v4f32 (MVE_VFMSf32 $src3, $src1, $src2))>;
2820}
2821
2822multiclass MVE_VADDSUB_fp_m<string iname, bit bit_21, MVEVectorVTInfo VTI,
2823                            SDNode unpred_op, Intrinsic pred_int> {
2824  def "" : MVE_VADDSUBFMA_fp<iname, VTI.Suffix, VTI.Size{0}, 0, 1, bit_21> {
2825    let validForTailPredication = 1;
2826  }
2827
2828  let Predicates = [HasMVEFloat] in {
2829    def : Pat<(VTI.Vec (unpred_op (VTI.Vec MQPR:$Qm), (VTI.Vec MQPR:$Qn))),
2830              (VTI.Vec (!cast<Instruction>(NAME)
2831                            (VTI.Vec MQPR:$Qm), (VTI.Vec MQPR:$Qn)))>;
2832    def : Pat<(VTI.Vec (pred_int (VTI.Vec MQPR:$Qm), (VTI.Vec MQPR:$Qn),
2833                            (VTI.Pred VCCR:$mask), (VTI.Vec MQPR:$inactive))),
2834              (VTI.Vec (!cast<Instruction>(NAME)
2835                            (VTI.Vec MQPR:$Qm), (VTI.Vec MQPR:$Qn),
2836                            (i32 1), (VTI.Pred VCCR:$mask),
2837                            (VTI.Vec MQPR:$inactive)))>;
2838  }
2839}
2840
2841multiclass MVE_VADD_fp_m<MVEVectorVTInfo VTI>
2842  : MVE_VADDSUB_fp_m<"vadd", 0, VTI, fadd, int_arm_mve_add_predicated>;
2843multiclass MVE_VSUB_fp_m<MVEVectorVTInfo VTI>
2844  : MVE_VADDSUB_fp_m<"vsub", 1, VTI, fsub, int_arm_mve_sub_predicated>;
2845
2846defm MVE_VADDf32 : MVE_VADD_fp_m<MVE_v4f32>;
2847defm MVE_VADDf16 : MVE_VADD_fp_m<MVE_v8f16>;
2848
2849defm MVE_VSUBf32 : MVE_VSUB_fp_m<MVE_v4f32>;
2850defm MVE_VSUBf16 : MVE_VSUB_fp_m<MVE_v8f16>;
2851
2852class MVE_VCADD<string suffix, bit size, string cstr="", list<dag> pattern=[]>
2853  : MVEFloatArithNeon<"vcadd", suffix, size, (outs MQPR:$Qd),
2854                         (ins MQPR:$Qn, MQPR:$Qm, complexrotateopodd:$rot),
2855                         "$Qd, $Qn, $Qm, $rot", vpred_r, cstr, pattern> {
2856  bits<4> Qd;
2857  bits<4> Qn;
2858  bit rot;
2859
2860  let Inst{28} = 0b1;
2861  let Inst{25} = 0b0;
2862  let Inst{24} = rot;
2863  let Inst{23} = 0b1;
2864  let Inst{22} = Qd{3};
2865  let Inst{21} = 0b0;
2866  let Inst{19-17} = Qn{2-0};
2867  let Inst{15-13} = Qd{2-0};
2868  let Inst{12-8} = 0b01000;
2869  let Inst{7} = Qn{3};
2870  let Inst{4} = 0b0;
2871}
2872
2873def MVE_VCADDf16 : MVE_VCADD<"f16", 0b0>;
2874def MVE_VCADDf32 : MVE_VCADD<"f32", 0b1, "@earlyclobber $Qd">;
2875
2876class MVE_VABD_fp<string suffix, bit size>
2877  : MVE_float<"vabd", suffix, (outs MQPR:$Qd), (ins MQPR:$Qn, MQPR:$Qm),
2878              "$Qd, $Qn, $Qm", vpred_r, ""> {
2879  bits<4> Qd;
2880  bits<4> Qn;
2881
2882  let Inst{28} = 0b1;
2883  let Inst{25-23} = 0b110;
2884  let Inst{22} = Qd{3};
2885  let Inst{21} = 0b1;
2886  let Inst{20} = size;
2887  let Inst{19-17} = Qn{2-0};
2888  let Inst{16} = 0b0;
2889  let Inst{15-13} = Qd{2-0};
2890  let Inst{11-8} = 0b1101;
2891  let Inst{7} = Qn{3};
2892  let Inst{4} = 0b0;
2893  let validForTailPredication = 1;
2894}
2895
2896def MVE_VABDf32 : MVE_VABD_fp<"f32", 0b0>;
2897def MVE_VABDf16 : MVE_VABD_fp<"f16", 0b1>;
2898
2899class MVE_VCVT_fix<string suffix, bit fsi, bit U, bit op,
2900                   Operand imm_operand_type, list<dag> pattern=[]>
2901  : MVE_float<"vcvt", suffix,
2902              (outs MQPR:$Qd), (ins MQPR:$Qm, imm_operand_type:$imm6),
2903              "$Qd, $Qm, $imm6", vpred_r, "", pattern> {
2904  bits<4> Qd;
2905  bits<6> imm6;
2906
2907  let Inst{28} = U;
2908  let Inst{25-23} = 0b111;
2909  let Inst{22} = Qd{3};
2910  let Inst{21} = 0b1;
2911  let Inst{19-16} = imm6{3-0};
2912  let Inst{15-13} = Qd{2-0};
2913  let Inst{11-10} = 0b11;
2914  let Inst{9} = fsi;
2915  let Inst{8} = op;
2916  let Inst{7} = 0b0;
2917  let Inst{4} = 0b1;
2918
2919  let DecoderMethod = "DecodeMVEVCVTt1fp";
2920  let validForTailPredication = 1;
2921}
2922
2923class MVE_VCVT_imm_asmop<int Bits> : AsmOperandClass {
2924  let PredicateMethod = "isImmediate<1," # Bits # ">";
2925  let DiagnosticString =
2926      "MVE fixed-point immediate operand must be between 1 and " # Bits;
2927  let Name = "MVEVcvtImm" # Bits;
2928  let RenderMethod = "addImmOperands";
2929}
2930class MVE_VCVT_imm<int Bits>: Operand<i32> {
2931  let ParserMatchClass = MVE_VCVT_imm_asmop<Bits>;
2932  let EncoderMethod = "getNEONVcvtImm32OpValue";
2933  let DecoderMethod = "DecodeVCVTImmOperand";
2934}
2935
2936class MVE_VCVT_fix_f32<string suffix, bit U, bit op>
2937    : MVE_VCVT_fix<suffix, 0b1, U, op, MVE_VCVT_imm<32>> {
2938  let Inst{20} = imm6{4};
2939}
2940class MVE_VCVT_fix_f16<string suffix, bit U, bit op>
2941    : MVE_VCVT_fix<suffix, 0b0, U, op, MVE_VCVT_imm<16>> {
2942  let Inst{20} = 0b1;
2943}
2944
2945def MVE_VCVTf16s16_fix : MVE_VCVT_fix_f16<"f16.s16", 0b0, 0b0>;
2946def MVE_VCVTs16f16_fix : MVE_VCVT_fix_f16<"s16.f16", 0b0, 0b1>;
2947def MVE_VCVTf16u16_fix : MVE_VCVT_fix_f16<"f16.u16", 0b1, 0b0>;
2948def MVE_VCVTu16f16_fix : MVE_VCVT_fix_f16<"u16.f16", 0b1, 0b1>;
2949def MVE_VCVTf32s32_fix : MVE_VCVT_fix_f32<"f32.s32", 0b0, 0b0>;
2950def MVE_VCVTs32f32_fix : MVE_VCVT_fix_f32<"s32.f32", 0b0, 0b1>;
2951def MVE_VCVTf32u32_fix : MVE_VCVT_fix_f32<"f32.u32", 0b1, 0b0>;
2952def MVE_VCVTu32f32_fix : MVE_VCVT_fix_f32<"u32.f32", 0b1, 0b1>;
2953
2954class MVE_VCVT_fp_int_anpm<string suffix, bits<2> size, bit op, string anpm,
2955                bits<2> rm, list<dag> pattern=[]>
2956  : MVE_float<!strconcat("vcvt", anpm), suffix, (outs MQPR:$Qd),
2957              (ins MQPR:$Qm), "$Qd, $Qm", vpred_r, "", pattern> {
2958  bits<4> Qd;
2959
2960  let Inst{28} = 0b1;
2961  let Inst{25-23} = 0b111;
2962  let Inst{22} = Qd{3};
2963  let Inst{21-20} = 0b11;
2964  let Inst{19-18} = size;
2965  let Inst{17-16} = 0b11;
2966  let Inst{15-13} = Qd{2-0};
2967  let Inst{12-10} = 0b000;
2968  let Inst{9-8} = rm;
2969  let Inst{7} = op;
2970  let Inst{4} = 0b0;
2971  let validForTailPredication = 1;
2972}
2973
2974multiclass MVE_VCVT_fp_int_anpm_multi<string suffix, bits<2> size, bit op,
2975                                list<dag> pattern=[]> {
2976  def a : MVE_VCVT_fp_int_anpm<suffix, size, op, "a", 0b00>;
2977  def n : MVE_VCVT_fp_int_anpm<suffix, size, op, "n", 0b01>;
2978  def p : MVE_VCVT_fp_int_anpm<suffix, size, op, "p", 0b10>;
2979  def m : MVE_VCVT_fp_int_anpm<suffix, size, op, "m", 0b11>;
2980}
2981
2982// This defines instructions such as MVE_VCVTu16f16a, with an explicit
2983// rounding-mode suffix on the mnemonic. The class below will define
2984// the bare MVE_VCVTu16f16 (with implied rounding toward zero).
2985defm MVE_VCVTs16f16 : MVE_VCVT_fp_int_anpm_multi<"s16.f16", 0b01, 0b0>;
2986defm MVE_VCVTu16f16 : MVE_VCVT_fp_int_anpm_multi<"u16.f16", 0b01, 0b1>;
2987defm MVE_VCVTs32f32 : MVE_VCVT_fp_int_anpm_multi<"s32.f32", 0b10, 0b0>;
2988defm MVE_VCVTu32f32 : MVE_VCVT_fp_int_anpm_multi<"u32.f32", 0b10, 0b1>;
2989
2990class MVE_VCVT_fp_int<string suffix, bits<2> size, bits<2> op,
2991                      list<dag> pattern=[]>
2992  : MVE_float<"vcvt", suffix, (outs MQPR:$Qd),
2993              (ins MQPR:$Qm), "$Qd, $Qm", vpred_r, "", pattern> {
2994  bits<4> Qd;
2995
2996  let Inst{28} = 0b1;
2997  let Inst{25-23} = 0b111;
2998  let Inst{22} = Qd{3};
2999  let Inst{21-20} = 0b11;
3000  let Inst{19-18} = size;
3001  let Inst{17-16} = 0b11;
3002  let Inst{15-13} = Qd{2-0};
3003  let Inst{12-9} = 0b0011;
3004  let Inst{8-7} = op;
3005  let Inst{4} = 0b0;
3006  let validForTailPredication = 1;
3007}
3008
3009// The unsuffixed VCVT for float->int implicitly rounds toward zero,
3010// which I reflect here in the llvm instruction names
3011def MVE_VCVTs16f16z : MVE_VCVT_fp_int<"s16.f16", 0b01, 0b10>;
3012def MVE_VCVTu16f16z : MVE_VCVT_fp_int<"u16.f16", 0b01, 0b11>;
3013def MVE_VCVTs32f32z : MVE_VCVT_fp_int<"s32.f32", 0b10, 0b10>;
3014def MVE_VCVTu32f32z : MVE_VCVT_fp_int<"u32.f32", 0b10, 0b11>;
3015// Whereas VCVT for int->float rounds to nearest
3016def MVE_VCVTf16s16n : MVE_VCVT_fp_int<"f16.s16", 0b01, 0b00>;
3017def MVE_VCVTf16u16n : MVE_VCVT_fp_int<"f16.u16", 0b01, 0b01>;
3018def MVE_VCVTf32s32n : MVE_VCVT_fp_int<"f32.s32", 0b10, 0b00>;
3019def MVE_VCVTf32u32n : MVE_VCVT_fp_int<"f32.u32", 0b10, 0b01>;
3020
3021let Predicates = [HasMVEFloat] in {
3022  def : Pat<(v4i32 (fp_to_sint (v4f32 MQPR:$src))),
3023            (v4i32 (MVE_VCVTs32f32z (v4f32 MQPR:$src)))>;
3024  def : Pat<(v4i32 (fp_to_uint (v4f32 MQPR:$src))),
3025            (v4i32 (MVE_VCVTu32f32z (v4f32 MQPR:$src)))>;
3026  def : Pat<(v8i16 (fp_to_sint (v8f16 MQPR:$src))),
3027            (v8i16 (MVE_VCVTs16f16z (v8f16 MQPR:$src)))>;
3028  def : Pat<(v8i16 (fp_to_uint (v8f16 MQPR:$src))),
3029            (v8i16 (MVE_VCVTu16f16z (v8f16 MQPR:$src)))>;
3030  def : Pat<(v4f32 (sint_to_fp (v4i32 MQPR:$src))),
3031            (v4f32 (MVE_VCVTf32s32n (v4i32 MQPR:$src)))>;
3032  def : Pat<(v4f32 (uint_to_fp (v4i32 MQPR:$src))),
3033            (v4f32 (MVE_VCVTf32u32n (v4i32 MQPR:$src)))>;
3034  def : Pat<(v8f16 (sint_to_fp (v8i16 MQPR:$src))),
3035            (v8f16 (MVE_VCVTf16s16n (v8i16 MQPR:$src)))>;
3036  def : Pat<(v8f16 (uint_to_fp (v8i16 MQPR:$src))),
3037            (v8f16 (MVE_VCVTf16u16n (v8i16 MQPR:$src)))>;
3038}
3039
3040class MVE_VABSNEG_fp<string iname, string suffix, bits<2> size, bit negate,
3041                   list<dag> pattern=[]>
3042  : MVE_float<iname, suffix, (outs MQPR:$Qd),
3043              (ins MQPR:$Qm), "$Qd, $Qm", vpred_r, "", pattern> {
3044  bits<4> Qd;
3045
3046  let Inst{28} = 0b1;
3047  let Inst{25-23} = 0b111;
3048  let Inst{22} = Qd{3};
3049  let Inst{21-20} = 0b11;
3050  let Inst{19-18} = size;
3051  let Inst{17-16} = 0b01;
3052  let Inst{15-13} = Qd{2-0};
3053  let Inst{11-8} = 0b0111;
3054  let Inst{7} = negate;
3055  let Inst{4} = 0b0;
3056  let validForTailPredication = 1;
3057}
3058
3059def MVE_VABSf16 : MVE_VABSNEG_fp<"vabs", "f16", 0b01, 0b0>;
3060def MVE_VABSf32 : MVE_VABSNEG_fp<"vabs", "f32", 0b10, 0b0>;
3061
3062let Predicates = [HasMVEFloat] in {
3063  def : Pat<(v8f16 (fabs MQPR:$src)),
3064            (MVE_VABSf16 MQPR:$src)>;
3065  def : Pat<(v4f32 (fabs MQPR:$src)),
3066            (MVE_VABSf32 MQPR:$src)>;
3067}
3068
3069def MVE_VNEGf16 : MVE_VABSNEG_fp<"vneg", "f16", 0b01, 0b1>;
3070def MVE_VNEGf32 : MVE_VABSNEG_fp<"vneg", "f32", 0b10, 0b1>;
3071
3072let Predicates = [HasMVEFloat] in {
3073  def : Pat<(v8f16 (fneg MQPR:$src)),
3074            (MVE_VNEGf16 MQPR:$src)>;
3075  def : Pat<(v4f32 (fneg MQPR:$src)),
3076            (MVE_VNEGf32 MQPR:$src)>;
3077}
3078
3079class MVE_VMAXMINNMA<string iname, string suffix, bit size, bit bit_12,
3080                     list<dag> pattern=[]>
3081  : MVE_f<(outs MQPR:$Qd), (ins MQPR:$Qd_src, MQPR:$Qm),
3082          NoItinerary, iname, suffix, "$Qd, $Qm", vpred_n, "$Qd = $Qd_src",
3083          pattern> {
3084  bits<4> Qd;
3085  bits<4> Qm;
3086
3087  let Inst{28} = size;
3088  let Inst{25-23} = 0b100;
3089  let Inst{22} = Qd{3};
3090  let Inst{21-16} = 0b111111;
3091  let Inst{15-13} = Qd{2-0};
3092  let Inst{12} = bit_12;
3093  let Inst{11-6} = 0b111010;
3094  let Inst{5} = Qm{3};
3095  let Inst{4} = 0b0;
3096  let Inst{3-1} = Qm{2-0};
3097  let Inst{0} = 0b1;
3098}
3099
3100def MVE_VMAXNMAf32 : MVE_VMAXMINNMA<"vmaxnma", "f32", 0b0, 0b0>;
3101def MVE_VMAXNMAf16 : MVE_VMAXMINNMA<"vmaxnma", "f16", 0b1, 0b0>;
3102
3103def MVE_VMINNMAf32 : MVE_VMAXMINNMA<"vminnma", "f32", 0b0, 0b1>;
3104def MVE_VMINNMAf16 : MVE_VMAXMINNMA<"vminnma", "f16", 0b1, 0b1>;
3105
3106// end of MVE Floating Point instructions
3107
3108// start of MVE compares
3109
3110class MVE_VCMPqq<string suffix, bit bit_28, bits<2> bits_21_20,
3111                 VCMPPredicateOperand predtype, list<dag> pattern=[]>
3112  : MVE_p<(outs VCCR:$P0), (ins MQPR:$Qn, MQPR:$Qm, predtype:$fc),
3113           NoItinerary, "vcmp", suffix, "$fc, $Qn, $Qm", vpred_n, "", pattern> {
3114  // Base class for comparing two vector registers
3115  bits<3> fc;
3116  bits<4> Qn;
3117  bits<4> Qm;
3118
3119  let Inst{28} = bit_28;
3120  let Inst{25-22} = 0b1000;
3121  let Inst{21-20} = bits_21_20;
3122  let Inst{19-17} = Qn{2-0};
3123  let Inst{16-13} = 0b1000;
3124  let Inst{12} = fc{2};
3125  let Inst{11-8} = 0b1111;
3126  let Inst{7} = fc{0};
3127  let Inst{6} = 0b0;
3128  let Inst{5} = Qm{3};
3129  let Inst{4} = 0b0;
3130  let Inst{3-1} = Qm{2-0};
3131  let Inst{0} = fc{1};
3132
3133  let Constraints = "";
3134
3135  // We need a custom decoder method for these instructions because of
3136  // the output VCCR operand, which isn't encoded in the instruction
3137  // bits anywhere (there is only one choice for it) but has to be
3138  // included in the MC operands so that codegen will be able to track
3139  // its data flow between instructions, spill/reload it when
3140  // necessary, etc. There seems to be no way to get the Tablegen
3141  // decoder to emit an operand that isn't affected by any instruction
3142  // bit.
3143  let DecoderMethod = "DecodeMVEVCMP<false," # predtype.DecoderMethod # ">";
3144  let validForTailPredication = 1;
3145}
3146
3147class MVE_VCMPqqf<string suffix, bit size>
3148    : MVE_VCMPqq<suffix, size, 0b11, pred_basic_fp> {
3149  let Predicates = [HasMVEFloat];
3150}
3151
3152class MVE_VCMPqqi<string suffix, bits<2> size>
3153    : MVE_VCMPqq<suffix, 0b1, size, pred_basic_i> {
3154  let Inst{12} = 0b0;
3155  let Inst{0} = 0b0;
3156}
3157
3158class MVE_VCMPqqu<string suffix, bits<2> size>
3159    : MVE_VCMPqq<suffix, 0b1, size, pred_basic_u> {
3160  let Inst{12} = 0b0;
3161  let Inst{0} = 0b1;
3162}
3163
3164class MVE_VCMPqqs<string suffix, bits<2> size>
3165    : MVE_VCMPqq<suffix, 0b1, size, pred_basic_s> {
3166  let Inst{12} = 0b1;
3167}
3168
3169def MVE_VCMPf32 : MVE_VCMPqqf<"f32", 0b0>;
3170def MVE_VCMPf16 : MVE_VCMPqqf<"f16", 0b1>;
3171
3172def MVE_VCMPi8  : MVE_VCMPqqi<"i8",  0b00>;
3173def MVE_VCMPi16 : MVE_VCMPqqi<"i16", 0b01>;
3174def MVE_VCMPi32 : MVE_VCMPqqi<"i32", 0b10>;
3175
3176def MVE_VCMPu8  : MVE_VCMPqqu<"u8",  0b00>;
3177def MVE_VCMPu16 : MVE_VCMPqqu<"u16", 0b01>;
3178def MVE_VCMPu32 : MVE_VCMPqqu<"u32", 0b10>;
3179
3180def MVE_VCMPs8  : MVE_VCMPqqs<"s8",  0b00>;
3181def MVE_VCMPs16 : MVE_VCMPqqs<"s16", 0b01>;
3182def MVE_VCMPs32 : MVE_VCMPqqs<"s32", 0b10>;
3183
3184class MVE_VCMPqr<string suffix, bit bit_28, bits<2> bits_21_20,
3185                 VCMPPredicateOperand predtype, list<dag> pattern=[]>
3186  : MVE_p<(outs VCCR:$P0), (ins MQPR:$Qn, GPRwithZR:$Rm, predtype:$fc),
3187           NoItinerary, "vcmp", suffix, "$fc, $Qn, $Rm", vpred_n, "", pattern> {
3188  // Base class for comparing a vector register with a scalar
3189  bits<3> fc;
3190  bits<4> Qn;
3191  bits<4> Rm;
3192
3193  let Inst{28} = bit_28;
3194  let Inst{25-22} = 0b1000;
3195  let Inst{21-20} = bits_21_20;
3196  let Inst{19-17} = Qn{2-0};
3197  let Inst{16-13} = 0b1000;
3198  let Inst{12} = fc{2};
3199  let Inst{11-8} = 0b1111;
3200  let Inst{7} = fc{0};
3201  let Inst{6} = 0b1;
3202  let Inst{5} = fc{1};
3203  let Inst{4} = 0b0;
3204  let Inst{3-0} = Rm{3-0};
3205
3206  let Constraints = "";
3207  // Custom decoder method, for the same reason as MVE_VCMPqq
3208  let DecoderMethod = "DecodeMVEVCMP<true," # predtype.DecoderMethod # ">";
3209  let validForTailPredication = 1;
3210}
3211
3212class MVE_VCMPqrf<string suffix, bit size>
3213    : MVE_VCMPqr<suffix, size, 0b11, pred_basic_fp> {
3214  let Predicates = [HasMVEFloat];
3215}
3216
3217class MVE_VCMPqri<string suffix, bits<2> size>
3218    : MVE_VCMPqr<suffix, 0b1, size, pred_basic_i> {
3219  let Inst{12} = 0b0;
3220  let Inst{5} = 0b0;
3221}
3222
3223class MVE_VCMPqru<string suffix, bits<2> size>
3224    : MVE_VCMPqr<suffix, 0b1, size, pred_basic_u> {
3225  let Inst{12} = 0b0;
3226  let Inst{5} = 0b1;
3227}
3228
3229class MVE_VCMPqrs<string suffix, bits<2> size>
3230    : MVE_VCMPqr<suffix, 0b1, size, pred_basic_s> {
3231  let Inst{12} = 0b1;
3232}
3233
3234def MVE_VCMPf32r : MVE_VCMPqrf<"f32", 0b0>;
3235def MVE_VCMPf16r : MVE_VCMPqrf<"f16", 0b1>;
3236
3237def MVE_VCMPi8r  : MVE_VCMPqri<"i8",  0b00>;
3238def MVE_VCMPi16r : MVE_VCMPqri<"i16", 0b01>;
3239def MVE_VCMPi32r : MVE_VCMPqri<"i32", 0b10>;
3240
3241def MVE_VCMPu8r  : MVE_VCMPqru<"u8",  0b00>;
3242def MVE_VCMPu16r : MVE_VCMPqru<"u16", 0b01>;
3243def MVE_VCMPu32r : MVE_VCMPqru<"u32", 0b10>;
3244
3245def MVE_VCMPs8r  : MVE_VCMPqrs<"s8",  0b00>;
3246def MVE_VCMPs16r : MVE_VCMPqrs<"s16", 0b01>;
3247def MVE_VCMPs32r : MVE_VCMPqrs<"s32", 0b10>;
3248
3249multiclass unpred_vcmp_z<string suffix, int fc> {
3250  def i8  : Pat<(v16i1 (ARMvcmpz (v16i8 MQPR:$v1), (i32 fc))),
3251                (v16i1 (!cast<Instruction>("MVE_VCMP"#suffix#"8r") (v16i8 MQPR:$v1), ZR, fc))>;
3252  def i16 : Pat<(v8i1 (ARMvcmpz (v8i16 MQPR:$v1), (i32 fc))),
3253                (v8i1 (!cast<Instruction>("MVE_VCMP"#suffix#"16r") (v8i16 MQPR:$v1), ZR, fc))>;
3254  def i32 : Pat<(v4i1 (ARMvcmpz (v4i32 MQPR:$v1), (i32 fc))),
3255                (v4i1 (!cast<Instruction>("MVE_VCMP"#suffix#"32r") (v4i32 MQPR:$v1), ZR, fc))>;
3256
3257  def : Pat<(v16i1 (and (v16i1 VCCR:$p1), (v16i1 (ARMvcmpz (v16i8 MQPR:$v1), (i32 fc))))),
3258            (v16i1 (!cast<Instruction>("MVE_VCMP"#suffix#"8r") (v16i8 MQPR:$v1), ZR, fc, 1, VCCR:$p1))>;
3259  def : Pat<(v8i1 (and (v8i1 VCCR:$p1), (v8i1 (ARMvcmpz (v8i16 MQPR:$v1), (i32 fc))))),
3260            (v8i1 (!cast<Instruction>("MVE_VCMP"#suffix#"16r") (v8i16 MQPR:$v1), ZR, fc, 1, VCCR:$p1))>;
3261  def : Pat<(v4i1 (and (v4i1 VCCR:$p1), (v4i1 (ARMvcmpz (v4i32 MQPR:$v1), (i32 fc))))),
3262            (v4i1 (!cast<Instruction>("MVE_VCMP"#suffix#"32r") (v4i32 MQPR:$v1), ZR, fc, 1, VCCR:$p1))>;
3263}
3264
3265multiclass unpred_vcmp_r<string suffix, int fc> {
3266  def i8  : Pat<(v16i1 (ARMvcmp (v16i8 MQPR:$v1), (v16i8 MQPR:$v2), (i32 fc))),
3267                (v16i1 (!cast<Instruction>("MVE_VCMP"#suffix#"8") (v16i8 MQPR:$v1), (v16i8 MQPR:$v2), fc))>;
3268  def i16 : Pat<(v8i1 (ARMvcmp (v8i16 MQPR:$v1), (v8i16 MQPR:$v2), (i32 fc))),
3269                (v8i1 (!cast<Instruction>("MVE_VCMP"#suffix#"16") (v8i16 MQPR:$v1), (v8i16 MQPR:$v2), fc))>;
3270  def i32 : Pat<(v4i1 (ARMvcmp (v4i32 MQPR:$v1), (v4i32 MQPR:$v2), (i32 fc))),
3271                (v4i1 (!cast<Instruction>("MVE_VCMP"#suffix#"32") (v4i32 MQPR:$v1), (v4i32 MQPR:$v2), fc))>;
3272
3273  def i8r  : Pat<(v16i1 (ARMvcmp (v16i8 MQPR:$v1), (v16i8 (ARMvdup GPR:$v2)), (i32 fc))),
3274                 (v16i1 (!cast<Instruction>("MVE_VCMP"#suffix#"8r") (v16i8 MQPR:$v1), (i32 GPR:$v2), fc))>;
3275  def i16r : Pat<(v8i1 (ARMvcmp (v8i16 MQPR:$v1), (v8i16 (ARMvdup GPR:$v2)), (i32 fc))),
3276                 (v8i1 (!cast<Instruction>("MVE_VCMP"#suffix#"16r") (v8i16 MQPR:$v1), (i32 GPR:$v2), fc))>;
3277  def i32r : Pat<(v4i1 (ARMvcmp (v4i32 MQPR:$v1), (v4i32 (ARMvdup GPR:$v2)), (i32 fc))),
3278                 (v4i1 (!cast<Instruction>("MVE_VCMP"#suffix#"32r") (v4i32 MQPR:$v1), (i32 GPR:$v2), fc))>;
3279
3280  def : Pat<(v16i1 (and (v16i1 VCCR:$p1), (v16i1 (ARMvcmp (v16i8 MQPR:$v1), (v16i8 MQPR:$v2), (i32 fc))))),
3281            (v16i1 (!cast<Instruction>("MVE_VCMP"#suffix#"8") (v16i8 MQPR:$v1), (v16i8 MQPR:$v2), fc, 1, VCCR:$p1))>;
3282  def : Pat<(v8i1 (and (v8i1 VCCR:$p1), (v8i1 (ARMvcmp (v8i16 MQPR:$v1), (v8i16 MQPR:$v2), (i32 fc))))),
3283            (v8i1 (!cast<Instruction>("MVE_VCMP"#suffix#"16") (v8i16 MQPR:$v1), (v8i16 MQPR:$v2), fc, 1, VCCR:$p1))>;
3284  def : Pat<(v4i1 (and (v4i1 VCCR:$p1), (v4i1 (ARMvcmp (v4i32 MQPR:$v1), (v4i32 MQPR:$v2), (i32 fc))))),
3285            (v4i1 (!cast<Instruction>("MVE_VCMP"#suffix#"32") (v4i32 MQPR:$v1), (v4i32 MQPR:$v2), fc, 1, VCCR:$p1))>;
3286
3287  def : Pat<(v16i1 (and (v16i1 VCCR:$p1), (v16i1 (ARMvcmp (v16i8 MQPR:$v1), (v16i8 (ARMvdup GPR:$v2)), (i32 fc))))),
3288            (v16i1 (!cast<Instruction>("MVE_VCMP"#suffix#"8r") (v16i8 MQPR:$v1), (i32 GPR:$v2), fc, 1, VCCR:$p1))>;
3289  def : Pat<(v8i1 (and (v8i1 VCCR:$p1), (v8i1 (ARMvcmp (v8i16 MQPR:$v1), (v8i16 (ARMvdup GPR:$v2)), (i32 fc))))),
3290            (v8i1 (!cast<Instruction>("MVE_VCMP"#suffix#"16r") (v8i16 MQPR:$v1), (i32 GPR:$v2), fc, 1, VCCR:$p1))>;
3291  def : Pat<(v4i1 (and (v4i1 VCCR:$p1), (v4i1 (ARMvcmp (v4i32 MQPR:$v1), (v4i32 (ARMvdup GPR:$v2)), (i32 fc))))),
3292            (v4i1 (!cast<Instruction>("MVE_VCMP"#suffix#"32r") (v4i32 MQPR:$v1), (i32 GPR:$v2), fc, 1, VCCR:$p1))>;
3293}
3294
3295multiclass unpred_vcmpf_z<int fc> {
3296  def f16 : Pat<(v8i1 (ARMvcmpz (v8f16 MQPR:$v1), (i32 fc))),
3297                (v8i1 (MVE_VCMPf16r (v8f16 MQPR:$v1), ZR, fc))>;
3298  def f32 : Pat<(v4i1 (ARMvcmpz (v4f32 MQPR:$v1), (i32 fc))),
3299                (v4i1 (MVE_VCMPf32r (v4f32 MQPR:$v1), ZR, fc))>;
3300
3301  def : Pat<(v8i1 (and (v8i1 VCCR:$p1), (v8i1 (ARMvcmpz (v8f16 MQPR:$v1), (i32 fc))))),
3302            (v8i1 (MVE_VCMPf32r (v8f16 MQPR:$v1), ZR, fc, 1, VCCR:$p1))>;
3303  def : Pat<(v4i1 (and (v4i1 VCCR:$p1), (v4i1 (ARMvcmpz (v4f32 MQPR:$v1), (i32 fc))))),
3304            (v4i1 (MVE_VCMPf32r (v4f32 MQPR:$v1), ZR, fc, 1, VCCR:$p1))>;
3305}
3306
3307multiclass unpred_vcmpf_r<int fc> {
3308  def f16 : Pat<(v8i1 (ARMvcmp (v8f16 MQPR:$v1), (v8f16 MQPR:$v2), (i32 fc))),
3309                (v8i1 (MVE_VCMPf16 (v8f16 MQPR:$v1), (v8f16 MQPR:$v2), fc))>;
3310  def f32 : Pat<(v4i1 (ARMvcmp (v4f32 MQPR:$v1), (v4f32 MQPR:$v2), (i32 fc))),
3311                (v4i1 (MVE_VCMPf32 (v4f32 MQPR:$v1), (v4f32 MQPR:$v2), fc))>;
3312
3313  def f16r : Pat<(v8i1 (ARMvcmp (v8f16 MQPR:$v1), (v8f16 (ARMvdup HPR:$v2)), (i32 fc))),
3314                 (v8i1 (MVE_VCMPf16r (v8f16 MQPR:$v1), (i32 (COPY_TO_REGCLASS (f16 HPR:$v2), rGPR)), fc))>;
3315  def f32r : Pat<(v4i1 (ARMvcmp (v4f32 MQPR:$v1), (v4f32 (ARMvdup SPR:$v2)), (i32 fc))),
3316                 (v4i1 (MVE_VCMPf32r (v4f32 MQPR:$v1), (i32 (COPY_TO_REGCLASS (f32 SPR:$v2), rGPR)), fc))>;
3317
3318  def : Pat<(v8i1 (and (v8i1 VCCR:$p1), (v8i1 (ARMvcmp (v8f16 MQPR:$v1), (v8f16 MQPR:$v2), (i32 fc))))),
3319            (v8i1 (MVE_VCMPf16 (v8f16 MQPR:$v1), (v8f16 MQPR:$v2), fc, 1, VCCR:$p1))>;
3320  def : Pat<(v4i1 (and (v4i1 VCCR:$p1), (v4i1 (ARMvcmp (v4f32 MQPR:$v1), (v4f32 MQPR:$v2), (i32 fc))))),
3321            (v4i1 (MVE_VCMPf32 (v4f32 MQPR:$v1), (v4f32 MQPR:$v2), fc, 1, VCCR:$p1))>;
3322
3323  def : Pat<(v8i1 (and (v8i1 VCCR:$p1), (v8i1 (ARMvcmp (v8f16 MQPR:$v1), (v8f16 (ARMvdup HPR:$v2)), (i32 fc))))),
3324            (v8i1 (MVE_VCMPf16r (v8f16 MQPR:$v1), (i32 (COPY_TO_REGCLASS (f16 HPR:$v2), rGPR)), fc, 1, VCCR:$p1))>;
3325  def : Pat<(v4i1 (and (v4i1 VCCR:$p1), (v4i1 (ARMvcmp (v4f32 MQPR:$v1), (v4f32 (ARMvdup SPR:$v2)), (i32 fc))))),
3326            (v4i1 (MVE_VCMPf32r (v4f32 MQPR:$v1), (i32 (COPY_TO_REGCLASS (f32 SPR:$v2), rGPR)), fc, 1, VCCR:$p1))>;
3327}
3328
3329let Predicates = [HasMVEInt] in {
3330  defm MVE_VCEQZ  : unpred_vcmp_z<"i", 0>;
3331  defm MVE_VCNEZ  : unpred_vcmp_z<"i", 1>;
3332  defm MVE_VCGEZ  : unpred_vcmp_z<"s", 10>;
3333  defm MVE_VCLTZ  : unpred_vcmp_z<"s", 11>;
3334  defm MVE_VCGTZ  : unpred_vcmp_z<"s", 12>;
3335  defm MVE_VCLEZ  : unpred_vcmp_z<"s", 13>;
3336  defm MVE_VCGTUZ : unpred_vcmp_z<"u", 8>;
3337  defm MVE_VCGEUZ : unpred_vcmp_z<"u", 2>;
3338
3339  defm MVE_VCEQ   : unpred_vcmp_r<"i", 0>;
3340  defm MVE_VCNE   : unpred_vcmp_r<"i", 1>;
3341  defm MVE_VCGE   : unpred_vcmp_r<"s", 10>;
3342  defm MVE_VCLT   : unpred_vcmp_r<"s", 11>;
3343  defm MVE_VCGT   : unpred_vcmp_r<"s", 12>;
3344  defm MVE_VCLE   : unpred_vcmp_r<"s", 13>;
3345  defm MVE_VCGTU  : unpred_vcmp_r<"u", 8>;
3346  defm MVE_VCGEU  : unpred_vcmp_r<"u", 2>;
3347}
3348
3349let Predicates = [HasMVEFloat] in {
3350  defm MVE_VFCEQZ  : unpred_vcmpf_z<0>;
3351  defm MVE_VFCNEZ  : unpred_vcmpf_z<1>;
3352  defm MVE_VFCGEZ  : unpred_vcmpf_z<10>;
3353  defm MVE_VFCLTZ  : unpred_vcmpf_z<11>;
3354  defm MVE_VFCGTZ  : unpred_vcmpf_z<12>;
3355  defm MVE_VFCLEZ  : unpred_vcmpf_z<13>;
3356
3357  defm MVE_VFCEQ   : unpred_vcmpf_r<0>;
3358  defm MVE_VFCNE   : unpred_vcmpf_r<1>;
3359  defm MVE_VFCGE   : unpred_vcmpf_r<10>;
3360  defm MVE_VFCLT   : unpred_vcmpf_r<11>;
3361  defm MVE_VFCGT   : unpred_vcmpf_r<12>;
3362  defm MVE_VFCLE   : unpred_vcmpf_r<13>;
3363}
3364
3365
3366// Extra "worst case" and/or/xor partterns, going into and out of GRP
3367multiclass two_predops<SDPatternOperator opnode, Instruction insn> {
3368  def v16i1 : Pat<(v16i1 (opnode (v16i1 VCCR:$p1), (v16i1 VCCR:$p2))),
3369                  (v16i1 (COPY_TO_REGCLASS
3370                           (insn (i32 (COPY_TO_REGCLASS (v16i1 VCCR:$p1), rGPR)),
3371                                 (i32 (COPY_TO_REGCLASS (v16i1 VCCR:$p2), rGPR))),
3372                           VCCR))>;
3373  def v8i1  : Pat<(v8i1 (opnode (v8i1 VCCR:$p1), (v8i1 VCCR:$p2))),
3374                  (v8i1 (COPY_TO_REGCLASS
3375                          (insn (i32 (COPY_TO_REGCLASS (v8i1 VCCR:$p1), rGPR)),
3376                                (i32 (COPY_TO_REGCLASS (v8i1 VCCR:$p2), rGPR))),
3377                          VCCR))>;
3378  def v4i1  : Pat<(v4i1 (opnode (v4i1 VCCR:$p1), (v4i1 VCCR:$p2))),
3379                  (v4i1 (COPY_TO_REGCLASS
3380                          (insn (i32 (COPY_TO_REGCLASS (v4i1 VCCR:$p1), rGPR)),
3381                                (i32 (COPY_TO_REGCLASS (v4i1 VCCR:$p2), rGPR))),
3382                          VCCR))>;
3383}
3384
3385let Predicates = [HasMVEInt] in {
3386  defm POR    : two_predops<or,  t2ORRrr>;
3387  defm PAND   : two_predops<and, t2ANDrr>;
3388  defm PEOR   : two_predops<xor, t2EORrr>;
3389}
3390
3391// Occasionally we need to cast between a i32 and a boolean vector, for
3392// example when moving between rGPR and VPR.P0 as part of predicate vector
3393// shuffles. We also sometimes need to cast between different predicate
3394// vector types (v4i1<>v8i1, etc.) also as part of lowering vector shuffles.
3395
3396def predicate_cast : SDNode<"ARMISD::PREDICATE_CAST", SDTUnaryOp>;
3397
3398let Predicates = [HasMVEInt] in {
3399  foreach VT = [ v4i1, v8i1, v16i1 ] in {
3400    def : Pat<(i32 (predicate_cast (VT VCCR:$src))),
3401              (i32 (COPY_TO_REGCLASS (VT VCCR:$src), VCCR))>;
3402    def : Pat<(VT  (predicate_cast (i32 VCCR:$src))),
3403              (VT  (COPY_TO_REGCLASS (i32 VCCR:$src), VCCR))>;
3404
3405    foreach VT2 = [ v4i1, v8i1, v16i1 ] in
3406      def : Pat<(VT  (predicate_cast (VT2 VCCR:$src))),
3407                (VT  (COPY_TO_REGCLASS (VT2 VCCR:$src), VCCR))>;
3408  }
3409}
3410
3411// end of MVE compares
3412
3413// start of MVE_qDest_qSrc
3414
3415class MVE_qDest_qSrc<string iname, string suffix, dag oops, dag iops,
3416                     string ops, vpred_ops vpred, string cstr,
3417                     list<dag> pattern=[]>
3418  : MVE_p<oops, iops, NoItinerary, iname, suffix,
3419          ops, vpred, cstr, pattern> {
3420  bits<4> Qd;
3421  bits<4> Qm;
3422
3423  let Inst{25-23} = 0b100;
3424  let Inst{22} = Qd{3};
3425  let Inst{15-13} = Qd{2-0};
3426  let Inst{11-9} = 0b111;
3427  let Inst{6} = 0b0;
3428  let Inst{5} = Qm{3};
3429  let Inst{4} = 0b0;
3430  let Inst{3-1} = Qm{2-0};
3431}
3432
3433class MVE_VQxDMLxDH<string iname, bit exch, bit round, bit subtract,
3434                    string suffix, bits<2> size, string cstr="", list<dag> pattern=[]>
3435  : MVE_qDest_qSrc<iname, suffix, (outs MQPR:$Qd),
3436                   (ins MQPR:$Qd_src, MQPR:$Qn, MQPR:$Qm), "$Qd, $Qn, $Qm",
3437                   vpred_n, "$Qd = $Qd_src"#cstr, pattern> {
3438  bits<4> Qn;
3439
3440  let Inst{28} = subtract;
3441  let Inst{21-20} = size;
3442  let Inst{19-17} = Qn{2-0};
3443  let Inst{16} = 0b0;
3444  let Inst{12} = exch;
3445  let Inst{8} = 0b0;
3446  let Inst{7} = Qn{3};
3447  let Inst{0} = round;
3448}
3449
3450multiclass MVE_VQxDMLxDH_multi<string iname, bit exch,
3451                               bit round, bit subtract> {
3452  def s8  : MVE_VQxDMLxDH<iname, exch, round, subtract, "s8",  0b00>;
3453  def s16 : MVE_VQxDMLxDH<iname, exch, round, subtract, "s16", 0b01>;
3454  def s32 : MVE_VQxDMLxDH<iname, exch, round, subtract, "s32", 0b10, ",@earlyclobber $Qd">;
3455}
3456
3457defm MVE_VQDMLADH   : MVE_VQxDMLxDH_multi<"vqdmladh",   0b0, 0b0, 0b0>;
3458defm MVE_VQDMLADHX  : MVE_VQxDMLxDH_multi<"vqdmladhx",  0b1, 0b0, 0b0>;
3459defm MVE_VQRDMLADH  : MVE_VQxDMLxDH_multi<"vqrdmladh",  0b0, 0b1, 0b0>;
3460defm MVE_VQRDMLADHX : MVE_VQxDMLxDH_multi<"vqrdmladhx", 0b1, 0b1, 0b0>;
3461defm MVE_VQDMLSDH   : MVE_VQxDMLxDH_multi<"vqdmlsdh",   0b0, 0b0, 0b1>;
3462defm MVE_VQDMLSDHX  : MVE_VQxDMLxDH_multi<"vqdmlsdhx",  0b1, 0b0, 0b1>;
3463defm MVE_VQRDMLSDH  : MVE_VQxDMLxDH_multi<"vqrdmlsdh",  0b0, 0b1, 0b1>;
3464defm MVE_VQRDMLSDHX : MVE_VQxDMLxDH_multi<"vqrdmlsdhx", 0b1, 0b1, 0b1>;
3465
3466class MVE_VCMUL<string iname, string suffix, bit size, string cstr="", list<dag> pattern=[]>
3467  : MVE_qDest_qSrc<iname, suffix, (outs MQPR:$Qd),
3468                   (ins MQPR:$Qn, MQPR:$Qm, complexrotateop:$rot),
3469                   "$Qd, $Qn, $Qm, $rot", vpred_r, cstr, pattern> {
3470  bits<4> Qn;
3471  bits<2> rot;
3472
3473  let Inst{28} = size;
3474  let Inst{21-20} = 0b11;
3475  let Inst{19-17} = Qn{2-0};
3476  let Inst{16} = 0b0;
3477  let Inst{12} = rot{1};
3478  let Inst{8} = 0b0;
3479  let Inst{7} = Qn{3};
3480  let Inst{0} = rot{0};
3481
3482  let Predicates = [HasMVEFloat];
3483}
3484
3485def MVE_VCMULf16 : MVE_VCMUL<"vcmul", "f16", 0b0>;
3486def MVE_VCMULf32 : MVE_VCMUL<"vcmul", "f32", 0b1, "@earlyclobber $Qd">;
3487
3488class MVE_VMULL<string iname, string suffix, bit bit_28, bits<2> bits_21_20,
3489                bit T, string cstr, list<dag> pattern=[]>
3490  : MVE_qDest_qSrc<iname, suffix, (outs MQPR:$Qd),
3491                   (ins MQPR:$Qn, MQPR:$Qm), "$Qd, $Qn, $Qm",
3492                   vpred_r, cstr, pattern> {
3493  bits<4> Qd;
3494  bits<4> Qn;
3495  bits<4> Qm;
3496
3497  let Inst{28} = bit_28;
3498  let Inst{21-20} = bits_21_20;
3499  let Inst{19-17} = Qn{2-0};
3500  let Inst{16} = 0b1;
3501  let Inst{12} = T;
3502  let Inst{8} = 0b0;
3503  let Inst{7} = Qn{3};
3504  let Inst{0} = 0b0;
3505}
3506
3507multiclass MVE_VMULL_multi<string iname, string suffix,
3508                           bit bit_28, bits<2> bits_21_20, string cstr=""> {
3509  def bh : MVE_VMULL<iname # "b", suffix, bit_28, bits_21_20, 0b0, cstr>;
3510  def th : MVE_VMULL<iname # "t", suffix, bit_28, bits_21_20, 0b1, cstr>;
3511}
3512
3513// For integer multiplies, bits 21:20 encode size, and bit 28 signedness.
3514// For polynomial multiplies, bits 21:20 take the unused value 0b11, and
3515// bit 28 switches to encoding the size.
3516
3517defm MVE_VMULLs8  : MVE_VMULL_multi<"vmull", "s8",  0b0, 0b00>;
3518defm MVE_VMULLs16 : MVE_VMULL_multi<"vmull", "s16", 0b0, 0b01>;
3519defm MVE_VMULLs32 : MVE_VMULL_multi<"vmull", "s32", 0b0, 0b10, "@earlyclobber $Qd">;
3520defm MVE_VMULLu8  : MVE_VMULL_multi<"vmull", "u8",  0b1, 0b00>;
3521defm MVE_VMULLu16 : MVE_VMULL_multi<"vmull", "u16", 0b1, 0b01>;
3522defm MVE_VMULLu32 : MVE_VMULL_multi<"vmull", "u32", 0b1, 0b10, "@earlyclobber $Qd">;
3523defm MVE_VMULLp8  : MVE_VMULL_multi<"vmull", "p8",  0b0, 0b11>;
3524defm MVE_VMULLp16 : MVE_VMULL_multi<"vmull", "p16", 0b1, 0b11>;
3525
3526class MVE_VxMULH<string iname, string suffix, bit U, bits<2> size,
3527                 bit round, list<dag> pattern=[]>
3528  : MVE_qDest_qSrc<iname, suffix, (outs MQPR:$Qd),
3529                   (ins MQPR:$Qn, MQPR:$Qm), "$Qd, $Qn, $Qm",
3530                   vpred_r, "", pattern> {
3531  bits<4> Qn;
3532
3533  let Inst{28} = U;
3534  let Inst{21-20} = size;
3535  let Inst{19-17} = Qn{2-0};
3536  let Inst{16} = 0b1;
3537  let Inst{12} = round;
3538  let Inst{8} = 0b0;
3539  let Inst{7} = Qn{3};
3540  let Inst{0} = 0b1;
3541}
3542
3543def MVE_VMULHs8   : MVE_VxMULH<"vmulh",  "s8",  0b0, 0b00, 0b0>;
3544def MVE_VMULHs16  : MVE_VxMULH<"vmulh",  "s16", 0b0, 0b01, 0b0>;
3545def MVE_VMULHs32  : MVE_VxMULH<"vmulh",  "s32", 0b0, 0b10, 0b0>;
3546def MVE_VMULHu8   : MVE_VxMULH<"vmulh",  "u8",  0b1, 0b00, 0b0>;
3547def MVE_VMULHu16  : MVE_VxMULH<"vmulh",  "u16", 0b1, 0b01, 0b0>;
3548def MVE_VMULHu32  : MVE_VxMULH<"vmulh",  "u32", 0b1, 0b10, 0b0>;
3549
3550def MVE_VRMULHs8  : MVE_VxMULH<"vrmulh", "s8",  0b0, 0b00, 0b1>;
3551def MVE_VRMULHs16 : MVE_VxMULH<"vrmulh", "s16", 0b0, 0b01, 0b1>;
3552def MVE_VRMULHs32 : MVE_VxMULH<"vrmulh", "s32", 0b0, 0b10, 0b1>;
3553def MVE_VRMULHu8  : MVE_VxMULH<"vrmulh", "u8",  0b1, 0b00, 0b1>;
3554def MVE_VRMULHu16 : MVE_VxMULH<"vrmulh", "u16", 0b1, 0b01, 0b1>;
3555def MVE_VRMULHu32 : MVE_VxMULH<"vrmulh", "u32", 0b1, 0b10, 0b1>;
3556
3557class MVE_VxMOVxN<string iname, string suffix, bit bit_28, bit bit_17,
3558                  bits<2> size, bit T, list<dag> pattern=[]>
3559  : MVE_qDest_qSrc<iname, suffix, (outs MQPR:$Qd),
3560                   (ins MQPR:$Qd_src, MQPR:$Qm), "$Qd, $Qm",
3561                   vpred_n, "$Qd = $Qd_src", pattern> {
3562
3563  let Inst{28} = bit_28;
3564  let Inst{21-20} = 0b11;
3565  let Inst{19-18} = size;
3566  let Inst{17} = bit_17;
3567  let Inst{16} = 0b1;
3568  let Inst{12} = T;
3569  let Inst{8} = 0b0;
3570  let Inst{7} = !if(!eq(bit_17, 0), 1, 0);
3571  let Inst{0} = 0b1;
3572}
3573
3574multiclass MVE_VxMOVxN_halves<string iname, string suffix,
3575                              bit bit_28, bit bit_17, bits<2> size> {
3576  def bh : MVE_VxMOVxN<iname # "b", suffix, bit_28, bit_17, size, 0b0>;
3577  def th : MVE_VxMOVxN<iname # "t", suffix, bit_28, bit_17, size, 0b1>;
3578}
3579
3580defm MVE_VMOVNi16   : MVE_VxMOVxN_halves<"vmovn",   "i16", 0b1, 0b0, 0b00>;
3581defm MVE_VMOVNi32   : MVE_VxMOVxN_halves<"vmovn",   "i32", 0b1, 0b0, 0b01>;
3582defm MVE_VQMOVNs16  : MVE_VxMOVxN_halves<"vqmovn",  "s16", 0b0, 0b1, 0b00>;
3583defm MVE_VQMOVNs32  : MVE_VxMOVxN_halves<"vqmovn",  "s32", 0b0, 0b1, 0b01>;
3584defm MVE_VQMOVNu16  : MVE_VxMOVxN_halves<"vqmovn",  "u16", 0b1, 0b1, 0b00>;
3585defm MVE_VQMOVNu32  : MVE_VxMOVxN_halves<"vqmovn",  "u32", 0b1, 0b1, 0b01>;
3586defm MVE_VQMOVUNs16 : MVE_VxMOVxN_halves<"vqmovun", "s16", 0b0, 0b0, 0b00>;
3587defm MVE_VQMOVUNs32 : MVE_VxMOVxN_halves<"vqmovun", "s32", 0b0, 0b0, 0b01>;
3588
3589def MVEvmovn       : SDNode<"ARMISD::VMOVN", SDTARMVEXT>;
3590let Predicates = [HasMVEInt] in {
3591  def : Pat<(v8i16 (MVEvmovn (v8i16 MQPR:$Qd_src), (v8i16 MQPR:$Qm), (i32 0))),
3592            (v8i16 (MVE_VMOVNi32bh (v8i16 MQPR:$Qd_src), (v8i16 MQPR:$Qm)))>;
3593  def : Pat<(v8i16 (MVEvmovn (v8i16 MQPR:$Qd_src), (v8i16 MQPR:$Qm), (i32 1))),
3594            (v8i16 (MVE_VMOVNi32th (v8i16 MQPR:$Qd_src), (v8i16 MQPR:$Qm)))>;
3595  def : Pat<(v16i8 (MVEvmovn (v16i8 MQPR:$Qd_src), (v16i8 MQPR:$Qm), (i32 0))),
3596            (v16i8 (MVE_VMOVNi16bh (v16i8 MQPR:$Qd_src), (v16i8 MQPR:$Qm)))>;
3597  def : Pat<(v16i8 (MVEvmovn (v16i8 MQPR:$Qd_src), (v16i8 MQPR:$Qm), (i32 1))),
3598            (v16i8 (MVE_VMOVNi16th (v16i8 MQPR:$Qd_src), (v16i8 MQPR:$Qm)))>;
3599}
3600
3601class MVE_VCVT_ff<string iname, string suffix, bit op, bit T,
3602                  list<dag> pattern=[]>
3603  : MVE_qDest_qSrc<iname, suffix, (outs MQPR:$Qd), (ins MQPR:$Qd_src, MQPR:$Qm),
3604                   "$Qd, $Qm", vpred_n, "$Qd = $Qd_src", pattern> {
3605  let Inst{28} = op;
3606  let Inst{21-16} = 0b111111;
3607  let Inst{12} = T;
3608  let Inst{8-7} = 0b00;
3609  let Inst{0} = 0b1;
3610
3611  let Predicates = [HasMVEFloat];
3612}
3613
3614multiclass MVE_VCVT_f2h_m<string iname, int half> {
3615  def "": MVE_VCVT_ff<iname, "f16.f32", 0b0, half>;
3616
3617  let Predicates = [HasMVEFloat] in {
3618    def : Pat<(v8f16 (int_arm_mve_vcvt_narrow
3619                         (v8f16 MQPR:$Qd_src), (v4f32 MQPR:$Qm), (i32 half))),
3620              (v8f16 (!cast<Instruction>(NAME)
3621                         (v8f16 MQPR:$Qd_src), (v4f32 MQPR:$Qm)))>;
3622    def : Pat<(v8f16 (int_arm_mve_vcvt_narrow_predicated
3623                         (v8f16 MQPR:$Qd_src), (v4f32 MQPR:$Qm), (i32 half),
3624                         (v4i1 VCCR:$mask))),
3625              (v8f16 (!cast<Instruction>(NAME)
3626                         (v8f16 MQPR:$Qd_src), (v4f32 MQPR:$Qm),
3627                         (i32 1), (v4i1 VCCR:$mask)))>;
3628  }
3629}
3630
3631multiclass MVE_VCVT_h2f_m<string iname, int half> {
3632  def "": MVE_VCVT_ff<iname, "f32.f16", 0b1, half>;
3633}
3634
3635defm MVE_VCVTf16f32bh : MVE_VCVT_f2h_m<"vcvtb", 0b0>;
3636defm MVE_VCVTf16f32th : MVE_VCVT_f2h_m<"vcvtt", 0b1>;
3637defm MVE_VCVTf32f16bh : MVE_VCVT_h2f_m<"vcvtb", 0b0>;
3638defm MVE_VCVTf32f16th : MVE_VCVT_h2f_m<"vcvtt", 0b1>;
3639
3640class MVE_VxCADD<string iname, string suffix, bits<2> size, bit halve,
3641                 string cstr="", list<dag> pattern=[]>
3642  : MVE_qDest_qSrc<iname, suffix, (outs MQPR:$Qd),
3643                   (ins MQPR:$Qn, MQPR:$Qm, complexrotateopodd:$rot),
3644                   "$Qd, $Qn, $Qm, $rot", vpred_r, cstr, pattern> {
3645  bits<4> Qn;
3646  bit rot;
3647
3648  let Inst{28} = halve;
3649  let Inst{21-20} = size;
3650  let Inst{19-17} = Qn{2-0};
3651  let Inst{16} = 0b0;
3652  let Inst{12} = rot;
3653  let Inst{8} = 0b1;
3654  let Inst{7} = Qn{3};
3655  let Inst{0} = 0b0;
3656}
3657
3658def MVE_VCADDi8   : MVE_VxCADD<"vcadd", "i8", 0b00, 0b1>;
3659def MVE_VCADDi16  : MVE_VxCADD<"vcadd", "i16", 0b01, 0b1>;
3660def MVE_VCADDi32  : MVE_VxCADD<"vcadd", "i32", 0b10, 0b1, "@earlyclobber $Qd">;
3661
3662def MVE_VHCADDs8  : MVE_VxCADD<"vhcadd", "s8", 0b00, 0b0>;
3663def MVE_VHCADDs16 : MVE_VxCADD<"vhcadd", "s16", 0b01, 0b0>;
3664def MVE_VHCADDs32 : MVE_VxCADD<"vhcadd", "s32", 0b10, 0b0, "@earlyclobber $Qd">;
3665
3666class MVE_VADCSBC<string iname, bit I, bit subtract,
3667                  dag carryin, list<dag> pattern=[]>
3668  : MVE_qDest_qSrc<iname, "i32", (outs MQPR:$Qd, cl_FPSCR_NZCV:$carryout),
3669                   !con((ins MQPR:$Qn, MQPR:$Qm), carryin),
3670                   "$Qd, $Qn, $Qm", vpred_r, "", pattern> {
3671  bits<4> Qn;
3672
3673  let Inst{28} = subtract;
3674  let Inst{21-20} = 0b11;
3675  let Inst{19-17} = Qn{2-0};
3676  let Inst{16} = 0b0;
3677  let Inst{12} = I;
3678  let Inst{8} = 0b1;
3679  let Inst{7} = Qn{3};
3680  let Inst{0} = 0b0;
3681
3682  // Custom decoder method in order to add the FPSCR operand(s), which
3683  // Tablegen won't do right
3684  let DecoderMethod = "DecodeMVEVADCInstruction";
3685}
3686
3687def MVE_VADC  : MVE_VADCSBC<"vadc",  0b0, 0b0, (ins cl_FPSCR_NZCV:$carryin)>;
3688def MVE_VADCI : MVE_VADCSBC<"vadci", 0b1, 0b0, (ins)>;
3689
3690def MVE_VSBC  : MVE_VADCSBC<"vsbc",  0b0, 0b1, (ins cl_FPSCR_NZCV:$carryin)>;
3691def MVE_VSBCI : MVE_VADCSBC<"vsbci", 0b1, 0b1, (ins)>;
3692
3693class MVE_VQDMULL<string iname, string suffix, bit size, bit T,
3694                  string cstr="", list<dag> pattern=[]>
3695  : MVE_qDest_qSrc<iname, suffix, (outs MQPR:$Qd),
3696                   (ins MQPR:$Qn, MQPR:$Qm), "$Qd, $Qn, $Qm",
3697                   vpred_r, cstr, pattern> {
3698  bits<4> Qn;
3699
3700  let Inst{28} = size;
3701  let Inst{21-20} = 0b11;
3702  let Inst{19-17} = Qn{2-0};
3703  let Inst{16} = 0b0;
3704  let Inst{12} = T;
3705  let Inst{8} = 0b1;
3706  let Inst{7} = Qn{3};
3707  let Inst{0} = 0b1;
3708}
3709
3710multiclass MVE_VQDMULL_halves<string suffix, bit size, string cstr=""> {
3711  def bh : MVE_VQDMULL<"vqdmullb", suffix, size, 0b0, cstr>;
3712  def th : MVE_VQDMULL<"vqdmullt", suffix, size, 0b1, cstr>;
3713}
3714
3715defm MVE_VQDMULLs16 : MVE_VQDMULL_halves<"s16", 0b0>;
3716defm MVE_VQDMULLs32 : MVE_VQDMULL_halves<"s32", 0b1, "@earlyclobber $Qd">;
3717
3718// end of mve_qDest_qSrc
3719
3720// start of mve_qDest_rSrc
3721
3722class MVE_qr_base<dag oops, dag iops, InstrItinClass itin, string iname,
3723                  string suffix, string ops, vpred_ops vpred, string cstr,
3724                  list<dag> pattern=[]>
3725   : MVE_p<oops, iops, NoItinerary, iname, suffix, ops, vpred, cstr, pattern> {
3726  bits<4> Qd;
3727  bits<4> Qn;
3728  bits<4> Rm;
3729
3730  let Inst{25-23} = 0b100;
3731  let Inst{22} = Qd{3};
3732  let Inst{19-17} = Qn{2-0};
3733  let Inst{15-13} = Qd{2-0};
3734  let Inst{11-9} = 0b111;
3735  let Inst{7} = Qn{3};
3736  let Inst{6} = 0b1;
3737  let Inst{4} = 0b0;
3738  let Inst{3-0} = Rm{3-0};
3739}
3740
3741class MVE_qDest_rSrc<string iname, string suffix, string cstr="", list<dag> pattern=[]>
3742  : MVE_qr_base<(outs MQPR:$Qd), (ins MQPR:$Qn, rGPR:$Rm),
3743          NoItinerary, iname, suffix, "$Qd, $Qn, $Rm", vpred_r, cstr,
3744           pattern>;
3745
3746class MVE_qDestSrc_rSrc<string iname, string suffix, list<dag> pattern=[]>
3747  : MVE_qr_base<(outs MQPR:$Qd), (ins MQPR:$Qd_src, MQPR:$Qn, rGPR:$Rm),
3748          NoItinerary, iname, suffix, "$Qd, $Qn, $Rm", vpred_n, "$Qd = $Qd_src",
3749           pattern>;
3750
3751class MVE_qDest_single_rSrc<string iname, string suffix, list<dag> pattern=[]>
3752  : MVE_p<(outs MQPR:$Qd), (ins MQPR:$Qd_src, rGPR:$Rm), NoItinerary, iname,
3753          suffix, "$Qd, $Rm", vpred_n, "$Qd = $Qd_src", pattern> {
3754  bits<4> Qd;
3755  bits<4> Rm;
3756
3757  let Inst{22} = Qd{3};
3758  let Inst{15-13} = Qd{2-0};
3759  let Inst{3-0} = Rm{3-0};
3760}
3761
3762class MVE_VADDSUB_qr<string iname, string suffix, bits<2> size,
3763                     bit bit_5, bit bit_12, bit bit_16,
3764                     bit bit_28, list<dag> pattern=[]>
3765  : MVE_qDest_rSrc<iname, suffix, "", pattern> {
3766
3767  let Inst{28} = bit_28;
3768  let Inst{21-20} = size;
3769  let Inst{16} = bit_16;
3770  let Inst{12} = bit_12;
3771  let Inst{8} = 0b1;
3772  let Inst{5} = bit_5;
3773  let validForTailPredication = 1;
3774}
3775
3776multiclass MVE_VADDSUB_qr_sizes<string iname, string suffix,
3777                                bit bit_5, bit bit_12, bit bit_16,
3778                                bit bit_28, list<dag> pattern=[]> {
3779  def "8"  : MVE_VADDSUB_qr<iname, suffix#"8",  0b00,
3780                            bit_5, bit_12, bit_16, bit_28>;
3781  def "16" : MVE_VADDSUB_qr<iname, suffix#"16", 0b01,
3782                            bit_5, bit_12, bit_16, bit_28>;
3783  def "32" : MVE_VADDSUB_qr<iname, suffix#"32", 0b10,
3784                            bit_5, bit_12, bit_16, bit_28>;
3785}
3786
3787defm MVE_VADD_qr_i  : MVE_VADDSUB_qr_sizes<"vadd",  "i", 0b0, 0b0, 0b1, 0b0>;
3788defm MVE_VQADD_qr_s : MVE_VADDSUB_qr_sizes<"vqadd", "s", 0b1, 0b0, 0b0, 0b0>;
3789defm MVE_VQADD_qr_u : MVE_VADDSUB_qr_sizes<"vqadd", "u", 0b1, 0b0, 0b0, 0b1>;
3790
3791defm MVE_VSUB_qr_i  : MVE_VADDSUB_qr_sizes<"vsub",  "i", 0b0, 0b1, 0b1, 0b0>;
3792defm MVE_VQSUB_qr_s : MVE_VADDSUB_qr_sizes<"vqsub", "s", 0b1, 0b1, 0b0, 0b0>;
3793defm MVE_VQSUB_qr_u : MVE_VADDSUB_qr_sizes<"vqsub", "u", 0b1, 0b1, 0b0, 0b1>;
3794
3795let Predicates = [HasMVEInt] in {
3796  def : Pat<(v16i8 (add (v16i8 MQPR:$val1), (v16i8 (ARMvdup GPR:$val2)))),
3797            (v16i8 (MVE_VADD_qr_i8 (v16i8 MQPR:$val1), (i32 GPR:$val2)))>;
3798  def : Pat<(v8i16 (add (v8i16 MQPR:$val1), (v8i16 (ARMvdup GPR:$val2)))),
3799            (v8i16 (MVE_VADD_qr_i16 (v8i16 MQPR:$val1), (i32 GPR:$val2)))>;
3800  def : Pat<(v4i32 (add (v4i32 MQPR:$val1), (v4i32 (ARMvdup GPR:$val2)))),
3801            (v4i32 (MVE_VADD_qr_i32 (v4i32 MQPR:$val1), (i32 GPR:$val2)))>;
3802}
3803
3804let Predicates = [HasMVEInt] in {
3805  def : Pat<(v16i8 (sub (v16i8 MQPR:$val1), (v16i8 (ARMvdup GPR:$val2)))),
3806            (v16i8 (MVE_VSUB_qr_i8 (v16i8 MQPR:$val1), (i32 GPR:$val2)))>;
3807  def : Pat<(v8i16 (sub (v8i16 MQPR:$val1), (v8i16 (ARMvdup GPR:$val2)))),
3808            (v8i16 (MVE_VSUB_qr_i16 (v8i16 MQPR:$val1), (i32 GPR:$val2)))>;
3809  def : Pat<(v4i32 (sub (v4i32 MQPR:$val1), (v4i32 (ARMvdup GPR:$val2)))),
3810            (v4i32 (MVE_VSUB_qr_i32 (v4i32 MQPR:$val1), (i32 GPR:$val2)))>;
3811}
3812
3813class MVE_VQDMULL_qr<string iname, string suffix, bit size,
3814                     bit T, string cstr="", list<dag> pattern=[]>
3815  : MVE_qDest_rSrc<iname, suffix, cstr, pattern> {
3816
3817  let Inst{28} = size;
3818  let Inst{21-20} = 0b11;
3819  let Inst{16} = 0b0;
3820  let Inst{12} = T;
3821  let Inst{8} = 0b1;
3822  let Inst{5} = 0b1;
3823}
3824
3825multiclass MVE_VQDMULL_qr_halves<string suffix, bit size, string cstr=""> {
3826  def bh : MVE_VQDMULL_qr<"vqdmullb", suffix, size, 0b0, cstr>;
3827  def th : MVE_VQDMULL_qr<"vqdmullt", suffix, size, 0b1, cstr>;
3828}
3829
3830defm MVE_VQDMULL_qr_s16 : MVE_VQDMULL_qr_halves<"s16", 0b0>;
3831defm MVE_VQDMULL_qr_s32 : MVE_VQDMULL_qr_halves<"s32", 0b1, "@earlyclobber $Qd">;
3832
3833class MVE_VxADDSUB_qr<string iname, string suffix,
3834                      bit bit_28, bits<2> bits_21_20, bit subtract,
3835                      list<dag> pattern=[]>
3836  : MVE_qDest_rSrc<iname, suffix, "", pattern> {
3837
3838  let Inst{28} = bit_28;
3839  let Inst{21-20} = bits_21_20;
3840  let Inst{16} = 0b0;
3841  let Inst{12} = subtract;
3842  let Inst{8} = 0b1;
3843  let Inst{5} = 0b0;
3844  let validForTailPredication = 1;
3845}
3846
3847def MVE_VHADD_qr_s8   : MVE_VxADDSUB_qr<"vhadd", "s8",  0b0, 0b00, 0b0>;
3848def MVE_VHADD_qr_s16  : MVE_VxADDSUB_qr<"vhadd", "s16", 0b0, 0b01, 0b0>;
3849def MVE_VHADD_qr_s32  : MVE_VxADDSUB_qr<"vhadd", "s32", 0b0, 0b10, 0b0>;
3850def MVE_VHADD_qr_u8   : MVE_VxADDSUB_qr<"vhadd", "u8",  0b1, 0b00, 0b0>;
3851def MVE_VHADD_qr_u16  : MVE_VxADDSUB_qr<"vhadd", "u16", 0b1, 0b01, 0b0>;
3852def MVE_VHADD_qr_u32  : MVE_VxADDSUB_qr<"vhadd", "u32", 0b1, 0b10, 0b0>;
3853
3854def MVE_VHSUB_qr_s8   : MVE_VxADDSUB_qr<"vhsub", "s8",  0b0, 0b00, 0b1>;
3855def MVE_VHSUB_qr_s16  : MVE_VxADDSUB_qr<"vhsub", "s16", 0b0, 0b01, 0b1>;
3856def MVE_VHSUB_qr_s32  : MVE_VxADDSUB_qr<"vhsub", "s32", 0b0, 0b10, 0b1>;
3857def MVE_VHSUB_qr_u8   : MVE_VxADDSUB_qr<"vhsub", "u8",  0b1, 0b00, 0b1>;
3858def MVE_VHSUB_qr_u16  : MVE_VxADDSUB_qr<"vhsub", "u16", 0b1, 0b01, 0b1>;
3859def MVE_VHSUB_qr_u32  : MVE_VxADDSUB_qr<"vhsub", "u32", 0b1, 0b10, 0b1>;
3860
3861let Predicates = [HasMVEFloat] in {
3862  def MVE_VADD_qr_f32 : MVE_VxADDSUB_qr<"vadd",  "f32", 0b0, 0b11, 0b0>;
3863  def MVE_VADD_qr_f16 : MVE_VxADDSUB_qr<"vadd",  "f16", 0b1, 0b11, 0b0>;
3864
3865  def MVE_VSUB_qr_f32 : MVE_VxADDSUB_qr<"vsub",  "f32", 0b0, 0b11, 0b1>;
3866  def MVE_VSUB_qr_f16 : MVE_VxADDSUB_qr<"vsub",  "f16", 0b1, 0b11, 0b1>;
3867}
3868
3869class MVE_VxSHL_qr<string iname, string suffix, bit U, bits<2> size,
3870                   bit bit_7, bit bit_17, list<dag> pattern=[]>
3871  : MVE_qDest_single_rSrc<iname, suffix, pattern> {
3872
3873  let Inst{28} = U;
3874  let Inst{25-23} = 0b100;
3875  let Inst{21-20} = 0b11;
3876  let Inst{19-18} = size;
3877  let Inst{17} = bit_17;
3878  let Inst{16} = 0b1;
3879  let Inst{12-8} = 0b11110;
3880  let Inst{7} = bit_7;
3881  let Inst{6-4} = 0b110;
3882  let validForTailPredication = 1;
3883}
3884
3885multiclass MVE_VxSHL_qr_types<string iname, bit bit_7, bit bit_17> {
3886  def s8  : MVE_VxSHL_qr<iname, "s8", 0b0, 0b00, bit_7, bit_17>;
3887  def s16 : MVE_VxSHL_qr<iname, "s16", 0b0, 0b01, bit_7, bit_17>;
3888  def s32 : MVE_VxSHL_qr<iname, "s32", 0b0, 0b10, bit_7, bit_17>;
3889  def u8  : MVE_VxSHL_qr<iname, "u8", 0b1, 0b00, bit_7, bit_17>;
3890  def u16 : MVE_VxSHL_qr<iname, "u16", 0b1, 0b01, bit_7, bit_17>;
3891  def u32 : MVE_VxSHL_qr<iname, "u32", 0b1, 0b10, bit_7, bit_17>;
3892}
3893
3894defm MVE_VSHL_qr   : MVE_VxSHL_qr_types<"vshl",   0b0, 0b0>;
3895defm MVE_VRSHL_qr  : MVE_VxSHL_qr_types<"vrshl",  0b0, 0b1>;
3896defm MVE_VQSHL_qr  : MVE_VxSHL_qr_types<"vqshl",  0b1, 0b0>;
3897defm MVE_VQRSHL_qr : MVE_VxSHL_qr_types<"vqrshl", 0b1, 0b1>;
3898
3899let Predicates = [HasMVEInt] in {
3900  def : Pat<(v4i32 (ARMvshlu (v4i32 MQPR:$Qm), (v4i32 (ARMvdup GPR:$Rm)))),
3901            (v4i32 (MVE_VSHL_qru32 (v4i32 MQPR:$Qm), GPR:$Rm))>;
3902  def : Pat<(v8i16 (ARMvshlu (v8i16 MQPR:$Qm), (v8i16 (ARMvdup GPR:$Rm)))),
3903            (v8i16 (MVE_VSHL_qru16 (v8i16 MQPR:$Qm), GPR:$Rm))>;
3904  def : Pat<(v16i8 (ARMvshlu (v16i8 MQPR:$Qm), (v16i8 (ARMvdup GPR:$Rm)))),
3905            (v16i8 (MVE_VSHL_qru8 (v16i8 MQPR:$Qm), GPR:$Rm))>;
3906
3907  def : Pat<(v4i32 (ARMvshls (v4i32 MQPR:$Qm), (v4i32 (ARMvdup GPR:$Rm)))),
3908            (v4i32 (MVE_VSHL_qrs32 (v4i32 MQPR:$Qm), GPR:$Rm))>;
3909  def : Pat<(v8i16 (ARMvshls (v8i16 MQPR:$Qm), (v8i16 (ARMvdup GPR:$Rm)))),
3910            (v8i16 (MVE_VSHL_qrs16 (v8i16 MQPR:$Qm), GPR:$Rm))>;
3911  def : Pat<(v16i8 (ARMvshls (v16i8 MQPR:$Qm), (v16i8 (ARMvdup GPR:$Rm)))),
3912            (v16i8 (MVE_VSHL_qrs8 (v16i8 MQPR:$Qm), GPR:$Rm))>;
3913}
3914
3915class MVE_VBRSR<string iname, string suffix, bits<2> size, list<dag> pattern=[]>
3916  : MVE_qDest_rSrc<iname, suffix, "", pattern> {
3917
3918  let Inst{28} = 0b1;
3919  let Inst{21-20} = size;
3920  let Inst{16} = 0b1;
3921  let Inst{12} = 0b1;
3922  let Inst{8} = 0b0;
3923  let Inst{5} = 0b1;
3924  let validForTailPredication = 1;
3925}
3926
3927def MVE_VBRSR8  : MVE_VBRSR<"vbrsr", "8", 0b00>;
3928def MVE_VBRSR16 : MVE_VBRSR<"vbrsr", "16", 0b01>;
3929def MVE_VBRSR32 : MVE_VBRSR<"vbrsr", "32", 0b10>;
3930
3931let Predicates = [HasMVEInt] in {
3932  def : Pat<(v16i8 ( bitreverse (v16i8 MQPR:$val1))),
3933            (v16i8 ( MVE_VBRSR8 (v16i8 MQPR:$val1), (t2MOVi (i32 8)) ))>;
3934
3935  def : Pat<(v4i32 ( bitreverse (v4i32 MQPR:$val1))),
3936            (v4i32 ( MVE_VBRSR32 (v4i32 MQPR:$val1), (t2MOVi (i32 32)) ))>;
3937
3938  def : Pat<(v8i16 ( bitreverse (v8i16 MQPR:$val1))),
3939            (v8i16 ( MVE_VBRSR16 (v8i16 MQPR:$val1), (t2MOVi (i32 16)) ))>;
3940}
3941
3942class MVE_VMUL_qr_int<string iname, string suffix,
3943                      bits<2> size, list<dag> pattern=[]>
3944  : MVE_qDest_rSrc<iname, suffix, "", pattern> {
3945
3946  let Inst{28} = 0b0;
3947  let Inst{21-20} = size;
3948  let Inst{16} = 0b1;
3949  let Inst{12} = 0b1;
3950  let Inst{8} = 0b0;
3951  let Inst{5} = 0b1;
3952  let validForTailPredication = 1;
3953}
3954
3955def MVE_VMUL_qr_i8  : MVE_VMUL_qr_int<"vmul", "i8",  0b00>;
3956def MVE_VMUL_qr_i16 : MVE_VMUL_qr_int<"vmul", "i16", 0b01>;
3957def MVE_VMUL_qr_i32 : MVE_VMUL_qr_int<"vmul", "i32", 0b10>;
3958
3959let Predicates = [HasMVEInt] in {
3960  def : Pat<(v16i8 (mul (v16i8 MQPR:$val1), (v16i8 (ARMvdup GPR:$val2)))),
3961            (v16i8 (MVE_VMUL_qr_i8 (v16i8 MQPR:$val1), (i32 GPR:$val2)))>;
3962  def : Pat<(v8i16 (mul (v8i16 MQPR:$val1), (v8i16 (ARMvdup GPR:$val2)))),
3963            (v8i16 (MVE_VMUL_qr_i16 (v8i16 MQPR:$val1), (i32 GPR:$val2)))>;
3964  def : Pat<(v4i32 (mul (v4i32 MQPR:$val1), (v4i32 (ARMvdup GPR:$val2)))),
3965            (v4i32 (MVE_VMUL_qr_i32 (v4i32 MQPR:$val1), (i32 GPR:$val2)))>;
3966}
3967
3968class MVE_VxxMUL_qr<string iname, string suffix,
3969                    bit bit_28, bits<2> bits_21_20, list<dag> pattern=[]>
3970  : MVE_qDest_rSrc<iname, suffix, "", pattern> {
3971
3972  let Inst{28} = bit_28;
3973  let Inst{21-20} = bits_21_20;
3974  let Inst{16} = 0b1;
3975  let Inst{12} = 0b0;
3976  let Inst{8} = 0b0;
3977  let Inst{5} = 0b1;
3978}
3979
3980def MVE_VQDMULH_qr_s8   : MVE_VxxMUL_qr<"vqdmulh",  "s8",  0b0, 0b00>;
3981def MVE_VQDMULH_qr_s16  : MVE_VxxMUL_qr<"vqdmulh",  "s16", 0b0, 0b01>;
3982def MVE_VQDMULH_qr_s32  : MVE_VxxMUL_qr<"vqdmulh",  "s32", 0b0, 0b10>;
3983
3984def MVE_VQRDMULH_qr_s8  : MVE_VxxMUL_qr<"vqrdmulh", "s8",  0b1, 0b00>;
3985def MVE_VQRDMULH_qr_s16 : MVE_VxxMUL_qr<"vqrdmulh", "s16", 0b1, 0b01>;
3986def MVE_VQRDMULH_qr_s32 : MVE_VxxMUL_qr<"vqrdmulh", "s32", 0b1, 0b10>;
3987
3988let Predicates = [HasMVEFloat], validForTailPredication = 1 in {
3989  def MVE_VMUL_qr_f16   : MVE_VxxMUL_qr<"vmul", "f16", 0b1, 0b11>;
3990  def MVE_VMUL_qr_f32   : MVE_VxxMUL_qr<"vmul", "f32", 0b0, 0b11>;
3991}
3992
3993class MVE_VFMAMLA_qr<string iname, string suffix,
3994                     bit bit_28, bits<2> bits_21_20, bit S,
3995                     list<dag> pattern=[]>
3996  : MVE_qDestSrc_rSrc<iname, suffix, pattern> {
3997
3998  let Inst{28} = bit_28;
3999  let Inst{21-20} = bits_21_20;
4000  let Inst{16} = 0b1;
4001  let Inst{12} = S;
4002  let Inst{8} = 0b0;
4003  let Inst{5} = 0b0;
4004  let validForTailPredication = 1;
4005}
4006
4007def MVE_VMLA_qr_s8     : MVE_VFMAMLA_qr<"vmla",  "s8",  0b0, 0b00, 0b0>;
4008def MVE_VMLA_qr_s16    : MVE_VFMAMLA_qr<"vmla",  "s16", 0b0, 0b01, 0b0>;
4009def MVE_VMLA_qr_s32    : MVE_VFMAMLA_qr<"vmla",  "s32", 0b0, 0b10, 0b0>;
4010def MVE_VMLA_qr_u8     : MVE_VFMAMLA_qr<"vmla",  "u8",  0b1, 0b00, 0b0>;
4011def MVE_VMLA_qr_u16    : MVE_VFMAMLA_qr<"vmla",  "u16", 0b1, 0b01, 0b0>;
4012def MVE_VMLA_qr_u32    : MVE_VFMAMLA_qr<"vmla",  "u32", 0b1, 0b10, 0b0>;
4013
4014def MVE_VMLAS_qr_s8    : MVE_VFMAMLA_qr<"vmlas", "s8",  0b0, 0b00, 0b1>;
4015def MVE_VMLAS_qr_s16   : MVE_VFMAMLA_qr<"vmlas", "s16", 0b0, 0b01, 0b1>;
4016def MVE_VMLAS_qr_s32   : MVE_VFMAMLA_qr<"vmlas", "s32", 0b0, 0b10, 0b1>;
4017def MVE_VMLAS_qr_u8    : MVE_VFMAMLA_qr<"vmlas", "u8",  0b1, 0b00, 0b1>;
4018def MVE_VMLAS_qr_u16   : MVE_VFMAMLA_qr<"vmlas", "u16", 0b1, 0b01, 0b1>;
4019def MVE_VMLAS_qr_u32   : MVE_VFMAMLA_qr<"vmlas", "u32", 0b1, 0b10, 0b1>;
4020
4021let Predicates = [HasMVEInt] in {
4022  def : Pat<(v4i32 (add (v4i32 MQPR:$src1),
4023                        (v4i32 (mul (v4i32 MQPR:$src2),
4024                                    (v4i32 (ARMvdup (i32 rGPR:$x))))))),
4025            (v4i32 (MVE_VMLA_qr_u32 $src1, $src2, $x))>;
4026  def : Pat<(v8i16 (add (v8i16 MQPR:$src1),
4027                        (v8i16 (mul (v8i16 MQPR:$src2),
4028                                    (v8i16 (ARMvdup (i32 rGPR:$x))))))),
4029            (v8i16 (MVE_VMLA_qr_u16 $src1, $src2, $x))>;
4030  def : Pat<(v16i8 (add (v16i8 MQPR:$src1),
4031                        (v16i8 (mul (v16i8 MQPR:$src2),
4032                                    (v16i8 (ARMvdup (i32 rGPR:$x))))))),
4033            (v16i8 (MVE_VMLA_qr_u8 $src1, $src2, $x))>;
4034}
4035
4036let Predicates = [HasMVEFloat] in {
4037  def MVE_VFMA_qr_f16  : MVE_VFMAMLA_qr<"vfma",  "f16", 0b1, 0b11, 0b0>;
4038  def MVE_VFMA_qr_f32  : MVE_VFMAMLA_qr<"vfma",  "f32", 0b0, 0b11, 0b0>;
4039  def MVE_VFMA_qr_Sf16 : MVE_VFMAMLA_qr<"vfmas", "f16", 0b1, 0b11, 0b1>;
4040  def MVE_VFMA_qr_Sf32 : MVE_VFMAMLA_qr<"vfmas", "f32", 0b0, 0b11, 0b1>;
4041}
4042
4043class MVE_VQDMLAH_qr<string iname, string suffix, bit U, bits<2> size,
4044                     bit bit_5, bit bit_12, list<dag> pattern=[]>
4045  : MVE_qDestSrc_rSrc<iname, suffix, pattern> {
4046
4047  let Inst{28} = U;
4048  let Inst{21-20} = size;
4049  let Inst{16} = 0b0;
4050  let Inst{12} = bit_12;
4051  let Inst{8} = 0b0;
4052  let Inst{5} = bit_5;
4053}
4054
4055multiclass MVE_VQDMLAH_qr_types<string iname, bit bit_5, bit bit_12> {
4056  def s8  : MVE_VQDMLAH_qr<iname, "s8",  0b0, 0b00, bit_5, bit_12>;
4057  def s16 : MVE_VQDMLAH_qr<iname, "s16", 0b0, 0b01, bit_5, bit_12>;
4058  def s32 : MVE_VQDMLAH_qr<iname, "s32", 0b0, 0b10, bit_5, bit_12>;
4059}
4060
4061defm MVE_VQDMLAH_qr   : MVE_VQDMLAH_qr_types<"vqdmlah",   0b1, 0b0>;
4062defm MVE_VQRDMLAH_qr  : MVE_VQDMLAH_qr_types<"vqrdmlah",  0b0, 0b0>;
4063defm MVE_VQDMLASH_qr  : MVE_VQDMLAH_qr_types<"vqdmlash",  0b1, 0b1>;
4064defm MVE_VQRDMLASH_qr : MVE_VQDMLAH_qr_types<"vqrdmlash", 0b0, 0b1>;
4065
4066class MVE_VxDUP<string iname, string suffix, bits<2> size, bit bit_12,
4067              list<dag> pattern=[]>
4068  : MVE_p<(outs MQPR:$Qd, tGPREven:$Rn),
4069          (ins tGPREven:$Rn_src, MVE_VIDUP_imm:$imm), NoItinerary,
4070          iname, suffix, "$Qd, $Rn, $imm", vpred_r, "$Rn = $Rn_src",
4071          pattern> {
4072  bits<4> Qd;
4073  bits<4> Rn;
4074  bits<2> imm;
4075
4076  let Inst{28} = 0b0;
4077  let Inst{25-23} = 0b100;
4078  let Inst{22} = Qd{3};
4079  let Inst{21-20} = size;
4080  let Inst{19-17} = Rn{3-1};
4081  let Inst{16} = 0b1;
4082  let Inst{15-13} = Qd{2-0};
4083  let Inst{12} = bit_12;
4084  let Inst{11-8} = 0b1111;
4085  let Inst{7} = imm{1};
4086  let Inst{6-1} = 0b110111;
4087  let Inst{0} = imm{0};
4088  let validForTailPredication = 1;
4089}
4090
4091def MVE_VIDUPu8  : MVE_VxDUP<"vidup", "u8",  0b00, 0b0>;
4092def MVE_VIDUPu16 : MVE_VxDUP<"vidup", "u16", 0b01, 0b0>;
4093def MVE_VIDUPu32 : MVE_VxDUP<"vidup", "u32", 0b10, 0b0>;
4094
4095def MVE_VDDUPu8  : MVE_VxDUP<"vddup", "u8",  0b00, 0b1>;
4096def MVE_VDDUPu16 : MVE_VxDUP<"vddup", "u16", 0b01, 0b1>;
4097def MVE_VDDUPu32 : MVE_VxDUP<"vddup", "u32", 0b10, 0b1>;
4098
4099class MVE_VxWDUP<string iname, string suffix, bits<2> size, bit bit_12,
4100                 list<dag> pattern=[]>
4101  : MVE_p<(outs MQPR:$Qd, tGPREven:$Rn),
4102          (ins tGPREven:$Rn_src, tGPROdd:$Rm, MVE_VIDUP_imm:$imm), NoItinerary,
4103          iname, suffix, "$Qd, $Rn, $Rm, $imm", vpred_r, "$Rn = $Rn_src",
4104          pattern> {
4105  bits<4> Qd;
4106  bits<4> Rm;
4107  bits<4> Rn;
4108  bits<2> imm;
4109
4110  let Inst{28} = 0b0;
4111  let Inst{25-23} = 0b100;
4112  let Inst{22} = Qd{3};
4113  let Inst{21-20} = size;
4114  let Inst{19-17} = Rn{3-1};
4115  let Inst{16} = 0b1;
4116  let Inst{15-13} = Qd{2-0};
4117  let Inst{12} = bit_12;
4118  let Inst{11-8} = 0b1111;
4119  let Inst{7} = imm{1};
4120  let Inst{6-4} = 0b110;
4121  let Inst{3-1} = Rm{3-1};
4122  let Inst{0} = imm{0};
4123  let validForTailPredication = 1;
4124}
4125
4126def MVE_VIWDUPu8  : MVE_VxWDUP<"viwdup", "u8",  0b00, 0b0>;
4127def MVE_VIWDUPu16 : MVE_VxWDUP<"viwdup", "u16", 0b01, 0b0>;
4128def MVE_VIWDUPu32 : MVE_VxWDUP<"viwdup", "u32", 0b10, 0b0>;
4129
4130def MVE_VDWDUPu8  : MVE_VxWDUP<"vdwdup", "u8",  0b00, 0b1>;
4131def MVE_VDWDUPu16 : MVE_VxWDUP<"vdwdup", "u16", 0b01, 0b1>;
4132def MVE_VDWDUPu32 : MVE_VxWDUP<"vdwdup", "u32", 0b10, 0b1>;
4133
4134let hasSideEffects = 1 in
4135class MVE_VCTP<string suffix, bits<2> size, list<dag> pattern=[]>
4136  : MVE_p<(outs VCCR:$P0), (ins rGPR:$Rn), NoItinerary, "vctp", suffix,
4137          "$Rn", vpred_n, "", pattern> {
4138  bits<4> Rn;
4139
4140  let Inst{28-27} = 0b10;
4141  let Inst{26-22} = 0b00000;
4142  let Inst{21-20} = size;
4143  let Inst{19-16} = Rn{3-0};
4144  let Inst{15-11} = 0b11101;
4145  let Inst{10-0}  = 0b00000000001;
4146  let Unpredictable{10-0} = 0b11111111111;
4147
4148  let Constraints = "";
4149  let DecoderMethod = "DecodeMveVCTP";
4150  let validForTailPredication = 1;
4151}
4152
4153def MVE_VCTP8  : MVE_VCTP<"8",  0b00>;
4154def MVE_VCTP16 : MVE_VCTP<"16", 0b01>;
4155def MVE_VCTP32 : MVE_VCTP<"32", 0b10>;
4156def MVE_VCTP64 : MVE_VCTP<"64", 0b11>;
4157
4158let Predicates = [HasMVEInt] in {
4159  def : Pat<(int_arm_vctp8 rGPR:$Rn),
4160            (v16i1 (MVE_VCTP8 rGPR:$Rn))>;
4161  def : Pat<(int_arm_vctp16 rGPR:$Rn),
4162            (v8i1 (MVE_VCTP16 rGPR:$Rn))>;
4163  def : Pat<(int_arm_vctp32 rGPR:$Rn),
4164            (v4i1 (MVE_VCTP32 rGPR:$Rn))>;
4165}
4166
4167// end of mve_qDest_rSrc
4168
4169// start of coproc mov
4170
4171class MVE_VMOV_64bit<dag oops, dag iops, bit to_qreg, string ops, string cstr>
4172  : MVE_VMOV_lane_base<oops, !con(iops, (ins MVEPairVectorIndex2:$idx,
4173                                             MVEPairVectorIndex0:$idx2)),
4174                       NoItinerary, "vmov", "", ops, cstr, []> {
4175  bits<5> Rt;
4176  bits<5> Rt2;
4177  bits<4> Qd;
4178  bit idx;
4179  bit idx2;
4180
4181  let Inst{31-23} = 0b111011000;
4182  let Inst{22} = Qd{3};
4183  let Inst{21} = 0b0;
4184  let Inst{20} = to_qreg;
4185  let Inst{19-16} = Rt2{3-0};
4186  let Inst{15-13} = Qd{2-0};
4187  let Inst{12-5} = 0b01111000;
4188  let Inst{4} = idx2;
4189  let Inst{3-0} = Rt{3-0};
4190}
4191
4192// The assembly syntax for these instructions mentions the vector
4193// register name twice, e.g.
4194//
4195//    vmov q2[2], q2[0], r0, r1
4196//    vmov r0, r1, q2[2], q2[0]
4197//
4198// which needs a bit of juggling with MC operand handling.
4199//
4200// For the move _into_ a vector register, the MC operand list also has
4201// to mention the register name twice: once as the output, and once as
4202// an extra input to represent where the unchanged half of the output
4203// register comes from (when this instruction is used in code
4204// generation). So we arrange that the first mention of the vector reg
4205// in the instruction is considered by the AsmMatcher to be the output
4206// ($Qd), and the second one is the input ($QdSrc). Binding them
4207// together with the existing 'tie' constraint is enough to enforce at
4208// register allocation time that they have to be the same register.
4209//
4210// For the move _from_ a vector register, there's no way to get round
4211// the fact that both instances of that register name have to be
4212// inputs. They have to be the same register again, but this time, we
4213// can't use a tie constraint, because that has to be between an
4214// output and an input operand. So this time, we have to arrange that
4215// the q-reg appears just once in the MC operand list, in spite of
4216// being mentioned twice in the asm syntax - which needs a custom
4217// AsmMatchConverter.
4218
4219def MVE_VMOV_q_rr : MVE_VMOV_64bit<(outs MQPR:$Qd),
4220                                   (ins MQPR:$QdSrc, rGPR:$Rt, rGPR:$Rt2),
4221                                   0b1, "$Qd$idx, $QdSrc$idx2, $Rt, $Rt2",
4222                                   "$Qd = $QdSrc"> {
4223  let DecoderMethod = "DecodeMVEVMOVDRegtoQ";
4224}
4225
4226def MVE_VMOV_rr_q : MVE_VMOV_64bit<(outs rGPR:$Rt, rGPR:$Rt2), (ins MQPR:$Qd),
4227                                   0b0, "$Rt, $Rt2, $Qd$idx, $Qd$idx2", ""> {
4228  let DecoderMethod = "DecodeMVEVMOVQtoDReg";
4229  let AsmMatchConverter = "cvtMVEVMOVQtoDReg";
4230}
4231
4232// end of coproc mov
4233
4234// start of MVE interleaving load/store
4235
4236// Base class for the family of interleaving/deinterleaving
4237// load/stores with names like VLD20.8 and VST43.32.
4238class MVE_vldst24_base<bit writeback, bit fourregs, bits<2> stage, bits<2> size,
4239                       bit load, dag Oops, dag loadIops, dag wbIops,
4240                       string iname, string ops,
4241                       string cstr, list<dag> pattern=[]>
4242  : MVE_MI<Oops, !con(loadIops, wbIops), NoItinerary, iname, ops, cstr, pattern> {
4243  bits<4> VQd;
4244  bits<4> Rn;
4245
4246  let Inst{31-22} = 0b1111110010;
4247  let Inst{21} = writeback;
4248  let Inst{20} = load;
4249  let Inst{19-16} = Rn;
4250  let Inst{15-13} = VQd{2-0};
4251  let Inst{12-9} = 0b1111;
4252  let Inst{8-7} = size;
4253  let Inst{6-5} = stage;
4254  let Inst{4-1} = 0b0000;
4255  let Inst{0} = fourregs;
4256
4257  let mayLoad = load;
4258  let mayStore = !eq(load,0);
4259}
4260
4261// A parameter class used to encapsulate all the ways the writeback
4262// variants of VLD20 and friends differ from the non-writeback ones.
4263class MVE_vldst24_writeback<bit b, dag Oo, dag Io,
4264                            string sy="", string c="", string n=""> {
4265  bit writeback = b;
4266  dag Oops = Oo;
4267  dag Iops = Io;
4268  string syntax = sy;
4269  string cstr = c;
4270  string id_suffix = n;
4271}
4272
4273// Another parameter class that encapsulates the differences between VLD2x
4274// and VLD4x.
4275class MVE_vldst24_nvecs<int n, list<int> s, bit b, RegisterOperand vl> {
4276  int nvecs = n;
4277  list<int> stages = s;
4278  bit bit0 = b;
4279  RegisterOperand VecList = vl;
4280}
4281
4282// A third parameter class that distinguishes VLDnn.8 from .16 from .32.
4283class MVE_vldst24_lanesize<int i, bits<2> b> {
4284  int lanesize = i;
4285  bits<2> sizebits = b;
4286}
4287
4288// A base class for each direction of transfer: one for load, one for
4289// store. I can't make these a fourth independent parametric tuple
4290// class, because they have to take the nvecs tuple class as a
4291// parameter, in order to find the right VecList operand type.
4292
4293class MVE_vld24_base<MVE_vldst24_nvecs n, bits<2> pat, bits<2> size,
4294                     MVE_vldst24_writeback wb, string iname,
4295                     list<dag> pattern=[]>
4296  : MVE_vldst24_base<wb.writeback, n.bit0, pat, size, 1,
4297                     !con((outs n.VecList:$VQd), wb.Oops),
4298                     (ins n.VecList:$VQdSrc), wb.Iops,
4299                     iname, "$VQd, $Rn" # wb.syntax,
4300                     wb.cstr # ",$VQdSrc = $VQd", pattern>;
4301
4302class MVE_vst24_base<MVE_vldst24_nvecs n, bits<2> pat, bits<2> size,
4303                     MVE_vldst24_writeback wb, string iname,
4304                     list<dag> pattern=[]>
4305  : MVE_vldst24_base<wb.writeback, n.bit0, pat, size, 0,
4306                     wb.Oops, (ins n.VecList:$VQd), wb.Iops,
4307                     iname, "$VQd, $Rn" # wb.syntax,
4308                     wb.cstr, pattern>;
4309
4310// Actually define all the interleaving loads and stores, by a series
4311// of nested foreaches over number of vectors (VLD2/VLD4); stage
4312// within one of those series (VLDx0/VLDx1/VLDx2/VLDx3); size of
4313// vector lane; writeback or no writeback.
4314foreach n = [MVE_vldst24_nvecs<2, [0,1],     0, VecList2Q>,
4315             MVE_vldst24_nvecs<4, [0,1,2,3], 1, VecList4Q>] in
4316foreach stage = n.stages in
4317foreach s = [MVE_vldst24_lanesize< 8, 0b00>,
4318             MVE_vldst24_lanesize<16, 0b01>,
4319             MVE_vldst24_lanesize<32, 0b10>] in
4320foreach wb = [MVE_vldst24_writeback<
4321                1, (outs rGPR:$wb), (ins t2_nosp_addr_offset_none:$Rn),
4322                "!", "$Rn.base = $wb", "_wb">,
4323              MVE_vldst24_writeback<0, (outs), (ins t2_addr_offset_none:$Rn)>] in {
4324
4325  // For each case within all of those foreaches, define the actual
4326  // instructions. The def names are made by gluing together pieces
4327  // from all the parameter classes, and will end up being things like
4328  // MVE_VLD20_8 and MVE_VST43_16_wb.
4329
4330  def "MVE_VLD" # n.nvecs # stage # "_" # s.lanesize # wb.id_suffix
4331    : MVE_vld24_base<n, stage, s.sizebits, wb,
4332                     "vld" # n.nvecs # stage # "." # s.lanesize>;
4333
4334  def "MVE_VST" # n.nvecs # stage # "_" # s.lanesize # wb.id_suffix
4335    : MVE_vst24_base<n, stage, s.sizebits, wb,
4336                     "vst" # n.nvecs # stage # "." # s.lanesize>;
4337}
4338
4339multiclass MVE_vst24_patterns<int lanesize, ValueType VT> {
4340  foreach stage = [0,1] in
4341    def : Pat<(int_arm_mve_vst2q i32:$addr,
4342               (VT MQPR:$v0), (VT MQPR:$v1), (i32 stage)),
4343              (!cast<Instruction>("MVE_VST2"#stage#"_"#lanesize)
4344               (REG_SEQUENCE QQPR, VT:$v0, qsub_0, VT:$v1, qsub_1),
4345               t2_addr_offset_none:$addr)>;
4346
4347  foreach stage = [0,1,2,3] in
4348    def : Pat<(int_arm_mve_vst4q i32:$addr,
4349               (VT MQPR:$v0), (VT MQPR:$v1),
4350               (VT MQPR:$v2), (VT MQPR:$v3), (i32 stage)),
4351              (!cast<Instruction>("MVE_VST4"#stage#"_"#lanesize)
4352               (REG_SEQUENCE QQQQPR, VT:$v0, qsub_0, VT:$v1, qsub_1,
4353                                     VT:$v2, qsub_2, VT:$v3, qsub_3),
4354               t2_addr_offset_none:$addr)>;
4355}
4356defm : MVE_vst24_patterns<8, v16i8>;
4357defm : MVE_vst24_patterns<16, v8i16>;
4358defm : MVE_vst24_patterns<32, v4i32>;
4359defm : MVE_vst24_patterns<16, v8f16>;
4360defm : MVE_vst24_patterns<32, v4f32>;
4361
4362// end of MVE interleaving load/store
4363
4364// start of MVE predicable load/store
4365
4366// A parameter class for the direction of transfer.
4367class MVE_ldst_direction<bit b, dag Oo, dag Io, string c=""> {
4368  bit load = b;
4369  dag Oops = Oo;
4370  dag Iops = Io;
4371  string cstr = c;
4372}
4373def MVE_ld: MVE_ldst_direction<1, (outs MQPR:$Qd), (ins), ",@earlyclobber $Qd">;
4374def MVE_st: MVE_ldst_direction<0, (outs), (ins MQPR:$Qd)>;
4375
4376// A parameter class for the size of memory access in a load.
4377class MVE_memsz<bits<2> e, int s, AddrMode m, string mn, list<string> types> {
4378  bits<2> encoding = e;         // opcode bit(s) for encoding
4379  int shift = s;                // shift applied to immediate load offset
4380  AddrMode AM = m;
4381
4382  // For instruction aliases: define the complete list of type
4383  // suffixes at this size, and the canonical ones for loads and
4384  // stores.
4385  string MnemonicLetter = mn;
4386  int TypeBits = !shl(8, s);
4387  string CanonLoadSuffix = ".u" # TypeBits;
4388  string CanonStoreSuffix = "." # TypeBits;
4389  list<string> suffixes = !foreach(letter, types, "." # letter # TypeBits);
4390}
4391
4392// Instances of MVE_memsz.
4393//
4394// (memD doesn't need an AddrMode, because those are only for
4395// contiguous loads, and memD is only used by gather/scatters.)
4396def MVE_memB: MVE_memsz<0b00, 0, AddrModeT2_i7,   "b", ["", "u", "s"]>;
4397def MVE_memH: MVE_memsz<0b01, 1, AddrModeT2_i7s2, "h", ["", "u", "s", "f"]>;
4398def MVE_memW: MVE_memsz<0b10, 2, AddrModeT2_i7s4, "w", ["", "u", "s", "f"]>;
4399def MVE_memD: MVE_memsz<0b11, 3, ?,               "d", ["", "u", "s", "f"]>;
4400
4401// This is the base class for all the MVE loads and stores other than
4402// the interleaving ones. All the non-interleaving loads/stores share
4403// the characteristic that they operate on just one vector register,
4404// so they are VPT-predicable.
4405//
4406// The predication operand is vpred_n, for both loads and stores. For
4407// store instructions, the reason is obvious: if there is no output
4408// register, there can't be a need for an input parameter giving the
4409// output register's previous value. Load instructions also don't need
4410// that input parameter, because unlike MVE data processing
4411// instructions, predicated loads are defined to set the inactive
4412// lanes of the output register to zero, instead of preserving their
4413// input values.
4414class MVE_VLDRSTR_base<MVE_ldst_direction dir, bit U, bit P, bit W, bit opc,
4415                       dag oops, dag iops, string asm, string suffix,
4416                       string ops, string cstr, list<dag> pattern=[]>
4417 : MVE_p<oops, iops, NoItinerary, asm, suffix, ops, vpred_n, cstr, pattern> {
4418  bits<3> Qd;
4419
4420  let Inst{28} = U;
4421  let Inst{25} = 0b0;
4422  let Inst{24} = P;
4423  let Inst{22} = 0b0;
4424  let Inst{21} = W;
4425  let Inst{20} = dir.load;
4426  let Inst{15-13} = Qd{2-0};
4427  let Inst{12} = opc;
4428  let Inst{11-9} = 0b111;
4429
4430  let mayLoad = dir.load;
4431  let mayStore = !eq(dir.load,0);
4432  let validForTailPredication = 1;
4433}
4434
4435// Contiguous load and store instructions. These come in two main
4436// categories: same-size loads/stores in which 128 bits of vector
4437// register is transferred to or from 128 bits of memory in the most
4438// obvious way, and widening loads / narrowing stores, in which the
4439// size of memory accessed is less than the size of a vector register,
4440// so the load instructions sign- or zero-extend each memory value
4441// into a wider vector lane, and the store instructions truncate
4442// correspondingly.
4443//
4444// The instruction mnemonics for these two classes look reasonably
4445// similar, but the actual encodings are different enough to need two
4446// separate base classes.
4447
4448// Contiguous, same size
4449class MVE_VLDRSTR_cs<MVE_ldst_direction dir, MVE_memsz memsz, bit P, bit W,
4450                     dag oops, dag iops, string asm, string suffix,
4451                     IndexMode im, string ops, string cstr>
4452  : MVE_VLDRSTR_base<dir, 0, P, W, 1, oops, iops, asm, suffix, ops, cstr> {
4453  bits<12> addr;
4454  let Inst{23} = addr{7};
4455  let Inst{19-16} = addr{11-8};
4456  let Inst{8-7} = memsz.encoding;
4457  let Inst{6-0} = addr{6-0};
4458}
4459
4460// Contiguous, widening/narrowing
4461class MVE_VLDRSTR_cw<MVE_ldst_direction dir, MVE_memsz memsz, bit U,
4462                     bit P, bit W, bits<2> size, dag oops, dag iops,
4463                     string asm, string suffix, IndexMode im,
4464                     string ops, string cstr>
4465  : MVE_VLDRSTR_base<dir, U, P, W, 0, oops, iops, asm, suffix, ops, cstr> {
4466  bits<11> addr;
4467  let Inst{23} = addr{7};
4468  let Inst{19} = memsz.encoding{0}; // enough to tell 16- from 32-bit
4469  let Inst{18-16} = addr{10-8};
4470  let Inst{8-7} = size;
4471  let Inst{6-0} = addr{6-0};
4472
4473  let IM = im;
4474}
4475
4476// Multiclass wrapper on each of the _cw and _cs base classes, to
4477// generate three writeback modes (none, preindex, postindex).
4478
4479multiclass MVE_VLDRSTR_cw_m<MVE_ldst_direction dir, MVE_memsz memsz,
4480                            string asm, string suffix, bit U, bits<2> size> {
4481  let AM = memsz.AM in {
4482    def "" : MVE_VLDRSTR_cw<
4483        dir, memsz, U, 1, 0, size,
4484        dir.Oops, !con(dir.Iops, (ins taddrmode_imm7<memsz.shift>:$addr)),
4485        asm, suffix, IndexModeNone, "$Qd, $addr", "">;
4486
4487    def _pre : MVE_VLDRSTR_cw<
4488        dir, memsz, U, 1, 1, size,
4489        !con((outs tGPR:$wb), dir.Oops),
4490        !con(dir.Iops, (ins taddrmode_imm7<memsz.shift>:$addr)),
4491        asm, suffix, IndexModePre, "$Qd, $addr!", "$addr.base = $wb"> {
4492      let DecoderMethod = "DecodeMVE_MEM_1_pre<"#memsz.shift#">";
4493    }
4494
4495    def _post : MVE_VLDRSTR_cw<
4496        dir, memsz, U, 0, 1, size,
4497        !con((outs tGPR:$wb), dir.Oops),
4498        !con(dir.Iops, (ins t_addr_offset_none:$Rn,
4499                            t2am_imm7_offset<memsz.shift>:$addr)),
4500        asm, suffix, IndexModePost, "$Qd, $Rn$addr", "$Rn.base = $wb"> {
4501      bits<4> Rn;
4502      let Inst{18-16} = Rn{2-0};
4503    }
4504  }
4505}
4506
4507multiclass MVE_VLDRSTR_cs_m<MVE_ldst_direction dir, MVE_memsz memsz,
4508                            string asm, string suffix> {
4509  let AM = memsz.AM in {
4510    def "" : MVE_VLDRSTR_cs<
4511        dir, memsz, 1, 0,
4512        dir.Oops, !con(dir.Iops, (ins t2addrmode_imm7<memsz.shift>:$addr)),
4513        asm, suffix, IndexModeNone, "$Qd, $addr", "">;
4514
4515    def _pre : MVE_VLDRSTR_cs<
4516        dir, memsz, 1, 1,
4517        !con((outs rGPR:$wb), dir.Oops),
4518        !con(dir.Iops, (ins t2addrmode_imm7_pre<memsz.shift>:$addr)),
4519        asm, suffix, IndexModePre, "$Qd, $addr!", "$addr.base = $wb"> {
4520      let DecoderMethod = "DecodeMVE_MEM_2_pre<"#memsz.shift#">";
4521    }
4522
4523    def _post : MVE_VLDRSTR_cs<
4524        dir, memsz, 0, 1,
4525        !con((outs rGPR:$wb), dir.Oops),
4526        // We need an !if here to select the base register class,
4527        // because it's legal to write back to SP in a load of this
4528        // type, but not in a store.
4529        !con(dir.Iops, (ins !if(dir.load, t2_addr_offset_none,
4530                                          t2_nosp_addr_offset_none):$Rn,
4531                            t2am_imm7_offset<memsz.shift>:$addr)),
4532        asm, suffix, IndexModePost, "$Qd, $Rn$addr", "$Rn.base = $wb"> {
4533      bits<4> Rn;
4534      let Inst{19-16} = Rn{3-0};
4535    }
4536  }
4537}
4538
4539// Now actually declare all the contiguous load/stores, via those
4540// multiclasses. The instruction ids coming out of this are the bare
4541// names shown in the defm, with _pre or _post appended for writeback,
4542// e.g. MVE_VLDRBS16, MVE_VSTRB16_pre, MVE_VSTRHU16_post.
4543
4544defm MVE_VLDRBS16: MVE_VLDRSTR_cw_m<MVE_ld, MVE_memB, "vldrb", "s16", 0, 0b01>;
4545defm MVE_VLDRBS32: MVE_VLDRSTR_cw_m<MVE_ld, MVE_memB, "vldrb", "s32", 0, 0b10>;
4546defm MVE_VLDRBU16: MVE_VLDRSTR_cw_m<MVE_ld, MVE_memB, "vldrb", "u16", 1, 0b01>;
4547defm MVE_VLDRBU32: MVE_VLDRSTR_cw_m<MVE_ld, MVE_memB, "vldrb", "u32", 1, 0b10>;
4548defm MVE_VLDRHS32: MVE_VLDRSTR_cw_m<MVE_ld, MVE_memH, "vldrh", "s32", 0, 0b10>;
4549defm MVE_VLDRHU32: MVE_VLDRSTR_cw_m<MVE_ld, MVE_memH, "vldrh", "u32", 1, 0b10>;
4550
4551defm MVE_VLDRBU8:  MVE_VLDRSTR_cs_m<MVE_ld, MVE_memB, "vldrb", "u8">;
4552defm MVE_VLDRHU16: MVE_VLDRSTR_cs_m<MVE_ld, MVE_memH, "vldrh", "u16">;
4553defm MVE_VLDRWU32: MVE_VLDRSTR_cs_m<MVE_ld, MVE_memW, "vldrw", "u32">;
4554
4555defm MVE_VSTRB16:  MVE_VLDRSTR_cw_m<MVE_st, MVE_memB, "vstrb", "16",  0, 0b01>;
4556defm MVE_VSTRB32:  MVE_VLDRSTR_cw_m<MVE_st, MVE_memB, "vstrb", "32",  0, 0b10>;
4557defm MVE_VSTRH32:  MVE_VLDRSTR_cw_m<MVE_st, MVE_memH, "vstrh", "32",  0, 0b10>;
4558
4559defm MVE_VSTRBU8 : MVE_VLDRSTR_cs_m<MVE_st, MVE_memB, "vstrb", "8">;
4560defm MVE_VSTRHU16: MVE_VLDRSTR_cs_m<MVE_st, MVE_memH, "vstrh", "16">;
4561defm MVE_VSTRWU32: MVE_VLDRSTR_cs_m<MVE_st, MVE_memW, "vstrw", "32">;
4562
4563// Gather loads / scatter stores whose address operand is of the form
4564// [Rn,Qm], i.e. a single GPR as the common base address, plus a
4565// vector of offset from it. ('Load/store this sequence of elements of
4566// the same array.')
4567//
4568// Like the contiguous family, these loads and stores can widen the
4569// loaded values / truncate the stored ones, or they can just
4570// load/store the same size of memory and vector lane. But unlike the
4571// contiguous family, there's no particular difference in encoding
4572// between those two cases.
4573//
4574// This family also comes with the option to scale the offset values
4575// in Qm by the size of the loaded memory (i.e. to treat them as array
4576// indices), or not to scale them (to treat them as plain byte offsets
4577// in memory, so that perhaps the loaded values are unaligned). The
4578// scaled instructions' address operand in assembly looks like
4579// [Rn,Qm,UXTW #2] or similar.
4580
4581// Base class.
4582class MVE_VLDRSTR_rq<MVE_ldst_direction dir, MVE_memsz memsz, bit U,
4583                     bits<2> size, bit os, string asm, string suffix, int shift>
4584  : MVE_VLDRSTR_base<dir, U, 0b0, 0b0, 0, dir.Oops,
4585                     !con(dir.Iops, (ins mve_addr_rq_shift<shift>:$addr)),
4586                     asm, suffix, "$Qd, $addr", dir.cstr> {
4587  bits<7> addr;
4588  let Inst{23} = 0b1;
4589  let Inst{19-16} = addr{6-3};
4590  let Inst{8-7} = size;
4591  let Inst{6} = memsz.encoding{1};
4592  let Inst{5} = 0;
4593  let Inst{4} = memsz.encoding{0};
4594  let Inst{3-1} = addr{2-0};
4595  let Inst{0} = os;
4596}
4597
4598// Multiclass that defines the scaled and unscaled versions of an
4599// instruction, when the memory size is wider than a byte. The scaled
4600// version gets the default name like MVE_VLDRBU16_rq; the unscaled /
4601// potentially unaligned version gets a "_u" suffix, e.g.
4602// MVE_VLDRBU16_rq_u.
4603multiclass MVE_VLDRSTR_rq_w<MVE_ldst_direction dir, MVE_memsz memsz,
4604                            string asm, string suffix, bit U, bits<2> size> {
4605  def _u : MVE_VLDRSTR_rq<dir, memsz, U, size, 0, asm, suffix, 0>;
4606  def "" : MVE_VLDRSTR_rq<dir, memsz, U, size, 1, asm, suffix, memsz.shift>;
4607}
4608
4609// Subclass of MVE_VLDRSTR_rq with the same API as that multiclass,
4610// for use when the memory size is one byte, so there's no 'scaled'
4611// version of the instruction at all. (This is encoded as if it were
4612// unscaled, but named in the default way with no _u suffix.)
4613class MVE_VLDRSTR_rq_b<MVE_ldst_direction dir, MVE_memsz memsz,
4614                       string asm, string suffix, bit U, bits<2> size>
4615  : MVE_VLDRSTR_rq<dir, memsz, U, size, 0, asm, suffix, 0>;
4616
4617// Actually define all the loads and stores in this family.
4618
4619def  MVE_VLDRBU8_rq : MVE_VLDRSTR_rq_b<MVE_ld, MVE_memB, "vldrb","u8",  1,0b00>;
4620def  MVE_VLDRBU16_rq: MVE_VLDRSTR_rq_b<MVE_ld, MVE_memB, "vldrb","u16", 1,0b01>;
4621def  MVE_VLDRBS16_rq: MVE_VLDRSTR_rq_b<MVE_ld, MVE_memB, "vldrb","s16", 0,0b01>;
4622def  MVE_VLDRBU32_rq: MVE_VLDRSTR_rq_b<MVE_ld, MVE_memB, "vldrb","u32", 1,0b10>;
4623def  MVE_VLDRBS32_rq: MVE_VLDRSTR_rq_b<MVE_ld, MVE_memB, "vldrb","s32", 0,0b10>;
4624
4625defm MVE_VLDRHU16_rq: MVE_VLDRSTR_rq_w<MVE_ld, MVE_memH, "vldrh","u16", 1,0b01>;
4626defm MVE_VLDRHU32_rq: MVE_VLDRSTR_rq_w<MVE_ld, MVE_memH, "vldrh","u32", 1,0b10>;
4627defm MVE_VLDRHS32_rq: MVE_VLDRSTR_rq_w<MVE_ld, MVE_memH, "vldrh","s32", 0,0b10>;
4628defm MVE_VLDRWU32_rq: MVE_VLDRSTR_rq_w<MVE_ld, MVE_memW, "vldrw","u32", 1,0b10>;
4629defm MVE_VLDRDU64_rq: MVE_VLDRSTR_rq_w<MVE_ld, MVE_memD, "vldrd","u64", 1,0b11>;
4630
4631def  MVE_VSTRB8_rq  : MVE_VLDRSTR_rq_b<MVE_st, MVE_memB, "vstrb","8",   0,0b00>;
4632def  MVE_VSTRB16_rq : MVE_VLDRSTR_rq_b<MVE_st, MVE_memB, "vstrb","16",  0,0b01>;
4633def  MVE_VSTRB32_rq : MVE_VLDRSTR_rq_b<MVE_st, MVE_memB, "vstrb","32",  0,0b10>;
4634
4635defm MVE_VSTRH16_rq : MVE_VLDRSTR_rq_w<MVE_st, MVE_memH, "vstrh","16",  0,0b01>;
4636defm MVE_VSTRH32_rq : MVE_VLDRSTR_rq_w<MVE_st, MVE_memH, "vstrh","32",  0,0b10>;
4637defm MVE_VSTRW32_rq : MVE_VLDRSTR_rq_w<MVE_st, MVE_memW, "vstrw","32",  0,0b10>;
4638defm MVE_VSTRD64_rq : MVE_VLDRSTR_rq_w<MVE_st, MVE_memD, "vstrd","64",  0,0b11>;
4639
4640// Gather loads / scatter stores whose address operand is of the form
4641// [Qm,#imm], i.e. a vector containing a full base address for each
4642// loaded item, plus an immediate offset applied consistently to all
4643// of them. ('Load/store the same field from this vector of pointers
4644// to a structure type.')
4645//
4646// This family requires the vector lane size to be at least 32 bits
4647// (so there's room for an address in each lane at all). It has no
4648// widening/narrowing variants. But it does support preindex
4649// writeback, in which the address vector is updated to hold the
4650// addresses actually loaded from.
4651
4652// Base class.
4653class MVE_VLDRSTR_qi<MVE_ldst_direction dir, MVE_memsz memsz, bit W, dag wbops,
4654                     string asm, string wbAsm, string suffix, string cstr = "">
4655  : MVE_VLDRSTR_base<dir, 1, 1, W, 1, !con(wbops, dir.Oops),
4656                     !con(dir.Iops, (ins mve_addr_q_shift<memsz.shift>:$addr)),
4657                     asm, suffix, "$Qd, $addr" # wbAsm, cstr # dir.cstr> {
4658  bits<11> addr;
4659  let Inst{23} = addr{7};
4660  let Inst{19-17} = addr{10-8};
4661  let Inst{16} = 0;
4662  let Inst{8} = memsz.encoding{0}; // enough to distinguish 32- from 64-bit
4663  let Inst{7} = 0;
4664  let Inst{6-0} = addr{6-0};
4665}
4666
4667// Multiclass that generates the non-writeback and writeback variants.
4668multiclass MVE_VLDRSTR_qi_m<MVE_ldst_direction dir, MVE_memsz memsz,
4669                            string asm, string suffix> {
4670  def ""   : MVE_VLDRSTR_qi<dir, memsz, 0, (outs),          asm, "",  suffix>;
4671  def _pre : MVE_VLDRSTR_qi<dir, memsz, 1, (outs MQPR:$wb), asm, "!", suffix,
4672                            "$addr.base = $wb"> {
4673    let DecoderMethod="DecodeMVE_MEM_3_pre<"#memsz.shift#">";
4674  }
4675}
4676
4677// Actual instruction definitions.
4678defm MVE_VLDRWU32_qi: MVE_VLDRSTR_qi_m<MVE_ld, MVE_memW, "vldrw", "u32">;
4679defm MVE_VLDRDU64_qi: MVE_VLDRSTR_qi_m<MVE_ld, MVE_memD, "vldrd", "u64">;
4680defm MVE_VSTRW32_qi:  MVE_VLDRSTR_qi_m<MVE_st, MVE_memW, "vstrw", "32">;
4681defm MVE_VSTRD64_qi:  MVE_VLDRSTR_qi_m<MVE_st, MVE_memD, "vstrd", "64">;
4682
4683// Define aliases for all the instructions where memory size and
4684// vector lane size are the same. These are mnemonic aliases, so they
4685// apply consistently across all of the above families - contiguous
4686// loads, and both the rq and qi types of gather/scatter.
4687//
4688// Rationale: As long as you're loading (for example) 16-bit memory
4689// values into 16-bit vector lanes, you can think of them as signed or
4690// unsigned integers, fp16 or just raw 16-bit blobs and it makes no
4691// difference. So we permit all of vldrh.16, vldrh.u16, vldrh.s16,
4692// vldrh.f16 and treat them all as equivalent to the canonical
4693// spelling (which happens to be .u16 for loads, and just .16 for
4694// stores).
4695
4696foreach vpt_cond = ["", "t", "e"] in
4697foreach memsz = [MVE_memB, MVE_memH, MVE_memW, MVE_memD] in
4698foreach suffix = memsz.suffixes in {
4699
4700  // These foreaches are conceptually ifs, implemented by iterating a
4701  // dummy variable over a list with 0 or 1 elements depending on the
4702  // condition. The idea is to iterate over _nearly_ all the suffixes
4703  // in memsz.suffixes, but omit the one we want all the others to alias.
4704
4705  foreach _ = !if(!ne(suffix, memsz.CanonLoadSuffix), [1], []<int>) in
4706  def : MnemonicAlias<
4707    "vldr" # memsz.MnemonicLetter # vpt_cond # suffix,
4708    "vldr" # memsz.MnemonicLetter # vpt_cond # memsz.CanonLoadSuffix>;
4709
4710  foreach _ = !if(!ne(suffix, memsz.CanonStoreSuffix), [1], []<int>) in
4711  def : MnemonicAlias<
4712    "vstr" # memsz.MnemonicLetter # vpt_cond # suffix,
4713    "vstr" # memsz.MnemonicLetter # vpt_cond # memsz.CanonStoreSuffix>;
4714}
4715
4716// end of MVE predicable load/store
4717
4718class MVE_VPT<string suffix, bits<2> size, dag iops, string asm, list<dag> pattern=[]>
4719  : MVE_MI<(outs ), iops, NoItinerary, !strconcat("vpt", "${Mk}", ".", suffix), asm, "", pattern> {
4720  bits<3> fc;
4721  bits<4> Mk;
4722  bits<3> Qn;
4723
4724  let Inst{31-23} = 0b111111100;
4725  let Inst{22} = Mk{3};
4726  let Inst{21-20} = size;
4727  let Inst{19-17} = Qn{2-0};
4728  let Inst{16} = 0b1;
4729  let Inst{15-13} = Mk{2-0};
4730  let Inst{12} = fc{2};
4731  let Inst{11-8} = 0b1111;
4732  let Inst{7} = fc{0};
4733  let Inst{4} = 0b0;
4734
4735  let Defs = [VPR];
4736  let validForTailPredication = 1;
4737}
4738
4739class MVE_VPTt1<string suffix, bits<2> size, dag iops>
4740  : MVE_VPT<suffix, size, iops, "$fc, $Qn, $Qm"> {
4741  bits<4> Qm;
4742  bits<4> Mk;
4743
4744  let Inst{6} = 0b0;
4745  let Inst{5} = Qm{3};
4746  let Inst{3-1} = Qm{2-0};
4747  let Inst{0} = fc{1};
4748  let validForTailPredication = 1;
4749}
4750
4751class MVE_VPTt1i<string suffix, bits<2> size>
4752 : MVE_VPTt1<suffix, size,
4753           (ins vpt_mask:$Mk, MQPR:$Qn, MQPR:$Qm, pred_basic_i:$fc)> {
4754  let Inst{12} = 0b0;
4755  let Inst{0} = 0b0;
4756}
4757
4758def MVE_VPTv4i32 : MVE_VPTt1i<"i32", 0b10>;
4759def MVE_VPTv8i16 : MVE_VPTt1i<"i16", 0b01>;
4760def MVE_VPTv16i8 : MVE_VPTt1i<"i8", 0b00>;
4761
4762class MVE_VPTt1u<string suffix, bits<2> size>
4763 : MVE_VPTt1<suffix, size,
4764           (ins vpt_mask:$Mk, MQPR:$Qn, MQPR:$Qm, pred_basic_u:$fc)> {
4765  let Inst{12} = 0b0;
4766  let Inst{0} = 0b1;
4767}
4768
4769def MVE_VPTv4u32 : MVE_VPTt1u<"u32", 0b10>;
4770def MVE_VPTv8u16 : MVE_VPTt1u<"u16", 0b01>;
4771def MVE_VPTv16u8 : MVE_VPTt1u<"u8", 0b00>;
4772
4773class MVE_VPTt1s<string suffix, bits<2> size>
4774 : MVE_VPTt1<suffix, size,
4775           (ins vpt_mask:$Mk, MQPR:$Qn, MQPR:$Qm, pred_basic_s:$fc)> {
4776  let Inst{12} = 0b1;
4777}
4778
4779def MVE_VPTv4s32 : MVE_VPTt1s<"s32", 0b10>;
4780def MVE_VPTv8s16 : MVE_VPTt1s<"s16", 0b01>;
4781def MVE_VPTv16s8 : MVE_VPTt1s<"s8", 0b00>;
4782
4783class MVE_VPTt2<string suffix, bits<2> size, dag iops>
4784  : MVE_VPT<suffix, size, iops,
4785          "$fc, $Qn, $Rm"> {
4786  bits<4> Rm;
4787  bits<3> fc;
4788  bits<4> Mk;
4789
4790  let Inst{6} = 0b1;
4791  let Inst{5} = fc{1};
4792  let Inst{3-0} = Rm{3-0};
4793}
4794
4795class MVE_VPTt2i<string suffix, bits<2> size>
4796  : MVE_VPTt2<suffix, size,
4797            (ins vpt_mask:$Mk, MQPR:$Qn, GPRwithZR:$Rm, pred_basic_i:$fc)> {
4798  let Inst{12} = 0b0;
4799  let Inst{5} = 0b0;
4800}
4801
4802def MVE_VPTv4i32r : MVE_VPTt2i<"i32", 0b10>;
4803def MVE_VPTv8i16r : MVE_VPTt2i<"i16", 0b01>;
4804def MVE_VPTv16i8r : MVE_VPTt2i<"i8", 0b00>;
4805
4806class MVE_VPTt2u<string suffix, bits<2> size>
4807  : MVE_VPTt2<suffix, size,
4808            (ins vpt_mask:$Mk, MQPR:$Qn, GPRwithZR:$Rm, pred_basic_u:$fc)> {
4809  let Inst{12} = 0b0;
4810  let Inst{5} = 0b1;
4811}
4812
4813def MVE_VPTv4u32r : MVE_VPTt2u<"u32", 0b10>;
4814def MVE_VPTv8u16r : MVE_VPTt2u<"u16", 0b01>;
4815def MVE_VPTv16u8r : MVE_VPTt2u<"u8", 0b00>;
4816
4817class MVE_VPTt2s<string suffix, bits<2> size>
4818  : MVE_VPTt2<suffix, size,
4819            (ins vpt_mask:$Mk, MQPR:$Qn, GPRwithZR:$Rm, pred_basic_s:$fc)> {
4820  let Inst{12} = 0b1;
4821}
4822
4823def MVE_VPTv4s32r : MVE_VPTt2s<"s32", 0b10>;
4824def MVE_VPTv8s16r : MVE_VPTt2s<"s16", 0b01>;
4825def MVE_VPTv16s8r : MVE_VPTt2s<"s8", 0b00>;
4826
4827
4828class MVE_VPTf<string suffix, bit size, dag iops, string asm, list<dag> pattern=[]>
4829  : MVE_MI<(outs ), iops, NoItinerary, !strconcat("vpt", "${Mk}", ".", suffix), asm,
4830            "", pattern> {
4831  bits<3> fc;
4832  bits<4> Mk;
4833  bits<3> Qn;
4834
4835  let Inst{31-29} = 0b111;
4836  let Inst{28} = size;
4837  let Inst{27-23} = 0b11100;
4838  let Inst{22} = Mk{3};
4839  let Inst{21-20} = 0b11;
4840  let Inst{19-17} = Qn{2-0};
4841  let Inst{16} = 0b1;
4842  let Inst{15-13} = Mk{2-0};
4843  let Inst{12} = fc{2};
4844  let Inst{11-8} = 0b1111;
4845  let Inst{7} = fc{0};
4846  let Inst{4} = 0b0;
4847
4848  let Defs = [VPR];
4849  let Predicates = [HasMVEFloat];
4850  let validForTailPredication = 1;
4851}
4852
4853class MVE_VPTft1<string suffix, bit size>
4854  : MVE_VPTf<suffix, size, (ins vpt_mask:$Mk, MQPR:$Qn, MQPR:$Qm, pred_basic_fp:$fc),
4855          "$fc, $Qn, $Qm"> {
4856  bits<3> fc;
4857  bits<4> Qm;
4858
4859  let Inst{6} = 0b0;
4860  let Inst{5} = Qm{3};
4861  let Inst{3-1} = Qm{2-0};
4862  let Inst{0} = fc{1};
4863}
4864
4865def MVE_VPTv4f32         : MVE_VPTft1<"f32", 0b0>;
4866def MVE_VPTv8f16         : MVE_VPTft1<"f16", 0b1>;
4867
4868class MVE_VPTft2<string suffix, bit size>
4869  : MVE_VPTf<suffix, size, (ins vpt_mask:$Mk, MQPR:$Qn, GPRwithZR:$Rm, pred_basic_fp:$fc),
4870          "$fc, $Qn, $Rm"> {
4871  bits<3> fc;
4872  bits<4> Rm;
4873
4874  let Inst{6} = 0b1;
4875  let Inst{5} = fc{1};
4876  let Inst{3-0} = Rm{3-0};
4877}
4878
4879def MVE_VPTv4f32r        : MVE_VPTft2<"f32", 0b0>;
4880def MVE_VPTv8f16r        : MVE_VPTft2<"f16", 0b1>;
4881
4882def MVE_VPST : MVE_MI<(outs ), (ins vpt_mask:$Mk), NoItinerary,
4883       !strconcat("vpst", "${Mk}"), "", "", []> {
4884  bits<4> Mk;
4885
4886  let Inst{31-23} = 0b111111100;
4887  let Inst{22} = Mk{3};
4888  let Inst{21-16} = 0b110001;
4889  let Inst{15-13} = Mk{2-0};
4890  let Inst{12-0} = 0b0111101001101;
4891  let Unpredictable{12} = 0b1;
4892  let Unpredictable{7} = 0b1;
4893  let Unpredictable{5} = 0b1;
4894
4895  let Uses = [VPR];
4896  let validForTailPredication = 1;
4897}
4898
4899def MVE_VPSEL : MVE_p<(outs MQPR:$Qd), (ins MQPR:$Qn, MQPR:$Qm), NoItinerary,
4900                      "vpsel", "", "$Qd, $Qn, $Qm", vpred_n, "", []> {
4901  bits<4> Qn;
4902  bits<4> Qd;
4903  bits<4> Qm;
4904
4905  let Inst{28} = 0b1;
4906  let Inst{25-23} = 0b100;
4907  let Inst{22} = Qd{3};
4908  let Inst{21-20} = 0b11;
4909  let Inst{19-17} = Qn{2-0};
4910  let Inst{16} = 0b1;
4911  let Inst{15-13} = Qd{2-0};
4912  let Inst{12-9} = 0b0111;
4913  let Inst{8} = 0b1;
4914  let Inst{7} = Qn{3};
4915  let Inst{6} = 0b0;
4916  let Inst{5} = Qm{3};
4917  let Inst{4} = 0b0;
4918  let Inst{3-1} = Qm{2-0};
4919  let Inst{0} = 0b1;
4920  let validForTailPredication = 1;
4921}
4922
4923foreach suffix = ["s8", "s16", "s32", "u8", "u16", "u32",
4924                  "i8", "i16", "i32",       "f16", "f32"] in
4925def : MVEInstAlias<"vpsel${vp}." # suffix # "\t$Qd, $Qn, $Qm",
4926                   (MVE_VPSEL MQPR:$Qd, MQPR:$Qn, MQPR:$Qm, vpred_n:$vp)>;
4927
4928let Predicates = [HasMVEInt] in {
4929  def : Pat<(v16i8 (vselect (v16i1 VCCR:$pred), (v16i8 MQPR:$v1), (v16i8 MQPR:$v2))),
4930            (v16i8 (MVE_VPSEL MQPR:$v1, MQPR:$v2, 0, VCCR:$pred))>;
4931  def : Pat<(v8i16 (vselect (v8i1 VCCR:$pred), (v8i16 MQPR:$v1), (v8i16 MQPR:$v2))),
4932            (v8i16 (MVE_VPSEL MQPR:$v1, MQPR:$v2, 0, VCCR:$pred))>;
4933  def : Pat<(v4i32 (vselect (v4i1 VCCR:$pred), (v4i32 MQPR:$v1), (v4i32 MQPR:$v2))),
4934            (v4i32 (MVE_VPSEL MQPR:$v1, MQPR:$v2, 0, VCCR:$pred))>;
4935
4936  def : Pat<(v8f16 (vselect (v8i1 VCCR:$pred), (v8f16 MQPR:$v1), (v8f16 MQPR:$v2))),
4937            (v8f16 (MVE_VPSEL MQPR:$v1, MQPR:$v2, 0, VCCR:$pred))>;
4938  def : Pat<(v4f32 (vselect (v4i1 VCCR:$pred), (v4f32 MQPR:$v1), (v4f32 MQPR:$v2))),
4939            (v4f32 (MVE_VPSEL MQPR:$v1, MQPR:$v2, 0, VCCR:$pred))>;
4940
4941  def : Pat<(v16i8 (vselect (v16i8 MQPR:$pred), (v16i8 MQPR:$v1), (v16i8 MQPR:$v2))),
4942            (v16i8 (MVE_VPSEL MQPR:$v1, MQPR:$v2, 0,
4943                              (MVE_VCMPi8 (v16i8 MQPR:$pred), (MVE_VMOVimmi8 0), 1)))>;
4944  def : Pat<(v8i16 (vselect (v8i16 MQPR:$pred), (v8i16 MQPR:$v1), (v8i16 MQPR:$v2))),
4945            (v8i16 (MVE_VPSEL MQPR:$v1, MQPR:$v2, 0,
4946                              (MVE_VCMPi16 (v8i16 MQPR:$pred), (MVE_VMOVimmi16 0), 1)))>;
4947  def : Pat<(v4i32 (vselect (v4i32 MQPR:$pred), (v4i32 MQPR:$v1), (v4i32 MQPR:$v2))),
4948            (v4i32 (MVE_VPSEL MQPR:$v1, MQPR:$v2, 0,
4949                              (MVE_VCMPi32 (v4i32 MQPR:$pred), (MVE_VMOVimmi32 0), 1)))>;
4950
4951  def : Pat<(v8f16 (vselect (v8i16 MQPR:$pred), (v8f16 MQPR:$v1), (v8f16 MQPR:$v2))),
4952            (v8f16 (MVE_VPSEL MQPR:$v1, MQPR:$v2, 0,
4953                              (MVE_VCMPi16 (v8i16 MQPR:$pred), (MVE_VMOVimmi16 0), 1)))>;
4954  def : Pat<(v4f32 (vselect (v4i32 MQPR:$pred), (v4f32 MQPR:$v1), (v4f32 MQPR:$v2))),
4955            (v4f32 (MVE_VPSEL MQPR:$v1, MQPR:$v2, 0,
4956                              (MVE_VCMPi32 (v4i32 MQPR:$pred), (MVE_VMOVimmi32 0), 1)))>;
4957
4958  // Pred <-> Int
4959  def : Pat<(v16i8 (zext  (v16i1 VCCR:$pred))),
4960            (v16i8 (MVE_VPSEL (MVE_VMOVimmi8 1), (MVE_VMOVimmi8 0), 0, VCCR:$pred))>;
4961  def : Pat<(v8i16 (zext  (v8i1  VCCR:$pred))),
4962            (v8i16 (MVE_VPSEL (MVE_VMOVimmi16 1), (MVE_VMOVimmi16 0), 0, VCCR:$pred))>;
4963  def : Pat<(v4i32 (zext  (v4i1  VCCR:$pred))),
4964            (v4i32 (MVE_VPSEL (MVE_VMOVimmi32 1), (MVE_VMOVimmi32 0), 0, VCCR:$pred))>;
4965
4966  def : Pat<(v16i8 (sext  (v16i1 VCCR:$pred))),
4967            (v16i8 (MVE_VPSEL (MVE_VMOVimmi8 255), (MVE_VMOVimmi8 0), 0, VCCR:$pred))>;
4968  def : Pat<(v8i16 (sext  (v8i1  VCCR:$pred))),
4969            (v8i16 (MVE_VPSEL (MVE_VMOVimmi8 255), (MVE_VMOVimmi16 0), 0, VCCR:$pred))>;
4970  def : Pat<(v4i32 (sext  (v4i1  VCCR:$pred))),
4971            (v4i32 (MVE_VPSEL (MVE_VMOVimmi8 255), (MVE_VMOVimmi32 0), 0, VCCR:$pred))>;
4972
4973  def : Pat<(v16i8 (anyext  (v16i1 VCCR:$pred))),
4974            (v16i8 (MVE_VPSEL (MVE_VMOVimmi8 1), (MVE_VMOVimmi8 0), 0, VCCR:$pred))>;
4975  def : Pat<(v8i16 (anyext  (v8i1  VCCR:$pred))),
4976            (v8i16 (MVE_VPSEL (MVE_VMOVimmi16 1), (MVE_VMOVimmi16 0), 0, VCCR:$pred))>;
4977  def : Pat<(v4i32 (anyext  (v4i1  VCCR:$pred))),
4978            (v4i32 (MVE_VPSEL (MVE_VMOVimmi32 1), (MVE_VMOVimmi32 0), 0, VCCR:$pred))>;
4979
4980  def : Pat<(v16i1 (trunc (v16i8 MQPR:$v1))),
4981            (v16i1 (MVE_VCMPi32r (v16i8 MQPR:$v1), ZR, 1))>;
4982  def : Pat<(v8i1 (trunc (v8i16  MQPR:$v1))),
4983            (v8i1 (MVE_VCMPi32r (v8i16 MQPR:$v1), ZR, 1))>;
4984  def : Pat<(v4i1 (trunc (v4i32  MQPR:$v1))),
4985            (v4i1 (MVE_VCMPi32r (v4i32 MQPR:$v1), ZR, 1))>;
4986}
4987
4988let Predicates = [HasMVEFloat] in {
4989  // Pred <-> Float
4990  // 112 is 1.0 in float
4991  def : Pat<(v4f32 (uint_to_fp (v4i1 VCCR:$pred))),
4992            (v4f32 (MVE_VPSEL (v4f32 (MVE_VMOVimmf32 112)), (v4f32 (MVE_VMOVimmi32 0)), 0, VCCR:$pred))>;
4993  // 2620 in 1.0 in half
4994  def : Pat<(v8f16 (uint_to_fp (v8i1 VCCR:$pred))),
4995            (v8f16 (MVE_VPSEL (v8f16 (MVE_VMOVimmi16 2620)), (v8f16 (MVE_VMOVimmi16 0)), 0, VCCR:$pred))>;
4996  // 240 is -1.0 in float
4997  def : Pat<(v4f32 (sint_to_fp (v4i1 VCCR:$pred))),
4998            (v4f32 (MVE_VPSEL (v4f32 (MVE_VMOVimmf32 240)), (v4f32 (MVE_VMOVimmi32 0)), 0, VCCR:$pred))>;
4999  // 2748 is -1.0 in half
5000  def : Pat<(v8f16 (sint_to_fp (v8i1 VCCR:$pred))),
5001            (v8f16 (MVE_VPSEL (v8f16 (MVE_VMOVimmi16 2748)), (v8f16 (MVE_VMOVimmi16 0)), 0, VCCR:$pred))>;
5002
5003  def : Pat<(v4i1 (fp_to_uint (v4f32 MQPR:$v1))),
5004            (v4i1 (MVE_VCMPf32r (v4f32 MQPR:$v1), ZR, 1))>;
5005  def : Pat<(v8i1 (fp_to_uint (v8f16 MQPR:$v1))),
5006            (v8i1 (MVE_VCMPf16r (v8f16 MQPR:$v1), ZR, 1))>;
5007  def : Pat<(v4i1 (fp_to_sint (v4f32 MQPR:$v1))),
5008            (v4i1 (MVE_VCMPf32r (v4f32 MQPR:$v1), ZR, 1))>;
5009  def : Pat<(v8i1 (fp_to_sint (v8f16 MQPR:$v1))),
5010            (v8i1 (MVE_VCMPf16r (v8f16 MQPR:$v1), ZR, 1))>;
5011}
5012
5013def MVE_VPNOT : MVE_p<(outs VCCR:$P0), (ins VCCR:$P0_in), NoItinerary,
5014                      "vpnot", "", "", vpred_n, "", []> {
5015  let Inst{31-0} = 0b11111110001100010000111101001101;
5016  let Unpredictable{19-17} = 0b111;
5017  let Unpredictable{12} = 0b1;
5018  let Unpredictable{7} = 0b1;
5019  let Unpredictable{5} = 0b1;
5020
5021  let Constraints = "";
5022  let DecoderMethod = "DecodeMVEVPNOT";
5023}
5024
5025let Predicates = [HasMVEInt] in {
5026  def : Pat<(v4i1 (xor (v4i1 VCCR:$pred), (v4i1 (predicate_cast (i32 65535))))),
5027            (v4i1 (MVE_VPNOT (v4i1 VCCR:$pred)))>;
5028  def : Pat<(v8i1 (xor (v8i1 VCCR:$pred), (v8i1 (predicate_cast (i32 65535))))),
5029            (v8i1 (MVE_VPNOT (v8i1 VCCR:$pred)))>;
5030  def : Pat<(v16i1 (xor (v16i1 VCCR:$pred), (v16i1 (predicate_cast (i32 65535))))),
5031            (v16i1 (MVE_VPNOT (v16i1 VCCR:$pred)))>;
5032}
5033
5034
5035class MVE_loltp_start<dag iops, string asm, string ops, bits<2> size>
5036  : t2LOL<(outs GPRlr:$LR), iops, asm, ops> {
5037  bits<4> Rn;
5038  let Predicates = [HasMVEInt];
5039  let Inst{22} = 0b0;
5040  let Inst{21-20} = size;
5041  let Inst{19-16} = Rn{3-0};
5042  let Inst{12} = 0b0;
5043}
5044
5045class MVE_DLSTP<string asm, bits<2> size>
5046  : MVE_loltp_start<(ins rGPR:$Rn), asm, "$LR, $Rn", size> {
5047  let Inst{13} = 0b1;
5048  let Inst{11-1} = 0b00000000000;
5049  let Unpredictable{10-1} = 0b1111111111;
5050}
5051
5052class MVE_WLSTP<string asm, bits<2> size>
5053  : MVE_loltp_start<(ins rGPR:$Rn, wlslabel_u11:$label),
5054                    asm, "$LR, $Rn, $label", size> {
5055  bits<11> label;
5056  let Inst{13} = 0b0;
5057  let Inst{11} = label{0};
5058  let Inst{10-1} = label{10-1};
5059}
5060
5061def MVE_DLSTP_8  : MVE_DLSTP<"dlstp.8",  0b00>;
5062def MVE_DLSTP_16 : MVE_DLSTP<"dlstp.16", 0b01>;
5063def MVE_DLSTP_32 : MVE_DLSTP<"dlstp.32", 0b10>;
5064def MVE_DLSTP_64 : MVE_DLSTP<"dlstp.64", 0b11>;
5065
5066def MVE_WLSTP_8  : MVE_WLSTP<"wlstp.8",  0b00>;
5067def MVE_WLSTP_16 : MVE_WLSTP<"wlstp.16", 0b01>;
5068def MVE_WLSTP_32 : MVE_WLSTP<"wlstp.32", 0b10>;
5069def MVE_WLSTP_64 : MVE_WLSTP<"wlstp.64", 0b11>;
5070
5071class MVE_loltp_end<dag oops, dag iops, string asm, string ops>
5072  : t2LOL<oops, iops, asm, ops> {
5073  let Predicates = [HasMVEInt];
5074  let Inst{22-21} = 0b00;
5075  let Inst{19-16} = 0b1111;
5076  let Inst{12} = 0b0;
5077}
5078
5079def MVE_LETP : MVE_loltp_end<(outs GPRlr:$LRout),
5080                             (ins GPRlr:$LRin, lelabel_u11:$label),
5081                             "letp", "$LRin, $label"> {
5082  bits<11> label;
5083  let Inst{20} = 0b1;
5084  let Inst{13} = 0b0;
5085  let Inst{11} = label{0};
5086  let Inst{10-1} = label{10-1};
5087}
5088
5089def MVE_LCTP : MVE_loltp_end<(outs), (ins pred:$p), "lctp${p}", ""> {
5090  let Inst{20} = 0b0;
5091  let Inst{13} = 0b1;
5092  let Inst{11-1} = 0b00000000000;
5093  let Unpredictable{21-20} = 0b11;
5094  let Unpredictable{11-1} = 0b11111111111;
5095}
5096
5097
5098//===----------------------------------------------------------------------===//
5099// Patterns
5100//===----------------------------------------------------------------------===//
5101
5102class MVE_vector_store_typed<ValueType Ty, Instruction RegImmInst,
5103                             PatFrag StoreKind, int shift>
5104  : Pat<(StoreKind (Ty MQPR:$val), t2addrmode_imm7<shift>:$addr),
5105        (RegImmInst (Ty MQPR:$val), t2addrmode_imm7<shift>:$addr)>;
5106class MVE_vector_maskedstore_typed<ValueType Ty, Instruction RegImmInst,
5107                                   PatFrag StoreKind, int shift>
5108  : Pat<(StoreKind (Ty MQPR:$val), t2addrmode_imm7<shift>:$addr, VCCR:$pred),
5109        (RegImmInst (Ty MQPR:$val), t2addrmode_imm7<shift>:$addr, (i32 1), VCCR:$pred)>;
5110
5111multiclass MVE_vector_store<Instruction RegImmInst, PatFrag StoreKind,
5112                            int shift> {
5113  def : MVE_vector_store_typed<v16i8, RegImmInst, StoreKind, shift>;
5114  def : MVE_vector_store_typed<v8i16, RegImmInst, StoreKind, shift>;
5115  def : MVE_vector_store_typed<v8f16, RegImmInst, StoreKind, shift>;
5116  def : MVE_vector_store_typed<v4i32, RegImmInst, StoreKind, shift>;
5117  def : MVE_vector_store_typed<v4f32, RegImmInst, StoreKind, shift>;
5118  def : MVE_vector_store_typed<v2i64, RegImmInst, StoreKind, shift>;
5119  def : MVE_vector_store_typed<v2f64, RegImmInst, StoreKind, shift>;
5120}
5121
5122class MVE_vector_load_typed<ValueType Ty, Instruction RegImmInst,
5123                            PatFrag LoadKind, int shift>
5124  : Pat<(Ty (LoadKind t2addrmode_imm7<shift>:$addr)),
5125        (Ty (RegImmInst t2addrmode_imm7<shift>:$addr))>;
5126class MVE_vector_maskedload_typed<ValueType Ty, Instruction RegImmInst,
5127                                  PatFrag LoadKind, int shift>
5128  : Pat<(Ty (LoadKind t2addrmode_imm7<shift>:$addr, VCCR:$pred, (Ty NEONimmAllZerosV))),
5129        (Ty (RegImmInst t2addrmode_imm7<shift>:$addr, (i32 1), VCCR:$pred))>;
5130
5131multiclass MVE_vector_load<Instruction RegImmInst, PatFrag LoadKind,
5132                           int shift> {
5133  def : MVE_vector_load_typed<v16i8, RegImmInst, LoadKind, shift>;
5134  def : MVE_vector_load_typed<v8i16, RegImmInst, LoadKind, shift>;
5135  def : MVE_vector_load_typed<v8f16, RegImmInst, LoadKind, shift>;
5136  def : MVE_vector_load_typed<v4i32, RegImmInst, LoadKind, shift>;
5137  def : MVE_vector_load_typed<v4f32, RegImmInst, LoadKind, shift>;
5138  def : MVE_vector_load_typed<v2i64, RegImmInst, LoadKind, shift>;
5139  def : MVE_vector_load_typed<v2f64, RegImmInst, LoadKind, shift>;
5140}
5141
5142class MVE_vector_offset_store_typed<ValueType Ty, Instruction Opcode,
5143                                    PatFrag StoreKind, int shift>
5144  : Pat<(StoreKind (Ty MQPR:$Rt), tGPR:$Rn, t2am_imm7_offset<shift>:$addr),
5145        (Opcode MQPR:$Rt, tGPR:$Rn, t2am_imm7_offset<shift>:$addr)>;
5146
5147multiclass MVE_vector_offset_store<Instruction RegImmInst, PatFrag StoreKind,
5148                                   int shift> {
5149  def : MVE_vector_offset_store_typed<v16i8, RegImmInst, StoreKind, shift>;
5150  def : MVE_vector_offset_store_typed<v8i16, RegImmInst, StoreKind, shift>;
5151  def : MVE_vector_offset_store_typed<v8f16, RegImmInst, StoreKind, shift>;
5152  def : MVE_vector_offset_store_typed<v4i32, RegImmInst, StoreKind, shift>;
5153  def : MVE_vector_offset_store_typed<v4f32, RegImmInst, StoreKind, shift>;
5154  def : MVE_vector_offset_store_typed<v2i64, RegImmInst, StoreKind, shift>;
5155  def : MVE_vector_offset_store_typed<v2f64, RegImmInst, StoreKind, shift>;
5156}
5157
5158def aligned32_pre_store : PatFrag<(ops node:$val, node:$ptr, node:$offset),
5159                                  (pre_store node:$val, node:$ptr, node:$offset), [{
5160  return cast<StoreSDNode>(N)->getAlignment() >= 4;
5161}]>;
5162def aligned32_post_store : PatFrag<(ops node:$val, node:$ptr, node:$offset),
5163                                   (post_store node:$val, node:$ptr, node:$offset), [{
5164  return cast<StoreSDNode>(N)->getAlignment() >= 4;
5165}]>;
5166def aligned16_pre_store : PatFrag<(ops node:$val, node:$ptr, node:$offset),
5167                                  (pre_store node:$val, node:$ptr, node:$offset), [{
5168  return cast<StoreSDNode>(N)->getAlignment() >= 2;
5169}]>;
5170def aligned16_post_store : PatFrag<(ops node:$val, node:$ptr, node:$offset),
5171                                   (post_store node:$val, node:$ptr, node:$offset), [{
5172  return cast<StoreSDNode>(N)->getAlignment() >= 2;
5173}]>;
5174
5175
5176def maskedload8 : PatFrag<(ops node:$ptr, node:$pred, node:$passthru),
5177                          (masked_ld node:$ptr, node:$pred, node:$passthru), [{
5178  auto *Ld = cast<MaskedLoadSDNode>(N);
5179  return Ld->getMemoryVT().getScalarType() == MVT::i8;
5180}]>;
5181def sextmaskedload8 : PatFrag<(ops node:$ptr, node:$pred, node:$passthru),
5182                              (maskedload8 node:$ptr, node:$pred, node:$passthru), [{
5183  return cast<MaskedLoadSDNode>(N)->getExtensionType() == ISD::SEXTLOAD;
5184}]>;
5185def zextmaskedload8 : PatFrag<(ops node:$ptr, node:$pred, node:$passthru),
5186                              (maskedload8 node:$ptr, node:$pred, node:$passthru), [{
5187  return cast<MaskedLoadSDNode>(N)->getExtensionType() == ISD::ZEXTLOAD;
5188}]>;
5189def extmaskedload8 : PatFrag<(ops node:$ptr, node:$pred, node:$passthru),
5190                             (maskedload8 node:$ptr, node:$pred, node:$passthru), [{
5191  auto *Ld = cast<MaskedLoadSDNode>(N);
5192  EVT ScalarVT = Ld->getMemoryVT().getScalarType();
5193  return ScalarVT.isInteger() && Ld->getExtensionType() == ISD::EXTLOAD;
5194}]>;
5195def alignedmaskedload16: PatFrag<(ops node:$ptr, node:$pred, node:$passthru),
5196                                 (masked_ld node:$ptr, node:$pred, node:$passthru), [{
5197  auto *Ld = cast<MaskedLoadSDNode>(N);
5198  EVT ScalarVT = Ld->getMemoryVT().getScalarType();
5199  return (ScalarVT == MVT::i16 || ScalarVT == MVT::f16) && Ld->getAlignment() >= 2;
5200}]>;
5201def sextmaskedload16 : PatFrag<(ops node:$ptr, node:$pred, node:$passthru),
5202                               (alignedmaskedload16 node:$ptr, node:$pred, node:$passthru), [{
5203  return cast<MaskedLoadSDNode>(N)->getExtensionType() == ISD::SEXTLOAD;
5204}]>;
5205def zextmaskedload16 : PatFrag<(ops node:$ptr, node:$pred, node:$passthru),
5206                               (alignedmaskedload16 node:$ptr, node:$pred, node:$passthru), [{
5207  return cast<MaskedLoadSDNode>(N)->getExtensionType() == ISD::ZEXTLOAD;
5208}]>;
5209def extmaskedload16 : PatFrag<(ops node:$ptr, node:$pred, node:$passthru),
5210                              (alignedmaskedload16 node:$ptr, node:$pred, node:$passthru), [{
5211  auto *Ld = cast<MaskedLoadSDNode>(N);
5212  EVT ScalarVT = Ld->getMemoryVT().getScalarType();
5213  return ScalarVT.isInteger() && Ld->getExtensionType() == ISD::EXTLOAD;
5214}]>;
5215def alignedmaskedload32: PatFrag<(ops node:$ptr, node:$pred, node:$passthru),
5216                                 (masked_ld node:$ptr, node:$pred, node:$passthru), [{
5217  auto *Ld = cast<MaskedLoadSDNode>(N);
5218  EVT ScalarVT = Ld->getMemoryVT().getScalarType();
5219  return (ScalarVT == MVT::i32 || ScalarVT == MVT::f32) && Ld->getAlignment() >= 4;
5220}]>;
5221
5222def maskedstore8 : PatFrag<(ops node:$val, node:$ptr, node:$pred),
5223                           (masked_st node:$val, node:$ptr, node:$pred), [{
5224  return cast<MaskedStoreSDNode>(N)->getMemoryVT().getScalarType() == MVT::i8;
5225}]>;
5226def truncatingmaskedstore8 : PatFrag<(ops node:$val, node:$ptr, node:$pred),
5227                                     (maskedstore8 node:$val, node:$ptr, node:$pred), [{
5228  return cast<MaskedStoreSDNode>(N)->isTruncatingStore();
5229}]>;
5230def maskedstore16 : PatFrag<(ops node:$val, node:$ptr, node:$pred),
5231                            (masked_st node:$val, node:$ptr, node:$pred), [{
5232  auto *St = cast<MaskedStoreSDNode>(N);
5233  EVT ScalarVT = St->getMemoryVT().getScalarType();
5234  return (ScalarVT == MVT::i16 || ScalarVT == MVT::f16) && St->getAlignment() >= 2;
5235}]>;
5236
5237def truncatingmaskedstore16 : PatFrag<(ops node:$val, node:$ptr, node:$pred),
5238                                      (maskedstore16 node:$val, node:$ptr, node:$pred), [{
5239  return cast<MaskedStoreSDNode>(N)->isTruncatingStore();
5240}]>;
5241def maskedstore32 : PatFrag<(ops node:$val, node:$ptr, node:$pred),
5242                            (masked_st node:$val, node:$ptr, node:$pred), [{
5243  auto *St = cast<MaskedStoreSDNode>(N);
5244  EVT ScalarVT = St->getMemoryVT().getScalarType();
5245  return (ScalarVT == MVT::i32 || ScalarVT == MVT::f32) && St->getAlignment() >= 4;
5246}]>;
5247
5248let Predicates = [HasMVEInt, IsLE] in {
5249  // Stores
5250  defm : MVE_vector_store<MVE_VSTRBU8, byte_alignedstore, 0>;
5251  defm : MVE_vector_store<MVE_VSTRHU16, hword_alignedstore, 1>;
5252  defm : MVE_vector_store<MVE_VSTRWU32, alignedstore32, 2>;
5253
5254  // Loads
5255  defm : MVE_vector_load<MVE_VLDRBU8, byte_alignedload, 0>;
5256  defm : MVE_vector_load<MVE_VLDRHU16, hword_alignedload, 1>;
5257  defm : MVE_vector_load<MVE_VLDRWU32, alignedload32, 2>;
5258
5259  // Pre/post inc stores
5260  defm : MVE_vector_offset_store<MVE_VSTRBU8_pre, pre_store, 0>;
5261  defm : MVE_vector_offset_store<MVE_VSTRBU8_post, post_store, 0>;
5262  defm : MVE_vector_offset_store<MVE_VSTRHU16_pre, aligned16_pre_store, 1>;
5263  defm : MVE_vector_offset_store<MVE_VSTRHU16_post, aligned16_post_store, 1>;
5264  defm : MVE_vector_offset_store<MVE_VSTRWU32_pre, aligned32_pre_store, 2>;
5265  defm : MVE_vector_offset_store<MVE_VSTRWU32_post, aligned32_post_store, 2>;
5266}
5267
5268let Predicates = [HasMVEInt, IsBE] in {
5269  // Aligned Stores
5270  def : MVE_vector_store_typed<v16i8, MVE_VSTRBU8, store, 0>;
5271  def : MVE_vector_store_typed<v8i16, MVE_VSTRHU16, alignedstore16, 1>;
5272  def : MVE_vector_store_typed<v8f16, MVE_VSTRHU16, alignedstore16, 1>;
5273  def : MVE_vector_store_typed<v4i32, MVE_VSTRWU32, alignedstore32, 2>;
5274  def : MVE_vector_store_typed<v4f32, MVE_VSTRWU32, alignedstore32, 2>;
5275
5276  // Aligned Loads
5277  def : MVE_vector_load_typed<v16i8, MVE_VLDRBU8, load, 0>;
5278  def : MVE_vector_load_typed<v8i16, MVE_VLDRHU16, alignedload16, 1>;
5279  def : MVE_vector_load_typed<v8f16, MVE_VLDRHU16, alignedload16, 1>;
5280  def : MVE_vector_load_typed<v4i32, MVE_VLDRWU32, alignedload32, 2>;
5281  def : MVE_vector_load_typed<v4f32, MVE_VLDRWU32, alignedload32, 2>;
5282
5283  // Other unaligned loads/stores need to go though a VREV
5284  def : Pat<(v2f64 (load t2addrmode_imm7<0>:$addr)),
5285            (v2f64 (MVE_VREV64_8 (MVE_VLDRBU8 t2addrmode_imm7<0>:$addr)))>;
5286  def : Pat<(v2i64 (load t2addrmode_imm7<0>:$addr)),
5287            (v2i64 (MVE_VREV64_8 (MVE_VLDRBU8 t2addrmode_imm7<0>:$addr)))>;
5288  def : Pat<(v4i32 (load t2addrmode_imm7<0>:$addr)),
5289            (v4i32 (MVE_VREV32_8 (MVE_VLDRBU8 t2addrmode_imm7<0>:$addr)))>;
5290  def : Pat<(v4f32 (load t2addrmode_imm7<0>:$addr)),
5291            (v4f32 (MVE_VREV32_8 (MVE_VLDRBU8 t2addrmode_imm7<0>:$addr)))>;
5292  def : Pat<(v8i16 (load t2addrmode_imm7<0>:$addr)),
5293            (v8i16 (MVE_VREV16_8 (MVE_VLDRBU8 t2addrmode_imm7<0>:$addr)))>;
5294  def : Pat<(v8f16 (load t2addrmode_imm7<0>:$addr)),
5295            (v8f16 (MVE_VREV16_8 (MVE_VLDRBU8 t2addrmode_imm7<0>:$addr)))>;
5296  def : Pat<(store (v2f64 MQPR:$val), t2addrmode_imm7<0>:$addr),
5297            (MVE_VSTRBU8 (MVE_VREV64_8 MQPR:$val), t2addrmode_imm7<0>:$addr)>;
5298  def : Pat<(store (v2i64 MQPR:$val), t2addrmode_imm7<0>:$addr),
5299            (MVE_VSTRBU8 (MVE_VREV64_8 MQPR:$val), t2addrmode_imm7<0>:$addr)>;
5300  def : Pat<(store (v4i32 MQPR:$val), t2addrmode_imm7<0>:$addr),
5301            (MVE_VSTRBU8 (MVE_VREV32_8 MQPR:$val), t2addrmode_imm7<0>:$addr)>;
5302  def : Pat<(store (v4f32 MQPR:$val), t2addrmode_imm7<0>:$addr),
5303            (MVE_VSTRBU8 (MVE_VREV32_8 MQPR:$val), t2addrmode_imm7<0>:$addr)>;
5304  def : Pat<(store (v8i16 MQPR:$val), t2addrmode_imm7<0>:$addr),
5305            (MVE_VSTRBU8 (MVE_VREV16_8 MQPR:$val), t2addrmode_imm7<0>:$addr)>;
5306  def : Pat<(store (v8f16 MQPR:$val), t2addrmode_imm7<0>:$addr),
5307            (MVE_VSTRBU8 (MVE_VREV16_8 MQPR:$val), t2addrmode_imm7<0>:$addr)>;
5308
5309  // Pre/Post inc stores
5310  def : MVE_vector_offset_store_typed<v16i8, MVE_VSTRBU8_pre, pre_store, 0>;
5311  def : MVE_vector_offset_store_typed<v16i8, MVE_VSTRBU8_post, post_store, 0>;
5312  def : MVE_vector_offset_store_typed<v8i16, MVE_VSTRHU16_pre, aligned16_pre_store, 1>;
5313  def : MVE_vector_offset_store_typed<v8i16, MVE_VSTRHU16_post, aligned16_post_store, 1>;
5314  def : MVE_vector_offset_store_typed<v8f16, MVE_VSTRHU16_pre, aligned16_pre_store, 1>;
5315  def : MVE_vector_offset_store_typed<v8f16, MVE_VSTRHU16_post, aligned16_post_store, 1>;
5316  def : MVE_vector_offset_store_typed<v4i32, MVE_VSTRWU32_pre, aligned32_pre_store, 2>;
5317  def : MVE_vector_offset_store_typed<v4i32, MVE_VSTRWU32_post, aligned32_post_store, 2>;
5318  def : MVE_vector_offset_store_typed<v4f32, MVE_VSTRWU32_pre, aligned32_pre_store, 2>;
5319  def : MVE_vector_offset_store_typed<v4f32, MVE_VSTRWU32_post, aligned32_post_store, 2>;
5320}
5321
5322let Predicates = [HasMVEInt] in {
5323  // Aligned masked store, shared between LE and BE
5324  def : MVE_vector_maskedstore_typed<v16i8, MVE_VSTRBU8, maskedstore8, 0>;
5325  def : MVE_vector_maskedstore_typed<v8i16, MVE_VSTRHU16, maskedstore16, 1>;
5326  def : MVE_vector_maskedstore_typed<v8f16, MVE_VSTRHU16, maskedstore16, 1>;
5327  def : MVE_vector_maskedstore_typed<v4i32, MVE_VSTRWU32, maskedstore32, 2>;
5328  def : MVE_vector_maskedstore_typed<v4f32, MVE_VSTRWU32, maskedstore32, 2>;
5329  // Truncating stores
5330  def : Pat<(truncatingmaskedstore8 (v8i16 MQPR:$val), t2addrmode_imm7<0>:$addr, VCCR:$pred),
5331            (MVE_VSTRB16 MQPR:$val, t2addrmode_imm7<0>:$addr, (i32 1), VCCR:$pred)>;
5332  def : Pat<(truncatingmaskedstore8 (v4i32 MQPR:$val), t2addrmode_imm7<0>:$addr, VCCR:$pred),
5333            (MVE_VSTRB32 MQPR:$val, t2addrmode_imm7<0>:$addr, (i32 1), VCCR:$pred)>;
5334  def : Pat<(truncatingmaskedstore16 (v4i32 MQPR:$val), t2addrmode_imm7<1>:$addr, VCCR:$pred),
5335            (MVE_VSTRH32 MQPR:$val, t2addrmode_imm7<1>:$addr, (i32 1), VCCR:$pred)>;
5336  // Aligned masked loads
5337  def : MVE_vector_maskedload_typed<v16i8, MVE_VLDRBU8, maskedload8, 0>;
5338  def : MVE_vector_maskedload_typed<v8i16, MVE_VLDRHU16, alignedmaskedload16, 1>;
5339  def : MVE_vector_maskedload_typed<v8f16, MVE_VLDRHU16, alignedmaskedload16, 1>;
5340  def : MVE_vector_maskedload_typed<v4i32, MVE_VLDRWU32, alignedmaskedload32, 2>;
5341  def : MVE_vector_maskedload_typed<v4f32, MVE_VLDRWU32, alignedmaskedload32, 2>;
5342  // Extending masked loads.
5343  def : Pat<(v8i16 (sextmaskedload8 t2addrmode_imm7<0>:$addr, VCCR:$pred,
5344                    (v8i16 NEONimmAllZerosV))),
5345            (v8i16 (MVE_VLDRBS16 t2addrmode_imm7<0>:$addr, (i32 1), VCCR:$pred))>;
5346  def : Pat<(v4i32 (sextmaskedload8 t2addrmode_imm7<0>:$addr, VCCR:$pred,
5347                    (v4i32 NEONimmAllZerosV))),
5348            (v4i32 (MVE_VLDRBS32 t2addrmode_imm7<0>:$addr, (i32 1), VCCR:$pred))>;
5349  def : Pat<(v8i16 (zextmaskedload8 t2addrmode_imm7<0>:$addr, VCCR:$pred,
5350                    (v8i16 NEONimmAllZerosV))),
5351            (v8i16 (MVE_VLDRBU16 t2addrmode_imm7<0>:$addr, (i32 1), VCCR:$pred))>;
5352  def : Pat<(v4i32 (zextmaskedload8 t2addrmode_imm7<0>:$addr, VCCR:$pred,
5353                    (v4i32 NEONimmAllZerosV))),
5354            (v4i32 (MVE_VLDRBU32 t2addrmode_imm7<0>:$addr, (i32 1), VCCR:$pred))>;
5355  def : Pat<(v8i16 (extmaskedload8 t2addrmode_imm7<0>:$addr, VCCR:$pred,
5356                    (v8i16 NEONimmAllZerosV))),
5357            (v8i16 (MVE_VLDRBU16 t2addrmode_imm7<0>:$addr, (i32 1), VCCR:$pred))>;
5358  def : Pat<(v4i32 (extmaskedload8 t2addrmode_imm7<0>:$addr, VCCR:$pred,
5359                    (v4i32 NEONimmAllZerosV))),
5360            (v4i32 (MVE_VLDRBU32 t2addrmode_imm7<0>:$addr, (i32 1), VCCR:$pred))>;
5361  def : Pat<(v4i32 (sextmaskedload16 t2addrmode_imm7<1>:$addr, VCCR:$pred,
5362                    (v4i32 NEONimmAllZerosV))),
5363            (v4i32 (MVE_VLDRHS32 t2addrmode_imm7<1>:$addr, (i32 1), VCCR:$pred))>;
5364  def : Pat<(v4i32 (zextmaskedload16 t2addrmode_imm7<1>:$addr, VCCR:$pred,
5365                    (v4i32 NEONimmAllZerosV))),
5366            (v4i32 (MVE_VLDRHU32 t2addrmode_imm7<1>:$addr, (i32 1), VCCR:$pred))>;
5367  def : Pat<(v4i32 (extmaskedload16 t2addrmode_imm7<1>:$addr, VCCR:$pred,
5368                    (v4i32 NEONimmAllZerosV))),
5369            (v4i32 (MVE_VLDRHU32 t2addrmode_imm7<1>:$addr, (i32 1), VCCR:$pred))>;
5370}
5371
5372// Widening/Narrowing Loads/Stores
5373
5374let MinAlignment = 2 in {
5375  def truncstorevi16_align2 : PatFrag<(ops node:$val, node:$ptr),
5376                                      (truncstorevi16 node:$val, node:$ptr)>;
5377  def post_truncstvi16_align2 : PatFrag<(ops node:$val, node:$base, node:$offset),
5378                                        (post_truncstvi16 node:$val, node:$base, node:$offset)>;
5379  def pre_truncstvi16_align2 : PatFrag<(ops node:$val, node:$base, node:$offset),
5380                                       (pre_truncstvi16 node:$val, node:$base, node:$offset)>;
5381}
5382
5383let Predicates = [HasMVEInt] in {
5384  def : Pat<(truncstorevi8 (v8i16 MQPR:$val), taddrmode_imm7<0>:$addr),
5385            (MVE_VSTRB16 MQPR:$val, taddrmode_imm7<0>:$addr)>;
5386  def : Pat<(truncstorevi8 (v4i32 MQPR:$val), taddrmode_imm7<0>:$addr),
5387            (MVE_VSTRB32 MQPR:$val, taddrmode_imm7<0>:$addr)>;
5388  def : Pat<(truncstorevi16_align2 (v4i32 MQPR:$val), taddrmode_imm7<1>:$addr),
5389            (MVE_VSTRH32 MQPR:$val, taddrmode_imm7<1>:$addr)>;
5390
5391  def : Pat<(post_truncstvi8 (v8i16 MQPR:$Rt), tGPR:$Rn, t2am_imm7_offset<0>:$addr),
5392            (MVE_VSTRB16_post MQPR:$Rt, tGPR:$Rn, t2am_imm7_offset<0>:$addr)>;
5393  def : Pat<(post_truncstvi8 (v4i32 MQPR:$Rt), tGPR:$Rn, t2am_imm7_offset<0>:$addr),
5394            (MVE_VSTRB32_post MQPR:$Rt, tGPR:$Rn, t2am_imm7_offset<0>:$addr)>;
5395  def : Pat<(post_truncstvi16_align2 (v4i32 MQPR:$Rt), tGPR:$Rn, t2am_imm7_offset<1>:$addr),
5396            (MVE_VSTRH32_post MQPR:$Rt, tGPR:$Rn, t2am_imm7_offset<1>:$addr)>;
5397
5398  def : Pat<(pre_truncstvi8 (v8i16 MQPR:$Rt), tGPR:$Rn, t2am_imm7_offset<0>:$addr),
5399            (MVE_VSTRB16_pre MQPR:$Rt, tGPR:$Rn, t2am_imm7_offset<0>:$addr)>;
5400  def : Pat<(pre_truncstvi8 (v4i32 MQPR:$Rt), tGPR:$Rn, t2am_imm7_offset<0>:$addr),
5401            (MVE_VSTRB32_pre MQPR:$Rt, tGPR:$Rn, t2am_imm7_offset<0>:$addr)>;
5402  def : Pat<(pre_truncstvi16_align2 (v4i32 MQPR:$Rt), tGPR:$Rn, t2am_imm7_offset<1>:$addr),
5403            (MVE_VSTRH32_pre MQPR:$Rt, tGPR:$Rn, t2am_imm7_offset<1>:$addr)>;
5404}
5405
5406
5407let MinAlignment = 2 in {
5408  def extloadvi16_align2  : PatFrag<(ops node:$ptr), (extloadvi16 node:$ptr)>;
5409  def sextloadvi16_align2 : PatFrag<(ops node:$ptr), (sextloadvi16 node:$ptr)>;
5410  def zextloadvi16_align2 : PatFrag<(ops node:$ptr), (zextloadvi16 node:$ptr)>;
5411}
5412
5413multiclass MVEExtLoad<string DestLanes, string DestElemBits,
5414                      string SrcElemBits, string SrcElemType,
5415                      string Align, Operand am> {
5416  def _Any : Pat<(!cast<ValueType>("v" # DestLanes # "i" # DestElemBits)
5417                   (!cast<PatFrag>("extloadvi"  # SrcElemBits # Align) am:$addr)),
5418                 (!cast<Instruction>("MVE_VLDR" # SrcElemType # "U" # DestElemBits)
5419                   am:$addr)>;
5420  def _Z   : Pat<(!cast<ValueType>("v" # DestLanes # "i" # DestElemBits)
5421                   (!cast<PatFrag>("zextloadvi"  # SrcElemBits # Align) am:$addr)),
5422                 (!cast<Instruction>("MVE_VLDR" # SrcElemType # "U" # DestElemBits)
5423                   am:$addr)>;
5424  def _S   : Pat<(!cast<ValueType>("v" # DestLanes # "i" # DestElemBits)
5425                   (!cast<PatFrag>("sextloadvi"  # SrcElemBits # Align) am:$addr)),
5426                 (!cast<Instruction>("MVE_VLDR" # SrcElemType # "S" # DestElemBits)
5427                   am:$addr)>;
5428}
5429
5430let Predicates = [HasMVEInt] in {
5431  defm : MVEExtLoad<"4", "32", "8",  "B", "", taddrmode_imm7<0>>;
5432  defm : MVEExtLoad<"8", "16", "8",  "B", "", taddrmode_imm7<0>>;
5433  defm : MVEExtLoad<"4", "32", "16", "H", "_align2", taddrmode_imm7<1>>;
5434}
5435
5436
5437// Bit convert patterns
5438
5439let Predicates = [HasMVEInt] in {
5440  def : Pat<(v2f64 (bitconvert (v2i64 MQPR:$src))), (v2f64 MQPR:$src)>;
5441  def : Pat<(v2i64 (bitconvert (v2f64 MQPR:$src))), (v2i64 MQPR:$src)>;
5442
5443  def : Pat<(v4i32 (bitconvert (v4f32 MQPR:$src))), (v4i32 MQPR:$src)>;
5444  def : Pat<(v4f32 (bitconvert (v4i32 MQPR:$src))), (v4f32 MQPR:$src)>;
5445
5446  def : Pat<(v8i16 (bitconvert (v8f16 MQPR:$src))), (v8i16  MQPR:$src)>;
5447  def : Pat<(v8f16 (bitconvert (v8i16 MQPR:$src))), (v8f16  MQPR:$src)>;
5448}
5449
5450let Predicates = [IsLE,HasMVEInt] in {
5451  def : Pat<(v2f64 (bitconvert (v4f32 MQPR:$src))), (v2f64 MQPR:$src)>;
5452  def : Pat<(v2f64 (bitconvert (v4i32 MQPR:$src))), (v2f64 MQPR:$src)>;
5453  def : Pat<(v2f64 (bitconvert (v8f16 MQPR:$src))), (v2f64 MQPR:$src)>;
5454  def : Pat<(v2f64 (bitconvert (v8i16 MQPR:$src))), (v2f64 MQPR:$src)>;
5455  def : Pat<(v2f64 (bitconvert (v16i8 MQPR:$src))), (v2f64 MQPR:$src)>;
5456
5457  def : Pat<(v2i64 (bitconvert (v4f32 MQPR:$src))), (v2i64 MQPR:$src)>;
5458  def : Pat<(v2i64 (bitconvert (v4i32 MQPR:$src))), (v2i64 MQPR:$src)>;
5459  def : Pat<(v2i64 (bitconvert (v8f16 MQPR:$src))), (v2i64 MQPR:$src)>;
5460  def : Pat<(v2i64 (bitconvert (v8i16 MQPR:$src))), (v2i64 MQPR:$src)>;
5461  def : Pat<(v2i64 (bitconvert (v16i8 MQPR:$src))), (v2i64 MQPR:$src)>;
5462
5463  def : Pat<(v4f32 (bitconvert (v2f64 MQPR:$src))), (v4f32 MQPR:$src)>;
5464  def : Pat<(v4f32 (bitconvert (v2i64 MQPR:$src))), (v4f32 MQPR:$src)>;
5465  def : Pat<(v4f32 (bitconvert (v8f16 MQPR:$src))), (v4f32 MQPR:$src)>;
5466  def : Pat<(v4f32 (bitconvert (v8i16 MQPR:$src))), (v4f32 MQPR:$src)>;
5467  def : Pat<(v4f32 (bitconvert (v16i8 MQPR:$src))), (v4f32 MQPR:$src)>;
5468
5469  def : Pat<(v4i32 (bitconvert (v2f64 MQPR:$src))), (v4i32 MQPR:$src)>;
5470  def : Pat<(v4i32 (bitconvert (v2i64 MQPR:$src))), (v4i32 MQPR:$src)>;
5471  def : Pat<(v4i32 (bitconvert (v8f16 MQPR:$src))), (v4i32 MQPR:$src)>;
5472  def : Pat<(v4i32 (bitconvert (v8i16 MQPR:$src))), (v4i32 MQPR:$src)>;
5473  def : Pat<(v4i32 (bitconvert (v16i8 MQPR:$src))), (v4i32 MQPR:$src)>;
5474
5475  def : Pat<(v8f16 (bitconvert (v2f64 MQPR:$src))), (v8f16 MQPR:$src)>;
5476  def : Pat<(v8f16 (bitconvert (v2i64 MQPR:$src))), (v8f16 MQPR:$src)>;
5477  def : Pat<(v8f16 (bitconvert (v4f32 MQPR:$src))), (v8f16 MQPR:$src)>;
5478  def : Pat<(v8f16 (bitconvert (v4i32 MQPR:$src))), (v8f16 MQPR:$src)>;
5479  def : Pat<(v8f16 (bitconvert (v16i8 MQPR:$src))), (v8f16 MQPR:$src)>;
5480
5481  def : Pat<(v8i16 (bitconvert (v2f64 MQPR:$src))), (v8i16 MQPR:$src)>;
5482  def : Pat<(v8i16 (bitconvert (v2i64 MQPR:$src))), (v8i16 MQPR:$src)>;
5483  def : Pat<(v8i16 (bitconvert (v4f32 MQPR:$src))), (v8i16 MQPR:$src)>;
5484  def : Pat<(v8i16 (bitconvert (v4i32 MQPR:$src))), (v8i16 MQPR:$src)>;
5485  def : Pat<(v8i16 (bitconvert (v16i8 MQPR:$src))), (v8i16 MQPR:$src)>;
5486
5487  def : Pat<(v16i8 (bitconvert (v2f64 MQPR:$src))), (v16i8 MQPR:$src)>;
5488  def : Pat<(v16i8 (bitconvert (v2i64 MQPR:$src))), (v16i8 MQPR:$src)>;
5489  def : Pat<(v16i8 (bitconvert (v4f32 MQPR:$src))), (v16i8 MQPR:$src)>;
5490  def : Pat<(v16i8 (bitconvert (v4i32 MQPR:$src))), (v16i8 MQPR:$src)>;
5491  def : Pat<(v16i8 (bitconvert (v8f16 MQPR:$src))), (v16i8 MQPR:$src)>;
5492  def : Pat<(v16i8 (bitconvert (v8i16 MQPR:$src))), (v16i8 MQPR:$src)>;
5493}
5494
5495let Predicates = [IsBE,HasMVEInt] in {
5496  def : Pat<(v2f64 (bitconvert (v4f32 MQPR:$src))), (v2f64 (MVE_VREV64_32 MQPR:$src))>;
5497  def : Pat<(v2f64 (bitconvert (v4i32 MQPR:$src))), (v2f64 (MVE_VREV64_32 MQPR:$src))>;
5498  def : Pat<(v2f64 (bitconvert (v8f16 MQPR:$src))), (v2f64 (MVE_VREV64_16 MQPR:$src))>;
5499  def : Pat<(v2f64 (bitconvert (v8i16 MQPR:$src))), (v2f64 (MVE_VREV64_16 MQPR:$src))>;
5500  def : Pat<(v2f64 (bitconvert (v16i8 MQPR:$src))), (v2f64 (MVE_VREV64_8 MQPR:$src))>;
5501
5502  def : Pat<(v2i64 (bitconvert (v4f32 MQPR:$src))), (v2i64 (MVE_VREV64_32 MQPR:$src))>;
5503  def : Pat<(v2i64 (bitconvert (v4i32 MQPR:$src))), (v2i64 (MVE_VREV64_32 MQPR:$src))>;
5504  def : Pat<(v2i64 (bitconvert (v8f16 MQPR:$src))), (v2i64 (MVE_VREV64_16 MQPR:$src))>;
5505  def : Pat<(v2i64 (bitconvert (v8i16 MQPR:$src))), (v2i64 (MVE_VREV64_16 MQPR:$src))>;
5506  def : Pat<(v2i64 (bitconvert (v16i8 MQPR:$src))), (v2i64 (MVE_VREV64_8 MQPR:$src))>;
5507
5508  def : Pat<(v4f32 (bitconvert (v2f64 MQPR:$src))), (v4f32 (MVE_VREV64_32 MQPR:$src))>;
5509  def : Pat<(v4f32 (bitconvert (v2i64 MQPR:$src))), (v4f32 (MVE_VREV64_32 MQPR:$src))>;
5510  def : Pat<(v4f32 (bitconvert (v8f16 MQPR:$src))), (v4f32 (MVE_VREV32_16 MQPR:$src))>;
5511  def : Pat<(v4f32 (bitconvert (v8i16 MQPR:$src))), (v4f32 (MVE_VREV32_16 MQPR:$src))>;
5512  def : Pat<(v4f32 (bitconvert (v16i8 MQPR:$src))), (v4f32 (MVE_VREV32_8 MQPR:$src))>;
5513
5514  def : Pat<(v4i32 (bitconvert (v2f64 MQPR:$src))), (v4i32 (MVE_VREV64_32 MQPR:$src))>;
5515  def : Pat<(v4i32 (bitconvert (v2i64 MQPR:$src))), (v4i32 (MVE_VREV64_32 MQPR:$src))>;
5516  def : Pat<(v4i32 (bitconvert (v8f16 MQPR:$src))), (v4i32 (MVE_VREV32_16 MQPR:$src))>;
5517  def : Pat<(v4i32 (bitconvert (v8i16 MQPR:$src))), (v4i32 (MVE_VREV32_16 MQPR:$src))>;
5518  def : Pat<(v4i32 (bitconvert (v16i8 MQPR:$src))), (v4i32 (MVE_VREV32_8 MQPR:$src))>;
5519
5520  def : Pat<(v8f16 (bitconvert (v2f64 MQPR:$src))), (v8f16 (MVE_VREV64_16 MQPR:$src))>;
5521  def : Pat<(v8f16 (bitconvert (v2i64 MQPR:$src))), (v8f16 (MVE_VREV64_16 MQPR:$src))>;
5522  def : Pat<(v8f16 (bitconvert (v4f32 MQPR:$src))), (v8f16 (MVE_VREV32_16 MQPR:$src))>;
5523  def : Pat<(v8f16 (bitconvert (v4i32 MQPR:$src))), (v8f16 (MVE_VREV32_16 MQPR:$src))>;
5524  def : Pat<(v8f16 (bitconvert (v16i8 MQPR:$src))), (v8f16 (MVE_VREV16_8 MQPR:$src))>;
5525
5526  def : Pat<(v8i16 (bitconvert (v2f64 MQPR:$src))), (v8i16 (MVE_VREV64_16 MQPR:$src))>;
5527  def : Pat<(v8i16 (bitconvert (v2i64 MQPR:$src))), (v8i16 (MVE_VREV64_16 MQPR:$src))>;
5528  def : Pat<(v8i16 (bitconvert (v4f32 MQPR:$src))), (v8i16 (MVE_VREV32_16 MQPR:$src))>;
5529  def : Pat<(v8i16 (bitconvert (v4i32 MQPR:$src))), (v8i16 (MVE_VREV32_16 MQPR:$src))>;
5530  def : Pat<(v8i16 (bitconvert (v16i8 MQPR:$src))), (v8i16 (MVE_VREV16_8 MQPR:$src))>;
5531
5532  def : Pat<(v16i8 (bitconvert (v2f64 MQPR:$src))), (v16i8 (MVE_VREV64_8 MQPR:$src))>;
5533  def : Pat<(v16i8 (bitconvert (v2i64 MQPR:$src))), (v16i8 (MVE_VREV64_8 MQPR:$src))>;
5534  def : Pat<(v16i8 (bitconvert (v4f32 MQPR:$src))), (v16i8 (MVE_VREV32_8 MQPR:$src))>;
5535  def : Pat<(v16i8 (bitconvert (v4i32 MQPR:$src))), (v16i8 (MVE_VREV32_8 MQPR:$src))>;
5536  def : Pat<(v16i8 (bitconvert (v8f16 MQPR:$src))), (v16i8 (MVE_VREV16_8 MQPR:$src))>;
5537  def : Pat<(v16i8 (bitconvert (v8i16 MQPR:$src))), (v16i8 (MVE_VREV16_8 MQPR:$src))>;
5538}
5539