clang 24.0.0git
ARM.cpp
Go to the documentation of this file.
1//===---------- ARM.cpp - Emit LLVM Code for builtins ---------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This contains code to emit Builtin calls as LLVM code.
10//
11//===----------------------------------------------------------------------===//
12
13#include "ABIInfo.h"
14#include "CGBuiltin.h"
15#include "CGDebugInfo.h"
16#include "TargetInfo.h"
19#include "llvm/IR/InlineAsm.h"
20#include "llvm/IR/IntrinsicsAArch64.h"
21#include "llvm/IR/IntrinsicsARM.h"
22#include "llvm/IR/IntrinsicsBPF.h"
23#include "llvm/TargetParser/AArch64TargetParser.h"
24
25#include <numeric>
26
27using namespace clang;
28using namespace CodeGen;
29using namespace llvm;
30using namespace clang::aarch64;
31
32static std::optional<CodeGenFunction::MSVCIntrin>
33translateAarch64ToMsvcIntrin(unsigned BuiltinID) {
34 using MSVCIntrin = CodeGenFunction::MSVCIntrin;
35 switch (BuiltinID) {
36 default:
37 return std::nullopt;
38 case clang::AArch64::BI_BitScanForward:
39 case clang::AArch64::BI_BitScanForward64:
40 return MSVCIntrin::_BitScanForward;
41 case clang::AArch64::BI_BitScanReverse:
42 case clang::AArch64::BI_BitScanReverse64:
43 return MSVCIntrin::_BitScanReverse;
44 case clang::AArch64::BI_InterlockedAnd64:
45 return MSVCIntrin::_InterlockedAnd;
46 case clang::AArch64::BI_InterlockedExchange64:
47 return MSVCIntrin::_InterlockedExchange;
48 case clang::AArch64::BI_InterlockedExchangeAdd64:
49 return MSVCIntrin::_InterlockedExchangeAdd;
50 case clang::AArch64::BI_InterlockedExchangeSub64:
51 return MSVCIntrin::_InterlockedExchangeSub;
52 case clang::AArch64::BI_InterlockedOr64:
53 return MSVCIntrin::_InterlockedOr;
54 case clang::AArch64::BI_InterlockedXor64:
55 return MSVCIntrin::_InterlockedXor;
56 case clang::AArch64::BI_InterlockedDecrement64:
57 return MSVCIntrin::_InterlockedDecrement;
58 case clang::AArch64::BI_InterlockedIncrement64:
59 return MSVCIntrin::_InterlockedIncrement;
60 case clang::AArch64::BI_InterlockedExchangeAdd8_acq:
61 case clang::AArch64::BI_InterlockedExchangeAdd16_acq:
62 case clang::AArch64::BI_InterlockedExchangeAdd_acq:
63 case clang::AArch64::BI_InterlockedExchangeAdd64_acq:
64 return MSVCIntrin::_InterlockedExchangeAdd_acq;
65 case clang::AArch64::BI_InterlockedExchangeAdd8_rel:
66 case clang::AArch64::BI_InterlockedExchangeAdd16_rel:
67 case clang::AArch64::BI_InterlockedExchangeAdd_rel:
68 case clang::AArch64::BI_InterlockedExchangeAdd64_rel:
69 return MSVCIntrin::_InterlockedExchangeAdd_rel;
70 case clang::AArch64::BI_InterlockedExchangeAdd8_nf:
71 case clang::AArch64::BI_InterlockedExchangeAdd16_nf:
72 case clang::AArch64::BI_InterlockedExchangeAdd_nf:
73 case clang::AArch64::BI_InterlockedExchangeAdd64_nf:
74 return MSVCIntrin::_InterlockedExchangeAdd_nf;
75 case clang::AArch64::BI_InterlockedExchange8_acq:
76 case clang::AArch64::BI_InterlockedExchange16_acq:
77 case clang::AArch64::BI_InterlockedExchange_acq:
78 case clang::AArch64::BI_InterlockedExchange64_acq:
79 case clang::AArch64::BI_InterlockedExchangePointer_acq:
80 return MSVCIntrin::_InterlockedExchange_acq;
81 case clang::AArch64::BI_InterlockedExchange8_rel:
82 case clang::AArch64::BI_InterlockedExchange16_rel:
83 case clang::AArch64::BI_InterlockedExchange_rel:
84 case clang::AArch64::BI_InterlockedExchange64_rel:
85 case clang::AArch64::BI_InterlockedExchangePointer_rel:
86 return MSVCIntrin::_InterlockedExchange_rel;
87 case clang::AArch64::BI_InterlockedExchange8_nf:
88 case clang::AArch64::BI_InterlockedExchange16_nf:
89 case clang::AArch64::BI_InterlockedExchange_nf:
90 case clang::AArch64::BI_InterlockedExchange64_nf:
91 case clang::AArch64::BI_InterlockedExchangePointer_nf:
92 return MSVCIntrin::_InterlockedExchange_nf;
93 case clang::AArch64::BI_InterlockedCompareExchange8_acq:
94 case clang::AArch64::BI_InterlockedCompareExchange16_acq:
95 case clang::AArch64::BI_InterlockedCompareExchange_acq:
96 case clang::AArch64::BI_InterlockedCompareExchange64_acq:
97 case clang::AArch64::BI_InterlockedCompareExchangePointer_acq:
98 return MSVCIntrin::_InterlockedCompareExchange_acq;
99 case clang::AArch64::BI_InterlockedCompareExchange8_rel:
100 case clang::AArch64::BI_InterlockedCompareExchange16_rel:
101 case clang::AArch64::BI_InterlockedCompareExchange_rel:
102 case clang::AArch64::BI_InterlockedCompareExchange64_rel:
103 case clang::AArch64::BI_InterlockedCompareExchangePointer_rel:
104 return MSVCIntrin::_InterlockedCompareExchange_rel;
105 case clang::AArch64::BI_InterlockedCompareExchange8_nf:
106 case clang::AArch64::BI_InterlockedCompareExchange16_nf:
107 case clang::AArch64::BI_InterlockedCompareExchange_nf:
108 case clang::AArch64::BI_InterlockedCompareExchange64_nf:
109 return MSVCIntrin::_InterlockedCompareExchange_nf;
110 case clang::AArch64::BI_InterlockedCompareExchange128:
111 return MSVCIntrin::_InterlockedCompareExchange128;
112 case clang::AArch64::BI_InterlockedCompareExchange128_acq:
113 return MSVCIntrin::_InterlockedCompareExchange128_acq;
114 case clang::AArch64::BI_InterlockedCompareExchange128_nf:
115 return MSVCIntrin::_InterlockedCompareExchange128_nf;
116 case clang::AArch64::BI_InterlockedCompareExchange128_rel:
117 return MSVCIntrin::_InterlockedCompareExchange128_rel;
118 case clang::AArch64::BI_InterlockedOr8_acq:
119 case clang::AArch64::BI_InterlockedOr16_acq:
120 case clang::AArch64::BI_InterlockedOr_acq:
121 case clang::AArch64::BI_InterlockedOr64_acq:
122 return MSVCIntrin::_InterlockedOr_acq;
123 case clang::AArch64::BI_InterlockedOr8_rel:
124 case clang::AArch64::BI_InterlockedOr16_rel:
125 case clang::AArch64::BI_InterlockedOr_rel:
126 case clang::AArch64::BI_InterlockedOr64_rel:
127 return MSVCIntrin::_InterlockedOr_rel;
128 case clang::AArch64::BI_InterlockedOr8_nf:
129 case clang::AArch64::BI_InterlockedOr16_nf:
130 case clang::AArch64::BI_InterlockedOr_nf:
131 case clang::AArch64::BI_InterlockedOr64_nf:
132 return MSVCIntrin::_InterlockedOr_nf;
133 case clang::AArch64::BI_InterlockedXor8_acq:
134 case clang::AArch64::BI_InterlockedXor16_acq:
135 case clang::AArch64::BI_InterlockedXor_acq:
136 case clang::AArch64::BI_InterlockedXor64_acq:
137 return MSVCIntrin::_InterlockedXor_acq;
138 case clang::AArch64::BI_InterlockedXor8_rel:
139 case clang::AArch64::BI_InterlockedXor16_rel:
140 case clang::AArch64::BI_InterlockedXor_rel:
141 case clang::AArch64::BI_InterlockedXor64_rel:
142 return MSVCIntrin::_InterlockedXor_rel;
143 case clang::AArch64::BI_InterlockedXor8_nf:
144 case clang::AArch64::BI_InterlockedXor16_nf:
145 case clang::AArch64::BI_InterlockedXor_nf:
146 case clang::AArch64::BI_InterlockedXor64_nf:
147 return MSVCIntrin::_InterlockedXor_nf;
148 case clang::AArch64::BI_InterlockedAnd8_acq:
149 case clang::AArch64::BI_InterlockedAnd16_acq:
150 case clang::AArch64::BI_InterlockedAnd_acq:
151 case clang::AArch64::BI_InterlockedAnd64_acq:
152 return MSVCIntrin::_InterlockedAnd_acq;
153 case clang::AArch64::BI_InterlockedAnd8_rel:
154 case clang::AArch64::BI_InterlockedAnd16_rel:
155 case clang::AArch64::BI_InterlockedAnd_rel:
156 case clang::AArch64::BI_InterlockedAnd64_rel:
157 return MSVCIntrin::_InterlockedAnd_rel;
158 case clang::AArch64::BI_InterlockedAnd8_nf:
159 case clang::AArch64::BI_InterlockedAnd16_nf:
160 case clang::AArch64::BI_InterlockedAnd_nf:
161 case clang::AArch64::BI_InterlockedAnd64_nf:
162 return MSVCIntrin::_InterlockedAnd_nf;
163 case clang::AArch64::BI_InterlockedIncrement16_acq:
164 case clang::AArch64::BI_InterlockedIncrement_acq:
165 case clang::AArch64::BI_InterlockedIncrement64_acq:
166 return MSVCIntrin::_InterlockedIncrement_acq;
167 case clang::AArch64::BI_InterlockedIncrement16_rel:
168 case clang::AArch64::BI_InterlockedIncrement_rel:
169 case clang::AArch64::BI_InterlockedIncrement64_rel:
170 return MSVCIntrin::_InterlockedIncrement_rel;
171 case clang::AArch64::BI_InterlockedIncrement16_nf:
172 case clang::AArch64::BI_InterlockedIncrement_nf:
173 case clang::AArch64::BI_InterlockedIncrement64_nf:
174 return MSVCIntrin::_InterlockedIncrement_nf;
175 case clang::AArch64::BI_InterlockedDecrement16_acq:
176 case clang::AArch64::BI_InterlockedDecrement_acq:
177 case clang::AArch64::BI_InterlockedDecrement64_acq:
178 return MSVCIntrin::_InterlockedDecrement_acq;
179 case clang::AArch64::BI_InterlockedDecrement16_rel:
180 case clang::AArch64::BI_InterlockedDecrement_rel:
181 case clang::AArch64::BI_InterlockedDecrement64_rel:
182 return MSVCIntrin::_InterlockedDecrement_rel;
183 case clang::AArch64::BI_InterlockedDecrement16_nf:
184 case clang::AArch64::BI_InterlockedDecrement_nf:
185 case clang::AArch64::BI_InterlockedDecrement64_nf:
186 return MSVCIntrin::_InterlockedDecrement_nf;
187 }
188 llvm_unreachable("must return from switch");
189}
190
191static std::optional<CodeGenFunction::MSVCIntrin>
192translateArmToMsvcIntrin(unsigned BuiltinID) {
193 using MSVCIntrin = CodeGenFunction::MSVCIntrin;
194 switch (BuiltinID) {
195 default:
196 return std::nullopt;
197 case clang::ARM::BI_BitScanForward:
198 case clang::ARM::BI_BitScanForward64:
199 return MSVCIntrin::_BitScanForward;
200 case clang::ARM::BI_BitScanReverse:
201 case clang::ARM::BI_BitScanReverse64:
202 return MSVCIntrin::_BitScanReverse;
203 case clang::ARM::BI_InterlockedAnd64:
204 return MSVCIntrin::_InterlockedAnd;
205 case clang::ARM::BI_InterlockedExchange64:
206 return MSVCIntrin::_InterlockedExchange;
207 case clang::ARM::BI_InterlockedExchangeAdd64:
208 return MSVCIntrin::_InterlockedExchangeAdd;
209 case clang::ARM::BI_InterlockedExchangeSub64:
210 return MSVCIntrin::_InterlockedExchangeSub;
211 case clang::ARM::BI_InterlockedOr64:
212 return MSVCIntrin::_InterlockedOr;
213 case clang::ARM::BI_InterlockedXor64:
214 return MSVCIntrin::_InterlockedXor;
215 case clang::ARM::BI_InterlockedDecrement64:
216 return MSVCIntrin::_InterlockedDecrement;
217 case clang::ARM::BI_InterlockedIncrement64:
218 return MSVCIntrin::_InterlockedIncrement;
219 case clang::ARM::BI_InterlockedExchangeAdd8_acq:
220 case clang::ARM::BI_InterlockedExchangeAdd16_acq:
221 case clang::ARM::BI_InterlockedExchangeAdd_acq:
222 case clang::ARM::BI_InterlockedExchangeAdd64_acq:
223 return MSVCIntrin::_InterlockedExchangeAdd_acq;
224 case clang::ARM::BI_InterlockedExchangeAdd8_rel:
225 case clang::ARM::BI_InterlockedExchangeAdd16_rel:
226 case clang::ARM::BI_InterlockedExchangeAdd_rel:
227 case clang::ARM::BI_InterlockedExchangeAdd64_rel:
228 return MSVCIntrin::_InterlockedExchangeAdd_rel;
229 case clang::ARM::BI_InterlockedExchangeAdd8_nf:
230 case clang::ARM::BI_InterlockedExchangeAdd16_nf:
231 case clang::ARM::BI_InterlockedExchangeAdd_nf:
232 case clang::ARM::BI_InterlockedExchangeAdd64_nf:
233 return MSVCIntrin::_InterlockedExchangeAdd_nf;
234 case clang::ARM::BI_InterlockedExchange8_acq:
235 case clang::ARM::BI_InterlockedExchange16_acq:
236 case clang::ARM::BI_InterlockedExchange_acq:
237 case clang::ARM::BI_InterlockedExchange64_acq:
238 case clang::ARM::BI_InterlockedExchangePointer_acq:
239 return MSVCIntrin::_InterlockedExchange_acq;
240 case clang::ARM::BI_InterlockedExchange8_rel:
241 case clang::ARM::BI_InterlockedExchange16_rel:
242 case clang::ARM::BI_InterlockedExchange_rel:
243 case clang::ARM::BI_InterlockedExchange64_rel:
244 case clang::ARM::BI_InterlockedExchangePointer_rel:
245 return MSVCIntrin::_InterlockedExchange_rel;
246 case clang::ARM::BI_InterlockedExchange8_nf:
247 case clang::ARM::BI_InterlockedExchange16_nf:
248 case clang::ARM::BI_InterlockedExchange_nf:
249 case clang::ARM::BI_InterlockedExchange64_nf:
250 case clang::ARM::BI_InterlockedExchangePointer_nf:
251 return MSVCIntrin::_InterlockedExchange_nf;
252 case clang::ARM::BI_InterlockedCompareExchange8_acq:
253 case clang::ARM::BI_InterlockedCompareExchange16_acq:
254 case clang::ARM::BI_InterlockedCompareExchange_acq:
255 case clang::ARM::BI_InterlockedCompareExchange64_acq:
256 case clang::ARM::BI_InterlockedCompareExchangePointer_acq:
257 return MSVCIntrin::_InterlockedCompareExchange_acq;
258 case clang::ARM::BI_InterlockedCompareExchange8_rel:
259 case clang::ARM::BI_InterlockedCompareExchange16_rel:
260 case clang::ARM::BI_InterlockedCompareExchange_rel:
261 case clang::ARM::BI_InterlockedCompareExchange64_rel:
262 case clang::ARM::BI_InterlockedCompareExchangePointer_rel:
263 return MSVCIntrin::_InterlockedCompareExchange_rel;
264 case clang::ARM::BI_InterlockedCompareExchange8_nf:
265 case clang::ARM::BI_InterlockedCompareExchange16_nf:
266 case clang::ARM::BI_InterlockedCompareExchange_nf:
267 case clang::ARM::BI_InterlockedCompareExchange64_nf:
268 return MSVCIntrin::_InterlockedCompareExchange_nf;
269 case clang::ARM::BI_InterlockedOr8_acq:
270 case clang::ARM::BI_InterlockedOr16_acq:
271 case clang::ARM::BI_InterlockedOr_acq:
272 case clang::ARM::BI_InterlockedOr64_acq:
273 return MSVCIntrin::_InterlockedOr_acq;
274 case clang::ARM::BI_InterlockedOr8_rel:
275 case clang::ARM::BI_InterlockedOr16_rel:
276 case clang::ARM::BI_InterlockedOr_rel:
277 case clang::ARM::BI_InterlockedOr64_rel:
278 return MSVCIntrin::_InterlockedOr_rel;
279 case clang::ARM::BI_InterlockedOr8_nf:
280 case clang::ARM::BI_InterlockedOr16_nf:
281 case clang::ARM::BI_InterlockedOr_nf:
282 case clang::ARM::BI_InterlockedOr64_nf:
283 return MSVCIntrin::_InterlockedOr_nf;
284 case clang::ARM::BI_InterlockedXor8_acq:
285 case clang::ARM::BI_InterlockedXor16_acq:
286 case clang::ARM::BI_InterlockedXor_acq:
287 case clang::ARM::BI_InterlockedXor64_acq:
288 return MSVCIntrin::_InterlockedXor_acq;
289 case clang::ARM::BI_InterlockedXor8_rel:
290 case clang::ARM::BI_InterlockedXor16_rel:
291 case clang::ARM::BI_InterlockedXor_rel:
292 case clang::ARM::BI_InterlockedXor64_rel:
293 return MSVCIntrin::_InterlockedXor_rel;
294 case clang::ARM::BI_InterlockedXor8_nf:
295 case clang::ARM::BI_InterlockedXor16_nf:
296 case clang::ARM::BI_InterlockedXor_nf:
297 case clang::ARM::BI_InterlockedXor64_nf:
298 return MSVCIntrin::_InterlockedXor_nf;
299 case clang::ARM::BI_InterlockedAnd8_acq:
300 case clang::ARM::BI_InterlockedAnd16_acq:
301 case clang::ARM::BI_InterlockedAnd_acq:
302 case clang::ARM::BI_InterlockedAnd64_acq:
303 return MSVCIntrin::_InterlockedAnd_acq;
304 case clang::ARM::BI_InterlockedAnd8_rel:
305 case clang::ARM::BI_InterlockedAnd16_rel:
306 case clang::ARM::BI_InterlockedAnd_rel:
307 case clang::ARM::BI_InterlockedAnd64_rel:
308 return MSVCIntrin::_InterlockedAnd_rel;
309 case clang::ARM::BI_InterlockedAnd8_nf:
310 case clang::ARM::BI_InterlockedAnd16_nf:
311 case clang::ARM::BI_InterlockedAnd_nf:
312 case clang::ARM::BI_InterlockedAnd64_nf:
313 return MSVCIntrin::_InterlockedAnd_nf;
314 case clang::ARM::BI_InterlockedIncrement16_acq:
315 case clang::ARM::BI_InterlockedIncrement_acq:
316 case clang::ARM::BI_InterlockedIncrement64_acq:
317 return MSVCIntrin::_InterlockedIncrement_acq;
318 case clang::ARM::BI_InterlockedIncrement16_rel:
319 case clang::ARM::BI_InterlockedIncrement_rel:
320 case clang::ARM::BI_InterlockedIncrement64_rel:
321 return MSVCIntrin::_InterlockedIncrement_rel;
322 case clang::ARM::BI_InterlockedIncrement16_nf:
323 case clang::ARM::BI_InterlockedIncrement_nf:
324 case clang::ARM::BI_InterlockedIncrement64_nf:
325 return MSVCIntrin::_InterlockedIncrement_nf;
326 case clang::ARM::BI_InterlockedDecrement16_acq:
327 case clang::ARM::BI_InterlockedDecrement_acq:
328 case clang::ARM::BI_InterlockedDecrement64_acq:
329 return MSVCIntrin::_InterlockedDecrement_acq;
330 case clang::ARM::BI_InterlockedDecrement16_rel:
331 case clang::ARM::BI_InterlockedDecrement_rel:
332 case clang::ARM::BI_InterlockedDecrement64_rel:
333 return MSVCIntrin::_InterlockedDecrement_rel;
334 case clang::ARM::BI_InterlockedDecrement16_nf:
335 case clang::ARM::BI_InterlockedDecrement_nf:
336 case clang::ARM::BI_InterlockedDecrement64_nf:
337 return MSVCIntrin::_InterlockedDecrement_nf;
338 }
339 llvm_unreachable("must return from switch");
340}
341
342// Emit an intrinsic where all operands are of the same type as the result.
343// Depending on mode, this may be a constrained floating-point intrinsic.
345 unsigned IntrinsicID,
346 unsigned ConstrainedIntrinsicID,
347 llvm::Type *Ty,
348 ArrayRef<Value *> Args) {
349 Function *F;
350 if (CGF.Builder.getIsFPConstrained())
351 F = CGF.CGM.getIntrinsic(ConstrainedIntrinsicID, Ty);
352 else
353 F = CGF.CGM.getIntrinsic(IntrinsicID, Ty);
354
355 if (CGF.Builder.getIsFPConstrained())
356 return CGF.Builder.CreateConstrainedFPCall(F, Args);
357
358 return CGF.Builder.CreateCall(F, Args);
359}
360
361static llvm::FixedVectorType *GetNeonType(CodeGenFunction *CGF,
362 NeonTypeFlags TypeFlags,
363 bool HasFastHalfType = true,
364 bool V1Ty = false,
365 bool AllowBFloatArgsAndRet = true) {
366 int IsQuad = TypeFlags.isQuad();
367 switch (TypeFlags.getEltType()) {
371 return llvm::FixedVectorType::get(CGF->Int8Ty, V1Ty ? 1 : (8 << IsQuad));
374 return llvm::FixedVectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad));
376 if (AllowBFloatArgsAndRet)
377 return llvm::FixedVectorType::get(CGF->BFloatTy, V1Ty ? 1 : (4 << IsQuad));
378 return llvm::FixedVectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad));
380 if (HasFastHalfType)
381 return llvm::FixedVectorType::get(CGF->HalfTy, V1Ty ? 1 : (4 << IsQuad));
382 return llvm::FixedVectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad));
384 return llvm::FixedVectorType::get(CGF->Int32Ty, V1Ty ? 1 : (2 << IsQuad));
387 return llvm::FixedVectorType::get(CGF->Int64Ty, V1Ty ? 1 : (1 << IsQuad));
389 // FIXME: i128 and f128 doesn't get fully support in Clang and llvm.
390 // There is a lot of i128 and f128 API missing.
391 // so we use v16i8 to represent poly128 and get pattern matched.
392 return llvm::FixedVectorType::get(CGF->Int8Ty, 16);
394 return llvm::FixedVectorType::get(CGF->FloatTy, V1Ty ? 1 : (2 << IsQuad));
396 return llvm::FixedVectorType::get(CGF->DoubleTy, V1Ty ? 1 : (1 << IsQuad));
397 }
398 llvm_unreachable("Unknown vector element type!");
399}
400
401static llvm::VectorType *GetFloatNeonType(CodeGenFunction *CGF,
402 NeonTypeFlags IntTypeFlags) {
403 int IsQuad = IntTypeFlags.isQuad();
404 switch (IntTypeFlags.getEltType()) {
406 return llvm::FixedVectorType::get(CGF->HalfTy, (4 << IsQuad));
408 return llvm::FixedVectorType::get(CGF->FloatTy, (2 << IsQuad));
410 return llvm::FixedVectorType::get(CGF->DoubleTy, (1 << IsQuad));
411 default:
412 llvm_unreachable("Type can't be converted to floating-point!");
413 }
414}
415
417 const ElementCount &Count) {
418 Value *SV = llvm::ConstantVector::getSplat(Count, C);
419 return Builder.CreateShuffleVector(V, V, SV, "lane");
420}
421
423 ElementCount EC = cast<llvm::VectorType>(V->getType())->getElementCount();
424 return EmitNeonSplat(V, C, EC);
425}
426
428 const char *name,
429 unsigned shift, bool rightshift) {
430 unsigned j = 0;
431 for (Function::const_arg_iterator ai = F->arg_begin(), ae = F->arg_end();
432 ai != ae; ++ai, ++j) {
433 if (F->isConstrainedFPIntrinsic())
434 if (ai->getType()->isMetadataTy())
435 continue;
436 if (shift > 0 && shift == j)
437 Ops[j] = EmitNeonShiftVector(Ops[j], ai->getType(), rightshift);
438 else
439 Ops[j] = Builder.CreateBitCast(Ops[j], ai->getType(), name);
440 }
441
442 if (F->isConstrainedFPIntrinsic())
443 return Builder.CreateConstrainedFPCall(F, Ops, name);
444 return Builder.CreateCall(F, Ops, name);
445}
446
450 const CallExpr *E, const char *name) {
451 Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_set_fpmr),
452 Ops.pop_back_val());
453 return EmitNeonCall(CGM.getIntrinsic(IID, Tys), Ops, name);
454}
455
457 unsigned IID, bool ExtendLaneArg, llvm::Type *RetTy,
458 SmallVectorImpl<llvm::Value *> &Ops, const CallExpr *E, const char *name) {
459
460 const unsigned ElemCount = Ops[0]->getType()->getPrimitiveSizeInBits() /
461 RetTy->getPrimitiveSizeInBits();
462 llvm::Type *Tys[] = {llvm::FixedVectorType::get(RetTy, ElemCount),
463 Ops[1]->getType()};
464 if (ExtendLaneArg) {
465 auto *VT = llvm::FixedVectorType::get(Int8Ty, 16);
466 Ops[2] = Builder.CreateInsertVector(VT, PoisonValue::get(VT), Ops[2],
467 uint64_t(0));
468 }
469 return EmitFP8NeonCall(IID, Tys, Ops, E, name);
470}
471
473 unsigned IID, bool ExtendLaneArg, llvm::Type *RetTy,
474 SmallVectorImpl<llvm::Value *> &Ops, const CallExpr *E, const char *name) {
475
476 if (ExtendLaneArg) {
477 auto *VT = llvm::FixedVectorType::get(Int8Ty, 16);
478 Ops[2] = Builder.CreateInsertVector(VT, PoisonValue::get(VT), Ops[2],
479 uint64_t(0));
480 }
481 const unsigned ElemCount = Ops[0]->getType()->getPrimitiveSizeInBits() /
482 RetTy->getPrimitiveSizeInBits();
483 return EmitFP8NeonCall(IID, {llvm::FixedVectorType::get(RetTy, ElemCount)},
484 Ops, E, name);
485}
486
488 bool neg) {
489 int SV = cast<ConstantInt>(V)->getSExtValue();
490 return ConstantInt::getSigned(Ty, neg ? -SV : SV);
491}
492
493Value *CodeGenFunction::EmitFP8NeonCvtCall(unsigned IID, llvm::Type *Ty0,
494 llvm::Type *Ty1, bool Extract,
496 const CallExpr *E,
497 const char *name) {
498 llvm::Type *Tys[] = {Ty0, Ty1};
499 if (Extract) {
500 // Op[0] is mfloat8x16_t, but the intrinsic converts only the lower part of
501 // the vector.
502 Tys[1] = llvm::FixedVectorType::get(Int8Ty, 8);
503 Ops[0] = Builder.CreateExtractVector(Tys[1], Ops[0], uint64_t(0));
504 }
505 return EmitFP8NeonCall(IID, Tys, Ops, E, name);
506}
507
508// Right-shift a vector by a constant.
510 llvm::Type *Ty, bool usgn,
511 const char *name) {
512 llvm::VectorType *VTy = cast<llvm::VectorType>(Ty);
513
514 int ShiftAmt = cast<ConstantInt>(Shift)->getSExtValue();
515 int EltSize = VTy->getScalarSizeInBits();
516
517 Vec = Builder.CreateBitCast(Vec, Ty);
518
519 // lshr/ashr are undefined when the shift amount is equal to the vector
520 // element size.
521 if (ShiftAmt == EltSize) {
522 if (usgn) {
523 // Right-shifting an unsigned value by its size yields 0.
524 return llvm::ConstantAggregateZero::get(VTy);
525 } else {
526 // Right-shifting a signed value by its size is equivalent
527 // to a shift of size-1.
528 --ShiftAmt;
529 Shift = ConstantInt::get(VTy->getElementType(), ShiftAmt);
530 }
531 }
532
533 Shift = EmitNeonShiftVector(Shift, Ty, false);
534 if (usgn)
535 return Builder.CreateLShr(Vec, Shift, name);
536 return Builder.CreateAShr(Vec, Shift, name);
537}
538
539// clang-format off
541 NEONMAP1(__a32_vcvt_bf16_f32, arm_neon_vcvtfp2bf, 0),
542 NEONMAP0(splat_lane_v),
543 NEONMAP0(splat_laneq_v),
544 NEONMAP0(splatq_lane_v),
545 NEONMAP0(splatq_laneq_v),
546 NEONMAP2(vabd_v, arm_neon_vabdu, arm_neon_vabds, Add1ArgType | UnsignedAlts),
547 NEONMAP2(vabdq_v, arm_neon_vabdu, arm_neon_vabds, Add1ArgType | UnsignedAlts),
548 NEONMAP1(vabs_v, arm_neon_vabs, 0),
549 NEONMAP1(vabsq_v, arm_neon_vabs, 0),
550 NEONMAP0(vadd_v),
551 NEONMAP0(vaddhn_v),
552 NEONMAP0(vaddq_v),
553 NEONMAP1(vaesdq_u8, arm_neon_aesd, 0),
554 NEONMAP1(vaeseq_u8, arm_neon_aese, 0),
555 NEONMAP1(vaesimcq_u8, arm_neon_aesimc, 0),
556 NEONMAP1(vaesmcq_u8, arm_neon_aesmc, 0),
557 NEONMAP1(vbfdot_f32, arm_neon_bfdot, 0),
558 NEONMAP1(vbfdotq_f32, arm_neon_bfdot, 0),
559 NEONMAP1(vbfmlalbq_f32, arm_neon_bfmlalb, 0),
560 NEONMAP1(vbfmlaltq_f32, arm_neon_bfmlalt, 0),
561 NEONMAP1(vbfmmlaq_f32, arm_neon_bfmmla, 0),
562 NEONMAP1(vbsl_v, arm_neon_vbsl, AddRetType),
563 NEONMAP1(vbslq_v, arm_neon_vbsl, AddRetType),
564 NEONMAP1(vcadd_rot270_f16, arm_neon_vcadd_rot270, Add1ArgType),
565 NEONMAP1(vcadd_rot270_f32, arm_neon_vcadd_rot270, Add1ArgType),
566 NEONMAP1(vcadd_rot90_f16, arm_neon_vcadd_rot90, Add1ArgType),
567 NEONMAP1(vcadd_rot90_f32, arm_neon_vcadd_rot90, Add1ArgType),
568 NEONMAP1(vcaddq_rot270_f16, arm_neon_vcadd_rot270, Add1ArgType),
569 NEONMAP1(vcaddq_rot270_f32, arm_neon_vcadd_rot270, Add1ArgType),
570 NEONMAP1(vcaddq_rot270_f64, arm_neon_vcadd_rot270, Add1ArgType),
571 NEONMAP1(vcaddq_rot90_f16, arm_neon_vcadd_rot90, Add1ArgType),
572 NEONMAP1(vcaddq_rot90_f32, arm_neon_vcadd_rot90, Add1ArgType),
573 NEONMAP1(vcaddq_rot90_f64, arm_neon_vcadd_rot90, Add1ArgType),
574 NEONMAP1(vcage_v, arm_neon_vacge, 0),
575 NEONMAP1(vcageq_v, arm_neon_vacge, 0),
576 NEONMAP1(vcagt_v, arm_neon_vacgt, 0),
577 NEONMAP1(vcagtq_v, arm_neon_vacgt, 0),
578 NEONMAP1(vcale_v, arm_neon_vacge, 0),
579 NEONMAP1(vcaleq_v, arm_neon_vacge, 0),
580 NEONMAP1(vcalt_v, arm_neon_vacgt, 0),
581 NEONMAP1(vcaltq_v, arm_neon_vacgt, 0),
582 NEONMAP0(vceqz_v),
583 NEONMAP0(vceqzq_v),
584 NEONMAP0(vcgez_v),
585 NEONMAP0(vcgezq_v),
586 NEONMAP0(vcgtz_v),
587 NEONMAP0(vcgtzq_v),
588 NEONMAP0(vclez_v),
589 NEONMAP0(vclezq_v),
590 NEONMAP1(vcls_v, arm_neon_vcls, Add1ArgType),
591 NEONMAP1(vclsq_v, arm_neon_vcls, Add1ArgType),
592 NEONMAP0(vcltz_v),
593 NEONMAP0(vcltzq_v),
594 NEONMAP1(vclz_v, ctlz, Add1ArgType),
595 NEONMAP1(vclzq_v, ctlz, Add1ArgType),
596 NEONMAP1(vcnt_v, ctpop, Add1ArgType),
597 NEONMAP1(vcntq_v, ctpop, Add1ArgType),
598 NEONMAP0(vcvt_f16_s16),
599 NEONMAP0(vcvt_f16_u16),
600 NEONMAP0(vcvt_f32_v),
601 NEONMAP1(vcvt_n_f16_s16, arm_neon_vcvtfxs2fp, 0),
602 NEONMAP1(vcvt_n_f16_u16, arm_neon_vcvtfxu2fp, 0),
603 NEONMAP2(vcvt_n_f32_v, arm_neon_vcvtfxu2fp, arm_neon_vcvtfxs2fp, 0),
604 NEONMAP1(vcvt_n_s16_f16, arm_neon_vcvtfp2fxs, 0),
605 NEONMAP1(vcvt_n_s32_v, arm_neon_vcvtfp2fxs, 0),
606 NEONMAP1(vcvt_n_s64_v, arm_neon_vcvtfp2fxs, 0),
607 NEONMAP1(vcvt_n_u16_f16, arm_neon_vcvtfp2fxu, 0),
608 NEONMAP1(vcvt_n_u32_v, arm_neon_vcvtfp2fxu, 0),
609 NEONMAP1(vcvt_n_u64_v, arm_neon_vcvtfp2fxu, 0),
610 NEONMAP0(vcvt_s16_f16),
611 NEONMAP0(vcvt_s32_v),
612 NEONMAP0(vcvt_s64_v),
613 NEONMAP0(vcvt_u16_f16),
614 NEONMAP0(vcvt_u32_v),
615 NEONMAP0(vcvt_u64_v),
616 NEONMAP1(vcvta_s16_f16, arm_neon_vcvtas, 0),
617 NEONMAP1(vcvta_s32_v, arm_neon_vcvtas, 0),
618 NEONMAP1(vcvta_s64_v, arm_neon_vcvtas, 0),
619 NEONMAP1(vcvta_u16_f16, arm_neon_vcvtau, 0),
620 NEONMAP1(vcvta_u32_v, arm_neon_vcvtau, 0),
621 NEONMAP1(vcvta_u64_v, arm_neon_vcvtau, 0),
622 NEONMAP1(vcvtaq_s16_f16, arm_neon_vcvtas, 0),
623 NEONMAP1(vcvtaq_s32_v, arm_neon_vcvtas, 0),
624 NEONMAP1(vcvtaq_s64_v, arm_neon_vcvtas, 0),
625 NEONMAP1(vcvtaq_u16_f16, arm_neon_vcvtau, 0),
626 NEONMAP1(vcvtaq_u32_v, arm_neon_vcvtau, 0),
627 NEONMAP1(vcvtaq_u64_v, arm_neon_vcvtau, 0),
628 NEONMAP1(vcvth_bf16_f32, arm_neon_vcvtbfp2bf, 0),
629 NEONMAP1(vcvtm_s16_f16, arm_neon_vcvtms, 0),
630 NEONMAP1(vcvtm_s32_v, arm_neon_vcvtms, 0),
631 NEONMAP1(vcvtm_s64_v, arm_neon_vcvtms, 0),
632 NEONMAP1(vcvtm_u16_f16, arm_neon_vcvtmu, 0),
633 NEONMAP1(vcvtm_u32_v, arm_neon_vcvtmu, 0),
634 NEONMAP1(vcvtm_u64_v, arm_neon_vcvtmu, 0),
635 NEONMAP1(vcvtmq_s16_f16, arm_neon_vcvtms, 0),
636 NEONMAP1(vcvtmq_s32_v, arm_neon_vcvtms, 0),
637 NEONMAP1(vcvtmq_s64_v, arm_neon_vcvtms, 0),
638 NEONMAP1(vcvtmq_u16_f16, arm_neon_vcvtmu, 0),
639 NEONMAP1(vcvtmq_u32_v, arm_neon_vcvtmu, 0),
640 NEONMAP1(vcvtmq_u64_v, arm_neon_vcvtmu, 0),
641 NEONMAP1(vcvtn_s16_f16, arm_neon_vcvtns, 0),
642 NEONMAP1(vcvtn_s32_v, arm_neon_vcvtns, 0),
643 NEONMAP1(vcvtn_s64_v, arm_neon_vcvtns, 0),
644 NEONMAP1(vcvtn_u16_f16, arm_neon_vcvtnu, 0),
645 NEONMAP1(vcvtn_u32_v, arm_neon_vcvtnu, 0),
646 NEONMAP1(vcvtn_u64_v, arm_neon_vcvtnu, 0),
647 NEONMAP1(vcvtnq_s16_f16, arm_neon_vcvtns, 0),
648 NEONMAP1(vcvtnq_s32_v, arm_neon_vcvtns, 0),
649 NEONMAP1(vcvtnq_s64_v, arm_neon_vcvtns, 0),
650 NEONMAP1(vcvtnq_u16_f16, arm_neon_vcvtnu, 0),
651 NEONMAP1(vcvtnq_u32_v, arm_neon_vcvtnu, 0),
652 NEONMAP1(vcvtnq_u64_v, arm_neon_vcvtnu, 0),
653 NEONMAP1(vcvtp_s16_f16, arm_neon_vcvtps, 0),
654 NEONMAP1(vcvtp_s32_v, arm_neon_vcvtps, 0),
655 NEONMAP1(vcvtp_s64_v, arm_neon_vcvtps, 0),
656 NEONMAP1(vcvtp_u16_f16, arm_neon_vcvtpu, 0),
657 NEONMAP1(vcvtp_u32_v, arm_neon_vcvtpu, 0),
658 NEONMAP1(vcvtp_u64_v, arm_neon_vcvtpu, 0),
659 NEONMAP1(vcvtpq_s16_f16, arm_neon_vcvtps, 0),
660 NEONMAP1(vcvtpq_s32_v, arm_neon_vcvtps, 0),
661 NEONMAP1(vcvtpq_s64_v, arm_neon_vcvtps, 0),
662 NEONMAP1(vcvtpq_u16_f16, arm_neon_vcvtpu, 0),
663 NEONMAP1(vcvtpq_u32_v, arm_neon_vcvtpu, 0),
664 NEONMAP1(vcvtpq_u64_v, arm_neon_vcvtpu, 0),
665 NEONMAP0(vcvtq_f16_s16),
666 NEONMAP0(vcvtq_f16_u16),
667 NEONMAP0(vcvtq_f32_v),
668 NEONMAP1(vcvtq_n_f16_s16, arm_neon_vcvtfxs2fp, 0),
669 NEONMAP1(vcvtq_n_f16_u16, arm_neon_vcvtfxu2fp, 0),
670 NEONMAP2(vcvtq_n_f32_v, arm_neon_vcvtfxu2fp, arm_neon_vcvtfxs2fp, 0),
671 NEONMAP1(vcvtq_n_s16_f16, arm_neon_vcvtfp2fxs, 0),
672 NEONMAP1(vcvtq_n_s32_v, arm_neon_vcvtfp2fxs, 0),
673 NEONMAP1(vcvtq_n_s64_v, arm_neon_vcvtfp2fxs, 0),
674 NEONMAP1(vcvtq_n_u16_f16, arm_neon_vcvtfp2fxu, 0),
675 NEONMAP1(vcvtq_n_u32_v, arm_neon_vcvtfp2fxu, 0),
676 NEONMAP1(vcvtq_n_u64_v, arm_neon_vcvtfp2fxu, 0),
677 NEONMAP0(vcvtq_s16_f16),
678 NEONMAP0(vcvtq_s32_v),
679 NEONMAP0(vcvtq_s64_v),
680 NEONMAP0(vcvtq_u16_f16),
681 NEONMAP0(vcvtq_u32_v),
682 NEONMAP0(vcvtq_u64_v),
683 NEONMAP1(vdot_s32, arm_neon_sdot, 0),
684 NEONMAP1(vdot_u32, arm_neon_udot, 0),
685 NEONMAP1(vdotq_s32, arm_neon_sdot, 0),
686 NEONMAP1(vdotq_u32, arm_neon_udot, 0),
687 NEONMAP0(vext_v),
688 NEONMAP0(vextq_v),
689 NEONMAP0(vfma_v),
690 NEONMAP0(vfmaq_v),
691 NEONMAP2(vhadd_v, arm_neon_vhaddu, arm_neon_vhadds, Add1ArgType | UnsignedAlts),
692 NEONMAP2(vhaddq_v, arm_neon_vhaddu, arm_neon_vhadds, Add1ArgType | UnsignedAlts),
693 NEONMAP2(vhsub_v, arm_neon_vhsubu, arm_neon_vhsubs, Add1ArgType | UnsignedAlts),
694 NEONMAP2(vhsubq_v, arm_neon_vhsubu, arm_neon_vhsubs, Add1ArgType | UnsignedAlts),
695 NEONMAP0(vld1_dup_v),
696 NEONMAP1(vld1_v, arm_neon_vld1, 0),
697 NEONMAP1(vld1_x2_v, arm_neon_vld1x2, 0),
698 NEONMAP1(vld1_x3_v, arm_neon_vld1x3, 0),
699 NEONMAP1(vld1_x4_v, arm_neon_vld1x4, 0),
700 NEONMAP0(vld1q_dup_v),
701 NEONMAP1(vld1q_v, arm_neon_vld1, 0),
702 NEONMAP1(vld1q_x2_v, arm_neon_vld1x2, 0),
703 NEONMAP1(vld1q_x3_v, arm_neon_vld1x3, 0),
704 NEONMAP1(vld1q_x4_v, arm_neon_vld1x4, 0),
705 NEONMAP1(vld2_dup_v, arm_neon_vld2dup, 0),
706 NEONMAP1(vld2_lane_v, arm_neon_vld2lane, 0),
707 NEONMAP1(vld2_v, arm_neon_vld2, 0),
708 NEONMAP1(vld2q_dup_v, arm_neon_vld2dup, 0),
709 NEONMAP1(vld2q_lane_v, arm_neon_vld2lane, 0),
710 NEONMAP1(vld2q_v, arm_neon_vld2, 0),
711 NEONMAP1(vld3_dup_v, arm_neon_vld3dup, 0),
712 NEONMAP1(vld3_lane_v, arm_neon_vld3lane, 0),
713 NEONMAP1(vld3_v, arm_neon_vld3, 0),
714 NEONMAP1(vld3q_dup_v, arm_neon_vld3dup, 0),
715 NEONMAP1(vld3q_lane_v, arm_neon_vld3lane, 0),
716 NEONMAP1(vld3q_v, arm_neon_vld3, 0),
717 NEONMAP1(vld4_dup_v, arm_neon_vld4dup, 0),
718 NEONMAP1(vld4_lane_v, arm_neon_vld4lane, 0),
719 NEONMAP1(vld4_v, arm_neon_vld4, 0),
720 NEONMAP1(vld4q_dup_v, arm_neon_vld4dup, 0),
721 NEONMAP1(vld4q_lane_v, arm_neon_vld4lane, 0),
722 NEONMAP1(vld4q_v, arm_neon_vld4, 0),
723 NEONMAP2(vmax_v, arm_neon_vmaxu, arm_neon_vmaxs, Add1ArgType | UnsignedAlts),
724 NEONMAP1(vmaxnm_v, arm_neon_vmaxnm, Add1ArgType),
725 NEONMAP1(vmaxnmq_v, arm_neon_vmaxnm, Add1ArgType),
726 NEONMAP2(vmaxq_v, arm_neon_vmaxu, arm_neon_vmaxs, Add1ArgType | UnsignedAlts),
727 NEONMAP2(vmin_v, arm_neon_vminu, arm_neon_vmins, Add1ArgType | UnsignedAlts),
728 NEONMAP1(vminnm_v, arm_neon_vminnm, Add1ArgType),
729 NEONMAP1(vminnmq_v, arm_neon_vminnm, Add1ArgType),
730 NEONMAP2(vminq_v, arm_neon_vminu, arm_neon_vmins, Add1ArgType | UnsignedAlts),
731 NEONMAP1(vmmlaq_s32, arm_neon_smmla, 0),
732 NEONMAP1(vmmlaq_u32, arm_neon_ummla, 0),
733 NEONMAP0(vmovl_v),
734 NEONMAP0(vmovn_v),
735 NEONMAP1(vmul_v, arm_neon_vmulp, Add1ArgType),
736 NEONMAP0(vmull_v),
737 NEONMAP1(vmulq_v, arm_neon_vmulp, Add1ArgType),
738 NEONMAP2(vpadal_v, arm_neon_vpadalu, arm_neon_vpadals, UnsignedAlts),
739 NEONMAP2(vpadalq_v, arm_neon_vpadalu, arm_neon_vpadals, UnsignedAlts),
740 NEONMAP1(vpadd_v, arm_neon_vpadd, Add1ArgType),
741 NEONMAP2(vpaddl_v, arm_neon_vpaddlu, arm_neon_vpaddls, UnsignedAlts),
742 NEONMAP2(vpaddlq_v, arm_neon_vpaddlu, arm_neon_vpaddls, UnsignedAlts),
743 NEONMAP1(vpaddq_v, arm_neon_vpadd, Add1ArgType),
744 NEONMAP2(vpmax_v, arm_neon_vpmaxu, arm_neon_vpmaxs, Add1ArgType | UnsignedAlts),
745 NEONMAP2(vpmin_v, arm_neon_vpminu, arm_neon_vpmins, Add1ArgType | UnsignedAlts),
746 NEONMAP1(vqabs_v, arm_neon_vqabs, Add1ArgType),
747 NEONMAP1(vqabsq_v, arm_neon_vqabs, Add1ArgType),
748 NEONMAP2(vqadd_v, uadd_sat, sadd_sat, Add1ArgType | UnsignedAlts),
749 NEONMAP2(vqaddq_v, uadd_sat, sadd_sat, Add1ArgType | UnsignedAlts),
750 NEONMAP2(vqdmlal_v, arm_neon_vqdmull, sadd_sat, 0),
751 NEONMAP2(vqdmlsl_v, arm_neon_vqdmull, ssub_sat, 0),
752 NEONMAP1(vqdmulh_v, arm_neon_vqdmulh, Add1ArgType),
753 NEONMAP1(vqdmulhq_v, arm_neon_vqdmulh, Add1ArgType),
754 NEONMAP1(vqdmull_v, arm_neon_vqdmull, Add1ArgType),
755 NEONMAP2(vqmovn_v, arm_neon_vqmovnu, arm_neon_vqmovns, Add1ArgType | UnsignedAlts),
756 NEONMAP1(vqmovun_v, arm_neon_vqmovnsu, Add1ArgType),
757 NEONMAP1(vqneg_v, arm_neon_vqneg, Add1ArgType),
758 NEONMAP1(vqnegq_v, arm_neon_vqneg, Add1ArgType),
759 NEONMAP1(vqrdmlah_s16, arm_neon_vqrdmlah, Add1ArgType),
760 NEONMAP1(vqrdmlah_s32, arm_neon_vqrdmlah, Add1ArgType),
761 NEONMAP1(vqrdmlahq_s16, arm_neon_vqrdmlah, Add1ArgType),
762 NEONMAP1(vqrdmlahq_s32, arm_neon_vqrdmlah, Add1ArgType),
763 NEONMAP1(vqrdmlsh_s16, arm_neon_vqrdmlsh, Add1ArgType),
764 NEONMAP1(vqrdmlsh_s32, arm_neon_vqrdmlsh, Add1ArgType),
765 NEONMAP1(vqrdmlshq_s16, arm_neon_vqrdmlsh, Add1ArgType),
766 NEONMAP1(vqrdmlshq_s32, arm_neon_vqrdmlsh, Add1ArgType),
767 NEONMAP1(vqrdmulh_v, arm_neon_vqrdmulh, Add1ArgType),
768 NEONMAP1(vqrdmulhq_v, arm_neon_vqrdmulh, Add1ArgType),
769 NEONMAP2(vqrshl_v, arm_neon_vqrshiftu, arm_neon_vqrshifts, Add1ArgType | UnsignedAlts),
770 NEONMAP2(vqrshlq_v, arm_neon_vqrshiftu, arm_neon_vqrshifts, Add1ArgType | UnsignedAlts),
771 NEONMAP2(vqshl_n_v, arm_neon_vqshiftu, arm_neon_vqshifts, UnsignedAlts),
772 NEONMAP2(vqshl_v, arm_neon_vqshiftu, arm_neon_vqshifts, Add1ArgType | UnsignedAlts),
773 NEONMAP2(vqshlq_n_v, arm_neon_vqshiftu, arm_neon_vqshifts, UnsignedAlts),
774 NEONMAP2(vqshlq_v, arm_neon_vqshiftu, arm_neon_vqshifts, Add1ArgType | UnsignedAlts),
775 NEONMAP1(vqshlu_n_v, arm_neon_vqshiftsu, 0),
776 NEONMAP1(vqshluq_n_v, arm_neon_vqshiftsu, 0),
777 NEONMAP2(vqsub_v, usub_sat, ssub_sat, Add1ArgType | UnsignedAlts),
778 NEONMAP2(vqsubq_v, usub_sat, ssub_sat, Add1ArgType | UnsignedAlts),
779 NEONMAP1(vraddhn_v, arm_neon_vraddhn, Add1ArgType),
780 NEONMAP2(vrecpe_v, arm_neon_vrecpe, arm_neon_vrecpe, 0),
781 NEONMAP2(vrecpeq_v, arm_neon_vrecpe, arm_neon_vrecpe, 0),
782 NEONMAP1(vrecps_v, arm_neon_vrecps, Add1ArgType),
783 NEONMAP1(vrecpsq_v, arm_neon_vrecps, Add1ArgType),
784 NEONMAP2(vrhadd_v, arm_neon_vrhaddu, arm_neon_vrhadds, Add1ArgType | UnsignedAlts),
785 NEONMAP2(vrhaddq_v, arm_neon_vrhaddu, arm_neon_vrhadds, Add1ArgType | UnsignedAlts),
786 NEONMAP1(vrnd_v, trunc, Add1ArgType),
787 NEONMAP1(vrnda_v, round, Add1ArgType),
788 NEONMAP1(vrndaq_v, round, Add1ArgType),
789 NEONMAP0(vrndi_v),
790 NEONMAP0(vrndiq_v),
791 NEONMAP1(vrndm_v, floor, Add1ArgType),
792 NEONMAP1(vrndmq_v, floor, Add1ArgType),
793 NEONMAP1(vrndn_v, roundeven, Add1ArgType),
794 NEONMAP1(vrndnq_v, roundeven, Add1ArgType),
795 NEONMAP1(vrndp_v, ceil, Add1ArgType),
796 NEONMAP1(vrndpq_v, ceil, Add1ArgType),
797 NEONMAP1(vrndq_v, trunc, Add1ArgType),
798 NEONMAP1(vrndx_v, rint, Add1ArgType),
799 NEONMAP1(vrndxq_v, rint, Add1ArgType),
800 NEONMAP2(vrshl_v, arm_neon_vrshiftu, arm_neon_vrshifts, Add1ArgType | UnsignedAlts),
801 NEONMAP2(vrshlq_v, arm_neon_vrshiftu, arm_neon_vrshifts, Add1ArgType | UnsignedAlts),
802 NEONMAP2(vrshr_n_v, arm_neon_vrshiftu, arm_neon_vrshifts, UnsignedAlts),
803 NEONMAP2(vrshrq_n_v, arm_neon_vrshiftu, arm_neon_vrshifts, UnsignedAlts),
804 NEONMAP2(vrsqrte_v, arm_neon_vrsqrte, arm_neon_vrsqrte, 0),
805 NEONMAP2(vrsqrteq_v, arm_neon_vrsqrte, arm_neon_vrsqrte, 0),
806 NEONMAP1(vrsqrts_v, arm_neon_vrsqrts, Add1ArgType),
807 NEONMAP1(vrsqrtsq_v, arm_neon_vrsqrts, Add1ArgType),
808 NEONMAP1(vrsubhn_v, arm_neon_vrsubhn, Add1ArgType),
809 NEONMAP1(vsha1su0q_u32, arm_neon_sha1su0, 0),
810 NEONMAP1(vsha1su1q_u32, arm_neon_sha1su1, 0),
811 NEONMAP1(vsha256h2q_u32, arm_neon_sha256h2, 0),
812 NEONMAP1(vsha256hq_u32, arm_neon_sha256h, 0),
813 NEONMAP1(vsha256su0q_u32, arm_neon_sha256su0, 0),
814 NEONMAP1(vsha256su1q_u32, arm_neon_sha256su1, 0),
815 NEONMAP0(vshl_n_v),
816 NEONMAP2(vshl_v, arm_neon_vshiftu, arm_neon_vshifts, Add1ArgType | UnsignedAlts),
817 NEONMAP0(vshll_n_v),
818 NEONMAP0(vshlq_n_v),
819 NEONMAP2(vshlq_v, arm_neon_vshiftu, arm_neon_vshifts, Add1ArgType | UnsignedAlts),
820 NEONMAP0(vshr_n_v),
821 NEONMAP0(vshrn_n_v),
822 NEONMAP0(vshrq_n_v),
823 NEONMAP1(vst1_v, arm_neon_vst1, 0),
824 NEONMAP1(vst1_x2_v, arm_neon_vst1x2, 0),
825 NEONMAP1(vst1_x3_v, arm_neon_vst1x3, 0),
826 NEONMAP1(vst1_x4_v, arm_neon_vst1x4, 0),
827 NEONMAP1(vst1q_v, arm_neon_vst1, 0),
828 NEONMAP1(vst1q_x2_v, arm_neon_vst1x2, 0),
829 NEONMAP1(vst1q_x3_v, arm_neon_vst1x3, 0),
830 NEONMAP1(vst1q_x4_v, arm_neon_vst1x4, 0),
831 NEONMAP1(vst2_lane_v, arm_neon_vst2lane, 0),
832 NEONMAP1(vst2_v, arm_neon_vst2, 0),
833 NEONMAP1(vst2q_lane_v, arm_neon_vst2lane, 0),
834 NEONMAP1(vst2q_v, arm_neon_vst2, 0),
835 NEONMAP1(vst3_lane_v, arm_neon_vst3lane, 0),
836 NEONMAP1(vst3_v, arm_neon_vst3, 0),
837 NEONMAP1(vst3q_lane_v, arm_neon_vst3lane, 0),
838 NEONMAP1(vst3q_v, arm_neon_vst3, 0),
839 NEONMAP1(vst4_lane_v, arm_neon_vst4lane, 0),
840 NEONMAP1(vst4_v, arm_neon_vst4, 0),
841 NEONMAP1(vst4q_lane_v, arm_neon_vst4lane, 0),
842 NEONMAP1(vst4q_v, arm_neon_vst4, 0),
843 NEONMAP0(vsubhn_v),
844 NEONMAP0(vtrn_v),
845 NEONMAP0(vtrnq_v),
846 NEONMAP0(vtst_v),
847 NEONMAP0(vtstq_v),
848 NEONMAP1(vusdot_s32, arm_neon_usdot, 0),
849 NEONMAP1(vusdotq_s32, arm_neon_usdot, 0),
850 NEONMAP1(vusmmlaq_s32, arm_neon_usmmla, 0),
851 NEONMAP0(vuzp_v),
852 NEONMAP0(vuzpq_v),
853 NEONMAP0(vzip_v),
854 NEONMAP0(vzipq_v)
855};
856
857// clang-format on
858
859// Some intrinsics are equivalent for codegen.
860static const std::pair<unsigned, unsigned> NEONEquivalentIntrinsicMap[] = {
861 { NEON::BI__builtin_neon_vabd_f16, NEON::BI__builtin_neon_vabd_v, },
862 { NEON::BI__builtin_neon_vabdq_f16, NEON::BI__builtin_neon_vabdq_v, },
863 { NEON::BI__builtin_neon_vabs_f16, NEON::BI__builtin_neon_vabs_v, },
864 { NEON::BI__builtin_neon_vabsq_f16, NEON::BI__builtin_neon_vabsq_v, },
865 { NEON::BI__builtin_neon_vcage_f16, NEON::BI__builtin_neon_vcage_v, },
866 { NEON::BI__builtin_neon_vcageq_f16, NEON::BI__builtin_neon_vcageq_v, },
867 { NEON::BI__builtin_neon_vcagt_f16, NEON::BI__builtin_neon_vcagt_v, },
868 { NEON::BI__builtin_neon_vcagtq_f16, NEON::BI__builtin_neon_vcagtq_v, },
869 { NEON::BI__builtin_neon_vcale_f16, NEON::BI__builtin_neon_vcale_v, },
870 { NEON::BI__builtin_neon_vcaleq_f16, NEON::BI__builtin_neon_vcaleq_v, },
871 { NEON::BI__builtin_neon_vcalt_f16, NEON::BI__builtin_neon_vcalt_v, },
872 { NEON::BI__builtin_neon_vcaltq_f16, NEON::BI__builtin_neon_vcaltq_v, },
873 { NEON::BI__builtin_neon_vceqz_f16, NEON::BI__builtin_neon_vceqz_v, },
874 { NEON::BI__builtin_neon_vceqzq_f16, NEON::BI__builtin_neon_vceqzq_v, },
875 { NEON::BI__builtin_neon_vcgez_f16, NEON::BI__builtin_neon_vcgez_v, },
876 { NEON::BI__builtin_neon_vcgezq_f16, NEON::BI__builtin_neon_vcgezq_v, },
877 { NEON::BI__builtin_neon_vcgtz_f16, NEON::BI__builtin_neon_vcgtz_v, },
878 { NEON::BI__builtin_neon_vcgtzq_f16, NEON::BI__builtin_neon_vcgtzq_v, },
879 { NEON::BI__builtin_neon_vclez_f16, NEON::BI__builtin_neon_vclez_v, },
880 { NEON::BI__builtin_neon_vclezq_f16, NEON::BI__builtin_neon_vclezq_v, },
881 { NEON::BI__builtin_neon_vcltz_f16, NEON::BI__builtin_neon_vcltz_v, },
882 { NEON::BI__builtin_neon_vcltzq_f16, NEON::BI__builtin_neon_vcltzq_v, },
883 { NEON::BI__builtin_neon_vfma_f16, NEON::BI__builtin_neon_vfma_v, },
884 { NEON::BI__builtin_neon_vfma_lane_f16, NEON::BI__builtin_neon_vfma_lane_v, },
885 { NEON::BI__builtin_neon_vfma_laneq_f16, NEON::BI__builtin_neon_vfma_laneq_v, },
886 { NEON::BI__builtin_neon_vfmaq_f16, NEON::BI__builtin_neon_vfmaq_v, },
887 { NEON::BI__builtin_neon_vfmaq_lane_f16, NEON::BI__builtin_neon_vfmaq_lane_v, },
888 { NEON::BI__builtin_neon_vfmaq_laneq_f16, NEON::BI__builtin_neon_vfmaq_laneq_v, },
889 { NEON::BI__builtin_neon_vmax_f16, NEON::BI__builtin_neon_vmax_v, },
890 { NEON::BI__builtin_neon_vmaxnm_f16, NEON::BI__builtin_neon_vmaxnm_v, },
891 { NEON::BI__builtin_neon_vmaxnmq_f16, NEON::BI__builtin_neon_vmaxnmq_v, },
892 { NEON::BI__builtin_neon_vmaxq_f16, NEON::BI__builtin_neon_vmaxq_v, },
893 { NEON::BI__builtin_neon_vmin_f16, NEON::BI__builtin_neon_vmin_v, },
894 { NEON::BI__builtin_neon_vminnm_f16, NEON::BI__builtin_neon_vminnm_v, },
895 { NEON::BI__builtin_neon_vminnmq_f16, NEON::BI__builtin_neon_vminnmq_v, },
896 { NEON::BI__builtin_neon_vminq_f16, NEON::BI__builtin_neon_vminq_v, },
897 { NEON::BI__builtin_neon_vmulx_f16, NEON::BI__builtin_neon_vmulx_v, },
898 { NEON::BI__builtin_neon_vmulxq_f16, NEON::BI__builtin_neon_vmulxq_v, },
899 { NEON::BI__builtin_neon_vpadd_f16, NEON::BI__builtin_neon_vpadd_v, },
900 { NEON::BI__builtin_neon_vpaddq_f16, NEON::BI__builtin_neon_vpaddq_v, },
901 { NEON::BI__builtin_neon_vpmax_f16, NEON::BI__builtin_neon_vpmax_v, },
902 { NEON::BI__builtin_neon_vpmaxnm_f16, NEON::BI__builtin_neon_vpmaxnm_v, },
903 { NEON::BI__builtin_neon_vpmaxnmq_f16, NEON::BI__builtin_neon_vpmaxnmq_v, },
904 { NEON::BI__builtin_neon_vpmaxq_f16, NEON::BI__builtin_neon_vpmaxq_v, },
905 { NEON::BI__builtin_neon_vpmin_f16, NEON::BI__builtin_neon_vpmin_v, },
906 { NEON::BI__builtin_neon_vpminnm_f16, NEON::BI__builtin_neon_vpminnm_v, },
907 { NEON::BI__builtin_neon_vpminnmq_f16, NEON::BI__builtin_neon_vpminnmq_v, },
908 { NEON::BI__builtin_neon_vpminq_f16, NEON::BI__builtin_neon_vpminq_v, },
909 { NEON::BI__builtin_neon_vrecpe_f16, NEON::BI__builtin_neon_vrecpe_v, },
910 { NEON::BI__builtin_neon_vrecpeq_f16, NEON::BI__builtin_neon_vrecpeq_v, },
911 { NEON::BI__builtin_neon_vrecps_f16, NEON::BI__builtin_neon_vrecps_v, },
912 { NEON::BI__builtin_neon_vrecpsq_f16, NEON::BI__builtin_neon_vrecpsq_v, },
913 { NEON::BI__builtin_neon_vrnd_f16, NEON::BI__builtin_neon_vrnd_v, },
914 { NEON::BI__builtin_neon_vrnda_f16, NEON::BI__builtin_neon_vrnda_v, },
915 { NEON::BI__builtin_neon_vrndaq_f16, NEON::BI__builtin_neon_vrndaq_v, },
916 { NEON::BI__builtin_neon_vrndi_f16, NEON::BI__builtin_neon_vrndi_v, },
917 { NEON::BI__builtin_neon_vrndiq_f16, NEON::BI__builtin_neon_vrndiq_v, },
918 { NEON::BI__builtin_neon_vrndm_f16, NEON::BI__builtin_neon_vrndm_v, },
919 { NEON::BI__builtin_neon_vrndmq_f16, NEON::BI__builtin_neon_vrndmq_v, },
920 { NEON::BI__builtin_neon_vrndn_f16, NEON::BI__builtin_neon_vrndn_v, },
921 { NEON::BI__builtin_neon_vrndnq_f16, NEON::BI__builtin_neon_vrndnq_v, },
922 { NEON::BI__builtin_neon_vrndp_f16, NEON::BI__builtin_neon_vrndp_v, },
923 { NEON::BI__builtin_neon_vrndpq_f16, NEON::BI__builtin_neon_vrndpq_v, },
924 { NEON::BI__builtin_neon_vrndq_f16, NEON::BI__builtin_neon_vrndq_v, },
925 { NEON::BI__builtin_neon_vrndx_f16, NEON::BI__builtin_neon_vrndx_v, },
926 { NEON::BI__builtin_neon_vrndxq_f16, NEON::BI__builtin_neon_vrndxq_v, },
927 { NEON::BI__builtin_neon_vrsqrte_f16, NEON::BI__builtin_neon_vrsqrte_v, },
928 { NEON::BI__builtin_neon_vrsqrteq_f16, NEON::BI__builtin_neon_vrsqrteq_v, },
929 { NEON::BI__builtin_neon_vrsqrts_f16, NEON::BI__builtin_neon_vrsqrts_v, },
930 { NEON::BI__builtin_neon_vrsqrtsq_f16, NEON::BI__builtin_neon_vrsqrtsq_v, },
931 { NEON::BI__builtin_neon_vsqrt_f16, NEON::BI__builtin_neon_vsqrt_v, },
932 { NEON::BI__builtin_neon_vsqrtq_f16, NEON::BI__builtin_neon_vsqrtq_v, },
933 // The mangling rules cause us to have one ID for each type for vldap1(q)_lane
934 // and vstl1(q)_lane, but codegen is equivalent for all of them. Choose an
935 // arbitrary one to be handled as tha canonical variation.
936 { NEON::BI__builtin_neon_vldap1_lane_u64, NEON::BI__builtin_neon_vldap1_lane_s64 },
937 { NEON::BI__builtin_neon_vldap1_lane_f64, NEON::BI__builtin_neon_vldap1_lane_s64 },
938 { NEON::BI__builtin_neon_vldap1_lane_p64, NEON::BI__builtin_neon_vldap1_lane_s64 },
939 { NEON::BI__builtin_neon_vldap1q_lane_u64, NEON::BI__builtin_neon_vldap1q_lane_s64 },
940 { NEON::BI__builtin_neon_vldap1q_lane_f64, NEON::BI__builtin_neon_vldap1q_lane_s64 },
941 { NEON::BI__builtin_neon_vldap1q_lane_p64, NEON::BI__builtin_neon_vldap1q_lane_s64 },
942 { NEON::BI__builtin_neon_vstl1_lane_u64, NEON::BI__builtin_neon_vstl1_lane_s64 },
943 { NEON::BI__builtin_neon_vstl1_lane_f64, NEON::BI__builtin_neon_vstl1_lane_s64 },
944 { NEON::BI__builtin_neon_vstl1_lane_p64, NEON::BI__builtin_neon_vstl1_lane_s64 },
945 { NEON::BI__builtin_neon_vstl1q_lane_u64, NEON::BI__builtin_neon_vstl1q_lane_s64 },
946 { NEON::BI__builtin_neon_vstl1q_lane_f64, NEON::BI__builtin_neon_vstl1q_lane_s64 },
947 { NEON::BI__builtin_neon_vstl1q_lane_p64, NEON::BI__builtin_neon_vstl1q_lane_s64 },
948};
949
950#undef NEONMAP0
951#undef NEONMAP1
952#undef NEONMAP2
953
954#define SVEMAP1(NameBase, LLVMIntrinsic, TypeModifier) \
955 {SVE::BI__builtin_sve_##NameBase, Intrinsic::LLVMIntrinsic, TypeModifier}
956
957#define SVEMAP2(NameBase, TypeModifier) \
958 {SVE::BI__builtin_sve_##NameBase, 0, TypeModifier}
960#define GET_SVE_LLVM_INTRINSIC_MAP
961#include "clang/Basic/arm_sve_builtin_cg.inc"
962#include "clang/Basic/BuiltinsAArch64NeonSVEBridge_cg.def"
963#undef GET_SVE_LLVM_INTRINSIC_MAP
964};
965
966#undef SVEMAP1
967#undef SVEMAP2
968
969#define SMEMAP1(NameBase, LLVMIntrinsic, TypeModifier) \
970 {SME::BI__builtin_sme_##NameBase, Intrinsic::LLVMIntrinsic, TypeModifier}
971
972#define SMEMAP2(NameBase, TypeModifier) \
973 {SME::BI__builtin_sme_##NameBase, 0, TypeModifier}
975#define GET_SME_LLVM_INTRINSIC_MAP
976#include "clang/Basic/arm_sme_builtin_cg.inc"
977#undef GET_SME_LLVM_INTRINSIC_MAP
978};
979
980#undef SMEMAP1
981#undef SMEMAP2
982
984
989
990// Check if Builtin `BuiltinId` is present in `IntrinsicMap`. If yes, returns
991// the corresponding info struct.
992template <typename IntrinsicInfo>
993static const IntrinsicInfo *
995 unsigned BuiltinID, bool &MapProvenSorted) {
996
997#ifndef NDEBUG
998 if (!MapProvenSorted) {
999 assert(llvm::is_sorted(IntrinsicMap));
1000 MapProvenSorted = true;
1001 }
1002#endif
1003
1004 const IntrinsicInfo *Builtin = llvm::lower_bound(IntrinsicMap, BuiltinID);
1005
1006 if (Builtin != IntrinsicMap.end() && Builtin->BuiltinID == BuiltinID)
1007 return Builtin;
1008
1009 return nullptr;
1010}
1011
1013 unsigned Modifier,
1014 llvm::Type *ArgType,
1015 const CallExpr *E) {
1016 int VectorSize = 0;
1017 if (Modifier & Use64BitVectors)
1018 VectorSize = 64;
1019 else if (Modifier & Use128BitVectors)
1020 VectorSize = 128;
1021
1022 // Return type.
1024 if (Modifier & AddRetType) {
1025 llvm::Type *Ty = ConvertType(E->getCallReturnType(getContext()));
1026 if (Modifier & VectorizeRetType)
1027 Ty = llvm::FixedVectorType::get(
1028 Ty, VectorSize ? VectorSize / Ty->getPrimitiveSizeInBits() : 1);
1029
1030 Tys.push_back(Ty);
1031 }
1032
1033 // Arguments.
1034 if (Modifier & VectorizeArgTypes) {
1035 int Elts = VectorSize ? VectorSize / ArgType->getPrimitiveSizeInBits() : 1;
1036 ArgType = llvm::FixedVectorType::get(ArgType, Elts);
1037 }
1038
1039 if (Modifier & (Add1ArgType | Add2ArgTypes))
1040 Tys.push_back(ArgType);
1041
1042 if (Modifier & Add2ArgTypes)
1043 Tys.push_back(ArgType);
1044
1045 if (Modifier & InventFloatType)
1046 Tys.push_back(FloatTy);
1047
1048 return CGM.getIntrinsic(IntrinsicID, Tys);
1049}
1050
1051//===----------------------------------------------------------------------===//
1052// Emit-helpers
1053//===----------------------------------------------------------------------===//
1055 CodeGenFunction &CGF, const ARMNeonVectorIntrinsicInfo &SISDInfo,
1056 SmallVectorImpl<Value *> &Ops, const CallExpr *E) {
1057 assert(SISDInfo.LLVMIntrinsic && "Generic code assumes a valid intrinsic");
1058
1059 switch (SISDInfo.BuiltinID) {
1060 case NEON::BI__builtin_neon_vcled_s64:
1061 case NEON::BI__builtin_neon_vcled_u64:
1062 case NEON::BI__builtin_neon_vcles_f32:
1063 case NEON::BI__builtin_neon_vcled_f64:
1064 case NEON::BI__builtin_neon_vcltd_s64:
1065 case NEON::BI__builtin_neon_vcltd_u64:
1066 case NEON::BI__builtin_neon_vclts_f32:
1067 case NEON::BI__builtin_neon_vcltd_f64:
1068 case NEON::BI__builtin_neon_vcales_f32:
1069 case NEON::BI__builtin_neon_vcaled_f64:
1070 case NEON::BI__builtin_neon_vcalts_f32:
1071 case NEON::BI__builtin_neon_vcaltd_f64:
1072 // Only one direction of comparisons actually exist, cmle is actually a cmge
1073 // with swapped operands. The table gives us the right intrinsic but we
1074 // still need to do the swap.
1075 std::swap(Ops[0], Ops[1]);
1076 break;
1077 }
1078
1079 // Use fptosi.sat/fptoui.sat unless under strict FP.
1080 unsigned LLVMIntrinsic = SISDInfo.LLVMIntrinsic;
1081 if (!CGF.Builder.getIsFPConstrained()) {
1082 if (LLVMIntrinsic == Intrinsic::aarch64_neon_fcvtzs)
1083 LLVMIntrinsic = Intrinsic::fptosi_sat;
1084 else if (LLVMIntrinsic == Intrinsic::aarch64_neon_fcvtzu)
1085 LLVMIntrinsic = Intrinsic::fptoui_sat;
1086 }
1087 llvm::Type *ArgTy = CGF.ConvertType(E->getArg(0)->getType());
1088 Function *F = CGF.LookupNeonLLVMIntrinsic(LLVMIntrinsic,
1089 SISDInfo.TypeModifier, ArgTy, E);
1090
1091 int j = 0;
1092 ConstantInt *C0 = ConstantInt::get(CGF.SizeTy, 0);
1093 for (Function::const_arg_iterator ai = F->arg_begin(), ae = F->arg_end();
1094 ai != ae; ++ai, ++j) {
1095 llvm::Type *ArgTy = ai->getType();
1096 if (Ops[j]->getType()->getPrimitiveSizeInBits() ==
1097 ArgTy->getPrimitiveSizeInBits())
1098 continue;
1099 assert(
1100 ArgTy->isVectorTy() && !Ops[j]->getType()->isVectorTy() &&
1101 "Expecting vector LLVM intrinsic type and scalar Clang builtin type!");
1102
1103 // The constant argument to an _n_ intrinsic always has Int32Ty, so truncate
1104 // it before inserting.
1105 Ops[j] = CGF.Builder.CreateTruncOrBitCast(
1106 Ops[j], cast<llvm::VectorType>(ArgTy)->getElementType());
1107 Ops[j] =
1108 CGF.Builder.CreateInsertElement(PoisonValue::get(ArgTy), Ops[j], C0);
1109 }
1110
1111 Value *Result = CGF.EmitNeonCall(F, Ops, SISDInfo.NameHint);
1112 llvm::Type *ResultType = CGF.ConvertType(E->getType());
1113 if (ResultType->getPrimitiveSizeInBits().getFixedValue() <
1114 Result->getType()->getPrimitiveSizeInBits().getFixedValue())
1115 return CGF.Builder.CreateExtractElement(Result, C0);
1116
1117 return CGF.Builder.CreateBitCast(Result, ResultType, SISDInfo.NameHint);
1118}
1119
1121 unsigned BuiltinID, unsigned LLVMIntrinsic, unsigned AltLLVMIntrinsic,
1122 const char *NameHint, unsigned Modifier, const CallExpr *E,
1123 SmallVectorImpl<llvm::Value *> &Ops, Address PtrOp0, Address PtrOp1,
1124 llvm::Triple::ArchType Arch) {
1125
1126 // Extract the trailing immediate argument that encodes the type discriminator
1127 // for this overloaded intrinsic.
1128 // TODO: Move to the parent code that takes care of argument processing.
1129 const Expr *Arg = E->getArg(E->getNumArgs() - 1);
1130 std::optional<llvm::APSInt> NeonTypeConst =
1132 if (!NeonTypeConst)
1133 return nullptr;
1134
1135 // Determine the type of this overloaded NEON intrinsic.
1136 NeonTypeFlags Type(NeonTypeConst->getZExtValue());
1137 const bool Usgn = Type.isUnsigned();
1138 const bool Quad = Type.isQuad();
1139 const bool Floating = Type.isFloatingPoint();
1140 const bool HasFastHalfType = getTarget().hasFastHalfType();
1141 const bool AllowBFloatArgsAndRet =
1142 getTargetHooks().getABIInfo().allowBFloatArgsAndRet();
1143
1144 llvm::FixedVectorType *VTy =
1145 GetNeonType(this, Type, HasFastHalfType, false, AllowBFloatArgsAndRet);
1146 llvm::Type *Ty = VTy;
1147 if (!Ty)
1148 return nullptr;
1149
1150 auto getAlignmentValue32 = [&](Address addr) -> Value* {
1151 return Builder.getInt32(addr.getAlignment().getQuantity());
1152 };
1153
1154 unsigned Int = LLVMIntrinsic;
1155 if ((Modifier & UnsignedAlts) && !Usgn)
1156 Int = AltLLVMIntrinsic;
1157
1158 switch (BuiltinID) {
1159 default: break;
1160 case NEON::BI__builtin_neon_splat_lane_v:
1161 case NEON::BI__builtin_neon_splat_laneq_v:
1162 case NEON::BI__builtin_neon_splatq_lane_v:
1163 case NEON::BI__builtin_neon_splatq_laneq_v: {
1164 auto NumElements = VTy->getElementCount();
1165 if (BuiltinID == NEON::BI__builtin_neon_splatq_lane_v)
1166 NumElements = NumElements * 2;
1167 if (BuiltinID == NEON::BI__builtin_neon_splat_laneq_v)
1168 NumElements = NumElements.divideCoefficientBy(2);
1169
1170 Ops[0] = Builder.CreateBitCast(Ops[0], VTy);
1171 return EmitNeonSplat(Ops[0], cast<ConstantInt>(Ops[1]), NumElements);
1172 }
1173 case NEON::BI__builtin_neon_vpadd_v:
1174 case NEON::BI__builtin_neon_vpaddq_v:
1175 // We don't allow fp/int overloading of intrinsics.
1176 if (VTy->getElementType()->isFloatingPointTy() &&
1177 Int == Intrinsic::aarch64_neon_addp)
1178 Int = Intrinsic::aarch64_neon_faddp;
1179 break;
1180 case NEON::BI__builtin_neon_vabs_v:
1181 case NEON::BI__builtin_neon_vabsq_v:
1182 if (VTy->getElementType()->isFloatingPointTy())
1183 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::fabs, Ty), Ops, "vabs");
1184 return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Ty), Ops, "vabs");
1185 case NEON::BI__builtin_neon_vadd_v:
1186 case NEON::BI__builtin_neon_vaddq_v: {
1187 llvm::Type *VTy = llvm::FixedVectorType::get(Int8Ty, Quad ? 16 : 8);
1188 Ops[0] = Builder.CreateBitCast(Ops[0], VTy);
1189 Ops[1] = Builder.CreateBitCast(Ops[1], VTy);
1190 Ops[0] = Builder.CreateXor(Ops[0], Ops[1]);
1191 return Builder.CreateBitCast(Ops[0], Ty);
1192 }
1193 case NEON::BI__builtin_neon_vaddhn_v: {
1194 llvm::FixedVectorType *SrcTy =
1195 llvm::FixedVectorType::getExtendedElementVectorType(VTy);
1196
1197 // %sum = add <4 x i32> %lhs, %rhs
1198 Ops[0] = Builder.CreateBitCast(Ops[0], SrcTy);
1199 Ops[1] = Builder.CreateBitCast(Ops[1], SrcTy);
1200 Ops[0] = Builder.CreateAdd(Ops[0], Ops[1], "vaddhn");
1201
1202 // %high = lshr <4 x i32> %sum, <i32 16, i32 16, i32 16, i32 16>
1203 Constant *ShiftAmt =
1204 ConstantInt::get(SrcTy, SrcTy->getScalarSizeInBits() / 2);
1205 Ops[0] = Builder.CreateLShr(Ops[0], ShiftAmt, "vaddhn");
1206
1207 // %res = trunc <4 x i32> %high to <4 x i16>
1208 return Builder.CreateTrunc(Ops[0], VTy, "vaddhn");
1209 }
1210 case NEON::BI__builtin_neon_vcale_v:
1211 case NEON::BI__builtin_neon_vcaleq_v:
1212 case NEON::BI__builtin_neon_vcalt_v:
1213 case NEON::BI__builtin_neon_vcaltq_v:
1214 std::swap(Ops[0], Ops[1]);
1215 [[fallthrough]];
1216 case NEON::BI__builtin_neon_vcage_v:
1217 case NEON::BI__builtin_neon_vcageq_v:
1218 case NEON::BI__builtin_neon_vcagt_v:
1219 case NEON::BI__builtin_neon_vcagtq_v: {
1220 llvm::Type *Ty;
1221 switch (VTy->getScalarSizeInBits()) {
1222 default: llvm_unreachable("unexpected type");
1223 case 32:
1224 Ty = FloatTy;
1225 break;
1226 case 64:
1227 Ty = DoubleTy;
1228 break;
1229 case 16:
1230 Ty = HalfTy;
1231 break;
1232 }
1233 auto *VecFlt = llvm::FixedVectorType::get(Ty, VTy->getNumElements());
1234 llvm::Type *Tys[] = { VTy, VecFlt };
1235 Function *F = CGM.getIntrinsic(LLVMIntrinsic, Tys);
1236 return EmitNeonCall(F, Ops, NameHint);
1237 }
1238 case NEON::BI__builtin_neon_vceqz_v:
1239 case NEON::BI__builtin_neon_vceqzq_v:
1241 Ops[0], Ty, Floating ? ICmpInst::FCMP_OEQ : ICmpInst::ICMP_EQ, "vceqz");
1242 case NEON::BI__builtin_neon_vcgez_v:
1243 case NEON::BI__builtin_neon_vcgezq_v:
1245 Ops[0], Ty, Floating ? ICmpInst::FCMP_OGE : ICmpInst::ICMP_SGE,
1246 "vcgez");
1247 case NEON::BI__builtin_neon_vclez_v:
1248 case NEON::BI__builtin_neon_vclezq_v:
1250 Ops[0], Ty, Floating ? ICmpInst::FCMP_OLE : ICmpInst::ICMP_SLE,
1251 "vclez");
1252 case NEON::BI__builtin_neon_vcgtz_v:
1253 case NEON::BI__builtin_neon_vcgtzq_v:
1255 Ops[0], Ty, Floating ? ICmpInst::FCMP_OGT : ICmpInst::ICMP_SGT,
1256 "vcgtz");
1257 case NEON::BI__builtin_neon_vcltz_v:
1258 case NEON::BI__builtin_neon_vcltzq_v:
1260 Ops[0], Ty, Floating ? ICmpInst::FCMP_OLT : ICmpInst::ICMP_SLT,
1261 "vcltz");
1262 case NEON::BI__builtin_neon_vclz_v:
1263 case NEON::BI__builtin_neon_vclzq_v:
1264 // We generate target-independent intrinsic, which needs a second argument
1265 // for whether or not clz of zero is undefined; on ARM it isn't.
1266 Ops.push_back(Builder.getInt1(getTarget().isCLZForZeroUndef()));
1267 break;
1268 case NEON::BI__builtin_neon_vcvt_f32_v:
1269 case NEON::BI__builtin_neon_vcvtq_f32_v:
1270 Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
1271 Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, Quad),
1272 HasFastHalfType);
1273 return Usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
1274 : Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
1275 case NEON::BI__builtin_neon_vcvt_f16_s16:
1276 case NEON::BI__builtin_neon_vcvt_f16_u16:
1277 case NEON::BI__builtin_neon_vcvtq_f16_s16:
1278 case NEON::BI__builtin_neon_vcvtq_f16_u16:
1279 Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
1280 Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float16, false, Quad),
1281 HasFastHalfType);
1282 return Usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
1283 : Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
1284 case NEON::BI__builtin_neon_vcvt_n_f16_s16:
1285 case NEON::BI__builtin_neon_vcvt_n_f16_u16:
1286 case NEON::BI__builtin_neon_vcvtq_n_f16_s16:
1287 case NEON::BI__builtin_neon_vcvtq_n_f16_u16: {
1288 llvm::Type *Tys[2] = { GetFloatNeonType(this, Type), Ty };
1289 Function *F = CGM.getIntrinsic(Int, Tys);
1290 return EmitNeonCall(F, Ops, "vcvt_n");
1291 }
1292 case NEON::BI__builtin_neon_vcvt_n_f32_v:
1293 case NEON::BI__builtin_neon_vcvt_n_f64_v:
1294 case NEON::BI__builtin_neon_vcvtq_n_f32_v:
1295 case NEON::BI__builtin_neon_vcvtq_n_f64_v: {
1296 llvm::Type *Tys[2] = { GetFloatNeonType(this, Type), Ty };
1297 Int = Usgn ? LLVMIntrinsic : AltLLVMIntrinsic;
1298 Function *F = CGM.getIntrinsic(Int, Tys);
1299 return EmitNeonCall(F, Ops, "vcvt_n");
1300 }
1301 case NEON::BI__builtin_neon_vcvt_n_s16_f16:
1302 case NEON::BI__builtin_neon_vcvt_n_s32_v:
1303 case NEON::BI__builtin_neon_vcvt_n_u16_f16:
1304 case NEON::BI__builtin_neon_vcvt_n_u32_v:
1305 case NEON::BI__builtin_neon_vcvt_n_s64_v:
1306 case NEON::BI__builtin_neon_vcvt_n_u64_v:
1307 case NEON::BI__builtin_neon_vcvtq_n_s16_f16:
1308 case NEON::BI__builtin_neon_vcvtq_n_s32_v:
1309 case NEON::BI__builtin_neon_vcvtq_n_u16_f16:
1310 case NEON::BI__builtin_neon_vcvtq_n_u32_v:
1311 case NEON::BI__builtin_neon_vcvtq_n_s64_v:
1312 case NEON::BI__builtin_neon_vcvtq_n_u64_v: {
1313 llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) };
1314 Function *F = CGM.getIntrinsic(LLVMIntrinsic, Tys);
1315 return EmitNeonCall(F, Ops, "vcvt_n");
1316 }
1317 case NEON::BI__builtin_neon_vcvt_s32_v:
1318 case NEON::BI__builtin_neon_vcvt_u32_v:
1319 case NEON::BI__builtin_neon_vcvt_s64_v:
1320 case NEON::BI__builtin_neon_vcvt_u64_v:
1321 case NEON::BI__builtin_neon_vcvt_s16_f16:
1322 case NEON::BI__builtin_neon_vcvt_u16_f16:
1323 case NEON::BI__builtin_neon_vcvtq_s32_v:
1324 case NEON::BI__builtin_neon_vcvtq_u32_v:
1325 case NEON::BI__builtin_neon_vcvtq_s64_v:
1326 case NEON::BI__builtin_neon_vcvtq_u64_v:
1327 case NEON::BI__builtin_neon_vcvtq_s16_f16:
1328 case NEON::BI__builtin_neon_vcvtq_u16_f16: {
1329 Ops[0] = Builder.CreateBitCast(Ops[0], GetFloatNeonType(this, Type));
1330 if (Int) {
1331 // AArch64: use fptosi.sat/fptoui.sat unless under strict FP.
1332 if (!Builder.getIsFPConstrained())
1333 Int = Usgn ? Intrinsic::fptoui_sat : Intrinsic::fptosi_sat;
1334 llvm::Type *Tys[2] = {Ty, Ops[0]->getType()};
1335 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtz");
1336 }
1337 // FIXME: ARM uses plain fptoui/fptosi which have UB on out-of-range
1338 // values. These should also use saturating intrinsics.
1339 return Usgn ? Builder.CreateFPToUI(Ops[0], Ty, "vcvt")
1340 : Builder.CreateFPToSI(Ops[0], Ty, "vcvt");
1341 }
1342 case NEON::BI__builtin_neon_vcvta_s16_f16:
1343 case NEON::BI__builtin_neon_vcvta_s32_v:
1344 case NEON::BI__builtin_neon_vcvta_s64_v:
1345 case NEON::BI__builtin_neon_vcvta_u16_f16:
1346 case NEON::BI__builtin_neon_vcvta_u32_v:
1347 case NEON::BI__builtin_neon_vcvta_u64_v:
1348 case NEON::BI__builtin_neon_vcvtaq_s16_f16:
1349 case NEON::BI__builtin_neon_vcvtaq_s32_v:
1350 case NEON::BI__builtin_neon_vcvtaq_s64_v:
1351 case NEON::BI__builtin_neon_vcvtaq_u16_f16:
1352 case NEON::BI__builtin_neon_vcvtaq_u32_v:
1353 case NEON::BI__builtin_neon_vcvtaq_u64_v:
1354 case NEON::BI__builtin_neon_vcvtn_s16_f16:
1355 case NEON::BI__builtin_neon_vcvtn_s32_v:
1356 case NEON::BI__builtin_neon_vcvtn_s64_v:
1357 case NEON::BI__builtin_neon_vcvtn_u16_f16:
1358 case NEON::BI__builtin_neon_vcvtn_u32_v:
1359 case NEON::BI__builtin_neon_vcvtn_u64_v:
1360 case NEON::BI__builtin_neon_vcvtnq_s16_f16:
1361 case NEON::BI__builtin_neon_vcvtnq_s32_v:
1362 case NEON::BI__builtin_neon_vcvtnq_s64_v:
1363 case NEON::BI__builtin_neon_vcvtnq_u16_f16:
1364 case NEON::BI__builtin_neon_vcvtnq_u32_v:
1365 case NEON::BI__builtin_neon_vcvtnq_u64_v:
1366 case NEON::BI__builtin_neon_vcvtp_s16_f16:
1367 case NEON::BI__builtin_neon_vcvtp_s32_v:
1368 case NEON::BI__builtin_neon_vcvtp_s64_v:
1369 case NEON::BI__builtin_neon_vcvtp_u16_f16:
1370 case NEON::BI__builtin_neon_vcvtp_u32_v:
1371 case NEON::BI__builtin_neon_vcvtp_u64_v:
1372 case NEON::BI__builtin_neon_vcvtpq_s16_f16:
1373 case NEON::BI__builtin_neon_vcvtpq_s32_v:
1374 case NEON::BI__builtin_neon_vcvtpq_s64_v:
1375 case NEON::BI__builtin_neon_vcvtpq_u16_f16:
1376 case NEON::BI__builtin_neon_vcvtpq_u32_v:
1377 case NEON::BI__builtin_neon_vcvtpq_u64_v:
1378 case NEON::BI__builtin_neon_vcvtm_s16_f16:
1379 case NEON::BI__builtin_neon_vcvtm_s32_v:
1380 case NEON::BI__builtin_neon_vcvtm_s64_v:
1381 case NEON::BI__builtin_neon_vcvtm_u16_f16:
1382 case NEON::BI__builtin_neon_vcvtm_u32_v:
1383 case NEON::BI__builtin_neon_vcvtm_u64_v:
1384 case NEON::BI__builtin_neon_vcvtmq_s16_f16:
1385 case NEON::BI__builtin_neon_vcvtmq_s32_v:
1386 case NEON::BI__builtin_neon_vcvtmq_s64_v:
1387 case NEON::BI__builtin_neon_vcvtmq_u16_f16:
1388 case NEON::BI__builtin_neon_vcvtmq_u32_v:
1389 case NEON::BI__builtin_neon_vcvtmq_u64_v: {
1390 llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) };
1391 return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Tys), Ops, NameHint);
1392 }
1393 case NEON::BI__builtin_neon_vcvtx_f32_v: {
1394 llvm::Type *Tys[2] = { VTy->getTruncatedElementVectorType(VTy), Ty};
1395 return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Tys), Ops, NameHint);
1396
1397 }
1398 case NEON::BI__builtin_neon_vext_v:
1399 case NEON::BI__builtin_neon_vextq_v: {
1400 int CV = cast<ConstantInt>(Ops[2])->getSExtValue();
1401 SmallVector<int, 16> Indices;
1402 for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i)
1403 Indices.push_back(i+CV);
1404
1405 Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
1406 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
1407 return Builder.CreateShuffleVector(Ops[0], Ops[1], Indices, "vext");
1408 }
1409 case NEON::BI__builtin_neon_vfma_v:
1410 case NEON::BI__builtin_neon_vfmaq_v: {
1411 Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
1412 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
1413 Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
1414
1415 // NEON intrinsic puts accumulator first, unlike the LLVM fma.
1417 *this, Intrinsic::fma, Intrinsic::experimental_constrained_fma, Ty,
1418 {Ops[1], Ops[2], Ops[0]});
1419 }
1420 case NEON::BI__builtin_neon_vld1_x2_v:
1421 case NEON::BI__builtin_neon_vld1q_x2_v:
1422 case NEON::BI__builtin_neon_vld1_x3_v:
1423 case NEON::BI__builtin_neon_vld1q_x3_v:
1424 case NEON::BI__builtin_neon_vld1_x4_v:
1425 case NEON::BI__builtin_neon_vld1q_x4_v: {
1426 llvm::Type *Tys[2] = {VTy, DefaultPtrTy};
1427 Function *F = CGM.getIntrinsic(LLVMIntrinsic, Tys);
1428 Ops[1] = Builder.CreateCall(F, Ops[1], "vld1xN");
1429 return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
1430 }
1431 case NEON::BI__builtin_neon_vld1_v:
1432 case NEON::BI__builtin_neon_vld1q_v: {
1433 llvm::Type *Tys[] = {Ty, Int8PtrTy};
1434 Ops.push_back(getAlignmentValue32(PtrOp0));
1435 return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Tys), Ops, "vld1");
1436 }
1437 case NEON::BI__builtin_neon_vld2_v:
1438 case NEON::BI__builtin_neon_vld2q_v:
1439 case NEON::BI__builtin_neon_vld3_v:
1440 case NEON::BI__builtin_neon_vld3q_v:
1441 case NEON::BI__builtin_neon_vld4_v:
1442 case NEON::BI__builtin_neon_vld4q_v:
1443 case NEON::BI__builtin_neon_vld2_dup_v:
1444 case NEON::BI__builtin_neon_vld2q_dup_v:
1445 case NEON::BI__builtin_neon_vld3_dup_v:
1446 case NEON::BI__builtin_neon_vld3q_dup_v:
1447 case NEON::BI__builtin_neon_vld4_dup_v:
1448 case NEON::BI__builtin_neon_vld4q_dup_v: {
1449 llvm::Type *Tys[] = {Ty, Int8PtrTy};
1450 Function *F = CGM.getIntrinsic(LLVMIntrinsic, Tys);
1451 Value *Align = getAlignmentValue32(PtrOp1);
1452 Ops[1] = Builder.CreateCall(F, {Ops[1], Align}, NameHint);
1453 return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
1454 }
1455 case NEON::BI__builtin_neon_vld1_dup_v:
1456 case NEON::BI__builtin_neon_vld1q_dup_v: {
1457 Value *V = PoisonValue::get(Ty);
1458 PtrOp0 = PtrOp0.withElementType(VTy->getElementType());
1459 LoadInst *Ld = Builder.CreateLoad(PtrOp0);
1460 llvm::Constant *CI = ConstantInt::get(SizeTy, 0);
1461 Ops[0] = Builder.CreateInsertElement(V, Ld, CI);
1462 return EmitNeonSplat(Ops[0], CI);
1463 }
1464 case NEON::BI__builtin_neon_vld2_lane_v:
1465 case NEON::BI__builtin_neon_vld2q_lane_v:
1466 case NEON::BI__builtin_neon_vld3_lane_v:
1467 case NEON::BI__builtin_neon_vld3q_lane_v:
1468 case NEON::BI__builtin_neon_vld4_lane_v:
1469 case NEON::BI__builtin_neon_vld4q_lane_v: {
1470 llvm::Type *Tys[] = {Ty, Int8PtrTy};
1471 Function *F = CGM.getIntrinsic(LLVMIntrinsic, Tys);
1472 for (unsigned I = 2; I < Ops.size() - 1; ++I)
1473 Ops[I] = Builder.CreateBitCast(Ops[I], Ty);
1474 Ops.push_back(getAlignmentValue32(PtrOp1));
1475 Ops[1] = Builder.CreateCall(F, ArrayRef(Ops).slice(1), NameHint);
1476 return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
1477 }
1478 case NEON::BI__builtin_neon_vmovl_v: {
1479 llvm::FixedVectorType *DTy =
1480 llvm::FixedVectorType::getTruncatedElementVectorType(VTy);
1481 Ops[0] = Builder.CreateBitCast(Ops[0], DTy);
1482 if (Usgn)
1483 return Builder.CreateZExt(Ops[0], Ty, "vmovl");
1484 return Builder.CreateSExt(Ops[0], Ty, "vmovl");
1485 }
1486 case NEON::BI__builtin_neon_vmovn_v: {
1487 llvm::FixedVectorType *QTy =
1488 llvm::FixedVectorType::getExtendedElementVectorType(VTy);
1489 Ops[0] = Builder.CreateBitCast(Ops[0], QTy);
1490 return Builder.CreateTrunc(Ops[0], Ty, "vmovn");
1491 }
1492 case NEON::BI__builtin_neon_vmull_v:
1493 // FIXME: the integer vmull operations could be emitted in terms of pure
1494 // LLVM IR (2 exts followed by a mul). Unfortunately LLVM has a habit of
1495 // hoisting the exts outside loops. Until global ISel comes along that can
1496 // see through such movement this leads to bad CodeGen. So we need an
1497 // intrinsic for now.
1498 Int = Usgn ? Intrinsic::arm_neon_vmullu : Intrinsic::arm_neon_vmulls;
1499 Int = Type.isPoly() ? (unsigned)Intrinsic::arm_neon_vmullp : Int;
1500 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmull");
1501 case NEON::BI__builtin_neon_vpadal_v:
1502 case NEON::BI__builtin_neon_vpadalq_v: {
1503 // The source operand type has twice as many elements of half the size.
1504 unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits();
1505 llvm::Type *EltTy =
1506 llvm::IntegerType::get(getLLVMContext(), EltBits / 2);
1507 auto *NarrowTy =
1508 llvm::FixedVectorType::get(EltTy, VTy->getNumElements() * 2);
1509 llvm::Type *Tys[2] = { Ty, NarrowTy };
1510 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, NameHint);
1511 }
1512 case NEON::BI__builtin_neon_vpaddl_v:
1513 case NEON::BI__builtin_neon_vpaddlq_v: {
1514 // The source operand type has twice as many elements of half the size.
1515 unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits();
1516 llvm::Type *EltTy = llvm::IntegerType::get(getLLVMContext(), EltBits / 2);
1517 auto *NarrowTy =
1518 llvm::FixedVectorType::get(EltTy, VTy->getNumElements() * 2);
1519 llvm::Type *Tys[2] = { Ty, NarrowTy };
1520 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vpaddl");
1521 }
1522 case NEON::BI__builtin_neon_vqdmlal_v:
1523 case NEON::BI__builtin_neon_vqdmlsl_v: {
1524 SmallVector<Value *, 2> MulOps(Ops.begin() + 1, Ops.end());
1525 Ops[1] =
1526 EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Ty), MulOps, "vqdmlal");
1527 Ops.resize(2);
1528 return EmitNeonCall(CGM.getIntrinsic(AltLLVMIntrinsic, Ty), Ops, NameHint);
1529 }
1530 case NEON::BI__builtin_neon_vqdmulhq_lane_v:
1531 case NEON::BI__builtin_neon_vqdmulh_lane_v:
1532 case NEON::BI__builtin_neon_vqrdmulhq_lane_v:
1533 case NEON::BI__builtin_neon_vqrdmulh_lane_v: {
1534 auto *RTy = cast<llvm::FixedVectorType>(Ty);
1535 if (BuiltinID == NEON::BI__builtin_neon_vqdmulhq_lane_v ||
1536 BuiltinID == NEON::BI__builtin_neon_vqrdmulhq_lane_v)
1537 RTy = llvm::FixedVectorType::get(RTy->getElementType(),
1538 RTy->getNumElements() * 2);
1539 llvm::Type *Tys[2] = {
1540 RTy, GetNeonType(this, NeonTypeFlags(Type.getEltType(), false,
1541 /*isQuad*/ false))};
1542 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, NameHint);
1543 }
1544 case NEON::BI__builtin_neon_vqdmulhq_laneq_v:
1545 case NEON::BI__builtin_neon_vqdmulh_laneq_v:
1546 case NEON::BI__builtin_neon_vqrdmulhq_laneq_v:
1547 case NEON::BI__builtin_neon_vqrdmulh_laneq_v: {
1548 llvm::Type *Tys[2] = {
1549 Ty, GetNeonType(this, NeonTypeFlags(Type.getEltType(), false,
1550 /*isQuad*/ true))};
1551 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, NameHint);
1552 }
1553 case NEON::BI__builtin_neon_vqshl_n_v:
1554 case NEON::BI__builtin_neon_vqshlq_n_v:
1555 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshl_n",
1556 1, false);
1557 case NEON::BI__builtin_neon_vqshlu_n_v:
1558 case NEON::BI__builtin_neon_vqshluq_n_v:
1559 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshlu_n",
1560 1, false);
1561 case NEON::BI__builtin_neon_vrecpe_v:
1562 case NEON::BI__builtin_neon_vrecpeq_v:
1563 case NEON::BI__builtin_neon_vrsqrte_v:
1564 case NEON::BI__builtin_neon_vrsqrteq_v:
1565 Int = Ty->isFPOrFPVectorTy() ? LLVMIntrinsic : AltLLVMIntrinsic;
1566 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, NameHint);
1567 case NEON::BI__builtin_neon_vrndi_v:
1568 case NEON::BI__builtin_neon_vrndiq_v:
1569 Int = Builder.getIsFPConstrained()
1570 ? Intrinsic::experimental_constrained_nearbyint
1571 : Intrinsic::nearbyint;
1572 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, NameHint);
1573 case NEON::BI__builtin_neon_vrshr_n_v:
1574 case NEON::BI__builtin_neon_vrshrq_n_v:
1575 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrshr_n",
1576 1, true);
1577 case NEON::BI__builtin_neon_vsha512hq_u64:
1578 case NEON::BI__builtin_neon_vsha512h2q_u64:
1579 case NEON::BI__builtin_neon_vsha512su0q_u64:
1580 case NEON::BI__builtin_neon_vsha512su1q_u64: {
1581 Function *F = CGM.getIntrinsic(Int);
1582 return EmitNeonCall(F, Ops, "");
1583 }
1584 case NEON::BI__builtin_neon_vshl_n_v:
1585 case NEON::BI__builtin_neon_vshlq_n_v:
1586 Ops[1] = EmitNeonShiftVector(Ops[1], Ty, false);
1587 return Builder.CreateShl(Builder.CreateBitCast(Ops[0],Ty), Ops[1],
1588 "vshl_n");
1589 case NEON::BI__builtin_neon_vshll_n_v: {
1590 llvm::FixedVectorType *SrcTy =
1591 llvm::FixedVectorType::getTruncatedElementVectorType(VTy);
1592 Ops[0] = Builder.CreateBitCast(Ops[0], SrcTy);
1593 if (Usgn)
1594 Ops[0] = Builder.CreateZExt(Ops[0], VTy);
1595 else
1596 Ops[0] = Builder.CreateSExt(Ops[0], VTy);
1597 Ops[1] = EmitNeonShiftVector(Ops[1], VTy, false);
1598 return Builder.CreateShl(Ops[0], Ops[1], "vshll_n");
1599 }
1600 case NEON::BI__builtin_neon_vshrn_n_v: {
1601 llvm::FixedVectorType *SrcTy =
1602 llvm::FixedVectorType::getExtendedElementVectorType(VTy);
1603 Ops[0] = Builder.CreateBitCast(Ops[0], SrcTy);
1604 Ops[1] = EmitNeonShiftVector(Ops[1], SrcTy, false);
1605 if (Usgn)
1606 Ops[0] = Builder.CreateLShr(Ops[0], Ops[1]);
1607 else
1608 Ops[0] = Builder.CreateAShr(Ops[0], Ops[1]);
1609 return Builder.CreateTrunc(Ops[0], Ty, "vshrn_n");
1610 }
1611 case NEON::BI__builtin_neon_vshr_n_v:
1612 case NEON::BI__builtin_neon_vshrq_n_v:
1613 return EmitNeonRShiftImm(Ops[0], Ops[1], Ty, Usgn, "vshr_n");
1614 case NEON::BI__builtin_neon_vst1_v:
1615 case NEON::BI__builtin_neon_vst1q_v:
1616 case NEON::BI__builtin_neon_vst2_v:
1617 case NEON::BI__builtin_neon_vst2q_v:
1618 case NEON::BI__builtin_neon_vst3_v:
1619 case NEON::BI__builtin_neon_vst3q_v:
1620 case NEON::BI__builtin_neon_vst4_v:
1621 case NEON::BI__builtin_neon_vst4q_v:
1622 case NEON::BI__builtin_neon_vst2_lane_v:
1623 case NEON::BI__builtin_neon_vst2q_lane_v:
1624 case NEON::BI__builtin_neon_vst3_lane_v:
1625 case NEON::BI__builtin_neon_vst3q_lane_v:
1626 case NEON::BI__builtin_neon_vst4_lane_v:
1627 case NEON::BI__builtin_neon_vst4q_lane_v: {
1628 llvm::Type *Tys[] = {Int8PtrTy, Ty};
1629 Ops.push_back(getAlignmentValue32(PtrOp0));
1630 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "");
1631 }
1632 case NEON::BI__builtin_neon_vsm3partw1q_u32:
1633 case NEON::BI__builtin_neon_vsm3partw2q_u32:
1634 case NEON::BI__builtin_neon_vsm3ss1q_u32:
1635 case NEON::BI__builtin_neon_vsm4ekeyq_u32:
1636 case NEON::BI__builtin_neon_vsm4eq_u32: {
1637 Function *F = CGM.getIntrinsic(Int);
1638 return EmitNeonCall(F, Ops, "");
1639 }
1640 case NEON::BI__builtin_neon_vsm3tt1aq_u32:
1641 case NEON::BI__builtin_neon_vsm3tt1bq_u32:
1642 case NEON::BI__builtin_neon_vsm3tt2aq_u32:
1643 case NEON::BI__builtin_neon_vsm3tt2bq_u32: {
1644 Function *F = CGM.getIntrinsic(Int);
1645 Ops[3] = Builder.CreateZExt(Ops[3], Int64Ty);
1646 return EmitNeonCall(F, Ops, "");
1647 }
1648 case NEON::BI__builtin_neon_vst1_x2_v:
1649 case NEON::BI__builtin_neon_vst1q_x2_v:
1650 case NEON::BI__builtin_neon_vst1_x3_v:
1651 case NEON::BI__builtin_neon_vst1q_x3_v:
1652 case NEON::BI__builtin_neon_vst1_x4_v:
1653 case NEON::BI__builtin_neon_vst1q_x4_v: {
1654 // TODO: Currently in AArch32 mode the pointer operand comes first, whereas
1655 // in AArch64 it comes last. We may want to stick to one or another.
1656 if (Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be ||
1657 Arch == llvm::Triple::aarch64_32) {
1658 llvm::Type *Tys[2] = {VTy, DefaultPtrTy};
1659 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());
1660 return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Tys), Ops, "");
1661 }
1662 llvm::Type *Tys[2] = {DefaultPtrTy, VTy};
1663 return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Tys), Ops, "");
1664 }
1665 case NEON::BI__builtin_neon_vsubhn_v: {
1666 llvm::FixedVectorType *SrcTy =
1667 llvm::FixedVectorType::getExtendedElementVectorType(VTy);
1668
1669 // %sum = add <4 x i32> %lhs, %rhs
1670 Ops[0] = Builder.CreateBitCast(Ops[0], SrcTy);
1671 Ops[1] = Builder.CreateBitCast(Ops[1], SrcTy);
1672 Ops[0] = Builder.CreateSub(Ops[0], Ops[1], "vsubhn");
1673
1674 // %high = lshr <4 x i32> %sum, <i32 16, i32 16, i32 16, i32 16>
1675 Constant *ShiftAmt =
1676 ConstantInt::get(SrcTy, SrcTy->getScalarSizeInBits() / 2);
1677 Ops[0] = Builder.CreateLShr(Ops[0], ShiftAmt, "vsubhn");
1678
1679 // %res = trunc <4 x i32> %high to <4 x i16>
1680 return Builder.CreateTrunc(Ops[0], VTy, "vsubhn");
1681 }
1682 case NEON::BI__builtin_neon_vtrn_v:
1683 case NEON::BI__builtin_neon_vtrnq_v: {
1684 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
1685 Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
1686 Value *SV = nullptr;
1687
1688 for (unsigned vi = 0; vi != 2; ++vi) {
1689 SmallVector<int, 16> Indices;
1690 for (unsigned i = 0, e = VTy->getNumElements(); i != e; i += 2) {
1691 Indices.push_back(i+vi);
1692 Indices.push_back(i+e+vi);
1693 }
1694 Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
1695 SV = Builder.CreateShuffleVector(Ops[1], Ops[2], Indices, "vtrn");
1696 SV = Builder.CreateDefaultAlignedStore(SV, Addr);
1697 }
1698 return SV;
1699 }
1700 case NEON::BI__builtin_neon_vtst_v:
1701 case NEON::BI__builtin_neon_vtstq_v: {
1702 Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
1703 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
1704 Ops[0] = Builder.CreateAnd(Ops[0], Ops[1]);
1705 Ops[0] = Builder.CreateICmp(ICmpInst::ICMP_NE, Ops[0],
1706 ConstantAggregateZero::get(Ty));
1707 return Builder.CreateSExt(Ops[0], Ty, "vtst");
1708 }
1709 case NEON::BI__builtin_neon_vuzp_v:
1710 case NEON::BI__builtin_neon_vuzpq_v: {
1711 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
1712 Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
1713 Value *SV = nullptr;
1714
1715 for (unsigned vi = 0; vi != 2; ++vi) {
1716 SmallVector<int, 16> Indices;
1717 for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i)
1718 Indices.push_back(2*i+vi);
1719
1720 Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
1721 SV = Builder.CreateShuffleVector(Ops[1], Ops[2], Indices, "vuzp");
1722 SV = Builder.CreateDefaultAlignedStore(SV, Addr);
1723 }
1724 return SV;
1725 }
1726 case NEON::BI__builtin_neon_vxarq_u64: {
1727 Function *F = CGM.getIntrinsic(Int);
1728 Ops[2] = Builder.CreateZExt(Ops[2], Int64Ty);
1729 return EmitNeonCall(F, Ops, "");
1730 }
1731 case NEON::BI__builtin_neon_vzip_v:
1732 case NEON::BI__builtin_neon_vzipq_v: {
1733 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
1734 Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
1735 Value *SV = nullptr;
1736
1737 for (unsigned vi = 0; vi != 2; ++vi) {
1738 SmallVector<int, 16> Indices;
1739 for (unsigned i = 0, e = VTy->getNumElements(); i != e; i += 2) {
1740 Indices.push_back((i + vi*e) >> 1);
1741 Indices.push_back(((i + vi*e) >> 1)+e);
1742 }
1743 Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
1744 SV = Builder.CreateShuffleVector(Ops[1], Ops[2], Indices, "vzip");
1745 SV = Builder.CreateDefaultAlignedStore(SV, Addr);
1746 }
1747 return SV;
1748 }
1749 case NEON::BI__builtin_neon_vdot_s32:
1750 case NEON::BI__builtin_neon_vdot_u32:
1751 case NEON::BI__builtin_neon_vdotq_s32:
1752 case NEON::BI__builtin_neon_vdotq_u32: {
1753 auto *InputTy =
1754 llvm::FixedVectorType::get(Int8Ty, Ty->getPrimitiveSizeInBits() / 8);
1755 llvm::Type *Tys[2] = { Ty, InputTy };
1756 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vdot");
1757 }
1758 case NEON::BI__builtin_neon_vfmlal_low_f16:
1759 case NEON::BI__builtin_neon_vfmlalq_low_f16: {
1760 auto *InputTy =
1761 llvm::FixedVectorType::get(HalfTy, Ty->getPrimitiveSizeInBits() / 16);
1762 llvm::Type *Tys[2] = { Ty, InputTy };
1763 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vfmlal_low");
1764 }
1765 case NEON::BI__builtin_neon_vfmlsl_low_f16:
1766 case NEON::BI__builtin_neon_vfmlslq_low_f16: {
1767 auto *InputTy =
1768 llvm::FixedVectorType::get(HalfTy, Ty->getPrimitiveSizeInBits() / 16);
1769 llvm::Type *Tys[2] = { Ty, InputTy };
1770 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vfmlsl_low");
1771 }
1772 case NEON::BI__builtin_neon_vfmlal_high_f16:
1773 case NEON::BI__builtin_neon_vfmlalq_high_f16: {
1774 auto *InputTy =
1775 llvm::FixedVectorType::get(HalfTy, Ty->getPrimitiveSizeInBits() / 16);
1776 llvm::Type *Tys[2] = { Ty, InputTy };
1777 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vfmlal_high");
1778 }
1779 case NEON::BI__builtin_neon_vfmlsl_high_f16:
1780 case NEON::BI__builtin_neon_vfmlslq_high_f16: {
1781 auto *InputTy =
1782 llvm::FixedVectorType::get(HalfTy, Ty->getPrimitiveSizeInBits() / 16);
1783 llvm::Type *Tys[2] = { Ty, InputTy };
1784 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vfmlsl_high");
1785 }
1786 case NEON::BI__builtin_neon_vmmlaq_s32:
1787 case NEON::BI__builtin_neon_vmmlaq_u32: {
1788 auto *InputTy =
1789 llvm::FixedVectorType::get(Int8Ty, Ty->getPrimitiveSizeInBits() / 8);
1790 llvm::Type *Tys[2] = { Ty, InputTy };
1791 return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Tys), Ops, "vmmla");
1792 }
1793 case NEON::BI__builtin_neon_vmmlaq_f16:
1794 case NEON::BI__builtin_neon_vmmlaq_f32_f16: {
1795 auto *InputTy =
1796 llvm::FixedVectorType::get(HalfTy, Ty->getPrimitiveSizeInBits() / 16);
1797 llvm::Type *Tys[2] = {Ty, InputTy};
1798 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "fmmla");
1799 }
1800 case NEON::BI__builtin_neon_vusmmlaq_s32: {
1801 auto *InputTy =
1802 llvm::FixedVectorType::get(Int8Ty, Ty->getPrimitiveSizeInBits() / 8);
1803 llvm::Type *Tys[2] = { Ty, InputTy };
1804 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vusmmla");
1805 }
1806 case NEON::BI__builtin_neon_vusdot_s32:
1807 case NEON::BI__builtin_neon_vusdotq_s32: {
1808 auto *InputTy =
1809 llvm::FixedVectorType::get(Int8Ty, Ty->getPrimitiveSizeInBits() / 8);
1810 llvm::Type *Tys[2] = { Ty, InputTy };
1811 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vusdot");
1812 }
1813 case NEON::BI__builtin_neon_vbfdot_f32:
1814 case NEON::BI__builtin_neon_vbfdotq_f32: {
1815 llvm::Type *InputTy =
1816 llvm::FixedVectorType::get(BFloatTy, Ty->getPrimitiveSizeInBits() / 16);
1817 llvm::Type *Tys[2] = { Ty, InputTy };
1818 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vbfdot");
1819 }
1820 case NEON::BI__builtin_neon___a32_vcvt_bf16_f32: {
1821 llvm::Type *Tys[1] = { Ty };
1822 Function *F = CGM.getIntrinsic(Int, Tys);
1823 return EmitNeonCall(F, Ops, "vcvtfp2bf");
1824 }
1825
1826 }
1827
1828 assert(Int && "Expected valid intrinsic number");
1829
1830 // Determine the type(s) of this overloaded AArch64 intrinsic.
1831 Function *F = LookupNeonLLVMIntrinsic(Int, Modifier, Ty, E);
1832
1833 Value *Result = EmitNeonCall(F, Ops, NameHint);
1834 llvm::Type *ResultType = ConvertType(E->getType());
1835 // AArch64 intrinsic one-element vector type cast to
1836 // scalar type expected by the builtin
1837 return Builder.CreateBitCast(Result, ResultType, NameHint);
1838}
1839
1840Value *
1842 const CmpInst::Predicate Pred,
1843 const Twine &Name) {
1844
1845 if (isa<FixedVectorType>(Ty)) {
1846 // Vector types are cast to i8 vectors. Recover original type.
1847 Op = Builder.CreateBitCast(Op, Ty);
1848 }
1849
1850 Constant *zero = Constant::getNullValue(Op->getType());
1851
1852 if (CmpInst::isFPPredicate(Pred)) {
1853 if (Pred == CmpInst::FCMP_OEQ)
1854 Op = Builder.CreateFCmp(Pred, Op, zero);
1855 else
1856 Op = Builder.CreateFCmpS(Pred, Op, zero);
1857 } else {
1858 Op = Builder.CreateICmp(Pred, Op, zero);
1859 }
1860
1861 llvm::Type *ResTy = Ty;
1862 if (auto *VTy = dyn_cast<FixedVectorType>(Ty))
1863 ResTy = FixedVectorType::get(
1864 IntegerType::get(getLLVMContext(), VTy->getScalarSizeInBits()),
1865 VTy->getNumElements());
1866
1867 return Builder.CreateSExt(Op, ResTy, Name);
1868}
1869
1871 Value *ExtOp, Value *IndexOp,
1872 llvm::Type *ResTy, unsigned IntID,
1873 const char *Name) {
1875 if (ExtOp)
1876 TblOps.push_back(ExtOp);
1877
1878 // Build a vector containing sequential number like (0, 1, 2, ..., 15)
1879 SmallVector<int, 16> Indices;
1880 auto *TblTy = cast<llvm::FixedVectorType>(Ops[0]->getType());
1881 for (unsigned i = 0, e = TblTy->getNumElements(); i != e; ++i) {
1882 Indices.push_back(2*i);
1883 Indices.push_back(2*i+1);
1884 }
1885
1886 int PairPos = 0, End = Ops.size() - 1;
1887 while (PairPos < End) {
1888 TblOps.push_back(CGF.Builder.CreateShuffleVector(Ops[PairPos],
1889 Ops[PairPos+1], Indices,
1890 Name));
1891 PairPos += 2;
1892 }
1893
1894 // If there's an odd number of 64-bit lookup table, fill the high 64-bit
1895 // of the 128-bit lookup table with zero.
1896 if (PairPos == End) {
1897 Value *ZeroTbl = ConstantAggregateZero::get(TblTy);
1898 TblOps.push_back(CGF.Builder.CreateShuffleVector(Ops[PairPos],
1899 ZeroTbl, Indices, Name));
1900 }
1901
1902 Function *TblF;
1903 TblOps.push_back(IndexOp);
1904 TblF = CGF.CGM.getIntrinsic(IntID, ResTy);
1905
1906 return CGF.EmitNeonCall(TblF, TblOps, Name);
1907}
1908
1909Value *CodeGenFunction::GetValueForARMHint(unsigned BuiltinID) {
1910 unsigned Value;
1911 switch (BuiltinID) {
1912 default:
1913 return nullptr;
1914 case clang::ARM::BI__builtin_arm_nop:
1915 Value = 0;
1916 break;
1917 case clang::ARM::BI__builtin_arm_yield:
1918 case clang::ARM::BI__yield:
1919 Value = 1;
1920 break;
1921 case clang::ARM::BI__builtin_arm_wfe:
1922 case clang::ARM::BI__wfe:
1923 Value = 2;
1924 break;
1925 case clang::ARM::BI__builtin_arm_wfi:
1926 case clang::ARM::BI__wfi:
1927 Value = 3;
1928 break;
1929 case clang::ARM::BI__builtin_arm_sev:
1930 case clang::ARM::BI__sev:
1931 Value = 4;
1932 break;
1933 case clang::ARM::BI__builtin_arm_sevl:
1934 case clang::ARM::BI__sevl:
1935 Value = 5;
1936 break;
1937 }
1938
1939 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_hint),
1940 llvm::ConstantInt::get(Int32Ty, Value));
1941}
1942
1948
1949// Generates the IR for the read/write special register builtin,
1950// ValueType is the type of the value that is to be written or read,
1951// RegisterType is the type of the register being written to or read from.
1953 const CallExpr *E,
1954 llvm::Type *RegisterType,
1955 llvm::Type *ValueType,
1956 SpecialRegisterAccessKind AccessKind,
1957 StringRef SysReg = "") {
1958 // write and register intrinsics only support 32, 64 and 128 bit operations.
1959 assert((RegisterType->isIntegerTy(32) || RegisterType->isIntegerTy(64) ||
1960 RegisterType->isIntegerTy(128)) &&
1961 "Unsupported size for register.");
1962
1963 CodeGen::CGBuilderTy &Builder = CGF.Builder;
1964 CodeGen::CodeGenModule &CGM = CGF.CGM;
1965 LLVMContext &Context = CGM.getLLVMContext();
1966
1967 if (SysReg.empty()) {
1968 const Expr *SysRegStrExpr = E->getArg(0)->IgnoreParenCasts();
1969 SysReg = cast<clang::StringLiteral>(SysRegStrExpr)->getString();
1970 }
1971
1972 llvm::Metadata *Ops[] = { llvm::MDString::get(Context, SysReg) };
1973 llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
1974 llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
1975
1976 llvm::Type *Types[] = { RegisterType };
1977
1978 bool MixedTypes = RegisterType->isIntegerTy(64) && ValueType->isIntegerTy(32);
1979 assert(!(RegisterType->isIntegerTy(32) && ValueType->isIntegerTy(64))
1980 && "Can't fit 64-bit value in 32-bit register");
1981
1982 if (AccessKind != Write) {
1983 assert(AccessKind == NormalRead || AccessKind == VolatileRead);
1984 llvm::Function *F = CGM.getIntrinsic(
1985 AccessKind == VolatileRead ? Intrinsic::read_volatile_register
1986 : Intrinsic::read_register,
1987 Types);
1988 llvm::Value *Call = Builder.CreateCall(F, Metadata);
1989
1990 if (MixedTypes)
1991 // Read into 64 bit register and then truncate result to 32 bit.
1992 return Builder.CreateTrunc(Call, ValueType);
1993
1994 if (ValueType->isPointerTy())
1995 // Have i32/i64 result (Call) but want to return a VoidPtrTy (i8*).
1996 return Builder.CreateIntToPtr(Call, ValueType);
1997
1998 return Call;
1999 }
2000
2001 llvm::Function *F = CGM.getIntrinsic(Intrinsic::write_register, Types);
2002 llvm::Value *ArgValue = CGF.EmitScalarExpr(E->getArg(1));
2003 if (MixedTypes) {
2004 // Extend 32 bit write value to 64 bit to pass to write.
2005 ArgValue = Builder.CreateZExt(ArgValue, RegisterType);
2006 return Builder.CreateCall(F, { Metadata, ArgValue });
2007 }
2008
2009 if (ValueType->isPointerTy()) {
2010 // Have VoidPtrTy ArgValue but want to return an i32/i64.
2011 ArgValue = Builder.CreatePtrToInt(ArgValue, RegisterType);
2012 return Builder.CreateCall(F, { Metadata, ArgValue });
2013 }
2014
2015 return Builder.CreateCall(F, { Metadata, ArgValue });
2016}
2017
2018static Value *EmitRangePrefetchBuiltin(CodeGenFunction &CGF, unsigned BuiltinID,
2019 const CallExpr *E) {
2020 CodeGen::CGBuilderTy &Builder = CGF.Builder;
2021 CodeGen::CodeGenModule &CGM = CGF.CGM;
2023
2024 auto getIntArg = [&](unsigned ArgNo) {
2026 if (!E->getArg(ArgNo)->EvaluateAsInt(Result, CGM.getContext()))
2027 llvm_unreachable("Expected constant argument to range prefetch.");
2028 return Result.Val.getInt().getExtValue();
2029 };
2030
2031 Ops.push_back(CGF.EmitScalarExpr(E->getArg(0))); /*Addr*/
2032 Ops.push_back(CGF.EmitScalarExpr(E->getArg(1))); /*Access Kind*/
2033 Ops.push_back(CGF.EmitScalarExpr(E->getArg(2))); /*Policy*/
2034
2035 if (BuiltinID == clang::AArch64::BI__builtin_arm_range_prefetch_x) {
2036 auto Length = getIntArg(3);
2037 auto Count = getIntArg(4) - 1;
2038 auto Stride = getIntArg(5);
2039 auto Distance = getIntArg(6);
2040
2041 // Map ReuseDistance given in bytes to four bits representing decreasing
2042 // powers of two in the range 512MiB (0b0001) to 32KiB (0b1111). Values
2043 // are rounded up to the nearest power of 2, starting at 32KiB. Any value
2044 // over the maximum is represented by 0 (distance not known).
2045 if (Distance > 0) {
2046 Distance = llvm::Log2_32_Ceil(Distance);
2047 if (Distance < 15)
2048 Distance = 15;
2049 else if (Distance > 29)
2050 Distance = 0;
2051 else
2052 Distance = 30 - Distance;
2053 }
2054
2055 uint64_t Mask22 = (1ULL << 22) - 1;
2056 uint64_t Mask16 = (1ULL << 16) - 1;
2057 uint64_t Metadata = (Distance << 60) | ((Stride & Mask22) << 38) |
2058 ((Count & Mask16) << 22) | (Length & Mask22);
2059
2060 Ops.push_back(llvm::ConstantInt::get(Builder.getInt64Ty(), Metadata));
2061 } else
2062 Ops.push_back(CGF.EmitScalarExpr(E->getArg(3)));
2063
2064 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_range_prefetch),
2065 Ops);
2066}
2067
2068/// Return true if BuiltinID is an overloaded Neon intrinsic with an extra
2069/// argument that specifies the vector type. The additional argument is meant
2070/// for Sema checking (see `CheckNeonBuiltinFunctionCall`) and this function
2071/// should be kept consistent with the logic in Sema.
2072/// TODO: Make this return false for SISD builtins.
2073static bool HasExtraNeonArgument(unsigned BuiltinID) {
2074 // Required by the headers included below, but not in this particular
2075 // function.
2076 [[maybe_unused]] int PtrArgNum = -1;
2077 [[maybe_unused]] bool HasConstPtr = false;
2078
2079 // The mask encodes the type. We don't care about the actual value. Instead,
2080 // we just check whether its been set.
2081 uint64_t mask = 0;
2082 switch (BuiltinID) {
2083#define GET_NEON_OVERLOAD_CHECK
2084#include "clang/Basic/arm_fp16.inc"
2085#include "clang/Basic/arm_neon.inc"
2086#undef GET_NEON_OVERLOAD_CHECK
2087 // Non-neon builtins for controling VFP that take extra argument for
2088 // discriminating the type.
2089 case ARM::BI__builtin_arm_vcvtr_f:
2090 case ARM::BI__builtin_arm_vcvtr_d:
2091 mask = 1;
2092 }
2093
2094 if (mask)
2095 return true;
2096
2097 return false;
2098}
2099
2101 const CallExpr *E,
2103 llvm::Triple::ArchType Arch) {
2104 if (auto Hint = GetValueForARMHint(BuiltinID))
2105 return Hint;
2106
2107 if (BuiltinID == clang::ARM::BI__emit) {
2108 bool IsThumb = getTarget().getTriple().getArch() == llvm::Triple::thumb;
2109 llvm::FunctionType *FTy =
2110 llvm::FunctionType::get(VoidTy, /*Variadic=*/false);
2111
2113 if (!E->getArg(0)->EvaluateAsInt(Result, CGM.getContext()))
2114 llvm_unreachable("Sema will ensure that the parameter is constant");
2115
2116 llvm::APSInt Value = Result.Val.getInt();
2117 uint64_t ZExtValue = Value.zextOrTrunc(IsThumb ? 16 : 32).getZExtValue();
2118
2119 llvm::InlineAsm *Emit =
2120 IsThumb ? InlineAsm::get(FTy, ".inst.n 0x" + utohexstr(ZExtValue), "",
2121 /*hasSideEffects=*/true)
2122 : InlineAsm::get(FTy, ".inst 0x" + utohexstr(ZExtValue), "",
2123 /*hasSideEffects=*/true);
2124
2125 return Builder.CreateCall(Emit);
2126 }
2127
2128 if (BuiltinID == clang::ARM::BI__builtin_arm_dbg) {
2129 Value *Option = EmitScalarExpr(E->getArg(0));
2130 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_dbg), Option);
2131 }
2132
2133 if (BuiltinID == clang::ARM::BI__builtin_arm_prefetch) {
2135 Value *RW = EmitScalarExpr(E->getArg(1));
2136 Value *IsData = EmitScalarExpr(E->getArg(2));
2137
2138 // Locality is not supported on ARM target
2139 Value *Locality = llvm::ConstantInt::get(Int32Ty, 3);
2140
2141 Function *F = CGM.getIntrinsic(Intrinsic::prefetch, Address->getType());
2142 return Builder.CreateCall(F, {Address, RW, Locality, IsData});
2143 }
2144
2145 if (BuiltinID == clang::ARM::BI__builtin_arm_rbit) {
2146 llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
2147 return Builder.CreateCall(
2148 CGM.getIntrinsic(Intrinsic::bitreverse, Arg->getType()), Arg, "rbit");
2149 }
2150
2151 if (BuiltinID == clang::ARM::BI__builtin_arm_clz ||
2152 BuiltinID == clang::ARM::BI__builtin_arm_clz64) {
2153 llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
2154 Function *F = CGM.getIntrinsic(Intrinsic::ctlz, Arg->getType());
2155 Value *Res = Builder.CreateCall(F, {Arg, Builder.getInt1(false)});
2156 if (BuiltinID == clang::ARM::BI__builtin_arm_clz64)
2157 Res = Builder.CreateTrunc(Res, Builder.getInt32Ty());
2158 return Res;
2159 }
2160
2161
2162 if (BuiltinID == clang::ARM::BI__builtin_arm_cls) {
2163 llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
2164 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_cls), Arg, "cls");
2165 }
2166 if (BuiltinID == clang::ARM::BI__builtin_arm_cls64) {
2167 llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
2168 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_cls64), Arg,
2169 "cls");
2170 }
2171
2172 if (BuiltinID == clang::ARM::BI__clear_cache) {
2173 Value *Begin = EmitScalarExpr(E->getArg(0));
2174 Value *End = EmitScalarExpr(E->getArg(1));
2175 Function *F = CGM.getIntrinsic(Intrinsic::clear_cache, {CGM.DefaultPtrTy});
2176 return Builder.CreateCall(F, {Begin, End});
2177 }
2178
2179 if (BuiltinID == clang::ARM::BI__builtin_arm_mcrr ||
2180 BuiltinID == clang::ARM::BI__builtin_arm_mcrr2) {
2181 Function *F;
2182
2183 switch (BuiltinID) {
2184 default: llvm_unreachable("unexpected builtin");
2185 case clang::ARM::BI__builtin_arm_mcrr:
2186 F = CGM.getIntrinsic(Intrinsic::arm_mcrr);
2187 break;
2188 case clang::ARM::BI__builtin_arm_mcrr2:
2189 F = CGM.getIntrinsic(Intrinsic::arm_mcrr2);
2190 break;
2191 }
2192
2193 // MCRR{2} instruction has 5 operands but
2194 // the intrinsic has 4 because Rt and Rt2
2195 // are represented as a single unsigned 64
2196 // bit integer in the intrinsic definition
2197 // but internally it's represented as 2 32
2198 // bit integers.
2199
2200 Value *Coproc = EmitScalarExpr(E->getArg(0));
2201 Value *Opc1 = EmitScalarExpr(E->getArg(1));
2202 Value *RtAndRt2 = EmitScalarExpr(E->getArg(2));
2203 Value *CRm = EmitScalarExpr(E->getArg(3));
2204
2205 Value *C1 = llvm::ConstantInt::get(Int64Ty, 32);
2206 Value *Rt = Builder.CreateTruncOrBitCast(RtAndRt2, Int32Ty);
2207 Value *Rt2 = Builder.CreateLShr(RtAndRt2, C1);
2208 Rt2 = Builder.CreateTruncOrBitCast(Rt2, Int32Ty);
2209
2210 return Builder.CreateCall(F, {Coproc, Opc1, Rt, Rt2, CRm});
2211 }
2212
2213 if (BuiltinID == clang::ARM::BI__builtin_arm_mrrc ||
2214 BuiltinID == clang::ARM::BI__builtin_arm_mrrc2) {
2215 Function *F;
2216
2217 switch (BuiltinID) {
2218 default: llvm_unreachable("unexpected builtin");
2219 case clang::ARM::BI__builtin_arm_mrrc:
2220 F = CGM.getIntrinsic(Intrinsic::arm_mrrc);
2221 break;
2222 case clang::ARM::BI__builtin_arm_mrrc2:
2223 F = CGM.getIntrinsic(Intrinsic::arm_mrrc2);
2224 break;
2225 }
2226
2227 Value *Coproc = EmitScalarExpr(E->getArg(0));
2228 Value *Opc1 = EmitScalarExpr(E->getArg(1));
2229 Value *CRm = EmitScalarExpr(E->getArg(2));
2230 Value *RtAndRt2 = Builder.CreateCall(F, {Coproc, Opc1, CRm});
2231
2232 // Returns an unsigned 64 bit integer, represented
2233 // as two 32 bit integers.
2234
2235 Value *Rt = Builder.CreateExtractValue(RtAndRt2, 1);
2236 Value *Rt1 = Builder.CreateExtractValue(RtAndRt2, 0);
2237 Rt = Builder.CreateZExt(Rt, Int64Ty);
2238 Rt1 = Builder.CreateZExt(Rt1, Int64Ty);
2239
2240 Value *ShiftCast = llvm::ConstantInt::get(Int64Ty, 32);
2241 RtAndRt2 = Builder.CreateShl(Rt, ShiftCast, "shl", true);
2242 RtAndRt2 = Builder.CreateOr(RtAndRt2, Rt1);
2243
2244 return Builder.CreateBitCast(RtAndRt2, ConvertType(E->getType()));
2245 }
2246
2247 if (BuiltinID == clang::ARM::BI__builtin_arm_ldrexd ||
2248 ((BuiltinID == clang::ARM::BI__builtin_arm_ldrex ||
2249 BuiltinID == clang::ARM::BI__builtin_arm_ldaex) &&
2250 getContext().getTypeSize(E->getType()) == 64) ||
2251 BuiltinID == clang::ARM::BI__ldrexd) {
2252 Function *F;
2253
2254 switch (BuiltinID) {
2255 default: llvm_unreachable("unexpected builtin");
2256 case clang::ARM::BI__builtin_arm_ldaex:
2257 F = CGM.getIntrinsic(Intrinsic::arm_ldaexd);
2258 break;
2259 case clang::ARM::BI__builtin_arm_ldrexd:
2260 case clang::ARM::BI__builtin_arm_ldrex:
2261 case clang::ARM::BI__ldrexd:
2262 F = CGM.getIntrinsic(Intrinsic::arm_ldrexd);
2263 break;
2264 }
2265
2266 Value *LdPtr = EmitScalarExpr(E->getArg(0));
2267 Value *Val = Builder.CreateCall(F, LdPtr, "ldrexd");
2268
2269 Value *Val0 = Builder.CreateExtractValue(Val, 1);
2270 Value *Val1 = Builder.CreateExtractValue(Val, 0);
2271 Val0 = Builder.CreateZExt(Val0, Int64Ty);
2272 Val1 = Builder.CreateZExt(Val1, Int64Ty);
2273
2274 Value *ShiftCst = llvm::ConstantInt::get(Int64Ty, 32);
2275 Val = Builder.CreateShl(Val0, ShiftCst, "shl", true /* nuw */);
2276 Val = Builder.CreateOr(Val, Val1);
2277 return Builder.CreateBitCast(Val, ConvertType(E->getType()));
2278 }
2279
2280 if (BuiltinID == clang::ARM::BI__builtin_arm_ldrex ||
2281 BuiltinID == clang::ARM::BI__builtin_arm_ldaex) {
2282 Value *LoadAddr = EmitScalarExpr(E->getArg(0));
2283
2284 QualType Ty = E->getType();
2285 llvm::Type *RealResTy = ConvertType(Ty);
2286 llvm::Type *IntTy =
2287 llvm::IntegerType::get(getLLVMContext(), getContext().getTypeSize(Ty));
2288
2289 Function *F = CGM.getIntrinsic(
2290 BuiltinID == clang::ARM::BI__builtin_arm_ldaex ? Intrinsic::arm_ldaex
2291 : Intrinsic::arm_ldrex,
2292 DefaultPtrTy);
2293 CallInst *Val = Builder.CreateCall(F, LoadAddr, "ldrex");
2294 Val->addParamAttr(
2295 0, Attribute::get(getLLVMContext(), Attribute::ElementType, IntTy));
2296
2297 if (RealResTy->isPointerTy())
2298 return Builder.CreateIntToPtr(Val, RealResTy);
2299 else {
2300 llvm::Type *IntResTy = llvm::IntegerType::get(
2301 getLLVMContext(), CGM.getDataLayout().getTypeSizeInBits(RealResTy));
2302 return Builder.CreateBitCast(Builder.CreateTruncOrBitCast(Val, IntResTy),
2303 RealResTy);
2304 }
2305 }
2306
2307 if (BuiltinID == clang::ARM::BI__builtin_arm_strexd ||
2308 ((BuiltinID == clang::ARM::BI__builtin_arm_stlex ||
2309 BuiltinID == clang::ARM::BI__builtin_arm_strex) &&
2310 getContext().getTypeSize(E->getArg(0)->getType()) == 64)) {
2311 Function *F = CGM.getIntrinsic(
2312 BuiltinID == clang::ARM::BI__builtin_arm_stlex ? Intrinsic::arm_stlexd
2313 : Intrinsic::arm_strexd);
2314 llvm::Type *STy = llvm::StructType::get(Int32Ty, Int32Ty);
2315
2317 Value *Val = EmitScalarExpr(E->getArg(0));
2318 Builder.CreateStore(Val, Tmp);
2319
2320 Address LdPtr = Tmp.withElementType(STy);
2321 Val = Builder.CreateLoad(LdPtr);
2322
2323 Value *Arg0 = Builder.CreateExtractValue(Val, 0);
2324 Value *Arg1 = Builder.CreateExtractValue(Val, 1);
2325 Value *StPtr = EmitScalarExpr(E->getArg(1));
2326 return Builder.CreateCall(F, {Arg0, Arg1, StPtr}, "strexd");
2327 }
2328
2329 if (BuiltinID == clang::ARM::BI__builtin_arm_strex ||
2330 BuiltinID == clang::ARM::BI__builtin_arm_stlex) {
2331 Value *StoreVal = EmitScalarExpr(E->getArg(0));
2332 Value *StoreAddr = EmitScalarExpr(E->getArg(1));
2333
2334 QualType Ty = E->getArg(0)->getType();
2335 llvm::Type *StoreTy =
2336 llvm::IntegerType::get(getLLVMContext(), getContext().getTypeSize(Ty));
2337
2338 if (StoreVal->getType()->isPointerTy())
2339 StoreVal = Builder.CreatePtrToInt(StoreVal, Int32Ty);
2340 else {
2341 llvm::Type *IntTy = llvm::IntegerType::get(
2343 CGM.getDataLayout().getTypeSizeInBits(StoreVal->getType()));
2344 StoreVal = Builder.CreateBitCast(StoreVal, IntTy);
2345 StoreVal = Builder.CreateZExtOrBitCast(StoreVal, Int32Ty);
2346 }
2347
2348 Function *F = CGM.getIntrinsic(
2349 BuiltinID == clang::ARM::BI__builtin_arm_stlex ? Intrinsic::arm_stlex
2350 : Intrinsic::arm_strex,
2351 StoreAddr->getType());
2352
2353 CallInst *CI = Builder.CreateCall(F, {StoreVal, StoreAddr}, "strex");
2354 CI->addParamAttr(
2355 1, Attribute::get(getLLVMContext(), Attribute::ElementType, StoreTy));
2356 return CI;
2357 }
2358
2359 if (BuiltinID == clang::ARM::BI__builtin_arm_clrex) {
2360 Function *F = CGM.getIntrinsic(Intrinsic::arm_clrex);
2361 return Builder.CreateCall(F);
2362 }
2363
2364 // CRC32
2365 Intrinsic::ID CRCIntrinsicID = Intrinsic::not_intrinsic;
2366 switch (BuiltinID) {
2367 case clang::ARM::BI__builtin_arm_crc32b:
2368 CRCIntrinsicID = Intrinsic::arm_crc32b; break;
2369 case clang::ARM::BI__builtin_arm_crc32cb:
2370 CRCIntrinsicID = Intrinsic::arm_crc32cb; break;
2371 case clang::ARM::BI__builtin_arm_crc32h:
2372 CRCIntrinsicID = Intrinsic::arm_crc32h; break;
2373 case clang::ARM::BI__builtin_arm_crc32ch:
2374 CRCIntrinsicID = Intrinsic::arm_crc32ch; break;
2375 case clang::ARM::BI__builtin_arm_crc32w:
2376 case clang::ARM::BI__builtin_arm_crc32d:
2377 CRCIntrinsicID = Intrinsic::arm_crc32w; break;
2378 case clang::ARM::BI__builtin_arm_crc32cw:
2379 case clang::ARM::BI__builtin_arm_crc32cd:
2380 CRCIntrinsicID = Intrinsic::arm_crc32cw; break;
2381 }
2382
2383 if (CRCIntrinsicID != Intrinsic::not_intrinsic) {
2384 Value *Arg0 = EmitScalarExpr(E->getArg(0));
2385 Value *Arg1 = EmitScalarExpr(E->getArg(1));
2386
2387 // crc32{c,}d intrinsics are implemented as two calls to crc32{c,}w
2388 // intrinsics, hence we need different codegen for these cases.
2389 if (BuiltinID == clang::ARM::BI__builtin_arm_crc32d ||
2390 BuiltinID == clang::ARM::BI__builtin_arm_crc32cd) {
2391 Value *C1 = llvm::ConstantInt::get(Int64Ty, 32);
2392 Value *Arg1a = Builder.CreateTruncOrBitCast(Arg1, Int32Ty);
2393 Value *Arg1b = Builder.CreateLShr(Arg1, C1);
2394 Arg1b = Builder.CreateTruncOrBitCast(Arg1b, Int32Ty);
2395
2396 Function *F = CGM.getIntrinsic(CRCIntrinsicID);
2397 Value *Res = Builder.CreateCall(F, {Arg0, Arg1a});
2398 return Builder.CreateCall(F, {Res, Arg1b});
2399 } else {
2400 Arg1 = Builder.CreateZExtOrBitCast(Arg1, Int32Ty);
2401
2402 Function *F = CGM.getIntrinsic(CRCIntrinsicID);
2403 return Builder.CreateCall(F, {Arg0, Arg1});
2404 }
2405 }
2406
2407 if (BuiltinID == clang::ARM::BI__builtin_arm_rsr ||
2408 BuiltinID == clang::ARM::BI__builtin_arm_rsr64 ||
2409 BuiltinID == clang::ARM::BI__builtin_arm_rsrp ||
2410 BuiltinID == clang::ARM::BI__builtin_arm_wsr ||
2411 BuiltinID == clang::ARM::BI__builtin_arm_wsr64 ||
2412 BuiltinID == clang::ARM::BI__builtin_arm_wsrp) {
2413
2414 SpecialRegisterAccessKind AccessKind = Write;
2415 if (BuiltinID == clang::ARM::BI__builtin_arm_rsr ||
2416 BuiltinID == clang::ARM::BI__builtin_arm_rsr64 ||
2417 BuiltinID == clang::ARM::BI__builtin_arm_rsrp)
2418 AccessKind = VolatileRead;
2419
2420 bool IsPointerBuiltin = BuiltinID == clang::ARM::BI__builtin_arm_rsrp ||
2421 BuiltinID == clang::ARM::BI__builtin_arm_wsrp;
2422
2423 bool Is64Bit = BuiltinID == clang::ARM::BI__builtin_arm_rsr64 ||
2424 BuiltinID == clang::ARM::BI__builtin_arm_wsr64;
2425
2426 llvm::Type *ValueType;
2427 llvm::Type *RegisterType;
2428 if (IsPointerBuiltin) {
2429 ValueType = VoidPtrTy;
2431 } else if (Is64Bit) {
2432 ValueType = RegisterType = Int64Ty;
2433 } else {
2434 ValueType = RegisterType = Int32Ty;
2435 }
2436
2437 return EmitSpecialRegisterBuiltin(*this, E, RegisterType, ValueType,
2438 AccessKind);
2439 }
2440
2441 if (BuiltinID == ARM::BI__builtin_sponentry) {
2442 llvm::Function *F = CGM.getIntrinsic(Intrinsic::sponentry, AllocaInt8PtrTy);
2443 return Builder.CreateCall(F);
2444 }
2445
2446 // Handle MSVC intrinsics before argument evaluation to prevent double
2447 // evaluation.
2448 if (std::optional<MSVCIntrin> MsvcIntId = translateArmToMsvcIntrin(BuiltinID))
2449 return EmitMSVCBuiltinExpr(*MsvcIntId, E);
2450
2451 // Deal with MVE builtins
2452 if (Value *Result = EmitARMMVEBuiltinExpr(BuiltinID, E, ReturnValue, Arch))
2453 return Result;
2454 // Handle CDE builtins
2455 if (Value *Result = EmitARMCDEBuiltinExpr(BuiltinID, E, ReturnValue, Arch))
2456 return Result;
2457
2458 // Some intrinsics are equivalent - if they are use the base intrinsic ID.
2459 auto It = llvm::find_if(NEONEquivalentIntrinsicMap, [BuiltinID](auto &P) {
2460 return P.first == BuiltinID;
2461 });
2462 if (It != end(NEONEquivalentIntrinsicMap))
2463 BuiltinID = It->second;
2464
2465 // Find out if any arguments are required to be integer constant
2466 // expressions.
2467 unsigned ICEArguments = 0;
2469 getContext().GetBuiltinType(BuiltinID, Error, &ICEArguments);
2470 assert(Error == ASTContext::GE_None && "Should not codegen an error");
2471
2472 auto getAlignmentValue32 = [&](Address addr) -> Value* {
2473 return Builder.getInt32(addr.getAlignment().getQuantity());
2474 };
2475
2476 Address PtrOp0 = Address::invalid();
2477 Address PtrOp1 = Address::invalid();
2479 bool HasExtraArg = HasExtraNeonArgument(BuiltinID);
2480 unsigned NumArgs = E->getNumArgs() - (HasExtraArg ? 1 : 0);
2481 for (unsigned i = 0, e = NumArgs; i != e; i++) {
2482 if (i == 0) {
2483 switch (BuiltinID) {
2484 case NEON::BI__builtin_neon_vld1_v:
2485 case NEON::BI__builtin_neon_vld1q_v:
2486 case NEON::BI__builtin_neon_vld1q_lane_v:
2487 case NEON::BI__builtin_neon_vld1_lane_v:
2488 case NEON::BI__builtin_neon_vld1_dup_v:
2489 case NEON::BI__builtin_neon_vld1q_dup_v:
2490 case NEON::BI__builtin_neon_vst1_v:
2491 case NEON::BI__builtin_neon_vst1q_v:
2492 case NEON::BI__builtin_neon_vst1q_lane_v:
2493 case NEON::BI__builtin_neon_vst1_lane_v:
2494 case NEON::BI__builtin_neon_vst2_v:
2495 case NEON::BI__builtin_neon_vst2q_v:
2496 case NEON::BI__builtin_neon_vst2_lane_v:
2497 case NEON::BI__builtin_neon_vst2q_lane_v:
2498 case NEON::BI__builtin_neon_vst3_v:
2499 case NEON::BI__builtin_neon_vst3q_v:
2500 case NEON::BI__builtin_neon_vst3_lane_v:
2501 case NEON::BI__builtin_neon_vst3q_lane_v:
2502 case NEON::BI__builtin_neon_vst4_v:
2503 case NEON::BI__builtin_neon_vst4q_v:
2504 case NEON::BI__builtin_neon_vst4_lane_v:
2505 case NEON::BI__builtin_neon_vst4q_lane_v:
2506 // Get the alignment for the argument in addition to the value;
2507 // we'll use it later.
2508 PtrOp0 = EmitPointerWithAlignment(E->getArg(0));
2509 Ops.push_back(PtrOp0.emitRawPointer(*this));
2510 continue;
2511 }
2512 }
2513 if (i == 1) {
2514 switch (BuiltinID) {
2515 case NEON::BI__builtin_neon_vld2_v:
2516 case NEON::BI__builtin_neon_vld2q_v:
2517 case NEON::BI__builtin_neon_vld3_v:
2518 case NEON::BI__builtin_neon_vld3q_v:
2519 case NEON::BI__builtin_neon_vld4_v:
2520 case NEON::BI__builtin_neon_vld4q_v:
2521 case NEON::BI__builtin_neon_vld2_lane_v:
2522 case NEON::BI__builtin_neon_vld2q_lane_v:
2523 case NEON::BI__builtin_neon_vld3_lane_v:
2524 case NEON::BI__builtin_neon_vld3q_lane_v:
2525 case NEON::BI__builtin_neon_vld4_lane_v:
2526 case NEON::BI__builtin_neon_vld4q_lane_v:
2527 case NEON::BI__builtin_neon_vld2_dup_v:
2528 case NEON::BI__builtin_neon_vld2q_dup_v:
2529 case NEON::BI__builtin_neon_vld3_dup_v:
2530 case NEON::BI__builtin_neon_vld3q_dup_v:
2531 case NEON::BI__builtin_neon_vld4_dup_v:
2532 case NEON::BI__builtin_neon_vld4q_dup_v:
2533 // Get the alignment for the argument in addition to the value;
2534 // we'll use it later.
2535 PtrOp1 = EmitPointerWithAlignment(E->getArg(1));
2536 Ops.push_back(PtrOp1.emitRawPointer(*this));
2537 continue;
2538 }
2539 }
2540
2541 Ops.push_back(EmitScalarOrConstFoldImmArg(ICEArguments, i, E));
2542 }
2543
2544 switch (BuiltinID) {
2545 default: break;
2546
2547 case NEON::BI__builtin_neon_vget_lane_i8:
2548 case NEON::BI__builtin_neon_vget_lane_i16:
2549 case NEON::BI__builtin_neon_vget_lane_i32:
2550 case NEON::BI__builtin_neon_vget_lane_i64:
2551 case NEON::BI__builtin_neon_vget_lane_bf16:
2552 case NEON::BI__builtin_neon_vget_lane_f32:
2553 case NEON::BI__builtin_neon_vgetq_lane_i8:
2554 case NEON::BI__builtin_neon_vgetq_lane_i16:
2555 case NEON::BI__builtin_neon_vgetq_lane_i32:
2556 case NEON::BI__builtin_neon_vgetq_lane_i64:
2557 case NEON::BI__builtin_neon_vgetq_lane_bf16:
2558 case NEON::BI__builtin_neon_vgetq_lane_f32:
2559 case NEON::BI__builtin_neon_vduph_lane_bf16:
2560 case NEON::BI__builtin_neon_vduph_laneq_bf16:
2561 return Builder.CreateExtractElement(Ops[0], Ops[1], "vget_lane");
2562
2563 case NEON::BI__builtin_neon_vrndns_f32: {
2564 Value *Arg = EmitScalarExpr(E->getArg(0));
2565 llvm::Type *Tys[] = {Arg->getType()};
2566 Function *F = CGM.getIntrinsic(Intrinsic::roundeven, Tys);
2567 return Builder.CreateCall(F, {Arg}, "vrndn"); }
2568
2569 case NEON::BI__builtin_neon_vset_lane_i8:
2570 case NEON::BI__builtin_neon_vset_lane_i16:
2571 case NEON::BI__builtin_neon_vset_lane_i32:
2572 case NEON::BI__builtin_neon_vset_lane_i64:
2573 case NEON::BI__builtin_neon_vset_lane_bf16:
2574 case NEON::BI__builtin_neon_vset_lane_f32:
2575 case NEON::BI__builtin_neon_vsetq_lane_i8:
2576 case NEON::BI__builtin_neon_vsetq_lane_i16:
2577 case NEON::BI__builtin_neon_vsetq_lane_i32:
2578 case NEON::BI__builtin_neon_vsetq_lane_i64:
2579 case NEON::BI__builtin_neon_vsetq_lane_bf16:
2580 case NEON::BI__builtin_neon_vsetq_lane_f32:
2581 return Builder.CreateInsertElement(Ops[1], Ops[0], Ops[2], "vset_lane");
2582
2583 case NEON::BI__builtin_neon_vsha1h_u32:
2584 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha1h), Ops,
2585 "vsha1h");
2586 case NEON::BI__builtin_neon_vsha1cq_u32:
2587 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha1c), Ops,
2588 "vsha1h");
2589 case NEON::BI__builtin_neon_vsha1pq_u32:
2590 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha1p), Ops,
2591 "vsha1h");
2592 case NEON::BI__builtin_neon_vsha1mq_u32:
2593 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha1m), Ops,
2594 "vsha1h");
2595
2596 case NEON::BI__builtin_neon_vcvth_bf16_f32:
2597 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vcvtbfp2bf), Ops,
2598 "vcvtbfp2bf");
2599 case NEON::BI__builtin_neon_vcvt_f16_f32:
2600 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vcvtfp2hf), Ops,
2601 "vcvtfp2hf");
2602 case NEON::BI__builtin_neon_vcvt_f32_f16:
2603 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vcvthf2fp), Ops,
2604 "vcvthf2fp");
2605
2606 // The ARM _MoveToCoprocessor builtins put the input register value as
2607 // the first argument, but the LLVM intrinsic expects it as the third one.
2608 case clang::ARM::BI_MoveToCoprocessor:
2609 case clang::ARM::BI_MoveToCoprocessor2: {
2610 Function *F = CGM.getIntrinsic(BuiltinID == clang::ARM::BI_MoveToCoprocessor
2611 ? Intrinsic::arm_mcr
2612 : Intrinsic::arm_mcr2);
2613 return Builder.CreateCall(F, {Ops[1], Ops[2], Ops[0],
2614 Ops[3], Ops[4], Ops[5]});
2615 }
2616 }
2617
2618 // Get the last argument, which specifies the vector type.
2619 assert(HasExtraArg);
2620 const Expr *Arg = E->getArg(E->getNumArgs()-1);
2621 std::optional<llvm::APSInt> Result =
2623 if (!Result)
2624 return nullptr;
2625
2626 if (BuiltinID == clang::ARM::BI__builtin_arm_vcvtr_f ||
2627 BuiltinID == clang::ARM::BI__builtin_arm_vcvtr_d) {
2628 // Determine the overloaded type of this builtin.
2629 llvm::Type *Ty;
2630 if (BuiltinID == clang::ARM::BI__builtin_arm_vcvtr_f)
2631 Ty = FloatTy;
2632 else
2633 Ty = DoubleTy;
2634
2635 // Determine whether this is an unsigned conversion or not.
2636 bool usgn = Result->getZExtValue() == 1;
2637 unsigned Int = usgn ? Intrinsic::arm_vcvtru : Intrinsic::arm_vcvtr;
2638
2639 // Call the appropriate intrinsic.
2640 Function *F = CGM.getIntrinsic(Int, Ty);
2641 return Builder.CreateCall(F, Ops, "vcvtr");
2642 }
2643
2644 // Determine the type of this overloaded NEON intrinsic.
2645 NeonTypeFlags Type = Result->getZExtValue();
2646 bool usgn = Type.isUnsigned();
2647 bool rightShift = false;
2648
2649 llvm::FixedVectorType *VTy =
2650 GetNeonType(this, Type, getTarget().hasFastHalfType(), false,
2651 getTarget().hasBFloat16Type());
2652 llvm::Type *Ty = VTy;
2653 if (!Ty)
2654 return nullptr;
2655
2656 // Many NEON builtins have identical semantics and uses in ARM and
2657 // AArch64. Emit these in a single function.
2658 auto IntrinsicMap = ArrayRef(ARMSIMDIntrinsicMap);
2660 IntrinsicMap, BuiltinID, NEONSIMDIntrinsicsProvenSorted);
2661 if (Builtin)
2663 Builtin->BuiltinID, Builtin->LLVMIntrinsic, Builtin->AltLLVMIntrinsic,
2664 Builtin->NameHint, Builtin->TypeModifier, E, Ops, PtrOp0, PtrOp1, Arch);
2665
2666 unsigned Int;
2667 switch (BuiltinID) {
2668 default: return nullptr;
2669 case NEON::BI__builtin_neon_vld1q_lane_v:
2670 // Handle 64-bit integer elements as a special case. Use shuffles of
2671 // one-element vectors to avoid poor code for i64 in the backend.
2672 if (VTy->getElementType()->isIntegerTy(64)) {
2673 // Extract the other lane.
2674 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
2675 int Lane = cast<ConstantInt>(Ops[2])->getZExtValue();
2676 Value *SV = llvm::ConstantVector::get(ConstantInt::get(Int32Ty, 1-Lane));
2677 Ops[1] = Builder.CreateShuffleVector(Ops[1], Ops[1], SV);
2678 // Load the value as a one-element vector.
2679 Ty = llvm::FixedVectorType::get(VTy->getElementType(), 1);
2680 llvm::Type *Tys[] = {Ty, Int8PtrTy};
2681 Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld1, Tys);
2682 Value *Align = getAlignmentValue32(PtrOp0);
2683 Value *Ld = Builder.CreateCall(F, {Ops[0], Align});
2684 // Combine them.
2685 int Indices[] = {1 - Lane, Lane};
2686 return Builder.CreateShuffleVector(Ops[1], Ld, Indices, "vld1q_lane");
2687 }
2688 [[fallthrough]];
2689 case NEON::BI__builtin_neon_vld1_lane_v: {
2690 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
2691 PtrOp0 = PtrOp0.withElementType(VTy->getElementType());
2692 Value *Ld = Builder.CreateLoad(PtrOp0);
2693 return Builder.CreateInsertElement(Ops[1], Ld, Ops[2], "vld1_lane");
2694 }
2695 case NEON::BI__builtin_neon_vqrshrn_n_v:
2696 Int =
2697 usgn ? Intrinsic::arm_neon_vqrshiftnu : Intrinsic::arm_neon_vqrshiftns;
2698 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqrshrn_n",
2699 1, true);
2700 case NEON::BI__builtin_neon_vqrshrun_n_v:
2701 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqrshiftnsu, Ty),
2702 Ops, "vqrshrun_n", 1, true);
2703 case NEON::BI__builtin_neon_vqshrn_n_v:
2704 Int = usgn ? Intrinsic::arm_neon_vqshiftnu : Intrinsic::arm_neon_vqshiftns;
2705 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshrn_n",
2706 1, true);
2707 case NEON::BI__builtin_neon_vqshrun_n_v:
2708 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqshiftnsu, Ty),
2709 Ops, "vqshrun_n", 1, true);
2710 case NEON::BI__builtin_neon_vrecpe_v:
2711 case NEON::BI__builtin_neon_vrecpeq_v:
2712 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vrecpe, Ty),
2713 Ops, "vrecpe");
2714 case NEON::BI__builtin_neon_vrshrn_n_v:
2715 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vrshiftn, Ty),
2716 Ops, "vrshrn_n", 1, true);
2717 case NEON::BI__builtin_neon_vrsra_n_v:
2718 case NEON::BI__builtin_neon_vrsraq_n_v:
2719 Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
2720 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
2721 Ops[2] = EmitNeonShiftVector(Ops[2], Ty, true);
2722 Int = usgn ? Intrinsic::arm_neon_vrshiftu : Intrinsic::arm_neon_vrshifts;
2723 Ops[1] = Builder.CreateCall(CGM.getIntrinsic(Int, Ty), {Ops[1], Ops[2]});
2724 return Builder.CreateAdd(Ops[0], Ops[1], "vrsra_n");
2725 case NEON::BI__builtin_neon_vsri_n_v:
2726 case NEON::BI__builtin_neon_vsriq_n_v:
2727 rightShift = true;
2728 [[fallthrough]];
2729 case NEON::BI__builtin_neon_vsli_n_v:
2730 case NEON::BI__builtin_neon_vsliq_n_v:
2731 Ops[2] = EmitNeonShiftVector(Ops[2], Ty, rightShift);
2732 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vshiftins, Ty),
2733 Ops, "vsli_n");
2734 case NEON::BI__builtin_neon_vsra_n_v:
2735 case NEON::BI__builtin_neon_vsraq_n_v:
2736 Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
2737 Ops[1] = EmitNeonRShiftImm(Ops[1], Ops[2], Ty, usgn, "vsra_n");
2738 return Builder.CreateAdd(Ops[0], Ops[1]);
2739 case NEON::BI__builtin_neon_vst1q_lane_v:
2740 // Handle 64-bit integer elements as a special case. Use a shuffle to get
2741 // a one-element vector and avoid poor code for i64 in the backend.
2742 if (VTy->getElementType()->isIntegerTy(64)) {
2743 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
2744 Value *SV = llvm::ConstantVector::get(cast<llvm::Constant>(Ops[2]));
2745 Ops[1] = Builder.CreateShuffleVector(Ops[1], Ops[1], SV);
2746 Ops[2] = getAlignmentValue32(PtrOp0);
2747 llvm::Type *Tys[] = {Int8PtrTy, Ops[1]->getType()};
2748 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst1,
2749 Tys), Ops);
2750 }
2751 [[fallthrough]];
2752 case NEON::BI__builtin_neon_vst1_lane_v: {
2753 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
2754 Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2]);
2755 return Builder.CreateStore(Ops[1],
2756 PtrOp0.withElementType(Ops[1]->getType()));
2757 }
2758 case NEON::BI__builtin_neon_vtbl1_v:
2759 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl1),
2760 Ops, "vtbl1");
2761 case NEON::BI__builtin_neon_vtbl2_v:
2762 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl2),
2763 Ops, "vtbl2");
2764 case NEON::BI__builtin_neon_vtbl3_v:
2765 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl3),
2766 Ops, "vtbl3");
2767 case NEON::BI__builtin_neon_vtbl4_v:
2768 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl4),
2769 Ops, "vtbl4");
2770 case NEON::BI__builtin_neon_vtbx1_v:
2771 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbx1),
2772 Ops, "vtbx1");
2773 case NEON::BI__builtin_neon_vtbx2_v:
2774 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbx2),
2775 Ops, "vtbx2");
2776 case NEON::BI__builtin_neon_vtbx3_v:
2777 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbx3),
2778 Ops, "vtbx3");
2779 case NEON::BI__builtin_neon_vtbx4_v:
2780 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbx4),
2781 Ops, "vtbx4");
2782 }
2783}
2784
2785template<typename Integer>
2787 return E->getIntegerConstantExpr(Context)->getExtValue();
2788}
2789
2790static llvm::Value *SignOrZeroExtend(CGBuilderTy &Builder, llvm::Value *V,
2791 llvm::Type *T, bool Unsigned) {
2792 // Helper function called by Tablegen-constructed ARM MVE builtin codegen,
2793 // which finds it convenient to specify signed/unsigned as a boolean flag.
2794 return Unsigned ? Builder.CreateZExt(V, T) : Builder.CreateSExt(V, T);
2795}
2796
2797static llvm::Value *MVEImmediateShr(CGBuilderTy &Builder, llvm::Value *V,
2798 uint32_t Shift, bool Unsigned) {
2799 // MVE helper function for integer shift right. This must handle signed vs
2800 // unsigned, and also deal specially with the case where the shift count is
2801 // equal to the lane size. In LLVM IR, an LShr with that parameter would be
2802 // undefined behavior, but in MVE it's legal, so we must convert it to code
2803 // that is not undefined in IR.
2804 unsigned LaneBits = cast<llvm::VectorType>(V->getType())
2805 ->getElementType()
2806 ->getPrimitiveSizeInBits();
2807 if (Shift == LaneBits) {
2808 // An unsigned shift of the full lane size always generates zero, so we can
2809 // simply emit a zero vector. A signed shift of the full lane size does the
2810 // same thing as shifting by one bit fewer.
2811 if (Unsigned)
2812 return llvm::Constant::getNullValue(V->getType());
2813 else
2814 --Shift;
2815 }
2816 return Unsigned ? Builder.CreateLShr(V, Shift) : Builder.CreateAShr(V, Shift);
2817}
2818
2819static llvm::Value *ARMMVEVectorSplat(CGBuilderTy &Builder, llvm::Value *V) {
2820 // MVE-specific helper function for a vector splat, which infers the element
2821 // count of the output vector by knowing that MVE vectors are all 128 bits
2822 // wide.
2823 unsigned Elements = 128 / V->getType()->getPrimitiveSizeInBits();
2824 return Builder.CreateVectorSplat(Elements, V);
2825}
2826
2827static llvm::Value *ARMMVEVectorReinterpret(CGBuilderTy &Builder,
2828 CodeGenFunction *CGF,
2829 llvm::Value *V,
2830 llvm::Type *DestType) {
2831 // Convert one MVE vector type into another by reinterpreting its in-register
2832 // format.
2833 //
2834 // Little-endian, this is identical to a bitcast (which reinterprets the
2835 // memory format). But big-endian, they're not necessarily the same, because
2836 // the register and memory formats map to each other differently depending on
2837 // the lane size.
2838 //
2839 // We generate a bitcast whenever we can (if we're little-endian, or if the
2840 // lane sizes are the same anyway). Otherwise we fall back to an IR intrinsic
2841 // that performs the different kind of reinterpretation.
2842 if (CGF->getTarget().isBigEndian() &&
2843 V->getType()->getScalarSizeInBits() != DestType->getScalarSizeInBits()) {
2844 return Builder.CreateCall(
2845 CGF->CGM.getIntrinsic(Intrinsic::arm_mve_vreinterpretq,
2846 {DestType, V->getType()}),
2847 V);
2848 } else {
2849 return Builder.CreateBitCast(V, DestType);
2850 }
2851}
2852
2853static llvm::Value *VectorUnzip(CGBuilderTy &Builder, llvm::Value *V, bool Odd) {
2854 // Make a shufflevector that extracts every other element of a vector (evens
2855 // or odds, as desired).
2856 SmallVector<int, 16> Indices;
2857 unsigned InputElements =
2858 cast<llvm::FixedVectorType>(V->getType())->getNumElements();
2859 for (unsigned i = 0; i < InputElements; i += 2)
2860 Indices.push_back(i + Odd);
2861 return Builder.CreateShuffleVector(V, Indices);
2862}
2863
2864static llvm::Value *VectorZip(CGBuilderTy &Builder, llvm::Value *V0,
2865 llvm::Value *V1) {
2866 // Make a shufflevector that interleaves two vectors element by element.
2867 assert(V0->getType() == V1->getType() && "Can't zip different vector types");
2868 SmallVector<int, 16> Indices;
2869 unsigned InputElements =
2870 cast<llvm::FixedVectorType>(V0->getType())->getNumElements();
2871 for (unsigned i = 0; i < InputElements; i++) {
2872 Indices.push_back(i);
2873 Indices.push_back(i + InputElements);
2874 }
2875 return Builder.CreateShuffleVector(V0, V1, Indices);
2876}
2877
2878template<unsigned HighBit, unsigned OtherBits>
2879static llvm::Value *ARMMVEConstantSplat(CGBuilderTy &Builder, llvm::Type *VT) {
2880 // MVE-specific helper function to make a vector splat of a constant such as
2881 // UINT_MAX or INT_MIN, in which all bits below the highest one are equal.
2882 llvm::Type *T = cast<llvm::VectorType>(VT)->getElementType();
2883 unsigned LaneBits = T->getPrimitiveSizeInBits();
2884 uint32_t Value = HighBit << (LaneBits - 1);
2885 if (OtherBits)
2886 Value |= (1UL << (LaneBits - 1)) - 1;
2887 llvm::Value *Lane = llvm::ConstantInt::get(T, Value);
2888 return ARMMVEVectorSplat(Builder, Lane);
2889}
2890
2891static llvm::Value *ARMMVEVectorElementReverse(CGBuilderTy &Builder,
2892 llvm::Value *V,
2893 unsigned ReverseWidth) {
2894 // MVE-specific helper function which reverses the elements of a
2895 // vector within every (ReverseWidth)-bit collection of lanes.
2896 SmallVector<int, 16> Indices;
2897 unsigned LaneSize = V->getType()->getScalarSizeInBits();
2898 unsigned Elements = 128 / LaneSize;
2899 unsigned Mask = ReverseWidth / LaneSize - 1;
2900 for (unsigned i = 0; i < Elements; i++)
2901 Indices.push_back(i ^ Mask);
2902 return Builder.CreateShuffleVector(V, Indices);
2903}
2904
2905static llvm::Value *ARMMVECreateSIToFP(CGBuilderTy &Builder,
2906 CodeGenFunction *CGF, llvm::Value *V,
2907 llvm::Type *Ty) {
2908 return Builder.CreateCall(
2909 CGF->CGM.getIntrinsic(Intrinsic::arm_mve_vcvt_fp_int, {Ty, V->getType()}),
2910 {V, llvm::ConstantInt::get(Builder.getInt32Ty(), 0)});
2911}
2912
2913static llvm::Value *ARMMVECreateUIToFP(CGBuilderTy &Builder,
2914 CodeGenFunction *CGF, llvm::Value *V,
2915 llvm::Type *Ty) {
2916 return Builder.CreateCall(
2917 CGF->CGM.getIntrinsic(Intrinsic::arm_mve_vcvt_fp_int, {Ty, V->getType()}),
2918 {V, llvm::ConstantInt::get(Builder.getInt32Ty(), 1)});
2919}
2920
2921static llvm::Value *ARMMVECreateFPToSI(CGBuilderTy &Builder,
2922 CodeGenFunction *CGF, llvm::Value *V,
2923 llvm::Type *Ty) {
2924 return Builder.CreateCall(
2925 CGF->CGM.getIntrinsic(Intrinsic::arm_mve_vcvt_int_fp, {Ty, V->getType()}),
2926 {V, llvm::ConstantInt::get(Builder.getInt32Ty(), 0)});
2927}
2928
2929static llvm::Value *ARMMVECreateFPToUI(CGBuilderTy &Builder,
2930 CodeGenFunction *CGF, llvm::Value *V,
2931 llvm::Type *Ty) {
2932 return Builder.CreateCall(
2933 CGF->CGM.getIntrinsic(Intrinsic::arm_mve_vcvt_int_fp, {Ty, V->getType()}),
2934 {V, llvm::ConstantInt::get(Builder.getInt32Ty(), 1)});
2935}
2936
2938 const CallExpr *E,
2940 llvm::Triple::ArchType Arch) {
2941 enum class CustomCodeGen { VLD24, VST24 } CustomCodeGenType;
2942 Intrinsic::ID IRIntr;
2943 unsigned NumVectors;
2944
2945 // Code autogenerated by Tablegen will handle all the simple builtins.
2946 switch (BuiltinID) {
2947 #include "clang/Basic/arm_mve_builtin_cg.inc"
2948
2949 // If we didn't match an MVE builtin id at all, go back to the
2950 // main EmitARMBuiltinExpr.
2951 default:
2952 return nullptr;
2953 }
2954
2955 // Anything that breaks from that switch is an MVE builtin that
2956 // needs handwritten code to generate.
2957
2958 switch (CustomCodeGenType) {
2959
2960 case CustomCodeGen::VLD24: {
2963
2964 auto MvecCType = E->getType();
2965 auto MvecLType = ConvertType(MvecCType);
2966 assert(MvecLType->isStructTy() &&
2967 "Return type for vld[24]q should be a struct");
2968 assert(MvecLType->getStructNumElements() == 1 &&
2969 "Return-type struct for vld[24]q should have one element");
2970 auto MvecLTypeInner = MvecLType->getStructElementType(0);
2971 assert(MvecLTypeInner->isArrayTy() &&
2972 "Return-type struct for vld[24]q should contain an array");
2973 assert(MvecLTypeInner->getArrayNumElements() == NumVectors &&
2974 "Array member of return-type struct vld[24]q has wrong length");
2975 auto VecLType = MvecLTypeInner->getArrayElementType();
2976
2977 Tys.push_back(VecLType);
2978
2979 auto Addr = E->getArg(0);
2980 Ops.push_back(EmitScalarExpr(Addr));
2981 Tys.push_back(ConvertType(Addr->getType()));
2982
2983 Function *F = CGM.getIntrinsic(IRIntr, ArrayRef(Tys));
2984 Value *LoadResult = Builder.CreateCall(F, Ops);
2985 Value *MvecOut = PoisonValue::get(MvecLType);
2986 for (unsigned i = 0; i < NumVectors; ++i) {
2987 Value *Vec = Builder.CreateExtractValue(LoadResult, i);
2988 MvecOut = Builder.CreateInsertValue(MvecOut, Vec, {0, i});
2989 }
2990
2991 if (ReturnValue.isNull())
2992 return MvecOut;
2993 else
2994 return Builder.CreateStore(MvecOut, ReturnValue.getAddress());
2995 }
2996
2997 case CustomCodeGen::VST24: {
3000
3001 auto Addr = E->getArg(0);
3002 Ops.push_back(EmitScalarExpr(Addr));
3003 Tys.push_back(ConvertType(Addr->getType()));
3004
3005 auto MvecCType = E->getArg(1)->getType();
3006 auto MvecLType = ConvertType(MvecCType);
3007 assert(MvecLType->isStructTy() && "Data type for vst2q should be a struct");
3008 assert(MvecLType->getStructNumElements() == 1 &&
3009 "Data-type struct for vst2q should have one element");
3010 auto MvecLTypeInner = MvecLType->getStructElementType(0);
3011 assert(MvecLTypeInner->isArrayTy() &&
3012 "Data-type struct for vst2q should contain an array");
3013 assert(MvecLTypeInner->getArrayNumElements() == NumVectors &&
3014 "Array member of return-type struct vld[24]q has wrong length");
3015 auto VecLType = MvecLTypeInner->getArrayElementType();
3016
3017 Tys.push_back(VecLType);
3018
3019 AggValueSlot MvecSlot = CreateAggTemp(MvecCType);
3020 EmitAggExpr(E->getArg(1), MvecSlot);
3021 auto Mvec = Builder.CreateLoad(MvecSlot.getAddress());
3022 for (unsigned i = 0; i < NumVectors; i++)
3023 Ops.push_back(Builder.CreateExtractValue(Mvec, {0, i}));
3024
3025 Function *F = CGM.getIntrinsic(IRIntr, ArrayRef(Tys));
3026 Value *ToReturn = nullptr;
3027 for (unsigned i = 0; i < NumVectors; i++) {
3028 Ops.push_back(llvm::ConstantInt::get(Int32Ty, i));
3029 ToReturn = Builder.CreateCall(F, Ops);
3030 Ops.pop_back();
3031 }
3032 return ToReturn;
3033 }
3034 }
3035 llvm_unreachable("unknown custom codegen type.");
3036}
3037
3039 const CallExpr *E,
3041 llvm::Triple::ArchType Arch) {
3042 switch (BuiltinID) {
3043 default:
3044 return nullptr;
3045#include "clang/Basic/arm_cde_builtin_cg.inc"
3046 }
3047}
3048
3049static Value *EmitAArch64TblBuiltinExpr(CodeGenFunction &CGF, unsigned BuiltinID,
3050 const CallExpr *E,
3052 llvm::Triple::ArchType Arch) {
3053 unsigned int Int = 0;
3054 const char *s = nullptr;
3055
3056 switch (BuiltinID) {
3057 default:
3058 return nullptr;
3059 case NEON::BI__builtin_neon_vtbl1_v:
3060 case NEON::BI__builtin_neon_vqtbl1_v:
3061 case NEON::BI__builtin_neon_vqtbl1q_v:
3062 case NEON::BI__builtin_neon_vtbl2_v:
3063 case NEON::BI__builtin_neon_vqtbl2_v:
3064 case NEON::BI__builtin_neon_vqtbl2q_v:
3065 case NEON::BI__builtin_neon_vtbl3_v:
3066 case NEON::BI__builtin_neon_vqtbl3_v:
3067 case NEON::BI__builtin_neon_vqtbl3q_v:
3068 case NEON::BI__builtin_neon_vtbl4_v:
3069 case NEON::BI__builtin_neon_vqtbl4_v:
3070 case NEON::BI__builtin_neon_vqtbl4q_v:
3071 break;
3072 case NEON::BI__builtin_neon_vtbx1_v:
3073 case NEON::BI__builtin_neon_vqtbx1_v:
3074 case NEON::BI__builtin_neon_vqtbx1q_v:
3075 case NEON::BI__builtin_neon_vtbx2_v:
3076 case NEON::BI__builtin_neon_vqtbx2_v:
3077 case NEON::BI__builtin_neon_vqtbx2q_v:
3078 case NEON::BI__builtin_neon_vtbx3_v:
3079 case NEON::BI__builtin_neon_vqtbx3_v:
3080 case NEON::BI__builtin_neon_vqtbx3q_v:
3081 case NEON::BI__builtin_neon_vtbx4_v:
3082 case NEON::BI__builtin_neon_vqtbx4_v:
3083 case NEON::BI__builtin_neon_vqtbx4q_v:
3084 break;
3085 }
3086
3087 assert(E->getNumArgs() >= 3);
3088
3089 // Get the last argument, which specifies the vector type.
3090 const Expr *Arg = E->getArg(E->getNumArgs() - 1);
3091 std::optional<llvm::APSInt> Result =
3093 if (!Result)
3094 return nullptr;
3095
3096 // Determine the type of this overloaded NEON intrinsic.
3097 NeonTypeFlags Type = Result->getZExtValue();
3098 llvm::FixedVectorType *Ty = GetNeonType(&CGF, Type);
3099 if (!Ty)
3100 return nullptr;
3101
3102 CodeGen::CGBuilderTy &Builder = CGF.Builder;
3103
3104 // AArch64 scalar builtins are not overloaded, they do not have an extra
3105 // argument that specifies the vector type, need to handle each case.
3106 switch (BuiltinID) {
3107 case NEON::BI__builtin_neon_vtbl1_v: {
3108 return packTBLDVectorList(CGF, ArrayRef(Ops).slice(0, 1), nullptr, Ops[1],
3109 Ty, Intrinsic::aarch64_neon_tbl1, "vtbl1");
3110 }
3111 case NEON::BI__builtin_neon_vtbl2_v: {
3112 return packTBLDVectorList(CGF, ArrayRef(Ops).slice(0, 2), nullptr, Ops[2],
3113 Ty, Intrinsic::aarch64_neon_tbl1, "vtbl1");
3114 }
3115 case NEON::BI__builtin_neon_vtbl3_v: {
3116 return packTBLDVectorList(CGF, ArrayRef(Ops).slice(0, 3), nullptr, Ops[3],
3117 Ty, Intrinsic::aarch64_neon_tbl2, "vtbl2");
3118 }
3119 case NEON::BI__builtin_neon_vtbl4_v: {
3120 return packTBLDVectorList(CGF, ArrayRef(Ops).slice(0, 4), nullptr, Ops[4],
3121 Ty, Intrinsic::aarch64_neon_tbl2, "vtbl2");
3122 }
3123 case NEON::BI__builtin_neon_vtbx1_v: {
3124 Value *TblRes =
3125 packTBLDVectorList(CGF, ArrayRef(Ops).slice(1, 1), nullptr, Ops[2], Ty,
3126 Intrinsic::aarch64_neon_tbl1, "vtbl1");
3127
3128 llvm::Constant *EightV = ConstantInt::get(Ty, 8);
3129 Value *CmpRes = Builder.CreateICmp(ICmpInst::ICMP_UGE, Ops[2], EightV);
3130 CmpRes = Builder.CreateSExt(CmpRes, Ty);
3131
3132 Value *EltsFromInput = Builder.CreateAnd(CmpRes, Ops[0]);
3133 Value *EltsFromTbl = Builder.CreateAnd(Builder.CreateNot(CmpRes), TblRes);
3134 return Builder.CreateOr(EltsFromInput, EltsFromTbl, "vtbx");
3135 }
3136 case NEON::BI__builtin_neon_vtbx2_v: {
3137 return packTBLDVectorList(CGF, ArrayRef(Ops).slice(1, 2), Ops[0], Ops[3],
3138 Ty, Intrinsic::aarch64_neon_tbx1, "vtbx1");
3139 }
3140 case NEON::BI__builtin_neon_vtbx3_v: {
3141 Value *TblRes =
3142 packTBLDVectorList(CGF, ArrayRef(Ops).slice(1, 3), nullptr, Ops[4], Ty,
3143 Intrinsic::aarch64_neon_tbl2, "vtbl2");
3144
3145 llvm::Constant *TwentyFourV = ConstantInt::get(Ty, 24);
3146 Value *CmpRes = Builder.CreateICmp(ICmpInst::ICMP_UGE, Ops[4],
3147 TwentyFourV);
3148 CmpRes = Builder.CreateSExt(CmpRes, Ty);
3149
3150 Value *EltsFromInput = Builder.CreateAnd(CmpRes, Ops[0]);
3151 Value *EltsFromTbl = Builder.CreateAnd(Builder.CreateNot(CmpRes), TblRes);
3152 return Builder.CreateOr(EltsFromInput, EltsFromTbl, "vtbx");
3153 }
3154 case NEON::BI__builtin_neon_vtbx4_v: {
3155 return packTBLDVectorList(CGF, ArrayRef(Ops).slice(1, 4), Ops[0], Ops[5],
3156 Ty, Intrinsic::aarch64_neon_tbx2, "vtbx2");
3157 }
3158 case NEON::BI__builtin_neon_vqtbl1_v:
3159 case NEON::BI__builtin_neon_vqtbl1q_v:
3160 Int = Intrinsic::aarch64_neon_tbl1; s = "vtbl1"; break;
3161 case NEON::BI__builtin_neon_vqtbl2_v:
3162 case NEON::BI__builtin_neon_vqtbl2q_v: {
3163 Int = Intrinsic::aarch64_neon_tbl2; s = "vtbl2"; break;
3164 case NEON::BI__builtin_neon_vqtbl3_v:
3165 case NEON::BI__builtin_neon_vqtbl3q_v:
3166 Int = Intrinsic::aarch64_neon_tbl3; s = "vtbl3"; break;
3167 case NEON::BI__builtin_neon_vqtbl4_v:
3168 case NEON::BI__builtin_neon_vqtbl4q_v:
3169 Int = Intrinsic::aarch64_neon_tbl4; s = "vtbl4"; break;
3170 case NEON::BI__builtin_neon_vqtbx1_v:
3171 case NEON::BI__builtin_neon_vqtbx1q_v:
3172 Int = Intrinsic::aarch64_neon_tbx1; s = "vtbx1"; break;
3173 case NEON::BI__builtin_neon_vqtbx2_v:
3174 case NEON::BI__builtin_neon_vqtbx2q_v:
3175 Int = Intrinsic::aarch64_neon_tbx2; s = "vtbx2"; break;
3176 case NEON::BI__builtin_neon_vqtbx3_v:
3177 case NEON::BI__builtin_neon_vqtbx3q_v:
3178 Int = Intrinsic::aarch64_neon_tbx3; s = "vtbx3"; break;
3179 case NEON::BI__builtin_neon_vqtbx4_v:
3180 case NEON::BI__builtin_neon_vqtbx4q_v:
3181 Int = Intrinsic::aarch64_neon_tbx4; s = "vtbx4"; break;
3182 }
3183 }
3184
3185 if (!Int)
3186 return nullptr;
3187
3188 Function *F = CGF.CGM.getIntrinsic(Int, Ty);
3189 return CGF.EmitNeonCall(F, Ops, s);
3190}
3191
3193 auto *VTy = llvm::FixedVectorType::get(Int16Ty, 4);
3194 Op = Builder.CreateBitCast(Op, Int16Ty);
3195 Value *V = PoisonValue::get(VTy);
3196 llvm::Constant *CI = ConstantInt::get(SizeTy, 0);
3197 Op = Builder.CreateInsertElement(V, Op, CI);
3198 return Op;
3199}
3200
3201/// SVEBuiltinMemEltTy - Returns the memory element type for this memory
3202/// access builtin. Only required if it can't be inferred from the base pointer
3203/// operand.
3205 switch (TypeFlags.getMemEltType()) {
3206 case SVETypeFlags::MemEltTyDefault:
3207 return getEltType(TypeFlags);
3208 case SVETypeFlags::MemEltTyInt8:
3209 return Builder.getInt8Ty();
3210 case SVETypeFlags::MemEltTyInt16:
3211 return Builder.getInt16Ty();
3212 case SVETypeFlags::MemEltTyInt32:
3213 return Builder.getInt32Ty();
3214 case SVETypeFlags::MemEltTyInt64:
3215 return Builder.getInt64Ty();
3216 }
3217 llvm_unreachable("Unknown MemEltType");
3218}
3219
3220llvm::Type *CodeGenFunction::getEltType(const SVETypeFlags &TypeFlags) {
3221 switch (TypeFlags.getEltType()) {
3222 default:
3223 llvm_unreachable("Invalid SVETypeFlag!");
3224
3225 case SVETypeFlags::EltTyMFloat8:
3226 case SVETypeFlags::EltTyInt8:
3227 return Builder.getInt8Ty();
3228 case SVETypeFlags::EltTyInt16:
3229 return Builder.getInt16Ty();
3230 case SVETypeFlags::EltTyInt32:
3231 return Builder.getInt32Ty();
3232 case SVETypeFlags::EltTyInt64:
3233 return Builder.getInt64Ty();
3234 case SVETypeFlags::EltTyInt128:
3235 return Builder.getInt128Ty();
3236
3237 case SVETypeFlags::EltTyFloat16:
3238 return Builder.getHalfTy();
3239 case SVETypeFlags::EltTyFloat32:
3240 return Builder.getFloatTy();
3241 case SVETypeFlags::EltTyFloat64:
3242 return Builder.getDoubleTy();
3243
3244 case SVETypeFlags::EltTyBFloat16:
3245 return Builder.getBFloatTy();
3246
3247 case SVETypeFlags::EltTyBool8:
3248 case SVETypeFlags::EltTyBool16:
3249 case SVETypeFlags::EltTyBool32:
3250 case SVETypeFlags::EltTyBool64:
3251 return Builder.getInt1Ty();
3252 }
3253}
3254
3255// Return the llvm predicate vector type corresponding to the specified element
3256// TypeFlags.
3257llvm::ScalableVectorType *
3259 switch (TypeFlags.getEltType()) {
3260 default: llvm_unreachable("Unhandled SVETypeFlag!");
3261
3262 case SVETypeFlags::EltTyInt8:
3263 return llvm::ScalableVectorType::get(Builder.getInt1Ty(), 16);
3264 case SVETypeFlags::EltTyInt16:
3265 return llvm::ScalableVectorType::get(Builder.getInt1Ty(), 8);
3266 case SVETypeFlags::EltTyInt32:
3267 return llvm::ScalableVectorType::get(Builder.getInt1Ty(), 4);
3268 case SVETypeFlags::EltTyInt64:
3269 return llvm::ScalableVectorType::get(Builder.getInt1Ty(), 2);
3270
3271 case SVETypeFlags::EltTyBFloat16:
3272 return llvm::ScalableVectorType::get(Builder.getInt1Ty(), 8);
3273 case SVETypeFlags::EltTyFloat16:
3274 return llvm::ScalableVectorType::get(Builder.getInt1Ty(), 8);
3275 case SVETypeFlags::EltTyFloat32:
3276 return llvm::ScalableVectorType::get(Builder.getInt1Ty(), 4);
3277 case SVETypeFlags::EltTyFloat64:
3278 return llvm::ScalableVectorType::get(Builder.getInt1Ty(), 2);
3279
3280 case SVETypeFlags::EltTyBool8:
3281 return llvm::ScalableVectorType::get(Builder.getInt1Ty(), 16);
3282 case SVETypeFlags::EltTyBool16:
3283 return llvm::ScalableVectorType::get(Builder.getInt1Ty(), 8);
3284 case SVETypeFlags::EltTyBool32:
3285 return llvm::ScalableVectorType::get(Builder.getInt1Ty(), 4);
3286 case SVETypeFlags::EltTyBool64:
3287 return llvm::ScalableVectorType::get(Builder.getInt1Ty(), 2);
3288 }
3289}
3290
3291// Return the llvm vector type corresponding to the specified element TypeFlags.
3292llvm::ScalableVectorType *
3294 switch (TypeFlags.getEltType()) {
3295 default:
3296 llvm_unreachable("Invalid SVETypeFlag!");
3297
3298 case SVETypeFlags::EltTyInt8:
3299 return llvm::ScalableVectorType::get(Builder.getInt8Ty(), 16);
3300 case SVETypeFlags::EltTyInt16:
3301 return llvm::ScalableVectorType::get(Builder.getInt16Ty(), 8);
3302 case SVETypeFlags::EltTyInt32:
3303 return llvm::ScalableVectorType::get(Builder.getInt32Ty(), 4);
3304 case SVETypeFlags::EltTyInt64:
3305 return llvm::ScalableVectorType::get(Builder.getInt64Ty(), 2);
3306
3307 case SVETypeFlags::EltTyMFloat8:
3308 return llvm::ScalableVectorType::get(Builder.getInt8Ty(), 16);
3309 case SVETypeFlags::EltTyFloat16:
3310 return llvm::ScalableVectorType::get(Builder.getHalfTy(), 8);
3311 case SVETypeFlags::EltTyBFloat16:
3312 return llvm::ScalableVectorType::get(Builder.getBFloatTy(), 8);
3313 case SVETypeFlags::EltTyFloat32:
3314 return llvm::ScalableVectorType::get(Builder.getFloatTy(), 4);
3315 case SVETypeFlags::EltTyFloat64:
3316 return llvm::ScalableVectorType::get(Builder.getDoubleTy(), 2);
3317
3318 case SVETypeFlags::EltTyBool8:
3319 return llvm::ScalableVectorType::get(Builder.getInt1Ty(), 16);
3320 case SVETypeFlags::EltTyBool16:
3321 return llvm::ScalableVectorType::get(Builder.getInt1Ty(), 8);
3322 case SVETypeFlags::EltTyBool32:
3323 return llvm::ScalableVectorType::get(Builder.getInt1Ty(), 4);
3324 case SVETypeFlags::EltTyBool64:
3325 return llvm::ScalableVectorType::get(Builder.getInt1Ty(), 2);
3326 }
3327}
3328
3329constexpr unsigned SVEBitsPerBlock = 128;
3330
3331static llvm::ScalableVectorType *getSVEVectorForElementType(llvm::Type *EltTy) {
3332 unsigned NumElts = SVEBitsPerBlock / EltTy->getScalarSizeInBits();
3333 return llvm::ScalableVectorType::get(EltTy, NumElts);
3334}
3335
3336// Reinterpret the input predicate so that it can be used to correctly isolate
3337// the elements of the specified datatype.
3339 llvm::ScalableVectorType *VTy) {
3340
3341 if (isa<TargetExtType>(Pred->getType()) &&
3342 cast<TargetExtType>(Pred->getType())->getName() == "aarch64.svcount")
3343 return Pred;
3344
3345 auto *RTy = llvm::VectorType::get(IntegerType::get(getLLVMContext(), 1), VTy);
3346 if (Pred->getType() == RTy)
3347 return Pred;
3348
3349 unsigned IntID;
3350 llvm::Type *IntrinsicTy;
3351 switch (VTy->getMinNumElements()) {
3352 default:
3353 llvm_unreachable("unsupported element count!");
3354 case 1:
3355 case 2:
3356 case 4:
3357 case 8:
3358 IntID = Intrinsic::aarch64_sve_convert_from_svbool;
3359 IntrinsicTy = RTy;
3360 break;
3361 case 16:
3362 IntID = Intrinsic::aarch64_sve_convert_to_svbool;
3363 IntrinsicTy = Pred->getType();
3364 break;
3365 }
3366
3367 Function *F = CGM.getIntrinsic(IntID, IntrinsicTy);
3368 Value *C = Builder.CreateCall(F, Pred);
3369 assert(C->getType() == RTy && "Unexpected return type!");
3370 return C;
3371}
3372
3374 llvm::StructType *Ty) {
3375 if (PredTuple->getType() == Ty)
3376 return PredTuple;
3377
3378 Value *Ret = llvm::PoisonValue::get(Ty);
3379 for (unsigned I = 0; I < Ty->getNumElements(); ++I) {
3380 Value *Pred = Builder.CreateExtractValue(PredTuple, I);
3381 Pred = EmitSVEPredicateCast(
3382 Pred, cast<llvm::ScalableVectorType>(Ty->getTypeAtIndex(I)));
3383 Ret = Builder.CreateInsertValue(Ret, Pred, I);
3384 }
3385
3386 return Ret;
3387}
3388
3391 unsigned IntID) {
3392 auto *ResultTy = getSVEType(TypeFlags);
3393 auto *OverloadedTy =
3394 llvm::ScalableVectorType::get(SVEBuiltinMemEltTy(TypeFlags), ResultTy);
3395 Function *F = CGM.getIntrinsic(IntID, {OverloadedTy, Ops[1]->getType()});
3396
3397 // At the ACLE level there's only one predicate type, svbool_t, which is
3398 // mapped to <n x 16 x i1>. However, this might be incompatible with the
3399 // actual type being loaded. For example, when loading doubles (i64) the
3400 // predicate should be <n x 2 x i1> instead. At the IR level the type of
3401 // the predicate and the data being loaded must match. Cast to the type
3402 // expected by the intrinsic. The intrinsic itself should be defined in
3403 // a way than enforces relations between parameter types.
3404 Ops[0] = EmitSVEPredicateCast(
3405 Ops[0], cast<llvm::ScalableVectorType>(F->getArg(0)->getType()));
3406
3407 // Pass 0 when the offset is missing. This can only be applied when using
3408 // the "vector base" addressing mode for which ACLE allows no offset. The
3409 // corresponding LLVM IR always requires an offset.
3410 if (Ops.size() == 2) {
3411 assert(Ops[1]->getType()->isVectorTy() && "Scalar base requires an offset");
3412 Ops.push_back(ConstantInt::get(Int64Ty, 0));
3413 }
3414
3415 // For "vector base, scalar index" scale the index so that it becomes a
3416 // scalar offset.
3417 if (!TypeFlags.isByteIndexed() && Ops[1]->getType()->isVectorTy()) {
3418 unsigned BytesPerElt =
3419 OverloadedTy->getElementType()->getScalarSizeInBits() / 8;
3420 Ops[2] = Builder.CreateShl(Ops[2], Log2_32(BytesPerElt));
3421 }
3422
3423 Value *Call = Builder.CreateCall(F, Ops);
3424
3425 // The following sext/zext is only needed when ResultTy != OverloadedTy. In
3426 // other cases it's folded into a nop.
3427 return TypeFlags.isZExtReturn() ? Builder.CreateZExt(Call, ResultTy)
3428 : Builder.CreateSExt(Call, ResultTy);
3429}
3430
3433 unsigned IntID) {
3434 auto *SrcDataTy = getSVEType(TypeFlags);
3435 auto *OverloadedTy =
3436 llvm::ScalableVectorType::get(SVEBuiltinMemEltTy(TypeFlags), SrcDataTy);
3437
3438 // In ACLE the source data is passed in the last argument, whereas in LLVM IR
3439 // it's the first argument. Move it accordingly.
3440 Ops.insert(Ops.begin(), Ops.pop_back_val());
3441
3442 Function *F = CGM.getIntrinsic(IntID, {OverloadedTy, Ops[2]->getType()});
3443
3444 // Pass 0 when the offset is missing. This can only be applied when using
3445 // the "vector base" addressing mode for which ACLE allows no offset. The
3446 // corresponding LLVM IR always requires an offset.
3447 if (Ops.size() == 3) {
3448 assert(Ops[1]->getType()->isVectorTy() && "Scalar base requires an offset");
3449 Ops.push_back(ConstantInt::get(Int64Ty, 0));
3450 }
3451
3452 // Truncation is needed when SrcDataTy != OverloadedTy. In other cases it's
3453 // folded into a nop.
3454 Ops[0] = Builder.CreateTrunc(Ops[0], OverloadedTy);
3455
3456 // At the ACLE level there's only one predicate type, svbool_t, which is
3457 // mapped to <n x 16 x i1>. However, this might be incompatible with the
3458 // actual type being stored. For example, when storing doubles (i64) the
3459 // predicated should be <n x 2 x i1> instead. At the IR level the type of
3460 // the predicate and the data being stored must match. Cast to the type
3461 // expected by the intrinsic. The intrinsic itself should be defined in
3462 // a way that enforces relations between parameter types.
3463 Ops[1] = EmitSVEPredicateCast(
3464 Ops[1], cast<llvm::ScalableVectorType>(F->getArg(1)->getType()));
3465
3466 // For "vector base, scalar index" scale the index so that it becomes a
3467 // scalar offset.
3468 if (!TypeFlags.isByteIndexed() && Ops[2]->getType()->isVectorTy()) {
3469 unsigned BytesPerElt =
3470 OverloadedTy->getElementType()->getScalarSizeInBits() / 8;
3471 Ops[3] = Builder.CreateShl(Ops[3], Log2_32(BytesPerElt));
3472 }
3473
3474 return Builder.CreateCall(F, Ops);
3475}
3476
3479 unsigned IntID) {
3480 // The gather prefetches are overloaded on the vector input - this can either
3481 // be the vector of base addresses or vector of offsets.
3482 auto *OverloadedTy = dyn_cast<llvm::ScalableVectorType>(Ops[1]->getType());
3483 if (!OverloadedTy)
3484 OverloadedTy = cast<llvm::ScalableVectorType>(Ops[2]->getType());
3485
3486 // Cast the predicate from svbool_t to the right number of elements.
3487 Ops[0] = EmitSVEPredicateCast(Ops[0], OverloadedTy);
3488
3489 // vector + imm addressing modes
3490 if (Ops[1]->getType()->isVectorTy()) {
3491 if (Ops.size() == 3) {
3492 // Pass 0 for 'vector+imm' when the index is omitted.
3493 Ops.push_back(ConstantInt::get(Int64Ty, 0));
3494
3495 // The sv_prfop is the last operand in the builtin and IR intrinsic.
3496 std::swap(Ops[2], Ops[3]);
3497 } else {
3498 // Index needs to be passed as scaled offset.
3499 llvm::Type *MemEltTy = SVEBuiltinMemEltTy(TypeFlags);
3500 unsigned BytesPerElt = MemEltTy->getPrimitiveSizeInBits() / 8;
3501 if (BytesPerElt > 1)
3502 Ops[2] = Builder.CreateShl(Ops[2], Log2_32(BytesPerElt));
3503 }
3504
3505 Function *F = CGM.getIntrinsic(IntID, OverloadedTy);
3506 return Builder.CreateCall(F, Ops);
3507 }
3508
3509 Function *F = CGM.getIntrinsic(IntID, {Ops[1]->getType(), OverloadedTy});
3510 return Builder.CreateCall(F, Ops);
3511}
3512
3515 unsigned IntID) {
3516 llvm::ScalableVectorType *VTy = getSVEType(TypeFlags);
3517 Value *Predicate = EmitSVEPredicateCast(Ops[0], VTy);
3518 Value *BasePtr = Ops[1];
3519
3520 // Does the load have an offset?
3521 if (Ops.size() > 2)
3522 BasePtr = Builder.CreateGEP(VTy, BasePtr, Ops[2]);
3523
3524 Function *F = CGM.getIntrinsic(IntID, {VTy, BasePtr->getType()});
3525 return Builder.CreateCall(F, {Predicate, BasePtr});
3526}
3527
3530 unsigned IntID) {
3531 llvm::ScalableVectorType *VTy = getSVEType(TypeFlags);
3532
3533 unsigned N;
3534 switch (IntID) {
3535 case Intrinsic::aarch64_sve_st2:
3536 case Intrinsic::aarch64_sve_st1_pn_x2:
3537 case Intrinsic::aarch64_sve_stnt1_pn_x2:
3538 case Intrinsic::aarch64_sve_st2q:
3539 N = 2;
3540 break;
3541 case Intrinsic::aarch64_sve_st3:
3542 case Intrinsic::aarch64_sve_st3q:
3543 N = 3;
3544 break;
3545 case Intrinsic::aarch64_sve_st4:
3546 case Intrinsic::aarch64_sve_st1_pn_x4:
3547 case Intrinsic::aarch64_sve_stnt1_pn_x4:
3548 case Intrinsic::aarch64_sve_st4q:
3549 N = 4;
3550 break;
3551 default:
3552 llvm_unreachable("unknown intrinsic!");
3553 }
3554
3555 Value *Predicate = EmitSVEPredicateCast(Ops[0], VTy);
3556 Value *BasePtr = Ops[1];
3557
3558 // Does the store have an offset?
3559 if (Ops.size() > (2 + N))
3560 BasePtr = Builder.CreateGEP(VTy, BasePtr, Ops[2]);
3561
3562 // The llvm.aarch64.sve.st2/3/4 intrinsics take legal part vectors, so we
3563 // need to break up the tuple vector.
3565 for (unsigned I = Ops.size() - N; I < Ops.size(); ++I)
3566 Operands.push_back(Ops[I]);
3567 Operands.append({Predicate, BasePtr});
3568 Function *F = CGM.getIntrinsic(IntID, {VTy, BasePtr->getType()});
3569
3570 return Builder.CreateCall(F, Operands);
3571}
3572
3573// SVE2's svpmullb and svpmullt builtins are similar to the svpmullb_pair and
3574// svpmullt_pair intrinsics, with the exception that their results are bitcast
3575// to a wider type.
3578 unsigned BuiltinID) {
3579 // Splat scalar operand to vector (intrinsics with _n infix)
3580 if (TypeFlags.hasSplatOperand()) {
3581 unsigned OpNo = TypeFlags.getSplatOperand();
3582 Ops[OpNo] = EmitSVEDupX(Ops[OpNo]);
3583 }
3584
3585 // The pair-wise function has a narrower overloaded type.
3586 Function *F = CGM.getIntrinsic(BuiltinID, Ops[0]->getType());
3587 Value *Call = Builder.CreateCall(F, {Ops[0], Ops[1]});
3588
3589 // Now bitcast to the wider result type.
3590 llvm::ScalableVectorType *Ty = getSVEType(TypeFlags);
3591 return EmitSVEReinterpret(Call, Ty);
3592}
3593
3595 ArrayRef<Value *> Ops, unsigned BuiltinID) {
3596 llvm::Type *OverloadedTy = getSVEType(TypeFlags);
3597 Function *F = CGM.getIntrinsic(BuiltinID, OverloadedTy);
3598 return Builder.CreateCall(F, {Ops[0], Builder.getInt32(0)});
3599}
3600
3603 unsigned BuiltinID) {
3604 auto *MemEltTy = SVEBuiltinMemEltTy(TypeFlags);
3605 auto *VectorTy = getSVEVectorForElementType(MemEltTy);
3606 auto *MemoryTy = llvm::ScalableVectorType::get(MemEltTy, VectorTy);
3607
3608 Value *Predicate = EmitSVEPredicateCast(Ops[0], MemoryTy);
3609 Value *BasePtr = Ops[1];
3610
3611 // Implement the index operand if not omitted.
3612 if (Ops.size() > 3)
3613 BasePtr = Builder.CreateGEP(MemoryTy, BasePtr, Ops[2]);
3614
3615 Value *PrfOp = Ops.back();
3616
3617 llvm::Type *Tys[2] = {Predicate->getType(), BasePtr->getType()};
3618 Function *F = CGM.getIntrinsic(BuiltinID, Tys);
3619 return Builder.CreateCall(F, {Predicate, BasePtr, PrfOp});
3620}
3621
3623 llvm::Type *ReturnTy,
3625 unsigned IntrinsicID,
3626 bool IsZExtReturn) {
3627 QualType LangPTy = E->getArg(1)->getType();
3628 llvm::Type *MemEltTy = CGM.getTypes().ConvertType(
3629 LangPTy->castAs<PointerType>()->getPointeeType());
3630
3631 // Mfloat8 types is stored as a vector, so extra work
3632 // to extract sclar element type is necessary.
3633 if (MemEltTy->isVectorTy()) {
3634 assert(MemEltTy == FixedVectorType::get(Int8Ty, 1) &&
3635 "Only <1 x i8> expected");
3636 MemEltTy = cast<llvm::VectorType>(MemEltTy)->getElementType();
3637 }
3638
3639 // The vector type that is returned may be different from the
3640 // eventual type loaded from memory.
3641 auto VectorTy = cast<llvm::ScalableVectorType>(ReturnTy);
3642 llvm::ScalableVectorType *MemoryTy = nullptr;
3643 llvm::ScalableVectorType *PredTy = nullptr;
3644 bool IsQuadLoad = false;
3645 switch (IntrinsicID) {
3646 case Intrinsic::aarch64_sve_ld1uwq:
3647 case Intrinsic::aarch64_sve_ld1udq:
3648 MemoryTy = llvm::ScalableVectorType::get(MemEltTy, 1);
3649 PredTy = llvm::ScalableVectorType::get(
3650 llvm::Type::getInt1Ty(getLLVMContext()), 1);
3651 IsQuadLoad = true;
3652 break;
3653 default:
3654 MemoryTy = llvm::ScalableVectorType::get(MemEltTy, VectorTy);
3655 PredTy = MemoryTy;
3656 break;
3657 }
3658
3659 Value *Predicate = EmitSVEPredicateCast(Ops[0], PredTy);
3660 Value *BasePtr = Ops[1];
3661
3662 // Does the load have an offset?
3663 if (Ops.size() > 2)
3664 BasePtr = Builder.CreateGEP(MemoryTy, BasePtr, Ops[2]);
3665
3666 llvm::Type *Tys[2] = {IsQuadLoad ? VectorTy : MemoryTy, BasePtr->getType()};
3667 Function *F = CGM.getIntrinsic(IntrinsicID, Tys);
3668 auto *Load = Builder.CreateCall(F, {Predicate, BasePtr});
3669 auto TBAAInfo = CGM.getTBAAAccessInfo(LangPTy->getPointeeType());
3670 CGM.DecorateInstructionWithTBAA(Load, TBAAInfo);
3671
3672 if (IsQuadLoad)
3673 return Load;
3674
3675 return IsZExtReturn ? Builder.CreateZExt(Load, VectorTy)
3676 : Builder.CreateSExt(Load, VectorTy);
3677}
3678
3681 unsigned IntrinsicID) {
3682 QualType LangPTy = E->getArg(1)->getType();
3683 llvm::Type *MemEltTy = CGM.getTypes().ConvertType(
3684 LangPTy->castAs<PointerType>()->getPointeeType());
3685
3686 // Mfloat8 types is stored as a vector, so extra work
3687 // to extract sclar element type is necessary.
3688 if (MemEltTy->isVectorTy()) {
3689 assert(MemEltTy == FixedVectorType::get(Int8Ty, 1) &&
3690 "Only <1 x i8> expected");
3691 MemEltTy = cast<llvm::VectorType>(MemEltTy)->getElementType();
3692 }
3693
3694 // The vector type that is stored may be different from the
3695 // eventual type stored to memory.
3696 auto VectorTy = cast<llvm::ScalableVectorType>(Ops.back()->getType());
3697 auto MemoryTy = llvm::ScalableVectorType::get(MemEltTy, VectorTy);
3698
3699 auto PredTy = MemoryTy;
3700 auto AddrMemoryTy = MemoryTy;
3701 bool IsQuadStore = false;
3702
3703 switch (IntrinsicID) {
3704 case Intrinsic::aarch64_sve_st1wq:
3705 case Intrinsic::aarch64_sve_st1dq:
3706 AddrMemoryTy = llvm::ScalableVectorType::get(MemEltTy, 1);
3707 PredTy =
3708 llvm::ScalableVectorType::get(IntegerType::get(getLLVMContext(), 1), 1);
3709 IsQuadStore = true;
3710 break;
3711 default:
3712 break;
3713 }
3714 Value *Predicate = EmitSVEPredicateCast(Ops[0], PredTy);
3715 Value *BasePtr = Ops[1];
3716
3717 // Does the store have an offset?
3718 if (Ops.size() == 4)
3719 BasePtr = Builder.CreateGEP(AddrMemoryTy, BasePtr, Ops[2]);
3720
3721 // Last value is always the data
3722 Value *Val =
3723 IsQuadStore ? Ops.back() : Builder.CreateTrunc(Ops.back(), MemoryTy);
3724
3725 llvm::Type *Tys[2] = {IsQuadStore ? VectorTy : MemoryTy, BasePtr->getType()};
3726 Function *F = CGM.getIntrinsic(IntrinsicID, Tys);
3727 auto *Store = Builder.CreateCall(F, {Val, Predicate, BasePtr});
3728 auto TBAAInfo = CGM.getTBAAAccessInfo(LangPTy->getPointeeType());
3729 CGM.DecorateInstructionWithTBAA(Store, TBAAInfo);
3730 return Store;
3731}
3732
3735 unsigned IntID) {
3736 Ops[2] = EmitSVEPredicateCast(
3738
3739 SmallVector<Value *> NewOps;
3740 NewOps.push_back(Ops[2]);
3741
3742 llvm::Value *BasePtr = Ops[3];
3743 llvm::Value *RealSlice = Ops[1];
3744 // If the intrinsic contains the vnum parameter, multiply it with the vector
3745 // size in bytes.
3746 if (Ops.size() == 5) {
3747 Function *StreamingVectorLength =
3748 CGM.getIntrinsic(Intrinsic::aarch64_sme_cntsd);
3749 llvm::Value *StreamingVectorLengthCall =
3750 Builder.CreateMul(Builder.CreateCall(StreamingVectorLength),
3751 llvm::ConstantInt::get(Int64Ty, 8), "svl",
3752 /* HasNUW */ true, /* HasNSW */ true);
3753 llvm::Value *Mulvl =
3754 Builder.CreateMul(StreamingVectorLengthCall, Ops[4], "mulvl");
3755 // The type of the ptr parameter is void *, so use Int8Ty here.
3756 BasePtr = Builder.CreateGEP(Int8Ty, Ops[3], Mulvl);
3757 RealSlice = Builder.CreateZExt(RealSlice, Int64Ty);
3758 RealSlice = Builder.CreateAdd(RealSlice, Ops[4]);
3759 RealSlice = Builder.CreateTrunc(RealSlice, Int32Ty);
3760 }
3761 NewOps.push_back(BasePtr);
3762 NewOps.push_back(Ops[0]);
3763 NewOps.push_back(RealSlice);
3764 Function *F = CGM.getIntrinsic(IntID, BasePtr->getType());
3765 return Builder.CreateCall(F, NewOps);
3766}
3767
3770 unsigned IntID) {
3771 auto *VecTy = getSVEType(TypeFlags);
3772 Function *F = CGM.getIntrinsic(IntID, VecTy);
3773 if (TypeFlags.isReadZA())
3774 Ops[1] = EmitSVEPredicateCast(Ops[1], VecTy);
3775 else if (TypeFlags.isWriteZA())
3776 Ops[2] = EmitSVEPredicateCast(Ops[2], VecTy);
3777 return Builder.CreateCall(F, Ops);
3778}
3779
3782 unsigned IntID) {
3783 // svzero_za() intrinsic zeros the entire za tile and has no paramters.
3784 if (Ops.size() == 0)
3785 Ops.push_back(llvm::ConstantInt::get(Int32Ty, 255));
3786 Function *F = CGM.getIntrinsic(IntID, {});
3787 return Builder.CreateCall(F, Ops);
3788}
3789
3792 unsigned IntID) {
3793 if (Ops.size() == 2)
3794 Ops.push_back(Builder.getInt32(0));
3795 else
3796 Ops[2] = Builder.CreateIntCast(Ops[2], Int32Ty, true);
3797 Function *F = CGM.getIntrinsic(IntID, Ops[1]->getType());
3798 return Builder.CreateCall(F, Ops);
3799}
3800
3801// Limit the usage of scalable llvm IR generated by the ACLE by using the
3802// sve dup.x intrinsic instead of IRBuilder::CreateVectorSplat.
3803Value *CodeGenFunction::EmitSVEDupX(Value *Scalar, llvm::Type *Ty) {
3804 return Builder.CreateVectorSplat(
3805 cast<llvm::VectorType>(Ty)->getElementCount(), Scalar);
3806}
3807
3809 if (auto *Ty = Scalar->getType(); Ty->isVectorTy()) {
3810#ifndef NDEBUG
3811 auto *VecTy = cast<llvm::VectorType>(Ty);
3812 ElementCount EC = VecTy->getElementCount();
3813 assert(EC.isScalar() && VecTy->getElementType() == Int8Ty &&
3814 "Only <1 x i8> expected");
3815#endif
3816 Scalar = Builder.CreateExtractElement(Scalar, uint64_t(0));
3817 }
3818 return EmitSVEDupX(Scalar, getSVEVectorForElementType(Scalar->getType()));
3819}
3820
3822 // FIXME: For big endian this needs an additional REV, or needs a separate
3823 // intrinsic that is code-generated as a no-op, because the LLVM bitcast
3824 // instruction is defined as 'bitwise' equivalent from memory point of
3825 // view (when storing/reloading), whereas the svreinterpret builtin
3826 // implements bitwise equivalent cast from register point of view.
3827 // LLVM CodeGen for a bitcast must add an explicit REV for big-endian.
3828
3829 if (auto *StructTy = dyn_cast<StructType>(Ty)) {
3830 Value *Tuple = llvm::PoisonValue::get(Ty);
3831
3832 for (unsigned I = 0; I < StructTy->getNumElements(); ++I) {
3833 Value *In = Builder.CreateExtractValue(Val, I);
3834 Value *Out = Builder.CreateBitCast(In, StructTy->getTypeAtIndex(I));
3835 Tuple = Builder.CreateInsertValue(Tuple, Out, I);
3836 }
3837
3838 return Tuple;
3839 }
3840
3841 return Builder.CreateBitCast(Val, Ty);
3842}
3843
3844static void InsertExplicitZeroOperand(CGBuilderTy &Builder, llvm::Type *Ty,
3846 auto *SplatZero = Constant::getNullValue(Ty);
3847 Ops.insert(Ops.begin(), SplatZero);
3848}
3849
3850static void InsertExplicitUndefOperand(CGBuilderTy &Builder, llvm::Type *Ty,
3852 auto *SplatUndef = UndefValue::get(Ty);
3853 Ops.insert(Ops.begin(), SplatUndef);
3854}
3855
3856SmallVector<llvm::Type *, 2>
3858 llvm::Type *ResultType,
3859 ArrayRef<Value *> Ops) {
3860 if (TypeFlags.isOverloadNone())
3861 return {};
3862
3863 llvm::Type *DefaultType = getSVEType(TypeFlags);
3864
3865 if (TypeFlags.isOverloadWhileOrMultiVecCvt())
3866 return {DefaultType, Ops[1]->getType()};
3867
3868 if (TypeFlags.isOverloadWhileRW())
3869 return {getSVEPredType(TypeFlags), Ops[0]->getType()};
3870
3871 if (TypeFlags.isOverloadDefaultAndOp0())
3872 return {DefaultType, Ops[0]->getType()};
3873
3874 if (TypeFlags.isOverloadFirstandLast())
3875 return {Ops[0]->getType(), Ops.back()->getType()};
3876
3877 if (TypeFlags.isReductionQV())
3878 return {ResultType, Ops[1]->getType()};
3879
3880 assert(TypeFlags.isOverloadDefault() && "Unexpected value for overloads");
3881 return {DefaultType};
3882}
3883
3885 ArrayRef<Value *> Ops) {
3886 assert((TypeFlags.isTupleSet() || TypeFlags.isTupleGet()) &&
3887 "Expects TypleFlags.isTupleSet() or TypeFlags.isTupleGet()");
3888 unsigned Idx = cast<ConstantInt>(Ops[1])->getZExtValue();
3889
3890 if (TypeFlags.isTupleSet())
3891 return Builder.CreateInsertValue(Ops[0], Ops[2], Idx);
3892 return Builder.CreateExtractValue(Ops[0], Idx);
3893}
3894
3896 llvm::Type *Ty,
3897 ArrayRef<Value *> Ops) {
3898 assert(TypeFlags.isTupleCreate() && "Expects TypleFlag isTupleCreate");
3899
3900 Value *Tuple = llvm::PoisonValue::get(Ty);
3901 for (unsigned Idx = 0; Idx < Ops.size(); Idx++)
3902 Tuple = Builder.CreateInsertValue(Tuple, Ops[Idx], Idx);
3903
3904 return Tuple;
3905}
3906
3908 unsigned BuiltinID, const CallExpr *E, SmallVectorImpl<Value *> &Ops,
3909 SVETypeFlags TypeFlags) {
3910 // Find out if any arguments are required to be integer constant expressions.
3911 unsigned ICEArguments = 0;
3913 getContext().GetBuiltinType(BuiltinID, Error, &ICEArguments);
3914 assert(Error == ASTContext::GE_None && "Should not codegen an error");
3915
3916 // Tuple set/get only requires one insert/extract vector, which is
3917 // created by EmitSVETupleSetOrGet.
3918 bool IsTupleGetOrSet = TypeFlags.isTupleSet() || TypeFlags.isTupleGet();
3919
3920 for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) {
3921 bool IsICE = ICEArguments & (1 << i);
3922 Value *Arg = EmitScalarExpr(E->getArg(i));
3923
3924 if (IsICE) {
3925 // If this is required to be a constant, constant fold it so that we know
3926 // that the generated intrinsic gets a ConstantInt.
3927 std::optional<llvm::APSInt> Result =
3929 assert(Result && "Expected argument to be a constant");
3930
3931 // Immediates for SVE llvm intrinsics are always 32bit. We can safely
3932 // truncate because the immediate has been range checked and no valid
3933 // immediate requires more than a handful of bits.
3934 *Result = Result->extOrTrunc(32);
3935 Ops.push_back(llvm::ConstantInt::get(getLLVMContext(), *Result));
3936 continue;
3937 }
3938
3939 if (isa<StructType>(Arg->getType()) && !IsTupleGetOrSet) {
3940 for (unsigned I = 0; I < Arg->getType()->getStructNumElements(); ++I)
3941 Ops.push_back(Builder.CreateExtractValue(Arg, I));
3942
3943 continue;
3944 }
3945
3946 Ops.push_back(Arg);
3947 }
3948}
3949
3951 const CallExpr *E) {
3952 llvm::Type *Ty = ConvertType(E->getType());
3953 if (BuiltinID >= SVE::BI__builtin_sve_reinterpret_s8_s8 &&
3954 BuiltinID <= SVE::BI__builtin_sve_reinterpret_f64_f64_x4) {
3955 Value *Val = EmitScalarExpr(E->getArg(0));
3956 return EmitSVEReinterpret(Val, Ty);
3957 }
3958
3959 auto *Builtin =
3962
3964 SVETypeFlags TypeFlags(Builtin->TypeModifier);
3965 GetAArch64SVEProcessedOperands(BuiltinID, E, Ops, TypeFlags);
3966
3967 if (TypeFlags.isLoad())
3968 return EmitSVEMaskedLoad(E, Ty, Ops, Builtin->LLVMIntrinsic,
3969 TypeFlags.isZExtReturn());
3970 if (TypeFlags.isStore())
3971 return EmitSVEMaskedStore(E, Ops, Builtin->LLVMIntrinsic);
3972 if (TypeFlags.isGatherLoad())
3973 return EmitSVEGatherLoad(TypeFlags, Ops, Builtin->LLVMIntrinsic);
3974 if (TypeFlags.isScatterStore())
3975 return EmitSVEScatterStore(TypeFlags, Ops, Builtin->LLVMIntrinsic);
3976 if (TypeFlags.isPrefetch())
3977 return EmitSVEPrefetchLoad(TypeFlags, Ops, Builtin->LLVMIntrinsic);
3978 if (TypeFlags.isGatherPrefetch())
3979 return EmitSVEGatherPrefetch(TypeFlags, Ops, Builtin->LLVMIntrinsic);
3980 if (TypeFlags.isStructLoad())
3981 return EmitSVEStructLoad(TypeFlags, Ops, Builtin->LLVMIntrinsic);
3982 if (TypeFlags.isStructStore())
3983 return EmitSVEStructStore(TypeFlags, Ops, Builtin->LLVMIntrinsic);
3984 if (TypeFlags.isTupleSet() || TypeFlags.isTupleGet())
3985 return EmitSVETupleSetOrGet(TypeFlags, Ops);
3986 if (TypeFlags.isTupleCreate())
3987 return EmitSVETupleCreate(TypeFlags, Ty, Ops);
3988 if (TypeFlags.isUndef())
3989 return UndefValue::get(Ty);
3990
3991 // Handle built-ins for which there is a corresponding LLVM Intrinsic.
3992 // -------------------------------------------------------------------
3993 if (Builtin->LLVMIntrinsic != 0) {
3994 // Emit set FPMR for intrinsics that require it
3995 if (TypeFlags.setsFPMR())
3996 Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_set_fpmr),
3997 Ops.pop_back_val());
3998 if (TypeFlags.getMergeType() == SVETypeFlags::MergeZeroExp)
4000
4001 if (TypeFlags.getMergeType() == SVETypeFlags::MergeAnyExp)
4003
4004 // Some ACLE builtins leave out the argument to specify the predicate
4005 // pattern, which is expected to be expanded to an SV_ALL pattern.
4006 if (TypeFlags.isAppendSVALL())
4007 Ops.push_back(Builder.getInt32(/*SV_ALL*/ 31));
4008 if (TypeFlags.isInsertOp1SVALL())
4009 Ops.insert(&Ops[1], Builder.getInt32(/*SV_ALL*/ 31));
4010
4011 // Predicates must match the main datatype.
4012 for (Value *&Op : Ops)
4013 if (auto PredTy = dyn_cast<llvm::VectorType>(Op->getType()))
4014 if (PredTy->getElementType()->isIntegerTy(1))
4015 Op = EmitSVEPredicateCast(Op, getSVEType(TypeFlags));
4016
4017 // Splat scalar operand to vector (intrinsics with _n infix)
4018 if (TypeFlags.hasSplatOperand()) {
4019 unsigned OpNo = TypeFlags.getSplatOperand();
4020 Ops[OpNo] = EmitSVEDupX(Ops[OpNo]);
4021 }
4022
4023 if (TypeFlags.isReverseCompare())
4024 std::swap(Ops[1], Ops[2]);
4025 else if (TypeFlags.isReverseUSDOT())
4026 std::swap(Ops[1], Ops[2]);
4027 else if (TypeFlags.isReverseMergeAnyBinOp() &&
4028 TypeFlags.getMergeType() == SVETypeFlags::MergeAny)
4029 std::swap(Ops[1], Ops[2]);
4030 else if (TypeFlags.isReverseMergeAnyAccOp() &&
4031 TypeFlags.getMergeType() == SVETypeFlags::MergeAny)
4032 std::swap(Ops[1], Ops[3]);
4033
4034 // Predicated intrinsics with _z suffix need a select w/ zeroinitializer.
4035 if (TypeFlags.getMergeType() == SVETypeFlags::MergeZero) {
4036 llvm::Type *OpndTy = Ops[1]->getType();
4037 auto *SplatZero = Constant::getNullValue(OpndTy);
4038 Ops[1] = Builder.CreateSelect(Ops[0], Ops[1], SplatZero);
4039 }
4040
4041 Function *F = CGM.getIntrinsic(Builtin->LLVMIntrinsic,
4042 getSVEOverloadTypes(TypeFlags, Ty, Ops));
4043 Value *Call = Builder.CreateCall(F, Ops);
4044
4045 if (Call->getType() == Ty)
4046 return Call;
4047
4048 // Predicate results must be converted to svbool_t.
4049 if (auto PredTy = dyn_cast<llvm::ScalableVectorType>(Ty))
4050 return EmitSVEPredicateCast(Call, PredTy);
4051 if (auto PredTupleTy = dyn_cast<llvm::StructType>(Ty))
4052 return EmitSVEPredicateTupleCast(Call, PredTupleTy);
4053
4054 llvm_unreachable("unsupported element count!");
4055 }
4056
4057 switch (BuiltinID) {
4058 default:
4059 return nullptr;
4060
4061 case SVE::BI__builtin_sve_svreinterpret_b: {
4062 Function *CastFromSVCountF =
4063 CGM.getIntrinsic(Intrinsic::aarch64_sve_convert_from_svcount);
4064 return Builder.CreateCall(CastFromSVCountF, Ops[0]);
4065 }
4066 case SVE::BI__builtin_sve_svreinterpret_c: {
4067 Function *CastToSVCountF =
4068 CGM.getIntrinsic(Intrinsic::aarch64_sve_convert_to_svcount);
4069 return Builder.CreateCall(CastToSVCountF, Ops[0]);
4070 }
4071
4072 case SVE::BI__builtin_sve_svpsel_lane_b8:
4073 case SVE::BI__builtin_sve_svpsel_lane_b16:
4074 case SVE::BI__builtin_sve_svpsel_lane_b32:
4075 case SVE::BI__builtin_sve_svpsel_lane_b64:
4076 case SVE::BI__builtin_sve_svpsel_lane_c8:
4077 case SVE::BI__builtin_sve_svpsel_lane_c16:
4078 case SVE::BI__builtin_sve_svpsel_lane_c32:
4079 case SVE::BI__builtin_sve_svpsel_lane_c64: {
4080 auto OverloadedTy = getSVEType(SVETypeFlags(Builtin->TypeModifier));
4081 Function *F = CGM.getIntrinsic(Intrinsic::aarch64_sve_psel,
4082 {Ops[0]->getType(), OverloadedTy});
4083 llvm::Value *Ops1 = EmitSVEPredicateCast(Ops[1], OverloadedTy);
4084 return Builder.CreateCall(F, {Ops[0], Ops1, Ops[2]});
4085 }
4086 case SVE::BI__builtin_sve_svmov_b_z: {
4087 // svmov_b_z(pg, op) <=> svand_b_z(pg, op, op)
4088 SVETypeFlags TypeFlags(Builtin->TypeModifier);
4089 llvm::Type* OverloadedTy = getSVEType(TypeFlags);
4090 Function *F = CGM.getIntrinsic(Intrinsic::aarch64_sve_and_z, OverloadedTy);
4091 return Builder.CreateCall(F, {Ops[0], Ops[1], Ops[1]});
4092 }
4093
4094 case SVE::BI__builtin_sve_svnot_b_z: {
4095 // svnot_b_z(pg, op) <=> sveor_b_z(pg, op, pg)
4096 SVETypeFlags TypeFlags(Builtin->TypeModifier);
4097 llvm::Type* OverloadedTy = getSVEType(TypeFlags);
4098 Function *F = CGM.getIntrinsic(Intrinsic::aarch64_sve_eor_z, OverloadedTy);
4099 return Builder.CreateCall(F, {Ops[0], Ops[1], Ops[0]});
4100 }
4101
4102 case SVE::BI__builtin_sve_svmovlb_u16:
4103 case SVE::BI__builtin_sve_svmovlb_u32:
4104 case SVE::BI__builtin_sve_svmovlb_u64:
4105 return EmitSVEMovl(TypeFlags, Ops, Intrinsic::aarch64_sve_ushllb);
4106
4107 case SVE::BI__builtin_sve_svmovlb_s16:
4108 case SVE::BI__builtin_sve_svmovlb_s32:
4109 case SVE::BI__builtin_sve_svmovlb_s64:
4110 return EmitSVEMovl(TypeFlags, Ops, Intrinsic::aarch64_sve_sshllb);
4111
4112 case SVE::BI__builtin_sve_svmovlt_u16:
4113 case SVE::BI__builtin_sve_svmovlt_u32:
4114 case SVE::BI__builtin_sve_svmovlt_u64:
4115 return EmitSVEMovl(TypeFlags, Ops, Intrinsic::aarch64_sve_ushllt);
4116
4117 case SVE::BI__builtin_sve_svmovlt_s16:
4118 case SVE::BI__builtin_sve_svmovlt_s32:
4119 case SVE::BI__builtin_sve_svmovlt_s64:
4120 return EmitSVEMovl(TypeFlags, Ops, Intrinsic::aarch64_sve_sshllt);
4121
4122 case SVE::BI__builtin_sve_svpmullt_u16:
4123 case SVE::BI__builtin_sve_svpmullt_u64:
4124 case SVE::BI__builtin_sve_svpmullt_n_u16:
4125 case SVE::BI__builtin_sve_svpmullt_n_u64:
4126 return EmitSVEPMull(TypeFlags, Ops, Intrinsic::aarch64_sve_pmullt_pair);
4127
4128 case SVE::BI__builtin_sve_svpmullb_u16:
4129 case SVE::BI__builtin_sve_svpmullb_u64:
4130 case SVE::BI__builtin_sve_svpmullb_n_u16:
4131 case SVE::BI__builtin_sve_svpmullb_n_u64:
4132 return EmitSVEPMull(TypeFlags, Ops, Intrinsic::aarch64_sve_pmullb_pair);
4133
4134 case SVE::BI__builtin_sve_svdup_n_b8:
4135 case SVE::BI__builtin_sve_svdup_n_b16:
4136 case SVE::BI__builtin_sve_svdup_n_b32:
4137 case SVE::BI__builtin_sve_svdup_n_b64: {
4138 llvm::ScalableVectorType *OverloadedTy = getSVEType(TypeFlags);
4139 Value *Dup = EmitSVEDupX(Ops[0], OverloadedTy);
4141 }
4142
4143 case SVE::BI__builtin_sve_svdupq_n_b8:
4144 case SVE::BI__builtin_sve_svdupq_n_b16:
4145 case SVE::BI__builtin_sve_svdupq_n_b32:
4146 case SVE::BI__builtin_sve_svdupq_n_b64:
4147 case SVE::BI__builtin_sve_svdupq_n_u8:
4148 case SVE::BI__builtin_sve_svdupq_n_s8:
4149 case SVE::BI__builtin_sve_svdupq_n_u64:
4150 case SVE::BI__builtin_sve_svdupq_n_f64:
4151 case SVE::BI__builtin_sve_svdupq_n_s64:
4152 case SVE::BI__builtin_sve_svdupq_n_u16:
4153 case SVE::BI__builtin_sve_svdupq_n_f16:
4154 case SVE::BI__builtin_sve_svdupq_n_bf16:
4155 case SVE::BI__builtin_sve_svdupq_n_s16:
4156 case SVE::BI__builtin_sve_svdupq_n_u32:
4157 case SVE::BI__builtin_sve_svdupq_n_f32:
4158 case SVE::BI__builtin_sve_svdupq_n_s32: {
4159 // These builtins are implemented by storing each element to an array and using
4160 // ld1rq to materialize a vector.
4161 unsigned NumOpnds = Ops.size();
4162
4163 bool IsBoolTy =
4164 cast<llvm::VectorType>(Ty)->getElementType()->isIntegerTy(1);
4165
4166 // For svdupq_n_b* the element type of is an integer of type 128/numelts,
4167 // so that the compare can use the width that is natural for the expected
4168 // number of predicate lanes.
4169 llvm::Type *EltTy = Ops[0]->getType();
4170 if (IsBoolTy)
4171 EltTy = IntegerType::get(getLLVMContext(), SVEBitsPerBlock / NumOpnds);
4172
4174 for (unsigned I = 0; I < NumOpnds; ++I)
4175 VecOps.push_back(Builder.CreateZExt(Ops[I], EltTy));
4176 Value *Vec = BuildVector(VecOps);
4177
4178 llvm::Type *OverloadedTy = getSVEVectorForElementType(EltTy);
4179 Value *InsertSubVec = Builder.CreateInsertVector(
4180 OverloadedTy, PoisonValue::get(OverloadedTy), Vec, uint64_t(0));
4181
4182 Function *F =
4183 CGM.getIntrinsic(Intrinsic::aarch64_sve_dupq_lane, OverloadedTy);
4184 Value *DupQLane =
4185 Builder.CreateCall(F, {InsertSubVec, Builder.getInt64(0)});
4186
4187 if (!IsBoolTy)
4188 return DupQLane;
4189
4190 SVETypeFlags TypeFlags(Builtin->TypeModifier);
4191 Constant *Pred = ConstantInt::getTrue(getSVEPredType(TypeFlags));
4192
4193 // For svdupq_n_b* we need to add an additional 'cmpne' with '0'.
4194 F = CGM.getIntrinsic(NumOpnds == 2 ? Intrinsic::aarch64_sve_cmpne
4195 : Intrinsic::aarch64_sve_cmpne_wide,
4196 OverloadedTy);
4197 Value *Call = Builder.CreateCall(
4198 F, {Pred, DupQLane, EmitSVEDupX(Builder.getInt64(0))});
4200 }
4201
4202 case SVE::BI__builtin_sve_svpfalse_b:
4203 return ConstantInt::getFalse(Ty);
4204
4205 case SVE::BI__builtin_sve_svpfalse_c:
4206 return Constant::getNullValue(Ty);
4207
4208 case SVE::BI__builtin_sve_svlen_bf16:
4209 case SVE::BI__builtin_sve_svlen_f16:
4210 case SVE::BI__builtin_sve_svlen_f32:
4211 case SVE::BI__builtin_sve_svlen_f64:
4212 case SVE::BI__builtin_sve_svlen_s8:
4213 case SVE::BI__builtin_sve_svlen_s16:
4214 case SVE::BI__builtin_sve_svlen_s32:
4215 case SVE::BI__builtin_sve_svlen_s64:
4216 case SVE::BI__builtin_sve_svlen_u8:
4217 case SVE::BI__builtin_sve_svlen_u16:
4218 case SVE::BI__builtin_sve_svlen_u32:
4219 case SVE::BI__builtin_sve_svlen_u64: {
4220 SVETypeFlags TF(Builtin->TypeModifier);
4221 return Builder.CreateElementCount(Ty, getSVEType(TF)->getElementCount());
4222 }
4223
4224 case SVE::BI__builtin_sve_svtbl2_u8:
4225 case SVE::BI__builtin_sve_svtbl2_s8:
4226 case SVE::BI__builtin_sve_svtbl2_u16:
4227 case SVE::BI__builtin_sve_svtbl2_s16:
4228 case SVE::BI__builtin_sve_svtbl2_u32:
4229 case SVE::BI__builtin_sve_svtbl2_s32:
4230 case SVE::BI__builtin_sve_svtbl2_u64:
4231 case SVE::BI__builtin_sve_svtbl2_s64:
4232 case SVE::BI__builtin_sve_svtbl2_f16:
4233 case SVE::BI__builtin_sve_svtbl2_bf16:
4234 case SVE::BI__builtin_sve_svtbl2_f32:
4235 case SVE::BI__builtin_sve_svtbl2_f64: {
4236 SVETypeFlags TF(Builtin->TypeModifier);
4237 Function *F = CGM.getIntrinsic(Intrinsic::aarch64_sve_tbl2, getSVEType(TF));
4238 return Builder.CreateCall(F, Ops);
4239 }
4240
4241 case SVE::BI__builtin_sve_svset_neonq_s8:
4242 case SVE::BI__builtin_sve_svset_neonq_s16:
4243 case SVE::BI__builtin_sve_svset_neonq_s32:
4244 case SVE::BI__builtin_sve_svset_neonq_s64:
4245 case SVE::BI__builtin_sve_svset_neonq_u8:
4246 case SVE::BI__builtin_sve_svset_neonq_u16:
4247 case SVE::BI__builtin_sve_svset_neonq_u32:
4248 case SVE::BI__builtin_sve_svset_neonq_u64:
4249 case SVE::BI__builtin_sve_svset_neonq_f16:
4250 case SVE::BI__builtin_sve_svset_neonq_f32:
4251 case SVE::BI__builtin_sve_svset_neonq_f64:
4252 case SVE::BI__builtin_sve_svset_neonq_bf16:
4253 case SVE::BI__builtin_sve_svset_neonq_mf8: {
4254 return Builder.CreateInsertVector(Ty, Ops[0], Ops[1], uint64_t(0));
4255 }
4256
4257 case SVE::BI__builtin_sve_svget_neonq_s8:
4258 case SVE::BI__builtin_sve_svget_neonq_s16:
4259 case SVE::BI__builtin_sve_svget_neonq_s32:
4260 case SVE::BI__builtin_sve_svget_neonq_s64:
4261 case SVE::BI__builtin_sve_svget_neonq_u8:
4262 case SVE::BI__builtin_sve_svget_neonq_u16:
4263 case SVE::BI__builtin_sve_svget_neonq_u32:
4264 case SVE::BI__builtin_sve_svget_neonq_u64:
4265 case SVE::BI__builtin_sve_svget_neonq_f16:
4266 case SVE::BI__builtin_sve_svget_neonq_f32:
4267 case SVE::BI__builtin_sve_svget_neonq_f64:
4268 case SVE::BI__builtin_sve_svget_neonq_bf16:
4269 case SVE::BI__builtin_sve_svget_neonq_mf8: {
4270 return Builder.CreateExtractVector(Ty, Ops[0], uint64_t(0));
4271 }
4272
4273 case SVE::BI__builtin_sve_svdup_neonq_s8:
4274 case SVE::BI__builtin_sve_svdup_neonq_s16:
4275 case SVE::BI__builtin_sve_svdup_neonq_s32:
4276 case SVE::BI__builtin_sve_svdup_neonq_s64:
4277 case SVE::BI__builtin_sve_svdup_neonq_u8:
4278 case SVE::BI__builtin_sve_svdup_neonq_u16:
4279 case SVE::BI__builtin_sve_svdup_neonq_u32:
4280 case SVE::BI__builtin_sve_svdup_neonq_u64:
4281 case SVE::BI__builtin_sve_svdup_neonq_f16:
4282 case SVE::BI__builtin_sve_svdup_neonq_f32:
4283 case SVE::BI__builtin_sve_svdup_neonq_f64:
4284 case SVE::BI__builtin_sve_svdup_neonq_bf16:
4285 case SVE::BI__builtin_sve_svdup_neonq_mf8: {
4286 Value *Insert = Builder.CreateInsertVector(Ty, PoisonValue::get(Ty), Ops[0],
4287 uint64_t(0));
4288 return Builder.CreateIntrinsic(Intrinsic::aarch64_sve_dupq_lane, {Ty},
4289 {Insert, Builder.getInt64(0)});
4290 }
4291 }
4292
4293 /// Should not happen
4294 return nullptr;
4295}
4296
4297static void swapCommutativeSMEOperands(unsigned BuiltinID,
4299 unsigned MultiVec;
4300 switch (BuiltinID) {
4301 default:
4302 return;
4303 case SME::BI__builtin_sme_svsumla_za32_s8_vg4x1:
4304 MultiVec = 1;
4305 break;
4306 case SME::BI__builtin_sme_svsumla_za32_s8_vg4x2:
4307 case SME::BI__builtin_sme_svsudot_za32_s8_vg1x2:
4308 MultiVec = 2;
4309 break;
4310 case SME::BI__builtin_sme_svsudot_za32_s8_vg1x4:
4311 case SME::BI__builtin_sme_svsumla_za32_s8_vg4x4:
4312 MultiVec = 4;
4313 break;
4314 }
4315
4316 if (MultiVec > 0)
4317 for (unsigned I = 0; I < MultiVec; ++I)
4318 std::swap(Ops[I + 1], Ops[I + 1 + MultiVec]);
4319}
4320
4322 const CallExpr *E) {
4323 auto *Builtin =
4326
4328 SVETypeFlags TypeFlags(Builtin->TypeModifier);
4329 GetAArch64SVEProcessedOperands(BuiltinID, E, Ops, TypeFlags);
4330
4331 if (TypeFlags.isLoad() || TypeFlags.isStore())
4332 return EmitSMELd1St1(TypeFlags, Ops, Builtin->LLVMIntrinsic);
4333 if (TypeFlags.isReadZA() || TypeFlags.isWriteZA())
4334 return EmitSMEReadWrite(TypeFlags, Ops, Builtin->LLVMIntrinsic);
4335 if (BuiltinID == SME::BI__builtin_sme_svzero_mask_za ||
4336 BuiltinID == SME::BI__builtin_sme_svzero_za)
4337 return EmitSMEZero(TypeFlags, Ops, Builtin->LLVMIntrinsic);
4338 if (BuiltinID == SME::BI__builtin_sme_svldr_vnum_za ||
4339 BuiltinID == SME::BI__builtin_sme_svstr_vnum_za ||
4340 BuiltinID == SME::BI__builtin_sme_svldr_za ||
4341 BuiltinID == SME::BI__builtin_sme_svstr_za)
4342 return EmitSMELdrStr(TypeFlags, Ops, Builtin->LLVMIntrinsic);
4343
4344 // Emit set FPMR for intrinsics that require it
4345 if (TypeFlags.setsFPMR())
4346 Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_set_fpmr),
4347 Ops.pop_back_val());
4348 // Handle builtins which require their multi-vector operands to be swapped
4349 swapCommutativeSMEOperands(BuiltinID, Ops);
4350
4351 auto isCntsBuiltin = [&]() {
4352 switch (BuiltinID) {
4353 default:
4354 return 0;
4355 case SME::BI__builtin_sme_svcntsb:
4356 return 8;
4357 case SME::BI__builtin_sme_svcntsh:
4358 return 4;
4359 case SME::BI__builtin_sme_svcntsw:
4360 return 2;
4361 }
4362 };
4363
4364 if (auto Mul = isCntsBuiltin()) {
4365 llvm::Value *Cntd =
4366 Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_sme_cntsd));
4367 return Builder.CreateMul(Cntd, llvm::ConstantInt::get(Int64Ty, Mul),
4368 "mulsvl", /* HasNUW */ true, /* HasNSW */ true);
4369 }
4370
4371 // Should not happen!
4372 if (Builtin->LLVMIntrinsic == 0)
4373 return nullptr;
4374
4375 // Predicates must match the main datatype.
4376 for (Value *&Op : Ops)
4377 if (auto PredTy = dyn_cast<llvm::VectorType>(Op->getType()))
4378 if (PredTy->getElementType()->isIntegerTy(1))
4379 Op = EmitSVEPredicateCast(Op, getSVEType(TypeFlags));
4380
4381 if (BuiltinID == SME::BI__builtin_sme_svldr_zt ||
4382 BuiltinID == SME::BI__builtin_sme_svstr_zt) {
4383 Function *F = CGM.getIntrinsic(Builtin->LLVMIntrinsic, Ops[1]->getType());
4384 return Builder.CreateCall(F, Ops);
4385 }
4386
4387 Function *F =
4388 TypeFlags.isOverloadNone()
4389 ? CGM.getIntrinsic(Builtin->LLVMIntrinsic)
4390 : CGM.getIntrinsic(Builtin->LLVMIntrinsic, {getSVEType(TypeFlags)});
4391
4392 return Builder.CreateCall(F, Ops);
4393}
4394
4395/// Helper for the read/write/add/inc X18 builtins: read the X18 register and
4396/// return it as an i8 pointer.
4398 LLVMContext &Context = CGF.CGM.getLLVMContext();
4399 llvm::Metadata *Ops[] = {llvm::MDString::get(Context, "x18")};
4400 llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
4401 llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
4402 llvm::Function *F =
4403 CGF.CGM.getIntrinsic(Intrinsic::read_register, {CGF.Int64Ty});
4404 llvm::Value *X18 = CGF.Builder.CreateCall(F, Metadata);
4405 return CGF.Builder.CreateIntToPtr(X18, CGF.Int8PtrTy);
4406}
4407
4409 const CallExpr *E,
4410 llvm::Triple::ArchType Arch) {
4411 if (BuiltinID >= clang::AArch64::FirstSVEBuiltin &&
4412 BuiltinID <= clang::AArch64::LastSVEBuiltin)
4413 return EmitAArch64SVEBuiltinExpr(BuiltinID, E);
4414
4415 if (BuiltinID >= clang::AArch64::FirstSMEBuiltin &&
4416 BuiltinID <= clang::AArch64::LastSMEBuiltin)
4417 return EmitAArch64SMEBuiltinExpr(BuiltinID, E);
4418
4419 if (BuiltinID == Builtin::BI__builtin_cpu_supports)
4420 return EmitAArch64CpuSupports(E);
4421
4422 unsigned HintID = static_cast<unsigned>(-1);
4423 switch (BuiltinID) {
4424 default: break;
4425 case clang::AArch64::BI__builtin_arm_nop:
4426 HintID = 0;
4427 break;
4428 case clang::AArch64::BI__builtin_arm_yield:
4429 case clang::AArch64::BI__yield:
4430 HintID = 1;
4431 break;
4432 case clang::AArch64::BI__builtin_arm_wfe:
4433 case clang::AArch64::BI__wfe:
4434 HintID = 2;
4435 break;
4436 case clang::AArch64::BI__builtin_arm_wfi:
4437 case clang::AArch64::BI__wfi:
4438 HintID = 3;
4439 break;
4440 case clang::AArch64::BI__builtin_arm_sev:
4441 case clang::AArch64::BI__sev:
4442 HintID = 4;
4443 break;
4444 case clang::AArch64::BI__builtin_arm_sevl:
4445 case clang::AArch64::BI__sevl:
4446 HintID = 5;
4447 break;
4448 }
4449
4450 if (HintID != static_cast<unsigned>(-1)) {
4451 Function *F = CGM.getIntrinsic(Intrinsic::aarch64_hint);
4452 return Builder.CreateCall(F, llvm::ConstantInt::get(Int32Ty, HintID));
4453 }
4454
4455 if (BuiltinID == clang::AArch64::BI__builtin_arm_trap) {
4456 Function *F = CGM.getIntrinsic(Intrinsic::aarch64_break);
4457 llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
4458 return Builder.CreateCall(F, Builder.CreateZExt(Arg, CGM.Int32Ty));
4459 }
4460
4461 if (BuiltinID == clang::AArch64::BI__builtin_arm_get_sme_state) {
4462 // Create call to __arm_sme_state and store the results to the two pointers.
4463 CallInst *CI = EmitRuntimeCall(CGM.CreateRuntimeFunction(
4464 llvm::FunctionType::get(StructType::get(CGM.Int64Ty, CGM.Int64Ty), {},
4465 false),
4466 "__arm_sme_state"));
4467 auto Attrs = AttributeList().addFnAttribute(getLLVMContext(),
4468 "aarch64_pstate_sm_compatible");
4469 CI->setAttributes(Attrs);
4470 CI->setCallingConv(
4471 llvm::CallingConv::
4472 AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2);
4473 Builder.CreateStore(Builder.CreateExtractValue(CI, 0),
4475 return Builder.CreateStore(Builder.CreateExtractValue(CI, 1),
4477 }
4478
4479 if (BuiltinID == clang::AArch64::BI__builtin_arm_rbit) {
4480 assert((getContext().getTypeSize(E->getType()) == 32) &&
4481 "rbit of unusual size!");
4482 llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
4483 return Builder.CreateCall(
4484 CGM.getIntrinsic(Intrinsic::bitreverse, Arg->getType()), Arg, "rbit");
4485 }
4486 if (BuiltinID == clang::AArch64::BI__builtin_arm_rbit64) {
4487 assert((getContext().getTypeSize(E->getType()) == 64) &&
4488 "rbit of unusual size!");
4489 llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
4490 return Builder.CreateCall(
4491 CGM.getIntrinsic(Intrinsic::bitreverse, Arg->getType()), Arg, "rbit");
4492 }
4493
4494 if (BuiltinID == clang::AArch64::BI__builtin_arm_clz ||
4495 BuiltinID == clang::AArch64::BI__builtin_arm_clz64) {
4496 llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
4497 Function *F = CGM.getIntrinsic(Intrinsic::ctlz, Arg->getType());
4498 Value *Res = Builder.CreateCall(F, {Arg, Builder.getInt1(false)});
4499 if (BuiltinID == clang::AArch64::BI__builtin_arm_clz64)
4500 Res = Builder.CreateTrunc(Res, Builder.getInt32Ty());
4501 return Res;
4502 }
4503
4504 if (BuiltinID == clang::AArch64::BI__builtin_arm_cls) {
4505 llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
4506 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_cls), Arg,
4507 "cls");
4508 }
4509 if (BuiltinID == clang::AArch64::BI__builtin_arm_cls64) {
4510 llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
4511 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_cls64), Arg,
4512 "cls");
4513 }
4514
4515 if (BuiltinID == clang::AArch64::BI__builtin_arm_rint32zf ||
4516 BuiltinID == clang::AArch64::BI__builtin_arm_rint32z) {
4517 llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
4518 llvm::Type *Ty = Arg->getType();
4519 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_frint32z, Ty),
4520 Arg, "frint32z");
4521 }
4522
4523 if (BuiltinID == clang::AArch64::BI__builtin_arm_rint64zf ||
4524 BuiltinID == clang::AArch64::BI__builtin_arm_rint64z) {
4525 llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
4526 llvm::Type *Ty = Arg->getType();
4527 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_frint64z, Ty),
4528 Arg, "frint64z");
4529 }
4530
4531 if (BuiltinID == clang::AArch64::BI__builtin_arm_rint32xf ||
4532 BuiltinID == clang::AArch64::BI__builtin_arm_rint32x) {
4533 llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
4534 llvm::Type *Ty = Arg->getType();
4535 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_frint32x, Ty),
4536 Arg, "frint32x");
4537 }
4538
4539 if (BuiltinID == clang::AArch64::BI__builtin_arm_rint64xf ||
4540 BuiltinID == clang::AArch64::BI__builtin_arm_rint64x) {
4541 llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
4542 llvm::Type *Ty = Arg->getType();
4543 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_frint64x, Ty),
4544 Arg, "frint64x");
4545 }
4546
4547 if (BuiltinID == clang::AArch64::BI__builtin_arm_jcvt) {
4548 assert((getContext().getTypeSize(E->getType()) == 32) &&
4549 "__jcvt of unusual size!");
4550 llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
4551 return Builder.CreateCall(
4552 CGM.getIntrinsic(Intrinsic::aarch64_fjcvtzs), Arg);
4553 }
4554
4555 if (BuiltinID == clang::AArch64::BI__builtin_arm_ld64b ||
4556 BuiltinID == clang::AArch64::BI__builtin_arm_st64b ||
4557 BuiltinID == clang::AArch64::BI__builtin_arm_st64bv ||
4558 BuiltinID == clang::AArch64::BI__builtin_arm_st64bv0) {
4559 llvm::Value *MemAddr = EmitScalarExpr(E->getArg(0));
4560 llvm::Value *ValPtr = EmitScalarExpr(E->getArg(1));
4561
4562 if (BuiltinID == clang::AArch64::BI__builtin_arm_ld64b) {
4563 // Load from the address via an LLVM intrinsic, receiving a
4564 // tuple of 8 i64 words, and store each one to ValPtr.
4565 Function *F = CGM.getIntrinsic(Intrinsic::aarch64_ld64b);
4566 llvm::Value *Val = Builder.CreateCall(F, MemAddr);
4567 llvm::Value *ToRet;
4568 for (size_t i = 0; i < 8; i++) {
4569 llvm::Value *ValOffsetPtr =
4570 Builder.CreateGEP(Int64Ty, ValPtr, Builder.getInt32(i));
4571 Address Addr =
4572 Address(ValOffsetPtr, Int64Ty, CharUnits::fromQuantity(8));
4573 ToRet = Builder.CreateStore(Builder.CreateExtractValue(Val, i), Addr);
4574 }
4575 return ToRet;
4576 }
4577
4578 // Load 8 i64 words from ValPtr, and store them to the address
4579 // via an LLVM intrinsic.
4581 Args.push_back(MemAddr);
4582 for (size_t i = 0; i < 8; i++) {
4583 llvm::Value *ValOffsetPtr =
4584 Builder.CreateGEP(Int64Ty, ValPtr, Builder.getInt32(i));
4585 Address Addr = Address(ValOffsetPtr, Int64Ty, CharUnits::fromQuantity(8));
4586 Args.push_back(Builder.CreateLoad(Addr));
4587 }
4588
4589 auto Intr = (BuiltinID == clang::AArch64::BI__builtin_arm_st64b
4590 ? Intrinsic::aarch64_st64b
4591 : BuiltinID == clang::AArch64::BI__builtin_arm_st64bv
4592 ? Intrinsic::aarch64_st64bv
4593 : Intrinsic::aarch64_st64bv0);
4594 Function *F = CGM.getIntrinsic(Intr);
4595 return Builder.CreateCall(F, Args);
4596 }
4597
4598 if (BuiltinID == clang::AArch64::BI__builtin_arm_rndr ||
4599 BuiltinID == clang::AArch64::BI__builtin_arm_rndrrs) {
4600
4601 auto Intr = (BuiltinID == clang::AArch64::BI__builtin_arm_rndr
4602 ? Intrinsic::aarch64_rndr
4603 : Intrinsic::aarch64_rndrrs);
4604 Function *F = CGM.getIntrinsic(Intr);
4605 llvm::Value *Val = Builder.CreateCall(F);
4606 Value *RandomValue = Builder.CreateExtractValue(Val, 0);
4607 Value *Status = Builder.CreateExtractValue(Val, 1);
4608
4609 Address MemAddress = EmitPointerWithAlignment(E->getArg(0));
4610 Builder.CreateStore(RandomValue, MemAddress);
4611 Status = Builder.CreateZExt(Status, Int32Ty);
4612 return Status;
4613 }
4614
4615 if (BuiltinID == clang::AArch64::BI__clear_cache) {
4616 Value *Begin = EmitScalarExpr(E->getArg(0));
4617 Value *End = EmitScalarExpr(E->getArg(1));
4618 Function *F = CGM.getIntrinsic(Intrinsic::clear_cache, {CGM.DefaultPtrTy});
4619 return Builder.CreateCall(F, {Begin, End});
4620 }
4621
4622 if ((BuiltinID == clang::AArch64::BI__builtin_arm_ldrex ||
4623 BuiltinID == clang::AArch64::BI__builtin_arm_ldaex) &&
4624 getContext().getTypeSize(E->getType()) == 128) {
4625 Function *F =
4626 CGM.getIntrinsic(BuiltinID == clang::AArch64::BI__builtin_arm_ldaex
4627 ? Intrinsic::aarch64_ldaxp
4628 : Intrinsic::aarch64_ldxp);
4629
4630 Value *LdPtr = EmitScalarExpr(E->getArg(0));
4631 Value *Val = Builder.CreateCall(F, LdPtr, "ldxp");
4632
4633 Value *Val0 = Builder.CreateExtractValue(Val, 1);
4634 Value *Val1 = Builder.CreateExtractValue(Val, 0);
4635 llvm::Type *Int128Ty = llvm::IntegerType::get(getLLVMContext(), 128);
4636 Val0 = Builder.CreateZExt(Val0, Int128Ty);
4637 Val1 = Builder.CreateZExt(Val1, Int128Ty);
4638
4639 Value *ShiftCst = llvm::ConstantInt::get(Int128Ty, 64);
4640 Val = Builder.CreateShl(Val0, ShiftCst, "shl", true /* nuw */);
4641 Val = Builder.CreateOr(Val, Val1);
4642 return Builder.CreateBitCast(Val, ConvertType(E->getType()));
4643 } else if (BuiltinID == clang::AArch64::BI__builtin_arm_ldrex ||
4644 BuiltinID == clang::AArch64::BI__builtin_arm_ldaex) {
4645 Value *LoadAddr = EmitScalarExpr(E->getArg(0));
4646
4647 QualType Ty = E->getType();
4648 llvm::Type *RealResTy = ConvertType(Ty);
4649 llvm::Type *IntTy =
4650 llvm::IntegerType::get(getLLVMContext(), getContext().getTypeSize(Ty));
4651
4652 Function *F =
4653 CGM.getIntrinsic(BuiltinID == clang::AArch64::BI__builtin_arm_ldaex
4654 ? Intrinsic::aarch64_ldaxr
4655 : Intrinsic::aarch64_ldxr,
4656 DefaultPtrTy);
4657 CallInst *Val = Builder.CreateCall(F, LoadAddr, "ldxr");
4658 Val->addParamAttr(
4659 0, Attribute::get(getLLVMContext(), Attribute::ElementType, IntTy));
4660
4661 if (RealResTy->isPointerTy())
4662 return Builder.CreateIntToPtr(Val, RealResTy);
4663
4664 llvm::Type *IntResTy = llvm::IntegerType::get(
4665 getLLVMContext(), CGM.getDataLayout().getTypeSizeInBits(RealResTy));
4666 return Builder.CreateBitCast(Builder.CreateTruncOrBitCast(Val, IntResTy),
4667 RealResTy);
4668 }
4669
4670 if ((BuiltinID == clang::AArch64::BI__builtin_arm_strex ||
4671 BuiltinID == clang::AArch64::BI__builtin_arm_stlex) &&
4672 getContext().getTypeSize(E->getArg(0)->getType()) == 128) {
4673 Function *F =
4674 CGM.getIntrinsic(BuiltinID == clang::AArch64::BI__builtin_arm_stlex
4675 ? Intrinsic::aarch64_stlxp
4676 : Intrinsic::aarch64_stxp);
4677 llvm::Type *STy = llvm::StructType::get(Int64Ty, Int64Ty);
4678
4680 EmitAnyExprToMem(E->getArg(0), Tmp, Qualifiers(), /*init*/ true);
4681
4682 Tmp = Tmp.withElementType(STy);
4683 llvm::Value *Val = Builder.CreateLoad(Tmp);
4684
4685 Value *Arg0 = Builder.CreateExtractValue(Val, 0);
4686 Value *Arg1 = Builder.CreateExtractValue(Val, 1);
4687 Value *StPtr = EmitScalarExpr(E->getArg(1));
4688 return Builder.CreateCall(F, {Arg0, Arg1, StPtr}, "stxp");
4689 }
4690
4691 if (BuiltinID == clang::AArch64::BI__builtin_arm_strex ||
4692 BuiltinID == clang::AArch64::BI__builtin_arm_stlex) {
4693 Value *StoreVal = EmitScalarExpr(E->getArg(0));
4694 Value *StoreAddr = EmitScalarExpr(E->getArg(1));
4695
4696 QualType Ty = E->getArg(0)->getType();
4697 llvm::Type *StoreTy =
4698 llvm::IntegerType::get(getLLVMContext(), getContext().getTypeSize(Ty));
4699
4700 if (StoreVal->getType()->isPointerTy())
4701 StoreVal = Builder.CreatePtrToInt(StoreVal, Int64Ty);
4702 else {
4703 llvm::Type *IntTy = llvm::IntegerType::get(
4705 CGM.getDataLayout().getTypeSizeInBits(StoreVal->getType()));
4706 StoreVal = Builder.CreateBitCast(StoreVal, IntTy);
4707 StoreVal = Builder.CreateZExtOrBitCast(StoreVal, Int64Ty);
4708 }
4709
4710 Function *F =
4711 CGM.getIntrinsic(BuiltinID == clang::AArch64::BI__builtin_arm_stlex
4712 ? Intrinsic::aarch64_stlxr
4713 : Intrinsic::aarch64_stxr,
4714 StoreAddr->getType());
4715 CallInst *CI = Builder.CreateCall(F, {StoreVal, StoreAddr}, "stxr");
4716 CI->addParamAttr(
4717 1, Attribute::get(getLLVMContext(), Attribute::ElementType, StoreTy));
4718 return CI;
4719 }
4720
4721 if (BuiltinID == clang::AArch64::BI__getReg ||
4722 BuiltinID == clang::AArch64::BI__setReg) {
4724 if (!E->getArg(0)->EvaluateAsInt(Result, CGM.getContext()))
4725 llvm_unreachable("Sema will ensure that the parameter is constant");
4726
4727 llvm::APSInt Value = Result.Val.getInt();
4728 LLVMContext &Context = CGM.getLLVMContext();
4729 std::string Reg = Value == 31 ? "sp" : "x" + toString(Value, 10);
4730
4731 llvm::Metadata *Ops[] = {llvm::MDString::get(Context, Reg)};
4732 llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
4733 llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
4734
4735 CallInst *CI;
4736 if (BuiltinID == clang::AArch64::BI__getReg) {
4737 llvm::Function *F =
4738 CGM.getIntrinsic(Intrinsic::read_volatile_register, {Int64Ty});
4739 CI = Builder.CreateCall(F, Metadata);
4740 } else {
4741 llvm::Function *F =
4742 CGM.getIntrinsic(Intrinsic::write_volatile_register, {Int64Ty});
4743 CI = Builder.CreateCall(F, {Metadata, EmitScalarExpr(E->getArg(1))});
4744 }
4745 return CI;
4746 }
4747
4748 if (BuiltinID == clang::AArch64::BI__getRegFp ||
4749 BuiltinID == clang::AArch64::BI__setRegFp) {
4751 if (!E->getArg(0)->EvaluateAsInt(Result, CGM.getContext()))
4752 llvm_unreachable("Sema will ensure that the parameter is constant");
4753
4754 llvm::APSInt Value = Result.Val.getInt();
4755 LLVMContext &Context = CGM.getLLVMContext();
4756 std::string Reg = "d" + toString(Value, 10);
4757
4758 llvm::Metadata *Ops[] = {llvm::MDString::get(Context, Reg)};
4759 llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
4760 llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
4761
4762 llvm::Value *Ret;
4763 if (BuiltinID == clang::AArch64::BI__getRegFp) {
4764 llvm::Function *F =
4765 CGM.getIntrinsic(Intrinsic::read_volatile_register, {Int64Ty});
4766 llvm::Value *Bits = Builder.CreateCall(F, Metadata);
4767 Ret = Builder.CreateBitCast(Bits, llvm::Type::getDoubleTy(Context));
4768 } else {
4769 llvm::Value *Val = EmitScalarExpr(E->getArg(1));
4770 llvm::Value *Bits = Builder.CreateBitCast(Val, Int64Ty);
4771 llvm::Function *F =
4772 CGM.getIntrinsic(Intrinsic::write_volatile_register, {Int64Ty});
4773 Ret = Builder.CreateCall(F, {Metadata, Bits});
4774 }
4775 return Ret;
4776 }
4777
4778 if (BuiltinID == clang::AArch64::BI__break) {
4780 if (!E->getArg(0)->EvaluateAsInt(Result, CGM.getContext()))
4781 llvm_unreachable("Sema will ensure that the parameter is constant");
4782
4783 llvm::Function *F = CGM.getIntrinsic(Intrinsic::aarch64_break);
4784 return Builder.CreateCall(F, {EmitScalarExpr(E->getArg(0))});
4785 }
4786
4787 if (BuiltinID == clang::AArch64::BI__builtin_arm_clrex) {
4788 Function *F = CGM.getIntrinsic(Intrinsic::aarch64_clrex);
4789 return Builder.CreateCall(F);
4790 }
4791
4792 if (BuiltinID == clang::AArch64::BI_ReadWriteBarrier)
4793 return Builder.CreateFence(llvm::AtomicOrdering::SequentiallyConsistent,
4794 llvm::SyncScope::SingleThread);
4795
4796 // CRC32
4797 Intrinsic::ID CRCIntrinsicID = Intrinsic::not_intrinsic;
4798 switch (BuiltinID) {
4799 case clang::AArch64::BI__builtin_arm_crc32b:
4800 CRCIntrinsicID = Intrinsic::aarch64_crc32b; break;
4801 case clang::AArch64::BI__builtin_arm_crc32cb:
4802 CRCIntrinsicID = Intrinsic::aarch64_crc32cb; break;
4803 case clang::AArch64::BI__builtin_arm_crc32h:
4804 CRCIntrinsicID = Intrinsic::aarch64_crc32h; break;
4805 case clang::AArch64::BI__builtin_arm_crc32ch:
4806 CRCIntrinsicID = Intrinsic::aarch64_crc32ch; break;
4807 case clang::AArch64::BI__builtin_arm_crc32w:
4808 CRCIntrinsicID = Intrinsic::aarch64_crc32w; break;
4809 case clang::AArch64::BI__builtin_arm_crc32cw:
4810 CRCIntrinsicID = Intrinsic::aarch64_crc32cw; break;
4811 case clang::AArch64::BI__builtin_arm_crc32d:
4812 CRCIntrinsicID = Intrinsic::aarch64_crc32x; break;
4813 case clang::AArch64::BI__builtin_arm_crc32cd:
4814 CRCIntrinsicID = Intrinsic::aarch64_crc32cx; break;
4815 }
4816
4817 if (CRCIntrinsicID != Intrinsic::not_intrinsic) {
4818 Value *Arg0 = EmitScalarExpr(E->getArg(0));
4819 Value *Arg1 = EmitScalarExpr(E->getArg(1));
4820 Function *F = CGM.getIntrinsic(CRCIntrinsicID);
4821
4822 llvm::Type *DataTy = F->getFunctionType()->getParamType(1);
4823 Arg1 = Builder.CreateZExtOrBitCast(Arg1, DataTy);
4824
4825 return Builder.CreateCall(F, {Arg0, Arg1});
4826 }
4827
4828 // Memory Operations (MOPS)
4829 if (BuiltinID == AArch64::BI__builtin_arm_mops_memset_tag) {
4830 Value *Dst = EmitScalarExpr(E->getArg(0));
4831 Value *Val = EmitScalarExpr(E->getArg(1));
4832 Value *Size = EmitScalarExpr(E->getArg(2));
4833 Val = Builder.CreateTrunc(Val, Int8Ty);
4834 Size = Builder.CreateIntCast(Size, Int64Ty, false);
4835 return Builder.CreateCall(
4836 CGM.getIntrinsic(Intrinsic::aarch64_mops_memset_tag), {Dst, Val, Size});
4837 }
4838
4839 if (BuiltinID == AArch64::BI__builtin_arm_range_prefetch ||
4840 BuiltinID == AArch64::BI__builtin_arm_range_prefetch_x)
4841 return EmitRangePrefetchBuiltin(*this, BuiltinID, E);
4842
4843 // Memory Tagging Extensions (MTE) Intrinsics
4844 Intrinsic::ID MTEIntrinsicID = Intrinsic::not_intrinsic;
4845 switch (BuiltinID) {
4846 case clang::AArch64::BI__builtin_arm_irg:
4847 MTEIntrinsicID = Intrinsic::aarch64_irg; break;
4848 case clang::AArch64::BI__builtin_arm_addg:
4849 MTEIntrinsicID = Intrinsic::aarch64_addg; break;
4850 case clang::AArch64::BI__builtin_arm_gmi:
4851 MTEIntrinsicID = Intrinsic::aarch64_gmi; break;
4852 case clang::AArch64::BI__builtin_arm_ldg:
4853 MTEIntrinsicID = Intrinsic::aarch64_ldg; break;
4854 case clang::AArch64::BI__builtin_arm_stg:
4855 MTEIntrinsicID = Intrinsic::aarch64_stg; break;
4856 case clang::AArch64::BI__builtin_arm_subp:
4857 MTEIntrinsicID = Intrinsic::aarch64_subp; break;
4858 }
4859
4860 if (MTEIntrinsicID != Intrinsic::not_intrinsic) {
4861 if (MTEIntrinsicID == Intrinsic::aarch64_irg) {
4863 Value *Mask = EmitScalarExpr(E->getArg(1));
4864 assert(Mask->getType()->getScalarSizeInBits() == 64 &&
4865 "SemaARM::BuiltinARMMemoryTaggingCall() enforces this");
4866 return Builder.CreateCall(CGM.getIntrinsic(MTEIntrinsicID),
4867 {Pointer, Mask});
4868 }
4869 if (MTEIntrinsicID == Intrinsic::aarch64_addg) {
4871 Value *TagOffset = EmitScalarExpr(E->getArg(1));
4872
4873 TagOffset = Builder.CreateZExt(TagOffset, Int64Ty);
4874 return Builder.CreateCall(CGM.getIntrinsic(MTEIntrinsicID),
4875 {Pointer, TagOffset});
4876 }
4877 if (MTEIntrinsicID == Intrinsic::aarch64_gmi) {
4879 Value *ExcludedMask = EmitScalarExpr(E->getArg(1));
4880 assert(ExcludedMask->getType()->getScalarSizeInBits() == 64 &&
4881 "SemaARM::BuiltinARMMemoryTaggingCall() enforces this");
4882 return Builder.CreateCall(CGM.getIntrinsic(MTEIntrinsicID),
4883 {Pointer, ExcludedMask});
4884 }
4885 // Although it is possible to supply a different return
4886 // address (first arg) to this intrinsic, for now we set
4887 // return address same as input address.
4888 if (MTEIntrinsicID == Intrinsic::aarch64_ldg) {
4889 Value *TagAddress = EmitScalarExpr(E->getArg(0));
4890 return Builder.CreateCall(CGM.getIntrinsic(MTEIntrinsicID),
4891 {TagAddress, TagAddress});
4892 }
4893 // Although it is possible to supply a different tag (to set)
4894 // to this intrinsic (as first arg), for now we supply
4895 // the tag that is in input address arg (common use case).
4896 if (MTEIntrinsicID == Intrinsic::aarch64_stg) {
4897 Value *TagAddress = EmitScalarExpr(E->getArg(0));
4898 return Builder.CreateCall(CGM.getIntrinsic(MTEIntrinsicID),
4899 {TagAddress, TagAddress});
4900 }
4901 if (MTEIntrinsicID == Intrinsic::aarch64_subp) {
4902 Value *PointerA = EmitScalarExpr(E->getArg(0));
4903 Value *PointerB = EmitScalarExpr(E->getArg(1));
4904 return Builder.CreateCall(
4905 CGM.getIntrinsic(MTEIntrinsicID), {PointerA, PointerB});
4906 }
4907 }
4908
4909 if (BuiltinID == clang::AArch64::BI__builtin_arm_rsr ||
4910 BuiltinID == clang::AArch64::BI__builtin_arm_rsr64 ||
4911 BuiltinID == clang::AArch64::BI__builtin_arm_rsr128 ||
4912 BuiltinID == clang::AArch64::BI__builtin_arm_rsrp ||
4913 BuiltinID == clang::AArch64::BI__builtin_arm_wsr ||
4914 BuiltinID == clang::AArch64::BI__builtin_arm_wsr64 ||
4915 BuiltinID == clang::AArch64::BI__builtin_arm_wsr128 ||
4916 BuiltinID == clang::AArch64::BI__builtin_arm_wsrp) {
4917
4918 SpecialRegisterAccessKind AccessKind = Write;
4919 if (BuiltinID == clang::AArch64::BI__builtin_arm_rsr ||
4920 BuiltinID == clang::AArch64::BI__builtin_arm_rsr64 ||
4921 BuiltinID == clang::AArch64::BI__builtin_arm_rsr128 ||
4922 BuiltinID == clang::AArch64::BI__builtin_arm_rsrp)
4923 AccessKind = VolatileRead;
4924
4925 bool IsPointerBuiltin = BuiltinID == clang::AArch64::BI__builtin_arm_rsrp ||
4926 BuiltinID == clang::AArch64::BI__builtin_arm_wsrp;
4927
4928 bool Is32Bit = BuiltinID == clang::AArch64::BI__builtin_arm_rsr ||
4929 BuiltinID == clang::AArch64::BI__builtin_arm_wsr;
4930
4931 bool Is128Bit = BuiltinID == clang::AArch64::BI__builtin_arm_rsr128 ||
4932 BuiltinID == clang::AArch64::BI__builtin_arm_wsr128;
4933
4934 llvm::Type *ValueType;
4935 llvm::Type *RegisterType = Int64Ty;
4936 if (Is32Bit) {
4937 ValueType = Int32Ty;
4938 } else if (Is128Bit) {
4939 llvm::Type *Int128Ty =
4940 llvm::IntegerType::getInt128Ty(CGM.getLLVMContext());
4941 ValueType = Int128Ty;
4942 RegisterType = Int128Ty;
4943 } else if (IsPointerBuiltin) {
4944 ValueType = VoidPtrTy;
4945 } else {
4946 ValueType = Int64Ty;
4947 };
4948
4949 return EmitSpecialRegisterBuiltin(*this, E, RegisterType, ValueType,
4950 AccessKind);
4951 }
4952
4953 if (BuiltinID == clang::AArch64::BI_ReadStatusReg ||
4954 BuiltinID == clang::AArch64::BI_WriteStatusReg) {
4955 LLVMContext &Context = CGM.getLLVMContext();
4956
4957 unsigned SysReg =
4958 E->getArg(0)->EvaluateKnownConstInt(getContext()).getZExtValue();
4959
4960 std::string SysRegStr;
4961 llvm::raw_string_ostream(SysRegStr)
4962 << (0b10 | SysReg >> 14) << ":" << ((SysReg >> 11) & 7) << ":"
4963 << ((SysReg >> 7) & 15) << ":" << ((SysReg >> 3) & 15) << ":"
4964 << (SysReg & 7);
4965
4966 llvm::Metadata *Ops[] = { llvm::MDString::get(Context, SysRegStr) };
4967 llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
4968 llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
4969
4970 llvm::Type *RegisterType = Int64Ty;
4971 llvm::Type *Types[] = { RegisterType };
4972
4973 if (BuiltinID == clang::AArch64::BI_ReadStatusReg) {
4974 llvm::Function *F = CGM.getIntrinsic(Intrinsic::read_register, Types);
4975
4976 return Builder.CreateCall(F, Metadata);
4977 }
4978
4979 llvm::Function *F = CGM.getIntrinsic(Intrinsic::write_register, Types);
4980 llvm::Value *ArgValue = EmitScalarExpr(E->getArg(1));
4981 llvm::Value *Result = Builder.CreateCall(F, {Metadata, ArgValue});
4982
4983 return Result;
4984 }
4985
4986 if (BuiltinID == clang::AArch64::BI__sys) {
4987 unsigned SysReg =
4988 E->getArg(0)->EvaluateKnownConstInt(getContext()).getZExtValue();
4989 const unsigned Op1 = SysReg >> 11;
4990 const unsigned CRn = (SysReg >> 7) & 0xf;
4991 const unsigned CRm = (SysReg >> 3) & 0xf;
4992 const unsigned Op2 = SysReg & 0x7;
4993
4994 Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_sys),
4995 {Builder.getInt32(Op1), Builder.getInt32(CRn),
4996 Builder.getInt32(CRm), Builder.getInt32(Op2),
4997 EmitScalarExpr(E->getArg(1))});
4998
4999 // Return 0 for convenience, even though MSVC returns some other undefined
5000 // value.
5001 return ConstantInt::get(Builder.getInt32Ty(), 0);
5002 }
5003
5004 if (BuiltinID == clang::AArch64::BI_AddressOfReturnAddress) {
5005 llvm::Function *F =
5006 CGM.getIntrinsic(Intrinsic::addressofreturnaddress, AllocaInt8PtrTy);
5007 return Builder.CreateCall(F);
5008 }
5009
5010 if (BuiltinID == clang::AArch64::BI__builtin_sponentry) {
5011 llvm::Function *F = CGM.getIntrinsic(Intrinsic::sponentry, AllocaInt8PtrTy);
5012 return Builder.CreateCall(F);
5013 }
5014
5015 if (BuiltinID == clang::AArch64::BI__mulh ||
5016 BuiltinID == clang::AArch64::BI__umulh) {
5017 llvm::Type *ResType = ConvertType(E->getType());
5018 llvm::Type *Int128Ty = llvm::IntegerType::get(getLLVMContext(), 128);
5019
5020 bool IsSigned = BuiltinID == clang::AArch64::BI__mulh;
5021 Value *LHS =
5022 Builder.CreateIntCast(EmitScalarExpr(E->getArg(0)), Int128Ty, IsSigned);
5023 Value *RHS =
5024 Builder.CreateIntCast(EmitScalarExpr(E->getArg(1)), Int128Ty, IsSigned);
5025
5026 Value *MulResult, *HigherBits;
5027 if (IsSigned) {
5028 MulResult = Builder.CreateNSWMul(LHS, RHS);
5029 HigherBits = Builder.CreateAShr(MulResult, 64);
5030 } else {
5031 MulResult = Builder.CreateNUWMul(LHS, RHS);
5032 HigherBits = Builder.CreateLShr(MulResult, 64);
5033 }
5034 HigherBits = Builder.CreateIntCast(HigherBits, ResType, IsSigned);
5035
5036 return HigherBits;
5037 }
5038
5039 if (BuiltinID == AArch64::BI__writex18byte ||
5040 BuiltinID == AArch64::BI__writex18word ||
5041 BuiltinID == AArch64::BI__writex18dword ||
5042 BuiltinID == AArch64::BI__writex18qword) {
5043 // Process the args first
5044 Value *OffsetArg = EmitScalarExpr(E->getArg(0));
5045 Value *DataArg = EmitScalarExpr(E->getArg(1));
5046
5047 // Read x18 as i8*
5048 llvm::Value *X18 = readX18AsPtr(*this);
5049
5050 // Store val at x18 + offset
5051 Value *Offset = Builder.CreateZExt(OffsetArg, Int64Ty);
5052 Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset);
5053 StoreInst *Store =
5054 Builder.CreateAlignedStore(DataArg, Ptr, CharUnits::One());
5055 return Store;
5056 }
5057
5058 if (BuiltinID == AArch64::BI__readx18byte ||
5059 BuiltinID == AArch64::BI__readx18word ||
5060 BuiltinID == AArch64::BI__readx18dword ||
5061 BuiltinID == AArch64::BI__readx18qword) {
5062 // Process the args first
5063 Value *OffsetArg = EmitScalarExpr(E->getArg(0));
5064
5065 // Read x18 as i8*
5066 llvm::Value *X18 = readX18AsPtr(*this);
5067
5068 // Load x18 + offset
5069 Value *Offset = Builder.CreateZExt(OffsetArg, Int64Ty);
5070 Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset);
5071 llvm::Type *IntTy = ConvertType(E->getType());
5072 LoadInst *Load = Builder.CreateAlignedLoad(IntTy, Ptr, CharUnits::One());
5073 return Load;
5074 }
5075
5076 if (BuiltinID == AArch64::BI__addx18byte ||
5077 BuiltinID == AArch64::BI__addx18word ||
5078 BuiltinID == AArch64::BI__addx18dword ||
5079 BuiltinID == AArch64::BI__addx18qword ||
5080 BuiltinID == AArch64::BI__incx18byte ||
5081 BuiltinID == AArch64::BI__incx18word ||
5082 BuiltinID == AArch64::BI__incx18dword ||
5083 BuiltinID == AArch64::BI__incx18qword) {
5084 llvm::Type *IntTy;
5085 bool isIncrement;
5086 switch (BuiltinID) {
5087 case AArch64::BI__incx18byte:
5088 IntTy = Int8Ty;
5089 isIncrement = true;
5090 break;
5091 case AArch64::BI__incx18word:
5092 IntTy = Int16Ty;
5093 isIncrement = true;
5094 break;
5095 case AArch64::BI__incx18dword:
5096 IntTy = Int32Ty;
5097 isIncrement = true;
5098 break;
5099 case AArch64::BI__incx18qword:
5100 IntTy = Int64Ty;
5101 isIncrement = true;
5102 break;
5103 default:
5104 IntTy = ConvertType(E->getArg(1)->getType());
5105 isIncrement = false;
5106 break;
5107 }
5108 // Process the args first
5109 Value *OffsetArg = EmitScalarExpr(E->getArg(0));
5110 Value *ValToAdd =
5111 isIncrement ? ConstantInt::get(IntTy, 1) : EmitScalarExpr(E->getArg(1));
5112
5113 // Read x18 as i8*
5114 llvm::Value *X18 = readX18AsPtr(*this);
5115
5116 // Load x18 + offset
5117 Value *Offset = Builder.CreateZExt(OffsetArg, Int64Ty);
5118 Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset);
5119 LoadInst *Load = Builder.CreateAlignedLoad(IntTy, Ptr, CharUnits::One());
5120
5121 // Add values
5122 Value *AddResult = Builder.CreateAdd(Load, ValToAdd);
5123
5124 // Store val at x18 + offset
5125 StoreInst *Store =
5126 Builder.CreateAlignedStore(AddResult, Ptr, CharUnits::One());
5127 return Store;
5128 }
5129
5130 if (BuiltinID == AArch64::BI_CopyDoubleFromInt64 ||
5131 BuiltinID == AArch64::BI_CopyFloatFromInt32 ||
5132 BuiltinID == AArch64::BI_CopyInt32FromFloat ||
5133 BuiltinID == AArch64::BI_CopyInt64FromDouble) {
5134 Value *Arg = EmitScalarExpr(E->getArg(0));
5135 llvm::Type *RetTy = ConvertType(E->getType());
5136 return Builder.CreateBitCast(Arg, RetTy);
5137 }
5138
5139 if (BuiltinID == AArch64::BI_CountLeadingOnes ||
5140 BuiltinID == AArch64::BI_CountLeadingOnes64 ||
5141 BuiltinID == AArch64::BI_CountLeadingZeros ||
5142 BuiltinID == AArch64::BI_CountLeadingZeros64) {
5143 Value *Arg = EmitScalarExpr(E->getArg(0));
5144 llvm::Type *ArgType = Arg->getType();
5145
5146 if (BuiltinID == AArch64::BI_CountLeadingOnes ||
5147 BuiltinID == AArch64::BI_CountLeadingOnes64)
5148 Arg = Builder.CreateXor(Arg, Constant::getAllOnesValue(ArgType));
5149
5150 Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
5151 Value *Result = Builder.CreateCall(F, {Arg, Builder.getInt1(false)});
5152
5153 if (BuiltinID == AArch64::BI_CountLeadingOnes64 ||
5154 BuiltinID == AArch64::BI_CountLeadingZeros64)
5155 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
5156 return Result;
5157 }
5158
5159 if (BuiltinID == AArch64::BI_CountLeadingSigns ||
5160 BuiltinID == AArch64::BI_CountLeadingSigns64) {
5161 Value *Arg = EmitScalarExpr(E->getArg(0));
5162
5163 Function *F = (BuiltinID == AArch64::BI_CountLeadingSigns)
5164 ? CGM.getIntrinsic(Intrinsic::aarch64_cls)
5165 : CGM.getIntrinsic(Intrinsic::aarch64_cls64);
5166
5167 Value *Result = Builder.CreateCall(F, Arg, "cls");
5168 if (BuiltinID == AArch64::BI_CountLeadingSigns64)
5169 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
5170 return Result;
5171 }
5172
5173 if (BuiltinID == AArch64::BI_CountOneBits ||
5174 BuiltinID == AArch64::BI_CountOneBits64) {
5175 Value *ArgValue = EmitScalarExpr(E->getArg(0));
5176 llvm::Type *ArgType = ArgValue->getType();
5177 Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ArgType);
5178
5179 Value *Result = Builder.CreateCall(F, ArgValue);
5180 if (BuiltinID == AArch64::BI_CountOneBits64)
5181 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
5182 return Result;
5183 }
5184
5185 if (BuiltinID == AArch64::BI_CountTrailingZeros ||
5186 BuiltinID == AArch64::BI_CountTrailingZeros64) {
5187 Value *ArgValue = EmitScalarExpr(E->getArg(0));
5188 llvm::Type *ArgType = ArgValue->getType();
5189 Function *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
5190
5191 // MSVC leaves 0 undefined; use false for predictable codegen
5192 Value *Result = Builder.CreateCall(F, {ArgValue, Builder.getInt1(false)});
5193 if (BuiltinID == AArch64::BI_CountTrailingZeros64)
5194 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
5195 return Result;
5196 }
5197
5198 if (BuiltinID == AArch64::BI__prefetch) {
5200 Value *RW = llvm::ConstantInt::get(Int32Ty, 0);
5201 Value *Locality = ConstantInt::get(Int32Ty, 3);
5202 Value *Data = llvm::ConstantInt::get(Int32Ty, 1);
5203 Function *F = CGM.getIntrinsic(Intrinsic::prefetch, Address->getType());
5204 return Builder.CreateCall(F, {Address, RW, Locality, Data});
5205 }
5206
5207 if (BuiltinID == AArch64::BI__prefetch2) {
5209 llvm::APSInt PrfOp = E->getArg(1)->EvaluateKnownConstInt(CGM.getContext());
5210 // Decode 5-bit PRFM encoding: bits[4:3]=type, bits[2:1]=target,
5211 // bit[0]=policy
5212 // type: PLD=0(load), PLI=1(instr), PST=2(store)
5213 // target: L1=0, L2=1, L3=2
5214 // policy: KEEP=0, STRM=1
5215 uint64_t Op = PrfOp.getZExtValue();
5216 uint64_t Type = (Op >> 3) & 0x3;
5217 uint64_t Target = (Op >> 1) & 0x3;
5218 uint64_t Policy = Op & 0x1;
5219 Value *RW = Builder.getInt32(Type == 2 ? 1 : 0);
5220 Value *Local = Builder.getInt32(Target);
5221 Value *IsStream = Builder.getInt32(Policy);
5222 Value *IsData = Builder.getInt32(Type == 1 ? 0 : 1);
5223 Function *F = CGM.getIntrinsic(Intrinsic::aarch64_prefetch);
5224 return Builder.CreateCall(F, {Address, RW, Local, IsStream, IsData});
5225 }
5226
5227 if (BuiltinID == AArch64::BI__hlt) {
5228 Function *F = CGM.getIntrinsic(Intrinsic::aarch64_hlt);
5229 Builder.CreateCall(F, {EmitScalarExpr(E->getArg(0))});
5230
5231 // FIXME: MSVC documents __hlt as taking further arguments in X0-X3 and
5232 // returning the value in X0, like __hvc/__svc below. This ignores the
5233 // extra arguments and returns 0.
5234 return ConstantInt::get(Builder.getInt32Ty(), 0);
5235 }
5236
5237 if (BuiltinID == AArch64::BI__hvc || BuiltinID == AArch64::BI__svc) {
5238 unsigned IID = BuiltinID == AArch64::BI__svc ? Intrinsic::aarch64_svc
5239 : Intrinsic::aarch64_hvc;
5240 // The first argument is the instruction immediate; it must be a constant
5241 // (ImmArg on the intrinsic, encoded in the instruction). The remaining
5242 // arguments (at most four, enforced by Sema) are passed in X0-X3, widened
5243 // to 64 bits. The intrinsic takes exactly four register operands, so any
5244 // unused trailing ones are passed as poison and dropped during lowering.
5245 SmallVector<Value *, 5> Args{Builder.getInt32(
5247 for (unsigned I = 1, N = E->getNumArgs(); I < N; ++I) {
5248 Value *Arg = EmitScalarExpr(E->getArg(I));
5249 llvm::Type *ArgTy = Arg->getType();
5250 if (ArgTy->isPointerTy())
5251 Arg = Builder.CreatePtrToInt(Arg, Int64Ty);
5252 else if (ArgTy->isFloatingPointTy())
5253 // Reinterpret the bits into the integer register, matching MSVC (e.g.
5254 // "fmov x0, d0" for a double).
5255 Arg = Builder.CreateZExtOrTrunc(
5256 Builder.CreateBitCast(
5257 Arg, Builder.getIntNTy(ArgTy->getPrimitiveSizeInBits())),
5258 Int64Ty);
5259 else
5260 Arg = Builder.CreateIntCast(
5261 Arg, Int64Ty, E->getArg(I)->getType()->isSignedIntegerType());
5262 Args.push_back(Arg);
5263 }
5264 while (Args.size() < 5)
5265 Args.push_back(llvm::PoisonValue::get(Int64Ty));
5266 Value *Call = Builder.CreateCall(CGM.getIntrinsic(IID), Args);
5267 // MSVC returns unsigned int, i.e. the low 32 bits of the X0 result.
5268 return Builder.CreateTrunc(Call, Int32Ty);
5269 }
5270
5271 if (BuiltinID == NEON::BI__builtin_neon_vcvth_bf16_f32)
5272 return Builder.CreateFPTrunc(
5273 Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)),
5274 Builder.getFloatTy()),
5275 Builder.getBFloatTy());
5276
5277 // Handle MSVC intrinsics before argument evaluation to prevent double
5278 // evaluation.
5279 if (std::optional<MSVCIntrin> MsvcIntId =
5281 return EmitMSVCBuiltinExpr(*MsvcIntId, E);
5282
5283 // Some intrinsics are equivalent - if they are use the base intrinsic ID.
5284 auto It = llvm::find_if(NEONEquivalentIntrinsicMap, [BuiltinID](auto &P) {
5285 return P.first == BuiltinID;
5286 });
5287 if (It != end(NEONEquivalentIntrinsicMap))
5288 BuiltinID = It->second;
5289
5290 // Check whether this is an SISD builtin.
5291 auto SISDMap = ArrayRef(AArch64SISDIntrinsicMap);
5293 SISDMap, BuiltinID, AArch64SISDIntrinsicsProvenSorted);
5294 bool IsSISD = (Builtin != nullptr);
5295
5296 // Find out if any arguments are required to be integer constant
5297 // expressions.
5298 unsigned ICEArguments = 0;
5300 getContext().GetBuiltinType(BuiltinID, Error, &ICEArguments);
5301 assert(Error == ASTContext::GE_None && "Should not codegen an error");
5302
5304 Address PtrOp0 = Address::invalid();
5305 // Note the assumption that SISD intrinsics do not contain extra arguments.
5306 // TODO: Fold this into a single function call instead of, effectively, two
5307 // separate checks.
5308 bool HasExtraArg = !IsSISD && HasExtraNeonArgument(BuiltinID);
5309 unsigned NumArgs = E->getNumArgs() - (HasExtraArg ? 1 : 0);
5310 for (unsigned i = 0, e = NumArgs; i != e; i++) {
5311 if (i == 0) {
5312 switch (BuiltinID) {
5313 case NEON::BI__builtin_neon_vld1_v:
5314 case NEON::BI__builtin_neon_vld1q_v:
5315 case NEON::BI__builtin_neon_vld1_dup_v:
5316 case NEON::BI__builtin_neon_vld1q_dup_v:
5317 case NEON::BI__builtin_neon_vld1_lane_v:
5318 case NEON::BI__builtin_neon_vld1q_lane_v:
5319 case NEON::BI__builtin_neon_vst1_v:
5320 case NEON::BI__builtin_neon_vst1q_v:
5321 case NEON::BI__builtin_neon_vst1_lane_v:
5322 case NEON::BI__builtin_neon_vst1q_lane_v:
5323 case NEON::BI__builtin_neon_vldap1_lane_s64:
5324 case NEON::BI__builtin_neon_vldap1q_lane_s64:
5325 case NEON::BI__builtin_neon_vstl1_lane_s64:
5326 case NEON::BI__builtin_neon_vstl1q_lane_s64:
5327 // Get the alignment for the argument in addition to the value;
5328 // we'll use it later.
5329 PtrOp0 = EmitPointerWithAlignment(E->getArg(0));
5330 Ops.push_back(PtrOp0.emitRawPointer(*this));
5331 continue;
5332 }
5333 }
5334 Ops.push_back(EmitScalarOrConstFoldImmArg(ICEArguments, i, E));
5335 }
5336
5337 if (Builtin) {
5339 assert(Result && "SISD intrinsic should have been handled");
5340 return Result;
5341 }
5342
5343 const Expr *Arg = E->getArg(E->getNumArgs()-1);
5345 if (std::optional<llvm::APSInt> Result =
5347 // Determine the type of this overloaded NEON intrinsic.
5348 Type = NeonTypeFlags(Result->getZExtValue());
5349
5350 bool usgn = Type.isUnsigned();
5351 bool quad = Type.isQuad();
5352 unsigned Int;
5353
5354 // Not all intrinsics handled by the common case work for AArch64 yet, so only
5355 // defer to common code if it's been added to our special map.
5356 Builtin =
5359
5360 if (Builtin)
5362 Builtin->BuiltinID, Builtin->LLVMIntrinsic, Builtin->AltLLVMIntrinsic,
5363 Builtin->NameHint, Builtin->TypeModifier, E, Ops,
5364 /*never use addresses*/ Address::invalid(), Address::invalid(), Arch);
5365
5366 if (Value *V = EmitAArch64TblBuiltinExpr(*this, BuiltinID, E, Ops, Arch))
5367 return V;
5368
5369 // Handle non-overloaded intrinsics first.
5370 switch (BuiltinID) {
5371 default: break;
5372 case NEON::BI__builtin_neon_vabsh_f16:
5373 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::fabs, HalfTy), Ops, "vabs");
5374 case NEON::BI__builtin_neon_vaddq_p128: {
5375 llvm::Type *Ty = GetNeonType(this, NeonTypeFlags::Poly128);
5376 Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
5377 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
5378 Ops[0] = Builder.CreateXor(Ops[0], Ops[1]);
5379 llvm::Type *Int128Ty = llvm::Type::getIntNTy(getLLVMContext(), 128);
5380 return Builder.CreateBitCast(Ops[0], Int128Ty);
5381 }
5382 case NEON::BI__builtin_neon_vldrq_p128: {
5383 llvm::Type *Int128Ty = llvm::Type::getIntNTy(getLLVMContext(), 128);
5384 return Builder.CreateAlignedLoad(Int128Ty, Ops[0],
5386 }
5387 case NEON::BI__builtin_neon_vstrq_p128: {
5388 return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
5389 }
5390 case NEON::BI__builtin_neon_vcvts_f32_u32:
5391 case NEON::BI__builtin_neon_vcvtd_f64_u64:
5392 usgn = true;
5393 [[fallthrough]];
5394 case NEON::BI__builtin_neon_vcvts_f32_s32:
5395 case NEON::BI__builtin_neon_vcvtd_f64_s64: {
5396 bool Is64 = Ops[0]->getType()->getPrimitiveSizeInBits() == 64;
5397 llvm::Type *InTy = Is64 ? Int64Ty : Int32Ty;
5398 llvm::Type *FTy = Is64 ? DoubleTy : FloatTy;
5399 Ops[0] = Builder.CreateBitCast(Ops[0], InTy);
5400 if (usgn)
5401 return Builder.CreateUIToFP(Ops[0], FTy);
5402 return Builder.CreateSIToFP(Ops[0], FTy);
5403 }
5404 case NEON::BI__builtin_neon_vcvth_f16_u16:
5405 case NEON::BI__builtin_neon_vcvth_f16_u32:
5406 case NEON::BI__builtin_neon_vcvth_f16_u64:
5407 usgn = true;
5408 [[fallthrough]];
5409 case NEON::BI__builtin_neon_vcvth_f16_s16:
5410 case NEON::BI__builtin_neon_vcvth_f16_s32:
5411 case NEON::BI__builtin_neon_vcvth_f16_s64: {
5412 llvm::Type *FTy = HalfTy;
5413 llvm::Type *InTy;
5414 if (Ops[0]->getType()->getPrimitiveSizeInBits() == 64)
5415 InTy = Int64Ty;
5416 else if (Ops[0]->getType()->getPrimitiveSizeInBits() == 32)
5417 InTy = Int32Ty;
5418 else
5419 InTy = Int16Ty;
5420 Ops[0] = Builder.CreateBitCast(Ops[0], InTy);
5421 if (usgn)
5422 return Builder.CreateUIToFP(Ops[0], FTy);
5423 return Builder.CreateSIToFP(Ops[0], FTy);
5424 }
5425 case NEON::BI__builtin_neon_vcvtah_u16_f16:
5426 case NEON::BI__builtin_neon_vcvtmh_u16_f16:
5427 case NEON::BI__builtin_neon_vcvtnh_u16_f16:
5428 case NEON::BI__builtin_neon_vcvtph_u16_f16:
5429 case NEON::BI__builtin_neon_vcvtah_s16_f16:
5430 case NEON::BI__builtin_neon_vcvtmh_s16_f16:
5431 case NEON::BI__builtin_neon_vcvtnh_s16_f16:
5432 case NEON::BI__builtin_neon_vcvtph_s16_f16: {
5433 llvm::Type *InTy = Int16Ty;
5434 llvm::Type* FTy = HalfTy;
5435 llvm::Type *Tys[2] = {InTy, FTy};
5436 switch (BuiltinID) {
5437 default: llvm_unreachable("missing builtin ID in switch!");
5438 case NEON::BI__builtin_neon_vcvtah_u16_f16:
5439 Int = Intrinsic::aarch64_neon_fcvtau; break;
5440 case NEON::BI__builtin_neon_vcvtmh_u16_f16:
5441 Int = Intrinsic::aarch64_neon_fcvtmu; break;
5442 case NEON::BI__builtin_neon_vcvtnh_u16_f16:
5443 Int = Intrinsic::aarch64_neon_fcvtnu; break;
5444 case NEON::BI__builtin_neon_vcvtph_u16_f16:
5445 Int = Intrinsic::aarch64_neon_fcvtpu; break;
5446 case NEON::BI__builtin_neon_vcvtah_s16_f16:
5447 Int = Intrinsic::aarch64_neon_fcvtas; break;
5448 case NEON::BI__builtin_neon_vcvtmh_s16_f16:
5449 Int = Intrinsic::aarch64_neon_fcvtms; break;
5450 case NEON::BI__builtin_neon_vcvtnh_s16_f16:
5451 Int = Intrinsic::aarch64_neon_fcvtns; break;
5452 case NEON::BI__builtin_neon_vcvtph_s16_f16:
5453 Int = Intrinsic::aarch64_neon_fcvtps; break;
5454 }
5455 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "fcvt");
5456 }
5457 case NEON::BI__builtin_neon_vcaleh_f16:
5458 case NEON::BI__builtin_neon_vcalth_f16:
5459 case NEON::BI__builtin_neon_vcageh_f16:
5460 case NEON::BI__builtin_neon_vcagth_f16: {
5461 llvm::Type* InTy = Int32Ty;
5462 llvm::Type* FTy = HalfTy;
5463 llvm::Type *Tys[2] = {InTy, FTy};
5464 switch (BuiltinID) {
5465 default: llvm_unreachable("missing builtin ID in switch!");
5466 case NEON::BI__builtin_neon_vcageh_f16:
5467 Int = Intrinsic::aarch64_neon_facge; break;
5468 case NEON::BI__builtin_neon_vcagth_f16:
5469 Int = Intrinsic::aarch64_neon_facgt; break;
5470 case NEON::BI__builtin_neon_vcaleh_f16:
5471 Int = Intrinsic::aarch64_neon_facge; std::swap(Ops[0], Ops[1]); break;
5472 case NEON::BI__builtin_neon_vcalth_f16:
5473 Int = Intrinsic::aarch64_neon_facgt; std::swap(Ops[0], Ops[1]); break;
5474 }
5475 Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "facg");
5476 return Builder.CreateTrunc(Ops[0], Int16Ty);
5477 }
5478 case NEON::BI__builtin_neon_vcvth_n_s16_f16:
5479 case NEON::BI__builtin_neon_vcvth_n_u16_f16: {
5480 llvm::Type* InTy = Int32Ty;
5481 llvm::Type* FTy = HalfTy;
5482 llvm::Type *Tys[2] = {InTy, FTy};
5483 switch (BuiltinID) {
5484 default: llvm_unreachable("missing builtin ID in switch!");
5485 case NEON::BI__builtin_neon_vcvth_n_s16_f16:
5486 Int = Intrinsic::aarch64_neon_vcvtfp2fxs; break;
5487 case NEON::BI__builtin_neon_vcvth_n_u16_f16:
5488 Int = Intrinsic::aarch64_neon_vcvtfp2fxu; break;
5489 }
5490 Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "fcvth_n");
5491 return Builder.CreateTrunc(Ops[0], Int16Ty);
5492 }
5493 case NEON::BI__builtin_neon_vcvth_n_f16_s16:
5494 case NEON::BI__builtin_neon_vcvth_n_f16_u16: {
5495 llvm::Type* FTy = HalfTy;
5496 llvm::Type* InTy = Int32Ty;
5497 llvm::Type *Tys[2] = {FTy, InTy};
5498 switch (BuiltinID) {
5499 default: llvm_unreachable("missing builtin ID in switch!");
5500 case NEON::BI__builtin_neon_vcvth_n_f16_s16:
5501 Int = Intrinsic::aarch64_neon_vcvtfxs2fp;
5502 Ops[0] = Builder.CreateSExt(Ops[0], InTy, "sext");
5503 break;
5504 case NEON::BI__builtin_neon_vcvth_n_f16_u16:
5505 Int = Intrinsic::aarch64_neon_vcvtfxu2fp;
5506 Ops[0] = Builder.CreateZExt(Ops[0], InTy);
5507 break;
5508 }
5509 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "fcvth_n");
5510 }
5511 case NEON::BI__builtin_neon_vpaddd_s64: {
5512 // TODO: Isn't this handled by
5513 // EmitCommonNeonSISDBuiltinExpr?
5514 auto *Ty = llvm::FixedVectorType::get(Int64Ty, 2);
5515 // The vector is v2f64, so make sure it's bitcast to that.
5516 Ops[0] = Builder.CreateBitCast(Ops[0], Ty, "v2i64");
5517 llvm::Value *Idx0 = llvm::ConstantInt::get(SizeTy, 0);
5518 llvm::Value *Idx1 = llvm::ConstantInt::get(SizeTy, 1);
5519 Value *Op0 = Builder.CreateExtractElement(Ops[0], Idx0, "lane0");
5520 Value *Op1 = Builder.CreateExtractElement(Ops[0], Idx1, "lane1");
5521 // Pairwise addition of a v2f64 into a scalar f64.
5522 return Builder.CreateAdd(Op0, Op1, "vpaddd");
5523 }
5524 case NEON::BI__builtin_neon_vpaddd_f64: {
5525 auto *Ty = llvm::FixedVectorType::get(DoubleTy, 2);
5526 // The vector is v2f64, so make sure it's bitcast to that.
5527 Ops[0] = Builder.CreateBitCast(Ops[0], Ty, "v2f64");
5528 llvm::Value *Idx0 = llvm::ConstantInt::get(SizeTy, 0);
5529 llvm::Value *Idx1 = llvm::ConstantInt::get(SizeTy, 1);
5530 Value *Op0 = Builder.CreateExtractElement(Ops[0], Idx0, "lane0");
5531 Value *Op1 = Builder.CreateExtractElement(Ops[0], Idx1, "lane1");
5532 // Pairwise addition of a v2f64 into a scalar f64.
5533 return Builder.CreateFAdd(Op0, Op1, "vpaddd");
5534 }
5535 case NEON::BI__builtin_neon_vpadds_f32: {
5536 auto *Ty = llvm::FixedVectorType::get(FloatTy, 2);
5537 // The vector is v2f32, so make sure it's bitcast to that.
5538 Ops[0] = Builder.CreateBitCast(Ops[0], Ty, "v2f32");
5539 llvm::Value *Idx0 = llvm::ConstantInt::get(SizeTy, 0);
5540 llvm::Value *Idx1 = llvm::ConstantInt::get(SizeTy, 1);
5541 Value *Op0 = Builder.CreateExtractElement(Ops[0], Idx0, "lane0");
5542 Value *Op1 = Builder.CreateExtractElement(Ops[0], Idx1, "lane1");
5543 // Pairwise addition of a v2f32 into a scalar f32.
5544 return Builder.CreateFAdd(Op0, Op1, "vpaddd");
5545 }
5546 case NEON::BI__builtin_neon_vceqzd_s64:
5549 ICmpInst::ICMP_EQ, "vceqz");
5550 case NEON::BI__builtin_neon_vceqzd_f64:
5551 case NEON::BI__builtin_neon_vceqzs_f32:
5552 case NEON::BI__builtin_neon_vceqzh_f16:
5555 ICmpInst::FCMP_OEQ, "vceqz");
5556 case NEON::BI__builtin_neon_vcgezd_s64:
5559 ICmpInst::ICMP_SGE, "vcgez");
5560 case NEON::BI__builtin_neon_vcgezd_f64:
5561 case NEON::BI__builtin_neon_vcgezs_f32:
5562 case NEON::BI__builtin_neon_vcgezh_f16:
5565 ICmpInst::FCMP_OGE, "vcgez");
5566 case NEON::BI__builtin_neon_vclezd_s64:
5569 ICmpInst::ICMP_SLE, "vclez");
5570 case NEON::BI__builtin_neon_vclezd_f64:
5571 case NEON::BI__builtin_neon_vclezs_f32:
5572 case NEON::BI__builtin_neon_vclezh_f16:
5575 ICmpInst::FCMP_OLE, "vclez");
5576 case NEON::BI__builtin_neon_vcgtzd_s64:
5579 ICmpInst::ICMP_SGT, "vcgtz");
5580 case NEON::BI__builtin_neon_vcgtzd_f64:
5581 case NEON::BI__builtin_neon_vcgtzs_f32:
5582 case NEON::BI__builtin_neon_vcgtzh_f16:
5585 ICmpInst::FCMP_OGT, "vcgtz");
5586 case NEON::BI__builtin_neon_vcltzd_s64:
5589 ICmpInst::ICMP_SLT, "vcltz");
5590
5591 case NEON::BI__builtin_neon_vcltzd_f64:
5592 case NEON::BI__builtin_neon_vcltzs_f32:
5593 case NEON::BI__builtin_neon_vcltzh_f16:
5596 ICmpInst::FCMP_OLT, "vcltz");
5597
5598 case NEON::BI__builtin_neon_vceqzd_u64: {
5601 ICmpInst::ICMP_EQ, "vceqzd");
5602 }
5603 case NEON::BI__builtin_neon_vceqd_f64:
5604 case NEON::BI__builtin_neon_vcled_f64:
5605 case NEON::BI__builtin_neon_vcltd_f64:
5606 case NEON::BI__builtin_neon_vcged_f64:
5607 case NEON::BI__builtin_neon_vcgtd_f64: {
5608 llvm::CmpInst::Predicate P;
5609 switch (BuiltinID) {
5610 default: llvm_unreachable("missing builtin ID in switch!");
5611 case NEON::BI__builtin_neon_vceqd_f64: P = llvm::FCmpInst::FCMP_OEQ; break;
5612 case NEON::BI__builtin_neon_vcled_f64: P = llvm::FCmpInst::FCMP_OLE; break;
5613 case NEON::BI__builtin_neon_vcltd_f64: P = llvm::FCmpInst::FCMP_OLT; break;
5614 case NEON::BI__builtin_neon_vcged_f64: P = llvm::FCmpInst::FCMP_OGE; break;
5615 case NEON::BI__builtin_neon_vcgtd_f64: P = llvm::FCmpInst::FCMP_OGT; break;
5616 }
5617 Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy);
5618 Ops[1] = Builder.CreateBitCast(Ops[1], DoubleTy);
5619 if (P == llvm::FCmpInst::FCMP_OEQ)
5620 Ops[0] = Builder.CreateFCmp(P, Ops[0], Ops[1]);
5621 else
5622 Ops[0] = Builder.CreateFCmpS(P, Ops[0], Ops[1]);
5623 return Builder.CreateSExt(Ops[0], Int64Ty, "vcmpd");
5624 }
5625 case NEON::BI__builtin_neon_vceqs_f32:
5626 case NEON::BI__builtin_neon_vcles_f32:
5627 case NEON::BI__builtin_neon_vclts_f32:
5628 case NEON::BI__builtin_neon_vcges_f32:
5629 case NEON::BI__builtin_neon_vcgts_f32: {
5630 llvm::CmpInst::Predicate P;
5631 switch (BuiltinID) {
5632 default: llvm_unreachable("missing builtin ID in switch!");
5633 case NEON::BI__builtin_neon_vceqs_f32: P = llvm::FCmpInst::FCMP_OEQ; break;
5634 case NEON::BI__builtin_neon_vcles_f32: P = llvm::FCmpInst::FCMP_OLE; break;
5635 case NEON::BI__builtin_neon_vclts_f32: P = llvm::FCmpInst::FCMP_OLT; break;
5636 case NEON::BI__builtin_neon_vcges_f32: P = llvm::FCmpInst::FCMP_OGE; break;
5637 case NEON::BI__builtin_neon_vcgts_f32: P = llvm::FCmpInst::FCMP_OGT; break;
5638 }
5639 Ops[0] = Builder.CreateBitCast(Ops[0], FloatTy);
5640 Ops[1] = Builder.CreateBitCast(Ops[1], FloatTy);
5641 if (P == llvm::FCmpInst::FCMP_OEQ)
5642 Ops[0] = Builder.CreateFCmp(P, Ops[0], Ops[1]);
5643 else
5644 Ops[0] = Builder.CreateFCmpS(P, Ops[0], Ops[1]);
5645 return Builder.CreateSExt(Ops[0], Int32Ty, "vcmpd");
5646 }
5647 case NEON::BI__builtin_neon_vceqh_f16:
5648 case NEON::BI__builtin_neon_vcleh_f16:
5649 case NEON::BI__builtin_neon_vclth_f16:
5650 case NEON::BI__builtin_neon_vcgeh_f16:
5651 case NEON::BI__builtin_neon_vcgth_f16: {
5652 llvm::CmpInst::Predicate P;
5653 switch (BuiltinID) {
5654 default: llvm_unreachable("missing builtin ID in switch!");
5655 case NEON::BI__builtin_neon_vceqh_f16: P = llvm::FCmpInst::FCMP_OEQ; break;
5656 case NEON::BI__builtin_neon_vcleh_f16: P = llvm::FCmpInst::FCMP_OLE; break;
5657 case NEON::BI__builtin_neon_vclth_f16: P = llvm::FCmpInst::FCMP_OLT; break;
5658 case NEON::BI__builtin_neon_vcgeh_f16: P = llvm::FCmpInst::FCMP_OGE; break;
5659 case NEON::BI__builtin_neon_vcgth_f16: P = llvm::FCmpInst::FCMP_OGT; break;
5660 }
5661 Ops[0] = Builder.CreateBitCast(Ops[0], HalfTy);
5662 Ops[1] = Builder.CreateBitCast(Ops[1], HalfTy);
5663 if (P == llvm::FCmpInst::FCMP_OEQ)
5664 Ops[0] = Builder.CreateFCmp(P, Ops[0], Ops[1]);
5665 else
5666 Ops[0] = Builder.CreateFCmpS(P, Ops[0], Ops[1]);
5667 return Builder.CreateSExt(Ops[0], Int16Ty, "vcmpd");
5668 }
5669 case NEON::BI__builtin_neon_vceqd_s64:
5670 case NEON::BI__builtin_neon_vceqd_u64:
5671 case NEON::BI__builtin_neon_vcgtd_s64:
5672 case NEON::BI__builtin_neon_vcgtd_u64:
5673 case NEON::BI__builtin_neon_vcltd_s64:
5674 case NEON::BI__builtin_neon_vcltd_u64:
5675 case NEON::BI__builtin_neon_vcged_u64:
5676 case NEON::BI__builtin_neon_vcged_s64:
5677 case NEON::BI__builtin_neon_vcled_u64:
5678 case NEON::BI__builtin_neon_vcled_s64: {
5679 llvm::CmpInst::Predicate P;
5680 switch (BuiltinID) {
5681 default: llvm_unreachable("missing builtin ID in switch!");
5682 case NEON::BI__builtin_neon_vceqd_s64:
5683 case NEON::BI__builtin_neon_vceqd_u64:P = llvm::ICmpInst::ICMP_EQ;break;
5684 case NEON::BI__builtin_neon_vcgtd_s64:P = llvm::ICmpInst::ICMP_SGT;break;
5685 case NEON::BI__builtin_neon_vcgtd_u64:P = llvm::ICmpInst::ICMP_UGT;break;
5686 case NEON::BI__builtin_neon_vcltd_s64:P = llvm::ICmpInst::ICMP_SLT;break;
5687 case NEON::BI__builtin_neon_vcltd_u64:P = llvm::ICmpInst::ICMP_ULT;break;
5688 case NEON::BI__builtin_neon_vcged_u64:P = llvm::ICmpInst::ICMP_UGE;break;
5689 case NEON::BI__builtin_neon_vcged_s64:P = llvm::ICmpInst::ICMP_SGE;break;
5690 case NEON::BI__builtin_neon_vcled_u64:P = llvm::ICmpInst::ICMP_ULE;break;
5691 case NEON::BI__builtin_neon_vcled_s64:P = llvm::ICmpInst::ICMP_SLE;break;
5692 }
5693 Ops[0] = Builder.CreateBitCast(Ops[0], Int64Ty);
5694 Ops[1] = Builder.CreateBitCast(Ops[1], Int64Ty);
5695 Ops[0] = Builder.CreateICmp(P, Ops[0], Ops[1]);
5696 return Builder.CreateSExt(Ops[0], Int64Ty, "vceqd");
5697 }
5698 case NEON::BI__builtin_neon_vnegd_s64:
5699 return Builder.CreateNeg(Ops[0], "vnegd");
5700 case NEON::BI__builtin_neon_vnegh_f16:
5701 return Builder.CreateFNeg(Ops[0], "vnegh");
5702 case NEON::BI__builtin_neon_vtstd_s64:
5703 case NEON::BI__builtin_neon_vtstd_u64: {
5704 Ops[0] = Builder.CreateBitCast(Ops[0], Int64Ty);
5705 Ops[1] = Builder.CreateBitCast(Ops[1], Int64Ty);
5706 Ops[0] = Builder.CreateAnd(Ops[0], Ops[1]);
5707 Ops[0] = Builder.CreateICmp(ICmpInst::ICMP_NE, Ops[0],
5708 llvm::Constant::getNullValue(Int64Ty));
5709 return Builder.CreateSExt(Ops[0], Int64Ty, "vtstd");
5710 }
5711 case NEON::BI__builtin_neon_vset_lane_i8:
5712 case NEON::BI__builtin_neon_vset_lane_i16:
5713 case NEON::BI__builtin_neon_vset_lane_i32:
5714 case NEON::BI__builtin_neon_vset_lane_i64:
5715 case NEON::BI__builtin_neon_vset_lane_bf16:
5716 case NEON::BI__builtin_neon_vset_lane_f32:
5717 case NEON::BI__builtin_neon_vsetq_lane_i8:
5718 case NEON::BI__builtin_neon_vsetq_lane_i16:
5719 case NEON::BI__builtin_neon_vsetq_lane_i32:
5720 case NEON::BI__builtin_neon_vsetq_lane_i64:
5721 case NEON::BI__builtin_neon_vsetq_lane_bf16:
5722 case NEON::BI__builtin_neon_vsetq_lane_f32:
5723 return Builder.CreateInsertElement(Ops[1], Ops[0], Ops[2], "vset_lane");
5724 case NEON::BI__builtin_neon_vset_lane_f64:
5725 // The vector type needs a cast for the v1f64 variant.
5726 Ops[1] =
5727 Builder.CreateBitCast(Ops[1], llvm::FixedVectorType::get(DoubleTy, 1));
5728 return Builder.CreateInsertElement(Ops[1], Ops[0], Ops[2], "vset_lane");
5729 case NEON::BI__builtin_neon_vset_lane_mf8:
5730 case NEON::BI__builtin_neon_vsetq_lane_mf8:
5731 // The input vector type needs a cast to scalar type.
5732 Ops[0] =
5733 Builder.CreateBitCast(Ops[0], llvm::Type::getInt8Ty(getLLVMContext()));
5734 return Builder.CreateInsertElement(Ops[1], Ops[0], Ops[2], "vset_lane");
5735 case NEON::BI__builtin_neon_vsetq_lane_f64:
5736 // The vector type needs a cast for the v2f64 variant.
5737 Ops[1] =
5738 Builder.CreateBitCast(Ops[1], llvm::FixedVectorType::get(DoubleTy, 2));
5739 return Builder.CreateInsertElement(Ops[1], Ops[0], Ops[2], "vset_lane");
5740
5741 case NEON::BI__builtin_neon_vget_lane_i8:
5742 case NEON::BI__builtin_neon_vdupb_lane_i8:
5743 return Builder.CreateExtractElement(Ops[0], Ops[1], "vget_lane");
5744 case NEON::BI__builtin_neon_vgetq_lane_i8:
5745 case NEON::BI__builtin_neon_vdupb_laneq_i8:
5746 return Builder.CreateExtractElement(Ops[0], Ops[1], "vgetq_lane");
5747 case NEON::BI__builtin_neon_vget_lane_mf8:
5748 case NEON::BI__builtin_neon_vdupb_lane_mf8:
5749 case NEON::BI__builtin_neon_vgetq_lane_mf8:
5750 case NEON::BI__builtin_neon_vdupb_laneq_mf8:
5751 return Builder.CreateExtractElement(Ops[0], Ops[1], "vget_lane");
5752 case NEON::BI__builtin_neon_vget_lane_i16:
5753 case NEON::BI__builtin_neon_vduph_lane_i16:
5754 return Builder.CreateExtractElement(Ops[0], Ops[1], "vget_lane");
5755 case NEON::BI__builtin_neon_vgetq_lane_i16:
5756 case NEON::BI__builtin_neon_vduph_laneq_i16:
5757 return Builder.CreateExtractElement(Ops[0], Ops[1], "vgetq_lane");
5758 case NEON::BI__builtin_neon_vget_lane_i32:
5759 case NEON::BI__builtin_neon_vdups_lane_i32:
5760 return Builder.CreateExtractElement(Ops[0], Ops[1], "vget_lane");
5761 case NEON::BI__builtin_neon_vdups_lane_f32:
5762 return Builder.CreateExtractElement(Ops[0], Ops[1], "vdups_lane");
5763 case NEON::BI__builtin_neon_vgetq_lane_i32:
5764 case NEON::BI__builtin_neon_vdups_laneq_i32:
5765 return Builder.CreateExtractElement(Ops[0], Ops[1], "vgetq_lane");
5766 case NEON::BI__builtin_neon_vget_lane_i64:
5767 case NEON::BI__builtin_neon_vdupd_lane_i64:
5768 return Builder.CreateExtractElement(Ops[0], Ops[1], "vget_lane");
5769 case NEON::BI__builtin_neon_vdupd_lane_f64:
5770 return Builder.CreateExtractElement(Ops[0], Ops[1], "vdupd_lane");
5771 case NEON::BI__builtin_neon_vgetq_lane_i64:
5772 case NEON::BI__builtin_neon_vdupd_laneq_i64:
5773 return Builder.CreateExtractElement(Ops[0], Ops[1], "vgetq_lane");
5774 case NEON::BI__builtin_neon_vget_lane_f32:
5775 return Builder.CreateExtractElement(Ops[0], Ops[1], "vget_lane");
5776 case NEON::BI__builtin_neon_vget_lane_f64:
5777 return Builder.CreateExtractElement(Ops[0], Ops[1], "vget_lane");
5778 case NEON::BI__builtin_neon_vgetq_lane_f32:
5779 case NEON::BI__builtin_neon_vdups_laneq_f32:
5780 return Builder.CreateExtractElement(Ops[0], Ops[1], "vgetq_lane");
5781 case NEON::BI__builtin_neon_vgetq_lane_f64:
5782 case NEON::BI__builtin_neon_vdupd_laneq_f64:
5783 return Builder.CreateExtractElement(Ops[0], Ops[1], "vgetq_lane");
5784 case NEON::BI__builtin_neon_vaddh_f16:
5785 return Builder.CreateFAdd(Ops[0], Ops[1], "vaddh");
5786 case NEON::BI__builtin_neon_vsubh_f16:
5787 return Builder.CreateFSub(Ops[0], Ops[1], "vsubh");
5788 case NEON::BI__builtin_neon_vmulh_f16:
5789 return Builder.CreateFMul(Ops[0], Ops[1], "vmulh");
5790 case NEON::BI__builtin_neon_vdivh_f16:
5791 return Builder.CreateFDiv(Ops[0], Ops[1], "vdivh");
5792 case NEON::BI__builtin_neon_vfmah_f16:
5793 // NEON intrinsic puts accumulator first, unlike the LLVM fma.
5795 *this, Intrinsic::fma, Intrinsic::experimental_constrained_fma, HalfTy,
5796 {Ops[1], Ops[2], Ops[0]});
5797 case NEON::BI__builtin_neon_vfmsh_f16: {
5798 Value *Neg = Builder.CreateFNeg(Ops[1], "vsubh");
5799
5800 // NEON intrinsic puts accumulator first, unlike the LLVM fma.
5802 *this, Intrinsic::fma, Intrinsic::experimental_constrained_fma, HalfTy,
5803 {Neg, Ops[2], Ops[0]});
5804 }
5805 case NEON::BI__builtin_neon_vaddd_s64:
5806 case NEON::BI__builtin_neon_vaddd_u64:
5807 return Builder.CreateAdd(Ops[0], Ops[1], "vaddd");
5808 case NEON::BI__builtin_neon_vsubd_s64:
5809 case NEON::BI__builtin_neon_vsubd_u64:
5810 return Builder.CreateSub(Ops[0], Ops[1], "vsubd");
5811 case NEON::BI__builtin_neon_vqdmlalh_s16:
5812 case NEON::BI__builtin_neon_vqdmlslh_s16: {
5813 SmallVector<Value *, 2> ProductOps;
5814 ProductOps.push_back(vectorWrapScalar16(Ops[1]));
5815 ProductOps.push_back(vectorWrapScalar16(Ops[2]));
5816 auto *VTy = llvm::FixedVectorType::get(Int32Ty, 4);
5817 Ops[1] = EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_sqdmull, VTy),
5818 ProductOps, "vqdmlXl");
5819 Constant *CI = ConstantInt::get(SizeTy, 0);
5820 Ops[1] = Builder.CreateExtractElement(Ops[1], CI, "lane0");
5821
5822 unsigned AccumInt = BuiltinID == NEON::BI__builtin_neon_vqdmlalh_s16
5823 ? Intrinsic::aarch64_neon_sqadd
5824 : Intrinsic::aarch64_neon_sqsub;
5825 // Drop the 2nd multiplication argument before the accumulation
5826 Ops.pop_back();
5827 return EmitNeonCall(CGM.getIntrinsic(AccumInt, Int32Ty), Ops, "vqdmlXl");
5828 }
5829 case NEON::BI__builtin_neon_vqshlud_n_s64: {
5830 Ops[1] = Builder.CreateZExt(Ops[1], Int64Ty);
5831 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_sqshlu, Int64Ty),
5832 Ops, "vqshlu_n");
5833 }
5834 case NEON::BI__builtin_neon_vqshld_n_u64:
5835 case NEON::BI__builtin_neon_vqshld_n_s64: {
5836 Int = BuiltinID == NEON::BI__builtin_neon_vqshld_n_u64
5837 ? Intrinsic::aarch64_neon_uqshl
5838 : Intrinsic::aarch64_neon_sqshl;
5839 Ops[1] = Builder.CreateZExt(Ops[1], Int64Ty);
5840 return EmitNeonCall(CGM.getIntrinsic(Int, Int64Ty), Ops, "vqshl_n");
5841 }
5842 case NEON::BI__builtin_neon_vrshrd_n_u64:
5843 case NEON::BI__builtin_neon_vrshrd_n_s64: {
5844 Int = BuiltinID == NEON::BI__builtin_neon_vrshrd_n_u64
5845 ? Intrinsic::aarch64_neon_urshl
5846 : Intrinsic::aarch64_neon_srshl;
5847 int SV = cast<ConstantInt>(Ops[1])->getSExtValue();
5848 Ops[1] = ConstantInt::get(Int64Ty, -SV);
5849 return EmitNeonCall(CGM.getIntrinsic(Int, Int64Ty), Ops, "vrshr_n");
5850 }
5851 case NEON::BI__builtin_neon_vrsrad_n_u64:
5852 case NEON::BI__builtin_neon_vrsrad_n_s64: {
5853 Int = BuiltinID == NEON::BI__builtin_neon_vrsrad_n_u64
5854 ? Intrinsic::aarch64_neon_urshl
5855 : Intrinsic::aarch64_neon_srshl;
5856 Ops[1] = Builder.CreateBitCast(Ops[1], Int64Ty);
5857 Ops[2] = Builder.CreateNeg(Ops[2]);
5858 Ops[1] = Builder.CreateCall(CGM.getIntrinsic(Int, Int64Ty),
5859 {Ops[1], Builder.CreateSExt(Ops[2], Int64Ty)});
5860 return Builder.CreateAdd(Ops[0], Builder.CreateBitCast(Ops[1], Int64Ty));
5861 }
5862 case NEON::BI__builtin_neon_vshld_n_s64:
5863 case NEON::BI__builtin_neon_vshld_n_u64: {
5864 llvm::ConstantInt *Amt = cast<ConstantInt>(Ops[1]);
5865 return Builder.CreateShl(
5866 Ops[0], ConstantInt::get(Int64Ty, Amt->getZExtValue()), "shld_n");
5867 }
5868 case NEON::BI__builtin_neon_vshrd_n_s64: {
5869 llvm::ConstantInt *Amt = cast<ConstantInt>(Ops[1]);
5870 return Builder.CreateAShr(
5871 Ops[0], ConstantInt::get(Int64Ty, std::min(static_cast<uint64_t>(63),
5872 Amt->getZExtValue())),
5873 "shrd_n");
5874 }
5875 case NEON::BI__builtin_neon_vshrd_n_u64: {
5876 llvm::ConstantInt *Amt = cast<ConstantInt>(Ops[1]);
5877 uint64_t ShiftAmt = Amt->getZExtValue();
5878 // Right-shifting an unsigned value by its size yields 0.
5879 if (ShiftAmt == 64)
5880 return ConstantInt::get(Int64Ty, 0);
5881 return Builder.CreateLShr(Ops[0], ConstantInt::get(Int64Ty, ShiftAmt),
5882 "shrd_n");
5883 }
5884 case NEON::BI__builtin_neon_vsrad_n_s64: {
5885 llvm::ConstantInt *Amt = cast<ConstantInt>(Ops[2]);
5886 Ops[1] = Builder.CreateAShr(
5887 Ops[1], ConstantInt::get(Int64Ty, std::min(static_cast<uint64_t>(63),
5888 Amt->getZExtValue())),
5889 "shrd_n");
5890 return Builder.CreateAdd(Ops[0], Ops[1]);
5891 }
5892 case NEON::BI__builtin_neon_vsrad_n_u64: {
5893 llvm::ConstantInt *Amt = cast<ConstantInt>(Ops[2]);
5894 uint64_t ShiftAmt = Amt->getZExtValue();
5895 // Right-shifting an unsigned value by its size yields 0.
5896 // As Op + 0 = Op, return Ops[0] directly.
5897 if (ShiftAmt == 64)
5898 return Ops[0];
5899 Ops[1] = Builder.CreateLShr(Ops[1], ConstantInt::get(Int64Ty, ShiftAmt),
5900 "shrd_n");
5901 return Builder.CreateAdd(Ops[0], Ops[1]);
5902 }
5903 case NEON::BI__builtin_neon_vqdmlalh_lane_s16:
5904 case NEON::BI__builtin_neon_vqdmlalh_laneq_s16:
5905 case NEON::BI__builtin_neon_vqdmlslh_lane_s16:
5906 case NEON::BI__builtin_neon_vqdmlslh_laneq_s16: {
5907 Ops[2] = Builder.CreateExtractElement(Ops[2], Ops[3], "lane");
5908 SmallVector<Value *, 2> ProductOps;
5909 ProductOps.push_back(vectorWrapScalar16(Ops[1]));
5910 ProductOps.push_back(vectorWrapScalar16(Ops[2]));
5911 auto *VTy = llvm::FixedVectorType::get(Int32Ty, 4);
5912 Ops[1] = EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_sqdmull, VTy),
5913 ProductOps, "vqdmlXl");
5914 Constant *CI = ConstantInt::get(SizeTy, 0);
5915 Ops[1] = Builder.CreateExtractElement(Ops[1], CI, "lane0");
5916 // Drop lane-selection and the corresponding vector argument (these have
5917 // already been used)
5918 Ops.pop_back_n(2);
5919
5920 unsigned AccInt = (BuiltinID == NEON::BI__builtin_neon_vqdmlalh_lane_s16 ||
5921 BuiltinID == NEON::BI__builtin_neon_vqdmlalh_laneq_s16)
5922 ? Intrinsic::aarch64_neon_sqadd
5923 : Intrinsic::aarch64_neon_sqsub;
5924 return EmitNeonCall(CGM.getIntrinsic(AccInt, Int32Ty), Ops, "vqdmlXl");
5925 }
5926 case NEON::BI__builtin_neon_vqdmlals_s32:
5927 case NEON::BI__builtin_neon_vqdmlsls_s32: {
5928 SmallVector<Value *, 2> ProductOps;
5929 ProductOps.push_back(Ops[1]);
5930 ProductOps.push_back(Ops[2]);
5931 Ops[1] =
5932 EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_sqdmulls_scalar),
5933 ProductOps, "vqdmlXl");
5934
5935 unsigned AccumInt = BuiltinID == NEON::BI__builtin_neon_vqdmlals_s32
5936 ? Intrinsic::aarch64_neon_sqadd
5937 : Intrinsic::aarch64_neon_sqsub;
5938 // Drop the 2nd multiplication argument before the accumulation
5939 Ops.pop_back();
5940 return EmitNeonCall(CGM.getIntrinsic(AccumInt, Int64Ty), Ops, "vqdmlXl");
5941 }
5942 case NEON::BI__builtin_neon_vqdmlals_lane_s32:
5943 case NEON::BI__builtin_neon_vqdmlals_laneq_s32:
5944 case NEON::BI__builtin_neon_vqdmlsls_lane_s32:
5945 case NEON::BI__builtin_neon_vqdmlsls_laneq_s32: {
5946 Ops[2] = Builder.CreateExtractElement(Ops[2], Ops[3], "lane");
5947 SmallVector<Value *, 2> ProductOps;
5948 ProductOps.push_back(Ops[1]);
5949 ProductOps.push_back(Ops[2]);
5950 Ops[1] =
5951 EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_sqdmulls_scalar),
5952 ProductOps, "vqdmlXl");
5953 // Drop lane-selection and the corresponding vector argument (these have
5954 // already been used)
5955 Ops.pop_back_n(2);
5956
5957 unsigned AccInt = (BuiltinID == NEON::BI__builtin_neon_vqdmlals_lane_s32 ||
5958 BuiltinID == NEON::BI__builtin_neon_vqdmlals_laneq_s32)
5959 ? Intrinsic::aarch64_neon_sqadd
5960 : Intrinsic::aarch64_neon_sqsub;
5961 return EmitNeonCall(CGM.getIntrinsic(AccInt, Int64Ty), Ops, "vqdmlXl");
5962 }
5963 case NEON::BI__builtin_neon_vget_lane_bf16:
5964 case NEON::BI__builtin_neon_vduph_lane_bf16:
5965 case NEON::BI__builtin_neon_vduph_lane_f16: {
5966 return Builder.CreateExtractElement(Ops[0], Ops[1], "vget_lane");
5967 }
5968 case NEON::BI__builtin_neon_vgetq_lane_bf16:
5969 case NEON::BI__builtin_neon_vduph_laneq_bf16:
5970 case NEON::BI__builtin_neon_vduph_laneq_f16: {
5971 return Builder.CreateExtractElement(Ops[0], Ops[1], "vgetq_lane");
5972 }
5973 case NEON::BI__builtin_neon_vcvt_bf16_f32: {
5974 llvm::Type *V4F32 = FixedVectorType::get(Builder.getFloatTy(), 4);
5975 llvm::Type *V4BF16 = FixedVectorType::get(Builder.getBFloatTy(), 4);
5976 return Builder.CreateFPTrunc(Builder.CreateBitCast(Ops[0], V4F32), V4BF16);
5977 }
5978 case NEON::BI__builtin_neon_vcvtq_low_bf16_f32: {
5979 SmallVector<int, 16> ConcatMask(8);
5980 std::iota(ConcatMask.begin(), ConcatMask.end(), 0);
5981 llvm::Type *V4F32 = FixedVectorType::get(Builder.getFloatTy(), 4);
5982 llvm::Type *V4BF16 = FixedVectorType::get(Builder.getBFloatTy(), 4);
5983 llvm::Value *Trunc =
5984 Builder.CreateFPTrunc(Builder.CreateBitCast(Ops[0], V4F32), V4BF16);
5985 return Builder.CreateShuffleVector(
5986 Trunc, ConstantAggregateZero::get(V4BF16), ConcatMask);
5987 }
5988 case NEON::BI__builtin_neon_vcvtq_high_bf16_f32: {
5989 SmallVector<int, 16> ConcatMask(8);
5990 std::iota(ConcatMask.begin(), ConcatMask.end(), 0);
5991 SmallVector<int, 16> LoMask(4);
5992 std::iota(LoMask.begin(), LoMask.end(), 0);
5993 llvm::Type *V4F32 = FixedVectorType::get(Builder.getFloatTy(), 4);
5994 llvm::Type *V4BF16 = FixedVectorType::get(Builder.getBFloatTy(), 4);
5995 llvm::Type *V8BF16 = FixedVectorType::get(Builder.getBFloatTy(), 8);
5996 llvm::Value *Inactive = Builder.CreateShuffleVector(
5997 Builder.CreateBitCast(Ops[0], V8BF16), LoMask);
5998 llvm::Value *Trunc =
5999 Builder.CreateFPTrunc(Builder.CreateBitCast(Ops[1], V4F32), V4BF16);
6000 return Builder.CreateShuffleVector(Inactive, Trunc, ConcatMask);
6001 }
6002 case NEON::BI__builtin_neon_vcvt_f16_f32: {
6003 llvm::Type *V4F32 = FixedVectorType::get(Builder.getFloatTy(), 4);
6004 llvm::Type *V4F16 = FixedVectorType::get(Builder.getHalfTy(), 4);
6005 return Builder.CreateFPTrunc(Builder.CreateBitCast(Ops[0], V4F32), V4F16);
6006 }
6007 case NEON::BI__builtin_neon_vcvt_f32_f16: {
6008 llvm::Type *V4F32 = FixedVectorType::get(Builder.getFloatTy(), 4);
6009 llvm::Type *V4F16 = FixedVectorType::get(Builder.getHalfTy(), 4);
6010 return Builder.CreateFPExt(Builder.CreateBitCast(Ops[0], V4F16), V4F32);
6011 }
6012
6013 case clang::AArch64::BI_InterlockedAdd:
6014 case clang::AArch64::BI_InterlockedAdd_acq:
6015 case clang::AArch64::BI_InterlockedAdd_rel:
6016 case clang::AArch64::BI_InterlockedAdd_nf:
6017 case clang::AArch64::BI_InterlockedAdd64:
6018 case clang::AArch64::BI_InterlockedAdd64_acq:
6019 case clang::AArch64::BI_InterlockedAdd64_rel:
6020 case clang::AArch64::BI_InterlockedAdd64_nf: {
6021 Address DestAddr = CheckAtomicAlignment(*this, E);
6022 Value *Val = Ops[1];
6023 llvm::AtomicOrdering Ordering;
6024 switch (BuiltinID) {
6025 case clang::AArch64::BI_InterlockedAdd:
6026 case clang::AArch64::BI_InterlockedAdd64:
6027 Ordering = llvm::AtomicOrdering::SequentiallyConsistent;
6028 break;
6029 case clang::AArch64::BI_InterlockedAdd_acq:
6030 case clang::AArch64::BI_InterlockedAdd64_acq:
6031 Ordering = llvm::AtomicOrdering::Acquire;
6032 break;
6033 case clang::AArch64::BI_InterlockedAdd_rel:
6034 case clang::AArch64::BI_InterlockedAdd64_rel:
6035 Ordering = llvm::AtomicOrdering::Release;
6036 break;
6037 case clang::AArch64::BI_InterlockedAdd_nf:
6038 case clang::AArch64::BI_InterlockedAdd64_nf:
6039 Ordering = llvm::AtomicOrdering::Monotonic;
6040 break;
6041 default:
6042 llvm_unreachable("missing builtin ID in switch!");
6043 }
6044 AtomicRMWInst *RMWI =
6045 Builder.CreateAtomicRMW(AtomicRMWInst::Add, DestAddr, Val, Ordering);
6046 return Builder.CreateAdd(RMWI, Val);
6047 }
6048 }
6049
6050 llvm::FixedVectorType *VTy = GetNeonType(this, Type);
6051 llvm::Type *Ty = VTy;
6052 if (!Ty)
6053 return nullptr;
6054
6055 bool ExtractLow = false;
6056 bool ExtendLaneArg = false;
6057 switch (BuiltinID) {
6058 default: return nullptr;
6059 case NEON::BI__builtin_neon_vbsl_v:
6060 case NEON::BI__builtin_neon_vbslq_v: {
6061 llvm::Type *BitTy = llvm::VectorType::getInteger(VTy);
6062 Ops[0] = Builder.CreateBitCast(Ops[0], BitTy, "vbsl");
6063 Ops[1] = Builder.CreateBitCast(Ops[1], BitTy, "vbsl");
6064 Ops[2] = Builder.CreateBitCast(Ops[2], BitTy, "vbsl");
6065
6066 Ops[1] = Builder.CreateAnd(Ops[0], Ops[1], "vbsl");
6067 Ops[2] = Builder.CreateAnd(Builder.CreateNot(Ops[0]), Ops[2], "vbsl");
6068 Ops[0] = Builder.CreateOr(Ops[1], Ops[2], "vbsl");
6069 return Builder.CreateBitCast(Ops[0], Ty);
6070 }
6071 case NEON::BI__builtin_neon_vfma_lane_v:
6072 case NEON::BI__builtin_neon_vfmaq_lane_v: { // Only used for FP types
6073 // The ARM builtins (and instructions) have the addend as the first
6074 // operand, but the 'fma' intrinsics have it last. Swap it around here.
6075 Value *Addend = Ops[0];
6076 Value *Multiplicand = Ops[1];
6077 Value *LaneSource = Ops[2];
6078 Ops[0] = Multiplicand;
6079 Ops[1] = LaneSource;
6080 Ops[2] = Addend;
6081
6082 // Now adjust things to handle the lane access.
6083 auto *SourceTy = BuiltinID == NEON::BI__builtin_neon_vfmaq_lane_v
6084 ? llvm::FixedVectorType::get(VTy->getElementType(),
6085 VTy->getNumElements() / 2)
6086 : VTy;
6087 llvm::Constant *cst = cast<Constant>(Ops[3]);
6088 Value *SV = llvm::ConstantVector::getSplat(VTy->getElementCount(), cst);
6089 Ops[1] = Builder.CreateBitCast(Ops[1], SourceTy);
6090 Ops[1] = Builder.CreateShuffleVector(Ops[1], Ops[1], SV, "lane");
6091
6092 Ops.pop_back();
6093 Int = Builder.getIsFPConstrained() ? Intrinsic::experimental_constrained_fma
6094 : Intrinsic::fma;
6095 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "fmla");
6096 }
6097 case NEON::BI__builtin_neon_vfma_laneq_v: {
6098 auto *VTy = cast<llvm::FixedVectorType>(Ty);
6099 // v1f64 fma should be mapped to Neon scalar f64 fma
6100 if (VTy && VTy->getElementType() == DoubleTy) {
6101 Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy);
6102 Ops[1] = Builder.CreateBitCast(Ops[1], DoubleTy);
6103 llvm::FixedVectorType *VTy =
6105 Ops[2] = Builder.CreateBitCast(Ops[2], VTy);
6106 Ops[2] = Builder.CreateExtractElement(Ops[2], Ops[3], "extract");
6107 Value *Result;
6109 *this, Intrinsic::fma, Intrinsic::experimental_constrained_fma,
6110 DoubleTy, {Ops[1], Ops[2], Ops[0]});
6111 return Builder.CreateBitCast(Result, Ty);
6112 }
6113 Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
6114 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
6115
6116 auto *STy = llvm::FixedVectorType::get(VTy->getElementType(),
6117 VTy->getNumElements() * 2);
6118 Ops[2] = Builder.CreateBitCast(Ops[2], STy);
6119 Value *SV = llvm::ConstantVector::getSplat(VTy->getElementCount(),
6120 cast<ConstantInt>(Ops[3]));
6121 Ops[2] = Builder.CreateShuffleVector(Ops[2], Ops[2], SV, "lane");
6122
6124 *this, Intrinsic::fma, Intrinsic::experimental_constrained_fma, Ty,
6125 {Ops[2], Ops[1], Ops[0]});
6126 }
6127 case NEON::BI__builtin_neon_vfmaq_laneq_v: {
6128 Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
6129 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
6130
6131 Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
6132 Ops[2] = EmitNeonSplat(Ops[2], cast<ConstantInt>(Ops[3]));
6134 *this, Intrinsic::fma, Intrinsic::experimental_constrained_fma, Ty,
6135 {Ops[2], Ops[1], Ops[0]});
6136 }
6137 case NEON::BI__builtin_neon_vfmah_lane_f16:
6138 case NEON::BI__builtin_neon_vfmas_lane_f32:
6139 case NEON::BI__builtin_neon_vfmah_laneq_f16:
6140 case NEON::BI__builtin_neon_vfmas_laneq_f32:
6141 case NEON::BI__builtin_neon_vfmad_lane_f64:
6142 case NEON::BI__builtin_neon_vfmad_laneq_f64: {
6143 llvm::Type *Ty = ConvertType(E->getCallReturnType(getContext()));
6144 Ops[2] = Builder.CreateExtractElement(Ops[2], Ops[3], "extract");
6146 *this, Intrinsic::fma, Intrinsic::experimental_constrained_fma, Ty,
6147 {Ops[1], Ops[2], Ops[0]});
6148 }
6149 case NEON::BI__builtin_neon_vmull_v:
6150 // FIXME: improve sharing scheme to cope with 3 alternative LLVM intrinsics.
6151 Int = usgn ? Intrinsic::aarch64_neon_umull : Intrinsic::aarch64_neon_smull;
6152 if (Type.isPoly()) Int = Intrinsic::aarch64_neon_pmull;
6153 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmull");
6154 case NEON::BI__builtin_neon_vmax_v:
6155 case NEON::BI__builtin_neon_vmaxq_v:
6156 // FIXME: improve sharing scheme to cope with 3 alternative LLVM intrinsics.
6157 Int = usgn ? Intrinsic::aarch64_neon_umax : Intrinsic::aarch64_neon_smax;
6158 if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::aarch64_neon_fmax;
6159 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmax");
6160 case NEON::BI__builtin_neon_vmaxh_f16: {
6161 Int = Intrinsic::aarch64_neon_fmax;
6162 return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vmax");
6163 }
6164 case NEON::BI__builtin_neon_vmin_v:
6165 case NEON::BI__builtin_neon_vminq_v:
6166 // FIXME: improve sharing scheme to cope with 3 alternative LLVM intrinsics.
6167 Int = usgn ? Intrinsic::aarch64_neon_umin : Intrinsic::aarch64_neon_smin;
6168 if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::aarch64_neon_fmin;
6169 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmin");
6170 case NEON::BI__builtin_neon_vminh_f16: {
6171 Int = Intrinsic::aarch64_neon_fmin;
6172 return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vmin");
6173 }
6174 case NEON::BI__builtin_neon_vabd_v:
6175 case NEON::BI__builtin_neon_vabdq_v:
6176 // FIXME: improve sharing scheme to cope with 3 alternative LLVM intrinsics.
6177 Int = usgn ? Intrinsic::aarch64_neon_uabd : Intrinsic::aarch64_neon_sabd;
6178 if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::aarch64_neon_fabd;
6179 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vabd");
6180 case NEON::BI__builtin_neon_vpadal_v:
6181 case NEON::BI__builtin_neon_vpadalq_v: {
6182 unsigned ArgElts = VTy->getNumElements();
6183 llvm::IntegerType *EltTy = cast<IntegerType>(VTy->getElementType());
6184 unsigned BitWidth = EltTy->getBitWidth();
6185 auto *ArgTy = llvm::FixedVectorType::get(
6186 llvm::IntegerType::get(getLLVMContext(), BitWidth / 2), 2 * ArgElts);
6187 llvm::Type* Tys[2] = { VTy, ArgTy };
6188 Int = usgn ? Intrinsic::aarch64_neon_uaddlp : Intrinsic::aarch64_neon_saddlp;
6190 TmpOps.push_back(Ops[1]);
6191 Function *F = CGM.getIntrinsic(Int, Tys);
6192 llvm::Value *tmp = EmitNeonCall(F, TmpOps, "vpadal");
6193 llvm::Value *addend = Builder.CreateBitCast(Ops[0], tmp->getType());
6194 return Builder.CreateAdd(tmp, addend);
6195 }
6196 case NEON::BI__builtin_neon_vpmin_v:
6197 case NEON::BI__builtin_neon_vpminq_v:
6198 // FIXME: improve sharing scheme to cope with 3 alternative LLVM intrinsics.
6199 Int = usgn ? Intrinsic::aarch64_neon_uminp : Intrinsic::aarch64_neon_sminp;
6200 if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::aarch64_neon_fminp;
6201 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpmin");
6202 case NEON::BI__builtin_neon_vpmax_v:
6203 case NEON::BI__builtin_neon_vpmaxq_v:
6204 // FIXME: improve sharing scheme to cope with 3 alternative LLVM intrinsics.
6205 Int = usgn ? Intrinsic::aarch64_neon_umaxp : Intrinsic::aarch64_neon_smaxp;
6206 if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::aarch64_neon_fmaxp;
6207 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpmax");
6208 case NEON::BI__builtin_neon_vminnm_v:
6209 case NEON::BI__builtin_neon_vminnmq_v:
6210 Int = Intrinsic::aarch64_neon_fminnm;
6211 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vminnm");
6212 case NEON::BI__builtin_neon_vminnmh_f16:
6213 Int = Intrinsic::aarch64_neon_fminnm;
6214 return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vminnm");
6215 case NEON::BI__builtin_neon_vmaxnm_v:
6216 case NEON::BI__builtin_neon_vmaxnmq_v:
6217 Int = Intrinsic::aarch64_neon_fmaxnm;
6218 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmaxnm");
6219 case NEON::BI__builtin_neon_vmaxnmh_f16:
6220 Int = Intrinsic::aarch64_neon_fmaxnm;
6221 return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vmaxnm");
6222 case NEON::BI__builtin_neon_vrecpss_f32: {
6223 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_frecps, FloatTy),
6224 Ops, "vrecps");
6225 }
6226 case NEON::BI__builtin_neon_vrecpsd_f64:
6227 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_frecps, DoubleTy),
6228 Ops, "vrecps");
6229 case NEON::BI__builtin_neon_vrecpsh_f16:
6230 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_frecps, HalfTy),
6231 Ops, "vrecps");
6232 case NEON::BI__builtin_neon_vqshrun_n_v:
6233 Int = Intrinsic::aarch64_neon_sqshrun;
6234 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshrun_n");
6235 case NEON::BI__builtin_neon_vqrshrun_n_v:
6236 Int = Intrinsic::aarch64_neon_sqrshrun;
6237 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqrshrun_n");
6238 case NEON::BI__builtin_neon_vqshrn_n_v:
6239 Int = usgn ? Intrinsic::aarch64_neon_uqshrn : Intrinsic::aarch64_neon_sqshrn;
6240 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshrn_n");
6241 case NEON::BI__builtin_neon_vrshrn_n_v:
6242 Int = Intrinsic::aarch64_neon_rshrn;
6243 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrshrn_n");
6244 case NEON::BI__builtin_neon_vqrshrn_n_v:
6245 Int = usgn ? Intrinsic::aarch64_neon_uqrshrn : Intrinsic::aarch64_neon_sqrshrn;
6246 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqrshrn_n");
6247 case NEON::BI__builtin_neon_vrndah_f16: {
6248 Int = Builder.getIsFPConstrained()
6249 ? Intrinsic::experimental_constrained_round
6250 : Intrinsic::round;
6251 return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrnda");
6252 }
6253 case NEON::BI__builtin_neon_vrnda_v:
6254 case NEON::BI__builtin_neon_vrndaq_v: {
6255 Int = Builder.getIsFPConstrained()
6256 ? Intrinsic::experimental_constrained_round
6257 : Intrinsic::round;
6258 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrnda");
6259 }
6260 case NEON::BI__builtin_neon_vrndih_f16: {
6261 Int = Builder.getIsFPConstrained()
6262 ? Intrinsic::experimental_constrained_nearbyint
6263 : Intrinsic::nearbyint;
6264 return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndi");
6265 }
6266 case NEON::BI__builtin_neon_vrndmh_f16: {
6267 Int = Builder.getIsFPConstrained()
6268 ? Intrinsic::experimental_constrained_floor
6269 : Intrinsic::floor;
6270 return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndm");
6271 }
6272 case NEON::BI__builtin_neon_vrndm_v:
6273 case NEON::BI__builtin_neon_vrndmq_v: {
6274 Int = Builder.getIsFPConstrained()
6275 ? Intrinsic::experimental_constrained_floor
6276 : Intrinsic::floor;
6277 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndm");
6278 }
6279 case NEON::BI__builtin_neon_vrndnh_f16: {
6280 Int = Builder.getIsFPConstrained()
6281 ? Intrinsic::experimental_constrained_roundeven
6282 : Intrinsic::roundeven;
6283 return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndn");
6284 }
6285 case NEON::BI__builtin_neon_vrndn_v:
6286 case NEON::BI__builtin_neon_vrndnq_v: {
6287 Int = Builder.getIsFPConstrained()
6288 ? Intrinsic::experimental_constrained_roundeven
6289 : Intrinsic::roundeven;
6290 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndn");
6291 }
6292 case NEON::BI__builtin_neon_vrndns_f32: {
6293 Int = Builder.getIsFPConstrained()
6294 ? Intrinsic::experimental_constrained_roundeven
6295 : Intrinsic::roundeven;
6296 return EmitNeonCall(CGM.getIntrinsic(Int, FloatTy), Ops, "vrndn");
6297 }
6298 case NEON::BI__builtin_neon_vrndph_f16: {
6299 Int = Builder.getIsFPConstrained()
6300 ? Intrinsic::experimental_constrained_ceil
6301 : Intrinsic::ceil;
6302 return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndp");
6303 }
6304 case NEON::BI__builtin_neon_vrndp_v:
6305 case NEON::BI__builtin_neon_vrndpq_v: {
6306 Int = Builder.getIsFPConstrained()
6307 ? Intrinsic::experimental_constrained_ceil
6308 : Intrinsic::ceil;
6309 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndp");
6310 }
6311 case NEON::BI__builtin_neon_vrndxh_f16: {
6312 Int = Builder.getIsFPConstrained()
6313 ? Intrinsic::experimental_constrained_rint
6314 : Intrinsic::rint;
6315 return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndx");
6316 }
6317 case NEON::BI__builtin_neon_vrndx_v:
6318 case NEON::BI__builtin_neon_vrndxq_v: {
6319 Int = Builder.getIsFPConstrained()
6320 ? Intrinsic::experimental_constrained_rint
6321 : Intrinsic::rint;
6322 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndx");
6323 }
6324 case NEON::BI__builtin_neon_vrndh_f16: {
6325 Int = Builder.getIsFPConstrained()
6326 ? Intrinsic::experimental_constrained_trunc
6327 : Intrinsic::trunc;
6328 return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndz");
6329 }
6330 case NEON::BI__builtin_neon_vrnd_v:
6331 case NEON::BI__builtin_neon_vrndq_v: {
6332 Int = Builder.getIsFPConstrained()
6333 ? Intrinsic::experimental_constrained_trunc
6334 : Intrinsic::trunc;
6335 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndz");
6336 }
6337 case NEON::BI__builtin_neon_vcvt_f64_v:
6338 case NEON::BI__builtin_neon_vcvtq_f64_v:
6339 Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
6340 Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float64, false, quad));
6341 return usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
6342 : Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
6343 case NEON::BI__builtin_neon_vcvt_f64_f32: {
6344 assert(Type.getEltType() == NeonTypeFlags::Float64 && quad &&
6345 "unexpected vcvt_f64_f32 builtin");
6346 NeonTypeFlags SrcFlag = NeonTypeFlags(NeonTypeFlags::Float32, false, false);
6347 Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(this, SrcFlag));
6348
6349 return Builder.CreateFPExt(Ops[0], Ty, "vcvt");
6350 }
6351 case NEON::BI__builtin_neon_vcvt_f32_f64: {
6352 assert(Type.getEltType() == NeonTypeFlags::Float32 &&
6353 "unexpected vcvt_f32_f64 builtin");
6354 NeonTypeFlags SrcFlag = NeonTypeFlags(NeonTypeFlags::Float64, false, true);
6355 Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(this, SrcFlag));
6356
6357 return Builder.CreateFPTrunc(Ops[0], Ty, "vcvt");
6358 }
6359 case NEON::BI__builtin_neon_vcvta_s16_f16:
6360 case NEON::BI__builtin_neon_vcvta_u16_f16:
6361 case NEON::BI__builtin_neon_vcvta_s32_v:
6362 case NEON::BI__builtin_neon_vcvtaq_s16_f16:
6363 case NEON::BI__builtin_neon_vcvtaq_s32_v:
6364 case NEON::BI__builtin_neon_vcvta_u32_v:
6365 case NEON::BI__builtin_neon_vcvtaq_u16_f16:
6366 case NEON::BI__builtin_neon_vcvtaq_u32_v:
6367 case NEON::BI__builtin_neon_vcvta_s64_v:
6368 case NEON::BI__builtin_neon_vcvtaq_s64_v:
6369 case NEON::BI__builtin_neon_vcvta_u64_v:
6370 case NEON::BI__builtin_neon_vcvtaq_u64_v: {
6371 Int = usgn ? Intrinsic::aarch64_neon_fcvtau : Intrinsic::aarch64_neon_fcvtas;
6372 llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) };
6373 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvta");
6374 }
6375 case NEON::BI__builtin_neon_vcvtm_s16_f16:
6376 case NEON::BI__builtin_neon_vcvtmq_s16_f16:
6377 case NEON::BI__builtin_neon_vcvtm_u16_f16:
6378 case NEON::BI__builtin_neon_vcvtmq_u16_f16:
6379 case NEON::BI__builtin_neon_vcvtm_s32_v:
6380 case NEON::BI__builtin_neon_vcvtmq_s32_v:
6381 case NEON::BI__builtin_neon_vcvtm_u32_v:
6382 case NEON::BI__builtin_neon_vcvtmq_u32_v:
6383 case NEON::BI__builtin_neon_vcvtm_s64_v:
6384 case NEON::BI__builtin_neon_vcvtmq_s64_v:
6385 case NEON::BI__builtin_neon_vcvtm_u64_v:
6386 case NEON::BI__builtin_neon_vcvtmq_u64_v: {
6387 Int = usgn ? Intrinsic::aarch64_neon_fcvtmu : Intrinsic::aarch64_neon_fcvtms;
6388 llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) };
6389 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtm");
6390 }
6391 case NEON::BI__builtin_neon_vcvtn_s16_f16:
6392 case NEON::BI__builtin_neon_vcvtnq_s16_f16:
6393 case NEON::BI__builtin_neon_vcvtn_u16_f16:
6394 case NEON::BI__builtin_neon_vcvtnq_u16_f16:
6395 case NEON::BI__builtin_neon_vcvtn_s32_v:
6396 case NEON::BI__builtin_neon_vcvtnq_s32_v:
6397 case NEON::BI__builtin_neon_vcvtn_u32_v:
6398 case NEON::BI__builtin_neon_vcvtnq_u32_v:
6399 case NEON::BI__builtin_neon_vcvtn_s64_v:
6400 case NEON::BI__builtin_neon_vcvtnq_s64_v:
6401 case NEON::BI__builtin_neon_vcvtn_u64_v:
6402 case NEON::BI__builtin_neon_vcvtnq_u64_v: {
6403 Int = usgn ? Intrinsic::aarch64_neon_fcvtnu : Intrinsic::aarch64_neon_fcvtns;
6404 llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) };
6405 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtn");
6406 }
6407 case NEON::BI__builtin_neon_vcvtp_s16_f16:
6408 case NEON::BI__builtin_neon_vcvtpq_s16_f16:
6409 case NEON::BI__builtin_neon_vcvtp_u16_f16:
6410 case NEON::BI__builtin_neon_vcvtpq_u16_f16:
6411 case NEON::BI__builtin_neon_vcvtp_s32_v:
6412 case NEON::BI__builtin_neon_vcvtpq_s32_v:
6413 case NEON::BI__builtin_neon_vcvtp_u32_v:
6414 case NEON::BI__builtin_neon_vcvtpq_u32_v:
6415 case NEON::BI__builtin_neon_vcvtp_s64_v:
6416 case NEON::BI__builtin_neon_vcvtpq_s64_v:
6417 case NEON::BI__builtin_neon_vcvtp_u64_v:
6418 case NEON::BI__builtin_neon_vcvtpq_u64_v: {
6419 Int = usgn ? Intrinsic::aarch64_neon_fcvtpu : Intrinsic::aarch64_neon_fcvtps;
6420 llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) };
6421 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtp");
6422 }
6423 case NEON::BI__builtin_neon_vmulx_v:
6424 case NEON::BI__builtin_neon_vmulxq_v: {
6425 Int = Intrinsic::aarch64_neon_fmulx;
6426 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmulx");
6427 }
6428 case NEON::BI__builtin_neon_vmulxh_lane_f16:
6429 case NEON::BI__builtin_neon_vmulxh_laneq_f16: {
6430 // vmulx_lane should be mapped to Neon scalar mulx after
6431 // extracting the scalar element
6432 Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2], "extract");
6433 Ops.pop_back();
6434 Int = Intrinsic::aarch64_neon_fmulx;
6435 return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vmulx");
6436 }
6437 case NEON::BI__builtin_neon_vmul_lane_v:
6438 case NEON::BI__builtin_neon_vmul_laneq_v: {
6439 // v1f64 vmul_lane should be mapped to Neon scalar mul lane
6440 bool Quad = false;
6441 if (BuiltinID == NEON::BI__builtin_neon_vmul_laneq_v)
6442 Quad = true;
6443 Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy);
6444 llvm::FixedVectorType *VTy =
6446 Ops[1] = Builder.CreateBitCast(Ops[1], VTy);
6447 Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2], "extract");
6448 Value *Result = Builder.CreateFMul(Ops[0], Ops[1]);
6449 return Builder.CreateBitCast(Result, Ty);
6450 }
6451 case NEON::BI__builtin_neon_vpmaxnm_v:
6452 case NEON::BI__builtin_neon_vpmaxnmq_v: {
6453 Int = Intrinsic::aarch64_neon_fmaxnmp;
6454 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpmaxnm");
6455 }
6456 case NEON::BI__builtin_neon_vpminnm_v:
6457 case NEON::BI__builtin_neon_vpminnmq_v: {
6458 Int = Intrinsic::aarch64_neon_fminnmp;
6459 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpminnm");
6460 }
6461 case NEON::BI__builtin_neon_vsqrth_f16: {
6462 Int = Builder.getIsFPConstrained()
6463 ? Intrinsic::experimental_constrained_sqrt
6464 : Intrinsic::sqrt;
6465 return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vsqrt");
6466 }
6467 case NEON::BI__builtin_neon_vsqrt_v:
6468 case NEON::BI__builtin_neon_vsqrtq_v: {
6469 Int = Builder.getIsFPConstrained()
6470 ? Intrinsic::experimental_constrained_sqrt
6471 : Intrinsic::sqrt;
6472 Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
6473 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vsqrt");
6474 }
6475 case NEON::BI__builtin_neon_vrbit_v:
6476 case NEON::BI__builtin_neon_vrbitq_v: {
6477 Int = Intrinsic::bitreverse;
6478 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrbit");
6479 }
6480 case NEON::BI__builtin_neon_vmaxv_f16: {
6481 Int = Intrinsic::aarch64_neon_fmaxv;
6482 Ty = HalfTy;
6483 VTy = llvm::FixedVectorType::get(HalfTy, 4);
6484 llvm::Type *Tys[2] = {Ty, VTy};
6485 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv");
6486 }
6487 case NEON::BI__builtin_neon_vmaxvq_f16: {
6488 Int = Intrinsic::aarch64_neon_fmaxv;
6489 Ty = HalfTy;
6490 VTy = llvm::FixedVectorType::get(HalfTy, 8);
6491 llvm::Type *Tys[2] = {Ty, VTy};
6492 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv");
6493 }
6494 case NEON::BI__builtin_neon_vminv_f16: {
6495 Int = Intrinsic::aarch64_neon_fminv;
6496 Ty = HalfTy;
6497 VTy = llvm::FixedVectorType::get(HalfTy, 4);
6498 llvm::Type *Tys[2] = {Ty, VTy};
6499 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv");
6500 }
6501 case NEON::BI__builtin_neon_vminvq_f16: {
6502 Int = Intrinsic::aarch64_neon_fminv;
6503 Ty = HalfTy;
6504 VTy = llvm::FixedVectorType::get(HalfTy, 8);
6505 llvm::Type *Tys[2] = {Ty, VTy};
6506 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv");
6507 }
6508 case NEON::BI__builtin_neon_vmaxnmv_f16: {
6509 Int = Intrinsic::aarch64_neon_fmaxnmv;
6510 Ty = HalfTy;
6511 VTy = llvm::FixedVectorType::get(HalfTy, 4);
6512 llvm::Type *Tys[2] = {Ty, VTy};
6513 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxnmv");
6514 }
6515 case NEON::BI__builtin_neon_vmaxnmvq_f16: {
6516 Int = Intrinsic::aarch64_neon_fmaxnmv;
6517 Ty = HalfTy;
6518 VTy = llvm::FixedVectorType::get(HalfTy, 8);
6519 llvm::Type *Tys[2] = {Ty, VTy};
6520 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxnmv");
6521 }
6522 case NEON::BI__builtin_neon_vminnmv_f16: {
6523 Int = Intrinsic::aarch64_neon_fminnmv;
6524 Ty = HalfTy;
6525 VTy = llvm::FixedVectorType::get(HalfTy, 4);
6526 llvm::Type *Tys[2] = {Ty, VTy};
6527 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminnmv");
6528 }
6529 case NEON::BI__builtin_neon_vminnmvq_f16: {
6530 Int = Intrinsic::aarch64_neon_fminnmv;
6531 Ty = HalfTy;
6532 VTy = llvm::FixedVectorType::get(HalfTy, 8);
6533 llvm::Type *Tys[2] = {Ty, VTy};
6534 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminnmv");
6535 }
6536 case NEON::BI__builtin_neon_vmul_n_f64: {
6537 Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy);
6538 Value *RHS = Builder.CreateBitCast(Ops[1], DoubleTy);
6539 return Builder.CreateFMul(Ops[0], RHS);
6540 }
6541 case NEON::BI__builtin_neon_vaddlv_u8:
6542 case NEON::BI__builtin_neon_vaddlvq_u8:
6543 case NEON::BI__builtin_neon_vaddlv_u16:
6544 case NEON::BI__builtin_neon_vaddlvq_u16: {
6545 Int = Intrinsic::aarch64_neon_uaddlv;
6546 Ty = Int32Ty;
6547 VTy = cast<llvm::FixedVectorType>(Ops[0]->getType());
6548 llvm::Type *Tys[2] = {Ty, VTy};
6549 Value *Result = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv");
6550 if (VTy->getElementType()->getPrimitiveSizeInBits() == 8)
6551 return Builder.CreateTrunc(Result, Int16Ty);
6552 return Result;
6553 }
6554 case NEON::BI__builtin_neon_vaddlv_s8:
6555 case NEON::BI__builtin_neon_vaddlvq_s8:
6556 case NEON::BI__builtin_neon_vaddlv_s16:
6557 case NEON::BI__builtin_neon_vaddlvq_s16: {
6558 Int = Intrinsic::aarch64_neon_saddlv;
6559 Ty = Int32Ty;
6560 VTy = cast<llvm::FixedVectorType>(Ops[0]->getType());
6561 llvm::Type *Tys[2] = {Ty, VTy};
6562 Value *Result = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv");
6563 if (VTy->getElementType()->getPrimitiveSizeInBits() == 8)
6564 return Builder.CreateTrunc(Result, Int16Ty);
6565 return Result;
6566 }
6567 case NEON::BI__builtin_neon_vsri_n_v:
6568 case NEON::BI__builtin_neon_vsriq_n_v: {
6569 Int = Intrinsic::aarch64_neon_vsri;
6570 llvm::Function *Intrin = CGM.getIntrinsic(Int, Ty);
6571 return EmitNeonCall(Intrin, Ops, "vsri_n");
6572 }
6573 case NEON::BI__builtin_neon_vsli_n_v:
6574 case NEON::BI__builtin_neon_vsliq_n_v: {
6575 Int = Intrinsic::aarch64_neon_vsli;
6576 llvm::Function *Intrin = CGM.getIntrinsic(Int, Ty);
6577 return EmitNeonCall(Intrin, Ops, "vsli_n");
6578 }
6579 case NEON::BI__builtin_neon_vsra_n_v:
6580 case NEON::BI__builtin_neon_vsraq_n_v:
6581 Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
6582 Ops[1] = EmitNeonRShiftImm(Ops[1], Ops[2], Ty, usgn, "vsra_n");
6583 return Builder.CreateAdd(Ops[0], Ops[1]);
6584 case NEON::BI__builtin_neon_vrsra_n_v:
6585 case NEON::BI__builtin_neon_vrsraq_n_v: {
6586 Int = usgn ? Intrinsic::aarch64_neon_urshl : Intrinsic::aarch64_neon_srshl;
6588 TmpOps.push_back(Ops[1]);
6589 TmpOps.push_back(Ops[2]);
6590 Function* F = CGM.getIntrinsic(Int, Ty);
6591 llvm::Value *tmp = EmitNeonCall(F, TmpOps, "vrshr_n", 1, true);
6592 Ops[0] = Builder.CreateBitCast(Ops[0], VTy);
6593 return Builder.CreateAdd(Ops[0], tmp);
6594 }
6595 case NEON::BI__builtin_neon_vld1_v:
6596 case NEON::BI__builtin_neon_vld1q_v: {
6597 return Builder.CreateAlignedLoad(VTy, Ops[0], PtrOp0.getAlignment());
6598 }
6599 case NEON::BI__builtin_neon_vst1_v:
6600 case NEON::BI__builtin_neon_vst1q_v:
6601 Ops[1] = Builder.CreateBitCast(Ops[1], VTy);
6602 return Builder.CreateAlignedStore(Ops[1], Ops[0], PtrOp0.getAlignment());
6603 case NEON::BI__builtin_neon_vld1_lane_v:
6604 case NEON::BI__builtin_neon_vld1q_lane_v: {
6605 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
6606 Ops[0] = Builder.CreateAlignedLoad(VTy->getElementType(), Ops[0],
6607 PtrOp0.getAlignment());
6608 return Builder.CreateInsertElement(Ops[1], Ops[0], Ops[2], "vld1_lane");
6609 }
6610 case NEON::BI__builtin_neon_vldap1_lane_s64:
6611 case NEON::BI__builtin_neon_vldap1q_lane_s64: {
6612 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
6613 llvm::LoadInst *LI = Builder.CreateAlignedLoad(
6614 VTy->getElementType(), Ops[0], PtrOp0.getAlignment());
6615 LI->setAtomic(llvm::AtomicOrdering::Acquire);
6616 Ops[0] = LI;
6617 return Builder.CreateInsertElement(Ops[1], Ops[0], Ops[2], "vldap1_lane");
6618 }
6619 case NEON::BI__builtin_neon_vld1_dup_v:
6620 case NEON::BI__builtin_neon_vld1q_dup_v: {
6621 Value *V = PoisonValue::get(Ty);
6622 Ops[0] = Builder.CreateAlignedLoad(VTy->getElementType(), Ops[0],
6623 PtrOp0.getAlignment());
6624 llvm::Constant *CI = ConstantInt::get(Int32Ty, 0);
6625 Ops[0] = Builder.CreateInsertElement(V, Ops[0], CI);
6626 return EmitNeonSplat(Ops[0], CI);
6627 }
6628 case NEON::BI__builtin_neon_vst1_lane_v:
6629 case NEON::BI__builtin_neon_vst1q_lane_v:
6630 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
6631 Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2]);
6632 return Builder.CreateAlignedStore(Ops[1], Ops[0], PtrOp0.getAlignment());
6633 case NEON::BI__builtin_neon_vstl1_lane_s64:
6634 case NEON::BI__builtin_neon_vstl1q_lane_s64: {
6635 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
6636 Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2]);
6637 llvm::StoreInst *SI =
6638 Builder.CreateAlignedStore(Ops[1], Ops[0], PtrOp0.getAlignment());
6639 SI->setAtomic(llvm::AtomicOrdering::Release);
6640 return SI;
6641 }
6642 case NEON::BI__builtin_neon_vld2_v:
6643 case NEON::BI__builtin_neon_vld2q_v: {
6644 llvm::Type *Tys[2] = {VTy, DefaultPtrTy};
6645 Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld2, Tys);
6646 Ops[1] = Builder.CreateCall(F, Ops[1], "vld2");
6647 return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
6648 }
6649 case NEON::BI__builtin_neon_vld3_v:
6650 case NEON::BI__builtin_neon_vld3q_v: {
6651 llvm::Type *Tys[2] = {VTy, DefaultPtrTy};
6652 Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld3, Tys);
6653 Ops[1] = Builder.CreateCall(F, Ops[1], "vld3");
6654 return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
6655 }
6656 case NEON::BI__builtin_neon_vld4_v:
6657 case NEON::BI__builtin_neon_vld4q_v: {
6658 llvm::Type *Tys[2] = {VTy, DefaultPtrTy};
6659 Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld4, Tys);
6660 Ops[1] = Builder.CreateCall(F, Ops[1], "vld4");
6661 return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
6662 }
6663 case NEON::BI__builtin_neon_vld2_dup_v:
6664 case NEON::BI__builtin_neon_vld2q_dup_v: {
6665 llvm::Type *Tys[2] = {VTy, DefaultPtrTy};
6666 Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld2r, Tys);
6667 Ops[1] = Builder.CreateCall(F, Ops[1], "vld2");
6668 return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
6669 }
6670 case NEON::BI__builtin_neon_vld3_dup_v:
6671 case NEON::BI__builtin_neon_vld3q_dup_v: {
6672 llvm::Type *Tys[2] = {VTy, DefaultPtrTy};
6673 Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld3r, Tys);
6674 Ops[1] = Builder.CreateCall(F, Ops[1], "vld3");
6675 return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
6676 }
6677 case NEON::BI__builtin_neon_vld4_dup_v:
6678 case NEON::BI__builtin_neon_vld4q_dup_v: {
6679 llvm::Type *Tys[2] = {VTy, DefaultPtrTy};
6680 Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld4r, Tys);
6681 Ops[1] = Builder.CreateCall(F, Ops[1], "vld4");
6682 return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
6683 }
6684 case NEON::BI__builtin_neon_vld2_lane_v:
6685 case NEON::BI__builtin_neon_vld2q_lane_v: {
6686 llvm::Type *Tys[2] = { VTy, Ops[1]->getType() };
6687 Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld2lane, Tys);
6688 std::rotate(Ops.begin() + 1, Ops.begin() + 2, Ops.end());
6689 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
6690 Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
6691 Ops[3] = Builder.CreateZExt(Ops[3], Int64Ty);
6692 Ops[1] = Builder.CreateCall(F, ArrayRef(Ops).slice(1), "vld2_lane");
6693 return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
6694 }
6695 case NEON::BI__builtin_neon_vld3_lane_v:
6696 case NEON::BI__builtin_neon_vld3q_lane_v: {
6697 llvm::Type *Tys[2] = { VTy, Ops[1]->getType() };
6698 Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld3lane, Tys);
6699 std::rotate(Ops.begin() + 1, Ops.begin() + 2, Ops.end());
6700 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
6701 Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
6702 Ops[3] = Builder.CreateBitCast(Ops[3], Ty);
6703 Ops[4] = Builder.CreateZExt(Ops[4], Int64Ty);
6704 Ops[1] = Builder.CreateCall(F, ArrayRef(Ops).slice(1), "vld3_lane");
6705 return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
6706 }
6707 case NEON::BI__builtin_neon_vld4_lane_v:
6708 case NEON::BI__builtin_neon_vld4q_lane_v: {
6709 llvm::Type *Tys[2] = { VTy, Ops[1]->getType() };
6710 Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld4lane, Tys);
6711 std::rotate(Ops.begin() + 1, Ops.begin() + 2, Ops.end());
6712 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
6713 Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
6714 Ops[3] = Builder.CreateBitCast(Ops[3], Ty);
6715 Ops[4] = Builder.CreateBitCast(Ops[4], Ty);
6716 Ops[5] = Builder.CreateZExt(Ops[5], Int64Ty);
6717 Ops[1] = Builder.CreateCall(F, ArrayRef(Ops).slice(1), "vld4_lane");
6718 return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
6719 }
6720 case NEON::BI__builtin_neon_vst2_v:
6721 case NEON::BI__builtin_neon_vst2q_v: {
6722 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());
6723 llvm::Type *Tys[2] = { VTy, Ops[2]->getType() };
6724 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st2, Tys),
6725 Ops, "");
6726 }
6727 case NEON::BI__builtin_neon_vst2_lane_v:
6728 case NEON::BI__builtin_neon_vst2q_lane_v: {
6729 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());
6730 Ops[2] = Builder.CreateZExt(Ops[2], Int64Ty);
6731 llvm::Type *Tys[2] = { VTy, Ops[3]->getType() };
6732 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st2lane, Tys),
6733 Ops, "");
6734 }
6735 case NEON::BI__builtin_neon_vst3_v:
6736 case NEON::BI__builtin_neon_vst3q_v: {
6737 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());
6738 llvm::Type *Tys[2] = { VTy, Ops[3]->getType() };
6739 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st3, Tys),
6740 Ops, "");
6741 }
6742 case NEON::BI__builtin_neon_vst3_lane_v:
6743 case NEON::BI__builtin_neon_vst3q_lane_v: {
6744 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());
6745 Ops[3] = Builder.CreateZExt(Ops[3], Int64Ty);
6746 llvm::Type *Tys[2] = { VTy, Ops[4]->getType() };
6747 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st3lane, Tys),
6748 Ops, "");
6749 }
6750 case NEON::BI__builtin_neon_vst4_v:
6751 case NEON::BI__builtin_neon_vst4q_v: {
6752 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());
6753 llvm::Type *Tys[2] = { VTy, Ops[4]->getType() };
6754 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st4, Tys),
6755 Ops, "");
6756 }
6757 case NEON::BI__builtin_neon_vst4_lane_v:
6758 case NEON::BI__builtin_neon_vst4q_lane_v: {
6759 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());
6760 Ops[4] = Builder.CreateZExt(Ops[4], Int64Ty);
6761 llvm::Type *Tys[2] = { VTy, Ops[5]->getType() };
6762 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st4lane, Tys),
6763 Ops, "");
6764 }
6765 case NEON::BI__builtin_neon_vtrn_v:
6766 case NEON::BI__builtin_neon_vtrnq_v: {
6767 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
6768 Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
6769 Value *SV = nullptr;
6770
6771 for (unsigned vi = 0; vi != 2; ++vi) {
6772 SmallVector<int, 16> Indices;
6773 for (unsigned i = 0, e = VTy->getNumElements(); i != e; i += 2) {
6774 Indices.push_back(i+vi);
6775 Indices.push_back(i+e+vi);
6776 }
6777 Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
6778 SV = Builder.CreateShuffleVector(Ops[1], Ops[2], Indices, "vtrn");
6779 SV = Builder.CreateDefaultAlignedStore(SV, Addr);
6780 }
6781 return SV;
6782 }
6783 case NEON::BI__builtin_neon_vuzp_v:
6784 case NEON::BI__builtin_neon_vuzpq_v: {
6785 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
6786 Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
6787 Value *SV = nullptr;
6788
6789 for (unsigned vi = 0; vi != 2; ++vi) {
6790 SmallVector<int, 16> Indices;
6791 for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i)
6792 Indices.push_back(2*i+vi);
6793
6794 Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
6795 SV = Builder.CreateShuffleVector(Ops[1], Ops[2], Indices, "vuzp");
6796 SV = Builder.CreateDefaultAlignedStore(SV, Addr);
6797 }
6798 return SV;
6799 }
6800 case NEON::BI__builtin_neon_vzip_v:
6801 case NEON::BI__builtin_neon_vzipq_v: {
6802 Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
6803 Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
6804 Value *SV = nullptr;
6805
6806 for (unsigned vi = 0; vi != 2; ++vi) {
6807 SmallVector<int, 16> Indices;
6808 for (unsigned i = 0, e = VTy->getNumElements(); i != e; i += 2) {
6809 Indices.push_back((i + vi*e) >> 1);
6810 Indices.push_back(((i + vi*e) >> 1)+e);
6811 }
6812 Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
6813 SV = Builder.CreateShuffleVector(Ops[1], Ops[2], Indices, "vzip");
6814 SV = Builder.CreateDefaultAlignedStore(SV, Addr);
6815 }
6816 return SV;
6817 }
6818 case NEON::BI__builtin_neon_vqtbl1q_v: {
6819 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbl1, Ty),
6820 Ops, "vtbl1");
6821 }
6822 case NEON::BI__builtin_neon_vqtbl2q_v: {
6823 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbl2, Ty),
6824 Ops, "vtbl2");
6825 }
6826 case NEON::BI__builtin_neon_vqtbl3q_v: {
6827 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbl3, Ty),
6828 Ops, "vtbl3");
6829 }
6830 case NEON::BI__builtin_neon_vqtbl4q_v: {
6831 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbl4, Ty),
6832 Ops, "vtbl4");
6833 }
6834 case NEON::BI__builtin_neon_vqtbx1q_v: {
6835 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbx1, Ty),
6836 Ops, "vtbx1");
6837 }
6838 case NEON::BI__builtin_neon_vqtbx2q_v: {
6839 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbx2, Ty),
6840 Ops, "vtbx2");
6841 }
6842 case NEON::BI__builtin_neon_vqtbx3q_v: {
6843 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbx3, Ty),
6844 Ops, "vtbx3");
6845 }
6846 case NEON::BI__builtin_neon_vqtbx4q_v: {
6847 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbx4, Ty),
6848 Ops, "vtbx4");
6849 }
6850 case NEON::BI__builtin_neon_vsqadd_v:
6851 case NEON::BI__builtin_neon_vsqaddq_v: {
6852 Int = Intrinsic::aarch64_neon_usqadd;
6853 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vsqadd");
6854 }
6855 case NEON::BI__builtin_neon_vuqadd_v:
6856 case NEON::BI__builtin_neon_vuqaddq_v: {
6857 Int = Intrinsic::aarch64_neon_suqadd;
6858 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vuqadd");
6859 }
6860
6861 case NEON::BI__builtin_neon_vluti2_laneq_mf8:
6862 case NEON::BI__builtin_neon_vluti2_laneq_bf16:
6863 case NEON::BI__builtin_neon_vluti2_laneq_f16:
6864 case NEON::BI__builtin_neon_vluti2_laneq_p16:
6865 case NEON::BI__builtin_neon_vluti2_laneq_p8:
6866 case NEON::BI__builtin_neon_vluti2_laneq_s16:
6867 case NEON::BI__builtin_neon_vluti2_laneq_s8:
6868 case NEON::BI__builtin_neon_vluti2_laneq_u16:
6869 case NEON::BI__builtin_neon_vluti2_laneq_u8: {
6870 Int = Intrinsic::aarch64_neon_vluti2_laneq;
6871 llvm::Type *Tys[2];
6872 Tys[0] = Ty;
6873 Tys[1] = GetNeonType(this, NeonTypeFlags(Type.getEltType(), false,
6874 /*isQuad*/ false));
6875 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vluti2_laneq");
6876 }
6877 case NEON::BI__builtin_neon_vluti2q_laneq_mf8:
6878 case NEON::BI__builtin_neon_vluti2q_laneq_bf16:
6879 case NEON::BI__builtin_neon_vluti2q_laneq_f16:
6880 case NEON::BI__builtin_neon_vluti2q_laneq_p16:
6881 case NEON::BI__builtin_neon_vluti2q_laneq_p8:
6882 case NEON::BI__builtin_neon_vluti2q_laneq_s16:
6883 case NEON::BI__builtin_neon_vluti2q_laneq_s8:
6884 case NEON::BI__builtin_neon_vluti2q_laneq_u16:
6885 case NEON::BI__builtin_neon_vluti2q_laneq_u8: {
6886 Int = Intrinsic::aarch64_neon_vluti2_laneq;
6887 llvm::Type *Tys[2];
6888 Tys[0] = Ty;
6889 Tys[1] = GetNeonType(this, NeonTypeFlags(Type.getEltType(), false,
6890 /*isQuad*/ true));
6891 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vluti2_laneq");
6892 }
6893 case NEON::BI__builtin_neon_vluti2_lane_mf8:
6894 case NEON::BI__builtin_neon_vluti2_lane_bf16:
6895 case NEON::BI__builtin_neon_vluti2_lane_f16:
6896 case NEON::BI__builtin_neon_vluti2_lane_p16:
6897 case NEON::BI__builtin_neon_vluti2_lane_p8:
6898 case NEON::BI__builtin_neon_vluti2_lane_s16:
6899 case NEON::BI__builtin_neon_vluti2_lane_s8:
6900 case NEON::BI__builtin_neon_vluti2_lane_u16:
6901 case NEON::BI__builtin_neon_vluti2_lane_u8: {
6902 Int = Intrinsic::aarch64_neon_vluti2_lane;
6903 llvm::Type *Tys[2];
6904 Tys[0] = Ty;
6905 Tys[1] = GetNeonType(this, NeonTypeFlags(Type.getEltType(), false,
6906 /*isQuad*/ false));
6907 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vluti2_lane");
6908 }
6909 case NEON::BI__builtin_neon_vluti2q_lane_mf8:
6910 case NEON::BI__builtin_neon_vluti2q_lane_bf16:
6911 case NEON::BI__builtin_neon_vluti2q_lane_f16:
6912 case NEON::BI__builtin_neon_vluti2q_lane_p16:
6913 case NEON::BI__builtin_neon_vluti2q_lane_p8:
6914 case NEON::BI__builtin_neon_vluti2q_lane_s16:
6915 case NEON::BI__builtin_neon_vluti2q_lane_s8:
6916 case NEON::BI__builtin_neon_vluti2q_lane_u16:
6917 case NEON::BI__builtin_neon_vluti2q_lane_u8: {
6918 Int = Intrinsic::aarch64_neon_vluti2_lane;
6919 llvm::Type *Tys[2];
6920 Tys[0] = Ty;
6921 Tys[1] = GetNeonType(this, NeonTypeFlags(Type.getEltType(), false,
6922 /*isQuad*/ true));
6923 return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vluti2_lane");
6924 }
6925 case NEON::BI__builtin_neon_vluti4q_lane_mf8:
6926 case NEON::BI__builtin_neon_vluti4q_lane_p8:
6927 case NEON::BI__builtin_neon_vluti4q_lane_s8:
6928 case NEON::BI__builtin_neon_vluti4q_lane_u8: {
6929 Int = Intrinsic::aarch64_neon_vluti4q_lane;
6930 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vluti4q_lane");
6931 }
6932 case NEON::BI__builtin_neon_vluti4q_laneq_mf8:
6933 case NEON::BI__builtin_neon_vluti4q_laneq_p8:
6934 case NEON::BI__builtin_neon_vluti4q_laneq_s8:
6935 case NEON::BI__builtin_neon_vluti4q_laneq_u8: {
6936 Int = Intrinsic::aarch64_neon_vluti4q_laneq;
6937 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vluti4q_laneq");
6938 }
6939 case NEON::BI__builtin_neon_vluti4q_lane_bf16_x2:
6940 case NEON::BI__builtin_neon_vluti4q_lane_f16_x2:
6941 case NEON::BI__builtin_neon_vluti4q_lane_p16_x2:
6942 case NEON::BI__builtin_neon_vluti4q_lane_s16_x2:
6943 case NEON::BI__builtin_neon_vluti4q_lane_u16_x2: {
6944 Int = Intrinsic::aarch64_neon_vluti4q_lane_x2;
6945 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vluti4q_lane_x2");
6946 }
6947 case NEON::BI__builtin_neon_vluti4q_laneq_bf16_x2:
6948 case NEON::BI__builtin_neon_vluti4q_laneq_f16_x2:
6949 case NEON::BI__builtin_neon_vluti4q_laneq_p16_x2:
6950 case NEON::BI__builtin_neon_vluti4q_laneq_s16_x2:
6951 case NEON::BI__builtin_neon_vluti4q_laneq_u16_x2: {
6952 Int = Intrinsic::aarch64_neon_vluti4q_laneq_x2;
6953 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vluti4q_laneq_x2");
6954 }
6955 case NEON::BI__builtin_neon_vmmlaq_f16_mf8_fpm:
6956 return EmitFP8NeonCall(Intrinsic::aarch64_neon_fmmla,
6957 {llvm::FixedVectorType::get(HalfTy, 8),
6958 llvm::FixedVectorType::get(Int8Ty, 16)},
6959 Ops, E, "fmmla");
6960 case NEON::BI__builtin_neon_vmmlaq_f32_mf8_fpm:
6961 return EmitFP8NeonCall(Intrinsic::aarch64_neon_fmmla,
6962 {llvm::FixedVectorType::get(FloatTy, 4),
6963 llvm::FixedVectorType::get(Int8Ty, 16)},
6964 Ops, E, "fmmla");
6965 case NEON::BI__builtin_neon_vcvt1_low_bf16_mf8_fpm:
6966 ExtractLow = true;
6967 [[fallthrough]];
6968 case NEON::BI__builtin_neon_vcvt1_bf16_mf8_fpm:
6969 case NEON::BI__builtin_neon_vcvt1_high_bf16_mf8_fpm:
6970 return EmitFP8NeonCvtCall(Intrinsic::aarch64_neon_fp8_cvtl1,
6971 llvm::FixedVectorType::get(BFloatTy, 8),
6972 Ops[0]->getType(), ExtractLow, Ops, E, "vbfcvt1");
6973 case NEON::BI__builtin_neon_vcvt2_low_bf16_mf8_fpm:
6974 ExtractLow = true;
6975 [[fallthrough]];
6976 case NEON::BI__builtin_neon_vcvt2_bf16_mf8_fpm:
6977 case NEON::BI__builtin_neon_vcvt2_high_bf16_mf8_fpm:
6978 return EmitFP8NeonCvtCall(Intrinsic::aarch64_neon_fp8_cvtl2,
6979 llvm::FixedVectorType::get(BFloatTy, 8),
6980 Ops[0]->getType(), ExtractLow, Ops, E, "vbfcvt2");
6981 case NEON::BI__builtin_neon_vcvt1_low_f16_mf8_fpm:
6982 ExtractLow = true;
6983 [[fallthrough]];
6984 case NEON::BI__builtin_neon_vcvt1_f16_mf8_fpm:
6985 case NEON::BI__builtin_neon_vcvt1_high_f16_mf8_fpm:
6986 return EmitFP8NeonCvtCall(Intrinsic::aarch64_neon_fp8_cvtl1,
6987 llvm::FixedVectorType::get(HalfTy, 8),
6988 Ops[0]->getType(), ExtractLow, Ops, E, "vbfcvt1");
6989 case NEON::BI__builtin_neon_vcvt2_low_f16_mf8_fpm:
6990 ExtractLow = true;
6991 [[fallthrough]];
6992 case NEON::BI__builtin_neon_vcvt2_f16_mf8_fpm:
6993 case NEON::BI__builtin_neon_vcvt2_high_f16_mf8_fpm:
6994 return EmitFP8NeonCvtCall(Intrinsic::aarch64_neon_fp8_cvtl2,
6995 llvm::FixedVectorType::get(HalfTy, 8),
6996 Ops[0]->getType(), ExtractLow, Ops, E, "vbfcvt2");
6997 case NEON::BI__builtin_neon_vcvt_mf8_f32_fpm:
6998 return EmitFP8NeonCvtCall(Intrinsic::aarch64_neon_fp8_fcvtn,
6999 llvm::FixedVectorType::get(Int8Ty, 8),
7000 Ops[0]->getType(), false, Ops, E, "vfcvtn");
7001 case NEON::BI__builtin_neon_vcvt_mf8_f16_fpm:
7002 return EmitFP8NeonCvtCall(Intrinsic::aarch64_neon_fp8_fcvtn,
7003 llvm::FixedVectorType::get(Int8Ty, 8),
7004 llvm::FixedVectorType::get(HalfTy, 4), false, Ops,
7005 E, "vfcvtn");
7006 case NEON::BI__builtin_neon_vcvtq_mf8_f16_fpm:
7007 return EmitFP8NeonCvtCall(Intrinsic::aarch64_neon_fp8_fcvtn,
7008 llvm::FixedVectorType::get(Int8Ty, 16),
7009 llvm::FixedVectorType::get(HalfTy, 8), false, Ops,
7010 E, "vfcvtn");
7011 case NEON::BI__builtin_neon_vcvt_high_mf8_f32_fpm: {
7012 llvm::Type *Ty = llvm::FixedVectorType::get(Int8Ty, 16);
7013 Ops[0] = Builder.CreateInsertVector(Ty, PoisonValue::get(Ty), Ops[0],
7014 uint64_t(0));
7015 return EmitFP8NeonCvtCall(Intrinsic::aarch64_neon_fp8_fcvtn2, Ty,
7016 Ops[1]->getType(), false, Ops, E, "vfcvtn2");
7017 }
7018
7019 case NEON::BI__builtin_neon_vdot_f16_mf8_fpm:
7020 case NEON::BI__builtin_neon_vdotq_f16_mf8_fpm:
7021 return EmitFP8NeonFDOTCall(Intrinsic::aarch64_neon_fp8_fdot2, false, HalfTy,
7022 Ops, E, "fdot2");
7023 case NEON::BI__builtin_neon_vdot_lane_f16_mf8_fpm:
7024 case NEON::BI__builtin_neon_vdotq_lane_f16_mf8_fpm:
7025 ExtendLaneArg = true;
7026 [[fallthrough]];
7027 case NEON::BI__builtin_neon_vdot_laneq_f16_mf8_fpm:
7028 case NEON::BI__builtin_neon_vdotq_laneq_f16_mf8_fpm:
7029 return EmitFP8NeonFDOTCall(Intrinsic::aarch64_neon_fp8_fdot2_lane,
7030 ExtendLaneArg, HalfTy, Ops, E, "fdot2_lane");
7031 case NEON::BI__builtin_neon_vdot_f32_mf8_fpm:
7032 case NEON::BI__builtin_neon_vdotq_f32_mf8_fpm:
7033 return EmitFP8NeonFDOTCall(Intrinsic::aarch64_neon_fp8_fdot4, false,
7034 FloatTy, Ops, E, "fdot4");
7035 case NEON::BI__builtin_neon_vdot_lane_f32_mf8_fpm:
7036 case NEON::BI__builtin_neon_vdotq_lane_f32_mf8_fpm:
7037 ExtendLaneArg = true;
7038 [[fallthrough]];
7039 case NEON::BI__builtin_neon_vdot_laneq_f32_mf8_fpm:
7040 case NEON::BI__builtin_neon_vdotq_laneq_f32_mf8_fpm:
7041 return EmitFP8NeonFDOTCall(Intrinsic::aarch64_neon_fp8_fdot4_lane,
7042 ExtendLaneArg, FloatTy, Ops, E, "fdot4_lane");
7043
7044 case NEON::BI__builtin_neon_vdot_f32_f16:
7045 case NEON::BI__builtin_neon_vdotq_f32_f16: {
7046 llvm::Type *InputTy =
7047 llvm::FixedVectorType::get(HalfTy, Ty->getPrimitiveSizeInBits() / 16);
7048 llvm::Type *Tys[2] = {Ty, InputTy};
7049 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_fdot, Tys),
7050 Ops, "vdot");
7051 }
7052
7053 case NEON::BI__builtin_neon_vdot_lane_f32_f16:
7054 case NEON::BI__builtin_neon_vdot_laneq_f32_f16:
7055 case NEON::BI__builtin_neon_vdotq_lane_f32_f16:
7056 case NEON::BI__builtin_neon_vdotq_laneq_f32_f16: {
7057 llvm::FixedVectorType *InputTy =
7058 llvm::FixedVectorType::get(HalfTy, Ty->getPrimitiveSizeInBits() / 16);
7059 llvm::FixedVectorType *LaneTy = llvm::FixedVectorType::get(
7060 HalfTy, Ops[2]->getType()->getPrimitiveSizeInBits() / 16);
7061 // Treat the lane argument as a splat and use non-lane version of the
7062 // intrinsic.
7063 Ops[2] = Builder.CreateBitCast(Ops[2], LaneTy);
7064 Ops[2] = EmitNeonSplat(Ops[2], cast<ConstantInt>(Ops[3]),
7065 InputTy->getElementCount());
7066 llvm::Type *Tys[2] = {Ty, InputTy};
7067 Ops.pop_back();
7068 return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_fdot, Tys),
7069 Ops, "vdot");
7070 }
7071
7072 case NEON::BI__builtin_neon_vmlalbq_f16_mf8_fpm:
7073 return EmitFP8NeonCall(Intrinsic::aarch64_neon_fp8_fmlalb,
7074 {llvm::FixedVectorType::get(HalfTy, 8)}, Ops, E,
7075 "vmlal");
7076 case NEON::BI__builtin_neon_vmlaltq_f16_mf8_fpm:
7077 return EmitFP8NeonCall(Intrinsic::aarch64_neon_fp8_fmlalt,
7078 {llvm::FixedVectorType::get(HalfTy, 8)}, Ops, E,
7079 "vmlal");
7080 case NEON::BI__builtin_neon_vmlallbbq_f32_mf8_fpm:
7081 return EmitFP8NeonCall(Intrinsic::aarch64_neon_fp8_fmlallbb,
7082 {llvm::FixedVectorType::get(FloatTy, 4)}, Ops, E,
7083 "vmlall");
7084 case NEON::BI__builtin_neon_vmlallbtq_f32_mf8_fpm:
7085 return EmitFP8NeonCall(Intrinsic::aarch64_neon_fp8_fmlallbt,
7086 {llvm::FixedVectorType::get(FloatTy, 4)}, Ops, E,
7087 "vmlall");
7088 case NEON::BI__builtin_neon_vmlalltbq_f32_mf8_fpm:
7089 return EmitFP8NeonCall(Intrinsic::aarch64_neon_fp8_fmlalltb,
7090 {llvm::FixedVectorType::get(FloatTy, 4)}, Ops, E,
7091 "vmlall");
7092 case NEON::BI__builtin_neon_vmlallttq_f32_mf8_fpm:
7093 return EmitFP8NeonCall(Intrinsic::aarch64_neon_fp8_fmlalltt,
7094 {llvm::FixedVectorType::get(FloatTy, 4)}, Ops, E,
7095 "vmlall");
7096 case NEON::BI__builtin_neon_vmlalbq_lane_f16_mf8_fpm:
7097 ExtendLaneArg = true;
7098 [[fallthrough]];
7099 case NEON::BI__builtin_neon_vmlalbq_laneq_f16_mf8_fpm:
7100 return EmitFP8NeonFMLACall(Intrinsic::aarch64_neon_fp8_fmlalb_lane,
7101 ExtendLaneArg, HalfTy, Ops, E, "vmlal_lane");
7102 case NEON::BI__builtin_neon_vmlaltq_lane_f16_mf8_fpm:
7103 ExtendLaneArg = true;
7104 [[fallthrough]];
7105 case NEON::BI__builtin_neon_vmlaltq_laneq_f16_mf8_fpm:
7106 return EmitFP8NeonFMLACall(Intrinsic::aarch64_neon_fp8_fmlalt_lane,
7107 ExtendLaneArg, HalfTy, Ops, E, "vmlal_lane");
7108 case NEON::BI__builtin_neon_vmlallbbq_lane_f32_mf8_fpm:
7109 ExtendLaneArg = true;
7110 [[fallthrough]];
7111 case NEON::BI__builtin_neon_vmlallbbq_laneq_f32_mf8_fpm:
7112 return EmitFP8NeonFMLACall(Intrinsic::aarch64_neon_fp8_fmlallbb_lane,
7113 ExtendLaneArg, FloatTy, Ops, E, "vmlall_lane");
7114 case NEON::BI__builtin_neon_vmlallbtq_lane_f32_mf8_fpm:
7115 ExtendLaneArg = true;
7116 [[fallthrough]];
7117 case NEON::BI__builtin_neon_vmlallbtq_laneq_f32_mf8_fpm:
7118 return EmitFP8NeonFMLACall(Intrinsic::aarch64_neon_fp8_fmlallbt_lane,
7119 ExtendLaneArg, FloatTy, Ops, E, "vmlall_lane");
7120 case NEON::BI__builtin_neon_vmlalltbq_lane_f32_mf8_fpm:
7121 ExtendLaneArg = true;
7122 [[fallthrough]];
7123 case NEON::BI__builtin_neon_vmlalltbq_laneq_f32_mf8_fpm:
7124 return EmitFP8NeonFMLACall(Intrinsic::aarch64_neon_fp8_fmlalltb_lane,
7125 ExtendLaneArg, FloatTy, Ops, E, "vmlall_lane");
7126 case NEON::BI__builtin_neon_vmlallttq_lane_f32_mf8_fpm:
7127 ExtendLaneArg = true;
7128 [[fallthrough]];
7129 case NEON::BI__builtin_neon_vmlallttq_laneq_f32_mf8_fpm:
7130 return EmitFP8NeonFMLACall(Intrinsic::aarch64_neon_fp8_fmlalltt_lane,
7131 ExtendLaneArg, FloatTy, Ops, E, "vmlall_lane");
7132 case NEON::BI__builtin_neon_vamin_f16:
7133 case NEON::BI__builtin_neon_vaminq_f16:
7134 case NEON::BI__builtin_neon_vamin_f32:
7135 case NEON::BI__builtin_neon_vaminq_f32:
7136 case NEON::BI__builtin_neon_vaminq_f64: {
7137 Int = Intrinsic::aarch64_neon_famin;
7138 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "famin");
7139 }
7140 case NEON::BI__builtin_neon_vamax_f16:
7141 case NEON::BI__builtin_neon_vamaxq_f16:
7142 case NEON::BI__builtin_neon_vamax_f32:
7143 case NEON::BI__builtin_neon_vamaxq_f32:
7144 case NEON::BI__builtin_neon_vamaxq_f64: {
7145 Int = Intrinsic::aarch64_neon_famax;
7146 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "famax");
7147 }
7148 case NEON::BI__builtin_neon_vscale_f16:
7149 case NEON::BI__builtin_neon_vscaleq_f16:
7150 case NEON::BI__builtin_neon_vscale_f32:
7151 case NEON::BI__builtin_neon_vscaleq_f32:
7152 case NEON::BI__builtin_neon_vscaleq_f64: {
7153 Int = Intrinsic::aarch64_neon_fp8_fscale;
7154 return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "fscale");
7155 }
7156 }
7157}
7158
7160 const CallExpr *E) {
7161 assert((BuiltinID == BPF::BI__builtin_preserve_field_info ||
7162 BuiltinID == BPF::BI__builtin_btf_type_id ||
7163 BuiltinID == BPF::BI__builtin_preserve_type_info ||
7164 BuiltinID == BPF::BI__builtin_preserve_enum_value) &&
7165 "unexpected BPF builtin");
7166
7167 // A sequence number, injected into IR builtin functions, to
7168 // prevent CSE given the only difference of the function
7169 // may just be the debuginfo metadata.
7170 static uint32_t BuiltinSeqNum;
7171
7172 switch (BuiltinID) {
7173 default:
7174 llvm_unreachable("Unexpected BPF builtin");
7175 case BPF::BI__builtin_preserve_field_info: {
7176 const Expr *Arg = E->getArg(0);
7177 bool IsBitField = Arg->IgnoreParens()->getObjectKind() == OK_BitField;
7178
7179 if (!getDebugInfo()) {
7180 CGM.Error(E->getExprLoc(),
7181 "using __builtin_preserve_field_info() without -g");
7182 return IsBitField ? EmitLValue(Arg).getRawBitFieldPointer(*this)
7183 : EmitLValue(Arg).emitRawPointer(*this);
7184 }
7185
7186 // Enable underlying preserve_*_access_index() generation.
7187 bool OldIsInPreservedAIRegion = IsInPreservedAIRegion;
7188 IsInPreservedAIRegion = true;
7189 Value *FieldAddr = IsBitField ? EmitLValue(Arg).getRawBitFieldPointer(*this)
7190 : EmitLValue(Arg).emitRawPointer(*this);
7191 IsInPreservedAIRegion = OldIsInPreservedAIRegion;
7192
7193 ConstantInt *C = cast<ConstantInt>(EmitScalarExpr(E->getArg(1)));
7194 Value *InfoKind = ConstantInt::get(Int64Ty, C->getSExtValue());
7195
7196 // Built the IR for the preserve_field_info intrinsic.
7197 llvm::Function *FnGetFieldInfo = Intrinsic::getOrInsertDeclaration(
7198 &CGM.getModule(), Intrinsic::bpf_preserve_field_info,
7199 {FieldAddr->getType()});
7200 return Builder.CreateCall(FnGetFieldInfo, {FieldAddr, InfoKind});
7201 }
7202 case BPF::BI__builtin_btf_type_id:
7203 case BPF::BI__builtin_preserve_type_info: {
7204 if (!getDebugInfo()) {
7205 CGM.Error(E->getExprLoc(), "using builtin function without -g");
7206 return nullptr;
7207 }
7208
7209 const Expr *Arg0 = E->getArg(0);
7210 llvm::DIType *DbgInfo = getDebugInfo()->getOrCreateStandaloneType(
7211 Arg0->getType(), Arg0->getExprLoc());
7212
7213 ConstantInt *Flag = cast<ConstantInt>(EmitScalarExpr(E->getArg(1)));
7214 Value *FlagValue = ConstantInt::get(Int64Ty, Flag->getSExtValue());
7215 Value *SeqNumVal = ConstantInt::get(Int32Ty, BuiltinSeqNum++);
7216
7217 llvm::Function *FnDecl;
7218 if (BuiltinID == BPF::BI__builtin_btf_type_id)
7219 FnDecl = Intrinsic::getOrInsertDeclaration(
7220 &CGM.getModule(), Intrinsic::bpf_btf_type_id, {});
7221 else
7222 FnDecl = Intrinsic::getOrInsertDeclaration(
7223 &CGM.getModule(), Intrinsic::bpf_preserve_type_info, {});
7224 CallInst *Fn = Builder.CreateCall(FnDecl, {SeqNumVal, FlagValue});
7225 Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);
7226 return Fn;
7227 }
7228 case BPF::BI__builtin_preserve_enum_value: {
7229 if (!getDebugInfo()) {
7230 CGM.Error(E->getExprLoc(), "using builtin function without -g");
7231 return nullptr;
7232 }
7233
7234 const Expr *Arg0 = E->getArg(0);
7235 llvm::DIType *DbgInfo = getDebugInfo()->getOrCreateStandaloneType(
7236 Arg0->getType(), Arg0->getExprLoc());
7237
7238 // Find enumerator
7239 const auto *UO = cast<UnaryOperator>(Arg0->IgnoreParens());
7240 const auto *CE = cast<CStyleCastExpr>(UO->getSubExpr());
7241 const auto *DR = cast<DeclRefExpr>(CE->getSubExpr());
7242 const auto *Enumerator = cast<EnumConstantDecl>(DR->getDecl());
7243
7244 auto InitVal = Enumerator->getInitVal();
7245 std::string InitValStr;
7246 if (InitVal.isNegative() || InitVal > uint64_t(INT64_MAX))
7247 InitValStr = std::to_string(InitVal.getSExtValue());
7248 else
7249 InitValStr = std::to_string(InitVal.getZExtValue());
7250 std::string EnumStr = Enumerator->getNameAsString() + ":" + InitValStr;
7251 Value *EnumStrVal = Builder.CreateGlobalString(EnumStr);
7252
7253 ConstantInt *Flag = cast<ConstantInt>(EmitScalarExpr(E->getArg(1)));
7254 Value *FlagValue = ConstantInt::get(Int64Ty, Flag->getSExtValue());
7255 Value *SeqNumVal = ConstantInt::get(Int32Ty, BuiltinSeqNum++);
7256
7257 llvm::Function *IntrinsicFn = Intrinsic::getOrInsertDeclaration(
7258 &CGM.getModule(), Intrinsic::bpf_preserve_enum_value, {});
7259 CallInst *Fn =
7260 Builder.CreateCall(IntrinsicFn, {SeqNumVal, EnumStrVal, FlagValue});
7261 Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);
7262 return Fn;
7263 }
7264 }
7265}
7266
7269 assert((Ops.size() & (Ops.size() - 1)) == 0 &&
7270 "Not a power-of-two sized vector!");
7271 bool AllConstants = true;
7272 for (unsigned i = 0, e = Ops.size(); i != e && AllConstants; ++i)
7273 AllConstants &= isa<Constant>(Ops[i]);
7274
7275 // If this is a constant vector, create a ConstantVector.
7276 if (AllConstants) {
7278 for (llvm::Value *Op : Ops)
7279 CstOps.push_back(cast<Constant>(Op));
7280 return llvm::ConstantVector::get(CstOps);
7281 }
7282
7283 // Otherwise, insertelement the values to build the vector.
7284 Value *Result = llvm::PoisonValue::get(
7285 llvm::FixedVectorType::get(Ops[0]->getType(), Ops.size()));
7286
7287 for (unsigned i = 0, e = Ops.size(); i != e; ++i)
7288 Result = Builder.CreateInsertElement(Result, Ops[i], Builder.getInt64(i));
7289
7290 return Result;
7291}
7292
7293Value *CodeGenFunction::EmitAArch64CpuInit() {
7294 llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
7295 llvm::FunctionCallee Func =
7296 CGM.CreateRuntimeFunction(FTy, "__init_cpu_features_resolver");
7297 cast<llvm::GlobalValue>(Func.getCallee())->setDSOLocal(true);
7298 cast<llvm::GlobalValue>(Func.getCallee())
7299 ->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
7300 return Builder.CreateCall(Func);
7301}
7302
7303Value *CodeGenFunction::EmitAArch64CpuSupports(const CallExpr *E) {
7304 const Expr *ArgExpr = E->getArg(0)->IgnoreParenCasts();
7305 StringRef ArgStr = cast<StringLiteral>(ArgExpr)->getString();
7307 ArgStr.split(OrigFeatures, "+");
7309 for (StringRef Feature : OrigFeatures) {
7310 Feature = Feature.trim();
7311 if (!llvm::AArch64::parseFMVExtension(Feature))
7312 return Builder.getFalse();
7313 if (Feature != "default")
7314 Features.push_back(Feature);
7315 }
7316 return EmitAArch64CpuSupports(Features);
7317}
7318
7319llvm::Value *
7320CodeGenFunction::EmitAArch64CpuSupports(ArrayRef<StringRef> FeaturesStrs) {
7321 llvm::APInt FeaturesMask = llvm::AArch64::getCpuSupportsMask(FeaturesStrs);
7322 Value *Result = Builder.getTrue();
7323 if (FeaturesMask != 0) {
7324 // Get features from structure in runtime library
7325 // struct {
7326 // unsigned long long features;
7327 // } __aarch64_cpu_features;
7328 llvm::Type *STy = llvm::StructType::get(Int64Ty);
7329 llvm::Constant *AArch64CPUFeatures =
7330 CGM.CreateRuntimeVariable(STy, "__aarch64_cpu_features");
7331 cast<llvm::GlobalValue>(AArch64CPUFeatures)->setDSOLocal(true);
7332 llvm::Value *CpuFeatures = Builder.CreateGEP(
7333 STy, AArch64CPUFeatures,
7334 {ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, 0)});
7335 Value *Features = Builder.CreateAlignedLoad(Int64Ty, CpuFeatures,
7337 Value *Mask = Builder.getInt(FeaturesMask.trunc(64));
7338 Value *Bitset = Builder.CreateAnd(Features, Mask);
7339 Value *Cmp = Builder.CreateICmpEQ(Bitset, Mask);
7340 Result = Builder.CreateAnd(Result, Cmp);
7341 }
7342 return Result;
7343}
Utilities used for generating code for AArch64 that are shared between the classic and ClangIR code-g...
#define NEONMAP2(NameBase, LLVMIntrinsic, AltLLVMIntrinsic, TypeModifier)
#define NEONMAP1(NameBase, LLVMIntrinsic, TypeModifier)
#define NEONMAP0(NameBase)
#define V(N, I)
Address CheckAtomicAlignment(CodeGenFunction &CGF, const CallExpr *E)
static cir::VectorType getSVEVectorForElementType(CIRGenModule &cgm, mlir::Type eltTy)
static const IntrinsicInfo * findARMVectorIntrinsicInMap(ArrayRef< IntrinsicInfo > intrinsicMap, unsigned builtinID, bool &mapProvenSorted)
static Value * EmitSpecialRegisterBuiltin(CodeGenFunction &CGF, const CallExpr *E, llvm::Type *RegisterType, llvm::Type *ValueType, SpecialRegisterAccessKind AccessKind, StringRef SysReg="")
Definition ARM.cpp:1952
static llvm::Value * ARMMVEVectorReinterpret(CGBuilderTy &Builder, CodeGenFunction *CGF, llvm::Value *V, llvm::Type *DestType)
Definition ARM.cpp:2827
static llvm::VectorType * GetFloatNeonType(CodeGenFunction *CGF, NeonTypeFlags IntTypeFlags)
Definition ARM.cpp:401
static llvm::Value * MVEImmediateShr(CGBuilderTy &Builder, llvm::Value *V, uint32_t Shift, bool Unsigned)
Definition ARM.cpp:2797
static llvm::Value * SignOrZeroExtend(CGBuilderTy &Builder, llvm::Value *V, llvm::Type *T, bool Unsigned)
Definition ARM.cpp:2790
static void InsertExplicitZeroOperand(CGBuilderTy &Builder, llvm::Type *Ty, SmallVectorImpl< Value * > &Ops)
Definition ARM.cpp:3844
static Value * EmitAArch64TblBuiltinExpr(CodeGenFunction &CGF, unsigned BuiltinID, const CallExpr *E, SmallVectorImpl< Value * > &Ops, llvm::Triple::ArchType Arch)
Definition ARM.cpp:3049
static void swapCommutativeSMEOperands(unsigned BuiltinID, SmallVectorImpl< Value * > &Ops)
Definition ARM.cpp:4297
static bool AArch64SISDIntrinsicsProvenSorted
Definition ARM.cpp:986
static llvm::Value * ARMMVECreateFPToSI(CGBuilderTy &Builder, CodeGenFunction *CGF, llvm::Value *V, llvm::Type *Ty)
Definition ARM.cpp:2921
static bool HasExtraNeonArgument(unsigned BuiltinID)
Return true if BuiltinID is an overloaded Neon intrinsic with an extra argument that specifies the ve...
Definition ARM.cpp:2073
static Value * EmitCommonNeonSISDBuiltinExpr(CodeGenFunction &CGF, const ARMNeonVectorIntrinsicInfo &SISDInfo, SmallVectorImpl< Value * > &Ops, const CallExpr *E)
Definition ARM.cpp:1054
static llvm::Value * ARMMVECreateFPToUI(CGBuilderTy &Builder, CodeGenFunction *CGF, llvm::Value *V, llvm::Type *Ty)
Definition ARM.cpp:2929
static llvm::Value * ARMMVECreateSIToFP(CGBuilderTy &Builder, CodeGenFunction *CGF, llvm::Value *V, llvm::Type *Ty)
Definition ARM.cpp:2905
static bool AArch64SVEIntrinsicsProvenSorted
Definition ARM.cpp:987
static void InsertExplicitUndefOperand(CGBuilderTy &Builder, llvm::Type *Ty, SmallVectorImpl< Value * > &Ops)
Definition ARM.cpp:3850
static Integer GetIntegerConstantValue(const Expr *E, ASTContext &Context)
Definition ARM.cpp:2786
static bool AArch64SMEIntrinsicsProvenSorted
Definition ARM.cpp:988
static llvm::Value * VectorZip(CGBuilderTy &Builder, llvm::Value *V0, llvm::Value *V1)
Definition ARM.cpp:2864
constexpr unsigned SVEBitsPerBlock
Definition ARM.cpp:3329
static const std::pair< unsigned, unsigned > NEONEquivalentIntrinsicMap[]
Definition ARM.cpp:860
static llvm::FixedVectorType * GetNeonType(CodeGenFunction *CGF, NeonTypeFlags TypeFlags, bool HasFastHalfType=true, bool V1Ty=false, bool AllowBFloatArgsAndRet=true)
Definition ARM.cpp:361
Value * readX18AsPtr(CodeGenFunction &CGF)
Helper for the read/write/add/inc X18 builtins: read the X18 register and return it as an i8 pointer.
Definition ARM.cpp:4397
static llvm::Value * ARMMVEVectorElementReverse(CGBuilderTy &Builder, llvm::Value *V, unsigned ReverseWidth)
Definition ARM.cpp:2891
static std::optional< CodeGenFunction::MSVCIntrin > translateAarch64ToMsvcIntrin(unsigned BuiltinID)
Definition ARM.cpp:33
static std::optional< CodeGenFunction::MSVCIntrin > translateArmToMsvcIntrin(unsigned BuiltinID)
Definition ARM.cpp:192
static llvm::Value * ARMMVECreateUIToFP(CGBuilderTy &Builder, CodeGenFunction *CGF, llvm::Value *V, llvm::Type *Ty)
Definition ARM.cpp:2913
static llvm::Value * VectorUnzip(CGBuilderTy &Builder, llvm::Value *V, bool Odd)
Definition ARM.cpp:2853
static llvm::Value * ARMMVEConstantSplat(CGBuilderTy &Builder, llvm::Type *VT)
Definition ARM.cpp:2879
SpecialRegisterAccessKind
Definition ARM.cpp:1943
@ VolatileRead
Definition ARM.cpp:1945
@ NormalRead
Definition ARM.cpp:1944
@ Write
Definition ARM.cpp:1946
static const AArch64SVEAndSMEVectorIntrinsicInfo AArch64SMEIntrinsicMap[]
Definition ARM.cpp:974
static llvm::Value * ARMMVEVectorSplat(CGBuilderTy &Builder, llvm::Value *V)
Definition ARM.cpp:2819
static bool NEONSIMDIntrinsicsProvenSorted
Definition ARM.cpp:983
static Value * emitCallMaybeConstrainedFPBuiltin(CodeGenFunction &CGF, unsigned IntrinsicID, unsigned ConstrainedIntrinsicID, llvm::Type *Ty, ArrayRef< Value * > Args)
Definition ARM.cpp:344
static Value * EmitRangePrefetchBuiltin(CodeGenFunction &CGF, unsigned BuiltinID, const CallExpr *E)
Definition ARM.cpp:2018
static Value * packTBLDVectorList(CodeGenFunction &CGF, ArrayRef< Value * > Ops, Value *ExtOp, Value *IndexOp, llvm::Type *ResTy, unsigned IntID, const char *Name)
Definition ARM.cpp:1870
static bool AArch64SIMDIntrinsicsProvenSorted
Definition ARM.cpp:985
static const ARMNeonVectorIntrinsicInfo ARMSIMDIntrinsicMap[]
Definition ARM.cpp:540
static const AArch64SVEAndSMEVectorIntrinsicInfo AArch64SVEIntrinsicMap[]
Definition ARM.cpp:959
TokenType getType() const
Returns the token's type, e.g.
Result
Implement __builtin_bit_cast and related operations.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
HLSLResourceBindingAttr::RegisterType RegisterType
Definition SemaHLSL.cpp:60
Enumerates target-specific builtins in their own namespaces within namespace clang.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:239
QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error, unsigned *IntegerConstantArgs=nullptr) const
Return the type for the specified builtin.
@ GE_None
No error.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2987
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3191
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition Expr.h:3178
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition Expr.cpp:1631
static CharUnits One()
One - Construct a CharUnits quantity of one.
Definition CharUnits.h:58
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
Definition Address.h:128
static Address invalid()
Definition Address.h:176
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
Definition Address.h:253
CharUnits getAlignment() const
Definition Address.h:194
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
Definition Address.h:276
llvm::PointerType * getType() const
Return the type of the pointer value.
Definition Address.h:204
An aggregate value slot.
Definition CGValue.h:551
Address getAddress() const
Definition CGValue.h:691
llvm::DIType * getOrCreateStandaloneType(QualType Ty, SourceLocation Loc)
Emit standalone debug info for a type.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
llvm::Value * EmitSVEPredicateCast(llvm::Value *Pred, llvm::ScalableVectorType *VTy)
Definition ARM.cpp:3338
llvm::Value * EmitFP8NeonFMLACall(unsigned IID, bool ExtendLaneArg, llvm::Type *RetTy, SmallVectorImpl< llvm::Value * > &Ops, const CallExpr *E, const char *name)
Definition ARM.cpp:472
llvm::Value * BuildVector(ArrayRef< llvm::Value * > Ops)
Definition ARM.cpp:7268
llvm::Value * EmitScalarOrConstFoldImmArg(unsigned ICEArguments, unsigned Idx, const CallExpr *E)
llvm::Value * EmitSVEStructLoad(const SVETypeFlags &TypeFlags, SmallVectorImpl< llvm::Value * > &Ops, unsigned IntID)
Definition ARM.cpp:3513
llvm::Value * EmitSVEMaskedLoad(const CallExpr *, llvm::Type *ReturnTy, SmallVectorImpl< llvm::Value * > &Ops, unsigned BuiltinID, bool IsZExtReturn)
Definition ARM.cpp:3622
llvm::Value * EmitFP8NeonCall(unsigned IID, ArrayRef< llvm::Type * > Tys, SmallVectorImpl< llvm::Value * > &O, const CallExpr *E, const char *name)
Definition ARM.cpp:447
llvm::Type * ConvertType(QualType T)
llvm::Value * EmitSVEGatherPrefetch(const SVETypeFlags &TypeFlags, SmallVectorImpl< llvm::Value * > &Ops, unsigned IntID)
Definition ARM.cpp:3477
llvm::Value * EmitSMEReadWrite(const SVETypeFlags &TypeFlags, llvm::SmallVectorImpl< llvm::Value * > &Ops, unsigned IntID)
Definition ARM.cpp:3768
llvm::Type * SVEBuiltinMemEltTy(const SVETypeFlags &TypeFlags)
SVEBuiltinMemEltTy - Returns the memory element type for this memory access builtin.
Definition ARM.cpp:3204
llvm::Value * EmitSVEScatterStore(const SVETypeFlags &TypeFlags, llvm::SmallVectorImpl< llvm::Value * > &Ops, unsigned IntID)
Definition ARM.cpp:3431
llvm::Value * EmitSVEMaskedStore(const CallExpr *, SmallVectorImpl< llvm::Value * > &Ops, unsigned BuiltinID)
Definition ARM.cpp:3679
llvm::Value * EmitAArch64SMEBuiltinExpr(unsigned BuiltinID, const CallExpr *E)
Definition ARM.cpp:4321
void GetAArch64SVEProcessedOperands(unsigned BuiltinID, const CallExpr *E, SmallVectorImpl< llvm::Value * > &Ops, SVETypeFlags TypeFlags)
Definition ARM.cpp:3907
llvm::Value * EmitSVEGatherLoad(const SVETypeFlags &TypeFlags, llvm::SmallVectorImpl< llvm::Value * > &Ops, unsigned IntID)
Definition ARM.cpp:3389
llvm::Function * LookupNeonLLVMIntrinsic(unsigned IntrinsicID, unsigned Modifier, llvm::Type *ArgTy, const CallExpr *E)
Definition ARM.cpp:1012
llvm::Type * getEltType(const SVETypeFlags &TypeFlags)
Definition ARM.cpp:3220
llvm::Value * EmitCommonNeonBuiltinExpr(unsigned BuiltinID, unsigned LLVMIntrinsic, unsigned AltLLVMIntrinsic, const char *NameHint, unsigned Modifier, const CallExpr *E, SmallVectorImpl< llvm::Value * > &Ops, Address PtrOp0, Address PtrOp1, llvm::Triple::ArchType Arch)
Definition ARM.cpp:1120
llvm::Value * EmitNeonSplat(llvm::Value *V, llvm::Constant *Idx, const llvm::ElementCount &Count)
llvm::Value * EmitSVEDupX(llvm::Value *Scalar)
const TargetInfo & getTarget() const
llvm::Value * EmitAArch64SVEBuiltinExpr(unsigned BuiltinID, const CallExpr *E)
Definition ARM.cpp:3950
llvm::Value * EmitFP8NeonCvtCall(unsigned IID, llvm::Type *Ty0, llvm::Type *Ty1, bool Extract, SmallVectorImpl< llvm::Value * > &Ops, const CallExpr *E, const char *name)
Definition ARM.cpp:493
llvm::Value * EmitARMBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue, llvm::Triple::ArchType Arch)
Definition ARM.cpp:2100
llvm::ScalableVectorType * getSVEType(const SVETypeFlags &TypeFlags)
Definition ARM.cpp:3293
llvm::Value * EmitBPFBuiltinExpr(unsigned BuiltinID, const CallExpr *E)
Definition ARM.cpp:7159
llvm::Value * EmitSMELdrStr(const SVETypeFlags &TypeFlags, llvm::SmallVectorImpl< llvm::Value * > &Ops, unsigned IntID)
Definition ARM.cpp:3790
llvm::Value * EmitSVETupleCreate(const SVETypeFlags &TypeFlags, llvm::Type *ReturnType, ArrayRef< llvm::Value * > Ops)
Definition ARM.cpp:3895
llvm::Value * EmitSVEPMull(const SVETypeFlags &TypeFlags, llvm::SmallVectorImpl< llvm::Value * > &Ops, unsigned BuiltinID)
Definition ARM.cpp:3576
llvm::Value * EmitARMMVEBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue, llvm::Triple::ArchType Arch)
Definition ARM.cpp:2937
AggValueSlot CreateAggTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateAggTemp - Create a temporary memory object for the given aggregate type.
llvm::Value * EmitNeonRShiftImm(llvm::Value *Vec, llvm::Value *Amt, llvm::Type *Ty, bool usgn, const char *name)
Definition ARM.cpp:509
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
SmallVector< llvm::Type *, 2 > getSVEOverloadTypes(const SVETypeFlags &TypeFlags, llvm::Type *ReturnType, ArrayRef< llvm::Value * > Ops)
Definition ARM.cpp:3857
const TargetCodeGenInfo & getTargetHooks() const
RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen without...
Definition CGExpr.cpp:233
llvm::Value * EmitNeonShiftVector(llvm::Value *V, llvm::Type *Ty, bool negateForRightShift)
Definition ARM.cpp:487
bool IsInPreservedAIRegion
True if CodeGen currently emits code inside presereved access index region.
llvm::Value * EmitAArch64BuiltinExpr(unsigned BuiltinID, const CallExpr *E, llvm::Triple::ArchType Arch)
Definition ARM.cpp:4408
llvm::Value * EmitMSVCBuiltinExpr(MSVCIntrin BuiltinID, const CallExpr *E)
llvm::Value * EmitFP8NeonFDOTCall(unsigned IID, bool ExtendLaneArg, llvm::Type *RetTy, SmallVectorImpl< llvm::Value * > &Ops, const CallExpr *E, const char *name)
Definition ARM.cpp:456
llvm::Value * vectorWrapScalar16(llvm::Value *Op)
Definition ARM.cpp:3192
llvm::Value * EmitARMCDEBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue, llvm::Triple::ArchType Arch)
Definition ARM.cpp:3038
llvm::Value * EmitAArch64CompareBuiltinExpr(llvm::Value *Op, llvm::Type *Ty, const llvm::CmpInst::Predicate Pred, const llvm::Twine &Name="")
Definition ARM.cpp:1841
void EmitAnyExprToMem(const Expr *E, Address Location, Qualifiers Quals, bool IsInitializer)
EmitAnyExprToMem - Emits the code necessary to evaluate an arbitrary expression into the given memory...
Definition CGExpr.cpp:311
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
llvm::Value * EmitSVEMovl(const SVETypeFlags &TypeFlags, llvm::ArrayRef< llvm::Value * > Ops, unsigned BuiltinID)
Definition ARM.cpp:3594
llvm::Value * EmitSVEPredicateTupleCast(llvm::Value *PredTuple, llvm::StructType *Ty)
Definition ARM.cpp:3373
llvm::Value * EmitSVEPrefetchLoad(const SVETypeFlags &TypeFlags, SmallVectorImpl< llvm::Value * > &Ops, unsigned BuiltinID)
Definition ARM.cpp:3601
llvm::Value * EmitSMEZero(const SVETypeFlags &TypeFlags, llvm::SmallVectorImpl< llvm::Value * > &Ops, unsigned IntID)
Definition ARM.cpp:3780
Address EmitPointerWithAlignment(const Expr *Addr, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitPointerWithAlignment - Given an expression with a pointer type, emit the value and compute our be...
Definition CGExpr.cpp:1617
llvm::Value * EmitSVEStructStore(const SVETypeFlags &TypeFlags, SmallVectorImpl< llvm::Value * > &Ops, unsigned IntID)
Definition ARM.cpp:3528
llvm::Value * EmitSMELd1St1(const SVETypeFlags &TypeFlags, llvm::SmallVectorImpl< llvm::Value * > &Ops, unsigned IntID)
Definition ARM.cpp:3733
void EmitAggExpr(const Expr *E, AggValueSlot AS)
EmitAggExpr - Emit the computation of the specified expression of aggregate type.
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
llvm::Value * EmitSVEReinterpret(llvm::Value *Val, llvm::Type *Ty)
Definition ARM.cpp:3821
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
Definition CGExpr.cpp:1733
llvm::LLVMContext & getLLVMContext()
llvm::ScalableVectorType * getSVEPredType(const SVETypeFlags &TypeFlags)
Definition ARM.cpp:3258
llvm::Value * EmitNeonCall(llvm::Function *F, SmallVectorImpl< llvm::Value * > &O, const char *name, unsigned shift=0, bool rightshift=false)
Definition ARM.cpp:427
llvm::Value * EmitSVETupleSetOrGet(const SVETypeFlags &TypeFlags, ArrayRef< llvm::Value * > Ops)
Definition ARM.cpp:3884
This class organizes the cross-function state that is used while generating LLVM code.
llvm::FunctionCallee CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeList ExtraAttrs=llvm::AttributeList(), bool Local=false, bool AssumeConvergent=false)
Create or return a runtime function declaration with the specified type and name.
ASTContext & getContext() const
llvm::LLVMContext & getLLVMContext()
llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys={})
llvm::Value * getRawBitFieldPointer(CodeGenFunction &CGF) const
Definition CGValue.h:441
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
ReturnValueSlot - Contains the address where the return value of a function can be stored,...
Definition CGCall.h:384
This represents one expression.
Definition Expr.h:113
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition Expr.cpp:3128
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3119
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition Expr.h:455
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, bool AllowRelaxedEval=false) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:145
Flags to identify the types for overloaded Neon builtins.
EltType getEltType() const
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3396
QualType getPointeeType() const
Definition TypeBase.h:3406
A (possibly-)qualified type.
Definition TypeBase.h:938
The collection of all-type qualifiers we support.
Definition TypeBase.h:332
Flags to identify the types for overloaded SVE builtins.
bool isZExtReturn() const
bool isReverseUSDOT() const
bool isOverloadNone() const
MemEltType getMemEltType() const
bool isGatherLoad() const
EltType getEltType() const
bool isOverloadFirstandLast() const
bool isOverloadDefault() const
bool isPrefetch() const
bool isOverloadWhileRW() const
bool isTupleSet() const
bool isReverseMergeAnyAccOp() const
bool isReductionQV() const
bool isTupleGet() const
bool isInsertOp1SVALL() const
bool isAppendSVALL() const
bool isReverseMergeAnyBinOp() const
bool isStructStore() const
bool isOverloadDefaultAndOp0() const
bool isTupleCreate() const
bool isGatherPrefetch() const
bool hasSplatOperand() const
MergeType getMergeType() const
bool isByteIndexed() const
bool isStructLoad() const
bool isOverloadWhileOrMultiVecCvt() const
unsigned getSplatOperand() const
bool isScatterStore() const
bool isReverseCompare() const
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
virtual bool hasFastHalfType() const
Determine whether the target has fast native support for operations on half types.
Definition TargetInfo.h:705
bool isBigEndian() const
The base class of the type hierarchy.
Definition TypeBase.h:1879
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
Definition Type.cpp:2305
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9324
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:798
QualType getType() const
Definition Value.cpp:238
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
Definition CGValue.h:155
const ARMNeonVectorIntrinsicInfo AArch64SISDIntrinsicMap[]
const ARMNeonVectorIntrinsicInfo AArch64SIMDIntrinsicMap[]
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ OK_BitField
A bitfield object is a bitfield on a C or C++ record.
Definition Specifiers.h:155
@ Result
The result type of a method or function.
Definition TypeBase.h:906
const FunctionProtoType * T
U cast(CodeGen::Address addr)
Definition Address.h:327
@ Enumerator
Enumerator value with fixed underlying type.
Definition Sema.h:834
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::Type * HalfTy
half, bfloat, float, double
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:666
Describes an AArch64 SVE or SME intrinsic.
Describes an ARM or AArch64 NEON intrinsic, or an AArch64 SISD intrinsic.
#define trunc(__x)
Definition tgmath.h:1216
#define round(__x)
Definition tgmath.h:1148
#define rint(__x)
Definition tgmath.h:1131
#define floor(__x)
Definition tgmath.h:722
#define ceil(__x)
Definition tgmath.h:601