• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1//=- AArch64InstrInfo.td - Describe the AArch64 Instructions -*- tablegen -*-=//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// AArch64 Instruction definitions.
11//
12//===----------------------------------------------------------------------===//
13
14//===----------------------------------------------------------------------===//
15// ARM Instruction Predicate Definitions.
16//
17def HasV8_1a         : Predicate<"Subtarget->hasV8_1aOps()">,
18                                 AssemblerPredicate<"HasV8_1aOps", "armv8.1a">;
19def HasFPARMv8       : Predicate<"Subtarget->hasFPARMv8()">,
20                               AssemblerPredicate<"FeatureFPARMv8", "fp-armv8">;
21def HasNEON          : Predicate<"Subtarget->hasNEON()">,
22                                 AssemblerPredicate<"FeatureNEON", "neon">;
23def HasCrypto        : Predicate<"Subtarget->hasCrypto()">,
24                                 AssemblerPredicate<"FeatureCrypto", "crypto">;
25def HasCRC           : Predicate<"Subtarget->hasCRC()">,
26                                 AssemblerPredicate<"FeatureCRC", "crc">;
27def IsLE             : Predicate<"Subtarget->isLittleEndian()">;
28def IsBE             : Predicate<"!Subtarget->isLittleEndian()">;
29def IsCyclone        : Predicate<"Subtarget->isCyclone()">;
30
31//===----------------------------------------------------------------------===//
32// AArch64-specific DAG Nodes.
33//
34
35// SDTBinaryArithWithFlagsOut - RES1, FLAGS = op LHS, RHS
36def SDTBinaryArithWithFlagsOut : SDTypeProfile<2, 2,
37                                              [SDTCisSameAs<0, 2>,
38                                               SDTCisSameAs<0, 3>,
39                                               SDTCisInt<0>, SDTCisVT<1, i32>]>;
40
41// SDTBinaryArithWithFlagsIn - RES1, FLAGS = op LHS, RHS, FLAGS
42def SDTBinaryArithWithFlagsIn : SDTypeProfile<1, 3,
43                                            [SDTCisSameAs<0, 1>,
44                                             SDTCisSameAs<0, 2>,
45                                             SDTCisInt<0>,
46                                             SDTCisVT<3, i32>]>;
47
48// SDTBinaryArithWithFlagsInOut - RES1, FLAGS = op LHS, RHS, FLAGS
49def SDTBinaryArithWithFlagsInOut : SDTypeProfile<2, 3,
50                                            [SDTCisSameAs<0, 2>,
51                                             SDTCisSameAs<0, 3>,
52                                             SDTCisInt<0>,
53                                             SDTCisVT<1, i32>,
54                                             SDTCisVT<4, i32>]>;
55
56def SDT_AArch64Brcond  : SDTypeProfile<0, 3,
57                                     [SDTCisVT<0, OtherVT>, SDTCisVT<1, i32>,
58                                      SDTCisVT<2, i32>]>;
59def SDT_AArch64cbz : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisVT<1, OtherVT>]>;
60def SDT_AArch64tbz : SDTypeProfile<0, 3, [SDTCisInt<0>, SDTCisInt<1>,
61                                        SDTCisVT<2, OtherVT>]>;
62
63
64def SDT_AArch64CSel  : SDTypeProfile<1, 4,
65                                   [SDTCisSameAs<0, 1>,
66                                    SDTCisSameAs<0, 2>,
67                                    SDTCisInt<3>,
68                                    SDTCisVT<4, i32>]>;
69def SDT_AArch64FCmp   : SDTypeProfile<0, 2,
70                                   [SDTCisFP<0>,
71                                    SDTCisSameAs<0, 1>]>;
72def SDT_AArch64Dup   : SDTypeProfile<1, 1, [SDTCisVec<0>]>;
73def SDT_AArch64DupLane   : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisInt<2>]>;
74def SDT_AArch64Zip   : SDTypeProfile<1, 2, [SDTCisVec<0>,
75                                          SDTCisSameAs<0, 1>,
76                                          SDTCisSameAs<0, 2>]>;
77def SDT_AArch64MOVIedit : SDTypeProfile<1, 1, [SDTCisInt<1>]>;
78def SDT_AArch64MOVIshift : SDTypeProfile<1, 2, [SDTCisInt<1>, SDTCisInt<2>]>;
79def SDT_AArch64vecimm : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0,1>,
80                                           SDTCisInt<2>, SDTCisInt<3>]>;
81def SDT_AArch64UnaryVec: SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisSameAs<0,1>]>;
82def SDT_AArch64ExtVec: SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0,1>,
83                                          SDTCisSameAs<0,2>, SDTCisInt<3>]>;
84def SDT_AArch64vshift : SDTypeProfile<1, 2, [SDTCisSameAs<0,1>, SDTCisInt<2>]>;
85
86def SDT_AArch64unvec : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisSameAs<0,1>]>;
87def SDT_AArch64fcmpz : SDTypeProfile<1, 1, []>;
88def SDT_AArch64fcmp  : SDTypeProfile<1, 2, [SDTCisSameAs<1,2>]>;
89def SDT_AArch64binvec : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0,1>,
90                                           SDTCisSameAs<0,2>]>;
91def SDT_AArch64trivec : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0,1>,
92                                           SDTCisSameAs<0,2>,
93                                           SDTCisSameAs<0,3>]>;
94def SDT_AArch64TCRET : SDTypeProfile<0, 2, [SDTCisPtrTy<0>]>;
95def SDT_AArch64PREFETCH : SDTypeProfile<0, 2, [SDTCisVT<0, i32>, SDTCisPtrTy<1>]>;
96
97def SDT_AArch64ITOF  : SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisSameAs<0,1>]>;
98
99def SDT_AArch64TLSDescCall : SDTypeProfile<0, -2, [SDTCisPtrTy<0>,
100                                                 SDTCisPtrTy<1>]>;
101
102// Generates the general dynamic sequences, i.e.
103//  adrp  x0, :tlsdesc:var
104//  ldr   x1, [x0, #:tlsdesc_lo12:var]
105//  add   x0, x0, #:tlsdesc_lo12:var
106//  .tlsdesccall var
107//  blr   x1
108
109// (the TPIDR_EL0 offset is put directly in X0, hence no "result" here)
110// number of operands (the variable)
111def SDT_AArch64TLSDescCallSeq : SDTypeProfile<0,1,
112                                          [SDTCisPtrTy<0>]>;
113
114def SDT_AArch64WrapperLarge : SDTypeProfile<1, 4,
115                                        [SDTCisVT<0, i64>, SDTCisVT<1, i32>,
116                                         SDTCisSameAs<1, 2>, SDTCisSameAs<1, 3>,
117                                         SDTCisSameAs<1, 4>]>;
118
119
120// Node definitions.
121def AArch64adrp          : SDNode<"AArch64ISD::ADRP", SDTIntUnaryOp, []>;
122def AArch64addlow        : SDNode<"AArch64ISD::ADDlow", SDTIntBinOp, []>;
123def AArch64LOADgot       : SDNode<"AArch64ISD::LOADgot", SDTIntUnaryOp>;
124def AArch64callseq_start : SDNode<"ISD::CALLSEQ_START",
125                                SDCallSeqStart<[ SDTCisVT<0, i32> ]>,
126                                [SDNPHasChain, SDNPOutGlue]>;
127def AArch64callseq_end   : SDNode<"ISD::CALLSEQ_END",
128                                SDCallSeqEnd<[ SDTCisVT<0, i32>,
129                                               SDTCisVT<1, i32> ]>,
130                                [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
131def AArch64call          : SDNode<"AArch64ISD::CALL",
132                                SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>,
133                                [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
134                                 SDNPVariadic]>;
135def AArch64brcond        : SDNode<"AArch64ISD::BRCOND", SDT_AArch64Brcond,
136                                [SDNPHasChain]>;
137def AArch64cbz           : SDNode<"AArch64ISD::CBZ", SDT_AArch64cbz,
138                                [SDNPHasChain]>;
139def AArch64cbnz           : SDNode<"AArch64ISD::CBNZ", SDT_AArch64cbz,
140                                [SDNPHasChain]>;
141def AArch64tbz           : SDNode<"AArch64ISD::TBZ", SDT_AArch64tbz,
142                                [SDNPHasChain]>;
143def AArch64tbnz           : SDNode<"AArch64ISD::TBNZ", SDT_AArch64tbz,
144                                [SDNPHasChain]>;
145
146
147def AArch64csel          : SDNode<"AArch64ISD::CSEL", SDT_AArch64CSel>;
148def AArch64csinv         : SDNode<"AArch64ISD::CSINV", SDT_AArch64CSel>;
149def AArch64csneg         : SDNode<"AArch64ISD::CSNEG", SDT_AArch64CSel>;
150def AArch64csinc         : SDNode<"AArch64ISD::CSINC", SDT_AArch64CSel>;
151def AArch64retflag       : SDNode<"AArch64ISD::RET_FLAG", SDTNone,
152                                [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
153def AArch64adc       : SDNode<"AArch64ISD::ADC",  SDTBinaryArithWithFlagsIn >;
154def AArch64sbc       : SDNode<"AArch64ISD::SBC",  SDTBinaryArithWithFlagsIn>;
155def AArch64add_flag  : SDNode<"AArch64ISD::ADDS",  SDTBinaryArithWithFlagsOut,
156                            [SDNPCommutative]>;
157def AArch64sub_flag  : SDNode<"AArch64ISD::SUBS",  SDTBinaryArithWithFlagsOut>;
158def AArch64and_flag  : SDNode<"AArch64ISD::ANDS",  SDTBinaryArithWithFlagsOut,
159                            [SDNPCommutative]>;
160def AArch64adc_flag  : SDNode<"AArch64ISD::ADCS",  SDTBinaryArithWithFlagsInOut>;
161def AArch64sbc_flag  : SDNode<"AArch64ISD::SBCS",  SDTBinaryArithWithFlagsInOut>;
162
163def AArch64threadpointer : SDNode<"AArch64ISD::THREAD_POINTER", SDTPtrLeaf>;
164
165def AArch64fcmp      : SDNode<"AArch64ISD::FCMP", SDT_AArch64FCmp>;
166
167def AArch64fmax      : SDNode<"AArch64ISD::FMAX", SDTFPBinOp>;
168def AArch64fmin      : SDNode<"AArch64ISD::FMIN", SDTFPBinOp>;
169
170def AArch64dup       : SDNode<"AArch64ISD::DUP", SDT_AArch64Dup>;
171def AArch64duplane8  : SDNode<"AArch64ISD::DUPLANE8", SDT_AArch64DupLane>;
172def AArch64duplane16 : SDNode<"AArch64ISD::DUPLANE16", SDT_AArch64DupLane>;
173def AArch64duplane32 : SDNode<"AArch64ISD::DUPLANE32", SDT_AArch64DupLane>;
174def AArch64duplane64 : SDNode<"AArch64ISD::DUPLANE64", SDT_AArch64DupLane>;
175
176def AArch64zip1      : SDNode<"AArch64ISD::ZIP1", SDT_AArch64Zip>;
177def AArch64zip2      : SDNode<"AArch64ISD::ZIP2", SDT_AArch64Zip>;
178def AArch64uzp1      : SDNode<"AArch64ISD::UZP1", SDT_AArch64Zip>;
179def AArch64uzp2      : SDNode<"AArch64ISD::UZP2", SDT_AArch64Zip>;
180def AArch64trn1      : SDNode<"AArch64ISD::TRN1", SDT_AArch64Zip>;
181def AArch64trn2      : SDNode<"AArch64ISD::TRN2", SDT_AArch64Zip>;
182
183def AArch64movi_edit : SDNode<"AArch64ISD::MOVIedit", SDT_AArch64MOVIedit>;
184def AArch64movi_shift : SDNode<"AArch64ISD::MOVIshift", SDT_AArch64MOVIshift>;
185def AArch64movi_msl : SDNode<"AArch64ISD::MOVImsl", SDT_AArch64MOVIshift>;
186def AArch64mvni_shift : SDNode<"AArch64ISD::MVNIshift", SDT_AArch64MOVIshift>;
187def AArch64mvni_msl : SDNode<"AArch64ISD::MVNImsl", SDT_AArch64MOVIshift>;
188def AArch64movi : SDNode<"AArch64ISD::MOVI", SDT_AArch64MOVIedit>;
189def AArch64fmov : SDNode<"AArch64ISD::FMOV", SDT_AArch64MOVIedit>;
190
191def AArch64rev16 : SDNode<"AArch64ISD::REV16", SDT_AArch64UnaryVec>;
192def AArch64rev32 : SDNode<"AArch64ISD::REV32", SDT_AArch64UnaryVec>;
193def AArch64rev64 : SDNode<"AArch64ISD::REV64", SDT_AArch64UnaryVec>;
194def AArch64ext : SDNode<"AArch64ISD::EXT", SDT_AArch64ExtVec>;
195
196def AArch64vashr : SDNode<"AArch64ISD::VASHR", SDT_AArch64vshift>;
197def AArch64vlshr : SDNode<"AArch64ISD::VLSHR", SDT_AArch64vshift>;
198def AArch64vshl : SDNode<"AArch64ISD::VSHL", SDT_AArch64vshift>;
199def AArch64sqshli : SDNode<"AArch64ISD::SQSHL_I", SDT_AArch64vshift>;
200def AArch64uqshli : SDNode<"AArch64ISD::UQSHL_I", SDT_AArch64vshift>;
201def AArch64sqshlui : SDNode<"AArch64ISD::SQSHLU_I", SDT_AArch64vshift>;
202def AArch64srshri : SDNode<"AArch64ISD::SRSHR_I", SDT_AArch64vshift>;
203def AArch64urshri : SDNode<"AArch64ISD::URSHR_I", SDT_AArch64vshift>;
204
205def AArch64not: SDNode<"AArch64ISD::NOT", SDT_AArch64unvec>;
206def AArch64bit: SDNode<"AArch64ISD::BIT", SDT_AArch64trivec>;
207def AArch64bsl: SDNode<"AArch64ISD::BSL", SDT_AArch64trivec>;
208
209def AArch64cmeq: SDNode<"AArch64ISD::CMEQ", SDT_AArch64binvec>;
210def AArch64cmge: SDNode<"AArch64ISD::CMGE", SDT_AArch64binvec>;
211def AArch64cmgt: SDNode<"AArch64ISD::CMGT", SDT_AArch64binvec>;
212def AArch64cmhi: SDNode<"AArch64ISD::CMHI", SDT_AArch64binvec>;
213def AArch64cmhs: SDNode<"AArch64ISD::CMHS", SDT_AArch64binvec>;
214
215def AArch64fcmeq: SDNode<"AArch64ISD::FCMEQ", SDT_AArch64fcmp>;
216def AArch64fcmge: SDNode<"AArch64ISD::FCMGE", SDT_AArch64fcmp>;
217def AArch64fcmgt: SDNode<"AArch64ISD::FCMGT", SDT_AArch64fcmp>;
218
219def AArch64cmeqz: SDNode<"AArch64ISD::CMEQz", SDT_AArch64unvec>;
220def AArch64cmgez: SDNode<"AArch64ISD::CMGEz", SDT_AArch64unvec>;
221def AArch64cmgtz: SDNode<"AArch64ISD::CMGTz", SDT_AArch64unvec>;
222def AArch64cmlez: SDNode<"AArch64ISD::CMLEz", SDT_AArch64unvec>;
223def AArch64cmltz: SDNode<"AArch64ISD::CMLTz", SDT_AArch64unvec>;
224def AArch64cmtst : PatFrag<(ops node:$LHS, node:$RHS),
225                        (AArch64not (AArch64cmeqz (and node:$LHS, node:$RHS)))>;
226
227def AArch64fcmeqz: SDNode<"AArch64ISD::FCMEQz", SDT_AArch64fcmpz>;
228def AArch64fcmgez: SDNode<"AArch64ISD::FCMGEz", SDT_AArch64fcmpz>;
229def AArch64fcmgtz: SDNode<"AArch64ISD::FCMGTz", SDT_AArch64fcmpz>;
230def AArch64fcmlez: SDNode<"AArch64ISD::FCMLEz", SDT_AArch64fcmpz>;
231def AArch64fcmltz: SDNode<"AArch64ISD::FCMLTz", SDT_AArch64fcmpz>;
232
233def AArch64bici: SDNode<"AArch64ISD::BICi", SDT_AArch64vecimm>;
234def AArch64orri: SDNode<"AArch64ISD::ORRi", SDT_AArch64vecimm>;
235
236def AArch64neg : SDNode<"AArch64ISD::NEG", SDT_AArch64unvec>;
237
238def AArch64tcret: SDNode<"AArch64ISD::TC_RETURN", SDT_AArch64TCRET,
239                  [SDNPHasChain,  SDNPOptInGlue, SDNPVariadic]>;
240
241def AArch64Prefetch        : SDNode<"AArch64ISD::PREFETCH", SDT_AArch64PREFETCH,
242                               [SDNPHasChain, SDNPSideEffect]>;
243
244def AArch64sitof: SDNode<"AArch64ISD::SITOF", SDT_AArch64ITOF>;
245def AArch64uitof: SDNode<"AArch64ISD::UITOF", SDT_AArch64ITOF>;
246
247def AArch64tlsdesc_callseq : SDNode<"AArch64ISD::TLSDESC_CALLSEQ",
248                                    SDT_AArch64TLSDescCallSeq,
249                                    [SDNPInGlue, SDNPOutGlue, SDNPHasChain,
250                                     SDNPVariadic]>;
251
252
253def AArch64WrapperLarge : SDNode<"AArch64ISD::WrapperLarge",
254                                 SDT_AArch64WrapperLarge>;
255
256def AArch64NvCast : SDNode<"AArch64ISD::NVCAST", SDTUnaryOp>;
257
258def SDT_AArch64mull : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisInt<1>,
259                                    SDTCisSameAs<1, 2>]>;
260def AArch64smull    : SDNode<"AArch64ISD::SMULL", SDT_AArch64mull>;
261def AArch64umull    : SDNode<"AArch64ISD::UMULL", SDT_AArch64mull>;
262
263def AArch64saddv    : SDNode<"AArch64ISD::SADDV", SDT_AArch64UnaryVec>;
264def AArch64uaddv    : SDNode<"AArch64ISD::UADDV", SDT_AArch64UnaryVec>;
265def AArch64sminv    : SDNode<"AArch64ISD::SMINV", SDT_AArch64UnaryVec>;
266def AArch64uminv    : SDNode<"AArch64ISD::UMINV", SDT_AArch64UnaryVec>;
267def AArch64smaxv    : SDNode<"AArch64ISD::SMAXV", SDT_AArch64UnaryVec>;
268def AArch64umaxv    : SDNode<"AArch64ISD::UMAXV", SDT_AArch64UnaryVec>;
269
270//===----------------------------------------------------------------------===//
271
272//===----------------------------------------------------------------------===//
273
274// AArch64 Instruction Predicate Definitions.
275//
276def HasZCZ    : Predicate<"Subtarget->hasZeroCycleZeroing()">;
277def NoZCZ     : Predicate<"!Subtarget->hasZeroCycleZeroing()">;
278def IsDarwin  : Predicate<"Subtarget->isTargetDarwin()">;
279def IsNotDarwin: Predicate<"!Subtarget->isTargetDarwin()">;
280def ForCodeSize   : Predicate<"ForCodeSize">;
281def NotForCodeSize   : Predicate<"!ForCodeSize">;
282
283include "AArch64InstrFormats.td"
284
285//===----------------------------------------------------------------------===//
286
287//===----------------------------------------------------------------------===//
288// Miscellaneous instructions.
289//===----------------------------------------------------------------------===//
290
291let Defs = [SP], Uses = [SP], hasSideEffects = 1, isCodeGenOnly = 1 in {
292def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt),
293                              [(AArch64callseq_start timm:$amt)]>;
294def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
295                            [(AArch64callseq_end timm:$amt1, timm:$amt2)]>;
296} // Defs = [SP], Uses = [SP], hasSideEffects = 1, isCodeGenOnly = 1
297
298let isReMaterializable = 1, isCodeGenOnly = 1 in {
299// FIXME: The following pseudo instructions are only needed because remat
300// cannot handle multiple instructions.  When that changes, they can be
301// removed, along with the AArch64Wrapper node.
302
303let AddedComplexity = 10 in
304def LOADgot : Pseudo<(outs GPR64:$dst), (ins i64imm:$addr),
305                     [(set GPR64:$dst, (AArch64LOADgot tglobaladdr:$addr))]>,
306              Sched<[WriteLDAdr]>;
307
308// The MOVaddr instruction should match only when the add is not folded
309// into a load or store address.
310def MOVaddr
311    : Pseudo<(outs GPR64:$dst), (ins i64imm:$hi, i64imm:$low),
312             [(set GPR64:$dst, (AArch64addlow (AArch64adrp tglobaladdr:$hi),
313                                            tglobaladdr:$low))]>,
314      Sched<[WriteAdrAdr]>;
315def MOVaddrJT
316    : Pseudo<(outs GPR64:$dst), (ins i64imm:$hi, i64imm:$low),
317             [(set GPR64:$dst, (AArch64addlow (AArch64adrp tjumptable:$hi),
318                                             tjumptable:$low))]>,
319      Sched<[WriteAdrAdr]>;
320def MOVaddrCP
321    : Pseudo<(outs GPR64:$dst), (ins i64imm:$hi, i64imm:$low),
322             [(set GPR64:$dst, (AArch64addlow (AArch64adrp tconstpool:$hi),
323                                             tconstpool:$low))]>,
324      Sched<[WriteAdrAdr]>;
325def MOVaddrBA
326    : Pseudo<(outs GPR64:$dst), (ins i64imm:$hi, i64imm:$low),
327             [(set GPR64:$dst, (AArch64addlow (AArch64adrp tblockaddress:$hi),
328                                             tblockaddress:$low))]>,
329      Sched<[WriteAdrAdr]>;
330def MOVaddrTLS
331    : Pseudo<(outs GPR64:$dst), (ins i64imm:$hi, i64imm:$low),
332             [(set GPR64:$dst, (AArch64addlow (AArch64adrp tglobaltlsaddr:$hi),
333                                            tglobaltlsaddr:$low))]>,
334      Sched<[WriteAdrAdr]>;
335def MOVaddrEXT
336    : Pseudo<(outs GPR64:$dst), (ins i64imm:$hi, i64imm:$low),
337             [(set GPR64:$dst, (AArch64addlow (AArch64adrp texternalsym:$hi),
338                                            texternalsym:$low))]>,
339      Sched<[WriteAdrAdr]>;
340
341} // isReMaterializable, isCodeGenOnly
342
343def : Pat<(AArch64LOADgot tglobaltlsaddr:$addr),
344          (LOADgot tglobaltlsaddr:$addr)>;
345
346def : Pat<(AArch64LOADgot texternalsym:$addr),
347          (LOADgot texternalsym:$addr)>;
348
349def : Pat<(AArch64LOADgot tconstpool:$addr),
350          (LOADgot tconstpool:$addr)>;
351
352//===----------------------------------------------------------------------===//
353// System instructions.
354//===----------------------------------------------------------------------===//
355
356def HINT : HintI<"hint">;
357def : InstAlias<"nop",  (HINT 0b000)>;
358def : InstAlias<"yield",(HINT 0b001)>;
359def : InstAlias<"wfe",  (HINT 0b010)>;
360def : InstAlias<"wfi",  (HINT 0b011)>;
361def : InstAlias<"sev",  (HINT 0b100)>;
362def : InstAlias<"sevl", (HINT 0b101)>;
363
364// As far as LLVM is concerned this writes to the system's exclusive monitors.
365let mayLoad = 1, mayStore = 1 in
366def CLREX : CRmSystemI<imm0_15, 0b010, "clrex">;
367
368// NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
369// model patterns with sufficiently fine granularity.
370let mayLoad = ?, mayStore = ? in {
371def DMB   : CRmSystemI<barrier_op, 0b101, "dmb",
372                       [(int_aarch64_dmb (i32 imm32_0_15:$CRm))]>;
373
374def DSB   : CRmSystemI<barrier_op, 0b100, "dsb",
375                       [(int_aarch64_dsb (i32 imm32_0_15:$CRm))]>;
376
377def ISB   : CRmSystemI<barrier_op, 0b110, "isb",
378                       [(int_aarch64_isb (i32 imm32_0_15:$CRm))]>;
379}
380
381def : InstAlias<"clrex", (CLREX 0xf)>;
382def : InstAlias<"isb", (ISB 0xf)>;
383
384def MRS    : MRSI;
385def MSR    : MSRI;
386def MSRpstate: MSRpstateI;
387
388// The thread pointer (on Linux, at least, where this has been implemented) is
389// TPIDR_EL0.
390def : Pat<(AArch64threadpointer), (MRS 0xde82)>;
391
392// Generic system instructions
393def SYSxt  : SystemXtI<0, "sys">;
394def SYSLxt : SystemLXtI<1, "sysl">;
395
396def : InstAlias<"sys $op1, $Cn, $Cm, $op2",
397                (SYSxt imm0_7:$op1, sys_cr_op:$Cn,
398                 sys_cr_op:$Cm, imm0_7:$op2, XZR)>;
399
400//===----------------------------------------------------------------------===//
401// Move immediate instructions.
402//===----------------------------------------------------------------------===//
403
404defm MOVK : InsertImmediate<0b11, "movk">;
405defm MOVN : MoveImmediate<0b00, "movn">;
406
407let PostEncoderMethod = "fixMOVZ" in
408defm MOVZ : MoveImmediate<0b10, "movz">;
409
410// First group of aliases covers an implicit "lsl #0".
411def : InstAlias<"movk $dst, $imm", (MOVKWi GPR32:$dst, imm0_65535:$imm, 0)>;
412def : InstAlias<"movk $dst, $imm", (MOVKXi GPR64:$dst, imm0_65535:$imm, 0)>;
413def : InstAlias<"movn $dst, $imm", (MOVNWi GPR32:$dst, imm0_65535:$imm, 0)>;
414def : InstAlias<"movn $dst, $imm", (MOVNXi GPR64:$dst, imm0_65535:$imm, 0)>;
415def : InstAlias<"movz $dst, $imm", (MOVZWi GPR32:$dst, imm0_65535:$imm, 0)>;
416def : InstAlias<"movz $dst, $imm", (MOVZXi GPR64:$dst, imm0_65535:$imm, 0)>;
417
418// Next, we have various ELF relocations with the ":XYZ_g0:sym" syntax.
419def : InstAlias<"movz $Rd, $sym", (MOVZXi GPR64:$Rd, movz_symbol_g3:$sym, 48)>;
420def : InstAlias<"movz $Rd, $sym", (MOVZXi GPR64:$Rd, movz_symbol_g2:$sym, 32)>;
421def : InstAlias<"movz $Rd, $sym", (MOVZXi GPR64:$Rd, movz_symbol_g1:$sym, 16)>;
422def : InstAlias<"movz $Rd, $sym", (MOVZXi GPR64:$Rd, movz_symbol_g0:$sym, 0)>;
423
424def : InstAlias<"movn $Rd, $sym", (MOVNXi GPR64:$Rd, movz_symbol_g3:$sym, 48)>;
425def : InstAlias<"movn $Rd, $sym", (MOVNXi GPR64:$Rd, movz_symbol_g2:$sym, 32)>;
426def : InstAlias<"movn $Rd, $sym", (MOVNXi GPR64:$Rd, movz_symbol_g1:$sym, 16)>;
427def : InstAlias<"movn $Rd, $sym", (MOVNXi GPR64:$Rd, movz_symbol_g0:$sym, 0)>;
428
429def : InstAlias<"movk $Rd, $sym", (MOVKXi GPR64:$Rd, movk_symbol_g3:$sym, 48)>;
430def : InstAlias<"movk $Rd, $sym", (MOVKXi GPR64:$Rd, movk_symbol_g2:$sym, 32)>;
431def : InstAlias<"movk $Rd, $sym", (MOVKXi GPR64:$Rd, movk_symbol_g1:$sym, 16)>;
432def : InstAlias<"movk $Rd, $sym", (MOVKXi GPR64:$Rd, movk_symbol_g0:$sym, 0)>;
433
434def : InstAlias<"movz $Rd, $sym", (MOVZWi GPR32:$Rd, movz_symbol_g1:$sym, 16)>;
435def : InstAlias<"movz $Rd, $sym", (MOVZWi GPR32:$Rd, movz_symbol_g0:$sym, 0)>;
436
437def : InstAlias<"movn $Rd, $sym", (MOVNWi GPR32:$Rd, movz_symbol_g1:$sym, 16)>;
438def : InstAlias<"movn $Rd, $sym", (MOVNWi GPR32:$Rd, movz_symbol_g0:$sym, 0)>;
439
440def : InstAlias<"movk $Rd, $sym", (MOVKWi GPR32:$Rd, movk_symbol_g1:$sym, 16)>;
441def : InstAlias<"movk $Rd, $sym", (MOVKWi GPR32:$Rd, movk_symbol_g0:$sym, 0)>;
442
443// Final group of aliases covers true "mov $Rd, $imm" cases.
444multiclass movw_mov_alias<string basename,Instruction INST, RegisterClass GPR,
445                          int width, int shift> {
446  def _asmoperand : AsmOperandClass {
447    let Name = basename # width # "_lsl" # shift # "MovAlias";
448    let PredicateMethod = "is" # basename # "MovAlias<" # width # ", "
449                               # shift # ">";
450    let RenderMethod = "add" # basename # "MovAliasOperands<" # shift # ">";
451  }
452
453  def _movimm : Operand<i32> {
454    let ParserMatchClass = !cast<AsmOperandClass>(NAME # "_asmoperand");
455  }
456
457  def : InstAlias<"mov $Rd, $imm",
458                  (INST GPR:$Rd, !cast<Operand>(NAME # "_movimm"):$imm, shift)>;
459}
460
461defm : movw_mov_alias<"MOVZ", MOVZWi, GPR32, 32, 0>;
462defm : movw_mov_alias<"MOVZ", MOVZWi, GPR32, 32, 16>;
463
464defm : movw_mov_alias<"MOVZ", MOVZXi, GPR64, 64, 0>;
465defm : movw_mov_alias<"MOVZ", MOVZXi, GPR64, 64, 16>;
466defm : movw_mov_alias<"MOVZ", MOVZXi, GPR64, 64, 32>;
467defm : movw_mov_alias<"MOVZ", MOVZXi, GPR64, 64, 48>;
468
469defm : movw_mov_alias<"MOVN", MOVNWi, GPR32, 32, 0>;
470defm : movw_mov_alias<"MOVN", MOVNWi, GPR32, 32, 16>;
471
472defm : movw_mov_alias<"MOVN", MOVNXi, GPR64, 64, 0>;
473defm : movw_mov_alias<"MOVN", MOVNXi, GPR64, 64, 16>;
474defm : movw_mov_alias<"MOVN", MOVNXi, GPR64, 64, 32>;
475defm : movw_mov_alias<"MOVN", MOVNXi, GPR64, 64, 48>;
476
477let isReMaterializable = 1, isCodeGenOnly = 1, isMoveImm = 1,
478    isAsCheapAsAMove = 1 in {
479// FIXME: The following pseudo instructions are only needed because remat
480// cannot handle multiple instructions.  When that changes, we can select
481// directly to the real instructions and get rid of these pseudos.
482
483def MOVi32imm
484    : Pseudo<(outs GPR32:$dst), (ins i32imm:$src),
485             [(set GPR32:$dst, imm:$src)]>,
486      Sched<[WriteImm]>;
487def MOVi64imm
488    : Pseudo<(outs GPR64:$dst), (ins i64imm:$src),
489             [(set GPR64:$dst, imm:$src)]>,
490      Sched<[WriteImm]>;
491} // isReMaterializable, isCodeGenOnly
492
493// If possible, we want to use MOVi32imm even for 64-bit moves. This gives the
494// eventual expansion code fewer bits to worry about getting right. Marshalling
495// the types is a little tricky though:
496def i64imm_32bit : ImmLeaf<i64, [{
497  return (Imm & 0xffffffffULL) == static_cast<uint64_t>(Imm);
498}]>;
499
500def trunc_imm : SDNodeXForm<imm, [{
501  return CurDAG->getTargetConstant(N->getZExtValue(), MVT::i32);
502}]>;
503
504def : Pat<(i64 i64imm_32bit:$src),
505          (SUBREG_TO_REG (i64 0), (MOVi32imm (trunc_imm imm:$src)), sub_32)>;
506
507// Materialize FP constants via MOVi32imm/MOVi64imm (MachO large code model).
508def bitcast_fpimm_to_i32 : SDNodeXForm<fpimm, [{
509return CurDAG->getTargetConstant(
510  N->getValueAPF().bitcastToAPInt().getZExtValue(), MVT::i32);
511}]>;
512
513def bitcast_fpimm_to_i64 : SDNodeXForm<fpimm, [{
514return CurDAG->getTargetConstant(
515  N->getValueAPF().bitcastToAPInt().getZExtValue(), MVT::i64);
516}]>;
517
518
519def : Pat<(f32 fpimm:$in),
520  (COPY_TO_REGCLASS (MOVi32imm (bitcast_fpimm_to_i32 f32:$in)), FPR32)>;
521def : Pat<(f64 fpimm:$in),
522  (COPY_TO_REGCLASS (MOVi64imm (bitcast_fpimm_to_i64 f64:$in)), FPR64)>;
523
524
525// Deal with the various forms of (ELF) large addressing with MOVZ/MOVK
526// sequences.
527def : Pat<(AArch64WrapperLarge tglobaladdr:$g3, tglobaladdr:$g2,
528                             tglobaladdr:$g1, tglobaladdr:$g0),
529          (MOVKXi (MOVKXi (MOVKXi (MOVZXi tglobaladdr:$g3, 48),
530                                  tglobaladdr:$g2, 32),
531                          tglobaladdr:$g1, 16),
532                  tglobaladdr:$g0, 0)>;
533
534def : Pat<(AArch64WrapperLarge tblockaddress:$g3, tblockaddress:$g2,
535                             tblockaddress:$g1, tblockaddress:$g0),
536          (MOVKXi (MOVKXi (MOVKXi (MOVZXi tblockaddress:$g3, 48),
537                                  tblockaddress:$g2, 32),
538                          tblockaddress:$g1, 16),
539                  tblockaddress:$g0, 0)>;
540
541def : Pat<(AArch64WrapperLarge tconstpool:$g3, tconstpool:$g2,
542                             tconstpool:$g1, tconstpool:$g0),
543          (MOVKXi (MOVKXi (MOVKXi (MOVZXi tconstpool:$g3, 48),
544                                  tconstpool:$g2, 32),
545                          tconstpool:$g1, 16),
546                  tconstpool:$g0, 0)>;
547
548def : Pat<(AArch64WrapperLarge tjumptable:$g3, tjumptable:$g2,
549                             tjumptable:$g1, tjumptable:$g0),
550          (MOVKXi (MOVKXi (MOVKXi (MOVZXi tjumptable:$g3, 48),
551                                  tjumptable:$g2, 32),
552                          tjumptable:$g1, 16),
553                  tjumptable:$g0, 0)>;
554
555
556//===----------------------------------------------------------------------===//
557// Arithmetic instructions.
558//===----------------------------------------------------------------------===//
559
560// Add/subtract with carry.
561defm ADC : AddSubCarry<0, "adc", "adcs", AArch64adc, AArch64adc_flag>;
562defm SBC : AddSubCarry<1, "sbc", "sbcs", AArch64sbc, AArch64sbc_flag>;
563
564def : InstAlias<"ngc $dst, $src",  (SBCWr  GPR32:$dst, WZR, GPR32:$src)>;
565def : InstAlias<"ngc $dst, $src",  (SBCXr  GPR64:$dst, XZR, GPR64:$src)>;
566def : InstAlias<"ngcs $dst, $src", (SBCSWr GPR32:$dst, WZR, GPR32:$src)>;
567def : InstAlias<"ngcs $dst, $src", (SBCSXr GPR64:$dst, XZR, GPR64:$src)>;
568
569// Add/subtract
570defm ADD : AddSub<0, "add", add>;
571defm SUB : AddSub<1, "sub">;
572
573def : InstAlias<"mov $dst, $src",
574                (ADDWri GPR32sponly:$dst, GPR32sp:$src, 0, 0)>;
575def : InstAlias<"mov $dst, $src",
576                (ADDWri GPR32sp:$dst, GPR32sponly:$src, 0, 0)>;
577def : InstAlias<"mov $dst, $src",
578                (ADDXri GPR64sponly:$dst, GPR64sp:$src, 0, 0)>;
579def : InstAlias<"mov $dst, $src",
580                (ADDXri GPR64sp:$dst, GPR64sponly:$src, 0, 0)>;
581
582defm ADDS : AddSubS<0, "adds", AArch64add_flag, "cmn">;
583defm SUBS : AddSubS<1, "subs", AArch64sub_flag, "cmp">;
584
585// Use SUBS instead of SUB to enable CSE between SUBS and SUB.
586def : Pat<(sub GPR32sp:$Rn, addsub_shifted_imm32:$imm),
587          (SUBSWri GPR32sp:$Rn, addsub_shifted_imm32:$imm)>;
588def : Pat<(sub GPR64sp:$Rn, addsub_shifted_imm64:$imm),
589          (SUBSXri GPR64sp:$Rn, addsub_shifted_imm64:$imm)>;
590def : Pat<(sub GPR32:$Rn, GPR32:$Rm),
591          (SUBSWrr GPR32:$Rn, GPR32:$Rm)>;
592def : Pat<(sub GPR64:$Rn, GPR64:$Rm),
593          (SUBSXrr GPR64:$Rn, GPR64:$Rm)>;
594def : Pat<(sub GPR32:$Rn, arith_shifted_reg32:$Rm),
595          (SUBSWrs GPR32:$Rn, arith_shifted_reg32:$Rm)>;
596def : Pat<(sub GPR64:$Rn, arith_shifted_reg64:$Rm),
597          (SUBSXrs GPR64:$Rn, arith_shifted_reg64:$Rm)>;
598def : Pat<(sub GPR32sp:$R2, arith_extended_reg32<i32>:$R3),
599          (SUBSWrx GPR32sp:$R2, arith_extended_reg32<i32>:$R3)>;
600def : Pat<(sub GPR64sp:$R2, arith_extended_reg32to64<i64>:$R3),
601          (SUBSXrx GPR64sp:$R2, arith_extended_reg32to64<i64>:$R3)>;
602
603// Because of the immediate format for add/sub-imm instructions, the
604// expression (add x, -1) must be transformed to (SUB{W,X}ri x, 1).
605//  These patterns capture that transformation.
606let AddedComplexity = 1 in {
607def : Pat<(add GPR32:$Rn, neg_addsub_shifted_imm32:$imm),
608          (SUBSWri GPR32:$Rn, neg_addsub_shifted_imm32:$imm)>;
609def : Pat<(add GPR64:$Rn, neg_addsub_shifted_imm64:$imm),
610          (SUBSXri GPR64:$Rn, neg_addsub_shifted_imm64:$imm)>;
611def : Pat<(sub GPR32:$Rn, neg_addsub_shifted_imm32:$imm),
612          (ADDWri GPR32:$Rn, neg_addsub_shifted_imm32:$imm)>;
613def : Pat<(sub GPR64:$Rn, neg_addsub_shifted_imm64:$imm),
614          (ADDXri GPR64:$Rn, neg_addsub_shifted_imm64:$imm)>;
615}
616
617// Because of the immediate format for add/sub-imm instructions, the
618// expression (add x, -1) must be transformed to (SUB{W,X}ri x, 1).
619//  These patterns capture that transformation.
620let AddedComplexity = 1 in {
621def : Pat<(AArch64add_flag GPR32:$Rn, neg_addsub_shifted_imm32:$imm),
622          (SUBSWri GPR32:$Rn, neg_addsub_shifted_imm32:$imm)>;
623def : Pat<(AArch64add_flag GPR64:$Rn, neg_addsub_shifted_imm64:$imm),
624          (SUBSXri GPR64:$Rn, neg_addsub_shifted_imm64:$imm)>;
625def : Pat<(AArch64sub_flag GPR32:$Rn, neg_addsub_shifted_imm32:$imm),
626          (ADDSWri GPR32:$Rn, neg_addsub_shifted_imm32:$imm)>;
627def : Pat<(AArch64sub_flag GPR64:$Rn, neg_addsub_shifted_imm64:$imm),
628          (ADDSXri GPR64:$Rn, neg_addsub_shifted_imm64:$imm)>;
629}
630
631def : InstAlias<"neg $dst, $src", (SUBWrs GPR32:$dst, WZR, GPR32:$src, 0), 3>;
632def : InstAlias<"neg $dst, $src", (SUBXrs GPR64:$dst, XZR, GPR64:$src, 0), 3>;
633def : InstAlias<"neg $dst, $src$shift",
634                (SUBWrs GPR32:$dst, WZR, GPR32:$src, arith_shift32:$shift), 2>;
635def : InstAlias<"neg $dst, $src$shift",
636                (SUBXrs GPR64:$dst, XZR, GPR64:$src, arith_shift64:$shift), 2>;
637
638def : InstAlias<"negs $dst, $src", (SUBSWrs GPR32:$dst, WZR, GPR32:$src, 0), 3>;
639def : InstAlias<"negs $dst, $src", (SUBSXrs GPR64:$dst, XZR, GPR64:$src, 0), 3>;
640def : InstAlias<"negs $dst, $src$shift",
641                (SUBSWrs GPR32:$dst, WZR, GPR32:$src, arith_shift32:$shift), 2>;
642def : InstAlias<"negs $dst, $src$shift",
643                (SUBSXrs GPR64:$dst, XZR, GPR64:$src, arith_shift64:$shift), 2>;
644
645
646// Unsigned/Signed divide
647defm UDIV : Div<0, "udiv", udiv>;
648defm SDIV : Div<1, "sdiv", sdiv>;
649let isCodeGenOnly = 1 in {
650defm UDIV_Int : Div<0, "udiv", int_aarch64_udiv>;
651defm SDIV_Int : Div<1, "sdiv", int_aarch64_sdiv>;
652}
653
654// Variable shift
655defm ASRV : Shift<0b10, "asr", sra>;
656defm LSLV : Shift<0b00, "lsl", shl>;
657defm LSRV : Shift<0b01, "lsr", srl>;
658defm RORV : Shift<0b11, "ror", rotr>;
659
660def : ShiftAlias<"asrv", ASRVWr, GPR32>;
661def : ShiftAlias<"asrv", ASRVXr, GPR64>;
662def : ShiftAlias<"lslv", LSLVWr, GPR32>;
663def : ShiftAlias<"lslv", LSLVXr, GPR64>;
664def : ShiftAlias<"lsrv", LSRVWr, GPR32>;
665def : ShiftAlias<"lsrv", LSRVXr, GPR64>;
666def : ShiftAlias<"rorv", RORVWr, GPR32>;
667def : ShiftAlias<"rorv", RORVXr, GPR64>;
668
669// Multiply-add
670let AddedComplexity = 7 in {
671defm MADD : MulAccum<0, "madd", add>;
672defm MSUB : MulAccum<1, "msub", sub>;
673
674def : Pat<(i32 (mul GPR32:$Rn, GPR32:$Rm)),
675          (MADDWrrr GPR32:$Rn, GPR32:$Rm, WZR)>;
676def : Pat<(i64 (mul GPR64:$Rn, GPR64:$Rm)),
677          (MADDXrrr GPR64:$Rn, GPR64:$Rm, XZR)>;
678
679def : Pat<(i32 (ineg (mul GPR32:$Rn, GPR32:$Rm))),
680          (MSUBWrrr GPR32:$Rn, GPR32:$Rm, WZR)>;
681def : Pat<(i64 (ineg (mul GPR64:$Rn, GPR64:$Rm))),
682          (MSUBXrrr GPR64:$Rn, GPR64:$Rm, XZR)>;
683def : Pat<(i32 (mul (ineg GPR32:$Rn), GPR32:$Rm)),
684          (MSUBWrrr GPR32:$Rn, GPR32:$Rm, WZR)>;
685def : Pat<(i64 (mul (ineg GPR64:$Rn), GPR64:$Rm)),
686          (MSUBXrrr GPR64:$Rn, GPR64:$Rm, XZR)>;
687} // AddedComplexity = 7
688
689let AddedComplexity = 5 in {
690def SMADDLrrr : WideMulAccum<0, 0b001, "smaddl", add, sext>;
691def SMSUBLrrr : WideMulAccum<1, 0b001, "smsubl", sub, sext>;
692def UMADDLrrr : WideMulAccum<0, 0b101, "umaddl", add, zext>;
693def UMSUBLrrr : WideMulAccum<1, 0b101, "umsubl", sub, zext>;
694
695def : Pat<(i64 (mul (sext GPR32:$Rn), (sext GPR32:$Rm))),
696          (SMADDLrrr GPR32:$Rn, GPR32:$Rm, XZR)>;
697def : Pat<(i64 (mul (zext GPR32:$Rn), (zext GPR32:$Rm))),
698          (UMADDLrrr GPR32:$Rn, GPR32:$Rm, XZR)>;
699
700def : Pat<(i64 (ineg (mul (sext GPR32:$Rn), (sext GPR32:$Rm)))),
701          (SMSUBLrrr GPR32:$Rn, GPR32:$Rm, XZR)>;
702def : Pat<(i64 (ineg (mul (zext GPR32:$Rn), (zext GPR32:$Rm)))),
703          (UMSUBLrrr GPR32:$Rn, GPR32:$Rm, XZR)>;
704} // AddedComplexity = 5
705
706def : MulAccumWAlias<"mul", MADDWrrr>;
707def : MulAccumXAlias<"mul", MADDXrrr>;
708def : MulAccumWAlias<"mneg", MSUBWrrr>;
709def : MulAccumXAlias<"mneg", MSUBXrrr>;
710def : WideMulAccumAlias<"smull", SMADDLrrr>;
711def : WideMulAccumAlias<"smnegl", SMSUBLrrr>;
712def : WideMulAccumAlias<"umull", UMADDLrrr>;
713def : WideMulAccumAlias<"umnegl", UMSUBLrrr>;
714
715// Multiply-high
716def SMULHrr : MulHi<0b010, "smulh", mulhs>;
717def UMULHrr : MulHi<0b110, "umulh", mulhu>;
718
719// CRC32
720def CRC32Brr : BaseCRC32<0, 0b00, 0, GPR32, int_aarch64_crc32b, "crc32b">;
721def CRC32Hrr : BaseCRC32<0, 0b01, 0, GPR32, int_aarch64_crc32h, "crc32h">;
722def CRC32Wrr : BaseCRC32<0, 0b10, 0, GPR32, int_aarch64_crc32w, "crc32w">;
723def CRC32Xrr : BaseCRC32<1, 0b11, 0, GPR64, int_aarch64_crc32x, "crc32x">;
724
725def CRC32CBrr : BaseCRC32<0, 0b00, 1, GPR32, int_aarch64_crc32cb, "crc32cb">;
726def CRC32CHrr : BaseCRC32<0, 0b01, 1, GPR32, int_aarch64_crc32ch, "crc32ch">;
727def CRC32CWrr : BaseCRC32<0, 0b10, 1, GPR32, int_aarch64_crc32cw, "crc32cw">;
728def CRC32CXrr : BaseCRC32<1, 0b11, 1, GPR64, int_aarch64_crc32cx, "crc32cx">;
729
730
731//===----------------------------------------------------------------------===//
732// Logical instructions.
733//===----------------------------------------------------------------------===//
734
735// (immediate)
736defm ANDS : LogicalImmS<0b11, "ands", AArch64and_flag, "bics">;
737defm AND  : LogicalImm<0b00, "and", and, "bic">;
738defm EOR  : LogicalImm<0b10, "eor", xor, "eon">;
739defm ORR  : LogicalImm<0b01, "orr", or, "orn">;
740
741// FIXME: these aliases *are* canonical sometimes (when movz can't be
742// used). Actually, it seems to be working right now, but putting logical_immXX
743// here is a bit dodgy on the AsmParser side too.
744def : InstAlias<"mov $dst, $imm", (ORRWri GPR32sp:$dst, WZR,
745                                          logical_imm32:$imm), 0>;
746def : InstAlias<"mov $dst, $imm", (ORRXri GPR64sp:$dst, XZR,
747                                          logical_imm64:$imm), 0>;
748
749
750// (register)
751defm ANDS : LogicalRegS<0b11, 0, "ands", AArch64and_flag>;
752defm BICS : LogicalRegS<0b11, 1, "bics",
753                        BinOpFrag<(AArch64and_flag node:$LHS, (not node:$RHS))>>;
754defm AND  : LogicalReg<0b00, 0, "and", and>;
755defm BIC  : LogicalReg<0b00, 1, "bic",
756                       BinOpFrag<(and node:$LHS, (not node:$RHS))>>;
757defm EON  : LogicalReg<0b10, 1, "eon",
758                       BinOpFrag<(xor node:$LHS, (not node:$RHS))>>;
759defm EOR  : LogicalReg<0b10, 0, "eor", xor>;
760defm ORN  : LogicalReg<0b01, 1, "orn",
761                       BinOpFrag<(or node:$LHS, (not node:$RHS))>>;
762defm ORR  : LogicalReg<0b01, 0, "orr", or>;
763
764def : InstAlias<"mov $dst, $src", (ORRWrs GPR32:$dst, WZR, GPR32:$src, 0), 2>;
765def : InstAlias<"mov $dst, $src", (ORRXrs GPR64:$dst, XZR, GPR64:$src, 0), 2>;
766
767def : InstAlias<"mvn $Wd, $Wm", (ORNWrs GPR32:$Wd, WZR, GPR32:$Wm, 0), 3>;
768def : InstAlias<"mvn $Xd, $Xm", (ORNXrs GPR64:$Xd, XZR, GPR64:$Xm, 0), 3>;
769
770def : InstAlias<"mvn $Wd, $Wm$sh",
771                (ORNWrs GPR32:$Wd, WZR, GPR32:$Wm, logical_shift32:$sh), 2>;
772def : InstAlias<"mvn $Xd, $Xm$sh",
773                (ORNXrs GPR64:$Xd, XZR, GPR64:$Xm, logical_shift64:$sh), 2>;
774
775def : InstAlias<"tst $src1, $src2",
776                (ANDSWri WZR, GPR32:$src1, logical_imm32:$src2), 2>;
777def : InstAlias<"tst $src1, $src2",
778                (ANDSXri XZR, GPR64:$src1, logical_imm64:$src2), 2>;
779
780def : InstAlias<"tst $src1, $src2",
781                        (ANDSWrs WZR, GPR32:$src1, GPR32:$src2, 0), 3>;
782def : InstAlias<"tst $src1, $src2",
783                        (ANDSXrs XZR, GPR64:$src1, GPR64:$src2, 0), 3>;
784
785def : InstAlias<"tst $src1, $src2$sh",
786               (ANDSWrs WZR, GPR32:$src1, GPR32:$src2, logical_shift32:$sh), 2>;
787def : InstAlias<"tst $src1, $src2$sh",
788               (ANDSXrs XZR, GPR64:$src1, GPR64:$src2, logical_shift64:$sh), 2>;
789
790
791def : Pat<(not GPR32:$Wm), (ORNWrr WZR, GPR32:$Wm)>;
792def : Pat<(not GPR64:$Xm), (ORNXrr XZR, GPR64:$Xm)>;
793
794
795//===----------------------------------------------------------------------===//
796// One operand data processing instructions.
797//===----------------------------------------------------------------------===//
798
799defm CLS    : OneOperandData<0b101, "cls">;
800defm CLZ    : OneOperandData<0b100, "clz", ctlz>;
801defm RBIT   : OneOperandData<0b000, "rbit">;
802
803def : Pat<(int_aarch64_rbit GPR32:$Rn), (RBITWr $Rn)>;
804def : Pat<(int_aarch64_rbit GPR64:$Rn), (RBITXr $Rn)>;
805
806def  REV16Wr : OneWRegData<0b001, "rev16",
807                                  UnOpFrag<(rotr (bswap node:$LHS), (i64 16))>>;
808def  REV16Xr : OneXRegData<0b001, "rev16", null_frag>;
809
810def : Pat<(cttz GPR32:$Rn),
811          (CLZWr (RBITWr GPR32:$Rn))>;
812def : Pat<(cttz GPR64:$Rn),
813          (CLZXr (RBITXr GPR64:$Rn))>;
814def : Pat<(ctlz (or (shl (xor (sra GPR32:$Rn, (i64 31)), GPR32:$Rn), (i64 1)),
815                (i32 1))),
816          (CLSWr GPR32:$Rn)>;
817def : Pat<(ctlz (or (shl (xor (sra GPR64:$Rn, (i64 63)), GPR64:$Rn), (i64 1)),
818                (i64 1))),
819          (CLSXr GPR64:$Rn)>;
820
821// Unlike the other one operand instructions, the instructions with the "rev"
822// mnemonic do *not* just different in the size bit, but actually use different
823// opcode bits for the different sizes.
824def REVWr   : OneWRegData<0b010, "rev", bswap>;
825def REVXr   : OneXRegData<0b011, "rev", bswap>;
826def REV32Xr : OneXRegData<0b010, "rev32",
827                                 UnOpFrag<(rotr (bswap node:$LHS), (i64 32))>>;
828
829// The bswap commutes with the rotr so we want a pattern for both possible
830// orders.
831def : Pat<(bswap (rotr GPR32:$Rn, (i64 16))), (REV16Wr GPR32:$Rn)>;
832def : Pat<(bswap (rotr GPR64:$Rn, (i64 32))), (REV32Xr GPR64:$Rn)>;
833
834//===----------------------------------------------------------------------===//
835// Bitfield immediate extraction instruction.
836//===----------------------------------------------------------------------===//
837let hasSideEffects = 0 in
838defm EXTR : ExtractImm<"extr">;
839def : InstAlias<"ror $dst, $src, $shift",
840            (EXTRWrri GPR32:$dst, GPR32:$src, GPR32:$src, imm0_31:$shift)>;
841def : InstAlias<"ror $dst, $src, $shift",
842            (EXTRXrri GPR64:$dst, GPR64:$src, GPR64:$src, imm0_63:$shift)>;
843
844def : Pat<(rotr GPR32:$Rn, (i64 imm0_31:$imm)),
845          (EXTRWrri GPR32:$Rn, GPR32:$Rn, imm0_31:$imm)>;
846def : Pat<(rotr GPR64:$Rn, (i64 imm0_63:$imm)),
847          (EXTRXrri GPR64:$Rn, GPR64:$Rn, imm0_63:$imm)>;
848
849//===----------------------------------------------------------------------===//
850// Other bitfield immediate instructions.
851//===----------------------------------------------------------------------===//
852let hasSideEffects = 0 in {
853defm BFM  : BitfieldImmWith2RegArgs<0b01, "bfm">;
854defm SBFM : BitfieldImm<0b00, "sbfm">;
855defm UBFM : BitfieldImm<0b10, "ubfm">;
856}
857
858def i32shift_a : Operand<i64>, SDNodeXForm<imm, [{
859  uint64_t enc = (32 - N->getZExtValue()) & 0x1f;
860  return CurDAG->getTargetConstant(enc, MVT::i64);
861}]>;
862
863def i32shift_b : Operand<i64>, SDNodeXForm<imm, [{
864  uint64_t enc = 31 - N->getZExtValue();
865  return CurDAG->getTargetConstant(enc, MVT::i64);
866}]>;
867
868// min(7, 31 - shift_amt)
869def i32shift_sext_i8 : Operand<i64>, SDNodeXForm<imm, [{
870  uint64_t enc = 31 - N->getZExtValue();
871  enc = enc > 7 ? 7 : enc;
872  return CurDAG->getTargetConstant(enc, MVT::i64);
873}]>;
874
875// min(15, 31 - shift_amt)
876def i32shift_sext_i16 : Operand<i64>, SDNodeXForm<imm, [{
877  uint64_t enc = 31 - N->getZExtValue();
878  enc = enc > 15 ? 15 : enc;
879  return CurDAG->getTargetConstant(enc, MVT::i64);
880}]>;
881
882def i64shift_a : Operand<i64>, SDNodeXForm<imm, [{
883  uint64_t enc = (64 - N->getZExtValue()) & 0x3f;
884  return CurDAG->getTargetConstant(enc, MVT::i64);
885}]>;
886
887def i64shift_b : Operand<i64>, SDNodeXForm<imm, [{
888  uint64_t enc = 63 - N->getZExtValue();
889  return CurDAG->getTargetConstant(enc, MVT::i64);
890}]>;
891
892// min(7, 63 - shift_amt)
893def i64shift_sext_i8 : Operand<i64>, SDNodeXForm<imm, [{
894  uint64_t enc = 63 - N->getZExtValue();
895  enc = enc > 7 ? 7 : enc;
896  return CurDAG->getTargetConstant(enc, MVT::i64);
897}]>;
898
899// min(15, 63 - shift_amt)
900def i64shift_sext_i16 : Operand<i64>, SDNodeXForm<imm, [{
901  uint64_t enc = 63 - N->getZExtValue();
902  enc = enc > 15 ? 15 : enc;
903  return CurDAG->getTargetConstant(enc, MVT::i64);
904}]>;
905
906// min(31, 63 - shift_amt)
907def i64shift_sext_i32 : Operand<i64>, SDNodeXForm<imm, [{
908  uint64_t enc = 63 - N->getZExtValue();
909  enc = enc > 31 ? 31 : enc;
910  return CurDAG->getTargetConstant(enc, MVT::i64);
911}]>;
912
913def : Pat<(shl GPR32:$Rn, (i64 imm0_31:$imm)),
914          (UBFMWri GPR32:$Rn, (i64 (i32shift_a imm0_31:$imm)),
915                              (i64 (i32shift_b imm0_31:$imm)))>;
916def : Pat<(shl GPR64:$Rn, (i64 imm0_63:$imm)),
917          (UBFMXri GPR64:$Rn, (i64 (i64shift_a imm0_63:$imm)),
918                              (i64 (i64shift_b imm0_63:$imm)))>;
919
920let AddedComplexity = 10 in {
921def : Pat<(sra GPR32:$Rn, (i64 imm0_31:$imm)),
922          (SBFMWri GPR32:$Rn, imm0_31:$imm, 31)>;
923def : Pat<(sra GPR64:$Rn, (i64 imm0_63:$imm)),
924          (SBFMXri GPR64:$Rn, imm0_63:$imm, 63)>;
925}
926
927def : InstAlias<"asr $dst, $src, $shift",
928                (SBFMWri GPR32:$dst, GPR32:$src, imm0_31:$shift, 31)>;
929def : InstAlias<"asr $dst, $src, $shift",
930                (SBFMXri GPR64:$dst, GPR64:$src, imm0_63:$shift, 63)>;
931def : InstAlias<"sxtb $dst, $src", (SBFMWri GPR32:$dst, GPR32:$src, 0, 7)>;
932def : InstAlias<"sxtb $dst, $src", (SBFMXri GPR64:$dst, GPR64:$src, 0, 7)>;
933def : InstAlias<"sxth $dst, $src", (SBFMWri GPR32:$dst, GPR32:$src, 0, 15)>;
934def : InstAlias<"sxth $dst, $src", (SBFMXri GPR64:$dst, GPR64:$src, 0, 15)>;
935def : InstAlias<"sxtw $dst, $src", (SBFMXri GPR64:$dst, GPR64:$src, 0, 31)>;
936
937def : Pat<(srl GPR32:$Rn, (i64 imm0_31:$imm)),
938          (UBFMWri GPR32:$Rn, imm0_31:$imm, 31)>;
939def : Pat<(srl GPR64:$Rn, (i64 imm0_63:$imm)),
940          (UBFMXri GPR64:$Rn, imm0_63:$imm, 63)>;
941
942def : InstAlias<"lsr $dst, $src, $shift",
943                (UBFMWri GPR32:$dst, GPR32:$src, imm0_31:$shift, 31)>;
944def : InstAlias<"lsr $dst, $src, $shift",
945                (UBFMXri GPR64:$dst, GPR64:$src, imm0_63:$shift, 63)>;
946def : InstAlias<"uxtb $dst, $src", (UBFMWri GPR32:$dst, GPR32:$src, 0, 7)>;
947def : InstAlias<"uxtb $dst, $src", (UBFMXri GPR64:$dst, GPR64:$src, 0, 7)>;
948def : InstAlias<"uxth $dst, $src", (UBFMWri GPR32:$dst, GPR32:$src, 0, 15)>;
949def : InstAlias<"uxth $dst, $src", (UBFMXri GPR64:$dst, GPR64:$src, 0, 15)>;
950def : InstAlias<"uxtw $dst, $src", (UBFMXri GPR64:$dst, GPR64:$src, 0, 31)>;
951
952//===----------------------------------------------------------------------===//
953// Conditionally set flags instructions.
954//===----------------------------------------------------------------------===//
955defm CCMN : CondSetFlagsImm<0, "ccmn">;
956defm CCMP : CondSetFlagsImm<1, "ccmp">;
957
958defm CCMN : CondSetFlagsReg<0, "ccmn">;
959defm CCMP : CondSetFlagsReg<1, "ccmp">;
960
961//===----------------------------------------------------------------------===//
962// Conditional select instructions.
963//===----------------------------------------------------------------------===//
964defm CSEL  : CondSelect<0, 0b00, "csel">;
965
966def inc : PatFrag<(ops node:$in), (add node:$in, 1)>;
967defm CSINC : CondSelectOp<0, 0b01, "csinc", inc>;
968defm CSINV : CondSelectOp<1, 0b00, "csinv", not>;
969defm CSNEG : CondSelectOp<1, 0b01, "csneg", ineg>;
970
971def : Pat<(AArch64csinv GPR32:$tval, GPR32:$fval, (i32 imm:$cc), NZCV),
972          (CSINVWr GPR32:$tval, GPR32:$fval, (i32 imm:$cc))>;
973def : Pat<(AArch64csinv GPR64:$tval, GPR64:$fval, (i32 imm:$cc), NZCV),
974          (CSINVXr GPR64:$tval, GPR64:$fval, (i32 imm:$cc))>;
975def : Pat<(AArch64csneg GPR32:$tval, GPR32:$fval, (i32 imm:$cc), NZCV),
976          (CSNEGWr GPR32:$tval, GPR32:$fval, (i32 imm:$cc))>;
977def : Pat<(AArch64csneg GPR64:$tval, GPR64:$fval, (i32 imm:$cc), NZCV),
978          (CSNEGXr GPR64:$tval, GPR64:$fval, (i32 imm:$cc))>;
979def : Pat<(AArch64csinc GPR32:$tval, GPR32:$fval, (i32 imm:$cc), NZCV),
980          (CSINCWr GPR32:$tval, GPR32:$fval, (i32 imm:$cc))>;
981def : Pat<(AArch64csinc GPR64:$tval, GPR64:$fval, (i32 imm:$cc), NZCV),
982          (CSINCXr GPR64:$tval, GPR64:$fval, (i32 imm:$cc))>;
983
984def : Pat<(AArch64csel (i32 0), (i32 1), (i32 imm:$cc), NZCV),
985          (CSINCWr WZR, WZR, (i32 imm:$cc))>;
986def : Pat<(AArch64csel (i64 0), (i64 1), (i32 imm:$cc), NZCV),
987          (CSINCXr XZR, XZR, (i32 imm:$cc))>;
988def : Pat<(AArch64csel (i32 0), (i32 -1), (i32 imm:$cc), NZCV),
989          (CSINVWr WZR, WZR, (i32 imm:$cc))>;
990def : Pat<(AArch64csel (i64 0), (i64 -1), (i32 imm:$cc), NZCV),
991          (CSINVXr XZR, XZR, (i32 imm:$cc))>;
992
993// The inverse of the condition code from the alias instruction is what is used
994// in the aliased instruction. The parser all ready inverts the condition code
995// for these aliases.
996def : InstAlias<"cset $dst, $cc",
997                (CSINCWr GPR32:$dst, WZR, WZR, inv_ccode:$cc)>;
998def : InstAlias<"cset $dst, $cc",
999                (CSINCXr GPR64:$dst, XZR, XZR, inv_ccode:$cc)>;
1000
1001def : InstAlias<"csetm $dst, $cc",
1002                (CSINVWr GPR32:$dst, WZR, WZR, inv_ccode:$cc)>;
1003def : InstAlias<"csetm $dst, $cc",
1004                (CSINVXr GPR64:$dst, XZR, XZR, inv_ccode:$cc)>;
1005
1006def : InstAlias<"cinc $dst, $src, $cc",
1007                (CSINCWr GPR32:$dst, GPR32:$src, GPR32:$src, inv_ccode:$cc)>;
1008def : InstAlias<"cinc $dst, $src, $cc",
1009                (CSINCXr GPR64:$dst, GPR64:$src, GPR64:$src, inv_ccode:$cc)>;
1010
1011def : InstAlias<"cinv $dst, $src, $cc",
1012                (CSINVWr GPR32:$dst, GPR32:$src, GPR32:$src, inv_ccode:$cc)>;
1013def : InstAlias<"cinv $dst, $src, $cc",
1014                (CSINVXr GPR64:$dst, GPR64:$src, GPR64:$src, inv_ccode:$cc)>;
1015
1016def : InstAlias<"cneg $dst, $src, $cc",
1017                (CSNEGWr GPR32:$dst, GPR32:$src, GPR32:$src, inv_ccode:$cc)>;
1018def : InstAlias<"cneg $dst, $src, $cc",
1019                (CSNEGXr GPR64:$dst, GPR64:$src, GPR64:$src, inv_ccode:$cc)>;
1020
1021//===----------------------------------------------------------------------===//
1022// PC-relative instructions.
1023//===----------------------------------------------------------------------===//
1024let isReMaterializable = 1 in {
1025let hasSideEffects = 0, mayStore = 0, mayLoad = 0 in {
1026def ADR  : ADRI<0, "adr", adrlabel, []>;
1027} // hasSideEffects = 0
1028
1029def ADRP : ADRI<1, "adrp", adrplabel,
1030                [(set GPR64:$Xd, (AArch64adrp tglobaladdr:$label))]>;
1031} // isReMaterializable = 1
1032
1033// page address of a constant pool entry, block address
1034def : Pat<(AArch64adrp tconstpool:$cp), (ADRP tconstpool:$cp)>;
1035def : Pat<(AArch64adrp tblockaddress:$cp), (ADRP tblockaddress:$cp)>;
1036
1037//===----------------------------------------------------------------------===//
1038// Unconditional branch (register) instructions.
1039//===----------------------------------------------------------------------===//
1040
1041let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
1042def RET  : BranchReg<0b0010, "ret", []>;
1043def DRPS : SpecialReturn<0b0101, "drps">;
1044def ERET : SpecialReturn<0b0100, "eret">;
1045} // isReturn = 1, isTerminator = 1, isBarrier = 1
1046
1047// Default to the LR register.
1048def : InstAlias<"ret", (RET LR)>;
1049
1050let isCall = 1, Defs = [LR], Uses = [SP] in {
1051def BLR : BranchReg<0b0001, "blr", [(AArch64call GPR64:$Rn)]>;
1052} // isCall
1053
1054let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
1055def BR  : BranchReg<0b0000, "br", [(brind GPR64:$Rn)]>;
1056} // isBranch, isTerminator, isBarrier, isIndirectBranch
1057
1058// Create a separate pseudo-instruction for codegen to use so that we don't
1059// flag lr as used in every function. It'll be restored before the RET by the
1060// epilogue if it's legitimately used.
1061def RET_ReallyLR : Pseudo<(outs), (ins), [(AArch64retflag)]> {
1062  let isTerminator = 1;
1063  let isBarrier = 1;
1064  let isReturn = 1;
1065}
1066
1067// This is a directive-like pseudo-instruction. The purpose is to insert an
1068// R_AARCH64_TLSDESC_CALL relocation at the offset of the following instruction
1069// (which in the usual case is a BLR).
1070let hasSideEffects = 1 in
1071def TLSDESCCALL : Pseudo<(outs), (ins i64imm:$sym), []> {
1072  let AsmString = ".tlsdesccall $sym";
1073}
1074
1075// FIXME: maybe the scratch register used shouldn't be fixed to X1?
1076// FIXME: can "hasSideEffects be dropped?
1077let isCall = 1, Defs = [LR, X0, X1], hasSideEffects = 1,
1078    isCodeGenOnly = 1 in
1079def TLSDESC_CALLSEQ
1080    : Pseudo<(outs), (ins i64imm:$sym),
1081             [(AArch64tlsdesc_callseq tglobaltlsaddr:$sym)]>;
1082def : Pat<(AArch64tlsdesc_callseq texternalsym:$sym),
1083          (TLSDESC_CALLSEQ texternalsym:$sym)>;
1084
1085//===----------------------------------------------------------------------===//
1086// Conditional branch (immediate) instruction.
1087//===----------------------------------------------------------------------===//
1088def Bcc : BranchCond;
1089
1090//===----------------------------------------------------------------------===//
1091// Compare-and-branch instructions.
1092//===----------------------------------------------------------------------===//
1093defm CBZ  : CmpBranch<0, "cbz", AArch64cbz>;
1094defm CBNZ : CmpBranch<1, "cbnz", AArch64cbnz>;
1095
1096//===----------------------------------------------------------------------===//
1097// Test-bit-and-branch instructions.
1098//===----------------------------------------------------------------------===//
1099defm TBZ  : TestBranch<0, "tbz", AArch64tbz>;
1100defm TBNZ : TestBranch<1, "tbnz", AArch64tbnz>;
1101
1102//===----------------------------------------------------------------------===//
1103// Unconditional branch (immediate) instructions.
1104//===----------------------------------------------------------------------===//
1105let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
1106def B  : BranchImm<0, "b", [(br bb:$addr)]>;
1107} // isBranch, isTerminator, isBarrier
1108
1109let isCall = 1, Defs = [LR], Uses = [SP] in {
1110def BL : CallImm<1, "bl", [(AArch64call tglobaladdr:$addr)]>;
1111} // isCall
1112def : Pat<(AArch64call texternalsym:$func), (BL texternalsym:$func)>;
1113
1114//===----------------------------------------------------------------------===//
1115// Exception generation instructions.
1116//===----------------------------------------------------------------------===//
1117def BRK   : ExceptionGeneration<0b001, 0b00, "brk">;
1118def DCPS1 : ExceptionGeneration<0b101, 0b01, "dcps1">;
1119def DCPS2 : ExceptionGeneration<0b101, 0b10, "dcps2">;
1120def DCPS3 : ExceptionGeneration<0b101, 0b11, "dcps3">;
1121def HLT   : ExceptionGeneration<0b010, 0b00, "hlt">;
1122def HVC   : ExceptionGeneration<0b000, 0b10, "hvc">;
1123def SMC   : ExceptionGeneration<0b000, 0b11, "smc">;
1124def SVC   : ExceptionGeneration<0b000, 0b01, "svc">;
1125
1126// DCPSn defaults to an immediate operand of zero if unspecified.
1127def : InstAlias<"dcps1", (DCPS1 0)>;
1128def : InstAlias<"dcps2", (DCPS2 0)>;
1129def : InstAlias<"dcps3", (DCPS3 0)>;
1130
1131//===----------------------------------------------------------------------===//
1132// Load instructions.
1133//===----------------------------------------------------------------------===//
1134
1135// Pair (indexed, offset)
1136defm LDPW : LoadPairOffset<0b00, 0, GPR32, simm7s4, "ldp">;
1137defm LDPX : LoadPairOffset<0b10, 0, GPR64, simm7s8, "ldp">;
1138defm LDPS : LoadPairOffset<0b00, 1, FPR32, simm7s4, "ldp">;
1139defm LDPD : LoadPairOffset<0b01, 1, FPR64, simm7s8, "ldp">;
1140defm LDPQ : LoadPairOffset<0b10, 1, FPR128, simm7s16, "ldp">;
1141
1142defm LDPSW : LoadPairOffset<0b01, 0, GPR64, simm7s4, "ldpsw">;
1143
1144// Pair (pre-indexed)
1145def LDPWpre : LoadPairPreIdx<0b00, 0, GPR32, simm7s4, "ldp">;
1146def LDPXpre : LoadPairPreIdx<0b10, 0, GPR64, simm7s8, "ldp">;
1147def LDPSpre : LoadPairPreIdx<0b00, 1, FPR32, simm7s4, "ldp">;
1148def LDPDpre : LoadPairPreIdx<0b01, 1, FPR64, simm7s8, "ldp">;
1149def LDPQpre : LoadPairPreIdx<0b10, 1, FPR128, simm7s16, "ldp">;
1150
1151def LDPSWpre : LoadPairPreIdx<0b01, 0, GPR64, simm7s4, "ldpsw">;
1152
1153// Pair (post-indexed)
1154def LDPWpost : LoadPairPostIdx<0b00, 0, GPR32, simm7s4, "ldp">;
1155def LDPXpost : LoadPairPostIdx<0b10, 0, GPR64, simm7s8, "ldp">;
1156def LDPSpost : LoadPairPostIdx<0b00, 1, FPR32, simm7s4, "ldp">;
1157def LDPDpost : LoadPairPostIdx<0b01, 1, FPR64, simm7s8, "ldp">;
1158def LDPQpost : LoadPairPostIdx<0b10, 1, FPR128, simm7s16, "ldp">;
1159
1160def LDPSWpost : LoadPairPostIdx<0b01, 0, GPR64, simm7s4, "ldpsw">;
1161
1162
1163// Pair (no allocate)
1164defm LDNPW : LoadPairNoAlloc<0b00, 0, GPR32, simm7s4, "ldnp">;
1165defm LDNPX : LoadPairNoAlloc<0b10, 0, GPR64, simm7s8, "ldnp">;
1166defm LDNPS : LoadPairNoAlloc<0b00, 1, FPR32, simm7s4, "ldnp">;
1167defm LDNPD : LoadPairNoAlloc<0b01, 1, FPR64, simm7s8, "ldnp">;
1168defm LDNPQ : LoadPairNoAlloc<0b10, 1, FPR128, simm7s16, "ldnp">;
1169
1170//---
1171// (register offset)
1172//---
1173
1174// Integer
1175defm LDRBB : Load8RO<0b00,  0, 0b01, GPR32, "ldrb", i32, zextloadi8>;
1176defm LDRHH : Load16RO<0b01, 0, 0b01, GPR32, "ldrh", i32, zextloadi16>;
1177defm LDRW  : Load32RO<0b10, 0, 0b01, GPR32, "ldr", i32, load>;
1178defm LDRX  : Load64RO<0b11, 0, 0b01, GPR64, "ldr", i64, load>;
1179
1180// Floating-point
1181defm LDRB : Load8RO<0b00,   1, 0b01, FPR8,   "ldr", untyped, load>;
1182defm LDRH : Load16RO<0b01,  1, 0b01, FPR16,  "ldr", f16, load>;
1183defm LDRS : Load32RO<0b10,  1, 0b01, FPR32,  "ldr", f32, load>;
1184defm LDRD : Load64RO<0b11,  1, 0b01, FPR64,  "ldr", f64, load>;
1185defm LDRQ : Load128RO<0b00, 1, 0b11, FPR128, "ldr", f128, load>;
1186
1187// Load sign-extended half-word
1188defm LDRSHW : Load16RO<0b01, 0, 0b11, GPR32, "ldrsh", i32, sextloadi16>;
1189defm LDRSHX : Load16RO<0b01, 0, 0b10, GPR64, "ldrsh", i64, sextloadi16>;
1190
1191// Load sign-extended byte
1192defm LDRSBW : Load8RO<0b00, 0, 0b11, GPR32, "ldrsb", i32, sextloadi8>;
1193defm LDRSBX : Load8RO<0b00, 0, 0b10, GPR64, "ldrsb", i64, sextloadi8>;
1194
1195// Load sign-extended word
1196defm LDRSW  : Load32RO<0b10, 0, 0b10, GPR64, "ldrsw", i64, sextloadi32>;
1197
1198// Pre-fetch.
1199defm PRFM : PrefetchRO<0b11, 0, 0b10, "prfm">;
1200
1201// For regular load, we do not have any alignment requirement.
1202// Thus, it is safe to directly map the vector loads with interesting
1203// addressing modes.
1204// FIXME: We could do the same for bitconvert to floating point vectors.
1205multiclass ScalToVecROLoadPat<ROAddrMode ro, SDPatternOperator loadop,
1206                              ValueType ScalTy, ValueType VecTy,
1207                              Instruction LOADW, Instruction LOADX,
1208                              SubRegIndex sub> {
1209  def : Pat<(VecTy (scalar_to_vector (ScalTy
1210              (loadop (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$offset))))),
1211            (INSERT_SUBREG (VecTy (IMPLICIT_DEF)),
1212                           (LOADW GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$offset),
1213                           sub)>;
1214
1215  def : Pat<(VecTy (scalar_to_vector (ScalTy
1216              (loadop (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$offset))))),
1217            (INSERT_SUBREG (VecTy (IMPLICIT_DEF)),
1218                           (LOADX GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$offset),
1219                           sub)>;
1220}
1221
1222let AddedComplexity = 10 in {
1223defm : ScalToVecROLoadPat<ro8,  extloadi8,  i32, v8i8,  LDRBroW, LDRBroX, bsub>;
1224defm : ScalToVecROLoadPat<ro8,  extloadi8,  i32, v16i8, LDRBroW, LDRBroX, bsub>;
1225
1226defm : ScalToVecROLoadPat<ro16, extloadi16, i32, v4i16, LDRHroW, LDRHroX, hsub>;
1227defm : ScalToVecROLoadPat<ro16, extloadi16, i32, v8i16, LDRHroW, LDRHroX, hsub>;
1228
1229defm : ScalToVecROLoadPat<ro16, load,       i32, v4f16, LDRHroW, LDRHroX, hsub>;
1230defm : ScalToVecROLoadPat<ro16, load,       i32, v8f16, LDRHroW, LDRHroX, hsub>;
1231
1232defm : ScalToVecROLoadPat<ro32, load,       i32, v2i32, LDRSroW, LDRSroX, ssub>;
1233defm : ScalToVecROLoadPat<ro32, load,       i32, v4i32, LDRSroW, LDRSroX, ssub>;
1234
1235defm : ScalToVecROLoadPat<ro32, load,       f32, v2f32, LDRSroW, LDRSroX, ssub>;
1236defm : ScalToVecROLoadPat<ro32, load,       f32, v4f32, LDRSroW, LDRSroX, ssub>;
1237
1238defm : ScalToVecROLoadPat<ro64, load,       i64, v2i64, LDRDroW, LDRDroX, dsub>;
1239
1240defm : ScalToVecROLoadPat<ro64, load,       f64, v2f64, LDRDroW, LDRDroX, dsub>;
1241
1242
1243def : Pat <(v1i64 (scalar_to_vector (i64
1244                      (load (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
1245                                           ro_Wextend64:$extend))))),
1246           (LDRDroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend)>;
1247
1248def : Pat <(v1i64 (scalar_to_vector (i64
1249                      (load (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
1250                                           ro_Xextend64:$extend))))),
1251           (LDRDroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend)>;
1252}
1253
1254// Match all load 64 bits width whose type is compatible with FPR64
1255multiclass VecROLoadPat<ROAddrMode ro, ValueType VecTy,
1256                        Instruction LOADW, Instruction LOADX> {
1257
1258  def : Pat<(VecTy (load (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend))),
1259            (LOADW GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)>;
1260
1261  def : Pat<(VecTy (load (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend))),
1262            (LOADX GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)>;
1263}
1264
1265let AddedComplexity = 10 in {
1266let Predicates = [IsLE] in {
1267  // We must do vector loads with LD1 in big-endian.
1268  defm : VecROLoadPat<ro64, v2i32, LDRDroW, LDRDroX>;
1269  defm : VecROLoadPat<ro64, v2f32, LDRDroW, LDRDroX>;
1270  defm : VecROLoadPat<ro64, v8i8,  LDRDroW, LDRDroX>;
1271  defm : VecROLoadPat<ro64, v4i16, LDRDroW, LDRDroX>;
1272  defm : VecROLoadPat<ro64, v4f16, LDRDroW, LDRDroX>;
1273}
1274
1275defm : VecROLoadPat<ro64, v1i64,  LDRDroW, LDRDroX>;
1276defm : VecROLoadPat<ro64, v1f64,  LDRDroW, LDRDroX>;
1277
1278// Match all load 128 bits width whose type is compatible with FPR128
1279let Predicates = [IsLE] in {
1280  // We must do vector loads with LD1 in big-endian.
1281  defm : VecROLoadPat<ro128, v2i64,  LDRQroW, LDRQroX>;
1282  defm : VecROLoadPat<ro128, v2f64,  LDRQroW, LDRQroX>;
1283  defm : VecROLoadPat<ro128, v4i32,  LDRQroW, LDRQroX>;
1284  defm : VecROLoadPat<ro128, v4f32,  LDRQroW, LDRQroX>;
1285  defm : VecROLoadPat<ro128, v8i16,  LDRQroW, LDRQroX>;
1286  defm : VecROLoadPat<ro128, v8f16,  LDRQroW, LDRQroX>;
1287  defm : VecROLoadPat<ro128, v16i8,  LDRQroW, LDRQroX>;
1288}
1289} // AddedComplexity = 10
1290
1291// zextload -> i64
1292multiclass ExtLoadTo64ROPat<ROAddrMode ro, SDPatternOperator loadop,
1293                            Instruction INSTW, Instruction INSTX> {
1294  def : Pat<(i64 (loadop (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend))),
1295            (SUBREG_TO_REG (i64 0),
1296                           (INSTW GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend),
1297                           sub_32)>;
1298
1299  def : Pat<(i64 (loadop (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend))),
1300            (SUBREG_TO_REG (i64 0),
1301                           (INSTX GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend),
1302                           sub_32)>;
1303}
1304
1305let AddedComplexity = 10 in {
1306  defm : ExtLoadTo64ROPat<ro8,  zextloadi8,  LDRBBroW, LDRBBroX>;
1307  defm : ExtLoadTo64ROPat<ro16, zextloadi16, LDRHHroW, LDRHHroX>;
1308  defm : ExtLoadTo64ROPat<ro32, zextloadi32, LDRWroW,  LDRWroX>;
1309
1310  // zextloadi1 -> zextloadi8
1311  defm : ExtLoadTo64ROPat<ro8,  zextloadi1,  LDRBBroW, LDRBBroX>;
1312
1313  // extload -> zextload
1314  defm : ExtLoadTo64ROPat<ro8,  extloadi8,   LDRBBroW, LDRBBroX>;
1315  defm : ExtLoadTo64ROPat<ro16, extloadi16,  LDRHHroW, LDRHHroX>;
1316  defm : ExtLoadTo64ROPat<ro32, extloadi32,  LDRWroW,  LDRWroX>;
1317
1318  // extloadi1 -> zextloadi8
1319  defm : ExtLoadTo64ROPat<ro8,  extloadi1,   LDRBBroW, LDRBBroX>;
1320}
1321
1322
1323// zextload -> i64
1324multiclass ExtLoadTo32ROPat<ROAddrMode ro, SDPatternOperator loadop,
1325                            Instruction INSTW, Instruction INSTX> {
1326  def : Pat<(i32 (loadop (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend))),
1327            (INSTW GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)>;
1328
1329  def : Pat<(i32 (loadop (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend))),
1330            (INSTX GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)>;
1331
1332}
1333
1334let AddedComplexity = 10 in {
1335  // extload -> zextload
1336  defm : ExtLoadTo32ROPat<ro8,  extloadi8,   LDRBBroW, LDRBBroX>;
1337  defm : ExtLoadTo32ROPat<ro16, extloadi16,  LDRHHroW, LDRHHroX>;
1338  defm : ExtLoadTo32ROPat<ro32, extloadi32,  LDRWroW,  LDRWroX>;
1339
1340  // zextloadi1 -> zextloadi8
1341  defm : ExtLoadTo32ROPat<ro8, zextloadi1, LDRBBroW, LDRBBroX>;
1342}
1343
1344//---
1345// (unsigned immediate)
1346//---
1347defm LDRX : LoadUI<0b11, 0, 0b01, GPR64, uimm12s8, "ldr",
1348                   [(set GPR64:$Rt,
1349                         (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)))]>;
1350defm LDRW : LoadUI<0b10, 0, 0b01, GPR32, uimm12s4, "ldr",
1351                   [(set GPR32:$Rt,
1352                         (load (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset)))]>;
1353defm LDRB : LoadUI<0b00, 1, 0b01, FPR8, uimm12s1, "ldr",
1354                   [(set FPR8:$Rt,
1355                         (load (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset)))]>;
1356defm LDRH : LoadUI<0b01, 1, 0b01, FPR16, uimm12s2, "ldr",
1357                   [(set (f16 FPR16:$Rt),
1358                         (load (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset)))]>;
1359defm LDRS : LoadUI<0b10, 1, 0b01, FPR32, uimm12s4, "ldr",
1360                   [(set (f32 FPR32:$Rt),
1361                         (load (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset)))]>;
1362defm LDRD : LoadUI<0b11, 1, 0b01, FPR64, uimm12s8, "ldr",
1363                   [(set (f64 FPR64:$Rt),
1364                         (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)))]>;
1365defm LDRQ : LoadUI<0b00, 1, 0b11, FPR128, uimm12s16, "ldr",
1366                 [(set (f128 FPR128:$Rt),
1367                       (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)))]>;
1368
1369// For regular load, we do not have any alignment requirement.
1370// Thus, it is safe to directly map the vector loads with interesting
1371// addressing modes.
1372// FIXME: We could do the same for bitconvert to floating point vectors.
1373def : Pat <(v8i8 (scalar_to_vector (i32
1374               (extloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))))),
1375           (INSERT_SUBREG (v8i8 (IMPLICIT_DEF)),
1376                          (LDRBui GPR64sp:$Rn, uimm12s1:$offset), bsub)>;
1377def : Pat <(v16i8 (scalar_to_vector (i32
1378               (extloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))))),
1379           (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
1380                          (LDRBui GPR64sp:$Rn, uimm12s1:$offset), bsub)>;
1381def : Pat <(v4i16 (scalar_to_vector (i32
1382               (extloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))))),
1383           (INSERT_SUBREG (v4i16 (IMPLICIT_DEF)),
1384                          (LDRHui GPR64sp:$Rn, uimm12s2:$offset), hsub)>;
1385def : Pat <(v8i16 (scalar_to_vector (i32
1386               (extloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))))),
1387           (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)),
1388                          (LDRHui GPR64sp:$Rn, uimm12s2:$offset), hsub)>;
1389def : Pat <(v2i32 (scalar_to_vector (i32
1390               (load (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))))),
1391           (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
1392                          (LDRSui GPR64sp:$Rn, uimm12s4:$offset), ssub)>;
1393def : Pat <(v4i32 (scalar_to_vector (i32
1394               (load (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))))),
1395           (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
1396                          (LDRSui GPR64sp:$Rn, uimm12s4:$offset), ssub)>;
1397def : Pat <(v1i64 (scalar_to_vector (i64
1398               (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))))),
1399           (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>;
1400def : Pat <(v2i64 (scalar_to_vector (i64
1401               (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))))),
1402           (INSERT_SUBREG (v2i64 (IMPLICIT_DEF)),
1403                          (LDRDui GPR64sp:$Rn, uimm12s8:$offset), dsub)>;
1404
1405// Match all load 64 bits width whose type is compatible with FPR64
1406let Predicates = [IsLE] in {
1407  // We must use LD1 to perform vector loads in big-endian.
1408  def : Pat<(v2f32 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))),
1409            (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>;
1410  def : Pat<(v8i8 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))),
1411            (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>;
1412  def : Pat<(v4i16 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))),
1413            (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>;
1414  def : Pat<(v2i32 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))),
1415            (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>;
1416  def : Pat<(v4f16 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))),
1417            (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>;
1418}
1419def : Pat<(v1f64 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))),
1420          (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>;
1421def : Pat<(v1i64 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))),
1422          (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>;
1423
1424// Match all load 128 bits width whose type is compatible with FPR128
1425let Predicates = [IsLE] in {
1426  // We must use LD1 to perform vector loads in big-endian.
1427  def : Pat<(v4f32 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))),
1428            (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>;
1429  def : Pat<(v2f64 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))),
1430            (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>;
1431  def : Pat<(v16i8 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))),
1432            (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>;
1433  def : Pat<(v8i16 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))),
1434            (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>;
1435  def : Pat<(v4i32 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))),
1436            (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>;
1437  def : Pat<(v2i64 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))),
1438            (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>;
1439  def : Pat<(v8f16 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))),
1440            (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>;
1441}
1442def : Pat<(f128  (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))),
1443          (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>;
1444
1445defm LDRHH : LoadUI<0b01, 0, 0b01, GPR32, uimm12s2, "ldrh",
1446                    [(set GPR32:$Rt,
1447                          (zextloadi16 (am_indexed16 GPR64sp:$Rn,
1448                                                     uimm12s2:$offset)))]>;
1449defm LDRBB : LoadUI<0b00, 0, 0b01, GPR32, uimm12s1, "ldrb",
1450                    [(set GPR32:$Rt,
1451                          (zextloadi8 (am_indexed8 GPR64sp:$Rn,
1452                                                   uimm12s1:$offset)))]>;
1453// zextload -> i64
1454def : Pat<(i64 (zextloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))),
1455    (SUBREG_TO_REG (i64 0), (LDRBBui GPR64sp:$Rn, uimm12s1:$offset), sub_32)>;
1456def : Pat<(i64 (zextloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))),
1457    (SUBREG_TO_REG (i64 0), (LDRHHui GPR64sp:$Rn, uimm12s2:$offset), sub_32)>;
1458
1459// zextloadi1 -> zextloadi8
1460def : Pat<(i32 (zextloadi1 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))),
1461          (LDRBBui GPR64sp:$Rn, uimm12s1:$offset)>;
1462def : Pat<(i64 (zextloadi1 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))),
1463    (SUBREG_TO_REG (i64 0), (LDRBBui GPR64sp:$Rn, uimm12s1:$offset), sub_32)>;
1464
1465// extload -> zextload
1466def : Pat<(i32 (extloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))),
1467          (LDRHHui GPR64sp:$Rn, uimm12s2:$offset)>;
1468def : Pat<(i32 (extloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))),
1469          (LDRBBui GPR64sp:$Rn, uimm12s1:$offset)>;
1470def : Pat<(i32 (extloadi1 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))),
1471          (LDRBBui GPR64sp:$Rn, uimm12s1:$offset)>;
1472def : Pat<(i64 (extloadi32 (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))),
1473    (SUBREG_TO_REG (i64 0), (LDRWui GPR64sp:$Rn, uimm12s4:$offset), sub_32)>;
1474def : Pat<(i64 (extloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))),
1475    (SUBREG_TO_REG (i64 0), (LDRHHui GPR64sp:$Rn, uimm12s2:$offset), sub_32)>;
1476def : Pat<(i64 (extloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))),
1477    (SUBREG_TO_REG (i64 0), (LDRBBui GPR64sp:$Rn, uimm12s1:$offset), sub_32)>;
1478def : Pat<(i64 (extloadi1 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))),
1479    (SUBREG_TO_REG (i64 0), (LDRBBui GPR64sp:$Rn, uimm12s1:$offset), sub_32)>;
1480
1481// load sign-extended half-word
1482defm LDRSHW : LoadUI<0b01, 0, 0b11, GPR32, uimm12s2, "ldrsh",
1483                     [(set GPR32:$Rt,
1484                           (sextloadi16 (am_indexed16 GPR64sp:$Rn,
1485                                                      uimm12s2:$offset)))]>;
1486defm LDRSHX : LoadUI<0b01, 0, 0b10, GPR64, uimm12s2, "ldrsh",
1487                     [(set GPR64:$Rt,
1488                           (sextloadi16 (am_indexed16 GPR64sp:$Rn,
1489                                                      uimm12s2:$offset)))]>;
1490
1491// load sign-extended byte
1492defm LDRSBW : LoadUI<0b00, 0, 0b11, GPR32, uimm12s1, "ldrsb",
1493                     [(set GPR32:$Rt,
1494                           (sextloadi8 (am_indexed8 GPR64sp:$Rn,
1495                                                    uimm12s1:$offset)))]>;
1496defm LDRSBX : LoadUI<0b00, 0, 0b10, GPR64, uimm12s1, "ldrsb",
1497                     [(set GPR64:$Rt,
1498                           (sextloadi8 (am_indexed8 GPR64sp:$Rn,
1499                                                    uimm12s1:$offset)))]>;
1500
1501// load sign-extended word
1502defm LDRSW  : LoadUI<0b10, 0, 0b10, GPR64, uimm12s4, "ldrsw",
1503                     [(set GPR64:$Rt,
1504                           (sextloadi32 (am_indexed32 GPR64sp:$Rn,
1505                                                      uimm12s4:$offset)))]>;
1506
1507// load zero-extended word
1508def : Pat<(i64 (zextloadi32 (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))),
1509      (SUBREG_TO_REG (i64 0), (LDRWui GPR64sp:$Rn, uimm12s4:$offset), sub_32)>;
1510
1511// Pre-fetch.
1512def PRFMui : PrefetchUI<0b11, 0, 0b10, "prfm",
1513                        [(AArch64Prefetch imm:$Rt,
1514                                        (am_indexed64 GPR64sp:$Rn,
1515                                                      uimm12s8:$offset))]>;
1516
1517def : InstAlias<"prfm $Rt, [$Rn]", (PRFMui prfop:$Rt, GPR64sp:$Rn, 0)>;
1518
1519//---
1520// (literal)
1521def LDRWl : LoadLiteral<0b00, 0, GPR32, "ldr">;
1522def LDRXl : LoadLiteral<0b01, 0, GPR64, "ldr">;
1523def LDRSl : LoadLiteral<0b00, 1, FPR32, "ldr">;
1524def LDRDl : LoadLiteral<0b01, 1, FPR64, "ldr">;
1525def LDRQl : LoadLiteral<0b10, 1, FPR128, "ldr">;
1526
1527// load sign-extended word
1528def LDRSWl : LoadLiteral<0b10, 0, GPR64, "ldrsw">;
1529
1530// prefetch
1531def PRFMl : PrefetchLiteral<0b11, 0, "prfm", []>;
1532//                   [(AArch64Prefetch imm:$Rt, tglobaladdr:$label)]>;
1533
1534//---
1535// (unscaled immediate)
1536defm LDURX : LoadUnscaled<0b11, 0, 0b01, GPR64, "ldur",
1537                    [(set GPR64:$Rt,
1538                          (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset)))]>;
1539defm LDURW : LoadUnscaled<0b10, 0, 0b01, GPR32, "ldur",
1540                    [(set GPR32:$Rt,
1541                          (load (am_unscaled32 GPR64sp:$Rn, simm9:$offset)))]>;
1542defm LDURB : LoadUnscaled<0b00, 1, 0b01, FPR8, "ldur",
1543                    [(set FPR8:$Rt,
1544                          (load (am_unscaled8 GPR64sp:$Rn, simm9:$offset)))]>;
1545defm LDURH : LoadUnscaled<0b01, 1, 0b01, FPR16, "ldur",
1546                    [(set FPR16:$Rt,
1547                          (load (am_unscaled16 GPR64sp:$Rn, simm9:$offset)))]>;
1548defm LDURS : LoadUnscaled<0b10, 1, 0b01, FPR32, "ldur",
1549                    [(set (f32 FPR32:$Rt),
1550                          (load (am_unscaled32 GPR64sp:$Rn, simm9:$offset)))]>;
1551defm LDURD : LoadUnscaled<0b11, 1, 0b01, FPR64, "ldur",
1552                    [(set (f64 FPR64:$Rt),
1553                          (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset)))]>;
1554defm LDURQ : LoadUnscaled<0b00, 1, 0b11, FPR128, "ldur",
1555                    [(set (f128 FPR128:$Rt),
1556                          (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset)))]>;
1557
1558defm LDURHH
1559    : LoadUnscaled<0b01, 0, 0b01, GPR32, "ldurh",
1560             [(set GPR32:$Rt,
1561                    (zextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset)))]>;
1562defm LDURBB
1563    : LoadUnscaled<0b00, 0, 0b01, GPR32, "ldurb",
1564             [(set GPR32:$Rt,
1565                    (zextloadi8 (am_unscaled16 GPR64sp:$Rn, simm9:$offset)))]>;
1566
1567// Match all load 64 bits width whose type is compatible with FPR64
1568let Predicates = [IsLE] in {
1569  def : Pat<(v2f32 (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset))),
1570            (LDURDi GPR64sp:$Rn, simm9:$offset)>;
1571  def : Pat<(v2i32 (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset))),
1572            (LDURDi GPR64sp:$Rn, simm9:$offset)>;
1573  def : Pat<(v4i16 (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset))),
1574            (LDURDi GPR64sp:$Rn, simm9:$offset)>;
1575  def : Pat<(v8i8 (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset))),
1576            (LDURDi GPR64sp:$Rn, simm9:$offset)>;
1577  def : Pat<(v4f16 (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset))),
1578            (LDURDi GPR64sp:$Rn, simm9:$offset)>;
1579}
1580def : Pat<(v1f64 (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset))),
1581          (LDURDi GPR64sp:$Rn, simm9:$offset)>;
1582def : Pat<(v1i64 (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset))),
1583          (LDURDi GPR64sp:$Rn, simm9:$offset)>;
1584
1585// Match all load 128 bits width whose type is compatible with FPR128
1586let Predicates = [IsLE] in {
1587  def : Pat<(v2f64 (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset))),
1588            (LDURQi GPR64sp:$Rn, simm9:$offset)>;
1589  def : Pat<(v2i64 (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset))),
1590            (LDURQi GPR64sp:$Rn, simm9:$offset)>;
1591  def : Pat<(v4f32 (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset))),
1592            (LDURQi GPR64sp:$Rn, simm9:$offset)>;
1593  def : Pat<(v4i32 (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset))),
1594            (LDURQi GPR64sp:$Rn, simm9:$offset)>;
1595  def : Pat<(v8i16 (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset))),
1596            (LDURQi GPR64sp:$Rn, simm9:$offset)>;
1597  def : Pat<(v16i8 (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset))),
1598            (LDURQi GPR64sp:$Rn, simm9:$offset)>;
1599  def : Pat<(v8f16 (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset))),
1600            (LDURQi GPR64sp:$Rn, simm9:$offset)>;
1601}
1602
1603//  anyext -> zext
1604def : Pat<(i32 (extloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))),
1605          (LDURHHi GPR64sp:$Rn, simm9:$offset)>;
1606def : Pat<(i32 (extloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))),
1607          (LDURBBi GPR64sp:$Rn, simm9:$offset)>;
1608def : Pat<(i32 (extloadi1 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))),
1609          (LDURBBi GPR64sp:$Rn, simm9:$offset)>;
1610def : Pat<(i64 (extloadi32 (am_unscaled32 GPR64sp:$Rn, simm9:$offset))),
1611    (SUBREG_TO_REG (i64 0), (LDURWi GPR64sp:$Rn, simm9:$offset), sub_32)>;
1612def : Pat<(i64 (extloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))),
1613    (SUBREG_TO_REG (i64 0), (LDURHHi GPR64sp:$Rn, simm9:$offset), sub_32)>;
1614def : Pat<(i64 (extloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))),
1615    (SUBREG_TO_REG (i64 0), (LDURBBi GPR64sp:$Rn, simm9:$offset), sub_32)>;
1616def : Pat<(i64 (extloadi1 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))),
1617    (SUBREG_TO_REG (i64 0), (LDURBBi GPR64sp:$Rn, simm9:$offset), sub_32)>;
1618// unscaled zext
1619def : Pat<(i32 (zextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))),
1620          (LDURHHi GPR64sp:$Rn, simm9:$offset)>;
1621def : Pat<(i32 (zextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))),
1622          (LDURBBi GPR64sp:$Rn, simm9:$offset)>;
1623def : Pat<(i32 (zextloadi1 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))),
1624          (LDURBBi GPR64sp:$Rn, simm9:$offset)>;
1625def : Pat<(i64 (zextloadi32 (am_unscaled32 GPR64sp:$Rn, simm9:$offset))),
1626    (SUBREG_TO_REG (i64 0), (LDURWi GPR64sp:$Rn, simm9:$offset), sub_32)>;
1627def : Pat<(i64 (zextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))),
1628    (SUBREG_TO_REG (i64 0), (LDURHHi GPR64sp:$Rn, simm9:$offset), sub_32)>;
1629def : Pat<(i64 (zextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))),
1630    (SUBREG_TO_REG (i64 0), (LDURBBi GPR64sp:$Rn, simm9:$offset), sub_32)>;
1631def : Pat<(i64 (zextloadi1 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))),
1632    (SUBREG_TO_REG (i64 0), (LDURBBi GPR64sp:$Rn, simm9:$offset), sub_32)>;
1633
1634
1635//---
1636// LDR mnemonics fall back to LDUR for negative or unaligned offsets.
1637
1638// Define new assembler match classes as we want to only match these when
1639// the don't otherwise match the scaled addressing mode for LDR/STR. Don't
1640// associate a DiagnosticType either, as we want the diagnostic for the
1641// canonical form (the scaled operand) to take precedence.
1642class SImm9OffsetOperand<int Width> : AsmOperandClass {
1643  let Name = "SImm9OffsetFB" # Width;
1644  let PredicateMethod = "isSImm9OffsetFB<" # Width # ">";
1645  let RenderMethod = "addImmOperands";
1646}
1647
1648def SImm9OffsetFB8Operand : SImm9OffsetOperand<8>;
1649def SImm9OffsetFB16Operand : SImm9OffsetOperand<16>;
1650def SImm9OffsetFB32Operand : SImm9OffsetOperand<32>;
1651def SImm9OffsetFB64Operand : SImm9OffsetOperand<64>;
1652def SImm9OffsetFB128Operand : SImm9OffsetOperand<128>;
1653
1654def simm9_offset_fb8 : Operand<i64> {
1655  let ParserMatchClass = SImm9OffsetFB8Operand;
1656}
1657def simm9_offset_fb16 : Operand<i64> {
1658  let ParserMatchClass = SImm9OffsetFB16Operand;
1659}
1660def simm9_offset_fb32 : Operand<i64> {
1661  let ParserMatchClass = SImm9OffsetFB32Operand;
1662}
1663def simm9_offset_fb64 : Operand<i64> {
1664  let ParserMatchClass = SImm9OffsetFB64Operand;
1665}
1666def simm9_offset_fb128 : Operand<i64> {
1667  let ParserMatchClass = SImm9OffsetFB128Operand;
1668}
1669
1670def : InstAlias<"ldr $Rt, [$Rn, $offset]",
1671                (LDURXi GPR64:$Rt, GPR64sp:$Rn, simm9_offset_fb64:$offset), 0>;
1672def : InstAlias<"ldr $Rt, [$Rn, $offset]",
1673                (LDURWi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb32:$offset), 0>;
1674def : InstAlias<"ldr $Rt, [$Rn, $offset]",
1675                (LDURBi FPR8:$Rt, GPR64sp:$Rn, simm9_offset_fb8:$offset), 0>;
1676def : InstAlias<"ldr $Rt, [$Rn, $offset]",
1677                (LDURHi FPR16:$Rt, GPR64sp:$Rn, simm9_offset_fb16:$offset), 0>;
1678def : InstAlias<"ldr $Rt, [$Rn, $offset]",
1679                (LDURSi FPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb32:$offset), 0>;
1680def : InstAlias<"ldr $Rt, [$Rn, $offset]",
1681                (LDURDi FPR64:$Rt, GPR64sp:$Rn, simm9_offset_fb64:$offset), 0>;
1682def : InstAlias<"ldr $Rt, [$Rn, $offset]",
1683               (LDURQi FPR128:$Rt, GPR64sp:$Rn, simm9_offset_fb128:$offset), 0>;
1684
1685// zextload -> i64
1686def : Pat<(i64 (zextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))),
1687  (SUBREG_TO_REG (i64 0), (LDURBBi GPR64sp:$Rn, simm9:$offset), sub_32)>;
1688def : Pat<(i64 (zextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))),
1689  (SUBREG_TO_REG (i64 0), (LDURHHi GPR64sp:$Rn, simm9:$offset), sub_32)>;
1690
1691// load sign-extended half-word
1692defm LDURSHW
1693    : LoadUnscaled<0b01, 0, 0b11, GPR32, "ldursh",
1694               [(set GPR32:$Rt,
1695                    (sextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset)))]>;
1696defm LDURSHX
1697    : LoadUnscaled<0b01, 0, 0b10, GPR64, "ldursh",
1698              [(set GPR64:$Rt,
1699                    (sextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset)))]>;
1700
1701// load sign-extended byte
1702defm LDURSBW
1703    : LoadUnscaled<0b00, 0, 0b11, GPR32, "ldursb",
1704                [(set GPR32:$Rt,
1705                      (sextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset)))]>;
1706defm LDURSBX
1707    : LoadUnscaled<0b00, 0, 0b10, GPR64, "ldursb",
1708                [(set GPR64:$Rt,
1709                      (sextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset)))]>;
1710
1711// load sign-extended word
1712defm LDURSW
1713    : LoadUnscaled<0b10, 0, 0b10, GPR64, "ldursw",
1714              [(set GPR64:$Rt,
1715                    (sextloadi32 (am_unscaled32 GPR64sp:$Rn, simm9:$offset)))]>;
1716
1717// zero and sign extending aliases from generic LDR* mnemonics to LDUR*.
1718def : InstAlias<"ldrb $Rt, [$Rn, $offset]",
1719                (LDURBBi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb8:$offset), 0>;
1720def : InstAlias<"ldrh $Rt, [$Rn, $offset]",
1721                (LDURHHi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb16:$offset), 0>;
1722def : InstAlias<"ldrsb $Rt, [$Rn, $offset]",
1723                (LDURSBWi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb8:$offset), 0>;
1724def : InstAlias<"ldrsb $Rt, [$Rn, $offset]",
1725                (LDURSBXi GPR64:$Rt, GPR64sp:$Rn, simm9_offset_fb8:$offset), 0>;
1726def : InstAlias<"ldrsh $Rt, [$Rn, $offset]",
1727                (LDURSHWi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb16:$offset), 0>;
1728def : InstAlias<"ldrsh $Rt, [$Rn, $offset]",
1729                (LDURSHXi GPR64:$Rt, GPR64sp:$Rn, simm9_offset_fb16:$offset), 0>;
1730def : InstAlias<"ldrsw $Rt, [$Rn, $offset]",
1731                (LDURSWi GPR64:$Rt, GPR64sp:$Rn, simm9_offset_fb32:$offset), 0>;
1732
1733// Pre-fetch.
1734defm PRFUM : PrefetchUnscaled<0b11, 0, 0b10, "prfum",
1735                  [(AArch64Prefetch imm:$Rt,
1736                                  (am_unscaled64 GPR64sp:$Rn, simm9:$offset))]>;
1737
1738//---
1739// (unscaled immediate, unprivileged)
1740defm LDTRX : LoadUnprivileged<0b11, 0, 0b01, GPR64, "ldtr">;
1741defm LDTRW : LoadUnprivileged<0b10, 0, 0b01, GPR32, "ldtr">;
1742
1743defm LDTRH : LoadUnprivileged<0b01, 0, 0b01, GPR32, "ldtrh">;
1744defm LDTRB : LoadUnprivileged<0b00, 0, 0b01, GPR32, "ldtrb">;
1745
1746// load sign-extended half-word
1747defm LDTRSHW : LoadUnprivileged<0b01, 0, 0b11, GPR32, "ldtrsh">;
1748defm LDTRSHX : LoadUnprivileged<0b01, 0, 0b10, GPR64, "ldtrsh">;
1749
1750// load sign-extended byte
1751defm LDTRSBW : LoadUnprivileged<0b00, 0, 0b11, GPR32, "ldtrsb">;
1752defm LDTRSBX : LoadUnprivileged<0b00, 0, 0b10, GPR64, "ldtrsb">;
1753
1754// load sign-extended word
1755defm LDTRSW  : LoadUnprivileged<0b10, 0, 0b10, GPR64, "ldtrsw">;
1756
1757//---
1758// (immediate pre-indexed)
1759def LDRWpre : LoadPreIdx<0b10, 0, 0b01, GPR32, "ldr">;
1760def LDRXpre : LoadPreIdx<0b11, 0, 0b01, GPR64, "ldr">;
1761def LDRBpre : LoadPreIdx<0b00, 1, 0b01, FPR8,  "ldr">;
1762def LDRHpre : LoadPreIdx<0b01, 1, 0b01, FPR16, "ldr">;
1763def LDRSpre : LoadPreIdx<0b10, 1, 0b01, FPR32, "ldr">;
1764def LDRDpre : LoadPreIdx<0b11, 1, 0b01, FPR64, "ldr">;
1765def LDRQpre : LoadPreIdx<0b00, 1, 0b11, FPR128, "ldr">;
1766
1767// load sign-extended half-word
1768def LDRSHWpre : LoadPreIdx<0b01, 0, 0b11, GPR32, "ldrsh">;
1769def LDRSHXpre : LoadPreIdx<0b01, 0, 0b10, GPR64, "ldrsh">;
1770
1771// load sign-extended byte
1772def LDRSBWpre : LoadPreIdx<0b00, 0, 0b11, GPR32, "ldrsb">;
1773def LDRSBXpre : LoadPreIdx<0b00, 0, 0b10, GPR64, "ldrsb">;
1774
1775// load zero-extended byte
1776def LDRBBpre : LoadPreIdx<0b00, 0, 0b01, GPR32, "ldrb">;
1777def LDRHHpre : LoadPreIdx<0b01, 0, 0b01, GPR32, "ldrh">;
1778
1779// load sign-extended word
1780def LDRSWpre : LoadPreIdx<0b10, 0, 0b10, GPR64, "ldrsw">;
1781
1782//---
1783// (immediate post-indexed)
1784def LDRWpost : LoadPostIdx<0b10, 0, 0b01, GPR32, "ldr">;
1785def LDRXpost : LoadPostIdx<0b11, 0, 0b01, GPR64, "ldr">;
1786def LDRBpost : LoadPostIdx<0b00, 1, 0b01, FPR8,  "ldr">;
1787def LDRHpost : LoadPostIdx<0b01, 1, 0b01, FPR16, "ldr">;
1788def LDRSpost : LoadPostIdx<0b10, 1, 0b01, FPR32, "ldr">;
1789def LDRDpost : LoadPostIdx<0b11, 1, 0b01, FPR64, "ldr">;
1790def LDRQpost : LoadPostIdx<0b00, 1, 0b11, FPR128, "ldr">;
1791
1792// load sign-extended half-word
1793def LDRSHWpost : LoadPostIdx<0b01, 0, 0b11, GPR32, "ldrsh">;
1794def LDRSHXpost : LoadPostIdx<0b01, 0, 0b10, GPR64, "ldrsh">;
1795
1796// load sign-extended byte
1797def LDRSBWpost : LoadPostIdx<0b00, 0, 0b11, GPR32, "ldrsb">;
1798def LDRSBXpost : LoadPostIdx<0b00, 0, 0b10, GPR64, "ldrsb">;
1799
1800// load zero-extended byte
1801def LDRBBpost : LoadPostIdx<0b00, 0, 0b01, GPR32, "ldrb">;
1802def LDRHHpost : LoadPostIdx<0b01, 0, 0b01, GPR32, "ldrh">;
1803
1804// load sign-extended word
1805def LDRSWpost : LoadPostIdx<0b10, 0, 0b10, GPR64, "ldrsw">;
1806
1807//===----------------------------------------------------------------------===//
1808// Store instructions.
1809//===----------------------------------------------------------------------===//
1810
1811// Pair (indexed, offset)
1812// FIXME: Use dedicated range-checked addressing mode operand here.
1813defm STPW : StorePairOffset<0b00, 0, GPR32, simm7s4, "stp">;
1814defm STPX : StorePairOffset<0b10, 0, GPR64, simm7s8, "stp">;
1815defm STPS : StorePairOffset<0b00, 1, FPR32, simm7s4, "stp">;
1816defm STPD : StorePairOffset<0b01, 1, FPR64, simm7s8, "stp">;
1817defm STPQ : StorePairOffset<0b10, 1, FPR128, simm7s16, "stp">;
1818
1819// Pair (pre-indexed)
1820def STPWpre : StorePairPreIdx<0b00, 0, GPR32, simm7s4, "stp">;
1821def STPXpre : StorePairPreIdx<0b10, 0, GPR64, simm7s8, "stp">;
1822def STPSpre : StorePairPreIdx<0b00, 1, FPR32, simm7s4, "stp">;
1823def STPDpre : StorePairPreIdx<0b01, 1, FPR64, simm7s8, "stp">;
1824def STPQpre : StorePairPreIdx<0b10, 1, FPR128, simm7s16, "stp">;
1825
1826// Pair (pre-indexed)
1827def STPWpost : StorePairPostIdx<0b00, 0, GPR32, simm7s4, "stp">;
1828def STPXpost : StorePairPostIdx<0b10, 0, GPR64, simm7s8, "stp">;
1829def STPSpost : StorePairPostIdx<0b00, 1, FPR32, simm7s4, "stp">;
1830def STPDpost : StorePairPostIdx<0b01, 1, FPR64, simm7s8, "stp">;
1831def STPQpost : StorePairPostIdx<0b10, 1, FPR128, simm7s16, "stp">;
1832
1833// Pair (no allocate)
1834defm STNPW : StorePairNoAlloc<0b00, 0, GPR32, simm7s4, "stnp">;
1835defm STNPX : StorePairNoAlloc<0b10, 0, GPR64, simm7s8, "stnp">;
1836defm STNPS : StorePairNoAlloc<0b00, 1, FPR32, simm7s4, "stnp">;
1837defm STNPD : StorePairNoAlloc<0b01, 1, FPR64, simm7s8, "stnp">;
1838defm STNPQ : StorePairNoAlloc<0b10, 1, FPR128, simm7s16, "stnp">;
1839
1840//---
1841// (Register offset)
1842
1843// Integer
1844defm STRBB : Store8RO< 0b00, 0, 0b00, GPR32, "strb", i32, truncstorei8>;
1845defm STRHH : Store16RO<0b01, 0, 0b00, GPR32, "strh", i32, truncstorei16>;
1846defm STRW  : Store32RO<0b10, 0, 0b00, GPR32, "str",  i32, store>;
1847defm STRX  : Store64RO<0b11, 0, 0b00, GPR64, "str",  i64, store>;
1848
1849
1850// Floating-point
1851defm STRB : Store8RO< 0b00,  1, 0b00, FPR8,   "str", untyped, store>;
1852defm STRH : Store16RO<0b01,  1, 0b00, FPR16,  "str", f16,     store>;
1853defm STRS : Store32RO<0b10,  1, 0b00, FPR32,  "str", f32,     store>;
1854defm STRD : Store64RO<0b11,  1, 0b00, FPR64,  "str", f64,     store>;
1855defm STRQ : Store128RO<0b00, 1, 0b10, FPR128, "str", f128,    store>;
1856
1857multiclass TruncStoreFrom64ROPat<ROAddrMode ro, SDPatternOperator storeop,
1858                                 Instruction STRW, Instruction STRX> {
1859
1860  def : Pat<(storeop GPR64:$Rt,
1861                     (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)),
1862            (STRW (EXTRACT_SUBREG GPR64:$Rt, sub_32),
1863                  GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)>;
1864
1865  def : Pat<(storeop GPR64:$Rt,
1866                     (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)),
1867            (STRX (EXTRACT_SUBREG GPR64:$Rt, sub_32),
1868                  GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)>;
1869}
1870
1871let AddedComplexity = 10 in {
1872  // truncstore i64
1873  defm : TruncStoreFrom64ROPat<ro8,  truncstorei8,  STRBBroW, STRBBroX>;
1874  defm : TruncStoreFrom64ROPat<ro16, truncstorei16, STRHHroW, STRHHroX>;
1875  defm : TruncStoreFrom64ROPat<ro32, truncstorei32, STRWroW,  STRWroX>;
1876}
1877
1878multiclass VecROStorePat<ROAddrMode ro, ValueType VecTy, RegisterClass FPR,
1879                         Instruction STRW, Instruction STRX> {
1880  def : Pat<(store (VecTy FPR:$Rt),
1881                   (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)),
1882            (STRW FPR:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)>;
1883
1884  def : Pat<(store (VecTy FPR:$Rt),
1885                   (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)),
1886            (STRX FPR:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)>;
1887}
1888
1889let AddedComplexity = 10 in {
1890// Match all store 64 bits width whose type is compatible with FPR64
1891let Predicates = [IsLE] in {
1892  // We must use ST1 to store vectors in big-endian.
1893  defm : VecROStorePat<ro64, v2i32, FPR64, STRDroW, STRDroX>;
1894  defm : VecROStorePat<ro64, v2f32, FPR64, STRDroW, STRDroX>;
1895  defm : VecROStorePat<ro64, v4i16, FPR64, STRDroW, STRDroX>;
1896  defm : VecROStorePat<ro64, v8i8, FPR64, STRDroW, STRDroX>;
1897  defm : VecROStorePat<ro64, v4f16, FPR64, STRDroW, STRDroX>;
1898}
1899
1900defm : VecROStorePat<ro64, v1i64, FPR64, STRDroW, STRDroX>;
1901defm : VecROStorePat<ro64, v1f64, FPR64, STRDroW, STRDroX>;
1902
1903// Match all store 128 bits width whose type is compatible with FPR128
1904let Predicates = [IsLE] in {
1905  // We must use ST1 to store vectors in big-endian.
1906  defm : VecROStorePat<ro128, v2i64, FPR128, STRQroW, STRQroX>;
1907  defm : VecROStorePat<ro128, v2f64, FPR128, STRQroW, STRQroX>;
1908  defm : VecROStorePat<ro128, v4i32, FPR128, STRQroW, STRQroX>;
1909  defm : VecROStorePat<ro128, v4f32, FPR128, STRQroW, STRQroX>;
1910  defm : VecROStorePat<ro128, v8i16, FPR128, STRQroW, STRQroX>;
1911  defm : VecROStorePat<ro128, v16i8, FPR128, STRQroW, STRQroX>;
1912  defm : VecROStorePat<ro128, v8f16, FPR128, STRQroW, STRQroX>;
1913}
1914} // AddedComplexity = 10
1915
1916// Match stores from lane 0 to the appropriate subreg's store.
1917multiclass VecROStoreLane0Pat<ROAddrMode ro, SDPatternOperator storeop,
1918                              ValueType VecTy, ValueType STy,
1919                              SubRegIndex SubRegIdx,
1920                              Instruction STRW, Instruction STRX> {
1921
1922  def : Pat<(storeop (STy (vector_extract (VecTy VecListOne128:$Vt), 0)),
1923                     (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)),
1924            (STRW (EXTRACT_SUBREG VecListOne128:$Vt, SubRegIdx),
1925                  GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)>;
1926
1927  def : Pat<(storeop (STy (vector_extract (VecTy VecListOne128:$Vt), 0)),
1928                     (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)),
1929            (STRX (EXTRACT_SUBREG VecListOne128:$Vt, SubRegIdx),
1930                  GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)>;
1931}
1932
1933let AddedComplexity = 19 in {
1934  defm : VecROStoreLane0Pat<ro16, truncstorei16, v8i16, i32, hsub, STRHroW, STRHroX>;
1935  defm : VecROStoreLane0Pat<ro16,      store   , v8i16, i16, hsub, STRHroW, STRHroX>;
1936  defm : VecROStoreLane0Pat<ro32, truncstorei32, v4i32, i32, ssub, STRSroW, STRSroX>;
1937  defm : VecROStoreLane0Pat<ro32,      store   , v4i32, i32, ssub, STRSroW, STRSroX>;
1938  defm : VecROStoreLane0Pat<ro32,      store   , v4f32, f32, ssub, STRSroW, STRSroX>;
1939  defm : VecROStoreLane0Pat<ro64,      store   , v2i64, i64, dsub, STRDroW, STRDroX>;
1940  defm : VecROStoreLane0Pat<ro64,      store   , v2f64, f64, dsub, STRDroW, STRDroX>;
1941}
1942
1943//---
1944// (unsigned immediate)
1945defm STRX : StoreUI<0b11, 0, 0b00, GPR64, uimm12s8, "str",
1946                   [(store GPR64:$Rt,
1947                            (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))]>;
1948defm STRW : StoreUI<0b10, 0, 0b00, GPR32, uimm12s4, "str",
1949                    [(store GPR32:$Rt,
1950                            (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))]>;
1951defm STRB : StoreUI<0b00, 1, 0b00, FPR8, uimm12s1, "str",
1952                    [(store FPR8:$Rt,
1953                            (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))]>;
1954defm STRH : StoreUI<0b01, 1, 0b00, FPR16, uimm12s2, "str",
1955                    [(store (f16 FPR16:$Rt),
1956                            (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))]>;
1957defm STRS : StoreUI<0b10, 1, 0b00, FPR32, uimm12s4, "str",
1958                    [(store (f32 FPR32:$Rt),
1959                            (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))]>;
1960defm STRD : StoreUI<0b11, 1, 0b00, FPR64, uimm12s8, "str",
1961                    [(store (f64 FPR64:$Rt),
1962                            (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))]>;
1963defm STRQ : StoreUI<0b00, 1, 0b10, FPR128, uimm12s16, "str", []>;
1964
1965defm STRHH : StoreUI<0b01, 0, 0b00, GPR32, uimm12s2, "strh",
1966                     [(truncstorei16 GPR32:$Rt,
1967                                     (am_indexed16 GPR64sp:$Rn,
1968                                                   uimm12s2:$offset))]>;
1969defm STRBB : StoreUI<0b00, 0, 0b00, GPR32, uimm12s1,  "strb",
1970                     [(truncstorei8 GPR32:$Rt,
1971                                    (am_indexed8 GPR64sp:$Rn,
1972                                                 uimm12s1:$offset))]>;
1973
1974// Match all store 64 bits width whose type is compatible with FPR64
1975let AddedComplexity = 10 in {
1976let Predicates = [IsLE] in {
1977  // We must use ST1 to store vectors in big-endian.
1978  def : Pat<(store (v2f32 FPR64:$Rt),
1979                   (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)),
1980            (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>;
1981  def : Pat<(store (v8i8 FPR64:$Rt),
1982                   (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)),
1983            (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>;
1984  def : Pat<(store (v4i16 FPR64:$Rt),
1985                   (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)),
1986            (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>;
1987  def : Pat<(store (v2i32 FPR64:$Rt),
1988                   (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)),
1989            (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>;
1990  def : Pat<(store (v4f16 FPR64:$Rt),
1991                   (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)),
1992            (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>;
1993}
1994def : Pat<(store (v1f64 FPR64:$Rt),
1995                 (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)),
1996          (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>;
1997def : Pat<(store (v1i64 FPR64:$Rt),
1998                 (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)),
1999          (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>;
2000
2001// Match all store 128 bits width whose type is compatible with FPR128
2002let Predicates = [IsLE] in {
2003  // We must use ST1 to store vectors in big-endian.
2004  def : Pat<(store (v4f32 FPR128:$Rt),
2005                   (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)),
2006            (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>;
2007  def : Pat<(store (v2f64 FPR128:$Rt),
2008                   (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)),
2009            (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>;
2010  def : Pat<(store (v16i8 FPR128:$Rt),
2011                   (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)),
2012            (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>;
2013  def : Pat<(store (v8i16 FPR128:$Rt),
2014                   (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)),
2015            (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>;
2016  def : Pat<(store (v4i32 FPR128:$Rt),
2017                   (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)),
2018            (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>;
2019  def : Pat<(store (v2i64 FPR128:$Rt),
2020                   (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)),
2021            (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>;
2022  def : Pat<(store (v8f16 FPR128:$Rt),
2023                   (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)),
2024            (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>;
2025}
2026def : Pat<(store (f128  FPR128:$Rt),
2027                 (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)),
2028          (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>;
2029
2030// truncstore i64
2031def : Pat<(truncstorei32 GPR64:$Rt,
2032                         (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset)),
2033  (STRWui (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$Rn, uimm12s4:$offset)>;
2034def : Pat<(truncstorei16 GPR64:$Rt,
2035                         (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset)),
2036  (STRHHui (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$Rn, uimm12s2:$offset)>;
2037def : Pat<(truncstorei8 GPR64:$Rt, (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset)),
2038  (STRBBui (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$Rn, uimm12s1:$offset)>;
2039
2040} // AddedComplexity = 10
2041
2042//---
2043// (unscaled immediate)
2044defm STURX : StoreUnscaled<0b11, 0, 0b00, GPR64, "stur",
2045                         [(store GPR64:$Rt,
2046                                 (am_unscaled64 GPR64sp:$Rn, simm9:$offset))]>;
2047defm STURW : StoreUnscaled<0b10, 0, 0b00, GPR32, "stur",
2048                         [(store GPR32:$Rt,
2049                                 (am_unscaled32 GPR64sp:$Rn, simm9:$offset))]>;
2050defm STURB : StoreUnscaled<0b00, 1, 0b00, FPR8, "stur",
2051                         [(store FPR8:$Rt,
2052                                 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))]>;
2053defm STURH : StoreUnscaled<0b01, 1, 0b00, FPR16, "stur",
2054                         [(store (f16 FPR16:$Rt),
2055                                 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))]>;
2056defm STURS : StoreUnscaled<0b10, 1, 0b00, FPR32, "stur",
2057                         [(store (f32 FPR32:$Rt),
2058                                 (am_unscaled32 GPR64sp:$Rn, simm9:$offset))]>;
2059defm STURD : StoreUnscaled<0b11, 1, 0b00, FPR64, "stur",
2060                         [(store (f64 FPR64:$Rt),
2061                                 (am_unscaled64 GPR64sp:$Rn, simm9:$offset))]>;
2062defm STURQ : StoreUnscaled<0b00, 1, 0b10, FPR128, "stur",
2063                         [(store (f128 FPR128:$Rt),
2064                                 (am_unscaled128 GPR64sp:$Rn, simm9:$offset))]>;
2065defm STURHH : StoreUnscaled<0b01, 0, 0b00, GPR32, "sturh",
2066                         [(truncstorei16 GPR32:$Rt,
2067                                 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))]>;
2068defm STURBB : StoreUnscaled<0b00, 0, 0b00, GPR32, "sturb",
2069                         [(truncstorei8 GPR32:$Rt,
2070                                  (am_unscaled8 GPR64sp:$Rn, simm9:$offset))]>;
2071
2072// Match all store 64 bits width whose type is compatible with FPR64
2073let Predicates = [IsLE] in {
2074  // We must use ST1 to store vectors in big-endian.
2075  def : Pat<(store (v2f32 FPR64:$Rt),
2076                   (am_unscaled64 GPR64sp:$Rn, simm9:$offset)),
2077            (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>;
2078  def : Pat<(store (v8i8 FPR64:$Rt),
2079                   (am_unscaled64 GPR64sp:$Rn, simm9:$offset)),
2080            (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>;
2081  def : Pat<(store (v4i16 FPR64:$Rt),
2082                   (am_unscaled64 GPR64sp:$Rn, simm9:$offset)),
2083            (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>;
2084  def : Pat<(store (v2i32 FPR64:$Rt),
2085                   (am_unscaled64 GPR64sp:$Rn, simm9:$offset)),
2086            (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>;
2087  def : Pat<(store (v4f16 FPR64:$Rt),
2088                   (am_unscaled64 GPR64sp:$Rn, simm9:$offset)),
2089            (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>;
2090}
2091def : Pat<(store (v1f64 FPR64:$Rt), (am_unscaled64 GPR64sp:$Rn, simm9:$offset)),
2092          (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>;
2093def : Pat<(store (v1i64 FPR64:$Rt), (am_unscaled64 GPR64sp:$Rn, simm9:$offset)),
2094          (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>;
2095
2096// Match all store 128 bits width whose type is compatible with FPR128
2097let Predicates = [IsLE] in {
2098  // We must use ST1 to store vectors in big-endian.
2099  def : Pat<(store (v4f32 FPR128:$Rt),
2100                   (am_unscaled128 GPR64sp:$Rn, simm9:$offset)),
2101            (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>;
2102  def : Pat<(store (v2f64 FPR128:$Rt),
2103                   (am_unscaled128 GPR64sp:$Rn, simm9:$offset)),
2104            (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>;
2105  def : Pat<(store (v16i8 FPR128:$Rt),
2106                   (am_unscaled128 GPR64sp:$Rn, simm9:$offset)),
2107            (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>;
2108  def : Pat<(store (v8i16 FPR128:$Rt),
2109                   (am_unscaled128 GPR64sp:$Rn, simm9:$offset)),
2110            (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>;
2111  def : Pat<(store (v4i32 FPR128:$Rt),
2112                   (am_unscaled128 GPR64sp:$Rn, simm9:$offset)),
2113            (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>;
2114  def : Pat<(store (v2i64 FPR128:$Rt),
2115                   (am_unscaled128 GPR64sp:$Rn, simm9:$offset)),
2116            (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>;
2117  def : Pat<(store (v2f64 FPR128:$Rt),
2118                   (am_unscaled128 GPR64sp:$Rn, simm9:$offset)),
2119            (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>;
2120  def : Pat<(store (v8f16 FPR128:$Rt),
2121                   (am_unscaled128 GPR64sp:$Rn, simm9:$offset)),
2122            (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>;
2123}
2124
2125// unscaled i64 truncating stores
2126def : Pat<(truncstorei32 GPR64:$Rt, (am_unscaled32 GPR64sp:$Rn, simm9:$offset)),
2127  (STURWi (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$Rn, simm9:$offset)>;
2128def : Pat<(truncstorei16 GPR64:$Rt, (am_unscaled16 GPR64sp:$Rn, simm9:$offset)),
2129  (STURHHi (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$Rn, simm9:$offset)>;
2130def : Pat<(truncstorei8 GPR64:$Rt, (am_unscaled8 GPR64sp:$Rn, simm9:$offset)),
2131  (STURBBi (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$Rn, simm9:$offset)>;
2132
2133//---
2134// STR mnemonics fall back to STUR for negative or unaligned offsets.
2135def : InstAlias<"str $Rt, [$Rn, $offset]",
2136                (STURXi GPR64:$Rt, GPR64sp:$Rn, simm9_offset_fb64:$offset), 0>;
2137def : InstAlias<"str $Rt, [$Rn, $offset]",
2138                (STURWi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb32:$offset), 0>;
2139def : InstAlias<"str $Rt, [$Rn, $offset]",
2140                (STURBi FPR8:$Rt, GPR64sp:$Rn, simm9_offset_fb8:$offset), 0>;
2141def : InstAlias<"str $Rt, [$Rn, $offset]",
2142                (STURHi FPR16:$Rt, GPR64sp:$Rn, simm9_offset_fb16:$offset), 0>;
2143def : InstAlias<"str $Rt, [$Rn, $offset]",
2144                (STURSi FPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb32:$offset), 0>;
2145def : InstAlias<"str $Rt, [$Rn, $offset]",
2146                (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9_offset_fb64:$offset), 0>;
2147def : InstAlias<"str $Rt, [$Rn, $offset]",
2148                (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9_offset_fb128:$offset), 0>;
2149
2150def : InstAlias<"strb $Rt, [$Rn, $offset]",
2151                (STURBBi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb8:$offset), 0>;
2152def : InstAlias<"strh $Rt, [$Rn, $offset]",
2153                (STURHHi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb16:$offset), 0>;
2154
2155//---
2156// (unscaled immediate, unprivileged)
2157defm STTRW : StoreUnprivileged<0b10, 0, 0b00, GPR32, "sttr">;
2158defm STTRX : StoreUnprivileged<0b11, 0, 0b00, GPR64, "sttr">;
2159
2160defm STTRH : StoreUnprivileged<0b01, 0, 0b00, GPR32, "sttrh">;
2161defm STTRB : StoreUnprivileged<0b00, 0, 0b00, GPR32, "sttrb">;
2162
2163//---
2164// (immediate pre-indexed)
2165def STRWpre : StorePreIdx<0b10, 0, 0b00, GPR32, "str",  pre_store, i32>;
2166def STRXpre : StorePreIdx<0b11, 0, 0b00, GPR64, "str",  pre_store, i64>;
2167def STRBpre : StorePreIdx<0b00, 1, 0b00, FPR8,  "str",  pre_store, untyped>;
2168def STRHpre : StorePreIdx<0b01, 1, 0b00, FPR16, "str",  pre_store, f16>;
2169def STRSpre : StorePreIdx<0b10, 1, 0b00, FPR32, "str",  pre_store, f32>;
2170def STRDpre : StorePreIdx<0b11, 1, 0b00, FPR64, "str",  pre_store, f64>;
2171def STRQpre : StorePreIdx<0b00, 1, 0b10, FPR128, "str", pre_store, f128>;
2172
2173def STRBBpre : StorePreIdx<0b00, 0, 0b00, GPR32, "strb", pre_truncsti8,  i32>;
2174def STRHHpre : StorePreIdx<0b01, 0, 0b00, GPR32, "strh", pre_truncsti16, i32>;
2175
2176// truncstore i64
2177def : Pat<(pre_truncsti32 GPR64:$Rt, GPR64sp:$addr, simm9:$off),
2178  (STRWpre (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr,
2179           simm9:$off)>;
2180def : Pat<(pre_truncsti16 GPR64:$Rt, GPR64sp:$addr, simm9:$off),
2181  (STRHHpre (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr,
2182            simm9:$off)>;
2183def : Pat<(pre_truncsti8 GPR64:$Rt, GPR64sp:$addr, simm9:$off),
2184  (STRBBpre (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr,
2185            simm9:$off)>;
2186
2187def : Pat<(pre_store (v8i8 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
2188          (STRDpre FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
2189def : Pat<(pre_store (v4i16 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
2190          (STRDpre FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
2191def : Pat<(pre_store (v2i32 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
2192          (STRDpre FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
2193def : Pat<(pre_store (v2f32 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
2194          (STRDpre FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
2195def : Pat<(pre_store (v1i64 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
2196          (STRDpre FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
2197def : Pat<(pre_store (v1f64 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
2198          (STRDpre FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
2199def : Pat<(pre_store (v4f16 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
2200          (STRDpre FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
2201
2202def : Pat<(pre_store (v16i8 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
2203          (STRQpre FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
2204def : Pat<(pre_store (v8i16 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
2205          (STRQpre FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
2206def : Pat<(pre_store (v4i32 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
2207          (STRQpre FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
2208def : Pat<(pre_store (v4f32 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
2209          (STRQpre FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
2210def : Pat<(pre_store (v2i64 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
2211          (STRQpre FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
2212def : Pat<(pre_store (v2f64 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
2213          (STRQpre FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
2214def : Pat<(pre_store (v8f16 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
2215          (STRQpre FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
2216
2217//---
2218// (immediate post-indexed)
2219def STRWpost : StorePostIdx<0b10, 0, 0b00, GPR32,  "str", post_store, i32>;
2220def STRXpost : StorePostIdx<0b11, 0, 0b00, GPR64,  "str", post_store, i64>;
2221def STRBpost : StorePostIdx<0b00, 1, 0b00, FPR8,   "str", post_store, untyped>;
2222def STRHpost : StorePostIdx<0b01, 1, 0b00, FPR16,  "str", post_store, f16>;
2223def STRSpost : StorePostIdx<0b10, 1, 0b00, FPR32,  "str", post_store, f32>;
2224def STRDpost : StorePostIdx<0b11, 1, 0b00, FPR64,  "str", post_store, f64>;
2225def STRQpost : StorePostIdx<0b00, 1, 0b10, FPR128, "str", post_store, f128>;
2226
2227def STRBBpost : StorePostIdx<0b00, 0, 0b00, GPR32, "strb", post_truncsti8, i32>;
2228def STRHHpost : StorePostIdx<0b01, 0, 0b00, GPR32, "strh", post_truncsti16, i32>;
2229
2230// truncstore i64
2231def : Pat<(post_truncsti32 GPR64:$Rt, GPR64sp:$addr, simm9:$off),
2232  (STRWpost (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr,
2233            simm9:$off)>;
2234def : Pat<(post_truncsti16 GPR64:$Rt, GPR64sp:$addr, simm9:$off),
2235  (STRHHpost (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr,
2236             simm9:$off)>;
2237def : Pat<(post_truncsti8 GPR64:$Rt, GPR64sp:$addr, simm9:$off),
2238  (STRBBpost (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr,
2239             simm9:$off)>;
2240
2241def : Pat<(post_store (v8i8 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
2242          (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
2243def : Pat<(post_store (v4i16 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
2244          (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
2245def : Pat<(post_store (v2i32 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
2246          (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
2247def : Pat<(post_store (v2f32 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
2248          (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
2249def : Pat<(post_store (v1i64 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
2250          (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
2251def : Pat<(post_store (v1f64 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
2252          (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
2253def : Pat<(post_store (v4f16 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
2254          (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
2255
2256def : Pat<(post_store (v16i8 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
2257          (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
2258def : Pat<(post_store (v8i16 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
2259          (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
2260def : Pat<(post_store (v4i32 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
2261          (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
2262def : Pat<(post_store (v4f32 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
2263          (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
2264def : Pat<(post_store (v2i64 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
2265          (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
2266def : Pat<(post_store (v2f64 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
2267          (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
2268def : Pat<(post_store (v8f16 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
2269          (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
2270
2271//===----------------------------------------------------------------------===//
2272// Load/store exclusive instructions.
2273//===----------------------------------------------------------------------===//
2274
2275def LDARW  : LoadAcquire   <0b10, 1, 1, 0, 1, GPR32, "ldar">;
2276def LDARX  : LoadAcquire   <0b11, 1, 1, 0, 1, GPR64, "ldar">;
2277def LDARB  : LoadAcquire   <0b00, 1, 1, 0, 1, GPR32, "ldarb">;
2278def LDARH  : LoadAcquire   <0b01, 1, 1, 0, 1, GPR32, "ldarh">;
2279
2280def LDAXRW : LoadExclusive <0b10, 0, 1, 0, 1, GPR32, "ldaxr">;
2281def LDAXRX : LoadExclusive <0b11, 0, 1, 0, 1, GPR64, "ldaxr">;
2282def LDAXRB : LoadExclusive <0b00, 0, 1, 0, 1, GPR32, "ldaxrb">;
2283def LDAXRH : LoadExclusive <0b01, 0, 1, 0, 1, GPR32, "ldaxrh">;
2284
2285def LDXRW  : LoadExclusive <0b10, 0, 1, 0, 0, GPR32, "ldxr">;
2286def LDXRX  : LoadExclusive <0b11, 0, 1, 0, 0, GPR64, "ldxr">;
2287def LDXRB  : LoadExclusive <0b00, 0, 1, 0, 0, GPR32, "ldxrb">;
2288def LDXRH  : LoadExclusive <0b01, 0, 1, 0, 0, GPR32, "ldxrh">;
2289
2290def STLRW  : StoreRelease  <0b10, 1, 0, 0, 1, GPR32, "stlr">;
2291def STLRX  : StoreRelease  <0b11, 1, 0, 0, 1, GPR64, "stlr">;
2292def STLRB  : StoreRelease  <0b00, 1, 0, 0, 1, GPR32, "stlrb">;
2293def STLRH  : StoreRelease  <0b01, 1, 0, 0, 1, GPR32, "stlrh">;
2294
2295def STLXRW : StoreExclusive<0b10, 0, 0, 0, 1, GPR32, "stlxr">;
2296def STLXRX : StoreExclusive<0b11, 0, 0, 0, 1, GPR64, "stlxr">;
2297def STLXRB : StoreExclusive<0b00, 0, 0, 0, 1, GPR32, "stlxrb">;
2298def STLXRH : StoreExclusive<0b01, 0, 0, 0, 1, GPR32, "stlxrh">;
2299
2300def STXRW  : StoreExclusive<0b10, 0, 0, 0, 0, GPR32, "stxr">;
2301def STXRX  : StoreExclusive<0b11, 0, 0, 0, 0, GPR64, "stxr">;
2302def STXRB  : StoreExclusive<0b00, 0, 0, 0, 0, GPR32, "stxrb">;
2303def STXRH  : StoreExclusive<0b01, 0, 0, 0, 0, GPR32, "stxrh">;
2304
2305def LDAXPW : LoadExclusivePair<0b10, 0, 1, 1, 1, GPR32, "ldaxp">;
2306def LDAXPX : LoadExclusivePair<0b11, 0, 1, 1, 1, GPR64, "ldaxp">;
2307
2308def LDXPW  : LoadExclusivePair<0b10, 0, 1, 1, 0, GPR32, "ldxp">;
2309def LDXPX  : LoadExclusivePair<0b11, 0, 1, 1, 0, GPR64, "ldxp">;
2310
2311def STLXPW : StoreExclusivePair<0b10, 0, 0, 1, 1, GPR32, "stlxp">;
2312def STLXPX : StoreExclusivePair<0b11, 0, 0, 1, 1, GPR64, "stlxp">;
2313
2314def STXPW  : StoreExclusivePair<0b10, 0, 0, 1, 0, GPR32, "stxp">;
2315def STXPX  : StoreExclusivePair<0b11, 0, 0, 1, 0, GPR64, "stxp">;
2316
2317let Predicates = [HasV8_1a] in {
2318  // v8.1a "Limited Order Region" extension load-acquire instructions
2319  def LDLARW  : LoadAcquire   <0b10, 1, 1, 0, 0, GPR32, "ldlar">;
2320  def LDLARX  : LoadAcquire   <0b11, 1, 1, 0, 0, GPR64, "ldlar">;
2321  def LDLARB  : LoadAcquire   <0b00, 1, 1, 0, 0, GPR32, "ldlarb">;
2322  def LDLARH  : LoadAcquire   <0b01, 1, 1, 0, 0, GPR32, "ldlarh">;
2323
2324  // v8.1a "Limited Order Region" extension store-release instructions
2325  def STLLRW  : StoreRelease   <0b10, 1, 0, 0, 0, GPR32, "stllr">;
2326  def STLLRX  : StoreRelease   <0b11, 1, 0, 0, 0, GPR64, "stllr">;
2327  def STLLRB  : StoreRelease   <0b00, 1, 0, 0, 0, GPR32, "stllrb">;
2328  def STLLRH  : StoreRelease   <0b01, 1, 0, 0, 0, GPR32, "stllrh">;
2329}
2330
2331//===----------------------------------------------------------------------===//
2332// Scaled floating point to integer conversion instructions.
2333//===----------------------------------------------------------------------===//
2334
2335defm FCVTAS : FPToIntegerUnscaled<0b00, 0b100, "fcvtas", int_aarch64_neon_fcvtas>;
2336defm FCVTAU : FPToIntegerUnscaled<0b00, 0b101, "fcvtau", int_aarch64_neon_fcvtau>;
2337defm FCVTMS : FPToIntegerUnscaled<0b10, 0b000, "fcvtms", int_aarch64_neon_fcvtms>;
2338defm FCVTMU : FPToIntegerUnscaled<0b10, 0b001, "fcvtmu", int_aarch64_neon_fcvtmu>;
2339defm FCVTNS : FPToIntegerUnscaled<0b00, 0b000, "fcvtns", int_aarch64_neon_fcvtns>;
2340defm FCVTNU : FPToIntegerUnscaled<0b00, 0b001, "fcvtnu", int_aarch64_neon_fcvtnu>;
2341defm FCVTPS : FPToIntegerUnscaled<0b01, 0b000, "fcvtps", int_aarch64_neon_fcvtps>;
2342defm FCVTPU : FPToIntegerUnscaled<0b01, 0b001, "fcvtpu", int_aarch64_neon_fcvtpu>;
2343defm FCVTZS : FPToIntegerUnscaled<0b11, 0b000, "fcvtzs", fp_to_sint>;
2344defm FCVTZU : FPToIntegerUnscaled<0b11, 0b001, "fcvtzu", fp_to_uint>;
2345defm FCVTZS : FPToIntegerScaled<0b11, 0b000, "fcvtzs", fp_to_sint>;
2346defm FCVTZU : FPToIntegerScaled<0b11, 0b001, "fcvtzu", fp_to_uint>;
2347let isCodeGenOnly = 1 in {
2348defm FCVTZS_Int : FPToIntegerUnscaled<0b11, 0b000, "fcvtzs", int_aarch64_neon_fcvtzs>;
2349defm FCVTZU_Int : FPToIntegerUnscaled<0b11, 0b001, "fcvtzu", int_aarch64_neon_fcvtzu>;
2350defm FCVTZS_Int : FPToIntegerScaled<0b11, 0b000, "fcvtzs", int_aarch64_neon_fcvtzs>;
2351defm FCVTZU_Int : FPToIntegerScaled<0b11, 0b001, "fcvtzu", int_aarch64_neon_fcvtzu>;
2352}
2353
2354//===----------------------------------------------------------------------===//
2355// Scaled integer to floating point conversion instructions.
2356//===----------------------------------------------------------------------===//
2357
2358defm SCVTF : IntegerToFP<0, "scvtf", sint_to_fp>;
2359defm UCVTF : IntegerToFP<1, "ucvtf", uint_to_fp>;
2360
2361//===----------------------------------------------------------------------===//
2362// Unscaled integer to floating point conversion instruction.
2363//===----------------------------------------------------------------------===//
2364
2365defm FMOV : UnscaledConversion<"fmov">;
2366
2367// Add pseudo ops for FMOV 0 so we can mark them as isReMaterializable
2368let isReMaterializable = 1, isCodeGenOnly = 1 in {
2369def FMOVS0 : Pseudo<(outs FPR32:$Rd), (ins), [(set f32:$Rd, (fpimm0))]>,
2370    PseudoInstExpansion<(FMOVWSr FPR32:$Rd, WZR)>,
2371    Requires<[NoZCZ]>;
2372def FMOVD0 : Pseudo<(outs FPR64:$Rd), (ins), [(set f64:$Rd, (fpimm0))]>,
2373    PseudoInstExpansion<(FMOVXDr FPR64:$Rd, XZR)>,
2374    Requires<[NoZCZ]>;
2375}
2376
2377//===----------------------------------------------------------------------===//
2378// Floating point conversion instruction.
2379//===----------------------------------------------------------------------===//
2380
2381defm FCVT : FPConversion<"fcvt">;
2382
2383//===----------------------------------------------------------------------===//
2384// Floating point single operand instructions.
2385//===----------------------------------------------------------------------===//
2386
2387defm FABS   : SingleOperandFPData<0b0001, "fabs", fabs>;
2388defm FMOV   : SingleOperandFPData<0b0000, "fmov">;
2389defm FNEG   : SingleOperandFPData<0b0010, "fneg", fneg>;
2390defm FRINTA : SingleOperandFPData<0b1100, "frinta", frnd>;
2391defm FRINTI : SingleOperandFPData<0b1111, "frinti", fnearbyint>;
2392defm FRINTM : SingleOperandFPData<0b1010, "frintm", ffloor>;
2393defm FRINTN : SingleOperandFPData<0b1000, "frintn", int_aarch64_neon_frintn>;
2394defm FRINTP : SingleOperandFPData<0b1001, "frintp", fceil>;
2395
2396def : Pat<(v1f64 (int_aarch64_neon_frintn (v1f64 FPR64:$Rn))),
2397          (FRINTNDr FPR64:$Rn)>;
2398
2399// FRINTX is inserted to set the flags as required by FENV_ACCESS ON behavior
2400// in the C spec. Setting hasSideEffects ensures it is not DCE'd.
2401// <rdar://problem/13715968>
2402// TODO: We should really model the FPSR flags correctly. This is really ugly.
2403let hasSideEffects = 1 in {
2404defm FRINTX : SingleOperandFPData<0b1110, "frintx", frint>;
2405}
2406
2407defm FRINTZ : SingleOperandFPData<0b1011, "frintz", ftrunc>;
2408
2409let SchedRW = [WriteFDiv] in {
2410defm FSQRT  : SingleOperandFPData<0b0011, "fsqrt", fsqrt>;
2411}
2412
2413//===----------------------------------------------------------------------===//
2414// Floating point two operand instructions.
2415//===----------------------------------------------------------------------===//
2416
2417defm FADD   : TwoOperandFPData<0b0010, "fadd", fadd>;
2418let SchedRW = [WriteFDiv] in {
2419defm FDIV   : TwoOperandFPData<0b0001, "fdiv", fdiv>;
2420}
2421defm FMAXNM : TwoOperandFPData<0b0110, "fmaxnm", int_aarch64_neon_fmaxnm>;
2422defm FMAX   : TwoOperandFPData<0b0100, "fmax", AArch64fmax>;
2423defm FMINNM : TwoOperandFPData<0b0111, "fminnm", int_aarch64_neon_fminnm>;
2424defm FMIN   : TwoOperandFPData<0b0101, "fmin", AArch64fmin>;
2425let SchedRW = [WriteFMul] in {
2426defm FMUL   : TwoOperandFPData<0b0000, "fmul", fmul>;
2427defm FNMUL  : TwoOperandFPDataNeg<0b1000, "fnmul", fmul>;
2428}
2429defm FSUB   : TwoOperandFPData<0b0011, "fsub", fsub>;
2430
2431def : Pat<(v1f64 (AArch64fmax (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
2432          (FMAXDrr FPR64:$Rn, FPR64:$Rm)>;
2433def : Pat<(v1f64 (AArch64fmin (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
2434          (FMINDrr FPR64:$Rn, FPR64:$Rm)>;
2435def : Pat<(v1f64 (int_aarch64_neon_fmaxnm (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
2436          (FMAXNMDrr FPR64:$Rn, FPR64:$Rm)>;
2437def : Pat<(v1f64 (int_aarch64_neon_fminnm (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
2438          (FMINNMDrr FPR64:$Rn, FPR64:$Rm)>;
2439
2440//===----------------------------------------------------------------------===//
2441// Floating point three operand instructions.
2442//===----------------------------------------------------------------------===//
2443
2444defm FMADD  : ThreeOperandFPData<0, 0, "fmadd", fma>;
2445defm FMSUB  : ThreeOperandFPData<0, 1, "fmsub",
2446     TriOpFrag<(fma node:$LHS, (fneg node:$MHS), node:$RHS)> >;
2447defm FNMADD : ThreeOperandFPData<1, 0, "fnmadd",
2448     TriOpFrag<(fneg (fma node:$LHS, node:$MHS, node:$RHS))> >;
2449defm FNMSUB : ThreeOperandFPData<1, 1, "fnmsub",
2450     TriOpFrag<(fma node:$LHS, node:$MHS, (fneg node:$RHS))> >;
2451
2452// The following def pats catch the case where the LHS of an FMA is negated.
2453// The TriOpFrag above catches the case where the middle operand is negated.
2454
2455// N.b. FMSUB etc have the accumulator at the *end* of (outs), unlike
2456// the NEON variant.
2457def : Pat<(f32 (fma (fneg FPR32:$Rn), FPR32:$Rm, FPR32:$Ra)),
2458          (FMSUBSrrr FPR32:$Rn, FPR32:$Rm, FPR32:$Ra)>;
2459
2460def : Pat<(f64 (fma (fneg FPR64:$Rn), FPR64:$Rm, FPR64:$Ra)),
2461          (FMSUBDrrr FPR64:$Rn, FPR64:$Rm, FPR64:$Ra)>;
2462
2463// We handled -(a + b*c) for FNMADD above, now it's time for "(-a) + (-b)*c" and
2464// "(-a) + b*(-c)".
2465def : Pat<(f32 (fma (fneg FPR32:$Rn), FPR32:$Rm, (fneg FPR32:$Ra))),
2466          (FNMADDSrrr FPR32:$Rn, FPR32:$Rm, FPR32:$Ra)>;
2467
2468def : Pat<(f64 (fma (fneg FPR64:$Rn), FPR64:$Rm, (fneg FPR64:$Ra))),
2469          (FNMADDDrrr FPR64:$Rn, FPR64:$Rm, FPR64:$Ra)>;
2470
2471def : Pat<(f32 (fma FPR32:$Rn, (fneg FPR32:$Rm), (fneg FPR32:$Ra))),
2472          (FNMADDSrrr FPR32:$Rn, FPR32:$Rm, FPR32:$Ra)>;
2473
2474def : Pat<(f64 (fma FPR64:$Rn, (fneg FPR64:$Rm), (fneg FPR64:$Ra))),
2475          (FNMADDDrrr FPR64:$Rn, FPR64:$Rm, FPR64:$Ra)>;
2476
2477//===----------------------------------------------------------------------===//
2478// Floating point comparison instructions.
2479//===----------------------------------------------------------------------===//
2480
2481defm FCMPE : FPComparison<1, "fcmpe">;
2482defm FCMP  : FPComparison<0, "fcmp", AArch64fcmp>;
2483
2484//===----------------------------------------------------------------------===//
2485// Floating point conditional comparison instructions.
2486//===----------------------------------------------------------------------===//
2487
2488defm FCCMPE : FPCondComparison<1, "fccmpe">;
2489defm FCCMP  : FPCondComparison<0, "fccmp">;
2490
2491//===----------------------------------------------------------------------===//
2492// Floating point conditional select instruction.
2493//===----------------------------------------------------------------------===//
2494
2495defm FCSEL : FPCondSelect<"fcsel">;
2496
2497// CSEL instructions providing f128 types need to be handled by a
2498// pseudo-instruction since the eventual code will need to introduce basic
2499// blocks and control flow.
2500def F128CSEL : Pseudo<(outs FPR128:$Rd),
2501                      (ins FPR128:$Rn, FPR128:$Rm, ccode:$cond),
2502                      [(set (f128 FPR128:$Rd),
2503                            (AArch64csel FPR128:$Rn, FPR128:$Rm,
2504                                       (i32 imm:$cond), NZCV))]> {
2505  let Uses = [NZCV];
2506  let usesCustomInserter = 1;
2507}
2508
2509
2510//===----------------------------------------------------------------------===//
2511// Floating point immediate move.
2512//===----------------------------------------------------------------------===//
2513
2514let isReMaterializable = 1 in {
2515defm FMOV : FPMoveImmediate<"fmov">;
2516}
2517
2518//===----------------------------------------------------------------------===//
2519// Advanced SIMD two vector instructions.
2520//===----------------------------------------------------------------------===//
2521
2522defm ABS    : SIMDTwoVectorBHSD<0, 0b01011, "abs", int_aarch64_neon_abs>;
2523def : Pat<(xor (v8i8 (AArch64vashr V64:$src, (i32 7))),
2524               (v8i8 (add V64:$src, (AArch64vashr V64:$src, (i32 7))))),
2525          (ABSv8i8 V64:$src)>;
2526def : Pat<(xor (v4i16 (AArch64vashr V64:$src, (i32 15))),
2527               (v4i16 (add V64:$src, (AArch64vashr V64:$src, (i32 15))))),
2528          (ABSv4i16 V64:$src)>;
2529def : Pat<(xor (v2i32 (AArch64vashr V64:$src, (i32 31))),
2530               (v2i32 (add V64:$src, (AArch64vashr V64:$src, (i32 31))))),
2531          (ABSv2i32 V64:$src)>;
2532def : Pat<(xor (v16i8 (AArch64vashr V128:$src, (i32 7))),
2533               (v16i8 (add V128:$src, (AArch64vashr V128:$src, (i32 7))))),
2534          (ABSv16i8 V128:$src)>;
2535def : Pat<(xor (v8i16 (AArch64vashr V128:$src, (i32 15))),
2536               (v8i16 (add V128:$src, (AArch64vashr V128:$src, (i32 15))))),
2537          (ABSv8i16 V128:$src)>;
2538def : Pat<(xor (v4i32 (AArch64vashr V128:$src, (i32 31))),
2539               (v4i32 (add V128:$src, (AArch64vashr V128:$src, (i32 31))))),
2540          (ABSv4i32 V128:$src)>;
2541def : Pat<(xor (v2i64 (AArch64vashr V128:$src, (i32 63))),
2542               (v2i64 (add V128:$src, (AArch64vashr V128:$src, (i32 63))))),
2543          (ABSv2i64 V128:$src)>;
2544
2545defm CLS    : SIMDTwoVectorBHS<0, 0b00100, "cls", int_aarch64_neon_cls>;
2546defm CLZ    : SIMDTwoVectorBHS<1, 0b00100, "clz", ctlz>;
2547defm CMEQ   : SIMDCmpTwoVector<0, 0b01001, "cmeq", AArch64cmeqz>;
2548defm CMGE   : SIMDCmpTwoVector<1, 0b01000, "cmge", AArch64cmgez>;
2549defm CMGT   : SIMDCmpTwoVector<0, 0b01000, "cmgt", AArch64cmgtz>;
2550defm CMLE   : SIMDCmpTwoVector<1, 0b01001, "cmle", AArch64cmlez>;
2551defm CMLT   : SIMDCmpTwoVector<0, 0b01010, "cmlt", AArch64cmltz>;
2552defm CNT    : SIMDTwoVectorB<0, 0b00, 0b00101, "cnt", ctpop>;
2553defm FABS   : SIMDTwoVectorFP<0, 1, 0b01111, "fabs", fabs>;
2554
2555defm FCMEQ  : SIMDFPCmpTwoVector<0, 1, 0b01101, "fcmeq", AArch64fcmeqz>;
2556defm FCMGE  : SIMDFPCmpTwoVector<1, 1, 0b01100, "fcmge", AArch64fcmgez>;
2557defm FCMGT  : SIMDFPCmpTwoVector<0, 1, 0b01100, "fcmgt", AArch64fcmgtz>;
2558defm FCMLE  : SIMDFPCmpTwoVector<1, 1, 0b01101, "fcmle", AArch64fcmlez>;
2559defm FCMLT  : SIMDFPCmpTwoVector<0, 1, 0b01110, "fcmlt", AArch64fcmltz>;
2560defm FCVTAS : SIMDTwoVectorFPToInt<0,0,0b11100, "fcvtas",int_aarch64_neon_fcvtas>;
2561defm FCVTAU : SIMDTwoVectorFPToInt<1,0,0b11100, "fcvtau",int_aarch64_neon_fcvtau>;
2562defm FCVTL  : SIMDFPWidenTwoVector<0, 0, 0b10111, "fcvtl">;
2563def : Pat<(v4f32 (int_aarch64_neon_vcvthf2fp (v4i16 V64:$Rn))),
2564          (FCVTLv4i16 V64:$Rn)>;
2565def : Pat<(v4f32 (int_aarch64_neon_vcvthf2fp (extract_subvector (v8i16 V128:$Rn),
2566                                                              (i64 4)))),
2567          (FCVTLv8i16 V128:$Rn)>;
2568def : Pat<(v2f64 (fextend (v2f32 V64:$Rn))), (FCVTLv2i32 V64:$Rn)>;
2569def : Pat<(v2f64 (fextend (v2f32 (extract_subvector (v4f32 V128:$Rn),
2570                                                    (i64 2))))),
2571          (FCVTLv4i32 V128:$Rn)>;
2572
2573def : Pat<(v4f32 (fextend (v4f16 V64:$Rn))), (FCVTLv4i16 V64:$Rn)>;
2574def : Pat<(v4f32 (fextend (v4f16 (extract_subvector (v8f16 V128:$Rn),
2575                                                    (i64 4))))),
2576          (FCVTLv8i16 V128:$Rn)>;
2577
2578defm FCVTMS : SIMDTwoVectorFPToInt<0,0,0b11011, "fcvtms",int_aarch64_neon_fcvtms>;
2579defm FCVTMU : SIMDTwoVectorFPToInt<1,0,0b11011, "fcvtmu",int_aarch64_neon_fcvtmu>;
2580defm FCVTNS : SIMDTwoVectorFPToInt<0,0,0b11010, "fcvtns",int_aarch64_neon_fcvtns>;
2581defm FCVTNU : SIMDTwoVectorFPToInt<1,0,0b11010, "fcvtnu",int_aarch64_neon_fcvtnu>;
2582defm FCVTN  : SIMDFPNarrowTwoVector<0, 0, 0b10110, "fcvtn">;
2583def : Pat<(v4i16 (int_aarch64_neon_vcvtfp2hf (v4f32 V128:$Rn))),
2584          (FCVTNv4i16 V128:$Rn)>;
2585def : Pat<(concat_vectors V64:$Rd,
2586                          (v4i16 (int_aarch64_neon_vcvtfp2hf (v4f32 V128:$Rn)))),
2587          (FCVTNv8i16 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
2588def : Pat<(v2f32 (fround (v2f64 V128:$Rn))), (FCVTNv2i32 V128:$Rn)>;
2589def : Pat<(v4f16 (fround (v4f32 V128:$Rn))), (FCVTNv4i16 V128:$Rn)>;
2590def : Pat<(concat_vectors V64:$Rd, (v2f32 (fround (v2f64 V128:$Rn)))),
2591          (FCVTNv4i32 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
2592defm FCVTPS : SIMDTwoVectorFPToInt<0,1,0b11010, "fcvtps",int_aarch64_neon_fcvtps>;
2593defm FCVTPU : SIMDTwoVectorFPToInt<1,1,0b11010, "fcvtpu",int_aarch64_neon_fcvtpu>;
2594defm FCVTXN : SIMDFPInexactCvtTwoVector<1, 0, 0b10110, "fcvtxn",
2595                                        int_aarch64_neon_fcvtxn>;
2596defm FCVTZS : SIMDTwoVectorFPToInt<0, 1, 0b11011, "fcvtzs", fp_to_sint>;
2597defm FCVTZU : SIMDTwoVectorFPToInt<1, 1, 0b11011, "fcvtzu", fp_to_uint>;
2598let isCodeGenOnly = 1 in {
2599defm FCVTZS_Int : SIMDTwoVectorFPToInt<0, 1, 0b11011, "fcvtzs",
2600                                       int_aarch64_neon_fcvtzs>;
2601defm FCVTZU_Int : SIMDTwoVectorFPToInt<1, 1, 0b11011, "fcvtzu",
2602                                       int_aarch64_neon_fcvtzu>;
2603}
2604defm FNEG   : SIMDTwoVectorFP<1, 1, 0b01111, "fneg", fneg>;
2605defm FRECPE : SIMDTwoVectorFP<0, 1, 0b11101, "frecpe", int_aarch64_neon_frecpe>;
2606defm FRINTA : SIMDTwoVectorFP<1, 0, 0b11000, "frinta", frnd>;
2607defm FRINTI : SIMDTwoVectorFP<1, 1, 0b11001, "frinti", fnearbyint>;
2608defm FRINTM : SIMDTwoVectorFP<0, 0, 0b11001, "frintm", ffloor>;
2609defm FRINTN : SIMDTwoVectorFP<0, 0, 0b11000, "frintn", int_aarch64_neon_frintn>;
2610defm FRINTP : SIMDTwoVectorFP<0, 1, 0b11000, "frintp", fceil>;
2611defm FRINTX : SIMDTwoVectorFP<1, 0, 0b11001, "frintx", frint>;
2612defm FRINTZ : SIMDTwoVectorFP<0, 1, 0b11001, "frintz", ftrunc>;
2613defm FRSQRTE: SIMDTwoVectorFP<1, 1, 0b11101, "frsqrte", int_aarch64_neon_frsqrte>;
2614defm FSQRT  : SIMDTwoVectorFP<1, 1, 0b11111, "fsqrt", fsqrt>;
2615defm NEG    : SIMDTwoVectorBHSD<1, 0b01011, "neg",
2616                               UnOpFrag<(sub immAllZerosV, node:$LHS)> >;
2617defm NOT    : SIMDTwoVectorB<1, 0b00, 0b00101, "not", vnot>;
2618// Aliases for MVN -> NOT.
2619def : InstAlias<"mvn{ $Vd.8b, $Vn.8b|.8b $Vd, $Vn}",
2620                (NOTv8i8 V64:$Vd, V64:$Vn)>;
2621def : InstAlias<"mvn{ $Vd.16b, $Vn.16b|.16b $Vd, $Vn}",
2622                (NOTv16i8 V128:$Vd, V128:$Vn)>;
2623
2624def : Pat<(AArch64neg (v8i8  V64:$Rn)),  (NEGv8i8  V64:$Rn)>;
2625def : Pat<(AArch64neg (v16i8 V128:$Rn)), (NEGv16i8 V128:$Rn)>;
2626def : Pat<(AArch64neg (v4i16 V64:$Rn)),  (NEGv4i16 V64:$Rn)>;
2627def : Pat<(AArch64neg (v8i16 V128:$Rn)), (NEGv8i16 V128:$Rn)>;
2628def : Pat<(AArch64neg (v2i32 V64:$Rn)),  (NEGv2i32 V64:$Rn)>;
2629def : Pat<(AArch64neg (v4i32 V128:$Rn)), (NEGv4i32 V128:$Rn)>;
2630def : Pat<(AArch64neg (v2i64 V128:$Rn)), (NEGv2i64 V128:$Rn)>;
2631
2632def : Pat<(AArch64not (v8i8 V64:$Rn)),   (NOTv8i8  V64:$Rn)>;
2633def : Pat<(AArch64not (v16i8 V128:$Rn)), (NOTv16i8 V128:$Rn)>;
2634def : Pat<(AArch64not (v4i16 V64:$Rn)),  (NOTv8i8  V64:$Rn)>;
2635def : Pat<(AArch64not (v8i16 V128:$Rn)), (NOTv16i8 V128:$Rn)>;
2636def : Pat<(AArch64not (v2i32 V64:$Rn)),  (NOTv8i8  V64:$Rn)>;
2637def : Pat<(AArch64not (v1i64 V64:$Rn)),  (NOTv8i8  V64:$Rn)>;
2638def : Pat<(AArch64not (v4i32 V128:$Rn)), (NOTv16i8 V128:$Rn)>;
2639def : Pat<(AArch64not (v2i64 V128:$Rn)), (NOTv16i8 V128:$Rn)>;
2640
2641def : Pat<(vnot (v4i16 V64:$Rn)),  (NOTv8i8  V64:$Rn)>;
2642def : Pat<(vnot (v8i16 V128:$Rn)), (NOTv16i8 V128:$Rn)>;
2643def : Pat<(vnot (v2i32 V64:$Rn)),  (NOTv8i8  V64:$Rn)>;
2644def : Pat<(vnot (v4i32 V128:$Rn)), (NOTv16i8 V128:$Rn)>;
2645def : Pat<(vnot (v2i64 V128:$Rn)), (NOTv16i8 V128:$Rn)>;
2646
2647defm RBIT   : SIMDTwoVectorB<1, 0b01, 0b00101, "rbit", int_aarch64_neon_rbit>;
2648defm REV16  : SIMDTwoVectorB<0, 0b00, 0b00001, "rev16", AArch64rev16>;
2649defm REV32  : SIMDTwoVectorBH<1, 0b00000, "rev32", AArch64rev32>;
2650defm REV64  : SIMDTwoVectorBHS<0, 0b00000, "rev64", AArch64rev64>;
2651defm SADALP : SIMDLongTwoVectorTied<0, 0b00110, "sadalp",
2652       BinOpFrag<(add node:$LHS, (int_aarch64_neon_saddlp node:$RHS))> >;
2653defm SADDLP : SIMDLongTwoVector<0, 0b00010, "saddlp", int_aarch64_neon_saddlp>;
2654defm SCVTF  : SIMDTwoVectorIntToFP<0, 0, 0b11101, "scvtf", sint_to_fp>;
2655defm SHLL   : SIMDVectorLShiftLongBySizeBHS;
2656defm SQABS  : SIMDTwoVectorBHSD<0, 0b00111, "sqabs", int_aarch64_neon_sqabs>;
2657defm SQNEG  : SIMDTwoVectorBHSD<1, 0b00111, "sqneg", int_aarch64_neon_sqneg>;
2658defm SQXTN  : SIMDMixedTwoVector<0, 0b10100, "sqxtn", int_aarch64_neon_sqxtn>;
2659defm SQXTUN : SIMDMixedTwoVector<1, 0b10010, "sqxtun", int_aarch64_neon_sqxtun>;
2660defm SUQADD : SIMDTwoVectorBHSDTied<0, 0b00011, "suqadd",int_aarch64_neon_suqadd>;
2661defm UADALP : SIMDLongTwoVectorTied<1, 0b00110, "uadalp",
2662       BinOpFrag<(add node:$LHS, (int_aarch64_neon_uaddlp node:$RHS))> >;
2663defm UADDLP : SIMDLongTwoVector<1, 0b00010, "uaddlp",
2664                    int_aarch64_neon_uaddlp>;
2665defm UCVTF  : SIMDTwoVectorIntToFP<1, 0, 0b11101, "ucvtf", uint_to_fp>;
2666defm UQXTN  : SIMDMixedTwoVector<1, 0b10100, "uqxtn", int_aarch64_neon_uqxtn>;
2667defm URECPE : SIMDTwoVectorS<0, 1, 0b11100, "urecpe", int_aarch64_neon_urecpe>;
2668defm URSQRTE: SIMDTwoVectorS<1, 1, 0b11100, "ursqrte", int_aarch64_neon_ursqrte>;
2669defm USQADD : SIMDTwoVectorBHSDTied<1, 0b00011, "usqadd",int_aarch64_neon_usqadd>;
2670defm XTN    : SIMDMixedTwoVector<0, 0b10010, "xtn", trunc>;
2671
2672def : Pat<(v4f16 (AArch64rev32 V64:$Rn)), (REV32v4i16 V64:$Rn)>;
2673def : Pat<(v4f16 (AArch64rev64 V64:$Rn)), (REV64v4i16 V64:$Rn)>;
2674def : Pat<(v8f16 (AArch64rev32 V128:$Rn)), (REV32v8i16 V128:$Rn)>;
2675def : Pat<(v8f16 (AArch64rev64 V128:$Rn)), (REV64v8i16 V128:$Rn)>;
2676def : Pat<(v2f32 (AArch64rev64 V64:$Rn)), (REV64v2i32 V64:$Rn)>;
2677def : Pat<(v4f32 (AArch64rev64 V128:$Rn)), (REV64v4i32 V128:$Rn)>;
2678
2679// Patterns for vector long shift (by element width). These need to match all
2680// three of zext, sext and anyext so it's easier to pull the patterns out of the
2681// definition.
2682multiclass SIMDVectorLShiftLongBySizeBHSPats<SDPatternOperator ext> {
2683  def : Pat<(AArch64vshl (v8i16 (ext (v8i8 V64:$Rn))), (i32 8)),
2684            (SHLLv8i8 V64:$Rn)>;
2685  def : Pat<(AArch64vshl (v8i16 (ext (extract_high_v16i8 V128:$Rn))), (i32 8)),
2686            (SHLLv16i8 V128:$Rn)>;
2687  def : Pat<(AArch64vshl (v4i32 (ext (v4i16 V64:$Rn))), (i32 16)),
2688            (SHLLv4i16 V64:$Rn)>;
2689  def : Pat<(AArch64vshl (v4i32 (ext (extract_high_v8i16 V128:$Rn))), (i32 16)),
2690            (SHLLv8i16 V128:$Rn)>;
2691  def : Pat<(AArch64vshl (v2i64 (ext (v2i32 V64:$Rn))), (i32 32)),
2692            (SHLLv2i32 V64:$Rn)>;
2693  def : Pat<(AArch64vshl (v2i64 (ext (extract_high_v4i32 V128:$Rn))), (i32 32)),
2694            (SHLLv4i32 V128:$Rn)>;
2695}
2696
2697defm : SIMDVectorLShiftLongBySizeBHSPats<anyext>;
2698defm : SIMDVectorLShiftLongBySizeBHSPats<zext>;
2699defm : SIMDVectorLShiftLongBySizeBHSPats<sext>;
2700
2701//===----------------------------------------------------------------------===//
2702// Advanced SIMD three vector instructions.
2703//===----------------------------------------------------------------------===//
2704
2705defm ADD     : SIMDThreeSameVector<0, 0b10000, "add", add>;
2706defm ADDP    : SIMDThreeSameVector<0, 0b10111, "addp", int_aarch64_neon_addp>;
2707defm CMEQ    : SIMDThreeSameVector<1, 0b10001, "cmeq", AArch64cmeq>;
2708defm CMGE    : SIMDThreeSameVector<0, 0b00111, "cmge", AArch64cmge>;
2709defm CMGT    : SIMDThreeSameVector<0, 0b00110, "cmgt", AArch64cmgt>;
2710defm CMHI    : SIMDThreeSameVector<1, 0b00110, "cmhi", AArch64cmhi>;
2711defm CMHS    : SIMDThreeSameVector<1, 0b00111, "cmhs", AArch64cmhs>;
2712defm CMTST   : SIMDThreeSameVector<0, 0b10001, "cmtst", AArch64cmtst>;
2713defm FABD    : SIMDThreeSameVectorFP<1,1,0b11010,"fabd", int_aarch64_neon_fabd>;
2714defm FACGE   : SIMDThreeSameVectorFPCmp<1,0,0b11101,"facge",int_aarch64_neon_facge>;
2715defm FACGT   : SIMDThreeSameVectorFPCmp<1,1,0b11101,"facgt",int_aarch64_neon_facgt>;
2716defm FADDP   : SIMDThreeSameVectorFP<1,0,0b11010,"faddp",int_aarch64_neon_addp>;
2717defm FADD    : SIMDThreeSameVectorFP<0,0,0b11010,"fadd", fadd>;
2718defm FCMEQ   : SIMDThreeSameVectorFPCmp<0, 0, 0b11100, "fcmeq", AArch64fcmeq>;
2719defm FCMGE   : SIMDThreeSameVectorFPCmp<1, 0, 0b11100, "fcmge", AArch64fcmge>;
2720defm FCMGT   : SIMDThreeSameVectorFPCmp<1, 1, 0b11100, "fcmgt", AArch64fcmgt>;
2721defm FDIV    : SIMDThreeSameVectorFP<1,0,0b11111,"fdiv", fdiv>;
2722defm FMAXNMP : SIMDThreeSameVectorFP<1,0,0b11000,"fmaxnmp", int_aarch64_neon_fmaxnmp>;
2723defm FMAXNM  : SIMDThreeSameVectorFP<0,0,0b11000,"fmaxnm", int_aarch64_neon_fmaxnm>;
2724defm FMAXP   : SIMDThreeSameVectorFP<1,0,0b11110,"fmaxp", int_aarch64_neon_fmaxp>;
2725defm FMAX    : SIMDThreeSameVectorFP<0,0,0b11110,"fmax", AArch64fmax>;
2726defm FMINNMP : SIMDThreeSameVectorFP<1,1,0b11000,"fminnmp", int_aarch64_neon_fminnmp>;
2727defm FMINNM  : SIMDThreeSameVectorFP<0,1,0b11000,"fminnm", int_aarch64_neon_fminnm>;
2728defm FMINP   : SIMDThreeSameVectorFP<1,1,0b11110,"fminp", int_aarch64_neon_fminp>;
2729defm FMIN    : SIMDThreeSameVectorFP<0,1,0b11110,"fmin", AArch64fmin>;
2730
2731// NOTE: The operands of the PatFrag are reordered on FMLA/FMLS because the
2732// instruction expects the addend first, while the fma intrinsic puts it last.
2733defm FMLA     : SIMDThreeSameVectorFPTied<0, 0, 0b11001, "fmla",
2734            TriOpFrag<(fma node:$RHS, node:$MHS, node:$LHS)> >;
2735defm FMLS     : SIMDThreeSameVectorFPTied<0, 1, 0b11001, "fmls",
2736            TriOpFrag<(fma node:$MHS, (fneg node:$RHS), node:$LHS)> >;
2737
2738// The following def pats catch the case where the LHS of an FMA is negated.
2739// The TriOpFrag above catches the case where the middle operand is negated.
2740def : Pat<(v2f32 (fma (fneg V64:$Rn), V64:$Rm, V64:$Rd)),
2741          (FMLSv2f32 V64:$Rd, V64:$Rn, V64:$Rm)>;
2742
2743def : Pat<(v4f32 (fma (fneg V128:$Rn), V128:$Rm, V128:$Rd)),
2744          (FMLSv4f32 V128:$Rd, V128:$Rn, V128:$Rm)>;
2745
2746def : Pat<(v2f64 (fma (fneg V128:$Rn), V128:$Rm, V128:$Rd)),
2747          (FMLSv2f64 V128:$Rd, V128:$Rn, V128:$Rm)>;
2748
2749defm FMULX    : SIMDThreeSameVectorFP<0,0,0b11011,"fmulx", int_aarch64_neon_fmulx>;
2750defm FMUL     : SIMDThreeSameVectorFP<1,0,0b11011,"fmul", fmul>;
2751defm FRECPS   : SIMDThreeSameVectorFP<0,0,0b11111,"frecps", int_aarch64_neon_frecps>;
2752defm FRSQRTS  : SIMDThreeSameVectorFP<0,1,0b11111,"frsqrts", int_aarch64_neon_frsqrts>;
2753defm FSUB     : SIMDThreeSameVectorFP<0,1,0b11010,"fsub", fsub>;
2754defm MLA      : SIMDThreeSameVectorBHSTied<0, 0b10010, "mla",
2755                      TriOpFrag<(add node:$LHS, (mul node:$MHS, node:$RHS))> >;
2756defm MLS      : SIMDThreeSameVectorBHSTied<1, 0b10010, "mls",
2757                      TriOpFrag<(sub node:$LHS, (mul node:$MHS, node:$RHS))> >;
2758defm MUL      : SIMDThreeSameVectorBHS<0, 0b10011, "mul", mul>;
2759defm PMUL     : SIMDThreeSameVectorB<1, 0b10011, "pmul", int_aarch64_neon_pmul>;
2760defm SABA     : SIMDThreeSameVectorBHSTied<0, 0b01111, "saba",
2761      TriOpFrag<(add node:$LHS, (int_aarch64_neon_sabd node:$MHS, node:$RHS))> >;
2762defm SABD     : SIMDThreeSameVectorBHS<0,0b01110,"sabd", int_aarch64_neon_sabd>;
2763defm SHADD    : SIMDThreeSameVectorBHS<0,0b00000,"shadd", int_aarch64_neon_shadd>;
2764defm SHSUB    : SIMDThreeSameVectorBHS<0,0b00100,"shsub", int_aarch64_neon_shsub>;
2765defm SMAXP    : SIMDThreeSameVectorBHS<0,0b10100,"smaxp", int_aarch64_neon_smaxp>;
2766defm SMAX     : SIMDThreeSameVectorBHS<0,0b01100,"smax", int_aarch64_neon_smax>;
2767defm SMINP    : SIMDThreeSameVectorBHS<0,0b10101,"sminp", int_aarch64_neon_sminp>;
2768defm SMIN     : SIMDThreeSameVectorBHS<0,0b01101,"smin", int_aarch64_neon_smin>;
2769defm SQADD    : SIMDThreeSameVector<0,0b00001,"sqadd", int_aarch64_neon_sqadd>;
2770defm SQDMULH  : SIMDThreeSameVectorHS<0,0b10110,"sqdmulh",int_aarch64_neon_sqdmulh>;
2771defm SQRDMULH : SIMDThreeSameVectorHS<1,0b10110,"sqrdmulh",int_aarch64_neon_sqrdmulh>;
2772defm SQRSHL   : SIMDThreeSameVector<0,0b01011,"sqrshl", int_aarch64_neon_sqrshl>;
2773defm SQSHL    : SIMDThreeSameVector<0,0b01001,"sqshl", int_aarch64_neon_sqshl>;
2774defm SQSUB    : SIMDThreeSameVector<0,0b00101,"sqsub", int_aarch64_neon_sqsub>;
2775defm SRHADD   : SIMDThreeSameVectorBHS<0,0b00010,"srhadd",int_aarch64_neon_srhadd>;
2776defm SRSHL    : SIMDThreeSameVector<0,0b01010,"srshl", int_aarch64_neon_srshl>;
2777defm SSHL     : SIMDThreeSameVector<0,0b01000,"sshl", int_aarch64_neon_sshl>;
2778defm SUB      : SIMDThreeSameVector<1,0b10000,"sub", sub>;
2779defm UABA     : SIMDThreeSameVectorBHSTied<1, 0b01111, "uaba",
2780      TriOpFrag<(add node:$LHS, (int_aarch64_neon_uabd node:$MHS, node:$RHS))> >;
2781defm UABD     : SIMDThreeSameVectorBHS<1,0b01110,"uabd", int_aarch64_neon_uabd>;
2782defm UHADD    : SIMDThreeSameVectorBHS<1,0b00000,"uhadd", int_aarch64_neon_uhadd>;
2783defm UHSUB    : SIMDThreeSameVectorBHS<1,0b00100,"uhsub", int_aarch64_neon_uhsub>;
2784defm UMAXP    : SIMDThreeSameVectorBHS<1,0b10100,"umaxp", int_aarch64_neon_umaxp>;
2785defm UMAX     : SIMDThreeSameVectorBHS<1,0b01100,"umax", int_aarch64_neon_umax>;
2786defm UMINP    : SIMDThreeSameVectorBHS<1,0b10101,"uminp", int_aarch64_neon_uminp>;
2787defm UMIN     : SIMDThreeSameVectorBHS<1,0b01101,"umin", int_aarch64_neon_umin>;
2788defm UQADD    : SIMDThreeSameVector<1,0b00001,"uqadd", int_aarch64_neon_uqadd>;
2789defm UQRSHL   : SIMDThreeSameVector<1,0b01011,"uqrshl", int_aarch64_neon_uqrshl>;
2790defm UQSHL    : SIMDThreeSameVector<1,0b01001,"uqshl", int_aarch64_neon_uqshl>;
2791defm UQSUB    : SIMDThreeSameVector<1,0b00101,"uqsub", int_aarch64_neon_uqsub>;
2792defm URHADD   : SIMDThreeSameVectorBHS<1,0b00010,"urhadd", int_aarch64_neon_urhadd>;
2793defm URSHL    : SIMDThreeSameVector<1,0b01010,"urshl", int_aarch64_neon_urshl>;
2794defm USHL     : SIMDThreeSameVector<1,0b01000,"ushl", int_aarch64_neon_ushl>;
2795defm SQRDMLAH : SIMDThreeSameVectorSQRDMLxHTiedHS<1,0b10000,"sqrdmlah",
2796                                                  int_aarch64_neon_sqadd>;
2797defm SQRDMLSH : SIMDThreeSameVectorSQRDMLxHTiedHS<1,0b10001,"sqrdmlsh",
2798                                                    int_aarch64_neon_sqsub>;
2799
2800defm AND : SIMDLogicalThreeVector<0, 0b00, "and", and>;
2801defm BIC : SIMDLogicalThreeVector<0, 0b01, "bic",
2802                                  BinOpFrag<(and node:$LHS, (vnot node:$RHS))> >;
2803defm BIF : SIMDLogicalThreeVector<1, 0b11, "bif">;
2804defm BIT : SIMDLogicalThreeVectorTied<1, 0b10, "bit", AArch64bit>;
2805defm BSL : SIMDLogicalThreeVectorTied<1, 0b01, "bsl",
2806    TriOpFrag<(or (and node:$LHS, node:$MHS), (and (vnot node:$LHS), node:$RHS))>>;
2807defm EOR : SIMDLogicalThreeVector<1, 0b00, "eor", xor>;
2808defm ORN : SIMDLogicalThreeVector<0, 0b11, "orn",
2809                                  BinOpFrag<(or node:$LHS, (vnot node:$RHS))> >;
2810defm ORR : SIMDLogicalThreeVector<0, 0b10, "orr", or>;
2811
2812def : Pat<(AArch64bsl (v8i8 V64:$Rd), V64:$Rn, V64:$Rm),
2813          (BSLv8i8 V64:$Rd, V64:$Rn, V64:$Rm)>;
2814def : Pat<(AArch64bsl (v4i16 V64:$Rd), V64:$Rn, V64:$Rm),
2815          (BSLv8i8 V64:$Rd, V64:$Rn, V64:$Rm)>;
2816def : Pat<(AArch64bsl (v2i32 V64:$Rd), V64:$Rn, V64:$Rm),
2817          (BSLv8i8 V64:$Rd, V64:$Rn, V64:$Rm)>;
2818def : Pat<(AArch64bsl (v1i64 V64:$Rd), V64:$Rn, V64:$Rm),
2819          (BSLv8i8 V64:$Rd, V64:$Rn, V64:$Rm)>;
2820
2821def : Pat<(AArch64bsl (v16i8 V128:$Rd), V128:$Rn, V128:$Rm),
2822          (BSLv16i8 V128:$Rd, V128:$Rn, V128:$Rm)>;
2823def : Pat<(AArch64bsl (v8i16 V128:$Rd), V128:$Rn, V128:$Rm),
2824          (BSLv16i8 V128:$Rd, V128:$Rn, V128:$Rm)>;
2825def : Pat<(AArch64bsl (v4i32 V128:$Rd), V128:$Rn, V128:$Rm),
2826          (BSLv16i8 V128:$Rd, V128:$Rn, V128:$Rm)>;
2827def : Pat<(AArch64bsl (v2i64 V128:$Rd), V128:$Rn, V128:$Rm),
2828          (BSLv16i8 V128:$Rd, V128:$Rn, V128:$Rm)>;
2829
2830def : InstAlias<"mov{\t$dst.16b, $src.16b|.16b\t$dst, $src}",
2831                (ORRv16i8 V128:$dst, V128:$src, V128:$src), 1>;
2832def : InstAlias<"mov{\t$dst.8h, $src.8h|.8h\t$dst, $src}",
2833                (ORRv16i8 V128:$dst, V128:$src, V128:$src), 0>;
2834def : InstAlias<"mov{\t$dst.4s, $src.4s|.4s\t$dst, $src}",
2835                (ORRv16i8 V128:$dst, V128:$src, V128:$src), 0>;
2836def : InstAlias<"mov{\t$dst.2d, $src.2d|.2d\t$dst, $src}",
2837                (ORRv16i8 V128:$dst, V128:$src, V128:$src), 0>;
2838
2839def : InstAlias<"mov{\t$dst.8b, $src.8b|.8b\t$dst, $src}",
2840                (ORRv8i8 V64:$dst, V64:$src, V64:$src), 1>;
2841def : InstAlias<"mov{\t$dst.4h, $src.4h|.4h\t$dst, $src}",
2842                (ORRv8i8 V64:$dst, V64:$src, V64:$src), 0>;
2843def : InstAlias<"mov{\t$dst.2s, $src.2s|.2s\t$dst, $src}",
2844                (ORRv8i8 V64:$dst, V64:$src, V64:$src), 0>;
2845def : InstAlias<"mov{\t$dst.1d, $src.1d|.1d\t$dst, $src}",
2846                (ORRv8i8 V64:$dst, V64:$src, V64:$src), 0>;
2847
2848def : InstAlias<"{cmls\t$dst.8b, $src1.8b, $src2.8b" #
2849                "|cmls.8b\t$dst, $src1, $src2}",
2850                (CMHSv8i8 V64:$dst, V64:$src2, V64:$src1), 0>;
2851def : InstAlias<"{cmls\t$dst.16b, $src1.16b, $src2.16b" #
2852                "|cmls.16b\t$dst, $src1, $src2}",
2853                (CMHSv16i8 V128:$dst, V128:$src2, V128:$src1), 0>;
2854def : InstAlias<"{cmls\t$dst.4h, $src1.4h, $src2.4h" #
2855                "|cmls.4h\t$dst, $src1, $src2}",
2856                (CMHSv4i16 V64:$dst, V64:$src2, V64:$src1), 0>;
2857def : InstAlias<"{cmls\t$dst.8h, $src1.8h, $src2.8h" #
2858                "|cmls.8h\t$dst, $src1, $src2}",
2859                (CMHSv8i16 V128:$dst, V128:$src2, V128:$src1), 0>;
2860def : InstAlias<"{cmls\t$dst.2s, $src1.2s, $src2.2s" #
2861                "|cmls.2s\t$dst, $src1, $src2}",
2862                (CMHSv2i32 V64:$dst, V64:$src2, V64:$src1), 0>;
2863def : InstAlias<"{cmls\t$dst.4s, $src1.4s, $src2.4s" #
2864                "|cmls.4s\t$dst, $src1, $src2}",
2865                (CMHSv4i32 V128:$dst, V128:$src2, V128:$src1), 0>;
2866def : InstAlias<"{cmls\t$dst.2d, $src1.2d, $src2.2d" #
2867                "|cmls.2d\t$dst, $src1, $src2}",
2868                (CMHSv2i64 V128:$dst, V128:$src2, V128:$src1), 0>;
2869
2870def : InstAlias<"{cmlo\t$dst.8b, $src1.8b, $src2.8b" #
2871                "|cmlo.8b\t$dst, $src1, $src2}",
2872                (CMHIv8i8 V64:$dst, V64:$src2, V64:$src1), 0>;
2873def : InstAlias<"{cmlo\t$dst.16b, $src1.16b, $src2.16b" #
2874                "|cmlo.16b\t$dst, $src1, $src2}",
2875                (CMHIv16i8 V128:$dst, V128:$src2, V128:$src1), 0>;
2876def : InstAlias<"{cmlo\t$dst.4h, $src1.4h, $src2.4h" #
2877                "|cmlo.4h\t$dst, $src1, $src2}",
2878                (CMHIv4i16 V64:$dst, V64:$src2, V64:$src1), 0>;
2879def : InstAlias<"{cmlo\t$dst.8h, $src1.8h, $src2.8h" #
2880                "|cmlo.8h\t$dst, $src1, $src2}",
2881                (CMHIv8i16 V128:$dst, V128:$src2, V128:$src1), 0>;
2882def : InstAlias<"{cmlo\t$dst.2s, $src1.2s, $src2.2s" #
2883                "|cmlo.2s\t$dst, $src1, $src2}",
2884                (CMHIv2i32 V64:$dst, V64:$src2, V64:$src1), 0>;
2885def : InstAlias<"{cmlo\t$dst.4s, $src1.4s, $src2.4s" #
2886                "|cmlo.4s\t$dst, $src1, $src2}",
2887                (CMHIv4i32 V128:$dst, V128:$src2, V128:$src1), 0>;
2888def : InstAlias<"{cmlo\t$dst.2d, $src1.2d, $src2.2d" #
2889                "|cmlo.2d\t$dst, $src1, $src2}",
2890                (CMHIv2i64 V128:$dst, V128:$src2, V128:$src1), 0>;
2891
2892def : InstAlias<"{cmle\t$dst.8b, $src1.8b, $src2.8b" #
2893                "|cmle.8b\t$dst, $src1, $src2}",
2894                (CMGEv8i8 V64:$dst, V64:$src2, V64:$src1), 0>;
2895def : InstAlias<"{cmle\t$dst.16b, $src1.16b, $src2.16b" #
2896                "|cmle.16b\t$dst, $src1, $src2}",
2897                (CMGEv16i8 V128:$dst, V128:$src2, V128:$src1), 0>;
2898def : InstAlias<"{cmle\t$dst.4h, $src1.4h, $src2.4h" #
2899                "|cmle.4h\t$dst, $src1, $src2}",
2900                (CMGEv4i16 V64:$dst, V64:$src2, V64:$src1), 0>;
2901def : InstAlias<"{cmle\t$dst.8h, $src1.8h, $src2.8h" #
2902                "|cmle.8h\t$dst, $src1, $src2}",
2903                (CMGEv8i16 V128:$dst, V128:$src2, V128:$src1), 0>;
2904def : InstAlias<"{cmle\t$dst.2s, $src1.2s, $src2.2s" #
2905                "|cmle.2s\t$dst, $src1, $src2}",
2906                (CMGEv2i32 V64:$dst, V64:$src2, V64:$src1), 0>;
2907def : InstAlias<"{cmle\t$dst.4s, $src1.4s, $src2.4s" #
2908                "|cmle.4s\t$dst, $src1, $src2}",
2909                (CMGEv4i32 V128:$dst, V128:$src2, V128:$src1), 0>;
2910def : InstAlias<"{cmle\t$dst.2d, $src1.2d, $src2.2d" #
2911                "|cmle.2d\t$dst, $src1, $src2}",
2912                (CMGEv2i64 V128:$dst, V128:$src2, V128:$src1), 0>;
2913
2914def : InstAlias<"{cmlt\t$dst.8b, $src1.8b, $src2.8b" #
2915                "|cmlt.8b\t$dst, $src1, $src2}",
2916                (CMGTv8i8 V64:$dst, V64:$src2, V64:$src1), 0>;
2917def : InstAlias<"{cmlt\t$dst.16b, $src1.16b, $src2.16b" #
2918                "|cmlt.16b\t$dst, $src1, $src2}",
2919                (CMGTv16i8 V128:$dst, V128:$src2, V128:$src1), 0>;
2920def : InstAlias<"{cmlt\t$dst.4h, $src1.4h, $src2.4h" #
2921                "|cmlt.4h\t$dst, $src1, $src2}",
2922                (CMGTv4i16 V64:$dst, V64:$src2, V64:$src1), 0>;
2923def : InstAlias<"{cmlt\t$dst.8h, $src1.8h, $src2.8h" #
2924                "|cmlt.8h\t$dst, $src1, $src2}",
2925                (CMGTv8i16 V128:$dst, V128:$src2, V128:$src1), 0>;
2926def : InstAlias<"{cmlt\t$dst.2s, $src1.2s, $src2.2s" #
2927                "|cmlt.2s\t$dst, $src1, $src2}",
2928                (CMGTv2i32 V64:$dst, V64:$src2, V64:$src1), 0>;
2929def : InstAlias<"{cmlt\t$dst.4s, $src1.4s, $src2.4s" #
2930                "|cmlt.4s\t$dst, $src1, $src2}",
2931                (CMGTv4i32 V128:$dst, V128:$src2, V128:$src1), 0>;
2932def : InstAlias<"{cmlt\t$dst.2d, $src1.2d, $src2.2d" #
2933                "|cmlt.2d\t$dst, $src1, $src2}",
2934                (CMGTv2i64 V128:$dst, V128:$src2, V128:$src1), 0>;
2935
2936def : InstAlias<"{fcmle\t$dst.2s, $src1.2s, $src2.2s" #
2937                "|fcmle.2s\t$dst, $src1, $src2}",
2938                (FCMGEv2f32 V64:$dst, V64:$src2, V64:$src1), 0>;
2939def : InstAlias<"{fcmle\t$dst.4s, $src1.4s, $src2.4s" #
2940                "|fcmle.4s\t$dst, $src1, $src2}",
2941                (FCMGEv4f32 V128:$dst, V128:$src2, V128:$src1), 0>;
2942def : InstAlias<"{fcmle\t$dst.2d, $src1.2d, $src2.2d" #
2943                "|fcmle.2d\t$dst, $src1, $src2}",
2944                (FCMGEv2f64 V128:$dst, V128:$src2, V128:$src1), 0>;
2945
2946def : InstAlias<"{fcmlt\t$dst.2s, $src1.2s, $src2.2s" #
2947                "|fcmlt.2s\t$dst, $src1, $src2}",
2948                (FCMGTv2f32 V64:$dst, V64:$src2, V64:$src1), 0>;
2949def : InstAlias<"{fcmlt\t$dst.4s, $src1.4s, $src2.4s" #
2950                "|fcmlt.4s\t$dst, $src1, $src2}",
2951                (FCMGTv4f32 V128:$dst, V128:$src2, V128:$src1), 0>;
2952def : InstAlias<"{fcmlt\t$dst.2d, $src1.2d, $src2.2d" #
2953                "|fcmlt.2d\t$dst, $src1, $src2}",
2954                (FCMGTv2f64 V128:$dst, V128:$src2, V128:$src1), 0>;
2955
2956def : InstAlias<"{facle\t$dst.2s, $src1.2s, $src2.2s" #
2957                "|facle.2s\t$dst, $src1, $src2}",
2958                (FACGEv2f32 V64:$dst, V64:$src2, V64:$src1), 0>;
2959def : InstAlias<"{facle\t$dst.4s, $src1.4s, $src2.4s" #
2960                "|facle.4s\t$dst, $src1, $src2}",
2961                (FACGEv4f32 V128:$dst, V128:$src2, V128:$src1), 0>;
2962def : InstAlias<"{facle\t$dst.2d, $src1.2d, $src2.2d" #
2963                "|facle.2d\t$dst, $src1, $src2}",
2964                (FACGEv2f64 V128:$dst, V128:$src2, V128:$src1), 0>;
2965
2966def : InstAlias<"{faclt\t$dst.2s, $src1.2s, $src2.2s" #
2967                "|faclt.2s\t$dst, $src1, $src2}",
2968                (FACGTv2f32 V64:$dst, V64:$src2, V64:$src1), 0>;
2969def : InstAlias<"{faclt\t$dst.4s, $src1.4s, $src2.4s" #
2970                "|faclt.4s\t$dst, $src1, $src2}",
2971                (FACGTv4f32 V128:$dst, V128:$src2, V128:$src1), 0>;
2972def : InstAlias<"{faclt\t$dst.2d, $src1.2d, $src2.2d" #
2973                "|faclt.2d\t$dst, $src1, $src2}",
2974                (FACGTv2f64 V128:$dst, V128:$src2, V128:$src1), 0>;
2975
2976//===----------------------------------------------------------------------===//
2977// Advanced SIMD three scalar instructions.
2978//===----------------------------------------------------------------------===//
2979
2980defm ADD      : SIMDThreeScalarD<0, 0b10000, "add", add>;
2981defm CMEQ     : SIMDThreeScalarD<1, 0b10001, "cmeq", AArch64cmeq>;
2982defm CMGE     : SIMDThreeScalarD<0, 0b00111, "cmge", AArch64cmge>;
2983defm CMGT     : SIMDThreeScalarD<0, 0b00110, "cmgt", AArch64cmgt>;
2984defm CMHI     : SIMDThreeScalarD<1, 0b00110, "cmhi", AArch64cmhi>;
2985defm CMHS     : SIMDThreeScalarD<1, 0b00111, "cmhs", AArch64cmhs>;
2986defm CMTST    : SIMDThreeScalarD<0, 0b10001, "cmtst", AArch64cmtst>;
2987defm FABD     : SIMDThreeScalarSD<1, 1, 0b11010, "fabd", int_aarch64_sisd_fabd>;
2988def : Pat<(v1f64 (int_aarch64_neon_fabd (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
2989          (FABD64 FPR64:$Rn, FPR64:$Rm)>;
2990defm FACGE    : SIMDThreeScalarFPCmp<1, 0, 0b11101, "facge",
2991                                     int_aarch64_neon_facge>;
2992defm FACGT    : SIMDThreeScalarFPCmp<1, 1, 0b11101, "facgt",
2993                                     int_aarch64_neon_facgt>;
2994defm FCMEQ    : SIMDThreeScalarFPCmp<0, 0, 0b11100, "fcmeq", AArch64fcmeq>;
2995defm FCMGE    : SIMDThreeScalarFPCmp<1, 0, 0b11100, "fcmge", AArch64fcmge>;
2996defm FCMGT    : SIMDThreeScalarFPCmp<1, 1, 0b11100, "fcmgt", AArch64fcmgt>;
2997defm FMULX    : SIMDThreeScalarSD<0, 0, 0b11011, "fmulx", int_aarch64_neon_fmulx>;
2998defm FRECPS   : SIMDThreeScalarSD<0, 0, 0b11111, "frecps", int_aarch64_neon_frecps>;
2999defm FRSQRTS  : SIMDThreeScalarSD<0, 1, 0b11111, "frsqrts", int_aarch64_neon_frsqrts>;
3000defm SQADD    : SIMDThreeScalarBHSD<0, 0b00001, "sqadd", int_aarch64_neon_sqadd>;
3001defm SQDMULH  : SIMDThreeScalarHS<  0, 0b10110, "sqdmulh", int_aarch64_neon_sqdmulh>;
3002defm SQRDMULH : SIMDThreeScalarHS<  1, 0b10110, "sqrdmulh", int_aarch64_neon_sqrdmulh>;
3003defm SQRSHL   : SIMDThreeScalarBHSD<0, 0b01011, "sqrshl",int_aarch64_neon_sqrshl>;
3004defm SQSHL    : SIMDThreeScalarBHSD<0, 0b01001, "sqshl", int_aarch64_neon_sqshl>;
3005defm SQSUB    : SIMDThreeScalarBHSD<0, 0b00101, "sqsub", int_aarch64_neon_sqsub>;
3006defm SRSHL    : SIMDThreeScalarD<   0, 0b01010, "srshl", int_aarch64_neon_srshl>;
3007defm SSHL     : SIMDThreeScalarD<   0, 0b01000, "sshl", int_aarch64_neon_sshl>;
3008defm SUB      : SIMDThreeScalarD<   1, 0b10000, "sub", sub>;
3009defm UQADD    : SIMDThreeScalarBHSD<1, 0b00001, "uqadd", int_aarch64_neon_uqadd>;
3010defm UQRSHL   : SIMDThreeScalarBHSD<1, 0b01011, "uqrshl",int_aarch64_neon_uqrshl>;
3011defm UQSHL    : SIMDThreeScalarBHSD<1, 0b01001, "uqshl", int_aarch64_neon_uqshl>;
3012defm UQSUB    : SIMDThreeScalarBHSD<1, 0b00101, "uqsub", int_aarch64_neon_uqsub>;
3013defm URSHL    : SIMDThreeScalarD<   1, 0b01010, "urshl", int_aarch64_neon_urshl>;
3014defm USHL     : SIMDThreeScalarD<   1, 0b01000, "ushl", int_aarch64_neon_ushl>;
3015let Predicates = [HasV8_1a] in {
3016  defm SQRDMLAH : SIMDThreeScalarHSTied<1, 0, 0b10000, "sqrdmlah">;
3017  defm SQRDMLSH : SIMDThreeScalarHSTied<1, 0, 0b10001, "sqrdmlsh">;
3018  def : Pat<(i32 (int_aarch64_neon_sqadd
3019                   (i32 FPR32:$Rd),
3020                   (i32 (int_aarch64_neon_sqrdmulh (i32 FPR32:$Rn),
3021                                                   (i32 FPR32:$Rm))))),
3022            (SQRDMLAHv1i32 FPR32:$Rd, FPR32:$Rn, FPR32:$Rm)>;
3023  def : Pat<(i32 (int_aarch64_neon_sqsub
3024                   (i32 FPR32:$Rd),
3025                   (i32 (int_aarch64_neon_sqrdmulh (i32 FPR32:$Rn),
3026                                                   (i32 FPR32:$Rm))))),
3027            (SQRDMLSHv1i32 FPR32:$Rd, FPR32:$Rn, FPR32:$Rm)>;
3028}
3029
3030def : InstAlias<"cmls $dst, $src1, $src2",
3031                (CMHSv1i64 FPR64:$dst, FPR64:$src2, FPR64:$src1), 0>;
3032def : InstAlias<"cmle $dst, $src1, $src2",
3033                (CMGEv1i64 FPR64:$dst, FPR64:$src2, FPR64:$src1), 0>;
3034def : InstAlias<"cmlo $dst, $src1, $src2",
3035                (CMHIv1i64 FPR64:$dst, FPR64:$src2, FPR64:$src1), 0>;
3036def : InstAlias<"cmlt $dst, $src1, $src2",
3037                (CMGTv1i64 FPR64:$dst, FPR64:$src2, FPR64:$src1), 0>;
3038def : InstAlias<"fcmle $dst, $src1, $src2",
3039                (FCMGE32 FPR32:$dst, FPR32:$src2, FPR32:$src1), 0>;
3040def : InstAlias<"fcmle $dst, $src1, $src2",
3041                (FCMGE64 FPR64:$dst, FPR64:$src2, FPR64:$src1), 0>;
3042def : InstAlias<"fcmlt $dst, $src1, $src2",
3043                (FCMGT32 FPR32:$dst, FPR32:$src2, FPR32:$src1), 0>;
3044def : InstAlias<"fcmlt $dst, $src1, $src2",
3045                (FCMGT64 FPR64:$dst, FPR64:$src2, FPR64:$src1), 0>;
3046def : InstAlias<"facle $dst, $src1, $src2",
3047                (FACGE32 FPR32:$dst, FPR32:$src2, FPR32:$src1), 0>;
3048def : InstAlias<"facle $dst, $src1, $src2",
3049                (FACGE64 FPR64:$dst, FPR64:$src2, FPR64:$src1), 0>;
3050def : InstAlias<"faclt $dst, $src1, $src2",
3051                (FACGT32 FPR32:$dst, FPR32:$src2, FPR32:$src1), 0>;
3052def : InstAlias<"faclt $dst, $src1, $src2",
3053                (FACGT64 FPR64:$dst, FPR64:$src2, FPR64:$src1), 0>;
3054
3055//===----------------------------------------------------------------------===//
3056// Advanced SIMD three scalar instructions (mixed operands).
3057//===----------------------------------------------------------------------===//
3058defm SQDMULL  : SIMDThreeScalarMixedHS<0, 0b11010, "sqdmull",
3059                                       int_aarch64_neon_sqdmulls_scalar>;
3060defm SQDMLAL  : SIMDThreeScalarMixedTiedHS<0, 0b10010, "sqdmlal">;
3061defm SQDMLSL  : SIMDThreeScalarMixedTiedHS<0, 0b10110, "sqdmlsl">;
3062
3063def : Pat<(i64 (int_aarch64_neon_sqadd (i64 FPR64:$Rd),
3064                   (i64 (int_aarch64_neon_sqdmulls_scalar (i32 FPR32:$Rn),
3065                                                        (i32 FPR32:$Rm))))),
3066          (SQDMLALi32 FPR64:$Rd, FPR32:$Rn, FPR32:$Rm)>;
3067def : Pat<(i64 (int_aarch64_neon_sqsub (i64 FPR64:$Rd),
3068                   (i64 (int_aarch64_neon_sqdmulls_scalar (i32 FPR32:$Rn),
3069                                                        (i32 FPR32:$Rm))))),
3070          (SQDMLSLi32 FPR64:$Rd, FPR32:$Rn, FPR32:$Rm)>;
3071
3072//===----------------------------------------------------------------------===//
3073// Advanced SIMD two scalar instructions.
3074//===----------------------------------------------------------------------===//
3075
3076defm ABS    : SIMDTwoScalarD<    0, 0b01011, "abs", int_aarch64_neon_abs>;
3077defm CMEQ   : SIMDCmpTwoScalarD< 0, 0b01001, "cmeq", AArch64cmeqz>;
3078defm CMGE   : SIMDCmpTwoScalarD< 1, 0b01000, "cmge", AArch64cmgez>;
3079defm CMGT   : SIMDCmpTwoScalarD< 0, 0b01000, "cmgt", AArch64cmgtz>;
3080defm CMLE   : SIMDCmpTwoScalarD< 1, 0b01001, "cmle", AArch64cmlez>;
3081defm CMLT   : SIMDCmpTwoScalarD< 0, 0b01010, "cmlt", AArch64cmltz>;
3082defm FCMEQ  : SIMDCmpTwoScalarSD<0, 1, 0b01101, "fcmeq", AArch64fcmeqz>;
3083defm FCMGE  : SIMDCmpTwoScalarSD<1, 1, 0b01100, "fcmge", AArch64fcmgez>;
3084defm FCMGT  : SIMDCmpTwoScalarSD<0, 1, 0b01100, "fcmgt", AArch64fcmgtz>;
3085defm FCMLE  : SIMDCmpTwoScalarSD<1, 1, 0b01101, "fcmle", AArch64fcmlez>;
3086defm FCMLT  : SIMDCmpTwoScalarSD<0, 1, 0b01110, "fcmlt", AArch64fcmltz>;
3087defm FCVTAS : SIMDTwoScalarSD<   0, 0, 0b11100, "fcvtas">;
3088defm FCVTAU : SIMDTwoScalarSD<   1, 0, 0b11100, "fcvtau">;
3089defm FCVTMS : SIMDTwoScalarSD<   0, 0, 0b11011, "fcvtms">;
3090defm FCVTMU : SIMDTwoScalarSD<   1, 0, 0b11011, "fcvtmu">;
3091defm FCVTNS : SIMDTwoScalarSD<   0, 0, 0b11010, "fcvtns">;
3092defm FCVTNU : SIMDTwoScalarSD<   1, 0, 0b11010, "fcvtnu">;
3093defm FCVTPS : SIMDTwoScalarSD<   0, 1, 0b11010, "fcvtps">;
3094defm FCVTPU : SIMDTwoScalarSD<   1, 1, 0b11010, "fcvtpu">;
3095def  FCVTXNv1i64 : SIMDInexactCvtTwoScalar<0b10110, "fcvtxn">;
3096defm FCVTZS : SIMDTwoScalarSD<   0, 1, 0b11011, "fcvtzs">;
3097defm FCVTZU : SIMDTwoScalarSD<   1, 1, 0b11011, "fcvtzu">;
3098defm FRECPE : SIMDTwoScalarSD<   0, 1, 0b11101, "frecpe">;
3099defm FRECPX : SIMDTwoScalarSD<   0, 1, 0b11111, "frecpx">;
3100defm FRSQRTE : SIMDTwoScalarSD<  1, 1, 0b11101, "frsqrte">;
3101defm NEG    : SIMDTwoScalarD<    1, 0b01011, "neg",
3102                                 UnOpFrag<(sub immAllZerosV, node:$LHS)> >;
3103defm SCVTF  : SIMDTwoScalarCVTSD<   0, 0, 0b11101, "scvtf", AArch64sitof>;
3104defm SQABS  : SIMDTwoScalarBHSD< 0, 0b00111, "sqabs", int_aarch64_neon_sqabs>;
3105defm SQNEG  : SIMDTwoScalarBHSD< 1, 0b00111, "sqneg", int_aarch64_neon_sqneg>;
3106defm SQXTN  : SIMDTwoScalarMixedBHS< 0, 0b10100, "sqxtn", int_aarch64_neon_scalar_sqxtn>;
3107defm SQXTUN : SIMDTwoScalarMixedBHS< 1, 0b10010, "sqxtun", int_aarch64_neon_scalar_sqxtun>;
3108defm SUQADD : SIMDTwoScalarBHSDTied< 0, 0b00011, "suqadd",
3109                                     int_aarch64_neon_suqadd>;
3110defm UCVTF  : SIMDTwoScalarCVTSD<   1, 0, 0b11101, "ucvtf", AArch64uitof>;
3111defm UQXTN  : SIMDTwoScalarMixedBHS<1, 0b10100, "uqxtn", int_aarch64_neon_scalar_uqxtn>;
3112defm USQADD : SIMDTwoScalarBHSDTied< 1, 0b00011, "usqadd",
3113                                    int_aarch64_neon_usqadd>;
3114
3115def : Pat<(AArch64neg (v1i64 V64:$Rn)), (NEGv1i64 V64:$Rn)>;
3116
3117def : Pat<(v1i64 (int_aarch64_neon_fcvtas (v1f64 FPR64:$Rn))),
3118          (FCVTASv1i64 FPR64:$Rn)>;
3119def : Pat<(v1i64 (int_aarch64_neon_fcvtau (v1f64 FPR64:$Rn))),
3120          (FCVTAUv1i64 FPR64:$Rn)>;
3121def : Pat<(v1i64 (int_aarch64_neon_fcvtms (v1f64 FPR64:$Rn))),
3122          (FCVTMSv1i64 FPR64:$Rn)>;
3123def : Pat<(v1i64 (int_aarch64_neon_fcvtmu (v1f64 FPR64:$Rn))),
3124          (FCVTMUv1i64 FPR64:$Rn)>;
3125def : Pat<(v1i64 (int_aarch64_neon_fcvtns (v1f64 FPR64:$Rn))),
3126          (FCVTNSv1i64 FPR64:$Rn)>;
3127def : Pat<(v1i64 (int_aarch64_neon_fcvtnu (v1f64 FPR64:$Rn))),
3128          (FCVTNUv1i64 FPR64:$Rn)>;
3129def : Pat<(v1i64 (int_aarch64_neon_fcvtps (v1f64 FPR64:$Rn))),
3130          (FCVTPSv1i64 FPR64:$Rn)>;
3131def : Pat<(v1i64 (int_aarch64_neon_fcvtpu (v1f64 FPR64:$Rn))),
3132          (FCVTPUv1i64 FPR64:$Rn)>;
3133
3134def : Pat<(f32 (int_aarch64_neon_frecpe (f32 FPR32:$Rn))),
3135          (FRECPEv1i32 FPR32:$Rn)>;
3136def : Pat<(f64 (int_aarch64_neon_frecpe (f64 FPR64:$Rn))),
3137          (FRECPEv1i64 FPR64:$Rn)>;
3138def : Pat<(v1f64 (int_aarch64_neon_frecpe (v1f64 FPR64:$Rn))),
3139          (FRECPEv1i64 FPR64:$Rn)>;
3140
3141def : Pat<(f32 (int_aarch64_neon_frecpx (f32 FPR32:$Rn))),
3142          (FRECPXv1i32 FPR32:$Rn)>;
3143def : Pat<(f64 (int_aarch64_neon_frecpx (f64 FPR64:$Rn))),
3144          (FRECPXv1i64 FPR64:$Rn)>;
3145
3146def : Pat<(f32 (int_aarch64_neon_frsqrte (f32 FPR32:$Rn))),
3147          (FRSQRTEv1i32 FPR32:$Rn)>;
3148def : Pat<(f64 (int_aarch64_neon_frsqrte (f64 FPR64:$Rn))),
3149          (FRSQRTEv1i64 FPR64:$Rn)>;
3150def : Pat<(v1f64 (int_aarch64_neon_frsqrte (v1f64 FPR64:$Rn))),
3151          (FRSQRTEv1i64 FPR64:$Rn)>;
3152
3153// If an integer is about to be converted to a floating point value,
3154// just load it on the floating point unit.
3155// Here are the patterns for 8 and 16-bits to float.
3156// 8-bits -> float.
3157multiclass UIntToFPROLoadPat<ValueType DstTy, ValueType SrcTy,
3158                             SDPatternOperator loadop, Instruction UCVTF,
3159                             ROAddrMode ro, Instruction LDRW, Instruction LDRX,
3160                             SubRegIndex sub> {
3161  def : Pat<(DstTy (uint_to_fp (SrcTy
3162                     (loadop (ro.Wpat GPR64sp:$Rn, GPR32:$Rm,
3163                                      ro.Wext:$extend))))),
3164           (UCVTF (INSERT_SUBREG (DstTy (IMPLICIT_DEF)),
3165                                 (LDRW GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend),
3166                                 sub))>;
3167
3168  def : Pat<(DstTy (uint_to_fp (SrcTy
3169                     (loadop (ro.Xpat GPR64sp:$Rn, GPR64:$Rm,
3170                                      ro.Wext:$extend))))),
3171           (UCVTF (INSERT_SUBREG (DstTy (IMPLICIT_DEF)),
3172                                 (LDRX GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend),
3173                                 sub))>;
3174}
3175
3176defm : UIntToFPROLoadPat<f32, i32, zextloadi8,
3177                         UCVTFv1i32, ro8, LDRBroW, LDRBroX, bsub>;
3178def : Pat <(f32 (uint_to_fp (i32
3179               (zextloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))))),
3180           (UCVTFv1i32 (INSERT_SUBREG (f32 (IMPLICIT_DEF)),
3181                          (LDRBui GPR64sp:$Rn, uimm12s1:$offset), bsub))>;
3182def : Pat <(f32 (uint_to_fp (i32
3183                     (zextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))))),
3184           (UCVTFv1i32 (INSERT_SUBREG (f32 (IMPLICIT_DEF)),
3185                          (LDURBi GPR64sp:$Rn, simm9:$offset), bsub))>;
3186// 16-bits -> float.
3187defm : UIntToFPROLoadPat<f32, i32, zextloadi16,
3188                         UCVTFv1i32, ro16, LDRHroW, LDRHroX, hsub>;
3189def : Pat <(f32 (uint_to_fp (i32
3190                  (zextloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))))),
3191           (UCVTFv1i32 (INSERT_SUBREG (f32 (IMPLICIT_DEF)),
3192                          (LDRHui GPR64sp:$Rn, uimm12s2:$offset), hsub))>;
3193def : Pat <(f32 (uint_to_fp (i32
3194                  (zextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))))),
3195           (UCVTFv1i32 (INSERT_SUBREG (f32 (IMPLICIT_DEF)),
3196                          (LDURHi GPR64sp:$Rn, simm9:$offset), hsub))>;
3197// 32-bits are handled in target specific dag combine:
3198// performIntToFpCombine.
3199// 64-bits integer to 32-bits floating point, not possible with
3200// UCVTF on floating point registers (both source and destination
3201// must have the same size).
3202
3203// Here are the patterns for 8, 16, 32, and 64-bits to double.
3204// 8-bits -> double.
3205defm : UIntToFPROLoadPat<f64, i32, zextloadi8,
3206                         UCVTFv1i64, ro8, LDRBroW, LDRBroX, bsub>;
3207def : Pat <(f64 (uint_to_fp (i32
3208                    (zextloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))))),
3209           (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
3210                          (LDRBui GPR64sp:$Rn, uimm12s1:$offset), bsub))>;
3211def : Pat <(f64 (uint_to_fp (i32
3212                  (zextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))))),
3213           (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
3214                          (LDURBi GPR64sp:$Rn, simm9:$offset), bsub))>;
3215// 16-bits -> double.
3216defm : UIntToFPROLoadPat<f64, i32, zextloadi16,
3217                         UCVTFv1i64, ro16, LDRHroW, LDRHroX, hsub>;
3218def : Pat <(f64 (uint_to_fp (i32
3219                  (zextloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))))),
3220           (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
3221                          (LDRHui GPR64sp:$Rn, uimm12s2:$offset), hsub))>;
3222def : Pat <(f64 (uint_to_fp (i32
3223                  (zextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))))),
3224           (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
3225                          (LDURHi GPR64sp:$Rn, simm9:$offset), hsub))>;
3226// 32-bits -> double.
3227defm : UIntToFPROLoadPat<f64, i32, load,
3228                         UCVTFv1i64, ro32, LDRSroW, LDRSroX, ssub>;
3229def : Pat <(f64 (uint_to_fp (i32
3230                  (load (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))))),
3231           (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
3232                          (LDRSui GPR64sp:$Rn, uimm12s4:$offset), ssub))>;
3233def : Pat <(f64 (uint_to_fp (i32
3234                  (load (am_unscaled32 GPR64sp:$Rn, simm9:$offset))))),
3235           (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
3236                          (LDURSi GPR64sp:$Rn, simm9:$offset), ssub))>;
3237// 64-bits -> double are handled in target specific dag combine:
3238// performIntToFpCombine.
3239
3240//===----------------------------------------------------------------------===//
3241// Advanced SIMD three different-sized vector instructions.
3242//===----------------------------------------------------------------------===//
3243
3244defm ADDHN  : SIMDNarrowThreeVectorBHS<0,0b0100,"addhn", int_aarch64_neon_addhn>;
3245defm SUBHN  : SIMDNarrowThreeVectorBHS<0,0b0110,"subhn", int_aarch64_neon_subhn>;
3246defm RADDHN : SIMDNarrowThreeVectorBHS<1,0b0100,"raddhn",int_aarch64_neon_raddhn>;
3247defm RSUBHN : SIMDNarrowThreeVectorBHS<1,0b0110,"rsubhn",int_aarch64_neon_rsubhn>;
3248defm PMULL  : SIMDDifferentThreeVectorBD<0,0b1110,"pmull",int_aarch64_neon_pmull>;
3249defm SABAL  : SIMDLongThreeVectorTiedBHSabal<0,0b0101,"sabal",
3250                                             int_aarch64_neon_sabd>;
3251defm SABDL   : SIMDLongThreeVectorBHSabdl<0, 0b0111, "sabdl",
3252                                          int_aarch64_neon_sabd>;
3253defm SADDL   : SIMDLongThreeVectorBHS<   0, 0b0000, "saddl",
3254            BinOpFrag<(add (sext node:$LHS), (sext node:$RHS))>>;
3255defm SADDW   : SIMDWideThreeVectorBHS<   0, 0b0001, "saddw",
3256                 BinOpFrag<(add node:$LHS, (sext node:$RHS))>>;
3257defm SMLAL   : SIMDLongThreeVectorTiedBHS<0, 0b1000, "smlal",
3258    TriOpFrag<(add node:$LHS, (int_aarch64_neon_smull node:$MHS, node:$RHS))>>;
3259defm SMLSL   : SIMDLongThreeVectorTiedBHS<0, 0b1010, "smlsl",
3260    TriOpFrag<(sub node:$LHS, (int_aarch64_neon_smull node:$MHS, node:$RHS))>>;
3261defm SMULL   : SIMDLongThreeVectorBHS<0, 0b1100, "smull", int_aarch64_neon_smull>;
3262defm SQDMLAL : SIMDLongThreeVectorSQDMLXTiedHS<0, 0b1001, "sqdmlal",
3263                                               int_aarch64_neon_sqadd>;
3264defm SQDMLSL : SIMDLongThreeVectorSQDMLXTiedHS<0, 0b1011, "sqdmlsl",
3265                                               int_aarch64_neon_sqsub>;
3266defm SQDMULL : SIMDLongThreeVectorHS<0, 0b1101, "sqdmull",
3267                                     int_aarch64_neon_sqdmull>;
3268defm SSUBL   : SIMDLongThreeVectorBHS<0, 0b0010, "ssubl",
3269                 BinOpFrag<(sub (sext node:$LHS), (sext node:$RHS))>>;
3270defm SSUBW   : SIMDWideThreeVectorBHS<0, 0b0011, "ssubw",
3271                 BinOpFrag<(sub node:$LHS, (sext node:$RHS))>>;
3272defm UABAL   : SIMDLongThreeVectorTiedBHSabal<1, 0b0101, "uabal",
3273                                              int_aarch64_neon_uabd>;
3274defm UABDL   : SIMDLongThreeVectorBHSabdl<1, 0b0111, "uabdl",
3275                                          int_aarch64_neon_uabd>;
3276defm UADDL   : SIMDLongThreeVectorBHS<1, 0b0000, "uaddl",
3277                 BinOpFrag<(add (zext node:$LHS), (zext node:$RHS))>>;
3278defm UADDW   : SIMDWideThreeVectorBHS<1, 0b0001, "uaddw",
3279                 BinOpFrag<(add node:$LHS, (zext node:$RHS))>>;
3280defm UMLAL   : SIMDLongThreeVectorTiedBHS<1, 0b1000, "umlal",
3281    TriOpFrag<(add node:$LHS, (int_aarch64_neon_umull node:$MHS, node:$RHS))>>;
3282defm UMLSL   : SIMDLongThreeVectorTiedBHS<1, 0b1010, "umlsl",
3283    TriOpFrag<(sub node:$LHS, (int_aarch64_neon_umull node:$MHS, node:$RHS))>>;
3284defm UMULL   : SIMDLongThreeVectorBHS<1, 0b1100, "umull", int_aarch64_neon_umull>;
3285defm USUBL   : SIMDLongThreeVectorBHS<1, 0b0010, "usubl",
3286                 BinOpFrag<(sub (zext node:$LHS), (zext node:$RHS))>>;
3287defm USUBW   : SIMDWideThreeVectorBHS<   1, 0b0011, "usubw",
3288                 BinOpFrag<(sub node:$LHS, (zext node:$RHS))>>;
3289
3290// Additional patterns for SMULL and UMULL
3291multiclass Neon_mul_widen_patterns<SDPatternOperator opnode,
3292  Instruction INST8B, Instruction INST4H, Instruction INST2S> {
3293  def : Pat<(v8i16 (opnode (v8i8 V64:$Rn), (v8i8 V64:$Rm))),
3294            (INST8B V64:$Rn, V64:$Rm)>;
3295  def : Pat<(v4i32 (opnode (v4i16 V64:$Rn), (v4i16 V64:$Rm))),
3296            (INST4H V64:$Rn, V64:$Rm)>;
3297  def : Pat<(v2i64 (opnode (v2i32 V64:$Rn), (v2i32 V64:$Rm))),
3298            (INST2S V64:$Rn, V64:$Rm)>;
3299}
3300
3301defm : Neon_mul_widen_patterns<AArch64smull, SMULLv8i8_v8i16,
3302  SMULLv4i16_v4i32, SMULLv2i32_v2i64>;
3303defm : Neon_mul_widen_patterns<AArch64umull, UMULLv8i8_v8i16,
3304  UMULLv4i16_v4i32, UMULLv2i32_v2i64>;
3305
3306// Additional patterns for SMLAL/SMLSL and UMLAL/UMLSL
3307multiclass Neon_mulacc_widen_patterns<SDPatternOperator opnode,
3308  Instruction INST8B, Instruction INST4H, Instruction INST2S> {
3309  def : Pat<(v8i16 (opnode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm))),
3310            (INST8B V128:$Rd, V64:$Rn, V64:$Rm)>;
3311  def : Pat<(v4i32 (opnode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm))),
3312            (INST4H V128:$Rd, V64:$Rn, V64:$Rm)>;
3313  def : Pat<(v2i64 (opnode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm))),
3314            (INST2S  V128:$Rd, V64:$Rn, V64:$Rm)>;
3315}
3316
3317defm : Neon_mulacc_widen_patterns<
3318  TriOpFrag<(add node:$LHS, (AArch64smull node:$MHS, node:$RHS))>,
3319  SMLALv8i8_v8i16, SMLALv4i16_v4i32, SMLALv2i32_v2i64>;
3320defm : Neon_mulacc_widen_patterns<
3321  TriOpFrag<(add node:$LHS, (AArch64umull node:$MHS, node:$RHS))>,
3322  UMLALv8i8_v8i16, UMLALv4i16_v4i32, UMLALv2i32_v2i64>;
3323defm : Neon_mulacc_widen_patterns<
3324  TriOpFrag<(sub node:$LHS, (AArch64smull node:$MHS, node:$RHS))>,
3325  SMLSLv8i8_v8i16, SMLSLv4i16_v4i32, SMLSLv2i32_v2i64>;
3326defm : Neon_mulacc_widen_patterns<
3327  TriOpFrag<(sub node:$LHS, (AArch64umull node:$MHS, node:$RHS))>,
3328  UMLSLv8i8_v8i16, UMLSLv4i16_v4i32, UMLSLv2i32_v2i64>;
3329
3330// Patterns for 64-bit pmull
3331def : Pat<(int_aarch64_neon_pmull64 V64:$Rn, V64:$Rm),
3332          (PMULLv1i64 V64:$Rn, V64:$Rm)>;
3333def : Pat<(int_aarch64_neon_pmull64 (vector_extract (v2i64 V128:$Rn), (i64 1)),
3334                                  (vector_extract (v2i64 V128:$Rm), (i64 1))),
3335          (PMULLv2i64 V128:$Rn, V128:$Rm)>;
3336
3337// CodeGen patterns for addhn and subhn instructions, which can actually be
3338// written in LLVM IR without too much difficulty.
3339
3340// ADDHN
3341def : Pat<(v8i8 (trunc (v8i16 (AArch64vlshr (add V128:$Rn, V128:$Rm), (i32 8))))),
3342          (ADDHNv8i16_v8i8 V128:$Rn, V128:$Rm)>;
3343def : Pat<(v4i16 (trunc (v4i32 (AArch64vlshr (add V128:$Rn, V128:$Rm),
3344                                           (i32 16))))),
3345          (ADDHNv4i32_v4i16 V128:$Rn, V128:$Rm)>;
3346def : Pat<(v2i32 (trunc (v2i64 (AArch64vlshr (add V128:$Rn, V128:$Rm),
3347                                           (i32 32))))),
3348          (ADDHNv2i64_v2i32 V128:$Rn, V128:$Rm)>;
3349def : Pat<(concat_vectors (v8i8 V64:$Rd),
3350                          (trunc (v8i16 (AArch64vlshr (add V128:$Rn, V128:$Rm),
3351                                                    (i32 8))))),
3352          (ADDHNv8i16_v16i8 (SUBREG_TO_REG (i32 0), V64:$Rd, dsub),
3353                            V128:$Rn, V128:$Rm)>;
3354def : Pat<(concat_vectors (v4i16 V64:$Rd),
3355                          (trunc (v4i32 (AArch64vlshr (add V128:$Rn, V128:$Rm),
3356                                                    (i32 16))))),
3357          (ADDHNv4i32_v8i16 (SUBREG_TO_REG (i32 0), V64:$Rd, dsub),
3358                            V128:$Rn, V128:$Rm)>;
3359def : Pat<(concat_vectors (v2i32 V64:$Rd),
3360                          (trunc (v2i64 (AArch64vlshr (add V128:$Rn, V128:$Rm),
3361                                                    (i32 32))))),
3362          (ADDHNv2i64_v4i32 (SUBREG_TO_REG (i32 0), V64:$Rd, dsub),
3363                            V128:$Rn, V128:$Rm)>;
3364
3365// SUBHN
3366def : Pat<(v8i8 (trunc (v8i16 (AArch64vlshr (sub V128:$Rn, V128:$Rm), (i32 8))))),
3367          (SUBHNv8i16_v8i8 V128:$Rn, V128:$Rm)>;
3368def : Pat<(v4i16 (trunc (v4i32 (AArch64vlshr (sub V128:$Rn, V128:$Rm),
3369                                           (i32 16))))),
3370          (SUBHNv4i32_v4i16 V128:$Rn, V128:$Rm)>;
3371def : Pat<(v2i32 (trunc (v2i64 (AArch64vlshr (sub V128:$Rn, V128:$Rm),
3372                                           (i32 32))))),
3373          (SUBHNv2i64_v2i32 V128:$Rn, V128:$Rm)>;
3374def : Pat<(concat_vectors (v8i8 V64:$Rd),
3375                          (trunc (v8i16 (AArch64vlshr (sub V128:$Rn, V128:$Rm),
3376                                                    (i32 8))))),
3377          (SUBHNv8i16_v16i8 (SUBREG_TO_REG (i32 0), V64:$Rd, dsub),
3378                            V128:$Rn, V128:$Rm)>;
3379def : Pat<(concat_vectors (v4i16 V64:$Rd),
3380                          (trunc (v4i32 (AArch64vlshr (sub V128:$Rn, V128:$Rm),
3381                                                    (i32 16))))),
3382          (SUBHNv4i32_v8i16 (SUBREG_TO_REG (i32 0), V64:$Rd, dsub),
3383                            V128:$Rn, V128:$Rm)>;
3384def : Pat<(concat_vectors (v2i32 V64:$Rd),
3385                          (trunc (v2i64 (AArch64vlshr (sub V128:$Rn, V128:$Rm),
3386                                                    (i32 32))))),
3387          (SUBHNv2i64_v4i32 (SUBREG_TO_REG (i32 0), V64:$Rd, dsub),
3388                            V128:$Rn, V128:$Rm)>;
3389
3390//----------------------------------------------------------------------------
3391// AdvSIMD bitwise extract from vector instruction.
3392//----------------------------------------------------------------------------
3393
3394defm EXT : SIMDBitwiseExtract<"ext">;
3395
3396def : Pat<(v4i16 (AArch64ext V64:$Rn, V64:$Rm, (i32 imm:$imm))),
3397          (EXTv8i8 V64:$Rn, V64:$Rm, imm:$imm)>;
3398def : Pat<(v8i16 (AArch64ext V128:$Rn, V128:$Rm, (i32 imm:$imm))),
3399          (EXTv16i8 V128:$Rn, V128:$Rm, imm:$imm)>;
3400def : Pat<(v2i32 (AArch64ext V64:$Rn, V64:$Rm, (i32 imm:$imm))),
3401          (EXTv8i8 V64:$Rn, V64:$Rm, imm:$imm)>;
3402def : Pat<(v2f32 (AArch64ext V64:$Rn, V64:$Rm, (i32 imm:$imm))),
3403          (EXTv8i8 V64:$Rn, V64:$Rm, imm:$imm)>;
3404def : Pat<(v4i32 (AArch64ext V128:$Rn, V128:$Rm, (i32 imm:$imm))),
3405          (EXTv16i8 V128:$Rn, V128:$Rm, imm:$imm)>;
3406def : Pat<(v4f32 (AArch64ext V128:$Rn, V128:$Rm, (i32 imm:$imm))),
3407          (EXTv16i8 V128:$Rn, V128:$Rm, imm:$imm)>;
3408def : Pat<(v2i64 (AArch64ext V128:$Rn, V128:$Rm, (i32 imm:$imm))),
3409          (EXTv16i8 V128:$Rn, V128:$Rm, imm:$imm)>;
3410def : Pat<(v2f64 (AArch64ext V128:$Rn, V128:$Rm, (i32 imm:$imm))),
3411          (EXTv16i8 V128:$Rn, V128:$Rm, imm:$imm)>;
3412def : Pat<(v4f16 (AArch64ext V64:$Rn, V64:$Rm, (i32 imm:$imm))),
3413          (EXTv8i8 V64:$Rn, V64:$Rm, imm:$imm)>;
3414def : Pat<(v8f16 (AArch64ext V128:$Rn, V128:$Rm, (i32 imm:$imm))),
3415          (EXTv16i8 V128:$Rn, V128:$Rm, imm:$imm)>;
3416
3417// We use EXT to handle extract_subvector to copy the upper 64-bits of a
3418// 128-bit vector.
3419def : Pat<(v8i8  (extract_subvector V128:$Rn, (i64 8))),
3420          (EXTRACT_SUBREG (EXTv16i8 V128:$Rn, V128:$Rn, 8), dsub)>;
3421def : Pat<(v4i16 (extract_subvector V128:$Rn, (i64 4))),
3422          (EXTRACT_SUBREG (EXTv16i8 V128:$Rn, V128:$Rn, 8), dsub)>;
3423def : Pat<(v2i32 (extract_subvector V128:$Rn, (i64 2))),
3424          (EXTRACT_SUBREG (EXTv16i8 V128:$Rn, V128:$Rn, 8), dsub)>;
3425def : Pat<(v1i64 (extract_subvector V128:$Rn, (i64 1))),
3426          (EXTRACT_SUBREG (EXTv16i8 V128:$Rn, V128:$Rn, 8), dsub)>;
3427def : Pat<(v4f16 (extract_subvector V128:$Rn, (i64 4))),
3428          (EXTRACT_SUBREG (EXTv16i8 V128:$Rn, V128:$Rn, 8), dsub)>;
3429def : Pat<(v2f32 (extract_subvector V128:$Rn, (i64 2))),
3430          (EXTRACT_SUBREG (EXTv16i8 V128:$Rn, V128:$Rn, 8), dsub)>;
3431def : Pat<(v1f64 (extract_subvector V128:$Rn, (i64 1))),
3432          (EXTRACT_SUBREG (EXTv16i8 V128:$Rn, V128:$Rn, 8), dsub)>;
3433
3434
3435//----------------------------------------------------------------------------
3436// AdvSIMD zip vector
3437//----------------------------------------------------------------------------
3438
3439defm TRN1 : SIMDZipVector<0b010, "trn1", AArch64trn1>;
3440defm TRN2 : SIMDZipVector<0b110, "trn2", AArch64trn2>;
3441defm UZP1 : SIMDZipVector<0b001, "uzp1", AArch64uzp1>;
3442defm UZP2 : SIMDZipVector<0b101, "uzp2", AArch64uzp2>;
3443defm ZIP1 : SIMDZipVector<0b011, "zip1", AArch64zip1>;
3444defm ZIP2 : SIMDZipVector<0b111, "zip2", AArch64zip2>;
3445
3446//----------------------------------------------------------------------------
3447// AdvSIMD TBL/TBX instructions
3448//----------------------------------------------------------------------------
3449
3450defm TBL : SIMDTableLookup<    0, "tbl">;
3451defm TBX : SIMDTableLookupTied<1, "tbx">;
3452
3453def : Pat<(v8i8 (int_aarch64_neon_tbl1 (v16i8 VecListOne128:$Rn), (v8i8 V64:$Ri))),
3454          (TBLv8i8One VecListOne128:$Rn, V64:$Ri)>;
3455def : Pat<(v16i8 (int_aarch64_neon_tbl1 (v16i8 V128:$Ri), (v16i8 V128:$Rn))),
3456          (TBLv16i8One V128:$Ri, V128:$Rn)>;
3457
3458def : Pat<(v8i8 (int_aarch64_neon_tbx1 (v8i8 V64:$Rd),
3459                  (v16i8 VecListOne128:$Rn), (v8i8 V64:$Ri))),
3460          (TBXv8i8One V64:$Rd, VecListOne128:$Rn, V64:$Ri)>;
3461def : Pat<(v16i8 (int_aarch64_neon_tbx1 (v16i8 V128:$Rd),
3462                   (v16i8 V128:$Ri), (v16i8 V128:$Rn))),
3463          (TBXv16i8One V128:$Rd, V128:$Ri, V128:$Rn)>;
3464
3465
3466//----------------------------------------------------------------------------
3467// AdvSIMD scalar CPY instruction
3468//----------------------------------------------------------------------------
3469
3470defm CPY : SIMDScalarCPY<"cpy">;
3471
3472//----------------------------------------------------------------------------
3473// AdvSIMD scalar pairwise instructions
3474//----------------------------------------------------------------------------
3475
3476defm ADDP    : SIMDPairwiseScalarD<0, 0b11011, "addp">;
3477defm FADDP   : SIMDPairwiseScalarSD<1, 0, 0b01101, "faddp">;
3478defm FMAXNMP : SIMDPairwiseScalarSD<1, 0, 0b01100, "fmaxnmp">;
3479defm FMAXP   : SIMDPairwiseScalarSD<1, 0, 0b01111, "fmaxp">;
3480defm FMINNMP : SIMDPairwiseScalarSD<1, 1, 0b01100, "fminnmp">;
3481defm FMINP   : SIMDPairwiseScalarSD<1, 1, 0b01111, "fminp">;
3482def : Pat<(v2i64 (AArch64saddv V128:$Rn)),
3483          (INSERT_SUBREG (v2i64 (IMPLICIT_DEF)), (ADDPv2i64p V128:$Rn), dsub)>;
3484def : Pat<(v2i64 (AArch64uaddv V128:$Rn)),
3485          (INSERT_SUBREG (v2i64 (IMPLICIT_DEF)), (ADDPv2i64p V128:$Rn), dsub)>;
3486def : Pat<(f32 (int_aarch64_neon_faddv (v2f32 V64:$Rn))),
3487          (FADDPv2i32p V64:$Rn)>;
3488def : Pat<(f32 (int_aarch64_neon_faddv (v4f32 V128:$Rn))),
3489          (FADDPv2i32p (EXTRACT_SUBREG (FADDPv4f32 V128:$Rn, V128:$Rn), dsub))>;
3490def : Pat<(f64 (int_aarch64_neon_faddv (v2f64 V128:$Rn))),
3491          (FADDPv2i64p V128:$Rn)>;
3492def : Pat<(f32 (int_aarch64_neon_fmaxnmv (v2f32 V64:$Rn))),
3493          (FMAXNMPv2i32p V64:$Rn)>;
3494def : Pat<(f64 (int_aarch64_neon_fmaxnmv (v2f64 V128:$Rn))),
3495          (FMAXNMPv2i64p V128:$Rn)>;
3496def : Pat<(f32 (int_aarch64_neon_fmaxv (v2f32 V64:$Rn))),
3497          (FMAXPv2i32p V64:$Rn)>;
3498def : Pat<(f64 (int_aarch64_neon_fmaxv (v2f64 V128:$Rn))),
3499          (FMAXPv2i64p V128:$Rn)>;
3500def : Pat<(f32 (int_aarch64_neon_fminnmv (v2f32 V64:$Rn))),
3501          (FMINNMPv2i32p V64:$Rn)>;
3502def : Pat<(f64 (int_aarch64_neon_fminnmv (v2f64 V128:$Rn))),
3503          (FMINNMPv2i64p V128:$Rn)>;
3504def : Pat<(f32 (int_aarch64_neon_fminv (v2f32 V64:$Rn))),
3505          (FMINPv2i32p V64:$Rn)>;
3506def : Pat<(f64 (int_aarch64_neon_fminv (v2f64 V128:$Rn))),
3507          (FMINPv2i64p V128:$Rn)>;
3508
3509//----------------------------------------------------------------------------
3510// AdvSIMD INS/DUP instructions
3511//----------------------------------------------------------------------------
3512
3513def DUPv8i8gpr  : SIMDDupFromMain<0, {?,?,?,?,1}, ".8b", v8i8, V64, GPR32>;
3514def DUPv16i8gpr : SIMDDupFromMain<1, {?,?,?,?,1}, ".16b", v16i8, V128, GPR32>;
3515def DUPv4i16gpr : SIMDDupFromMain<0, {?,?,?,1,0}, ".4h", v4i16, V64, GPR32>;
3516def DUPv8i16gpr : SIMDDupFromMain<1, {?,?,?,1,0}, ".8h", v8i16, V128, GPR32>;
3517def DUPv2i32gpr : SIMDDupFromMain<0, {?,?,1,0,0}, ".2s", v2i32, V64, GPR32>;
3518def DUPv4i32gpr : SIMDDupFromMain<1, {?,?,1,0,0}, ".4s", v4i32, V128, GPR32>;
3519def DUPv2i64gpr : SIMDDupFromMain<1, {?,1,0,0,0}, ".2d", v2i64, V128, GPR64>;
3520
3521def DUPv2i64lane : SIMDDup64FromElement;
3522def DUPv2i32lane : SIMDDup32FromElement<0, ".2s", v2i32, V64>;
3523def DUPv4i32lane : SIMDDup32FromElement<1, ".4s", v4i32, V128>;
3524def DUPv4i16lane : SIMDDup16FromElement<0, ".4h", v4i16, V64>;
3525def DUPv8i16lane : SIMDDup16FromElement<1, ".8h", v8i16, V128>;
3526def DUPv8i8lane  : SIMDDup8FromElement <0, ".8b", v8i8, V64>;
3527def DUPv16i8lane : SIMDDup8FromElement <1, ".16b", v16i8, V128>;
3528
3529def : Pat<(v2f32 (AArch64dup (f32 FPR32:$Rn))),
3530          (v2f32 (DUPv2i32lane
3531            (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), FPR32:$Rn, ssub),
3532            (i64 0)))>;
3533def : Pat<(v4f32 (AArch64dup (f32 FPR32:$Rn))),
3534          (v4f32 (DUPv4i32lane
3535            (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), FPR32:$Rn, ssub),
3536            (i64 0)))>;
3537def : Pat<(v2f64 (AArch64dup (f64 FPR64:$Rn))),
3538          (v2f64 (DUPv2i64lane
3539            (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), FPR64:$Rn, dsub),
3540            (i64 0)))>;
3541def : Pat<(v4f16 (AArch64dup (f16 FPR16:$Rn))),
3542          (v4f16 (DUPv4i16lane
3543            (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)), FPR16:$Rn, hsub),
3544            (i64 0)))>;
3545def : Pat<(v8f16 (AArch64dup (f16 FPR16:$Rn))),
3546          (v8f16 (DUPv8i16lane
3547            (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)), FPR16:$Rn, hsub),
3548            (i64 0)))>;
3549
3550def : Pat<(v4f16 (AArch64duplane16 (v8f16 V128:$Rn), VectorIndexH:$imm)),
3551          (DUPv4i16lane V128:$Rn, VectorIndexH:$imm)>;
3552def : Pat<(v8f16 (AArch64duplane16 (v8f16 V128:$Rn), VectorIndexH:$imm)),
3553          (DUPv8i16lane V128:$Rn, VectorIndexH:$imm)>;
3554
3555def : Pat<(v2f32 (AArch64duplane32 (v4f32 V128:$Rn), VectorIndexS:$imm)),
3556          (DUPv2i32lane V128:$Rn, VectorIndexS:$imm)>;
3557def : Pat<(v4f32 (AArch64duplane32 (v4f32 V128:$Rn), VectorIndexS:$imm)),
3558         (DUPv4i32lane V128:$Rn, VectorIndexS:$imm)>;
3559def : Pat<(v2f64 (AArch64duplane64 (v2f64 V128:$Rn), VectorIndexD:$imm)),
3560          (DUPv2i64lane V128:$Rn, VectorIndexD:$imm)>;
3561
3562// If there's an (AArch64dup (vector_extract ...) ...), we can use a duplane
3563// instruction even if the types don't match: we just have to remap the lane
3564// carefully. N.b. this trick only applies to truncations.
3565def VecIndex_x2 : SDNodeXForm<imm, [{
3566  return CurDAG->getTargetConstant(2 * N->getZExtValue(), MVT::i64);
3567}]>;
3568def VecIndex_x4 : SDNodeXForm<imm, [{
3569  return CurDAG->getTargetConstant(4 * N->getZExtValue(), MVT::i64);
3570}]>;
3571def VecIndex_x8 : SDNodeXForm<imm, [{
3572  return CurDAG->getTargetConstant(8 * N->getZExtValue(), MVT::i64);
3573}]>;
3574
3575multiclass DUPWithTruncPats<ValueType ResVT, ValueType Src64VT,
3576                            ValueType Src128VT, ValueType ScalVT,
3577                            Instruction DUP, SDNodeXForm IdxXFORM> {
3578  def : Pat<(ResVT (AArch64dup (ScalVT (vector_extract (Src128VT V128:$Rn),
3579                                                     imm:$idx)))),
3580            (DUP V128:$Rn, (IdxXFORM imm:$idx))>;
3581
3582  def : Pat<(ResVT (AArch64dup (ScalVT (vector_extract (Src64VT V64:$Rn),
3583                                                     imm:$idx)))),
3584            (DUP (SUBREG_TO_REG (i64 0), V64:$Rn, dsub), (IdxXFORM imm:$idx))>;
3585}
3586
3587defm : DUPWithTruncPats<v8i8,   v4i16, v8i16, i32, DUPv8i8lane,  VecIndex_x2>;
3588defm : DUPWithTruncPats<v8i8,   v2i32, v4i32, i32, DUPv8i8lane,  VecIndex_x4>;
3589defm : DUPWithTruncPats<v4i16,  v2i32, v4i32, i32, DUPv4i16lane, VecIndex_x2>;
3590
3591defm : DUPWithTruncPats<v16i8,  v4i16, v8i16, i32, DUPv16i8lane, VecIndex_x2>;
3592defm : DUPWithTruncPats<v16i8,  v2i32, v4i32, i32, DUPv16i8lane, VecIndex_x4>;
3593defm : DUPWithTruncPats<v8i16,  v2i32, v4i32, i32, DUPv8i16lane, VecIndex_x2>;
3594
3595multiclass DUPWithTrunci64Pats<ValueType ResVT, Instruction DUP,
3596                               SDNodeXForm IdxXFORM> {
3597  def : Pat<(ResVT (AArch64dup (i32 (trunc (vector_extract (v2i64 V128:$Rn),
3598                                                         imm:$idx))))),
3599            (DUP V128:$Rn, (IdxXFORM imm:$idx))>;
3600
3601  def : Pat<(ResVT (AArch64dup (i32 (trunc (vector_extract (v1i64 V64:$Rn),
3602                                                         imm:$idx))))),
3603            (DUP (SUBREG_TO_REG (i64 0), V64:$Rn, dsub), (IdxXFORM imm:$idx))>;
3604}
3605
3606defm : DUPWithTrunci64Pats<v8i8,  DUPv8i8lane,   VecIndex_x8>;
3607defm : DUPWithTrunci64Pats<v4i16, DUPv4i16lane,  VecIndex_x4>;
3608defm : DUPWithTrunci64Pats<v2i32, DUPv2i32lane,  VecIndex_x2>;
3609
3610defm : DUPWithTrunci64Pats<v16i8, DUPv16i8lane, VecIndex_x8>;
3611defm : DUPWithTrunci64Pats<v8i16, DUPv8i16lane, VecIndex_x4>;
3612defm : DUPWithTrunci64Pats<v4i32, DUPv4i32lane, VecIndex_x2>;
3613
3614// SMOV and UMOV definitions, with some extra patterns for convenience
3615defm SMOV : SMov;
3616defm UMOV : UMov;
3617
3618def : Pat<(sext_inreg (vector_extract (v16i8 V128:$Rn), VectorIndexB:$idx), i8),
3619          (i32 (SMOVvi8to32 V128:$Rn, VectorIndexB:$idx))>;
3620def : Pat<(sext_inreg (vector_extract (v16i8 V128:$Rn), VectorIndexB:$idx), i8),
3621          (i64 (SMOVvi8to64 V128:$Rn, VectorIndexB:$idx))>;
3622def : Pat<(sext_inreg (vector_extract (v8i16 V128:$Rn), VectorIndexH:$idx),i16),
3623          (i32 (SMOVvi16to32 V128:$Rn, VectorIndexH:$idx))>;
3624def : Pat<(sext_inreg (vector_extract (v8i16 V128:$Rn), VectorIndexH:$idx),i16),
3625          (i64 (SMOVvi16to64 V128:$Rn, VectorIndexH:$idx))>;
3626def : Pat<(sext_inreg (vector_extract (v8i16 V128:$Rn), VectorIndexH:$idx),i16),
3627          (i32 (SMOVvi16to32 V128:$Rn, VectorIndexH:$idx))>;
3628def : Pat<(sext (i32 (vector_extract (v4i32 V128:$Rn), VectorIndexS:$idx))),
3629          (i64 (SMOVvi32to64 V128:$Rn, VectorIndexS:$idx))>;
3630
3631// Extracting i8 or i16 elements will have the zero-extend transformed to
3632// an 'and' mask by type legalization since neither i8 nor i16 are legal types
3633// for AArch64. Match these patterns here since UMOV already zeroes out the high
3634// bits of the destination register.
3635def : Pat<(and (vector_extract (v16i8 V128:$Rn), VectorIndexB:$idx),
3636               (i32 0xff)),
3637          (i32 (UMOVvi8 V128:$Rn, VectorIndexB:$idx))>;
3638def : Pat<(and (vector_extract (v8i16 V128:$Rn), VectorIndexH:$idx),
3639               (i32 0xffff)),
3640          (i32 (UMOVvi16 V128:$Rn, VectorIndexH:$idx))>;
3641
3642defm INS : SIMDIns;
3643
3644def : Pat<(v16i8 (scalar_to_vector GPR32:$Rn)),
3645          (SUBREG_TO_REG (i32 0),
3646                         (f32 (COPY_TO_REGCLASS GPR32:$Rn, FPR32)), ssub)>;
3647def : Pat<(v8i8 (scalar_to_vector GPR32:$Rn)),
3648          (SUBREG_TO_REG (i32 0),
3649                         (f32 (COPY_TO_REGCLASS GPR32:$Rn, FPR32)), ssub)>;
3650
3651def : Pat<(v8i16 (scalar_to_vector GPR32:$Rn)),
3652          (SUBREG_TO_REG (i32 0),
3653                         (f32 (COPY_TO_REGCLASS GPR32:$Rn, FPR32)), ssub)>;
3654def : Pat<(v4i16 (scalar_to_vector GPR32:$Rn)),
3655          (SUBREG_TO_REG (i32 0),
3656                         (f32 (COPY_TO_REGCLASS GPR32:$Rn, FPR32)), ssub)>;
3657
3658def : Pat<(v2i32 (scalar_to_vector (i32 FPR32:$Rn))),
3659            (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
3660                                  (i32 FPR32:$Rn), ssub))>;
3661def : Pat<(v4i32 (scalar_to_vector (i32 FPR32:$Rn))),
3662            (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
3663                                  (i32 FPR32:$Rn), ssub))>;
3664def : Pat<(v2i64 (scalar_to_vector (i64 FPR64:$Rn))),
3665            (v2i64 (INSERT_SUBREG (v2i64 (IMPLICIT_DEF)),
3666                                  (i64 FPR64:$Rn), dsub))>;
3667
3668def : Pat<(v4f32 (scalar_to_vector (f32 FPR32:$Rn))),
3669          (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), FPR32:$Rn, ssub)>;
3670def : Pat<(v2f32 (scalar_to_vector (f32 FPR32:$Rn))),
3671          (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), FPR32:$Rn, ssub)>;
3672def : Pat<(v2f64 (scalar_to_vector (f64 FPR64:$Rn))),
3673          (INSERT_SUBREG (v2f64 (IMPLICIT_DEF)), FPR64:$Rn, dsub)>;
3674
3675def : Pat<(v4f16 (vector_insert (v4f16 V64:$Rn),
3676            (f16 FPR16:$Rm), (i64 VectorIndexS:$imm))),
3677          (EXTRACT_SUBREG
3678            (INSvi16lane
3679              (v8f16 (INSERT_SUBREG (v8f16 (IMPLICIT_DEF)), V64:$Rn, dsub)),
3680              VectorIndexS:$imm,
3681              (v8f16 (INSERT_SUBREG (v8f16 (IMPLICIT_DEF)), FPR16:$Rm, hsub)),
3682              (i64 0)),
3683            dsub)>;
3684
3685def : Pat<(v8f16 (vector_insert (v8f16 V128:$Rn),
3686            (f16 FPR16:$Rm), (i64 VectorIndexH:$imm))),
3687          (INSvi16lane
3688            V128:$Rn, VectorIndexH:$imm,
3689            (v8f16 (INSERT_SUBREG (v8f16 (IMPLICIT_DEF)), FPR16:$Rm, hsub)),
3690            (i64 0))>;
3691
3692def : Pat<(v2f32 (vector_insert (v2f32 V64:$Rn),
3693            (f32 FPR32:$Rm), (i64 VectorIndexS:$imm))),
3694          (EXTRACT_SUBREG
3695            (INSvi32lane
3696              (v4f32 (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), V64:$Rn, dsub)),
3697              VectorIndexS:$imm,
3698              (v4f32 (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), FPR32:$Rm, ssub)),
3699              (i64 0)),
3700            dsub)>;
3701def : Pat<(v4f32 (vector_insert (v4f32 V128:$Rn),
3702            (f32 FPR32:$Rm), (i64 VectorIndexS:$imm))),
3703          (INSvi32lane
3704            V128:$Rn, VectorIndexS:$imm,
3705            (v4f32 (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), FPR32:$Rm, ssub)),
3706            (i64 0))>;
3707def : Pat<(v2f64 (vector_insert (v2f64 V128:$Rn),
3708            (f64 FPR64:$Rm), (i64 VectorIndexD:$imm))),
3709          (INSvi64lane
3710            V128:$Rn, VectorIndexD:$imm,
3711            (v2f64 (INSERT_SUBREG (v2f64 (IMPLICIT_DEF)), FPR64:$Rm, dsub)),
3712            (i64 0))>;
3713
3714// Copy an element at a constant index in one vector into a constant indexed
3715// element of another.
3716// FIXME refactor to a shared class/dev parameterized on vector type, vector
3717// index type and INS extension
3718def : Pat<(v16i8 (int_aarch64_neon_vcopy_lane
3719                   (v16i8 V128:$Vd), VectorIndexB:$idx, (v16i8 V128:$Vs),
3720                   VectorIndexB:$idx2)),
3721          (v16i8 (INSvi8lane
3722                   V128:$Vd, VectorIndexB:$idx, V128:$Vs, VectorIndexB:$idx2)
3723          )>;
3724def : Pat<(v8i16 (int_aarch64_neon_vcopy_lane
3725                   (v8i16 V128:$Vd), VectorIndexH:$idx, (v8i16 V128:$Vs),
3726                   VectorIndexH:$idx2)),
3727          (v8i16 (INSvi16lane
3728                   V128:$Vd, VectorIndexH:$idx, V128:$Vs, VectorIndexH:$idx2)
3729          )>;
3730def : Pat<(v4i32 (int_aarch64_neon_vcopy_lane
3731                   (v4i32 V128:$Vd), VectorIndexS:$idx, (v4i32 V128:$Vs),
3732                   VectorIndexS:$idx2)),
3733          (v4i32 (INSvi32lane
3734                   V128:$Vd, VectorIndexS:$idx, V128:$Vs, VectorIndexS:$idx2)
3735          )>;
3736def : Pat<(v2i64 (int_aarch64_neon_vcopy_lane
3737                   (v2i64 V128:$Vd), VectorIndexD:$idx, (v2i64 V128:$Vs),
3738                   VectorIndexD:$idx2)),
3739          (v2i64 (INSvi64lane
3740                   V128:$Vd, VectorIndexD:$idx, V128:$Vs, VectorIndexD:$idx2)
3741          )>;
3742
3743multiclass Neon_INS_elt_pattern<ValueType VT128, ValueType VT64,
3744                                ValueType VTScal, Instruction INS> {
3745  def : Pat<(VT128 (vector_insert V128:$src,
3746                        (VTScal (vector_extract (VT128 V128:$Rn), imm:$Immn)),
3747                        imm:$Immd)),
3748            (INS V128:$src, imm:$Immd, V128:$Rn, imm:$Immn)>;
3749
3750  def : Pat<(VT128 (vector_insert V128:$src,
3751                        (VTScal (vector_extract (VT64 V64:$Rn), imm:$Immn)),
3752                        imm:$Immd)),
3753            (INS V128:$src, imm:$Immd,
3754                 (SUBREG_TO_REG (i64 0), V64:$Rn, dsub), imm:$Immn)>;
3755
3756  def : Pat<(VT64 (vector_insert V64:$src,
3757                        (VTScal (vector_extract (VT128 V128:$Rn), imm:$Immn)),
3758                        imm:$Immd)),
3759            (EXTRACT_SUBREG (INS (SUBREG_TO_REG (i64 0), V64:$src, dsub),
3760                                 imm:$Immd, V128:$Rn, imm:$Immn),
3761                            dsub)>;
3762
3763  def : Pat<(VT64 (vector_insert V64:$src,
3764                        (VTScal (vector_extract (VT64 V64:$Rn), imm:$Immn)),
3765                        imm:$Immd)),
3766            (EXTRACT_SUBREG
3767                (INS (SUBREG_TO_REG (i64 0), V64:$src, dsub), imm:$Immd,
3768                     (SUBREG_TO_REG (i64 0), V64:$Rn, dsub), imm:$Immn),
3769                dsub)>;
3770}
3771
3772defm : Neon_INS_elt_pattern<v8f16, v4f16, f16, INSvi16lane>;
3773defm : Neon_INS_elt_pattern<v4f32, v2f32, f32, INSvi32lane>;
3774defm : Neon_INS_elt_pattern<v2f64, v1f64, f64, INSvi64lane>;
3775
3776
3777// Floating point vector extractions are codegen'd as either a sequence of
3778// subregister extractions, or a MOV (aka CPY here, alias for DUP) if
3779// the lane number is anything other than zero.
3780def : Pat<(vector_extract (v2f64 V128:$Rn), 0),
3781          (f64 (EXTRACT_SUBREG V128:$Rn, dsub))>;
3782def : Pat<(vector_extract (v4f32 V128:$Rn), 0),
3783          (f32 (EXTRACT_SUBREG V128:$Rn, ssub))>;
3784def : Pat<(vector_extract (v8f16 V128:$Rn), 0),
3785          (f16 (EXTRACT_SUBREG V128:$Rn, hsub))>;
3786
3787def : Pat<(vector_extract (v2f64 V128:$Rn), VectorIndexD:$idx),
3788          (f64 (CPYi64 V128:$Rn, VectorIndexD:$idx))>;
3789def : Pat<(vector_extract (v4f32 V128:$Rn), VectorIndexS:$idx),
3790          (f32 (CPYi32 V128:$Rn, VectorIndexS:$idx))>;
3791def : Pat<(vector_extract (v8f16 V128:$Rn), VectorIndexH:$idx),
3792          (f16 (CPYi16 V128:$Rn, VectorIndexH:$idx))>;
3793
3794// All concat_vectors operations are canonicalised to act on i64 vectors for
3795// AArch64. In the general case we need an instruction, which had just as well be
3796// INS.
3797class ConcatPat<ValueType DstTy, ValueType SrcTy>
3798  : Pat<(DstTy (concat_vectors (SrcTy V64:$Rd), V64:$Rn)),
3799        (INSvi64lane (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), 1,
3800                     (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rn, dsub), 0)>;
3801
3802def : ConcatPat<v2i64, v1i64>;
3803def : ConcatPat<v2f64, v1f64>;
3804def : ConcatPat<v4i32, v2i32>;
3805def : ConcatPat<v4f32, v2f32>;
3806def : ConcatPat<v8i16, v4i16>;
3807def : ConcatPat<v8f16, v4f16>;
3808def : ConcatPat<v16i8, v8i8>;
3809
3810// If the high lanes are undef, though, we can just ignore them:
3811class ConcatUndefPat<ValueType DstTy, ValueType SrcTy>
3812  : Pat<(DstTy (concat_vectors (SrcTy V64:$Rn), undef)),
3813        (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rn, dsub)>;
3814
3815def : ConcatUndefPat<v2i64, v1i64>;
3816def : ConcatUndefPat<v2f64, v1f64>;
3817def : ConcatUndefPat<v4i32, v2i32>;
3818def : ConcatUndefPat<v4f32, v2f32>;
3819def : ConcatUndefPat<v8i16, v4i16>;
3820def : ConcatUndefPat<v16i8, v8i8>;
3821
3822//----------------------------------------------------------------------------
3823// AdvSIMD across lanes instructions
3824//----------------------------------------------------------------------------
3825
3826defm ADDV    : SIMDAcrossLanesBHS<0, 0b11011, "addv">;
3827defm SMAXV   : SIMDAcrossLanesBHS<0, 0b01010, "smaxv">;
3828defm SMINV   : SIMDAcrossLanesBHS<0, 0b11010, "sminv">;
3829defm UMAXV   : SIMDAcrossLanesBHS<1, 0b01010, "umaxv">;
3830defm UMINV   : SIMDAcrossLanesBHS<1, 0b11010, "uminv">;
3831defm SADDLV  : SIMDAcrossLanesHSD<0, 0b00011, "saddlv">;
3832defm UADDLV  : SIMDAcrossLanesHSD<1, 0b00011, "uaddlv">;
3833defm FMAXNMV : SIMDAcrossLanesS<0b01100, 0, "fmaxnmv", int_aarch64_neon_fmaxnmv>;
3834defm FMAXV   : SIMDAcrossLanesS<0b01111, 0, "fmaxv", int_aarch64_neon_fmaxv>;
3835defm FMINNMV : SIMDAcrossLanesS<0b01100, 1, "fminnmv", int_aarch64_neon_fminnmv>;
3836defm FMINV   : SIMDAcrossLanesS<0b01111, 1, "fminv", int_aarch64_neon_fminv>;
3837
3838// Patterns for across-vector intrinsics, that have a node equivalent, that
3839// returns a vector (with only the low lane defined) instead of a scalar.
3840// In effect, opNode is the same as (scalar_to_vector (IntNode)).
3841multiclass SIMDAcrossLanesIntrinsic<string baseOpc,
3842                                    SDPatternOperator opNode> {
3843// If a lane instruction caught the vector_extract around opNode, we can
3844// directly match the latter to the instruction.
3845def : Pat<(v8i8 (opNode V64:$Rn)),
3846          (INSERT_SUBREG (v8i8 (IMPLICIT_DEF)),
3847           (!cast<Instruction>(!strconcat(baseOpc, "v8i8v")) V64:$Rn), bsub)>;
3848def : Pat<(v16i8 (opNode V128:$Rn)),
3849          (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
3850           (!cast<Instruction>(!strconcat(baseOpc, "v16i8v")) V128:$Rn), bsub)>;
3851def : Pat<(v4i16 (opNode V64:$Rn)),
3852          (INSERT_SUBREG (v4i16 (IMPLICIT_DEF)),
3853           (!cast<Instruction>(!strconcat(baseOpc, "v4i16v")) V64:$Rn), hsub)>;
3854def : Pat<(v8i16 (opNode V128:$Rn)),
3855          (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)),
3856           (!cast<Instruction>(!strconcat(baseOpc, "v8i16v")) V128:$Rn), hsub)>;
3857def : Pat<(v4i32 (opNode V128:$Rn)),
3858          (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
3859           (!cast<Instruction>(!strconcat(baseOpc, "v4i32v")) V128:$Rn), ssub)>;
3860
3861
3862// If none did, fallback to the explicit patterns, consuming the vector_extract.
3863def : Pat<(i32 (vector_extract (insert_subvector undef, (v8i8 (opNode V64:$Rn)),
3864            (i32 0)), (i64 0))),
3865          (EXTRACT_SUBREG (INSERT_SUBREG (v8i8 (IMPLICIT_DEF)),
3866            (!cast<Instruction>(!strconcat(baseOpc, "v8i8v")) V64:$Rn),
3867            bsub), ssub)>;
3868def : Pat<(i32 (vector_extract (v16i8 (opNode V128:$Rn)), (i64 0))),
3869          (EXTRACT_SUBREG (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
3870            (!cast<Instruction>(!strconcat(baseOpc, "v16i8v")) V128:$Rn),
3871            bsub), ssub)>;
3872def : Pat<(i32 (vector_extract (insert_subvector undef,
3873            (v4i16 (opNode V64:$Rn)), (i32 0)), (i64 0))),
3874          (EXTRACT_SUBREG (INSERT_SUBREG (v4i16 (IMPLICIT_DEF)),
3875            (!cast<Instruction>(!strconcat(baseOpc, "v4i16v")) V64:$Rn),
3876            hsub), ssub)>;
3877def : Pat<(i32 (vector_extract (v8i16 (opNode V128:$Rn)), (i64 0))),
3878          (EXTRACT_SUBREG (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)),
3879            (!cast<Instruction>(!strconcat(baseOpc, "v8i16v")) V128:$Rn),
3880            hsub), ssub)>;
3881def : Pat<(i32 (vector_extract (v4i32 (opNode V128:$Rn)), (i64 0))),
3882          (EXTRACT_SUBREG (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
3883            (!cast<Instruction>(!strconcat(baseOpc, "v4i32v")) V128:$Rn),
3884            ssub), ssub)>;
3885
3886}
3887
3888multiclass SIMDAcrossLanesSignedIntrinsic<string baseOpc,
3889                                          SDPatternOperator opNode>
3890    : SIMDAcrossLanesIntrinsic<baseOpc, opNode> {
3891// If there is a sign extension after this intrinsic, consume it as smov already
3892// performed it
3893def : Pat<(i32 (sext_inreg (i32 (vector_extract (insert_subvector undef,
3894            (opNode (v8i8 V64:$Rn)), (i32 0)), (i64 0))), i8)),
3895          (i32 (SMOVvi8to32
3896            (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
3897              (!cast<Instruction>(!strconcat(baseOpc, "v8i8v")) V64:$Rn), bsub),
3898            (i64 0)))>;
3899def : Pat<(i32 (sext_inreg (i32 (vector_extract
3900            (opNode (v16i8 V128:$Rn)), (i64 0))), i8)),
3901          (i32 (SMOVvi8to32
3902            (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
3903             (!cast<Instruction>(!strconcat(baseOpc, "v16i8v")) V128:$Rn), bsub),
3904            (i64 0)))>;
3905def : Pat<(i32 (sext_inreg (i32 (vector_extract (insert_subvector undef,
3906            (opNode (v4i16 V64:$Rn)), (i32 0)), (i64 0))), i16)),
3907          (i32 (SMOVvi16to32
3908           (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
3909            (!cast<Instruction>(!strconcat(baseOpc, "v4i16v")) V64:$Rn), hsub),
3910           (i64 0)))>;
3911def : Pat<(i32 (sext_inreg (i32 (vector_extract
3912            (opNode (v8i16 V128:$Rn)), (i64 0))), i16)),
3913          (i32 (SMOVvi16to32
3914            (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
3915             (!cast<Instruction>(!strconcat(baseOpc, "v8i16v")) V128:$Rn), hsub),
3916            (i64 0)))>;
3917}
3918
3919multiclass SIMDAcrossLanesUnsignedIntrinsic<string baseOpc,
3920                                            SDPatternOperator opNode>
3921    : SIMDAcrossLanesIntrinsic<baseOpc, opNode> {
3922// If there is a masking operation keeping only what has been actually
3923// generated, consume it.
3924def : Pat<(i32 (and (i32 (vector_extract (insert_subvector undef,
3925            (opNode (v8i8 V64:$Rn)), (i32 0)), (i64 0))), maski8_or_more)),
3926      (i32 (EXTRACT_SUBREG
3927        (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
3928          (!cast<Instruction>(!strconcat(baseOpc, "v8i8v")) V64:$Rn), bsub),
3929        ssub))>;
3930def : Pat<(i32 (and (i32 (vector_extract (opNode (v16i8 V128:$Rn)), (i64 0))),
3931            maski8_or_more)),
3932        (i32 (EXTRACT_SUBREG
3933          (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
3934            (!cast<Instruction>(!strconcat(baseOpc, "v16i8v")) V128:$Rn), bsub),
3935          ssub))>;
3936def : Pat<(i32 (and (i32 (vector_extract (insert_subvector undef,
3937            (opNode (v4i16 V64:$Rn)), (i32 0)), (i64 0))), maski16_or_more)),
3938          (i32 (EXTRACT_SUBREG
3939            (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
3940              (!cast<Instruction>(!strconcat(baseOpc, "v4i16v")) V64:$Rn), hsub),
3941            ssub))>;
3942def : Pat<(i32 (and (i32 (vector_extract (opNode (v8i16 V128:$Rn)), (i64 0))),
3943            maski16_or_more)),
3944        (i32 (EXTRACT_SUBREG
3945          (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
3946            (!cast<Instruction>(!strconcat(baseOpc, "v8i16v")) V128:$Rn), hsub),
3947          ssub))>;
3948}
3949
3950defm : SIMDAcrossLanesSignedIntrinsic<"ADDV",  AArch64saddv>;
3951// vaddv_[su]32 is special; -> ADDP Vd.2S,Vn.2S,Vm.2S; return Vd.s[0];Vn==Vm
3952def : Pat<(v2i32 (AArch64saddv (v2i32 V64:$Rn))),
3953          (ADDPv2i32 V64:$Rn, V64:$Rn)>;
3954
3955defm : SIMDAcrossLanesUnsignedIntrinsic<"ADDV", AArch64uaddv>;
3956// vaddv_[su]32 is special; -> ADDP Vd.2S,Vn.2S,Vm.2S; return Vd.s[0];Vn==Vm
3957def : Pat<(v2i32 (AArch64uaddv (v2i32 V64:$Rn))),
3958          (ADDPv2i32 V64:$Rn, V64:$Rn)>;
3959
3960defm : SIMDAcrossLanesSignedIntrinsic<"SMAXV", AArch64smaxv>;
3961def : Pat<(v2i32 (AArch64smaxv (v2i32 V64:$Rn))),
3962          (SMAXPv2i32 V64:$Rn, V64:$Rn)>;
3963
3964defm : SIMDAcrossLanesSignedIntrinsic<"SMINV", AArch64sminv>;
3965def : Pat<(v2i32 (AArch64sminv (v2i32 V64:$Rn))),
3966          (SMINPv2i32 V64:$Rn, V64:$Rn)>;
3967
3968defm : SIMDAcrossLanesUnsignedIntrinsic<"UMAXV", AArch64umaxv>;
3969def : Pat<(v2i32 (AArch64umaxv (v2i32 V64:$Rn))),
3970          (UMAXPv2i32 V64:$Rn, V64:$Rn)>;
3971
3972defm : SIMDAcrossLanesUnsignedIntrinsic<"UMINV", AArch64uminv>;
3973def : Pat<(v2i32 (AArch64uminv (v2i32 V64:$Rn))),
3974          (UMINPv2i32 V64:$Rn, V64:$Rn)>;
3975
3976multiclass SIMDAcrossLanesSignedLongIntrinsic<string baseOpc, Intrinsic intOp> {
3977  def : Pat<(i32 (intOp (v8i8 V64:$Rn))),
3978        (i32 (SMOVvi16to32
3979          (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
3980            (!cast<Instruction>(!strconcat(baseOpc, "v8i8v")) V64:$Rn), hsub),
3981          (i64 0)))>;
3982def : Pat<(i32 (intOp (v16i8 V128:$Rn))),
3983        (i32 (SMOVvi16to32
3984          (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
3985           (!cast<Instruction>(!strconcat(baseOpc, "v16i8v")) V128:$Rn), hsub),
3986          (i64 0)))>;
3987
3988def : Pat<(i32 (intOp (v4i16 V64:$Rn))),
3989          (i32 (EXTRACT_SUBREG
3990           (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
3991            (!cast<Instruction>(!strconcat(baseOpc, "v4i16v")) V64:$Rn), ssub),
3992           ssub))>;
3993def : Pat<(i32 (intOp (v8i16 V128:$Rn))),
3994        (i32 (EXTRACT_SUBREG
3995          (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
3996           (!cast<Instruction>(!strconcat(baseOpc, "v8i16v")) V128:$Rn), ssub),
3997          ssub))>;
3998
3999def : Pat<(i64 (intOp (v4i32 V128:$Rn))),
4000        (i64 (EXTRACT_SUBREG
4001          (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
4002           (!cast<Instruction>(!strconcat(baseOpc, "v4i32v")) V128:$Rn), dsub),
4003          dsub))>;
4004}
4005
4006multiclass SIMDAcrossLanesUnsignedLongIntrinsic<string baseOpc,
4007                                                Intrinsic intOp> {
4008  def : Pat<(i32 (intOp (v8i8 V64:$Rn))),
4009        (i32 (EXTRACT_SUBREG
4010          (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
4011            (!cast<Instruction>(!strconcat(baseOpc, "v8i8v")) V64:$Rn), hsub),
4012          ssub))>;
4013def : Pat<(i32 (intOp (v16i8 V128:$Rn))),
4014        (i32 (EXTRACT_SUBREG
4015          (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
4016            (!cast<Instruction>(!strconcat(baseOpc, "v16i8v")) V128:$Rn), hsub),
4017          ssub))>;
4018
4019def : Pat<(i32 (intOp (v4i16 V64:$Rn))),
4020          (i32 (EXTRACT_SUBREG
4021            (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
4022              (!cast<Instruction>(!strconcat(baseOpc, "v4i16v")) V64:$Rn), ssub),
4023            ssub))>;
4024def : Pat<(i32 (intOp (v8i16 V128:$Rn))),
4025        (i32 (EXTRACT_SUBREG
4026          (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
4027            (!cast<Instruction>(!strconcat(baseOpc, "v8i16v")) V128:$Rn), ssub),
4028          ssub))>;
4029
4030def : Pat<(i64 (intOp (v4i32 V128:$Rn))),
4031        (i64 (EXTRACT_SUBREG
4032          (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
4033            (!cast<Instruction>(!strconcat(baseOpc, "v4i32v")) V128:$Rn), dsub),
4034          dsub))>;
4035}
4036
4037defm : SIMDAcrossLanesSignedLongIntrinsic<"SADDLV", int_aarch64_neon_saddlv>;
4038defm : SIMDAcrossLanesUnsignedLongIntrinsic<"UADDLV", int_aarch64_neon_uaddlv>;
4039
4040// The vaddlv_s32 intrinsic gets mapped to SADDLP.
4041def : Pat<(i64 (int_aarch64_neon_saddlv (v2i32 V64:$Rn))),
4042          (i64 (EXTRACT_SUBREG
4043            (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
4044              (SADDLPv2i32_v1i64 V64:$Rn), dsub),
4045            dsub))>;
4046// The vaddlv_u32 intrinsic gets mapped to UADDLP.
4047def : Pat<(i64 (int_aarch64_neon_uaddlv (v2i32 V64:$Rn))),
4048          (i64 (EXTRACT_SUBREG
4049            (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
4050              (UADDLPv2i32_v1i64 V64:$Rn), dsub),
4051            dsub))>;
4052
4053//------------------------------------------------------------------------------
4054// AdvSIMD modified immediate instructions
4055//------------------------------------------------------------------------------
4056
4057// AdvSIMD BIC
4058defm BIC : SIMDModifiedImmVectorShiftTied<1, 0b11, 0b01, "bic", AArch64bici>;
4059// AdvSIMD ORR
4060defm ORR : SIMDModifiedImmVectorShiftTied<0, 0b11, 0b01, "orr", AArch64orri>;
4061
4062def : InstAlias<"bic $Vd.4h, $imm", (BICv4i16 V64:$Vd,  imm0_255:$imm, 0)>;
4063def : InstAlias<"bic $Vd.8h, $imm", (BICv8i16 V128:$Vd, imm0_255:$imm, 0)>;
4064def : InstAlias<"bic $Vd.2s, $imm", (BICv2i32 V64:$Vd,  imm0_255:$imm, 0)>;
4065def : InstAlias<"bic $Vd.4s, $imm", (BICv4i32 V128:$Vd, imm0_255:$imm, 0)>;
4066
4067def : InstAlias<"bic.4h $Vd, $imm", (BICv4i16 V64:$Vd,  imm0_255:$imm, 0), 0>;
4068def : InstAlias<"bic.8h $Vd, $imm", (BICv8i16 V128:$Vd, imm0_255:$imm, 0), 0>;
4069def : InstAlias<"bic.2s $Vd, $imm", (BICv2i32 V64:$Vd,  imm0_255:$imm, 0), 0>;
4070def : InstAlias<"bic.4s $Vd, $imm", (BICv4i32 V128:$Vd, imm0_255:$imm, 0), 0>;
4071
4072def : InstAlias<"orr $Vd.4h, $imm", (ORRv4i16 V64:$Vd,  imm0_255:$imm, 0)>;
4073def : InstAlias<"orr $Vd.8h, $imm", (ORRv8i16 V128:$Vd, imm0_255:$imm, 0)>;
4074def : InstAlias<"orr $Vd.2s, $imm", (ORRv2i32 V64:$Vd,  imm0_255:$imm, 0)>;
4075def : InstAlias<"orr $Vd.4s, $imm", (ORRv4i32 V128:$Vd, imm0_255:$imm, 0)>;
4076
4077def : InstAlias<"orr.4h $Vd, $imm", (ORRv4i16 V64:$Vd,  imm0_255:$imm, 0), 0>;
4078def : InstAlias<"orr.8h $Vd, $imm", (ORRv8i16 V128:$Vd, imm0_255:$imm, 0), 0>;
4079def : InstAlias<"orr.2s $Vd, $imm", (ORRv2i32 V64:$Vd,  imm0_255:$imm, 0), 0>;
4080def : InstAlias<"orr.4s $Vd, $imm", (ORRv4i32 V128:$Vd, imm0_255:$imm, 0), 0>;
4081
4082// AdvSIMD FMOV
4083def FMOVv2f64_ns : SIMDModifiedImmVectorNoShift<1, 1, 0b1111, V128, fpimm8,
4084                                              "fmov", ".2d",
4085                       [(set (v2f64 V128:$Rd), (AArch64fmov imm0_255:$imm8))]>;
4086def FMOVv2f32_ns : SIMDModifiedImmVectorNoShift<0, 0, 0b1111, V64,  fpimm8,
4087                                              "fmov", ".2s",
4088                       [(set (v2f32 V64:$Rd), (AArch64fmov imm0_255:$imm8))]>;
4089def FMOVv4f32_ns : SIMDModifiedImmVectorNoShift<1, 0, 0b1111, V128, fpimm8,
4090                                              "fmov", ".4s",
4091                       [(set (v4f32 V128:$Rd), (AArch64fmov imm0_255:$imm8))]>;
4092
4093// AdvSIMD MOVI
4094
4095// EDIT byte mask: scalar
4096let isReMaterializable = 1, isAsCheapAsAMove = 1 in
4097def MOVID      : SIMDModifiedImmScalarNoShift<0, 1, 0b1110, "movi",
4098                    [(set FPR64:$Rd, simdimmtype10:$imm8)]>;
4099// The movi_edit node has the immediate value already encoded, so we use
4100// a plain imm0_255 here.
4101def : Pat<(f64 (AArch64movi_edit imm0_255:$shift)),
4102          (MOVID imm0_255:$shift)>;
4103
4104def : Pat<(v1i64 immAllZerosV), (MOVID (i32 0))>;
4105def : Pat<(v2i32 immAllZerosV), (MOVID (i32 0))>;
4106def : Pat<(v4i16 immAllZerosV), (MOVID (i32 0))>;
4107def : Pat<(v8i8  immAllZerosV), (MOVID (i32 0))>;
4108
4109def : Pat<(v1i64 immAllOnesV), (MOVID (i32 255))>;
4110def : Pat<(v2i32 immAllOnesV), (MOVID (i32 255))>;
4111def : Pat<(v4i16 immAllOnesV), (MOVID (i32 255))>;
4112def : Pat<(v8i8  immAllOnesV), (MOVID (i32 255))>;
4113
4114// EDIT byte mask: 2d
4115
4116// The movi_edit node has the immediate value already encoded, so we use
4117// a plain imm0_255 in the pattern
4118let isReMaterializable = 1, isAsCheapAsAMove = 1 in
4119def MOVIv2d_ns   : SIMDModifiedImmVectorNoShift<1, 1, 0b1110, V128,
4120                                                simdimmtype10,
4121                                                "movi", ".2d",
4122                   [(set (v2i64 V128:$Rd), (AArch64movi_edit imm0_255:$imm8))]>;
4123
4124
4125// Use movi.2d to materialize 0.0 if the HW does zero-cycle zeroing.
4126// Complexity is added to break a tie with a plain MOVI.
4127let AddedComplexity = 1 in {
4128def : Pat<(f32   fpimm0),
4129          (f32 (EXTRACT_SUBREG (v2i64 (MOVIv2d_ns (i32 0))), ssub))>,
4130      Requires<[HasZCZ]>;
4131def : Pat<(f64   fpimm0),
4132          (f64 (EXTRACT_SUBREG (v2i64 (MOVIv2d_ns (i32 0))), dsub))>,
4133      Requires<[HasZCZ]>;
4134}
4135
4136def : Pat<(v2i64 immAllZerosV), (MOVIv2d_ns (i32 0))>;
4137def : Pat<(v4i32 immAllZerosV), (MOVIv2d_ns (i32 0))>;
4138def : Pat<(v8i16 immAllZerosV), (MOVIv2d_ns (i32 0))>;
4139def : Pat<(v16i8 immAllZerosV), (MOVIv2d_ns (i32 0))>;
4140
4141def : Pat<(v2i64 immAllOnesV), (MOVIv2d_ns (i32 255))>;
4142def : Pat<(v4i32 immAllOnesV), (MOVIv2d_ns (i32 255))>;
4143def : Pat<(v8i16 immAllOnesV), (MOVIv2d_ns (i32 255))>;
4144def : Pat<(v16i8 immAllOnesV), (MOVIv2d_ns (i32 255))>;
4145
4146def : Pat<(v2f64 (AArch64dup (f64 fpimm0))), (MOVIv2d_ns (i32 0))>;
4147def : Pat<(v4f32 (AArch64dup (f32 fpimm0))), (MOVIv2d_ns (i32 0))>;
4148
4149// EDIT per word & halfword: 2s, 4h, 4s, & 8h
4150defm MOVI      : SIMDModifiedImmVectorShift<0, 0b10, 0b00, "movi">;
4151
4152def : InstAlias<"movi $Vd.4h, $imm", (MOVIv4i16 V64:$Vd,  imm0_255:$imm, 0), 0>;
4153def : InstAlias<"movi $Vd.8h, $imm", (MOVIv8i16 V128:$Vd, imm0_255:$imm, 0), 0>;
4154def : InstAlias<"movi $Vd.2s, $imm", (MOVIv2i32 V64:$Vd,  imm0_255:$imm, 0), 0>;
4155def : InstAlias<"movi $Vd.4s, $imm", (MOVIv4i32 V128:$Vd, imm0_255:$imm, 0), 0>;
4156
4157def : InstAlias<"movi.4h $Vd, $imm", (MOVIv4i16 V64:$Vd,  imm0_255:$imm, 0), 0>;
4158def : InstAlias<"movi.8h $Vd, $imm", (MOVIv8i16 V128:$Vd, imm0_255:$imm, 0), 0>;
4159def : InstAlias<"movi.2s $Vd, $imm", (MOVIv2i32 V64:$Vd,  imm0_255:$imm, 0), 0>;
4160def : InstAlias<"movi.4s $Vd, $imm", (MOVIv4i32 V128:$Vd, imm0_255:$imm, 0), 0>;
4161
4162def : Pat<(v2i32 (AArch64movi_shift imm0_255:$imm8, (i32 imm:$shift))),
4163          (MOVIv2i32 imm0_255:$imm8, imm:$shift)>;
4164def : Pat<(v4i32 (AArch64movi_shift imm0_255:$imm8, (i32 imm:$shift))),
4165          (MOVIv4i32 imm0_255:$imm8, imm:$shift)>;
4166def : Pat<(v4i16 (AArch64movi_shift imm0_255:$imm8, (i32 imm:$shift))),
4167          (MOVIv4i16 imm0_255:$imm8, imm:$shift)>;
4168def : Pat<(v8i16 (AArch64movi_shift imm0_255:$imm8, (i32 imm:$shift))),
4169          (MOVIv8i16 imm0_255:$imm8, imm:$shift)>;
4170
4171// EDIT per word: 2s & 4s with MSL shifter
4172def MOVIv2s_msl  : SIMDModifiedImmMoveMSL<0, 0, {1,1,0,?}, V64, "movi", ".2s",
4173                      [(set (v2i32 V64:$Rd),
4174                            (AArch64movi_msl imm0_255:$imm8, (i32 imm:$shift)))]>;
4175def MOVIv4s_msl  : SIMDModifiedImmMoveMSL<1, 0, {1,1,0,?}, V128, "movi", ".4s",
4176                      [(set (v4i32 V128:$Rd),
4177                            (AArch64movi_msl imm0_255:$imm8, (i32 imm:$shift)))]>;
4178
4179// Per byte: 8b & 16b
4180def MOVIv8b_ns   : SIMDModifiedImmVectorNoShift<0, 0, 0b1110, V64,  imm0_255,
4181                                                 "movi", ".8b",
4182                       [(set (v8i8 V64:$Rd), (AArch64movi imm0_255:$imm8))]>;
4183def MOVIv16b_ns  : SIMDModifiedImmVectorNoShift<1, 0, 0b1110, V128, imm0_255,
4184                                                 "movi", ".16b",
4185                       [(set (v16i8 V128:$Rd), (AArch64movi imm0_255:$imm8))]>;
4186
4187// AdvSIMD MVNI
4188
4189// EDIT per word & halfword: 2s, 4h, 4s, & 8h
4190defm MVNI      : SIMDModifiedImmVectorShift<1, 0b10, 0b00, "mvni">;
4191
4192def : InstAlias<"mvni $Vd.4h, $imm", (MVNIv4i16 V64:$Vd,  imm0_255:$imm, 0), 0>;
4193def : InstAlias<"mvni $Vd.8h, $imm", (MVNIv8i16 V128:$Vd, imm0_255:$imm, 0), 0>;
4194def : InstAlias<"mvni $Vd.2s, $imm", (MVNIv2i32 V64:$Vd,  imm0_255:$imm, 0), 0>;
4195def : InstAlias<"mvni $Vd.4s, $imm", (MVNIv4i32 V128:$Vd, imm0_255:$imm, 0), 0>;
4196
4197def : InstAlias<"mvni.4h $Vd, $imm", (MVNIv4i16 V64:$Vd,  imm0_255:$imm, 0), 0>;
4198def : InstAlias<"mvni.8h $Vd, $imm", (MVNIv8i16 V128:$Vd, imm0_255:$imm, 0), 0>;
4199def : InstAlias<"mvni.2s $Vd, $imm", (MVNIv2i32 V64:$Vd,  imm0_255:$imm, 0), 0>;
4200def : InstAlias<"mvni.4s $Vd, $imm", (MVNIv4i32 V128:$Vd, imm0_255:$imm, 0), 0>;
4201
4202def : Pat<(v2i32 (AArch64mvni_shift imm0_255:$imm8, (i32 imm:$shift))),
4203          (MVNIv2i32 imm0_255:$imm8, imm:$shift)>;
4204def : Pat<(v4i32 (AArch64mvni_shift imm0_255:$imm8, (i32 imm:$shift))),
4205          (MVNIv4i32 imm0_255:$imm8, imm:$shift)>;
4206def : Pat<(v4i16 (AArch64mvni_shift imm0_255:$imm8, (i32 imm:$shift))),
4207          (MVNIv4i16 imm0_255:$imm8, imm:$shift)>;
4208def : Pat<(v8i16 (AArch64mvni_shift imm0_255:$imm8, (i32 imm:$shift))),
4209          (MVNIv8i16 imm0_255:$imm8, imm:$shift)>;
4210
4211// EDIT per word: 2s & 4s with MSL shifter
4212def MVNIv2s_msl   : SIMDModifiedImmMoveMSL<0, 1, {1,1,0,?}, V64, "mvni", ".2s",
4213                      [(set (v2i32 V64:$Rd),
4214                            (AArch64mvni_msl imm0_255:$imm8, (i32 imm:$shift)))]>;
4215def MVNIv4s_msl   : SIMDModifiedImmMoveMSL<1, 1, {1,1,0,?}, V128, "mvni", ".4s",
4216                      [(set (v4i32 V128:$Rd),
4217                            (AArch64mvni_msl imm0_255:$imm8, (i32 imm:$shift)))]>;
4218
4219//----------------------------------------------------------------------------
4220// AdvSIMD indexed element
4221//----------------------------------------------------------------------------
4222
4223let hasSideEffects = 0 in {
4224  defm FMLA  : SIMDFPIndexedSDTied<0, 0b0001, "fmla">;
4225  defm FMLS  : SIMDFPIndexedSDTied<0, 0b0101, "fmls">;
4226}
4227
4228// NOTE: Operands are reordered in the FMLA/FMLS PatFrags because the
4229// instruction expects the addend first, while the intrinsic expects it last.
4230
4231// On the other hand, there are quite a few valid combinatorial options due to
4232// the commutativity of multiplication and the fact that (-x) * y = x * (-y).
4233defm : SIMDFPIndexedSDTiedPatterns<"FMLA",
4234           TriOpFrag<(fma node:$RHS, node:$MHS, node:$LHS)>>;
4235defm : SIMDFPIndexedSDTiedPatterns<"FMLA",
4236           TriOpFrag<(fma node:$MHS, node:$RHS, node:$LHS)>>;
4237
4238defm : SIMDFPIndexedSDTiedPatterns<"FMLS",
4239           TriOpFrag<(fma node:$MHS, (fneg node:$RHS), node:$LHS)> >;
4240defm : SIMDFPIndexedSDTiedPatterns<"FMLS",
4241           TriOpFrag<(fma node:$RHS, (fneg node:$MHS), node:$LHS)> >;
4242defm : SIMDFPIndexedSDTiedPatterns<"FMLS",
4243           TriOpFrag<(fma (fneg node:$RHS), node:$MHS, node:$LHS)> >;
4244defm : SIMDFPIndexedSDTiedPatterns<"FMLS",
4245           TriOpFrag<(fma (fneg node:$MHS), node:$RHS, node:$LHS)> >;
4246
4247multiclass FMLSIndexedAfterNegPatterns<SDPatternOperator OpNode> {
4248  // 3 variants for the .2s version: DUPLANE from 128-bit, DUPLANE from 64-bit
4249  // and DUP scalar.
4250  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
4251                           (AArch64duplane32 (v4f32 (fneg V128:$Rm)),
4252                                           VectorIndexS:$idx))),
4253            (FMLSv2i32_indexed V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
4254  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
4255                           (v2f32 (AArch64duplane32
4256                                      (v4f32 (insert_subvector undef,
4257                                                 (v2f32 (fneg V64:$Rm)),
4258                                                 (i32 0))),
4259                                      VectorIndexS:$idx)))),
4260            (FMLSv2i32_indexed V64:$Rd, V64:$Rn,
4261                               (SUBREG_TO_REG (i32 0), V64:$Rm, dsub),
4262                               VectorIndexS:$idx)>;
4263  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
4264                           (AArch64dup (f32 (fneg FPR32Op:$Rm))))),
4265            (FMLSv2i32_indexed V64:$Rd, V64:$Rn,
4266                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
4267
4268  // 3 variants for the .4s version: DUPLANE from 128-bit, DUPLANE from 64-bit
4269  // and DUP scalar.
4270  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
4271                           (AArch64duplane32 (v4f32 (fneg V128:$Rm)),
4272                                           VectorIndexS:$idx))),
4273            (FMLSv4i32_indexed V128:$Rd, V128:$Rn, V128:$Rm,
4274                               VectorIndexS:$idx)>;
4275  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
4276                           (v4f32 (AArch64duplane32
4277                                      (v4f32 (insert_subvector undef,
4278                                                 (v2f32 (fneg V64:$Rm)),
4279                                                 (i32 0))),
4280                                      VectorIndexS:$idx)))),
4281            (FMLSv4i32_indexed V128:$Rd, V128:$Rn,
4282                               (SUBREG_TO_REG (i32 0), V64:$Rm, dsub),
4283                               VectorIndexS:$idx)>;
4284  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
4285                           (AArch64dup (f32 (fneg FPR32Op:$Rm))))),
4286            (FMLSv4i32_indexed V128:$Rd, V128:$Rn,
4287                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
4288
4289  // 2 variants for the .2d version: DUPLANE from 128-bit, and DUP scalar
4290  // (DUPLANE from 64-bit would be trivial).
4291  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
4292                           (AArch64duplane64 (v2f64 (fneg V128:$Rm)),
4293                                           VectorIndexD:$idx))),
4294            (FMLSv2i64_indexed
4295                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
4296  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
4297                           (AArch64dup (f64 (fneg FPR64Op:$Rm))))),
4298            (FMLSv2i64_indexed V128:$Rd, V128:$Rn,
4299                (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
4300
4301  // 2 variants for 32-bit scalar version: extract from .2s or from .4s
4302  def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
4303                         (vector_extract (v4f32 (fneg V128:$Rm)),
4304                                         VectorIndexS:$idx))),
4305            (FMLSv1i32_indexed FPR32:$Rd, FPR32:$Rn,
4306                V128:$Rm, VectorIndexS:$idx)>;
4307  def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
4308                         (vector_extract (v2f32 (fneg V64:$Rm)),
4309                                         VectorIndexS:$idx))),
4310            (FMLSv1i32_indexed FPR32:$Rd, FPR32:$Rn,
4311                (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
4312
4313  // 1 variant for 64-bit scalar version: extract from .1d or from .2d
4314  def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
4315                         (vector_extract (v2f64 (fneg V128:$Rm)),
4316                                         VectorIndexS:$idx))),
4317            (FMLSv1i64_indexed FPR64:$Rd, FPR64:$Rn,
4318                V128:$Rm, VectorIndexS:$idx)>;
4319}
4320
4321defm : FMLSIndexedAfterNegPatterns<
4322           TriOpFrag<(fma node:$RHS, node:$MHS, node:$LHS)> >;
4323defm : FMLSIndexedAfterNegPatterns<
4324           TriOpFrag<(fma node:$MHS, node:$RHS, node:$LHS)> >;
4325
4326defm FMULX : SIMDFPIndexedSD<1, 0b1001, "fmulx", int_aarch64_neon_fmulx>;
4327defm FMUL  : SIMDFPIndexedSD<0, 0b1001, "fmul", fmul>;
4328
4329def : Pat<(v2f32 (fmul V64:$Rn, (AArch64dup (f32 FPR32:$Rm)))),
4330          (FMULv2i32_indexed V64:$Rn,
4331            (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), FPR32:$Rm, ssub),
4332            (i64 0))>;
4333def : Pat<(v4f32 (fmul V128:$Rn, (AArch64dup (f32 FPR32:$Rm)))),
4334          (FMULv4i32_indexed V128:$Rn,
4335            (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), FPR32:$Rm, ssub),
4336            (i64 0))>;
4337def : Pat<(v2f64 (fmul V128:$Rn, (AArch64dup (f64 FPR64:$Rm)))),
4338          (FMULv2i64_indexed V128:$Rn,
4339            (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), FPR64:$Rm, dsub),
4340            (i64 0))>;
4341
4342defm SQDMULH : SIMDIndexedHS<0, 0b1100, "sqdmulh", int_aarch64_neon_sqdmulh>;
4343defm SQRDMULH : SIMDIndexedHS<0, 0b1101, "sqrdmulh", int_aarch64_neon_sqrdmulh>;
4344defm MLA   : SIMDVectorIndexedHSTied<1, 0b0000, "mla",
4345              TriOpFrag<(add node:$LHS, (mul node:$MHS, node:$RHS))>>;
4346defm MLS   : SIMDVectorIndexedHSTied<1, 0b0100, "mls",
4347              TriOpFrag<(sub node:$LHS, (mul node:$MHS, node:$RHS))>>;
4348defm MUL   : SIMDVectorIndexedHS<0, 0b1000, "mul", mul>;
4349defm SMLAL : SIMDVectorIndexedLongSDTied<0, 0b0010, "smlal",
4350    TriOpFrag<(add node:$LHS, (int_aarch64_neon_smull node:$MHS, node:$RHS))>>;
4351defm SMLSL : SIMDVectorIndexedLongSDTied<0, 0b0110, "smlsl",
4352    TriOpFrag<(sub node:$LHS, (int_aarch64_neon_smull node:$MHS, node:$RHS))>>;
4353defm SMULL : SIMDVectorIndexedLongSD<0, 0b1010, "smull",
4354                int_aarch64_neon_smull>;
4355defm SQDMLAL : SIMDIndexedLongSQDMLXSDTied<0, 0b0011, "sqdmlal",
4356                                           int_aarch64_neon_sqadd>;
4357defm SQDMLSL : SIMDIndexedLongSQDMLXSDTied<0, 0b0111, "sqdmlsl",
4358                                           int_aarch64_neon_sqsub>;
4359defm SQRDMLAH : SIMDIndexedSQRDMLxHSDTied<1, 0b1101, "sqrdmlah",
4360                                          int_aarch64_neon_sqadd>;
4361defm SQRDMLSH : SIMDIndexedSQRDMLxHSDTied<1, 0b1111, "sqrdmlsh",
4362                                          int_aarch64_neon_sqsub>;
4363defm SQDMULL : SIMDIndexedLongSD<0, 0b1011, "sqdmull", int_aarch64_neon_sqdmull>;
4364defm UMLAL   : SIMDVectorIndexedLongSDTied<1, 0b0010, "umlal",
4365    TriOpFrag<(add node:$LHS, (int_aarch64_neon_umull node:$MHS, node:$RHS))>>;
4366defm UMLSL   : SIMDVectorIndexedLongSDTied<1, 0b0110, "umlsl",
4367    TriOpFrag<(sub node:$LHS, (int_aarch64_neon_umull node:$MHS, node:$RHS))>>;
4368defm UMULL   : SIMDVectorIndexedLongSD<1, 0b1010, "umull",
4369                int_aarch64_neon_umull>;
4370
4371// A scalar sqdmull with the second operand being a vector lane can be
4372// handled directly with the indexed instruction encoding.
4373def : Pat<(int_aarch64_neon_sqdmulls_scalar (i32 FPR32:$Rn),
4374                                          (vector_extract (v4i32 V128:$Vm),
4375                                                           VectorIndexS:$idx)),
4376          (SQDMULLv1i64_indexed FPR32:$Rn, V128:$Vm, VectorIndexS:$idx)>;
4377
4378//----------------------------------------------------------------------------
4379// AdvSIMD scalar shift instructions
4380//----------------------------------------------------------------------------
4381defm FCVTZS : SIMDScalarRShiftSD<0, 0b11111, "fcvtzs">;
4382defm FCVTZU : SIMDScalarRShiftSD<1, 0b11111, "fcvtzu">;
4383defm SCVTF  : SIMDScalarRShiftSD<0, 0b11100, "scvtf">;
4384defm UCVTF  : SIMDScalarRShiftSD<1, 0b11100, "ucvtf">;
4385// Codegen patterns for the above. We don't put these directly on the
4386// instructions because TableGen's type inference can't handle the truth.
4387// Having the same base pattern for fp <--> int totally freaks it out.
4388def : Pat<(int_aarch64_neon_vcvtfp2fxs FPR32:$Rn, vecshiftR32:$imm),
4389          (FCVTZSs FPR32:$Rn, vecshiftR32:$imm)>;
4390def : Pat<(int_aarch64_neon_vcvtfp2fxu FPR32:$Rn, vecshiftR32:$imm),
4391          (FCVTZUs FPR32:$Rn, vecshiftR32:$imm)>;
4392def : Pat<(i64 (int_aarch64_neon_vcvtfp2fxs (f64 FPR64:$Rn), vecshiftR64:$imm)),
4393          (FCVTZSd FPR64:$Rn, vecshiftR64:$imm)>;
4394def : Pat<(i64 (int_aarch64_neon_vcvtfp2fxu (f64 FPR64:$Rn), vecshiftR64:$imm)),
4395          (FCVTZUd FPR64:$Rn, vecshiftR64:$imm)>;
4396def : Pat<(v1i64 (int_aarch64_neon_vcvtfp2fxs (v1f64 FPR64:$Rn),
4397                                            vecshiftR64:$imm)),
4398          (FCVTZSd FPR64:$Rn, vecshiftR64:$imm)>;
4399def : Pat<(v1i64 (int_aarch64_neon_vcvtfp2fxu (v1f64 FPR64:$Rn),
4400                                            vecshiftR64:$imm)),
4401          (FCVTZUd FPR64:$Rn, vecshiftR64:$imm)>;
4402def : Pat<(int_aarch64_neon_vcvtfxs2fp FPR32:$Rn, vecshiftR32:$imm),
4403          (SCVTFs FPR32:$Rn, vecshiftR32:$imm)>;
4404def : Pat<(int_aarch64_neon_vcvtfxu2fp FPR32:$Rn, vecshiftR32:$imm),
4405          (UCVTFs FPR32:$Rn, vecshiftR32:$imm)>;
4406def : Pat<(f64 (int_aarch64_neon_vcvtfxs2fp (i64 FPR64:$Rn), vecshiftR64:$imm)),
4407          (SCVTFd FPR64:$Rn, vecshiftR64:$imm)>;
4408def : Pat<(f64 (int_aarch64_neon_vcvtfxu2fp (i64 FPR64:$Rn), vecshiftR64:$imm)),
4409          (UCVTFd FPR64:$Rn, vecshiftR64:$imm)>;
4410def : Pat<(v1f64 (int_aarch64_neon_vcvtfxs2fp (v1i64 FPR64:$Rn),
4411                                            vecshiftR64:$imm)),
4412          (SCVTFd FPR64:$Rn, vecshiftR64:$imm)>;
4413def : Pat<(v1f64 (int_aarch64_neon_vcvtfxu2fp (v1i64 FPR64:$Rn),
4414                                            vecshiftR64:$imm)),
4415          (UCVTFd FPR64:$Rn, vecshiftR64:$imm)>;
4416
4417defm SHL      : SIMDScalarLShiftD<   0, 0b01010, "shl", AArch64vshl>;
4418defm SLI      : SIMDScalarLShiftDTied<1, 0b01010, "sli">;
4419defm SQRSHRN  : SIMDScalarRShiftBHS< 0, 0b10011, "sqrshrn",
4420                                     int_aarch64_neon_sqrshrn>;
4421defm SQRSHRUN : SIMDScalarRShiftBHS< 1, 0b10001, "sqrshrun",
4422                                     int_aarch64_neon_sqrshrun>;
4423defm SQSHLU   : SIMDScalarLShiftBHSD<1, 0b01100, "sqshlu", AArch64sqshlui>;
4424defm SQSHL    : SIMDScalarLShiftBHSD<0, 0b01110, "sqshl", AArch64sqshli>;
4425defm SQSHRN   : SIMDScalarRShiftBHS< 0, 0b10010, "sqshrn",
4426                                     int_aarch64_neon_sqshrn>;
4427defm SQSHRUN  : SIMDScalarRShiftBHS< 1, 0b10000, "sqshrun",
4428                                     int_aarch64_neon_sqshrun>;
4429defm SRI      : SIMDScalarRShiftDTied<   1, 0b01000, "sri">;
4430defm SRSHR    : SIMDScalarRShiftD<   0, 0b00100, "srshr", AArch64srshri>;
4431defm SRSRA    : SIMDScalarRShiftDTied<   0, 0b00110, "srsra",
4432    TriOpFrag<(add node:$LHS,
4433                   (AArch64srshri node:$MHS, node:$RHS))>>;
4434defm SSHR     : SIMDScalarRShiftD<   0, 0b00000, "sshr", AArch64vashr>;
4435defm SSRA     : SIMDScalarRShiftDTied<   0, 0b00010, "ssra",
4436    TriOpFrag<(add node:$LHS,
4437                   (AArch64vashr node:$MHS, node:$RHS))>>;
4438defm UQRSHRN  : SIMDScalarRShiftBHS< 1, 0b10011, "uqrshrn",
4439                                     int_aarch64_neon_uqrshrn>;
4440defm UQSHL    : SIMDScalarLShiftBHSD<1, 0b01110, "uqshl", AArch64uqshli>;
4441defm UQSHRN   : SIMDScalarRShiftBHS< 1, 0b10010, "uqshrn",
4442                                     int_aarch64_neon_uqshrn>;
4443defm URSHR    : SIMDScalarRShiftD<   1, 0b00100, "urshr", AArch64urshri>;
4444defm URSRA    : SIMDScalarRShiftDTied<   1, 0b00110, "ursra",
4445    TriOpFrag<(add node:$LHS,
4446                   (AArch64urshri node:$MHS, node:$RHS))>>;
4447defm USHR     : SIMDScalarRShiftD<   1, 0b00000, "ushr", AArch64vlshr>;
4448defm USRA     : SIMDScalarRShiftDTied<   1, 0b00010, "usra",
4449    TriOpFrag<(add node:$LHS,
4450                   (AArch64vlshr node:$MHS, node:$RHS))>>;
4451
4452//----------------------------------------------------------------------------
4453// AdvSIMD vector shift instructions
4454//----------------------------------------------------------------------------
4455defm FCVTZS:SIMDVectorRShiftSD<0, 0b11111, "fcvtzs", int_aarch64_neon_vcvtfp2fxs>;
4456defm FCVTZU:SIMDVectorRShiftSD<1, 0b11111, "fcvtzu", int_aarch64_neon_vcvtfp2fxu>;
4457defm SCVTF: SIMDVectorRShiftSDToFP<0, 0b11100, "scvtf",
4458                                   int_aarch64_neon_vcvtfxs2fp>;
4459defm RSHRN   : SIMDVectorRShiftNarrowBHS<0, 0b10001, "rshrn",
4460                                         int_aarch64_neon_rshrn>;
4461defm SHL     : SIMDVectorLShiftBHSD<0, 0b01010, "shl", AArch64vshl>;
4462defm SHRN    : SIMDVectorRShiftNarrowBHS<0, 0b10000, "shrn",
4463                          BinOpFrag<(trunc (AArch64vashr node:$LHS, node:$RHS))>>;
4464defm SLI     : SIMDVectorLShiftBHSDTied<1, 0b01010, "sli", int_aarch64_neon_vsli>;
4465def : Pat<(v1i64 (int_aarch64_neon_vsli (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
4466                                      (i32 vecshiftL64:$imm))),
4467          (SLId FPR64:$Rd, FPR64:$Rn, vecshiftL64:$imm)>;
4468defm SQRSHRN : SIMDVectorRShiftNarrowBHS<0, 0b10011, "sqrshrn",
4469                                         int_aarch64_neon_sqrshrn>;
4470defm SQRSHRUN: SIMDVectorRShiftNarrowBHS<1, 0b10001, "sqrshrun",
4471                                         int_aarch64_neon_sqrshrun>;
4472defm SQSHLU : SIMDVectorLShiftBHSD<1, 0b01100, "sqshlu", AArch64sqshlui>;
4473defm SQSHL  : SIMDVectorLShiftBHSD<0, 0b01110, "sqshl", AArch64sqshli>;
4474defm SQSHRN  : SIMDVectorRShiftNarrowBHS<0, 0b10010, "sqshrn",
4475                                         int_aarch64_neon_sqshrn>;
4476defm SQSHRUN : SIMDVectorRShiftNarrowBHS<1, 0b10000, "sqshrun",
4477                                         int_aarch64_neon_sqshrun>;
4478defm SRI     : SIMDVectorRShiftBHSDTied<1, 0b01000, "sri", int_aarch64_neon_vsri>;
4479def : Pat<(v1i64 (int_aarch64_neon_vsri (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
4480                                      (i32 vecshiftR64:$imm))),
4481          (SRId FPR64:$Rd, FPR64:$Rn, vecshiftR64:$imm)>;
4482defm SRSHR   : SIMDVectorRShiftBHSD<0, 0b00100, "srshr", AArch64srshri>;
4483defm SRSRA   : SIMDVectorRShiftBHSDTied<0, 0b00110, "srsra",
4484                 TriOpFrag<(add node:$LHS,
4485                                (AArch64srshri node:$MHS, node:$RHS))> >;
4486defm SSHLL   : SIMDVectorLShiftLongBHSD<0, 0b10100, "sshll",
4487                BinOpFrag<(AArch64vshl (sext node:$LHS), node:$RHS)>>;
4488
4489defm SSHR    : SIMDVectorRShiftBHSD<0, 0b00000, "sshr", AArch64vashr>;
4490defm SSRA    : SIMDVectorRShiftBHSDTied<0, 0b00010, "ssra",
4491                TriOpFrag<(add node:$LHS, (AArch64vashr node:$MHS, node:$RHS))>>;
4492defm UCVTF   : SIMDVectorRShiftSDToFP<1, 0b11100, "ucvtf",
4493                        int_aarch64_neon_vcvtfxu2fp>;
4494defm UQRSHRN : SIMDVectorRShiftNarrowBHS<1, 0b10011, "uqrshrn",
4495                                         int_aarch64_neon_uqrshrn>;
4496defm UQSHL   : SIMDVectorLShiftBHSD<1, 0b01110, "uqshl", AArch64uqshli>;
4497defm UQSHRN  : SIMDVectorRShiftNarrowBHS<1, 0b10010, "uqshrn",
4498                                         int_aarch64_neon_uqshrn>;
4499defm URSHR   : SIMDVectorRShiftBHSD<1, 0b00100, "urshr", AArch64urshri>;
4500defm URSRA   : SIMDVectorRShiftBHSDTied<1, 0b00110, "ursra",
4501                TriOpFrag<(add node:$LHS,
4502                               (AArch64urshri node:$MHS, node:$RHS))> >;
4503defm USHLL   : SIMDVectorLShiftLongBHSD<1, 0b10100, "ushll",
4504                BinOpFrag<(AArch64vshl (zext node:$LHS), node:$RHS)>>;
4505defm USHR    : SIMDVectorRShiftBHSD<1, 0b00000, "ushr", AArch64vlshr>;
4506defm USRA    : SIMDVectorRShiftBHSDTied<1, 0b00010, "usra",
4507                TriOpFrag<(add node:$LHS, (AArch64vlshr node:$MHS, node:$RHS))> >;
4508
4509// SHRN patterns for when a logical right shift was used instead of arithmetic
4510// (the immediate guarantees no sign bits actually end up in the result so it
4511// doesn't matter).
4512def : Pat<(v8i8 (trunc (AArch64vlshr (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))),
4513          (SHRNv8i8_shift V128:$Rn, vecshiftR16Narrow:$imm)>;
4514def : Pat<(v4i16 (trunc (AArch64vlshr (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))),
4515          (SHRNv4i16_shift V128:$Rn, vecshiftR32Narrow:$imm)>;
4516def : Pat<(v2i32 (trunc (AArch64vlshr (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))),
4517          (SHRNv2i32_shift V128:$Rn, vecshiftR64Narrow:$imm)>;
4518
4519def : Pat<(v16i8 (concat_vectors (v8i8 V64:$Rd),
4520                                 (trunc (AArch64vlshr (v8i16 V128:$Rn),
4521                                                    vecshiftR16Narrow:$imm)))),
4522          (SHRNv16i8_shift (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4523                           V128:$Rn, vecshiftR16Narrow:$imm)>;
4524def : Pat<(v8i16 (concat_vectors (v4i16 V64:$Rd),
4525                                 (trunc (AArch64vlshr (v4i32 V128:$Rn),
4526                                                    vecshiftR32Narrow:$imm)))),
4527          (SHRNv8i16_shift (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4528                           V128:$Rn, vecshiftR32Narrow:$imm)>;
4529def : Pat<(v4i32 (concat_vectors (v2i32 V64:$Rd),
4530                                 (trunc (AArch64vlshr (v2i64 V128:$Rn),
4531                                                    vecshiftR64Narrow:$imm)))),
4532          (SHRNv4i32_shift (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4533                           V128:$Rn, vecshiftR32Narrow:$imm)>;
4534
4535// Vector sign and zero extensions are implemented with SSHLL and USSHLL.
4536// Anyexts are implemented as zexts.
4537def : Pat<(v8i16 (sext   (v8i8 V64:$Rn))),  (SSHLLv8i8_shift  V64:$Rn, (i32 0))>;
4538def : Pat<(v8i16 (zext   (v8i8 V64:$Rn))),  (USHLLv8i8_shift  V64:$Rn, (i32 0))>;
4539def : Pat<(v8i16 (anyext (v8i8 V64:$Rn))),  (USHLLv8i8_shift  V64:$Rn, (i32 0))>;
4540def : Pat<(v4i32 (sext   (v4i16 V64:$Rn))), (SSHLLv4i16_shift V64:$Rn, (i32 0))>;
4541def : Pat<(v4i32 (zext   (v4i16 V64:$Rn))), (USHLLv4i16_shift V64:$Rn, (i32 0))>;
4542def : Pat<(v4i32 (anyext (v4i16 V64:$Rn))), (USHLLv4i16_shift V64:$Rn, (i32 0))>;
4543def : Pat<(v2i64 (sext   (v2i32 V64:$Rn))), (SSHLLv2i32_shift V64:$Rn, (i32 0))>;
4544def : Pat<(v2i64 (zext   (v2i32 V64:$Rn))), (USHLLv2i32_shift V64:$Rn, (i32 0))>;
4545def : Pat<(v2i64 (anyext (v2i32 V64:$Rn))), (USHLLv2i32_shift V64:$Rn, (i32 0))>;
4546// Also match an extend from the upper half of a 128 bit source register.
4547def : Pat<(v8i16 (anyext (v8i8 (extract_subvector V128:$Rn, (i64 8)) ))),
4548          (USHLLv16i8_shift V128:$Rn, (i32 0))>;
4549def : Pat<(v8i16 (zext   (v8i8 (extract_subvector V128:$Rn, (i64 8)) ))),
4550          (USHLLv16i8_shift V128:$Rn, (i32 0))>;
4551def : Pat<(v8i16 (sext   (v8i8 (extract_subvector V128:$Rn, (i64 8)) ))),
4552          (SSHLLv16i8_shift V128:$Rn, (i32 0))>;
4553def : Pat<(v4i32 (anyext (v4i16 (extract_subvector V128:$Rn, (i64 4)) ))),
4554          (USHLLv8i16_shift V128:$Rn, (i32 0))>;
4555def : Pat<(v4i32 (zext   (v4i16 (extract_subvector V128:$Rn, (i64 4)) ))),
4556          (USHLLv8i16_shift V128:$Rn, (i32 0))>;
4557def : Pat<(v4i32 (sext   (v4i16 (extract_subvector V128:$Rn, (i64 4)) ))),
4558          (SSHLLv8i16_shift V128:$Rn, (i32 0))>;
4559def : Pat<(v2i64 (anyext (v2i32 (extract_subvector V128:$Rn, (i64 2)) ))),
4560          (USHLLv4i32_shift V128:$Rn, (i32 0))>;
4561def : Pat<(v2i64 (zext   (v2i32 (extract_subvector V128:$Rn, (i64 2)) ))),
4562          (USHLLv4i32_shift V128:$Rn, (i32 0))>;
4563def : Pat<(v2i64 (sext   (v2i32 (extract_subvector V128:$Rn, (i64 2)) ))),
4564          (SSHLLv4i32_shift V128:$Rn, (i32 0))>;
4565
4566// Vector shift sxtl aliases
4567def : InstAlias<"sxtl.8h $dst, $src1",
4568                (SSHLLv8i8_shift V128:$dst, V64:$src1, 0)>;
4569def : InstAlias<"sxtl $dst.8h, $src1.8b",
4570                (SSHLLv8i8_shift V128:$dst, V64:$src1, 0)>;
4571def : InstAlias<"sxtl.4s $dst, $src1",
4572                (SSHLLv4i16_shift V128:$dst, V64:$src1, 0)>;
4573def : InstAlias<"sxtl $dst.4s, $src1.4h",
4574                (SSHLLv4i16_shift V128:$dst, V64:$src1, 0)>;
4575def : InstAlias<"sxtl.2d $dst, $src1",
4576                (SSHLLv2i32_shift V128:$dst, V64:$src1, 0)>;
4577def : InstAlias<"sxtl $dst.2d, $src1.2s",
4578                (SSHLLv2i32_shift V128:$dst, V64:$src1, 0)>;
4579
4580// Vector shift sxtl2 aliases
4581def : InstAlias<"sxtl2.8h $dst, $src1",
4582                (SSHLLv16i8_shift V128:$dst, V128:$src1, 0)>;
4583def : InstAlias<"sxtl2 $dst.8h, $src1.16b",
4584                (SSHLLv16i8_shift V128:$dst, V128:$src1, 0)>;
4585def : InstAlias<"sxtl2.4s $dst, $src1",
4586                (SSHLLv8i16_shift V128:$dst, V128:$src1, 0)>;
4587def : InstAlias<"sxtl2 $dst.4s, $src1.8h",
4588                (SSHLLv8i16_shift V128:$dst, V128:$src1, 0)>;
4589def : InstAlias<"sxtl2.2d $dst, $src1",
4590                (SSHLLv4i32_shift V128:$dst, V128:$src1, 0)>;
4591def : InstAlias<"sxtl2 $dst.2d, $src1.4s",
4592                (SSHLLv4i32_shift V128:$dst, V128:$src1, 0)>;
4593
4594// Vector shift uxtl aliases
4595def : InstAlias<"uxtl.8h $dst, $src1",
4596                (USHLLv8i8_shift V128:$dst, V64:$src1, 0)>;
4597def : InstAlias<"uxtl $dst.8h, $src1.8b",
4598                (USHLLv8i8_shift V128:$dst, V64:$src1, 0)>;
4599def : InstAlias<"uxtl.4s $dst, $src1",
4600                (USHLLv4i16_shift V128:$dst, V64:$src1, 0)>;
4601def : InstAlias<"uxtl $dst.4s, $src1.4h",
4602                (USHLLv4i16_shift V128:$dst, V64:$src1, 0)>;
4603def : InstAlias<"uxtl.2d $dst, $src1",
4604                (USHLLv2i32_shift V128:$dst, V64:$src1, 0)>;
4605def : InstAlias<"uxtl $dst.2d, $src1.2s",
4606                (USHLLv2i32_shift V128:$dst, V64:$src1, 0)>;
4607
4608// Vector shift uxtl2 aliases
4609def : InstAlias<"uxtl2.8h $dst, $src1",
4610                (USHLLv16i8_shift V128:$dst, V128:$src1, 0)>;
4611def : InstAlias<"uxtl2 $dst.8h, $src1.16b",
4612                (USHLLv16i8_shift V128:$dst, V128:$src1, 0)>;
4613def : InstAlias<"uxtl2.4s $dst, $src1",
4614                (USHLLv8i16_shift V128:$dst, V128:$src1, 0)>;
4615def : InstAlias<"uxtl2 $dst.4s, $src1.8h",
4616                (USHLLv8i16_shift V128:$dst, V128:$src1, 0)>;
4617def : InstAlias<"uxtl2.2d $dst, $src1",
4618                (USHLLv4i32_shift V128:$dst, V128:$src1, 0)>;
4619def : InstAlias<"uxtl2 $dst.2d, $src1.4s",
4620                (USHLLv4i32_shift V128:$dst, V128:$src1, 0)>;
4621
4622// If an integer is about to be converted to a floating point value,
4623// just load it on the floating point unit.
4624// These patterns are more complex because floating point loads do not
4625// support sign extension.
4626// The sign extension has to be explicitly added and is only supported for
4627// one step: byte-to-half, half-to-word, word-to-doubleword.
4628// SCVTF GPR -> FPR is 9 cycles.
4629// SCVTF FPR -> FPR is 4 cyclces.
4630// (sign extension with lengthen) SXTL FPR -> FPR is 2 cycles.
4631// Therefore, we can do 2 sign extensions and one SCVTF FPR -> FPR
4632// and still being faster.
4633// However, this is not good for code size.
4634// 8-bits -> float. 2 sizes step-up.
4635class SExtLoadi8CVTf32Pat<dag addrmode, dag INST>
4636  : Pat<(f32 (sint_to_fp (i32 (sextloadi8 addrmode)))),
4637        (SCVTFv1i32 (f32 (EXTRACT_SUBREG
4638                            (SSHLLv4i16_shift
4639                              (f64
4640                                (EXTRACT_SUBREG
4641                                  (SSHLLv8i8_shift
4642                                    (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
4643                                        INST,
4644                                        bsub),
4645                                    0),
4646                                  dsub)),
4647                               0),
4648                             ssub)))>, Requires<[NotForCodeSize, IsCyclone]>;
4649
4650def : SExtLoadi8CVTf32Pat<(ro8.Wpat GPR64sp:$Rn, GPR32:$Rm, ro8.Wext:$ext),
4651                          (LDRBroW  GPR64sp:$Rn, GPR32:$Rm, ro8.Wext:$ext)>;
4652def : SExtLoadi8CVTf32Pat<(ro8.Xpat GPR64sp:$Rn, GPR64:$Rm, ro8.Xext:$ext),
4653                          (LDRBroX  GPR64sp:$Rn, GPR64:$Rm, ro8.Xext:$ext)>;
4654def : SExtLoadi8CVTf32Pat<(am_indexed8 GPR64sp:$Rn, uimm12s1:$offset),
4655                          (LDRBui GPR64sp:$Rn, uimm12s1:$offset)>;
4656def : SExtLoadi8CVTf32Pat<(am_unscaled8 GPR64sp:$Rn, simm9:$offset),
4657                          (LDURBi GPR64sp:$Rn, simm9:$offset)>;
4658
4659// 16-bits -> float. 1 size step-up.
4660class SExtLoadi16CVTf32Pat<dag addrmode, dag INST>
4661  : Pat<(f32 (sint_to_fp (i32 (sextloadi16 addrmode)))),
4662        (SCVTFv1i32 (f32 (EXTRACT_SUBREG
4663                            (SSHLLv4i16_shift
4664                                (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
4665                                  INST,
4666                                  hsub),
4667                                0),
4668                            ssub)))>, Requires<[NotForCodeSize]>;
4669
4670def : SExtLoadi16CVTf32Pat<(ro16.Wpat GPR64sp:$Rn, GPR32:$Rm, ro16.Wext:$ext),
4671                           (LDRHroW   GPR64sp:$Rn, GPR32:$Rm, ro16.Wext:$ext)>;
4672def : SExtLoadi16CVTf32Pat<(ro16.Xpat GPR64sp:$Rn, GPR64:$Rm, ro16.Xext:$ext),
4673                           (LDRHroX   GPR64sp:$Rn, GPR64:$Rm, ro16.Xext:$ext)>;
4674def : SExtLoadi16CVTf32Pat<(am_indexed16 GPR64sp:$Rn, uimm12s2:$offset),
4675                           (LDRHui GPR64sp:$Rn, uimm12s2:$offset)>;
4676def : SExtLoadi16CVTf32Pat<(am_unscaled16 GPR64sp:$Rn, simm9:$offset),
4677                           (LDURHi GPR64sp:$Rn, simm9:$offset)>;
4678
4679// 32-bits to 32-bits are handled in target specific dag combine:
4680// performIntToFpCombine.
4681// 64-bits integer to 32-bits floating point, not possible with
4682// SCVTF on floating point registers (both source and destination
4683// must have the same size).
4684
4685// Here are the patterns for 8, 16, 32, and 64-bits to double.
4686// 8-bits -> double. 3 size step-up: give up.
4687// 16-bits -> double. 2 size step.
4688class SExtLoadi16CVTf64Pat<dag addrmode, dag INST>
4689  : Pat <(f64 (sint_to_fp (i32 (sextloadi16 addrmode)))),
4690           (SCVTFv1i64 (f64 (EXTRACT_SUBREG
4691                              (SSHLLv2i32_shift
4692                                 (f64
4693                                  (EXTRACT_SUBREG
4694                                    (SSHLLv4i16_shift
4695                                      (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
4696                                        INST,
4697                                        hsub),
4698                                     0),
4699                                   dsub)),
4700                               0),
4701                             dsub)))>, Requires<[NotForCodeSize, IsCyclone]>;
4702
4703def : SExtLoadi16CVTf64Pat<(ro16.Wpat GPR64sp:$Rn, GPR32:$Rm, ro16.Wext:$ext),
4704                           (LDRHroW GPR64sp:$Rn, GPR32:$Rm, ro16.Wext:$ext)>;
4705def : SExtLoadi16CVTf64Pat<(ro16.Xpat GPR64sp:$Rn, GPR64:$Rm, ro16.Xext:$ext),
4706                           (LDRHroX GPR64sp:$Rn, GPR64:$Rm, ro16.Xext:$ext)>;
4707def : SExtLoadi16CVTf64Pat<(am_indexed16 GPR64sp:$Rn, uimm12s2:$offset),
4708                           (LDRHui GPR64sp:$Rn, uimm12s2:$offset)>;
4709def : SExtLoadi16CVTf64Pat<(am_unscaled16 GPR64sp:$Rn, simm9:$offset),
4710                           (LDURHi GPR64sp:$Rn, simm9:$offset)>;
4711// 32-bits -> double. 1 size step-up.
4712class SExtLoadi32CVTf64Pat<dag addrmode, dag INST>
4713  : Pat <(f64 (sint_to_fp (i32 (load addrmode)))),
4714           (SCVTFv1i64 (f64 (EXTRACT_SUBREG
4715                              (SSHLLv2i32_shift
4716                                (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
4717                                  INST,
4718                                  ssub),
4719                               0),
4720                             dsub)))>, Requires<[NotForCodeSize]>;
4721
4722def : SExtLoadi32CVTf64Pat<(ro32.Wpat GPR64sp:$Rn, GPR32:$Rm, ro32.Wext:$ext),
4723                           (LDRSroW GPR64sp:$Rn, GPR32:$Rm, ro32.Wext:$ext)>;
4724def : SExtLoadi32CVTf64Pat<(ro32.Xpat GPR64sp:$Rn, GPR64:$Rm, ro32.Xext:$ext),
4725                           (LDRSroX GPR64sp:$Rn, GPR64:$Rm, ro32.Xext:$ext)>;
4726def : SExtLoadi32CVTf64Pat<(am_indexed32 GPR64sp:$Rn, uimm12s4:$offset),
4727                           (LDRSui GPR64sp:$Rn, uimm12s4:$offset)>;
4728def : SExtLoadi32CVTf64Pat<(am_unscaled32 GPR64sp:$Rn, simm9:$offset),
4729                           (LDURSi GPR64sp:$Rn, simm9:$offset)>;
4730
4731// 64-bits -> double are handled in target specific dag combine:
4732// performIntToFpCombine.
4733
4734
4735//----------------------------------------------------------------------------
4736// AdvSIMD Load-Store Structure
4737//----------------------------------------------------------------------------
4738defm LD1 : SIMDLd1Multiple<"ld1">;
4739defm LD2 : SIMDLd2Multiple<"ld2">;
4740defm LD3 : SIMDLd3Multiple<"ld3">;
4741defm LD4 : SIMDLd4Multiple<"ld4">;
4742
4743defm ST1 : SIMDSt1Multiple<"st1">;
4744defm ST2 : SIMDSt2Multiple<"st2">;
4745defm ST3 : SIMDSt3Multiple<"st3">;
4746defm ST4 : SIMDSt4Multiple<"st4">;
4747
4748class Ld1Pat<ValueType ty, Instruction INST>
4749  : Pat<(ty (load GPR64sp:$Rn)), (INST GPR64sp:$Rn)>;
4750
4751def : Ld1Pat<v16i8, LD1Onev16b>;
4752def : Ld1Pat<v8i16, LD1Onev8h>;
4753def : Ld1Pat<v4i32, LD1Onev4s>;
4754def : Ld1Pat<v2i64, LD1Onev2d>;
4755def : Ld1Pat<v8i8,  LD1Onev8b>;
4756def : Ld1Pat<v4i16, LD1Onev4h>;
4757def : Ld1Pat<v2i32, LD1Onev2s>;
4758def : Ld1Pat<v1i64, LD1Onev1d>;
4759
4760class St1Pat<ValueType ty, Instruction INST>
4761  : Pat<(store ty:$Vt, GPR64sp:$Rn),
4762        (INST ty:$Vt, GPR64sp:$Rn)>;
4763
4764def : St1Pat<v16i8, ST1Onev16b>;
4765def : St1Pat<v8i16, ST1Onev8h>;
4766def : St1Pat<v4i32, ST1Onev4s>;
4767def : St1Pat<v2i64, ST1Onev2d>;
4768def : St1Pat<v8i8,  ST1Onev8b>;
4769def : St1Pat<v4i16, ST1Onev4h>;
4770def : St1Pat<v2i32, ST1Onev2s>;
4771def : St1Pat<v1i64, ST1Onev1d>;
4772
4773//---
4774// Single-element
4775//---
4776
4777defm LD1R          : SIMDLdR<0, 0b110, 0, "ld1r", "One", 1, 2, 4, 8>;
4778defm LD2R          : SIMDLdR<1, 0b110, 0, "ld2r", "Two", 2, 4, 8, 16>;
4779defm LD3R          : SIMDLdR<0, 0b111, 0, "ld3r", "Three", 3, 6, 12, 24>;
4780defm LD4R          : SIMDLdR<1, 0b111, 0, "ld4r", "Four", 4, 8, 16, 32>;
4781let mayLoad = 1, hasSideEffects = 0 in {
4782defm LD1 : SIMDLdSingleBTied<0, 0b000,       "ld1", VecListOneb,   GPR64pi1>;
4783defm LD1 : SIMDLdSingleHTied<0, 0b010, 0,    "ld1", VecListOneh,   GPR64pi2>;
4784defm LD1 : SIMDLdSingleSTied<0, 0b100, 0b00, "ld1", VecListOnes,   GPR64pi4>;
4785defm LD1 : SIMDLdSingleDTied<0, 0b100, 0b01, "ld1", VecListOned,   GPR64pi8>;
4786defm LD2 : SIMDLdSingleBTied<1, 0b000,       "ld2", VecListTwob,   GPR64pi2>;
4787defm LD2 : SIMDLdSingleHTied<1, 0b010, 0,    "ld2", VecListTwoh,   GPR64pi4>;
4788defm LD2 : SIMDLdSingleSTied<1, 0b100, 0b00, "ld2", VecListTwos,   GPR64pi8>;
4789defm LD2 : SIMDLdSingleDTied<1, 0b100, 0b01, "ld2", VecListTwod,   GPR64pi16>;
4790defm LD3 : SIMDLdSingleBTied<0, 0b001,       "ld3", VecListThreeb, GPR64pi3>;
4791defm LD3 : SIMDLdSingleHTied<0, 0b011, 0,    "ld3", VecListThreeh, GPR64pi6>;
4792defm LD3 : SIMDLdSingleSTied<0, 0b101, 0b00, "ld3", VecListThrees, GPR64pi12>;
4793defm LD3 : SIMDLdSingleDTied<0, 0b101, 0b01, "ld3", VecListThreed, GPR64pi24>;
4794defm LD4 : SIMDLdSingleBTied<1, 0b001,       "ld4", VecListFourb,  GPR64pi4>;
4795defm LD4 : SIMDLdSingleHTied<1, 0b011, 0,    "ld4", VecListFourh,  GPR64pi8>;
4796defm LD4 : SIMDLdSingleSTied<1, 0b101, 0b00, "ld4", VecListFours,  GPR64pi16>;
4797defm LD4 : SIMDLdSingleDTied<1, 0b101, 0b01, "ld4", VecListFourd,  GPR64pi32>;
4798}
4799
4800def : Pat<(v8i8 (AArch64dup (i32 (extloadi8 GPR64sp:$Rn)))),
4801          (LD1Rv8b GPR64sp:$Rn)>;
4802def : Pat<(v16i8 (AArch64dup (i32 (extloadi8 GPR64sp:$Rn)))),
4803          (LD1Rv16b GPR64sp:$Rn)>;
4804def : Pat<(v4i16 (AArch64dup (i32 (extloadi16 GPR64sp:$Rn)))),
4805          (LD1Rv4h GPR64sp:$Rn)>;
4806def : Pat<(v8i16 (AArch64dup (i32 (extloadi16 GPR64sp:$Rn)))),
4807          (LD1Rv8h GPR64sp:$Rn)>;
4808def : Pat<(v2i32 (AArch64dup (i32 (load GPR64sp:$Rn)))),
4809          (LD1Rv2s GPR64sp:$Rn)>;
4810def : Pat<(v4i32 (AArch64dup (i32 (load GPR64sp:$Rn)))),
4811          (LD1Rv4s GPR64sp:$Rn)>;
4812def : Pat<(v2i64 (AArch64dup (i64 (load GPR64sp:$Rn)))),
4813          (LD1Rv2d GPR64sp:$Rn)>;
4814def : Pat<(v1i64 (AArch64dup (i64 (load GPR64sp:$Rn)))),
4815          (LD1Rv1d GPR64sp:$Rn)>;
4816// Grab the floating point version too
4817def : Pat<(v2f32 (AArch64dup (f32 (load GPR64sp:$Rn)))),
4818          (LD1Rv2s GPR64sp:$Rn)>;
4819def : Pat<(v4f32 (AArch64dup (f32 (load GPR64sp:$Rn)))),
4820          (LD1Rv4s GPR64sp:$Rn)>;
4821def : Pat<(v2f64 (AArch64dup (f64 (load GPR64sp:$Rn)))),
4822          (LD1Rv2d GPR64sp:$Rn)>;
4823def : Pat<(v1f64 (AArch64dup (f64 (load GPR64sp:$Rn)))),
4824          (LD1Rv1d GPR64sp:$Rn)>;
4825def : Pat<(v4f16 (AArch64dup (f16 (load GPR64sp:$Rn)))),
4826          (LD1Rv4h GPR64sp:$Rn)>;
4827def : Pat<(v8f16 (AArch64dup (f16 (load GPR64sp:$Rn)))),
4828          (LD1Rv8h GPR64sp:$Rn)>;
4829
4830class Ld1Lane128Pat<SDPatternOperator scalar_load, Operand VecIndex,
4831                    ValueType VTy, ValueType STy, Instruction LD1>
4832  : Pat<(vector_insert (VTy VecListOne128:$Rd),
4833           (STy (scalar_load GPR64sp:$Rn)), VecIndex:$idx),
4834        (LD1 VecListOne128:$Rd, VecIndex:$idx, GPR64sp:$Rn)>;
4835
4836def : Ld1Lane128Pat<extloadi8,  VectorIndexB, v16i8, i32, LD1i8>;
4837def : Ld1Lane128Pat<extloadi16, VectorIndexH, v8i16, i32, LD1i16>;
4838def : Ld1Lane128Pat<load,       VectorIndexS, v4i32, i32, LD1i32>;
4839def : Ld1Lane128Pat<load,       VectorIndexS, v4f32, f32, LD1i32>;
4840def : Ld1Lane128Pat<load,       VectorIndexD, v2i64, i64, LD1i64>;
4841def : Ld1Lane128Pat<load,       VectorIndexD, v2f64, f64, LD1i64>;
4842def : Ld1Lane128Pat<load,       VectorIndexH, v8f16, f16, LD1i16>;
4843
4844class Ld1Lane64Pat<SDPatternOperator scalar_load, Operand VecIndex,
4845                   ValueType VTy, ValueType STy, Instruction LD1>
4846  : Pat<(vector_insert (VTy VecListOne64:$Rd),
4847           (STy (scalar_load GPR64sp:$Rn)), VecIndex:$idx),
4848        (EXTRACT_SUBREG
4849            (LD1 (SUBREG_TO_REG (i32 0), VecListOne64:$Rd, dsub),
4850                          VecIndex:$idx, GPR64sp:$Rn),
4851            dsub)>;
4852
4853def : Ld1Lane64Pat<extloadi8,  VectorIndexB, v8i8,  i32, LD1i8>;
4854def : Ld1Lane64Pat<extloadi16, VectorIndexH, v4i16, i32, LD1i16>;
4855def : Ld1Lane64Pat<load,       VectorIndexS, v2i32, i32, LD1i32>;
4856def : Ld1Lane64Pat<load,       VectorIndexS, v2f32, f32, LD1i32>;
4857def : Ld1Lane64Pat<load,       VectorIndexH, v4f16, f16, LD1i16>;
4858
4859
4860defm LD1 : SIMDLdSt1SingleAliases<"ld1">;
4861defm LD2 : SIMDLdSt2SingleAliases<"ld2">;
4862defm LD3 : SIMDLdSt3SingleAliases<"ld3">;
4863defm LD4 : SIMDLdSt4SingleAliases<"ld4">;
4864
4865// Stores
4866defm ST1 : SIMDStSingleB<0, 0b000,       "st1", VecListOneb, GPR64pi1>;
4867defm ST1 : SIMDStSingleH<0, 0b010, 0,    "st1", VecListOneh, GPR64pi2>;
4868defm ST1 : SIMDStSingleS<0, 0b100, 0b00, "st1", VecListOnes, GPR64pi4>;
4869defm ST1 : SIMDStSingleD<0, 0b100, 0b01, "st1", VecListOned, GPR64pi8>;
4870
4871let AddedComplexity = 19 in
4872class St1Lane128Pat<SDPatternOperator scalar_store, Operand VecIndex,
4873                    ValueType VTy, ValueType STy, Instruction ST1>
4874  : Pat<(scalar_store
4875             (STy (vector_extract (VTy VecListOne128:$Vt), VecIndex:$idx)),
4876             GPR64sp:$Rn),
4877        (ST1 VecListOne128:$Vt, VecIndex:$idx, GPR64sp:$Rn)>;
4878
4879def : St1Lane128Pat<truncstorei8,  VectorIndexB, v16i8, i32, ST1i8>;
4880def : St1Lane128Pat<truncstorei16, VectorIndexH, v8i16, i32, ST1i16>;
4881def : St1Lane128Pat<store,         VectorIndexS, v4i32, i32, ST1i32>;
4882def : St1Lane128Pat<store,         VectorIndexS, v4f32, f32, ST1i32>;
4883def : St1Lane128Pat<store,         VectorIndexD, v2i64, i64, ST1i64>;
4884def : St1Lane128Pat<store,         VectorIndexD, v2f64, f64, ST1i64>;
4885def : St1Lane128Pat<store,         VectorIndexH, v8f16, f16, ST1i16>;
4886
4887let AddedComplexity = 19 in
4888class St1Lane64Pat<SDPatternOperator scalar_store, Operand VecIndex,
4889                   ValueType VTy, ValueType STy, Instruction ST1>
4890  : Pat<(scalar_store
4891             (STy (vector_extract (VTy VecListOne64:$Vt), VecIndex:$idx)),
4892             GPR64sp:$Rn),
4893        (ST1 (SUBREG_TO_REG (i32 0), VecListOne64:$Vt, dsub),
4894             VecIndex:$idx, GPR64sp:$Rn)>;
4895
4896def : St1Lane64Pat<truncstorei8,  VectorIndexB, v8i8, i32, ST1i8>;
4897def : St1Lane64Pat<truncstorei16, VectorIndexH, v4i16, i32, ST1i16>;
4898def : St1Lane64Pat<store,         VectorIndexS, v2i32, i32, ST1i32>;
4899def : St1Lane64Pat<store,         VectorIndexS, v2f32, f32, ST1i32>;
4900def : St1Lane64Pat<store,         VectorIndexH, v4f16, f16, ST1i16>;
4901
4902multiclass St1LanePost64Pat<SDPatternOperator scalar_store, Operand VecIndex,
4903                             ValueType VTy, ValueType STy, Instruction ST1,
4904                             int offset> {
4905  def : Pat<(scalar_store
4906              (STy (vector_extract (VTy VecListOne64:$Vt), VecIndex:$idx)),
4907              GPR64sp:$Rn, offset),
4908        (ST1 (SUBREG_TO_REG (i32 0), VecListOne64:$Vt, dsub),
4909             VecIndex:$idx, GPR64sp:$Rn, XZR)>;
4910
4911  def : Pat<(scalar_store
4912              (STy (vector_extract (VTy VecListOne64:$Vt), VecIndex:$idx)),
4913              GPR64sp:$Rn, GPR64:$Rm),
4914        (ST1 (SUBREG_TO_REG (i32 0), VecListOne64:$Vt, dsub),
4915             VecIndex:$idx, GPR64sp:$Rn, $Rm)>;
4916}
4917
4918defm : St1LanePost64Pat<post_truncsti8, VectorIndexB, v8i8, i32, ST1i8_POST, 1>;
4919defm : St1LanePost64Pat<post_truncsti16, VectorIndexH, v4i16, i32, ST1i16_POST,
4920                        2>;
4921defm : St1LanePost64Pat<post_store, VectorIndexS, v2i32, i32, ST1i32_POST, 4>;
4922defm : St1LanePost64Pat<post_store, VectorIndexS, v2f32, f32, ST1i32_POST, 4>;
4923defm : St1LanePost64Pat<post_store, VectorIndexD, v1i64, i64, ST1i64_POST, 8>;
4924defm : St1LanePost64Pat<post_store, VectorIndexD, v1f64, f64, ST1i64_POST, 8>;
4925defm : St1LanePost64Pat<post_store, VectorIndexH, v4f16, f16, ST1i16_POST, 2>;
4926
4927multiclass St1LanePost128Pat<SDPatternOperator scalar_store, Operand VecIndex,
4928                             ValueType VTy, ValueType STy, Instruction ST1,
4929                             int offset> {
4930  def : Pat<(scalar_store
4931              (STy (vector_extract (VTy VecListOne128:$Vt), VecIndex:$idx)),
4932              GPR64sp:$Rn, offset),
4933        (ST1 VecListOne128:$Vt, VecIndex:$idx, GPR64sp:$Rn, XZR)>;
4934
4935  def : Pat<(scalar_store
4936              (STy (vector_extract (VTy VecListOne128:$Vt), VecIndex:$idx)),
4937              GPR64sp:$Rn, GPR64:$Rm),
4938        (ST1 VecListOne128:$Vt, VecIndex:$idx, GPR64sp:$Rn, $Rm)>;
4939}
4940
4941defm : St1LanePost128Pat<post_truncsti8, VectorIndexB, v16i8, i32, ST1i8_POST,
4942                         1>;
4943defm : St1LanePost128Pat<post_truncsti16, VectorIndexH, v8i16, i32, ST1i16_POST,
4944                         2>;
4945defm : St1LanePost128Pat<post_store, VectorIndexS, v4i32, i32, ST1i32_POST, 4>;
4946defm : St1LanePost128Pat<post_store, VectorIndexS, v4f32, f32, ST1i32_POST, 4>;
4947defm : St1LanePost128Pat<post_store, VectorIndexD, v2i64, i64, ST1i64_POST, 8>;
4948defm : St1LanePost128Pat<post_store, VectorIndexD, v2f64, f64, ST1i64_POST, 8>;
4949defm : St1LanePost128Pat<post_store, VectorIndexH, v8f16, f16, ST1i16_POST, 2>;
4950
4951let mayStore = 1, hasSideEffects = 0 in {
4952defm ST2 : SIMDStSingleB<1, 0b000,       "st2", VecListTwob,   GPR64pi2>;
4953defm ST2 : SIMDStSingleH<1, 0b010, 0,    "st2", VecListTwoh,   GPR64pi4>;
4954defm ST2 : SIMDStSingleS<1, 0b100, 0b00, "st2", VecListTwos,   GPR64pi8>;
4955defm ST2 : SIMDStSingleD<1, 0b100, 0b01, "st2", VecListTwod,   GPR64pi16>;
4956defm ST3 : SIMDStSingleB<0, 0b001,       "st3", VecListThreeb, GPR64pi3>;
4957defm ST3 : SIMDStSingleH<0, 0b011, 0,    "st3", VecListThreeh, GPR64pi6>;
4958defm ST3 : SIMDStSingleS<0, 0b101, 0b00, "st3", VecListThrees, GPR64pi12>;
4959defm ST3 : SIMDStSingleD<0, 0b101, 0b01, "st3", VecListThreed, GPR64pi24>;
4960defm ST4 : SIMDStSingleB<1, 0b001,       "st4", VecListFourb,  GPR64pi4>;
4961defm ST4 : SIMDStSingleH<1, 0b011, 0,    "st4", VecListFourh,  GPR64pi8>;
4962defm ST4 : SIMDStSingleS<1, 0b101, 0b00, "st4", VecListFours,  GPR64pi16>;
4963defm ST4 : SIMDStSingleD<1, 0b101, 0b01, "st4", VecListFourd,  GPR64pi32>;
4964}
4965
4966defm ST1 : SIMDLdSt1SingleAliases<"st1">;
4967defm ST2 : SIMDLdSt2SingleAliases<"st2">;
4968defm ST3 : SIMDLdSt3SingleAliases<"st3">;
4969defm ST4 : SIMDLdSt4SingleAliases<"st4">;
4970
4971//----------------------------------------------------------------------------
4972// Crypto extensions
4973//----------------------------------------------------------------------------
4974
4975def AESErr   : AESTiedInst<0b0100, "aese",   int_aarch64_crypto_aese>;
4976def AESDrr   : AESTiedInst<0b0101, "aesd",   int_aarch64_crypto_aesd>;
4977def AESMCrr  : AESInst<    0b0110, "aesmc",  int_aarch64_crypto_aesmc>;
4978def AESIMCrr : AESInst<    0b0111, "aesimc", int_aarch64_crypto_aesimc>;
4979
4980def SHA1Crrr     : SHATiedInstQSV<0b000, "sha1c",   int_aarch64_crypto_sha1c>;
4981def SHA1Prrr     : SHATiedInstQSV<0b001, "sha1p",   int_aarch64_crypto_sha1p>;
4982def SHA1Mrrr     : SHATiedInstQSV<0b010, "sha1m",   int_aarch64_crypto_sha1m>;
4983def SHA1SU0rrr   : SHATiedInstVVV<0b011, "sha1su0", int_aarch64_crypto_sha1su0>;
4984def SHA256Hrrr   : SHATiedInstQQV<0b100, "sha256h", int_aarch64_crypto_sha256h>;
4985def SHA256H2rrr  : SHATiedInstQQV<0b101, "sha256h2",int_aarch64_crypto_sha256h2>;
4986def SHA256SU1rrr :SHATiedInstVVV<0b110, "sha256su1",int_aarch64_crypto_sha256su1>;
4987
4988def SHA1Hrr     : SHAInstSS<    0b0000, "sha1h",    int_aarch64_crypto_sha1h>;
4989def SHA1SU1rr   : SHATiedInstVV<0b0001, "sha1su1",  int_aarch64_crypto_sha1su1>;
4990def SHA256SU0rr : SHATiedInstVV<0b0010, "sha256su0",int_aarch64_crypto_sha256su0>;
4991
4992//----------------------------------------------------------------------------
4993// Compiler-pseudos
4994//----------------------------------------------------------------------------
4995// FIXME: Like for X86, these should go in their own separate .td file.
4996
4997// Any instruction that defines a 32-bit result leaves the high half of the
4998// register. Truncate can be lowered to EXTRACT_SUBREG. CopyFromReg may
4999// be copying from a truncate. But any other 32-bit operation will zero-extend
5000// up to 64 bits.
5001// FIXME: X86 also checks for CMOV here. Do we need something similar?
5002def def32 : PatLeaf<(i32 GPR32:$src), [{
5003  return N->getOpcode() != ISD::TRUNCATE &&
5004         N->getOpcode() != TargetOpcode::EXTRACT_SUBREG &&
5005         N->getOpcode() != ISD::CopyFromReg;
5006}]>;
5007
5008// In the case of a 32-bit def that is known to implicitly zero-extend,
5009// we can use a SUBREG_TO_REG.
5010def : Pat<(i64 (zext def32:$src)), (SUBREG_TO_REG (i64 0), GPR32:$src, sub_32)>;
5011
5012// For an anyext, we don't care what the high bits are, so we can perform an
5013// INSERT_SUBREF into an IMPLICIT_DEF.
5014def : Pat<(i64 (anyext GPR32:$src)),
5015          (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32)>;
5016
5017// When we need to explicitly zero-extend, we use an unsigned bitfield move
5018// instruction (UBFM) on the enclosing super-reg.
5019def : Pat<(i64 (zext GPR32:$src)),
5020 (UBFMXri (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32), 0, 31)>;
5021
5022// To sign extend, we use a signed bitfield move instruction (SBFM) on the
5023// containing super-reg.
5024def : Pat<(i64 (sext GPR32:$src)),
5025   (SBFMXri (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32), 0, 31)>;
5026def : Pat<(i64 (sext_inreg GPR64:$src, i32)), (SBFMXri GPR64:$src, 0, 31)>;
5027def : Pat<(i64 (sext_inreg GPR64:$src, i16)), (SBFMXri GPR64:$src, 0, 15)>;
5028def : Pat<(i64 (sext_inreg GPR64:$src, i8)),  (SBFMXri GPR64:$src, 0, 7)>;
5029def : Pat<(i64 (sext_inreg GPR64:$src, i1)),  (SBFMXri GPR64:$src, 0, 0)>;
5030def : Pat<(i32 (sext_inreg GPR32:$src, i16)), (SBFMWri GPR32:$src, 0, 15)>;
5031def : Pat<(i32 (sext_inreg GPR32:$src, i8)),  (SBFMWri GPR32:$src, 0, 7)>;
5032def : Pat<(i32 (sext_inreg GPR32:$src, i1)),  (SBFMWri GPR32:$src, 0, 0)>;
5033
5034def : Pat<(shl (sext_inreg GPR32:$Rn, i8), (i64 imm0_31:$imm)),
5035          (SBFMWri GPR32:$Rn, (i64 (i32shift_a       imm0_31:$imm)),
5036                              (i64 (i32shift_sext_i8 imm0_31:$imm)))>;
5037def : Pat<(shl (sext_inreg GPR64:$Rn, i8), (i64 imm0_63:$imm)),
5038          (SBFMXri GPR64:$Rn, (i64 (i64shift_a imm0_63:$imm)),
5039                              (i64 (i64shift_sext_i8 imm0_63:$imm)))>;
5040
5041def : Pat<(shl (sext_inreg GPR32:$Rn, i16), (i64 imm0_31:$imm)),
5042          (SBFMWri GPR32:$Rn, (i64 (i32shift_a        imm0_31:$imm)),
5043                              (i64 (i32shift_sext_i16 imm0_31:$imm)))>;
5044def : Pat<(shl (sext_inreg GPR64:$Rn, i16), (i64 imm0_63:$imm)),
5045          (SBFMXri GPR64:$Rn, (i64 (i64shift_a        imm0_63:$imm)),
5046                              (i64 (i64shift_sext_i16 imm0_63:$imm)))>;
5047
5048def : Pat<(shl (i64 (sext GPR32:$Rn)), (i64 imm0_63:$imm)),
5049          (SBFMXri (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$Rn, sub_32),
5050                   (i64 (i64shift_a        imm0_63:$imm)),
5051                   (i64 (i64shift_sext_i32 imm0_63:$imm)))>;
5052
5053// sra patterns have an AddedComplexity of 10, so make sure we have a higher
5054// AddedComplexity for the following patterns since we want to match sext + sra
5055// patterns before we attempt to match a single sra node.
5056let AddedComplexity = 20 in {
5057// We support all sext + sra combinations which preserve at least one bit of the
5058// original value which is to be sign extended. E.g. we support shifts up to
5059// bitwidth-1 bits.
5060def : Pat<(sra (sext_inreg GPR32:$Rn, i8), (i64 imm0_7:$imm)),
5061          (SBFMWri GPR32:$Rn, (i64 imm0_7:$imm), 7)>;
5062def : Pat<(sra (sext_inreg GPR64:$Rn, i8), (i64 imm0_7:$imm)),
5063          (SBFMXri GPR64:$Rn, (i64 imm0_7:$imm), 7)>;
5064
5065def : Pat<(sra (sext_inreg GPR32:$Rn, i16), (i64 imm0_15:$imm)),
5066          (SBFMWri GPR32:$Rn, (i64 imm0_15:$imm), 15)>;
5067def : Pat<(sra (sext_inreg GPR64:$Rn, i16), (i64 imm0_15:$imm)),
5068          (SBFMXri GPR64:$Rn, (i64 imm0_15:$imm), 15)>;
5069
5070def : Pat<(sra (i64 (sext GPR32:$Rn)), (i64 imm0_31:$imm)),
5071          (SBFMXri (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$Rn, sub_32),
5072                   (i64 imm0_31:$imm), 31)>;
5073} // AddedComplexity = 20
5074
5075// To truncate, we can simply extract from a subregister.
5076def : Pat<(i32 (trunc GPR64sp:$src)),
5077          (i32 (EXTRACT_SUBREG GPR64sp:$src, sub_32))>;
5078
5079// __builtin_trap() uses the BRK instruction on AArch64.
5080def : Pat<(trap), (BRK 1)>;
5081
5082// Conversions within AdvSIMD types in the same register size are free.
5083// But because we need a consistent lane ordering, in big endian many
5084// conversions require one or more REV instructions.
5085//
5086// Consider a simple memory load followed by a bitconvert then a store.
5087//   v0 = load v2i32
5088//   v1 = BITCAST v2i32 v0 to v4i16
5089//        store v4i16 v2
5090//
5091// In big endian mode every memory access has an implicit byte swap. LDR and
5092// STR do a 64-bit byte swap, whereas LD1/ST1 do a byte swap per lane - that
5093// is, they treat the vector as a sequence of elements to be byte-swapped.
5094// The two pairs of instructions are fundamentally incompatible. We've decided
5095// to use LD1/ST1 only to simplify compiler implementation.
5096//
5097// LD1/ST1 perform the equivalent of a sequence of LDR/STR + REV. This makes
5098// the original code sequence:
5099//   v0 = load v2i32
5100//   v1 = REV v2i32                  (implicit)
5101//   v2 = BITCAST v2i32 v1 to v4i16
5102//   v3 = REV v4i16 v2               (implicit)
5103//        store v4i16 v3
5104//
5105// But this is now broken - the value stored is different to the value loaded
5106// due to lane reordering. To fix this, on every BITCAST we must perform two
5107// other REVs:
5108//   v0 = load v2i32
5109//   v1 = REV v2i32                  (implicit)
5110//   v2 = REV v2i32
5111//   v3 = BITCAST v2i32 v2 to v4i16
5112//   v4 = REV v4i16
5113//   v5 = REV v4i16 v4               (implicit)
5114//        store v4i16 v5
5115//
5116// This means an extra two instructions, but actually in most cases the two REV
5117// instructions can be combined into one. For example:
5118//   (REV64_2s (REV64_4h X)) === (REV32_4h X)
5119//
5120// There is also no 128-bit REV instruction. This must be synthesized with an
5121// EXT instruction.
5122//
5123// Most bitconverts require some sort of conversion. The only exceptions are:
5124//   a) Identity conversions -  vNfX <-> vNiX
5125//   b) Single-lane-to-scalar - v1fX <-> fX or v1iX <-> iX
5126//
5127
5128// Natural vector casts (64 bit)
5129def : Pat<(v8i8 (AArch64NvCast (v2i32 FPR64:$src))), (v8i8 FPR64:$src)>;
5130def : Pat<(v4i16 (AArch64NvCast (v2i32 FPR64:$src))), (v4i16 FPR64:$src)>;
5131def : Pat<(v4f16 (AArch64NvCast (v2i32 FPR64:$src))), (v4f16 FPR64:$src)>;
5132def : Pat<(v2i32 (AArch64NvCast (v2i32 FPR64:$src))), (v2i32 FPR64:$src)>;
5133def : Pat<(v2f32 (AArch64NvCast (v2i32 FPR64:$src))), (v2f32 FPR64:$src)>;
5134def : Pat<(v1i64 (AArch64NvCast (v2i32 FPR64:$src))), (v1i64 FPR64:$src)>;
5135
5136def : Pat<(v8i8 (AArch64NvCast (v4i16 FPR64:$src))), (v8i8 FPR64:$src)>;
5137def : Pat<(v4i16 (AArch64NvCast (v4i16 FPR64:$src))), (v4i16 FPR64:$src)>;
5138def : Pat<(v4f16 (AArch64NvCast (v4i16 FPR64:$src))), (v4f16 FPR64:$src)>;
5139def : Pat<(v2i32 (AArch64NvCast (v4i16 FPR64:$src))), (v2i32 FPR64:$src)>;
5140def : Pat<(v1i64 (AArch64NvCast (v4i16 FPR64:$src))), (v1i64 FPR64:$src)>;
5141
5142def : Pat<(v8i8 (AArch64NvCast (v8i8 FPR64:$src))), (v8i8 FPR64:$src)>;
5143def : Pat<(v4i16 (AArch64NvCast (v8i8 FPR64:$src))), (v4i16 FPR64:$src)>;
5144def : Pat<(v4f16 (AArch64NvCast (v8i8 FPR64:$src))), (v4f16 FPR64:$src)>;
5145def : Pat<(v2i32 (AArch64NvCast (v8i8 FPR64:$src))), (v2i32 FPR64:$src)>;
5146def : Pat<(v1i64 (AArch64NvCast (v8i8 FPR64:$src))), (v1i64 FPR64:$src)>;
5147
5148def : Pat<(v8i8 (AArch64NvCast (f64 FPR64:$src))), (v8i8 FPR64:$src)>;
5149def : Pat<(v4i16 (AArch64NvCast (f64 FPR64:$src))), (v4i16 FPR64:$src)>;
5150def : Pat<(v4f16 (AArch64NvCast (f64 FPR64:$src))), (v4f16 FPR64:$src)>;
5151def : Pat<(v2i32 (AArch64NvCast (f64 FPR64:$src))), (v2i32 FPR64:$src)>;
5152def : Pat<(v2f32 (AArch64NvCast (f64 FPR64:$src))), (v2f32 FPR64:$src)>;
5153def : Pat<(v1i64 (AArch64NvCast (f64 FPR64:$src))), (v1i64 FPR64:$src)>;
5154def : Pat<(v1f64 (AArch64NvCast (f64 FPR64:$src))), (v1f64 FPR64:$src)>;
5155
5156def : Pat<(v8i8 (AArch64NvCast (v2f32 FPR64:$src))), (v8i8 FPR64:$src)>;
5157def : Pat<(v4i16 (AArch64NvCast (v2f32 FPR64:$src))), (v4i16 FPR64:$src)>;
5158def : Pat<(v2i32 (AArch64NvCast (v2f32 FPR64:$src))), (v2i32 FPR64:$src)>;
5159def : Pat<(v2f32 (AArch64NvCast (v2f32 FPR64:$src))), (v2f32 FPR64:$src)>;
5160def : Pat<(v1i64 (AArch64NvCast (v2f32 FPR64:$src))), (v1i64 FPR64:$src)>;
5161
5162// Natural vector casts (128 bit)
5163def : Pat<(v16i8 (AArch64NvCast (v4i32 FPR128:$src))), (v16i8 FPR128:$src)>;
5164def : Pat<(v8i16 (AArch64NvCast (v4i32 FPR128:$src))), (v8i16 FPR128:$src)>;
5165def : Pat<(v8f16 (AArch64NvCast (v4i32 FPR128:$src))), (v8f16 FPR128:$src)>;
5166def : Pat<(v4i32 (AArch64NvCast (v4i32 FPR128:$src))), (v4i32 FPR128:$src)>;
5167def : Pat<(v4f32 (AArch64NvCast (v4i32 FPR128:$src))), (v4f32 FPR128:$src)>;
5168def : Pat<(v2i64 (AArch64NvCast (v4i32 FPR128:$src))), (v2i64 FPR128:$src)>;
5169
5170def : Pat<(v16i8 (AArch64NvCast (v8i16 FPR128:$src))), (v16i8 FPR128:$src)>;
5171def : Pat<(v8i16 (AArch64NvCast (v8i16 FPR128:$src))), (v8i16 FPR128:$src)>;
5172def : Pat<(v8f16 (AArch64NvCast (v8i16 FPR128:$src))), (v8f16 FPR128:$src)>;
5173def : Pat<(v4i32 (AArch64NvCast (v8i16 FPR128:$src))), (v4i32 FPR128:$src)>;
5174def : Pat<(v2i64 (AArch64NvCast (v8i16 FPR128:$src))), (v2i64 FPR128:$src)>;
5175
5176def : Pat<(v16i8 (AArch64NvCast (v16i8 FPR128:$src))), (v16i8 FPR128:$src)>;
5177def : Pat<(v8i16 (AArch64NvCast (v16i8 FPR128:$src))), (v8i16 FPR128:$src)>;
5178def : Pat<(v8f16 (AArch64NvCast (v16i8 FPR128:$src))), (v8f16 FPR128:$src)>;
5179def : Pat<(v4i32 (AArch64NvCast (v16i8 FPR128:$src))), (v4i32 FPR128:$src)>;
5180def : Pat<(v2i64 (AArch64NvCast (v16i8 FPR128:$src))), (v2i64 FPR128:$src)>;
5181
5182def : Pat<(v16i8 (AArch64NvCast (v2i64 FPR128:$src))), (v16i8 FPR128:$src)>;
5183def : Pat<(v8i16 (AArch64NvCast (v2i64 FPR128:$src))), (v8i16 FPR128:$src)>;
5184def : Pat<(v8f16 (AArch64NvCast (v2i64 FPR128:$src))), (v8f16 FPR128:$src)>;
5185def : Pat<(v4i32 (AArch64NvCast (v2i64 FPR128:$src))), (v4i32 FPR128:$src)>;
5186def : Pat<(v2i64 (AArch64NvCast (v2i64 FPR128:$src))), (v2i64 FPR128:$src)>;
5187def : Pat<(v4f32 (AArch64NvCast (v2i64 FPR128:$src))), (v4f32 FPR128:$src)>;
5188def : Pat<(v2f64 (AArch64NvCast (v2i64 FPR128:$src))), (v2f64 FPR128:$src)>;
5189
5190def : Pat<(v16i8 (AArch64NvCast (v4f32 FPR128:$src))), (v16i8 FPR128:$src)>;
5191def : Pat<(v8i16 (AArch64NvCast (v4f32 FPR128:$src))), (v8i16 FPR128:$src)>;
5192def : Pat<(v4i32 (AArch64NvCast (v4f32 FPR128:$src))), (v4i32 FPR128:$src)>;
5193def : Pat<(v4f32 (AArch64NvCast (v4f32 FPR128:$src))), (v4f32 FPR128:$src)>;
5194def : Pat<(v2i64 (AArch64NvCast (v4f32 FPR128:$src))), (v2i64 FPR128:$src)>;
5195
5196def : Pat<(v16i8 (AArch64NvCast (v2f64 FPR128:$src))), (v16i8 FPR128:$src)>;
5197def : Pat<(v8i16 (AArch64NvCast (v2f64 FPR128:$src))), (v8i16 FPR128:$src)>;
5198def : Pat<(v4i32 (AArch64NvCast (v2f64 FPR128:$src))), (v4i32 FPR128:$src)>;
5199def : Pat<(v2i64 (AArch64NvCast (v2f64 FPR128:$src))), (v2i64 FPR128:$src)>;
5200def : Pat<(v2f64 (AArch64NvCast (v2f64 FPR128:$src))), (v2f64 FPR128:$src)>;
5201
5202let Predicates = [IsLE] in {
5203def : Pat<(v8i8  (bitconvert GPR64:$Xn)), (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
5204def : Pat<(v4i16 (bitconvert GPR64:$Xn)), (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
5205def : Pat<(v2i32 (bitconvert GPR64:$Xn)), (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
5206def : Pat<(v4f16 (bitconvert GPR64:$Xn)), (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
5207def : Pat<(v2f32 (bitconvert GPR64:$Xn)), (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
5208
5209def : Pat<(i64 (bitconvert (v8i8  V64:$Vn))),
5210          (COPY_TO_REGCLASS V64:$Vn, GPR64)>;
5211def : Pat<(i64 (bitconvert (v4i16 V64:$Vn))),
5212          (COPY_TO_REGCLASS V64:$Vn, GPR64)>;
5213def : Pat<(i64 (bitconvert (v2i32 V64:$Vn))),
5214          (COPY_TO_REGCLASS V64:$Vn, GPR64)>;
5215def : Pat<(i64 (bitconvert (v4f16 V64:$Vn))),
5216          (COPY_TO_REGCLASS V64:$Vn, GPR64)>;
5217def : Pat<(i64 (bitconvert (v2f32 V64:$Vn))),
5218          (COPY_TO_REGCLASS V64:$Vn, GPR64)>;
5219def : Pat<(i64 (bitconvert (v1f64 V64:$Vn))),
5220          (COPY_TO_REGCLASS V64:$Vn, GPR64)>;
5221}
5222let Predicates = [IsBE] in {
5223def : Pat<(v8i8  (bitconvert GPR64:$Xn)),
5224                 (REV64v8i8 (COPY_TO_REGCLASS GPR64:$Xn, FPR64))>;
5225def : Pat<(v4i16 (bitconvert GPR64:$Xn)),
5226                 (REV64v4i16 (COPY_TO_REGCLASS GPR64:$Xn, FPR64))>;
5227def : Pat<(v2i32 (bitconvert GPR64:$Xn)),
5228                 (REV64v2i32 (COPY_TO_REGCLASS GPR64:$Xn, FPR64))>;
5229def : Pat<(v4f16 (bitconvert GPR64:$Xn)),
5230                 (REV64v4i16 (COPY_TO_REGCLASS GPR64:$Xn, FPR64))>;
5231def : Pat<(v2f32 (bitconvert GPR64:$Xn)),
5232                 (REV64v2i32 (COPY_TO_REGCLASS GPR64:$Xn, FPR64))>;
5233
5234def : Pat<(i64 (bitconvert (v8i8  V64:$Vn))),
5235          (REV64v8i8 (COPY_TO_REGCLASS V64:$Vn, GPR64))>;
5236def : Pat<(i64 (bitconvert (v4i16 V64:$Vn))),
5237          (REV64v4i16 (COPY_TO_REGCLASS V64:$Vn, GPR64))>;
5238def : Pat<(i64 (bitconvert (v2i32 V64:$Vn))),
5239          (REV64v2i32 (COPY_TO_REGCLASS V64:$Vn, GPR64))>;
5240def : Pat<(i64 (bitconvert (v4f16 V64:$Vn))),
5241          (REV64v4i16 (COPY_TO_REGCLASS V64:$Vn, GPR64))>;
5242def : Pat<(i64 (bitconvert (v2f32 V64:$Vn))),
5243          (REV64v2i32 (COPY_TO_REGCLASS V64:$Vn, GPR64))>;
5244}
5245def : Pat<(v1i64 (bitconvert GPR64:$Xn)), (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
5246def : Pat<(v1f64 (bitconvert GPR64:$Xn)), (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
5247def : Pat<(i64 (bitconvert (v1i64 V64:$Vn))),
5248          (COPY_TO_REGCLASS V64:$Vn, GPR64)>;
5249def : Pat<(v1i64 (scalar_to_vector GPR64:$Xn)),
5250          (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
5251def : Pat<(v1f64 (scalar_to_vector GPR64:$Xn)),
5252          (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
5253def : Pat<(v1f64 (scalar_to_vector (f64 FPR64:$Xn))), (v1f64 FPR64:$Xn)>;
5254
5255def : Pat<(f32 (bitconvert (i32 GPR32:$Xn))),
5256          (COPY_TO_REGCLASS GPR32:$Xn, FPR32)>;
5257def : Pat<(i32 (bitconvert (f32 FPR32:$Xn))),
5258          (COPY_TO_REGCLASS FPR32:$Xn, GPR32)>;
5259def : Pat<(f64 (bitconvert (i64 GPR64:$Xn))),
5260          (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
5261def : Pat<(i64 (bitconvert (f64 FPR64:$Xn))),
5262          (COPY_TO_REGCLASS FPR64:$Xn, GPR64)>;
5263def : Pat<(i64 (bitconvert (v1f64 V64:$Vn))),
5264          (COPY_TO_REGCLASS V64:$Vn, GPR64)>;
5265
5266let Predicates = [IsLE] in {
5267def : Pat<(v1i64 (bitconvert (v2i32 FPR64:$src))), (v1i64 FPR64:$src)>;
5268def : Pat<(v1i64 (bitconvert (v4i16 FPR64:$src))), (v1i64 FPR64:$src)>;
5269def : Pat<(v1i64 (bitconvert (v8i8  FPR64:$src))), (v1i64 FPR64:$src)>;
5270def : Pat<(v1i64 (bitconvert (v4f16 FPR64:$src))), (v1i64 FPR64:$src)>;
5271def : Pat<(v1i64 (bitconvert (v2f32 FPR64:$src))), (v1i64 FPR64:$src)>;
5272}
5273let Predicates = [IsBE] in {
5274def : Pat<(v1i64 (bitconvert (v2i32 FPR64:$src))),
5275                             (v1i64 (REV64v2i32 FPR64:$src))>;
5276def : Pat<(v1i64 (bitconvert (v4i16 FPR64:$src))),
5277                             (v1i64 (REV64v4i16 FPR64:$src))>;
5278def : Pat<(v1i64 (bitconvert (v8i8  FPR64:$src))),
5279                             (v1i64 (REV64v8i8 FPR64:$src))>;
5280def : Pat<(v1i64 (bitconvert (v4f16 FPR64:$src))),
5281                             (v1i64 (REV64v4i16 FPR64:$src))>;
5282def : Pat<(v1i64 (bitconvert (v2f32 FPR64:$src))),
5283                             (v1i64 (REV64v2i32 FPR64:$src))>;
5284}
5285def : Pat<(v1i64 (bitconvert (v1f64 FPR64:$src))), (v1i64 FPR64:$src)>;
5286def : Pat<(v1i64 (bitconvert (f64   FPR64:$src))), (v1i64 FPR64:$src)>;
5287
5288let Predicates = [IsLE] in {
5289def : Pat<(v2i32 (bitconvert (v1i64 FPR64:$src))), (v2i32 FPR64:$src)>;
5290def : Pat<(v2i32 (bitconvert (v4i16 FPR64:$src))), (v2i32 FPR64:$src)>;
5291def : Pat<(v2i32 (bitconvert (v8i8  FPR64:$src))), (v2i32 FPR64:$src)>;
5292def : Pat<(v2i32 (bitconvert (f64   FPR64:$src))), (v2i32 FPR64:$src)>;
5293def : Pat<(v2i32 (bitconvert (v1f64 FPR64:$src))), (v2i32 FPR64:$src)>;
5294def : Pat<(v2i32 (bitconvert (v4f16 FPR64:$src))), (v2i32 FPR64:$src)>;
5295}
5296let Predicates = [IsBE] in {
5297def : Pat<(v2i32 (bitconvert (v1i64 FPR64:$src))),
5298                             (v2i32 (REV64v2i32 FPR64:$src))>;
5299def : Pat<(v2i32 (bitconvert (v4i16 FPR64:$src))),
5300                             (v2i32 (REV32v4i16 FPR64:$src))>;
5301def : Pat<(v2i32 (bitconvert (v8i8  FPR64:$src))),
5302                             (v2i32 (REV32v8i8 FPR64:$src))>;
5303def : Pat<(v2i32 (bitconvert (f64   FPR64:$src))),
5304                             (v2i32 (REV64v2i32 FPR64:$src))>;
5305def : Pat<(v2i32 (bitconvert (v1f64 FPR64:$src))),
5306                             (v2i32 (REV64v2i32 FPR64:$src))>;
5307def : Pat<(v2i32 (bitconvert (v4f16 FPR64:$src))),
5308                             (v2i32 (REV64v4i16 FPR64:$src))>;
5309}
5310def : Pat<(v2i32 (bitconvert (v2f32 FPR64:$src))), (v2i32 FPR64:$src)>;
5311
5312let Predicates = [IsLE] in {
5313def : Pat<(v4i16 (bitconvert (v1i64 FPR64:$src))), (v4i16 FPR64:$src)>;
5314def : Pat<(v4i16 (bitconvert (v2i32 FPR64:$src))), (v4i16 FPR64:$src)>;
5315def : Pat<(v4i16 (bitconvert (v8i8  FPR64:$src))), (v4i16 FPR64:$src)>;
5316def : Pat<(v4i16 (bitconvert (f64   FPR64:$src))), (v4i16 FPR64:$src)>;
5317def : Pat<(v4i16 (bitconvert (v4f16 FPR64:$src))), (v4i16 FPR64:$src)>;
5318def : Pat<(v4i16 (bitconvert (v2f32 FPR64:$src))), (v4i16 FPR64:$src)>;
5319def : Pat<(v4i16 (bitconvert (v1f64 FPR64:$src))), (v4i16 FPR64:$src)>;
5320}
5321let Predicates = [IsBE] in {
5322def : Pat<(v4i16 (bitconvert (v1i64 FPR64:$src))),
5323                             (v4i16 (REV64v4i16 FPR64:$src))>;
5324def : Pat<(v4i16 (bitconvert (v2i32 FPR64:$src))),
5325                             (v4i16 (REV32v4i16 FPR64:$src))>;
5326def : Pat<(v4i16 (bitconvert (v8i8  FPR64:$src))),
5327                             (v4i16 (REV16v8i8 FPR64:$src))>;
5328def : Pat<(v4i16 (bitconvert (f64   FPR64:$src))),
5329                             (v4i16 (REV64v4i16 FPR64:$src))>;
5330def : Pat<(v4i16 (bitconvert (v4f16 FPR64:$src))),
5331                             (v4i16 (REV32v4i16 FPR64:$src))>;
5332def : Pat<(v4i16 (bitconvert (v2f32 FPR64:$src))),
5333                             (v4i16 (REV32v4i16 FPR64:$src))>;
5334def : Pat<(v4i16 (bitconvert (v1f64 FPR64:$src))),
5335                             (v4i16 (REV64v4i16 FPR64:$src))>;
5336}
5337
5338let Predicates = [IsLE] in {
5339def : Pat<(v4f16 (bitconvert (v1i64 FPR64:$src))), (v4f16 FPR64:$src)>;
5340def : Pat<(v4f16 (bitconvert (v2i32 FPR64:$src))), (v4f16 FPR64:$src)>;
5341def : Pat<(v4f16 (bitconvert (v4i16 FPR64:$src))), (v4f16 FPR64:$src)>;
5342def : Pat<(v4f16 (bitconvert (v8i8  FPR64:$src))), (v4f16 FPR64:$src)>;
5343def : Pat<(v4f16 (bitconvert (f64   FPR64:$src))), (v4f16 FPR64:$src)>;
5344def : Pat<(v4f16 (bitconvert (v2f32 FPR64:$src))), (v4f16 FPR64:$src)>;
5345def : Pat<(v4f16 (bitconvert (v1f64 FPR64:$src))), (v4f16 FPR64:$src)>;
5346}
5347let Predicates = [IsBE] in {
5348def : Pat<(v4f16 (bitconvert (v1i64 FPR64:$src))),
5349                             (v4f16 (REV64v4i16 FPR64:$src))>;
5350def : Pat<(v4f16 (bitconvert (v2i32 FPR64:$src))),
5351                             (v4f16 (REV64v4i16 FPR64:$src))>;
5352def : Pat<(v4f16 (bitconvert (v4i16 FPR64:$src))),
5353                             (v4f16 (REV64v4i16 FPR64:$src))>;
5354def : Pat<(v4f16 (bitconvert (v8i8  FPR64:$src))),
5355                             (v4f16 (REV16v8i8 FPR64:$src))>;
5356def : Pat<(v4f16 (bitconvert (f64   FPR64:$src))),
5357                             (v4f16 (REV64v4i16 FPR64:$src))>;
5358def : Pat<(v4f16 (bitconvert (v2f32 FPR64:$src))),
5359                             (v4f16 (REV64v4i16 FPR64:$src))>;
5360def : Pat<(v4f16 (bitconvert (v1f64 FPR64:$src))),
5361                             (v4f16 (REV64v4i16 FPR64:$src))>;
5362}
5363
5364
5365
5366let Predicates = [IsLE] in {
5367def : Pat<(v8i8  (bitconvert (v1i64 FPR64:$src))), (v8i8  FPR64:$src)>;
5368def : Pat<(v8i8  (bitconvert (v2i32 FPR64:$src))), (v8i8  FPR64:$src)>;
5369def : Pat<(v8i8  (bitconvert (v4i16 FPR64:$src))), (v8i8  FPR64:$src)>;
5370def : Pat<(v8i8  (bitconvert (f64   FPR64:$src))), (v8i8  FPR64:$src)>;
5371def : Pat<(v8i8  (bitconvert (v2f32 FPR64:$src))), (v8i8  FPR64:$src)>;
5372def : Pat<(v8i8  (bitconvert (v1f64 FPR64:$src))), (v8i8  FPR64:$src)>;
5373def : Pat<(v8i8  (bitconvert (v4f16 FPR64:$src))), (v8i8  FPR64:$src)>;
5374}
5375let Predicates = [IsBE] in {
5376def : Pat<(v8i8  (bitconvert (v1i64 FPR64:$src))),
5377                             (v8i8 (REV64v8i8 FPR64:$src))>;
5378def : Pat<(v8i8  (bitconvert (v2i32 FPR64:$src))),
5379                             (v8i8 (REV32v8i8 FPR64:$src))>;
5380def : Pat<(v8i8  (bitconvert (v4i16 FPR64:$src))),
5381                             (v8i8 (REV16v8i8 FPR64:$src))>;
5382def : Pat<(v8i8  (bitconvert (f64   FPR64:$src))),
5383                             (v8i8 (REV64v8i8 FPR64:$src))>;
5384def : Pat<(v8i8  (bitconvert (v2f32 FPR64:$src))),
5385                             (v8i8 (REV32v8i8 FPR64:$src))>;
5386def : Pat<(v8i8  (bitconvert (v1f64 FPR64:$src))),
5387                             (v8i8 (REV64v8i8 FPR64:$src))>;
5388def : Pat<(v8i8  (bitconvert (v4f16 FPR64:$src))),
5389                             (v8i8 (REV16v8i8 FPR64:$src))>;
5390}
5391
5392let Predicates = [IsLE] in {
5393def : Pat<(f64   (bitconvert (v2i32 FPR64:$src))), (f64   FPR64:$src)>;
5394def : Pat<(f64   (bitconvert (v4i16 FPR64:$src))), (f64   FPR64:$src)>;
5395def : Pat<(f64   (bitconvert (v2f32 FPR64:$src))), (f64   FPR64:$src)>;
5396def : Pat<(f64   (bitconvert (v8i8  FPR64:$src))), (f64   FPR64:$src)>;
5397def : Pat<(f64   (bitconvert (v4f16 FPR64:$src))), (f64   FPR64:$src)>;
5398}
5399let Predicates = [IsBE] in {
5400def : Pat<(f64   (bitconvert (v2i32 FPR64:$src))),
5401                             (f64 (REV64v2i32 FPR64:$src))>;
5402def : Pat<(f64   (bitconvert (v4i16 FPR64:$src))),
5403                             (f64 (REV64v4i16 FPR64:$src))>;
5404def : Pat<(f64   (bitconvert (v2f32 FPR64:$src))),
5405                             (f64 (REV64v2i32 FPR64:$src))>;
5406def : Pat<(f64   (bitconvert (v8i8  FPR64:$src))),
5407                             (f64 (REV64v8i8 FPR64:$src))>;
5408def : Pat<(f64   (bitconvert (v4f16 FPR64:$src))),
5409                             (f64 (REV64v4i16 FPR64:$src))>;
5410}
5411def : Pat<(f64   (bitconvert (v1i64 FPR64:$src))), (f64   FPR64:$src)>;
5412def : Pat<(f64   (bitconvert (v1f64 FPR64:$src))), (f64   FPR64:$src)>;
5413
5414let Predicates = [IsLE] in {
5415def : Pat<(v1f64 (bitconvert (v2i32 FPR64:$src))), (v1f64 FPR64:$src)>;
5416def : Pat<(v1f64 (bitconvert (v4i16 FPR64:$src))), (v1f64 FPR64:$src)>;
5417def : Pat<(v1f64 (bitconvert (v8i8  FPR64:$src))), (v1f64 FPR64:$src)>;
5418def : Pat<(v1f64 (bitconvert (v2f32 FPR64:$src))), (v1f64 FPR64:$src)>;
5419def : Pat<(v1f64 (bitconvert (v4f16 FPR64:$src))), (v1f64 FPR64:$src)>;
5420}
5421let Predicates = [IsBE] in {
5422def : Pat<(v1f64 (bitconvert (v2i32 FPR64:$src))),
5423                             (v1f64 (REV64v2i32 FPR64:$src))>;
5424def : Pat<(v1f64 (bitconvert (v4i16 FPR64:$src))),
5425                             (v1f64 (REV64v4i16 FPR64:$src))>;
5426def : Pat<(v1f64 (bitconvert (v8i8  FPR64:$src))),
5427                             (v1f64 (REV64v8i8 FPR64:$src))>;
5428def : Pat<(v1f64 (bitconvert (v2f32 FPR64:$src))),
5429                             (v1f64 (REV64v2i32 FPR64:$src))>;
5430def : Pat<(v1f64 (bitconvert (v4f16 FPR64:$src))),
5431                             (v1f64 (REV64v4i16 FPR64:$src))>;
5432}
5433def : Pat<(v1f64 (bitconvert (v1i64 FPR64:$src))), (v1f64 FPR64:$src)>;
5434def : Pat<(v1f64 (bitconvert (f64   FPR64:$src))), (v1f64 FPR64:$src)>;
5435
5436let Predicates = [IsLE] in {
5437def : Pat<(v2f32 (bitconvert (v1i64 FPR64:$src))), (v2f32 FPR64:$src)>;
5438def : Pat<(v2f32 (bitconvert (v4i16 FPR64:$src))), (v2f32 FPR64:$src)>;
5439def : Pat<(v2f32 (bitconvert (v8i8  FPR64:$src))), (v2f32 FPR64:$src)>;
5440def : Pat<(v2f32 (bitconvert (v1f64 FPR64:$src))), (v2f32 FPR64:$src)>;
5441def : Pat<(v2f32 (bitconvert (f64   FPR64:$src))), (v2f32 FPR64:$src)>;
5442def : Pat<(v2f32 (bitconvert (v4f16 FPR64:$src))), (v2f32 FPR64:$src)>;
5443}
5444let Predicates = [IsBE] in {
5445def : Pat<(v2f32 (bitconvert (v1i64 FPR64:$src))),
5446                             (v2f32 (REV64v2i32 FPR64:$src))>;
5447def : Pat<(v2f32 (bitconvert (v4i16 FPR64:$src))),
5448                             (v2f32 (REV32v4i16 FPR64:$src))>;
5449def : Pat<(v2f32 (bitconvert (v8i8  FPR64:$src))),
5450                             (v2f32 (REV32v8i8 FPR64:$src))>;
5451def : Pat<(v2f32 (bitconvert (v1f64 FPR64:$src))),
5452                             (v2f32 (REV64v2i32 FPR64:$src))>;
5453def : Pat<(v2f32 (bitconvert (f64   FPR64:$src))),
5454                             (v2f32 (REV64v2i32 FPR64:$src))>;
5455def : Pat<(v2f32 (bitconvert (v4f16 FPR64:$src))),
5456                             (v2f32 (REV64v4i16 FPR64:$src))>;
5457}
5458def : Pat<(v2f32 (bitconvert (v2i32 FPR64:$src))), (v2f32 FPR64:$src)>;
5459
5460let Predicates = [IsLE] in {
5461def : Pat<(f128 (bitconvert (v2i64 FPR128:$src))), (f128 FPR128:$src)>;
5462def : Pat<(f128 (bitconvert (v4i32 FPR128:$src))), (f128 FPR128:$src)>;
5463def : Pat<(f128 (bitconvert (v8i16 FPR128:$src))), (f128 FPR128:$src)>;
5464def : Pat<(f128 (bitconvert (v2f64 FPR128:$src))), (f128 FPR128:$src)>;
5465def : Pat<(f128 (bitconvert (v4f32 FPR128:$src))), (f128 FPR128:$src)>;
5466def : Pat<(f128 (bitconvert (v8f16 FPR128:$src))), (f128 FPR128:$src)>;
5467def : Pat<(f128 (bitconvert (v16i8 FPR128:$src))), (f128 FPR128:$src)>;
5468}
5469let Predicates = [IsBE] in {
5470def : Pat<(f128 (bitconvert (v2i64 FPR128:$src))),
5471                            (f128 (EXTv16i8 FPR128:$src, FPR128:$src, (i32 8)))>;
5472def : Pat<(f128 (bitconvert (v4i32 FPR128:$src))),
5473                            (f128 (EXTv16i8 (REV64v4i32 FPR128:$src),
5474                                            (REV64v4i32 FPR128:$src), (i32 8)))>;
5475def : Pat<(f128 (bitconvert (v8i16 FPR128:$src))),
5476                            (f128 (EXTv16i8 (REV64v8i16 FPR128:$src),
5477                                            (REV64v8i16 FPR128:$src), (i32 8)))>;
5478def : Pat<(f128 (bitconvert (v8f16 FPR128:$src))),
5479                            (f128 (EXTv16i8 (REV64v8i16 FPR128:$src),
5480                                            (REV64v8i16 FPR128:$src), (i32 8)))>;
5481def : Pat<(f128 (bitconvert (v2f64 FPR128:$src))),
5482                            (f128 (EXTv16i8 FPR128:$src, FPR128:$src, (i32 8)))>;
5483def : Pat<(f128 (bitconvert (v4f32 FPR128:$src))),
5484                            (f128 (EXTv16i8 (REV64v4i32 FPR128:$src),
5485                                            (REV64v4i32 FPR128:$src), (i32 8)))>;
5486def : Pat<(f128 (bitconvert (v16i8 FPR128:$src))),
5487                            (f128 (EXTv16i8 (REV64v16i8 FPR128:$src),
5488                                            (REV64v16i8 FPR128:$src), (i32 8)))>;
5489}
5490
5491let Predicates = [IsLE] in {
5492def : Pat<(v2f64 (bitconvert (f128  FPR128:$src))), (v2f64 FPR128:$src)>;
5493def : Pat<(v2f64 (bitconvert (v4i32 FPR128:$src))), (v2f64 FPR128:$src)>;
5494def : Pat<(v2f64 (bitconvert (v8i16 FPR128:$src))), (v2f64 FPR128:$src)>;
5495def : Pat<(v2f64 (bitconvert (v8f16 FPR128:$src))), (v2f64 FPR128:$src)>;
5496def : Pat<(v2f64 (bitconvert (v16i8 FPR128:$src))), (v2f64 FPR128:$src)>;
5497def : Pat<(v2f64 (bitconvert (v4f32 FPR128:$src))), (v2f64 FPR128:$src)>;
5498}
5499let Predicates = [IsBE] in {
5500def : Pat<(v2f64 (bitconvert (f128  FPR128:$src))),
5501                             (v2f64 (EXTv16i8 FPR128:$src,
5502                                              FPR128:$src, (i32 8)))>;
5503def : Pat<(v2f64 (bitconvert (v4i32 FPR128:$src))),
5504                             (v2f64 (REV64v4i32 FPR128:$src))>;
5505def : Pat<(v2f64 (bitconvert (v8i16 FPR128:$src))),
5506                             (v2f64 (REV64v8i16 FPR128:$src))>;
5507def : Pat<(v2f64 (bitconvert (v8f16 FPR128:$src))),
5508                             (v2f64 (REV64v8i16 FPR128:$src))>;
5509def : Pat<(v2f64 (bitconvert (v16i8 FPR128:$src))),
5510                             (v2f64 (REV64v16i8 FPR128:$src))>;
5511def : Pat<(v2f64 (bitconvert (v4f32 FPR128:$src))),
5512                             (v2f64 (REV64v4i32 FPR128:$src))>;
5513}
5514def : Pat<(v2f64 (bitconvert (v2i64 FPR128:$src))), (v2f64 FPR128:$src)>;
5515
5516let Predicates = [IsLE] in {
5517def : Pat<(v4f32 (bitconvert (f128  FPR128:$src))), (v4f32 FPR128:$src)>;
5518def : Pat<(v4f32 (bitconvert (v8i16 FPR128:$src))), (v4f32 FPR128:$src)>;
5519def : Pat<(v4f32 (bitconvert (v8f16 FPR128:$src))), (v4f32 FPR128:$src)>;
5520def : Pat<(v4f32 (bitconvert (v16i8 FPR128:$src))), (v4f32 FPR128:$src)>;
5521def : Pat<(v4f32 (bitconvert (v2i64 FPR128:$src))), (v4f32 FPR128:$src)>;
5522def : Pat<(v4f32 (bitconvert (v2f64 FPR128:$src))), (v4f32 FPR128:$src)>;
5523}
5524let Predicates = [IsBE] in {
5525def : Pat<(v4f32 (bitconvert (f128  FPR128:$src))),
5526                             (v4f32 (EXTv16i8 (REV64v4i32 FPR128:$src),
5527                                    (REV64v4i32 FPR128:$src), (i32 8)))>;
5528def : Pat<(v4f32 (bitconvert (v8i16 FPR128:$src))),
5529                             (v4f32 (REV32v8i16 FPR128:$src))>;
5530def : Pat<(v4f32 (bitconvert (v8f16 FPR128:$src))),
5531                             (v4f32 (REV32v8i16 FPR128:$src))>;
5532def : Pat<(v4f32 (bitconvert (v16i8 FPR128:$src))),
5533                             (v4f32 (REV32v16i8 FPR128:$src))>;
5534def : Pat<(v4f32 (bitconvert (v2i64 FPR128:$src))),
5535                             (v4f32 (REV64v4i32 FPR128:$src))>;
5536def : Pat<(v4f32 (bitconvert (v2f64 FPR128:$src))),
5537                             (v4f32 (REV64v4i32 FPR128:$src))>;
5538}
5539def : Pat<(v4f32 (bitconvert (v4i32 FPR128:$src))), (v4f32 FPR128:$src)>;
5540
5541let Predicates = [IsLE] in {
5542def : Pat<(v2i64 (bitconvert (f128  FPR128:$src))), (v2i64 FPR128:$src)>;
5543def : Pat<(v2i64 (bitconvert (v4i32 FPR128:$src))), (v2i64 FPR128:$src)>;
5544def : Pat<(v2i64 (bitconvert (v8i16 FPR128:$src))), (v2i64 FPR128:$src)>;
5545def : Pat<(v2i64 (bitconvert (v16i8 FPR128:$src))), (v2i64 FPR128:$src)>;
5546def : Pat<(v2i64 (bitconvert (v4f32 FPR128:$src))), (v2i64 FPR128:$src)>;
5547def : Pat<(v2i64 (bitconvert (v8f16 FPR128:$src))), (v2i64 FPR128:$src)>;
5548}
5549let Predicates = [IsBE] in {
5550def : Pat<(v2i64 (bitconvert (f128  FPR128:$src))),
5551                             (v2i64 (EXTv16i8 FPR128:$src,
5552                                              FPR128:$src, (i32 8)))>;
5553def : Pat<(v2i64 (bitconvert (v4i32 FPR128:$src))),
5554                             (v2i64 (REV64v4i32 FPR128:$src))>;
5555def : Pat<(v2i64 (bitconvert (v8i16 FPR128:$src))),
5556                             (v2i64 (REV64v8i16 FPR128:$src))>;
5557def : Pat<(v2i64 (bitconvert (v16i8 FPR128:$src))),
5558                             (v2i64 (REV64v16i8 FPR128:$src))>;
5559def : Pat<(v2i64 (bitconvert (v4f32 FPR128:$src))),
5560                             (v2i64 (REV64v4i32 FPR128:$src))>;
5561def : Pat<(v2i64 (bitconvert (v8f16 FPR128:$src))),
5562                             (v2i64 (REV64v8i16 FPR128:$src))>;
5563}
5564def : Pat<(v2i64 (bitconvert (v2f64 FPR128:$src))), (v2i64 FPR128:$src)>;
5565
5566let Predicates = [IsLE] in {
5567def : Pat<(v4i32 (bitconvert (f128  FPR128:$src))), (v4i32 FPR128:$src)>;
5568def : Pat<(v4i32 (bitconvert (v2i64 FPR128:$src))), (v4i32 FPR128:$src)>;
5569def : Pat<(v4i32 (bitconvert (v8i16 FPR128:$src))), (v4i32 FPR128:$src)>;
5570def : Pat<(v4i32 (bitconvert (v16i8 FPR128:$src))), (v4i32 FPR128:$src)>;
5571def : Pat<(v4i32 (bitconvert (v2f64 FPR128:$src))), (v4i32 FPR128:$src)>;
5572def : Pat<(v4i32 (bitconvert (v8f16 FPR128:$src))), (v4i32 FPR128:$src)>;
5573}
5574let Predicates = [IsBE] in {
5575def : Pat<(v4i32 (bitconvert (f128  FPR128:$src))),
5576                             (v4i32 (EXTv16i8 (REV64v4i32 FPR128:$src),
5577                                              (REV64v4i32 FPR128:$src),
5578                                              (i32 8)))>;
5579def : Pat<(v4i32 (bitconvert (v2i64 FPR128:$src))),
5580                             (v4i32 (REV64v4i32 FPR128:$src))>;
5581def : Pat<(v4i32 (bitconvert (v8i16 FPR128:$src))),
5582                             (v4i32 (REV32v8i16 FPR128:$src))>;
5583def : Pat<(v4i32 (bitconvert (v16i8 FPR128:$src))),
5584                             (v4i32 (REV32v16i8 FPR128:$src))>;
5585def : Pat<(v4i32 (bitconvert (v2f64 FPR128:$src))),
5586                             (v4i32 (REV64v4i32 FPR128:$src))>;
5587def : Pat<(v4i32 (bitconvert (v8f16 FPR128:$src))),
5588                             (v4i32 (REV32v8i16 FPR128:$src))>;
5589}
5590def : Pat<(v4i32 (bitconvert (v4f32 FPR128:$src))), (v4i32 FPR128:$src)>;
5591
5592let Predicates = [IsLE] in {
5593def : Pat<(v8i16 (bitconvert (f128  FPR128:$src))), (v8i16 FPR128:$src)>;
5594def : Pat<(v8i16 (bitconvert (v2i64 FPR128:$src))), (v8i16 FPR128:$src)>;
5595def : Pat<(v8i16 (bitconvert (v4i32 FPR128:$src))), (v8i16 FPR128:$src)>;
5596def : Pat<(v8i16 (bitconvert (v16i8 FPR128:$src))), (v8i16 FPR128:$src)>;
5597def : Pat<(v8i16 (bitconvert (v2f64 FPR128:$src))), (v8i16 FPR128:$src)>;
5598def : Pat<(v8i16 (bitconvert (v4f32 FPR128:$src))), (v8i16 FPR128:$src)>;
5599def : Pat<(v8i16 (bitconvert (v8f16 FPR128:$src))), (v8i16 FPR128:$src)>;
5600}
5601let Predicates = [IsBE] in {
5602def : Pat<(v8i16 (bitconvert (f128  FPR128:$src))),
5603                             (v8i16 (EXTv16i8 (REV64v8i16 FPR128:$src),
5604                                              (REV64v8i16 FPR128:$src),
5605                                              (i32 8)))>;
5606def : Pat<(v8i16 (bitconvert (v2i64 FPR128:$src))),
5607                             (v8i16 (REV64v8i16 FPR128:$src))>;
5608def : Pat<(v8i16 (bitconvert (v4i32 FPR128:$src))),
5609                             (v8i16 (REV32v8i16 FPR128:$src))>;
5610def : Pat<(v8i16 (bitconvert (v16i8 FPR128:$src))),
5611                             (v8i16 (REV16v16i8 FPR128:$src))>;
5612def : Pat<(v8i16 (bitconvert (v2f64 FPR128:$src))),
5613                             (v8i16 (REV64v8i16 FPR128:$src))>;
5614def : Pat<(v8i16 (bitconvert (v4f32 FPR128:$src))),
5615                             (v8i16 (REV32v8i16 FPR128:$src))>;
5616def : Pat<(v8i16 (bitconvert (v8f16 FPR128:$src))),
5617                             (v8i16 (REV32v8i16 FPR128:$src))>;
5618}
5619
5620let Predicates = [IsLE] in {
5621def : Pat<(v8f16 (bitconvert (f128  FPR128:$src))), (v8f16 FPR128:$src)>;
5622def : Pat<(v8f16 (bitconvert (v2i64 FPR128:$src))), (v8f16 FPR128:$src)>;
5623def : Pat<(v8f16 (bitconvert (v4i32 FPR128:$src))), (v8f16 FPR128:$src)>;
5624def : Pat<(v8f16 (bitconvert (v8i16 FPR128:$src))), (v8f16 FPR128:$src)>;
5625def : Pat<(v8f16 (bitconvert (v16i8 FPR128:$src))), (v8f16 FPR128:$src)>;
5626def : Pat<(v8f16 (bitconvert (v2f64 FPR128:$src))), (v8f16 FPR128:$src)>;
5627def : Pat<(v8f16 (bitconvert (v4f32 FPR128:$src))), (v8f16 FPR128:$src)>;
5628}
5629let Predicates = [IsBE] in {
5630def : Pat<(v8f16 (bitconvert (f128  FPR128:$src))),
5631                             (v8f16 (EXTv16i8 (REV64v8i16 FPR128:$src),
5632                                              (REV64v8i16 FPR128:$src),
5633                                              (i32 8)))>;
5634def : Pat<(v8f16 (bitconvert (v2i64 FPR128:$src))),
5635                             (v8f16 (REV64v8i16 FPR128:$src))>;
5636def : Pat<(v8f16 (bitconvert (v4i32 FPR128:$src))),
5637                             (v8f16 (REV32v8i16 FPR128:$src))>;
5638def : Pat<(v8f16 (bitconvert (v8i16 FPR128:$src))),
5639                             (v8f16 (REV64v8i16 FPR128:$src))>;
5640def : Pat<(v8f16 (bitconvert (v16i8 FPR128:$src))),
5641                             (v8f16 (REV16v16i8 FPR128:$src))>;
5642def : Pat<(v8f16 (bitconvert (v2f64 FPR128:$src))),
5643                             (v8f16 (REV64v8i16 FPR128:$src))>;
5644def : Pat<(v8f16 (bitconvert (v4f32 FPR128:$src))),
5645                             (v8f16 (REV32v8i16 FPR128:$src))>;
5646}
5647
5648let Predicates = [IsLE] in {
5649def : Pat<(v16i8 (bitconvert (f128  FPR128:$src))), (v16i8 FPR128:$src)>;
5650def : Pat<(v16i8 (bitconvert (v2i64 FPR128:$src))), (v16i8 FPR128:$src)>;
5651def : Pat<(v16i8 (bitconvert (v4i32 FPR128:$src))), (v16i8 FPR128:$src)>;
5652def : Pat<(v16i8 (bitconvert (v8i16 FPR128:$src))), (v16i8 FPR128:$src)>;
5653def : Pat<(v16i8 (bitconvert (v2f64 FPR128:$src))), (v16i8 FPR128:$src)>;
5654def : Pat<(v16i8 (bitconvert (v4f32 FPR128:$src))), (v16i8 FPR128:$src)>;
5655def : Pat<(v16i8 (bitconvert (v8f16 FPR128:$src))), (v16i8 FPR128:$src)>;
5656}
5657let Predicates = [IsBE] in {
5658def : Pat<(v16i8 (bitconvert (f128  FPR128:$src))),
5659                             (v16i8 (EXTv16i8 (REV64v16i8 FPR128:$src),
5660                                              (REV64v16i8 FPR128:$src),
5661                                              (i32 8)))>;
5662def : Pat<(v16i8 (bitconvert (v2i64 FPR128:$src))),
5663                             (v16i8 (REV64v16i8 FPR128:$src))>;
5664def : Pat<(v16i8 (bitconvert (v4i32 FPR128:$src))),
5665                             (v16i8 (REV32v16i8 FPR128:$src))>;
5666def : Pat<(v16i8 (bitconvert (v8i16 FPR128:$src))),
5667                             (v16i8 (REV16v16i8 FPR128:$src))>;
5668def : Pat<(v16i8 (bitconvert (v2f64 FPR128:$src))),
5669                             (v16i8 (REV64v16i8 FPR128:$src))>;
5670def : Pat<(v16i8 (bitconvert (v4f32 FPR128:$src))),
5671                             (v16i8 (REV32v16i8 FPR128:$src))>;
5672def : Pat<(v16i8 (bitconvert (v8f16 FPR128:$src))),
5673                             (v16i8 (REV16v16i8 FPR128:$src))>;
5674}
5675
5676def : Pat<(v8i8 (extract_subvector (v16i8 FPR128:$Rn), (i64 1))),
5677          (EXTRACT_SUBREG (DUPv2i64lane FPR128:$Rn, 1), dsub)>;
5678def : Pat<(v4i16 (extract_subvector (v8i16 FPR128:$Rn), (i64 1))),
5679          (EXTRACT_SUBREG (DUPv2i64lane FPR128:$Rn, 1), dsub)>;
5680def : Pat<(v2i32 (extract_subvector (v4i32 FPR128:$Rn), (i64 1))),
5681          (EXTRACT_SUBREG (DUPv2i64lane FPR128:$Rn, 1), dsub)>;
5682def : Pat<(v1i64 (extract_subvector (v2i64 FPR128:$Rn), (i64 1))),
5683          (EXTRACT_SUBREG (DUPv2i64lane FPR128:$Rn, 1), dsub)>;
5684
5685// A 64-bit subvector insert to the first 128-bit vector position
5686// is a subregister copy that needs no instruction.
5687def : Pat<(insert_subvector undef, (v1i64 FPR64:$src), (i32 0)),
5688          (INSERT_SUBREG (v2i64 (IMPLICIT_DEF)), FPR64:$src, dsub)>;
5689def : Pat<(insert_subvector undef, (v1f64 FPR64:$src), (i32 0)),
5690          (INSERT_SUBREG (v2f64 (IMPLICIT_DEF)), FPR64:$src, dsub)>;
5691def : Pat<(insert_subvector undef, (v2i32 FPR64:$src), (i32 0)),
5692          (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), FPR64:$src, dsub)>;
5693def : Pat<(insert_subvector undef, (v2f32 FPR64:$src), (i32 0)),
5694          (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), FPR64:$src, dsub)>;
5695def : Pat<(insert_subvector undef, (v4i16 FPR64:$src), (i32 0)),
5696          (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)), FPR64:$src, dsub)>;
5697def : Pat<(insert_subvector undef, (v4f16 FPR64:$src), (i32 0)),
5698          (INSERT_SUBREG (v8f16 (IMPLICIT_DEF)), FPR64:$src, dsub)>;
5699def : Pat<(insert_subvector undef, (v8i8 FPR64:$src), (i32 0)),
5700          (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)), FPR64:$src, dsub)>;
5701
5702// Use pair-wise add instructions when summing up the lanes for v2f64, v2i64
5703// or v2f32.
5704def : Pat<(i64 (add (vector_extract (v2i64 FPR128:$Rn), (i64 0)),
5705                    (vector_extract (v2i64 FPR128:$Rn), (i64 1)))),
5706           (i64 (ADDPv2i64p (v2i64 FPR128:$Rn)))>;
5707def : Pat<(f64 (fadd (vector_extract (v2f64 FPR128:$Rn), (i64 0)),
5708                     (vector_extract (v2f64 FPR128:$Rn), (i64 1)))),
5709           (f64 (FADDPv2i64p (v2f64 FPR128:$Rn)))>;
5710    // vector_extract on 64-bit vectors gets promoted to a 128 bit vector,
5711    // so we match on v4f32 here, not v2f32. This will also catch adding
5712    // the low two lanes of a true v4f32 vector.
5713def : Pat<(fadd (vector_extract (v4f32 FPR128:$Rn), (i64 0)),
5714                (vector_extract (v4f32 FPR128:$Rn), (i64 1))),
5715          (f32 (FADDPv2i32p (EXTRACT_SUBREG FPR128:$Rn, dsub)))>;
5716
5717// Scalar 64-bit shifts in FPR64 registers.
5718def : Pat<(i64 (int_aarch64_neon_sshl (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
5719          (SSHLv1i64 FPR64:$Rn, FPR64:$Rm)>;
5720def : Pat<(i64 (int_aarch64_neon_ushl (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
5721          (USHLv1i64 FPR64:$Rn, FPR64:$Rm)>;
5722def : Pat<(i64 (int_aarch64_neon_srshl (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
5723          (SRSHLv1i64 FPR64:$Rn, FPR64:$Rm)>;
5724def : Pat<(i64 (int_aarch64_neon_urshl (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
5725          (URSHLv1i64 FPR64:$Rn, FPR64:$Rm)>;
5726
5727// Tail call return handling. These are all compiler pseudo-instructions,
5728// so no encoding information or anything like that.
5729let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [SP] in {
5730  def TCRETURNdi : Pseudo<(outs), (ins i64imm:$dst, i32imm:$FPDiff),[]>;
5731  def TCRETURNri : Pseudo<(outs), (ins tcGPR64:$dst, i32imm:$FPDiff), []>;
5732}
5733
5734def : Pat<(AArch64tcret tcGPR64:$dst, (i32 timm:$FPDiff)),
5735          (TCRETURNri tcGPR64:$dst, imm:$FPDiff)>;
5736def : Pat<(AArch64tcret tglobaladdr:$dst, (i32 timm:$FPDiff)),
5737          (TCRETURNdi texternalsym:$dst, imm:$FPDiff)>;
5738def : Pat<(AArch64tcret texternalsym:$dst, (i32 timm:$FPDiff)),
5739          (TCRETURNdi texternalsym:$dst, imm:$FPDiff)>;
5740
5741include "AArch64InstrAtomics.td"
5742