[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / lib / Target / AArch64 / AArch64InstrInfo.td
blob9e7b5a0ffddef9da1a03ee38dddede9f2b79fade
1 //=- AArch64InstrInfo.td - Describe the AArch64 Instructions -*- tablegen -*-=//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // AArch64 Instruction definitions.
11 //===----------------------------------------------------------------------===//
13 //===----------------------------------------------------------------------===//
14 // ARM Instruction Predicate Definitions.
16 def HasV8_1a         : Predicate<"Subtarget->hasV8_1aOps()">,
17                                  AssemblerPredicate<(all_of HasV8_1aOps), "armv8.1a">;
18 def HasV8_2a         : Predicate<"Subtarget->hasV8_2aOps()">,
19                                  AssemblerPredicate<(all_of HasV8_2aOps), "armv8.2a">;
20 def HasV8_3a         : Predicate<"Subtarget->hasV8_3aOps()">,
21                                  AssemblerPredicate<(all_of HasV8_3aOps), "armv8.3a">;
22 def HasV8_4a         : Predicate<"Subtarget->hasV8_4aOps()">,
23                                  AssemblerPredicate<(all_of HasV8_4aOps), "armv8.4a">;
24 def HasV8_5a         : Predicate<"Subtarget->hasV8_5aOps()">,
25                                  AssemblerPredicate<(all_of HasV8_5aOps), "armv8.5a">;
26 def HasV8_6a         : Predicate<"Subtarget->hasV8_6aOps()">,
27                                  AssemblerPredicate<(all_of HasV8_6aOps), "armv8.6a">;
28 def HasV8_7a         : Predicate<"Subtarget->hasV8_7aOps()">,
29                                  AssemblerPredicate<(all_of HasV8_7aOps), "armv8.7a">;
30 def HasVH            : Predicate<"Subtarget->hasVH()">,
31                        AssemblerPredicate<(all_of FeatureVH), "vh">;
33 def HasLOR           : Predicate<"Subtarget->hasLOR()">,
34                        AssemblerPredicate<(all_of FeatureLOR), "lor">;
36 def HasPAuth         : Predicate<"Subtarget->hasPAuth()">,
37                        AssemblerPredicate<(all_of FeaturePAuth), "pauth">;
39 def HasJS            : Predicate<"Subtarget->hasJS()">,
40                        AssemblerPredicate<(all_of FeatureJS), "jsconv">;
42 def HasCCIDX         : Predicate<"Subtarget->hasCCIDX()">,
43                        AssemblerPredicate<(all_of FeatureCCIDX), "ccidx">;
45 def HasComplxNum      : Predicate<"Subtarget->hasComplxNum()">,
46                        AssemblerPredicate<(all_of FeatureComplxNum), "complxnum">;
48 def HasNV            : Predicate<"Subtarget->hasNV()">,
49                        AssemblerPredicate<(all_of FeatureNV), "nv">;
51 def HasMPAM          : Predicate<"Subtarget->hasMPAM()">,
52                        AssemblerPredicate<(all_of FeatureMPAM), "mpam">;
54 def HasDIT           : Predicate<"Subtarget->hasDIT()">,
55                        AssemblerPredicate<(all_of FeatureDIT), "dit">;
57 def HasTRACEV8_4         : Predicate<"Subtarget->hasTRACEV8_4()">,
58                        AssemblerPredicate<(all_of FeatureTRACEV8_4), "tracev8.4">;
60 def HasAM            : Predicate<"Subtarget->hasAM()">,
61                        AssemblerPredicate<(all_of FeatureAM), "am">;
63 def HasSEL2          : Predicate<"Subtarget->hasSEL2()">,
64                        AssemblerPredicate<(all_of FeatureSEL2), "sel2">;
66 def HasPMU           : Predicate<"Subtarget->hasPMU()">,
67                        AssemblerPredicate<(all_of FeaturePMU), "pmu">;
69 def HasTLB_RMI          : Predicate<"Subtarget->hasTLB_RMI()">,
70                        AssemblerPredicate<(all_of FeatureTLB_RMI), "tlb-rmi">;
72 def HasFlagM         : Predicate<"Subtarget->hasFlagM()">,
73                        AssemblerPredicate<(all_of FeatureFlagM), "flagm">;
75 def HasRCPC_IMMO      : Predicate<"Subtarget->hasRCPCImm()">,
76                        AssemblerPredicate<(all_of FeatureRCPC_IMMO), "rcpc-immo">;
78 def HasFPARMv8       : Predicate<"Subtarget->hasFPARMv8()">,
79                                AssemblerPredicate<(all_of FeatureFPARMv8), "fp-armv8">;
80 def HasNEON          : Predicate<"Subtarget->hasNEON()">,
81                                  AssemblerPredicate<(all_of FeatureNEON), "neon">;
82 def HasCrypto        : Predicate<"Subtarget->hasCrypto()">,
83                                  AssemblerPredicate<(all_of FeatureCrypto), "crypto">;
84 def HasSM4           : Predicate<"Subtarget->hasSM4()">,
85                                  AssemblerPredicate<(all_of FeatureSM4), "sm4">;
86 def HasSHA3          : Predicate<"Subtarget->hasSHA3()">,
87                                  AssemblerPredicate<(all_of FeatureSHA3), "sha3">;
88 def HasSHA2          : Predicate<"Subtarget->hasSHA2()">,
89                                  AssemblerPredicate<(all_of FeatureSHA2), "sha2">;
90 def HasAES           : Predicate<"Subtarget->hasAES()">,
91                                  AssemblerPredicate<(all_of FeatureAES), "aes">;
92 def HasDotProd       : Predicate<"Subtarget->hasDotProd()">,
93                                  AssemblerPredicate<(all_of FeatureDotProd), "dotprod">;
94 def HasCRC           : Predicate<"Subtarget->hasCRC()">,
95                                  AssemblerPredicate<(all_of FeatureCRC), "crc">;
96 def HasLSE           : Predicate<"Subtarget->hasLSE()">,
97                                  AssemblerPredicate<(all_of FeatureLSE), "lse">;
98 def HasNoLSE         : Predicate<"!Subtarget->hasLSE()">;
99 def HasRAS           : Predicate<"Subtarget->hasRAS()">,
100                                  AssemblerPredicate<(all_of FeatureRAS), "ras">;
101 def HasRDM           : Predicate<"Subtarget->hasRDM()">,
102                                  AssemblerPredicate<(all_of FeatureRDM), "rdm">;
103 def HasPerfMon       : Predicate<"Subtarget->hasPerfMon()">;
104 def HasFullFP16      : Predicate<"Subtarget->hasFullFP16()">,
105                                  AssemblerPredicate<(all_of FeatureFullFP16), "fullfp16">;
106 def HasFP16FML       : Predicate<"Subtarget->hasFP16FML()">,
107                                  AssemblerPredicate<(all_of FeatureFP16FML), "fp16fml">;
108 def HasSPE           : Predicate<"Subtarget->hasSPE()">,
109                                  AssemblerPredicate<(all_of FeatureSPE), "spe">;
110 def HasFuseAES       : Predicate<"Subtarget->hasFuseAES()">,
111                                  AssemblerPredicate<(all_of FeatureFuseAES),
112                                  "fuse-aes">;
113 def HasSVE           : Predicate<"Subtarget->hasSVE()">,
114                                  AssemblerPredicate<(all_of FeatureSVE), "sve">;
115 def HasSVE2          : Predicate<"Subtarget->hasSVE2()">,
116                                  AssemblerPredicate<(all_of FeatureSVE2), "sve2">;
117 def HasSVE2AES       : Predicate<"Subtarget->hasSVE2AES()">,
118                                  AssemblerPredicate<(all_of FeatureSVE2AES), "sve2-aes">;
119 def HasSVE2SM4       : Predicate<"Subtarget->hasSVE2SM4()">,
120                                  AssemblerPredicate<(all_of FeatureSVE2SM4), "sve2-sm4">;
121 def HasSVE2SHA3      : Predicate<"Subtarget->hasSVE2SHA3()">,
122                                  AssemblerPredicate<(all_of FeatureSVE2SHA3), "sve2-sha3">;
123 def HasSVE2BitPerm   : Predicate<"Subtarget->hasSVE2BitPerm()">,
124                                  AssemblerPredicate<(all_of FeatureSVE2BitPerm), "sve2-bitperm">;
125 def HasSME           : Predicate<"Subtarget->hasSME()">,
126                                  AssemblerPredicate<(all_of FeatureSME), "sme">;
127 def HasSMEF64        : Predicate<"Subtarget->hasSMEF64()">,
128                                  AssemblerPredicate<(all_of FeatureSMEF64), "sme-f64">;
129 def HasSMEI64        : Predicate<"Subtarget->hasSMEI64()">,
130                                  AssemblerPredicate<(all_of FeatureSMEI64), "sme-i64">;
131 def HasStreamingSVE  : Predicate<"Subtarget->hasStreamingSVE()">,
132                                  AssemblerPredicate<(all_of FeatureStreamingSVE), "streaming-sve">;
133 // A subset of SVE(2) instructions are legal in Streaming SVE execution mode,
134 // they should be enabled if either has been specified.
135 def HasSVEorStreamingSVE
136     : Predicate<"Subtarget->hasSVE() || Subtarget->hasStreamingSVE()">,
137                 AssemblerPredicate<(any_of FeatureSVE, FeatureStreamingSVE),
138                 "streaming-sve or sve">;
139 def HasSVE2orStreamingSVE
140     : Predicate<"Subtarget->hasSVE2() || Subtarget->hasStreamingSVE()">,
141                 AssemblerPredicate<(any_of FeatureSVE2, FeatureStreamingSVE),
142                 "streaming-sve or sve2">;
143 def HasRCPC          : Predicate<"Subtarget->hasRCPC()">,
144                                  AssemblerPredicate<(all_of FeatureRCPC), "rcpc">;
145 def HasAltNZCV       : Predicate<"Subtarget->hasAlternativeNZCV()">,
146                        AssemblerPredicate<(all_of FeatureAltFPCmp), "altnzcv">;
147 def HasFRInt3264     : Predicate<"Subtarget->hasFRInt3264()">,
148                        AssemblerPredicate<(all_of FeatureFRInt3264), "frint3264">;
149 def HasSB            : Predicate<"Subtarget->hasSB()">,
150                        AssemblerPredicate<(all_of FeatureSB), "sb">;
151 def HasPredRes      : Predicate<"Subtarget->hasPredRes()">,
152                        AssemblerPredicate<(all_of FeaturePredRes), "predres">;
153 def HasCCDP          : Predicate<"Subtarget->hasCCDP()">,
154                        AssemblerPredicate<(all_of FeatureCacheDeepPersist), "ccdp">;
155 def HasBTI           : Predicate<"Subtarget->hasBTI()">,
156                        AssemblerPredicate<(all_of FeatureBranchTargetId), "bti">;
157 def HasMTE           : Predicate<"Subtarget->hasMTE()">,
158                        AssemblerPredicate<(all_of FeatureMTE), "mte">;
159 def HasTME           : Predicate<"Subtarget->hasTME()">,
160                        AssemblerPredicate<(all_of FeatureTME), "tme">;
161 def HasETE           : Predicate<"Subtarget->hasETE()">,
162                        AssemblerPredicate<(all_of FeatureETE), "ete">;
163 def HasTRBE          : Predicate<"Subtarget->hasTRBE()">,
164                        AssemblerPredicate<(all_of FeatureTRBE), "trbe">;
165 def HasBF16          : Predicate<"Subtarget->hasBF16()">,
166                        AssemblerPredicate<(all_of FeatureBF16), "bf16">;
167 def HasMatMulInt8    : Predicate<"Subtarget->hasMatMulInt8()">,
168                        AssemblerPredicate<(all_of FeatureMatMulInt8), "i8mm">;
169 def HasMatMulFP32    : Predicate<"Subtarget->hasMatMulFP32()">,
170                        AssemblerPredicate<(all_of FeatureMatMulFP32), "f32mm">;
171 def HasMatMulFP64    : Predicate<"Subtarget->hasMatMulFP64()">,
172                        AssemblerPredicate<(all_of FeatureMatMulFP64), "f64mm">;
173 def HasXS            : Predicate<"Subtarget->hasXS()">,
174                        AssemblerPredicate<(all_of FeatureXS), "xs">;
175 def HasWFxT          : Predicate<"Subtarget->hasWFxT()">,
176                        AssemblerPredicate<(all_of FeatureWFxT), "wfxt">;
177 def HasLS64          : Predicate<"Subtarget->hasLS64()">,
178                        AssemblerPredicate<(all_of FeatureLS64), "ls64">;
179 def HasBRBE          : Predicate<"Subtarget->hasBRBE()">,
180                        AssemblerPredicate<(all_of FeatureBRBE), "brbe">;
181 def HasSPE_EEF       : Predicate<"Subtarget->hasSPE_EEF()">,
182                        AssemblerPredicate<(all_of FeatureSPE_EEF), "spe-eef">;
183 def IsLE             : Predicate<"Subtarget->isLittleEndian()">;
184 def IsBE             : Predicate<"!Subtarget->isLittleEndian()">;
185 def IsWindows        : Predicate<"Subtarget->isTargetWindows()">;
186 def UseExperimentalZeroingPseudos
187     : Predicate<"Subtarget->useExperimentalZeroingPseudos()">;
188 def UseAlternateSExtLoadCVTF32
189     : Predicate<"Subtarget->useAlternateSExtLoadCVTF32Pattern()">;
191 def UseNegativeImmediates
192     : Predicate<"false">, AssemblerPredicate<(all_of (not FeatureNoNegativeImmediates)),
193                                              "NegativeImmediates">;
195 def AArch64LocalRecover : SDNode<"ISD::LOCAL_RECOVER",
196                                   SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>,
197                                                        SDTCisInt<1>]>>;
200 //===----------------------------------------------------------------------===//
201 // AArch64-specific DAG Nodes.
204 // SDTBinaryArithWithFlagsOut - RES1, FLAGS = op LHS, RHS
205 def SDTBinaryArithWithFlagsOut : SDTypeProfile<2, 2,
206                                               [SDTCisSameAs<0, 2>,
207                                                SDTCisSameAs<0, 3>,
208                                                SDTCisInt<0>, SDTCisVT<1, i32>]>;
210 // SDTBinaryArithWithFlagsIn - RES1, FLAGS = op LHS, RHS, FLAGS
211 def SDTBinaryArithWithFlagsIn : SDTypeProfile<1, 3,
212                                             [SDTCisSameAs<0, 1>,
213                                              SDTCisSameAs<0, 2>,
214                                              SDTCisInt<0>,
215                                              SDTCisVT<3, i32>]>;
217 // SDTBinaryArithWithFlagsInOut - RES1, FLAGS = op LHS, RHS, FLAGS
218 def SDTBinaryArithWithFlagsInOut : SDTypeProfile<2, 3,
219                                             [SDTCisSameAs<0, 2>,
220                                              SDTCisSameAs<0, 3>,
221                                              SDTCisInt<0>,
222                                              SDTCisVT<1, i32>,
223                                              SDTCisVT<4, i32>]>;
225 def SDT_AArch64Brcond  : SDTypeProfile<0, 3,
226                                      [SDTCisVT<0, OtherVT>, SDTCisVT<1, i32>,
227                                       SDTCisVT<2, i32>]>;
228 def SDT_AArch64cbz : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisVT<1, OtherVT>]>;
229 def SDT_AArch64tbz : SDTypeProfile<0, 3, [SDTCisInt<0>, SDTCisInt<1>,
230                                         SDTCisVT<2, OtherVT>]>;
233 def SDT_AArch64CSel  : SDTypeProfile<1, 4,
234                                    [SDTCisSameAs<0, 1>,
235                                     SDTCisSameAs<0, 2>,
236                                     SDTCisInt<3>,
237                                     SDTCisVT<4, i32>]>;
238 def SDT_AArch64CCMP : SDTypeProfile<1, 5,
239                                     [SDTCisVT<0, i32>,
240                                      SDTCisInt<1>,
241                                      SDTCisSameAs<1, 2>,
242                                      SDTCisInt<3>,
243                                      SDTCisInt<4>,
244                                      SDTCisVT<5, i32>]>;
245 def SDT_AArch64FCCMP : SDTypeProfile<1, 5,
246                                      [SDTCisVT<0, i32>,
247                                       SDTCisFP<1>,
248                                       SDTCisSameAs<1, 2>,
249                                       SDTCisInt<3>,
250                                       SDTCisInt<4>,
251                                       SDTCisVT<5, i32>]>;
252 def SDT_AArch64FCmp   : SDTypeProfile<0, 2,
253                                    [SDTCisFP<0>,
254                                     SDTCisSameAs<0, 1>]>;
255 def SDT_AArch64Dup   : SDTypeProfile<1, 1, [SDTCisVec<0>]>;
256 def SDT_AArch64DupLane   : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisInt<2>]>;
257 def SDT_AArch64Insr  : SDTypeProfile<1, 2, [SDTCisVec<0>]>;
258 def SDT_AArch64Zip   : SDTypeProfile<1, 2, [SDTCisVec<0>,
259                                           SDTCisSameAs<0, 1>,
260                                           SDTCisSameAs<0, 2>]>;
261 def SDT_AArch64MOVIedit : SDTypeProfile<1, 1, [SDTCisInt<1>]>;
262 def SDT_AArch64MOVIshift : SDTypeProfile<1, 2, [SDTCisInt<1>, SDTCisInt<2>]>;
263 def SDT_AArch64vecimm : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0,1>,
264                                            SDTCisInt<2>, SDTCisInt<3>]>;
265 def SDT_AArch64UnaryVec: SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisSameAs<0,1>]>;
266 def SDT_AArch64ExtVec: SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0,1>,
267                                           SDTCisSameAs<0,2>, SDTCisInt<3>]>;
268 def SDT_AArch64vshift : SDTypeProfile<1, 2, [SDTCisSameAs<0,1>, SDTCisInt<2>]>;
269 def SDT_AArch64Dot: SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0,1>,
270                                          SDTCisVec<2>, SDTCisSameAs<2,3>]>;
272 def SDT_AArch64vshiftinsert : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisInt<3>,
273                                                  SDTCisSameAs<0,1>,
274                                                  SDTCisSameAs<0,2>]>;
276 def SDT_AArch64unvec : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisSameAs<0,1>]>;
277 def SDT_AArch64fcmpz : SDTypeProfile<1, 1, []>;
278 def SDT_AArch64fcmp  : SDTypeProfile<1, 2, [SDTCisSameAs<1,2>]>;
279 def SDT_AArch64binvec : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0,1>,
280                                            SDTCisSameAs<0,2>]>;
281 def SDT_AArch64trivec : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0,1>,
282                                            SDTCisSameAs<0,2>,
283                                            SDTCisSameAs<0,3>]>;
284 def SDT_AArch64TCRET : SDTypeProfile<0, 2, [SDTCisPtrTy<0>]>;
285 def SDT_AArch64PREFETCH : SDTypeProfile<0, 2, [SDTCisVT<0, i32>, SDTCisPtrTy<1>]>;
287 def SDT_AArch64ITOF  : SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisSameAs<0,1>]>;
289 def SDT_AArch64TLSDescCall : SDTypeProfile<0, -2, [SDTCisPtrTy<0>,
290                                                  SDTCisPtrTy<1>]>;
292 def SDT_AArch64uaddlp : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVec<1>]>;
294 def SDT_AArch64ldp : SDTypeProfile<2, 1, [SDTCisVT<0, i64>, SDTCisSameAs<0, 1>, SDTCisPtrTy<2>]>;
295 def SDT_AArch64stp : SDTypeProfile<0, 3, [SDTCisVT<0, i64>, SDTCisSameAs<0, 1>, SDTCisPtrTy<2>]>;
296 def SDT_AArch64stnp : SDTypeProfile<0, 3, [SDTCisVT<0, v4i32>, SDTCisSameAs<0, 1>, SDTCisPtrTy<2>]>;
298 // Generates the general dynamic sequences, i.e.
299 //  adrp  x0, :tlsdesc:var
300 //  ldr   x1, [x0, #:tlsdesc_lo12:var]
301 //  add   x0, x0, #:tlsdesc_lo12:var
302 //  .tlsdesccall var
303 //  blr   x1
305 // (the TPIDR_EL0 offset is put directly in X0, hence no "result" here)
306 // number of operands (the variable)
307 def SDT_AArch64TLSDescCallSeq : SDTypeProfile<0,1,
308                                           [SDTCisPtrTy<0>]>;
310 def SDT_AArch64WrapperLarge : SDTypeProfile<1, 4,
311                                         [SDTCisVT<0, i64>, SDTCisVT<1, i32>,
312                                          SDTCisSameAs<1, 2>, SDTCisSameAs<1, 3>,
313                                          SDTCisSameAs<1, 4>]>;
315 def SDT_AArch64TBL : SDTypeProfile<1, 2, [
316   SDTCisVec<0>, SDTCisSameAs<0, 1>, SDTCisInt<2>
319 // non-extending masked load fragment.
320 def nonext_masked_load :
321   PatFrag<(ops node:$ptr, node:$pred, node:$def),
322           (masked_ld node:$ptr, undef, node:$pred, node:$def), [{
323   return cast<MaskedLoadSDNode>(N)->getExtensionType() == ISD::NON_EXTLOAD &&
324          cast<MaskedLoadSDNode>(N)->isUnindexed() &&
325          !cast<MaskedLoadSDNode>(N)->isNonTemporal();
326 }]>;
327 // sign extending masked load fragments.
328 def asext_masked_load :
329   PatFrag<(ops node:$ptr, node:$pred, node:$def),
330           (masked_ld node:$ptr, undef, node:$pred, node:$def),[{
331   return (cast<MaskedLoadSDNode>(N)->getExtensionType() == ISD::EXTLOAD ||
332           cast<MaskedLoadSDNode>(N)->getExtensionType() == ISD::SEXTLOAD) &&
333          cast<MaskedLoadSDNode>(N)->isUnindexed();
334 }]>;
335 def asext_masked_load_i8 :
336   PatFrag<(ops node:$ptr, node:$pred, node:$def),
337           (asext_masked_load node:$ptr, node:$pred, node:$def), [{
338   return cast<MaskedLoadSDNode>(N)->getMemoryVT().getScalarType() == MVT::i8;
339 }]>;
340 def asext_masked_load_i16 :
341   PatFrag<(ops node:$ptr, node:$pred, node:$def),
342           (asext_masked_load node:$ptr, node:$pred, node:$def), [{
343   return cast<MaskedLoadSDNode>(N)->getMemoryVT().getScalarType() == MVT::i16;
344 }]>;
345 def asext_masked_load_i32 :
346   PatFrag<(ops node:$ptr, node:$pred, node:$def),
347           (asext_masked_load node:$ptr, node:$pred, node:$def), [{
348   return cast<MaskedLoadSDNode>(N)->getMemoryVT().getScalarType() == MVT::i32;
349 }]>;
350 // zero extending masked load fragments.
351 def zext_masked_load :
352   PatFrag<(ops node:$ptr, node:$pred, node:$def),
353           (masked_ld node:$ptr, undef, node:$pred, node:$def), [{
354   return cast<MaskedLoadSDNode>(N)->getExtensionType() == ISD::ZEXTLOAD &&
355          cast<MaskedLoadSDNode>(N)->isUnindexed();
356 }]>;
357 def zext_masked_load_i8 :
358   PatFrag<(ops node:$ptr, node:$pred, node:$def),
359           (zext_masked_load node:$ptr, node:$pred, node:$def), [{
360   return cast<MaskedLoadSDNode>(N)->getMemoryVT().getScalarType() == MVT::i8;
361 }]>;
362 def zext_masked_load_i16 :
363   PatFrag<(ops node:$ptr, node:$pred, node:$def),
364           (zext_masked_load node:$ptr, node:$pred, node:$def), [{
365   return cast<MaskedLoadSDNode>(N)->getMemoryVT().getScalarType() == MVT::i16;
366 }]>;
367 def zext_masked_load_i32 :
368   PatFrag<(ops node:$ptr, node:$pred, node:$def),
369           (zext_masked_load node:$ptr, node:$pred, node:$def), [{
370   return cast<MaskedLoadSDNode>(N)->getMemoryVT().getScalarType() == MVT::i32;
371 }]>;
373 def non_temporal_load :
374    PatFrag<(ops node:$ptr, node:$pred, node:$def),
375            (masked_ld node:$ptr, undef, node:$pred, node:$def), [{
376    return cast<MaskedLoadSDNode>(N)->getExtensionType() == ISD::NON_EXTLOAD &&
377           cast<MaskedLoadSDNode>(N)->isUnindexed() &&
378           cast<MaskedLoadSDNode>(N)->isNonTemporal();
379 }]>;
381 // non-truncating masked store fragment.
382 def nontrunc_masked_store :
383   PatFrag<(ops node:$val, node:$ptr, node:$pred),
384           (masked_st node:$val, node:$ptr, undef, node:$pred), [{
385   return !cast<MaskedStoreSDNode>(N)->isTruncatingStore() &&
386          cast<MaskedStoreSDNode>(N)->isUnindexed() &&
387          !cast<MaskedStoreSDNode>(N)->isNonTemporal();
388 }]>;
389 // truncating masked store fragments.
390 def trunc_masked_store :
391   PatFrag<(ops node:$val, node:$ptr, node:$pred),
392           (masked_st node:$val, node:$ptr, undef, node:$pred), [{
393   return cast<MaskedStoreSDNode>(N)->isTruncatingStore() &&
394          cast<MaskedStoreSDNode>(N)->isUnindexed();
395 }]>;
396 def trunc_masked_store_i8 :
397   PatFrag<(ops node:$val, node:$ptr, node:$pred),
398           (trunc_masked_store node:$val, node:$ptr, node:$pred), [{
399   return cast<MaskedStoreSDNode>(N)->getMemoryVT().getScalarType() == MVT::i8;
400 }]>;
401 def trunc_masked_store_i16 :
402   PatFrag<(ops node:$val, node:$ptr, node:$pred),
403           (trunc_masked_store node:$val, node:$ptr, node:$pred), [{
404   return cast<MaskedStoreSDNode>(N)->getMemoryVT().getScalarType() == MVT::i16;
405 }]>;
406 def trunc_masked_store_i32 :
407   PatFrag<(ops node:$val, node:$ptr, node:$pred),
408           (trunc_masked_store node:$val, node:$ptr, node:$pred), [{
409   return cast<MaskedStoreSDNode>(N)->getMemoryVT().getScalarType() == MVT::i32;
410 }]>;
412 def non_temporal_store :
413   PatFrag<(ops node:$val, node:$ptr, node:$pred),
414           (masked_st node:$val, node:$ptr, undef, node:$pred), [{
415   return !cast<MaskedStoreSDNode>(N)->isTruncatingStore() &&
416          cast<MaskedStoreSDNode>(N)->isUnindexed() &&
417          cast<MaskedStoreSDNode>(N)->isNonTemporal();
418 }]>;
420 // Node definitions.
421 def AArch64adrp          : SDNode<"AArch64ISD::ADRP", SDTIntUnaryOp, []>;
422 def AArch64adr           : SDNode<"AArch64ISD::ADR", SDTIntUnaryOp, []>;
423 def AArch64addlow        : SDNode<"AArch64ISD::ADDlow", SDTIntBinOp, []>;
424 def AArch64LOADgot       : SDNode<"AArch64ISD::LOADgot", SDTIntUnaryOp>;
425 def AArch64callseq_start : SDNode<"ISD::CALLSEQ_START",
426                                 SDCallSeqStart<[ SDTCisVT<0, i32>,
427                                                  SDTCisVT<1, i32> ]>,
428                                 [SDNPHasChain, SDNPOutGlue]>;
429 def AArch64callseq_end   : SDNode<"ISD::CALLSEQ_END",
430                                 SDCallSeqEnd<[ SDTCisVT<0, i32>,
431                                                SDTCisVT<1, i32> ]>,
432                                 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
433 def AArch64call          : SDNode<"AArch64ISD::CALL",
434                                 SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>,
435                                 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
436                                  SDNPVariadic]>;
438 def AArch64call_rvmarker: SDNode<"AArch64ISD::CALL_RVMARKER",
439                              SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>,
440                              [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
441                               SDNPVariadic]>;
443 def AArch64brcond        : SDNode<"AArch64ISD::BRCOND", SDT_AArch64Brcond,
444                                 [SDNPHasChain]>;
445 def AArch64cbz           : SDNode<"AArch64ISD::CBZ", SDT_AArch64cbz,
446                                 [SDNPHasChain]>;
447 def AArch64cbnz           : SDNode<"AArch64ISD::CBNZ", SDT_AArch64cbz,
448                                 [SDNPHasChain]>;
449 def AArch64tbz           : SDNode<"AArch64ISD::TBZ", SDT_AArch64tbz,
450                                 [SDNPHasChain]>;
451 def AArch64tbnz           : SDNode<"AArch64ISD::TBNZ", SDT_AArch64tbz,
452                                 [SDNPHasChain]>;
455 def AArch64csel          : SDNode<"AArch64ISD::CSEL", SDT_AArch64CSel>;
456 def AArch64csinv         : SDNode<"AArch64ISD::CSINV", SDT_AArch64CSel>;
457 def AArch64csneg         : SDNode<"AArch64ISD::CSNEG", SDT_AArch64CSel>;
458 def AArch64csinc         : SDNode<"AArch64ISD::CSINC", SDT_AArch64CSel>;
459 def AArch64retflag       : SDNode<"AArch64ISD::RET_FLAG", SDTNone,
460                                 [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
461 def AArch64adc       : SDNode<"AArch64ISD::ADC",  SDTBinaryArithWithFlagsIn >;
462 def AArch64sbc       : SDNode<"AArch64ISD::SBC",  SDTBinaryArithWithFlagsIn>;
463 def AArch64add_flag  : SDNode<"AArch64ISD::ADDS",  SDTBinaryArithWithFlagsOut,
464                             [SDNPCommutative]>;
465 def AArch64sub_flag  : SDNode<"AArch64ISD::SUBS",  SDTBinaryArithWithFlagsOut>;
466 def AArch64and_flag  : SDNode<"AArch64ISD::ANDS",  SDTBinaryArithWithFlagsOut,
467                             [SDNPCommutative]>;
468 def AArch64adc_flag  : SDNode<"AArch64ISD::ADCS",  SDTBinaryArithWithFlagsInOut>;
469 def AArch64sbc_flag  : SDNode<"AArch64ISD::SBCS",  SDTBinaryArithWithFlagsInOut>;
471 def AArch64ccmp      : SDNode<"AArch64ISD::CCMP",  SDT_AArch64CCMP>;
472 def AArch64ccmn      : SDNode<"AArch64ISD::CCMN",  SDT_AArch64CCMP>;
473 def AArch64fccmp     : SDNode<"AArch64ISD::FCCMP", SDT_AArch64FCCMP>;
475 def AArch64threadpointer : SDNode<"AArch64ISD::THREAD_POINTER", SDTPtrLeaf>;
477 def AArch64fcmp         : SDNode<"AArch64ISD::FCMP", SDT_AArch64FCmp>;
478 def AArch64strict_fcmp  : SDNode<"AArch64ISD::STRICT_FCMP", SDT_AArch64FCmp,
479                                  [SDNPHasChain]>;
480 def AArch64strict_fcmpe : SDNode<"AArch64ISD::STRICT_FCMPE", SDT_AArch64FCmp,
481                                  [SDNPHasChain]>;
482 def AArch64any_fcmp     : PatFrags<(ops node:$lhs, node:$rhs),
483                                    [(AArch64strict_fcmp node:$lhs, node:$rhs),
484                                     (AArch64fcmp node:$lhs, node:$rhs)]>;
486 def AArch64dup       : SDNode<"AArch64ISD::DUP", SDT_AArch64Dup>;
487 def AArch64duplane8  : SDNode<"AArch64ISD::DUPLANE8", SDT_AArch64DupLane>;
488 def AArch64duplane16 : SDNode<"AArch64ISD::DUPLANE16", SDT_AArch64DupLane>;
489 def AArch64duplane32 : SDNode<"AArch64ISD::DUPLANE32", SDT_AArch64DupLane>;
490 def AArch64duplane64 : SDNode<"AArch64ISD::DUPLANE64", SDT_AArch64DupLane>;
492 def AArch64insr      : SDNode<"AArch64ISD::INSR", SDT_AArch64Insr>;
494 def AArch64zip1      : SDNode<"AArch64ISD::ZIP1", SDT_AArch64Zip>;
495 def AArch64zip2      : SDNode<"AArch64ISD::ZIP2", SDT_AArch64Zip>;
496 def AArch64uzp1      : SDNode<"AArch64ISD::UZP1", SDT_AArch64Zip>;
497 def AArch64uzp2      : SDNode<"AArch64ISD::UZP2", SDT_AArch64Zip>;
498 def AArch64trn1      : SDNode<"AArch64ISD::TRN1", SDT_AArch64Zip>;
499 def AArch64trn2      : SDNode<"AArch64ISD::TRN2", SDT_AArch64Zip>;
501 def AArch64movi_edit : SDNode<"AArch64ISD::MOVIedit", SDT_AArch64MOVIedit>;
502 def AArch64movi_shift : SDNode<"AArch64ISD::MOVIshift", SDT_AArch64MOVIshift>;
503 def AArch64movi_msl : SDNode<"AArch64ISD::MOVImsl", SDT_AArch64MOVIshift>;
504 def AArch64mvni_shift : SDNode<"AArch64ISD::MVNIshift", SDT_AArch64MOVIshift>;
505 def AArch64mvni_msl : SDNode<"AArch64ISD::MVNImsl", SDT_AArch64MOVIshift>;
506 def AArch64movi : SDNode<"AArch64ISD::MOVI", SDT_AArch64MOVIedit>;
507 def AArch64fmov : SDNode<"AArch64ISD::FMOV", SDT_AArch64MOVIedit>;
509 def AArch64rev16 : SDNode<"AArch64ISD::REV16", SDT_AArch64UnaryVec>;
510 def AArch64rev32 : SDNode<"AArch64ISD::REV32", SDT_AArch64UnaryVec>;
511 def AArch64rev64 : SDNode<"AArch64ISD::REV64", SDT_AArch64UnaryVec>;
512 def AArch64ext : SDNode<"AArch64ISD::EXT", SDT_AArch64ExtVec>;
514 def AArch64vashr : SDNode<"AArch64ISD::VASHR", SDT_AArch64vshift>;
515 def AArch64vlshr : SDNode<"AArch64ISD::VLSHR", SDT_AArch64vshift>;
516 def AArch64vshl : SDNode<"AArch64ISD::VSHL", SDT_AArch64vshift>;
517 def AArch64sqshli : SDNode<"AArch64ISD::SQSHL_I", SDT_AArch64vshift>;
518 def AArch64uqshli : SDNode<"AArch64ISD::UQSHL_I", SDT_AArch64vshift>;
519 def AArch64sqshlui : SDNode<"AArch64ISD::SQSHLU_I", SDT_AArch64vshift>;
520 def AArch64srshri : SDNode<"AArch64ISD::SRSHR_I", SDT_AArch64vshift>;
521 def AArch64urshri : SDNode<"AArch64ISD::URSHR_I", SDT_AArch64vshift>;
522 def AArch64vsli : SDNode<"AArch64ISD::VSLI", SDT_AArch64vshiftinsert>;
523 def AArch64vsri : SDNode<"AArch64ISD::VSRI", SDT_AArch64vshiftinsert>;
525 def AArch64bit: SDNode<"AArch64ISD::BIT", SDT_AArch64trivec>;
526 def AArch64bsp: SDNode<"AArch64ISD::BSP", SDT_AArch64trivec>;
528 def AArch64cmeq: SDNode<"AArch64ISD::CMEQ", SDT_AArch64binvec>;
529 def AArch64cmge: SDNode<"AArch64ISD::CMGE", SDT_AArch64binvec>;
530 def AArch64cmgt: SDNode<"AArch64ISD::CMGT", SDT_AArch64binvec>;
531 def AArch64cmhi: SDNode<"AArch64ISD::CMHI", SDT_AArch64binvec>;
532 def AArch64cmhs: SDNode<"AArch64ISD::CMHS", SDT_AArch64binvec>;
534 def AArch64fcmeq: SDNode<"AArch64ISD::FCMEQ", SDT_AArch64fcmp>;
535 def AArch64fcmge: SDNode<"AArch64ISD::FCMGE", SDT_AArch64fcmp>;
536 def AArch64fcmgt: SDNode<"AArch64ISD::FCMGT", SDT_AArch64fcmp>;
538 def AArch64cmeqz: SDNode<"AArch64ISD::CMEQz", SDT_AArch64unvec>;
539 def AArch64cmgez: SDNode<"AArch64ISD::CMGEz", SDT_AArch64unvec>;
540 def AArch64cmgtz: SDNode<"AArch64ISD::CMGTz", SDT_AArch64unvec>;
541 def AArch64cmlez: SDNode<"AArch64ISD::CMLEz", SDT_AArch64unvec>;
542 def AArch64cmltz: SDNode<"AArch64ISD::CMLTz", SDT_AArch64unvec>;
543 def AArch64cmtst : PatFrag<(ops node:$LHS, node:$RHS),
544                         (vnot (AArch64cmeqz (and node:$LHS, node:$RHS)))>;
546 def AArch64fcmeqz: SDNode<"AArch64ISD::FCMEQz", SDT_AArch64fcmpz>;
547 def AArch64fcmgez: SDNode<"AArch64ISD::FCMGEz", SDT_AArch64fcmpz>;
548 def AArch64fcmgtz: SDNode<"AArch64ISD::FCMGTz", SDT_AArch64fcmpz>;
549 def AArch64fcmlez: SDNode<"AArch64ISD::FCMLEz", SDT_AArch64fcmpz>;
550 def AArch64fcmltz: SDNode<"AArch64ISD::FCMLTz", SDT_AArch64fcmpz>;
552 def AArch64bici: SDNode<"AArch64ISD::BICi", SDT_AArch64vecimm>;
553 def AArch64orri: SDNode<"AArch64ISD::ORRi", SDT_AArch64vecimm>;
555 def AArch64tcret: SDNode<"AArch64ISD::TC_RETURN", SDT_AArch64TCRET,
556                   [SDNPHasChain,  SDNPOptInGlue, SDNPVariadic]>;
558 def AArch64Prefetch        : SDNode<"AArch64ISD::PREFETCH", SDT_AArch64PREFETCH,
559                                [SDNPHasChain, SDNPSideEffect]>;
561 def AArch64sitof: SDNode<"AArch64ISD::SITOF", SDT_AArch64ITOF>;
562 def AArch64uitof: SDNode<"AArch64ISD::UITOF", SDT_AArch64ITOF>;
564 def AArch64tlsdesc_callseq : SDNode<"AArch64ISD::TLSDESC_CALLSEQ",
565                                     SDT_AArch64TLSDescCallSeq,
566                                     [SDNPInGlue, SDNPOutGlue, SDNPHasChain,
567                                      SDNPVariadic]>;
570 def AArch64WrapperLarge : SDNode<"AArch64ISD::WrapperLarge",
571                                  SDT_AArch64WrapperLarge>;
573 def AArch64NvCast : SDNode<"AArch64ISD::NVCAST", SDTUnaryOp>;
575 def SDT_AArch64mull : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisInt<1>,
576                                     SDTCisSameAs<1, 2>]>;
577 def AArch64smull    : SDNode<"AArch64ISD::SMULL", SDT_AArch64mull>;
578 def AArch64umull    : SDNode<"AArch64ISD::UMULL", SDT_AArch64mull>;
580 def AArch64frecpe   : SDNode<"AArch64ISD::FRECPE", SDTFPUnaryOp>;
581 def AArch64frecps   : SDNode<"AArch64ISD::FRECPS", SDTFPBinOp>;
582 def AArch64frsqrte  : SDNode<"AArch64ISD::FRSQRTE", SDTFPUnaryOp>;
583 def AArch64frsqrts  : SDNode<"AArch64ISD::FRSQRTS", SDTFPBinOp>;
585 def AArch64sdot     : SDNode<"AArch64ISD::SDOT", SDT_AArch64Dot>;
586 def AArch64udot     : SDNode<"AArch64ISD::UDOT", SDT_AArch64Dot>;
588 def AArch64saddv    : SDNode<"AArch64ISD::SADDV", SDT_AArch64UnaryVec>;
589 def AArch64uaddv    : SDNode<"AArch64ISD::UADDV", SDT_AArch64UnaryVec>;
590 def AArch64sminv    : SDNode<"AArch64ISD::SMINV", SDT_AArch64UnaryVec>;
591 def AArch64uminv    : SDNode<"AArch64ISD::UMINV", SDT_AArch64UnaryVec>;
592 def AArch64smaxv    : SDNode<"AArch64ISD::SMAXV", SDT_AArch64UnaryVec>;
593 def AArch64umaxv    : SDNode<"AArch64ISD::UMAXV", SDT_AArch64UnaryVec>;
595 def AArch64srhadd   : SDNode<"AArch64ISD::SRHADD", SDT_AArch64binvec>;
596 def AArch64urhadd   : SDNode<"AArch64ISD::URHADD", SDT_AArch64binvec>;
597 def AArch64shadd   : SDNode<"AArch64ISD::SHADD", SDT_AArch64binvec>;
598 def AArch64uhadd   : SDNode<"AArch64ISD::UHADD", SDT_AArch64binvec>;
600 def AArch64uabd     : PatFrags<(ops node:$lhs, node:$rhs),
601                                [(abdu node:$lhs, node:$rhs),
602                                 (int_aarch64_neon_uabd node:$lhs, node:$rhs)]>;
603 def AArch64sabd     : PatFrags<(ops node:$lhs, node:$rhs),
604                                [(abds node:$lhs, node:$rhs),
605                                 (int_aarch64_neon_sabd node:$lhs, node:$rhs)]>;
607 def AArch64uaddlp_n : SDNode<"AArch64ISD::UADDLP", SDT_AArch64uaddlp>;
608 def AArch64uaddlp   : PatFrags<(ops node:$src),
609                                [(AArch64uaddlp_n node:$src),
610                                 (int_aarch64_neon_uaddlp node:$src)]>;
612 def SDT_AArch64SETTAG : SDTypeProfile<0, 2, [SDTCisPtrTy<0>, SDTCisPtrTy<1>]>;
613 def AArch64stg : SDNode<"AArch64ISD::STG", SDT_AArch64SETTAG, [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
614 def AArch64stzg : SDNode<"AArch64ISD::STZG", SDT_AArch64SETTAG, [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
615 def AArch64st2g : SDNode<"AArch64ISD::ST2G", SDT_AArch64SETTAG, [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
616 def AArch64stz2g : SDNode<"AArch64ISD::STZ2G", SDT_AArch64SETTAG, [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
618 def SDT_AArch64unpk : SDTypeProfile<1, 1, [
619     SDTCisInt<0>, SDTCisInt<1>, SDTCisOpSmallerThanOp<1, 0>
621 def AArch64sunpkhi : SDNode<"AArch64ISD::SUNPKHI", SDT_AArch64unpk>;
622 def AArch64sunpklo : SDNode<"AArch64ISD::SUNPKLO", SDT_AArch64unpk>;
623 def AArch64uunpkhi : SDNode<"AArch64ISD::UUNPKHI", SDT_AArch64unpk>;
624 def AArch64uunpklo : SDNode<"AArch64ISD::UUNPKLO", SDT_AArch64unpk>;
626 def AArch64ldp : SDNode<"AArch64ISD::LDP", SDT_AArch64ldp, [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
627 def AArch64stp : SDNode<"AArch64ISD::STP", SDT_AArch64stp, [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
628 def AArch64stnp : SDNode<"AArch64ISD::STNP", SDT_AArch64stnp, [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
630 def AArch64tbl : SDNode<"AArch64ISD::TBL", SDT_AArch64TBL>;
631 def AArch64mrs : SDNode<"AArch64ISD::MRS",
632                         SDTypeProfile<1, 1, [SDTCisVT<0, i64>, SDTCisVT<1, i32>]>,
633                         [SDNPHasChain, SDNPOutGlue]>;
634 //===----------------------------------------------------------------------===//
636 //===----------------------------------------------------------------------===//
638 // AArch64 Instruction Predicate Definitions.
639 // We could compute these on a per-module basis but doing so requires accessing
640 // the Function object through the <Target>Subtarget and objections were raised
641 // to that (see post-commit review comments for r301750).
642 let RecomputePerFunction = 1 in {
643   def ForCodeSize   : Predicate<"shouldOptForSize(MF)">;
644   def NotForCodeSize   : Predicate<"!shouldOptForSize(MF)">;
645   // Avoid generating STRQro if it is slow, unless we're optimizing for code size.
646   def UseSTRQro : Predicate<"!Subtarget->isSTRQroSlow() || shouldOptForSize(MF)">;
648   def UseBTI : Predicate<[{ MF->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement() }]>;
649   def NotUseBTI : Predicate<[{ !MF->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement() }]>;
651   def SLSBLRMitigation : Predicate<[{ MF->getSubtarget<AArch64Subtarget>().hardenSlsBlr() }]>;
652   def NoSLSBLRMitigation : Predicate<[{ !MF->getSubtarget<AArch64Subtarget>().hardenSlsBlr() }]>;
653   // Toggles patterns which aren't beneficial in GlobalISel when we aren't
654   // optimizing. This allows us to selectively use patterns without impacting
655   // SelectionDAG's behaviour.
656   // FIXME: One day there will probably be a nicer way to check for this, but
657   // today is not that day.
658   def OptimizedGISelOrOtherSelector : Predicate<"!MF->getFunction().hasOptNone() || MF->getProperties().hasProperty(MachineFunctionProperties::Property::FailedISel) || !MF->getProperties().hasProperty(MachineFunctionProperties::Property::Legalized)">;
661 include "AArch64InstrFormats.td"
662 include "SVEInstrFormats.td"
663 include "SMEInstrFormats.td"
665 //===----------------------------------------------------------------------===//
667 //===----------------------------------------------------------------------===//
668 // Miscellaneous instructions.
669 //===----------------------------------------------------------------------===//
671 let Defs = [SP], Uses = [SP], hasSideEffects = 1, isCodeGenOnly = 1 in {
672 // We set Sched to empty list because we expect these instructions to simply get
673 // removed in most cases.
674 def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
675                               [(AArch64callseq_start timm:$amt1, timm:$amt2)]>,
676                               Sched<[]>;
677 def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
678                             [(AArch64callseq_end timm:$amt1, timm:$amt2)]>,
679                             Sched<[]>;
680 } // Defs = [SP], Uses = [SP], hasSideEffects = 1, isCodeGenOnly = 1
682 let isReMaterializable = 1, isCodeGenOnly = 1 in {
683 // FIXME: The following pseudo instructions are only needed because remat
684 // cannot handle multiple instructions.  When that changes, they can be
685 // removed, along with the AArch64Wrapper node.
687 let AddedComplexity = 10 in
688 def LOADgot : Pseudo<(outs GPR64:$dst), (ins i64imm:$addr),
689                      [(set GPR64:$dst, (AArch64LOADgot tglobaladdr:$addr))]>,
690               Sched<[WriteLDAdr]>;
692 // The MOVaddr instruction should match only when the add is not folded
693 // into a load or store address.
694 def MOVaddr
695     : Pseudo<(outs GPR64:$dst), (ins i64imm:$hi, i64imm:$low),
696              [(set GPR64:$dst, (AArch64addlow (AArch64adrp tglobaladdr:$hi),
697                                             tglobaladdr:$low))]>,
698       Sched<[WriteAdrAdr]>;
699 def MOVaddrJT
700     : Pseudo<(outs GPR64:$dst), (ins i64imm:$hi, i64imm:$low),
701              [(set GPR64:$dst, (AArch64addlow (AArch64adrp tjumptable:$hi),
702                                              tjumptable:$low))]>,
703       Sched<[WriteAdrAdr]>;
704 def MOVaddrCP
705     : Pseudo<(outs GPR64:$dst), (ins i64imm:$hi, i64imm:$low),
706              [(set GPR64:$dst, (AArch64addlow (AArch64adrp tconstpool:$hi),
707                                              tconstpool:$low))]>,
708       Sched<[WriteAdrAdr]>;
709 def MOVaddrBA
710     : Pseudo<(outs GPR64:$dst), (ins i64imm:$hi, i64imm:$low),
711              [(set GPR64:$dst, (AArch64addlow (AArch64adrp tblockaddress:$hi),
712                                              tblockaddress:$low))]>,
713       Sched<[WriteAdrAdr]>;
714 def MOVaddrTLS
715     : Pseudo<(outs GPR64:$dst), (ins i64imm:$hi, i64imm:$low),
716              [(set GPR64:$dst, (AArch64addlow (AArch64adrp tglobaltlsaddr:$hi),
717                                             tglobaltlsaddr:$low))]>,
718       Sched<[WriteAdrAdr]>;
719 def MOVaddrEXT
720     : Pseudo<(outs GPR64:$dst), (ins i64imm:$hi, i64imm:$low),
721              [(set GPR64:$dst, (AArch64addlow (AArch64adrp texternalsym:$hi),
722                                             texternalsym:$low))]>,
723       Sched<[WriteAdrAdr]>;
724 // Normally AArch64addlow either gets folded into a following ldr/str,
725 // or together with an adrp into MOVaddr above. For cases with TLS, it
726 // might appear without either of them, so allow lowering it into a plain
727 // add.
728 def ADDlowTLS
729     : Pseudo<(outs GPR64:$dst), (ins GPR64:$src, i64imm:$low),
730              [(set GPR64:$dst, (AArch64addlow GPR64:$src,
731                                             tglobaltlsaddr:$low))]>,
732       Sched<[WriteAdr]>;
734 } // isReMaterializable, isCodeGenOnly
736 def : Pat<(AArch64LOADgot tglobaltlsaddr:$addr),
737           (LOADgot tglobaltlsaddr:$addr)>;
739 def : Pat<(AArch64LOADgot texternalsym:$addr),
740           (LOADgot texternalsym:$addr)>;
742 def : Pat<(AArch64LOADgot tconstpool:$addr),
743           (LOADgot tconstpool:$addr)>;
745 // 32-bit jump table destination is actually only 2 instructions since we can
746 // use the table itself as a PC-relative base. But optimization occurs after
747 // branch relaxation so be pessimistic.
748 let Size = 12, Constraints = "@earlyclobber $dst,@earlyclobber $scratch",
749     isNotDuplicable = 1 in {
750 def JumpTableDest32 : Pseudo<(outs GPR64:$dst, GPR64sp:$scratch),
751                              (ins GPR64:$table, GPR64:$entry, i32imm:$jti), []>,
752                       Sched<[]>;
753 def JumpTableDest16 : Pseudo<(outs GPR64:$dst, GPR64sp:$scratch),
754                              (ins GPR64:$table, GPR64:$entry, i32imm:$jti), []>,
755                       Sched<[]>;
756 def JumpTableDest8 : Pseudo<(outs GPR64:$dst, GPR64sp:$scratch),
757                             (ins GPR64:$table, GPR64:$entry, i32imm:$jti), []>,
758                      Sched<[]>;
761 // Space-consuming pseudo to aid testing of placement and reachability
762 // algorithms. Immediate operand is the number of bytes this "instruction"
763 // occupies; register operands can be used to enforce dependency and constrain
764 // the scheduler.
765 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
766 def SPACE : Pseudo<(outs GPR64:$Rd), (ins i32imm:$size, GPR64:$Rn),
767                    [(set GPR64:$Rd, (int_aarch64_space imm:$size, GPR64:$Rn))]>,
768             Sched<[]>;
770 let hasSideEffects = 1, isCodeGenOnly = 1 in {
771   def SpeculationSafeValueX
772       : Pseudo<(outs GPR64:$dst), (ins GPR64:$src), []>, Sched<[]>;
773   def SpeculationSafeValueW
774       : Pseudo<(outs GPR32:$dst), (ins GPR32:$src), []>, Sched<[]>;
777 // SpeculationBarrierEndBB must only be used after an unconditional control
778 // flow, i.e. after a terminator for which isBarrier is True.
779 let hasSideEffects = 1, isCodeGenOnly = 1, isTerminator = 1, isBarrier = 1 in {
780   def SpeculationBarrierISBDSBEndBB
781       : Pseudo<(outs), (ins), []>, Sched<[]>;
782   def SpeculationBarrierSBEndBB
783       : Pseudo<(outs), (ins), []>, Sched<[]>;
786 //===----------------------------------------------------------------------===//
787 // System instructions.
788 //===----------------------------------------------------------------------===//
790 def HINT : HintI<"hint">;
791 def : InstAlias<"nop",  (HINT 0b000)>;
792 def : InstAlias<"yield",(HINT 0b001)>;
793 def : InstAlias<"wfe",  (HINT 0b010)>;
794 def : InstAlias<"wfi",  (HINT 0b011)>;
795 def : InstAlias<"sev",  (HINT 0b100)>;
796 def : InstAlias<"sevl", (HINT 0b101)>;
797 def : InstAlias<"dgh",  (HINT 0b110)>;
798 def : InstAlias<"esb",  (HINT 0b10000)>, Requires<[HasRAS]>;
799 def : InstAlias<"csdb", (HINT 20)>;
800 // In order to be able to write readable assembly, LLVM should accept assembly
801 // inputs that use Branch Target Indentification mnemonics, even with BTI disabled.
802 // However, in order to be compatible with other assemblers (e.g. GAS), LLVM
803 // should not emit these mnemonics unless BTI is enabled.
804 def : InstAlias<"bti",  (HINT 32), 0>;
805 def : InstAlias<"bti $op", (HINT btihint_op:$op), 0>;
806 def : InstAlias<"bti",  (HINT 32)>, Requires<[HasBTI]>;
807 def : InstAlias<"bti $op", (HINT btihint_op:$op)>, Requires<[HasBTI]>;
809 // v8.2a Statistical Profiling extension
810 def : InstAlias<"psb $op",  (HINT psbhint_op:$op)>, Requires<[HasSPE]>;
812 // As far as LLVM is concerned this writes to the system's exclusive monitors.
813 let mayLoad = 1, mayStore = 1 in
814 def CLREX : CRmSystemI<imm0_15, 0b010, "clrex">;
816 // NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
817 // model patterns with sufficiently fine granularity.
818 let mayLoad = ?, mayStore = ? in {
819 def DMB   : CRmSystemI<barrier_op, 0b101, "dmb",
820                        [(int_aarch64_dmb (i32 imm32_0_15:$CRm))]>;
822 def DSB   : CRmSystemI<barrier_op, 0b100, "dsb",
823                        [(int_aarch64_dsb (i32 imm32_0_15:$CRm))]>;
825 def ISB   : CRmSystemI<barrier_op, 0b110, "isb",
826                        [(int_aarch64_isb (i32 imm32_0_15:$CRm))]>;
828 def TSB   : CRmSystemI<barrier_op, 0b010, "tsb", []> {
829   let CRm        = 0b0010;
830   let Inst{12}   = 0;
831   let Predicates = [HasTRACEV8_4];
834 def DSBnXS  : CRmSystemI<barrier_nxs_op, 0b001, "dsb"> {
835   let CRm{1-0}   = 0b11;
836   let Inst{9-8}  = 0b10;
837   let Predicates = [HasXS];
840 let Predicates = [HasWFxT] in {
841 def WFET : RegInputSystemI<0b0000, 0b000, "wfet">;
842 def WFIT : RegInputSystemI<0b0000, 0b001, "wfit">;
845 // Branch Record Buffer two-word mnemonic instructions
846 class BRBEI<bits<3> op2, string keyword>
847     : SimpleSystemI<0, (ins), "brb", keyword>, Sched<[WriteSys]> {
848   let Inst{31-8} = 0b110101010000100101110010;
849   let Inst{7-5} = op2;
850   let Predicates = [HasBRBE];
852 def BRB_IALL: BRBEI<0b100, "\tiall">;
853 def BRB_INJ:  BRBEI<0b101, "\tinj">;
857 // Allow uppercase and lowercase keyword arguments for BRB IALL and BRB INJ
858 def : TokenAlias<"INJ", "inj">;
859 def : TokenAlias<"IALL", "iall">;
861 // ARMv8.2-A Dot Product
862 let Predicates = [HasDotProd] in {
863 defm SDOT : SIMDThreeSameVectorDot<0, 0, "sdot", AArch64sdot>;
864 defm UDOT : SIMDThreeSameVectorDot<1, 0, "udot", AArch64udot>;
865 defm SDOTlane : SIMDThreeSameVectorDotIndex<0, 0, 0b10, "sdot", AArch64sdot>;
866 defm UDOTlane : SIMDThreeSameVectorDotIndex<1, 0, 0b10, "udot", AArch64udot>;
869 // ARMv8.6-A BFloat
870 let Predicates = [HasBF16] in {
871 defm BFDOT       : SIMDThreeSameVectorBFDot<1, "bfdot">;
872 defm BF16DOTlane : SIMDThreeSameVectorBF16DotI<0, "bfdot">;
873 def BFMMLA       : SIMDThreeSameVectorBF16MatrixMul<"bfmmla">;
874 def BFMLALB      : SIMDBF16MLAL<0, "bfmlalb", int_aarch64_neon_bfmlalb>;
875 def BFMLALT      : SIMDBF16MLAL<1, "bfmlalt", int_aarch64_neon_bfmlalt>;
876 def BFMLALBIdx   : SIMDBF16MLALIndex<0, "bfmlalb", int_aarch64_neon_bfmlalb>;
877 def BFMLALTIdx   : SIMDBF16MLALIndex<1, "bfmlalt", int_aarch64_neon_bfmlalt>;
878 def BFCVTN       : SIMD_BFCVTN;
879 def BFCVTN2      : SIMD_BFCVTN2;
880 def BFCVT        : BF16ToSinglePrecision<"bfcvt">;
882 // Vector-scalar BFDOT:
883 // The second source operand of the 64-bit variant of BF16DOTlane is a 128-bit
884 // register (the instruction uses a single 32-bit lane from it), so the pattern
885 // is a bit tricky.
886 def : Pat<(v2f32 (int_aarch64_neon_bfdot
887                     (v2f32 V64:$Rd), (v4bf16 V64:$Rn),
888                     (v4bf16 (bitconvert
889                       (v2i32 (AArch64duplane32
890                         (v4i32 (bitconvert
891                           (v8bf16 (insert_subvector undef,
892                             (v4bf16 V64:$Rm),
893                             (i64 0))))),
894                         VectorIndexS:$idx)))))),
895           (BF16DOTlanev4bf16 (v2f32 V64:$Rd), (v4bf16 V64:$Rn),
896                              (SUBREG_TO_REG (i32 0), V64:$Rm, dsub),
897                              VectorIndexS:$idx)>;
900 // ARMv8.6A AArch64 matrix multiplication
901 let Predicates = [HasMatMulInt8] in {
902 def  SMMLA : SIMDThreeSameVectorMatMul<0, 0, "smmla", int_aarch64_neon_smmla>;
903 def  UMMLA : SIMDThreeSameVectorMatMul<0, 1, "ummla", int_aarch64_neon_ummla>;
904 def USMMLA : SIMDThreeSameVectorMatMul<1, 0, "usmmla", int_aarch64_neon_usmmla>;
905 defm USDOT : SIMDThreeSameVectorDot<0, 1, "usdot", int_aarch64_neon_usdot>;
906 defm USDOTlane : SIMDThreeSameVectorDotIndex<0, 1, 0b10, "usdot", int_aarch64_neon_usdot>;
908 // sudot lane has a pattern where usdot is expected (there is no sudot).
909 // The second operand is used in the dup operation to repeat the indexed
910 // element.
911 class BaseSIMDSUDOTIndex<bit Q, string dst_kind, string lhs_kind,
912                          string rhs_kind, RegisterOperand RegType,
913                          ValueType AccumType, ValueType InputType>
914       : BaseSIMDThreeSameVectorDotIndex<Q, 0, 1, 0b00, "sudot", dst_kind,
915                                         lhs_kind, rhs_kind, RegType, AccumType,
916                                         InputType, null_frag> {
917   let Pattern = [(set (AccumType RegType:$dst),
918                       (AccumType (int_aarch64_neon_usdot (AccumType RegType:$Rd),
919                                  (InputType (bitconvert (AccumType
920                                     (AArch64duplane32 (v4i32 V128:$Rm),
921                                         VectorIndexS:$idx)))),
922                                  (InputType RegType:$Rn))))];
925 multiclass SIMDSUDOTIndex {
926   def v8i8  : BaseSIMDSUDOTIndex<0, ".2s", ".8b", ".4b", V64, v2i32, v8i8>;
927   def v16i8 : BaseSIMDSUDOTIndex<1, ".4s", ".16b", ".4b", V128, v4i32, v16i8>;
930 defm SUDOTlane : SIMDSUDOTIndex;
934 // ARMv8.2-A FP16 Fused Multiply-Add Long
935 let Predicates = [HasNEON, HasFP16FML] in {
936 defm FMLAL      : SIMDThreeSameVectorFML<0, 1, 0b001, "fmlal", int_aarch64_neon_fmlal>;
937 defm FMLSL      : SIMDThreeSameVectorFML<0, 1, 0b101, "fmlsl", int_aarch64_neon_fmlsl>;
938 defm FMLAL2     : SIMDThreeSameVectorFML<1, 0, 0b001, "fmlal2", int_aarch64_neon_fmlal2>;
939 defm FMLSL2     : SIMDThreeSameVectorFML<1, 0, 0b101, "fmlsl2", int_aarch64_neon_fmlsl2>;
940 defm FMLALlane  : SIMDThreeSameVectorFMLIndex<0, 0b0000, "fmlal", int_aarch64_neon_fmlal>;
941 defm FMLSLlane  : SIMDThreeSameVectorFMLIndex<0, 0b0100, "fmlsl", int_aarch64_neon_fmlsl>;
942 defm FMLAL2lane : SIMDThreeSameVectorFMLIndex<1, 0b1000, "fmlal2", int_aarch64_neon_fmlal2>;
943 defm FMLSL2lane : SIMDThreeSameVectorFMLIndex<1, 0b1100, "fmlsl2", int_aarch64_neon_fmlsl2>;
946 // Armv8.2-A Crypto extensions
947 let Predicates = [HasSHA3] in {
948 def SHA512H   : CryptoRRRTied<0b0, 0b00, "sha512h">;
949 def SHA512H2  : CryptoRRRTied<0b0, 0b01, "sha512h2">;
950 def SHA512SU0 : CryptoRRTied_2D<0b0, 0b00, "sha512su0">;
951 def SHA512SU1 : CryptoRRRTied_2D<0b0, 0b10, "sha512su1">;
952 def RAX1      : CryptoRRR_2D<0b0,0b11, "rax1">;
953 def EOR3      : CryptoRRRR_16B<0b00, "eor3">;
954 def BCAX      : CryptoRRRR_16B<0b01, "bcax">;
955 def XAR       : CryptoRRRi6<"xar">;
957 class SHA3_pattern<Instruction INST, Intrinsic OpNode, ValueType VecTy>
958   : Pat<(VecTy (OpNode (VecTy V128:$Vd), (VecTy V128:$Vn), (VecTy V128:$Vm))),
959         (INST (VecTy V128:$Vd), (VecTy V128:$Vn), (VecTy V128:$Vm))>;
961 def : Pat<(v2i64 (int_aarch64_crypto_sha512su0 (v2i64 V128:$Vn), (v2i64 V128:$Vm))),
962           (SHA512SU0 (v2i64 V128:$Vn), (v2i64 V128:$Vm))>;
964 def : SHA3_pattern<SHA512H, int_aarch64_crypto_sha512h, v2i64>;
965 def : SHA3_pattern<SHA512H2, int_aarch64_crypto_sha512h2, v2i64>;
966 def : SHA3_pattern<SHA512SU1, int_aarch64_crypto_sha512su1, v2i64>;
968 def : SHA3_pattern<EOR3, int_aarch64_crypto_eor3u, v16i8>;
969 def : SHA3_pattern<EOR3, int_aarch64_crypto_eor3u, v8i16>;
970 def : SHA3_pattern<EOR3, int_aarch64_crypto_eor3u, v4i32>;
971 def : SHA3_pattern<EOR3, int_aarch64_crypto_eor3u, v2i64>;
973 def : SHA3_pattern<BCAX, int_aarch64_crypto_bcaxu, v16i8>;
974 def : SHA3_pattern<BCAX, int_aarch64_crypto_bcaxu, v8i16>;
975 def : SHA3_pattern<BCAX, int_aarch64_crypto_bcaxu, v4i32>;
976 def : SHA3_pattern<BCAX, int_aarch64_crypto_bcaxu, v2i64>;
978 def : SHA3_pattern<EOR3, int_aarch64_crypto_eor3s, v16i8>;
979 def : SHA3_pattern<EOR3, int_aarch64_crypto_eor3s, v8i16>;
980 def : SHA3_pattern<EOR3, int_aarch64_crypto_eor3s, v4i32>;
981 def : SHA3_pattern<EOR3, int_aarch64_crypto_eor3s, v2i64>;
983 def : SHA3_pattern<BCAX, int_aarch64_crypto_bcaxs, v16i8>;
984 def : SHA3_pattern<BCAX, int_aarch64_crypto_bcaxs, v8i16>;
985 def : SHA3_pattern<BCAX, int_aarch64_crypto_bcaxs, v4i32>;
986 def : SHA3_pattern<BCAX, int_aarch64_crypto_bcaxs, v2i64>;
988 def : Pat<(v2i64 (int_aarch64_crypto_rax1 (v2i64 V128:$Vn), (v2i64 V128:$Vm))),
989           (RAX1 (v2i64 V128:$Vn), (v2i64 V128:$Vm))>;
991 def : Pat<(v2i64 (int_aarch64_crypto_xar (v2i64 V128:$Vn), (v2i64 V128:$Vm), (i64 timm0_63:$imm))),
992           (XAR (v2i64 V128:$Vn), (v2i64 V128:$Vm), (timm0_63:$imm))>;
995 } // HasSHA3
997 let Predicates = [HasSM4] in {
998 def SM3TT1A   : CryptoRRRi2Tied<0b0, 0b00, "sm3tt1a">;
999 def SM3TT1B   : CryptoRRRi2Tied<0b0, 0b01, "sm3tt1b">;
1000 def SM3TT2A   : CryptoRRRi2Tied<0b0, 0b10, "sm3tt2a">;
1001 def SM3TT2B   : CryptoRRRi2Tied<0b0, 0b11, "sm3tt2b">;
1002 def SM3SS1    : CryptoRRRR_4S<0b10, "sm3ss1">;
1003 def SM3PARTW1 : CryptoRRRTied_4S<0b1, 0b00, "sm3partw1">;
1004 def SM3PARTW2 : CryptoRRRTied_4S<0b1, 0b01, "sm3partw2">;
1005 def SM4ENCKEY : CryptoRRR_4S<0b1, 0b10, "sm4ekey">;
1006 def SM4E      : CryptoRRTied_4S<0b0, 0b01, "sm4e">;
1008 def : Pat<(v4i32 (int_aarch64_crypto_sm3ss1 (v4i32 V128:$Vn), (v4i32 V128:$Vm), (v4i32 V128:$Va))),
1009           (SM3SS1 (v4i32 V128:$Vn), (v4i32 V128:$Vm), (v4i32 V128:$Va))>;
1011 class SM3PARTW_pattern<Instruction INST, Intrinsic OpNode>
1012   : Pat<(v4i32 (OpNode (v4i32 V128:$Vd), (v4i32 V128:$Vn), (v4i32 V128:$Vm))),
1013         (INST (v4i32 V128:$Vd), (v4i32 V128:$Vn), (v4i32 V128:$Vm))>;
1015 class SM3TT_pattern<Instruction INST, Intrinsic OpNode>
1016   : Pat<(v4i32 (OpNode (v4i32 V128:$Vd), (v4i32 V128:$Vn), (v4i32 V128:$Vm), (i64 VectorIndexS_timm:$imm) )),
1017         (INST (v4i32 V128:$Vd), (v4i32 V128:$Vn), (v4i32 V128:$Vm), (VectorIndexS_timm:$imm))>;
1019 class SM4_pattern<Instruction INST, Intrinsic OpNode>
1020   : Pat<(v4i32 (OpNode (v4i32 V128:$Vn), (v4i32 V128:$Vm))),
1021         (INST (v4i32 V128:$Vn), (v4i32 V128:$Vm))>;
1023 def : SM3PARTW_pattern<SM3PARTW1, int_aarch64_crypto_sm3partw1>;
1024 def : SM3PARTW_pattern<SM3PARTW2, int_aarch64_crypto_sm3partw2>;
1026 def : SM3TT_pattern<SM3TT1A, int_aarch64_crypto_sm3tt1a>;
1027 def : SM3TT_pattern<SM3TT1B, int_aarch64_crypto_sm3tt1b>;
1028 def : SM3TT_pattern<SM3TT2A, int_aarch64_crypto_sm3tt2a>;
1029 def : SM3TT_pattern<SM3TT2B, int_aarch64_crypto_sm3tt2b>;
1031 def : SM4_pattern<SM4ENCKEY, int_aarch64_crypto_sm4ekey>;
1032 def : SM4_pattern<SM4E, int_aarch64_crypto_sm4e>;
1033 } // HasSM4
1035 let Predicates = [HasRCPC] in {
1036   // v8.3 Release Consistent Processor Consistent support, optional in v8.2.
1037   def LDAPRB  : RCPCLoad<0b00, "ldaprb", GPR32>;
1038   def LDAPRH  : RCPCLoad<0b01, "ldaprh", GPR32>;
1039   def LDAPRW  : RCPCLoad<0b10, "ldapr", GPR32>;
1040   def LDAPRX  : RCPCLoad<0b11, "ldapr", GPR64>;
1043 // v8.3a complex add and multiply-accumulate. No predicate here, that is done
1044 // inside the multiclass as the FP16 versions need different predicates.
1045 defm FCMLA : SIMDThreeSameVectorTiedComplexHSD<1, 0b110, complexrotateop,
1046                                                "fcmla", null_frag>;
1047 defm FCADD : SIMDThreeSameVectorComplexHSD<1, 0b111, complexrotateopodd,
1048                                            "fcadd", null_frag>;
1049 defm FCMLA : SIMDIndexedTiedComplexHSD<1, 0, 1, complexrotateop, "fcmla",
1050                                        null_frag>;
1052 let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
1053   def : Pat<(v4f16 (int_aarch64_neon_vcadd_rot90 (v4f16 V64:$Rn), (v4f16 V64:$Rm))),
1054             (FCADDv4f16 (v4f16 V64:$Rn), (v4f16 V64:$Rm), (i32 0))>;
1055   def : Pat<(v4f16 (int_aarch64_neon_vcadd_rot270 (v4f16 V64:$Rn), (v4f16 V64:$Rm))),
1056             (FCADDv4f16 (v4f16 V64:$Rn), (v4f16 V64:$Rm), (i32 1))>;
1057   def : Pat<(v8f16 (int_aarch64_neon_vcadd_rot90 (v8f16 V128:$Rn), (v8f16 V128:$Rm))),
1058             (FCADDv8f16 (v8f16 V128:$Rn), (v8f16 V128:$Rm), (i32 0))>;
1059   def : Pat<(v8f16 (int_aarch64_neon_vcadd_rot270 (v8f16 V128:$Rn), (v8f16 V128:$Rm))),
1060             (FCADDv8f16 (v8f16 V128:$Rn), (v8f16 V128:$Rm), (i32 1))>;
1063 let Predicates = [HasComplxNum, HasNEON] in {
1064   def : Pat<(v2f32 (int_aarch64_neon_vcadd_rot90 (v2f32 V64:$Rn), (v2f32 V64:$Rm))),
1065             (FCADDv2f32 (v2f32 V64:$Rn), (v2f32 V64:$Rm), (i32 0))>;
1066   def : Pat<(v2f32 (int_aarch64_neon_vcadd_rot270 (v2f32 V64:$Rn), (v2f32 V64:$Rm))),
1067             (FCADDv2f32 (v2f32 V64:$Rn), (v2f32 V64:$Rm), (i32 1))>;
1068   foreach Ty = [v4f32, v2f64] in {
1069     def : Pat<(Ty (int_aarch64_neon_vcadd_rot90 (Ty V128:$Rn), (Ty V128:$Rm))),
1070               (!cast<Instruction>("FCADD"#Ty) (Ty V128:$Rn), (Ty V128:$Rm), (i32 0))>;
1071     def : Pat<(Ty (int_aarch64_neon_vcadd_rot270 (Ty V128:$Rn), (Ty V128:$Rm))),
1072               (!cast<Instruction>("FCADD"#Ty) (Ty V128:$Rn), (Ty V128:$Rm), (i32 1))>;
1073   }
1076 multiclass FCMLA_PATS<ValueType ty, DAGOperand Reg> {
1077   def : Pat<(ty (int_aarch64_neon_vcmla_rot0 (ty Reg:$Rd), (ty Reg:$Rn), (ty Reg:$Rm))),
1078             (!cast<Instruction>("FCMLA" # ty) $Rd, $Rn, $Rm, 0)>;
1079   def : Pat<(ty (int_aarch64_neon_vcmla_rot90 (ty Reg:$Rd), (ty Reg:$Rn), (ty Reg:$Rm))),
1080             (!cast<Instruction>("FCMLA" # ty) $Rd, $Rn, $Rm, 1)>;
1081   def : Pat<(ty (int_aarch64_neon_vcmla_rot180 (ty Reg:$Rd), (ty Reg:$Rn), (ty Reg:$Rm))),
1082             (!cast<Instruction>("FCMLA" # ty) $Rd, $Rn, $Rm, 2)>;
1083   def : Pat<(ty (int_aarch64_neon_vcmla_rot270 (ty Reg:$Rd), (ty Reg:$Rn), (ty Reg:$Rm))),
1084             (!cast<Instruction>("FCMLA" # ty) $Rd, $Rn, $Rm, 3)>;
1087 multiclass FCMLA_LANE_PATS<ValueType ty, DAGOperand Reg, dag RHSDup> {
1088   def : Pat<(ty (int_aarch64_neon_vcmla_rot0 (ty Reg:$Rd), (ty Reg:$Rn), RHSDup)),
1089             (!cast<Instruction>("FCMLA" # ty # "_indexed") $Rd, $Rn, $Rm, VectorIndexS:$idx, 0)>;
1090   def : Pat<(ty (int_aarch64_neon_vcmla_rot90 (ty Reg:$Rd), (ty Reg:$Rn), RHSDup)),
1091             (!cast<Instruction>("FCMLA" # ty # "_indexed") $Rd, $Rn, $Rm, VectorIndexS:$idx, 1)>;
1092   def : Pat<(ty (int_aarch64_neon_vcmla_rot180 (ty Reg:$Rd), (ty Reg:$Rn), RHSDup)),
1093             (!cast<Instruction>("FCMLA" # ty # "_indexed") $Rd, $Rn, $Rm, VectorIndexS:$idx, 2)>;
1094   def : Pat<(ty (int_aarch64_neon_vcmla_rot270 (ty Reg:$Rd), (ty Reg:$Rn), RHSDup)),
1095             (!cast<Instruction>("FCMLA" # ty # "_indexed") $Rd, $Rn, $Rm, VectorIndexS:$idx, 3)>;
1099 let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
1100   defm : FCMLA_PATS<v4f16, V64>;
1101   defm : FCMLA_PATS<v8f16, V128>;
1103   defm : FCMLA_LANE_PATS<v4f16, V64,
1104                          (v4f16 (bitconvert (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexD:$idx))))>;
1105   defm : FCMLA_LANE_PATS<v8f16, V128,
1106                          (v8f16 (bitconvert (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))>;
1108 let Predicates = [HasComplxNum, HasNEON] in {
1109   defm : FCMLA_PATS<v2f32, V64>;
1110   defm : FCMLA_PATS<v4f32, V128>;
1111   defm : FCMLA_PATS<v2f64, V128>;
1113   defm : FCMLA_LANE_PATS<v4f32, V128,
1114                          (v4f32 (bitconvert (v2i64 (AArch64duplane64 (v2i64 V128:$Rm), VectorIndexD:$idx))))>;
1117 // v8.3a Pointer Authentication
1118 // These instructions inhabit part of the hint space and so can be used for
1119 // armv8 targets. Keeping the old HINT mnemonic when compiling without PA is
1120 // important for compatibility with other assemblers (e.g. GAS) when building
1121 // software compatible with both CPUs that do or don't implement PA.
1122 let Uses = [LR], Defs = [LR] in {
1123   def PACIAZ   : SystemNoOperands<0b000, "hint\t#24">;
1124   def PACIBZ   : SystemNoOperands<0b010, "hint\t#26">;
1125   let isAuthenticated = 1 in {
1126     def AUTIAZ   : SystemNoOperands<0b100, "hint\t#28">;
1127     def AUTIBZ   : SystemNoOperands<0b110, "hint\t#30">;
1128   }
1130 let Uses = [LR, SP], Defs = [LR] in {
1131   def PACIASP  : SystemNoOperands<0b001, "hint\t#25">;
1132   def PACIBSP  : SystemNoOperands<0b011, "hint\t#27">;
1133   let isAuthenticated = 1 in {
1134     def AUTIASP  : SystemNoOperands<0b101, "hint\t#29">;
1135     def AUTIBSP  : SystemNoOperands<0b111, "hint\t#31">;
1136   }
1138 let Uses = [X16, X17], Defs = [X17], CRm = 0b0001 in {
1139   def PACIA1716  : SystemNoOperands<0b000, "hint\t#8">;
1140   def PACIB1716  : SystemNoOperands<0b010, "hint\t#10">;
1141   let isAuthenticated = 1 in {
1142     def AUTIA1716  : SystemNoOperands<0b100, "hint\t#12">;
1143     def AUTIB1716  : SystemNoOperands<0b110, "hint\t#14">;
1144   }
1147 let Uses = [LR], Defs = [LR], CRm = 0b0000 in {
1148   def XPACLRI   : SystemNoOperands<0b111, "hint\t#7">;
1151 // In order to be able to write readable assembly, LLVM should accept assembly
1152 // inputs that use pointer authentication mnemonics, even with PA disabled.
1153 // However, in order to be compatible with other assemblers (e.g. GAS), LLVM
1154 // should not emit these mnemonics unless PA is enabled.
1155 def : InstAlias<"paciaz", (PACIAZ), 0>;
1156 def : InstAlias<"pacibz", (PACIBZ), 0>;
1157 def : InstAlias<"autiaz", (AUTIAZ), 0>;
1158 def : InstAlias<"autibz", (AUTIBZ), 0>;
1159 def : InstAlias<"paciasp", (PACIASP), 0>;
1160 def : InstAlias<"pacibsp", (PACIBSP), 0>;
1161 def : InstAlias<"autiasp", (AUTIASP), 0>;
1162 def : InstAlias<"autibsp", (AUTIBSP), 0>;
1163 def : InstAlias<"pacia1716", (PACIA1716), 0>;
1164 def : InstAlias<"pacib1716", (PACIB1716), 0>;
1165 def : InstAlias<"autia1716", (AUTIA1716), 0>;
1166 def : InstAlias<"autib1716", (AUTIB1716), 0>;
1167 def : InstAlias<"xpaclri", (XPACLRI), 0>;
1169 // These pointer authentication instructions require armv8.3a
1170 let Predicates = [HasPAuth] in {
1172   // When PA is enabled, a better mnemonic should be emitted.
1173   def : InstAlias<"paciaz", (PACIAZ), 1>;
1174   def : InstAlias<"pacibz", (PACIBZ), 1>;
1175   def : InstAlias<"autiaz", (AUTIAZ), 1>;
1176   def : InstAlias<"autibz", (AUTIBZ), 1>;
1177   def : InstAlias<"paciasp", (PACIASP), 1>;
1178   def : InstAlias<"pacibsp", (PACIBSP), 1>;
1179   def : InstAlias<"autiasp", (AUTIASP), 1>;
1180   def : InstAlias<"autibsp", (AUTIBSP), 1>;
1181   def : InstAlias<"pacia1716", (PACIA1716), 1>;
1182   def : InstAlias<"pacib1716", (PACIB1716), 1>;
1183   def : InstAlias<"autia1716", (AUTIA1716), 1>;
1184   def : InstAlias<"autib1716", (AUTIB1716), 1>;
1185   def : InstAlias<"xpaclri", (XPACLRI), 1>;
1187   multiclass SignAuth<bits<3> prefix, bits<3> prefix_z, string asm> {
1188     def IA   : SignAuthOneData<prefix, 0b00, !strconcat(asm, "ia")>;
1189     def IB   : SignAuthOneData<prefix, 0b01, !strconcat(asm, "ib")>;
1190     def DA   : SignAuthOneData<prefix, 0b10, !strconcat(asm, "da")>;
1191     def DB   : SignAuthOneData<prefix, 0b11, !strconcat(asm, "db")>;
1192     def IZA  : SignAuthZero<prefix_z, 0b00, !strconcat(asm, "iza")>;
1193     def DZA  : SignAuthZero<prefix_z, 0b10, !strconcat(asm, "dza")>;
1194     def IZB  : SignAuthZero<prefix_z, 0b01, !strconcat(asm, "izb")>;
1195     def DZB  : SignAuthZero<prefix_z, 0b11, !strconcat(asm, "dzb")>;
1196   }
1198   defm PAC : SignAuth<0b000, 0b010, "pac">;
1199   defm AUT : SignAuth<0b001, 0b011, "aut">;
1201   def XPACI : ClearAuth<0, "xpaci">;
1202   def XPACD : ClearAuth<1, "xpacd">;
1203   def PACGA : SignAuthTwoOperand<0b1100, "pacga", null_frag>;
1205   // Combined Instructions
1206   let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1  in {
1207     def BRAA    : AuthBranchTwoOperands<0, 0, "braa">;
1208     def BRAB    : AuthBranchTwoOperands<0, 1, "brab">;
1209   }
1210   let isCall = 1, Defs = [LR], Uses = [SP] in {
1211     def BLRAA   : AuthBranchTwoOperands<1, 0, "blraa">;
1212     def BLRAB   : AuthBranchTwoOperands<1, 1, "blrab">;
1213   }
1215   let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1  in {
1216     def BRAAZ   : AuthOneOperand<0b000, 0, "braaz">;
1217     def BRABZ   : AuthOneOperand<0b000, 1, "brabz">;
1218   }
1219   let isCall = 1, Defs = [LR], Uses = [SP] in {
1220     def BLRAAZ  : AuthOneOperand<0b001, 0, "blraaz">;
1221     def BLRABZ  : AuthOneOperand<0b001, 1, "blrabz">;
1222   }
1224   let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
1225     def RETAA   : AuthReturn<0b010, 0, "retaa">;
1226     def RETAB   : AuthReturn<0b010, 1, "retab">;
1227     def ERETAA  : AuthReturn<0b100, 0, "eretaa">;
1228     def ERETAB  : AuthReturn<0b100, 1, "eretab">;
1229   }
1231   defm LDRAA  : AuthLoad<0, "ldraa", simm10Scaled>;
1232   defm LDRAB  : AuthLoad<1, "ldrab", simm10Scaled>;
1236 // v8.3a floating point conversion for javascript
1237 let Predicates = [HasJS, HasFPARMv8], Defs = [NZCV] in
1238 def FJCVTZS  : BaseFPToIntegerUnscaled<0b01, 0b11, 0b110, FPR64, GPR32,
1239                                       "fjcvtzs",
1240                                       [(set GPR32:$Rd,
1241                                          (int_aarch64_fjcvtzs FPR64:$Rn))]> {
1242   let Inst{31} = 0;
1243 } // HasJS, HasFPARMv8
1245 // v8.4 Flag manipulation instructions
1246 let Predicates = [HasFlagM], Defs = [NZCV], Uses = [NZCV] in {
1247 def CFINV : SimpleSystemI<0, (ins), "cfinv", "">, Sched<[WriteSys]> {
1248   let Inst{20-5} = 0b0000001000000000;
1250 def SETF8  : BaseFlagManipulation<0, 0, (ins GPR32:$Rn), "setf8", "{\t$Rn}">;
1251 def SETF16 : BaseFlagManipulation<0, 1, (ins GPR32:$Rn), "setf16", "{\t$Rn}">;
1252 def RMIF   : FlagRotate<(ins GPR64:$Rn, uimm6:$imm, imm0_15:$mask), "rmif",
1253                         "{\t$Rn, $imm, $mask}">;
1254 } // HasFlagM
1256 // v8.5 flag manipulation instructions
1257 let Predicates = [HasAltNZCV], Uses = [NZCV], Defs = [NZCV] in {
1259 def XAFLAG : PstateWriteSimple<(ins), "xaflag", "">, Sched<[WriteSys]> {
1260   let Inst{18-16} = 0b000;
1261   let Inst{11-8} = 0b0000;
1262   let Unpredictable{11-8} = 0b1111;
1263   let Inst{7-5} = 0b001;
1266 def AXFLAG : PstateWriteSimple<(ins), "axflag", "">, Sched<[WriteSys]> {
1267   let Inst{18-16} = 0b000;
1268   let Inst{11-8} = 0b0000;
1269   let Unpredictable{11-8} = 0b1111;
1270   let Inst{7-5} = 0b010;
1272 } // HasAltNZCV
1275 // Armv8.5-A speculation barrier
1276 def SB : SimpleSystemI<0, (ins), "sb", "">, Sched<[]> {
1277   let Inst{20-5} = 0b0001100110000111;
1278   let Unpredictable{11-8} = 0b1111;
1279   let Predicates = [HasSB];
1280   let hasSideEffects = 1;
1283 def : InstAlias<"clrex", (CLREX 0xf)>;
1284 def : InstAlias<"isb", (ISB 0xf)>;
1285 def : InstAlias<"ssbb", (DSB 0)>;
1286 def : InstAlias<"pssbb", (DSB 4)>;
1288 def MRS    : MRSI;
1289 def MSR    : MSRI;
1290 def MSRpstateImm1 : MSRpstateImm0_1;
1291 def MSRpstateImm4 : MSRpstateImm0_15;
1293 def : Pat<(AArch64mrs imm:$id),
1294           (MRS imm:$id)>;
1296 // The thread pointer (on Linux, at least, where this has been implemented) is
1297 // TPIDR_EL0.
1298 def MOVbaseTLS : Pseudo<(outs GPR64:$dst), (ins),
1299                        [(set GPR64:$dst, AArch64threadpointer)]>, Sched<[WriteSys]>;
1301 let Uses = [ X9 ], Defs = [ X16, X17, LR, NZCV ] in {
1302 def HWASAN_CHECK_MEMACCESS : Pseudo<
1303   (outs), (ins GPR64noip:$ptr, i32imm:$accessinfo),
1304   [(int_hwasan_check_memaccess X9, GPR64noip:$ptr, (i32 timm:$accessinfo))]>,
1305   Sched<[]>;
1308 let Uses = [ X20 ], Defs = [ X16, X17, LR, NZCV ] in {
1309 def HWASAN_CHECK_MEMACCESS_SHORTGRANULES : Pseudo<
1310   (outs), (ins GPR64noip:$ptr, i32imm:$accessinfo),
1311   [(int_hwasan_check_memaccess_shortgranules X20, GPR64noip:$ptr, (i32 timm:$accessinfo))]>,
1312   Sched<[]>;
1315 // The cycle counter PMC register is PMCCNTR_EL0.
1316 let Predicates = [HasPerfMon] in
1317 def : Pat<(readcyclecounter), (MRS 0xdce8)>;
1319 // FPCR register
1320 def : Pat<(i64 (int_aarch64_get_fpcr)), (MRS 0xda20)>;
1321 def : Pat<(int_aarch64_set_fpcr i64:$val), (MSR 0xda20, GPR64:$val)>;
1323 // Generic system instructions
1324 def SYSxt  : SystemXtI<0, "sys">;
1325 def SYSLxt : SystemLXtI<1, "sysl">;
1327 def : InstAlias<"sys $op1, $Cn, $Cm, $op2",
1328                 (SYSxt imm0_7:$op1, sys_cr_op:$Cn,
1329                  sys_cr_op:$Cm, imm0_7:$op2, XZR)>;
1332 let Predicates = [HasTME] in {
1334 def TSTART : TMSystemI<0b0000, "tstart",
1335                       [(set GPR64:$Rt, (int_aarch64_tstart))]>;
1337 def TCOMMIT : TMSystemINoOperand<0b0000, "tcommit", [(int_aarch64_tcommit)]>;
1339 def TCANCEL : TMSystemException<0b011, "tcancel",
1340                                 [(int_aarch64_tcancel i64_imm0_65535:$imm)]>;
1342 def TTEST : TMSystemI<0b0001, "ttest", [(set GPR64:$Rt, (int_aarch64_ttest))]> {
1343   let mayLoad = 0;
1344   let mayStore = 0;
1346 } // HasTME
1348 //===----------------------------------------------------------------------===//
1349 // Move immediate instructions.
1350 //===----------------------------------------------------------------------===//
1352 defm MOVK : InsertImmediate<0b11, "movk">;
1353 defm MOVN : MoveImmediate<0b00, "movn">;
1355 let PostEncoderMethod = "fixMOVZ" in
1356 defm MOVZ : MoveImmediate<0b10, "movz">;
1358 // First group of aliases covers an implicit "lsl #0".
1359 def : InstAlias<"movk $dst, $imm", (MOVKWi GPR32:$dst, i32_imm0_65535:$imm, 0), 0>;
1360 def : InstAlias<"movk $dst, $imm", (MOVKXi GPR64:$dst, i32_imm0_65535:$imm, 0), 0>;
1361 def : InstAlias<"movn $dst, $imm", (MOVNWi GPR32:$dst, i32_imm0_65535:$imm, 0)>;
1362 def : InstAlias<"movn $dst, $imm", (MOVNXi GPR64:$dst, i32_imm0_65535:$imm, 0)>;
1363 def : InstAlias<"movz $dst, $imm", (MOVZWi GPR32:$dst, i32_imm0_65535:$imm, 0)>;
1364 def : InstAlias<"movz $dst, $imm", (MOVZXi GPR64:$dst, i32_imm0_65535:$imm, 0)>;
1366 // Next, we have various ELF relocations with the ":XYZ_g0:sym" syntax.
1367 def : InstAlias<"movz $Rd, $sym", (MOVZXi GPR64:$Rd, movw_symbol_g3:$sym, 48)>;
1368 def : InstAlias<"movz $Rd, $sym", (MOVZXi GPR64:$Rd, movw_symbol_g2:$sym, 32)>;
1369 def : InstAlias<"movz $Rd, $sym", (MOVZXi GPR64:$Rd, movw_symbol_g1:$sym, 16)>;
1370 def : InstAlias<"movz $Rd, $sym", (MOVZXi GPR64:$Rd, movw_symbol_g0:$sym, 0)>;
1372 def : InstAlias<"movn $Rd, $sym", (MOVNXi GPR64:$Rd, movw_symbol_g3:$sym, 48)>;
1373 def : InstAlias<"movn $Rd, $sym", (MOVNXi GPR64:$Rd, movw_symbol_g2:$sym, 32)>;
1374 def : InstAlias<"movn $Rd, $sym", (MOVNXi GPR64:$Rd, movw_symbol_g1:$sym, 16)>;
1375 def : InstAlias<"movn $Rd, $sym", (MOVNXi GPR64:$Rd, movw_symbol_g0:$sym, 0)>;
1377 def : InstAlias<"movk $Rd, $sym", (MOVKXi GPR64:$Rd, movw_symbol_g3:$sym, 48), 0>;
1378 def : InstAlias<"movk $Rd, $sym", (MOVKXi GPR64:$Rd, movw_symbol_g2:$sym, 32), 0>;
1379 def : InstAlias<"movk $Rd, $sym", (MOVKXi GPR64:$Rd, movw_symbol_g1:$sym, 16), 0>;
1380 def : InstAlias<"movk $Rd, $sym", (MOVKXi GPR64:$Rd, movw_symbol_g0:$sym, 0), 0>;
1382 def : InstAlias<"movz $Rd, $sym", (MOVZWi GPR32:$Rd, movw_symbol_g1:$sym, 16)>;
1383 def : InstAlias<"movz $Rd, $sym", (MOVZWi GPR32:$Rd, movw_symbol_g0:$sym, 0)>;
1385 def : InstAlias<"movn $Rd, $sym", (MOVNWi GPR32:$Rd, movw_symbol_g1:$sym, 16)>;
1386 def : InstAlias<"movn $Rd, $sym", (MOVNWi GPR32:$Rd, movw_symbol_g0:$sym, 0)>;
1388 def : InstAlias<"movk $Rd, $sym", (MOVKWi GPR32:$Rd, movw_symbol_g1:$sym, 16), 0>;
1389 def : InstAlias<"movk $Rd, $sym", (MOVKWi GPR32:$Rd, movw_symbol_g0:$sym, 0), 0>;
1391 // Final group of aliases covers true "mov $Rd, $imm" cases.
1392 multiclass movw_mov_alias<string basename,Instruction INST, RegisterClass GPR,
1393                           int width, int shift> {
1394   def _asmoperand : AsmOperandClass {
1395     let Name = basename # width # "_lsl" # shift # "MovAlias";
1396     let PredicateMethod = "is" # basename # "MovAlias<" # width # ", "
1397                                # shift # ">";
1398     let RenderMethod = "add" # basename # "MovAliasOperands<" # shift # ">";
1399   }
1401   def _movimm : Operand<i32> {
1402     let ParserMatchClass = !cast<AsmOperandClass>(NAME # "_asmoperand");
1403   }
1405   def : InstAlias<"mov $Rd, $imm",
1406                   (INST GPR:$Rd, !cast<Operand>(NAME # "_movimm"):$imm, shift)>;
1409 defm : movw_mov_alias<"MOVZ", MOVZWi, GPR32, 32, 0>;
1410 defm : movw_mov_alias<"MOVZ", MOVZWi, GPR32, 32, 16>;
1412 defm : movw_mov_alias<"MOVZ", MOVZXi, GPR64, 64, 0>;
1413 defm : movw_mov_alias<"MOVZ", MOVZXi, GPR64, 64, 16>;
1414 defm : movw_mov_alias<"MOVZ", MOVZXi, GPR64, 64, 32>;
1415 defm : movw_mov_alias<"MOVZ", MOVZXi, GPR64, 64, 48>;
1417 defm : movw_mov_alias<"MOVN", MOVNWi, GPR32, 32, 0>;
1418 defm : movw_mov_alias<"MOVN", MOVNWi, GPR32, 32, 16>;
1420 defm : movw_mov_alias<"MOVN", MOVNXi, GPR64, 64, 0>;
1421 defm : movw_mov_alias<"MOVN", MOVNXi, GPR64, 64, 16>;
1422 defm : movw_mov_alias<"MOVN", MOVNXi, GPR64, 64, 32>;
1423 defm : movw_mov_alias<"MOVN", MOVNXi, GPR64, 64, 48>;
1425 let isReMaterializable = 1, isCodeGenOnly = 1, isMoveImm = 1,
1426     isAsCheapAsAMove = 1 in {
1427 // FIXME: The following pseudo instructions are only needed because remat
1428 // cannot handle multiple instructions.  When that changes, we can select
1429 // directly to the real instructions and get rid of these pseudos.
1431 def MOVi32imm
1432     : Pseudo<(outs GPR32:$dst), (ins i32imm:$src),
1433              [(set GPR32:$dst, imm:$src)]>,
1434       Sched<[WriteImm]>;
1435 def MOVi64imm
1436     : Pseudo<(outs GPR64:$dst), (ins i64imm:$src),
1437              [(set GPR64:$dst, imm:$src)]>,
1438       Sched<[WriteImm]>;
1439 } // isReMaterializable, isCodeGenOnly
1441 // If possible, we want to use MOVi32imm even for 64-bit moves. This gives the
1442 // eventual expansion code fewer bits to worry about getting right. Marshalling
1443 // the types is a little tricky though:
1444 def i64imm_32bit : ImmLeaf<i64, [{
1445   return (Imm & 0xffffffffULL) == static_cast<uint64_t>(Imm);
1446 }]>;
1448 def s64imm_32bit : ImmLeaf<i64, [{
1449   int64_t Imm64 = static_cast<int64_t>(Imm);
1450   return Imm64 >= std::numeric_limits<int32_t>::min() &&
1451          Imm64 <= std::numeric_limits<int32_t>::max();
1452 }]>;
1454 def trunc_imm : SDNodeXForm<imm, [{
1455   return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i32);
1456 }]>;
1458 def gi_trunc_imm : GICustomOperandRenderer<"renderTruncImm">,
1459   GISDNodeXFormEquiv<trunc_imm>;
1461 let Predicates = [OptimizedGISelOrOtherSelector] in {
1462 // The SUBREG_TO_REG isn't eliminated at -O0, which can result in pointless
1463 // copies.
1464 def : Pat<(i64 i64imm_32bit:$src),
1465           (SUBREG_TO_REG (i64 0), (MOVi32imm (trunc_imm imm:$src)), sub_32)>;
1468 // Materialize FP constants via MOVi32imm/MOVi64imm (MachO large code model).
1469 def bitcast_fpimm_to_i32 : SDNodeXForm<fpimm, [{
1470 return CurDAG->getTargetConstant(
1471   N->getValueAPF().bitcastToAPInt().getZExtValue(), SDLoc(N), MVT::i32);
1472 }]>;
1474 def bitcast_fpimm_to_i64 : SDNodeXForm<fpimm, [{
1475 return CurDAG->getTargetConstant(
1476   N->getValueAPF().bitcastToAPInt().getZExtValue(), SDLoc(N), MVT::i64);
1477 }]>;
1480 def : Pat<(f32 fpimm:$in),
1481   (COPY_TO_REGCLASS (MOVi32imm (bitcast_fpimm_to_i32 f32:$in)), FPR32)>;
1482 def : Pat<(f64 fpimm:$in),
1483   (COPY_TO_REGCLASS (MOVi64imm (bitcast_fpimm_to_i64 f64:$in)), FPR64)>;
1486 // Deal with the various forms of (ELF) large addressing with MOVZ/MOVK
1487 // sequences.
1488 def : Pat<(AArch64WrapperLarge tglobaladdr:$g3, tglobaladdr:$g2,
1489                              tglobaladdr:$g1, tglobaladdr:$g0),
1490           (MOVKXi (MOVKXi (MOVKXi (MOVZXi tglobaladdr:$g0, 0),
1491                                   tglobaladdr:$g1, 16),
1492                           tglobaladdr:$g2, 32),
1493                   tglobaladdr:$g3, 48)>;
1495 def : Pat<(AArch64WrapperLarge tblockaddress:$g3, tblockaddress:$g2,
1496                              tblockaddress:$g1, tblockaddress:$g0),
1497           (MOVKXi (MOVKXi (MOVKXi (MOVZXi tblockaddress:$g0, 0),
1498                                   tblockaddress:$g1, 16),
1499                           tblockaddress:$g2, 32),
1500                   tblockaddress:$g3, 48)>;
1502 def : Pat<(AArch64WrapperLarge tconstpool:$g3, tconstpool:$g2,
1503                              tconstpool:$g1, tconstpool:$g0),
1504           (MOVKXi (MOVKXi (MOVKXi (MOVZXi tconstpool:$g0, 0),
1505                                   tconstpool:$g1, 16),
1506                           tconstpool:$g2, 32),
1507                   tconstpool:$g3, 48)>;
1509 def : Pat<(AArch64WrapperLarge tjumptable:$g3, tjumptable:$g2,
1510                              tjumptable:$g1, tjumptable:$g0),
1511           (MOVKXi (MOVKXi (MOVKXi (MOVZXi tjumptable:$g0, 0),
1512                                   tjumptable:$g1, 16),
1513                           tjumptable:$g2, 32),
1514                   tjumptable:$g3, 48)>;
1517 //===----------------------------------------------------------------------===//
1518 // Arithmetic instructions.
1519 //===----------------------------------------------------------------------===//
1521 // Add/subtract with carry.
1522 defm ADC : AddSubCarry<0, "adc", "adcs", AArch64adc, AArch64adc_flag>;
1523 defm SBC : AddSubCarry<1, "sbc", "sbcs", AArch64sbc, AArch64sbc_flag>;
1525 def : InstAlias<"ngc $dst, $src",  (SBCWr  GPR32:$dst, WZR, GPR32:$src)>;
1526 def : InstAlias<"ngc $dst, $src",  (SBCXr  GPR64:$dst, XZR, GPR64:$src)>;
1527 def : InstAlias<"ngcs $dst, $src", (SBCSWr GPR32:$dst, WZR, GPR32:$src)>;
1528 def : InstAlias<"ngcs $dst, $src", (SBCSXr GPR64:$dst, XZR, GPR64:$src)>;
1530 // Add/subtract
1531 defm ADD : AddSub<0, "add", "sub", add>;
1532 defm SUB : AddSub<1, "sub", "add">;
1534 def : InstAlias<"mov $dst, $src",
1535                 (ADDWri GPR32sponly:$dst, GPR32sp:$src, 0, 0)>;
1536 def : InstAlias<"mov $dst, $src",
1537                 (ADDWri GPR32sp:$dst, GPR32sponly:$src, 0, 0)>;
1538 def : InstAlias<"mov $dst, $src",
1539                 (ADDXri GPR64sponly:$dst, GPR64sp:$src, 0, 0)>;
1540 def : InstAlias<"mov $dst, $src",
1541                 (ADDXri GPR64sp:$dst, GPR64sponly:$src, 0, 0)>;
1543 defm ADDS : AddSubS<0, "adds", AArch64add_flag, "cmn", "subs", "cmp">;
1544 defm SUBS : AddSubS<1, "subs", AArch64sub_flag, "cmp", "adds", "cmn">;
1546 // Use SUBS instead of SUB to enable CSE between SUBS and SUB.
1547 def : Pat<(sub GPR32sp:$Rn, addsub_shifted_imm32:$imm),
1548           (SUBSWri GPR32sp:$Rn, addsub_shifted_imm32:$imm)>;
1549 def : Pat<(sub GPR64sp:$Rn, addsub_shifted_imm64:$imm),
1550           (SUBSXri GPR64sp:$Rn, addsub_shifted_imm64:$imm)>;
1551 def : Pat<(sub GPR32:$Rn, GPR32:$Rm),
1552           (SUBSWrr GPR32:$Rn, GPR32:$Rm)>;
1553 def : Pat<(sub GPR64:$Rn, GPR64:$Rm),
1554           (SUBSXrr GPR64:$Rn, GPR64:$Rm)>;
1555 def : Pat<(sub GPR32:$Rn, arith_shifted_reg32:$Rm),
1556           (SUBSWrs GPR32:$Rn, arith_shifted_reg32:$Rm)>;
1557 def : Pat<(sub GPR64:$Rn, arith_shifted_reg64:$Rm),
1558           (SUBSXrs GPR64:$Rn, arith_shifted_reg64:$Rm)>;
1559 let AddedComplexity = 1 in {
1560 def : Pat<(sub GPR32sp:$R2, arith_extended_reg32_i32:$R3),
1561           (SUBSWrx GPR32sp:$R2, arith_extended_reg32_i32:$R3)>;
1562 def : Pat<(sub GPR64sp:$R2, arith_extended_reg32to64_i64:$R3),
1563           (SUBSXrx GPR64sp:$R2, arith_extended_reg32to64_i64:$R3)>;
1566 // Because of the immediate format for add/sub-imm instructions, the
1567 // expression (add x, -1) must be transformed to (SUB{W,X}ri x, 1).
1568 //  These patterns capture that transformation.
1569 let AddedComplexity = 1 in {
1570 def : Pat<(add GPR32:$Rn, neg_addsub_shifted_imm32:$imm),
1571           (SUBSWri GPR32:$Rn, neg_addsub_shifted_imm32:$imm)>;
1572 def : Pat<(add GPR64:$Rn, neg_addsub_shifted_imm64:$imm),
1573           (SUBSXri GPR64:$Rn, neg_addsub_shifted_imm64:$imm)>;
1574 def : Pat<(sub GPR32:$Rn, neg_addsub_shifted_imm32:$imm),
1575           (ADDWri GPR32:$Rn, neg_addsub_shifted_imm32:$imm)>;
1576 def : Pat<(sub GPR64:$Rn, neg_addsub_shifted_imm64:$imm),
1577           (ADDXri GPR64:$Rn, neg_addsub_shifted_imm64:$imm)>;
1580 // Because of the immediate format for add/sub-imm instructions, the
1581 // expression (add x, -1) must be transformed to (SUB{W,X}ri x, 1).
1582 //  These patterns capture that transformation.
1583 let AddedComplexity = 1 in {
1584 def : Pat<(AArch64add_flag GPR32:$Rn, neg_addsub_shifted_imm32:$imm),
1585           (SUBSWri GPR32:$Rn, neg_addsub_shifted_imm32:$imm)>;
1586 def : Pat<(AArch64add_flag GPR64:$Rn, neg_addsub_shifted_imm64:$imm),
1587           (SUBSXri GPR64:$Rn, neg_addsub_shifted_imm64:$imm)>;
1588 def : Pat<(AArch64sub_flag GPR32:$Rn, neg_addsub_shifted_imm32:$imm),
1589           (ADDSWri GPR32:$Rn, neg_addsub_shifted_imm32:$imm)>;
1590 def : Pat<(AArch64sub_flag GPR64:$Rn, neg_addsub_shifted_imm64:$imm),
1591           (ADDSXri GPR64:$Rn, neg_addsub_shifted_imm64:$imm)>;
1594 def : InstAlias<"neg $dst, $src", (SUBWrs GPR32:$dst, WZR, GPR32:$src, 0), 3>;
1595 def : InstAlias<"neg $dst, $src", (SUBXrs GPR64:$dst, XZR, GPR64:$src, 0), 3>;
1596 def : InstAlias<"neg $dst, $src$shift",
1597                 (SUBWrs GPR32:$dst, WZR, GPR32:$src, arith_shift32:$shift), 2>;
1598 def : InstAlias<"neg $dst, $src$shift",
1599                 (SUBXrs GPR64:$dst, XZR, GPR64:$src, arith_shift64:$shift), 2>;
1601 def : InstAlias<"negs $dst, $src", (SUBSWrs GPR32:$dst, WZR, GPR32:$src, 0), 3>;
1602 def : InstAlias<"negs $dst, $src", (SUBSXrs GPR64:$dst, XZR, GPR64:$src, 0), 3>;
1603 def : InstAlias<"negs $dst, $src$shift",
1604                 (SUBSWrs GPR32:$dst, WZR, GPR32:$src, arith_shift32:$shift), 2>;
1605 def : InstAlias<"negs $dst, $src$shift",
1606                 (SUBSXrs GPR64:$dst, XZR, GPR64:$src, arith_shift64:$shift), 2>;
1609 // Unsigned/Signed divide
1610 defm UDIV : Div<0, "udiv", udiv>;
1611 defm SDIV : Div<1, "sdiv", sdiv>;
1613 def : Pat<(int_aarch64_udiv GPR32:$Rn, GPR32:$Rm), (UDIVWr GPR32:$Rn, GPR32:$Rm)>;
1614 def : Pat<(int_aarch64_udiv GPR64:$Rn, GPR64:$Rm), (UDIVXr GPR64:$Rn, GPR64:$Rm)>;
1615 def : Pat<(int_aarch64_sdiv GPR32:$Rn, GPR32:$Rm), (SDIVWr GPR32:$Rn, GPR32:$Rm)>;
1616 def : Pat<(int_aarch64_sdiv GPR64:$Rn, GPR64:$Rm), (SDIVXr GPR64:$Rn, GPR64:$Rm)>;
1618 // Variable shift
1619 defm ASRV : Shift<0b10, "asr", sra>;
1620 defm LSLV : Shift<0b00, "lsl", shl>;
1621 defm LSRV : Shift<0b01, "lsr", srl>;
1622 defm RORV : Shift<0b11, "ror", rotr>;
1624 def : ShiftAlias<"asrv", ASRVWr, GPR32>;
1625 def : ShiftAlias<"asrv", ASRVXr, GPR64>;
1626 def : ShiftAlias<"lslv", LSLVWr, GPR32>;
1627 def : ShiftAlias<"lslv", LSLVXr, GPR64>;
1628 def : ShiftAlias<"lsrv", LSRVWr, GPR32>;
1629 def : ShiftAlias<"lsrv", LSRVXr, GPR64>;
1630 def : ShiftAlias<"rorv", RORVWr, GPR32>;
1631 def : ShiftAlias<"rorv", RORVXr, GPR64>;
1633 // Multiply-add
1634 let AddedComplexity = 5 in {
1635 defm MADD : MulAccum<0, "madd", add>;
1636 defm MSUB : MulAccum<1, "msub", sub>;
1638 def : Pat<(i32 (mul GPR32:$Rn, GPR32:$Rm)),
1639           (MADDWrrr GPR32:$Rn, GPR32:$Rm, WZR)>;
1640 def : Pat<(i64 (mul GPR64:$Rn, GPR64:$Rm)),
1641           (MADDXrrr GPR64:$Rn, GPR64:$Rm, XZR)>;
1643 def : Pat<(i32 (ineg (mul GPR32:$Rn, GPR32:$Rm))),
1644           (MSUBWrrr GPR32:$Rn, GPR32:$Rm, WZR)>;
1645 def : Pat<(i64 (ineg (mul GPR64:$Rn, GPR64:$Rm))),
1646           (MSUBXrrr GPR64:$Rn, GPR64:$Rm, XZR)>;
1647 def : Pat<(i32 (mul (ineg GPR32:$Rn), GPR32:$Rm)),
1648           (MSUBWrrr GPR32:$Rn, GPR32:$Rm, WZR)>;
1649 def : Pat<(i64 (mul (ineg GPR64:$Rn), GPR64:$Rm)),
1650           (MSUBXrrr GPR64:$Rn, GPR64:$Rm, XZR)>;
1651 } // AddedComplexity = 5
1653 let AddedComplexity = 5 in {
1654 def SMADDLrrr : WideMulAccum<0, 0b001, "smaddl", add, sext>;
1655 def SMSUBLrrr : WideMulAccum<1, 0b001, "smsubl", sub, sext>;
1656 def UMADDLrrr : WideMulAccum<0, 0b101, "umaddl", add, zext>;
1657 def UMSUBLrrr : WideMulAccum<1, 0b101, "umsubl", sub, zext>;
1659 def : Pat<(i64 (mul (sext_inreg GPR64:$Rn, i32), (sext_inreg GPR64:$Rm, i32))),
1660           (SMADDLrrr (EXTRACT_SUBREG $Rn, sub_32), (EXTRACT_SUBREG $Rm, sub_32), XZR)>;
1661 def : Pat<(i64 (mul (sext_inreg GPR64:$Rn, i32), (sext GPR32:$Rm))),
1662           (SMADDLrrr (EXTRACT_SUBREG $Rn, sub_32), $Rm, XZR)>;
1663 def : Pat<(i64 (mul (sext GPR32:$Rn), (sext GPR32:$Rm))),
1664           (SMADDLrrr GPR32:$Rn, GPR32:$Rm, XZR)>;
1665 def : Pat<(i64 (mul (and GPR64:$Rn, 0xFFFFFFFF), (and GPR64:$Rm, 0xFFFFFFFF))),
1666           (UMADDLrrr (EXTRACT_SUBREG $Rn, sub_32), (EXTRACT_SUBREG $Rm, sub_32), XZR)>;
1667 def : Pat<(i64 (mul (and GPR64:$Rn, 0xFFFFFFFF), (zext GPR32:$Rm))),
1668           (UMADDLrrr (EXTRACT_SUBREG $Rn, sub_32), $Rm, XZR)>;
1669 def : Pat<(i64 (mul (zext GPR32:$Rn), (zext GPR32:$Rm))),
1670           (UMADDLrrr GPR32:$Rn, GPR32:$Rm, XZR)>;
1672 def : Pat<(i64 (ineg (mul (sext GPR32:$Rn), (sext GPR32:$Rm)))),
1673           (SMSUBLrrr GPR32:$Rn, GPR32:$Rm, XZR)>;
1674 def : Pat<(i64 (ineg (mul (zext GPR32:$Rn), (zext GPR32:$Rm)))),
1675           (UMSUBLrrr GPR32:$Rn, GPR32:$Rm, XZR)>;
1677 def : Pat<(i64 (mul (sext GPR32:$Rn), (s64imm_32bit:$C))),
1678           (SMADDLrrr GPR32:$Rn, (MOVi32imm (trunc_imm imm:$C)), XZR)>;
1679 def : Pat<(i64 (mul (zext GPR32:$Rn), (i64imm_32bit:$C))),
1680           (UMADDLrrr GPR32:$Rn, (MOVi32imm (trunc_imm imm:$C)), XZR)>;
1681 def : Pat<(i64 (mul (sext_inreg GPR64:$Rn, i32), (s64imm_32bit:$C))),
1682           (SMADDLrrr (i32 (EXTRACT_SUBREG GPR64:$Rn, sub_32)),
1683                      (MOVi32imm (trunc_imm imm:$C)), XZR)>;
1685 def : Pat<(i64 (ineg (mul (sext GPR32:$Rn), (s64imm_32bit:$C)))),
1686           (SMSUBLrrr GPR32:$Rn, (MOVi32imm (trunc_imm imm:$C)), XZR)>;
1687 def : Pat<(i64 (ineg (mul (zext GPR32:$Rn), (i64imm_32bit:$C)))),
1688           (UMSUBLrrr GPR32:$Rn, (MOVi32imm (trunc_imm imm:$C)), XZR)>;
1689 def : Pat<(i64 (ineg (mul (sext_inreg GPR64:$Rn, i32), (s64imm_32bit:$C)))),
1690           (SMSUBLrrr (i32 (EXTRACT_SUBREG GPR64:$Rn, sub_32)),
1691                      (MOVi32imm (trunc_imm imm:$C)), XZR)>;
1693 def : Pat<(i64 (add (mul (sext GPR32:$Rn), (s64imm_32bit:$C)), GPR64:$Ra)),
1694           (SMADDLrrr GPR32:$Rn, (MOVi32imm (trunc_imm imm:$C)), GPR64:$Ra)>;
1695 def : Pat<(i64 (add (mul (zext GPR32:$Rn), (i64imm_32bit:$C)), GPR64:$Ra)),
1696           (UMADDLrrr GPR32:$Rn, (MOVi32imm (trunc_imm imm:$C)), GPR64:$Ra)>;
1697 def : Pat<(i64 (add (mul (sext_inreg GPR64:$Rn, i32), (s64imm_32bit:$C)),
1698                     GPR64:$Ra)),
1699           (SMADDLrrr (i32 (EXTRACT_SUBREG GPR64:$Rn, sub_32)),
1700                      (MOVi32imm (trunc_imm imm:$C)), GPR64:$Ra)>;
1702 def : Pat<(i64 (sub GPR64:$Ra, (mul (sext GPR32:$Rn), (s64imm_32bit:$C)))),
1703           (SMSUBLrrr GPR32:$Rn, (MOVi32imm (trunc_imm imm:$C)), GPR64:$Ra)>;
1704 def : Pat<(i64 (sub GPR64:$Ra, (mul (zext GPR32:$Rn), (i64imm_32bit:$C)))),
1705           (UMSUBLrrr GPR32:$Rn, (MOVi32imm (trunc_imm imm:$C)), GPR64:$Ra)>;
1706 def : Pat<(i64 (sub GPR64:$Ra, (mul (sext_inreg GPR64:$Rn, i32),
1707                                     (s64imm_32bit:$C)))),
1708           (SMSUBLrrr (i32 (EXTRACT_SUBREG GPR64:$Rn, sub_32)),
1709                      (MOVi32imm (trunc_imm imm:$C)), GPR64:$Ra)>;
1710 } // AddedComplexity = 5
1712 def : MulAccumWAlias<"mul", MADDWrrr>;
1713 def : MulAccumXAlias<"mul", MADDXrrr>;
1714 def : MulAccumWAlias<"mneg", MSUBWrrr>;
1715 def : MulAccumXAlias<"mneg", MSUBXrrr>;
1716 def : WideMulAccumAlias<"smull", SMADDLrrr>;
1717 def : WideMulAccumAlias<"smnegl", SMSUBLrrr>;
1718 def : WideMulAccumAlias<"umull", UMADDLrrr>;
1719 def : WideMulAccumAlias<"umnegl", UMSUBLrrr>;
1721 // Multiply-high
1722 def SMULHrr : MulHi<0b010, "smulh", mulhs>;
1723 def UMULHrr : MulHi<0b110, "umulh", mulhu>;
1725 // CRC32
1726 def CRC32Brr : BaseCRC32<0, 0b00, 0, GPR32, int_aarch64_crc32b, "crc32b">;
1727 def CRC32Hrr : BaseCRC32<0, 0b01, 0, GPR32, int_aarch64_crc32h, "crc32h">;
1728 def CRC32Wrr : BaseCRC32<0, 0b10, 0, GPR32, int_aarch64_crc32w, "crc32w">;
1729 def CRC32Xrr : BaseCRC32<1, 0b11, 0, GPR64, int_aarch64_crc32x, "crc32x">;
1731 def CRC32CBrr : BaseCRC32<0, 0b00, 1, GPR32, int_aarch64_crc32cb, "crc32cb">;
1732 def CRC32CHrr : BaseCRC32<0, 0b01, 1, GPR32, int_aarch64_crc32ch, "crc32ch">;
1733 def CRC32CWrr : BaseCRC32<0, 0b10, 1, GPR32, int_aarch64_crc32cw, "crc32cw">;
1734 def CRC32CXrr : BaseCRC32<1, 0b11, 1, GPR64, int_aarch64_crc32cx, "crc32cx">;
1736 // v8.1 atomic CAS
1737 defm CAS   : CompareAndSwap<0, 0, "">;
1738 defm CASA  : CompareAndSwap<1, 0, "a">;
1739 defm CASL  : CompareAndSwap<0, 1, "l">;
1740 defm CASAL : CompareAndSwap<1, 1, "al">;
1742 // v8.1 atomic CASP
1743 defm CASP   : CompareAndSwapPair<0, 0, "">;
1744 defm CASPA  : CompareAndSwapPair<1, 0, "a">;
1745 defm CASPL  : CompareAndSwapPair<0, 1, "l">;
1746 defm CASPAL : CompareAndSwapPair<1, 1, "al">;
1748 // v8.1 atomic SWP
1749 defm SWP   : Swap<0, 0, "">;
1750 defm SWPA  : Swap<1, 0, "a">;
1751 defm SWPL  : Swap<0, 1, "l">;
1752 defm SWPAL : Swap<1, 1, "al">;
1754 // v8.1 atomic LD<OP>(register). Performs load and then ST<OP>(register)
1755 defm LDADD   : LDOPregister<0b000, "add", 0, 0, "">;
1756 defm LDADDA  : LDOPregister<0b000, "add", 1, 0, "a">;
1757 defm LDADDL  : LDOPregister<0b000, "add", 0, 1, "l">;
1758 defm LDADDAL : LDOPregister<0b000, "add", 1, 1, "al">;
1760 defm LDCLR   : LDOPregister<0b001, "clr", 0, 0, "">;
1761 defm LDCLRA  : LDOPregister<0b001, "clr", 1, 0, "a">;
1762 defm LDCLRL  : LDOPregister<0b001, "clr", 0, 1, "l">;
1763 defm LDCLRAL : LDOPregister<0b001, "clr", 1, 1, "al">;
1765 defm LDEOR   : LDOPregister<0b010, "eor", 0, 0, "">;
1766 defm LDEORA  : LDOPregister<0b010, "eor", 1, 0, "a">;
1767 defm LDEORL  : LDOPregister<0b010, "eor", 0, 1, "l">;
1768 defm LDEORAL : LDOPregister<0b010, "eor", 1, 1, "al">;
1770 defm LDSET   : LDOPregister<0b011, "set", 0, 0, "">;
1771 defm LDSETA  : LDOPregister<0b011, "set", 1, 0, "a">;
1772 defm LDSETL  : LDOPregister<0b011, "set", 0, 1, "l">;
1773 defm LDSETAL : LDOPregister<0b011, "set", 1, 1, "al">;
1775 defm LDSMAX   : LDOPregister<0b100, "smax", 0, 0, "">;
1776 defm LDSMAXA  : LDOPregister<0b100, "smax", 1, 0, "a">;
1777 defm LDSMAXL  : LDOPregister<0b100, "smax", 0, 1, "l">;
1778 defm LDSMAXAL : LDOPregister<0b100, "smax", 1, 1, "al">;
1780 defm LDSMIN   : LDOPregister<0b101, "smin", 0, 0, "">;
1781 defm LDSMINA  : LDOPregister<0b101, "smin", 1, 0, "a">;
1782 defm LDSMINL  : LDOPregister<0b101, "smin", 0, 1, "l">;
1783 defm LDSMINAL : LDOPregister<0b101, "smin", 1, 1, "al">;
1785 defm LDUMAX   : LDOPregister<0b110, "umax", 0, 0, "">;
1786 defm LDUMAXA  : LDOPregister<0b110, "umax", 1, 0, "a">;
1787 defm LDUMAXL  : LDOPregister<0b110, "umax", 0, 1, "l">;
1788 defm LDUMAXAL : LDOPregister<0b110, "umax", 1, 1, "al">;
1790 defm LDUMIN   : LDOPregister<0b111, "umin", 0, 0, "">;
1791 defm LDUMINA  : LDOPregister<0b111, "umin", 1, 0, "a">;
1792 defm LDUMINL  : LDOPregister<0b111, "umin", 0, 1, "l">;
1793 defm LDUMINAL : LDOPregister<0b111, "umin", 1, 1, "al">;
1795 // v8.1 atomic ST<OP>(register) as aliases to "LD<OP>(register) when Rt=xZR"
1796 defm : STOPregister<"stadd","LDADD">; // STADDx
1797 defm : STOPregister<"stclr","LDCLR">; // STCLRx
1798 defm : STOPregister<"steor","LDEOR">; // STEORx
1799 defm : STOPregister<"stset","LDSET">; // STSETx
1800 defm : STOPregister<"stsmax","LDSMAX">;// STSMAXx
1801 defm : STOPregister<"stsmin","LDSMIN">;// STSMINx
1802 defm : STOPregister<"stumax","LDUMAX">;// STUMAXx
1803 defm : STOPregister<"stumin","LDUMIN">;// STUMINx
1805 // v8.5 Memory Tagging Extension
1806 let Predicates = [HasMTE] in {
1808 def IRG   : BaseTwoOperand<0b0100, GPR64sp, "irg", int_aarch64_irg, GPR64sp, GPR64>,
1809             Sched<[]>{
1810   let Inst{31} = 1;
1812 def GMI   : BaseTwoOperand<0b0101, GPR64, "gmi", int_aarch64_gmi, GPR64sp>, Sched<[]>{
1813   let Inst{31} = 1;
1814   let isNotDuplicable = 1;
1816 def ADDG  : AddSubG<0, "addg", null_frag>;
1817 def SUBG  : AddSubG<1, "subg", null_frag>;
1819 def : InstAlias<"irg $dst, $src", (IRG GPR64sp:$dst, GPR64sp:$src, XZR), 1>;
1821 def SUBP : SUBP<0, "subp", int_aarch64_subp>, Sched<[]>;
1822 def SUBPS : SUBP<1, "subps", null_frag>, Sched<[]>{
1823   let Defs = [NZCV];
1826 def : InstAlias<"cmpp $lhs, $rhs", (SUBPS XZR, GPR64sp:$lhs, GPR64sp:$rhs), 0>;
1828 def LDG : MemTagLoad<"ldg", "\t$Rt, [$Rn, $offset]">;
1830 def : Pat<(int_aarch64_addg (am_indexedu6s128 GPR64sp:$Rn, uimm6s16:$imm6), imm0_15:$imm4),
1831           (ADDG GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4)>;
1832 def : Pat<(int_aarch64_ldg GPR64:$Rt, (am_indexeds9s128 GPR64sp:$Rn,  simm9s16:$offset)),
1833           (LDG GPR64:$Rt, GPR64sp:$Rn,  simm9s16:$offset)>;
1835 def : InstAlias<"ldg $Rt, [$Rn]", (LDG GPR64:$Rt, GPR64sp:$Rn, 0), 1>;
1837 def LDGM : MemTagVector<1, "ldgm", "\t$Rt, [$Rn]",
1838                    (outs GPR64:$Rt), (ins GPR64sp:$Rn)>;
1839 def STGM : MemTagVector<0, "stgm", "\t$Rt, [$Rn]",
1840                    (outs), (ins GPR64:$Rt, GPR64sp:$Rn)>;
1841 def STZGM : MemTagVector<0, "stzgm", "\t$Rt, [$Rn]",
1842                    (outs), (ins GPR64:$Rt, GPR64sp:$Rn)> {
1843   let Inst{23} = 0;
1846 defm STG   : MemTagStore<0b00, "stg">;
1847 defm STZG  : MemTagStore<0b01, "stzg">;
1848 defm ST2G  : MemTagStore<0b10, "st2g">;
1849 defm STZ2G : MemTagStore<0b11, "stz2g">;
1851 def : Pat<(AArch64stg GPR64sp:$Rn, (am_indexeds9s128 GPR64sp:$Rm, simm9s16:$imm)),
1852           (STGOffset $Rn, $Rm, $imm)>;
1853 def : Pat<(AArch64stzg GPR64sp:$Rn, (am_indexeds9s128 GPR64sp:$Rm, simm9s16:$imm)),
1854           (STZGOffset $Rn, $Rm, $imm)>;
1855 def : Pat<(AArch64st2g GPR64sp:$Rn, (am_indexeds9s128 GPR64sp:$Rm, simm9s16:$imm)),
1856           (ST2GOffset $Rn, $Rm, $imm)>;
1857 def : Pat<(AArch64stz2g GPR64sp:$Rn, (am_indexeds9s128 GPR64sp:$Rm, simm9s16:$imm)),
1858           (STZ2GOffset $Rn, $Rm, $imm)>;
1860 defm STGP     : StorePairOffset <0b01, 0, GPR64z, simm7s16, "stgp">;
1861 def  STGPpre  : StorePairPreIdx <0b01, 0, GPR64z, simm7s16, "stgp">;
1862 def  STGPpost : StorePairPostIdx<0b01, 0, GPR64z, simm7s16, "stgp">;
1864 def : Pat<(int_aarch64_stg GPR64:$Rt, (am_indexeds9s128 GPR64sp:$Rn, simm9s16:$offset)),
1865           (STGOffset GPR64:$Rt, GPR64sp:$Rn,  simm9s16:$offset)>;
1867 def : Pat<(int_aarch64_stgp (am_indexed7s128 GPR64sp:$Rn, simm7s16:$imm), GPR64:$Rt, GPR64:$Rt2),
1868           (STGPi $Rt, $Rt2, $Rn, $imm)>;
1870 def IRGstack
1871     : Pseudo<(outs GPR64sp:$Rd), (ins GPR64sp:$Rsp, GPR64:$Rm), []>,
1872       Sched<[]>;
1873 def TAGPstack
1874     : Pseudo<(outs GPR64sp:$Rd), (ins GPR64sp:$Rn, uimm6s16:$imm6, GPR64sp:$Rm, imm0_15:$imm4), []>,
1875       Sched<[]>;
1877 // Explicit SP in the first operand prevents ShrinkWrap optimization
1878 // from leaving this instruction out of the stack frame. When IRGstack
1879 // is transformed into IRG, this operand is replaced with the actual
1880 // register / expression for the tagged base pointer of the current function.
1881 def : Pat<(int_aarch64_irg_sp i64:$Rm), (IRGstack SP, i64:$Rm)>;
1883 // Large STG to be expanded into a loop. $sz is the size, $Rn is start address.
1884 // $Rn_wback is one past the end of the range. $Rm is the loop counter.
1885 let isCodeGenOnly=1, mayStore=1 in {
1886 def STGloop_wback
1887     : Pseudo<(outs GPR64common:$Rm, GPR64sp:$Rn_wback), (ins i64imm:$sz, GPR64sp:$Rn),
1888              [], "$Rn = $Rn_wback,@earlyclobber $Rn_wback,@earlyclobber $Rm" >,
1889       Sched<[WriteAdr, WriteST]>;
1891 def STZGloop_wback
1892     : Pseudo<(outs GPR64common:$Rm, GPR64sp:$Rn_wback), (ins i64imm:$sz, GPR64sp:$Rn),
1893              [], "$Rn = $Rn_wback,@earlyclobber $Rn_wback,@earlyclobber $Rm" >,
1894       Sched<[WriteAdr, WriteST]>;
1896 // A variant of the above where $Rn2 is an independent register not tied to the input register $Rn.
1897 // Their purpose is to use a FrameIndex operand as $Rn (which of course can not be written back).
1898 def STGloop
1899     : Pseudo<(outs GPR64common:$Rm, GPR64sp:$Rn2), (ins i64imm:$sz, GPR64sp:$Rn),
1900              [], "@earlyclobber $Rn2,@earlyclobber $Rm" >,
1901       Sched<[WriteAdr, WriteST]>;
1903 def STZGloop
1904     : Pseudo<(outs GPR64common:$Rm, GPR64sp:$Rn2), (ins i64imm:$sz, GPR64sp:$Rn),
1905              [], "@earlyclobber $Rn2,@earlyclobber $Rm" >,
1906       Sched<[WriteAdr, WriteST]>;
1909 } // Predicates = [HasMTE]
1911 //===----------------------------------------------------------------------===//
1912 // Logical instructions.
1913 //===----------------------------------------------------------------------===//
1915 // (immediate)
1916 defm ANDS : LogicalImmS<0b11, "ands", AArch64and_flag, "bics">;
1917 defm AND  : LogicalImm<0b00, "and", and, "bic">;
1918 defm EOR  : LogicalImm<0b10, "eor", xor, "eon">;
1919 defm ORR  : LogicalImm<0b01, "orr", or, "orn">;
1921 // FIXME: these aliases *are* canonical sometimes (when movz can't be
1922 // used). Actually, it seems to be working right now, but putting logical_immXX
1923 // here is a bit dodgy on the AsmParser side too.
1924 def : InstAlias<"mov $dst, $imm", (ORRWri GPR32sp:$dst, WZR,
1925                                           logical_imm32:$imm), 0>;
1926 def : InstAlias<"mov $dst, $imm", (ORRXri GPR64sp:$dst, XZR,
1927                                           logical_imm64:$imm), 0>;
1930 // (register)
1931 defm ANDS : LogicalRegS<0b11, 0, "ands", AArch64and_flag>;
1932 defm BICS : LogicalRegS<0b11, 1, "bics",
1933                         BinOpFrag<(AArch64and_flag node:$LHS, (not node:$RHS))>>;
1934 defm AND  : LogicalReg<0b00, 0, "and", and>;
1935 defm BIC  : LogicalReg<0b00, 1, "bic",
1936                        BinOpFrag<(and node:$LHS, (not node:$RHS))>>;
1937 defm EON  : LogicalReg<0b10, 1, "eon",
1938                        BinOpFrag<(not (xor node:$LHS, node:$RHS))>>;
1939 defm EOR  : LogicalReg<0b10, 0, "eor", xor>;
1940 defm ORN  : LogicalReg<0b01, 1, "orn",
1941                        BinOpFrag<(or node:$LHS, (not node:$RHS))>>;
1942 defm ORR  : LogicalReg<0b01, 0, "orr", or>;
1944 def : InstAlias<"mov $dst, $src", (ORRWrs GPR32:$dst, WZR, GPR32:$src, 0), 2>;
1945 def : InstAlias<"mov $dst, $src", (ORRXrs GPR64:$dst, XZR, GPR64:$src, 0), 2>;
1947 def : InstAlias<"mvn $Wd, $Wm", (ORNWrs GPR32:$Wd, WZR, GPR32:$Wm, 0), 3>;
1948 def : InstAlias<"mvn $Xd, $Xm", (ORNXrs GPR64:$Xd, XZR, GPR64:$Xm, 0), 3>;
1950 def : InstAlias<"mvn $Wd, $Wm$sh",
1951                 (ORNWrs GPR32:$Wd, WZR, GPR32:$Wm, logical_shift32:$sh), 2>;
1952 def : InstAlias<"mvn $Xd, $Xm$sh",
1953                 (ORNXrs GPR64:$Xd, XZR, GPR64:$Xm, logical_shift64:$sh), 2>;
1955 def : InstAlias<"tst $src1, $src2",
1956                 (ANDSWri WZR, GPR32:$src1, logical_imm32:$src2), 2>;
1957 def : InstAlias<"tst $src1, $src2",
1958                 (ANDSXri XZR, GPR64:$src1, logical_imm64:$src2), 2>;
1960 def : InstAlias<"tst $src1, $src2",
1961                         (ANDSWrs WZR, GPR32:$src1, GPR32:$src2, 0), 3>;
1962 def : InstAlias<"tst $src1, $src2",
1963                         (ANDSXrs XZR, GPR64:$src1, GPR64:$src2, 0), 3>;
1965 def : InstAlias<"tst $src1, $src2$sh",
1966                (ANDSWrs WZR, GPR32:$src1, GPR32:$src2, logical_shift32:$sh), 2>;
1967 def : InstAlias<"tst $src1, $src2$sh",
1968                (ANDSXrs XZR, GPR64:$src1, GPR64:$src2, logical_shift64:$sh), 2>;
1971 def : Pat<(not GPR32:$Wm), (ORNWrr WZR, GPR32:$Wm)>;
1972 def : Pat<(not GPR64:$Xm), (ORNXrr XZR, GPR64:$Xm)>;
1975 //===----------------------------------------------------------------------===//
1976 // One operand data processing instructions.
1977 //===----------------------------------------------------------------------===//
1979 defm CLS    : OneOperandData<0b101, "cls">;
1980 defm CLZ    : OneOperandData<0b100, "clz", ctlz>;
1981 defm RBIT   : OneOperandData<0b000, "rbit", bitreverse>;
1983 def  REV16Wr : OneWRegData<0b001, "rev16",
1984                                   UnOpFrag<(rotr (bswap node:$LHS), (i64 16))>>;
1985 def  REV16Xr : OneXRegData<0b001, "rev16", null_frag>;
1987 def : Pat<(cttz GPR32:$Rn),
1988           (CLZWr (RBITWr GPR32:$Rn))>;
1989 def : Pat<(cttz GPR64:$Rn),
1990           (CLZXr (RBITXr GPR64:$Rn))>;
1991 def : Pat<(ctlz (or (shl (xor (sra GPR32:$Rn, (i64 31)), GPR32:$Rn), (i64 1)),
1992                 (i32 1))),
1993           (CLSWr GPR32:$Rn)>;
1994 def : Pat<(ctlz (or (shl (xor (sra GPR64:$Rn, (i64 63)), GPR64:$Rn), (i64 1)),
1995                 (i64 1))),
1996           (CLSXr GPR64:$Rn)>;
1997 def : Pat<(int_aarch64_cls GPR32:$Rn), (CLSWr GPR32:$Rn)>;
1998 def : Pat<(int_aarch64_cls64 GPR64:$Rm), (EXTRACT_SUBREG (CLSXr GPR64:$Rm), sub_32)>;
2000 // Unlike the other one operand instructions, the instructions with the "rev"
2001 // mnemonic do *not* just different in the size bit, but actually use different
2002 // opcode bits for the different sizes.
2003 def REVWr   : OneWRegData<0b010, "rev", bswap>;
2004 def REVXr   : OneXRegData<0b011, "rev", bswap>;
2005 def REV32Xr : OneXRegData<0b010, "rev32",
2006                                  UnOpFrag<(rotr (bswap node:$LHS), (i64 32))>>;
2008 def : InstAlias<"rev64 $Rd, $Rn", (REVXr GPR64:$Rd, GPR64:$Rn), 0>;
2010 // The bswap commutes with the rotr so we want a pattern for both possible
2011 // orders.
2012 def : Pat<(bswap (rotr GPR32:$Rn, (i64 16))), (REV16Wr GPR32:$Rn)>;
2013 def : Pat<(bswap (rotr GPR64:$Rn, (i64 32))), (REV32Xr GPR64:$Rn)>;
2015 //===----------------------------------------------------------------------===//
2016 // Bitfield immediate extraction instruction.
2017 //===----------------------------------------------------------------------===//
2018 let hasSideEffects = 0 in
2019 defm EXTR : ExtractImm<"extr">;
2020 def : InstAlias<"ror $dst, $src, $shift",
2021             (EXTRWrri GPR32:$dst, GPR32:$src, GPR32:$src, imm0_31:$shift)>;
2022 def : InstAlias<"ror $dst, $src, $shift",
2023             (EXTRXrri GPR64:$dst, GPR64:$src, GPR64:$src, imm0_63:$shift)>;
2025 def : Pat<(rotr GPR32:$Rn, (i64 imm0_31:$imm)),
2026           (EXTRWrri GPR32:$Rn, GPR32:$Rn, imm0_31:$imm)>;
2027 def : Pat<(rotr GPR64:$Rn, (i64 imm0_63:$imm)),
2028           (EXTRXrri GPR64:$Rn, GPR64:$Rn, imm0_63:$imm)>;
2030 //===----------------------------------------------------------------------===//
2031 // Other bitfield immediate instructions.
2032 //===----------------------------------------------------------------------===//
2033 let hasSideEffects = 0 in {
2034 defm BFM  : BitfieldImmWith2RegArgs<0b01, "bfm">;
2035 defm SBFM : BitfieldImm<0b00, "sbfm">;
2036 defm UBFM : BitfieldImm<0b10, "ubfm">;
2039 def i32shift_a : Operand<i64>, SDNodeXForm<imm, [{
2040   uint64_t enc = (32 - N->getZExtValue()) & 0x1f;
2041   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i64);
2042 }]>;
2044 def i32shift_b : Operand<i64>, SDNodeXForm<imm, [{
2045   uint64_t enc = 31 - N->getZExtValue();
2046   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i64);
2047 }]>;
2049 // min(7, 31 - shift_amt)
2050 def i32shift_sext_i8 : Operand<i64>, SDNodeXForm<imm, [{
2051   uint64_t enc = 31 - N->getZExtValue();
2052   enc = enc > 7 ? 7 : enc;
2053   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i64);
2054 }]>;
2056 // min(15, 31 - shift_amt)
2057 def i32shift_sext_i16 : Operand<i64>, SDNodeXForm<imm, [{
2058   uint64_t enc = 31 - N->getZExtValue();
2059   enc = enc > 15 ? 15 : enc;
2060   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i64);
2061 }]>;
2063 def i64shift_a : Operand<i64>, SDNodeXForm<imm, [{
2064   uint64_t enc = (64 - N->getZExtValue()) & 0x3f;
2065   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i64);
2066 }]>;
2068 def i64shift_b : Operand<i64>, SDNodeXForm<imm, [{
2069   uint64_t enc = 63 - N->getZExtValue();
2070   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i64);
2071 }]>;
2073 // min(7, 63 - shift_amt)
2074 def i64shift_sext_i8 : Operand<i64>, SDNodeXForm<imm, [{
2075   uint64_t enc = 63 - N->getZExtValue();
2076   enc = enc > 7 ? 7 : enc;
2077   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i64);
2078 }]>;
2080 // min(15, 63 - shift_amt)
2081 def i64shift_sext_i16 : Operand<i64>, SDNodeXForm<imm, [{
2082   uint64_t enc = 63 - N->getZExtValue();
2083   enc = enc > 15 ? 15 : enc;
2084   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i64);
2085 }]>;
2087 // min(31, 63 - shift_amt)
2088 def i64shift_sext_i32 : Operand<i64>, SDNodeXForm<imm, [{
2089   uint64_t enc = 63 - N->getZExtValue();
2090   enc = enc > 31 ? 31 : enc;
2091   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i64);
2092 }]>;
2094 def : Pat<(shl GPR32:$Rn, (i64 imm0_31:$imm)),
2095           (UBFMWri GPR32:$Rn, (i64 (i32shift_a imm0_31:$imm)),
2096                               (i64 (i32shift_b imm0_31:$imm)))>;
2097 def : Pat<(shl GPR64:$Rn, (i64 imm0_63:$imm)),
2098           (UBFMXri GPR64:$Rn, (i64 (i64shift_a imm0_63:$imm)),
2099                               (i64 (i64shift_b imm0_63:$imm)))>;
2101 let AddedComplexity = 10 in {
2102 def : Pat<(sra GPR32:$Rn, (i64 imm0_31:$imm)),
2103           (SBFMWri GPR32:$Rn, imm0_31:$imm, 31)>;
2104 def : Pat<(sra GPR64:$Rn, (i64 imm0_63:$imm)),
2105           (SBFMXri GPR64:$Rn, imm0_63:$imm, 63)>;
2108 def : InstAlias<"asr $dst, $src, $shift",
2109                 (SBFMWri GPR32:$dst, GPR32:$src, imm0_31:$shift, 31)>;
2110 def : InstAlias<"asr $dst, $src, $shift",
2111                 (SBFMXri GPR64:$dst, GPR64:$src, imm0_63:$shift, 63)>;
2112 def : InstAlias<"sxtb $dst, $src", (SBFMWri GPR32:$dst, GPR32:$src, 0, 7)>;
2113 def : InstAlias<"sxtb $dst, $src", (SBFMXri GPR64:$dst, GPR64:$src, 0, 7)>;
2114 def : InstAlias<"sxth $dst, $src", (SBFMWri GPR32:$dst, GPR32:$src, 0, 15)>;
2115 def : InstAlias<"sxth $dst, $src", (SBFMXri GPR64:$dst, GPR64:$src, 0, 15)>;
2116 def : InstAlias<"sxtw $dst, $src", (SBFMXri GPR64:$dst, GPR64:$src, 0, 31)>;
2118 def : Pat<(srl GPR32:$Rn, (i64 imm0_31:$imm)),
2119           (UBFMWri GPR32:$Rn, imm0_31:$imm, 31)>;
2120 def : Pat<(srl GPR64:$Rn, (i64 imm0_63:$imm)),
2121           (UBFMXri GPR64:$Rn, imm0_63:$imm, 63)>;
2123 def : InstAlias<"lsr $dst, $src, $shift",
2124                 (UBFMWri GPR32:$dst, GPR32:$src, imm0_31:$shift, 31)>;
2125 def : InstAlias<"lsr $dst, $src, $shift",
2126                 (UBFMXri GPR64:$dst, GPR64:$src, imm0_63:$shift, 63)>;
2127 def : InstAlias<"uxtb $dst, $src", (UBFMWri GPR32:$dst, GPR32:$src, 0, 7)>;
2128 def : InstAlias<"uxtb $dst, $src", (UBFMXri GPR64:$dst, GPR64:$src, 0, 7)>;
2129 def : InstAlias<"uxth $dst, $src", (UBFMWri GPR32:$dst, GPR32:$src, 0, 15)>;
2130 def : InstAlias<"uxth $dst, $src", (UBFMXri GPR64:$dst, GPR64:$src, 0, 15)>;
2131 def : InstAlias<"uxtw $dst, $src", (UBFMXri GPR64:$dst, GPR64:$src, 0, 31)>;
2133 //===----------------------------------------------------------------------===//
2134 // Conditional comparison instructions.
2135 //===----------------------------------------------------------------------===//
2136 defm CCMN : CondComparison<0, "ccmn", AArch64ccmn>;
2137 defm CCMP : CondComparison<1, "ccmp", AArch64ccmp>;
2139 //===----------------------------------------------------------------------===//
2140 // Conditional select instructions.
2141 //===----------------------------------------------------------------------===//
2142 defm CSEL  : CondSelect<0, 0b00, "csel">;
2144 def inc : PatFrag<(ops node:$in), (add node:$in, 1)>;
2145 defm CSINC : CondSelectOp<0, 0b01, "csinc", inc>;
2146 defm CSINV : CondSelectOp<1, 0b00, "csinv", not>;
2147 defm CSNEG : CondSelectOp<1, 0b01, "csneg", ineg>;
2149 def : Pat<(AArch64csinv GPR32:$tval, GPR32:$fval, (i32 imm:$cc), NZCV),
2150           (CSINVWr GPR32:$tval, GPR32:$fval, (i32 imm:$cc))>;
2151 def : Pat<(AArch64csinv GPR64:$tval, GPR64:$fval, (i32 imm:$cc), NZCV),
2152           (CSINVXr GPR64:$tval, GPR64:$fval, (i32 imm:$cc))>;
2153 def : Pat<(AArch64csneg GPR32:$tval, GPR32:$fval, (i32 imm:$cc), NZCV),
2154           (CSNEGWr GPR32:$tval, GPR32:$fval, (i32 imm:$cc))>;
2155 def : Pat<(AArch64csneg GPR64:$tval, GPR64:$fval, (i32 imm:$cc), NZCV),
2156           (CSNEGXr GPR64:$tval, GPR64:$fval, (i32 imm:$cc))>;
2157 def : Pat<(AArch64csinc GPR32:$tval, GPR32:$fval, (i32 imm:$cc), NZCV),
2158           (CSINCWr GPR32:$tval, GPR32:$fval, (i32 imm:$cc))>;
2159 def : Pat<(AArch64csinc GPR64:$tval, GPR64:$fval, (i32 imm:$cc), NZCV),
2160           (CSINCXr GPR64:$tval, GPR64:$fval, (i32 imm:$cc))>;
2162 def : Pat<(AArch64csel (i32 0), (i32 1), (i32 imm:$cc), NZCV),
2163           (CSINCWr WZR, WZR, (i32 imm:$cc))>;
2164 def : Pat<(AArch64csel (i64 0), (i64 1), (i32 imm:$cc), NZCV),
2165           (CSINCXr XZR, XZR, (i32 imm:$cc))>;
2166 def : Pat<(AArch64csel GPR32:$tval, (i32 1), (i32 imm:$cc), NZCV),
2167           (CSINCWr GPR32:$tval, WZR, (i32 imm:$cc))>;
2168 def : Pat<(AArch64csel GPR64:$tval, (i64 1), (i32 imm:$cc), NZCV),
2169           (CSINCXr GPR64:$tval, XZR, (i32 imm:$cc))>;
2170 def : Pat<(AArch64csel (i32 1), GPR32:$fval, (i32 imm:$cc), NZCV),
2171           (CSINCWr GPR32:$fval, WZR, (i32 (inv_cond_XFORM imm:$cc)))>;
2172 def : Pat<(AArch64csel (i64 1), GPR64:$fval, (i32 imm:$cc), NZCV),
2173           (CSINCXr GPR64:$fval, XZR, (i32 (inv_cond_XFORM imm:$cc)))>;
2174 def : Pat<(AArch64csel (i32 0), (i32 -1), (i32 imm:$cc), NZCV),
2175           (CSINVWr WZR, WZR, (i32 imm:$cc))>;
2176 def : Pat<(AArch64csel (i64 0), (i64 -1), (i32 imm:$cc), NZCV),
2177           (CSINVXr XZR, XZR, (i32 imm:$cc))>;
2178 def : Pat<(AArch64csel GPR32:$tval, (i32 -1), (i32 imm:$cc), NZCV),
2179           (CSINVWr GPR32:$tval, WZR, (i32 imm:$cc))>;
2180 def : Pat<(AArch64csel GPR64:$tval, (i64 -1), (i32 imm:$cc), NZCV),
2181           (CSINVXr GPR64:$tval, XZR, (i32 imm:$cc))>;
2182 def : Pat<(AArch64csel (i32 -1), GPR32:$fval, (i32 imm:$cc), NZCV),
2183           (CSINVWr GPR32:$fval, WZR, (i32 (inv_cond_XFORM imm:$cc)))>;
2184 def : Pat<(AArch64csel (i64 -1), GPR64:$fval, (i32 imm:$cc), NZCV),
2185           (CSINVXr GPR64:$fval, XZR, (i32 (inv_cond_XFORM imm:$cc)))>;
2187 def : Pat<(add GPR32:$val, (AArch64csel (i32 0), (i32 1), (i32 imm:$cc), NZCV)),
2188           (CSINCWr GPR32:$val, GPR32:$val, (i32 imm:$cc))>;
2189 def : Pat<(add GPR64:$val, (zext (AArch64csel (i32 0), (i32 1), (i32 imm:$cc), NZCV))),
2190           (CSINCXr GPR64:$val, GPR64:$val, (i32 imm:$cc))>;
2192 // The inverse of the condition code from the alias instruction is what is used
2193 // in the aliased instruction. The parser all ready inverts the condition code
2194 // for these aliases.
2195 def : InstAlias<"cset $dst, $cc",
2196                 (CSINCWr GPR32:$dst, WZR, WZR, inv_ccode:$cc)>;
2197 def : InstAlias<"cset $dst, $cc",
2198                 (CSINCXr GPR64:$dst, XZR, XZR, inv_ccode:$cc)>;
2200 def : InstAlias<"csetm $dst, $cc",
2201                 (CSINVWr GPR32:$dst, WZR, WZR, inv_ccode:$cc)>;
2202 def : InstAlias<"csetm $dst, $cc",
2203                 (CSINVXr GPR64:$dst, XZR, XZR, inv_ccode:$cc)>;
2205 def : InstAlias<"cinc $dst, $src, $cc",
2206                 (CSINCWr GPR32:$dst, GPR32:$src, GPR32:$src, inv_ccode:$cc)>;
2207 def : InstAlias<"cinc $dst, $src, $cc",
2208                 (CSINCXr GPR64:$dst, GPR64:$src, GPR64:$src, inv_ccode:$cc)>;
2210 def : InstAlias<"cinv $dst, $src, $cc",
2211                 (CSINVWr GPR32:$dst, GPR32:$src, GPR32:$src, inv_ccode:$cc)>;
2212 def : InstAlias<"cinv $dst, $src, $cc",
2213                 (CSINVXr GPR64:$dst, GPR64:$src, GPR64:$src, inv_ccode:$cc)>;
2215 def : InstAlias<"cneg $dst, $src, $cc",
2216                 (CSNEGWr GPR32:$dst, GPR32:$src, GPR32:$src, inv_ccode:$cc)>;
2217 def : InstAlias<"cneg $dst, $src, $cc",
2218                 (CSNEGXr GPR64:$dst, GPR64:$src, GPR64:$src, inv_ccode:$cc)>;
2220 //===----------------------------------------------------------------------===//
2221 // PC-relative instructions.
2222 //===----------------------------------------------------------------------===//
2223 let isReMaterializable = 1 in {
2224 let hasSideEffects = 0, mayStore = 0, mayLoad = 0 in {
2225 def ADR  : ADRI<0, "adr", adrlabel,
2226                 [(set GPR64:$Xd, (AArch64adr tglobaladdr:$label))]>;
2227 } // hasSideEffects = 0
2229 def ADRP : ADRI<1, "adrp", adrplabel,
2230                 [(set GPR64:$Xd, (AArch64adrp tglobaladdr:$label))]>;
2231 } // isReMaterializable = 1
2233 // page address of a constant pool entry, block address
2234 def : Pat<(AArch64adr tconstpool:$cp), (ADR tconstpool:$cp)>;
2235 def : Pat<(AArch64adr tblockaddress:$cp), (ADR tblockaddress:$cp)>;
2236 def : Pat<(AArch64adr texternalsym:$sym), (ADR texternalsym:$sym)>;
2237 def : Pat<(AArch64adr tjumptable:$sym), (ADR tjumptable:$sym)>;
2238 def : Pat<(AArch64adrp tconstpool:$cp), (ADRP tconstpool:$cp)>;
2239 def : Pat<(AArch64adrp tblockaddress:$cp), (ADRP tblockaddress:$cp)>;
2240 def : Pat<(AArch64adrp texternalsym:$sym), (ADRP texternalsym:$sym)>;
2242 //===----------------------------------------------------------------------===//
2243 // Unconditional branch (register) instructions.
2244 //===----------------------------------------------------------------------===//
2246 let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
2247 def RET  : BranchReg<0b0010, "ret", []>;
2248 def DRPS : SpecialReturn<0b0101, "drps">;
2249 def ERET : SpecialReturn<0b0100, "eret">;
2250 } // isReturn = 1, isTerminator = 1, isBarrier = 1
2252 // Default to the LR register.
2253 def : InstAlias<"ret", (RET LR)>;
2255 let isCall = 1, Defs = [LR], Uses = [SP] in {
2256   def BLR : BranchReg<0b0001, "blr", []>;
2257   def BLRNoIP : Pseudo<(outs), (ins GPR64noip:$Rn), []>,
2258                 Sched<[WriteBrReg]>,
2259                 PseudoInstExpansion<(BLR GPR64:$Rn)>;
2260   def BLR_RVMARKER : Pseudo<(outs), (ins variable_ops), []>,
2261                      Sched<[WriteBrReg]>;
2262 } // isCall
2264 def : Pat<(AArch64call GPR64:$Rn),
2265           (BLR GPR64:$Rn)>,
2266       Requires<[NoSLSBLRMitigation]>;
2267 def : Pat<(AArch64call GPR64noip:$Rn),
2268           (BLRNoIP GPR64noip:$Rn)>,
2269       Requires<[SLSBLRMitigation]>;
2271 def : Pat<(AArch64call_rvmarker GPR64:$Rn),
2272           (BLR_RVMARKER GPR64:$Rn)>,
2273       Requires<[NoSLSBLRMitigation]>;
2275 let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
2276 def BR  : BranchReg<0b0000, "br", [(brind GPR64:$Rn)]>;
2277 } // isBranch, isTerminator, isBarrier, isIndirectBranch
2279 // Create a separate pseudo-instruction for codegen to use so that we don't
2280 // flag lr as used in every function. It'll be restored before the RET by the
2281 // epilogue if it's legitimately used.
2282 def RET_ReallyLR : Pseudo<(outs), (ins), [(AArch64retflag)]>,
2283                    Sched<[WriteBrReg]> {
2284   let isTerminator = 1;
2285   let isBarrier = 1;
2286   let isReturn = 1;
2289 // This is a directive-like pseudo-instruction. The purpose is to insert an
2290 // R_AARCH64_TLSDESC_CALL relocation at the offset of the following instruction
2291 // (which in the usual case is a BLR).
2292 let hasSideEffects = 1 in
2293 def TLSDESCCALL : Pseudo<(outs), (ins i64imm:$sym), []>, Sched<[]> {
2294   let AsmString = ".tlsdesccall $sym";
2297 // Pseudo instruction to tell the streamer to emit a 'B' character into the
2298 // augmentation string.
2299 def EMITBKEY : Pseudo<(outs), (ins), []>, Sched<[]> {}
2301 // FIXME: maybe the scratch register used shouldn't be fixed to X1?
2302 // FIXME: can "hasSideEffects be dropped?
2303 let isCall = 1, Defs = [LR, X0, X1], hasSideEffects = 1,
2304     isCodeGenOnly = 1 in
2305 def TLSDESC_CALLSEQ
2306     : Pseudo<(outs), (ins i64imm:$sym),
2307              [(AArch64tlsdesc_callseq tglobaltlsaddr:$sym)]>,
2308       Sched<[WriteI, WriteLD, WriteI, WriteBrReg]>;
2309 def : Pat<(AArch64tlsdesc_callseq texternalsym:$sym),
2310           (TLSDESC_CALLSEQ texternalsym:$sym)>;
2312 //===----------------------------------------------------------------------===//
2313 // Conditional branch (immediate) instruction.
2314 //===----------------------------------------------------------------------===//
2315 def Bcc : BranchCond;
2317 //===----------------------------------------------------------------------===//
2318 // Compare-and-branch instructions.
2319 //===----------------------------------------------------------------------===//
2320 defm CBZ  : CmpBranch<0, "cbz", AArch64cbz>;
2321 defm CBNZ : CmpBranch<1, "cbnz", AArch64cbnz>;
2323 //===----------------------------------------------------------------------===//
2324 // Test-bit-and-branch instructions.
2325 //===----------------------------------------------------------------------===//
2326 defm TBZ  : TestBranch<0, "tbz", AArch64tbz>;
2327 defm TBNZ : TestBranch<1, "tbnz", AArch64tbnz>;
2329 //===----------------------------------------------------------------------===//
2330 // Unconditional branch (immediate) instructions.
2331 //===----------------------------------------------------------------------===//
2332 let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
2333 def B  : BranchImm<0, "b", [(br bb:$addr)]>;
2334 } // isBranch, isTerminator, isBarrier
2336 let isCall = 1, Defs = [LR], Uses = [SP] in {
2337 def BL : CallImm<1, "bl", [(AArch64call tglobaladdr:$addr)]>;
2338 } // isCall
2339 def : Pat<(AArch64call texternalsym:$func), (BL texternalsym:$func)>;
2341 //===----------------------------------------------------------------------===//
2342 // Exception generation instructions.
2343 //===----------------------------------------------------------------------===//
2344 let isTrap = 1 in {
2345 def BRK   : ExceptionGeneration<0b001, 0b00, "brk">;
2347 def DCPS1 : ExceptionGeneration<0b101, 0b01, "dcps1">;
2348 def DCPS2 : ExceptionGeneration<0b101, 0b10, "dcps2">;
2349 def DCPS3 : ExceptionGeneration<0b101, 0b11, "dcps3">;
2350 def HLT   : ExceptionGeneration<0b010, 0b00, "hlt">;
2351 def HVC   : ExceptionGeneration<0b000, 0b10, "hvc">;
2352 def SMC   : ExceptionGeneration<0b000, 0b11, "smc">;
2353 def SVC   : ExceptionGeneration<0b000, 0b01, "svc">;
2355 // DCPSn defaults to an immediate operand of zero if unspecified.
2356 def : InstAlias<"dcps1", (DCPS1 0)>;
2357 def : InstAlias<"dcps2", (DCPS2 0)>;
2358 def : InstAlias<"dcps3", (DCPS3 0)>;
2360 def UDF : UDFType<0, "udf">;
2362 //===----------------------------------------------------------------------===//
2363 // Load instructions.
2364 //===----------------------------------------------------------------------===//
2366 // Pair (indexed, offset)
2367 defm LDPW : LoadPairOffset<0b00, 0, GPR32z, simm7s4, "ldp">;
2368 defm LDPX : LoadPairOffset<0b10, 0, GPR64z, simm7s8, "ldp">;
2369 defm LDPS : LoadPairOffset<0b00, 1, FPR32Op, simm7s4, "ldp">;
2370 defm LDPD : LoadPairOffset<0b01, 1, FPR64Op, simm7s8, "ldp">;
2371 defm LDPQ : LoadPairOffset<0b10, 1, FPR128Op, simm7s16, "ldp">;
2373 defm LDPSW : LoadPairOffset<0b01, 0, GPR64z, simm7s4, "ldpsw">;
2375 // Pair (pre-indexed)
2376 def LDPWpre : LoadPairPreIdx<0b00, 0, GPR32z, simm7s4, "ldp">;
2377 def LDPXpre : LoadPairPreIdx<0b10, 0, GPR64z, simm7s8, "ldp">;
2378 def LDPSpre : LoadPairPreIdx<0b00, 1, FPR32Op, simm7s4, "ldp">;
2379 def LDPDpre : LoadPairPreIdx<0b01, 1, FPR64Op, simm7s8, "ldp">;
2380 def LDPQpre : LoadPairPreIdx<0b10, 1, FPR128Op, simm7s16, "ldp">;
2382 def LDPSWpre : LoadPairPreIdx<0b01, 0, GPR64z, simm7s4, "ldpsw">;
2384 // Pair (post-indexed)
2385 def LDPWpost : LoadPairPostIdx<0b00, 0, GPR32z, simm7s4, "ldp">;
2386 def LDPXpost : LoadPairPostIdx<0b10, 0, GPR64z, simm7s8, "ldp">;
2387 def LDPSpost : LoadPairPostIdx<0b00, 1, FPR32Op, simm7s4, "ldp">;
2388 def LDPDpost : LoadPairPostIdx<0b01, 1, FPR64Op, simm7s8, "ldp">;
2389 def LDPQpost : LoadPairPostIdx<0b10, 1, FPR128Op, simm7s16, "ldp">;
2391 def LDPSWpost : LoadPairPostIdx<0b01, 0, GPR64z, simm7s4, "ldpsw">;
2394 // Pair (no allocate)
2395 defm LDNPW : LoadPairNoAlloc<0b00, 0, GPR32z, simm7s4, "ldnp">;
2396 defm LDNPX : LoadPairNoAlloc<0b10, 0, GPR64z, simm7s8, "ldnp">;
2397 defm LDNPS : LoadPairNoAlloc<0b00, 1, FPR32Op, simm7s4, "ldnp">;
2398 defm LDNPD : LoadPairNoAlloc<0b01, 1, FPR64Op, simm7s8, "ldnp">;
2399 defm LDNPQ : LoadPairNoAlloc<0b10, 1, FPR128Op, simm7s16, "ldnp">;
2401 def : Pat<(AArch64ldp (am_indexed7s64 GPR64sp:$Rn, simm7s8:$offset)),
2402           (LDPXi GPR64sp:$Rn, simm7s8:$offset)>;
2404 //---
2405 // (register offset)
2406 //---
2408 // Integer
2409 defm LDRBB : Load8RO<0b00,  0, 0b01, GPR32, "ldrb", i32, zextloadi8>;
2410 defm LDRHH : Load16RO<0b01, 0, 0b01, GPR32, "ldrh", i32, zextloadi16>;
2411 defm LDRW  : Load32RO<0b10, 0, 0b01, GPR32, "ldr", i32, load>;
2412 defm LDRX  : Load64RO<0b11, 0, 0b01, GPR64, "ldr", i64, load>;
2414 // Floating-point
2415 defm LDRB : Load8RO<0b00,   1, 0b01, FPR8Op,   "ldr", untyped, load>;
2416 defm LDRH : Load16RO<0b01,  1, 0b01, FPR16Op,  "ldr", f16, load>;
2417 defm LDRS : Load32RO<0b10,  1, 0b01, FPR32Op,  "ldr", f32, load>;
2418 defm LDRD : Load64RO<0b11,  1, 0b01, FPR64Op,  "ldr", f64, load>;
2419 defm LDRQ : Load128RO<0b00, 1, 0b11, FPR128Op, "ldr", f128, load>;
2421 // Load sign-extended half-word
2422 defm LDRSHW : Load16RO<0b01, 0, 0b11, GPR32, "ldrsh", i32, sextloadi16>;
2423 defm LDRSHX : Load16RO<0b01, 0, 0b10, GPR64, "ldrsh", i64, sextloadi16>;
2425 // Load sign-extended byte
2426 defm LDRSBW : Load8RO<0b00, 0, 0b11, GPR32, "ldrsb", i32, sextloadi8>;
2427 defm LDRSBX : Load8RO<0b00, 0, 0b10, GPR64, "ldrsb", i64, sextloadi8>;
2429 // Load sign-extended word
2430 defm LDRSW  : Load32RO<0b10, 0, 0b10, GPR64, "ldrsw", i64, sextloadi32>;
2432 // Pre-fetch.
2433 defm PRFM : PrefetchRO<0b11, 0, 0b10, "prfm">;
2435 // For regular load, we do not have any alignment requirement.
2436 // Thus, it is safe to directly map the vector loads with interesting
2437 // addressing modes.
2438 // FIXME: We could do the same for bitconvert to floating point vectors.
2439 multiclass ScalToVecROLoadPat<ROAddrMode ro, SDPatternOperator loadop,
2440                               ValueType ScalTy, ValueType VecTy,
2441                               Instruction LOADW, Instruction LOADX,
2442                               SubRegIndex sub> {
2443   def : Pat<(VecTy (scalar_to_vector (ScalTy
2444               (loadop (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$offset))))),
2445             (INSERT_SUBREG (VecTy (IMPLICIT_DEF)),
2446                            (LOADW GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$offset),
2447                            sub)>;
2449   def : Pat<(VecTy (scalar_to_vector (ScalTy
2450               (loadop (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$offset))))),
2451             (INSERT_SUBREG (VecTy (IMPLICIT_DEF)),
2452                            (LOADX GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$offset),
2453                            sub)>;
2456 let AddedComplexity = 10 in {
2457 defm : ScalToVecROLoadPat<ro8,  extloadi8,  i32, v8i8,  LDRBroW, LDRBroX, bsub>;
2458 defm : ScalToVecROLoadPat<ro8,  extloadi8,  i32, v16i8, LDRBroW, LDRBroX, bsub>;
2460 defm : ScalToVecROLoadPat<ro16, extloadi16, i32, v4i16, LDRHroW, LDRHroX, hsub>;
2461 defm : ScalToVecROLoadPat<ro16, extloadi16, i32, v8i16, LDRHroW, LDRHroX, hsub>;
2463 defm : ScalToVecROLoadPat<ro16, load,       i32, v4f16, LDRHroW, LDRHroX, hsub>;
2464 defm : ScalToVecROLoadPat<ro16, load,       i32, v8f16, LDRHroW, LDRHroX, hsub>;
2466 defm : ScalToVecROLoadPat<ro32, load,       i32, v2i32, LDRSroW, LDRSroX, ssub>;
2467 defm : ScalToVecROLoadPat<ro32, load,       i32, v4i32, LDRSroW, LDRSroX, ssub>;
2469 defm : ScalToVecROLoadPat<ro32, load,       f32, v2f32, LDRSroW, LDRSroX, ssub>;
2470 defm : ScalToVecROLoadPat<ro32, load,       f32, v4f32, LDRSroW, LDRSroX, ssub>;
2472 defm : ScalToVecROLoadPat<ro64, load,       i64, v2i64, LDRDroW, LDRDroX, dsub>;
2474 defm : ScalToVecROLoadPat<ro64, load,       f64, v2f64, LDRDroW, LDRDroX, dsub>;
2477 def : Pat <(v1i64 (scalar_to_vector (i64
2478                       (load (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2479                                            ro_Wextend64:$extend))))),
2480            (LDRDroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend)>;
2482 def : Pat <(v1i64 (scalar_to_vector (i64
2483                       (load (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2484                                            ro_Xextend64:$extend))))),
2485            (LDRDroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend)>;
2488 // Match all load 64 bits width whose type is compatible with FPR64
2489 multiclass VecROLoadPat<ROAddrMode ro, ValueType VecTy,
2490                         Instruction LOADW, Instruction LOADX> {
2492   def : Pat<(VecTy (load (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend))),
2493             (LOADW GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)>;
2495   def : Pat<(VecTy (load (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend))),
2496             (LOADX GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)>;
2499 let AddedComplexity = 10 in {
2500 let Predicates = [IsLE] in {
2501   // We must do vector loads with LD1 in big-endian.
2502   defm : VecROLoadPat<ro64, v2i32, LDRDroW, LDRDroX>;
2503   defm : VecROLoadPat<ro64, v2f32, LDRDroW, LDRDroX>;
2504   defm : VecROLoadPat<ro64, v8i8,  LDRDroW, LDRDroX>;
2505   defm : VecROLoadPat<ro64, v4i16, LDRDroW, LDRDroX>;
2506   defm : VecROLoadPat<ro64, v4f16, LDRDroW, LDRDroX>;
2507   defm : VecROLoadPat<ro64, v4bf16, LDRDroW, LDRDroX>;
2510 defm : VecROLoadPat<ro64, v1i64,  LDRDroW, LDRDroX>;
2511 defm : VecROLoadPat<ro64, v1f64,  LDRDroW, LDRDroX>;
2513 // Match all load 128 bits width whose type is compatible with FPR128
2514 let Predicates = [IsLE] in {
2515   // We must do vector loads with LD1 in big-endian.
2516   defm : VecROLoadPat<ro128, v2i64,  LDRQroW, LDRQroX>;
2517   defm : VecROLoadPat<ro128, v2f64,  LDRQroW, LDRQroX>;
2518   defm : VecROLoadPat<ro128, v4i32,  LDRQroW, LDRQroX>;
2519   defm : VecROLoadPat<ro128, v4f32,  LDRQroW, LDRQroX>;
2520   defm : VecROLoadPat<ro128, v8i16,  LDRQroW, LDRQroX>;
2521   defm : VecROLoadPat<ro128, v8f16,  LDRQroW, LDRQroX>;
2522   defm : VecROLoadPat<ro128, v8bf16,  LDRQroW, LDRQroX>;
2523   defm : VecROLoadPat<ro128, v16i8,  LDRQroW, LDRQroX>;
2525 } // AddedComplexity = 10
2527 // zextload -> i64
2528 multiclass ExtLoadTo64ROPat<ROAddrMode ro, SDPatternOperator loadop,
2529                             Instruction INSTW, Instruction INSTX> {
2530   def : Pat<(i64 (loadop (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend))),
2531             (SUBREG_TO_REG (i64 0),
2532                            (INSTW GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend),
2533                            sub_32)>;
2535   def : Pat<(i64 (loadop (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend))),
2536             (SUBREG_TO_REG (i64 0),
2537                            (INSTX GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend),
2538                            sub_32)>;
2541 let AddedComplexity = 10 in {
2542   defm : ExtLoadTo64ROPat<ro8,  zextloadi8,  LDRBBroW, LDRBBroX>;
2543   defm : ExtLoadTo64ROPat<ro16, zextloadi16, LDRHHroW, LDRHHroX>;
2544   defm : ExtLoadTo64ROPat<ro32, zextloadi32, LDRWroW,  LDRWroX>;
2546   // zextloadi1 -> zextloadi8
2547   defm : ExtLoadTo64ROPat<ro8,  zextloadi1,  LDRBBroW, LDRBBroX>;
2549   // extload -> zextload
2550   defm : ExtLoadTo64ROPat<ro8,  extloadi8,   LDRBBroW, LDRBBroX>;
2551   defm : ExtLoadTo64ROPat<ro16, extloadi16,  LDRHHroW, LDRHHroX>;
2552   defm : ExtLoadTo64ROPat<ro32, extloadi32,  LDRWroW,  LDRWroX>;
2554   // extloadi1 -> zextloadi8
2555   defm : ExtLoadTo64ROPat<ro8,  extloadi1,   LDRBBroW, LDRBBroX>;
2559 // zextload -> i64
2560 multiclass ExtLoadTo32ROPat<ROAddrMode ro, SDPatternOperator loadop,
2561                             Instruction INSTW, Instruction INSTX> {
2562   def : Pat<(i32 (loadop (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend))),
2563             (INSTW GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)>;
2565   def : Pat<(i32 (loadop (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend))),
2566             (INSTX GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)>;
2570 let AddedComplexity = 10 in {
2571   // extload -> zextload
2572   defm : ExtLoadTo32ROPat<ro8,  extloadi8,   LDRBBroW, LDRBBroX>;
2573   defm : ExtLoadTo32ROPat<ro16, extloadi16,  LDRHHroW, LDRHHroX>;
2574   defm : ExtLoadTo32ROPat<ro32, extloadi32,  LDRWroW,  LDRWroX>;
2576   // zextloadi1 -> zextloadi8
2577   defm : ExtLoadTo32ROPat<ro8, zextloadi1, LDRBBroW, LDRBBroX>;
2580 //---
2581 // (unsigned immediate)
2582 //---
2583 defm LDRX : LoadUI<0b11, 0, 0b01, GPR64z, uimm12s8, "ldr",
2584                    [(set GPR64z:$Rt,
2585                          (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)))]>;
2586 defm LDRW : LoadUI<0b10, 0, 0b01, GPR32z, uimm12s4, "ldr",
2587                    [(set GPR32z:$Rt,
2588                          (load (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset)))]>;
2589 defm LDRB : LoadUI<0b00, 1, 0b01, FPR8Op, uimm12s1, "ldr",
2590                    [(set FPR8Op:$Rt,
2591                          (load (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset)))]>;
2592 defm LDRH : LoadUI<0b01, 1, 0b01, FPR16Op, uimm12s2, "ldr",
2593                    [(set (f16 FPR16Op:$Rt),
2594                          (load (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset)))]>;
2595 defm LDRS : LoadUI<0b10, 1, 0b01, FPR32Op, uimm12s4, "ldr",
2596                    [(set (f32 FPR32Op:$Rt),
2597                          (load (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset)))]>;
2598 defm LDRD : LoadUI<0b11, 1, 0b01, FPR64Op, uimm12s8, "ldr",
2599                    [(set (f64 FPR64Op:$Rt),
2600                          (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)))]>;
2601 defm LDRQ : LoadUI<0b00, 1, 0b11, FPR128Op, uimm12s16, "ldr",
2602                  [(set (f128 FPR128Op:$Rt),
2603                        (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)))]>;
2605 // bf16 load pattern
2606 def : Pat <(bf16 (load (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))),
2607            (LDRHui GPR64sp:$Rn, uimm12s2:$offset)>;
2609 // For regular load, we do not have any alignment requirement.
2610 // Thus, it is safe to directly map the vector loads with interesting
2611 // addressing modes.
2612 // FIXME: We could do the same for bitconvert to floating point vectors.
2613 def : Pat <(v8i8 (scalar_to_vector (i32
2614                (extloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))))),
2615            (INSERT_SUBREG (v8i8 (IMPLICIT_DEF)),
2616                           (LDRBui GPR64sp:$Rn, uimm12s1:$offset), bsub)>;
2617 def : Pat <(v16i8 (scalar_to_vector (i32
2618                (extloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))))),
2619            (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
2620                           (LDRBui GPR64sp:$Rn, uimm12s1:$offset), bsub)>;
2621 def : Pat <(v4i16 (scalar_to_vector (i32
2622                (extloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))))),
2623            (INSERT_SUBREG (v4i16 (IMPLICIT_DEF)),
2624                           (LDRHui GPR64sp:$Rn, uimm12s2:$offset), hsub)>;
2625 def : Pat <(v8i16 (scalar_to_vector (i32
2626                (extloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))))),
2627            (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)),
2628                           (LDRHui GPR64sp:$Rn, uimm12s2:$offset), hsub)>;
2629 def : Pat <(v2i32 (scalar_to_vector (i32
2630                (load (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))))),
2631            (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
2632                           (LDRSui GPR64sp:$Rn, uimm12s4:$offset), ssub)>;
2633 def : Pat <(v4i32 (scalar_to_vector (i32
2634                (load (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))))),
2635            (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
2636                           (LDRSui GPR64sp:$Rn, uimm12s4:$offset), ssub)>;
2637 def : Pat <(v1i64 (scalar_to_vector (i64
2638                (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))))),
2639            (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>;
2640 def : Pat <(v2i64 (scalar_to_vector (i64
2641                (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))))),
2642            (INSERT_SUBREG (v2i64 (IMPLICIT_DEF)),
2643                           (LDRDui GPR64sp:$Rn, uimm12s8:$offset), dsub)>;
2645 // Match all load 64 bits width whose type is compatible with FPR64
2646 let Predicates = [IsLE] in {
2647   // We must use LD1 to perform vector loads in big-endian.
2648   def : Pat<(v2f32 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))),
2649             (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>;
2650   def : Pat<(v8i8 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))),
2651             (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>;
2652   def : Pat<(v4i16 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))),
2653             (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>;
2654   def : Pat<(v2i32 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))),
2655             (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>;
2656   def : Pat<(v4f16 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))),
2657             (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>;
2658   def : Pat<(v4bf16 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))),
2659             (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>;
2661 def : Pat<(v1f64 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))),
2662           (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>;
2663 def : Pat<(v1i64 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))),
2664           (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>;
2666 // Match all load 128 bits width whose type is compatible with FPR128
2667 let Predicates = [IsLE] in {
2668   // We must use LD1 to perform vector loads in big-endian.
2669   def : Pat<(v4f32 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))),
2670             (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>;
2671   def : Pat<(v2f64 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))),
2672             (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>;
2673   def : Pat<(v16i8 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))),
2674             (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>;
2675   def : Pat<(v8i16 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))),
2676             (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>;
2677   def : Pat<(v4i32 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))),
2678             (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>;
2679   def : Pat<(v2i64 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))),
2680             (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>;
2681   def : Pat<(v8f16 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))),
2682             (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>;
2683   def : Pat<(v8bf16 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))),
2684             (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>;
2686 def : Pat<(f128  (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))),
2687           (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>;
2689 defm LDRHH : LoadUI<0b01, 0, 0b01, GPR32, uimm12s2, "ldrh",
2690                     [(set GPR32:$Rt,
2691                           (zextloadi16 (am_indexed16 GPR64sp:$Rn,
2692                                                      uimm12s2:$offset)))]>;
2693 defm LDRBB : LoadUI<0b00, 0, 0b01, GPR32, uimm12s1, "ldrb",
2694                     [(set GPR32:$Rt,
2695                           (zextloadi8 (am_indexed8 GPR64sp:$Rn,
2696                                                    uimm12s1:$offset)))]>;
2697 // zextload -> i64
2698 def : Pat<(i64 (zextloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))),
2699     (SUBREG_TO_REG (i64 0), (LDRBBui GPR64sp:$Rn, uimm12s1:$offset), sub_32)>;
2700 def : Pat<(i64 (zextloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))),
2701     (SUBREG_TO_REG (i64 0), (LDRHHui GPR64sp:$Rn, uimm12s2:$offset), sub_32)>;
2703 // zextloadi1 -> zextloadi8
2704 def : Pat<(i32 (zextloadi1 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))),
2705           (LDRBBui GPR64sp:$Rn, uimm12s1:$offset)>;
2706 def : Pat<(i64 (zextloadi1 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))),
2707     (SUBREG_TO_REG (i64 0), (LDRBBui GPR64sp:$Rn, uimm12s1:$offset), sub_32)>;
2709 // extload -> zextload
2710 def : Pat<(i32 (extloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))),
2711           (LDRHHui GPR64sp:$Rn, uimm12s2:$offset)>;
2712 def : Pat<(i32 (extloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))),
2713           (LDRBBui GPR64sp:$Rn, uimm12s1:$offset)>;
2714 def : Pat<(i32 (extloadi1 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))),
2715           (LDRBBui GPR64sp:$Rn, uimm12s1:$offset)>;
2716 def : Pat<(i64 (extloadi32 (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))),
2717     (SUBREG_TO_REG (i64 0), (LDRWui GPR64sp:$Rn, uimm12s4:$offset), sub_32)>;
2718 def : Pat<(i64 (extloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))),
2719     (SUBREG_TO_REG (i64 0), (LDRHHui GPR64sp:$Rn, uimm12s2:$offset), sub_32)>;
2720 def : Pat<(i64 (extloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))),
2721     (SUBREG_TO_REG (i64 0), (LDRBBui GPR64sp:$Rn, uimm12s1:$offset), sub_32)>;
2722 def : Pat<(i64 (extloadi1 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))),
2723     (SUBREG_TO_REG (i64 0), (LDRBBui GPR64sp:$Rn, uimm12s1:$offset), sub_32)>;
2725 // load sign-extended half-word
2726 defm LDRSHW : LoadUI<0b01, 0, 0b11, GPR32, uimm12s2, "ldrsh",
2727                      [(set GPR32:$Rt,
2728                            (sextloadi16 (am_indexed16 GPR64sp:$Rn,
2729                                                       uimm12s2:$offset)))]>;
2730 defm LDRSHX : LoadUI<0b01, 0, 0b10, GPR64, uimm12s2, "ldrsh",
2731                      [(set GPR64:$Rt,
2732                            (sextloadi16 (am_indexed16 GPR64sp:$Rn,
2733                                                       uimm12s2:$offset)))]>;
2735 // load sign-extended byte
2736 defm LDRSBW : LoadUI<0b00, 0, 0b11, GPR32, uimm12s1, "ldrsb",
2737                      [(set GPR32:$Rt,
2738                            (sextloadi8 (am_indexed8 GPR64sp:$Rn,
2739                                                     uimm12s1:$offset)))]>;
2740 defm LDRSBX : LoadUI<0b00, 0, 0b10, GPR64, uimm12s1, "ldrsb",
2741                      [(set GPR64:$Rt,
2742                            (sextloadi8 (am_indexed8 GPR64sp:$Rn,
2743                                                     uimm12s1:$offset)))]>;
2745 // load sign-extended word
2746 defm LDRSW  : LoadUI<0b10, 0, 0b10, GPR64, uimm12s4, "ldrsw",
2747                      [(set GPR64:$Rt,
2748                            (sextloadi32 (am_indexed32 GPR64sp:$Rn,
2749                                                       uimm12s4:$offset)))]>;
2751 // load zero-extended word
2752 def : Pat<(i64 (zextloadi32 (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))),
2753       (SUBREG_TO_REG (i64 0), (LDRWui GPR64sp:$Rn, uimm12s4:$offset), sub_32)>;
2755 // Pre-fetch.
2756 def PRFMui : PrefetchUI<0b11, 0, 0b10, "prfm",
2757                         [(AArch64Prefetch imm:$Rt,
2758                                         (am_indexed64 GPR64sp:$Rn,
2759                                                       uimm12s8:$offset))]>;
2761 def : InstAlias<"prfm $Rt, [$Rn]", (PRFMui prfop:$Rt, GPR64sp:$Rn, 0)>;
2763 //---
2764 // (literal)
2766 def alignedglobal : PatLeaf<(iPTR iPTR:$label), [{
2767   if (auto *G = dyn_cast<GlobalAddressSDNode>(N)) {
2768     const DataLayout &DL = MF->getDataLayout();
2769     Align Align = G->getGlobal()->getPointerAlignment(DL);
2770     return Align >= 4 && G->getOffset() % 4 == 0;
2771   }
2772   if (auto *C = dyn_cast<ConstantPoolSDNode>(N))
2773     return C->getAlign() >= 4 && C->getOffset() % 4 == 0;
2774   return false;
2775 }]>;
2777 def LDRWl : LoadLiteral<0b00, 0, GPR32z, "ldr",
2778   [(set GPR32z:$Rt, (load (AArch64adr alignedglobal:$label)))]>;
2779 def LDRXl : LoadLiteral<0b01, 0, GPR64z, "ldr",
2780   [(set GPR64z:$Rt, (load (AArch64adr alignedglobal:$label)))]>;
2781 def LDRSl : LoadLiteral<0b00, 1, FPR32Op, "ldr",
2782   [(set (f32 FPR32Op:$Rt), (load (AArch64adr alignedglobal:$label)))]>;
2783 def LDRDl : LoadLiteral<0b01, 1, FPR64Op, "ldr",
2784   [(set (f64 FPR64Op:$Rt), (load (AArch64adr alignedglobal:$label)))]>;
2785 def LDRQl : LoadLiteral<0b10, 1, FPR128Op, "ldr",
2786   [(set (f128 FPR128Op:$Rt), (load (AArch64adr alignedglobal:$label)))]>;
2788 // load sign-extended word
2789 def LDRSWl : LoadLiteral<0b10, 0, GPR64z, "ldrsw",
2790   [(set GPR64z:$Rt, (sextloadi32 (AArch64adr alignedglobal:$label)))]>;
2792 let AddedComplexity = 20 in {
2793 def : Pat<(i64 (zextloadi32 (AArch64adr alignedglobal:$label))),
2794         (SUBREG_TO_REG (i64 0), (LDRWl $label), sub_32)>;
2797 // prefetch
2798 def PRFMl : PrefetchLiteral<0b11, 0, "prfm", []>;
2799 //                   [(AArch64Prefetch imm:$Rt, tglobaladdr:$label)]>;
2801 //---
2802 // (unscaled immediate)
2803 defm LDURX : LoadUnscaled<0b11, 0, 0b01, GPR64z, "ldur",
2804                     [(set GPR64z:$Rt,
2805                           (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset)))]>;
2806 defm LDURW : LoadUnscaled<0b10, 0, 0b01, GPR32z, "ldur",
2807                     [(set GPR32z:$Rt,
2808                           (load (am_unscaled32 GPR64sp:$Rn, simm9:$offset)))]>;
2809 defm LDURB : LoadUnscaled<0b00, 1, 0b01, FPR8Op, "ldur",
2810                     [(set FPR8Op:$Rt,
2811                           (load (am_unscaled8 GPR64sp:$Rn, simm9:$offset)))]>;
2812 defm LDURH : LoadUnscaled<0b01, 1, 0b01, FPR16Op, "ldur",
2813                     [(set (f16 FPR16Op:$Rt),
2814                           (load (am_unscaled16 GPR64sp:$Rn, simm9:$offset)))]>;
2815 defm LDURS : LoadUnscaled<0b10, 1, 0b01, FPR32Op, "ldur",
2816                     [(set (f32 FPR32Op:$Rt),
2817                           (load (am_unscaled32 GPR64sp:$Rn, simm9:$offset)))]>;
2818 defm LDURD : LoadUnscaled<0b11, 1, 0b01, FPR64Op, "ldur",
2819                     [(set (f64 FPR64Op:$Rt),
2820                           (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset)))]>;
2821 defm LDURQ : LoadUnscaled<0b00, 1, 0b11, FPR128Op, "ldur",
2822                     [(set (f128 FPR128Op:$Rt),
2823                           (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset)))]>;
2825 defm LDURHH
2826     : LoadUnscaled<0b01, 0, 0b01, GPR32, "ldurh",
2827              [(set GPR32:$Rt,
2828                     (zextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset)))]>;
2829 defm LDURBB
2830     : LoadUnscaled<0b00, 0, 0b01, GPR32, "ldurb",
2831              [(set GPR32:$Rt,
2832                     (zextloadi8 (am_unscaled16 GPR64sp:$Rn, simm9:$offset)))]>;
2834 // Match all load 64 bits width whose type is compatible with FPR64
2835 let Predicates = [IsLE] in {
2836   def : Pat<(v2f32 (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset))),
2837             (LDURDi GPR64sp:$Rn, simm9:$offset)>;
2838   def : Pat<(v2i32 (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset))),
2839             (LDURDi GPR64sp:$Rn, simm9:$offset)>;
2840   def : Pat<(v4i16 (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset))),
2841             (LDURDi GPR64sp:$Rn, simm9:$offset)>;
2842   def : Pat<(v8i8 (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset))),
2843             (LDURDi GPR64sp:$Rn, simm9:$offset)>;
2844   def : Pat<(v4f16 (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset))),
2845             (LDURDi GPR64sp:$Rn, simm9:$offset)>;
2847 def : Pat<(v1f64 (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset))),
2848           (LDURDi GPR64sp:$Rn, simm9:$offset)>;
2849 def : Pat<(v1i64 (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset))),
2850           (LDURDi GPR64sp:$Rn, simm9:$offset)>;
2852 // Match all load 128 bits width whose type is compatible with FPR128
2853 let Predicates = [IsLE] in {
2854   def : Pat<(v2f64 (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset))),
2855             (LDURQi GPR64sp:$Rn, simm9:$offset)>;
2856   def : Pat<(v2i64 (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset))),
2857             (LDURQi GPR64sp:$Rn, simm9:$offset)>;
2858   def : Pat<(v4f32 (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset))),
2859             (LDURQi GPR64sp:$Rn, simm9:$offset)>;
2860   def : Pat<(v4i32 (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset))),
2861             (LDURQi GPR64sp:$Rn, simm9:$offset)>;
2862   def : Pat<(v8i16 (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset))),
2863             (LDURQi GPR64sp:$Rn, simm9:$offset)>;
2864   def : Pat<(v16i8 (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset))),
2865             (LDURQi GPR64sp:$Rn, simm9:$offset)>;
2866   def : Pat<(v8f16 (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset))),
2867             (LDURQi GPR64sp:$Rn, simm9:$offset)>;
2870 //  anyext -> zext
2871 def : Pat<(i32 (extloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))),
2872           (LDURHHi GPR64sp:$Rn, simm9:$offset)>;
2873 def : Pat<(i32 (extloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))),
2874           (LDURBBi GPR64sp:$Rn, simm9:$offset)>;
2875 def : Pat<(i32 (extloadi1 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))),
2876           (LDURBBi GPR64sp:$Rn, simm9:$offset)>;
2877 def : Pat<(i64 (extloadi32 (am_unscaled32 GPR64sp:$Rn, simm9:$offset))),
2878     (SUBREG_TO_REG (i64 0), (LDURWi GPR64sp:$Rn, simm9:$offset), sub_32)>;
2879 def : Pat<(i64 (extloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))),
2880     (SUBREG_TO_REG (i64 0), (LDURHHi GPR64sp:$Rn, simm9:$offset), sub_32)>;
2881 def : Pat<(i64 (extloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))),
2882     (SUBREG_TO_REG (i64 0), (LDURBBi GPR64sp:$Rn, simm9:$offset), sub_32)>;
2883 def : Pat<(i64 (extloadi1 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))),
2884     (SUBREG_TO_REG (i64 0), (LDURBBi GPR64sp:$Rn, simm9:$offset), sub_32)>;
2885 // unscaled zext
2886 def : Pat<(i32 (zextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))),
2887           (LDURHHi GPR64sp:$Rn, simm9:$offset)>;
2888 def : Pat<(i32 (zextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))),
2889           (LDURBBi GPR64sp:$Rn, simm9:$offset)>;
2890 def : Pat<(i32 (zextloadi1 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))),
2891           (LDURBBi GPR64sp:$Rn, simm9:$offset)>;
2892 def : Pat<(i64 (zextloadi32 (am_unscaled32 GPR64sp:$Rn, simm9:$offset))),
2893     (SUBREG_TO_REG (i64 0), (LDURWi GPR64sp:$Rn, simm9:$offset), sub_32)>;
2894 def : Pat<(i64 (zextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))),
2895     (SUBREG_TO_REG (i64 0), (LDURHHi GPR64sp:$Rn, simm9:$offset), sub_32)>;
2896 def : Pat<(i64 (zextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))),
2897     (SUBREG_TO_REG (i64 0), (LDURBBi GPR64sp:$Rn, simm9:$offset), sub_32)>;
2898 def : Pat<(i64 (zextloadi1 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))),
2899     (SUBREG_TO_REG (i64 0), (LDURBBi GPR64sp:$Rn, simm9:$offset), sub_32)>;
2902 //---
2903 // LDR mnemonics fall back to LDUR for negative or unaligned offsets.
2905 // Define new assembler match classes as we want to only match these when
2906 // the don't otherwise match the scaled addressing mode for LDR/STR. Don't
2907 // associate a DiagnosticType either, as we want the diagnostic for the
2908 // canonical form (the scaled operand) to take precedence.
2909 class SImm9OffsetOperand<int Width> : AsmOperandClass {
2910   let Name = "SImm9OffsetFB" # Width;
2911   let PredicateMethod = "isSImm9OffsetFB<" # Width # ">";
2912   let RenderMethod = "addImmOperands";
2915 def SImm9OffsetFB8Operand : SImm9OffsetOperand<8>;
2916 def SImm9OffsetFB16Operand : SImm9OffsetOperand<16>;
2917 def SImm9OffsetFB32Operand : SImm9OffsetOperand<32>;
2918 def SImm9OffsetFB64Operand : SImm9OffsetOperand<64>;
2919 def SImm9OffsetFB128Operand : SImm9OffsetOperand<128>;
2921 def simm9_offset_fb8 : Operand<i64> {
2922   let ParserMatchClass = SImm9OffsetFB8Operand;
2924 def simm9_offset_fb16 : Operand<i64> {
2925   let ParserMatchClass = SImm9OffsetFB16Operand;
2927 def simm9_offset_fb32 : Operand<i64> {
2928   let ParserMatchClass = SImm9OffsetFB32Operand;
2930 def simm9_offset_fb64 : Operand<i64> {
2931   let ParserMatchClass = SImm9OffsetFB64Operand;
2933 def simm9_offset_fb128 : Operand<i64> {
2934   let ParserMatchClass = SImm9OffsetFB128Operand;
2937 def : InstAlias<"ldr $Rt, [$Rn, $offset]",
2938                 (LDURXi GPR64:$Rt, GPR64sp:$Rn, simm9_offset_fb64:$offset), 0>;
2939 def : InstAlias<"ldr $Rt, [$Rn, $offset]",
2940                 (LDURWi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb32:$offset), 0>;
2941 def : InstAlias<"ldr $Rt, [$Rn, $offset]",
2942                 (LDURBi FPR8Op:$Rt, GPR64sp:$Rn, simm9_offset_fb8:$offset), 0>;
2943 def : InstAlias<"ldr $Rt, [$Rn, $offset]",
2944                 (LDURHi FPR16Op:$Rt, GPR64sp:$Rn, simm9_offset_fb16:$offset), 0>;
2945 def : InstAlias<"ldr $Rt, [$Rn, $offset]",
2946                 (LDURSi FPR32Op:$Rt, GPR64sp:$Rn, simm9_offset_fb32:$offset), 0>;
2947 def : InstAlias<"ldr $Rt, [$Rn, $offset]",
2948                 (LDURDi FPR64Op:$Rt, GPR64sp:$Rn, simm9_offset_fb64:$offset), 0>;
2949 def : InstAlias<"ldr $Rt, [$Rn, $offset]",
2950                (LDURQi FPR128Op:$Rt, GPR64sp:$Rn, simm9_offset_fb128:$offset), 0>;
2952 // zextload -> i64
2953 def : Pat<(i64 (zextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))),
2954   (SUBREG_TO_REG (i64 0), (LDURBBi GPR64sp:$Rn, simm9:$offset), sub_32)>;
2955 def : Pat<(i64 (zextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))),
2956   (SUBREG_TO_REG (i64 0), (LDURHHi GPR64sp:$Rn, simm9:$offset), sub_32)>;
2958 // load sign-extended half-word
2959 defm LDURSHW
2960     : LoadUnscaled<0b01, 0, 0b11, GPR32, "ldursh",
2961                [(set GPR32:$Rt,
2962                     (sextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset)))]>;
2963 defm LDURSHX
2964     : LoadUnscaled<0b01, 0, 0b10, GPR64, "ldursh",
2965               [(set GPR64:$Rt,
2966                     (sextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset)))]>;
2968 // load sign-extended byte
2969 defm LDURSBW
2970     : LoadUnscaled<0b00, 0, 0b11, GPR32, "ldursb",
2971                 [(set GPR32:$Rt,
2972                       (sextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset)))]>;
2973 defm LDURSBX
2974     : LoadUnscaled<0b00, 0, 0b10, GPR64, "ldursb",
2975                 [(set GPR64:$Rt,
2976                       (sextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset)))]>;
2978 // load sign-extended word
2979 defm LDURSW
2980     : LoadUnscaled<0b10, 0, 0b10, GPR64, "ldursw",
2981               [(set GPR64:$Rt,
2982                     (sextloadi32 (am_unscaled32 GPR64sp:$Rn, simm9:$offset)))]>;
2984 // zero and sign extending aliases from generic LDR* mnemonics to LDUR*.
2985 def : InstAlias<"ldrb $Rt, [$Rn, $offset]",
2986                 (LDURBBi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb8:$offset), 0>;
2987 def : InstAlias<"ldrh $Rt, [$Rn, $offset]",
2988                 (LDURHHi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb16:$offset), 0>;
2989 def : InstAlias<"ldrsb $Rt, [$Rn, $offset]",
2990                 (LDURSBWi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb8:$offset), 0>;
2991 def : InstAlias<"ldrsb $Rt, [$Rn, $offset]",
2992                 (LDURSBXi GPR64:$Rt, GPR64sp:$Rn, simm9_offset_fb8:$offset), 0>;
2993 def : InstAlias<"ldrsh $Rt, [$Rn, $offset]",
2994                 (LDURSHWi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb16:$offset), 0>;
2995 def : InstAlias<"ldrsh $Rt, [$Rn, $offset]",
2996                 (LDURSHXi GPR64:$Rt, GPR64sp:$Rn, simm9_offset_fb16:$offset), 0>;
2997 def : InstAlias<"ldrsw $Rt, [$Rn, $offset]",
2998                 (LDURSWi GPR64:$Rt, GPR64sp:$Rn, simm9_offset_fb32:$offset), 0>;
3000 // Pre-fetch.
3001 defm PRFUM : PrefetchUnscaled<0b11, 0, 0b10, "prfum",
3002                   [(AArch64Prefetch imm:$Rt,
3003                                   (am_unscaled64 GPR64sp:$Rn, simm9:$offset))]>;
3005 //---
3006 // (unscaled immediate, unprivileged)
3007 defm LDTRX : LoadUnprivileged<0b11, 0, 0b01, GPR64, "ldtr">;
3008 defm LDTRW : LoadUnprivileged<0b10, 0, 0b01, GPR32, "ldtr">;
3010 defm LDTRH : LoadUnprivileged<0b01, 0, 0b01, GPR32, "ldtrh">;
3011 defm LDTRB : LoadUnprivileged<0b00, 0, 0b01, GPR32, "ldtrb">;
3013 // load sign-extended half-word
3014 defm LDTRSHW : LoadUnprivileged<0b01, 0, 0b11, GPR32, "ldtrsh">;
3015 defm LDTRSHX : LoadUnprivileged<0b01, 0, 0b10, GPR64, "ldtrsh">;
3017 // load sign-extended byte
3018 defm LDTRSBW : LoadUnprivileged<0b00, 0, 0b11, GPR32, "ldtrsb">;
3019 defm LDTRSBX : LoadUnprivileged<0b00, 0, 0b10, GPR64, "ldtrsb">;
3021 // load sign-extended word
3022 defm LDTRSW  : LoadUnprivileged<0b10, 0, 0b10, GPR64, "ldtrsw">;
3024 //---
3025 // (immediate pre-indexed)
3026 def LDRWpre : LoadPreIdx<0b10, 0, 0b01, GPR32z, "ldr">;
3027 def LDRXpre : LoadPreIdx<0b11, 0, 0b01, GPR64z, "ldr">;
3028 def LDRBpre : LoadPreIdx<0b00, 1, 0b01, FPR8Op,  "ldr">;
3029 def LDRHpre : LoadPreIdx<0b01, 1, 0b01, FPR16Op, "ldr">;
3030 def LDRSpre : LoadPreIdx<0b10, 1, 0b01, FPR32Op, "ldr">;
3031 def LDRDpre : LoadPreIdx<0b11, 1, 0b01, FPR64Op, "ldr">;
3032 def LDRQpre : LoadPreIdx<0b00, 1, 0b11, FPR128Op, "ldr">;
3034 // load sign-extended half-word
3035 def LDRSHWpre : LoadPreIdx<0b01, 0, 0b11, GPR32z, "ldrsh">;
3036 def LDRSHXpre : LoadPreIdx<0b01, 0, 0b10, GPR64z, "ldrsh">;
3038 // load sign-extended byte
3039 def LDRSBWpre : LoadPreIdx<0b00, 0, 0b11, GPR32z, "ldrsb">;
3040 def LDRSBXpre : LoadPreIdx<0b00, 0, 0b10, GPR64z, "ldrsb">;
3042 // load zero-extended byte
3043 def LDRBBpre : LoadPreIdx<0b00, 0, 0b01, GPR32z, "ldrb">;
3044 def LDRHHpre : LoadPreIdx<0b01, 0, 0b01, GPR32z, "ldrh">;
3046 // load sign-extended word
3047 def LDRSWpre : LoadPreIdx<0b10, 0, 0b10, GPR64z, "ldrsw">;
3049 //---
3050 // (immediate post-indexed)
3051 def LDRWpost : LoadPostIdx<0b10, 0, 0b01, GPR32z, "ldr">;
3052 def LDRXpost : LoadPostIdx<0b11, 0, 0b01, GPR64z, "ldr">;
3053 def LDRBpost : LoadPostIdx<0b00, 1, 0b01, FPR8Op,  "ldr">;
3054 def LDRHpost : LoadPostIdx<0b01, 1, 0b01, FPR16Op, "ldr">;
3055 def LDRSpost : LoadPostIdx<0b10, 1, 0b01, FPR32Op, "ldr">;
3056 def LDRDpost : LoadPostIdx<0b11, 1, 0b01, FPR64Op, "ldr">;
3057 def LDRQpost : LoadPostIdx<0b00, 1, 0b11, FPR128Op, "ldr">;
3059 // load sign-extended half-word
3060 def LDRSHWpost : LoadPostIdx<0b01, 0, 0b11, GPR32z, "ldrsh">;
3061 def LDRSHXpost : LoadPostIdx<0b01, 0, 0b10, GPR64z, "ldrsh">;
3063 // load sign-extended byte
3064 def LDRSBWpost : LoadPostIdx<0b00, 0, 0b11, GPR32z, "ldrsb">;
3065 def LDRSBXpost : LoadPostIdx<0b00, 0, 0b10, GPR64z, "ldrsb">;
3067 // load zero-extended byte
3068 def LDRBBpost : LoadPostIdx<0b00, 0, 0b01, GPR32z, "ldrb">;
3069 def LDRHHpost : LoadPostIdx<0b01, 0, 0b01, GPR32z, "ldrh">;
3071 // load sign-extended word
3072 def LDRSWpost : LoadPostIdx<0b10, 0, 0b10, GPR64z, "ldrsw">;
3074 //===----------------------------------------------------------------------===//
3075 // Store instructions.
3076 //===----------------------------------------------------------------------===//
3078 // Pair (indexed, offset)
3079 // FIXME: Use dedicated range-checked addressing mode operand here.
3080 defm STPW : StorePairOffset<0b00, 0, GPR32z, simm7s4, "stp">;
3081 defm STPX : StorePairOffset<0b10, 0, GPR64z, simm7s8, "stp">;
3082 defm STPS : StorePairOffset<0b00, 1, FPR32Op, simm7s4, "stp">;
3083 defm STPD : StorePairOffset<0b01, 1, FPR64Op, simm7s8, "stp">;
3084 defm STPQ : StorePairOffset<0b10, 1, FPR128Op, simm7s16, "stp">;
3086 // Pair (pre-indexed)
3087 def STPWpre : StorePairPreIdx<0b00, 0, GPR32z, simm7s4, "stp">;
3088 def STPXpre : StorePairPreIdx<0b10, 0, GPR64z, simm7s8, "stp">;
3089 def STPSpre : StorePairPreIdx<0b00, 1, FPR32Op, simm7s4, "stp">;
3090 def STPDpre : StorePairPreIdx<0b01, 1, FPR64Op, simm7s8, "stp">;
3091 def STPQpre : StorePairPreIdx<0b10, 1, FPR128Op, simm7s16, "stp">;
3093 // Pair (pre-indexed)
3094 def STPWpost : StorePairPostIdx<0b00, 0, GPR32z, simm7s4, "stp">;
3095 def STPXpost : StorePairPostIdx<0b10, 0, GPR64z, simm7s8, "stp">;
3096 def STPSpost : StorePairPostIdx<0b00, 1, FPR32Op, simm7s4, "stp">;
3097 def STPDpost : StorePairPostIdx<0b01, 1, FPR64Op, simm7s8, "stp">;
3098 def STPQpost : StorePairPostIdx<0b10, 1, FPR128Op, simm7s16, "stp">;
3100 // Pair (no allocate)
3101 defm STNPW : StorePairNoAlloc<0b00, 0, GPR32z, simm7s4, "stnp">;
3102 defm STNPX : StorePairNoAlloc<0b10, 0, GPR64z, simm7s8, "stnp">;
3103 defm STNPS : StorePairNoAlloc<0b00, 1, FPR32Op, simm7s4, "stnp">;
3104 defm STNPD : StorePairNoAlloc<0b01, 1, FPR64Op, simm7s8, "stnp">;
3105 defm STNPQ : StorePairNoAlloc<0b10, 1, FPR128Op, simm7s16, "stnp">;
3107 def : Pat<(AArch64stp GPR64z:$Rt, GPR64z:$Rt2, (am_indexed7s64 GPR64sp:$Rn, simm7s8:$offset)),
3108           (STPXi GPR64z:$Rt, GPR64z:$Rt2, GPR64sp:$Rn, simm7s8:$offset)>;
3110 def : Pat<(AArch64stnp FPR128:$Rt, FPR128:$Rt2, (am_indexed7s128 GPR64sp:$Rn, simm7s16:$offset)),
3111           (STNPQi FPR128:$Rt, FPR128:$Rt2, GPR64sp:$Rn, simm7s16:$offset)>;
3114 //---
3115 // (Register offset)
3117 // Integer
3118 defm STRBB : Store8RO< 0b00, 0, 0b00, GPR32, "strb", i32, truncstorei8>;
3119 defm STRHH : Store16RO<0b01, 0, 0b00, GPR32, "strh", i32, truncstorei16>;
3120 defm STRW  : Store32RO<0b10, 0, 0b00, GPR32, "str",  i32, store>;
3121 defm STRX  : Store64RO<0b11, 0, 0b00, GPR64, "str",  i64, store>;
3124 // Floating-point
3125 defm STRB : Store8RO< 0b00,  1, 0b00, FPR8Op,   "str", untyped, store>;
3126 defm STRH : Store16RO<0b01,  1, 0b00, FPR16Op,  "str", f16,     store>;
3127 defm STRS : Store32RO<0b10,  1, 0b00, FPR32Op,  "str", f32,     store>;
3128 defm STRD : Store64RO<0b11,  1, 0b00, FPR64Op,  "str", f64,     store>;
3129 defm STRQ : Store128RO<0b00, 1, 0b10, FPR128Op, "str", f128,    store>;
3131 let Predicates = [UseSTRQro], AddedComplexity = 10 in {
3132   def : Pat<(store (f128 FPR128:$Rt),
3133                         (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
3134                                         ro_Wextend128:$extend)),
3135             (STRQroW FPR128:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend)>;
3136   def : Pat<(store (f128 FPR128:$Rt),
3137                         (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
3138                                         ro_Xextend128:$extend)),
3139             (STRQroX FPR128:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Wextend128:$extend)>;
3142 multiclass TruncStoreFrom64ROPat<ROAddrMode ro, SDPatternOperator storeop,
3143                                  Instruction STRW, Instruction STRX> {
3145   def : Pat<(storeop GPR64:$Rt,
3146                      (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)),
3147             (STRW (EXTRACT_SUBREG GPR64:$Rt, sub_32),
3148                   GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)>;
3150   def : Pat<(storeop GPR64:$Rt,
3151                      (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)),
3152             (STRX (EXTRACT_SUBREG GPR64:$Rt, sub_32),
3153                   GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)>;
3156 let AddedComplexity = 10 in {
3157   // truncstore i64
3158   defm : TruncStoreFrom64ROPat<ro8,  truncstorei8,  STRBBroW, STRBBroX>;
3159   defm : TruncStoreFrom64ROPat<ro16, truncstorei16, STRHHroW, STRHHroX>;
3160   defm : TruncStoreFrom64ROPat<ro32, truncstorei32, STRWroW,  STRWroX>;
3163 multiclass VecROStorePat<ROAddrMode ro, ValueType VecTy, RegisterClass FPR,
3164                          Instruction STRW, Instruction STRX> {
3165   def : Pat<(store (VecTy FPR:$Rt),
3166                    (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)),
3167             (STRW FPR:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)>;
3169   def : Pat<(store (VecTy FPR:$Rt),
3170                    (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)),
3171             (STRX FPR:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)>;
3174 let AddedComplexity = 10 in {
3175 // Match all store 64 bits width whose type is compatible with FPR64
3176 let Predicates = [IsLE] in {
3177   // We must use ST1 to store vectors in big-endian.
3178   defm : VecROStorePat<ro64, v2i32, FPR64, STRDroW, STRDroX>;
3179   defm : VecROStorePat<ro64, v2f32, FPR64, STRDroW, STRDroX>;
3180   defm : VecROStorePat<ro64, v4i16, FPR64, STRDroW, STRDroX>;
3181   defm : VecROStorePat<ro64, v8i8, FPR64, STRDroW, STRDroX>;
3182   defm : VecROStorePat<ro64, v4f16, FPR64, STRDroW, STRDroX>;
3183   defm : VecROStorePat<ro64, v4bf16, FPR64, STRDroW, STRDroX>;
3186 defm : VecROStorePat<ro64, v1i64, FPR64, STRDroW, STRDroX>;
3187 defm : VecROStorePat<ro64, v1f64, FPR64, STRDroW, STRDroX>;
3189 // Match all store 128 bits width whose type is compatible with FPR128
3190 let Predicates = [IsLE, UseSTRQro] in {
3191   // We must use ST1 to store vectors in big-endian.
3192   defm : VecROStorePat<ro128, v2i64, FPR128, STRQroW, STRQroX>;
3193   defm : VecROStorePat<ro128, v2f64, FPR128, STRQroW, STRQroX>;
3194   defm : VecROStorePat<ro128, v4i32, FPR128, STRQroW, STRQroX>;
3195   defm : VecROStorePat<ro128, v4f32, FPR128, STRQroW, STRQroX>;
3196   defm : VecROStorePat<ro128, v8i16, FPR128, STRQroW, STRQroX>;
3197   defm : VecROStorePat<ro128, v16i8, FPR128, STRQroW, STRQroX>;
3198   defm : VecROStorePat<ro128, v8f16, FPR128, STRQroW, STRQroX>;
3199   defm : VecROStorePat<ro128, v8bf16, FPR128, STRQroW, STRQroX>;
3201 } // AddedComplexity = 10
3203 // Match stores from lane 0 to the appropriate subreg's store.
3204 multiclass VecROStoreLane0Pat<ROAddrMode ro, SDPatternOperator storeop,
3205                               ValueType VecTy, ValueType STy,
3206                               SubRegIndex SubRegIdx,
3207                               Instruction STRW, Instruction STRX> {
3209   def : Pat<(storeop (STy (vector_extract (VecTy VecListOne128:$Vt), 0)),
3210                      (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)),
3211             (STRW (EXTRACT_SUBREG VecListOne128:$Vt, SubRegIdx),
3212                   GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)>;
3214   def : Pat<(storeop (STy (vector_extract (VecTy VecListOne128:$Vt), 0)),
3215                      (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)),
3216             (STRX (EXTRACT_SUBREG VecListOne128:$Vt, SubRegIdx),
3217                   GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)>;
3220 let AddedComplexity = 19 in {
3221   defm : VecROStoreLane0Pat<ro16, truncstorei16, v8i16, i32, hsub, STRHroW, STRHroX>;
3222   defm : VecROStoreLane0Pat<ro16,         store, v8f16, f16, hsub, STRHroW, STRHroX>;
3223   defm : VecROStoreLane0Pat<ro32,         store, v4i32, i32, ssub, STRSroW, STRSroX>;
3224   defm : VecROStoreLane0Pat<ro32,         store, v4f32, f32, ssub, STRSroW, STRSroX>;
3225   defm : VecROStoreLane0Pat<ro64,         store, v2i64, i64, dsub, STRDroW, STRDroX>;
3226   defm : VecROStoreLane0Pat<ro64,         store, v2f64, f64, dsub, STRDroW, STRDroX>;
3229 //---
3230 // (unsigned immediate)
3231 defm STRX : StoreUIz<0b11, 0, 0b00, GPR64z, uimm12s8, "str",
3232                    [(store GPR64z:$Rt,
3233                             (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))]>;
3234 defm STRW : StoreUIz<0b10, 0, 0b00, GPR32z, uimm12s4, "str",
3235                     [(store GPR32z:$Rt,
3236                             (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))]>;
3237 defm STRB : StoreUI<0b00, 1, 0b00, FPR8Op, uimm12s1, "str",
3238                     [(store FPR8Op:$Rt,
3239                             (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))]>;
3240 defm STRH : StoreUI<0b01, 1, 0b00, FPR16Op, uimm12s2, "str",
3241                     [(store (f16 FPR16Op:$Rt),
3242                             (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))]>;
3243 defm STRS : StoreUI<0b10, 1, 0b00, FPR32Op, uimm12s4, "str",
3244                     [(store (f32 FPR32Op:$Rt),
3245                             (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))]>;
3246 defm STRD : StoreUI<0b11, 1, 0b00, FPR64Op, uimm12s8, "str",
3247                     [(store (f64 FPR64Op:$Rt),
3248                             (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))]>;
3249 defm STRQ : StoreUI<0b00, 1, 0b10, FPR128Op, uimm12s16, "str", []>;
3251 defm STRHH : StoreUIz<0b01, 0, 0b00, GPR32z, uimm12s2, "strh",
3252                      [(truncstorei16 GPR32z:$Rt,
3253                                      (am_indexed16 GPR64sp:$Rn,
3254                                                    uimm12s2:$offset))]>;
3255 defm STRBB : StoreUIz<0b00, 0, 0b00, GPR32z, uimm12s1,  "strb",
3256                      [(truncstorei8 GPR32z:$Rt,
3257                                     (am_indexed8 GPR64sp:$Rn,
3258                                                  uimm12s1:$offset))]>;
3260 // bf16 store pattern
3261 def : Pat<(store (bf16 FPR16Op:$Rt),
3262                  (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset)),
3263           (STRHui FPR16:$Rt, GPR64sp:$Rn, uimm12s2:$offset)>;
3265 let AddedComplexity = 10 in {
3267 // Match all store 64 bits width whose type is compatible with FPR64
3268 def : Pat<(store (v1i64 FPR64:$Rt),
3269                  (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)),
3270           (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>;
3271 def : Pat<(store (v1f64 FPR64:$Rt),
3272                  (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)),
3273           (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>;
3275 let Predicates = [IsLE] in {
3276   // We must use ST1 to store vectors in big-endian.
3277   def : Pat<(store (v2f32 FPR64:$Rt),
3278                    (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)),
3279             (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>;
3280   def : Pat<(store (v8i8 FPR64:$Rt),
3281                    (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)),
3282             (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>;
3283   def : Pat<(store (v4i16 FPR64:$Rt),
3284                    (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)),
3285             (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>;
3286   def : Pat<(store (v2i32 FPR64:$Rt),
3287                    (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)),
3288             (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>;
3289   def : Pat<(store (v4f16 FPR64:$Rt),
3290                    (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)),
3291             (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>;
3292   def : Pat<(store (v4bf16 FPR64:$Rt),
3293                    (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)),
3294             (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>;
3297 // Match all store 128 bits width whose type is compatible with FPR128
3298 def : Pat<(store (f128  FPR128:$Rt),
3299                  (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)),
3300           (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>;
3302 let Predicates = [IsLE] in {
3303   // We must use ST1 to store vectors in big-endian.
3304   def : Pat<(store (v4f32 FPR128:$Rt),
3305                    (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)),
3306             (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>;
3307   def : Pat<(store (v2f64 FPR128:$Rt),
3308                    (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)),
3309             (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>;
3310   def : Pat<(store (v16i8 FPR128:$Rt),
3311                    (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)),
3312             (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>;
3313   def : Pat<(store (v8i16 FPR128:$Rt),
3314                    (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)),
3315             (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>;
3316   def : Pat<(store (v4i32 FPR128:$Rt),
3317                    (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)),
3318             (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>;
3319   def : Pat<(store (v2i64 FPR128:$Rt),
3320                    (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)),
3321             (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>;
3322   def : Pat<(store (v8f16 FPR128:$Rt),
3323                    (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)),
3324             (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>;
3325   def : Pat<(store (v8bf16 FPR128:$Rt),
3326                    (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)),
3327             (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>;
3330 // truncstore i64
3331 def : Pat<(truncstorei32 GPR64:$Rt,
3332                          (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset)),
3333   (STRWui (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$Rn, uimm12s4:$offset)>;
3334 def : Pat<(truncstorei16 GPR64:$Rt,
3335                          (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset)),
3336   (STRHHui (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$Rn, uimm12s2:$offset)>;
3337 def : Pat<(truncstorei8 GPR64:$Rt, (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset)),
3338   (STRBBui (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$Rn, uimm12s1:$offset)>;
3340 } // AddedComplexity = 10
3342 // Match stores from lane 0 to the appropriate subreg's store.
3343 multiclass VecStoreLane0Pat<ComplexPattern UIAddrMode, SDPatternOperator storeop,
3344                             ValueType VTy, ValueType STy,
3345                             SubRegIndex SubRegIdx, Operand IndexType,
3346                             Instruction STR> {
3347   def : Pat<(storeop (STy (vector_extract (VTy VecListOne128:$Vt), 0)),
3348                      (UIAddrMode GPR64sp:$Rn, IndexType:$offset)),
3349             (STR (EXTRACT_SUBREG VecListOne128:$Vt, SubRegIdx),
3350                  GPR64sp:$Rn, IndexType:$offset)>;
3353 let AddedComplexity = 19 in {
3354   defm : VecStoreLane0Pat<am_indexed16, truncstorei16, v8i16, i32, hsub, uimm12s2, STRHui>;
3355   defm : VecStoreLane0Pat<am_indexed16,         store, v8f16, f16, hsub, uimm12s2, STRHui>;
3356   defm : VecStoreLane0Pat<am_indexed32,         store, v4i32, i32, ssub, uimm12s4, STRSui>;
3357   defm : VecStoreLane0Pat<am_indexed32,         store, v4f32, f32, ssub, uimm12s4, STRSui>;
3358   defm : VecStoreLane0Pat<am_indexed64,         store, v2i64, i64, dsub, uimm12s8, STRDui>;
3359   defm : VecStoreLane0Pat<am_indexed64,         store, v2f64, f64, dsub, uimm12s8, STRDui>;
3362 //---
3363 // (unscaled immediate)
3364 defm STURX : StoreUnscaled<0b11, 0, 0b00, GPR64z, "stur",
3365                          [(store GPR64z:$Rt,
3366                                  (am_unscaled64 GPR64sp:$Rn, simm9:$offset))]>;
3367 defm STURW : StoreUnscaled<0b10, 0, 0b00, GPR32z, "stur",
3368                          [(store GPR32z:$Rt,
3369                                  (am_unscaled32 GPR64sp:$Rn, simm9:$offset))]>;
3370 defm STURB : StoreUnscaled<0b00, 1, 0b00, FPR8Op, "stur",
3371                          [(store FPR8Op:$Rt,
3372                                  (am_unscaled8 GPR64sp:$Rn, simm9:$offset))]>;
3373 defm STURH : StoreUnscaled<0b01, 1, 0b00, FPR16Op, "stur",
3374                          [(store (f16 FPR16Op:$Rt),
3375                                  (am_unscaled16 GPR64sp:$Rn, simm9:$offset))]>;
3376 defm STURS : StoreUnscaled<0b10, 1, 0b00, FPR32Op, "stur",
3377                          [(store (f32 FPR32Op:$Rt),
3378                                  (am_unscaled32 GPR64sp:$Rn, simm9:$offset))]>;
3379 defm STURD : StoreUnscaled<0b11, 1, 0b00, FPR64Op, "stur",
3380                          [(store (f64 FPR64Op:$Rt),
3381                                  (am_unscaled64 GPR64sp:$Rn, simm9:$offset))]>;
3382 defm STURQ : StoreUnscaled<0b00, 1, 0b10, FPR128Op, "stur",
3383                          [(store (f128 FPR128Op:$Rt),
3384                                  (am_unscaled128 GPR64sp:$Rn, simm9:$offset))]>;
3385 defm STURHH : StoreUnscaled<0b01, 0, 0b00, GPR32z, "sturh",
3386                          [(truncstorei16 GPR32z:$Rt,
3387                                  (am_unscaled16 GPR64sp:$Rn, simm9:$offset))]>;
3388 defm STURBB : StoreUnscaled<0b00, 0, 0b00, GPR32z, "sturb",
3389                          [(truncstorei8 GPR32z:$Rt,
3390                                   (am_unscaled8 GPR64sp:$Rn, simm9:$offset))]>;
3392 // Armv8.4 Weaker Release Consistency enhancements
3393 //         LDAPR & STLR with Immediate Offset instructions
3394 let Predicates = [HasRCPC_IMMO] in {
3395 defm STLURB     : BaseStoreUnscaleV84<"stlurb",  0b00, 0b00, GPR32>;
3396 defm STLURH     : BaseStoreUnscaleV84<"stlurh",  0b01, 0b00, GPR32>;
3397 defm STLURW     : BaseStoreUnscaleV84<"stlur",   0b10, 0b00, GPR32>;
3398 defm STLURX     : BaseStoreUnscaleV84<"stlur",   0b11, 0b00, GPR64>;
3399 defm LDAPURB    : BaseLoadUnscaleV84<"ldapurb",  0b00, 0b01, GPR32>;
3400 defm LDAPURSBW  : BaseLoadUnscaleV84<"ldapursb", 0b00, 0b11, GPR32>;
3401 defm LDAPURSBX  : BaseLoadUnscaleV84<"ldapursb", 0b00, 0b10, GPR64>;
3402 defm LDAPURH    : BaseLoadUnscaleV84<"ldapurh",  0b01, 0b01, GPR32>;
3403 defm LDAPURSHW  : BaseLoadUnscaleV84<"ldapursh", 0b01, 0b11, GPR32>;
3404 defm LDAPURSHX  : BaseLoadUnscaleV84<"ldapursh", 0b01, 0b10, GPR64>;
3405 defm LDAPUR     : BaseLoadUnscaleV84<"ldapur",   0b10, 0b01, GPR32>;
3406 defm LDAPURSW   : BaseLoadUnscaleV84<"ldapursw", 0b10, 0b10, GPR64>;
3407 defm LDAPURX    : BaseLoadUnscaleV84<"ldapur",   0b11, 0b01, GPR64>;
3410 // Match all store 64 bits width whose type is compatible with FPR64
3411 def : Pat<(store (v1f64 FPR64:$Rt), (am_unscaled64 GPR64sp:$Rn, simm9:$offset)),
3412           (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>;
3413 def : Pat<(store (v1i64 FPR64:$Rt), (am_unscaled64 GPR64sp:$Rn, simm9:$offset)),
3414           (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>;
3416 let AddedComplexity = 10 in {
3418 let Predicates = [IsLE] in {
3419   // We must use ST1 to store vectors in big-endian.
3420   def : Pat<(store (v2f32 FPR64:$Rt),
3421                    (am_unscaled64 GPR64sp:$Rn, simm9:$offset)),
3422             (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>;
3423   def : Pat<(store (v8i8 FPR64:$Rt),
3424                    (am_unscaled64 GPR64sp:$Rn, simm9:$offset)),
3425             (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>;
3426   def : Pat<(store (v4i16 FPR64:$Rt),
3427                    (am_unscaled64 GPR64sp:$Rn, simm9:$offset)),
3428             (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>;
3429   def : Pat<(store (v2i32 FPR64:$Rt),
3430                    (am_unscaled64 GPR64sp:$Rn, simm9:$offset)),
3431             (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>;
3432   def : Pat<(store (v4f16 FPR64:$Rt),
3433                    (am_unscaled64 GPR64sp:$Rn, simm9:$offset)),
3434             (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>;
3435   def : Pat<(store (v4bf16 FPR64:$Rt),
3436                    (am_unscaled64 GPR64sp:$Rn, simm9:$offset)),
3437             (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>;
3440 // Match all store 128 bits width whose type is compatible with FPR128
3441 def : Pat<(store (f128 FPR128:$Rt), (am_unscaled128 GPR64sp:$Rn, simm9:$offset)),
3442           (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>;
3444 let Predicates = [IsLE] in {
3445   // We must use ST1 to store vectors in big-endian.
3446   def : Pat<(store (v4f32 FPR128:$Rt),
3447                    (am_unscaled128 GPR64sp:$Rn, simm9:$offset)),
3448             (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>;
3449   def : Pat<(store (v2f64 FPR128:$Rt),
3450                    (am_unscaled128 GPR64sp:$Rn, simm9:$offset)),
3451             (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>;
3452   def : Pat<(store (v16i8 FPR128:$Rt),
3453                    (am_unscaled128 GPR64sp:$Rn, simm9:$offset)),
3454             (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>;
3455   def : Pat<(store (v8i16 FPR128:$Rt),
3456                    (am_unscaled128 GPR64sp:$Rn, simm9:$offset)),
3457             (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>;
3458   def : Pat<(store (v4i32 FPR128:$Rt),
3459                    (am_unscaled128 GPR64sp:$Rn, simm9:$offset)),
3460             (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>;
3461   def : Pat<(store (v2i64 FPR128:$Rt),
3462                    (am_unscaled128 GPR64sp:$Rn, simm9:$offset)),
3463             (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>;
3464   def : Pat<(store (v2f64 FPR128:$Rt),
3465                    (am_unscaled128 GPR64sp:$Rn, simm9:$offset)),
3466             (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>;
3467   def : Pat<(store (v8f16 FPR128:$Rt),
3468                    (am_unscaled128 GPR64sp:$Rn, simm9:$offset)),
3469             (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>;
3470   def : Pat<(store (v8bf16 FPR128:$Rt),
3471                    (am_unscaled128 GPR64sp:$Rn, simm9:$offset)),
3472             (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>;
3475 } // AddedComplexity = 10
3477 // unscaled i64 truncating stores
3478 def : Pat<(truncstorei32 GPR64:$Rt, (am_unscaled32 GPR64sp:$Rn, simm9:$offset)),
3479   (STURWi (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$Rn, simm9:$offset)>;
3480 def : Pat<(truncstorei16 GPR64:$Rt, (am_unscaled16 GPR64sp:$Rn, simm9:$offset)),
3481   (STURHHi (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$Rn, simm9:$offset)>;
3482 def : Pat<(truncstorei8 GPR64:$Rt, (am_unscaled8 GPR64sp:$Rn, simm9:$offset)),
3483   (STURBBi (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$Rn, simm9:$offset)>;
3485 // Match stores from lane 0 to the appropriate subreg's store.
3486 multiclass VecStoreULane0Pat<SDPatternOperator StoreOp,
3487                              ValueType VTy, ValueType STy,
3488                              SubRegIndex SubRegIdx, Instruction STR> {
3489   defm : VecStoreLane0Pat<am_unscaled128, StoreOp, VTy, STy, SubRegIdx, simm9, STR>;
3492 let AddedComplexity = 19 in {
3493   defm : VecStoreULane0Pat<truncstorei16, v8i16, i32, hsub, STURHi>;
3494   defm : VecStoreULane0Pat<store,         v8f16, f16, hsub, STURHi>;
3495   defm : VecStoreULane0Pat<store,         v4i32, i32, ssub, STURSi>;
3496   defm : VecStoreULane0Pat<store,         v4f32, f32, ssub, STURSi>;
3497   defm : VecStoreULane0Pat<store,         v2i64, i64, dsub, STURDi>;
3498   defm : VecStoreULane0Pat<store,         v2f64, f64, dsub, STURDi>;
3501 //---
3502 // STR mnemonics fall back to STUR for negative or unaligned offsets.
3503 def : InstAlias<"str $Rt, [$Rn, $offset]",
3504                 (STURXi GPR64:$Rt, GPR64sp:$Rn, simm9_offset_fb64:$offset), 0>;
3505 def : InstAlias<"str $Rt, [$Rn, $offset]",
3506                 (STURWi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb32:$offset), 0>;
3507 def : InstAlias<"str $Rt, [$Rn, $offset]",
3508                 (STURBi FPR8Op:$Rt, GPR64sp:$Rn, simm9_offset_fb8:$offset), 0>;
3509 def : InstAlias<"str $Rt, [$Rn, $offset]",
3510                 (STURHi FPR16Op:$Rt, GPR64sp:$Rn, simm9_offset_fb16:$offset), 0>;
3511 def : InstAlias<"str $Rt, [$Rn, $offset]",
3512                 (STURSi FPR32Op:$Rt, GPR64sp:$Rn, simm9_offset_fb32:$offset), 0>;
3513 def : InstAlias<"str $Rt, [$Rn, $offset]",
3514                 (STURDi FPR64Op:$Rt, GPR64sp:$Rn, simm9_offset_fb64:$offset), 0>;
3515 def : InstAlias<"str $Rt, [$Rn, $offset]",
3516                 (STURQi FPR128Op:$Rt, GPR64sp:$Rn, simm9_offset_fb128:$offset), 0>;
3518 def : InstAlias<"strb $Rt, [$Rn, $offset]",
3519                 (STURBBi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb8:$offset), 0>;
3520 def : InstAlias<"strh $Rt, [$Rn, $offset]",
3521                 (STURHHi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb16:$offset), 0>;
3523 //---
3524 // (unscaled immediate, unprivileged)
3525 defm STTRW : StoreUnprivileged<0b10, 0, 0b00, GPR32, "sttr">;
3526 defm STTRX : StoreUnprivileged<0b11, 0, 0b00, GPR64, "sttr">;
3528 defm STTRH : StoreUnprivileged<0b01, 0, 0b00, GPR32, "sttrh">;
3529 defm STTRB : StoreUnprivileged<0b00, 0, 0b00, GPR32, "sttrb">;
3531 //---
3532 // (immediate pre-indexed)
3533 def STRWpre : StorePreIdx<0b10, 0, 0b00, GPR32z, "str",  pre_store, i32>;
3534 def STRXpre : StorePreIdx<0b11, 0, 0b00, GPR64z, "str",  pre_store, i64>;
3535 def STRBpre : StorePreIdx<0b00, 1, 0b00, FPR8Op,  "str",  pre_store, untyped>;
3536 def STRHpre : StorePreIdx<0b01, 1, 0b00, FPR16Op, "str",  pre_store, f16>;
3537 def STRSpre : StorePreIdx<0b10, 1, 0b00, FPR32Op, "str",  pre_store, f32>;
3538 def STRDpre : StorePreIdx<0b11, 1, 0b00, FPR64Op, "str",  pre_store, f64>;
3539 def STRQpre : StorePreIdx<0b00, 1, 0b10, FPR128Op, "str", pre_store, f128>;
3541 def STRBBpre : StorePreIdx<0b00, 0, 0b00, GPR32z, "strb", pre_truncsti8,  i32>;
3542 def STRHHpre : StorePreIdx<0b01, 0, 0b00, GPR32z, "strh", pre_truncsti16, i32>;
3544 // truncstore i64
3545 def : Pat<(pre_truncsti32 GPR64:$Rt, GPR64sp:$addr, simm9:$off),
3546   (STRWpre (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr,
3547            simm9:$off)>;
3548 def : Pat<(pre_truncsti16 GPR64:$Rt, GPR64sp:$addr, simm9:$off),
3549   (STRHHpre (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr,
3550             simm9:$off)>;
3551 def : Pat<(pre_truncsti8 GPR64:$Rt, GPR64sp:$addr, simm9:$off),
3552   (STRBBpre (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr,
3553             simm9:$off)>;
3555 def : Pat<(pre_store (v8i8 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
3556           (STRDpre FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
3557 def : Pat<(pre_store (v4i16 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
3558           (STRDpre FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
3559 def : Pat<(pre_store (v2i32 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
3560           (STRDpre FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
3561 def : Pat<(pre_store (v2f32 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
3562           (STRDpre FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
3563 def : Pat<(pre_store (v1i64 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
3564           (STRDpre FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
3565 def : Pat<(pre_store (v1f64 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
3566           (STRDpre FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
3567 def : Pat<(pre_store (v4f16 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
3568           (STRDpre FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
3570 def : Pat<(pre_store (v16i8 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
3571           (STRQpre FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
3572 def : Pat<(pre_store (v8i16 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
3573           (STRQpre FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
3574 def : Pat<(pre_store (v4i32 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
3575           (STRQpre FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
3576 def : Pat<(pre_store (v4f32 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
3577           (STRQpre FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
3578 def : Pat<(pre_store (v2i64 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
3579           (STRQpre FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
3580 def : Pat<(pre_store (v2f64 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
3581           (STRQpre FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
3582 def : Pat<(pre_store (v8f16 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
3583           (STRQpre FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
3585 //---
3586 // (immediate post-indexed)
3587 def STRWpost : StorePostIdx<0b10, 0, 0b00, GPR32z,  "str", post_store, i32>;
3588 def STRXpost : StorePostIdx<0b11, 0, 0b00, GPR64z,  "str", post_store, i64>;
3589 def STRBpost : StorePostIdx<0b00, 1, 0b00, FPR8Op,   "str", post_store, untyped>;
3590 def STRHpost : StorePostIdx<0b01, 1, 0b00, FPR16Op,  "str", post_store, f16>;
3591 def STRSpost : StorePostIdx<0b10, 1, 0b00, FPR32Op,  "str", post_store, f32>;
3592 def STRDpost : StorePostIdx<0b11, 1, 0b00, FPR64Op,  "str", post_store, f64>;
3593 def STRQpost : StorePostIdx<0b00, 1, 0b10, FPR128Op, "str", post_store, f128>;
3595 def STRBBpost : StorePostIdx<0b00, 0, 0b00, GPR32z, "strb", post_truncsti8, i32>;
3596 def STRHHpost : StorePostIdx<0b01, 0, 0b00, GPR32z, "strh", post_truncsti16, i32>;
3598 // truncstore i64
3599 def : Pat<(post_truncsti32 GPR64:$Rt, GPR64sp:$addr, simm9:$off),
3600   (STRWpost (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr,
3601             simm9:$off)>;
3602 def : Pat<(post_truncsti16 GPR64:$Rt, GPR64sp:$addr, simm9:$off),
3603   (STRHHpost (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr,
3604              simm9:$off)>;
3605 def : Pat<(post_truncsti8 GPR64:$Rt, GPR64sp:$addr, simm9:$off),
3606   (STRBBpost (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr,
3607              simm9:$off)>;
3609 def : Pat<(post_store (bf16 FPR16:$Rt), GPR64sp:$addr, simm9:$off),
3610           (STRHpost FPR16:$Rt, GPR64sp:$addr, simm9:$off)>;
3612 def : Pat<(post_store (v8i8 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
3613           (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
3614 def : Pat<(post_store (v4i16 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
3615           (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
3616 def : Pat<(post_store (v2i32 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
3617           (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
3618 def : Pat<(post_store (v2f32 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
3619           (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
3620 def : Pat<(post_store (v1i64 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
3621           (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
3622 def : Pat<(post_store (v1f64 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
3623           (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
3624 def : Pat<(post_store (v4f16 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
3625           (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
3626 def : Pat<(post_store (v4bf16 FPR64:$Rt), GPR64sp:$addr, simm9:$off),
3627           (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>;
3629 def : Pat<(post_store (v16i8 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
3630           (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
3631 def : Pat<(post_store (v8i16 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
3632           (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
3633 def : Pat<(post_store (v4i32 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
3634           (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
3635 def : Pat<(post_store (v4f32 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
3636           (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
3637 def : Pat<(post_store (v2i64 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
3638           (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
3639 def : Pat<(post_store (v2f64 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
3640           (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
3641 def : Pat<(post_store (v8f16 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
3642           (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
3643 def : Pat<(post_store (v8bf16 FPR128:$Rt), GPR64sp:$addr, simm9:$off),
3644           (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>;
3646 //===----------------------------------------------------------------------===//
3647 // Load/store exclusive instructions.
3648 //===----------------------------------------------------------------------===//
3650 def LDARW  : LoadAcquire   <0b10, 1, 1, 0, 1, GPR32, "ldar">;
3651 def LDARX  : LoadAcquire   <0b11, 1, 1, 0, 1, GPR64, "ldar">;
3652 def LDARB  : LoadAcquire   <0b00, 1, 1, 0, 1, GPR32, "ldarb">;
3653 def LDARH  : LoadAcquire   <0b01, 1, 1, 0, 1, GPR32, "ldarh">;
3655 def LDAXRW : LoadExclusive <0b10, 0, 1, 0, 1, GPR32, "ldaxr">;
3656 def LDAXRX : LoadExclusive <0b11, 0, 1, 0, 1, GPR64, "ldaxr">;
3657 def LDAXRB : LoadExclusive <0b00, 0, 1, 0, 1, GPR32, "ldaxrb">;
3658 def LDAXRH : LoadExclusive <0b01, 0, 1, 0, 1, GPR32, "ldaxrh">;
3660 def LDXRW  : LoadExclusive <0b10, 0, 1, 0, 0, GPR32, "ldxr">;
3661 def LDXRX  : LoadExclusive <0b11, 0, 1, 0, 0, GPR64, "ldxr">;
3662 def LDXRB  : LoadExclusive <0b00, 0, 1, 0, 0, GPR32, "ldxrb">;
3663 def LDXRH  : LoadExclusive <0b01, 0, 1, 0, 0, GPR32, "ldxrh">;
3665 def STLRW  : StoreRelease  <0b10, 1, 0, 0, 1, GPR32, "stlr">;
3666 def STLRX  : StoreRelease  <0b11, 1, 0, 0, 1, GPR64, "stlr">;
3667 def STLRB  : StoreRelease  <0b00, 1, 0, 0, 1, GPR32, "stlrb">;
3668 def STLRH  : StoreRelease  <0b01, 1, 0, 0, 1, GPR32, "stlrh">;
3670 def STLXRW : StoreExclusive<0b10, 0, 0, 0, 1, GPR32, "stlxr">;
3671 def STLXRX : StoreExclusive<0b11, 0, 0, 0, 1, GPR64, "stlxr">;
3672 def STLXRB : StoreExclusive<0b00, 0, 0, 0, 1, GPR32, "stlxrb">;
3673 def STLXRH : StoreExclusive<0b01, 0, 0, 0, 1, GPR32, "stlxrh">;
3675 def STXRW  : StoreExclusive<0b10, 0, 0, 0, 0, GPR32, "stxr">;
3676 def STXRX  : StoreExclusive<0b11, 0, 0, 0, 0, GPR64, "stxr">;
3677 def STXRB  : StoreExclusive<0b00, 0, 0, 0, 0, GPR32, "stxrb">;
3678 def STXRH  : StoreExclusive<0b01, 0, 0, 0, 0, GPR32, "stxrh">;
3680 def LDAXPW : LoadExclusivePair<0b10, 0, 1, 1, 1, GPR32, "ldaxp">;
3681 def LDAXPX : LoadExclusivePair<0b11, 0, 1, 1, 1, GPR64, "ldaxp">;
3683 def LDXPW  : LoadExclusivePair<0b10, 0, 1, 1, 0, GPR32, "ldxp">;
3684 def LDXPX  : LoadExclusivePair<0b11, 0, 1, 1, 0, GPR64, "ldxp">;
3686 def STLXPW : StoreExclusivePair<0b10, 0, 0, 1, 1, GPR32, "stlxp">;
3687 def STLXPX : StoreExclusivePair<0b11, 0, 0, 1, 1, GPR64, "stlxp">;
3689 def STXPW  : StoreExclusivePair<0b10, 0, 0, 1, 0, GPR32, "stxp">;
3690 def STXPX  : StoreExclusivePair<0b11, 0, 0, 1, 0, GPR64, "stxp">;
3692 let Predicates = [HasLOR] in {
3693   // v8.1a "Limited Order Region" extension load-acquire instructions
3694   def LDLARW  : LoadAcquire   <0b10, 1, 1, 0, 0, GPR32, "ldlar">;
3695   def LDLARX  : LoadAcquire   <0b11, 1, 1, 0, 0, GPR64, "ldlar">;
3696   def LDLARB  : LoadAcquire   <0b00, 1, 1, 0, 0, GPR32, "ldlarb">;
3697   def LDLARH  : LoadAcquire   <0b01, 1, 1, 0, 0, GPR32, "ldlarh">;
3699   // v8.1a "Limited Order Region" extension store-release instructions
3700   def STLLRW  : StoreRelease   <0b10, 1, 0, 0, 0, GPR32, "stllr">;
3701   def STLLRX  : StoreRelease   <0b11, 1, 0, 0, 0, GPR64, "stllr">;
3702   def STLLRB  : StoreRelease   <0b00, 1, 0, 0, 0, GPR32, "stllrb">;
3703   def STLLRH  : StoreRelease   <0b01, 1, 0, 0, 0, GPR32, "stllrh">;
3706 //===----------------------------------------------------------------------===//
3707 // Scaled floating point to integer conversion instructions.
3708 //===----------------------------------------------------------------------===//
3710 defm FCVTAS : FPToIntegerUnscaled<0b00, 0b100, "fcvtas", int_aarch64_neon_fcvtas>;
3711 defm FCVTAU : FPToIntegerUnscaled<0b00, 0b101, "fcvtau", int_aarch64_neon_fcvtau>;
3712 defm FCVTMS : FPToIntegerUnscaled<0b10, 0b000, "fcvtms", int_aarch64_neon_fcvtms>;
3713 defm FCVTMU : FPToIntegerUnscaled<0b10, 0b001, "fcvtmu", int_aarch64_neon_fcvtmu>;
3714 defm FCVTNS : FPToIntegerUnscaled<0b00, 0b000, "fcvtns", int_aarch64_neon_fcvtns>;
3715 defm FCVTNU : FPToIntegerUnscaled<0b00, 0b001, "fcvtnu", int_aarch64_neon_fcvtnu>;
3716 defm FCVTPS : FPToIntegerUnscaled<0b01, 0b000, "fcvtps", int_aarch64_neon_fcvtps>;
3717 defm FCVTPU : FPToIntegerUnscaled<0b01, 0b001, "fcvtpu", int_aarch64_neon_fcvtpu>;
3718 defm FCVTZS : FPToIntegerUnscaled<0b11, 0b000, "fcvtzs", any_fp_to_sint>;
3719 defm FCVTZU : FPToIntegerUnscaled<0b11, 0b001, "fcvtzu", any_fp_to_uint>;
3720 defm FCVTZS : FPToIntegerScaled<0b11, 0b000, "fcvtzs", any_fp_to_sint>;
3721 defm FCVTZU : FPToIntegerScaled<0b11, 0b001, "fcvtzu", any_fp_to_uint>;
3723 // AArch64's FCVT instructions saturate when out of range.
3724 multiclass FPToIntegerSatPats<SDNode to_int_sat, string INST> {
3725   def : Pat<(i32 (to_int_sat f16:$Rn, i32)),
3726             (!cast<Instruction>(INST # UWHr) f16:$Rn)>;
3727   def : Pat<(i32 (to_int_sat f32:$Rn, i32)),
3728             (!cast<Instruction>(INST # UWSr) f32:$Rn)>;
3729   def : Pat<(i32 (to_int_sat f64:$Rn, i32)),
3730             (!cast<Instruction>(INST # UWDr) f64:$Rn)>;
3731   def : Pat<(i64 (to_int_sat f16:$Rn, i64)),
3732             (!cast<Instruction>(INST # UXHr) f16:$Rn)>;
3733   def : Pat<(i64 (to_int_sat f32:$Rn, i64)),
3734             (!cast<Instruction>(INST # UXSr) f32:$Rn)>;
3735   def : Pat<(i64 (to_int_sat f64:$Rn, i64)),
3736             (!cast<Instruction>(INST # UXDr) f64:$Rn)>;
3739 defm : FPToIntegerSatPats<fp_to_sint_sat, "FCVTZS">;
3740 defm : FPToIntegerSatPats<fp_to_uint_sat, "FCVTZU">;
3742 multiclass FPToIntegerIntPats<Intrinsic round, string INST> {
3743   def : Pat<(i32 (round f16:$Rn)), (!cast<Instruction>(INST # UWHr) $Rn)>;
3744   def : Pat<(i64 (round f16:$Rn)), (!cast<Instruction>(INST # UXHr) $Rn)>;
3745   def : Pat<(i32 (round f32:$Rn)), (!cast<Instruction>(INST # UWSr) $Rn)>;
3746   def : Pat<(i64 (round f32:$Rn)), (!cast<Instruction>(INST # UXSr) $Rn)>;
3747   def : Pat<(i32 (round f64:$Rn)), (!cast<Instruction>(INST # UWDr) $Rn)>;
3748   def : Pat<(i64 (round f64:$Rn)), (!cast<Instruction>(INST # UXDr) $Rn)>;
3750   def : Pat<(i32 (round (fmul f16:$Rn, fixedpoint_f16_i32:$scale))),
3751             (!cast<Instruction>(INST # SWHri) $Rn, $scale)>;
3752   def : Pat<(i64 (round (fmul f16:$Rn, fixedpoint_f16_i64:$scale))),
3753             (!cast<Instruction>(INST # SXHri) $Rn, $scale)>;
3754   def : Pat<(i32 (round (fmul f32:$Rn, fixedpoint_f32_i32:$scale))),
3755             (!cast<Instruction>(INST # SWSri) $Rn, $scale)>;
3756   def : Pat<(i64 (round (fmul f32:$Rn, fixedpoint_f32_i64:$scale))),
3757             (!cast<Instruction>(INST # SXSri) $Rn, $scale)>;
3758   def : Pat<(i32 (round (fmul f64:$Rn, fixedpoint_f64_i32:$scale))),
3759             (!cast<Instruction>(INST # SWDri) $Rn, $scale)>;
3760   def : Pat<(i64 (round (fmul f64:$Rn, fixedpoint_f64_i64:$scale))),
3761             (!cast<Instruction>(INST # SXDri) $Rn, $scale)>;
3764 defm : FPToIntegerIntPats<int_aarch64_neon_fcvtzs, "FCVTZS">;
3765 defm : FPToIntegerIntPats<int_aarch64_neon_fcvtzu, "FCVTZU">;
3767 multiclass FPToIntegerPats<SDNode to_int, SDNode to_int_sat, SDNode round, string INST> {
3768   def : Pat<(i32 (to_int (round f32:$Rn))),
3769             (!cast<Instruction>(INST # UWSr) f32:$Rn)>;
3770   def : Pat<(i64 (to_int (round f32:$Rn))),
3771             (!cast<Instruction>(INST # UXSr) f32:$Rn)>;
3772   def : Pat<(i32 (to_int (round f64:$Rn))),
3773             (!cast<Instruction>(INST # UWDr) f64:$Rn)>;
3774   def : Pat<(i64 (to_int (round f64:$Rn))),
3775             (!cast<Instruction>(INST # UXDr) f64:$Rn)>;
3777   // These instructions saturate like fp_to_[su]int_sat.
3778   def : Pat<(i32 (to_int_sat (round f16:$Rn), i32)),
3779             (!cast<Instruction>(INST # UWHr) f16:$Rn)>;
3780   def : Pat<(i64 (to_int_sat (round f16:$Rn), i64)),
3781             (!cast<Instruction>(INST # UXHr) f16:$Rn)>;
3782   def : Pat<(i32 (to_int_sat (round f32:$Rn), i32)),
3783             (!cast<Instruction>(INST # UWSr) f32:$Rn)>;
3784   def : Pat<(i64 (to_int_sat (round f32:$Rn), i64)),
3785             (!cast<Instruction>(INST # UXSr) f32:$Rn)>;
3786   def : Pat<(i32 (to_int_sat (round f64:$Rn), i32)),
3787             (!cast<Instruction>(INST # UWDr) f64:$Rn)>;
3788   def : Pat<(i64 (to_int_sat (round f64:$Rn), i64)),
3789             (!cast<Instruction>(INST # UXDr) f64:$Rn)>;
3792 defm : FPToIntegerPats<fp_to_sint, fp_to_sint_sat, fceil,  "FCVTPS">;
3793 defm : FPToIntegerPats<fp_to_uint, fp_to_uint_sat, fceil,  "FCVTPU">;
3794 defm : FPToIntegerPats<fp_to_sint, fp_to_sint_sat, ffloor, "FCVTMS">;
3795 defm : FPToIntegerPats<fp_to_uint, fp_to_uint_sat, ffloor, "FCVTMU">;
3796 defm : FPToIntegerPats<fp_to_sint, fp_to_sint_sat, ftrunc, "FCVTZS">;
3797 defm : FPToIntegerPats<fp_to_uint, fp_to_uint_sat, ftrunc, "FCVTZU">;
3798 defm : FPToIntegerPats<fp_to_sint, fp_to_sint_sat, fround, "FCVTAS">;
3799 defm : FPToIntegerPats<fp_to_uint, fp_to_uint_sat, fround, "FCVTAU">;
3803 let Predicates = [HasFullFP16] in {
3804   def : Pat<(i32 (lround f16:$Rn)),
3805             (!cast<Instruction>(FCVTASUWHr) f16:$Rn)>;
3806   def : Pat<(i64 (lround f16:$Rn)),
3807             (!cast<Instruction>(FCVTASUXHr) f16:$Rn)>;
3808   def : Pat<(i64 (llround f16:$Rn)),
3809             (!cast<Instruction>(FCVTASUXHr) f16:$Rn)>;
3811 def : Pat<(i32 (lround f32:$Rn)),
3812           (!cast<Instruction>(FCVTASUWSr) f32:$Rn)>;
3813 def : Pat<(i32 (lround f64:$Rn)),
3814           (!cast<Instruction>(FCVTASUWDr) f64:$Rn)>;
3815 def : Pat<(i64 (lround f32:$Rn)),
3816           (!cast<Instruction>(FCVTASUXSr) f32:$Rn)>;
3817 def : Pat<(i64 (lround f64:$Rn)),
3818           (!cast<Instruction>(FCVTASUXDr) f64:$Rn)>;
3819 def : Pat<(i64 (llround f32:$Rn)),
3820           (!cast<Instruction>(FCVTASUXSr) f32:$Rn)>;
3821 def : Pat<(i64 (llround f64:$Rn)),
3822           (!cast<Instruction>(FCVTASUXDr) f64:$Rn)>;
3824 //===----------------------------------------------------------------------===//
3825 // Scaled integer to floating point conversion instructions.
3826 //===----------------------------------------------------------------------===//
3828 defm SCVTF : IntegerToFP<0, "scvtf", any_sint_to_fp>;
3829 defm UCVTF : IntegerToFP<1, "ucvtf", any_uint_to_fp>;
3831 //===----------------------------------------------------------------------===//
3832 // Unscaled integer to floating point conversion instruction.
3833 //===----------------------------------------------------------------------===//
3835 defm FMOV : UnscaledConversion<"fmov">;
3837 // Add pseudo ops for FMOV 0 so we can mark them as isReMaterializable
3838 let isReMaterializable = 1, isCodeGenOnly = 1, isAsCheapAsAMove = 1 in {
3839 def FMOVH0 : Pseudo<(outs FPR16:$Rd), (ins), [(set f16:$Rd, (fpimm0))]>,
3840     Sched<[WriteF]>, Requires<[HasFullFP16]>;
3841 def FMOVS0 : Pseudo<(outs FPR32:$Rd), (ins), [(set f32:$Rd, (fpimm0))]>,
3842     Sched<[WriteF]>;
3843 def FMOVD0 : Pseudo<(outs FPR64:$Rd), (ins), [(set f64:$Rd, (fpimm0))]>,
3844     Sched<[WriteF]>;
3846 // Similarly add aliases
3847 def : InstAlias<"fmov $Rd, #0.0", (FMOVWHr FPR16:$Rd, WZR), 0>,
3848     Requires<[HasFullFP16]>;
3849 def : InstAlias<"fmov $Rd, #0.0", (FMOVWSr FPR32:$Rd, WZR), 0>;
3850 def : InstAlias<"fmov $Rd, #0.0", (FMOVXDr FPR64:$Rd, XZR), 0>;
3852 //===----------------------------------------------------------------------===//
3853 // Floating point conversion instruction.
3854 //===----------------------------------------------------------------------===//
3856 defm FCVT : FPConversion<"fcvt">;
3858 //===----------------------------------------------------------------------===//
3859 // Floating point single operand instructions.
3860 //===----------------------------------------------------------------------===//
3862 defm FABS   : SingleOperandFPData<0b0001, "fabs", fabs>;
3863 defm FMOV   : SingleOperandFPData<0b0000, "fmov">;
3864 defm FNEG   : SingleOperandFPData<0b0010, "fneg", fneg>;
3865 defm FRINTA : SingleOperandFPData<0b1100, "frinta", fround>;
3866 defm FRINTI : SingleOperandFPData<0b1111, "frinti", fnearbyint>;
3867 defm FRINTM : SingleOperandFPData<0b1010, "frintm", ffloor>;
3868 defm FRINTN : SingleOperandFPData<0b1000, "frintn", froundeven>;
3869 defm FRINTP : SingleOperandFPData<0b1001, "frintp", fceil>;
3871 defm FRINTX : SingleOperandFPData<0b1110, "frintx", frint>;
3872 defm FRINTZ : SingleOperandFPData<0b1011, "frintz", ftrunc>;
3874 let SchedRW = [WriteFDiv] in {
3875 defm FSQRT  : SingleOperandFPData<0b0011, "fsqrt", fsqrt>;
3878 let Predicates = [HasFRInt3264] in {
3879   defm FRINT32Z : FRIntNNT<0b00, "frint32z", int_aarch64_frint32z>;
3880   defm FRINT64Z : FRIntNNT<0b10, "frint64z", int_aarch64_frint64z>;
3881   defm FRINT32X : FRIntNNT<0b01, "frint32x", int_aarch64_frint32x>;
3882   defm FRINT64X : FRIntNNT<0b11, "frint64x", int_aarch64_frint64x>;
3883 } // HasFRInt3264
3885 let Predicates = [HasFullFP16] in {
3886   def : Pat<(i32 (lrint f16:$Rn)),
3887             (FCVTZSUWHr (!cast<Instruction>(FRINTXHr) f16:$Rn))>;
3888   def : Pat<(i64 (lrint f16:$Rn)),
3889             (FCVTZSUXHr (!cast<Instruction>(FRINTXHr) f16:$Rn))>;
3890   def : Pat<(i64 (llrint f16:$Rn)),
3891             (FCVTZSUXHr (!cast<Instruction>(FRINTXHr) f16:$Rn))>;
3893 def : Pat<(i32 (lrint f32:$Rn)),
3894           (FCVTZSUWSr (!cast<Instruction>(FRINTXSr) f32:$Rn))>;
3895 def : Pat<(i32 (lrint f64:$Rn)),
3896           (FCVTZSUWDr (!cast<Instruction>(FRINTXDr) f64:$Rn))>;
3897 def : Pat<(i64 (lrint f32:$Rn)),
3898           (FCVTZSUXSr (!cast<Instruction>(FRINTXSr) f32:$Rn))>;
3899 def : Pat<(i64 (lrint f64:$Rn)),
3900           (FCVTZSUXDr (!cast<Instruction>(FRINTXDr) f64:$Rn))>;
3901 def : Pat<(i64 (llrint f32:$Rn)),
3902           (FCVTZSUXSr (!cast<Instruction>(FRINTXSr) f32:$Rn))>;
3903 def : Pat<(i64 (llrint f64:$Rn)),
3904           (FCVTZSUXDr (!cast<Instruction>(FRINTXDr) f64:$Rn))>;
3906 //===----------------------------------------------------------------------===//
3907 // Floating point two operand instructions.
3908 //===----------------------------------------------------------------------===//
3910 defm FADD   : TwoOperandFPData<0b0010, "fadd", fadd>;
3911 let SchedRW = [WriteFDiv] in {
3912 defm FDIV   : TwoOperandFPData<0b0001, "fdiv", fdiv>;
3914 defm FMAXNM : TwoOperandFPData<0b0110, "fmaxnm", fmaxnum>;
3915 defm FMAX   : TwoOperandFPData<0b0100, "fmax", fmaximum>;
3916 defm FMINNM : TwoOperandFPData<0b0111, "fminnm", fminnum>;
3917 defm FMIN   : TwoOperandFPData<0b0101, "fmin", fminimum>;
3918 let SchedRW = [WriteFMul] in {
3919 defm FMUL   : TwoOperandFPData<0b0000, "fmul", fmul>;
3920 defm FNMUL  : TwoOperandFPDataNeg<0b1000, "fnmul", fmul>;
3922 defm FSUB   : TwoOperandFPData<0b0011, "fsub", fsub>;
3924 def : Pat<(v1f64 (fmaximum (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
3925           (FMAXDrr FPR64:$Rn, FPR64:$Rm)>;
3926 def : Pat<(v1f64 (fminimum (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
3927           (FMINDrr FPR64:$Rn, FPR64:$Rm)>;
3928 def : Pat<(v1f64 (fmaxnum (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
3929           (FMAXNMDrr FPR64:$Rn, FPR64:$Rm)>;
3930 def : Pat<(v1f64 (fminnum (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
3931           (FMINNMDrr FPR64:$Rn, FPR64:$Rm)>;
3933 //===----------------------------------------------------------------------===//
3934 // Floating point three operand instructions.
3935 //===----------------------------------------------------------------------===//
3937 defm FMADD  : ThreeOperandFPData<0, 0, "fmadd", fma>;
3938 defm FMSUB  : ThreeOperandFPData<0, 1, "fmsub",
3939      TriOpFrag<(fma node:$LHS, (fneg node:$MHS), node:$RHS)> >;
3940 defm FNMADD : ThreeOperandFPData<1, 0, "fnmadd",
3941      TriOpFrag<(fneg (fma node:$LHS, node:$MHS, node:$RHS))> >;
3942 defm FNMSUB : ThreeOperandFPData<1, 1, "fnmsub",
3943      TriOpFrag<(fma node:$LHS, node:$MHS, (fneg node:$RHS))> >;
3945 // The following def pats catch the case where the LHS of an FMA is negated.
3946 // The TriOpFrag above catches the case where the middle operand is negated.
3948 // N.b. FMSUB etc have the accumulator at the *end* of (outs), unlike
3949 // the NEON variant.
3951 // Here we handle first -(a + b*c) for FNMADD:
3953 let Predicates = [HasNEON, HasFullFP16] in
3954 def : Pat<(f16 (fma (fneg FPR16:$Rn), FPR16:$Rm, FPR16:$Ra)),
3955           (FMSUBHrrr FPR16:$Rn, FPR16:$Rm, FPR16:$Ra)>;
3957 def : Pat<(f32 (fma (fneg FPR32:$Rn), FPR32:$Rm, FPR32:$Ra)),
3958           (FMSUBSrrr FPR32:$Rn, FPR32:$Rm, FPR32:$Ra)>;
3960 def : Pat<(f64 (fma (fneg FPR64:$Rn), FPR64:$Rm, FPR64:$Ra)),
3961           (FMSUBDrrr FPR64:$Rn, FPR64:$Rm, FPR64:$Ra)>;
3963 // Now it's time for "(-a) + (-b)*c"
3965 let Predicates = [HasNEON, HasFullFP16] in
3966 def : Pat<(f16 (fma (fneg FPR16:$Rn), FPR16:$Rm, (fneg FPR16:$Ra))),
3967           (FNMADDHrrr FPR16:$Rn, FPR16:$Rm, FPR16:$Ra)>;
3969 def : Pat<(f32 (fma (fneg FPR32:$Rn), FPR32:$Rm, (fneg FPR32:$Ra))),
3970           (FNMADDSrrr FPR32:$Rn, FPR32:$Rm, FPR32:$Ra)>;
3972 def : Pat<(f64 (fma (fneg FPR64:$Rn), FPR64:$Rm, (fneg FPR64:$Ra))),
3973           (FNMADDDrrr FPR64:$Rn, FPR64:$Rm, FPR64:$Ra)>;
3975 //===----------------------------------------------------------------------===//
3976 // Floating point comparison instructions.
3977 //===----------------------------------------------------------------------===//
3979 defm FCMPE : FPComparison<1, "fcmpe", AArch64strict_fcmpe>;
3980 defm FCMP  : FPComparison<0, "fcmp", AArch64any_fcmp>;
3982 //===----------------------------------------------------------------------===//
3983 // Floating point conditional comparison instructions.
3984 //===----------------------------------------------------------------------===//
3986 defm FCCMPE : FPCondComparison<1, "fccmpe">;
3987 defm FCCMP  : FPCondComparison<0, "fccmp", AArch64fccmp>;
3989 //===----------------------------------------------------------------------===//
3990 // Floating point conditional select instruction.
3991 //===----------------------------------------------------------------------===//
3993 defm FCSEL : FPCondSelect<"fcsel">;
3995 // CSEL instructions providing f128 types need to be handled by a
3996 // pseudo-instruction since the eventual code will need to introduce basic
3997 // blocks and control flow.
3998 def F128CSEL : Pseudo<(outs FPR128:$Rd),
3999                       (ins FPR128:$Rn, FPR128:$Rm, ccode:$cond),
4000                       [(set (f128 FPR128:$Rd),
4001                             (AArch64csel FPR128:$Rn, FPR128:$Rm,
4002                                        (i32 imm:$cond), NZCV))]> {
4003   let Uses = [NZCV];
4004   let usesCustomInserter = 1;
4005   let hasNoSchedulingInfo = 1;
4008 //===----------------------------------------------------------------------===//
4009 // Instructions used for emitting unwind opcodes on ARM64 Windows.
4010 //===----------------------------------------------------------------------===//
4011 let isPseudo = 1 in {
4012   def SEH_StackAlloc : Pseudo<(outs), (ins i32imm:$size), []>, Sched<[]>;
4013   def SEH_SaveFPLR : Pseudo<(outs), (ins i32imm:$offs), []>, Sched<[]>;
4014   def SEH_SaveFPLR_X : Pseudo<(outs), (ins i32imm:$offs), []>, Sched<[]>;
4015   def SEH_SaveReg : Pseudo<(outs), (ins i32imm:$reg, i32imm:$offs), []>, Sched<[]>;
4016   def SEH_SaveReg_X : Pseudo<(outs), (ins i32imm:$reg, i32imm:$offs), []>, Sched<[]>;
4017   def SEH_SaveRegP : Pseudo<(outs), (ins i32imm:$reg0, i32imm:$reg1, i32imm:$offs), []>, Sched<[]>;
4018   def SEH_SaveRegP_X : Pseudo<(outs), (ins i32imm:$reg0, i32imm:$reg1, i32imm:$offs), []>, Sched<[]>;
4019   def SEH_SaveFReg : Pseudo<(outs), (ins i32imm:$reg, i32imm:$offs), []>, Sched<[]>;
4020   def SEH_SaveFReg_X :  Pseudo<(outs), (ins i32imm:$reg, i32imm:$offs), []>, Sched<[]>;
4021   def SEH_SaveFRegP : Pseudo<(outs), (ins i32imm:$reg0, i32imm:$reg1, i32imm:$offs), []>, Sched<[]>;
4022   def SEH_SaveFRegP_X : Pseudo<(outs), (ins i32imm:$reg0, i32imm:$reg1, i32imm:$offs), []>, Sched<[]>;
4023   def SEH_SetFP : Pseudo<(outs), (ins), []>, Sched<[]>;
4024   def SEH_AddFP : Pseudo<(outs), (ins i32imm:$offs), []>, Sched<[]>;
4025   def SEH_Nop : Pseudo<(outs), (ins), []>, Sched<[]>;
4026   def SEH_PrologEnd : Pseudo<(outs), (ins), []>, Sched<[]>;
4027   def SEH_EpilogStart : Pseudo<(outs), (ins), []>, Sched<[]>;
4028   def SEH_EpilogEnd : Pseudo<(outs), (ins), []>, Sched<[]>;
4031 // Pseudo instructions for Windows EH
4032 //===----------------------------------------------------------------------===//
4033 let isTerminator = 1, hasSideEffects = 1, isBarrier = 1, hasCtrlDep = 1,
4034     isCodeGenOnly = 1, isReturn = 1, isEHScopeReturn = 1, isPseudo = 1 in {
4035    def CLEANUPRET : Pseudo<(outs), (ins), [(cleanupret)]>, Sched<[]>;
4036    let usesCustomInserter = 1 in
4037      def CATCHRET : Pseudo<(outs), (ins am_brcond:$dst, am_brcond:$src), [(catchret bb:$dst, bb:$src)]>,
4038                     Sched<[]>;
4041 // Pseudo instructions for homogeneous prolog/epilog
4042 let isPseudo = 1 in {
4043   // Save CSRs in order, {FPOffset}
4044   def HOM_Prolog : Pseudo<(outs), (ins variable_ops), []>, Sched<[]>;
4045   // Restore CSRs in order
4046   def HOM_Epilog : Pseudo<(outs), (ins variable_ops), []>, Sched<[]>;
4049 //===----------------------------------------------------------------------===//
4050 // Floating point immediate move.
4051 //===----------------------------------------------------------------------===//
4053 let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
4054 defm FMOV : FPMoveImmediate<"fmov">;
4057 //===----------------------------------------------------------------------===//
4058 // Advanced SIMD two vector instructions.
4059 //===----------------------------------------------------------------------===//
4061 defm UABDL   : SIMDLongThreeVectorBHSabdl<1, 0b0111, "uabdl",
4062                                           AArch64uabd>;
4063 // Match UABDL in log2-shuffle patterns.
4064 def : Pat<(abs (v8i16 (sub (zext (v8i8 V64:$opA)),
4065                            (zext (v8i8 V64:$opB))))),
4066           (UABDLv8i8_v8i16 V64:$opA, V64:$opB)>;
4067 def : Pat<(xor (v8i16 (AArch64vashr v8i16:$src, (i32 15))),
4068                (v8i16 (add (sub (zext (v8i8 V64:$opA)),
4069                                 (zext (v8i8 V64:$opB))),
4070                            (AArch64vashr v8i16:$src, (i32 15))))),
4071           (UABDLv8i8_v8i16 V64:$opA, V64:$opB)>;
4072 def : Pat<(abs (v8i16 (sub (zext (extract_high_v16i8 V128:$opA)),
4073                            (zext (extract_high_v16i8 V128:$opB))))),
4074           (UABDLv16i8_v8i16 V128:$opA, V128:$opB)>;
4075 def : Pat<(xor (v8i16 (AArch64vashr v8i16:$src, (i32 15))),
4076                (v8i16 (add (sub (zext (extract_high_v16i8 V128:$opA)),
4077                                 (zext (extract_high_v16i8 V128:$opB))),
4078                            (AArch64vashr v8i16:$src, (i32 15))))),
4079           (UABDLv16i8_v8i16 V128:$opA, V128:$opB)>;
4080 def : Pat<(abs (v4i32 (sub (zext (v4i16 V64:$opA)),
4081                            (zext (v4i16 V64:$opB))))),
4082           (UABDLv4i16_v4i32 V64:$opA, V64:$opB)>;
4083 def : Pat<(abs (v4i32 (sub (zext (extract_high_v8i16 V128:$opA)),
4084                            (zext (extract_high_v8i16 V128:$opB))))),
4085           (UABDLv8i16_v4i32 V128:$opA, V128:$opB)>;
4086 def : Pat<(abs (v2i64 (sub (zext (v2i32 V64:$opA)),
4087                            (zext (v2i32 V64:$opB))))),
4088           (UABDLv2i32_v2i64 V64:$opA, V64:$opB)>;
4089 def : Pat<(abs (v2i64 (sub (zext (extract_high_v4i32 V128:$opA)),
4090                            (zext (extract_high_v4i32 V128:$opB))))),
4091           (UABDLv4i32_v2i64 V128:$opA, V128:$opB)>;
4093 defm ABS    : SIMDTwoVectorBHSD<0, 0b01011, "abs", abs>;
4094 defm CLS    : SIMDTwoVectorBHS<0, 0b00100, "cls", int_aarch64_neon_cls>;
4095 defm CLZ    : SIMDTwoVectorBHS<1, 0b00100, "clz", ctlz>;
4096 defm CMEQ   : SIMDCmpTwoVector<0, 0b01001, "cmeq", AArch64cmeqz>;
4097 defm CMGE   : SIMDCmpTwoVector<1, 0b01000, "cmge", AArch64cmgez>;
4098 defm CMGT   : SIMDCmpTwoVector<0, 0b01000, "cmgt", AArch64cmgtz>;
4099 defm CMLE   : SIMDCmpTwoVector<1, 0b01001, "cmle", AArch64cmlez>;
4100 defm CMLT   : SIMDCmpTwoVector<0, 0b01010, "cmlt", AArch64cmltz>;
4101 defm CNT    : SIMDTwoVectorB<0, 0b00, 0b00101, "cnt", ctpop>;
4102 defm FABS   : SIMDTwoVectorFP<0, 1, 0b01111, "fabs", fabs>;
4104 defm FCMEQ  : SIMDFPCmpTwoVector<0, 1, 0b01101, "fcmeq", AArch64fcmeqz>;
4105 defm FCMGE  : SIMDFPCmpTwoVector<1, 1, 0b01100, "fcmge", AArch64fcmgez>;
4106 defm FCMGT  : SIMDFPCmpTwoVector<0, 1, 0b01100, "fcmgt", AArch64fcmgtz>;
4107 defm FCMLE  : SIMDFPCmpTwoVector<1, 1, 0b01101, "fcmle", AArch64fcmlez>;
4108 defm FCMLT  : SIMDFPCmpTwoVector<0, 1, 0b01110, "fcmlt", AArch64fcmltz>;
4109 defm FCVTAS : SIMDTwoVectorFPToInt<0,0,0b11100, "fcvtas",int_aarch64_neon_fcvtas>;
4110 defm FCVTAU : SIMDTwoVectorFPToInt<1,0,0b11100, "fcvtau",int_aarch64_neon_fcvtau>;
4111 defm FCVTL  : SIMDFPWidenTwoVector<0, 0, 0b10111, "fcvtl">;
4112 def : Pat<(v4f32 (int_aarch64_neon_vcvthf2fp (v4i16 V64:$Rn))),
4113           (FCVTLv4i16 V64:$Rn)>;
4114 def : Pat<(v4f32 (int_aarch64_neon_vcvthf2fp (extract_subvector (v8i16 V128:$Rn),
4115                                                               (i64 4)))),
4116           (FCVTLv8i16 V128:$Rn)>;
4117 def : Pat<(v2f64 (fpextend (v2f32 V64:$Rn))), (FCVTLv2i32 V64:$Rn)>;
4119 def : Pat<(v4f32 (fpextend (v4f16 V64:$Rn))), (FCVTLv4i16 V64:$Rn)>;
4121 defm FCVTMS : SIMDTwoVectorFPToInt<0,0,0b11011, "fcvtms",int_aarch64_neon_fcvtms>;
4122 defm FCVTMU : SIMDTwoVectorFPToInt<1,0,0b11011, "fcvtmu",int_aarch64_neon_fcvtmu>;
4123 defm FCVTNS : SIMDTwoVectorFPToInt<0,0,0b11010, "fcvtns",int_aarch64_neon_fcvtns>;
4124 defm FCVTNU : SIMDTwoVectorFPToInt<1,0,0b11010, "fcvtnu",int_aarch64_neon_fcvtnu>;
4125 defm FCVTN  : SIMDFPNarrowTwoVector<0, 0, 0b10110, "fcvtn">;
4126 def : Pat<(v4i16 (int_aarch64_neon_vcvtfp2hf (v4f32 V128:$Rn))),
4127           (FCVTNv4i16 V128:$Rn)>;
4128 def : Pat<(concat_vectors V64:$Rd,
4129                           (v4i16 (int_aarch64_neon_vcvtfp2hf (v4f32 V128:$Rn)))),
4130           (FCVTNv8i16 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4131 def : Pat<(v2f32 (fpround (v2f64 V128:$Rn))), (FCVTNv2i32 V128:$Rn)>;
4132 def : Pat<(v4f16 (fpround (v4f32 V128:$Rn))), (FCVTNv4i16 V128:$Rn)>;
4133 def : Pat<(concat_vectors V64:$Rd, (v2f32 (fpround (v2f64 V128:$Rn)))),
4134           (FCVTNv4i32 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4135 defm FCVTPS : SIMDTwoVectorFPToInt<0,1,0b11010, "fcvtps",int_aarch64_neon_fcvtps>;
4136 defm FCVTPU : SIMDTwoVectorFPToInt<1,1,0b11010, "fcvtpu",int_aarch64_neon_fcvtpu>;
4137 defm FCVTXN : SIMDFPInexactCvtTwoVector<1, 0, 0b10110, "fcvtxn",
4138                                         int_aarch64_neon_fcvtxn>;
4139 defm FCVTZS : SIMDTwoVectorFPToInt<0, 1, 0b11011, "fcvtzs", fp_to_sint>;
4140 defm FCVTZU : SIMDTwoVectorFPToInt<1, 1, 0b11011, "fcvtzu", fp_to_uint>;
4142 def : Pat<(v4i16 (int_aarch64_neon_fcvtzs v4f16:$Rn)), (FCVTZSv4f16 $Rn)>;
4143 def : Pat<(v8i16 (int_aarch64_neon_fcvtzs v8f16:$Rn)), (FCVTZSv8f16 $Rn)>;
4144 def : Pat<(v2i32 (int_aarch64_neon_fcvtzs v2f32:$Rn)), (FCVTZSv2f32 $Rn)>;
4145 def : Pat<(v4i32 (int_aarch64_neon_fcvtzs v4f32:$Rn)), (FCVTZSv4f32 $Rn)>;
4146 def : Pat<(v2i64 (int_aarch64_neon_fcvtzs v2f64:$Rn)), (FCVTZSv2f64 $Rn)>;
4148 def : Pat<(v4i16 (int_aarch64_neon_fcvtzu v4f16:$Rn)), (FCVTZUv4f16 $Rn)>;
4149 def : Pat<(v8i16 (int_aarch64_neon_fcvtzu v8f16:$Rn)), (FCVTZUv8f16 $Rn)>;
4150 def : Pat<(v2i32 (int_aarch64_neon_fcvtzu v2f32:$Rn)), (FCVTZUv2f32 $Rn)>;
4151 def : Pat<(v4i32 (int_aarch64_neon_fcvtzu v4f32:$Rn)), (FCVTZUv4f32 $Rn)>;
4152 def : Pat<(v2i64 (int_aarch64_neon_fcvtzu v2f64:$Rn)), (FCVTZUv2f64 $Rn)>;
4154 defm FNEG   : SIMDTwoVectorFP<1, 1, 0b01111, "fneg", fneg>;
4155 defm FRECPE : SIMDTwoVectorFP<0, 1, 0b11101, "frecpe", int_aarch64_neon_frecpe>;
4156 defm FRINTA : SIMDTwoVectorFP<1, 0, 0b11000, "frinta", fround>;
4157 defm FRINTI : SIMDTwoVectorFP<1, 1, 0b11001, "frinti", fnearbyint>;
4158 defm FRINTM : SIMDTwoVectorFP<0, 0, 0b11001, "frintm", ffloor>;
4159 defm FRINTN : SIMDTwoVectorFP<0, 0, 0b11000, "frintn", froundeven>;
4160 defm FRINTP : SIMDTwoVectorFP<0, 1, 0b11000, "frintp", fceil>;
4161 defm FRINTX : SIMDTwoVectorFP<1, 0, 0b11001, "frintx", frint>;
4162 defm FRINTZ : SIMDTwoVectorFP<0, 1, 0b11001, "frintz", ftrunc>;
4164 let Predicates = [HasFRInt3264] in {
4165   defm FRINT32Z : FRIntNNTVector<0, 0, "frint32z", int_aarch64_neon_frint32z>;
4166   defm FRINT64Z : FRIntNNTVector<0, 1, "frint64z", int_aarch64_neon_frint64z>;
4167   defm FRINT32X : FRIntNNTVector<1, 0, "frint32x", int_aarch64_neon_frint32x>;
4168   defm FRINT64X : FRIntNNTVector<1, 1, "frint64x", int_aarch64_neon_frint64x>;
4169 } // HasFRInt3264
4171 defm FRSQRTE: SIMDTwoVectorFP<1, 1, 0b11101, "frsqrte", int_aarch64_neon_frsqrte>;
4172 defm FSQRT  : SIMDTwoVectorFP<1, 1, 0b11111, "fsqrt", fsqrt>;
4173 defm NEG    : SIMDTwoVectorBHSD<1, 0b01011, "neg",
4174                                UnOpFrag<(sub immAllZerosV, node:$LHS)> >;
4175 defm NOT    : SIMDTwoVectorB<1, 0b00, 0b00101, "not", vnot>;
4176 // Aliases for MVN -> NOT.
4177 def : InstAlias<"mvn{ $Vd.8b, $Vn.8b|.8b $Vd, $Vn}",
4178                 (NOTv8i8 V64:$Vd, V64:$Vn)>;
4179 def : InstAlias<"mvn{ $Vd.16b, $Vn.16b|.16b $Vd, $Vn}",
4180                 (NOTv16i8 V128:$Vd, V128:$Vn)>;
4182 def : Pat<(vnot (v4i16 V64:$Rn)),  (NOTv8i8  V64:$Rn)>;
4183 def : Pat<(vnot (v8i16 V128:$Rn)), (NOTv16i8 V128:$Rn)>;
4184 def : Pat<(vnot (v2i32 V64:$Rn)),  (NOTv8i8  V64:$Rn)>;
4185 def : Pat<(vnot (v4i32 V128:$Rn)), (NOTv16i8 V128:$Rn)>;
4186 def : Pat<(vnot (v1i64 V64:$Rn)),  (NOTv8i8  V64:$Rn)>;
4187 def : Pat<(vnot (v2i64 V128:$Rn)), (NOTv16i8 V128:$Rn)>;
4189 defm RBIT   : SIMDTwoVectorB<1, 0b01, 0b00101, "rbit", bitreverse>;
4190 defm REV16  : SIMDTwoVectorB<0, 0b00, 0b00001, "rev16", AArch64rev16>;
4191 defm REV32  : SIMDTwoVectorBH<1, 0b00000, "rev32", AArch64rev32>;
4192 defm REV64  : SIMDTwoVectorBHS<0, 0b00000, "rev64", AArch64rev64>;
4193 defm SADALP : SIMDLongTwoVectorTied<0, 0b00110, "sadalp",
4194        BinOpFrag<(add node:$LHS, (int_aarch64_neon_saddlp node:$RHS))> >;
4195 defm SADDLP : SIMDLongTwoVector<0, 0b00010, "saddlp", int_aarch64_neon_saddlp>;
4196 defm SCVTF  : SIMDTwoVectorIntToFP<0, 0, 0b11101, "scvtf", sint_to_fp>;
4197 defm SHLL   : SIMDVectorLShiftLongBySizeBHS;
4198 defm SQABS  : SIMDTwoVectorBHSD<0, 0b00111, "sqabs", int_aarch64_neon_sqabs>;
4199 defm SQNEG  : SIMDTwoVectorBHSD<1, 0b00111, "sqneg", int_aarch64_neon_sqneg>;
4200 defm SQXTN  : SIMDMixedTwoVector<0, 0b10100, "sqxtn", int_aarch64_neon_sqxtn>;
4201 defm SQXTUN : SIMDMixedTwoVector<1, 0b10010, "sqxtun", int_aarch64_neon_sqxtun>;
4202 defm SUQADD : SIMDTwoVectorBHSDTied<0, 0b00011, "suqadd",int_aarch64_neon_suqadd>;
4203 defm UADALP : SIMDLongTwoVectorTied<1, 0b00110, "uadalp",
4204        BinOpFrag<(add node:$LHS, (AArch64uaddlp node:$RHS))> >;
4205 defm UADDLP : SIMDLongTwoVector<1, 0b00010, "uaddlp", AArch64uaddlp>;
4206 defm UCVTF  : SIMDTwoVectorIntToFP<1, 0, 0b11101, "ucvtf", uint_to_fp>;
4207 defm UQXTN  : SIMDMixedTwoVector<1, 0b10100, "uqxtn", int_aarch64_neon_uqxtn>;
4208 defm URECPE : SIMDTwoVectorS<0, 1, 0b11100, "urecpe", int_aarch64_neon_urecpe>;
4209 defm URSQRTE: SIMDTwoVectorS<1, 1, 0b11100, "ursqrte", int_aarch64_neon_ursqrte>;
4210 defm USQADD : SIMDTwoVectorBHSDTied<1, 0b00011, "usqadd",int_aarch64_neon_usqadd>;
4211 defm XTN    : SIMDMixedTwoVector<0, 0b10010, "xtn", trunc>;
4213 def : Pat<(v4f16  (AArch64rev32 V64:$Rn)),  (REV32v4i16 V64:$Rn)>;
4214 def : Pat<(v4f16  (AArch64rev64 V64:$Rn)),  (REV64v4i16 V64:$Rn)>;
4215 def : Pat<(v4bf16 (AArch64rev32 V64:$Rn)),  (REV32v4i16 V64:$Rn)>;
4216 def : Pat<(v4bf16 (AArch64rev64 V64:$Rn)),  (REV64v4i16 V64:$Rn)>;
4217 def : Pat<(v8f16  (AArch64rev32 V128:$Rn)), (REV32v8i16 V128:$Rn)>;
4218 def : Pat<(v8f16  (AArch64rev64 V128:$Rn)), (REV64v8i16 V128:$Rn)>;
4219 def : Pat<(v8bf16 (AArch64rev32 V128:$Rn)), (REV32v8i16 V128:$Rn)>;
4220 def : Pat<(v8bf16 (AArch64rev64 V128:$Rn)), (REV64v8i16 V128:$Rn)>;
4221 def : Pat<(v2f32  (AArch64rev64 V64:$Rn)),  (REV64v2i32 V64:$Rn)>;
4222 def : Pat<(v4f32  (AArch64rev64 V128:$Rn)), (REV64v4i32 V128:$Rn)>;
4224 // Patterns for vector long shift (by element width). These need to match all
4225 // three of zext, sext and anyext so it's easier to pull the patterns out of the
4226 // definition.
4227 multiclass SIMDVectorLShiftLongBySizeBHSPats<SDPatternOperator ext> {
4228   def : Pat<(AArch64vshl (v8i16 (ext (v8i8 V64:$Rn))), (i32 8)),
4229             (SHLLv8i8 V64:$Rn)>;
4230   def : Pat<(AArch64vshl (v8i16 (ext (extract_high_v16i8 V128:$Rn))), (i32 8)),
4231             (SHLLv16i8 V128:$Rn)>;
4232   def : Pat<(AArch64vshl (v4i32 (ext (v4i16 V64:$Rn))), (i32 16)),
4233             (SHLLv4i16 V64:$Rn)>;
4234   def : Pat<(AArch64vshl (v4i32 (ext (extract_high_v8i16 V128:$Rn))), (i32 16)),
4235             (SHLLv8i16 V128:$Rn)>;
4236   def : Pat<(AArch64vshl (v2i64 (ext (v2i32 V64:$Rn))), (i32 32)),
4237             (SHLLv2i32 V64:$Rn)>;
4238   def : Pat<(AArch64vshl (v2i64 (ext (extract_high_v4i32 V128:$Rn))), (i32 32)),
4239             (SHLLv4i32 V128:$Rn)>;
4242 defm : SIMDVectorLShiftLongBySizeBHSPats<anyext>;
4243 defm : SIMDVectorLShiftLongBySizeBHSPats<zext>;
4244 defm : SIMDVectorLShiftLongBySizeBHSPats<sext>;
4246 // Constant vector values, used in the S/UQXTN patterns below.
4247 def VImmFF:   PatLeaf<(AArch64NvCast (v2i64 (AArch64movi_edit (i32 85))))>;
4248 def VImmFFFF: PatLeaf<(AArch64NvCast (v2i64 (AArch64movi_edit (i32 51))))>;
4249 def VImm7F:   PatLeaf<(AArch64movi_shift (i32 127), (i32 0))>;
4250 def VImm80:   PatLeaf<(AArch64mvni_shift (i32 127), (i32 0))>;
4251 def VImm7FFF: PatLeaf<(AArch64movi_msl (i32 127), (i32 264))>;
4252 def VImm8000: PatLeaf<(AArch64mvni_msl (i32 127), (i32 264))>;
4254 // trunc(umin(X, 255)) -> UQXTRN v8i8
4255 def : Pat<(v8i8 (trunc (umin (v8i16 V128:$Vn), (v8i16 VImmFF)))),
4256           (UQXTNv8i8 V128:$Vn)>;
4257 // trunc(umin(X, 65535)) -> UQXTRN v4i16
4258 def : Pat<(v4i16 (trunc (umin (v4i32 V128:$Vn), (v4i32 VImmFFFF)))),
4259           (UQXTNv4i16 V128:$Vn)>;
4260 // trunc(smin(smax(X, -128), 128)) -> SQXTRN
4261 //  with reversed min/max
4262 def : Pat<(v8i8 (trunc (smin (smax (v8i16 V128:$Vn), (v8i16 VImm80)),
4263                              (v8i16 VImm7F)))),
4264           (SQXTNv8i8 V128:$Vn)>;
4265 def : Pat<(v8i8 (trunc (smax (smin (v8i16 V128:$Vn), (v8i16 VImm7F)),
4266                              (v8i16 VImm80)))),
4267           (SQXTNv8i8 V128:$Vn)>;
4268 // trunc(smin(smax(X, -32768), 32767)) -> SQXTRN
4269 //  with reversed min/max
4270 def : Pat<(v4i16 (trunc (smin (smax (v4i32 V128:$Vn), (v4i32 VImm8000)),
4271                               (v4i32 VImm7FFF)))),
4272           (SQXTNv4i16 V128:$Vn)>;
4273 def : Pat<(v4i16 (trunc (smax (smin (v4i32 V128:$Vn), (v4i32 VImm7FFF)),
4274                               (v4i32 VImm8000)))),
4275           (SQXTNv4i16 V128:$Vn)>;
4277 //===----------------------------------------------------------------------===//
4278 // Advanced SIMD three vector instructions.
4279 //===----------------------------------------------------------------------===//
4281 defm ADD     : SIMDThreeSameVector<0, 0b10000, "add", add>;
4282 defm ADDP    : SIMDThreeSameVector<0, 0b10111, "addp", int_aarch64_neon_addp>;
4283 defm CMEQ    : SIMDThreeSameVector<1, 0b10001, "cmeq", AArch64cmeq>;
4284 defm CMGE    : SIMDThreeSameVector<0, 0b00111, "cmge", AArch64cmge>;
4285 defm CMGT    : SIMDThreeSameVector<0, 0b00110, "cmgt", AArch64cmgt>;
4286 defm CMHI    : SIMDThreeSameVector<1, 0b00110, "cmhi", AArch64cmhi>;
4287 defm CMHS    : SIMDThreeSameVector<1, 0b00111, "cmhs", AArch64cmhs>;
4288 defm CMTST   : SIMDThreeSameVector<0, 0b10001, "cmtst", AArch64cmtst>;
4289 foreach VT = [ v8i8, v16i8, v4i16, v8i16, v2i32, v4i32, v2i64 ] in {
4290 def : Pat<(vnot (AArch64cmeqz VT:$Rn)), (!cast<Instruction>("CMTST"#VT) VT:$Rn, VT:$Rn)>;
4292 defm FABD    : SIMDThreeSameVectorFP<1,1,0b010,"fabd", int_aarch64_neon_fabd>;
4293 let Predicates = [HasNEON] in {
4294 foreach VT = [ v2f32, v4f32, v2f64 ] in
4295 def : Pat<(fabs (fsub VT:$Rn, VT:$Rm)), (!cast<Instruction>("FABD"#VT) VT:$Rn, VT:$Rm)>;
4297 let Predicates = [HasNEON, HasFullFP16] in {
4298 foreach VT = [ v4f16, v8f16 ] in
4299 def : Pat<(fabs (fsub VT:$Rn, VT:$Rm)), (!cast<Instruction>("FABD"#VT) VT:$Rn, VT:$Rm)>;
4301 defm FACGE   : SIMDThreeSameVectorFPCmp<1,0,0b101,"facge",int_aarch64_neon_facge>;
4302 defm FACGT   : SIMDThreeSameVectorFPCmp<1,1,0b101,"facgt",int_aarch64_neon_facgt>;
4303 defm FADDP   : SIMDThreeSameVectorFP<1,0,0b010,"faddp",int_aarch64_neon_faddp>;
4304 defm FADD    : SIMDThreeSameVectorFP<0,0,0b010,"fadd", fadd>;
4305 defm FCMEQ   : SIMDThreeSameVectorFPCmp<0, 0, 0b100, "fcmeq", AArch64fcmeq>;
4306 defm FCMGE   : SIMDThreeSameVectorFPCmp<1, 0, 0b100, "fcmge", AArch64fcmge>;
4307 defm FCMGT   : SIMDThreeSameVectorFPCmp<1, 1, 0b100, "fcmgt", AArch64fcmgt>;
4308 defm FDIV    : SIMDThreeSameVectorFP<1,0,0b111,"fdiv", fdiv>;
4309 defm FMAXNMP : SIMDThreeSameVectorFP<1,0,0b000,"fmaxnmp", int_aarch64_neon_fmaxnmp>;
4310 defm FMAXNM  : SIMDThreeSameVectorFP<0,0,0b000,"fmaxnm", fmaxnum>;
4311 defm FMAXP   : SIMDThreeSameVectorFP<1,0,0b110,"fmaxp", int_aarch64_neon_fmaxp>;
4312 defm FMAX    : SIMDThreeSameVectorFP<0,0,0b110,"fmax", fmaximum>;
4313 defm FMINNMP : SIMDThreeSameVectorFP<1,1,0b000,"fminnmp", int_aarch64_neon_fminnmp>;
4314 defm FMINNM  : SIMDThreeSameVectorFP<0,1,0b000,"fminnm", fminnum>;
4315 defm FMINP   : SIMDThreeSameVectorFP<1,1,0b110,"fminp", int_aarch64_neon_fminp>;
4316 defm FMIN    : SIMDThreeSameVectorFP<0,1,0b110,"fmin", fminimum>;
4318 // NOTE: The operands of the PatFrag are reordered on FMLA/FMLS because the
4319 // instruction expects the addend first, while the fma intrinsic puts it last.
4320 defm FMLA     : SIMDThreeSameVectorFPTied<0, 0, 0b001, "fmla",
4321             TriOpFrag<(fma node:$RHS, node:$MHS, node:$LHS)> >;
4322 defm FMLS     : SIMDThreeSameVectorFPTied<0, 1, 0b001, "fmls",
4323             TriOpFrag<(fma node:$MHS, (fneg node:$RHS), node:$LHS)> >;
4325 defm FMULX    : SIMDThreeSameVectorFP<0,0,0b011,"fmulx", int_aarch64_neon_fmulx>;
4326 defm FMUL     : SIMDThreeSameVectorFP<1,0,0b011,"fmul", fmul>;
4327 defm FRECPS   : SIMDThreeSameVectorFP<0,0,0b111,"frecps", int_aarch64_neon_frecps>;
4328 defm FRSQRTS  : SIMDThreeSameVectorFP<0,1,0b111,"frsqrts", int_aarch64_neon_frsqrts>;
4329 defm FSUB     : SIMDThreeSameVectorFP<0,1,0b010,"fsub", fsub>;
4331 // MLA and MLS are generated in MachineCombine
4332 defm MLA      : SIMDThreeSameVectorBHSTied<0, 0b10010, "mla", null_frag>;
4333 defm MLS      : SIMDThreeSameVectorBHSTied<1, 0b10010, "mls", null_frag>;
4335 defm MUL      : SIMDThreeSameVectorBHS<0, 0b10011, "mul", mul>;
4336 defm PMUL     : SIMDThreeSameVectorB<1, 0b10011, "pmul", int_aarch64_neon_pmul>;
4337 defm SABA     : SIMDThreeSameVectorBHSTied<0, 0b01111, "saba",
4338       TriOpFrag<(add node:$LHS, (AArch64sabd node:$MHS, node:$RHS))> >;
4339 defm SABD     : SIMDThreeSameVectorBHS<0,0b01110,"sabd", AArch64sabd>;
4340 defm SHADD    : SIMDThreeSameVectorBHS<0,0b00000,"shadd", AArch64shadd>;
4341 defm SHSUB    : SIMDThreeSameVectorBHS<0,0b00100,"shsub", int_aarch64_neon_shsub>;
4342 defm SMAXP    : SIMDThreeSameVectorBHS<0,0b10100,"smaxp", int_aarch64_neon_smaxp>;
4343 defm SMAX     : SIMDThreeSameVectorBHS<0,0b01100,"smax", smax>;
4344 defm SMINP    : SIMDThreeSameVectorBHS<0,0b10101,"sminp", int_aarch64_neon_sminp>;
4345 defm SMIN     : SIMDThreeSameVectorBHS<0,0b01101,"smin", smin>;
4346 defm SQADD    : SIMDThreeSameVector<0,0b00001,"sqadd", int_aarch64_neon_sqadd>;
4347 defm SQDMULH  : SIMDThreeSameVectorHS<0,0b10110,"sqdmulh",int_aarch64_neon_sqdmulh>;
4348 defm SQRDMULH : SIMDThreeSameVectorHS<1,0b10110,"sqrdmulh",int_aarch64_neon_sqrdmulh>;
4349 defm SQRSHL   : SIMDThreeSameVector<0,0b01011,"sqrshl", int_aarch64_neon_sqrshl>;
4350 defm SQSHL    : SIMDThreeSameVector<0,0b01001,"sqshl", int_aarch64_neon_sqshl>;
4351 defm SQSUB    : SIMDThreeSameVector<0,0b00101,"sqsub", int_aarch64_neon_sqsub>;
4352 defm SRHADD   : SIMDThreeSameVectorBHS<0,0b00010,"srhadd", AArch64srhadd>;
4353 defm SRSHL    : SIMDThreeSameVector<0,0b01010,"srshl", int_aarch64_neon_srshl>;
4354 defm SSHL     : SIMDThreeSameVector<0,0b01000,"sshl", int_aarch64_neon_sshl>;
4355 defm SUB      : SIMDThreeSameVector<1,0b10000,"sub", sub>;
4356 defm UABA     : SIMDThreeSameVectorBHSTied<1, 0b01111, "uaba",
4357       TriOpFrag<(add node:$LHS, (AArch64uabd node:$MHS, node:$RHS))> >;
4358 defm UABD     : SIMDThreeSameVectorBHS<1,0b01110,"uabd", AArch64uabd>;
4359 defm UHADD    : SIMDThreeSameVectorBHS<1,0b00000,"uhadd", AArch64uhadd>;
4360 defm UHSUB    : SIMDThreeSameVectorBHS<1,0b00100,"uhsub", int_aarch64_neon_uhsub>;
4361 defm UMAXP    : SIMDThreeSameVectorBHS<1,0b10100,"umaxp", int_aarch64_neon_umaxp>;
4362 defm UMAX     : SIMDThreeSameVectorBHS<1,0b01100,"umax", umax>;
4363 defm UMINP    : SIMDThreeSameVectorBHS<1,0b10101,"uminp", int_aarch64_neon_uminp>;
4364 defm UMIN     : SIMDThreeSameVectorBHS<1,0b01101,"umin", umin>;
4365 defm UQADD    : SIMDThreeSameVector<1,0b00001,"uqadd", int_aarch64_neon_uqadd>;
4366 defm UQRSHL   : SIMDThreeSameVector<1,0b01011,"uqrshl", int_aarch64_neon_uqrshl>;
4367 defm UQSHL    : SIMDThreeSameVector<1,0b01001,"uqshl", int_aarch64_neon_uqshl>;
4368 defm UQSUB    : SIMDThreeSameVector<1,0b00101,"uqsub", int_aarch64_neon_uqsub>;
4369 defm URHADD   : SIMDThreeSameVectorBHS<1,0b00010,"urhadd", AArch64urhadd>;
4370 defm URSHL    : SIMDThreeSameVector<1,0b01010,"urshl", int_aarch64_neon_urshl>;
4371 defm USHL     : SIMDThreeSameVector<1,0b01000,"ushl", int_aarch64_neon_ushl>;
4372 defm SQRDMLAH : SIMDThreeSameVectorSQRDMLxHTiedHS<1,0b10000,"sqrdmlah",
4373                                                   int_aarch64_neon_sqadd>;
4374 defm SQRDMLSH : SIMDThreeSameVectorSQRDMLxHTiedHS<1,0b10001,"sqrdmlsh",
4375                                                     int_aarch64_neon_sqsub>;
4377 // Extra saturate patterns, other than the intrinsics matches above
4378 defm : SIMDThreeSameVectorExtraPatterns<"SQADD", saddsat>;
4379 defm : SIMDThreeSameVectorExtraPatterns<"UQADD", uaddsat>;
4380 defm : SIMDThreeSameVectorExtraPatterns<"SQSUB", ssubsat>;
4381 defm : SIMDThreeSameVectorExtraPatterns<"UQSUB", usubsat>;
4383 defm AND : SIMDLogicalThreeVector<0, 0b00, "and", and>;
4384 defm BIC : SIMDLogicalThreeVector<0, 0b01, "bic",
4385                                   BinOpFrag<(and node:$LHS, (vnot node:$RHS))> >;
4386 defm EOR : SIMDLogicalThreeVector<1, 0b00, "eor", xor>;
4387 defm ORN : SIMDLogicalThreeVector<0, 0b11, "orn",
4388                                   BinOpFrag<(or node:$LHS, (vnot node:$RHS))> >;
4389 defm ORR : SIMDLogicalThreeVector<0, 0b10, "orr", or>;
4391 // Pseudo bitwise select pattern BSP.
4392 // It is expanded into BSL/BIT/BIF after register allocation.
4393 defm BSP : SIMDLogicalThreeVectorPseudo<TriOpFrag<(or (and node:$LHS, node:$MHS),
4394                                                       (and (vnot node:$LHS), node:$RHS))>>;
4395 defm BSL : SIMDLogicalThreeVectorTied<1, 0b01, "bsl">;
4396 defm BIT : SIMDLogicalThreeVectorTied<1, 0b10, "bit", AArch64bit>;
4397 defm BIF : SIMDLogicalThreeVectorTied<1, 0b11, "bif">;
4399 def : Pat<(AArch64bsp (v8i8 V64:$Rd), V64:$Rn, V64:$Rm),
4400           (BSPv8i8 V64:$Rd, V64:$Rn, V64:$Rm)>;
4401 def : Pat<(AArch64bsp (v4i16 V64:$Rd), V64:$Rn, V64:$Rm),
4402           (BSPv8i8 V64:$Rd, V64:$Rn, V64:$Rm)>;
4403 def : Pat<(AArch64bsp (v2i32 V64:$Rd), V64:$Rn, V64:$Rm),
4404           (BSPv8i8 V64:$Rd, V64:$Rn, V64:$Rm)>;
4405 def : Pat<(AArch64bsp (v1i64 V64:$Rd), V64:$Rn, V64:$Rm),
4406           (BSPv8i8 V64:$Rd, V64:$Rn, V64:$Rm)>;
4408 def : Pat<(AArch64bsp (v16i8 V128:$Rd), V128:$Rn, V128:$Rm),
4409           (BSPv16i8 V128:$Rd, V128:$Rn, V128:$Rm)>;
4410 def : Pat<(AArch64bsp (v8i16 V128:$Rd), V128:$Rn, V128:$Rm),
4411           (BSPv16i8 V128:$Rd, V128:$Rn, V128:$Rm)>;
4412 def : Pat<(AArch64bsp (v4i32 V128:$Rd), V128:$Rn, V128:$Rm),
4413           (BSPv16i8 V128:$Rd, V128:$Rn, V128:$Rm)>;
4414 def : Pat<(AArch64bsp (v2i64 V128:$Rd), V128:$Rn, V128:$Rm),
4415           (BSPv16i8 V128:$Rd, V128:$Rn, V128:$Rm)>;
4417 def : InstAlias<"mov{\t$dst.16b, $src.16b|.16b\t$dst, $src}",
4418                 (ORRv16i8 V128:$dst, V128:$src, V128:$src), 1>;
4419 def : InstAlias<"mov{\t$dst.8h, $src.8h|.8h\t$dst, $src}",
4420                 (ORRv16i8 V128:$dst, V128:$src, V128:$src), 0>;
4421 def : InstAlias<"mov{\t$dst.4s, $src.4s|.4s\t$dst, $src}",
4422                 (ORRv16i8 V128:$dst, V128:$src, V128:$src), 0>;
4423 def : InstAlias<"mov{\t$dst.2d, $src.2d|.2d\t$dst, $src}",
4424                 (ORRv16i8 V128:$dst, V128:$src, V128:$src), 0>;
4426 def : InstAlias<"mov{\t$dst.8b, $src.8b|.8b\t$dst, $src}",
4427                 (ORRv8i8 V64:$dst, V64:$src, V64:$src), 1>;
4428 def : InstAlias<"mov{\t$dst.4h, $src.4h|.4h\t$dst, $src}",
4429                 (ORRv8i8 V64:$dst, V64:$src, V64:$src), 0>;
4430 def : InstAlias<"mov{\t$dst.2s, $src.2s|.2s\t$dst, $src}",
4431                 (ORRv8i8 V64:$dst, V64:$src, V64:$src), 0>;
4432 def : InstAlias<"mov{\t$dst.1d, $src.1d|.1d\t$dst, $src}",
4433                 (ORRv8i8 V64:$dst, V64:$src, V64:$src), 0>;
4435 def : InstAlias<"{cmls\t$dst.8b, $src1.8b, $src2.8b" #
4436                 "|cmls.8b\t$dst, $src1, $src2}",
4437                 (CMHSv8i8 V64:$dst, V64:$src2, V64:$src1), 0>;
4438 def : InstAlias<"{cmls\t$dst.16b, $src1.16b, $src2.16b" #
4439                 "|cmls.16b\t$dst, $src1, $src2}",
4440                 (CMHSv16i8 V128:$dst, V128:$src2, V128:$src1), 0>;
4441 def : InstAlias<"{cmls\t$dst.4h, $src1.4h, $src2.4h" #
4442                 "|cmls.4h\t$dst, $src1, $src2}",
4443                 (CMHSv4i16 V64:$dst, V64:$src2, V64:$src1), 0>;
4444 def : InstAlias<"{cmls\t$dst.8h, $src1.8h, $src2.8h" #
4445                 "|cmls.8h\t$dst, $src1, $src2}",
4446                 (CMHSv8i16 V128:$dst, V128:$src2, V128:$src1), 0>;
4447 def : InstAlias<"{cmls\t$dst.2s, $src1.2s, $src2.2s" #
4448                 "|cmls.2s\t$dst, $src1, $src2}",
4449                 (CMHSv2i32 V64:$dst, V64:$src2, V64:$src1), 0>;
4450 def : InstAlias<"{cmls\t$dst.4s, $src1.4s, $src2.4s" #
4451                 "|cmls.4s\t$dst, $src1, $src2}",
4452                 (CMHSv4i32 V128:$dst, V128:$src2, V128:$src1), 0>;
4453 def : InstAlias<"{cmls\t$dst.2d, $src1.2d, $src2.2d" #
4454                 "|cmls.2d\t$dst, $src1, $src2}",
4455                 (CMHSv2i64 V128:$dst, V128:$src2, V128:$src1), 0>;
4457 def : InstAlias<"{cmlo\t$dst.8b, $src1.8b, $src2.8b" #
4458                 "|cmlo.8b\t$dst, $src1, $src2}",
4459                 (CMHIv8i8 V64:$dst, V64:$src2, V64:$src1), 0>;
4460 def : InstAlias<"{cmlo\t$dst.16b, $src1.16b, $src2.16b" #
4461                 "|cmlo.16b\t$dst, $src1, $src2}",
4462                 (CMHIv16i8 V128:$dst, V128:$src2, V128:$src1), 0>;
4463 def : InstAlias<"{cmlo\t$dst.4h, $src1.4h, $src2.4h" #
4464                 "|cmlo.4h\t$dst, $src1, $src2}",
4465                 (CMHIv4i16 V64:$dst, V64:$src2, V64:$src1), 0>;
4466 def : InstAlias<"{cmlo\t$dst.8h, $src1.8h, $src2.8h" #
4467                 "|cmlo.8h\t$dst, $src1, $src2}",
4468                 (CMHIv8i16 V128:$dst, V128:$src2, V128:$src1), 0>;
4469 def : InstAlias<"{cmlo\t$dst.2s, $src1.2s, $src2.2s" #
4470                 "|cmlo.2s\t$dst, $src1, $src2}",
4471                 (CMHIv2i32 V64:$dst, V64:$src2, V64:$src1), 0>;
4472 def : InstAlias<"{cmlo\t$dst.4s, $src1.4s, $src2.4s" #
4473                 "|cmlo.4s\t$dst, $src1, $src2}",
4474                 (CMHIv4i32 V128:$dst, V128:$src2, V128:$src1), 0>;
4475 def : InstAlias<"{cmlo\t$dst.2d, $src1.2d, $src2.2d" #
4476                 "|cmlo.2d\t$dst, $src1, $src2}",
4477                 (CMHIv2i64 V128:$dst, V128:$src2, V128:$src1), 0>;
4479 def : InstAlias<"{cmle\t$dst.8b, $src1.8b, $src2.8b" #
4480                 "|cmle.8b\t$dst, $src1, $src2}",
4481                 (CMGEv8i8 V64:$dst, V64:$src2, V64:$src1), 0>;
4482 def : InstAlias<"{cmle\t$dst.16b, $src1.16b, $src2.16b" #
4483                 "|cmle.16b\t$dst, $src1, $src2}",
4484                 (CMGEv16i8 V128:$dst, V128:$src2, V128:$src1), 0>;
4485 def : InstAlias<"{cmle\t$dst.4h, $src1.4h, $src2.4h" #
4486                 "|cmle.4h\t$dst, $src1, $src2}",
4487                 (CMGEv4i16 V64:$dst, V64:$src2, V64:$src1), 0>;
4488 def : InstAlias<"{cmle\t$dst.8h, $src1.8h, $src2.8h" #
4489                 "|cmle.8h\t$dst, $src1, $src2}",
4490                 (CMGEv8i16 V128:$dst, V128:$src2, V128:$src1), 0>;
4491 def : InstAlias<"{cmle\t$dst.2s, $src1.2s, $src2.2s" #
4492                 "|cmle.2s\t$dst, $src1, $src2}",
4493                 (CMGEv2i32 V64:$dst, V64:$src2, V64:$src1), 0>;
4494 def : InstAlias<"{cmle\t$dst.4s, $src1.4s, $src2.4s" #
4495                 "|cmle.4s\t$dst, $src1, $src2}",
4496                 (CMGEv4i32 V128:$dst, V128:$src2, V128:$src1), 0>;
4497 def : InstAlias<"{cmle\t$dst.2d, $src1.2d, $src2.2d" #
4498                 "|cmle.2d\t$dst, $src1, $src2}",
4499                 (CMGEv2i64 V128:$dst, V128:$src2, V128:$src1), 0>;
4501 def : InstAlias<"{cmlt\t$dst.8b, $src1.8b, $src2.8b" #
4502                 "|cmlt.8b\t$dst, $src1, $src2}",
4503                 (CMGTv8i8 V64:$dst, V64:$src2, V64:$src1), 0>;
4504 def : InstAlias<"{cmlt\t$dst.16b, $src1.16b, $src2.16b" #
4505                 "|cmlt.16b\t$dst, $src1, $src2}",
4506                 (CMGTv16i8 V128:$dst, V128:$src2, V128:$src1), 0>;
4507 def : InstAlias<"{cmlt\t$dst.4h, $src1.4h, $src2.4h" #
4508                 "|cmlt.4h\t$dst, $src1, $src2}",
4509                 (CMGTv4i16 V64:$dst, V64:$src2, V64:$src1), 0>;
4510 def : InstAlias<"{cmlt\t$dst.8h, $src1.8h, $src2.8h" #
4511                 "|cmlt.8h\t$dst, $src1, $src2}",
4512                 (CMGTv8i16 V128:$dst, V128:$src2, V128:$src1), 0>;
4513 def : InstAlias<"{cmlt\t$dst.2s, $src1.2s, $src2.2s" #
4514                 "|cmlt.2s\t$dst, $src1, $src2}",
4515                 (CMGTv2i32 V64:$dst, V64:$src2, V64:$src1), 0>;
4516 def : InstAlias<"{cmlt\t$dst.4s, $src1.4s, $src2.4s" #
4517                 "|cmlt.4s\t$dst, $src1, $src2}",
4518                 (CMGTv4i32 V128:$dst, V128:$src2, V128:$src1), 0>;
4519 def : InstAlias<"{cmlt\t$dst.2d, $src1.2d, $src2.2d" #
4520                 "|cmlt.2d\t$dst, $src1, $src2}",
4521                 (CMGTv2i64 V128:$dst, V128:$src2, V128:$src1), 0>;
4523 let Predicates = [HasNEON, HasFullFP16] in {
4524 def : InstAlias<"{fcmle\t$dst.4h, $src1.4h, $src2.4h" #
4525                 "|fcmle.4h\t$dst, $src1, $src2}",
4526                 (FCMGEv4f16 V64:$dst, V64:$src2, V64:$src1), 0>;
4527 def : InstAlias<"{fcmle\t$dst.8h, $src1.8h, $src2.8h" #
4528                 "|fcmle.8h\t$dst, $src1, $src2}",
4529                 (FCMGEv8f16 V128:$dst, V128:$src2, V128:$src1), 0>;
4531 def : InstAlias<"{fcmle\t$dst.2s, $src1.2s, $src2.2s" #
4532                 "|fcmle.2s\t$dst, $src1, $src2}",
4533                 (FCMGEv2f32 V64:$dst, V64:$src2, V64:$src1), 0>;
4534 def : InstAlias<"{fcmle\t$dst.4s, $src1.4s, $src2.4s" #
4535                 "|fcmle.4s\t$dst, $src1, $src2}",
4536                 (FCMGEv4f32 V128:$dst, V128:$src2, V128:$src1), 0>;
4537 def : InstAlias<"{fcmle\t$dst.2d, $src1.2d, $src2.2d" #
4538                 "|fcmle.2d\t$dst, $src1, $src2}",
4539                 (FCMGEv2f64 V128:$dst, V128:$src2, V128:$src1), 0>;
4541 let Predicates = [HasNEON, HasFullFP16] in {
4542 def : InstAlias<"{fcmlt\t$dst.4h, $src1.4h, $src2.4h" #
4543                 "|fcmlt.4h\t$dst, $src1, $src2}",
4544                 (FCMGTv4f16 V64:$dst, V64:$src2, V64:$src1), 0>;
4545 def : InstAlias<"{fcmlt\t$dst.8h, $src1.8h, $src2.8h" #
4546                 "|fcmlt.8h\t$dst, $src1, $src2}",
4547                 (FCMGTv8f16 V128:$dst, V128:$src2, V128:$src1), 0>;
4549 def : InstAlias<"{fcmlt\t$dst.2s, $src1.2s, $src2.2s" #
4550                 "|fcmlt.2s\t$dst, $src1, $src2}",
4551                 (FCMGTv2f32 V64:$dst, V64:$src2, V64:$src1), 0>;
4552 def : InstAlias<"{fcmlt\t$dst.4s, $src1.4s, $src2.4s" #
4553                 "|fcmlt.4s\t$dst, $src1, $src2}",
4554                 (FCMGTv4f32 V128:$dst, V128:$src2, V128:$src1), 0>;
4555 def : InstAlias<"{fcmlt\t$dst.2d, $src1.2d, $src2.2d" #
4556                 "|fcmlt.2d\t$dst, $src1, $src2}",
4557                 (FCMGTv2f64 V128:$dst, V128:$src2, V128:$src1), 0>;
4559 let Predicates = [HasNEON, HasFullFP16] in {
4560 def : InstAlias<"{facle\t$dst.4h, $src1.4h, $src2.4h" #
4561                 "|facle.4h\t$dst, $src1, $src2}",
4562                 (FACGEv4f16 V64:$dst, V64:$src2, V64:$src1), 0>;
4563 def : InstAlias<"{facle\t$dst.8h, $src1.8h, $src2.8h" #
4564                 "|facle.8h\t$dst, $src1, $src2}",
4565                 (FACGEv8f16 V128:$dst, V128:$src2, V128:$src1), 0>;
4567 def : InstAlias<"{facle\t$dst.2s, $src1.2s, $src2.2s" #
4568                 "|facle.2s\t$dst, $src1, $src2}",
4569                 (FACGEv2f32 V64:$dst, V64:$src2, V64:$src1), 0>;
4570 def : InstAlias<"{facle\t$dst.4s, $src1.4s, $src2.4s" #
4571                 "|facle.4s\t$dst, $src1, $src2}",
4572                 (FACGEv4f32 V128:$dst, V128:$src2, V128:$src1), 0>;
4573 def : InstAlias<"{facle\t$dst.2d, $src1.2d, $src2.2d" #
4574                 "|facle.2d\t$dst, $src1, $src2}",
4575                 (FACGEv2f64 V128:$dst, V128:$src2, V128:$src1), 0>;
4577 let Predicates = [HasNEON, HasFullFP16] in {
4578 def : InstAlias<"{faclt\t$dst.4h, $src1.4h, $src2.4h" #
4579                 "|faclt.4h\t$dst, $src1, $src2}",
4580                 (FACGTv4f16 V64:$dst, V64:$src2, V64:$src1), 0>;
4581 def : InstAlias<"{faclt\t$dst.8h, $src1.8h, $src2.8h" #
4582                 "|faclt.8h\t$dst, $src1, $src2}",
4583                 (FACGTv8f16 V128:$dst, V128:$src2, V128:$src1), 0>;
4585 def : InstAlias<"{faclt\t$dst.2s, $src1.2s, $src2.2s" #
4586                 "|faclt.2s\t$dst, $src1, $src2}",
4587                 (FACGTv2f32 V64:$dst, V64:$src2, V64:$src1), 0>;
4588 def : InstAlias<"{faclt\t$dst.4s, $src1.4s, $src2.4s" #
4589                 "|faclt.4s\t$dst, $src1, $src2}",
4590                 (FACGTv4f32 V128:$dst, V128:$src2, V128:$src1), 0>;
4591 def : InstAlias<"{faclt\t$dst.2d, $src1.2d, $src2.2d" #
4592                 "|faclt.2d\t$dst, $src1, $src2}",
4593                 (FACGTv2f64 V128:$dst, V128:$src2, V128:$src1), 0>;
4595 //===----------------------------------------------------------------------===//
4596 // Advanced SIMD three scalar instructions.
4597 //===----------------------------------------------------------------------===//
4599 defm ADD      : SIMDThreeScalarD<0, 0b10000, "add", add>;
4600 defm CMEQ     : SIMDThreeScalarD<1, 0b10001, "cmeq", AArch64cmeq>;
4601 defm CMGE     : SIMDThreeScalarD<0, 0b00111, "cmge", AArch64cmge>;
4602 defm CMGT     : SIMDThreeScalarD<0, 0b00110, "cmgt", AArch64cmgt>;
4603 defm CMHI     : SIMDThreeScalarD<1, 0b00110, "cmhi", AArch64cmhi>;
4604 defm CMHS     : SIMDThreeScalarD<1, 0b00111, "cmhs", AArch64cmhs>;
4605 defm CMTST    : SIMDThreeScalarD<0, 0b10001, "cmtst", AArch64cmtst>;
4606 defm FABD     : SIMDFPThreeScalar<1, 1, 0b010, "fabd", int_aarch64_sisd_fabd>;
4607 def : Pat<(v1f64 (int_aarch64_neon_fabd (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
4608           (FABD64 FPR64:$Rn, FPR64:$Rm)>;
4609 let Predicates = [HasFullFP16] in {
4610 def : Pat<(fabs (fsub f16:$Rn, f16:$Rm)), (FABD16 f16:$Rn, f16:$Rm)>;
4612 def : Pat<(fabs (fsub f32:$Rn, f32:$Rm)), (FABD32 f32:$Rn, f32:$Rm)>;
4613 def : Pat<(fabs (fsub f64:$Rn, f64:$Rm)), (FABD64 f64:$Rn, f64:$Rm)>;
4614 defm FACGE    : SIMDThreeScalarFPCmp<1, 0, 0b101, "facge",
4615                                      int_aarch64_neon_facge>;
4616 defm FACGT    : SIMDThreeScalarFPCmp<1, 1, 0b101, "facgt",
4617                                      int_aarch64_neon_facgt>;
4618 defm FCMEQ    : SIMDThreeScalarFPCmp<0, 0, 0b100, "fcmeq", AArch64fcmeq>;
4619 defm FCMGE    : SIMDThreeScalarFPCmp<1, 0, 0b100, "fcmge", AArch64fcmge>;
4620 defm FCMGT    : SIMDThreeScalarFPCmp<1, 1, 0b100, "fcmgt", AArch64fcmgt>;
4621 defm FMULX    : SIMDFPThreeScalar<0, 0, 0b011, "fmulx", int_aarch64_neon_fmulx>;
4622 defm FRECPS   : SIMDFPThreeScalar<0, 0, 0b111, "frecps", int_aarch64_neon_frecps>;
4623 defm FRSQRTS  : SIMDFPThreeScalar<0, 1, 0b111, "frsqrts", int_aarch64_neon_frsqrts>;
4624 defm SQADD    : SIMDThreeScalarBHSD<0, 0b00001, "sqadd", int_aarch64_neon_sqadd>;
4625 defm SQDMULH  : SIMDThreeScalarHS<  0, 0b10110, "sqdmulh", int_aarch64_neon_sqdmulh>;
4626 defm SQRDMULH : SIMDThreeScalarHS<  1, 0b10110, "sqrdmulh", int_aarch64_neon_sqrdmulh>;
4627 defm SQRSHL   : SIMDThreeScalarBHSD<0, 0b01011, "sqrshl",int_aarch64_neon_sqrshl>;
4628 defm SQSHL    : SIMDThreeScalarBHSD<0, 0b01001, "sqshl", int_aarch64_neon_sqshl>;
4629 defm SQSUB    : SIMDThreeScalarBHSD<0, 0b00101, "sqsub", int_aarch64_neon_sqsub>;
4630 defm SRSHL    : SIMDThreeScalarD<   0, 0b01010, "srshl", int_aarch64_neon_srshl>;
4631 defm SSHL     : SIMDThreeScalarD<   0, 0b01000, "sshl", int_aarch64_neon_sshl>;
4632 defm SUB      : SIMDThreeScalarD<   1, 0b10000, "sub", sub>;
4633 defm UQADD    : SIMDThreeScalarBHSD<1, 0b00001, "uqadd", int_aarch64_neon_uqadd>;
4634 defm UQRSHL   : SIMDThreeScalarBHSD<1, 0b01011, "uqrshl",int_aarch64_neon_uqrshl>;
4635 defm UQSHL    : SIMDThreeScalarBHSD<1, 0b01001, "uqshl", int_aarch64_neon_uqshl>;
4636 defm UQSUB    : SIMDThreeScalarBHSD<1, 0b00101, "uqsub", int_aarch64_neon_uqsub>;
4637 defm URSHL    : SIMDThreeScalarD<   1, 0b01010, "urshl", int_aarch64_neon_urshl>;
4638 defm USHL     : SIMDThreeScalarD<   1, 0b01000, "ushl", int_aarch64_neon_ushl>;
4639 let Predicates = [HasRDM] in {
4640   defm SQRDMLAH : SIMDThreeScalarHSTied<1, 0, 0b10000, "sqrdmlah">;
4641   defm SQRDMLSH : SIMDThreeScalarHSTied<1, 0, 0b10001, "sqrdmlsh">;
4642   def : Pat<(i32 (int_aarch64_neon_sqadd
4643                    (i32 FPR32:$Rd),
4644                    (i32 (int_aarch64_neon_sqrdmulh (i32 FPR32:$Rn),
4645                                                    (i32 FPR32:$Rm))))),
4646             (SQRDMLAHv1i32 FPR32:$Rd, FPR32:$Rn, FPR32:$Rm)>;
4647   def : Pat<(i32 (int_aarch64_neon_sqsub
4648                    (i32 FPR32:$Rd),
4649                    (i32 (int_aarch64_neon_sqrdmulh (i32 FPR32:$Rn),
4650                                                    (i32 FPR32:$Rm))))),
4651             (SQRDMLSHv1i32 FPR32:$Rd, FPR32:$Rn, FPR32:$Rm)>;
4654 def : InstAlias<"cmls $dst, $src1, $src2",
4655                 (CMHSv1i64 FPR64:$dst, FPR64:$src2, FPR64:$src1), 0>;
4656 def : InstAlias<"cmle $dst, $src1, $src2",
4657                 (CMGEv1i64 FPR64:$dst, FPR64:$src2, FPR64:$src1), 0>;
4658 def : InstAlias<"cmlo $dst, $src1, $src2",
4659                 (CMHIv1i64 FPR64:$dst, FPR64:$src2, FPR64:$src1), 0>;
4660 def : InstAlias<"cmlt $dst, $src1, $src2",
4661                 (CMGTv1i64 FPR64:$dst, FPR64:$src2, FPR64:$src1), 0>;
4662 def : InstAlias<"fcmle $dst, $src1, $src2",
4663                 (FCMGE32 FPR32:$dst, FPR32:$src2, FPR32:$src1), 0>;
4664 def : InstAlias<"fcmle $dst, $src1, $src2",
4665                 (FCMGE64 FPR64:$dst, FPR64:$src2, FPR64:$src1), 0>;
4666 def : InstAlias<"fcmlt $dst, $src1, $src2",
4667                 (FCMGT32 FPR32:$dst, FPR32:$src2, FPR32:$src1), 0>;
4668 def : InstAlias<"fcmlt $dst, $src1, $src2",
4669                 (FCMGT64 FPR64:$dst, FPR64:$src2, FPR64:$src1), 0>;
4670 def : InstAlias<"facle $dst, $src1, $src2",
4671                 (FACGE32 FPR32:$dst, FPR32:$src2, FPR32:$src1), 0>;
4672 def : InstAlias<"facle $dst, $src1, $src2",
4673                 (FACGE64 FPR64:$dst, FPR64:$src2, FPR64:$src1), 0>;
4674 def : InstAlias<"faclt $dst, $src1, $src2",
4675                 (FACGT32 FPR32:$dst, FPR32:$src2, FPR32:$src1), 0>;
4676 def : InstAlias<"faclt $dst, $src1, $src2",
4677                 (FACGT64 FPR64:$dst, FPR64:$src2, FPR64:$src1), 0>;
4679 //===----------------------------------------------------------------------===//
4680 // Advanced SIMD three scalar instructions (mixed operands).
4681 //===----------------------------------------------------------------------===//
4682 defm SQDMULL  : SIMDThreeScalarMixedHS<0, 0b11010, "sqdmull",
4683                                        int_aarch64_neon_sqdmulls_scalar>;
4684 defm SQDMLAL  : SIMDThreeScalarMixedTiedHS<0, 0b10010, "sqdmlal">;
4685 defm SQDMLSL  : SIMDThreeScalarMixedTiedHS<0, 0b10110, "sqdmlsl">;
4687 def : Pat<(i64 (int_aarch64_neon_sqadd (i64 FPR64:$Rd),
4688                    (i64 (int_aarch64_neon_sqdmulls_scalar (i32 FPR32:$Rn),
4689                                                         (i32 FPR32:$Rm))))),
4690           (SQDMLALi32 FPR64:$Rd, FPR32:$Rn, FPR32:$Rm)>;
4691 def : Pat<(i64 (int_aarch64_neon_sqsub (i64 FPR64:$Rd),
4692                    (i64 (int_aarch64_neon_sqdmulls_scalar (i32 FPR32:$Rn),
4693                                                         (i32 FPR32:$Rm))))),
4694           (SQDMLSLi32 FPR64:$Rd, FPR32:$Rn, FPR32:$Rm)>;
4696 //===----------------------------------------------------------------------===//
4697 // Advanced SIMD two scalar instructions.
4698 //===----------------------------------------------------------------------===//
4700 defm ABS    : SIMDTwoScalarD<    0, 0b01011, "abs", abs>;
4701 defm CMEQ   : SIMDCmpTwoScalarD< 0, 0b01001, "cmeq", AArch64cmeqz>;
4702 defm CMGE   : SIMDCmpTwoScalarD< 1, 0b01000, "cmge", AArch64cmgez>;
4703 defm CMGT   : SIMDCmpTwoScalarD< 0, 0b01000, "cmgt", AArch64cmgtz>;
4704 defm CMLE   : SIMDCmpTwoScalarD< 1, 0b01001, "cmle", AArch64cmlez>;
4705 defm CMLT   : SIMDCmpTwoScalarD< 0, 0b01010, "cmlt", AArch64cmltz>;
4706 defm FCMEQ  : SIMDFPCmpTwoScalar<0, 1, 0b01101, "fcmeq", AArch64fcmeqz>;
4707 defm FCMGE  : SIMDFPCmpTwoScalar<1, 1, 0b01100, "fcmge", AArch64fcmgez>;
4708 defm FCMGT  : SIMDFPCmpTwoScalar<0, 1, 0b01100, "fcmgt", AArch64fcmgtz>;
4709 defm FCMLE  : SIMDFPCmpTwoScalar<1, 1, 0b01101, "fcmle", AArch64fcmlez>;
4710 defm FCMLT  : SIMDFPCmpTwoScalar<0, 1, 0b01110, "fcmlt", AArch64fcmltz>;
4711 defm FCVTAS : SIMDFPTwoScalar<   0, 0, 0b11100, "fcvtas">;
4712 defm FCVTAU : SIMDFPTwoScalar<   1, 0, 0b11100, "fcvtau">;
4713 defm FCVTMS : SIMDFPTwoScalar<   0, 0, 0b11011, "fcvtms">;
4714 defm FCVTMU : SIMDFPTwoScalar<   1, 0, 0b11011, "fcvtmu">;
4715 defm FCVTNS : SIMDFPTwoScalar<   0, 0, 0b11010, "fcvtns">;
4716 defm FCVTNU : SIMDFPTwoScalar<   1, 0, 0b11010, "fcvtnu">;
4717 defm FCVTPS : SIMDFPTwoScalar<   0, 1, 0b11010, "fcvtps">;
4718 defm FCVTPU : SIMDFPTwoScalar<   1, 1, 0b11010, "fcvtpu">;
4719 def  FCVTXNv1i64 : SIMDInexactCvtTwoScalar<0b10110, "fcvtxn">;
4720 defm FCVTZS : SIMDFPTwoScalar<   0, 1, 0b11011, "fcvtzs">;
4721 defm FCVTZU : SIMDFPTwoScalar<   1, 1, 0b11011, "fcvtzu">;
4722 defm FRECPE : SIMDFPTwoScalar<   0, 1, 0b11101, "frecpe">;
4723 defm FRECPX : SIMDFPTwoScalar<   0, 1, 0b11111, "frecpx">;
4724 defm FRSQRTE : SIMDFPTwoScalar<  1, 1, 0b11101, "frsqrte">;
4725 defm NEG    : SIMDTwoScalarD<    1, 0b01011, "neg",
4726                                  UnOpFrag<(sub immAllZerosV, node:$LHS)> >;
4727 defm SCVTF  : SIMDFPTwoScalarCVT<   0, 0, 0b11101, "scvtf", AArch64sitof>;
4728 defm SQABS  : SIMDTwoScalarBHSD< 0, 0b00111, "sqabs", int_aarch64_neon_sqabs>;
4729 defm SQNEG  : SIMDTwoScalarBHSD< 1, 0b00111, "sqneg", int_aarch64_neon_sqneg>;
4730 defm SQXTN  : SIMDTwoScalarMixedBHS< 0, 0b10100, "sqxtn", int_aarch64_neon_scalar_sqxtn>;
4731 defm SQXTUN : SIMDTwoScalarMixedBHS< 1, 0b10010, "sqxtun", int_aarch64_neon_scalar_sqxtun>;
4732 defm SUQADD : SIMDTwoScalarBHSDTied< 0, 0b00011, "suqadd",
4733                                      int_aarch64_neon_suqadd>;
4734 defm UCVTF  : SIMDFPTwoScalarCVT<   1, 0, 0b11101, "ucvtf", AArch64uitof>;
4735 defm UQXTN  : SIMDTwoScalarMixedBHS<1, 0b10100, "uqxtn", int_aarch64_neon_scalar_uqxtn>;
4736 defm USQADD : SIMDTwoScalarBHSDTied< 1, 0b00011, "usqadd",
4737                                     int_aarch64_neon_usqadd>;
4739 def : Pat<(v1i64 (int_aarch64_neon_fcvtas (v1f64 FPR64:$Rn))),
4740           (FCVTASv1i64 FPR64:$Rn)>;
4741 def : Pat<(v1i64 (int_aarch64_neon_fcvtau (v1f64 FPR64:$Rn))),
4742           (FCVTAUv1i64 FPR64:$Rn)>;
4743 def : Pat<(v1i64 (int_aarch64_neon_fcvtms (v1f64 FPR64:$Rn))),
4744           (FCVTMSv1i64 FPR64:$Rn)>;
4745 def : Pat<(v1i64 (int_aarch64_neon_fcvtmu (v1f64 FPR64:$Rn))),
4746           (FCVTMUv1i64 FPR64:$Rn)>;
4747 def : Pat<(v1i64 (int_aarch64_neon_fcvtns (v1f64 FPR64:$Rn))),
4748           (FCVTNSv1i64 FPR64:$Rn)>;
4749 def : Pat<(v1i64 (int_aarch64_neon_fcvtnu (v1f64 FPR64:$Rn))),
4750           (FCVTNUv1i64 FPR64:$Rn)>;
4751 def : Pat<(v1i64 (int_aarch64_neon_fcvtps (v1f64 FPR64:$Rn))),
4752           (FCVTPSv1i64 FPR64:$Rn)>;
4753 def : Pat<(v1i64 (int_aarch64_neon_fcvtpu (v1f64 FPR64:$Rn))),
4754           (FCVTPUv1i64 FPR64:$Rn)>;
4755 def : Pat<(v1i64 (int_aarch64_neon_fcvtzs (v1f64 FPR64:$Rn))),
4756           (FCVTZSv1i64 FPR64:$Rn)>;
4757 def : Pat<(v1i64 (int_aarch64_neon_fcvtzu (v1f64 FPR64:$Rn))),
4758           (FCVTZUv1i64 FPR64:$Rn)>;
4760 def : Pat<(f16 (int_aarch64_neon_frecpe (f16 FPR16:$Rn))),
4761           (FRECPEv1f16 FPR16:$Rn)>;
4762 def : Pat<(f32 (int_aarch64_neon_frecpe (f32 FPR32:$Rn))),
4763           (FRECPEv1i32 FPR32:$Rn)>;
4764 def : Pat<(f64 (int_aarch64_neon_frecpe (f64 FPR64:$Rn))),
4765           (FRECPEv1i64 FPR64:$Rn)>;
4766 def : Pat<(v1f64 (int_aarch64_neon_frecpe (v1f64 FPR64:$Rn))),
4767           (FRECPEv1i64 FPR64:$Rn)>;
4769 def : Pat<(f32 (AArch64frecpe (f32 FPR32:$Rn))),
4770           (FRECPEv1i32 FPR32:$Rn)>;
4771 def : Pat<(v2f32 (AArch64frecpe (v2f32 V64:$Rn))),
4772           (FRECPEv2f32 V64:$Rn)>;
4773 def : Pat<(v4f32 (AArch64frecpe (v4f32 FPR128:$Rn))),
4774           (FRECPEv4f32 FPR128:$Rn)>;
4775 def : Pat<(f64 (AArch64frecpe (f64 FPR64:$Rn))),
4776           (FRECPEv1i64 FPR64:$Rn)>;
4777 def : Pat<(v1f64 (AArch64frecpe (v1f64 FPR64:$Rn))),
4778           (FRECPEv1i64 FPR64:$Rn)>;
4779 def : Pat<(v2f64 (AArch64frecpe (v2f64 FPR128:$Rn))),
4780           (FRECPEv2f64 FPR128:$Rn)>;
4782 def : Pat<(f32 (AArch64frecps (f32 FPR32:$Rn), (f32 FPR32:$Rm))),
4783           (FRECPS32 FPR32:$Rn, FPR32:$Rm)>;
4784 def : Pat<(v2f32 (AArch64frecps (v2f32 V64:$Rn), (v2f32 V64:$Rm))),
4785           (FRECPSv2f32 V64:$Rn, V64:$Rm)>;
4786 def : Pat<(v4f32 (AArch64frecps (v4f32 FPR128:$Rn), (v4f32 FPR128:$Rm))),
4787           (FRECPSv4f32 FPR128:$Rn, FPR128:$Rm)>;
4788 def : Pat<(f64 (AArch64frecps (f64 FPR64:$Rn), (f64 FPR64:$Rm))),
4789           (FRECPS64 FPR64:$Rn, FPR64:$Rm)>;
4790 def : Pat<(v2f64 (AArch64frecps (v2f64 FPR128:$Rn), (v2f64 FPR128:$Rm))),
4791           (FRECPSv2f64 FPR128:$Rn, FPR128:$Rm)>;
4793 def : Pat<(f16 (int_aarch64_neon_frecpx (f16 FPR16:$Rn))),
4794           (FRECPXv1f16 FPR16:$Rn)>;
4795 def : Pat<(f32 (int_aarch64_neon_frecpx (f32 FPR32:$Rn))),
4796           (FRECPXv1i32 FPR32:$Rn)>;
4797 def : Pat<(f64 (int_aarch64_neon_frecpx (f64 FPR64:$Rn))),
4798           (FRECPXv1i64 FPR64:$Rn)>;
4800 def : Pat<(f16 (int_aarch64_neon_frsqrte (f16 FPR16:$Rn))),
4801           (FRSQRTEv1f16 FPR16:$Rn)>;
4802 def : Pat<(f32 (int_aarch64_neon_frsqrte (f32 FPR32:$Rn))),
4803           (FRSQRTEv1i32 FPR32:$Rn)>;
4804 def : Pat<(f64 (int_aarch64_neon_frsqrte (f64 FPR64:$Rn))),
4805           (FRSQRTEv1i64 FPR64:$Rn)>;
4806 def : Pat<(v1f64 (int_aarch64_neon_frsqrte (v1f64 FPR64:$Rn))),
4807           (FRSQRTEv1i64 FPR64:$Rn)>;
4809 def : Pat<(f32 (AArch64frsqrte (f32 FPR32:$Rn))),
4810           (FRSQRTEv1i32 FPR32:$Rn)>;
4811 def : Pat<(v2f32 (AArch64frsqrte (v2f32 V64:$Rn))),
4812           (FRSQRTEv2f32 V64:$Rn)>;
4813 def : Pat<(v4f32 (AArch64frsqrte (v4f32 FPR128:$Rn))),
4814           (FRSQRTEv4f32 FPR128:$Rn)>;
4815 def : Pat<(f64 (AArch64frsqrte (f64 FPR64:$Rn))),
4816           (FRSQRTEv1i64 FPR64:$Rn)>;
4817 def : Pat<(v1f64 (AArch64frsqrte (v1f64 FPR64:$Rn))),
4818           (FRSQRTEv1i64 FPR64:$Rn)>;
4819 def : Pat<(v2f64 (AArch64frsqrte (v2f64 FPR128:$Rn))),
4820           (FRSQRTEv2f64 FPR128:$Rn)>;
4822 def : Pat<(f32 (AArch64frsqrts (f32 FPR32:$Rn), (f32 FPR32:$Rm))),
4823           (FRSQRTS32 FPR32:$Rn, FPR32:$Rm)>;
4824 def : Pat<(v2f32 (AArch64frsqrts (v2f32 V64:$Rn), (v2f32 V64:$Rm))),
4825           (FRSQRTSv2f32 V64:$Rn, V64:$Rm)>;
4826 def : Pat<(v4f32 (AArch64frsqrts (v4f32 FPR128:$Rn), (v4f32 FPR128:$Rm))),
4827           (FRSQRTSv4f32 FPR128:$Rn, FPR128:$Rm)>;
4828 def : Pat<(f64 (AArch64frsqrts (f64 FPR64:$Rn), (f64 FPR64:$Rm))),
4829           (FRSQRTS64 FPR64:$Rn, FPR64:$Rm)>;
4830 def : Pat<(v2f64 (AArch64frsqrts (v2f64 FPR128:$Rn), (v2f64 FPR128:$Rm))),
4831           (FRSQRTSv2f64 FPR128:$Rn, FPR128:$Rm)>;
4833 // Some float -> int -> float conversion patterns for which we want to keep the
4834 // int values in FP registers using the corresponding NEON instructions to
4835 // avoid more costly int <-> fp register transfers.
4836 let Predicates = [HasNEON] in {
4837 def : Pat<(f64 (sint_to_fp (i64 (fp_to_sint f64:$Rn)))),
4838           (SCVTFv1i64 (i64 (FCVTZSv1i64 f64:$Rn)))>;
4839 def : Pat<(f32 (sint_to_fp (i32 (fp_to_sint f32:$Rn)))),
4840           (SCVTFv1i32 (i32 (FCVTZSv1i32 f32:$Rn)))>;
4841 def : Pat<(f64 (uint_to_fp (i64 (fp_to_uint f64:$Rn)))),
4842           (UCVTFv1i64 (i64 (FCVTZUv1i64 f64:$Rn)))>;
4843 def : Pat<(f32 (uint_to_fp (i32 (fp_to_uint f32:$Rn)))),
4844           (UCVTFv1i32 (i32 (FCVTZUv1i32 f32:$Rn)))>;
4846 let Predicates = [HasFullFP16] in {
4847 def : Pat<(f16 (sint_to_fp (i32 (fp_to_sint f16:$Rn)))),
4848           (SCVTFv1i16 (f16 (FCVTZSv1f16 f16:$Rn)))>;
4849 def : Pat<(f16 (uint_to_fp (i32 (fp_to_uint f16:$Rn)))),
4850           (UCVTFv1i16 (f16 (FCVTZUv1f16 f16:$Rn)))>;
4854 // If an integer is about to be converted to a floating point value,
4855 // just load it on the floating point unit.
4856 // Here are the patterns for 8 and 16-bits to float.
4857 // 8-bits -> float.
4858 multiclass UIntToFPROLoadPat<ValueType DstTy, ValueType SrcTy,
4859                              SDPatternOperator loadop, Instruction UCVTF,
4860                              ROAddrMode ro, Instruction LDRW, Instruction LDRX,
4861                              SubRegIndex sub> {
4862   def : Pat<(DstTy (uint_to_fp (SrcTy
4863                      (loadop (ro.Wpat GPR64sp:$Rn, GPR32:$Rm,
4864                                       ro.Wext:$extend))))),
4865            (UCVTF (INSERT_SUBREG (DstTy (IMPLICIT_DEF)),
4866                                  (LDRW GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend),
4867                                  sub))>;
4869   def : Pat<(DstTy (uint_to_fp (SrcTy
4870                      (loadop (ro.Xpat GPR64sp:$Rn, GPR64:$Rm,
4871                                       ro.Wext:$extend))))),
4872            (UCVTF (INSERT_SUBREG (DstTy (IMPLICIT_DEF)),
4873                                  (LDRX GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend),
4874                                  sub))>;
4877 defm : UIntToFPROLoadPat<f32, i32, zextloadi8,
4878                          UCVTFv1i32, ro8, LDRBroW, LDRBroX, bsub>;
4879 def : Pat <(f32 (uint_to_fp (i32
4880                (zextloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))))),
4881            (UCVTFv1i32 (INSERT_SUBREG (f32 (IMPLICIT_DEF)),
4882                           (LDRBui GPR64sp:$Rn, uimm12s1:$offset), bsub))>;
4883 def : Pat <(f32 (uint_to_fp (i32
4884                      (zextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))))),
4885            (UCVTFv1i32 (INSERT_SUBREG (f32 (IMPLICIT_DEF)),
4886                           (LDURBi GPR64sp:$Rn, simm9:$offset), bsub))>;
4887 // 16-bits -> float.
4888 defm : UIntToFPROLoadPat<f32, i32, zextloadi16,
4889                          UCVTFv1i32, ro16, LDRHroW, LDRHroX, hsub>;
4890 def : Pat <(f32 (uint_to_fp (i32
4891                   (zextloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))))),
4892            (UCVTFv1i32 (INSERT_SUBREG (f32 (IMPLICIT_DEF)),
4893                           (LDRHui GPR64sp:$Rn, uimm12s2:$offset), hsub))>;
4894 def : Pat <(f32 (uint_to_fp (i32
4895                   (zextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))))),
4896            (UCVTFv1i32 (INSERT_SUBREG (f32 (IMPLICIT_DEF)),
4897                           (LDURHi GPR64sp:$Rn, simm9:$offset), hsub))>;
4898 // 32-bits are handled in target specific dag combine:
4899 // performIntToFpCombine.
4900 // 64-bits integer to 32-bits floating point, not possible with
4901 // UCVTF on floating point registers (both source and destination
4902 // must have the same size).
4904 // Here are the patterns for 8, 16, 32, and 64-bits to double.
4905 // 8-bits -> double.
4906 defm : UIntToFPROLoadPat<f64, i32, zextloadi8,
4907                          UCVTFv1i64, ro8, LDRBroW, LDRBroX, bsub>;
4908 def : Pat <(f64 (uint_to_fp (i32
4909                     (zextloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))))),
4910            (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
4911                           (LDRBui GPR64sp:$Rn, uimm12s1:$offset), bsub))>;
4912 def : Pat <(f64 (uint_to_fp (i32
4913                   (zextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))))),
4914            (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
4915                           (LDURBi GPR64sp:$Rn, simm9:$offset), bsub))>;
4916 // 16-bits -> double.
4917 defm : UIntToFPROLoadPat<f64, i32, zextloadi16,
4918                          UCVTFv1i64, ro16, LDRHroW, LDRHroX, hsub>;
4919 def : Pat <(f64 (uint_to_fp (i32
4920                   (zextloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))))),
4921            (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
4922                           (LDRHui GPR64sp:$Rn, uimm12s2:$offset), hsub))>;
4923 def : Pat <(f64 (uint_to_fp (i32
4924                   (zextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))))),
4925            (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
4926                           (LDURHi GPR64sp:$Rn, simm9:$offset), hsub))>;
4927 // 32-bits -> double.
4928 defm : UIntToFPROLoadPat<f64, i32, load,
4929                          UCVTFv1i64, ro32, LDRSroW, LDRSroX, ssub>;
4930 def : Pat <(f64 (uint_to_fp (i32
4931                   (load (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))))),
4932            (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
4933                           (LDRSui GPR64sp:$Rn, uimm12s4:$offset), ssub))>;
4934 def : Pat <(f64 (uint_to_fp (i32
4935                   (load (am_unscaled32 GPR64sp:$Rn, simm9:$offset))))),
4936            (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
4937                           (LDURSi GPR64sp:$Rn, simm9:$offset), ssub))>;
4938 // 64-bits -> double are handled in target specific dag combine:
4939 // performIntToFpCombine.
4941 //===----------------------------------------------------------------------===//
4942 // Advanced SIMD three different-sized vector instructions.
4943 //===----------------------------------------------------------------------===//
4945 defm ADDHN  : SIMDNarrowThreeVectorBHS<0,0b0100,"addhn", int_aarch64_neon_addhn>;
4946 defm SUBHN  : SIMDNarrowThreeVectorBHS<0,0b0110,"subhn", int_aarch64_neon_subhn>;
4947 defm RADDHN : SIMDNarrowThreeVectorBHS<1,0b0100,"raddhn",int_aarch64_neon_raddhn>;
4948 defm RSUBHN : SIMDNarrowThreeVectorBHS<1,0b0110,"rsubhn",int_aarch64_neon_rsubhn>;
4949 defm PMULL  : SIMDDifferentThreeVectorBD<0,0b1110,"pmull",int_aarch64_neon_pmull>;
4950 defm SABAL  : SIMDLongThreeVectorTiedBHSabal<0,0b0101,"sabal",
4951                                              AArch64sabd>;
4952 defm SABDL   : SIMDLongThreeVectorBHSabdl<0, 0b0111, "sabdl",
4953                                           AArch64sabd>;
4954 defm SADDL   : SIMDLongThreeVectorBHS<   0, 0b0000, "saddl",
4955             BinOpFrag<(add (sext node:$LHS), (sext node:$RHS))>>;
4956 defm SADDW   : SIMDWideThreeVectorBHS<   0, 0b0001, "saddw",
4957                  BinOpFrag<(add node:$LHS, (sext node:$RHS))>>;
4958 defm SMLAL   : SIMDLongThreeVectorTiedBHS<0, 0b1000, "smlal",
4959     TriOpFrag<(add node:$LHS, (int_aarch64_neon_smull node:$MHS, node:$RHS))>>;
4960 defm SMLSL   : SIMDLongThreeVectorTiedBHS<0, 0b1010, "smlsl",
4961     TriOpFrag<(sub node:$LHS, (int_aarch64_neon_smull node:$MHS, node:$RHS))>>;
4962 defm SMULL   : SIMDLongThreeVectorBHS<0, 0b1100, "smull", int_aarch64_neon_smull>;
4963 defm SQDMLAL : SIMDLongThreeVectorSQDMLXTiedHS<0, 0b1001, "sqdmlal",
4964                                                int_aarch64_neon_sqadd>;
4965 defm SQDMLSL : SIMDLongThreeVectorSQDMLXTiedHS<0, 0b1011, "sqdmlsl",
4966                                                int_aarch64_neon_sqsub>;
4967 defm SQDMULL : SIMDLongThreeVectorHS<0, 0b1101, "sqdmull",
4968                                      int_aarch64_neon_sqdmull>;
4969 defm SSUBL   : SIMDLongThreeVectorBHS<0, 0b0010, "ssubl",
4970                  BinOpFrag<(sub (sext node:$LHS), (sext node:$RHS))>>;
4971 defm SSUBW   : SIMDWideThreeVectorBHS<0, 0b0011, "ssubw",
4972                  BinOpFrag<(sub node:$LHS, (sext node:$RHS))>>;
4973 defm UABAL   : SIMDLongThreeVectorTiedBHSabal<1, 0b0101, "uabal",
4974                                               AArch64uabd>;
4975 defm UADDL   : SIMDLongThreeVectorBHS<1, 0b0000, "uaddl",
4976                  BinOpFrag<(add (zanyext node:$LHS), (zanyext node:$RHS))>>;
4977 defm UADDW   : SIMDWideThreeVectorBHS<1, 0b0001, "uaddw",
4978                  BinOpFrag<(add node:$LHS, (zanyext node:$RHS))>>;
4979 defm UMLAL   : SIMDLongThreeVectorTiedBHS<1, 0b1000, "umlal",
4980     TriOpFrag<(add node:$LHS, (int_aarch64_neon_umull node:$MHS, node:$RHS))>>;
4981 defm UMLSL   : SIMDLongThreeVectorTiedBHS<1, 0b1010, "umlsl",
4982     TriOpFrag<(sub node:$LHS, (int_aarch64_neon_umull node:$MHS, node:$RHS))>>;
4983 defm UMULL   : SIMDLongThreeVectorBHS<1, 0b1100, "umull", int_aarch64_neon_umull>;
4984 defm USUBL   : SIMDLongThreeVectorBHS<1, 0b0010, "usubl",
4985                  BinOpFrag<(sub (zanyext node:$LHS), (zanyext node:$RHS))>>;
4986 defm USUBW   : SIMDWideThreeVectorBHS<   1, 0b0011, "usubw",
4987                  BinOpFrag<(sub node:$LHS, (zanyext node:$RHS))>>;
4989 // Additional patterns for [SU]ML[AS]L
4990 multiclass Neon_mul_acc_widen_patterns<SDPatternOperator opnode, SDPatternOperator vecopnode,
4991   Instruction INST8B, Instruction INST4H, Instruction INST2S> {
4992   def : Pat<(v4i16 (opnode
4993                     V64:$Ra,
4994                     (v4i16 (extract_subvector
4995                             (vecopnode (v8i8 V64:$Rn),(v8i8 V64:$Rm)),
4996                             (i64 0))))),
4997              (EXTRACT_SUBREG (v8i16 (INST8B
4998                                      (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)), V64:$Ra, dsub),
4999                                      V64:$Rn, V64:$Rm)), dsub)>;
5000   def : Pat<(v2i32 (opnode
5001                     V64:$Ra,
5002                     (v2i32 (extract_subvector
5003                             (vecopnode (v4i16 V64:$Rn),(v4i16 V64:$Rm)),
5004                             (i64 0))))),
5005              (EXTRACT_SUBREG (v4i32 (INST4H
5006                                      (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), V64:$Ra, dsub),
5007                                      V64:$Rn, V64:$Rm)), dsub)>;
5008   def : Pat<(v1i64 (opnode
5009                     V64:$Ra,
5010                     (v1i64 (extract_subvector
5011                             (vecopnode (v2i32 V64:$Rn),(v2i32 V64:$Rm)),
5012                             (i64 0))))),
5013              (EXTRACT_SUBREG (v2i64 (INST2S
5014                                      (INSERT_SUBREG (v2i64 (IMPLICIT_DEF)), V64:$Ra, dsub),
5015                                      V64:$Rn, V64:$Rm)), dsub)>;
5018 defm : Neon_mul_acc_widen_patterns<add, int_aarch64_neon_umull,
5019      UMLALv8i8_v8i16, UMLALv4i16_v4i32, UMLALv2i32_v2i64>;
5020 defm : Neon_mul_acc_widen_patterns<add, int_aarch64_neon_smull,
5021      SMLALv8i8_v8i16, SMLALv4i16_v4i32, SMLALv2i32_v2i64>;
5022 defm : Neon_mul_acc_widen_patterns<sub, int_aarch64_neon_umull,
5023      UMLSLv8i8_v8i16, UMLSLv4i16_v4i32, UMLSLv2i32_v2i64>;
5024 defm : Neon_mul_acc_widen_patterns<sub, int_aarch64_neon_smull,
5025      SMLSLv8i8_v8i16, SMLSLv4i16_v4i32, SMLSLv2i32_v2i64>;
5027 // Additional patterns for SMULL and UMULL
5028 multiclass Neon_mul_widen_patterns<SDPatternOperator opnode,
5029   Instruction INST8B, Instruction INST4H, Instruction INST2S> {
5030   def : Pat<(v8i16 (opnode (v8i8 V64:$Rn), (v8i8 V64:$Rm))),
5031             (INST8B V64:$Rn, V64:$Rm)>;
5032   def : Pat<(v4i32 (opnode (v4i16 V64:$Rn), (v4i16 V64:$Rm))),
5033             (INST4H V64:$Rn, V64:$Rm)>;
5034   def : Pat<(v2i64 (opnode (v2i32 V64:$Rn), (v2i32 V64:$Rm))),
5035             (INST2S V64:$Rn, V64:$Rm)>;
5038 defm : Neon_mul_widen_patterns<AArch64smull, SMULLv8i8_v8i16,
5039   SMULLv4i16_v4i32, SMULLv2i32_v2i64>;
5040 defm : Neon_mul_widen_patterns<AArch64umull, UMULLv8i8_v8i16,
5041   UMULLv4i16_v4i32, UMULLv2i32_v2i64>;
5043 // Patterns for smull2/umull2.
5044 multiclass Neon_mul_high_patterns<SDPatternOperator opnode,
5045   Instruction INST8B, Instruction INST4H, Instruction INST2S> {
5046   def : Pat<(v8i16 (opnode (extract_high_v16i8 V128:$Rn),
5047                            (extract_high_v16i8 V128:$Rm))),
5048              (INST8B V128:$Rn, V128:$Rm)>;
5049   def : Pat<(v4i32 (opnode (extract_high_v8i16 V128:$Rn),
5050                            (extract_high_v8i16 V128:$Rm))),
5051              (INST4H V128:$Rn, V128:$Rm)>;
5052   def : Pat<(v2i64 (opnode (extract_high_v4i32 V128:$Rn),
5053                            (extract_high_v4i32 V128:$Rm))),
5054              (INST2S V128:$Rn, V128:$Rm)>;
5057 defm : Neon_mul_high_patterns<AArch64smull, SMULLv16i8_v8i16,
5058   SMULLv8i16_v4i32, SMULLv4i32_v2i64>;
5059 defm : Neon_mul_high_patterns<AArch64umull, UMULLv16i8_v8i16,
5060   UMULLv8i16_v4i32, UMULLv4i32_v2i64>;
5062 // Additional patterns for SMLAL/SMLSL and UMLAL/UMLSL
5063 multiclass Neon_mulacc_widen_patterns<SDPatternOperator opnode,
5064   Instruction INST8B, Instruction INST4H, Instruction INST2S> {
5065   def : Pat<(v8i16 (opnode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm))),
5066             (INST8B V128:$Rd, V64:$Rn, V64:$Rm)>;
5067   def : Pat<(v4i32 (opnode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm))),
5068             (INST4H V128:$Rd, V64:$Rn, V64:$Rm)>;
5069   def : Pat<(v2i64 (opnode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm))),
5070             (INST2S  V128:$Rd, V64:$Rn, V64:$Rm)>;
5073 defm : Neon_mulacc_widen_patterns<
5074   TriOpFrag<(add node:$LHS, (AArch64smull node:$MHS, node:$RHS))>,
5075   SMLALv8i8_v8i16, SMLALv4i16_v4i32, SMLALv2i32_v2i64>;
5076 defm : Neon_mulacc_widen_patterns<
5077   TriOpFrag<(add node:$LHS, (AArch64umull node:$MHS, node:$RHS))>,
5078   UMLALv8i8_v8i16, UMLALv4i16_v4i32, UMLALv2i32_v2i64>;
5079 defm : Neon_mulacc_widen_patterns<
5080   TriOpFrag<(sub node:$LHS, (AArch64smull node:$MHS, node:$RHS))>,
5081   SMLSLv8i8_v8i16, SMLSLv4i16_v4i32, SMLSLv2i32_v2i64>;
5082 defm : Neon_mulacc_widen_patterns<
5083   TriOpFrag<(sub node:$LHS, (AArch64umull node:$MHS, node:$RHS))>,
5084   UMLSLv8i8_v8i16, UMLSLv4i16_v4i32, UMLSLv2i32_v2i64>;
5086 // Patterns for 64-bit pmull
5087 def : Pat<(int_aarch64_neon_pmull64 V64:$Rn, V64:$Rm),
5088           (PMULLv1i64 V64:$Rn, V64:$Rm)>;
5089 def : Pat<(int_aarch64_neon_pmull64 (extractelt (v2i64 V128:$Rn), (i64 1)),
5090                                     (extractelt (v2i64 V128:$Rm), (i64 1))),
5091           (PMULLv2i64 V128:$Rn, V128:$Rm)>;
5093 // CodeGen patterns for addhn and subhn instructions, which can actually be
5094 // written in LLVM IR without too much difficulty.
5096 // ADDHN
5097 def : Pat<(v8i8 (trunc (v8i16 (AArch64vlshr (add V128:$Rn, V128:$Rm), (i32 8))))),
5098           (ADDHNv8i16_v8i8 V128:$Rn, V128:$Rm)>;
5099 def : Pat<(v4i16 (trunc (v4i32 (AArch64vlshr (add V128:$Rn, V128:$Rm),
5100                                            (i32 16))))),
5101           (ADDHNv4i32_v4i16 V128:$Rn, V128:$Rm)>;
5102 def : Pat<(v2i32 (trunc (v2i64 (AArch64vlshr (add V128:$Rn, V128:$Rm),
5103                                            (i32 32))))),
5104           (ADDHNv2i64_v2i32 V128:$Rn, V128:$Rm)>;
5105 def : Pat<(concat_vectors (v8i8 V64:$Rd),
5106                           (trunc (v8i16 (AArch64vlshr (add V128:$Rn, V128:$Rm),
5107                                                     (i32 8))))),
5108           (ADDHNv8i16_v16i8 (SUBREG_TO_REG (i32 0), V64:$Rd, dsub),
5109                             V128:$Rn, V128:$Rm)>;
5110 def : Pat<(concat_vectors (v4i16 V64:$Rd),
5111                           (trunc (v4i32 (AArch64vlshr (add V128:$Rn, V128:$Rm),
5112                                                     (i32 16))))),
5113           (ADDHNv4i32_v8i16 (SUBREG_TO_REG (i32 0), V64:$Rd, dsub),
5114                             V128:$Rn, V128:$Rm)>;
5115 def : Pat<(concat_vectors (v2i32 V64:$Rd),
5116                           (trunc (v2i64 (AArch64vlshr (add V128:$Rn, V128:$Rm),
5117                                                     (i32 32))))),
5118           (ADDHNv2i64_v4i32 (SUBREG_TO_REG (i32 0), V64:$Rd, dsub),
5119                             V128:$Rn, V128:$Rm)>;
5121 // SUBHN
5122 def : Pat<(v8i8 (trunc (v8i16 (AArch64vlshr (sub V128:$Rn, V128:$Rm), (i32 8))))),
5123           (SUBHNv8i16_v8i8 V128:$Rn, V128:$Rm)>;
5124 def : Pat<(v4i16 (trunc (v4i32 (AArch64vlshr (sub V128:$Rn, V128:$Rm),
5125                                            (i32 16))))),
5126           (SUBHNv4i32_v4i16 V128:$Rn, V128:$Rm)>;
5127 def : Pat<(v2i32 (trunc (v2i64 (AArch64vlshr (sub V128:$Rn, V128:$Rm),
5128                                            (i32 32))))),
5129           (SUBHNv2i64_v2i32 V128:$Rn, V128:$Rm)>;
5130 def : Pat<(concat_vectors (v8i8 V64:$Rd),
5131                           (trunc (v8i16 (AArch64vlshr (sub V128:$Rn, V128:$Rm),
5132                                                     (i32 8))))),
5133           (SUBHNv8i16_v16i8 (SUBREG_TO_REG (i32 0), V64:$Rd, dsub),
5134                             V128:$Rn, V128:$Rm)>;
5135 def : Pat<(concat_vectors (v4i16 V64:$Rd),
5136                           (trunc (v4i32 (AArch64vlshr (sub V128:$Rn, V128:$Rm),
5137                                                     (i32 16))))),
5138           (SUBHNv4i32_v8i16 (SUBREG_TO_REG (i32 0), V64:$Rd, dsub),
5139                             V128:$Rn, V128:$Rm)>;
5140 def : Pat<(concat_vectors (v2i32 V64:$Rd),
5141                           (trunc (v2i64 (AArch64vlshr (sub V128:$Rn, V128:$Rm),
5142                                                     (i32 32))))),
5143           (SUBHNv2i64_v4i32 (SUBREG_TO_REG (i32 0), V64:$Rd, dsub),
5144                             V128:$Rn, V128:$Rm)>;
5146 //----------------------------------------------------------------------------
5147 // AdvSIMD bitwise extract from vector instruction.
5148 //----------------------------------------------------------------------------
5150 defm EXT : SIMDBitwiseExtract<"ext">;
5152 def AdjustExtImm : SDNodeXForm<imm, [{
5153   return CurDAG->getTargetConstant(8 + N->getZExtValue(), SDLoc(N), MVT::i32);
5154 }]>;
5155 multiclass ExtPat<ValueType VT64, ValueType VT128, int N> {
5156   def : Pat<(VT64 (AArch64ext V64:$Rn, V64:$Rm, (i32 imm:$imm))),
5157             (EXTv8i8 V64:$Rn, V64:$Rm, imm:$imm)>;
5158   def : Pat<(VT128 (AArch64ext V128:$Rn, V128:$Rm, (i32 imm:$imm))),
5159             (EXTv16i8 V128:$Rn, V128:$Rm, imm:$imm)>;
5160   // We use EXT to handle extract_subvector to copy the upper 64-bits of a
5161   // 128-bit vector.
5162   def : Pat<(VT64 (extract_subvector V128:$Rn, (i64 N))),
5163             (EXTRACT_SUBREG (EXTv16i8 V128:$Rn, V128:$Rn, 8), dsub)>;
5164   // A 64-bit EXT of two halves of the same 128-bit register can be done as a
5165   // single 128-bit EXT.
5166   def : Pat<(VT64 (AArch64ext (extract_subvector V128:$Rn, (i64 0)),
5167                               (extract_subvector V128:$Rn, (i64 N)),
5168                               (i32 imm:$imm))),
5169             (EXTRACT_SUBREG (EXTv16i8 V128:$Rn, V128:$Rn, imm:$imm), dsub)>;
5170   // A 64-bit EXT of the high half of a 128-bit register can be done using a
5171   // 128-bit EXT of the whole register with an adjustment to the immediate. The
5172   // top half of the other operand will be unset, but that doesn't matter as it
5173   // will not be used.
5174   def : Pat<(VT64 (AArch64ext (extract_subvector V128:$Rn, (i64 N)),
5175                               V64:$Rm,
5176                               (i32 imm:$imm))),
5177             (EXTRACT_SUBREG (EXTv16i8 V128:$Rn,
5178                                       (SUBREG_TO_REG (i32 0), V64:$Rm, dsub),
5179                                       (AdjustExtImm imm:$imm)), dsub)>;
5182 defm : ExtPat<v8i8, v16i8, 8>;
5183 defm : ExtPat<v4i16, v8i16, 4>;
5184 defm : ExtPat<v4f16, v8f16, 4>;
5185 defm : ExtPat<v4bf16, v8bf16, 4>;
5186 defm : ExtPat<v2i32, v4i32, 2>;
5187 defm : ExtPat<v2f32, v4f32, 2>;
5188 defm : ExtPat<v1i64, v2i64, 1>;
5189 defm : ExtPat<v1f64, v2f64, 1>;
5191 //----------------------------------------------------------------------------
5192 // AdvSIMD zip vector
5193 //----------------------------------------------------------------------------
5195 defm TRN1 : SIMDZipVector<0b010, "trn1", AArch64trn1>;
5196 defm TRN2 : SIMDZipVector<0b110, "trn2", AArch64trn2>;
5197 defm UZP1 : SIMDZipVector<0b001, "uzp1", AArch64uzp1>;
5198 defm UZP2 : SIMDZipVector<0b101, "uzp2", AArch64uzp2>;
5199 defm ZIP1 : SIMDZipVector<0b011, "zip1", AArch64zip1>;
5200 defm ZIP2 : SIMDZipVector<0b111, "zip2", AArch64zip2>;
5202 //----------------------------------------------------------------------------
5203 // AdvSIMD TBL/TBX instructions
5204 //----------------------------------------------------------------------------
5206 defm TBL : SIMDTableLookup<    0, "tbl">;
5207 defm TBX : SIMDTableLookupTied<1, "tbx">;
5209 def : Pat<(v8i8 (int_aarch64_neon_tbl1 (v16i8 VecListOne128:$Rn), (v8i8 V64:$Ri))),
5210           (TBLv8i8One VecListOne128:$Rn, V64:$Ri)>;
5211 def : Pat<(v16i8 (int_aarch64_neon_tbl1 (v16i8 V128:$Ri), (v16i8 V128:$Rn))),
5212           (TBLv16i8One V128:$Ri, V128:$Rn)>;
5214 def : Pat<(v8i8 (int_aarch64_neon_tbx1 (v8i8 V64:$Rd),
5215                   (v16i8 VecListOne128:$Rn), (v8i8 V64:$Ri))),
5216           (TBXv8i8One V64:$Rd, VecListOne128:$Rn, V64:$Ri)>;
5217 def : Pat<(v16i8 (int_aarch64_neon_tbx1 (v16i8 V128:$Rd),
5218                    (v16i8 V128:$Ri), (v16i8 V128:$Rn))),
5219           (TBXv16i8One V128:$Rd, V128:$Ri, V128:$Rn)>;
5222 //----------------------------------------------------------------------------
5223 // AdvSIMD scalar CPY instruction
5224 //----------------------------------------------------------------------------
5226 defm CPY : SIMDScalarCPY<"cpy">;
5228 //----------------------------------------------------------------------------
5229 // AdvSIMD scalar pairwise instructions
5230 //----------------------------------------------------------------------------
5232 defm ADDP    : SIMDPairwiseScalarD<0, 0b11011, "addp">;
5233 defm FADDP   : SIMDFPPairwiseScalar<0, 0b01101, "faddp">;
5234 defm FMAXNMP : SIMDFPPairwiseScalar<0, 0b01100, "fmaxnmp">;
5235 defm FMAXP   : SIMDFPPairwiseScalar<0, 0b01111, "fmaxp">;
5236 defm FMINNMP : SIMDFPPairwiseScalar<1, 0b01100, "fminnmp">;
5237 defm FMINP   : SIMDFPPairwiseScalar<1, 0b01111, "fminp">;
5239 let Predicates = [HasFullFP16] in {
5240 def : Pat<(f16 (vecreduce_fadd (v8f16 V128:$Rn))),
5241             (FADDPv2i16p
5242               (EXTRACT_SUBREG
5243                  (FADDPv8f16 (FADDPv8f16 V128:$Rn, (v8f16 (IMPLICIT_DEF))), (v8f16 (IMPLICIT_DEF))),
5244                dsub))>;
5245 def : Pat<(f16 (vecreduce_fadd (v4f16 V64:$Rn))),
5246           (FADDPv2i16p (FADDPv4f16 V64:$Rn, (v4f16 (IMPLICIT_DEF))))>;
5248 def : Pat<(f32 (vecreduce_fadd (v4f32 V128:$Rn))),
5249           (FADDPv2i32p
5250             (EXTRACT_SUBREG
5251               (FADDPv4f32 V128:$Rn, (v4f32 (IMPLICIT_DEF))),
5252              dsub))>;
5253 def : Pat<(f32 (vecreduce_fadd (v2f32 V64:$Rn))),
5254           (FADDPv2i32p V64:$Rn)>;
5255 def : Pat<(f64 (vecreduce_fadd (v2f64 V128:$Rn))),
5256           (FADDPv2i64p V128:$Rn)>;
5258 def : Pat<(v2i64 (AArch64saddv V128:$Rn)),
5259           (INSERT_SUBREG (v2i64 (IMPLICIT_DEF)), (ADDPv2i64p V128:$Rn), dsub)>;
5260 def : Pat<(v2i64 (AArch64uaddv V128:$Rn)),
5261           (INSERT_SUBREG (v2i64 (IMPLICIT_DEF)), (ADDPv2i64p V128:$Rn), dsub)>;
5262 def : Pat<(f32 (int_aarch64_neon_faddv (v2f32 V64:$Rn))),
5263           (FADDPv2i32p V64:$Rn)>;
5264 def : Pat<(f32 (int_aarch64_neon_faddv (v4f32 V128:$Rn))),
5265           (FADDPv2i32p (EXTRACT_SUBREG (FADDPv4f32 V128:$Rn, V128:$Rn), dsub))>;
5266 def : Pat<(f64 (int_aarch64_neon_faddv (v2f64 V128:$Rn))),
5267           (FADDPv2i64p V128:$Rn)>;
5268 def : Pat<(f32 (int_aarch64_neon_fmaxnmv (v2f32 V64:$Rn))),
5269           (FMAXNMPv2i32p V64:$Rn)>;
5270 def : Pat<(f64 (int_aarch64_neon_fmaxnmv (v2f64 V128:$Rn))),
5271           (FMAXNMPv2i64p V128:$Rn)>;
5272 def : Pat<(f32 (int_aarch64_neon_fmaxv (v2f32 V64:$Rn))),
5273           (FMAXPv2i32p V64:$Rn)>;
5274 def : Pat<(f64 (int_aarch64_neon_fmaxv (v2f64 V128:$Rn))),
5275           (FMAXPv2i64p V128:$Rn)>;
5276 def : Pat<(f32 (int_aarch64_neon_fminnmv (v2f32 V64:$Rn))),
5277           (FMINNMPv2i32p V64:$Rn)>;
5278 def : Pat<(f64 (int_aarch64_neon_fminnmv (v2f64 V128:$Rn))),
5279           (FMINNMPv2i64p V128:$Rn)>;
5280 def : Pat<(f32 (int_aarch64_neon_fminv (v2f32 V64:$Rn))),
5281           (FMINPv2i32p V64:$Rn)>;
5282 def : Pat<(f64 (int_aarch64_neon_fminv (v2f64 V128:$Rn))),
5283           (FMINPv2i64p V128:$Rn)>;
5285 //----------------------------------------------------------------------------
5286 // AdvSIMD INS/DUP instructions
5287 //----------------------------------------------------------------------------
5289 def DUPv8i8gpr  : SIMDDupFromMain<0, {?,?,?,?,1}, ".8b", v8i8, V64, GPR32>;
5290 def DUPv16i8gpr : SIMDDupFromMain<1, {?,?,?,?,1}, ".16b", v16i8, V128, GPR32>;
5291 def DUPv4i16gpr : SIMDDupFromMain<0, {?,?,?,1,0}, ".4h", v4i16, V64, GPR32>;
5292 def DUPv8i16gpr : SIMDDupFromMain<1, {?,?,?,1,0}, ".8h", v8i16, V128, GPR32>;
5293 def DUPv2i32gpr : SIMDDupFromMain<0, {?,?,1,0,0}, ".2s", v2i32, V64, GPR32>;
5294 def DUPv4i32gpr : SIMDDupFromMain<1, {?,?,1,0,0}, ".4s", v4i32, V128, GPR32>;
5295 def DUPv2i64gpr : SIMDDupFromMain<1, {?,1,0,0,0}, ".2d", v2i64, V128, GPR64>;
5297 def DUPv2i64lane : SIMDDup64FromElement;
5298 def DUPv2i32lane : SIMDDup32FromElement<0, ".2s", v2i32, V64>;
5299 def DUPv4i32lane : SIMDDup32FromElement<1, ".4s", v4i32, V128>;
5300 def DUPv4i16lane : SIMDDup16FromElement<0, ".4h", v4i16, V64>;
5301 def DUPv8i16lane : SIMDDup16FromElement<1, ".8h", v8i16, V128>;
5302 def DUPv8i8lane  : SIMDDup8FromElement <0, ".8b", v8i8, V64>;
5303 def DUPv16i8lane : SIMDDup8FromElement <1, ".16b", v16i8, V128>;
5305 // DUP from a 64-bit register to a 64-bit register is just a copy
5306 def : Pat<(v1i64 (AArch64dup (i64 GPR64:$Rn))),
5307           (COPY_TO_REGCLASS GPR64:$Rn, FPR64)>;
5308 def : Pat<(v1f64 (AArch64dup (f64 FPR64:$Rn))),
5309           (COPY_TO_REGCLASS FPR64:$Rn, FPR64)>;
5311 def : Pat<(v2f32 (AArch64dup (f32 FPR32:$Rn))),
5312           (v2f32 (DUPv2i32lane
5313             (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), FPR32:$Rn, ssub),
5314             (i64 0)))>;
5315 def : Pat<(v4f32 (AArch64dup (f32 FPR32:$Rn))),
5316           (v4f32 (DUPv4i32lane
5317             (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), FPR32:$Rn, ssub),
5318             (i64 0)))>;
5319 def : Pat<(v2f64 (AArch64dup (f64 FPR64:$Rn))),
5320           (v2f64 (DUPv2i64lane
5321             (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), FPR64:$Rn, dsub),
5322             (i64 0)))>;
5323 def : Pat<(v4f16 (AArch64dup (f16 FPR16:$Rn))),
5324           (v4f16 (DUPv4i16lane
5325             (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)), FPR16:$Rn, hsub),
5326             (i64 0)))>;
5327 def : Pat<(v4bf16 (AArch64dup (bf16 FPR16:$Rn))),
5328           (v4bf16 (DUPv4i16lane
5329             (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)), FPR16:$Rn, hsub),
5330             (i64 0)))>;
5331 def : Pat<(v8f16 (AArch64dup (f16 FPR16:$Rn))),
5332           (v8f16 (DUPv8i16lane
5333             (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)), FPR16:$Rn, hsub),
5334             (i64 0)))>;
5335 def : Pat<(v8bf16 (AArch64dup (bf16 FPR16:$Rn))),
5336           (v8bf16 (DUPv8i16lane
5337             (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)), FPR16:$Rn, hsub),
5338             (i64 0)))>;
5340 def : Pat<(v4f16 (AArch64duplane16 (v8f16 V128:$Rn), VectorIndexH:$imm)),
5341           (DUPv4i16lane V128:$Rn, VectorIndexH:$imm)>;
5342 def : Pat<(v8f16 (AArch64duplane16 (v8f16 V128:$Rn), VectorIndexH:$imm)),
5343           (DUPv8i16lane V128:$Rn, VectorIndexH:$imm)>;
5345 def : Pat<(v4bf16 (AArch64duplane16 (v8bf16 V128:$Rn), VectorIndexH:$imm)),
5346           (DUPv4i16lane V128:$Rn, VectorIndexH:$imm)>;
5347 def : Pat<(v8bf16 (AArch64duplane16 (v8bf16 V128:$Rn), VectorIndexH:$imm)),
5348           (DUPv8i16lane V128:$Rn, VectorIndexH:$imm)>;
5350 def : Pat<(v2f32 (AArch64duplane32 (v4f32 V128:$Rn), VectorIndexS:$imm)),
5351           (DUPv2i32lane V128:$Rn, VectorIndexS:$imm)>;
5352 def : Pat<(v4f32 (AArch64duplane32 (v4f32 V128:$Rn), VectorIndexS:$imm)),
5353          (DUPv4i32lane V128:$Rn, VectorIndexS:$imm)>;
5354 def : Pat<(v2f64 (AArch64duplane64 (v2f64 V128:$Rn), VectorIndexD:$imm)),
5355           (DUPv2i64lane V128:$Rn, VectorIndexD:$imm)>;
5357 // If there's an (AArch64dup (vector_extract ...) ...), we can use a duplane
5358 // instruction even if the types don't match: we just have to remap the lane
5359 // carefully. N.b. this trick only applies to truncations.
5360 def VecIndex_x2 : SDNodeXForm<imm, [{
5361   return CurDAG->getTargetConstant(2 * N->getZExtValue(), SDLoc(N), MVT::i64);
5362 }]>;
5363 def VecIndex_x4 : SDNodeXForm<imm, [{
5364   return CurDAG->getTargetConstant(4 * N->getZExtValue(), SDLoc(N), MVT::i64);
5365 }]>;
5366 def VecIndex_x8 : SDNodeXForm<imm, [{
5367   return CurDAG->getTargetConstant(8 * N->getZExtValue(), SDLoc(N), MVT::i64);
5368 }]>;
5370 multiclass DUPWithTruncPats<ValueType ResVT, ValueType Src64VT,
5371                             ValueType Src128VT, ValueType ScalVT,
5372                             Instruction DUP, SDNodeXForm IdxXFORM> {
5373   def : Pat<(ResVT (AArch64dup (ScalVT (vector_extract (Src128VT V128:$Rn),
5374                                                      imm:$idx)))),
5375             (DUP V128:$Rn, (IdxXFORM imm:$idx))>;
5377   def : Pat<(ResVT (AArch64dup (ScalVT (vector_extract (Src64VT V64:$Rn),
5378                                                      imm:$idx)))),
5379             (DUP (SUBREG_TO_REG (i64 0), V64:$Rn, dsub), (IdxXFORM imm:$idx))>;
5382 defm : DUPWithTruncPats<v8i8,   v4i16, v8i16, i32, DUPv8i8lane,  VecIndex_x2>;
5383 defm : DUPWithTruncPats<v8i8,   v2i32, v4i32, i32, DUPv8i8lane,  VecIndex_x4>;
5384 defm : DUPWithTruncPats<v4i16,  v2i32, v4i32, i32, DUPv4i16lane, VecIndex_x2>;
5386 defm : DUPWithTruncPats<v16i8,  v4i16, v8i16, i32, DUPv16i8lane, VecIndex_x2>;
5387 defm : DUPWithTruncPats<v16i8,  v2i32, v4i32, i32, DUPv16i8lane, VecIndex_x4>;
5388 defm : DUPWithTruncPats<v8i16,  v2i32, v4i32, i32, DUPv8i16lane, VecIndex_x2>;
5390 multiclass DUPWithTrunci64Pats<ValueType ResVT, Instruction DUP,
5391                                SDNodeXForm IdxXFORM> {
5392   def : Pat<(ResVT (AArch64dup (i32 (trunc (extractelt (v2i64 V128:$Rn),
5393                                                          imm:$idx))))),
5394             (DUP V128:$Rn, (IdxXFORM imm:$idx))>;
5396   def : Pat<(ResVT (AArch64dup (i32 (trunc (extractelt (v1i64 V64:$Rn),
5397                                                        imm:$idx))))),
5398             (DUP (SUBREG_TO_REG (i64 0), V64:$Rn, dsub), (IdxXFORM imm:$idx))>;
5401 defm : DUPWithTrunci64Pats<v8i8,  DUPv8i8lane,   VecIndex_x8>;
5402 defm : DUPWithTrunci64Pats<v4i16, DUPv4i16lane,  VecIndex_x4>;
5403 defm : DUPWithTrunci64Pats<v2i32, DUPv2i32lane,  VecIndex_x2>;
5405 defm : DUPWithTrunci64Pats<v16i8, DUPv16i8lane, VecIndex_x8>;
5406 defm : DUPWithTrunci64Pats<v8i16, DUPv8i16lane, VecIndex_x4>;
5407 defm : DUPWithTrunci64Pats<v4i32, DUPv4i32lane, VecIndex_x2>;
5409 // SMOV and UMOV definitions, with some extra patterns for convenience
5410 defm SMOV : SMov;
5411 defm UMOV : UMov;
5413 def : Pat<(sext_inreg (vector_extract (v16i8 V128:$Rn), VectorIndexB:$idx), i8),
5414           (i32 (SMOVvi8to32 V128:$Rn, VectorIndexB:$idx))>;
5415 def : Pat<(sext_inreg (vector_extract (v16i8 V128:$Rn), VectorIndexB:$idx), i8),
5416           (i64 (SMOVvi8to64 V128:$Rn, VectorIndexB:$idx))>;
5417 def : Pat<(sext_inreg (vector_extract (v8i16 V128:$Rn), VectorIndexH:$idx),i16),
5418           (i32 (SMOVvi16to32 V128:$Rn, VectorIndexH:$idx))>;
5419 def : Pat<(sext_inreg (vector_extract (v8i16 V128:$Rn), VectorIndexH:$idx),i16),
5420           (i64 (SMOVvi16to64 V128:$Rn, VectorIndexH:$idx))>;
5421 def : Pat<(sext_inreg (vector_extract (v8i16 V128:$Rn), VectorIndexH:$idx),i16),
5422           (i32 (SMOVvi16to32 V128:$Rn, VectorIndexH:$idx))>;
5423 def : Pat<(sext (i32 (vector_extract (v4i32 V128:$Rn), VectorIndexS:$idx))),
5424           (i64 (SMOVvi32to64 V128:$Rn, VectorIndexS:$idx))>;
5426 def : Pat<(sext_inreg (i64 (anyext (i32 (vector_extract (v16i8 V128:$Rn),
5427             VectorIndexB:$idx)))), i8),
5428           (i64 (SMOVvi8to64 V128:$Rn, VectorIndexB:$idx))>;
5429 def : Pat<(sext_inreg (i64 (anyext (i32 (vector_extract (v8i16 V128:$Rn),
5430             VectorIndexH:$idx)))), i16),
5431           (i64 (SMOVvi16to64 V128:$Rn, VectorIndexH:$idx))>;
5433 // Extracting i8 or i16 elements will have the zero-extend transformed to
5434 // an 'and' mask by type legalization since neither i8 nor i16 are legal types
5435 // for AArch64. Match these patterns here since UMOV already zeroes out the high
5436 // bits of the destination register.
5437 def : Pat<(and (vector_extract (v16i8 V128:$Rn), VectorIndexB:$idx),
5438                (i32 0xff)),
5439           (i32 (UMOVvi8 V128:$Rn, VectorIndexB:$idx))>;
5440 def : Pat<(and (vector_extract (v8i16 V128:$Rn), VectorIndexH:$idx),
5441                (i32 0xffff)),
5442           (i32 (UMOVvi16 V128:$Rn, VectorIndexH:$idx))>;
5444 def : Pat<(i64 (and (i64 (anyext (i32 (vector_extract (v16i8 V128:$Rn),
5445             VectorIndexB:$idx)))), (i64 0xff))),
5446           (SUBREG_TO_REG (i64 0), (i32 (UMOVvi8 V128:$Rn, VectorIndexB:$idx)), sub_32)>;
5447 def : Pat<(i64 (and (i64 (anyext (i32 (vector_extract (v8i16 V128:$Rn),
5448             VectorIndexH:$idx)))), (i64 0xffff))),
5449           (SUBREG_TO_REG (i64 0), (i32 (UMOVvi16 V128:$Rn, VectorIndexH:$idx)), sub_32)>;
5451 defm INS : SIMDIns;
5453 def : Pat<(v16i8 (scalar_to_vector GPR32:$Rn)),
5454           (SUBREG_TO_REG (i32 0),
5455                          (f32 (COPY_TO_REGCLASS GPR32:$Rn, FPR32)), ssub)>;
5456 def : Pat<(v8i8 (scalar_to_vector GPR32:$Rn)),
5457           (SUBREG_TO_REG (i32 0),
5458                          (f32 (COPY_TO_REGCLASS GPR32:$Rn, FPR32)), ssub)>;
5460 def : Pat<(v8i16 (scalar_to_vector GPR32:$Rn)),
5461           (SUBREG_TO_REG (i32 0),
5462                          (f32 (COPY_TO_REGCLASS GPR32:$Rn, FPR32)), ssub)>;
5463 def : Pat<(v4i16 (scalar_to_vector GPR32:$Rn)),
5464           (SUBREG_TO_REG (i32 0),
5465                          (f32 (COPY_TO_REGCLASS GPR32:$Rn, FPR32)), ssub)>;
5467 def : Pat<(v4f16 (scalar_to_vector (f16 FPR16:$Rn))),
5468           (INSERT_SUBREG (v4f16 (IMPLICIT_DEF)), FPR16:$Rn, hsub)>;
5469 def : Pat<(v8f16 (scalar_to_vector (f16 FPR16:$Rn))),
5470           (INSERT_SUBREG (v8f16 (IMPLICIT_DEF)), FPR16:$Rn, hsub)>;
5472 def : Pat<(v4bf16 (scalar_to_vector (bf16 FPR16:$Rn))),
5473           (INSERT_SUBREG (v4bf16 (IMPLICIT_DEF)), FPR16:$Rn, hsub)>;
5474 def : Pat<(v8bf16 (scalar_to_vector (bf16 FPR16:$Rn))),
5475           (INSERT_SUBREG (v8bf16 (IMPLICIT_DEF)), FPR16:$Rn, hsub)>;
5477 def : Pat<(v2i32 (scalar_to_vector (i32 FPR32:$Rn))),
5478             (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
5479                                   (i32 FPR32:$Rn), ssub))>;
5480 def : Pat<(v4i32 (scalar_to_vector (i32 FPR32:$Rn))),
5481             (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
5482                                   (i32 FPR32:$Rn), ssub))>;
5484 def : Pat<(v2i64 (scalar_to_vector (i64 FPR64:$Rn))),
5485             (v2i64 (INSERT_SUBREG (v2i64 (IMPLICIT_DEF)),
5486                                   (i64 FPR64:$Rn), dsub))>;
5488 def : Pat<(v4f16 (scalar_to_vector (f16 FPR16:$Rn))),
5489           (INSERT_SUBREG (v4f16 (IMPLICIT_DEF)), FPR16:$Rn, hsub)>;
5490 def : Pat<(v8f16 (scalar_to_vector (f16 FPR16:$Rn))),
5491           (INSERT_SUBREG (v8f16 (IMPLICIT_DEF)), FPR16:$Rn, hsub)>;
5493 def : Pat<(v4bf16 (scalar_to_vector (bf16 FPR16:$Rn))),
5494           (INSERT_SUBREG (v4bf16 (IMPLICIT_DEF)), FPR16:$Rn, hsub)>;
5495 def : Pat<(v8bf16 (scalar_to_vector (bf16 FPR16:$Rn))),
5496           (INSERT_SUBREG (v8bf16 (IMPLICIT_DEF)), FPR16:$Rn, hsub)>;
5498 def : Pat<(v4f32 (scalar_to_vector (f32 FPR32:$Rn))),
5499           (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), FPR32:$Rn, ssub)>;
5500 def : Pat<(v2f32 (scalar_to_vector (f32 FPR32:$Rn))),
5501           (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), FPR32:$Rn, ssub)>;
5503 def : Pat<(v2f64 (scalar_to_vector (f64 FPR64:$Rn))),
5504           (INSERT_SUBREG (v2f64 (IMPLICIT_DEF)), FPR64:$Rn, dsub)>;
5506 def : Pat<(v4f16 (vector_insert (v4f16 V64:$Rn),
5507             (f16 FPR16:$Rm), (i64 VectorIndexS:$imm))),
5508           (EXTRACT_SUBREG
5509             (INSvi16lane
5510               (v8f16 (INSERT_SUBREG (v8f16 (IMPLICIT_DEF)), V64:$Rn, dsub)),
5511               VectorIndexS:$imm,
5512               (v8f16 (INSERT_SUBREG (v8f16 (IMPLICIT_DEF)), FPR16:$Rm, hsub)),
5513               (i64 0)),
5514             dsub)>;
5516 def : Pat<(vector_insert (v8f16 v8f16:$Rn), (f16 fpimm0),
5517             (i64 VectorIndexH:$imm)),
5518           (INSvi16gpr V128:$Rn, VectorIndexH:$imm, WZR)>;
5519 def : Pat<(vector_insert v4f32:$Rn, (f32 fpimm0),
5520             (i64 VectorIndexS:$imm)),
5521           (INSvi32gpr V128:$Rn, VectorIndexS:$imm, WZR)>;
5522 def : Pat<(vector_insert v2f64:$Rn, (f64 fpimm0),
5523             (i64 VectorIndexD:$imm)),
5524           (INSvi64gpr V128:$Rn, VectorIndexS:$imm, XZR)>;
5526 def : Pat<(v8f16 (vector_insert (v8f16 V128:$Rn),
5527             (f16 FPR16:$Rm), (i64 VectorIndexH:$imm))),
5528           (INSvi16lane
5529             V128:$Rn, VectorIndexH:$imm,
5530             (v8f16 (INSERT_SUBREG (v8f16 (IMPLICIT_DEF)), FPR16:$Rm, hsub)),
5531             (i64 0))>;
5533 def : Pat<(v4bf16 (vector_insert (v4bf16 V64:$Rn),
5534             (bf16 FPR16:$Rm), (i64 VectorIndexS:$imm))),
5535           (EXTRACT_SUBREG
5536             (INSvi16lane
5537               (v8bf16 (INSERT_SUBREG (v8bf16 (IMPLICIT_DEF)), V64:$Rn, dsub)),
5538               VectorIndexS:$imm,
5539               (v8bf16 (INSERT_SUBREG (v8bf16 (IMPLICIT_DEF)), FPR16:$Rm, hsub)),
5540               (i64 0)),
5541             dsub)>;
5543 def : Pat<(v8bf16 (vector_insert (v8bf16 V128:$Rn),
5544             (bf16 FPR16:$Rm), (i64 VectorIndexH:$imm))),
5545           (INSvi16lane
5546             V128:$Rn, VectorIndexH:$imm,
5547             (v8bf16 (INSERT_SUBREG (v8bf16 (IMPLICIT_DEF)), FPR16:$Rm, hsub)),
5548             (i64 0))>;
5550 def : Pat<(v2f32 (vector_insert (v2f32 V64:$Rn),
5551             (f32 FPR32:$Rm), (i64 VectorIndexS:$imm))),
5552           (EXTRACT_SUBREG
5553             (INSvi32lane
5554               (v4f32 (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), V64:$Rn, dsub)),
5555               VectorIndexS:$imm,
5556               (v4f32 (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), FPR32:$Rm, ssub)),
5557               (i64 0)),
5558             dsub)>;
5559 def : Pat<(v4f32 (vector_insert (v4f32 V128:$Rn),
5560             (f32 FPR32:$Rm), (i64 VectorIndexS:$imm))),
5561           (INSvi32lane
5562             V128:$Rn, VectorIndexS:$imm,
5563             (v4f32 (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), FPR32:$Rm, ssub)),
5564             (i64 0))>;
5565 def : Pat<(v2f64 (vector_insert (v2f64 V128:$Rn),
5566             (f64 FPR64:$Rm), (i64 VectorIndexD:$imm))),
5567           (INSvi64lane
5568             V128:$Rn, VectorIndexD:$imm,
5569             (v2f64 (INSERT_SUBREG (v2f64 (IMPLICIT_DEF)), FPR64:$Rm, dsub)),
5570             (i64 0))>;
5572 // Copy an element at a constant index in one vector into a constant indexed
5573 // element of another.
5574 // FIXME refactor to a shared class/dev parameterized on vector type, vector
5575 // index type and INS extension
5576 def : Pat<(v16i8 (int_aarch64_neon_vcopy_lane
5577                    (v16i8 V128:$Vd), VectorIndexB:$idx, (v16i8 V128:$Vs),
5578                    VectorIndexB:$idx2)),
5579           (v16i8 (INSvi8lane
5580                    V128:$Vd, VectorIndexB:$idx, V128:$Vs, VectorIndexB:$idx2)
5581           )>;
5582 def : Pat<(v8i16 (int_aarch64_neon_vcopy_lane
5583                    (v8i16 V128:$Vd), VectorIndexH:$idx, (v8i16 V128:$Vs),
5584                    VectorIndexH:$idx2)),
5585           (v8i16 (INSvi16lane
5586                    V128:$Vd, VectorIndexH:$idx, V128:$Vs, VectorIndexH:$idx2)
5587           )>;
5588 def : Pat<(v4i32 (int_aarch64_neon_vcopy_lane
5589                    (v4i32 V128:$Vd), VectorIndexS:$idx, (v4i32 V128:$Vs),
5590                    VectorIndexS:$idx2)),
5591           (v4i32 (INSvi32lane
5592                    V128:$Vd, VectorIndexS:$idx, V128:$Vs, VectorIndexS:$idx2)
5593           )>;
5594 def : Pat<(v2i64 (int_aarch64_neon_vcopy_lane
5595                    (v2i64 V128:$Vd), VectorIndexD:$idx, (v2i64 V128:$Vs),
5596                    VectorIndexD:$idx2)),
5597           (v2i64 (INSvi64lane
5598                    V128:$Vd, VectorIndexD:$idx, V128:$Vs, VectorIndexD:$idx2)
5599           )>;
5601 multiclass Neon_INS_elt_pattern<ValueType VT128, ValueType VT64,
5602                                 ValueType VTScal, Instruction INS> {
5603   def : Pat<(VT128 (vector_insert V128:$src,
5604                         (VTScal (vector_extract (VT128 V128:$Rn), imm:$Immn)),
5605                         imm:$Immd)),
5606             (INS V128:$src, imm:$Immd, V128:$Rn, imm:$Immn)>;
5608   def : Pat<(VT128 (vector_insert V128:$src,
5609                         (VTScal (vector_extract (VT64 V64:$Rn), imm:$Immn)),
5610                         imm:$Immd)),
5611             (INS V128:$src, imm:$Immd,
5612                  (SUBREG_TO_REG (i64 0), V64:$Rn, dsub), imm:$Immn)>;
5614   def : Pat<(VT64 (vector_insert V64:$src,
5615                         (VTScal (vector_extract (VT128 V128:$Rn), imm:$Immn)),
5616                         imm:$Immd)),
5617             (EXTRACT_SUBREG (INS (SUBREG_TO_REG (i64 0), V64:$src, dsub),
5618                                  imm:$Immd, V128:$Rn, imm:$Immn),
5619                             dsub)>;
5621   def : Pat<(VT64 (vector_insert V64:$src,
5622                         (VTScal (vector_extract (VT64 V64:$Rn), imm:$Immn)),
5623                         imm:$Immd)),
5624             (EXTRACT_SUBREG
5625                 (INS (SUBREG_TO_REG (i64 0), V64:$src, dsub), imm:$Immd,
5626                      (SUBREG_TO_REG (i64 0), V64:$Rn, dsub), imm:$Immn),
5627                 dsub)>;
5630 defm : Neon_INS_elt_pattern<v8f16, v4f16, f16, INSvi16lane>;
5631 defm : Neon_INS_elt_pattern<v8bf16, v4bf16, bf16, INSvi16lane>;
5632 defm : Neon_INS_elt_pattern<v4f32, v2f32, f32, INSvi32lane>;
5633 defm : Neon_INS_elt_pattern<v2f64, v1f64, f64, INSvi64lane>;
5636 // Floating point vector extractions are codegen'd as either a sequence of
5637 // subregister extractions, or a MOV (aka CPY here, alias for DUP) if
5638 // the lane number is anything other than zero.
5639 def : Pat<(vector_extract (v2f64 V128:$Rn), 0),
5640           (f64 (EXTRACT_SUBREG V128:$Rn, dsub))>;
5641 def : Pat<(vector_extract (v4f32 V128:$Rn), 0),
5642           (f32 (EXTRACT_SUBREG V128:$Rn, ssub))>;
5643 def : Pat<(vector_extract (v8f16 V128:$Rn), 0),
5644           (f16 (EXTRACT_SUBREG V128:$Rn, hsub))>;
5645 def : Pat<(vector_extract (v8bf16 V128:$Rn), 0),
5646           (bf16 (EXTRACT_SUBREG V128:$Rn, hsub))>;
5649 def : Pat<(vector_extract (v2f64 V128:$Rn), VectorIndexD:$idx),
5650           (f64 (CPYi64 V128:$Rn, VectorIndexD:$idx))>;
5651 def : Pat<(vector_extract (v4f32 V128:$Rn), VectorIndexS:$idx),
5652           (f32 (CPYi32 V128:$Rn, VectorIndexS:$idx))>;
5653 def : Pat<(vector_extract (v8f16 V128:$Rn), VectorIndexH:$idx),
5654           (f16 (CPYi16 V128:$Rn, VectorIndexH:$idx))>;
5655 def : Pat<(vector_extract (v8bf16 V128:$Rn), VectorIndexH:$idx),
5656           (bf16 (CPYi16 V128:$Rn, VectorIndexH:$idx))>;
5658 // All concat_vectors operations are canonicalised to act on i64 vectors for
5659 // AArch64. In the general case we need an instruction, which had just as well be
5660 // INS.
5661 class ConcatPat<ValueType DstTy, ValueType SrcTy>
5662   : Pat<(DstTy (concat_vectors (SrcTy V64:$Rd), V64:$Rn)),
5663         (INSvi64lane (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), 1,
5664                      (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rn, dsub), 0)>;
5666 def : ConcatPat<v2i64, v1i64>;
5667 def : ConcatPat<v2f64, v1f64>;
5668 def : ConcatPat<v4i32, v2i32>;
5669 def : ConcatPat<v4f32, v2f32>;
5670 def : ConcatPat<v8i16, v4i16>;
5671 def : ConcatPat<v8f16, v4f16>;
5672 def : ConcatPat<v8bf16, v4bf16>;
5673 def : ConcatPat<v16i8, v8i8>;
5675 // If the high lanes are undef, though, we can just ignore them:
5676 class ConcatUndefPat<ValueType DstTy, ValueType SrcTy>
5677   : Pat<(DstTy (concat_vectors (SrcTy V64:$Rn), undef)),
5678         (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rn, dsub)>;
5680 def : ConcatUndefPat<v2i64, v1i64>;
5681 def : ConcatUndefPat<v2f64, v1f64>;
5682 def : ConcatUndefPat<v4i32, v2i32>;
5683 def : ConcatUndefPat<v4f32, v2f32>;
5684 def : ConcatUndefPat<v8i16, v4i16>;
5685 def : ConcatUndefPat<v16i8, v8i8>;
5687 //----------------------------------------------------------------------------
5688 // AdvSIMD across lanes instructions
5689 //----------------------------------------------------------------------------
5691 defm ADDV    : SIMDAcrossLanesBHS<0, 0b11011, "addv">;
5692 defm SMAXV   : SIMDAcrossLanesBHS<0, 0b01010, "smaxv">;
5693 defm SMINV   : SIMDAcrossLanesBHS<0, 0b11010, "sminv">;
5694 defm UMAXV   : SIMDAcrossLanesBHS<1, 0b01010, "umaxv">;
5695 defm UMINV   : SIMDAcrossLanesBHS<1, 0b11010, "uminv">;
5696 defm SADDLV  : SIMDAcrossLanesHSD<0, 0b00011, "saddlv">;
5697 defm UADDLV  : SIMDAcrossLanesHSD<1, 0b00011, "uaddlv">;
5698 defm FMAXNMV : SIMDFPAcrossLanes<0b01100, 0, "fmaxnmv", int_aarch64_neon_fmaxnmv>;
5699 defm FMAXV   : SIMDFPAcrossLanes<0b01111, 0, "fmaxv", int_aarch64_neon_fmaxv>;
5700 defm FMINNMV : SIMDFPAcrossLanes<0b01100, 1, "fminnmv", int_aarch64_neon_fminnmv>;
5701 defm FMINV   : SIMDFPAcrossLanes<0b01111, 1, "fminv", int_aarch64_neon_fminv>;
5703 // Patterns for uaddv(uaddlp(x)) ==> uaddlv
5704 def : Pat<(i32 (vector_extract (v8i16 (insert_subvector undef,
5705             (v4i16 (AArch64uaddv (v4i16 (AArch64uaddlp (v8i8 V64:$op))))),
5706             (i64 0))), (i64 0))),
5707           (EXTRACT_SUBREG (INSERT_SUBREG (v4i16 (IMPLICIT_DEF)),
5708            (UADDLVv4i16v V64:$op), ssub), ssub)>;
5709 def : Pat<(i32 (vector_extract (v8i16 (AArch64uaddv (v8i16 (AArch64uaddlp
5710            (v16i8 V128:$op))))), (i64 0))),
5711           (EXTRACT_SUBREG (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)),
5712            (UADDLVv16i8v V128:$op), hsub), ssub)>;
5713 def : Pat<(v4i32 (AArch64uaddv (v4i32 (AArch64uaddlp (v8i16 V128:$op))))),
5714           (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), (UADDLVv8i16v V128:$op), ssub)>;
5716 // Patterns for addp(uaddlp(x))) ==> uaddlv
5717 def : Pat<(v2i32 (AArch64uaddv (v2i32 (AArch64uaddlp (v4i16 V64:$op))))),
5718           (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)), (UADDLVv4i16v V64:$op), ssub)>;
5719 def : Pat<(v2i64 (AArch64uaddv (v2i64 (AArch64uaddlp (v4i32 V128:$op))))),
5720           (INSERT_SUBREG (v2i64 (IMPLICIT_DEF)), (UADDLVv4i32v V128:$op), dsub)>;
5722 // Patterns for across-vector intrinsics, that have a node equivalent, that
5723 // returns a vector (with only the low lane defined) instead of a scalar.
5724 // In effect, opNode is the same as (scalar_to_vector (IntNode)).
5725 multiclass SIMDAcrossLanesIntrinsic<string baseOpc,
5726                                     SDPatternOperator opNode> {
5727 // If a lane instruction caught the vector_extract around opNode, we can
5728 // directly match the latter to the instruction.
5729 def : Pat<(v8i8 (opNode V64:$Rn)),
5730           (INSERT_SUBREG (v8i8 (IMPLICIT_DEF)),
5731            (!cast<Instruction>(!strconcat(baseOpc, "v8i8v")) V64:$Rn), bsub)>;
5732 def : Pat<(v16i8 (opNode V128:$Rn)),
5733           (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5734            (!cast<Instruction>(!strconcat(baseOpc, "v16i8v")) V128:$Rn), bsub)>;
5735 def : Pat<(v4i16 (opNode V64:$Rn)),
5736           (INSERT_SUBREG (v4i16 (IMPLICIT_DEF)),
5737            (!cast<Instruction>(!strconcat(baseOpc, "v4i16v")) V64:$Rn), hsub)>;
5738 def : Pat<(v8i16 (opNode V128:$Rn)),
5739           (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)),
5740            (!cast<Instruction>(!strconcat(baseOpc, "v8i16v")) V128:$Rn), hsub)>;
5741 def : Pat<(v4i32 (opNode V128:$Rn)),
5742           (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
5743            (!cast<Instruction>(!strconcat(baseOpc, "v4i32v")) V128:$Rn), ssub)>;
5746 // If none did, fallback to the explicit patterns, consuming the vector_extract.
5747 def : Pat<(i32 (vector_extract (insert_subvector undef, (v8i8 (opNode V64:$Rn)),
5748             (i64 0)), (i64 0))),
5749           (EXTRACT_SUBREG (INSERT_SUBREG (v8i8 (IMPLICIT_DEF)),
5750             (!cast<Instruction>(!strconcat(baseOpc, "v8i8v")) V64:$Rn),
5751             bsub), ssub)>;
5752 def : Pat<(i32 (vector_extract (v16i8 (opNode V128:$Rn)), (i64 0))),
5753           (EXTRACT_SUBREG (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5754             (!cast<Instruction>(!strconcat(baseOpc, "v16i8v")) V128:$Rn),
5755             bsub), ssub)>;
5756 def : Pat<(i32 (vector_extract (insert_subvector undef,
5757             (v4i16 (opNode V64:$Rn)), (i64 0)), (i64 0))),
5758           (EXTRACT_SUBREG (INSERT_SUBREG (v4i16 (IMPLICIT_DEF)),
5759             (!cast<Instruction>(!strconcat(baseOpc, "v4i16v")) V64:$Rn),
5760             hsub), ssub)>;
5761 def : Pat<(i32 (vector_extract (v8i16 (opNode V128:$Rn)), (i64 0))),
5762           (EXTRACT_SUBREG (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)),
5763             (!cast<Instruction>(!strconcat(baseOpc, "v8i16v")) V128:$Rn),
5764             hsub), ssub)>;
5765 def : Pat<(i32 (vector_extract (v4i32 (opNode V128:$Rn)), (i64 0))),
5766           (EXTRACT_SUBREG (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
5767             (!cast<Instruction>(!strconcat(baseOpc, "v4i32v")) V128:$Rn),
5768             ssub), ssub)>;
5772 multiclass SIMDAcrossLanesSignedIntrinsic<string baseOpc,
5773                                           SDPatternOperator opNode>
5774     : SIMDAcrossLanesIntrinsic<baseOpc, opNode> {
5775 // If there is a sign extension after this intrinsic, consume it as smov already
5776 // performed it
5777 def : Pat<(i32 (sext_inreg (i32 (vector_extract (insert_subvector undef,
5778             (opNode (v8i8 V64:$Rn)), (i64 0)), (i64 0))), i8)),
5779           (i32 (SMOVvi8to32
5780             (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5781               (!cast<Instruction>(!strconcat(baseOpc, "v8i8v")) V64:$Rn), bsub),
5782             (i64 0)))>;
5783 def : Pat<(i32 (sext_inreg (i32 (vector_extract
5784             (opNode (v16i8 V128:$Rn)), (i64 0))), i8)),
5785           (i32 (SMOVvi8to32
5786             (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5787              (!cast<Instruction>(!strconcat(baseOpc, "v16i8v")) V128:$Rn), bsub),
5788             (i64 0)))>;
5789 def : Pat<(i32 (sext_inreg (i32 (vector_extract (insert_subvector undef,
5790             (opNode (v4i16 V64:$Rn)), (i64 0)), (i64 0))), i16)),
5791           (i32 (SMOVvi16to32
5792            (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5793             (!cast<Instruction>(!strconcat(baseOpc, "v4i16v")) V64:$Rn), hsub),
5794            (i64 0)))>;
5795 def : Pat<(i32 (sext_inreg (i32 (vector_extract
5796             (opNode (v8i16 V128:$Rn)), (i64 0))), i16)),
5797           (i32 (SMOVvi16to32
5798             (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5799              (!cast<Instruction>(!strconcat(baseOpc, "v8i16v")) V128:$Rn), hsub),
5800             (i64 0)))>;
5803 multiclass SIMDAcrossLanesUnsignedIntrinsic<string baseOpc,
5804                                             SDPatternOperator opNode>
5805     : SIMDAcrossLanesIntrinsic<baseOpc, opNode> {
5806 // If there is a masking operation keeping only what has been actually
5807 // generated, consume it.
5808 def : Pat<(i32 (and (i32 (vector_extract (insert_subvector undef,
5809             (opNode (v8i8 V64:$Rn)), (i64 0)), (i64 0))), maski8_or_more)),
5810       (i32 (EXTRACT_SUBREG
5811         (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5812           (!cast<Instruction>(!strconcat(baseOpc, "v8i8v")) V64:$Rn), bsub),
5813         ssub))>;
5814 def : Pat<(i32 (and (i32 (vector_extract (opNode (v16i8 V128:$Rn)), (i64 0))),
5815             maski8_or_more)),
5816         (i32 (EXTRACT_SUBREG
5817           (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5818             (!cast<Instruction>(!strconcat(baseOpc, "v16i8v")) V128:$Rn), bsub),
5819           ssub))>;
5820 def : Pat<(i32 (and (i32 (vector_extract (insert_subvector undef,
5821             (opNode (v4i16 V64:$Rn)), (i64 0)), (i64 0))), maski16_or_more)),
5822           (i32 (EXTRACT_SUBREG
5823             (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5824               (!cast<Instruction>(!strconcat(baseOpc, "v4i16v")) V64:$Rn), hsub),
5825             ssub))>;
5826 def : Pat<(i32 (and (i32 (vector_extract (opNode (v8i16 V128:$Rn)), (i64 0))),
5827             maski16_or_more)),
5828         (i32 (EXTRACT_SUBREG
5829           (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5830             (!cast<Instruction>(!strconcat(baseOpc, "v8i16v")) V128:$Rn), hsub),
5831           ssub))>;
5834 defm : SIMDAcrossLanesSignedIntrinsic<"ADDV",  AArch64saddv>;
5835 // vaddv_[su]32 is special; -> ADDP Vd.2S,Vn.2S,Vm.2S; return Vd.s[0];Vn==Vm
5836 def : Pat<(v2i32 (AArch64saddv (v2i32 V64:$Rn))),
5837           (ADDPv2i32 V64:$Rn, V64:$Rn)>;
5839 defm : SIMDAcrossLanesUnsignedIntrinsic<"ADDV", AArch64uaddv>;
5840 // vaddv_[su]32 is special; -> ADDP Vd.2S,Vn.2S,Vm.2S; return Vd.s[0];Vn==Vm
5841 def : Pat<(v2i32 (AArch64uaddv (v2i32 V64:$Rn))),
5842           (ADDPv2i32 V64:$Rn, V64:$Rn)>;
5844 defm : SIMDAcrossLanesSignedIntrinsic<"SMAXV", AArch64smaxv>;
5845 def : Pat<(v2i32 (AArch64smaxv (v2i32 V64:$Rn))),
5846           (SMAXPv2i32 V64:$Rn, V64:$Rn)>;
5848 defm : SIMDAcrossLanesSignedIntrinsic<"SMINV", AArch64sminv>;
5849 def : Pat<(v2i32 (AArch64sminv (v2i32 V64:$Rn))),
5850           (SMINPv2i32 V64:$Rn, V64:$Rn)>;
5852 defm : SIMDAcrossLanesUnsignedIntrinsic<"UMAXV", AArch64umaxv>;
5853 def : Pat<(v2i32 (AArch64umaxv (v2i32 V64:$Rn))),
5854           (UMAXPv2i32 V64:$Rn, V64:$Rn)>;
5856 defm : SIMDAcrossLanesUnsignedIntrinsic<"UMINV", AArch64uminv>;
5857 def : Pat<(v2i32 (AArch64uminv (v2i32 V64:$Rn))),
5858           (UMINPv2i32 V64:$Rn, V64:$Rn)>;
5860 multiclass SIMDAcrossLanesSignedLongIntrinsic<string baseOpc, Intrinsic intOp> {
5861   def : Pat<(i32 (intOp (v8i8 V64:$Rn))),
5862         (i32 (SMOVvi16to32
5863           (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5864             (!cast<Instruction>(!strconcat(baseOpc, "v8i8v")) V64:$Rn), hsub),
5865           (i64 0)))>;
5866 def : Pat<(i32 (intOp (v16i8 V128:$Rn))),
5867         (i32 (SMOVvi16to32
5868           (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5869            (!cast<Instruction>(!strconcat(baseOpc, "v16i8v")) V128:$Rn), hsub),
5870           (i64 0)))>;
5872 def : Pat<(i32 (intOp (v4i16 V64:$Rn))),
5873           (i32 (EXTRACT_SUBREG
5874            (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5875             (!cast<Instruction>(!strconcat(baseOpc, "v4i16v")) V64:$Rn), ssub),
5876            ssub))>;
5877 def : Pat<(i32 (intOp (v8i16 V128:$Rn))),
5878         (i32 (EXTRACT_SUBREG
5879           (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5880            (!cast<Instruction>(!strconcat(baseOpc, "v8i16v")) V128:$Rn), ssub),
5881           ssub))>;
5883 def : Pat<(i64 (intOp (v4i32 V128:$Rn))),
5884         (i64 (EXTRACT_SUBREG
5885           (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5886            (!cast<Instruction>(!strconcat(baseOpc, "v4i32v")) V128:$Rn), dsub),
5887           dsub))>;
5890 multiclass SIMDAcrossLanesUnsignedLongIntrinsic<string baseOpc,
5891                                                 Intrinsic intOp> {
5892   def : Pat<(i32 (intOp (v8i8 V64:$Rn))),
5893         (i32 (EXTRACT_SUBREG
5894           (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5895             (!cast<Instruction>(!strconcat(baseOpc, "v8i8v")) V64:$Rn), hsub),
5896           ssub))>;
5897 def : Pat<(i32 (intOp (v16i8 V128:$Rn))),
5898         (i32 (EXTRACT_SUBREG
5899           (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5900             (!cast<Instruction>(!strconcat(baseOpc, "v16i8v")) V128:$Rn), hsub),
5901           ssub))>;
5903 def : Pat<(i32 (intOp (v4i16 V64:$Rn))),
5904           (i32 (EXTRACT_SUBREG
5905             (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5906               (!cast<Instruction>(!strconcat(baseOpc, "v4i16v")) V64:$Rn), ssub),
5907             ssub))>;
5908 def : Pat<(i32 (intOp (v8i16 V128:$Rn))),
5909         (i32 (EXTRACT_SUBREG
5910           (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5911             (!cast<Instruction>(!strconcat(baseOpc, "v8i16v")) V128:$Rn), ssub),
5912           ssub))>;
5914 def : Pat<(i64 (intOp (v4i32 V128:$Rn))),
5915         (i64 (EXTRACT_SUBREG
5916           (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5917             (!cast<Instruction>(!strconcat(baseOpc, "v4i32v")) V128:$Rn), dsub),
5918           dsub))>;
5921 defm : SIMDAcrossLanesSignedLongIntrinsic<"SADDLV", int_aarch64_neon_saddlv>;
5922 defm : SIMDAcrossLanesUnsignedLongIntrinsic<"UADDLV", int_aarch64_neon_uaddlv>;
5924 // The vaddlv_s32 intrinsic gets mapped to SADDLP.
5925 def : Pat<(i64 (int_aarch64_neon_saddlv (v2i32 V64:$Rn))),
5926           (i64 (EXTRACT_SUBREG
5927             (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5928               (SADDLPv2i32_v1i64 V64:$Rn), dsub),
5929             dsub))>;
5930 // The vaddlv_u32 intrinsic gets mapped to UADDLP.
5931 def : Pat<(i64 (int_aarch64_neon_uaddlv (v2i32 V64:$Rn))),
5932           (i64 (EXTRACT_SUBREG
5933             (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)),
5934               (UADDLPv2i32_v1i64 V64:$Rn), dsub),
5935             dsub))>;
5937 //------------------------------------------------------------------------------
5938 // AdvSIMD modified immediate instructions
5939 //------------------------------------------------------------------------------
5941 // AdvSIMD BIC
5942 defm BIC : SIMDModifiedImmVectorShiftTied<1, 0b11, 0b01, "bic", AArch64bici>;
5943 // AdvSIMD ORR
5944 defm ORR : SIMDModifiedImmVectorShiftTied<0, 0b11, 0b01, "orr", AArch64orri>;
5946 def : InstAlias<"bic $Vd.4h, $imm", (BICv4i16 V64:$Vd,  imm0_255:$imm, 0)>;
5947 def : InstAlias<"bic $Vd.8h, $imm", (BICv8i16 V128:$Vd, imm0_255:$imm, 0)>;
5948 def : InstAlias<"bic $Vd.2s, $imm", (BICv2i32 V64:$Vd,  imm0_255:$imm, 0)>;
5949 def : InstAlias<"bic $Vd.4s, $imm", (BICv4i32 V128:$Vd, imm0_255:$imm, 0)>;
5951 def : InstAlias<"bic.4h $Vd, $imm", (BICv4i16 V64:$Vd,  imm0_255:$imm, 0)>;
5952 def : InstAlias<"bic.8h $Vd, $imm", (BICv8i16 V128:$Vd, imm0_255:$imm, 0)>;
5953 def : InstAlias<"bic.2s $Vd, $imm", (BICv2i32 V64:$Vd,  imm0_255:$imm, 0)>;
5954 def : InstAlias<"bic.4s $Vd, $imm", (BICv4i32 V128:$Vd, imm0_255:$imm, 0)>;
5956 def : InstAlias<"orr $Vd.4h, $imm", (ORRv4i16 V64:$Vd,  imm0_255:$imm, 0)>;
5957 def : InstAlias<"orr $Vd.8h, $imm", (ORRv8i16 V128:$Vd, imm0_255:$imm, 0)>;
5958 def : InstAlias<"orr $Vd.2s, $imm", (ORRv2i32 V64:$Vd,  imm0_255:$imm, 0)>;
5959 def : InstAlias<"orr $Vd.4s, $imm", (ORRv4i32 V128:$Vd, imm0_255:$imm, 0)>;
5961 def : InstAlias<"orr.4h $Vd, $imm", (ORRv4i16 V64:$Vd,  imm0_255:$imm, 0)>;
5962 def : InstAlias<"orr.8h $Vd, $imm", (ORRv8i16 V128:$Vd, imm0_255:$imm, 0)>;
5963 def : InstAlias<"orr.2s $Vd, $imm", (ORRv2i32 V64:$Vd,  imm0_255:$imm, 0)>;
5964 def : InstAlias<"orr.4s $Vd, $imm", (ORRv4i32 V128:$Vd, imm0_255:$imm, 0)>;
5966 // AdvSIMD FMOV
5967 def FMOVv2f64_ns : SIMDModifiedImmVectorNoShift<1, 1, 0, 0b1111, V128, fpimm8,
5968                                               "fmov", ".2d",
5969                        [(set (v2f64 V128:$Rd), (AArch64fmov imm0_255:$imm8))]>;
5970 def FMOVv2f32_ns : SIMDModifiedImmVectorNoShift<0, 0, 0, 0b1111, V64,  fpimm8,
5971                                               "fmov", ".2s",
5972                        [(set (v2f32 V64:$Rd), (AArch64fmov imm0_255:$imm8))]>;
5973 def FMOVv4f32_ns : SIMDModifiedImmVectorNoShift<1, 0, 0, 0b1111, V128, fpimm8,
5974                                               "fmov", ".4s",
5975                        [(set (v4f32 V128:$Rd), (AArch64fmov imm0_255:$imm8))]>;
5976 let Predicates = [HasNEON, HasFullFP16] in {
5977 def FMOVv4f16_ns : SIMDModifiedImmVectorNoShift<0, 0, 1, 0b1111, V64,  fpimm8,
5978                                               "fmov", ".4h",
5979                        [(set (v4f16 V64:$Rd), (AArch64fmov imm0_255:$imm8))]>;
5980 def FMOVv8f16_ns : SIMDModifiedImmVectorNoShift<1, 0, 1, 0b1111, V128, fpimm8,
5981                                               "fmov", ".8h",
5982                        [(set (v8f16 V128:$Rd), (AArch64fmov imm0_255:$imm8))]>;
5983 } // Predicates = [HasNEON, HasFullFP16]
5985 // AdvSIMD MOVI
5987 // EDIT byte mask: scalar
5988 let isReMaterializable = 1, isAsCheapAsAMove = 1 in
5989 def MOVID      : SIMDModifiedImmScalarNoShift<0, 1, 0b1110, "movi",
5990                     [(set FPR64:$Rd, simdimmtype10:$imm8)]>;
5991 // The movi_edit node has the immediate value already encoded, so we use
5992 // a plain imm0_255 here.
5993 def : Pat<(f64 (AArch64movi_edit imm0_255:$shift)),
5994           (MOVID imm0_255:$shift)>;
5996 // EDIT byte mask: 2d
5998 // The movi_edit node has the immediate value already encoded, so we use
5999 // a plain imm0_255 in the pattern
6000 let isReMaterializable = 1, isAsCheapAsAMove = 1 in
6001 def MOVIv2d_ns   : SIMDModifiedImmVectorNoShift<1, 1, 0, 0b1110, V128,
6002                                                 simdimmtype10,
6003                                                 "movi", ".2d",
6004                    [(set (v2i64 V128:$Rd), (AArch64movi_edit imm0_255:$imm8))]>;
6006 def : Pat<(v2i64 immAllZerosV), (MOVIv2d_ns (i32 0))>;
6007 def : Pat<(v4i32 immAllZerosV), (MOVIv2d_ns (i32 0))>;
6008 def : Pat<(v8i16 immAllZerosV), (MOVIv2d_ns (i32 0))>;
6009 def : Pat<(v16i8 immAllZerosV), (MOVIv2d_ns (i32 0))>;
6011 def : Pat<(v2i64 immAllOnesV), (MOVIv2d_ns (i32 255))>;
6012 def : Pat<(v4i32 immAllOnesV), (MOVIv2d_ns (i32 255))>;
6013 def : Pat<(v8i16 immAllOnesV), (MOVIv2d_ns (i32 255))>;
6014 def : Pat<(v16i8 immAllOnesV), (MOVIv2d_ns (i32 255))>;
6016 // Set 64-bit vectors to all 0/1 by extracting from a 128-bit register as the
6017 // extract is free and this gives better MachineCSE results.
6018 def : Pat<(v1i64 immAllZerosV), (EXTRACT_SUBREG (MOVIv2d_ns (i32 0)), dsub)>;
6019 def : Pat<(v2i32 immAllZerosV), (EXTRACT_SUBREG (MOVIv2d_ns (i32 0)), dsub)>;
6020 def : Pat<(v4i16 immAllZerosV), (EXTRACT_SUBREG (MOVIv2d_ns (i32 0)), dsub)>;
6021 def : Pat<(v8i8  immAllZerosV), (EXTRACT_SUBREG (MOVIv2d_ns (i32 0)), dsub)>;
6023 def : Pat<(v1i64 immAllOnesV), (EXTRACT_SUBREG (MOVIv2d_ns (i32 255)), dsub)>;
6024 def : Pat<(v2i32 immAllOnesV), (EXTRACT_SUBREG (MOVIv2d_ns (i32 255)), dsub)>;
6025 def : Pat<(v4i16 immAllOnesV), (EXTRACT_SUBREG (MOVIv2d_ns (i32 255)), dsub)>;
6026 def : Pat<(v8i8  immAllOnesV), (EXTRACT_SUBREG (MOVIv2d_ns (i32 255)), dsub)>;
6028 // EDIT per word & halfword: 2s, 4h, 4s, & 8h
6029 let isReMaterializable = 1, isAsCheapAsAMove = 1 in
6030 defm MOVI      : SIMDModifiedImmVectorShift<0, 0b10, 0b00, "movi">;
6032 def : InstAlias<"movi $Vd.4h, $imm", (MOVIv4i16 V64:$Vd,  imm0_255:$imm, 0), 0>;
6033 def : InstAlias<"movi $Vd.8h, $imm", (MOVIv8i16 V128:$Vd, imm0_255:$imm, 0), 0>;
6034 def : InstAlias<"movi $Vd.2s, $imm", (MOVIv2i32 V64:$Vd,  imm0_255:$imm, 0), 0>;
6035 def : InstAlias<"movi $Vd.4s, $imm", (MOVIv4i32 V128:$Vd, imm0_255:$imm, 0), 0>;
6037 def : InstAlias<"movi.4h $Vd, $imm", (MOVIv4i16 V64:$Vd,  imm0_255:$imm, 0), 0>;
6038 def : InstAlias<"movi.8h $Vd, $imm", (MOVIv8i16 V128:$Vd, imm0_255:$imm, 0), 0>;
6039 def : InstAlias<"movi.2s $Vd, $imm", (MOVIv2i32 V64:$Vd,  imm0_255:$imm, 0), 0>;
6040 def : InstAlias<"movi.4s $Vd, $imm", (MOVIv4i32 V128:$Vd, imm0_255:$imm, 0), 0>;
6042 def : Pat<(v2i32 (AArch64movi_shift imm0_255:$imm8, (i32 imm:$shift))),
6043           (MOVIv2i32 imm0_255:$imm8, imm:$shift)>;
6044 def : Pat<(v4i32 (AArch64movi_shift imm0_255:$imm8, (i32 imm:$shift))),
6045           (MOVIv4i32 imm0_255:$imm8, imm:$shift)>;
6046 def : Pat<(v4i16 (AArch64movi_shift imm0_255:$imm8, (i32 imm:$shift))),
6047           (MOVIv4i16 imm0_255:$imm8, imm:$shift)>;
6048 def : Pat<(v8i16 (AArch64movi_shift imm0_255:$imm8, (i32 imm:$shift))),
6049           (MOVIv8i16 imm0_255:$imm8, imm:$shift)>;
6051 let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
6052 // EDIT per word: 2s & 4s with MSL shifter
6053 def MOVIv2s_msl  : SIMDModifiedImmMoveMSL<0, 0, {1,1,0,?}, V64, "movi", ".2s",
6054                       [(set (v2i32 V64:$Rd),
6055                             (AArch64movi_msl imm0_255:$imm8, (i32 imm:$shift)))]>;
6056 def MOVIv4s_msl  : SIMDModifiedImmMoveMSL<1, 0, {1,1,0,?}, V128, "movi", ".4s",
6057                       [(set (v4i32 V128:$Rd),
6058                             (AArch64movi_msl imm0_255:$imm8, (i32 imm:$shift)))]>;
6060 // Per byte: 8b & 16b
6061 def MOVIv8b_ns   : SIMDModifiedImmVectorNoShift<0, 0, 0, 0b1110, V64,  imm0_255,
6062                                                  "movi", ".8b",
6063                        [(set (v8i8 V64:$Rd), (AArch64movi imm0_255:$imm8))]>;
6065 def MOVIv16b_ns  : SIMDModifiedImmVectorNoShift<1, 0, 0, 0b1110, V128, imm0_255,
6066                                                  "movi", ".16b",
6067                        [(set (v16i8 V128:$Rd), (AArch64movi imm0_255:$imm8))]>;
6070 // AdvSIMD MVNI
6072 // EDIT per word & halfword: 2s, 4h, 4s, & 8h
6073 let isReMaterializable = 1, isAsCheapAsAMove = 1 in
6074 defm MVNI      : SIMDModifiedImmVectorShift<1, 0b10, 0b00, "mvni">;
6076 def : InstAlias<"mvni $Vd.4h, $imm", (MVNIv4i16 V64:$Vd,  imm0_255:$imm, 0), 0>;
6077 def : InstAlias<"mvni $Vd.8h, $imm", (MVNIv8i16 V128:$Vd, imm0_255:$imm, 0), 0>;
6078 def : InstAlias<"mvni $Vd.2s, $imm", (MVNIv2i32 V64:$Vd,  imm0_255:$imm, 0), 0>;
6079 def : InstAlias<"mvni $Vd.4s, $imm", (MVNIv4i32 V128:$Vd, imm0_255:$imm, 0), 0>;
6081 def : InstAlias<"mvni.4h $Vd, $imm", (MVNIv4i16 V64:$Vd,  imm0_255:$imm, 0), 0>;
6082 def : InstAlias<"mvni.8h $Vd, $imm", (MVNIv8i16 V128:$Vd, imm0_255:$imm, 0), 0>;
6083 def : InstAlias<"mvni.2s $Vd, $imm", (MVNIv2i32 V64:$Vd,  imm0_255:$imm, 0), 0>;
6084 def : InstAlias<"mvni.4s $Vd, $imm", (MVNIv4i32 V128:$Vd, imm0_255:$imm, 0), 0>;
6086 def : Pat<(v2i32 (AArch64mvni_shift imm0_255:$imm8, (i32 imm:$shift))),
6087           (MVNIv2i32 imm0_255:$imm8, imm:$shift)>;
6088 def : Pat<(v4i32 (AArch64mvni_shift imm0_255:$imm8, (i32 imm:$shift))),
6089           (MVNIv4i32 imm0_255:$imm8, imm:$shift)>;
6090 def : Pat<(v4i16 (AArch64mvni_shift imm0_255:$imm8, (i32 imm:$shift))),
6091           (MVNIv4i16 imm0_255:$imm8, imm:$shift)>;
6092 def : Pat<(v8i16 (AArch64mvni_shift imm0_255:$imm8, (i32 imm:$shift))),
6093           (MVNIv8i16 imm0_255:$imm8, imm:$shift)>;
6095 // EDIT per word: 2s & 4s with MSL shifter
6096 let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
6097 def MVNIv2s_msl   : SIMDModifiedImmMoveMSL<0, 1, {1,1,0,?}, V64, "mvni", ".2s",
6098                       [(set (v2i32 V64:$Rd),
6099                             (AArch64mvni_msl imm0_255:$imm8, (i32 imm:$shift)))]>;
6100 def MVNIv4s_msl   : SIMDModifiedImmMoveMSL<1, 1, {1,1,0,?}, V128, "mvni", ".4s",
6101                       [(set (v4i32 V128:$Rd),
6102                             (AArch64mvni_msl imm0_255:$imm8, (i32 imm:$shift)))]>;
6105 //----------------------------------------------------------------------------
6106 // AdvSIMD indexed element
6107 //----------------------------------------------------------------------------
6109 let hasSideEffects = 0 in {
6110   defm FMLA  : SIMDFPIndexedTied<0, 0b0001, "fmla">;
6111   defm FMLS  : SIMDFPIndexedTied<0, 0b0101, "fmls">;
6114 // NOTE: Operands are reordered in the FMLA/FMLS PatFrags because the
6115 // instruction expects the addend first, while the intrinsic expects it last.
6117 // On the other hand, there are quite a few valid combinatorial options due to
6118 // the commutativity of multiplication and the fact that (-x) * y = x * (-y).
6119 defm : SIMDFPIndexedTiedPatterns<"FMLA",
6120            TriOpFrag<(fma node:$RHS, node:$MHS, node:$LHS)>>;
6121 defm : SIMDFPIndexedTiedPatterns<"FMLA",
6122            TriOpFrag<(fma node:$MHS, node:$RHS, node:$LHS)>>;
6124 defm : SIMDFPIndexedTiedPatterns<"FMLS",
6125            TriOpFrag<(fma node:$MHS, (fneg node:$RHS), node:$LHS)> >;
6126 defm : SIMDFPIndexedTiedPatterns<"FMLS",
6127            TriOpFrag<(fma node:$RHS, (fneg node:$MHS), node:$LHS)> >;
6128 defm : SIMDFPIndexedTiedPatterns<"FMLS",
6129            TriOpFrag<(fma (fneg node:$RHS), node:$MHS, node:$LHS)> >;
6130 defm : SIMDFPIndexedTiedPatterns<"FMLS",
6131            TriOpFrag<(fma (fneg node:$MHS), node:$RHS, node:$LHS)> >;
6133 multiclass FMLSIndexedAfterNegPatterns<SDPatternOperator OpNode> {
6134   // 3 variants for the .2s version: DUPLANE from 128-bit, DUPLANE from 64-bit
6135   // and DUP scalar.
6136   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6137                            (AArch64duplane32 (v4f32 (fneg V128:$Rm)),
6138                                            VectorIndexS:$idx))),
6139             (FMLSv2i32_indexed V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6140   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6141                            (v2f32 (AArch64duplane32
6142                                       (v4f32 (insert_subvector undef,
6143                                                  (v2f32 (fneg V64:$Rm)),
6144                                                  (i64 0))),
6145                                       VectorIndexS:$idx)))),
6146             (FMLSv2i32_indexed V64:$Rd, V64:$Rn,
6147                                (SUBREG_TO_REG (i32 0), V64:$Rm, dsub),
6148                                VectorIndexS:$idx)>;
6149   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6150                            (AArch64dup (f32 (fneg FPR32Op:$Rm))))),
6151             (FMLSv2i32_indexed V64:$Rd, V64:$Rn,
6152                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6154   // 3 variants for the .4s version: DUPLANE from 128-bit, DUPLANE from 64-bit
6155   // and DUP scalar.
6156   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6157                            (AArch64duplane32 (v4f32 (fneg V128:$Rm)),
6158                                            VectorIndexS:$idx))),
6159             (FMLSv4i32_indexed V128:$Rd, V128:$Rn, V128:$Rm,
6160                                VectorIndexS:$idx)>;
6161   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6162                            (v4f32 (AArch64duplane32
6163                                       (v4f32 (insert_subvector undef,
6164                                                  (v2f32 (fneg V64:$Rm)),
6165                                                  (i64 0))),
6166                                       VectorIndexS:$idx)))),
6167             (FMLSv4i32_indexed V128:$Rd, V128:$Rn,
6168                                (SUBREG_TO_REG (i32 0), V64:$Rm, dsub),
6169                                VectorIndexS:$idx)>;
6170   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6171                            (AArch64dup (f32 (fneg FPR32Op:$Rm))))),
6172             (FMLSv4i32_indexed V128:$Rd, V128:$Rn,
6173                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6175   // 2 variants for the .2d version: DUPLANE from 128-bit, and DUP scalar
6176   // (DUPLANE from 64-bit would be trivial).
6177   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6178                            (AArch64duplane64 (v2f64 (fneg V128:$Rm)),
6179                                            VectorIndexD:$idx))),
6180             (FMLSv2i64_indexed
6181                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6182   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6183                            (AArch64dup (f64 (fneg FPR64Op:$Rm))))),
6184             (FMLSv2i64_indexed V128:$Rd, V128:$Rn,
6185                 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6187   // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6188   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6189                          (vector_extract (v4f32 (fneg V128:$Rm)),
6190                                          VectorIndexS:$idx))),
6191             (FMLSv1i32_indexed FPR32:$Rd, FPR32:$Rn,
6192                 V128:$Rm, VectorIndexS:$idx)>;
6193   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6194                          (vector_extract (v4f32 (insert_subvector undef,
6195                                                     (v2f32 (fneg V64:$Rm)),
6196                                                     (i64 0))),
6197                                          VectorIndexS:$idx))),
6198             (FMLSv1i32_indexed FPR32:$Rd, FPR32:$Rn,
6199                 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6201   // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6202   def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6203                          (vector_extract (v2f64 (fneg V128:$Rm)),
6204                                          VectorIndexS:$idx))),
6205             (FMLSv1i64_indexed FPR64:$Rd, FPR64:$Rn,
6206                 V128:$Rm, VectorIndexS:$idx)>;
6209 defm : FMLSIndexedAfterNegPatterns<
6210            TriOpFrag<(fma node:$RHS, node:$MHS, node:$LHS)> >;
6211 defm : FMLSIndexedAfterNegPatterns<
6212            TriOpFrag<(fma node:$MHS, node:$RHS, node:$LHS)> >;
6214 defm FMULX : SIMDFPIndexed<1, 0b1001, "fmulx", int_aarch64_neon_fmulx>;
6215 defm FMUL  : SIMDFPIndexed<0, 0b1001, "fmul", fmul>;
6217 def : Pat<(v2f32 (fmul V64:$Rn, (AArch64dup (f32 FPR32:$Rm)))),
6218           (FMULv2i32_indexed V64:$Rn,
6219             (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), FPR32:$Rm, ssub),
6220             (i64 0))>;
6221 def : Pat<(v4f32 (fmul V128:$Rn, (AArch64dup (f32 FPR32:$Rm)))),
6222           (FMULv4i32_indexed V128:$Rn,
6223             (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), FPR32:$Rm, ssub),
6224             (i64 0))>;
6225 def : Pat<(v2f64 (fmul V128:$Rn, (AArch64dup (f64 FPR64:$Rm)))),
6226           (FMULv2i64_indexed V128:$Rn,
6227             (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), FPR64:$Rm, dsub),
6228             (i64 0))>;
6230 defm SQDMULH : SIMDIndexedHS<0, 0b1100, "sqdmulh", int_aarch64_neon_sqdmulh>;
6231 defm SQRDMULH : SIMDIndexedHS<0, 0b1101, "sqrdmulh", int_aarch64_neon_sqrdmulh>;
6233 defm SQDMULH : SIMDIndexedHSPatterns<int_aarch64_neon_sqdmulh_lane,
6234                                      int_aarch64_neon_sqdmulh_laneq>;
6235 defm SQRDMULH : SIMDIndexedHSPatterns<int_aarch64_neon_sqrdmulh_lane,
6236                                       int_aarch64_neon_sqrdmulh_laneq>;
6238 // Generated by MachineCombine
6239 defm MLA   : SIMDVectorIndexedHSTied<1, 0b0000, "mla", null_frag>;
6240 defm MLS   : SIMDVectorIndexedHSTied<1, 0b0100, "mls", null_frag>;
6242 defm MUL   : SIMDVectorIndexedHS<0, 0b1000, "mul", mul>;
6243 defm SMLAL : SIMDVectorIndexedLongSDTied<0, 0b0010, "smlal",
6244     TriOpFrag<(add node:$LHS, (int_aarch64_neon_smull node:$MHS, node:$RHS))>>;
6245 defm SMLSL : SIMDVectorIndexedLongSDTied<0, 0b0110, "smlsl",
6246     TriOpFrag<(sub node:$LHS, (int_aarch64_neon_smull node:$MHS, node:$RHS))>>;
6247 defm SMULL : SIMDVectorIndexedLongSD<0, 0b1010, "smull",
6248                 int_aarch64_neon_smull>;
6249 defm SQDMLAL : SIMDIndexedLongSQDMLXSDTied<0, 0b0011, "sqdmlal",
6250                                            int_aarch64_neon_sqadd>;
6251 defm SQDMLSL : SIMDIndexedLongSQDMLXSDTied<0, 0b0111, "sqdmlsl",
6252                                            int_aarch64_neon_sqsub>;
6253 defm SQRDMLAH : SIMDIndexedSQRDMLxHSDTied<1, 0b1101, "sqrdmlah",
6254                                           int_aarch64_neon_sqadd>;
6255 defm SQRDMLSH : SIMDIndexedSQRDMLxHSDTied<1, 0b1111, "sqrdmlsh",
6256                                           int_aarch64_neon_sqsub>;
6257 defm SQDMULL : SIMDIndexedLongSD<0, 0b1011, "sqdmull", int_aarch64_neon_sqdmull>;
6258 defm UMLAL   : SIMDVectorIndexedLongSDTied<1, 0b0010, "umlal",
6259     TriOpFrag<(add node:$LHS, (int_aarch64_neon_umull node:$MHS, node:$RHS))>>;
6260 defm UMLSL   : SIMDVectorIndexedLongSDTied<1, 0b0110, "umlsl",
6261     TriOpFrag<(sub node:$LHS, (int_aarch64_neon_umull node:$MHS, node:$RHS))>>;
6262 defm UMULL   : SIMDVectorIndexedLongSD<1, 0b1010, "umull",
6263                 int_aarch64_neon_umull>;
6265 // A scalar sqdmull with the second operand being a vector lane can be
6266 // handled directly with the indexed instruction encoding.
6267 def : Pat<(int_aarch64_neon_sqdmulls_scalar (i32 FPR32:$Rn),
6268                                           (vector_extract (v4i32 V128:$Vm),
6269                                                            VectorIndexS:$idx)),
6270           (SQDMULLv1i64_indexed FPR32:$Rn, V128:$Vm, VectorIndexS:$idx)>;
6272 //----------------------------------------------------------------------------
6273 // AdvSIMD scalar shift instructions
6274 //----------------------------------------------------------------------------
6275 defm FCVTZS : SIMDFPScalarRShift<0, 0b11111, "fcvtzs">;
6276 defm FCVTZU : SIMDFPScalarRShift<1, 0b11111, "fcvtzu">;
6277 defm SCVTF  : SIMDFPScalarRShift<0, 0b11100, "scvtf">;
6278 defm UCVTF  : SIMDFPScalarRShift<1, 0b11100, "ucvtf">;
6279 // Codegen patterns for the above. We don't put these directly on the
6280 // instructions because TableGen's type inference can't handle the truth.
6281 // Having the same base pattern for fp <--> int totally freaks it out.
6282 def : Pat<(int_aarch64_neon_vcvtfp2fxs FPR32:$Rn, vecshiftR32:$imm),
6283           (FCVTZSs FPR32:$Rn, vecshiftR32:$imm)>;
6284 def : Pat<(int_aarch64_neon_vcvtfp2fxu FPR32:$Rn, vecshiftR32:$imm),
6285           (FCVTZUs FPR32:$Rn, vecshiftR32:$imm)>;
6286 def : Pat<(i64 (int_aarch64_neon_vcvtfp2fxs (f64 FPR64:$Rn), vecshiftR64:$imm)),
6287           (FCVTZSd FPR64:$Rn, vecshiftR64:$imm)>;
6288 def : Pat<(i64 (int_aarch64_neon_vcvtfp2fxu (f64 FPR64:$Rn), vecshiftR64:$imm)),
6289           (FCVTZUd FPR64:$Rn, vecshiftR64:$imm)>;
6290 def : Pat<(v1i64 (int_aarch64_neon_vcvtfp2fxs (v1f64 FPR64:$Rn),
6291                                             vecshiftR64:$imm)),
6292           (FCVTZSd FPR64:$Rn, vecshiftR64:$imm)>;
6293 def : Pat<(v1i64 (int_aarch64_neon_vcvtfp2fxu (v1f64 FPR64:$Rn),
6294                                             vecshiftR64:$imm)),
6295           (FCVTZUd FPR64:$Rn, vecshiftR64:$imm)>;
6296 def : Pat<(int_aarch64_neon_vcvtfxu2fp FPR32:$Rn, vecshiftR32:$imm),
6297           (UCVTFs FPR32:$Rn, vecshiftR32:$imm)>;
6298 def : Pat<(f64 (int_aarch64_neon_vcvtfxu2fp (i64 FPR64:$Rn), vecshiftR64:$imm)),
6299           (UCVTFd FPR64:$Rn, vecshiftR64:$imm)>;
6300 def : Pat<(v1f64 (int_aarch64_neon_vcvtfxs2fp (v1i64 FPR64:$Rn),
6301                                             vecshiftR64:$imm)),
6302           (SCVTFd FPR64:$Rn, vecshiftR64:$imm)>;
6303 def : Pat<(f64 (int_aarch64_neon_vcvtfxs2fp (i64 FPR64:$Rn), vecshiftR64:$imm)),
6304           (SCVTFd FPR64:$Rn, vecshiftR64:$imm)>;
6305 def : Pat<(v1f64 (int_aarch64_neon_vcvtfxu2fp (v1i64 FPR64:$Rn),
6306                                             vecshiftR64:$imm)),
6307           (UCVTFd FPR64:$Rn, vecshiftR64:$imm)>;
6308 def : Pat<(int_aarch64_neon_vcvtfxs2fp FPR32:$Rn, vecshiftR32:$imm),
6309           (SCVTFs FPR32:$Rn, vecshiftR32:$imm)>;
6311 // Patterns for FP16 Instrinsics - requires reg copy to/from as i16s not supported.
6313 def : Pat<(f16 (int_aarch64_neon_vcvtfxs2fp (i32 (sext_inreg FPR32:$Rn, i16)), vecshiftR16:$imm)),
6314           (SCVTFh (EXTRACT_SUBREG FPR32:$Rn, hsub), vecshiftR16:$imm)>;
6315 def : Pat<(f16 (int_aarch64_neon_vcvtfxs2fp (i32 FPR32:$Rn), vecshiftR16:$imm)),
6316           (SCVTFh (EXTRACT_SUBREG FPR32:$Rn, hsub), vecshiftR16:$imm)>;
6317 def : Pat<(f16 (int_aarch64_neon_vcvtfxs2fp (i64 FPR64:$Rn), vecshiftR16:$imm)),
6318           (SCVTFh (EXTRACT_SUBREG FPR64:$Rn, hsub), vecshiftR16:$imm)>;
6319 def : Pat<(f16 (int_aarch64_neon_vcvtfxu2fp
6320             (and FPR32:$Rn, (i32 65535)),
6321             vecshiftR16:$imm)),
6322           (UCVTFh (EXTRACT_SUBREG FPR32:$Rn, hsub), vecshiftR16:$imm)>;
6323 def : Pat<(f16 (int_aarch64_neon_vcvtfxu2fp FPR32:$Rn, vecshiftR16:$imm)),
6324           (UCVTFh (EXTRACT_SUBREG FPR32:$Rn, hsub), vecshiftR16:$imm)>;
6325 def : Pat<(f16 (int_aarch64_neon_vcvtfxu2fp (i64 FPR64:$Rn), vecshiftR16:$imm)),
6326           (UCVTFh (EXTRACT_SUBREG FPR64:$Rn, hsub), vecshiftR16:$imm)>;
6327 def : Pat<(i32 (int_aarch64_neon_vcvtfp2fxs (f16 FPR16:$Rn), vecshiftR32:$imm)),
6328           (i32 (INSERT_SUBREG
6329             (i32 (IMPLICIT_DEF)),
6330             (FCVTZSh FPR16:$Rn, vecshiftR32:$imm),
6331             hsub))>;
6332 def : Pat<(i64 (int_aarch64_neon_vcvtfp2fxs (f16 FPR16:$Rn), vecshiftR64:$imm)),
6333           (i64 (INSERT_SUBREG
6334             (i64 (IMPLICIT_DEF)),
6335             (FCVTZSh FPR16:$Rn, vecshiftR64:$imm),
6336             hsub))>;
6337 def : Pat<(i32 (int_aarch64_neon_vcvtfp2fxu (f16 FPR16:$Rn), vecshiftR32:$imm)),
6338           (i32 (INSERT_SUBREG
6339             (i32 (IMPLICIT_DEF)),
6340             (FCVTZUh FPR16:$Rn, vecshiftR32:$imm),
6341             hsub))>;
6342 def : Pat<(i64 (int_aarch64_neon_vcvtfp2fxu (f16 FPR16:$Rn), vecshiftR64:$imm)),
6343           (i64 (INSERT_SUBREG
6344             (i64 (IMPLICIT_DEF)),
6345             (FCVTZUh FPR16:$Rn, vecshiftR64:$imm),
6346             hsub))>;
6347 def : Pat<(i32 (int_aarch64_neon_facge (f16 FPR16:$Rn), (f16 FPR16:$Rm))),
6348           (i32 (INSERT_SUBREG
6349             (i32 (IMPLICIT_DEF)),
6350             (FACGE16 FPR16:$Rn, FPR16:$Rm),
6351             hsub))>;
6352 def : Pat<(i32 (int_aarch64_neon_facgt (f16 FPR16:$Rn), (f16 FPR16:$Rm))),
6353           (i32 (INSERT_SUBREG
6354             (i32 (IMPLICIT_DEF)),
6355             (FACGT16 FPR16:$Rn, FPR16:$Rm),
6356             hsub))>;
6358 defm SHL      : SIMDScalarLShiftD<   0, 0b01010, "shl", AArch64vshl>;
6359 defm SLI      : SIMDScalarLShiftDTied<1, 0b01010, "sli">;
6360 defm SQRSHRN  : SIMDScalarRShiftBHS< 0, 0b10011, "sqrshrn",
6361                                      int_aarch64_neon_sqrshrn>;
6362 defm SQRSHRUN : SIMDScalarRShiftBHS< 1, 0b10001, "sqrshrun",
6363                                      int_aarch64_neon_sqrshrun>;
6364 defm SQSHLU   : SIMDScalarLShiftBHSD<1, 0b01100, "sqshlu", AArch64sqshlui>;
6365 defm SQSHL    : SIMDScalarLShiftBHSD<0, 0b01110, "sqshl", AArch64sqshli>;
6366 defm SQSHRN   : SIMDScalarRShiftBHS< 0, 0b10010, "sqshrn",
6367                                      int_aarch64_neon_sqshrn>;
6368 defm SQSHRUN  : SIMDScalarRShiftBHS< 1, 0b10000, "sqshrun",
6369                                      int_aarch64_neon_sqshrun>;
6370 defm SRI      : SIMDScalarRShiftDTied<   1, 0b01000, "sri">;
6371 defm SRSHR    : SIMDScalarRShiftD<   0, 0b00100, "srshr", AArch64srshri>;
6372 defm SRSRA    : SIMDScalarRShiftDTied<   0, 0b00110, "srsra",
6373     TriOpFrag<(add node:$LHS,
6374                    (AArch64srshri node:$MHS, node:$RHS))>>;
6375 defm SSHR     : SIMDScalarRShiftD<   0, 0b00000, "sshr", AArch64vashr>;
6376 defm SSRA     : SIMDScalarRShiftDTied<   0, 0b00010, "ssra",
6377     TriOpFrag<(add node:$LHS,
6378                    (AArch64vashr node:$MHS, node:$RHS))>>;
6379 defm UQRSHRN  : SIMDScalarRShiftBHS< 1, 0b10011, "uqrshrn",
6380                                      int_aarch64_neon_uqrshrn>;
6381 defm UQSHL    : SIMDScalarLShiftBHSD<1, 0b01110, "uqshl", AArch64uqshli>;
6382 defm UQSHRN   : SIMDScalarRShiftBHS< 1, 0b10010, "uqshrn",
6383                                      int_aarch64_neon_uqshrn>;
6384 defm URSHR    : SIMDScalarRShiftD<   1, 0b00100, "urshr", AArch64urshri>;
6385 defm URSRA    : SIMDScalarRShiftDTied<   1, 0b00110, "ursra",
6386     TriOpFrag<(add node:$LHS,
6387                    (AArch64urshri node:$MHS, node:$RHS))>>;
6388 defm USHR     : SIMDScalarRShiftD<   1, 0b00000, "ushr", AArch64vlshr>;
6389 defm USRA     : SIMDScalarRShiftDTied<   1, 0b00010, "usra",
6390     TriOpFrag<(add node:$LHS,
6391                    (AArch64vlshr node:$MHS, node:$RHS))>>;
6393 //----------------------------------------------------------------------------
6394 // AdvSIMD vector shift instructions
6395 //----------------------------------------------------------------------------
6396 defm FCVTZS:SIMDVectorRShiftSD<0, 0b11111, "fcvtzs", int_aarch64_neon_vcvtfp2fxs>;
6397 defm FCVTZU:SIMDVectorRShiftSD<1, 0b11111, "fcvtzu", int_aarch64_neon_vcvtfp2fxu>;
6398 defm SCVTF: SIMDVectorRShiftToFP<0, 0b11100, "scvtf",
6399                                    int_aarch64_neon_vcvtfxs2fp>;
6400 defm RSHRN   : SIMDVectorRShiftNarrowBHS<0, 0b10001, "rshrn",
6401                                          int_aarch64_neon_rshrn>;
6402 defm SHL     : SIMDVectorLShiftBHSD<0, 0b01010, "shl", AArch64vshl>;
6403 defm SHRN    : SIMDVectorRShiftNarrowBHS<0, 0b10000, "shrn",
6404                           BinOpFrag<(trunc (AArch64vashr node:$LHS, node:$RHS))>>;
6405 defm SLI     : SIMDVectorLShiftBHSDTied<1, 0b01010, "sli", AArch64vsli>;
6406 def : Pat<(v1i64 (AArch64vsli (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
6407                                       (i32 vecshiftL64:$imm))),
6408           (SLId FPR64:$Rd, FPR64:$Rn, vecshiftL64:$imm)>;
6409 defm SQRSHRN : SIMDVectorRShiftNarrowBHS<0, 0b10011, "sqrshrn",
6410                                          int_aarch64_neon_sqrshrn>;
6411 defm SQRSHRUN: SIMDVectorRShiftNarrowBHS<1, 0b10001, "sqrshrun",
6412                                          int_aarch64_neon_sqrshrun>;
6413 defm SQSHLU : SIMDVectorLShiftBHSD<1, 0b01100, "sqshlu", AArch64sqshlui>;
6414 defm SQSHL  : SIMDVectorLShiftBHSD<0, 0b01110, "sqshl", AArch64sqshli>;
6415 defm SQSHRN  : SIMDVectorRShiftNarrowBHS<0, 0b10010, "sqshrn",
6416                                          int_aarch64_neon_sqshrn>;
6417 defm SQSHRUN : SIMDVectorRShiftNarrowBHS<1, 0b10000, "sqshrun",
6418                                          int_aarch64_neon_sqshrun>;
6419 defm SRI     : SIMDVectorRShiftBHSDTied<1, 0b01000, "sri", AArch64vsri>;
6420 def : Pat<(v1i64 (AArch64vsri (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
6421                                       (i32 vecshiftR64:$imm))),
6422           (SRId FPR64:$Rd, FPR64:$Rn, vecshiftR64:$imm)>;
6423 defm SRSHR   : SIMDVectorRShiftBHSD<0, 0b00100, "srshr", AArch64srshri>;
6424 defm SRSRA   : SIMDVectorRShiftBHSDTied<0, 0b00110, "srsra",
6425                  TriOpFrag<(add node:$LHS,
6426                                 (AArch64srshri node:$MHS, node:$RHS))> >;
6427 defm SSHLL   : SIMDVectorLShiftLongBHSD<0, 0b10100, "sshll",
6428                 BinOpFrag<(AArch64vshl (sext node:$LHS), node:$RHS)>>;
6430 defm SSHR    : SIMDVectorRShiftBHSD<0, 0b00000, "sshr", AArch64vashr>;
6431 defm SSRA    : SIMDVectorRShiftBHSDTied<0, 0b00010, "ssra",
6432                 TriOpFrag<(add node:$LHS, (AArch64vashr node:$MHS, node:$RHS))>>;
6433 defm UCVTF   : SIMDVectorRShiftToFP<1, 0b11100, "ucvtf",
6434                         int_aarch64_neon_vcvtfxu2fp>;
6435 defm UQRSHRN : SIMDVectorRShiftNarrowBHS<1, 0b10011, "uqrshrn",
6436                                          int_aarch64_neon_uqrshrn>;
6437 defm UQSHL   : SIMDVectorLShiftBHSD<1, 0b01110, "uqshl", AArch64uqshli>;
6438 defm UQSHRN  : SIMDVectorRShiftNarrowBHS<1, 0b10010, "uqshrn",
6439                                          int_aarch64_neon_uqshrn>;
6440 defm URSHR   : SIMDVectorRShiftBHSD<1, 0b00100, "urshr", AArch64urshri>;
6441 defm URSRA   : SIMDVectorRShiftBHSDTied<1, 0b00110, "ursra",
6442                 TriOpFrag<(add node:$LHS,
6443                                (AArch64urshri node:$MHS, node:$RHS))> >;
6444 defm USHLL   : SIMDVectorLShiftLongBHSD<1, 0b10100, "ushll",
6445                 BinOpFrag<(AArch64vshl (zext node:$LHS), node:$RHS)>>;
6446 defm USHR    : SIMDVectorRShiftBHSD<1, 0b00000, "ushr", AArch64vlshr>;
6447 defm USRA    : SIMDVectorRShiftBHSDTied<1, 0b00010, "usra",
6448                 TriOpFrag<(add node:$LHS, (AArch64vlshr node:$MHS, node:$RHS))> >;
6450 // SHRN patterns for when a logical right shift was used instead of arithmetic
6451 // (the immediate guarantees no sign bits actually end up in the result so it
6452 // doesn't matter).
6453 def : Pat<(v8i8 (trunc (AArch64vlshr (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))),
6454           (SHRNv8i8_shift V128:$Rn, vecshiftR16Narrow:$imm)>;
6455 def : Pat<(v4i16 (trunc (AArch64vlshr (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))),
6456           (SHRNv4i16_shift V128:$Rn, vecshiftR32Narrow:$imm)>;
6457 def : Pat<(v2i32 (trunc (AArch64vlshr (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))),
6458           (SHRNv2i32_shift V128:$Rn, vecshiftR64Narrow:$imm)>;
6460 def : Pat<(v16i8 (concat_vectors (v8i8 V64:$Rd),
6461                                  (trunc (AArch64vlshr (v8i16 V128:$Rn),
6462                                                     vecshiftR16Narrow:$imm)))),
6463           (SHRNv16i8_shift (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6464                            V128:$Rn, vecshiftR16Narrow:$imm)>;
6465 def : Pat<(v8i16 (concat_vectors (v4i16 V64:$Rd),
6466                                  (trunc (AArch64vlshr (v4i32 V128:$Rn),
6467                                                     vecshiftR32Narrow:$imm)))),
6468           (SHRNv8i16_shift (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6469                            V128:$Rn, vecshiftR32Narrow:$imm)>;
6470 def : Pat<(v4i32 (concat_vectors (v2i32 V64:$Rd),
6471                                  (trunc (AArch64vlshr (v2i64 V128:$Rn),
6472                                                     vecshiftR64Narrow:$imm)))),
6473           (SHRNv4i32_shift (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6474                            V128:$Rn, vecshiftR32Narrow:$imm)>;
6476 // Vector sign and zero extensions are implemented with SSHLL and USSHLL.
6477 // Anyexts are implemented as zexts.
6478 def : Pat<(v8i16 (sext   (v8i8 V64:$Rn))),  (SSHLLv8i8_shift  V64:$Rn, (i32 0))>;
6479 def : Pat<(v8i16 (zext   (v8i8 V64:$Rn))),  (USHLLv8i8_shift  V64:$Rn, (i32 0))>;
6480 def : Pat<(v8i16 (anyext (v8i8 V64:$Rn))),  (USHLLv8i8_shift  V64:$Rn, (i32 0))>;
6481 def : Pat<(v4i32 (sext   (v4i16 V64:$Rn))), (SSHLLv4i16_shift V64:$Rn, (i32 0))>;
6482 def : Pat<(v4i32 (zext   (v4i16 V64:$Rn))), (USHLLv4i16_shift V64:$Rn, (i32 0))>;
6483 def : Pat<(v4i32 (anyext (v4i16 V64:$Rn))), (USHLLv4i16_shift V64:$Rn, (i32 0))>;
6484 def : Pat<(v2i64 (sext   (v2i32 V64:$Rn))), (SSHLLv2i32_shift V64:$Rn, (i32 0))>;
6485 def : Pat<(v2i64 (zext   (v2i32 V64:$Rn))), (USHLLv2i32_shift V64:$Rn, (i32 0))>;
6486 def : Pat<(v2i64 (anyext (v2i32 V64:$Rn))), (USHLLv2i32_shift V64:$Rn, (i32 0))>;
6487 // Also match an extend from the upper half of a 128 bit source register.
6488 def : Pat<(v8i16 (anyext (v8i8 (extract_subvector V128:$Rn, (i64 8)) ))),
6489           (USHLLv16i8_shift V128:$Rn, (i32 0))>;
6490 def : Pat<(v8i16 (zext   (v8i8 (extract_subvector V128:$Rn, (i64 8)) ))),
6491           (USHLLv16i8_shift V128:$Rn, (i32 0))>;
6492 def : Pat<(v8i16 (sext   (v8i8 (extract_subvector V128:$Rn, (i64 8)) ))),
6493           (SSHLLv16i8_shift V128:$Rn, (i32 0))>;
6494 def : Pat<(v4i32 (anyext (v4i16 (extract_subvector V128:$Rn, (i64 4)) ))),
6495           (USHLLv8i16_shift V128:$Rn, (i32 0))>;
6496 def : Pat<(v4i32 (zext   (v4i16 (extract_subvector V128:$Rn, (i64 4)) ))),
6497           (USHLLv8i16_shift V128:$Rn, (i32 0))>;
6498 def : Pat<(v4i32 (sext   (v4i16 (extract_subvector V128:$Rn, (i64 4)) ))),
6499           (SSHLLv8i16_shift V128:$Rn, (i32 0))>;
6500 def : Pat<(v2i64 (anyext (v2i32 (extract_subvector V128:$Rn, (i64 2)) ))),
6501           (USHLLv4i32_shift V128:$Rn, (i32 0))>;
6502 def : Pat<(v2i64 (zext   (v2i32 (extract_subvector V128:$Rn, (i64 2)) ))),
6503           (USHLLv4i32_shift V128:$Rn, (i32 0))>;
6504 def : Pat<(v2i64 (sext   (v2i32 (extract_subvector V128:$Rn, (i64 2)) ))),
6505           (SSHLLv4i32_shift V128:$Rn, (i32 0))>;
6507 // Vector shift sxtl aliases
6508 def : InstAlias<"sxtl.8h $dst, $src1",
6509                 (SSHLLv8i8_shift V128:$dst, V64:$src1, 0)>;
6510 def : InstAlias<"sxtl $dst.8h, $src1.8b",
6511                 (SSHLLv8i8_shift V128:$dst, V64:$src1, 0)>;
6512 def : InstAlias<"sxtl.4s $dst, $src1",
6513                 (SSHLLv4i16_shift V128:$dst, V64:$src1, 0)>;
6514 def : InstAlias<"sxtl $dst.4s, $src1.4h",
6515                 (SSHLLv4i16_shift V128:$dst, V64:$src1, 0)>;
6516 def : InstAlias<"sxtl.2d $dst, $src1",
6517                 (SSHLLv2i32_shift V128:$dst, V64:$src1, 0)>;
6518 def : InstAlias<"sxtl $dst.2d, $src1.2s",
6519                 (SSHLLv2i32_shift V128:$dst, V64:$src1, 0)>;
6521 // Vector shift sxtl2 aliases
6522 def : InstAlias<"sxtl2.8h $dst, $src1",
6523                 (SSHLLv16i8_shift V128:$dst, V128:$src1, 0)>;
6524 def : InstAlias<"sxtl2 $dst.8h, $src1.16b",
6525                 (SSHLLv16i8_shift V128:$dst, V128:$src1, 0)>;
6526 def : InstAlias<"sxtl2.4s $dst, $src1",
6527                 (SSHLLv8i16_shift V128:$dst, V128:$src1, 0)>;
6528 def : InstAlias<"sxtl2 $dst.4s, $src1.8h",
6529                 (SSHLLv8i16_shift V128:$dst, V128:$src1, 0)>;
6530 def : InstAlias<"sxtl2.2d $dst, $src1",
6531                 (SSHLLv4i32_shift V128:$dst, V128:$src1, 0)>;
6532 def : InstAlias<"sxtl2 $dst.2d, $src1.4s",
6533                 (SSHLLv4i32_shift V128:$dst, V128:$src1, 0)>;
6535 // Vector shift uxtl aliases
6536 def : InstAlias<"uxtl.8h $dst, $src1",
6537                 (USHLLv8i8_shift V128:$dst, V64:$src1, 0)>;
6538 def : InstAlias<"uxtl $dst.8h, $src1.8b",
6539                 (USHLLv8i8_shift V128:$dst, V64:$src1, 0)>;
6540 def : InstAlias<"uxtl.4s $dst, $src1",
6541                 (USHLLv4i16_shift V128:$dst, V64:$src1, 0)>;
6542 def : InstAlias<"uxtl $dst.4s, $src1.4h",
6543                 (USHLLv4i16_shift V128:$dst, V64:$src1, 0)>;
6544 def : InstAlias<"uxtl.2d $dst, $src1",
6545                 (USHLLv2i32_shift V128:$dst, V64:$src1, 0)>;
6546 def : InstAlias<"uxtl $dst.2d, $src1.2s",
6547                 (USHLLv2i32_shift V128:$dst, V64:$src1, 0)>;
6549 // Vector shift uxtl2 aliases
6550 def : InstAlias<"uxtl2.8h $dst, $src1",
6551                 (USHLLv16i8_shift V128:$dst, V128:$src1, 0)>;
6552 def : InstAlias<"uxtl2 $dst.8h, $src1.16b",
6553                 (USHLLv16i8_shift V128:$dst, V128:$src1, 0)>;
6554 def : InstAlias<"uxtl2.4s $dst, $src1",
6555                 (USHLLv8i16_shift V128:$dst, V128:$src1, 0)>;
6556 def : InstAlias<"uxtl2 $dst.4s, $src1.8h",
6557                 (USHLLv8i16_shift V128:$dst, V128:$src1, 0)>;
6558 def : InstAlias<"uxtl2.2d $dst, $src1",
6559                 (USHLLv4i32_shift V128:$dst, V128:$src1, 0)>;
6560 def : InstAlias<"uxtl2 $dst.2d, $src1.4s",
6561                 (USHLLv4i32_shift V128:$dst, V128:$src1, 0)>;
6563 // If an integer is about to be converted to a floating point value,
6564 // just load it on the floating point unit.
6565 // These patterns are more complex because floating point loads do not
6566 // support sign extension.
6567 // The sign extension has to be explicitly added and is only supported for
6568 // one step: byte-to-half, half-to-word, word-to-doubleword.
6569 // SCVTF GPR -> FPR is 9 cycles.
6570 // SCVTF FPR -> FPR is 4 cyclces.
6571 // (sign extension with lengthen) SXTL FPR -> FPR is 2 cycles.
6572 // Therefore, we can do 2 sign extensions and one SCVTF FPR -> FPR
6573 // and still being faster.
6574 // However, this is not good for code size.
6575 // 8-bits -> float. 2 sizes step-up.
6576 class SExtLoadi8CVTf32Pat<dag addrmode, dag INST>
6577   : Pat<(f32 (sint_to_fp (i32 (sextloadi8 addrmode)))),
6578         (SCVTFv1i32 (f32 (EXTRACT_SUBREG
6579                             (SSHLLv4i16_shift
6580                               (f64
6581                                 (EXTRACT_SUBREG
6582                                   (SSHLLv8i8_shift
6583                                     (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
6584                                         INST,
6585                                         bsub),
6586                                     0),
6587                                   dsub)),
6588                                0),
6589                              ssub)))>,
6590     Requires<[NotForCodeSize, UseAlternateSExtLoadCVTF32]>;
6592 def : SExtLoadi8CVTf32Pat<(ro8.Wpat GPR64sp:$Rn, GPR32:$Rm, ro8.Wext:$ext),
6593                           (LDRBroW  GPR64sp:$Rn, GPR32:$Rm, ro8.Wext:$ext)>;
6594 def : SExtLoadi8CVTf32Pat<(ro8.Xpat GPR64sp:$Rn, GPR64:$Rm, ro8.Xext:$ext),
6595                           (LDRBroX  GPR64sp:$Rn, GPR64:$Rm, ro8.Xext:$ext)>;
6596 def : SExtLoadi8CVTf32Pat<(am_indexed8 GPR64sp:$Rn, uimm12s1:$offset),
6597                           (LDRBui GPR64sp:$Rn, uimm12s1:$offset)>;
6598 def : SExtLoadi8CVTf32Pat<(am_unscaled8 GPR64sp:$Rn, simm9:$offset),
6599                           (LDURBi GPR64sp:$Rn, simm9:$offset)>;
6601 // 16-bits -> float. 1 size step-up.
6602 class SExtLoadi16CVTf32Pat<dag addrmode, dag INST>
6603   : Pat<(f32 (sint_to_fp (i32 (sextloadi16 addrmode)))),
6604         (SCVTFv1i32 (f32 (EXTRACT_SUBREG
6605                             (SSHLLv4i16_shift
6606                                 (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
6607                                   INST,
6608                                   hsub),
6609                                 0),
6610                             ssub)))>, Requires<[NotForCodeSize]>;
6612 def : SExtLoadi16CVTf32Pat<(ro16.Wpat GPR64sp:$Rn, GPR32:$Rm, ro16.Wext:$ext),
6613                            (LDRHroW   GPR64sp:$Rn, GPR32:$Rm, ro16.Wext:$ext)>;
6614 def : SExtLoadi16CVTf32Pat<(ro16.Xpat GPR64sp:$Rn, GPR64:$Rm, ro16.Xext:$ext),
6615                            (LDRHroX   GPR64sp:$Rn, GPR64:$Rm, ro16.Xext:$ext)>;
6616 def : SExtLoadi16CVTf32Pat<(am_indexed16 GPR64sp:$Rn, uimm12s2:$offset),
6617                            (LDRHui GPR64sp:$Rn, uimm12s2:$offset)>;
6618 def : SExtLoadi16CVTf32Pat<(am_unscaled16 GPR64sp:$Rn, simm9:$offset),
6619                            (LDURHi GPR64sp:$Rn, simm9:$offset)>;
6621 // 32-bits to 32-bits are handled in target specific dag combine:
6622 // performIntToFpCombine.
6623 // 64-bits integer to 32-bits floating point, not possible with
6624 // SCVTF on floating point registers (both source and destination
6625 // must have the same size).
6627 // Here are the patterns for 8, 16, 32, and 64-bits to double.
6628 // 8-bits -> double. 3 size step-up: give up.
6629 // 16-bits -> double. 2 size step.
6630 class SExtLoadi16CVTf64Pat<dag addrmode, dag INST>
6631   : Pat <(f64 (sint_to_fp (i32 (sextloadi16 addrmode)))),
6632            (SCVTFv1i64 (f64 (EXTRACT_SUBREG
6633                               (SSHLLv2i32_shift
6634                                  (f64
6635                                   (EXTRACT_SUBREG
6636                                     (SSHLLv4i16_shift
6637                                       (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
6638                                         INST,
6639                                         hsub),
6640                                      0),
6641                                    dsub)),
6642                                0),
6643                              dsub)))>,
6644     Requires<[NotForCodeSize, UseAlternateSExtLoadCVTF32]>;
6646 def : SExtLoadi16CVTf64Pat<(ro16.Wpat GPR64sp:$Rn, GPR32:$Rm, ro16.Wext:$ext),
6647                            (LDRHroW GPR64sp:$Rn, GPR32:$Rm, ro16.Wext:$ext)>;
6648 def : SExtLoadi16CVTf64Pat<(ro16.Xpat GPR64sp:$Rn, GPR64:$Rm, ro16.Xext:$ext),
6649                            (LDRHroX GPR64sp:$Rn, GPR64:$Rm, ro16.Xext:$ext)>;
6650 def : SExtLoadi16CVTf64Pat<(am_indexed16 GPR64sp:$Rn, uimm12s2:$offset),
6651                            (LDRHui GPR64sp:$Rn, uimm12s2:$offset)>;
6652 def : SExtLoadi16CVTf64Pat<(am_unscaled16 GPR64sp:$Rn, simm9:$offset),
6653                            (LDURHi GPR64sp:$Rn, simm9:$offset)>;
6654 // 32-bits -> double. 1 size step-up.
6655 class SExtLoadi32CVTf64Pat<dag addrmode, dag INST>
6656   : Pat <(f64 (sint_to_fp (i32 (load addrmode)))),
6657            (SCVTFv1i64 (f64 (EXTRACT_SUBREG
6658                               (SSHLLv2i32_shift
6659                                 (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
6660                                   INST,
6661                                   ssub),
6662                                0),
6663                              dsub)))>, Requires<[NotForCodeSize]>;
6665 def : SExtLoadi32CVTf64Pat<(ro32.Wpat GPR64sp:$Rn, GPR32:$Rm, ro32.Wext:$ext),
6666                            (LDRSroW GPR64sp:$Rn, GPR32:$Rm, ro32.Wext:$ext)>;
6667 def : SExtLoadi32CVTf64Pat<(ro32.Xpat GPR64sp:$Rn, GPR64:$Rm, ro32.Xext:$ext),
6668                            (LDRSroX GPR64sp:$Rn, GPR64:$Rm, ro32.Xext:$ext)>;
6669 def : SExtLoadi32CVTf64Pat<(am_indexed32 GPR64sp:$Rn, uimm12s4:$offset),
6670                            (LDRSui GPR64sp:$Rn, uimm12s4:$offset)>;
6671 def : SExtLoadi32CVTf64Pat<(am_unscaled32 GPR64sp:$Rn, simm9:$offset),
6672                            (LDURSi GPR64sp:$Rn, simm9:$offset)>;
6674 // 64-bits -> double are handled in target specific dag combine:
6675 // performIntToFpCombine.
6678 //----------------------------------------------------------------------------
6679 // AdvSIMD Load-Store Structure
6680 //----------------------------------------------------------------------------
6681 defm LD1 : SIMDLd1Multiple<"ld1">;
6682 defm LD2 : SIMDLd2Multiple<"ld2">;
6683 defm LD3 : SIMDLd3Multiple<"ld3">;
6684 defm LD4 : SIMDLd4Multiple<"ld4">;
6686 defm ST1 : SIMDSt1Multiple<"st1">;
6687 defm ST2 : SIMDSt2Multiple<"st2">;
6688 defm ST3 : SIMDSt3Multiple<"st3">;
6689 defm ST4 : SIMDSt4Multiple<"st4">;
6691 class Ld1Pat<ValueType ty, Instruction INST>
6692   : Pat<(ty (load GPR64sp:$Rn)), (INST GPR64sp:$Rn)>;
6694 def : Ld1Pat<v16i8, LD1Onev16b>;
6695 def : Ld1Pat<v8i16, LD1Onev8h>;
6696 def : Ld1Pat<v4i32, LD1Onev4s>;
6697 def : Ld1Pat<v2i64, LD1Onev2d>;
6698 def : Ld1Pat<v8i8,  LD1Onev8b>;
6699 def : Ld1Pat<v4i16, LD1Onev4h>;
6700 def : Ld1Pat<v2i32, LD1Onev2s>;
6701 def : Ld1Pat<v1i64, LD1Onev1d>;
6703 class St1Pat<ValueType ty, Instruction INST>
6704   : Pat<(store ty:$Vt, GPR64sp:$Rn),
6705         (INST ty:$Vt, GPR64sp:$Rn)>;
6707 def : St1Pat<v16i8, ST1Onev16b>;
6708 def : St1Pat<v8i16, ST1Onev8h>;
6709 def : St1Pat<v4i32, ST1Onev4s>;
6710 def : St1Pat<v2i64, ST1Onev2d>;
6711 def : St1Pat<v8i8,  ST1Onev8b>;
6712 def : St1Pat<v4i16, ST1Onev4h>;
6713 def : St1Pat<v2i32, ST1Onev2s>;
6714 def : St1Pat<v1i64, ST1Onev1d>;
6716 //---
6717 // Single-element
6718 //---
6720 defm LD1R          : SIMDLdR<0, 0b110, 0, "ld1r", "One", 1, 2, 4, 8>;
6721 defm LD2R          : SIMDLdR<1, 0b110, 0, "ld2r", "Two", 2, 4, 8, 16>;
6722 defm LD3R          : SIMDLdR<0, 0b111, 0, "ld3r", "Three", 3, 6, 12, 24>;
6723 defm LD4R          : SIMDLdR<1, 0b111, 0, "ld4r", "Four", 4, 8, 16, 32>;
6724 let mayLoad = 1, hasSideEffects = 0 in {
6725 defm LD1 : SIMDLdSingleBTied<0, 0b000,       "ld1", VecListOneb,   GPR64pi1>;
6726 defm LD1 : SIMDLdSingleHTied<0, 0b010, 0,    "ld1", VecListOneh,   GPR64pi2>;
6727 defm LD1 : SIMDLdSingleSTied<0, 0b100, 0b00, "ld1", VecListOnes,   GPR64pi4>;
6728 defm LD1 : SIMDLdSingleDTied<0, 0b100, 0b01, "ld1", VecListOned,   GPR64pi8>;
6729 defm LD2 : SIMDLdSingleBTied<1, 0b000,       "ld2", VecListTwob,   GPR64pi2>;
6730 defm LD2 : SIMDLdSingleHTied<1, 0b010, 0,    "ld2", VecListTwoh,   GPR64pi4>;
6731 defm LD2 : SIMDLdSingleSTied<1, 0b100, 0b00, "ld2", VecListTwos,   GPR64pi8>;
6732 defm LD2 : SIMDLdSingleDTied<1, 0b100, 0b01, "ld2", VecListTwod,   GPR64pi16>;
6733 defm LD3 : SIMDLdSingleBTied<0, 0b001,       "ld3", VecListThreeb, GPR64pi3>;
6734 defm LD3 : SIMDLdSingleHTied<0, 0b011, 0,    "ld3", VecListThreeh, GPR64pi6>;
6735 defm LD3 : SIMDLdSingleSTied<0, 0b101, 0b00, "ld3", VecListThrees, GPR64pi12>;
6736 defm LD3 : SIMDLdSingleDTied<0, 0b101, 0b01, "ld3", VecListThreed, GPR64pi24>;
6737 defm LD4 : SIMDLdSingleBTied<1, 0b001,       "ld4", VecListFourb,  GPR64pi4>;
6738 defm LD4 : SIMDLdSingleHTied<1, 0b011, 0,    "ld4", VecListFourh,  GPR64pi8>;
6739 defm LD4 : SIMDLdSingleSTied<1, 0b101, 0b00, "ld4", VecListFours,  GPR64pi16>;
6740 defm LD4 : SIMDLdSingleDTied<1, 0b101, 0b01, "ld4", VecListFourd,  GPR64pi32>;
6743 def : Pat<(v8i8 (AArch64dup (i32 (extloadi8 GPR64sp:$Rn)))),
6744           (LD1Rv8b GPR64sp:$Rn)>;
6745 def : Pat<(v16i8 (AArch64dup (i32 (extloadi8 GPR64sp:$Rn)))),
6746           (LD1Rv16b GPR64sp:$Rn)>;
6747 def : Pat<(v4i16 (AArch64dup (i32 (extloadi16 GPR64sp:$Rn)))),
6748           (LD1Rv4h GPR64sp:$Rn)>;
6749 def : Pat<(v8i16 (AArch64dup (i32 (extloadi16 GPR64sp:$Rn)))),
6750           (LD1Rv8h GPR64sp:$Rn)>;
6751 def : Pat<(v2i32 (AArch64dup (i32 (load GPR64sp:$Rn)))),
6752           (LD1Rv2s GPR64sp:$Rn)>;
6753 def : Pat<(v4i32 (AArch64dup (i32 (load GPR64sp:$Rn)))),
6754           (LD1Rv4s GPR64sp:$Rn)>;
6755 def : Pat<(v2i64 (AArch64dup (i64 (load GPR64sp:$Rn)))),
6756           (LD1Rv2d GPR64sp:$Rn)>;
6757 def : Pat<(v1i64 (AArch64dup (i64 (load GPR64sp:$Rn)))),
6758           (LD1Rv1d GPR64sp:$Rn)>;
6759 // Grab the floating point version too
6760 def : Pat<(v2f32 (AArch64dup (f32 (load GPR64sp:$Rn)))),
6761           (LD1Rv2s GPR64sp:$Rn)>;
6762 def : Pat<(v4f32 (AArch64dup (f32 (load GPR64sp:$Rn)))),
6763           (LD1Rv4s GPR64sp:$Rn)>;
6764 def : Pat<(v2f64 (AArch64dup (f64 (load GPR64sp:$Rn)))),
6765           (LD1Rv2d GPR64sp:$Rn)>;
6766 def : Pat<(v1f64 (AArch64dup (f64 (load GPR64sp:$Rn)))),
6767           (LD1Rv1d GPR64sp:$Rn)>;
6768 def : Pat<(v4f16 (AArch64dup (f16 (load GPR64sp:$Rn)))),
6769           (LD1Rv4h GPR64sp:$Rn)>;
6770 def : Pat<(v8f16 (AArch64dup (f16 (load GPR64sp:$Rn)))),
6771           (LD1Rv8h GPR64sp:$Rn)>;
6772 def : Pat<(v4bf16 (AArch64dup (bf16 (load GPR64sp:$Rn)))),
6773           (LD1Rv4h GPR64sp:$Rn)>;
6774 def : Pat<(v8bf16 (AArch64dup (bf16 (load GPR64sp:$Rn)))),
6775           (LD1Rv8h GPR64sp:$Rn)>;
6777 class Ld1Lane128Pat<SDPatternOperator scalar_load, Operand VecIndex,
6778                     ValueType VTy, ValueType STy, Instruction LD1>
6779   : Pat<(vector_insert (VTy VecListOne128:$Rd),
6780            (STy (scalar_load GPR64sp:$Rn)), VecIndex:$idx),
6781         (LD1 VecListOne128:$Rd, VecIndex:$idx, GPR64sp:$Rn)>;
6783 def : Ld1Lane128Pat<extloadi8,  VectorIndexB, v16i8, i32, LD1i8>;
6784 def : Ld1Lane128Pat<extloadi16, VectorIndexH, v8i16, i32, LD1i16>;
6785 def : Ld1Lane128Pat<load,       VectorIndexS, v4i32, i32, LD1i32>;
6786 def : Ld1Lane128Pat<load,       VectorIndexS, v4f32, f32, LD1i32>;
6787 def : Ld1Lane128Pat<load,       VectorIndexD, v2i64, i64, LD1i64>;
6788 def : Ld1Lane128Pat<load,       VectorIndexD, v2f64, f64, LD1i64>;
6789 def : Ld1Lane128Pat<load,       VectorIndexH, v8f16, f16, LD1i16>;
6790 def : Ld1Lane128Pat<load,       VectorIndexH, v8bf16, bf16, LD1i16>;
6792 // Generate LD1 for extload if memory type does not match the
6793 // destination type, for example:
6795 //   (v4i32 (insert_vector_elt (load anyext from i8) idx))
6797 // In this case, the index must be adjusted to match LD1 type.
6799 class Ld1Lane128IdxOpPat<SDPatternOperator scalar_load, Operand
6800                     VecIndex, ValueType VTy, ValueType STy,
6801                     Instruction LD1, SDNodeXForm IdxOp>
6802   : Pat<(vector_insert (VTy VecListOne128:$Rd),
6803                        (STy (scalar_load GPR64sp:$Rn)), VecIndex:$idx),
6804         (LD1 VecListOne128:$Rd, (IdxOp VecIndex:$idx), GPR64sp:$Rn)>;
6806 def VectorIndexStoH : SDNodeXForm<imm, [{
6807   return CurDAG->getTargetConstant(N->getZExtValue() * 2, SDLoc(N), MVT::i64);
6808 }]>;
6809 def VectorIndexStoB : SDNodeXForm<imm, [{
6810   return CurDAG->getTargetConstant(N->getZExtValue() * 4, SDLoc(N), MVT::i64);
6811 }]>;
6812 def VectorIndexHtoB : SDNodeXForm<imm, [{
6813   return CurDAG->getTargetConstant(N->getZExtValue() * 2, SDLoc(N), MVT::i64);
6814 }]>;
6816 def : Ld1Lane128IdxOpPat<extloadi16, VectorIndexS, v4i32, i32, LD1i16, VectorIndexStoH>;
6817 def : Ld1Lane128IdxOpPat<extloadi8, VectorIndexS, v4i32, i32, LD1i8, VectorIndexStoB>;
6818 def : Ld1Lane128IdxOpPat<extloadi8, VectorIndexH, v8i16, i32, LD1i8, VectorIndexHtoB>;
6820 // Same as above, but the first element is populated using
6821 // scalar_to_vector + insert_subvector instead of insert_vector_elt.
6822 class Ld1Lane128FirstElm<ValueType ResultTy, ValueType VecTy,
6823                         SDPatternOperator ExtLoad, Instruction LD1>
6824   : Pat<(ResultTy (scalar_to_vector (i32 (ExtLoad GPR64sp:$Rn)))),
6825           (ResultTy (EXTRACT_SUBREG
6826             (LD1 (VecTy (IMPLICIT_DEF)), 0, GPR64sp:$Rn), dsub))>;
6828 def : Ld1Lane128FirstElm<v2i32, v8i16, extloadi16, LD1i16>;
6829 def : Ld1Lane128FirstElm<v2i32, v16i8, extloadi8, LD1i8>;
6830 def : Ld1Lane128FirstElm<v4i16, v16i8, extloadi8, LD1i8>;
6832 class Ld1Lane64Pat<SDPatternOperator scalar_load, Operand VecIndex,
6833                    ValueType VTy, ValueType STy, Instruction LD1>
6834   : Pat<(vector_insert (VTy VecListOne64:$Rd),
6835            (STy (scalar_load GPR64sp:$Rn)), VecIndex:$idx),
6836         (EXTRACT_SUBREG
6837             (LD1 (SUBREG_TO_REG (i32 0), VecListOne64:$Rd, dsub),
6838                           VecIndex:$idx, GPR64sp:$Rn),
6839             dsub)>;
6841 def : Ld1Lane64Pat<extloadi8,  VectorIndexB, v8i8,  i32, LD1i8>;
6842 def : Ld1Lane64Pat<extloadi16, VectorIndexH, v4i16, i32, LD1i16>;
6843 def : Ld1Lane64Pat<load,       VectorIndexS, v2i32, i32, LD1i32>;
6844 def : Ld1Lane64Pat<load,       VectorIndexS, v2f32, f32, LD1i32>;
6845 def : Ld1Lane64Pat<load,       VectorIndexH, v4f16, f16, LD1i16>;
6846 def : Ld1Lane64Pat<load,       VectorIndexH, v4bf16, bf16, LD1i16>;
6849 defm LD1 : SIMDLdSt1SingleAliases<"ld1">;
6850 defm LD2 : SIMDLdSt2SingleAliases<"ld2">;
6851 defm LD3 : SIMDLdSt3SingleAliases<"ld3">;
6852 defm LD4 : SIMDLdSt4SingleAliases<"ld4">;
6854 // Stores
6855 defm ST1 : SIMDStSingleB<0, 0b000,       "st1", VecListOneb, GPR64pi1>;
6856 defm ST1 : SIMDStSingleH<0, 0b010, 0,    "st1", VecListOneh, GPR64pi2>;
6857 defm ST1 : SIMDStSingleS<0, 0b100, 0b00, "st1", VecListOnes, GPR64pi4>;
6858 defm ST1 : SIMDStSingleD<0, 0b100, 0b01, "st1", VecListOned, GPR64pi8>;
6860 let AddedComplexity = 19 in
6861 class St1Lane128Pat<SDPatternOperator scalar_store, Operand VecIndex,
6862                     ValueType VTy, ValueType STy, Instruction ST1>
6863   : Pat<(scalar_store
6864              (STy (vector_extract (VTy VecListOne128:$Vt), VecIndex:$idx)),
6865              GPR64sp:$Rn),
6866         (ST1 VecListOne128:$Vt, VecIndex:$idx, GPR64sp:$Rn)>;
6868 def : St1Lane128Pat<truncstorei8,  VectorIndexB, v16i8, i32, ST1i8>;
6869 def : St1Lane128Pat<truncstorei16, VectorIndexH, v8i16, i32, ST1i16>;
6870 def : St1Lane128Pat<store,         VectorIndexS, v4i32, i32, ST1i32>;
6871 def : St1Lane128Pat<store,         VectorIndexS, v4f32, f32, ST1i32>;
6872 def : St1Lane128Pat<store,         VectorIndexD, v2i64, i64, ST1i64>;
6873 def : St1Lane128Pat<store,         VectorIndexD, v2f64, f64, ST1i64>;
6874 def : St1Lane128Pat<store,         VectorIndexH, v8f16, f16, ST1i16>;
6875 def : St1Lane128Pat<store,         VectorIndexH, v8bf16, bf16, ST1i16>;
6877 let AddedComplexity = 19 in
6878 class St1Lane64Pat<SDPatternOperator scalar_store, Operand VecIndex,
6879                    ValueType VTy, ValueType STy, Instruction ST1>
6880   : Pat<(scalar_store
6881              (STy (vector_extract (VTy VecListOne64:$Vt), VecIndex:$idx)),
6882              GPR64sp:$Rn),
6883         (ST1 (SUBREG_TO_REG (i32 0), VecListOne64:$Vt, dsub),
6884              VecIndex:$idx, GPR64sp:$Rn)>;
6886 def : St1Lane64Pat<truncstorei8,  VectorIndexB, v8i8, i32, ST1i8>;
6887 def : St1Lane64Pat<truncstorei16, VectorIndexH, v4i16, i32, ST1i16>;
6888 def : St1Lane64Pat<store,         VectorIndexS, v2i32, i32, ST1i32>;
6889 def : St1Lane64Pat<store,         VectorIndexS, v2f32, f32, ST1i32>;
6890 def : St1Lane64Pat<store,         VectorIndexH, v4f16, f16, ST1i16>;
6891 def : St1Lane64Pat<store,         VectorIndexH, v4bf16, bf16, ST1i16>;
6893 multiclass St1LanePost64Pat<SDPatternOperator scalar_store, Operand VecIndex,
6894                              ValueType VTy, ValueType STy, Instruction ST1,
6895                              int offset> {
6896   def : Pat<(scalar_store
6897               (STy (vector_extract (VTy VecListOne64:$Vt), VecIndex:$idx)),
6898               GPR64sp:$Rn, offset),
6899         (ST1 (SUBREG_TO_REG (i32 0), VecListOne64:$Vt, dsub),
6900              VecIndex:$idx, GPR64sp:$Rn, XZR)>;
6902   def : Pat<(scalar_store
6903               (STy (vector_extract (VTy VecListOne64:$Vt), VecIndex:$idx)),
6904               GPR64sp:$Rn, GPR64:$Rm),
6905         (ST1 (SUBREG_TO_REG (i32 0), VecListOne64:$Vt, dsub),
6906              VecIndex:$idx, GPR64sp:$Rn, $Rm)>;
6909 defm : St1LanePost64Pat<post_truncsti8, VectorIndexB, v8i8, i32, ST1i8_POST, 1>;
6910 defm : St1LanePost64Pat<post_truncsti16, VectorIndexH, v4i16, i32, ST1i16_POST,
6911                         2>;
6912 defm : St1LanePost64Pat<post_store, VectorIndexS, v2i32, i32, ST1i32_POST, 4>;
6913 defm : St1LanePost64Pat<post_store, VectorIndexS, v2f32, f32, ST1i32_POST, 4>;
6914 defm : St1LanePost64Pat<post_store, VectorIndexD, v1i64, i64, ST1i64_POST, 8>;
6915 defm : St1LanePost64Pat<post_store, VectorIndexD, v1f64, f64, ST1i64_POST, 8>;
6916 defm : St1LanePost64Pat<post_store, VectorIndexH, v4f16, f16, ST1i16_POST, 2>;
6917 defm : St1LanePost64Pat<post_store, VectorIndexH, v4bf16, bf16, ST1i16_POST, 2>;
6919 multiclass St1LanePost128Pat<SDPatternOperator scalar_store, Operand VecIndex,
6920                              ValueType VTy, ValueType STy, Instruction ST1,
6921                              int offset> {
6922   def : Pat<(scalar_store
6923               (STy (vector_extract (VTy VecListOne128:$Vt), VecIndex:$idx)),
6924               GPR64sp:$Rn, offset),
6925         (ST1 VecListOne128:$Vt, VecIndex:$idx, GPR64sp:$Rn, XZR)>;
6927   def : Pat<(scalar_store
6928               (STy (vector_extract (VTy VecListOne128:$Vt), VecIndex:$idx)),
6929               GPR64sp:$Rn, GPR64:$Rm),
6930         (ST1 VecListOne128:$Vt, VecIndex:$idx, GPR64sp:$Rn, $Rm)>;
6933 defm : St1LanePost128Pat<post_truncsti8, VectorIndexB, v16i8, i32, ST1i8_POST,
6934                          1>;
6935 defm : St1LanePost128Pat<post_truncsti16, VectorIndexH, v8i16, i32, ST1i16_POST,
6936                          2>;
6937 defm : St1LanePost128Pat<post_store, VectorIndexS, v4i32, i32, ST1i32_POST, 4>;
6938 defm : St1LanePost128Pat<post_store, VectorIndexS, v4f32, f32, ST1i32_POST, 4>;
6939 defm : St1LanePost128Pat<post_store, VectorIndexD, v2i64, i64, ST1i64_POST, 8>;
6940 defm : St1LanePost128Pat<post_store, VectorIndexD, v2f64, f64, ST1i64_POST, 8>;
6941 defm : St1LanePost128Pat<post_store, VectorIndexH, v8f16, f16, ST1i16_POST, 2>;
6942 defm : St1LanePost128Pat<post_store, VectorIndexH, v8bf16, bf16, ST1i16_POST, 2>;
6944 let mayStore = 1, hasSideEffects = 0 in {
6945 defm ST2 : SIMDStSingleB<1, 0b000,       "st2", VecListTwob,   GPR64pi2>;
6946 defm ST2 : SIMDStSingleH<1, 0b010, 0,    "st2", VecListTwoh,   GPR64pi4>;
6947 defm ST2 : SIMDStSingleS<1, 0b100, 0b00, "st2", VecListTwos,   GPR64pi8>;
6948 defm ST2 : SIMDStSingleD<1, 0b100, 0b01, "st2", VecListTwod,   GPR64pi16>;
6949 defm ST3 : SIMDStSingleB<0, 0b001,       "st3", VecListThreeb, GPR64pi3>;
6950 defm ST3 : SIMDStSingleH<0, 0b011, 0,    "st3", VecListThreeh, GPR64pi6>;
6951 defm ST3 : SIMDStSingleS<0, 0b101, 0b00, "st3", VecListThrees, GPR64pi12>;
6952 defm ST3 : SIMDStSingleD<0, 0b101, 0b01, "st3", VecListThreed, GPR64pi24>;
6953 defm ST4 : SIMDStSingleB<1, 0b001,       "st4", VecListFourb,  GPR64pi4>;
6954 defm ST4 : SIMDStSingleH<1, 0b011, 0,    "st4", VecListFourh,  GPR64pi8>;
6955 defm ST4 : SIMDStSingleS<1, 0b101, 0b00, "st4", VecListFours,  GPR64pi16>;
6956 defm ST4 : SIMDStSingleD<1, 0b101, 0b01, "st4", VecListFourd,  GPR64pi32>;
6959 defm ST1 : SIMDLdSt1SingleAliases<"st1">;
6960 defm ST2 : SIMDLdSt2SingleAliases<"st2">;
6961 defm ST3 : SIMDLdSt3SingleAliases<"st3">;
6962 defm ST4 : SIMDLdSt4SingleAliases<"st4">;
6964 //----------------------------------------------------------------------------
6965 // Crypto extensions
6966 //----------------------------------------------------------------------------
6968 let Predicates = [HasAES] in {
6969 def AESErr   : AESTiedInst<0b0100, "aese",   int_aarch64_crypto_aese>;
6970 def AESDrr   : AESTiedInst<0b0101, "aesd",   int_aarch64_crypto_aesd>;
6971 def AESMCrr  : AESInst<    0b0110, "aesmc",  int_aarch64_crypto_aesmc>;
6972 def AESIMCrr : AESInst<    0b0111, "aesimc", int_aarch64_crypto_aesimc>;
6975 // Pseudo instructions for AESMCrr/AESIMCrr with a register constraint required
6976 // for AES fusion on some CPUs.
6977 let hasSideEffects = 0, mayStore = 0, mayLoad = 0 in {
6978 def AESMCrrTied: Pseudo<(outs V128:$Rd), (ins V128:$Rn), [], "$Rn = $Rd">,
6979                         Sched<[WriteV]>;
6980 def AESIMCrrTied: Pseudo<(outs V128:$Rd), (ins V128:$Rn), [], "$Rn = $Rd">,
6981                          Sched<[WriteV]>;
6984 // Only use constrained versions of AES(I)MC instructions if they are paired with
6985 // AESE/AESD.
6986 def : Pat<(v16i8 (int_aarch64_crypto_aesmc
6987             (v16i8 (int_aarch64_crypto_aese (v16i8 V128:$src1),
6988                                             (v16i8 V128:$src2))))),
6989           (v16i8 (AESMCrrTied (v16i8 (AESErr (v16i8 V128:$src1),
6990                                              (v16i8 V128:$src2)))))>,
6991           Requires<[HasFuseAES]>;
6993 def : Pat<(v16i8 (int_aarch64_crypto_aesimc
6994             (v16i8 (int_aarch64_crypto_aesd (v16i8 V128:$src1),
6995                                             (v16i8 V128:$src2))))),
6996           (v16i8 (AESIMCrrTied (v16i8 (AESDrr (v16i8 V128:$src1),
6997                                               (v16i8 V128:$src2)))))>,
6998           Requires<[HasFuseAES]>;
7000 let Predicates = [HasSHA2] in {
7001 def SHA1Crrr     : SHATiedInstQSV<0b000, "sha1c",   int_aarch64_crypto_sha1c>;
7002 def SHA1Prrr     : SHATiedInstQSV<0b001, "sha1p",   int_aarch64_crypto_sha1p>;
7003 def SHA1Mrrr     : SHATiedInstQSV<0b010, "sha1m",   int_aarch64_crypto_sha1m>;
7004 def SHA1SU0rrr   : SHATiedInstVVV<0b011, "sha1su0", int_aarch64_crypto_sha1su0>;
7005 def SHA256Hrrr   : SHATiedInstQQV<0b100, "sha256h", int_aarch64_crypto_sha256h>;
7006 def SHA256H2rrr  : SHATiedInstQQV<0b101, "sha256h2",int_aarch64_crypto_sha256h2>;
7007 def SHA256SU1rrr :SHATiedInstVVV<0b110, "sha256su1",int_aarch64_crypto_sha256su1>;
7009 def SHA1Hrr     : SHAInstSS<    0b0000, "sha1h",    int_aarch64_crypto_sha1h>;
7010 def SHA1SU1rr   : SHATiedInstVV<0b0001, "sha1su1",  int_aarch64_crypto_sha1su1>;
7011 def SHA256SU0rr : SHATiedInstVV<0b0010, "sha256su0",int_aarch64_crypto_sha256su0>;
7014 //----------------------------------------------------------------------------
7015 // Compiler-pseudos
7016 //----------------------------------------------------------------------------
7017 // FIXME: Like for X86, these should go in their own separate .td file.
7019 def def32 : PatLeaf<(i32 GPR32:$src), [{
7020   return isDef32(*N);
7021 }]>;
7023 // In the case of a 32-bit def that is known to implicitly zero-extend,
7024 // we can use a SUBREG_TO_REG.
7025 def : Pat<(i64 (zext def32:$src)), (SUBREG_TO_REG (i64 0), GPR32:$src, sub_32)>;
7027 // For an anyext, we don't care what the high bits are, so we can perform an
7028 // INSERT_SUBREF into an IMPLICIT_DEF.
7029 def : Pat<(i64 (anyext GPR32:$src)),
7030           (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32)>;
7032 // When we need to explicitly zero-extend, we use a 32-bit MOV instruction and
7033 // then assert the extension has happened.
7034 def : Pat<(i64 (zext GPR32:$src)),
7035           (SUBREG_TO_REG (i32 0), (ORRWrs WZR, GPR32:$src, 0), sub_32)>;
7037 // To sign extend, we use a signed bitfield move instruction (SBFM) on the
7038 // containing super-reg.
7039 def : Pat<(i64 (sext GPR32:$src)),
7040    (SBFMXri (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32), 0, 31)>;
7041 def : Pat<(i64 (sext_inreg GPR64:$src, i32)), (SBFMXri GPR64:$src, 0, 31)>;
7042 def : Pat<(i64 (sext_inreg GPR64:$src, i16)), (SBFMXri GPR64:$src, 0, 15)>;
7043 def : Pat<(i64 (sext_inreg GPR64:$src, i8)),  (SBFMXri GPR64:$src, 0, 7)>;
7044 def : Pat<(i64 (sext_inreg GPR64:$src, i1)),  (SBFMXri GPR64:$src, 0, 0)>;
7045 def : Pat<(i32 (sext_inreg GPR32:$src, i16)), (SBFMWri GPR32:$src, 0, 15)>;
7046 def : Pat<(i32 (sext_inreg GPR32:$src, i8)),  (SBFMWri GPR32:$src, 0, 7)>;
7047 def : Pat<(i32 (sext_inreg GPR32:$src, i1)),  (SBFMWri GPR32:$src, 0, 0)>;
7049 def : Pat<(shl (sext_inreg GPR32:$Rn, i8), (i64 imm0_31:$imm)),
7050           (SBFMWri GPR32:$Rn, (i64 (i32shift_a       imm0_31:$imm)),
7051                               (i64 (i32shift_sext_i8 imm0_31:$imm)))>;
7052 def : Pat<(shl (sext_inreg GPR64:$Rn, i8), (i64 imm0_63:$imm)),
7053           (SBFMXri GPR64:$Rn, (i64 (i64shift_a imm0_63:$imm)),
7054                               (i64 (i64shift_sext_i8 imm0_63:$imm)))>;
7056 def : Pat<(shl (sext_inreg GPR32:$Rn, i16), (i64 imm0_31:$imm)),
7057           (SBFMWri GPR32:$Rn, (i64 (i32shift_a        imm0_31:$imm)),
7058                               (i64 (i32shift_sext_i16 imm0_31:$imm)))>;
7059 def : Pat<(shl (sext_inreg GPR64:$Rn, i16), (i64 imm0_63:$imm)),
7060           (SBFMXri GPR64:$Rn, (i64 (i64shift_a        imm0_63:$imm)),
7061                               (i64 (i64shift_sext_i16 imm0_63:$imm)))>;
7063 def : Pat<(shl (i64 (sext GPR32:$Rn)), (i64 imm0_63:$imm)),
7064           (SBFMXri (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$Rn, sub_32),
7065                    (i64 (i64shift_a        imm0_63:$imm)),
7066                    (i64 (i64shift_sext_i32 imm0_63:$imm)))>;
7068 // sra patterns have an AddedComplexity of 10, so make sure we have a higher
7069 // AddedComplexity for the following patterns since we want to match sext + sra
7070 // patterns before we attempt to match a single sra node.
7071 let AddedComplexity = 20 in {
7072 // We support all sext + sra combinations which preserve at least one bit of the
7073 // original value which is to be sign extended. E.g. we support shifts up to
7074 // bitwidth-1 bits.
7075 def : Pat<(sra (sext_inreg GPR32:$Rn, i8), (i64 imm0_7:$imm)),
7076           (SBFMWri GPR32:$Rn, (i64 imm0_7:$imm), 7)>;
7077 def : Pat<(sra (sext_inreg GPR64:$Rn, i8), (i64 imm0_7:$imm)),
7078           (SBFMXri GPR64:$Rn, (i64 imm0_7:$imm), 7)>;
7080 def : Pat<(sra (sext_inreg GPR32:$Rn, i16), (i64 imm0_15:$imm)),
7081           (SBFMWri GPR32:$Rn, (i64 imm0_15:$imm), 15)>;
7082 def : Pat<(sra (sext_inreg GPR64:$Rn, i16), (i64 imm0_15:$imm)),
7083           (SBFMXri GPR64:$Rn, (i64 imm0_15:$imm), 15)>;
7085 def : Pat<(sra (i64 (sext GPR32:$Rn)), (i64 imm0_31:$imm)),
7086           (SBFMXri (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$Rn, sub_32),
7087                    (i64 imm0_31:$imm), 31)>;
7088 } // AddedComplexity = 20
7090 // To truncate, we can simply extract from a subregister.
7091 def : Pat<(i32 (trunc GPR64sp:$src)),
7092           (i32 (EXTRACT_SUBREG GPR64sp:$src, sub_32))>;
7094 // __builtin_trap() uses the BRK instruction on AArch64.
7095 def : Pat<(trap), (BRK 1)>;
7096 def : Pat<(debugtrap), (BRK 0xF000)>;
7098 def ubsan_trap_xform : SDNodeXForm<timm, [{
7099   return CurDAG->getTargetConstant(N->getZExtValue() | ('U' << 8), SDLoc(N), MVT::i32);
7100 }]>;
7102 def ubsan_trap_imm : TImmLeaf<i32, [{
7103   return isUInt<8>(Imm);
7104 }], ubsan_trap_xform>;
7106 def : Pat<(ubsantrap ubsan_trap_imm:$kind), (BRK ubsan_trap_imm:$kind)>;
7108 // Multiply high patterns which multiply the lower subvector using smull/umull
7109 // and the upper subvector with smull2/umull2. Then shuffle the high the high
7110 // part of both results together.
7111 def : Pat<(v16i8 (mulhs V128:$Rn, V128:$Rm)),
7112           (UZP2v16i8
7113            (SMULLv8i8_v8i16 (EXTRACT_SUBREG V128:$Rn, dsub),
7114                             (EXTRACT_SUBREG V128:$Rm, dsub)),
7115            (SMULLv16i8_v8i16 V128:$Rn, V128:$Rm))>;
7116 def : Pat<(v8i16 (mulhs V128:$Rn, V128:$Rm)),
7117           (UZP2v8i16
7118            (SMULLv4i16_v4i32 (EXTRACT_SUBREG V128:$Rn, dsub),
7119                              (EXTRACT_SUBREG V128:$Rm, dsub)),
7120            (SMULLv8i16_v4i32 V128:$Rn, V128:$Rm))>;
7121 def : Pat<(v4i32 (mulhs V128:$Rn, V128:$Rm)),
7122           (UZP2v4i32
7123            (SMULLv2i32_v2i64 (EXTRACT_SUBREG V128:$Rn, dsub),
7124                              (EXTRACT_SUBREG V128:$Rm, dsub)),
7125            (SMULLv4i32_v2i64 V128:$Rn, V128:$Rm))>;
7127 def : Pat<(v16i8 (mulhu V128:$Rn, V128:$Rm)),
7128           (UZP2v16i8
7129            (UMULLv8i8_v8i16 (EXTRACT_SUBREG V128:$Rn, dsub),
7130                             (EXTRACT_SUBREG V128:$Rm, dsub)),
7131            (UMULLv16i8_v8i16 V128:$Rn, V128:$Rm))>;
7132 def : Pat<(v8i16 (mulhu V128:$Rn, V128:$Rm)),
7133           (UZP2v8i16
7134            (UMULLv4i16_v4i32 (EXTRACT_SUBREG V128:$Rn, dsub),
7135                              (EXTRACT_SUBREG V128:$Rm, dsub)),
7136            (UMULLv8i16_v4i32 V128:$Rn, V128:$Rm))>;
7137 def : Pat<(v4i32 (mulhu V128:$Rn, V128:$Rm)),
7138           (UZP2v4i32
7139            (UMULLv2i32_v2i64 (EXTRACT_SUBREG V128:$Rn, dsub),
7140                              (EXTRACT_SUBREG V128:$Rm, dsub)),
7141            (UMULLv4i32_v2i64 V128:$Rn, V128:$Rm))>;
7143 // Conversions within AdvSIMD types in the same register size are free.
7144 // But because we need a consistent lane ordering, in big endian many
7145 // conversions require one or more REV instructions.
7147 // Consider a simple memory load followed by a bitconvert then a store.
7148 //   v0 = load v2i32
7149 //   v1 = BITCAST v2i32 v0 to v4i16
7150 //        store v4i16 v2
7152 // In big endian mode every memory access has an implicit byte swap. LDR and
7153 // STR do a 64-bit byte swap, whereas LD1/ST1 do a byte swap per lane - that
7154 // is, they treat the vector as a sequence of elements to be byte-swapped.
7155 // The two pairs of instructions are fundamentally incompatible. We've decided
7156 // to use LD1/ST1 only to simplify compiler implementation.
7158 // LD1/ST1 perform the equivalent of a sequence of LDR/STR + REV. This makes
7159 // the original code sequence:
7160 //   v0 = load v2i32
7161 //   v1 = REV v2i32                  (implicit)
7162 //   v2 = BITCAST v2i32 v1 to v4i16
7163 //   v3 = REV v4i16 v2               (implicit)
7164 //        store v4i16 v3
7166 // But this is now broken - the value stored is different to the value loaded
7167 // due to lane reordering. To fix this, on every BITCAST we must perform two
7168 // other REVs:
7169 //   v0 = load v2i32
7170 //   v1 = REV v2i32                  (implicit)
7171 //   v2 = REV v2i32
7172 //   v3 = BITCAST v2i32 v2 to v4i16
7173 //   v4 = REV v4i16
7174 //   v5 = REV v4i16 v4               (implicit)
7175 //        store v4i16 v5
7177 // This means an extra two instructions, but actually in most cases the two REV
7178 // instructions can be combined into one. For example:
7179 //   (REV64_2s (REV64_4h X)) === (REV32_4h X)
7181 // There is also no 128-bit REV instruction. This must be synthesized with an
7182 // EXT instruction.
7184 // Most bitconverts require some sort of conversion. The only exceptions are:
7185 //   a) Identity conversions -  vNfX <-> vNiX
7186 //   b) Single-lane-to-scalar - v1fX <-> fX or v1iX <-> iX
7189 // Natural vector casts (64 bit)
7190 def : Pat<(v8i8 (AArch64NvCast (v2i32 FPR64:$src))), (v8i8 FPR64:$src)>;
7191 def : Pat<(v4i16 (AArch64NvCast (v2i32 FPR64:$src))), (v4i16 FPR64:$src)>;
7192 def : Pat<(v4f16 (AArch64NvCast (v2i32 FPR64:$src))), (v4f16 FPR64:$src)>;
7193 def : Pat<(v4bf16 (AArch64NvCast (v2i32 FPR64:$src))), (v4bf16 FPR64:$src)>;
7194 def : Pat<(v2i32 (AArch64NvCast (v2i32 FPR64:$src))), (v2i32 FPR64:$src)>;
7195 def : Pat<(v2f32 (AArch64NvCast (v2i32 FPR64:$src))), (v2f32 FPR64:$src)>;
7196 def : Pat<(v1i64 (AArch64NvCast (v2i32 FPR64:$src))), (v1i64 FPR64:$src)>;
7198 def : Pat<(v8i8 (AArch64NvCast (v4i16 FPR64:$src))), (v8i8 FPR64:$src)>;
7199 def : Pat<(v4i16 (AArch64NvCast (v4i16 FPR64:$src))), (v4i16 FPR64:$src)>;
7200 def : Pat<(v4f16 (AArch64NvCast (v4i16 FPR64:$src))), (v4f16 FPR64:$src)>;
7201 def : Pat<(v4bf16 (AArch64NvCast (v4i16 FPR64:$src))), (v4bf16 FPR64:$src)>;
7202 def : Pat<(v2i32 (AArch64NvCast (v4i16 FPR64:$src))), (v2i32 FPR64:$src)>;
7203 def : Pat<(v1i64 (AArch64NvCast (v4i16 FPR64:$src))), (v1i64 FPR64:$src)>;
7205 def : Pat<(v8i8 (AArch64NvCast (v8i8 FPR64:$src))), (v8i8 FPR64:$src)>;
7206 def : Pat<(v4i16 (AArch64NvCast (v8i8 FPR64:$src))), (v4i16 FPR64:$src)>;
7207 def : Pat<(v4f16 (AArch64NvCast (v8i8 FPR64:$src))), (v4f16 FPR64:$src)>;
7208 def : Pat<(v4bf16 (AArch64NvCast (v8i8 FPR64:$src))), (v4bf16 FPR64:$src)>;
7209 def : Pat<(v2i32 (AArch64NvCast (v8i8 FPR64:$src))), (v2i32 FPR64:$src)>;
7210 def : Pat<(v2f32 (AArch64NvCast (v8i8 FPR64:$src))), (v2f32 FPR64:$src)>;
7211 def : Pat<(v1i64 (AArch64NvCast (v8i8 FPR64:$src))), (v1i64 FPR64:$src)>;
7213 def : Pat<(v8i8 (AArch64NvCast (f64 FPR64:$src))), (v8i8 FPR64:$src)>;
7214 def : Pat<(v4i16 (AArch64NvCast (f64 FPR64:$src))), (v4i16 FPR64:$src)>;
7215 def : Pat<(v4f16 (AArch64NvCast (f64 FPR64:$src))), (v4f16 FPR64:$src)>;
7216 def : Pat<(v4bf16 (AArch64NvCast (f64 FPR64:$src))), (v4bf16 FPR64:$src)>;
7217 def : Pat<(v2i32 (AArch64NvCast (f64 FPR64:$src))), (v2i32 FPR64:$src)>;
7218 def : Pat<(v2f32 (AArch64NvCast (f64 FPR64:$src))), (v2f32 FPR64:$src)>;
7219 def : Pat<(v1i64 (AArch64NvCast (f64 FPR64:$src))), (v1i64 FPR64:$src)>;
7220 def : Pat<(v1f64 (AArch64NvCast (f64 FPR64:$src))), (v1f64 FPR64:$src)>;
7222 def : Pat<(v8i8 (AArch64NvCast (v2f32 FPR64:$src))), (v8i8 FPR64:$src)>;
7223 def : Pat<(v4i16 (AArch64NvCast (v2f32 FPR64:$src))), (v4i16 FPR64:$src)>;
7224 def : Pat<(v2i32 (AArch64NvCast (v2f32 FPR64:$src))), (v2i32 FPR64:$src)>;
7225 def : Pat<(v2f32 (AArch64NvCast (v2f32 FPR64:$src))), (v2f32 FPR64:$src)>;
7226 def : Pat<(v1i64 (AArch64NvCast (v2f32 FPR64:$src))), (v1i64 FPR64:$src)>;
7227 def : Pat<(v1f64 (AArch64NvCast (v2f32 FPR64:$src))), (v1f64 FPR64:$src)>;
7229 // Natural vector casts (128 bit)
7230 def : Pat<(v16i8 (AArch64NvCast (v4i32 FPR128:$src))), (v16i8 FPR128:$src)>;
7231 def : Pat<(v8i16 (AArch64NvCast (v4i32 FPR128:$src))), (v8i16 FPR128:$src)>;
7232 def : Pat<(v8f16 (AArch64NvCast (v4i32 FPR128:$src))), (v8f16 FPR128:$src)>;
7233 def : Pat<(v8bf16 (AArch64NvCast (v4i32 FPR128:$src))), (v8bf16 FPR128:$src)>;
7234 def : Pat<(v4i32 (AArch64NvCast (v4i32 FPR128:$src))), (v4i32 FPR128:$src)>;
7235 def : Pat<(v4f32 (AArch64NvCast (v4i32 FPR128:$src))), (v4f32 FPR128:$src)>;
7236 def : Pat<(v2i64 (AArch64NvCast (v4i32 FPR128:$src))), (v2i64 FPR128:$src)>;
7237 def : Pat<(v2f64 (AArch64NvCast (v4i32 FPR128:$src))), (v2f64 FPR128:$src)>;
7239 def : Pat<(v16i8 (AArch64NvCast (v8i16 FPR128:$src))), (v16i8 FPR128:$src)>;
7240 def : Pat<(v8i16 (AArch64NvCast (v8i16 FPR128:$src))), (v8i16 FPR128:$src)>;
7241 def : Pat<(v8f16 (AArch64NvCast (v8i16 FPR128:$src))), (v8f16 FPR128:$src)>;
7242 def : Pat<(v8bf16 (AArch64NvCast (v8i16 FPR128:$src))), (v8bf16 FPR128:$src)>;
7243 def : Pat<(v4i32 (AArch64NvCast (v8i16 FPR128:$src))), (v4i32 FPR128:$src)>;
7244 def : Pat<(v2i64 (AArch64NvCast (v8i16 FPR128:$src))), (v2i64 FPR128:$src)>;
7245 def : Pat<(v4f32 (AArch64NvCast (v8i16 FPR128:$src))), (v4f32 FPR128:$src)>;
7246 def : Pat<(v2f64 (AArch64NvCast (v8i16 FPR128:$src))), (v2f64 FPR128:$src)>;
7248 def : Pat<(v16i8 (AArch64NvCast (v16i8 FPR128:$src))), (v16i8 FPR128:$src)>;
7249 def : Pat<(v8i16 (AArch64NvCast (v16i8 FPR128:$src))), (v8i16 FPR128:$src)>;
7250 def : Pat<(v8f16 (AArch64NvCast (v16i8 FPR128:$src))), (v8f16 FPR128:$src)>;
7251 def : Pat<(v8bf16 (AArch64NvCast (v16i8 FPR128:$src))), (v8bf16 FPR128:$src)>;
7252 def : Pat<(v4i32 (AArch64NvCast (v16i8 FPR128:$src))), (v4i32 FPR128:$src)>;
7253 def : Pat<(v2i64 (AArch64NvCast (v16i8 FPR128:$src))), (v2i64 FPR128:$src)>;
7254 def : Pat<(v4f32 (AArch64NvCast (v16i8 FPR128:$src))), (v4f32 FPR128:$src)>;
7255 def : Pat<(v2f64 (AArch64NvCast (v16i8 FPR128:$src))), (v2f64 FPR128:$src)>;
7257 def : Pat<(v16i8 (AArch64NvCast (v2i64 FPR128:$src))), (v16i8 FPR128:$src)>;
7258 def : Pat<(v8i16 (AArch64NvCast (v2i64 FPR128:$src))), (v8i16 FPR128:$src)>;
7259 def : Pat<(v8f16 (AArch64NvCast (v2i64 FPR128:$src))), (v8f16 FPR128:$src)>;
7260 def : Pat<(v8bf16 (AArch64NvCast (v2i64 FPR128:$src))), (v8bf16 FPR128:$src)>;
7261 def : Pat<(v4i32 (AArch64NvCast (v2i64 FPR128:$src))), (v4i32 FPR128:$src)>;
7262 def : Pat<(v2i64 (AArch64NvCast (v2i64 FPR128:$src))), (v2i64 FPR128:$src)>;
7263 def : Pat<(v4f32 (AArch64NvCast (v2i64 FPR128:$src))), (v4f32 FPR128:$src)>;
7264 def : Pat<(v2f64 (AArch64NvCast (v2i64 FPR128:$src))), (v2f64 FPR128:$src)>;
7266 def : Pat<(v16i8 (AArch64NvCast (v4f32 FPR128:$src))), (v16i8 FPR128:$src)>;
7267 def : Pat<(v8i16 (AArch64NvCast (v4f32 FPR128:$src))), (v8i16 FPR128:$src)>;
7268 def : Pat<(v4i32 (AArch64NvCast (v4f32 FPR128:$src))), (v4i32 FPR128:$src)>;
7269 def : Pat<(v4f32 (AArch64NvCast (v4f32 FPR128:$src))), (v4f32 FPR128:$src)>;
7270 def : Pat<(v2i64 (AArch64NvCast (v4f32 FPR128:$src))), (v2i64 FPR128:$src)>;
7271 def : Pat<(v8f16 (AArch64NvCast (v4f32 FPR128:$src))), (v8f16 FPR128:$src)>;
7272 def : Pat<(v8bf16 (AArch64NvCast (v4f32 FPR128:$src))), (v8bf16 FPR128:$src)>;
7273 def : Pat<(v2f64 (AArch64NvCast (v4f32 FPR128:$src))), (v2f64 FPR128:$src)>;
7275 def : Pat<(v16i8 (AArch64NvCast (v2f64 FPR128:$src))), (v16i8 FPR128:$src)>;
7276 def : Pat<(v8i16 (AArch64NvCast (v2f64 FPR128:$src))), (v8i16 FPR128:$src)>;
7277 def : Pat<(v4i32 (AArch64NvCast (v2f64 FPR128:$src))), (v4i32 FPR128:$src)>;
7278 def : Pat<(v2i64 (AArch64NvCast (v2f64 FPR128:$src))), (v2i64 FPR128:$src)>;
7279 def : Pat<(v2f64 (AArch64NvCast (v2f64 FPR128:$src))), (v2f64 FPR128:$src)>;
7280 def : Pat<(v8f16 (AArch64NvCast (v2f64 FPR128:$src))), (v8f16 FPR128:$src)>;
7281 def : Pat<(v8bf16 (AArch64NvCast (v2f64 FPR128:$src))), (v8bf16 FPR128:$src)>;
7282 def : Pat<(v4f32 (AArch64NvCast (v2f64 FPR128:$src))), (v4f32 FPR128:$src)>;
7284 let Predicates = [IsLE] in {
7285 def : Pat<(v8i8  (bitconvert GPR64:$Xn)), (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
7286 def : Pat<(v4i16 (bitconvert GPR64:$Xn)), (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
7287 def : Pat<(v2i32 (bitconvert GPR64:$Xn)), (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
7288 def : Pat<(v4f16 (bitconvert GPR64:$Xn)), (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
7289 def : Pat<(v4bf16 (bitconvert GPR64:$Xn)), (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
7290 def : Pat<(v2f32 (bitconvert GPR64:$Xn)), (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
7292 def : Pat<(i64 (bitconvert (v8i8  V64:$Vn))),
7293           (COPY_TO_REGCLASS V64:$Vn, GPR64)>;
7294 def : Pat<(i64 (bitconvert (v4i16 V64:$Vn))),
7295           (COPY_TO_REGCLASS V64:$Vn, GPR64)>;
7296 def : Pat<(i64 (bitconvert (v2i32 V64:$Vn))),
7297           (COPY_TO_REGCLASS V64:$Vn, GPR64)>;
7298 def : Pat<(i64 (bitconvert (v4f16 V64:$Vn))),
7299           (COPY_TO_REGCLASS V64:$Vn, GPR64)>;
7300 def : Pat<(i64 (bitconvert (v4bf16 V64:$Vn))),
7301           (COPY_TO_REGCLASS V64:$Vn, GPR64)>;
7302 def : Pat<(i64 (bitconvert (v2f32 V64:$Vn))),
7303           (COPY_TO_REGCLASS V64:$Vn, GPR64)>;
7304 def : Pat<(i64 (bitconvert (v1f64 V64:$Vn))),
7305           (COPY_TO_REGCLASS V64:$Vn, GPR64)>;
7307 let Predicates = [IsBE] in {
7308 def : Pat<(v8i8  (bitconvert GPR64:$Xn)),
7309                  (REV64v8i8 (COPY_TO_REGCLASS GPR64:$Xn, FPR64))>;
7310 def : Pat<(v4i16 (bitconvert GPR64:$Xn)),
7311                  (REV64v4i16 (COPY_TO_REGCLASS GPR64:$Xn, FPR64))>;
7312 def : Pat<(v2i32 (bitconvert GPR64:$Xn)),
7313                  (REV64v2i32 (COPY_TO_REGCLASS GPR64:$Xn, FPR64))>;
7314 def : Pat<(v4f16 (bitconvert GPR64:$Xn)),
7315                  (REV64v4i16 (COPY_TO_REGCLASS GPR64:$Xn, FPR64))>;
7316 def : Pat<(v4bf16 (bitconvert GPR64:$Xn)),
7317                   (REV64v4i16 (COPY_TO_REGCLASS GPR64:$Xn, FPR64))>;
7318 def : Pat<(v2f32 (bitconvert GPR64:$Xn)),
7319                  (REV64v2i32 (COPY_TO_REGCLASS GPR64:$Xn, FPR64))>;
7321 def : Pat<(i64 (bitconvert (v8i8  V64:$Vn))),
7322           (REV64v8i8 (COPY_TO_REGCLASS V64:$Vn, GPR64))>;
7323 def : Pat<(i64 (bitconvert (v4i16 V64:$Vn))),
7324           (REV64v4i16 (COPY_TO_REGCLASS V64:$Vn, GPR64))>;
7325 def : Pat<(i64 (bitconvert (v2i32 V64:$Vn))),
7326           (REV64v2i32 (COPY_TO_REGCLASS V64:$Vn, GPR64))>;
7327 def : Pat<(i64 (bitconvert (v4f16 V64:$Vn))),
7328           (REV64v4i16 (COPY_TO_REGCLASS V64:$Vn, GPR64))>;
7329 def : Pat<(i64 (bitconvert (v4bf16 V64:$Vn))),
7330           (REV64v4i16 (COPY_TO_REGCLASS V64:$Vn, GPR64))>;
7331 def : Pat<(i64 (bitconvert (v2f32 V64:$Vn))),
7332           (REV64v2i32 (COPY_TO_REGCLASS V64:$Vn, GPR64))>;
7334 def : Pat<(v1i64 (bitconvert GPR64:$Xn)), (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
7335 def : Pat<(v1f64 (bitconvert GPR64:$Xn)), (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
7336 def : Pat<(i64 (bitconvert (v1i64 V64:$Vn))),
7337           (COPY_TO_REGCLASS V64:$Vn, GPR64)>;
7338 def : Pat<(v1i64 (scalar_to_vector GPR64:$Xn)),
7339           (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
7340 def : Pat<(v1f64 (scalar_to_vector GPR64:$Xn)),
7341           (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
7342 def : Pat<(v1f64 (scalar_to_vector (f64 FPR64:$Xn))), (v1f64 FPR64:$Xn)>;
7344 def : Pat<(f32 (bitconvert (i32 GPR32:$Xn))),
7345           (COPY_TO_REGCLASS GPR32:$Xn, FPR32)>;
7346 def : Pat<(i32 (bitconvert (f32 FPR32:$Xn))),
7347           (COPY_TO_REGCLASS FPR32:$Xn, GPR32)>;
7348 def : Pat<(f64 (bitconvert (i64 GPR64:$Xn))),
7349           (COPY_TO_REGCLASS GPR64:$Xn, FPR64)>;
7350 def : Pat<(i64 (bitconvert (f64 FPR64:$Xn))),
7351           (COPY_TO_REGCLASS FPR64:$Xn, GPR64)>;
7352 def : Pat<(i64 (bitconvert (v1f64 V64:$Vn))),
7353           (COPY_TO_REGCLASS V64:$Vn, GPR64)>;
7355 let Predicates = [IsLE] in {
7356 def : Pat<(v1i64 (bitconvert (v2i32 FPR64:$src))), (v1i64 FPR64:$src)>;
7357 def : Pat<(v1i64 (bitconvert (v4i16 FPR64:$src))), (v1i64 FPR64:$src)>;
7358 def : Pat<(v1i64 (bitconvert (v8i8  FPR64:$src))), (v1i64 FPR64:$src)>;
7359 def : Pat<(v1i64 (bitconvert (v4f16 FPR64:$src))), (v1i64 FPR64:$src)>;
7360 def : Pat<(v1i64 (bitconvert (v4bf16 FPR64:$src))), (v1i64 FPR64:$src)>;
7361 def : Pat<(v1i64 (bitconvert (v2f32 FPR64:$src))), (v1i64 FPR64:$src)>;
7363 let Predicates = [IsBE] in {
7364 def : Pat<(v1i64 (bitconvert (v2i32 FPR64:$src))),
7365                              (v1i64 (REV64v2i32 FPR64:$src))>;
7366 def : Pat<(v1i64 (bitconvert (v4i16 FPR64:$src))),
7367                              (v1i64 (REV64v4i16 FPR64:$src))>;
7368 def : Pat<(v1i64 (bitconvert (v8i8  FPR64:$src))),
7369                              (v1i64 (REV64v8i8 FPR64:$src))>;
7370 def : Pat<(v1i64 (bitconvert (v4f16 FPR64:$src))),
7371                              (v1i64 (REV64v4i16 FPR64:$src))>;
7372 def : Pat<(v1i64 (bitconvert (v4bf16 FPR64:$src))),
7373                              (v1i64 (REV64v4i16 FPR64:$src))>;
7374 def : Pat<(v1i64 (bitconvert (v2f32 FPR64:$src))),
7375                              (v1i64 (REV64v2i32 FPR64:$src))>;
7377 def : Pat<(v1i64 (bitconvert (v1f64 FPR64:$src))), (v1i64 FPR64:$src)>;
7378 def : Pat<(v1i64 (bitconvert (f64   FPR64:$src))), (v1i64 FPR64:$src)>;
7380 let Predicates = [IsLE] in {
7381 def : Pat<(v2i32 (bitconvert (v1i64 FPR64:$src))), (v2i32 FPR64:$src)>;
7382 def : Pat<(v2i32 (bitconvert (v4i16 FPR64:$src))), (v2i32 FPR64:$src)>;
7383 def : Pat<(v2i32 (bitconvert (v8i8  FPR64:$src))), (v2i32 FPR64:$src)>;
7384 def : Pat<(v2i32 (bitconvert (f64   FPR64:$src))), (v2i32 FPR64:$src)>;
7385 def : Pat<(v2i32 (bitconvert (v1f64 FPR64:$src))), (v2i32 FPR64:$src)>;
7386 def : Pat<(v2i32 (bitconvert (v4f16 FPR64:$src))), (v2i32 FPR64:$src)>;
7387 def : Pat<(v2i32 (bitconvert (v4bf16 FPR64:$src))), (v2i32 FPR64:$src)>;
7389 let Predicates = [IsBE] in {
7390 def : Pat<(v2i32 (bitconvert (v1i64 FPR64:$src))),
7391                              (v2i32 (REV64v2i32 FPR64:$src))>;
7392 def : Pat<(v2i32 (bitconvert (v4i16 FPR64:$src))),
7393                              (v2i32 (REV32v4i16 FPR64:$src))>;
7394 def : Pat<(v2i32 (bitconvert (v8i8  FPR64:$src))),
7395                              (v2i32 (REV32v8i8 FPR64:$src))>;
7396 def : Pat<(v2i32 (bitconvert (f64   FPR64:$src))),
7397                              (v2i32 (REV64v2i32 FPR64:$src))>;
7398 def : Pat<(v2i32 (bitconvert (v1f64 FPR64:$src))),
7399                              (v2i32 (REV64v2i32 FPR64:$src))>;
7400 def : Pat<(v2i32 (bitconvert (v4f16 FPR64:$src))),
7401                              (v2i32 (REV32v4i16 FPR64:$src))>;
7402 def : Pat<(v2i32 (bitconvert (v4bf16 FPR64:$src))),
7403                              (v2i32 (REV32v4i16 FPR64:$src))>;
7405 def : Pat<(v2i32 (bitconvert (v2f32 FPR64:$src))), (v2i32 FPR64:$src)>;
7407 let Predicates = [IsLE] in {
7408 def : Pat<(v4i16 (bitconvert (v1i64 FPR64:$src))), (v4i16 FPR64:$src)>;
7409 def : Pat<(v4i16 (bitconvert (v2i32 FPR64:$src))), (v4i16 FPR64:$src)>;
7410 def : Pat<(v4i16 (bitconvert (v8i8  FPR64:$src))), (v4i16 FPR64:$src)>;
7411 def : Pat<(v4i16 (bitconvert (f64   FPR64:$src))), (v4i16 FPR64:$src)>;
7412 def : Pat<(v4i16 (bitconvert (v2f32 FPR64:$src))), (v4i16 FPR64:$src)>;
7413 def : Pat<(v4i16 (bitconvert (v1f64 FPR64:$src))), (v4i16 FPR64:$src)>;
7415 let Predicates = [IsBE] in {
7416 def : Pat<(v4i16 (bitconvert (v1i64 FPR64:$src))),
7417                              (v4i16 (REV64v4i16 FPR64:$src))>;
7418 def : Pat<(v4i16 (bitconvert (v2i32 FPR64:$src))),
7419                              (v4i16 (REV32v4i16 FPR64:$src))>;
7420 def : Pat<(v4i16 (bitconvert (v8i8  FPR64:$src))),
7421                              (v4i16 (REV16v8i8 FPR64:$src))>;
7422 def : Pat<(v4i16 (bitconvert (f64   FPR64:$src))),
7423                              (v4i16 (REV64v4i16 FPR64:$src))>;
7424 def : Pat<(v4i16 (bitconvert (v2f32 FPR64:$src))),
7425                              (v4i16 (REV32v4i16 FPR64:$src))>;
7426 def : Pat<(v4i16 (bitconvert (v1f64 FPR64:$src))),
7427                              (v4i16 (REV64v4i16 FPR64:$src))>;
7429 def : Pat<(v4i16 (bitconvert (v4f16 FPR64:$src))), (v4i16 FPR64:$src)>;
7430 def : Pat<(v4i16 (bitconvert (v4bf16 FPR64:$src))), (v4i16 FPR64:$src)>;
7432 let Predicates = [IsLE] in {
7433 def : Pat<(v4f16 (bitconvert (v1i64 FPR64:$src))), (v4f16 FPR64:$src)>;
7434 def : Pat<(v4f16 (bitconvert (v2i32 FPR64:$src))), (v4f16 FPR64:$src)>;
7435 def : Pat<(v4f16 (bitconvert (v8i8  FPR64:$src))), (v4f16 FPR64:$src)>;
7436 def : Pat<(v4f16 (bitconvert (f64   FPR64:$src))), (v4f16 FPR64:$src)>;
7437 def : Pat<(v4f16 (bitconvert (v2f32 FPR64:$src))), (v4f16 FPR64:$src)>;
7438 def : Pat<(v4f16 (bitconvert (v1f64 FPR64:$src))), (v4f16 FPR64:$src)>;
7440 def : Pat<(v4bf16 (bitconvert (v1i64 FPR64:$src))), (v4bf16 FPR64:$src)>;
7441 def : Pat<(v4bf16 (bitconvert (v2i32 FPR64:$src))), (v4bf16 FPR64:$src)>;
7442 def : Pat<(v4bf16 (bitconvert (v8i8  FPR64:$src))), (v4bf16 FPR64:$src)>;
7443 def : Pat<(v4bf16 (bitconvert (f64   FPR64:$src))), (v4bf16 FPR64:$src)>;
7444 def : Pat<(v4bf16 (bitconvert (v2f32 FPR64:$src))), (v4bf16 FPR64:$src)>;
7445 def : Pat<(v4bf16 (bitconvert (v1f64 FPR64:$src))), (v4bf16 FPR64:$src)>;
7447 let Predicates = [IsBE] in {
7448 def : Pat<(v4f16 (bitconvert (v1i64 FPR64:$src))),
7449                              (v4f16 (REV64v4i16 FPR64:$src))>;
7450 def : Pat<(v4f16 (bitconvert (v2i32 FPR64:$src))),
7451                              (v4f16 (REV32v4i16 FPR64:$src))>;
7452 def : Pat<(v4f16 (bitconvert (v8i8  FPR64:$src))),
7453                              (v4f16 (REV16v8i8 FPR64:$src))>;
7454 def : Pat<(v4f16 (bitconvert (f64   FPR64:$src))),
7455                              (v4f16 (REV64v4i16 FPR64:$src))>;
7456 def : Pat<(v4f16 (bitconvert (v2f32 FPR64:$src))),
7457                              (v4f16 (REV32v4i16 FPR64:$src))>;
7458 def : Pat<(v4f16 (bitconvert (v1f64 FPR64:$src))),
7459                              (v4f16 (REV64v4i16 FPR64:$src))>;
7461 def : Pat<(v4bf16 (bitconvert (v1i64 FPR64:$src))),
7462                              (v4bf16 (REV64v4i16 FPR64:$src))>;
7463 def : Pat<(v4bf16 (bitconvert (v2i32 FPR64:$src))),
7464                              (v4bf16 (REV32v4i16 FPR64:$src))>;
7465 def : Pat<(v4bf16 (bitconvert (v8i8  FPR64:$src))),
7466                              (v4bf16 (REV16v8i8 FPR64:$src))>;
7467 def : Pat<(v4bf16 (bitconvert (f64   FPR64:$src))),
7468                              (v4bf16 (REV64v4i16 FPR64:$src))>;
7469 def : Pat<(v4bf16 (bitconvert (v2f32 FPR64:$src))),
7470                              (v4bf16 (REV32v4i16 FPR64:$src))>;
7471 def : Pat<(v4bf16 (bitconvert (v1f64 FPR64:$src))),
7472                              (v4bf16 (REV64v4i16 FPR64:$src))>;
7474 def : Pat<(v4f16 (bitconvert (v4i16 FPR64:$src))), (v4f16 FPR64:$src)>;
7475 def : Pat<(v4bf16 (bitconvert (v4i16 FPR64:$src))), (v4bf16 FPR64:$src)>;
7477 let Predicates = [IsLE] in {
7478 def : Pat<(v8i8  (bitconvert (v1i64 FPR64:$src))), (v8i8  FPR64:$src)>;
7479 def : Pat<(v8i8  (bitconvert (v2i32 FPR64:$src))), (v8i8  FPR64:$src)>;
7480 def : Pat<(v8i8  (bitconvert (v4i16 FPR64:$src))), (v8i8  FPR64:$src)>;
7481 def : Pat<(v8i8  (bitconvert (f64   FPR64:$src))), (v8i8  FPR64:$src)>;
7482 def : Pat<(v8i8  (bitconvert (v2f32 FPR64:$src))), (v8i8  FPR64:$src)>;
7483 def : Pat<(v8i8  (bitconvert (v1f64 FPR64:$src))), (v8i8  FPR64:$src)>;
7484 def : Pat<(v8i8  (bitconvert (v4f16 FPR64:$src))), (v8i8  FPR64:$src)>;
7485 def : Pat<(v8i8  (bitconvert (v4bf16 FPR64:$src))), (v8i8  FPR64:$src)>;
7487 let Predicates = [IsBE] in {
7488 def : Pat<(v8i8  (bitconvert (v1i64 FPR64:$src))),
7489                              (v8i8 (REV64v8i8 FPR64:$src))>;
7490 def : Pat<(v8i8  (bitconvert (v2i32 FPR64:$src))),
7491                              (v8i8 (REV32v8i8 FPR64:$src))>;
7492 def : Pat<(v8i8  (bitconvert (v4i16 FPR64:$src))),
7493                              (v8i8 (REV16v8i8 FPR64:$src))>;
7494 def : Pat<(v8i8  (bitconvert (f64   FPR64:$src))),
7495                              (v8i8 (REV64v8i8 FPR64:$src))>;
7496 def : Pat<(v8i8  (bitconvert (v2f32 FPR64:$src))),
7497                              (v8i8 (REV32v8i8 FPR64:$src))>;
7498 def : Pat<(v8i8  (bitconvert (v1f64 FPR64:$src))),
7499                              (v8i8 (REV64v8i8 FPR64:$src))>;
7500 def : Pat<(v8i8  (bitconvert (v4f16 FPR64:$src))),
7501                              (v8i8 (REV16v8i8 FPR64:$src))>;
7502 def : Pat<(v8i8  (bitconvert (v4bf16 FPR64:$src))),
7503                              (v8i8 (REV16v8i8 FPR64:$src))>;
7506 let Predicates = [IsLE] in {
7507 def : Pat<(f64   (bitconvert (v2i32 FPR64:$src))), (f64   FPR64:$src)>;
7508 def : Pat<(f64   (bitconvert (v4i16 FPR64:$src))), (f64   FPR64:$src)>;
7509 def : Pat<(f64   (bitconvert (v2f32 FPR64:$src))), (f64   FPR64:$src)>;
7510 def : Pat<(f64   (bitconvert (v8i8  FPR64:$src))), (f64   FPR64:$src)>;
7511 def : Pat<(f64   (bitconvert (v4f16 FPR64:$src))), (f64   FPR64:$src)>;
7512 def : Pat<(f64   (bitconvert (v4bf16 FPR64:$src))), (f64   FPR64:$src)>;
7514 let Predicates = [IsBE] in {
7515 def : Pat<(f64   (bitconvert (v2i32 FPR64:$src))),
7516                              (f64 (REV64v2i32 FPR64:$src))>;
7517 def : Pat<(f64   (bitconvert (v4i16 FPR64:$src))),
7518                              (f64 (REV64v4i16 FPR64:$src))>;
7519 def : Pat<(f64   (bitconvert (v2f32 FPR64:$src))),
7520                              (f64 (REV64v2i32 FPR64:$src))>;
7521 def : Pat<(f64   (bitconvert (v8i8  FPR64:$src))),
7522                              (f64 (REV64v8i8 FPR64:$src))>;
7523 def : Pat<(f64   (bitconvert (v4f16 FPR64:$src))),
7524                              (f64 (REV64v4i16 FPR64:$src))>;
7525 def : Pat<(f64   (bitconvert (v4bf16 FPR64:$src))),
7526                              (f64 (REV64v4i16 FPR64:$src))>;
7528 def : Pat<(f64   (bitconvert (v1i64 FPR64:$src))), (f64   FPR64:$src)>;
7529 def : Pat<(f64   (bitconvert (v1f64 FPR64:$src))), (f64   FPR64:$src)>;
7531 let Predicates = [IsLE] in {
7532 def : Pat<(v1f64 (bitconvert (v2i32 FPR64:$src))), (v1f64 FPR64:$src)>;
7533 def : Pat<(v1f64 (bitconvert (v4i16 FPR64:$src))), (v1f64 FPR64:$src)>;
7534 def : Pat<(v1f64 (bitconvert (v8i8  FPR64:$src))), (v1f64 FPR64:$src)>;
7535 def : Pat<(v1f64 (bitconvert (v2f32 FPR64:$src))), (v1f64 FPR64:$src)>;
7536 def : Pat<(v1f64 (bitconvert (v4f16 FPR64:$src))), (v1f64 FPR64:$src)>;
7537 def : Pat<(v1f64 (bitconvert (v4bf16 FPR64:$src))), (v1f64 FPR64:$src)>;
7539 let Predicates = [IsBE] in {
7540 def : Pat<(v1f64 (bitconvert (v2i32 FPR64:$src))),
7541                              (v1f64 (REV64v2i32 FPR64:$src))>;
7542 def : Pat<(v1f64 (bitconvert (v4i16 FPR64:$src))),
7543                              (v1f64 (REV64v4i16 FPR64:$src))>;
7544 def : Pat<(v1f64 (bitconvert (v8i8  FPR64:$src))),
7545                              (v1f64 (REV64v8i8 FPR64:$src))>;
7546 def : Pat<(v1f64 (bitconvert (v2f32 FPR64:$src))),
7547                              (v1f64 (REV64v2i32 FPR64:$src))>;
7548 def : Pat<(v1f64 (bitconvert (v4f16 FPR64:$src))),
7549                              (v1f64 (REV64v4i16 FPR64:$src))>;
7550 def : Pat<(v1f64 (bitconvert (v4bf16 FPR64:$src))),
7551                              (v1f64 (REV64v4i16 FPR64:$src))>;
7553 def : Pat<(v1f64 (bitconvert (v1i64 FPR64:$src))), (v1f64 FPR64:$src)>;
7554 def : Pat<(v1f64 (bitconvert (f64   FPR64:$src))), (v1f64 FPR64:$src)>;
7556 let Predicates = [IsLE] in {
7557 def : Pat<(v2f32 (bitconvert (v1i64 FPR64:$src))), (v2f32 FPR64:$src)>;
7558 def : Pat<(v2f32 (bitconvert (v4i16 FPR64:$src))), (v2f32 FPR64:$src)>;
7559 def : Pat<(v2f32 (bitconvert (v8i8  FPR64:$src))), (v2f32 FPR64:$src)>;
7560 def : Pat<(v2f32 (bitconvert (v1f64 FPR64:$src))), (v2f32 FPR64:$src)>;
7561 def : Pat<(v2f32 (bitconvert (f64   FPR64:$src))), (v2f32 FPR64:$src)>;
7562 def : Pat<(v2f32 (bitconvert (v4f16 FPR64:$src))), (v2f32 FPR64:$src)>;
7563 def : Pat<(v2f32 (bitconvert (v4bf16 FPR64:$src))), (v2f32 FPR64:$src)>;
7565 let Predicates = [IsBE] in {
7566 def : Pat<(v2f32 (bitconvert (v1i64 FPR64:$src))),
7567                              (v2f32 (REV64v2i32 FPR64:$src))>;
7568 def : Pat<(v2f32 (bitconvert (v4i16 FPR64:$src))),
7569                              (v2f32 (REV32v4i16 FPR64:$src))>;
7570 def : Pat<(v2f32 (bitconvert (v8i8  FPR64:$src))),
7571                              (v2f32 (REV32v8i8 FPR64:$src))>;
7572 def : Pat<(v2f32 (bitconvert (v1f64 FPR64:$src))),
7573                              (v2f32 (REV64v2i32 FPR64:$src))>;
7574 def : Pat<(v2f32 (bitconvert (f64   FPR64:$src))),
7575                              (v2f32 (REV64v2i32 FPR64:$src))>;
7576 def : Pat<(v2f32 (bitconvert (v4f16 FPR64:$src))),
7577                              (v2f32 (REV32v4i16 FPR64:$src))>;
7578 def : Pat<(v2f32 (bitconvert (v4bf16 FPR64:$src))),
7579                              (v2f32 (REV32v4i16 FPR64:$src))>;
7581 def : Pat<(v2f32 (bitconvert (v2i32 FPR64:$src))), (v2f32 FPR64:$src)>;
7583 let Predicates = [IsLE] in {
7584 def : Pat<(f128 (bitconvert (v2i64 FPR128:$src))), (f128 FPR128:$src)>;
7585 def : Pat<(f128 (bitconvert (v4i32 FPR128:$src))), (f128 FPR128:$src)>;
7586 def : Pat<(f128 (bitconvert (v8i16 FPR128:$src))), (f128 FPR128:$src)>;
7587 def : Pat<(f128 (bitconvert (v2f64 FPR128:$src))), (f128 FPR128:$src)>;
7588 def : Pat<(f128 (bitconvert (v4f32 FPR128:$src))), (f128 FPR128:$src)>;
7589 def : Pat<(f128 (bitconvert (v8f16 FPR128:$src))), (f128 FPR128:$src)>;
7590 def : Pat<(f128 (bitconvert (v8bf16 FPR128:$src))), (f128 FPR128:$src)>;
7591 def : Pat<(f128 (bitconvert (v16i8 FPR128:$src))), (f128 FPR128:$src)>;
7593 let Predicates = [IsBE] in {
7594 def : Pat<(f128 (bitconvert (v2i64 FPR128:$src))),
7595                             (f128 (EXTv16i8 FPR128:$src, FPR128:$src, (i32 8)))>;
7596 def : Pat<(f128 (bitconvert (v4i32 FPR128:$src))),
7597                             (f128 (EXTv16i8 (REV64v4i32 FPR128:$src),
7598                                             (REV64v4i32 FPR128:$src), (i32 8)))>;
7599 def : Pat<(f128 (bitconvert (v8i16 FPR128:$src))),
7600                             (f128 (EXTv16i8 (REV64v8i16 FPR128:$src),
7601                                             (REV64v8i16 FPR128:$src), (i32 8)))>;
7602 def : Pat<(f128 (bitconvert (v8f16 FPR128:$src))),
7603                             (f128 (EXTv16i8 (REV64v8i16 FPR128:$src),
7604                                             (REV64v8i16 FPR128:$src), (i32 8)))>;
7605 def : Pat<(f128 (bitconvert (v8bf16 FPR128:$src))),
7606                             (f128 (EXTv16i8 (REV64v8i16 FPR128:$src),
7607                                             (REV64v8i16 FPR128:$src), (i32 8)))>;
7608 def : Pat<(f128 (bitconvert (v2f64 FPR128:$src))),
7609                             (f128 (EXTv16i8 FPR128:$src, FPR128:$src, (i32 8)))>;
7610 def : Pat<(f128 (bitconvert (v4f32 FPR128:$src))),
7611                             (f128 (EXTv16i8 (REV64v4i32 FPR128:$src),
7612                                             (REV64v4i32 FPR128:$src), (i32 8)))>;
7613 def : Pat<(f128 (bitconvert (v16i8 FPR128:$src))),
7614                             (f128 (EXTv16i8 (REV64v16i8 FPR128:$src),
7615                                             (REV64v16i8 FPR128:$src), (i32 8)))>;
7618 let Predicates = [IsLE] in {
7619 def : Pat<(v2f64 (bitconvert (f128  FPR128:$src))), (v2f64 FPR128:$src)>;
7620 def : Pat<(v2f64 (bitconvert (v4i32 FPR128:$src))), (v2f64 FPR128:$src)>;
7621 def : Pat<(v2f64 (bitconvert (v8i16 FPR128:$src))), (v2f64 FPR128:$src)>;
7622 def : Pat<(v2f64 (bitconvert (v8f16 FPR128:$src))), (v2f64 FPR128:$src)>;
7623 def : Pat<(v2f64 (bitconvert (v8bf16 FPR128:$src))), (v2f64 FPR128:$src)>;
7624 def : Pat<(v2f64 (bitconvert (v16i8 FPR128:$src))), (v2f64 FPR128:$src)>;
7625 def : Pat<(v2f64 (bitconvert (v4f32 FPR128:$src))), (v2f64 FPR128:$src)>;
7627 let Predicates = [IsBE] in {
7628 def : Pat<(v2f64 (bitconvert (f128  FPR128:$src))),
7629                              (v2f64 (EXTv16i8 FPR128:$src,
7630                                               FPR128:$src, (i32 8)))>;
7631 def : Pat<(v2f64 (bitconvert (v4i32 FPR128:$src))),
7632                              (v2f64 (REV64v4i32 FPR128:$src))>;
7633 def : Pat<(v2f64 (bitconvert (v8i16 FPR128:$src))),
7634                              (v2f64 (REV64v8i16 FPR128:$src))>;
7635 def : Pat<(v2f64 (bitconvert (v8f16 FPR128:$src))),
7636                              (v2f64 (REV64v8i16 FPR128:$src))>;
7637 def : Pat<(v2f64 (bitconvert (v8bf16 FPR128:$src))),
7638                              (v2f64 (REV64v8i16 FPR128:$src))>;
7639 def : Pat<(v2f64 (bitconvert (v16i8 FPR128:$src))),
7640                              (v2f64 (REV64v16i8 FPR128:$src))>;
7641 def : Pat<(v2f64 (bitconvert (v4f32 FPR128:$src))),
7642                              (v2f64 (REV64v4i32 FPR128:$src))>;
7644 def : Pat<(v2f64 (bitconvert (v2i64 FPR128:$src))), (v2f64 FPR128:$src)>;
7646 let Predicates = [IsLE] in {
7647 def : Pat<(v4f32 (bitconvert (f128  FPR128:$src))), (v4f32 FPR128:$src)>;
7648 def : Pat<(v4f32 (bitconvert (v8i16 FPR128:$src))), (v4f32 FPR128:$src)>;
7649 def : Pat<(v4f32 (bitconvert (v8f16 FPR128:$src))), (v4f32 FPR128:$src)>;
7650 def : Pat<(v4f32 (bitconvert (v8bf16 FPR128:$src))), (v4f32 FPR128:$src)>;
7651 def : Pat<(v4f32 (bitconvert (v16i8 FPR128:$src))), (v4f32 FPR128:$src)>;
7652 def : Pat<(v4f32 (bitconvert (v2i64 FPR128:$src))), (v4f32 FPR128:$src)>;
7653 def : Pat<(v4f32 (bitconvert (v2f64 FPR128:$src))), (v4f32 FPR128:$src)>;
7655 let Predicates = [IsBE] in {
7656 def : Pat<(v4f32 (bitconvert (f128  FPR128:$src))),
7657                              (v4f32 (EXTv16i8 (REV64v4i32 FPR128:$src),
7658                                     (REV64v4i32 FPR128:$src), (i32 8)))>;
7659 def : Pat<(v4f32 (bitconvert (v8i16 FPR128:$src))),
7660                              (v4f32 (REV32v8i16 FPR128:$src))>;
7661 def : Pat<(v4f32 (bitconvert (v8f16 FPR128:$src))),
7662                              (v4f32 (REV32v8i16 FPR128:$src))>;
7663 def : Pat<(v4f32 (bitconvert (v8bf16 FPR128:$src))),
7664                              (v4f32 (REV32v8i16 FPR128:$src))>;
7665 def : Pat<(v4f32 (bitconvert (v16i8 FPR128:$src))),
7666                              (v4f32 (REV32v16i8 FPR128:$src))>;
7667 def : Pat<(v4f32 (bitconvert (v2i64 FPR128:$src))),
7668                              (v4f32 (REV64v4i32 FPR128:$src))>;
7669 def : Pat<(v4f32 (bitconvert (v2f64 FPR128:$src))),
7670                              (v4f32 (REV64v4i32 FPR128:$src))>;
7672 def : Pat<(v4f32 (bitconvert (v4i32 FPR128:$src))), (v4f32 FPR128:$src)>;
7674 let Predicates = [IsLE] in {
7675 def : Pat<(v2i64 (bitconvert (f128  FPR128:$src))), (v2i64 FPR128:$src)>;
7676 def : Pat<(v2i64 (bitconvert (v4i32 FPR128:$src))), (v2i64 FPR128:$src)>;
7677 def : Pat<(v2i64 (bitconvert (v8i16 FPR128:$src))), (v2i64 FPR128:$src)>;
7678 def : Pat<(v2i64 (bitconvert (v16i8 FPR128:$src))), (v2i64 FPR128:$src)>;
7679 def : Pat<(v2i64 (bitconvert (v4f32 FPR128:$src))), (v2i64 FPR128:$src)>;
7680 def : Pat<(v2i64 (bitconvert (v8f16 FPR128:$src))), (v2i64 FPR128:$src)>;
7681 def : Pat<(v2i64 (bitconvert (v8bf16 FPR128:$src))), (v2i64 FPR128:$src)>;
7683 let Predicates = [IsBE] in {
7684 def : Pat<(v2i64 (bitconvert (f128  FPR128:$src))),
7685                              (v2i64 (EXTv16i8 FPR128:$src,
7686                                               FPR128:$src, (i32 8)))>;
7687 def : Pat<(v2i64 (bitconvert (v4i32 FPR128:$src))),
7688                              (v2i64 (REV64v4i32 FPR128:$src))>;
7689 def : Pat<(v2i64 (bitconvert (v8i16 FPR128:$src))),
7690                              (v2i64 (REV64v8i16 FPR128:$src))>;
7691 def : Pat<(v2i64 (bitconvert (v16i8 FPR128:$src))),
7692                              (v2i64 (REV64v16i8 FPR128:$src))>;
7693 def : Pat<(v2i64 (bitconvert (v4f32 FPR128:$src))),
7694                              (v2i64 (REV64v4i32 FPR128:$src))>;
7695 def : Pat<(v2i64 (bitconvert (v8f16 FPR128:$src))),
7696                              (v2i64 (REV64v8i16 FPR128:$src))>;
7697 def : Pat<(v2i64 (bitconvert (v8bf16 FPR128:$src))),
7698                              (v2i64 (REV64v8i16 FPR128:$src))>;
7700 def : Pat<(v2i64 (bitconvert (v2f64 FPR128:$src))), (v2i64 FPR128:$src)>;
7702 let Predicates = [IsLE] in {
7703 def : Pat<(v4i32 (bitconvert (f128  FPR128:$src))), (v4i32 FPR128:$src)>;
7704 def : Pat<(v4i32 (bitconvert (v2i64 FPR128:$src))), (v4i32 FPR128:$src)>;
7705 def : Pat<(v4i32 (bitconvert (v8i16 FPR128:$src))), (v4i32 FPR128:$src)>;
7706 def : Pat<(v4i32 (bitconvert (v16i8 FPR128:$src))), (v4i32 FPR128:$src)>;
7707 def : Pat<(v4i32 (bitconvert (v2f64 FPR128:$src))), (v4i32 FPR128:$src)>;
7708 def : Pat<(v4i32 (bitconvert (v8f16 FPR128:$src))), (v4i32 FPR128:$src)>;
7709 def : Pat<(v4i32 (bitconvert (v8bf16 FPR128:$src))), (v4i32 FPR128:$src)>;
7711 let Predicates = [IsBE] in {
7712 def : Pat<(v4i32 (bitconvert (f128  FPR128:$src))),
7713                              (v4i32 (EXTv16i8 (REV64v4i32 FPR128:$src),
7714                                               (REV64v4i32 FPR128:$src),
7715                                               (i32 8)))>;
7716 def : Pat<(v4i32 (bitconvert (v2i64 FPR128:$src))),
7717                              (v4i32 (REV64v4i32 FPR128:$src))>;
7718 def : Pat<(v4i32 (bitconvert (v8i16 FPR128:$src))),
7719                              (v4i32 (REV32v8i16 FPR128:$src))>;
7720 def : Pat<(v4i32 (bitconvert (v16i8 FPR128:$src))),
7721                              (v4i32 (REV32v16i8 FPR128:$src))>;
7722 def : Pat<(v4i32 (bitconvert (v2f64 FPR128:$src))),
7723                              (v4i32 (REV64v4i32 FPR128:$src))>;
7724 def : Pat<(v4i32 (bitconvert (v8f16 FPR128:$src))),
7725                              (v4i32 (REV32v8i16 FPR128:$src))>;
7726 def : Pat<(v4i32 (bitconvert (v8bf16 FPR128:$src))),
7727                              (v4i32 (REV32v8i16 FPR128:$src))>;
7729 def : Pat<(v4i32 (bitconvert (v4f32 FPR128:$src))), (v4i32 FPR128:$src)>;
7731 let Predicates = [IsLE] in {
7732 def : Pat<(v8i16 (bitconvert (f128  FPR128:$src))), (v8i16 FPR128:$src)>;
7733 def : Pat<(v8i16 (bitconvert (v2i64 FPR128:$src))), (v8i16 FPR128:$src)>;
7734 def : Pat<(v8i16 (bitconvert (v4i32 FPR128:$src))), (v8i16 FPR128:$src)>;
7735 def : Pat<(v8i16 (bitconvert (v16i8 FPR128:$src))), (v8i16 FPR128:$src)>;
7736 def : Pat<(v8i16 (bitconvert (v2f64 FPR128:$src))), (v8i16 FPR128:$src)>;
7737 def : Pat<(v8i16 (bitconvert (v4f32 FPR128:$src))), (v8i16 FPR128:$src)>;
7739 let Predicates = [IsBE] in {
7740 def : Pat<(v8i16 (bitconvert (f128  FPR128:$src))),
7741                              (v8i16 (EXTv16i8 (REV64v8i16 FPR128:$src),
7742                                               (REV64v8i16 FPR128:$src),
7743                                               (i32 8)))>;
7744 def : Pat<(v8i16 (bitconvert (v2i64 FPR128:$src))),
7745                              (v8i16 (REV64v8i16 FPR128:$src))>;
7746 def : Pat<(v8i16 (bitconvert (v4i32 FPR128:$src))),
7747                              (v8i16 (REV32v8i16 FPR128:$src))>;
7748 def : Pat<(v8i16 (bitconvert (v16i8 FPR128:$src))),
7749                              (v8i16 (REV16v16i8 FPR128:$src))>;
7750 def : Pat<(v8i16 (bitconvert (v2f64 FPR128:$src))),
7751                              (v8i16 (REV64v8i16 FPR128:$src))>;
7752 def : Pat<(v8i16 (bitconvert (v4f32 FPR128:$src))),
7753                              (v8i16 (REV32v8i16 FPR128:$src))>;
7755 def : Pat<(v8i16 (bitconvert (v8f16 FPR128:$src))), (v8i16 FPR128:$src)>;
7756 def : Pat<(v8i16 (bitconvert (v8bf16 FPR128:$src))), (v8i16 FPR128:$src)>;
7758 let Predicates = [IsLE] in {
7759 def : Pat<(v8f16 (bitconvert (f128  FPR128:$src))), (v8f16 FPR128:$src)>;
7760 def : Pat<(v8f16 (bitconvert (v2i64 FPR128:$src))), (v8f16 FPR128:$src)>;
7761 def : Pat<(v8f16 (bitconvert (v4i32 FPR128:$src))), (v8f16 FPR128:$src)>;
7762 def : Pat<(v8f16 (bitconvert (v16i8 FPR128:$src))), (v8f16 FPR128:$src)>;
7763 def : Pat<(v8f16 (bitconvert (v2f64 FPR128:$src))), (v8f16 FPR128:$src)>;
7764 def : Pat<(v8f16 (bitconvert (v4f32 FPR128:$src))), (v8f16 FPR128:$src)>;
7766 def : Pat<(v8bf16 (bitconvert (f128  FPR128:$src))), (v8bf16 FPR128:$src)>;
7767 def : Pat<(v8bf16 (bitconvert (v2i64 FPR128:$src))), (v8bf16 FPR128:$src)>;
7768 def : Pat<(v8bf16 (bitconvert (v4i32 FPR128:$src))), (v8bf16 FPR128:$src)>;
7769 def : Pat<(v8bf16 (bitconvert (v16i8 FPR128:$src))), (v8bf16 FPR128:$src)>;
7770 def : Pat<(v8bf16 (bitconvert (v2f64 FPR128:$src))), (v8bf16 FPR128:$src)>;
7771 def : Pat<(v8bf16 (bitconvert (v4f32 FPR128:$src))), (v8bf16 FPR128:$src)>;
7773 let Predicates = [IsBE] in {
7774 def : Pat<(v8f16 (bitconvert (f128  FPR128:$src))),
7775                              (v8f16 (EXTv16i8 (REV64v8i16 FPR128:$src),
7776                                               (REV64v8i16 FPR128:$src),
7777                                               (i32 8)))>;
7778 def : Pat<(v8f16 (bitconvert (v2i64 FPR128:$src))),
7779                              (v8f16 (REV64v8i16 FPR128:$src))>;
7780 def : Pat<(v8f16 (bitconvert (v4i32 FPR128:$src))),
7781                              (v8f16 (REV32v8i16 FPR128:$src))>;
7782 def : Pat<(v8f16 (bitconvert (v16i8 FPR128:$src))),
7783                              (v8f16 (REV16v16i8 FPR128:$src))>;
7784 def : Pat<(v8f16 (bitconvert (v2f64 FPR128:$src))),
7785                              (v8f16 (REV64v8i16 FPR128:$src))>;
7786 def : Pat<(v8f16 (bitconvert (v4f32 FPR128:$src))),
7787                              (v8f16 (REV32v8i16 FPR128:$src))>;
7789 def : Pat<(v8bf16 (bitconvert (f128  FPR128:$src))),
7790                              (v8bf16 (EXTv16i8 (REV64v8i16 FPR128:$src),
7791                                               (REV64v8i16 FPR128:$src),
7792                                               (i32 8)))>;
7793 def : Pat<(v8bf16 (bitconvert (v2i64 FPR128:$src))),
7794                              (v8bf16 (REV64v8i16 FPR128:$src))>;
7795 def : Pat<(v8bf16 (bitconvert (v4i32 FPR128:$src))),
7796                              (v8bf16 (REV32v8i16 FPR128:$src))>;
7797 def : Pat<(v8bf16 (bitconvert (v16i8 FPR128:$src))),
7798                              (v8bf16 (REV16v16i8 FPR128:$src))>;
7799 def : Pat<(v8bf16 (bitconvert (v2f64 FPR128:$src))),
7800                              (v8bf16 (REV64v8i16 FPR128:$src))>;
7801 def : Pat<(v8bf16 (bitconvert (v4f32 FPR128:$src))),
7802                              (v8bf16 (REV32v8i16 FPR128:$src))>;
7804 def : Pat<(v8f16 (bitconvert (v8i16 FPR128:$src))), (v8f16 FPR128:$src)>;
7805 def : Pat<(v8bf16 (bitconvert (v8i16 FPR128:$src))), (v8bf16 FPR128:$src)>;
7807 let Predicates = [IsLE] in {
7808 def : Pat<(v16i8 (bitconvert (f128  FPR128:$src))), (v16i8 FPR128:$src)>;
7809 def : Pat<(v16i8 (bitconvert (v2i64 FPR128:$src))), (v16i8 FPR128:$src)>;
7810 def : Pat<(v16i8 (bitconvert (v4i32 FPR128:$src))), (v16i8 FPR128:$src)>;
7811 def : Pat<(v16i8 (bitconvert (v8i16 FPR128:$src))), (v16i8 FPR128:$src)>;
7812 def : Pat<(v16i8 (bitconvert (v2f64 FPR128:$src))), (v16i8 FPR128:$src)>;
7813 def : Pat<(v16i8 (bitconvert (v4f32 FPR128:$src))), (v16i8 FPR128:$src)>;
7814 def : Pat<(v16i8 (bitconvert (v8f16 FPR128:$src))), (v16i8 FPR128:$src)>;
7815 def : Pat<(v16i8 (bitconvert (v8bf16 FPR128:$src))), (v16i8 FPR128:$src)>;
7817 let Predicates = [IsBE] in {
7818 def : Pat<(v16i8 (bitconvert (f128  FPR128:$src))),
7819                              (v16i8 (EXTv16i8 (REV64v16i8 FPR128:$src),
7820                                               (REV64v16i8 FPR128:$src),
7821                                               (i32 8)))>;
7822 def : Pat<(v16i8 (bitconvert (v2i64 FPR128:$src))),
7823                              (v16i8 (REV64v16i8 FPR128:$src))>;
7824 def : Pat<(v16i8 (bitconvert (v4i32 FPR128:$src))),
7825                              (v16i8 (REV32v16i8 FPR128:$src))>;
7826 def : Pat<(v16i8 (bitconvert (v8i16 FPR128:$src))),
7827                              (v16i8 (REV16v16i8 FPR128:$src))>;
7828 def : Pat<(v16i8 (bitconvert (v2f64 FPR128:$src))),
7829                              (v16i8 (REV64v16i8 FPR128:$src))>;
7830 def : Pat<(v16i8 (bitconvert (v4f32 FPR128:$src))),
7831                              (v16i8 (REV32v16i8 FPR128:$src))>;
7832 def : Pat<(v16i8 (bitconvert (v8f16 FPR128:$src))),
7833                              (v16i8 (REV16v16i8 FPR128:$src))>;
7834 def : Pat<(v16i8 (bitconvert (v8bf16 FPR128:$src))),
7835                              (v16i8 (REV16v16i8 FPR128:$src))>;
7838 def : Pat<(v4i16 (extract_subvector V128:$Rn, (i64 0))),
7839            (EXTRACT_SUBREG V128:$Rn, dsub)>;
7840 def : Pat<(v8i8 (extract_subvector V128:$Rn, (i64 0))),
7841            (EXTRACT_SUBREG V128:$Rn, dsub)>;
7842 def : Pat<(v2f32 (extract_subvector V128:$Rn, (i64 0))),
7843            (EXTRACT_SUBREG V128:$Rn, dsub)>;
7844 def : Pat<(v4f16 (extract_subvector V128:$Rn, (i64 0))),
7845            (EXTRACT_SUBREG V128:$Rn, dsub)>;
7846 def : Pat<(v4bf16 (extract_subvector V128:$Rn, (i64 0))),
7847            (EXTRACT_SUBREG V128:$Rn, dsub)>;
7848 def : Pat<(v2i32 (extract_subvector V128:$Rn, (i64 0))),
7849            (EXTRACT_SUBREG V128:$Rn, dsub)>;
7850 def : Pat<(v1i64 (extract_subvector V128:$Rn, (i64 0))),
7851            (EXTRACT_SUBREG V128:$Rn, dsub)>;
7852 def : Pat<(v1f64 (extract_subvector V128:$Rn, (i64 0))),
7853            (EXTRACT_SUBREG V128:$Rn, dsub)>;
7855 def : Pat<(v8i8 (extract_subvector (v16i8 FPR128:$Rn), (i64 1))),
7856           (EXTRACT_SUBREG (DUPv2i64lane FPR128:$Rn, 1), dsub)>;
7857 def : Pat<(v4i16 (extract_subvector (v8i16 FPR128:$Rn), (i64 1))),
7858           (EXTRACT_SUBREG (DUPv2i64lane FPR128:$Rn, 1), dsub)>;
7859 def : Pat<(v2i32 (extract_subvector (v4i32 FPR128:$Rn), (i64 1))),
7860           (EXTRACT_SUBREG (DUPv2i64lane FPR128:$Rn, 1), dsub)>;
7861 def : Pat<(v1i64 (extract_subvector (v2i64 FPR128:$Rn), (i64 1))),
7862           (EXTRACT_SUBREG (DUPv2i64lane FPR128:$Rn, 1), dsub)>;
7864 // A 64-bit subvector insert to the first 128-bit vector position
7865 // is a subregister copy that needs no instruction.
7866 multiclass InsertSubvectorUndef<ValueType Ty> {
7867   def : Pat<(insert_subvector undef, (v1i64 FPR64:$src), (Ty 0)),
7868             (INSERT_SUBREG (v2i64 (IMPLICIT_DEF)), FPR64:$src, dsub)>;
7869   def : Pat<(insert_subvector undef, (v1f64 FPR64:$src), (Ty 0)),
7870             (INSERT_SUBREG (v2f64 (IMPLICIT_DEF)), FPR64:$src, dsub)>;
7871   def : Pat<(insert_subvector undef, (v2i32 FPR64:$src), (Ty 0)),
7872             (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), FPR64:$src, dsub)>;
7873   def : Pat<(insert_subvector undef, (v2f32 FPR64:$src), (Ty 0)),
7874             (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), FPR64:$src, dsub)>;
7875   def : Pat<(insert_subvector undef, (v4i16 FPR64:$src), (Ty 0)),
7876             (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)), FPR64:$src, dsub)>;
7877   def : Pat<(insert_subvector undef, (v4f16 FPR64:$src), (Ty 0)),
7878             (INSERT_SUBREG (v8f16 (IMPLICIT_DEF)), FPR64:$src, dsub)>;
7879   def : Pat<(insert_subvector undef, (v4bf16 FPR64:$src), (Ty 0)),
7880             (INSERT_SUBREG (v8bf16 (IMPLICIT_DEF)), FPR64:$src, dsub)>;
7881   def : Pat<(insert_subvector undef, (v8i8 FPR64:$src), (Ty 0)),
7882             (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)), FPR64:$src, dsub)>;
7885 defm : InsertSubvectorUndef<i32>;
7886 defm : InsertSubvectorUndef<i64>;
7888 // Use pair-wise add instructions when summing up the lanes for v2f64, v2i64
7889 // or v2f32.
7890 def : Pat<(i64 (add (vector_extract (v2i64 FPR128:$Rn), (i64 0)),
7891                     (vector_extract (v2i64 FPR128:$Rn), (i64 1)))),
7892            (i64 (ADDPv2i64p (v2i64 FPR128:$Rn)))>;
7893 def : Pat<(f64 (fadd (vector_extract (v2f64 FPR128:$Rn), (i64 0)),
7894                      (vector_extract (v2f64 FPR128:$Rn), (i64 1)))),
7895            (f64 (FADDPv2i64p (v2f64 FPR128:$Rn)))>;
7896     // vector_extract on 64-bit vectors gets promoted to a 128 bit vector,
7897     // so we match on v4f32 here, not v2f32. This will also catch adding
7898     // the low two lanes of a true v4f32 vector.
7899 def : Pat<(fadd (vector_extract (v4f32 FPR128:$Rn), (i64 0)),
7900                 (vector_extract (v4f32 FPR128:$Rn), (i64 1))),
7901           (f32 (FADDPv2i32p (EXTRACT_SUBREG FPR128:$Rn, dsub)))>;
7902 def : Pat<(fadd (vector_extract (v8f16 FPR128:$Rn), (i64 0)),
7903                 (vector_extract (v8f16 FPR128:$Rn), (i64 1))),
7904           (f16 (FADDPv2i16p (EXTRACT_SUBREG FPR128:$Rn, dsub)))>;
7906 // Scalar 64-bit shifts in FPR64 registers.
7907 def : Pat<(i64 (int_aarch64_neon_sshl (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
7908           (SSHLv1i64 FPR64:$Rn, FPR64:$Rm)>;
7909 def : Pat<(i64 (int_aarch64_neon_ushl (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
7910           (USHLv1i64 FPR64:$Rn, FPR64:$Rm)>;
7911 def : Pat<(i64 (int_aarch64_neon_srshl (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
7912           (SRSHLv1i64 FPR64:$Rn, FPR64:$Rm)>;
7913 def : Pat<(i64 (int_aarch64_neon_urshl (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
7914           (URSHLv1i64 FPR64:$Rn, FPR64:$Rm)>;
7916 // Patterns for nontemporal/no-allocate stores.
7917 // We have to resort to tricks to turn a single-input store into a store pair,
7918 // because there is no single-input nontemporal store, only STNP.
7919 let Predicates = [IsLE] in {
7920 let AddedComplexity = 15 in {
7921 class NTStore128Pat<ValueType VT> :
7922   Pat<(nontemporalstore (VT FPR128:$Rt),
7923         (am_indexed7s64 GPR64sp:$Rn, simm7s8:$offset)),
7924       (STNPDi (EXTRACT_SUBREG FPR128:$Rt, dsub),
7925               (CPYi64 FPR128:$Rt, (i64 1)),
7926               GPR64sp:$Rn, simm7s8:$offset)>;
7928 def : NTStore128Pat<v2i64>;
7929 def : NTStore128Pat<v4i32>;
7930 def : NTStore128Pat<v8i16>;
7931 def : NTStore128Pat<v16i8>;
7933 class NTStore64Pat<ValueType VT> :
7934   Pat<(nontemporalstore (VT FPR64:$Rt),
7935         (am_indexed7s32 GPR64sp:$Rn, simm7s4:$offset)),
7936       (STNPSi (EXTRACT_SUBREG FPR64:$Rt, ssub),
7937               (CPYi32 (SUBREG_TO_REG (i64 0), FPR64:$Rt, dsub), (i64 1)),
7938               GPR64sp:$Rn, simm7s4:$offset)>;
7940 // FIXME: Shouldn't v1f64 loads/stores be promoted to v1i64?
7941 def : NTStore64Pat<v1f64>;
7942 def : NTStore64Pat<v1i64>;
7943 def : NTStore64Pat<v2i32>;
7944 def : NTStore64Pat<v4i16>;
7945 def : NTStore64Pat<v8i8>;
7947 def : Pat<(nontemporalstore GPR64:$Rt,
7948             (am_indexed7s32 GPR64sp:$Rn, simm7s4:$offset)),
7949           (STNPWi (EXTRACT_SUBREG GPR64:$Rt, sub_32),
7950                   (EXTRACT_SUBREG (UBFMXri GPR64:$Rt, 32, 63), sub_32),
7951                   GPR64sp:$Rn, simm7s4:$offset)>;
7952 } // AddedComplexity=10
7953 } // Predicates = [IsLE]
7955 // Tail call return handling. These are all compiler pseudo-instructions,
7956 // so no encoding information or anything like that.
7957 let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [SP] in {
7958   def TCRETURNdi : Pseudo<(outs), (ins i64imm:$dst, i32imm:$FPDiff), []>,
7959                    Sched<[WriteBrReg]>;
7960   def TCRETURNri : Pseudo<(outs), (ins tcGPR64:$dst, i32imm:$FPDiff), []>,
7961                    Sched<[WriteBrReg]>;
7962   // Indirect tail-call with any register allowed, used by MachineOutliner when
7963   // this is proven safe.
7964   // FIXME: If we have to add any more hacks like this, we should instead relax
7965   // some verifier checks for outlined functions.
7966   def TCRETURNriALL : Pseudo<(outs), (ins GPR64:$dst, i32imm:$FPDiff), []>,
7967                       Sched<[WriteBrReg]>;
7968   // Indirect tail-call limited to only use registers (x16 and x17) which are
7969   // allowed to tail-call a "BTI c" instruction.
7970   def TCRETURNriBTI : Pseudo<(outs), (ins rtcGPR64:$dst, i32imm:$FPDiff), []>,
7971                       Sched<[WriteBrReg]>;
7974 def : Pat<(AArch64tcret tcGPR64:$dst, (i32 timm:$FPDiff)),
7975           (TCRETURNri tcGPR64:$dst, imm:$FPDiff)>,
7976       Requires<[NotUseBTI]>;
7977 def : Pat<(AArch64tcret rtcGPR64:$dst, (i32 timm:$FPDiff)),
7978           (TCRETURNriBTI rtcGPR64:$dst, imm:$FPDiff)>,
7979       Requires<[UseBTI]>;
7980 def : Pat<(AArch64tcret tglobaladdr:$dst, (i32 timm:$FPDiff)),
7981           (TCRETURNdi texternalsym:$dst, imm:$FPDiff)>;
7982 def : Pat<(AArch64tcret texternalsym:$dst, (i32 timm:$FPDiff)),
7983           (TCRETURNdi texternalsym:$dst, imm:$FPDiff)>;
7985 def MOVMCSym : Pseudo<(outs GPR64:$dst), (ins i64imm:$sym), []>, Sched<[]>;
7986 def : Pat<(i64 (AArch64LocalRecover mcsym:$sym)), (MOVMCSym mcsym:$sym)>;
7988 // Extracting lane zero is a special case where we can just use a plain
7989 // EXTRACT_SUBREG instruction, which will become FMOV. This is easier for the
7990 // rest of the compiler, especially the register allocator and copy propagation,
7991 // to reason about, so is preferred when it's possible to use it.
7992 let AddedComplexity = 10 in {
7993   def : Pat<(i64 (extractelt (v2i64 V128:$V), (i64 0))), (EXTRACT_SUBREG V128:$V, dsub)>;
7994   def : Pat<(i32 (extractelt (v4i32 V128:$V), (i64 0))), (EXTRACT_SUBREG V128:$V, ssub)>;
7995   def : Pat<(i32 (extractelt (v2i32 V64:$V), (i64 0))), (EXTRACT_SUBREG V64:$V, ssub)>;
7998 // dot_v4i8
7999 class mul_v4i8<SDPatternOperator ldop> :
8000   PatFrag<(ops node:$Rn, node:$Rm, node:$offset),
8001           (mul (ldop (add node:$Rn, node:$offset)),
8002                (ldop (add node:$Rm, node:$offset)))>;
8003 class mulz_v4i8<SDPatternOperator ldop> :
8004   PatFrag<(ops node:$Rn, node:$Rm),
8005           (mul (ldop node:$Rn), (ldop node:$Rm))>;
8007 def load_v4i8 :
8008   OutPatFrag<(ops node:$R),
8009              (INSERT_SUBREG
8010               (v2i32 (IMPLICIT_DEF)),
8011                (i32 (COPY_TO_REGCLASS (LDRWui node:$R, (i64 0)), FPR32)),
8012               ssub)>;
8014 class dot_v4i8<Instruction DOT, SDPatternOperator ldop> :
8015   Pat<(i32 (add (mul_v4i8<ldop> GPR64sp:$Rn, GPR64sp:$Rm, (i64 3)),
8016            (add (mul_v4i8<ldop> GPR64sp:$Rn, GPR64sp:$Rm, (i64 2)),
8017            (add (mul_v4i8<ldop> GPR64sp:$Rn, GPR64sp:$Rm, (i64 1)),
8018                 (mulz_v4i8<ldop> GPR64sp:$Rn, GPR64sp:$Rm))))),
8019       (EXTRACT_SUBREG (i64 (DOT (DUPv2i32gpr WZR),
8020                                 (load_v4i8 GPR64sp:$Rn),
8021                                 (load_v4i8 GPR64sp:$Rm))),
8022                       sub_32)>, Requires<[HasDotProd]>;
8024 // dot_v8i8
8025 class ee_v8i8<SDPatternOperator extend> :
8026   PatFrag<(ops node:$V, node:$K),
8027           (v4i16 (extract_subvector (v8i16 (extend node:$V)), node:$K))>;
8029 class mul_v8i8<SDPatternOperator mulop, SDPatternOperator extend> :
8030   PatFrag<(ops node:$M, node:$N, node:$K),
8031           (mulop (v4i16 (ee_v8i8<extend> node:$M, node:$K)),
8032                  (v4i16 (ee_v8i8<extend> node:$N, node:$K)))>;
8034 class idot_v8i8<SDPatternOperator mulop, SDPatternOperator extend> :
8035   PatFrag<(ops node:$M, node:$N),
8036           (i32 (extractelt
8037            (v4i32 (AArch64uaddv
8038             (add (mul_v8i8<mulop, extend> node:$M, node:$N, (i64 0)),
8039                  (mul_v8i8<mulop, extend> node:$M, node:$N, (i64 4))))),
8040            (i64 0)))>;
8042 // vaddv_[su]32 is special; -> ADDP Vd.2S,Vn.2S,Vm.2S; return Vd.s[0];Vn==Vm
8043 def VADDV_32 : OutPatFrag<(ops node:$R), (ADDPv2i32 node:$R, node:$R)>;
8045 class odot_v8i8<Instruction DOT> :
8046   OutPatFrag<(ops node:$Vm, node:$Vn),
8047              (EXTRACT_SUBREG
8048               (VADDV_32
8049                (i64 (DOT (DUPv2i32gpr WZR),
8050                          (v8i8 node:$Vm),
8051                          (v8i8 node:$Vn)))),
8052               sub_32)>;
8054 class dot_v8i8<Instruction DOT, SDPatternOperator mulop,
8055                     SDPatternOperator extend> :
8056   Pat<(idot_v8i8<mulop, extend> V64:$Vm, V64:$Vn),
8057       (odot_v8i8<DOT> V64:$Vm, V64:$Vn)>,
8058   Requires<[HasDotProd]>;
8060 // dot_v16i8
8061 class ee_v16i8<SDPatternOperator extend> :
8062   PatFrag<(ops node:$V, node:$K1, node:$K2),
8063           (v4i16 (extract_subvector
8064            (v8i16 (extend
8065             (v8i8 (extract_subvector node:$V, node:$K1)))), node:$K2))>;
8067 class mul_v16i8<SDPatternOperator mulop, SDPatternOperator extend> :
8068   PatFrag<(ops node:$M, node:$N, node:$K1, node:$K2),
8069           (v4i32
8070            (mulop (v4i16 (ee_v16i8<extend> node:$M, node:$K1, node:$K2)),
8071                   (v4i16 (ee_v16i8<extend> node:$N, node:$K1, node:$K2))))>;
8073 class idot_v16i8<SDPatternOperator m, SDPatternOperator x> :
8074   PatFrag<(ops node:$M, node:$N),
8075           (i32 (extractelt
8076            (v4i32 (AArch64uaddv
8077             (add
8078              (add (mul_v16i8<m, x> node:$M, node:$N, (i64 0), (i64 0)),
8079                   (mul_v16i8<m, x> node:$M, node:$N, (i64 8), (i64 0))),
8080              (add (mul_v16i8<m, x> node:$M, node:$N, (i64 0), (i64 4)),
8081                   (mul_v16i8<m, x> node:$M, node:$N, (i64 8), (i64 4)))))),
8082            (i64 0)))>;
8084 class odot_v16i8<Instruction DOT> :
8085   OutPatFrag<(ops node:$Vm, node:$Vn),
8086              (i32 (ADDVv4i32v
8087               (DOT (DUPv4i32gpr WZR), node:$Vm, node:$Vn)))>;
8089 class dot_v16i8<Instruction DOT, SDPatternOperator mulop,
8090                 SDPatternOperator extend> :
8091   Pat<(idot_v16i8<mulop, extend> V128:$Vm, V128:$Vn),
8092       (odot_v16i8<DOT> V128:$Vm, V128:$Vn)>,
8093   Requires<[HasDotProd]>;
8095 let AddedComplexity = 10 in {
8096   def : dot_v4i8<SDOTv8i8, sextloadi8>;
8097   def : dot_v4i8<UDOTv8i8, zextloadi8>;
8098   def : dot_v8i8<SDOTv8i8, AArch64smull, sext>;
8099   def : dot_v8i8<UDOTv8i8, AArch64umull, zext>;
8100   def : dot_v16i8<SDOTv16i8, AArch64smull, sext>;
8101   def : dot_v16i8<UDOTv16i8, AArch64umull, zext>;
8103   // FIXME: add patterns to generate vector by element dot product.
8104   // FIXME: add SVE dot-product patterns.
8107 // Custom DAG nodes and isel rules to make a 64-byte block out of eight GPRs,
8108 // so that it can be used as input to inline asm, and vice versa.
8109 def LS64_BUILD : SDNode<"AArch64ISD::LS64_BUILD", SDTypeProfile<1, 8, []>>;
8110 def LS64_EXTRACT : SDNode<"AArch64ISD::LS64_EXTRACT", SDTypeProfile<1, 2, []>>;
8111 def : Pat<(i64x8 (LS64_BUILD GPR64:$x0, GPR64:$x1, GPR64:$x2, GPR64:$x3,
8112                              GPR64:$x4, GPR64:$x5, GPR64:$x6, GPR64:$x7)),
8113           (REG_SEQUENCE GPR64x8Class,
8114               $x0, x8sub_0, $x1, x8sub_1, $x2, x8sub_2, $x3, x8sub_3,
8115               $x4, x8sub_4, $x5, x8sub_5, $x6, x8sub_6, $x7, x8sub_7)>;
8116 foreach i = 0-7 in {
8117   def : Pat<(i64 (LS64_EXTRACT (i64x8 GPR64x8:$val), (i32 i))),
8118             (EXTRACT_SUBREG $val, !cast<SubRegIndex>("x8sub_"#i))>;
8121 let Predicates = [HasLS64] in {
8122   def LD64B: LoadStore64B<0b101, "ld64b", (ins GPR64sp:$Rn),
8123                                           (outs GPR64x8:$Rt)>;
8124   def ST64B: LoadStore64B<0b001, "st64b", (ins GPR64x8:$Rt, GPR64sp:$Rn),
8125                                           (outs)>;
8126   def ST64BV:   Store64BV<0b011, "st64bv">;
8127   def ST64BV0:  Store64BV<0b010, "st64bv0">;
8129   class ST64BPattern<Intrinsic intrinsic, Instruction instruction>
8130     : Pat<(intrinsic GPR64sp:$addr, GPR64:$x0, GPR64:$x1, GPR64:$x2, GPR64:$x3, GPR64:$x4, GPR64:$x5, GPR64:$x6, GPR64:$x7),
8131           (instruction (REG_SEQUENCE GPR64x8Class, $x0, x8sub_0, $x1, x8sub_1, $x2, x8sub_2, $x3, x8sub_3, $x4, x8sub_4, $x5, x8sub_5, $x6, x8sub_6, $x7, x8sub_7), $addr)>;
8133   def : ST64BPattern<int_aarch64_st64b, ST64B>;
8134   def : ST64BPattern<int_aarch64_st64bv, ST64BV>;
8135   def : ST64BPattern<int_aarch64_st64bv0, ST64BV0>;
8138 let Defs = [X16, X17], mayStore = 1, isCodeGenOnly = 1 in
8139 def StoreSwiftAsyncContext
8140       : Pseudo<(outs), (ins GPR64:$ctx, GPR64sp:$base, simm9:$offset),
8141                []>, Sched<[]>;
8143 include "AArch64InstrAtomics.td"
8144 include "AArch64SVEInstrInfo.td"
8145 include "AArch64SMEInstrInfo.td"
8146 include "AArch64InstrGISel.td"