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