3118 lines · cpp
1//===---------- X86.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 "CGBuiltin.h"14#include "clang/Basic/TargetBuiltins.h"15#include "llvm/IR/InlineAsm.h"16#include "llvm/IR/IntrinsicsX86.h"17#include "llvm/TargetParser/X86TargetParser.h"18 19using namespace clang;20using namespace CodeGen;21using namespace llvm;22 23static std::optional<CodeGenFunction::MSVCIntrin>24translateX86ToMsvcIntrin(unsigned BuiltinID) {25 using MSVCIntrin = CodeGenFunction::MSVCIntrin;26 switch (BuiltinID) {27 default:28 return std::nullopt;29 case clang::X86::BI_BitScanForward:30 case clang::X86::BI_BitScanForward64:31 return MSVCIntrin::_BitScanForward;32 case clang::X86::BI_BitScanReverse:33 case clang::X86::BI_BitScanReverse64:34 return MSVCIntrin::_BitScanReverse;35 case clang::X86::BI_InterlockedAnd64:36 return MSVCIntrin::_InterlockedAnd;37 case clang::X86::BI_InterlockedCompareExchange128:38 return MSVCIntrin::_InterlockedCompareExchange128;39 case clang::X86::BI_InterlockedExchange64:40 return MSVCIntrin::_InterlockedExchange;41 case clang::X86::BI_InterlockedExchangeAdd64:42 return MSVCIntrin::_InterlockedExchangeAdd;43 case clang::X86::BI_InterlockedExchangeSub64:44 return MSVCIntrin::_InterlockedExchangeSub;45 case clang::X86::BI_InterlockedOr64:46 return MSVCIntrin::_InterlockedOr;47 case clang::X86::BI_InterlockedXor64:48 return MSVCIntrin::_InterlockedXor;49 case clang::X86::BI_InterlockedDecrement64:50 return MSVCIntrin::_InterlockedDecrement;51 case clang::X86::BI_InterlockedIncrement64:52 return MSVCIntrin::_InterlockedIncrement;53 }54 llvm_unreachable("must return from switch");55}56 57// Convert the mask from an integer type to a vector of i1.58static Value *getMaskVecValue(CodeGenFunction &CGF, Value *Mask,59 unsigned NumElts) {60 61 auto *MaskTy = llvm::FixedVectorType::get(62 CGF.Builder.getInt1Ty(),63 cast<IntegerType>(Mask->getType())->getBitWidth());64 Value *MaskVec = CGF.Builder.CreateBitCast(Mask, MaskTy);65 66 // If we have less than 8 elements, then the starting mask was an i8 and67 // we need to extract down to the right number of elements.68 if (NumElts < 8) {69 int Indices[4];70 for (unsigned i = 0; i != NumElts; ++i)71 Indices[i] = i;72 MaskVec = CGF.Builder.CreateShuffleVector(73 MaskVec, MaskVec, ArrayRef(Indices, NumElts), "extract");74 }75 return MaskVec;76}77 78static Value *EmitX86MaskedStore(CodeGenFunction &CGF, ArrayRef<Value *> Ops,79 Align Alignment) {80 Value *Ptr = Ops[0];81 82 Value *MaskVec = getMaskVecValue(83 CGF, Ops[2],84 cast<llvm::FixedVectorType>(Ops[1]->getType())->getNumElements());85 86 return CGF.Builder.CreateMaskedStore(Ops[1], Ptr, Alignment, MaskVec);87}88 89static Value *EmitX86MaskedLoad(CodeGenFunction &CGF, ArrayRef<Value *> Ops,90 Align Alignment) {91 llvm::Type *Ty = Ops[1]->getType();92 Value *Ptr = Ops[0];93 94 Value *MaskVec = getMaskVecValue(95 CGF, Ops[2], cast<llvm::FixedVectorType>(Ty)->getNumElements());96 97 return CGF.Builder.CreateMaskedLoad(Ty, Ptr, Alignment, MaskVec, Ops[1]);98}99 100static Value *EmitX86ExpandLoad(CodeGenFunction &CGF,101 ArrayRef<Value *> Ops) {102 auto *ResultTy = cast<llvm::VectorType>(Ops[1]->getType());103 Value *Ptr = Ops[0];104 105 Value *MaskVec = getMaskVecValue(106 CGF, Ops[2], cast<FixedVectorType>(ResultTy)->getNumElements());107 108 llvm::Function *F = CGF.CGM.getIntrinsic(Intrinsic::masked_expandload,109 ResultTy);110 return CGF.Builder.CreateCall(F, { Ptr, MaskVec, Ops[1] });111}112 113static Value *EmitX86CompressExpand(CodeGenFunction &CGF,114 ArrayRef<Value *> Ops,115 bool IsCompress) {116 auto *ResultTy = cast<llvm::FixedVectorType>(Ops[1]->getType());117 118 Value *MaskVec = getMaskVecValue(CGF, Ops[2], ResultTy->getNumElements());119 120 Intrinsic::ID IID = IsCompress ? Intrinsic::x86_avx512_mask_compress121 : Intrinsic::x86_avx512_mask_expand;122 llvm::Function *F = CGF.CGM.getIntrinsic(IID, ResultTy);123 return CGF.Builder.CreateCall(F, { Ops[0], Ops[1], MaskVec });124}125 126static Value *EmitX86CompressStore(CodeGenFunction &CGF,127 ArrayRef<Value *> Ops) {128 auto *ResultTy = cast<llvm::FixedVectorType>(Ops[1]->getType());129 Value *Ptr = Ops[0];130 131 Value *MaskVec = getMaskVecValue(CGF, Ops[2], ResultTy->getNumElements());132 133 llvm::Function *F = CGF.CGM.getIntrinsic(Intrinsic::masked_compressstore,134 ResultTy);135 return CGF.Builder.CreateCall(F, { Ops[1], Ptr, MaskVec });136}137 138static Value *EmitX86MaskLogic(CodeGenFunction &CGF, Instruction::BinaryOps Opc,139 ArrayRef<Value *> Ops,140 bool InvertLHS = false) {141 unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth();142 Value *LHS = getMaskVecValue(CGF, Ops[0], NumElts);143 Value *RHS = getMaskVecValue(CGF, Ops[1], NumElts);144 145 if (InvertLHS)146 LHS = CGF.Builder.CreateNot(LHS);147 148 return CGF.Builder.CreateBitCast(CGF.Builder.CreateBinOp(Opc, LHS, RHS),149 Ops[0]->getType());150}151 152static Value *EmitX86FunnelShift(CodeGenFunction &CGF, Value *Op0, Value *Op1,153 Value *Amt, bool IsRight) {154 llvm::Type *Ty = Op0->getType();155 156 // Amount may be scalar immediate, in which case create a splat vector.157 // Funnel shifts amounts are treated as modulo and types are all power-of-2 so158 // we only care about the lowest log2 bits anyway.159 if (Amt->getType() != Ty) {160 unsigned NumElts = cast<llvm::FixedVectorType>(Ty)->getNumElements();161 Amt = CGF.Builder.CreateIntCast(Amt, Ty->getScalarType(), false);162 Amt = CGF.Builder.CreateVectorSplat(NumElts, Amt);163 }164 165 unsigned IID = IsRight ? Intrinsic::fshr : Intrinsic::fshl;166 Function *F = CGF.CGM.getIntrinsic(IID, Ty);167 return CGF.Builder.CreateCall(F, {Op0, Op1, Amt});168}169 170static Value *EmitX86vpcom(CodeGenFunction &CGF, ArrayRef<Value *> Ops,171 bool IsSigned) {172 Value *Op0 = Ops[0];173 Value *Op1 = Ops[1];174 llvm::Type *Ty = Op0->getType();175 uint64_t Imm = cast<llvm::ConstantInt>(Ops[2])->getZExtValue() & 0x7;176 177 CmpInst::Predicate Pred;178 switch (Imm) {179 case 0x0:180 Pred = IsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT;181 break;182 case 0x1:183 Pred = IsSigned ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE;184 break;185 case 0x2:186 Pred = IsSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT;187 break;188 case 0x3:189 Pred = IsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE;190 break;191 case 0x4:192 Pred = ICmpInst::ICMP_EQ;193 break;194 case 0x5:195 Pred = ICmpInst::ICMP_NE;196 break;197 case 0x6:198 return llvm::Constant::getNullValue(Ty); // FALSE199 case 0x7:200 return llvm::Constant::getAllOnesValue(Ty); // TRUE201 default:202 llvm_unreachable("Unexpected XOP vpcom/vpcomu predicate");203 }204 205 Value *Cmp = CGF.Builder.CreateICmp(Pred, Op0, Op1);206 Value *Res = CGF.Builder.CreateSExt(Cmp, Ty);207 return Res;208}209 210static Value *EmitX86Select(CodeGenFunction &CGF,211 Value *Mask, Value *Op0, Value *Op1) {212 213 // If the mask is all ones just return first argument.214 if (const auto *C = dyn_cast<Constant>(Mask))215 if (C->isAllOnesValue())216 return Op0;217 218 Mask = getMaskVecValue(219 CGF, Mask, cast<llvm::FixedVectorType>(Op0->getType())->getNumElements());220 221 return CGF.Builder.CreateSelect(Mask, Op0, Op1);222}223 224static Value *EmitX86ScalarSelect(CodeGenFunction &CGF,225 Value *Mask, Value *Op0, Value *Op1) {226 // If the mask is all ones just return first argument.227 if (const auto *C = dyn_cast<Constant>(Mask))228 if (C->isAllOnesValue())229 return Op0;230 231 auto *MaskTy = llvm::FixedVectorType::get(232 CGF.Builder.getInt1Ty(), Mask->getType()->getIntegerBitWidth());233 Mask = CGF.Builder.CreateBitCast(Mask, MaskTy);234 Mask = CGF.Builder.CreateExtractElement(Mask, (uint64_t)0);235 return CGF.Builder.CreateSelect(Mask, Op0, Op1);236}237 238static Value *EmitX86MaskedCompareResult(CodeGenFunction &CGF, Value *Cmp,239 unsigned NumElts, Value *MaskIn) {240 if (MaskIn) {241 const auto *C = dyn_cast<Constant>(MaskIn);242 if (!C || !C->isAllOnesValue())243 Cmp = CGF.Builder.CreateAnd(Cmp, getMaskVecValue(CGF, MaskIn, NumElts));244 }245 246 if (NumElts < 8) {247 int Indices[8];248 for (unsigned i = 0; i != NumElts; ++i)249 Indices[i] = i;250 for (unsigned i = NumElts; i != 8; ++i)251 Indices[i] = i % NumElts + NumElts;252 Cmp = CGF.Builder.CreateShuffleVector(253 Cmp, llvm::Constant::getNullValue(Cmp->getType()), Indices);254 }255 256 return CGF.Builder.CreateBitCast(Cmp,257 IntegerType::get(CGF.getLLVMContext(),258 std::max(NumElts, 8U)));259}260 261static Value *EmitX86MaskedCompare(CodeGenFunction &CGF, unsigned CC,262 bool Signed, ArrayRef<Value *> Ops) {263 assert((Ops.size() == 2 || Ops.size() == 4) &&264 "Unexpected number of arguments");265 unsigned NumElts =266 cast<llvm::FixedVectorType>(Ops[0]->getType())->getNumElements();267 Value *Cmp;268 269 if (CC == 3) {270 Cmp = Constant::getNullValue(271 llvm::FixedVectorType::get(CGF.Builder.getInt1Ty(), NumElts));272 } else if (CC == 7) {273 Cmp = Constant::getAllOnesValue(274 llvm::FixedVectorType::get(CGF.Builder.getInt1Ty(), NumElts));275 } else {276 ICmpInst::Predicate Pred;277 switch (CC) {278 default: llvm_unreachable("Unknown condition code");279 case 0: Pred = ICmpInst::ICMP_EQ; break;280 case 1: Pred = Signed ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT; break;281 case 2: Pred = Signed ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE; break;282 case 4: Pred = ICmpInst::ICMP_NE; break;283 case 5: Pred = Signed ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE; break;284 case 6: Pred = Signed ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT; break;285 }286 Cmp = CGF.Builder.CreateICmp(Pred, Ops[0], Ops[1]);287 }288 289 Value *MaskIn = nullptr;290 if (Ops.size() == 4)291 MaskIn = Ops[3];292 293 return EmitX86MaskedCompareResult(CGF, Cmp, NumElts, MaskIn);294}295 296static Value *EmitX86ConvertToMask(CodeGenFunction &CGF, Value *In) {297 Value *Zero = Constant::getNullValue(In->getType());298 return EmitX86MaskedCompare(CGF, 1, true, { In, Zero });299}300 301static Value *EmitX86ConvertIntToFp(CodeGenFunction &CGF, const CallExpr *E,302 ArrayRef<Value *> Ops, bool IsSigned) {303 unsigned Rnd = cast<llvm::ConstantInt>(Ops[3])->getZExtValue();304 llvm::Type *Ty = Ops[1]->getType();305 306 Value *Res;307 if (Rnd != 4) {308 Intrinsic::ID IID = IsSigned ? Intrinsic::x86_avx512_sitofp_round309 : Intrinsic::x86_avx512_uitofp_round;310 Function *F = CGF.CGM.getIntrinsic(IID, { Ty, Ops[0]->getType() });311 Res = CGF.Builder.CreateCall(F, { Ops[0], Ops[3] });312 } else {313 CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);314 Res = IsSigned ? CGF.Builder.CreateSIToFP(Ops[0], Ty)315 : CGF.Builder.CreateUIToFP(Ops[0], Ty);316 }317 318 return EmitX86Select(CGF, Ops[2], Res, Ops[1]);319}320 321// Lowers X86 FMA intrinsics to IR.322static Value *EmitX86FMAExpr(CodeGenFunction &CGF, const CallExpr *E,323 ArrayRef<Value *> Ops, unsigned BuiltinID,324 bool IsAddSub) {325 326 bool Subtract = false;327 Intrinsic::ID IID = Intrinsic::not_intrinsic;328 switch (BuiltinID) {329 default: break;330 case clang::X86::BI__builtin_ia32_vfmsubph512_mask3:331 Subtract = true;332 [[fallthrough]];333 case clang::X86::BI__builtin_ia32_vfmaddph512_mask:334 case clang::X86::BI__builtin_ia32_vfmaddph512_maskz:335 case clang::X86::BI__builtin_ia32_vfmaddph512_mask3:336 IID = Intrinsic::x86_avx512fp16_vfmadd_ph_512;337 break;338 case clang::X86::BI__builtin_ia32_vfmsubaddph512_mask3:339 Subtract = true;340 [[fallthrough]];341 case clang::X86::BI__builtin_ia32_vfmaddsubph512_mask:342 case clang::X86::BI__builtin_ia32_vfmaddsubph512_maskz:343 case clang::X86::BI__builtin_ia32_vfmaddsubph512_mask3:344 IID = Intrinsic::x86_avx512fp16_vfmaddsub_ph_512;345 break;346 case clang::X86::BI__builtin_ia32_vfmsubps512_mask3:347 Subtract = true;348 [[fallthrough]];349 case clang::X86::BI__builtin_ia32_vfmaddps512_mask:350 case clang::X86::BI__builtin_ia32_vfmaddps512_maskz:351 case clang::X86::BI__builtin_ia32_vfmaddps512_mask3:352 IID = Intrinsic::x86_avx512_vfmadd_ps_512; break;353 case clang::X86::BI__builtin_ia32_vfmsubpd512_mask3:354 Subtract = true;355 [[fallthrough]];356 case clang::X86::BI__builtin_ia32_vfmaddpd512_mask:357 case clang::X86::BI__builtin_ia32_vfmaddpd512_maskz:358 case clang::X86::BI__builtin_ia32_vfmaddpd512_mask3:359 IID = Intrinsic::x86_avx512_vfmadd_pd_512; break;360 case clang::X86::BI__builtin_ia32_vfmsubaddps512_mask3:361 Subtract = true;362 [[fallthrough]];363 case clang::X86::BI__builtin_ia32_vfmaddsubps512_mask:364 case clang::X86::BI__builtin_ia32_vfmaddsubps512_maskz:365 case clang::X86::BI__builtin_ia32_vfmaddsubps512_mask3:366 IID = Intrinsic::x86_avx512_vfmaddsub_ps_512;367 break;368 case clang::X86::BI__builtin_ia32_vfmsubaddpd512_mask3:369 Subtract = true;370 [[fallthrough]];371 case clang::X86::BI__builtin_ia32_vfmaddsubpd512_mask:372 case clang::X86::BI__builtin_ia32_vfmaddsubpd512_maskz:373 case clang::X86::BI__builtin_ia32_vfmaddsubpd512_mask3:374 IID = Intrinsic::x86_avx512_vfmaddsub_pd_512;375 break;376 }377 378 Value *A = Ops[0];379 Value *B = Ops[1];380 Value *C = Ops[2];381 382 if (Subtract)383 C = CGF.Builder.CreateFNeg(C);384 385 Value *Res;386 387 // Only handle in case of _MM_FROUND_CUR_DIRECTION/4 (no rounding).388 if (IID != Intrinsic::not_intrinsic &&389 (cast<llvm::ConstantInt>(Ops.back())->getZExtValue() != (uint64_t)4 ||390 IsAddSub)) {391 Function *Intr = CGF.CGM.getIntrinsic(IID);392 Res = CGF.Builder.CreateCall(Intr, {A, B, C, Ops.back() });393 } else {394 llvm::Type *Ty = A->getType();395 Function *FMA;396 if (CGF.Builder.getIsFPConstrained()) {397 CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);398 FMA = CGF.CGM.getIntrinsic(Intrinsic::experimental_constrained_fma, Ty);399 Res = CGF.Builder.CreateConstrainedFPCall(FMA, {A, B, C});400 } else {401 FMA = CGF.CGM.getIntrinsic(Intrinsic::fma, Ty);402 Res = CGF.Builder.CreateCall(FMA, {A, B, C});403 }404 }405 406 // Handle any required masking.407 Value *MaskFalseVal = nullptr;408 switch (BuiltinID) {409 case clang::X86::BI__builtin_ia32_vfmaddph512_mask:410 case clang::X86::BI__builtin_ia32_vfmaddps512_mask:411 case clang::X86::BI__builtin_ia32_vfmaddpd512_mask:412 case clang::X86::BI__builtin_ia32_vfmaddsubph512_mask:413 case clang::X86::BI__builtin_ia32_vfmaddsubps512_mask:414 case clang::X86::BI__builtin_ia32_vfmaddsubpd512_mask:415 MaskFalseVal = Ops[0];416 break;417 case clang::X86::BI__builtin_ia32_vfmaddph512_maskz:418 case clang::X86::BI__builtin_ia32_vfmaddps512_maskz:419 case clang::X86::BI__builtin_ia32_vfmaddpd512_maskz:420 case clang::X86::BI__builtin_ia32_vfmaddsubph512_maskz:421 case clang::X86::BI__builtin_ia32_vfmaddsubps512_maskz:422 case clang::X86::BI__builtin_ia32_vfmaddsubpd512_maskz:423 MaskFalseVal = Constant::getNullValue(Ops[0]->getType());424 break;425 case clang::X86::BI__builtin_ia32_vfmsubph512_mask3:426 case clang::X86::BI__builtin_ia32_vfmaddph512_mask3:427 case clang::X86::BI__builtin_ia32_vfmsubps512_mask3:428 case clang::X86::BI__builtin_ia32_vfmaddps512_mask3:429 case clang::X86::BI__builtin_ia32_vfmsubpd512_mask3:430 case clang::X86::BI__builtin_ia32_vfmaddpd512_mask3:431 case clang::X86::BI__builtin_ia32_vfmsubaddph512_mask3:432 case clang::X86::BI__builtin_ia32_vfmaddsubph512_mask3:433 case clang::X86::BI__builtin_ia32_vfmsubaddps512_mask3:434 case clang::X86::BI__builtin_ia32_vfmaddsubps512_mask3:435 case clang::X86::BI__builtin_ia32_vfmsubaddpd512_mask3:436 case clang::X86::BI__builtin_ia32_vfmaddsubpd512_mask3:437 MaskFalseVal = Ops[2];438 break;439 }440 441 if (MaskFalseVal)442 return EmitX86Select(CGF, Ops[3], Res, MaskFalseVal);443 444 return Res;445}446 447static Value *EmitScalarFMAExpr(CodeGenFunction &CGF, const CallExpr *E,448 MutableArrayRef<Value *> Ops, Value *Upper,449 bool ZeroMask = false, unsigned PTIdx = 0,450 bool NegAcc = false) {451 unsigned Rnd = 4;452 if (Ops.size() > 4)453 Rnd = cast<llvm::ConstantInt>(Ops[4])->getZExtValue();454 455 if (NegAcc)456 Ops[2] = CGF.Builder.CreateFNeg(Ops[2]);457 458 Ops[0] = CGF.Builder.CreateExtractElement(Ops[0], (uint64_t)0);459 Ops[1] = CGF.Builder.CreateExtractElement(Ops[1], (uint64_t)0);460 Ops[2] = CGF.Builder.CreateExtractElement(Ops[2], (uint64_t)0);461 Value *Res;462 if (Rnd != 4) {463 Intrinsic::ID IID;464 465 switch (Ops[0]->getType()->getPrimitiveSizeInBits()) {466 case 16:467 IID = Intrinsic::x86_avx512fp16_vfmadd_f16;468 break;469 case 32:470 IID = Intrinsic::x86_avx512_vfmadd_f32;471 break;472 case 64:473 IID = Intrinsic::x86_avx512_vfmadd_f64;474 break;475 default:476 llvm_unreachable("Unexpected size");477 }478 Res = CGF.Builder.CreateCall(CGF.CGM.getIntrinsic(IID),479 {Ops[0], Ops[1], Ops[2], Ops[4]});480 } else if (CGF.Builder.getIsFPConstrained()) {481 CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);482 Function *FMA = CGF.CGM.getIntrinsic(483 Intrinsic::experimental_constrained_fma, Ops[0]->getType());484 Res = CGF.Builder.CreateConstrainedFPCall(FMA, Ops.slice(0, 3));485 } else {486 Function *FMA = CGF.CGM.getIntrinsic(Intrinsic::fma, Ops[0]->getType());487 Res = CGF.Builder.CreateCall(FMA, Ops.slice(0, 3));488 }489 // If we have more than 3 arguments, we need to do masking.490 if (Ops.size() > 3) {491 Value *PassThru = ZeroMask ? Constant::getNullValue(Res->getType())492 : Ops[PTIdx];493 494 // If we negated the accumulator and the its the PassThru value we need to495 // bypass the negate. Conveniently Upper should be the same thing in this496 // case.497 if (NegAcc && PTIdx == 2)498 PassThru = CGF.Builder.CreateExtractElement(Upper, (uint64_t)0);499 500 Res = EmitX86ScalarSelect(CGF, Ops[3], Res, PassThru);501 }502 return CGF.Builder.CreateInsertElement(Upper, Res, (uint64_t)0);503}504 505static Value *EmitX86Muldq(CodeGenFunction &CGF, bool IsSigned,506 ArrayRef<Value *> Ops) {507 llvm::Type *Ty = Ops[0]->getType();508 // Arguments have a vXi32 type so cast to vXi64.509 Ty = llvm::FixedVectorType::get(CGF.Int64Ty,510 Ty->getPrimitiveSizeInBits() / 64);511 Value *LHS = CGF.Builder.CreateBitCast(Ops[0], Ty);512 Value *RHS = CGF.Builder.CreateBitCast(Ops[1], Ty);513 514 if (IsSigned) {515 // Shift left then arithmetic shift right.516 Constant *ShiftAmt = ConstantInt::get(Ty, 32);517 LHS = CGF.Builder.CreateShl(LHS, ShiftAmt);518 LHS = CGF.Builder.CreateAShr(LHS, ShiftAmt);519 RHS = CGF.Builder.CreateShl(RHS, ShiftAmt);520 RHS = CGF.Builder.CreateAShr(RHS, ShiftAmt);521 } else {522 // Clear the upper bits.523 Constant *Mask = ConstantInt::get(Ty, 0xffffffff);524 LHS = CGF.Builder.CreateAnd(LHS, Mask);525 RHS = CGF.Builder.CreateAnd(RHS, Mask);526 }527 528 return CGF.Builder.CreateMul(LHS, RHS);529}530 531// Emit a masked pternlog intrinsic. This only exists because the header has to532// use a macro and we aren't able to pass the input argument to a pternlog533// builtin and a select builtin without evaluating it twice.534static Value *EmitX86Ternlog(CodeGenFunction &CGF, bool ZeroMask,535 ArrayRef<Value *> Ops) {536 llvm::Type *Ty = Ops[0]->getType();537 538 unsigned VecWidth = Ty->getPrimitiveSizeInBits();539 unsigned EltWidth = Ty->getScalarSizeInBits();540 Intrinsic::ID IID;541 if (VecWidth == 128 && EltWidth == 32)542 IID = Intrinsic::x86_avx512_pternlog_d_128;543 else if (VecWidth == 256 && EltWidth == 32)544 IID = Intrinsic::x86_avx512_pternlog_d_256;545 else if (VecWidth == 512 && EltWidth == 32)546 IID = Intrinsic::x86_avx512_pternlog_d_512;547 else if (VecWidth == 128 && EltWidth == 64)548 IID = Intrinsic::x86_avx512_pternlog_q_128;549 else if (VecWidth == 256 && EltWidth == 64)550 IID = Intrinsic::x86_avx512_pternlog_q_256;551 else if (VecWidth == 512 && EltWidth == 64)552 IID = Intrinsic::x86_avx512_pternlog_q_512;553 else554 llvm_unreachable("Unexpected intrinsic");555 556 Value *Ternlog = CGF.Builder.CreateCall(CGF.CGM.getIntrinsic(IID),557 Ops.drop_back());558 Value *PassThru = ZeroMask ? ConstantAggregateZero::get(Ty) : Ops[0];559 return EmitX86Select(CGF, Ops[4], Ternlog, PassThru);560}561 562static Value *EmitX86SExtMask(CodeGenFunction &CGF, Value *Op,563 llvm::Type *DstTy) {564 unsigned NumberOfElements =565 cast<llvm::FixedVectorType>(DstTy)->getNumElements();566 Value *Mask = getMaskVecValue(CGF, Op, NumberOfElements);567 return CGF.Builder.CreateSExt(Mask, DstTy, "vpmovm2");568}569 570Value *CodeGenFunction::EmitX86CpuIs(const CallExpr *E) {571 const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts();572 StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString();573 return EmitX86CpuIs(CPUStr);574}575 576// Convert F16 halfs to floats.577static Value *EmitX86CvtF16ToFloatExpr(CodeGenFunction &CGF,578 ArrayRef<Value *> Ops,579 llvm::Type *DstTy) {580 assert((Ops.size() == 1 || Ops.size() == 3 || Ops.size() == 4) &&581 "Unknown cvtph2ps intrinsic");582 583 // If the SAE intrinsic doesn't use default rounding then we can't upgrade.584 if (Ops.size() == 4 && cast<llvm::ConstantInt>(Ops[3])->getZExtValue() != 4) {585 Function *F =586 CGF.CGM.getIntrinsic(Intrinsic::x86_avx512_mask_vcvtph2ps_512);587 return CGF.Builder.CreateCall(F, {Ops[0], Ops[1], Ops[2], Ops[3]});588 }589 590 unsigned NumDstElts = cast<llvm::FixedVectorType>(DstTy)->getNumElements();591 Value *Src = Ops[0];592 593 // Extract the subvector.594 if (NumDstElts !=595 cast<llvm::FixedVectorType>(Src->getType())->getNumElements()) {596 assert(NumDstElts == 4 && "Unexpected vector size");597 Src = CGF.Builder.CreateShuffleVector(Src, {0, 1, 2, 3});598 }599 600 // Bitcast from vXi16 to vXf16.601 auto *HalfTy = llvm::FixedVectorType::get(602 llvm::Type::getHalfTy(CGF.getLLVMContext()), NumDstElts);603 Src = CGF.Builder.CreateBitCast(Src, HalfTy);604 605 // Perform the fp-extension.606 Value *Res = CGF.Builder.CreateFPExt(Src, DstTy, "cvtph2ps");607 608 if (Ops.size() >= 3)609 Res = EmitX86Select(CGF, Ops[2], Res, Ops[1]);610 return Res;611}612 613Value *CodeGenFunction::EmitX86CpuIs(StringRef CPUStr) {614 615 llvm::Type *Int32Ty = Builder.getInt32Ty();616 617 // Matching the struct layout from the compiler-rt/libgcc structure that is618 // filled in:619 // unsigned int __cpu_vendor;620 // unsigned int __cpu_type;621 // unsigned int __cpu_subtype;622 // unsigned int __cpu_features[1];623 llvm::Type *STy = llvm::StructType::get(Int32Ty, Int32Ty, Int32Ty,624 llvm::ArrayType::get(Int32Ty, 1));625 626 // Grab the global __cpu_model.627 llvm::Constant *CpuModel = CGM.CreateRuntimeVariable(STy, "__cpu_model");628 cast<llvm::GlobalValue>(CpuModel)->setDSOLocal(true);629 630 // Calculate the index needed to access the correct field based on the631 // range. Also adjust the expected value.632 auto [Index, Value] = StringSwitch<std::pair<unsigned, unsigned>>(CPUStr)633#define X86_VENDOR(ENUM, STRING) \634 .Case(STRING, {0u, static_cast<unsigned>(llvm::X86::ENUM)})635#define X86_CPU_TYPE_ALIAS(ENUM, ALIAS) \636 .Case(ALIAS, {1u, static_cast<unsigned>(llvm::X86::ENUM)})637#define X86_CPU_TYPE(ENUM, STR) \638 .Case(STR, {1u, static_cast<unsigned>(llvm::X86::ENUM)})639#define X86_CPU_SUBTYPE_ALIAS(ENUM, ALIAS) \640 .Case(ALIAS, {2u, static_cast<unsigned>(llvm::X86::ENUM)})641#define X86_CPU_SUBTYPE(ENUM, STR) \642 .Case(STR, {2u, static_cast<unsigned>(llvm::X86::ENUM)})643#include "llvm/TargetParser/X86TargetParser.def"644 .Default({0, 0});645 assert(Value != 0 && "Invalid CPUStr passed to CpuIs");646 647 // Grab the appropriate field from __cpu_model.648 llvm::Value *Idxs[] = {ConstantInt::get(Int32Ty, 0),649 ConstantInt::get(Int32Ty, Index)};650 llvm::Value *CpuValue = Builder.CreateInBoundsGEP(STy, CpuModel, Idxs);651 CpuValue = Builder.CreateAlignedLoad(Int32Ty, CpuValue,652 CharUnits::fromQuantity(4));653 654 // Check the value of the field against the requested value.655 return Builder.CreateICmpEQ(CpuValue,656 llvm::ConstantInt::get(Int32Ty, Value));657}658 659Value *CodeGenFunction::EmitX86CpuSupports(const CallExpr *E) {660 const Expr *FeatureExpr = E->getArg(0)->IgnoreParenCasts();661 StringRef FeatureStr = cast<StringLiteral>(FeatureExpr)->getString();662 if (!getContext().getTargetInfo().validateCpuSupports(FeatureStr))663 return Builder.getFalse();664 return EmitX86CpuSupports(FeatureStr);665}666 667Value *CodeGenFunction::EmitX86CpuSupports(ArrayRef<StringRef> FeatureStrs) {668 return EmitX86CpuSupports(llvm::X86::getCpuSupportsMask(FeatureStrs));669}670 671llvm::Value *672CodeGenFunction::EmitX86CpuSupports(std::array<uint32_t, 4> FeatureMask) {673 Value *Result = Builder.getTrue();674 if (FeatureMask[0] != 0) {675 // Matching the struct layout from the compiler-rt/libgcc structure that is676 // filled in:677 // unsigned int __cpu_vendor;678 // unsigned int __cpu_type;679 // unsigned int __cpu_subtype;680 // unsigned int __cpu_features[1];681 llvm::Type *STy = llvm::StructType::get(Int32Ty, Int32Ty, Int32Ty,682 llvm::ArrayType::get(Int32Ty, 1));683 684 // Grab the global __cpu_model.685 llvm::Constant *CpuModel = CGM.CreateRuntimeVariable(STy, "__cpu_model");686 cast<llvm::GlobalValue>(CpuModel)->setDSOLocal(true);687 688 // Grab the first (0th) element from the field __cpu_features off of the689 // global in the struct STy.690 Value *Idxs[] = {Builder.getInt32(0), Builder.getInt32(3),691 Builder.getInt32(0)};692 Value *CpuFeatures = Builder.CreateInBoundsGEP(STy, CpuModel, Idxs);693 Value *Features = Builder.CreateAlignedLoad(Int32Ty, CpuFeatures,694 CharUnits::fromQuantity(4));695 696 // Check the value of the bit corresponding to the feature requested.697 Value *Mask = Builder.getInt32(FeatureMask[0]);698 Value *Bitset = Builder.CreateAnd(Features, Mask);699 Value *Cmp = Builder.CreateICmpEQ(Bitset, Mask);700 Result = Builder.CreateAnd(Result, Cmp);701 }702 703 llvm::Type *ATy = llvm::ArrayType::get(Int32Ty, 3);704 llvm::Constant *CpuFeatures2 =705 CGM.CreateRuntimeVariable(ATy, "__cpu_features2");706 cast<llvm::GlobalValue>(CpuFeatures2)->setDSOLocal(true);707 for (int i = 1; i != 4; ++i) {708 const uint32_t M = FeatureMask[i];709 if (!M)710 continue;711 Value *Idxs[] = {Builder.getInt32(0), Builder.getInt32(i - 1)};712 Value *Features = Builder.CreateAlignedLoad(713 Int32Ty, Builder.CreateInBoundsGEP(ATy, CpuFeatures2, Idxs),714 CharUnits::fromQuantity(4));715 // Check the value of the bit corresponding to the feature requested.716 Value *Mask = Builder.getInt32(M);717 Value *Bitset = Builder.CreateAnd(Features, Mask);718 Value *Cmp = Builder.CreateICmpEQ(Bitset, Mask);719 Result = Builder.CreateAnd(Result, Cmp);720 }721 722 return Result;723}724 725Value *CodeGenFunction::EmitX86CpuInit() {726 llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy,727 /*Variadic*/ false);728 llvm::FunctionCallee Func =729 CGM.CreateRuntimeFunction(FTy, "__cpu_indicator_init");730 cast<llvm::GlobalValue>(Func.getCallee())->setDSOLocal(true);731 cast<llvm::GlobalValue>(Func.getCallee())732 ->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);733 return Builder.CreateCall(Func);734}735 736 737Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,738 const CallExpr *E) {739 if (BuiltinID == Builtin::BI__builtin_cpu_is)740 return EmitX86CpuIs(E);741 if (BuiltinID == Builtin::BI__builtin_cpu_supports)742 return EmitX86CpuSupports(E);743 if (BuiltinID == Builtin::BI__builtin_cpu_init)744 return EmitX86CpuInit();745 746 // Handle MSVC intrinsics before argument evaluation to prevent double747 // evaluation.748 if (std::optional<MSVCIntrin> MsvcIntId = translateX86ToMsvcIntrin(BuiltinID))749 return EmitMSVCBuiltinExpr(*MsvcIntId, E);750 751 SmallVector<Value*, 4> Ops;752 bool IsMaskFCmp = false;753 bool IsConjFMA = false;754 755 // Find out if any arguments are required to be integer constant expressions.756 unsigned ICEArguments = 0;757 ASTContext::GetBuiltinTypeError Error;758 getContext().GetBuiltinType(BuiltinID, Error, &ICEArguments);759 assert(Error == ASTContext::GE_None && "Should not codegen an error");760 761 for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) {762 Ops.push_back(EmitScalarOrConstFoldImmArg(ICEArguments, i, E));763 }764 765 // These exist so that the builtin that takes an immediate can be bounds766 // checked by clang to avoid passing bad immediates to the backend. Since767 // AVX has a larger immediate than SSE we would need separate builtins to768 // do the different bounds checking. Rather than create a clang specific769 // SSE only builtin, this implements eight separate builtins to match gcc770 // implementation.771 auto getCmpIntrinsicCall = [this, &Ops](Intrinsic::ID ID, unsigned Imm) {772 Ops.push_back(llvm::ConstantInt::get(Int8Ty, Imm));773 llvm::Function *F = CGM.getIntrinsic(ID);774 return Builder.CreateCall(F, Ops);775 };776 777 // For the vector forms of FP comparisons, translate the builtins directly to778 // IR.779 // TODO: The builtins could be removed if the SSE header files used vector780 // extension comparisons directly (vector ordered/unordered may need781 // additional support via __builtin_isnan()).782 auto getVectorFCmpIR = [this, &Ops, E](CmpInst::Predicate Pred,783 bool IsSignaling) {784 CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);785 Value *Cmp;786 if (IsSignaling)787 Cmp = Builder.CreateFCmpS(Pred, Ops[0], Ops[1]);788 else789 Cmp = Builder.CreateFCmp(Pred, Ops[0], Ops[1]);790 llvm::VectorType *FPVecTy = cast<llvm::VectorType>(Ops[0]->getType());791 llvm::VectorType *IntVecTy = llvm::VectorType::getInteger(FPVecTy);792 Value *Sext = Builder.CreateSExt(Cmp, IntVecTy);793 return Builder.CreateBitCast(Sext, FPVecTy);794 };795 796 switch (BuiltinID) {797 default: return nullptr;798 case X86::BI_mm_prefetch: {799 Value *Address = Ops[0];800 ConstantInt *C = cast<ConstantInt>(Ops[1]);801 Value *RW = ConstantInt::get(Int32Ty, (C->getZExtValue() >> 2) & 0x1);802 Value *Locality = ConstantInt::get(Int32Ty, C->getZExtValue() & 0x3);803 Value *Data = ConstantInt::get(Int32Ty, 1);804 Function *F = CGM.getIntrinsic(Intrinsic::prefetch, Address->getType());805 return Builder.CreateCall(F, {Address, RW, Locality, Data});806 }807 case X86::BI_m_prefetch:808 case X86::BI_m_prefetchw: {809 Value *Address = Ops[0];810 // The 'w' suffix implies write.811 Value *RW =812 ConstantInt::get(Int32Ty, BuiltinID == X86::BI_m_prefetchw ? 1 : 0);813 Value *Locality = ConstantInt::get(Int32Ty, 0x3);814 Value *Data = ConstantInt::get(Int32Ty, 1);815 Function *F = CGM.getIntrinsic(Intrinsic::prefetch, Address->getType());816 return Builder.CreateCall(F, {Address, RW, Locality, Data});817 }818 case X86::BI_mm_clflush: {819 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse2_clflush),820 Ops[0]);821 }822 case X86::BI_mm_lfence: {823 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse2_lfence));824 }825 case X86::BI_mm_mfence: {826 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse2_mfence));827 }828 case X86::BI_mm_sfence: {829 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_sfence));830 }831 case X86::BI_mm_pause: {832 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse2_pause));833 }834 case X86::BI__rdtsc: {835 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_rdtsc));836 }837 case X86::BI__builtin_ia32_rdtscp: {838 Value *Call = Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_rdtscp));839 Builder.CreateDefaultAlignedStore(Builder.CreateExtractValue(Call, 1),840 Ops[0]);841 return Builder.CreateExtractValue(Call, 0);842 }843 case X86::BI__builtin_ia32_lzcnt_u16:844 case X86::BI__builtin_ia32_lzcnt_u32:845 case X86::BI__builtin_ia32_lzcnt_u64: {846 Function *F = CGM.getIntrinsic(Intrinsic::ctlz, Ops[0]->getType());847 return Builder.CreateCall(F, {Ops[0], Builder.getInt1(false)});848 }849 case X86::BI__builtin_ia32_tzcnt_u16:850 case X86::BI__builtin_ia32_tzcnt_u32:851 case X86::BI__builtin_ia32_tzcnt_u64: {852 Function *F = CGM.getIntrinsic(Intrinsic::cttz, Ops[0]->getType());853 return Builder.CreateCall(F, {Ops[0], Builder.getInt1(false)});854 }855 case X86::BI__builtin_ia32_undef128:856 case X86::BI__builtin_ia32_undef256:857 case X86::BI__builtin_ia32_undef512:858 // The x86 definition of "undef" is not the same as the LLVM definition859 // (PR32176). We leave optimizing away an unnecessary zero constant to the860 // IR optimizer and backend.861 // TODO: If we had a "freeze" IR instruction to generate a fixed undef862 // value, we should use that here instead of a zero.863 return llvm::Constant::getNullValue(ConvertType(E->getType()));864 case X86::BI__builtin_ia32_vec_ext_v4hi:865 case X86::BI__builtin_ia32_vec_ext_v16qi:866 case X86::BI__builtin_ia32_vec_ext_v8hi:867 case X86::BI__builtin_ia32_vec_ext_v4si:868 case X86::BI__builtin_ia32_vec_ext_v4sf:869 case X86::BI__builtin_ia32_vec_ext_v2di:870 case X86::BI__builtin_ia32_vec_ext_v32qi:871 case X86::BI__builtin_ia32_vec_ext_v16hi:872 case X86::BI__builtin_ia32_vec_ext_v8si:873 case X86::BI__builtin_ia32_vec_ext_v4di: {874 unsigned NumElts =875 cast<llvm::FixedVectorType>(Ops[0]->getType())->getNumElements();876 uint64_t Index = cast<ConstantInt>(Ops[1])->getZExtValue();877 Index &= NumElts - 1;878 // These builtins exist so we can ensure the index is an ICE and in range.879 // Otherwise we could just do this in the header file.880 return Builder.CreateExtractElement(Ops[0], Index);881 }882 case X86::BI__builtin_ia32_vec_set_v4hi:883 case X86::BI__builtin_ia32_vec_set_v16qi:884 case X86::BI__builtin_ia32_vec_set_v8hi:885 case X86::BI__builtin_ia32_vec_set_v4si:886 case X86::BI__builtin_ia32_vec_set_v2di:887 case X86::BI__builtin_ia32_vec_set_v32qi:888 case X86::BI__builtin_ia32_vec_set_v16hi:889 case X86::BI__builtin_ia32_vec_set_v8si:890 case X86::BI__builtin_ia32_vec_set_v4di: {891 unsigned NumElts =892 cast<llvm::FixedVectorType>(Ops[0]->getType())->getNumElements();893 unsigned Index = cast<ConstantInt>(Ops[2])->getZExtValue();894 Index &= NumElts - 1;895 // These builtins exist so we can ensure the index is an ICE and in range.896 // Otherwise we could just do this in the header file.897 return Builder.CreateInsertElement(Ops[0], Ops[1], Index);898 }899 case X86::BI_mm_setcsr:900 case X86::BI__builtin_ia32_ldmxcsr: {901 RawAddress Tmp = CreateMemTemp(E->getArg(0)->getType());902 Builder.CreateStore(Ops[0], Tmp);903 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_ldmxcsr),904 Tmp.getPointer());905 }906 case X86::BI_mm_getcsr:907 case X86::BI__builtin_ia32_stmxcsr: {908 RawAddress Tmp = CreateMemTemp(E->getType());909 Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_stmxcsr),910 Tmp.getPointer());911 return Builder.CreateLoad(Tmp, "stmxcsr");912 }913 case X86::BI__builtin_ia32_xsave:914 case X86::BI__builtin_ia32_xsave64:915 case X86::BI__builtin_ia32_xrstor:916 case X86::BI__builtin_ia32_xrstor64:917 case X86::BI__builtin_ia32_xsaveopt:918 case X86::BI__builtin_ia32_xsaveopt64:919 case X86::BI__builtin_ia32_xrstors:920 case X86::BI__builtin_ia32_xrstors64:921 case X86::BI__builtin_ia32_xsavec:922 case X86::BI__builtin_ia32_xsavec64:923 case X86::BI__builtin_ia32_xsaves:924 case X86::BI__builtin_ia32_xsaves64:925 case X86::BI__builtin_ia32_xsetbv:926 case X86::BI_xsetbv: {927 Intrinsic::ID ID;928#define INTRINSIC_X86_XSAVE_ID(NAME) \929 case X86::BI__builtin_ia32_##NAME: \930 ID = Intrinsic::x86_##NAME; \931 break932 switch (BuiltinID) {933 default: llvm_unreachable("Unsupported intrinsic!");934 INTRINSIC_X86_XSAVE_ID(xsave);935 INTRINSIC_X86_XSAVE_ID(xsave64);936 INTRINSIC_X86_XSAVE_ID(xrstor);937 INTRINSIC_X86_XSAVE_ID(xrstor64);938 INTRINSIC_X86_XSAVE_ID(xsaveopt);939 INTRINSIC_X86_XSAVE_ID(xsaveopt64);940 INTRINSIC_X86_XSAVE_ID(xrstors);941 INTRINSIC_X86_XSAVE_ID(xrstors64);942 INTRINSIC_X86_XSAVE_ID(xsavec);943 INTRINSIC_X86_XSAVE_ID(xsavec64);944 INTRINSIC_X86_XSAVE_ID(xsaves);945 INTRINSIC_X86_XSAVE_ID(xsaves64);946 INTRINSIC_X86_XSAVE_ID(xsetbv);947 case X86::BI_xsetbv:948 ID = Intrinsic::x86_xsetbv;949 break;950 }951#undef INTRINSIC_X86_XSAVE_ID952 Value *Mhi = Builder.CreateTrunc(953 Builder.CreateLShr(Ops[1], ConstantInt::get(Int64Ty, 32)), Int32Ty);954 Value *Mlo = Builder.CreateTrunc(Ops[1], Int32Ty);955 Ops[1] = Mhi;956 Ops.push_back(Mlo);957 return Builder.CreateCall(CGM.getIntrinsic(ID), Ops);958 }959 case X86::BI__builtin_ia32_xgetbv:960 case X86::BI_xgetbv:961 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_xgetbv), Ops);962 case X86::BI__builtin_ia32_storedqudi128_mask:963 case X86::BI__builtin_ia32_storedqusi128_mask:964 case X86::BI__builtin_ia32_storedquhi128_mask:965 case X86::BI__builtin_ia32_storedquqi128_mask:966 case X86::BI__builtin_ia32_storeupd128_mask:967 case X86::BI__builtin_ia32_storeups128_mask:968 case X86::BI__builtin_ia32_storedqudi256_mask:969 case X86::BI__builtin_ia32_storedqusi256_mask:970 case X86::BI__builtin_ia32_storedquhi256_mask:971 case X86::BI__builtin_ia32_storedquqi256_mask:972 case X86::BI__builtin_ia32_storeupd256_mask:973 case X86::BI__builtin_ia32_storeups256_mask:974 case X86::BI__builtin_ia32_storedqudi512_mask:975 case X86::BI__builtin_ia32_storedqusi512_mask:976 case X86::BI__builtin_ia32_storedquhi512_mask:977 case X86::BI__builtin_ia32_storedquqi512_mask:978 case X86::BI__builtin_ia32_storeupd512_mask:979 case X86::BI__builtin_ia32_storeups512_mask:980 return EmitX86MaskedStore(*this, Ops, Align(1));981 982 case X86::BI__builtin_ia32_storesbf16128_mask:983 case X86::BI__builtin_ia32_storesh128_mask:984 case X86::BI__builtin_ia32_storess128_mask:985 case X86::BI__builtin_ia32_storesd128_mask:986 return EmitX86MaskedStore(*this, Ops, Align(1));987 988 case X86::BI__builtin_ia32_cvtmask2b128:989 case X86::BI__builtin_ia32_cvtmask2b256:990 case X86::BI__builtin_ia32_cvtmask2b512:991 case X86::BI__builtin_ia32_cvtmask2w128:992 case X86::BI__builtin_ia32_cvtmask2w256:993 case X86::BI__builtin_ia32_cvtmask2w512:994 case X86::BI__builtin_ia32_cvtmask2d128:995 case X86::BI__builtin_ia32_cvtmask2d256:996 case X86::BI__builtin_ia32_cvtmask2d512:997 case X86::BI__builtin_ia32_cvtmask2q128:998 case X86::BI__builtin_ia32_cvtmask2q256:999 case X86::BI__builtin_ia32_cvtmask2q512:1000 return EmitX86SExtMask(*this, Ops[0], ConvertType(E->getType()));1001 1002 case X86::BI__builtin_ia32_cvtb2mask128:1003 case X86::BI__builtin_ia32_cvtb2mask256:1004 case X86::BI__builtin_ia32_cvtb2mask512:1005 case X86::BI__builtin_ia32_cvtw2mask128:1006 case X86::BI__builtin_ia32_cvtw2mask256:1007 case X86::BI__builtin_ia32_cvtw2mask512:1008 case X86::BI__builtin_ia32_cvtd2mask128:1009 case X86::BI__builtin_ia32_cvtd2mask256:1010 case X86::BI__builtin_ia32_cvtd2mask512:1011 case X86::BI__builtin_ia32_cvtq2mask128:1012 case X86::BI__builtin_ia32_cvtq2mask256:1013 case X86::BI__builtin_ia32_cvtq2mask512:1014 return EmitX86ConvertToMask(*this, Ops[0]);1015 1016 case X86::BI__builtin_ia32_cvtdq2ps512_mask:1017 case X86::BI__builtin_ia32_cvtqq2ps512_mask:1018 case X86::BI__builtin_ia32_cvtqq2pd512_mask:1019 case X86::BI__builtin_ia32_vcvtw2ph512_mask:1020 case X86::BI__builtin_ia32_vcvtdq2ph512_mask:1021 case X86::BI__builtin_ia32_vcvtqq2ph512_mask:1022 return EmitX86ConvertIntToFp(*this, E, Ops, /*IsSigned*/ true);1023 case X86::BI__builtin_ia32_cvtudq2ps512_mask:1024 case X86::BI__builtin_ia32_cvtuqq2ps512_mask:1025 case X86::BI__builtin_ia32_cvtuqq2pd512_mask:1026 case X86::BI__builtin_ia32_vcvtuw2ph512_mask:1027 case X86::BI__builtin_ia32_vcvtudq2ph512_mask:1028 case X86::BI__builtin_ia32_vcvtuqq2ph512_mask:1029 return EmitX86ConvertIntToFp(*this, E, Ops, /*IsSigned*/ false);1030 1031 case X86::BI__builtin_ia32_vfmaddsh3_mask:1032 case X86::BI__builtin_ia32_vfmaddss3_mask:1033 case X86::BI__builtin_ia32_vfmaddsd3_mask:1034 return EmitScalarFMAExpr(*this, E, Ops, Ops[0]);1035 case X86::BI__builtin_ia32_vfmaddsh3_maskz:1036 case X86::BI__builtin_ia32_vfmaddss3_maskz:1037 case X86::BI__builtin_ia32_vfmaddsd3_maskz:1038 return EmitScalarFMAExpr(*this, E, Ops, Ops[0], /*ZeroMask*/ true);1039 case X86::BI__builtin_ia32_vfmaddsh3_mask3:1040 case X86::BI__builtin_ia32_vfmaddss3_mask3:1041 case X86::BI__builtin_ia32_vfmaddsd3_mask3:1042 return EmitScalarFMAExpr(*this, E, Ops, Ops[2], /*ZeroMask*/ false, 2);1043 case X86::BI__builtin_ia32_vfmsubsh3_mask3:1044 case X86::BI__builtin_ia32_vfmsubss3_mask3:1045 case X86::BI__builtin_ia32_vfmsubsd3_mask3:1046 return EmitScalarFMAExpr(*this, E, Ops, Ops[2], /*ZeroMask*/ false, 2,1047 /*NegAcc*/ true);1048 case X86::BI__builtin_ia32_vfmaddph512_mask:1049 case X86::BI__builtin_ia32_vfmaddph512_maskz:1050 case X86::BI__builtin_ia32_vfmaddph512_mask3:1051 case X86::BI__builtin_ia32_vfmaddps512_mask:1052 case X86::BI__builtin_ia32_vfmaddps512_maskz:1053 case X86::BI__builtin_ia32_vfmaddps512_mask3:1054 case X86::BI__builtin_ia32_vfmsubps512_mask3:1055 case X86::BI__builtin_ia32_vfmaddpd512_mask:1056 case X86::BI__builtin_ia32_vfmaddpd512_maskz:1057 case X86::BI__builtin_ia32_vfmaddpd512_mask3:1058 case X86::BI__builtin_ia32_vfmsubpd512_mask3:1059 case X86::BI__builtin_ia32_vfmsubph512_mask3:1060 return EmitX86FMAExpr(*this, E, Ops, BuiltinID, /*IsAddSub*/ false);1061 case X86::BI__builtin_ia32_vfmaddsubph512_mask:1062 case X86::BI__builtin_ia32_vfmaddsubph512_maskz:1063 case X86::BI__builtin_ia32_vfmaddsubph512_mask3:1064 case X86::BI__builtin_ia32_vfmsubaddph512_mask3:1065 case X86::BI__builtin_ia32_vfmaddsubps512_mask:1066 case X86::BI__builtin_ia32_vfmaddsubps512_maskz:1067 case X86::BI__builtin_ia32_vfmaddsubps512_mask3:1068 case X86::BI__builtin_ia32_vfmsubaddps512_mask3:1069 case X86::BI__builtin_ia32_vfmaddsubpd512_mask:1070 case X86::BI__builtin_ia32_vfmaddsubpd512_maskz:1071 case X86::BI__builtin_ia32_vfmaddsubpd512_mask3:1072 case X86::BI__builtin_ia32_vfmsubaddpd512_mask3:1073 return EmitX86FMAExpr(*this, E, Ops, BuiltinID, /*IsAddSub*/ true);1074 1075 case X86::BI__builtin_ia32_movdqa32store128_mask:1076 case X86::BI__builtin_ia32_movdqa64store128_mask:1077 case X86::BI__builtin_ia32_storeaps128_mask:1078 case X86::BI__builtin_ia32_storeapd128_mask:1079 case X86::BI__builtin_ia32_movdqa32store256_mask:1080 case X86::BI__builtin_ia32_movdqa64store256_mask:1081 case X86::BI__builtin_ia32_storeaps256_mask:1082 case X86::BI__builtin_ia32_storeapd256_mask:1083 case X86::BI__builtin_ia32_movdqa32store512_mask:1084 case X86::BI__builtin_ia32_movdqa64store512_mask:1085 case X86::BI__builtin_ia32_storeaps512_mask:1086 case X86::BI__builtin_ia32_storeapd512_mask:1087 return EmitX86MaskedStore(1088 *this, Ops,1089 getContext().getTypeAlignInChars(E->getArg(1)->getType()).getAsAlign());1090 1091 case X86::BI__builtin_ia32_loadups128_mask:1092 case X86::BI__builtin_ia32_loadups256_mask:1093 case X86::BI__builtin_ia32_loadups512_mask:1094 case X86::BI__builtin_ia32_loadupd128_mask:1095 case X86::BI__builtin_ia32_loadupd256_mask:1096 case X86::BI__builtin_ia32_loadupd512_mask:1097 case X86::BI__builtin_ia32_loaddquqi128_mask:1098 case X86::BI__builtin_ia32_loaddquqi256_mask:1099 case X86::BI__builtin_ia32_loaddquqi512_mask:1100 case X86::BI__builtin_ia32_loaddquhi128_mask:1101 case X86::BI__builtin_ia32_loaddquhi256_mask:1102 case X86::BI__builtin_ia32_loaddquhi512_mask:1103 case X86::BI__builtin_ia32_loaddqusi128_mask:1104 case X86::BI__builtin_ia32_loaddqusi256_mask:1105 case X86::BI__builtin_ia32_loaddqusi512_mask:1106 case X86::BI__builtin_ia32_loaddqudi128_mask:1107 case X86::BI__builtin_ia32_loaddqudi256_mask:1108 case X86::BI__builtin_ia32_loaddqudi512_mask:1109 return EmitX86MaskedLoad(*this, Ops, Align(1));1110 1111 case X86::BI__builtin_ia32_loadsbf16128_mask:1112 case X86::BI__builtin_ia32_loadsh128_mask:1113 case X86::BI__builtin_ia32_loadss128_mask:1114 case X86::BI__builtin_ia32_loadsd128_mask:1115 return EmitX86MaskedLoad(*this, Ops, Align(1));1116 1117 case X86::BI__builtin_ia32_loadaps128_mask:1118 case X86::BI__builtin_ia32_loadaps256_mask:1119 case X86::BI__builtin_ia32_loadaps512_mask:1120 case X86::BI__builtin_ia32_loadapd128_mask:1121 case X86::BI__builtin_ia32_loadapd256_mask:1122 case X86::BI__builtin_ia32_loadapd512_mask:1123 case X86::BI__builtin_ia32_movdqa32load128_mask:1124 case X86::BI__builtin_ia32_movdqa32load256_mask:1125 case X86::BI__builtin_ia32_movdqa32load512_mask:1126 case X86::BI__builtin_ia32_movdqa64load128_mask:1127 case X86::BI__builtin_ia32_movdqa64load256_mask:1128 case X86::BI__builtin_ia32_movdqa64load512_mask:1129 return EmitX86MaskedLoad(1130 *this, Ops,1131 getContext().getTypeAlignInChars(E->getArg(1)->getType()).getAsAlign());1132 1133 case X86::BI__builtin_ia32_expandloaddf128_mask:1134 case X86::BI__builtin_ia32_expandloaddf256_mask:1135 case X86::BI__builtin_ia32_expandloaddf512_mask:1136 case X86::BI__builtin_ia32_expandloadsf128_mask:1137 case X86::BI__builtin_ia32_expandloadsf256_mask:1138 case X86::BI__builtin_ia32_expandloadsf512_mask:1139 case X86::BI__builtin_ia32_expandloaddi128_mask:1140 case X86::BI__builtin_ia32_expandloaddi256_mask:1141 case X86::BI__builtin_ia32_expandloaddi512_mask:1142 case X86::BI__builtin_ia32_expandloadsi128_mask:1143 case X86::BI__builtin_ia32_expandloadsi256_mask:1144 case X86::BI__builtin_ia32_expandloadsi512_mask:1145 case X86::BI__builtin_ia32_expandloadhi128_mask:1146 case X86::BI__builtin_ia32_expandloadhi256_mask:1147 case X86::BI__builtin_ia32_expandloadhi512_mask:1148 case X86::BI__builtin_ia32_expandloadqi128_mask:1149 case X86::BI__builtin_ia32_expandloadqi256_mask:1150 case X86::BI__builtin_ia32_expandloadqi512_mask:1151 return EmitX86ExpandLoad(*this, Ops);1152 1153 case X86::BI__builtin_ia32_compressstoredf128_mask:1154 case X86::BI__builtin_ia32_compressstoredf256_mask:1155 case X86::BI__builtin_ia32_compressstoredf512_mask:1156 case X86::BI__builtin_ia32_compressstoresf128_mask:1157 case X86::BI__builtin_ia32_compressstoresf256_mask:1158 case X86::BI__builtin_ia32_compressstoresf512_mask:1159 case X86::BI__builtin_ia32_compressstoredi128_mask:1160 case X86::BI__builtin_ia32_compressstoredi256_mask:1161 case X86::BI__builtin_ia32_compressstoredi512_mask:1162 case X86::BI__builtin_ia32_compressstoresi128_mask:1163 case X86::BI__builtin_ia32_compressstoresi256_mask:1164 case X86::BI__builtin_ia32_compressstoresi512_mask:1165 case X86::BI__builtin_ia32_compressstorehi128_mask:1166 case X86::BI__builtin_ia32_compressstorehi256_mask:1167 case X86::BI__builtin_ia32_compressstorehi512_mask:1168 case X86::BI__builtin_ia32_compressstoreqi128_mask:1169 case X86::BI__builtin_ia32_compressstoreqi256_mask:1170 case X86::BI__builtin_ia32_compressstoreqi512_mask:1171 return EmitX86CompressStore(*this, Ops);1172 1173 case X86::BI__builtin_ia32_expanddf128_mask:1174 case X86::BI__builtin_ia32_expanddf256_mask:1175 case X86::BI__builtin_ia32_expanddf512_mask:1176 case X86::BI__builtin_ia32_expandsf128_mask:1177 case X86::BI__builtin_ia32_expandsf256_mask:1178 case X86::BI__builtin_ia32_expandsf512_mask:1179 case X86::BI__builtin_ia32_expanddi128_mask:1180 case X86::BI__builtin_ia32_expanddi256_mask:1181 case X86::BI__builtin_ia32_expanddi512_mask:1182 case X86::BI__builtin_ia32_expandsi128_mask:1183 case X86::BI__builtin_ia32_expandsi256_mask:1184 case X86::BI__builtin_ia32_expandsi512_mask:1185 case X86::BI__builtin_ia32_expandhi128_mask:1186 case X86::BI__builtin_ia32_expandhi256_mask:1187 case X86::BI__builtin_ia32_expandhi512_mask:1188 case X86::BI__builtin_ia32_expandqi128_mask:1189 case X86::BI__builtin_ia32_expandqi256_mask:1190 case X86::BI__builtin_ia32_expandqi512_mask:1191 return EmitX86CompressExpand(*this, Ops, /*IsCompress*/false);1192 1193 case X86::BI__builtin_ia32_compressdf128_mask:1194 case X86::BI__builtin_ia32_compressdf256_mask:1195 case X86::BI__builtin_ia32_compressdf512_mask:1196 case X86::BI__builtin_ia32_compresssf128_mask:1197 case X86::BI__builtin_ia32_compresssf256_mask:1198 case X86::BI__builtin_ia32_compresssf512_mask:1199 case X86::BI__builtin_ia32_compressdi128_mask:1200 case X86::BI__builtin_ia32_compressdi256_mask:1201 case X86::BI__builtin_ia32_compressdi512_mask:1202 case X86::BI__builtin_ia32_compresssi128_mask:1203 case X86::BI__builtin_ia32_compresssi256_mask:1204 case X86::BI__builtin_ia32_compresssi512_mask:1205 case X86::BI__builtin_ia32_compresshi128_mask:1206 case X86::BI__builtin_ia32_compresshi256_mask:1207 case X86::BI__builtin_ia32_compresshi512_mask:1208 case X86::BI__builtin_ia32_compressqi128_mask:1209 case X86::BI__builtin_ia32_compressqi256_mask:1210 case X86::BI__builtin_ia32_compressqi512_mask:1211 return EmitX86CompressExpand(*this, Ops, /*IsCompress*/true);1212 1213 case X86::BI__builtin_ia32_gather3div2df:1214 case X86::BI__builtin_ia32_gather3div2di:1215 case X86::BI__builtin_ia32_gather3div4df:1216 case X86::BI__builtin_ia32_gather3div4di:1217 case X86::BI__builtin_ia32_gather3div4sf:1218 case X86::BI__builtin_ia32_gather3div4si:1219 case X86::BI__builtin_ia32_gather3div8sf:1220 case X86::BI__builtin_ia32_gather3div8si:1221 case X86::BI__builtin_ia32_gather3siv2df:1222 case X86::BI__builtin_ia32_gather3siv2di:1223 case X86::BI__builtin_ia32_gather3siv4df:1224 case X86::BI__builtin_ia32_gather3siv4di:1225 case X86::BI__builtin_ia32_gather3siv4sf:1226 case X86::BI__builtin_ia32_gather3siv4si:1227 case X86::BI__builtin_ia32_gather3siv8sf:1228 case X86::BI__builtin_ia32_gather3siv8si:1229 case X86::BI__builtin_ia32_gathersiv8df:1230 case X86::BI__builtin_ia32_gathersiv16sf:1231 case X86::BI__builtin_ia32_gatherdiv8df:1232 case X86::BI__builtin_ia32_gatherdiv16sf:1233 case X86::BI__builtin_ia32_gathersiv8di:1234 case X86::BI__builtin_ia32_gathersiv16si:1235 case X86::BI__builtin_ia32_gatherdiv8di:1236 case X86::BI__builtin_ia32_gatherdiv16si: {1237 Intrinsic::ID IID;1238 switch (BuiltinID) {1239 default: llvm_unreachable("Unexpected builtin");1240 case X86::BI__builtin_ia32_gather3div2df:1241 IID = Intrinsic::x86_avx512_mask_gather3div2_df;1242 break;1243 case X86::BI__builtin_ia32_gather3div2di:1244 IID = Intrinsic::x86_avx512_mask_gather3div2_di;1245 break;1246 case X86::BI__builtin_ia32_gather3div4df:1247 IID = Intrinsic::x86_avx512_mask_gather3div4_df;1248 break;1249 case X86::BI__builtin_ia32_gather3div4di:1250 IID = Intrinsic::x86_avx512_mask_gather3div4_di;1251 break;1252 case X86::BI__builtin_ia32_gather3div4sf:1253 IID = Intrinsic::x86_avx512_mask_gather3div4_sf;1254 break;1255 case X86::BI__builtin_ia32_gather3div4si:1256 IID = Intrinsic::x86_avx512_mask_gather3div4_si;1257 break;1258 case X86::BI__builtin_ia32_gather3div8sf:1259 IID = Intrinsic::x86_avx512_mask_gather3div8_sf;1260 break;1261 case X86::BI__builtin_ia32_gather3div8si:1262 IID = Intrinsic::x86_avx512_mask_gather3div8_si;1263 break;1264 case X86::BI__builtin_ia32_gather3siv2df:1265 IID = Intrinsic::x86_avx512_mask_gather3siv2_df;1266 break;1267 case X86::BI__builtin_ia32_gather3siv2di:1268 IID = Intrinsic::x86_avx512_mask_gather3siv2_di;1269 break;1270 case X86::BI__builtin_ia32_gather3siv4df:1271 IID = Intrinsic::x86_avx512_mask_gather3siv4_df;1272 break;1273 case X86::BI__builtin_ia32_gather3siv4di:1274 IID = Intrinsic::x86_avx512_mask_gather3siv4_di;1275 break;1276 case X86::BI__builtin_ia32_gather3siv4sf:1277 IID = Intrinsic::x86_avx512_mask_gather3siv4_sf;1278 break;1279 case X86::BI__builtin_ia32_gather3siv4si:1280 IID = Intrinsic::x86_avx512_mask_gather3siv4_si;1281 break;1282 case X86::BI__builtin_ia32_gather3siv8sf:1283 IID = Intrinsic::x86_avx512_mask_gather3siv8_sf;1284 break;1285 case X86::BI__builtin_ia32_gather3siv8si:1286 IID = Intrinsic::x86_avx512_mask_gather3siv8_si;1287 break;1288 case X86::BI__builtin_ia32_gathersiv8df:1289 IID = Intrinsic::x86_avx512_mask_gather_dpd_512;1290 break;1291 case X86::BI__builtin_ia32_gathersiv16sf:1292 IID = Intrinsic::x86_avx512_mask_gather_dps_512;1293 break;1294 case X86::BI__builtin_ia32_gatherdiv8df:1295 IID = Intrinsic::x86_avx512_mask_gather_qpd_512;1296 break;1297 case X86::BI__builtin_ia32_gatherdiv16sf:1298 IID = Intrinsic::x86_avx512_mask_gather_qps_512;1299 break;1300 case X86::BI__builtin_ia32_gathersiv8di:1301 IID = Intrinsic::x86_avx512_mask_gather_dpq_512;1302 break;1303 case X86::BI__builtin_ia32_gathersiv16si:1304 IID = Intrinsic::x86_avx512_mask_gather_dpi_512;1305 break;1306 case X86::BI__builtin_ia32_gatherdiv8di:1307 IID = Intrinsic::x86_avx512_mask_gather_qpq_512;1308 break;1309 case X86::BI__builtin_ia32_gatherdiv16si:1310 IID = Intrinsic::x86_avx512_mask_gather_qpi_512;1311 break;1312 }1313 1314 unsigned MinElts = std::min(1315 cast<llvm::FixedVectorType>(Ops[0]->getType())->getNumElements(),1316 cast<llvm::FixedVectorType>(Ops[2]->getType())->getNumElements());1317 Ops[3] = getMaskVecValue(*this, Ops[3], MinElts);1318 Function *Intr = CGM.getIntrinsic(IID);1319 return Builder.CreateCall(Intr, Ops);1320 }1321 1322 case X86::BI__builtin_ia32_scattersiv8df:1323 case X86::BI__builtin_ia32_scattersiv16sf:1324 case X86::BI__builtin_ia32_scatterdiv8df:1325 case X86::BI__builtin_ia32_scatterdiv16sf:1326 case X86::BI__builtin_ia32_scattersiv8di:1327 case X86::BI__builtin_ia32_scattersiv16si:1328 case X86::BI__builtin_ia32_scatterdiv8di:1329 case X86::BI__builtin_ia32_scatterdiv16si:1330 case X86::BI__builtin_ia32_scatterdiv2df:1331 case X86::BI__builtin_ia32_scatterdiv2di:1332 case X86::BI__builtin_ia32_scatterdiv4df:1333 case X86::BI__builtin_ia32_scatterdiv4di:1334 case X86::BI__builtin_ia32_scatterdiv4sf:1335 case X86::BI__builtin_ia32_scatterdiv4si:1336 case X86::BI__builtin_ia32_scatterdiv8sf:1337 case X86::BI__builtin_ia32_scatterdiv8si:1338 case X86::BI__builtin_ia32_scattersiv2df:1339 case X86::BI__builtin_ia32_scattersiv2di:1340 case X86::BI__builtin_ia32_scattersiv4df:1341 case X86::BI__builtin_ia32_scattersiv4di:1342 case X86::BI__builtin_ia32_scattersiv4sf:1343 case X86::BI__builtin_ia32_scattersiv4si:1344 case X86::BI__builtin_ia32_scattersiv8sf:1345 case X86::BI__builtin_ia32_scattersiv8si: {1346 Intrinsic::ID IID;1347 switch (BuiltinID) {1348 default: llvm_unreachable("Unexpected builtin");1349 case X86::BI__builtin_ia32_scattersiv8df:1350 IID = Intrinsic::x86_avx512_mask_scatter_dpd_512;1351 break;1352 case X86::BI__builtin_ia32_scattersiv16sf:1353 IID = Intrinsic::x86_avx512_mask_scatter_dps_512;1354 break;1355 case X86::BI__builtin_ia32_scatterdiv8df:1356 IID = Intrinsic::x86_avx512_mask_scatter_qpd_512;1357 break;1358 case X86::BI__builtin_ia32_scatterdiv16sf:1359 IID = Intrinsic::x86_avx512_mask_scatter_qps_512;1360 break;1361 case X86::BI__builtin_ia32_scattersiv8di:1362 IID = Intrinsic::x86_avx512_mask_scatter_dpq_512;1363 break;1364 case X86::BI__builtin_ia32_scattersiv16si:1365 IID = Intrinsic::x86_avx512_mask_scatter_dpi_512;1366 break;1367 case X86::BI__builtin_ia32_scatterdiv8di:1368 IID = Intrinsic::x86_avx512_mask_scatter_qpq_512;1369 break;1370 case X86::BI__builtin_ia32_scatterdiv16si:1371 IID = Intrinsic::x86_avx512_mask_scatter_qpi_512;1372 break;1373 case X86::BI__builtin_ia32_scatterdiv2df:1374 IID = Intrinsic::x86_avx512_mask_scatterdiv2_df;1375 break;1376 case X86::BI__builtin_ia32_scatterdiv2di:1377 IID = Intrinsic::x86_avx512_mask_scatterdiv2_di;1378 break;1379 case X86::BI__builtin_ia32_scatterdiv4df:1380 IID = Intrinsic::x86_avx512_mask_scatterdiv4_df;1381 break;1382 case X86::BI__builtin_ia32_scatterdiv4di:1383 IID = Intrinsic::x86_avx512_mask_scatterdiv4_di;1384 break;1385 case X86::BI__builtin_ia32_scatterdiv4sf:1386 IID = Intrinsic::x86_avx512_mask_scatterdiv4_sf;1387 break;1388 case X86::BI__builtin_ia32_scatterdiv4si:1389 IID = Intrinsic::x86_avx512_mask_scatterdiv4_si;1390 break;1391 case X86::BI__builtin_ia32_scatterdiv8sf:1392 IID = Intrinsic::x86_avx512_mask_scatterdiv8_sf;1393 break;1394 case X86::BI__builtin_ia32_scatterdiv8si:1395 IID = Intrinsic::x86_avx512_mask_scatterdiv8_si;1396 break;1397 case X86::BI__builtin_ia32_scattersiv2df:1398 IID = Intrinsic::x86_avx512_mask_scattersiv2_df;1399 break;1400 case X86::BI__builtin_ia32_scattersiv2di:1401 IID = Intrinsic::x86_avx512_mask_scattersiv2_di;1402 break;1403 case X86::BI__builtin_ia32_scattersiv4df:1404 IID = Intrinsic::x86_avx512_mask_scattersiv4_df;1405 break;1406 case X86::BI__builtin_ia32_scattersiv4di:1407 IID = Intrinsic::x86_avx512_mask_scattersiv4_di;1408 break;1409 case X86::BI__builtin_ia32_scattersiv4sf:1410 IID = Intrinsic::x86_avx512_mask_scattersiv4_sf;1411 break;1412 case X86::BI__builtin_ia32_scattersiv4si:1413 IID = Intrinsic::x86_avx512_mask_scattersiv4_si;1414 break;1415 case X86::BI__builtin_ia32_scattersiv8sf:1416 IID = Intrinsic::x86_avx512_mask_scattersiv8_sf;1417 break;1418 case X86::BI__builtin_ia32_scattersiv8si:1419 IID = Intrinsic::x86_avx512_mask_scattersiv8_si;1420 break;1421 }1422 1423 unsigned MinElts = std::min(1424 cast<llvm::FixedVectorType>(Ops[2]->getType())->getNumElements(),1425 cast<llvm::FixedVectorType>(Ops[3]->getType())->getNumElements());1426 Ops[1] = getMaskVecValue(*this, Ops[1], MinElts);1427 Function *Intr = CGM.getIntrinsic(IID);1428 return Builder.CreateCall(Intr, Ops);1429 }1430 1431 case X86::BI__builtin_ia32_vextractf128_pd256:1432 case X86::BI__builtin_ia32_vextractf128_ps256:1433 case X86::BI__builtin_ia32_vextractf128_si256:1434 case X86::BI__builtin_ia32_extract128i256:1435 case X86::BI__builtin_ia32_extractf64x4_mask:1436 case X86::BI__builtin_ia32_extractf32x4_mask:1437 case X86::BI__builtin_ia32_extracti64x4_mask:1438 case X86::BI__builtin_ia32_extracti32x4_mask:1439 case X86::BI__builtin_ia32_extractf32x8_mask:1440 case X86::BI__builtin_ia32_extracti32x8_mask:1441 case X86::BI__builtin_ia32_extractf32x4_256_mask:1442 case X86::BI__builtin_ia32_extracti32x4_256_mask:1443 case X86::BI__builtin_ia32_extractf64x2_256_mask:1444 case X86::BI__builtin_ia32_extracti64x2_256_mask:1445 case X86::BI__builtin_ia32_extractf64x2_512_mask:1446 case X86::BI__builtin_ia32_extracti64x2_512_mask: {1447 auto *DstTy = cast<llvm::FixedVectorType>(ConvertType(E->getType()));1448 unsigned NumElts = DstTy->getNumElements();1449 unsigned SrcNumElts =1450 cast<llvm::FixedVectorType>(Ops[0]->getType())->getNumElements();1451 unsigned SubVectors = SrcNumElts / NumElts;1452 unsigned Index = cast<ConstantInt>(Ops[1])->getZExtValue();1453 assert(llvm::isPowerOf2_32(SubVectors) && "Expected power of 2 subvectors");1454 Index &= SubVectors - 1; // Remove any extra bits.1455 Index *= NumElts;1456 1457 int Indices[16];1458 for (unsigned i = 0; i != NumElts; ++i)1459 Indices[i] = i + Index;1460 1461 Value *Res = Builder.CreateShuffleVector(Ops[0], ArrayRef(Indices, NumElts),1462 "extract");1463 1464 if (Ops.size() == 4)1465 Res = EmitX86Select(*this, Ops[3], Res, Ops[2]);1466 1467 return Res;1468 }1469 case X86::BI__builtin_ia32_vinsertf128_pd256:1470 case X86::BI__builtin_ia32_vinsertf128_ps256:1471 case X86::BI__builtin_ia32_vinsertf128_si256:1472 case X86::BI__builtin_ia32_insert128i256:1473 case X86::BI__builtin_ia32_insertf64x4:1474 case X86::BI__builtin_ia32_insertf32x4:1475 case X86::BI__builtin_ia32_inserti64x4:1476 case X86::BI__builtin_ia32_inserti32x4:1477 case X86::BI__builtin_ia32_insertf32x8:1478 case X86::BI__builtin_ia32_inserti32x8:1479 case X86::BI__builtin_ia32_insertf32x4_256:1480 case X86::BI__builtin_ia32_inserti32x4_256:1481 case X86::BI__builtin_ia32_insertf64x2_256:1482 case X86::BI__builtin_ia32_inserti64x2_256:1483 case X86::BI__builtin_ia32_insertf64x2_512:1484 case X86::BI__builtin_ia32_inserti64x2_512: {1485 unsigned DstNumElts =1486 cast<llvm::FixedVectorType>(Ops[0]->getType())->getNumElements();1487 unsigned SrcNumElts =1488 cast<llvm::FixedVectorType>(Ops[1]->getType())->getNumElements();1489 unsigned SubVectors = DstNumElts / SrcNumElts;1490 unsigned Index = cast<ConstantInt>(Ops[2])->getZExtValue();1491 assert(llvm::isPowerOf2_32(SubVectors) && "Expected power of 2 subvectors");1492 Index &= SubVectors - 1; // Remove any extra bits.1493 Index *= SrcNumElts;1494 1495 int Indices[16];1496 for (unsigned i = 0; i != DstNumElts; ++i)1497 Indices[i] = (i >= SrcNumElts) ? SrcNumElts + (i % SrcNumElts) : i;1498 1499 Value *Op1 = Builder.CreateShuffleVector(1500 Ops[1], ArrayRef(Indices, DstNumElts), "widen");1501 1502 for (unsigned i = 0; i != DstNumElts; ++i) {1503 if (i >= Index && i < (Index + SrcNumElts))1504 Indices[i] = (i - Index) + DstNumElts;1505 else1506 Indices[i] = i;1507 }1508 1509 return Builder.CreateShuffleVector(Ops[0], Op1,1510 ArrayRef(Indices, DstNumElts), "insert");1511 }1512 case X86::BI__builtin_ia32_pmovqd512_mask:1513 case X86::BI__builtin_ia32_pmovwb512_mask: {1514 Value *Res = Builder.CreateTrunc(Ops[0], Ops[1]->getType());1515 return EmitX86Select(*this, Ops[2], Res, Ops[1]);1516 }1517 case X86::BI__builtin_ia32_pmovdb512_mask:1518 case X86::BI__builtin_ia32_pmovdw512_mask:1519 case X86::BI__builtin_ia32_pmovqw512_mask: {1520 if (const auto *C = dyn_cast<Constant>(Ops[2]))1521 if (C->isAllOnesValue())1522 return Builder.CreateTrunc(Ops[0], Ops[1]->getType());1523 1524 Intrinsic::ID IID;1525 switch (BuiltinID) {1526 default: llvm_unreachable("Unsupported intrinsic!");1527 case X86::BI__builtin_ia32_pmovdb512_mask:1528 IID = Intrinsic::x86_avx512_mask_pmov_db_512;1529 break;1530 case X86::BI__builtin_ia32_pmovdw512_mask:1531 IID = Intrinsic::x86_avx512_mask_pmov_dw_512;1532 break;1533 case X86::BI__builtin_ia32_pmovqw512_mask:1534 IID = Intrinsic::x86_avx512_mask_pmov_qw_512;1535 break;1536 }1537 1538 Function *Intr = CGM.getIntrinsic(IID);1539 return Builder.CreateCall(Intr, Ops);1540 }1541 case X86::BI__builtin_ia32_pblendw128:1542 case X86::BI__builtin_ia32_blendpd:1543 case X86::BI__builtin_ia32_blendps:1544 case X86::BI__builtin_ia32_blendpd256:1545 case X86::BI__builtin_ia32_blendps256:1546 case X86::BI__builtin_ia32_pblendw256:1547 case X86::BI__builtin_ia32_pblendd128:1548 case X86::BI__builtin_ia32_pblendd256: {1549 unsigned NumElts =1550 cast<llvm::FixedVectorType>(Ops[0]->getType())->getNumElements();1551 unsigned Imm = cast<llvm::ConstantInt>(Ops[2])->getZExtValue();1552 1553 int Indices[16];1554 // If there are more than 8 elements, the immediate is used twice so make1555 // sure we handle that.1556 for (unsigned i = 0; i != NumElts; ++i)1557 Indices[i] = ((Imm >> (i % 8)) & 0x1) ? NumElts + i : i;1558 1559 return Builder.CreateShuffleVector(Ops[0], Ops[1],1560 ArrayRef(Indices, NumElts), "blend");1561 }1562 case X86::BI__builtin_ia32_pshuflw:1563 case X86::BI__builtin_ia32_pshuflw256:1564 case X86::BI__builtin_ia32_pshuflw512: {1565 uint32_t Imm = cast<llvm::ConstantInt>(Ops[1])->getZExtValue();1566 auto *Ty = cast<llvm::FixedVectorType>(Ops[0]->getType());1567 unsigned NumElts = Ty->getNumElements();1568 1569 // Splat the 8-bits of immediate 4 times to help the loop wrap around.1570 Imm = (Imm & 0xff) * 0x01010101;1571 1572 int Indices[32];1573 for (unsigned l = 0; l != NumElts; l += 8) {1574 for (unsigned i = 0; i != 4; ++i) {1575 Indices[l + i] = l + (Imm & 3);1576 Imm >>= 2;1577 }1578 for (unsigned i = 4; i != 8; ++i)1579 Indices[l + i] = l + i;1580 }1581 1582 return Builder.CreateShuffleVector(Ops[0], ArrayRef(Indices, NumElts),1583 "pshuflw");1584 }1585 case X86::BI__builtin_ia32_pshufhw:1586 case X86::BI__builtin_ia32_pshufhw256:1587 case X86::BI__builtin_ia32_pshufhw512: {1588 uint32_t Imm = cast<llvm::ConstantInt>(Ops[1])->getZExtValue();1589 auto *Ty = cast<llvm::FixedVectorType>(Ops[0]->getType());1590 unsigned NumElts = Ty->getNumElements();1591 1592 // Splat the 8-bits of immediate 4 times to help the loop wrap around.1593 Imm = (Imm & 0xff) * 0x01010101;1594 1595 int Indices[32];1596 for (unsigned l = 0; l != NumElts; l += 8) {1597 for (unsigned i = 0; i != 4; ++i)1598 Indices[l + i] = l + i;1599 for (unsigned i = 4; i != 8; ++i) {1600 Indices[l + i] = l + 4 + (Imm & 3);1601 Imm >>= 2;1602 }1603 }1604 1605 return Builder.CreateShuffleVector(Ops[0], ArrayRef(Indices, NumElts),1606 "pshufhw");1607 }1608 case X86::BI__builtin_ia32_pshufd:1609 case X86::BI__builtin_ia32_pshufd256:1610 case X86::BI__builtin_ia32_pshufd512:1611 case X86::BI__builtin_ia32_vpermilpd:1612 case X86::BI__builtin_ia32_vpermilps:1613 case X86::BI__builtin_ia32_vpermilpd256:1614 case X86::BI__builtin_ia32_vpermilps256:1615 case X86::BI__builtin_ia32_vpermilpd512:1616 case X86::BI__builtin_ia32_vpermilps512: {1617 uint32_t Imm = cast<llvm::ConstantInt>(Ops[1])->getZExtValue();1618 auto *Ty = cast<llvm::FixedVectorType>(Ops[0]->getType());1619 unsigned NumElts = Ty->getNumElements();1620 unsigned NumLanes = Ty->getPrimitiveSizeInBits() / 128;1621 unsigned NumLaneElts = NumElts / NumLanes;1622 1623 // Splat the 8-bits of immediate 4 times to help the loop wrap around.1624 Imm = (Imm & 0xff) * 0x01010101;1625 1626 int Indices[16];1627 for (unsigned l = 0; l != NumElts; l += NumLaneElts) {1628 for (unsigned i = 0; i != NumLaneElts; ++i) {1629 Indices[i + l] = (Imm % NumLaneElts) + l;1630 Imm /= NumLaneElts;1631 }1632 }1633 1634 return Builder.CreateShuffleVector(Ops[0], ArrayRef(Indices, NumElts),1635 "permil");1636 }1637 case X86::BI__builtin_ia32_shufpd:1638 case X86::BI__builtin_ia32_shufpd256:1639 case X86::BI__builtin_ia32_shufpd512:1640 case X86::BI__builtin_ia32_shufps:1641 case X86::BI__builtin_ia32_shufps256:1642 case X86::BI__builtin_ia32_shufps512: {1643 uint32_t Imm = cast<llvm::ConstantInt>(Ops[2])->getZExtValue();1644 auto *Ty = cast<llvm::FixedVectorType>(Ops[0]->getType());1645 unsigned NumElts = Ty->getNumElements();1646 unsigned NumLanes = Ty->getPrimitiveSizeInBits() / 128;1647 unsigned NumLaneElts = NumElts / NumLanes;1648 1649 // Splat the 8-bits of immediate 4 times to help the loop wrap around.1650 Imm = (Imm & 0xff) * 0x01010101;1651 1652 int Indices[16];1653 for (unsigned l = 0; l != NumElts; l += NumLaneElts) {1654 for (unsigned i = 0; i != NumLaneElts; ++i) {1655 unsigned Index = Imm % NumLaneElts;1656 Imm /= NumLaneElts;1657 if (i >= (NumLaneElts / 2))1658 Index += NumElts;1659 Indices[l + i] = l + Index;1660 }1661 }1662 1663 return Builder.CreateShuffleVector(Ops[0], Ops[1],1664 ArrayRef(Indices, NumElts), "shufp");1665 }1666 case X86::BI__builtin_ia32_permdi256:1667 case X86::BI__builtin_ia32_permdf256:1668 case X86::BI__builtin_ia32_permdi512:1669 case X86::BI__builtin_ia32_permdf512: {1670 unsigned Imm = cast<llvm::ConstantInt>(Ops[1])->getZExtValue();1671 auto *Ty = cast<llvm::FixedVectorType>(Ops[0]->getType());1672 unsigned NumElts = Ty->getNumElements();1673 1674 // These intrinsics operate on 256-bit lanes of four 64-bit elements.1675 int Indices[8];1676 for (unsigned l = 0; l != NumElts; l += 4)1677 for (unsigned i = 0; i != 4; ++i)1678 Indices[l + i] = l + ((Imm >> (2 * i)) & 0x3);1679 1680 return Builder.CreateShuffleVector(Ops[0], ArrayRef(Indices, NumElts),1681 "perm");1682 }1683 case X86::BI__builtin_ia32_palignr128:1684 case X86::BI__builtin_ia32_palignr256:1685 case X86::BI__builtin_ia32_palignr512: {1686 unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[2])->getZExtValue() & 0xff;1687 1688 unsigned NumElts =1689 cast<llvm::FixedVectorType>(Ops[0]->getType())->getNumElements();1690 assert(NumElts % 16 == 0);1691 1692 // If palignr is shifting the pair of vectors more than the size of two1693 // lanes, emit zero.1694 if (ShiftVal >= 32)1695 return llvm::Constant::getNullValue(ConvertType(E->getType()));1696 1697 // If palignr is shifting the pair of input vectors more than one lane,1698 // but less than two lanes, convert to shifting in zeroes.1699 if (ShiftVal > 16) {1700 ShiftVal -= 16;1701 Ops[1] = Ops[0];1702 Ops[0] = llvm::Constant::getNullValue(Ops[0]->getType());1703 }1704 1705 int Indices[64];1706 // 256-bit palignr operates on 128-bit lanes so we need to handle that1707 for (unsigned l = 0; l != NumElts; l += 16) {1708 for (unsigned i = 0; i != 16; ++i) {1709 unsigned Idx = ShiftVal + i;1710 if (Idx >= 16)1711 Idx += NumElts - 16; // End of lane, switch operand.1712 Indices[l + i] = Idx + l;1713 }1714 }1715 1716 return Builder.CreateShuffleVector(Ops[1], Ops[0],1717 ArrayRef(Indices, NumElts), "palignr");1718 }1719 case X86::BI__builtin_ia32_alignd128:1720 case X86::BI__builtin_ia32_alignd256:1721 case X86::BI__builtin_ia32_alignd512:1722 case X86::BI__builtin_ia32_alignq128:1723 case X86::BI__builtin_ia32_alignq256:1724 case X86::BI__builtin_ia32_alignq512: {1725 unsigned NumElts =1726 cast<llvm::FixedVectorType>(Ops[0]->getType())->getNumElements();1727 unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[2])->getZExtValue() & 0xff;1728 1729 // Mask the shift amount to width of a vector.1730 ShiftVal &= NumElts - 1;1731 1732 int Indices[16];1733 for (unsigned i = 0; i != NumElts; ++i)1734 Indices[i] = i + ShiftVal;1735 1736 return Builder.CreateShuffleVector(Ops[1], Ops[0],1737 ArrayRef(Indices, NumElts), "valign");1738 }1739 case X86::BI__builtin_ia32_shuf_f32x4_256:1740 case X86::BI__builtin_ia32_shuf_f64x2_256:1741 case X86::BI__builtin_ia32_shuf_i32x4_256:1742 case X86::BI__builtin_ia32_shuf_i64x2_256:1743 case X86::BI__builtin_ia32_shuf_f32x4:1744 case X86::BI__builtin_ia32_shuf_f64x2:1745 case X86::BI__builtin_ia32_shuf_i32x4:1746 case X86::BI__builtin_ia32_shuf_i64x2: {1747 unsigned Imm = cast<llvm::ConstantInt>(Ops[2])->getZExtValue();1748 auto *Ty = cast<llvm::FixedVectorType>(Ops[0]->getType());1749 unsigned NumElts = Ty->getNumElements();1750 unsigned NumLanes = Ty->getPrimitiveSizeInBits() == 512 ? 4 : 2;1751 unsigned NumLaneElts = NumElts / NumLanes;1752 1753 int Indices[16];1754 for (unsigned l = 0; l != NumElts; l += NumLaneElts) {1755 unsigned Index = (Imm % NumLanes) * NumLaneElts;1756 Imm /= NumLanes; // Discard the bits we just used.1757 if (l >= (NumElts / 2))1758 Index += NumElts; // Switch to other source.1759 for (unsigned i = 0; i != NumLaneElts; ++i) {1760 Indices[l + i] = Index + i;1761 }1762 }1763 1764 return Builder.CreateShuffleVector(Ops[0], Ops[1],1765 ArrayRef(Indices, NumElts), "shuf");1766 }1767 1768 case X86::BI__builtin_ia32_vperm2f128_pd256:1769 case X86::BI__builtin_ia32_vperm2f128_ps256:1770 case X86::BI__builtin_ia32_vperm2f128_si256:1771 case X86::BI__builtin_ia32_permti256: {1772 unsigned Imm = cast<llvm::ConstantInt>(Ops[2])->getZExtValue();1773 unsigned NumElts =1774 cast<llvm::FixedVectorType>(Ops[0]->getType())->getNumElements();1775 1776 // This takes a very simple approach since there are two lanes and a1777 // shuffle can have 2 inputs. So we reserve the first input for the first1778 // lane and the second input for the second lane. This may result in1779 // duplicate sources, but this can be dealt with in the backend.1780 1781 Value *OutOps[2];1782 int Indices[8];1783 for (unsigned l = 0; l != 2; ++l) {1784 // Determine the source for this lane.1785 if (Imm & (1 << ((l * 4) + 3)))1786 OutOps[l] = llvm::ConstantAggregateZero::get(Ops[0]->getType());1787 else if (Imm & (1 << ((l * 4) + 1)))1788 OutOps[l] = Ops[1];1789 else1790 OutOps[l] = Ops[0];1791 1792 for (unsigned i = 0; i != NumElts/2; ++i) {1793 // Start with ith element of the source for this lane.1794 unsigned Idx = (l * NumElts) + i;1795 // If bit 0 of the immediate half is set, switch to the high half of1796 // the source.1797 if (Imm & (1 << (l * 4)))1798 Idx += NumElts/2;1799 Indices[(l * (NumElts/2)) + i] = Idx;1800 }1801 }1802 1803 return Builder.CreateShuffleVector(OutOps[0], OutOps[1],1804 ArrayRef(Indices, NumElts), "vperm");1805 }1806 1807 case X86::BI__builtin_ia32_pslldqi128_byteshift:1808 case X86::BI__builtin_ia32_pslldqi256_byteshift:1809 case X86::BI__builtin_ia32_pslldqi512_byteshift: {1810 unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[1])->getZExtValue() & 0xff;1811 auto *VecTy = cast<llvm::FixedVectorType>(Ops[0]->getType());1812 // Builtin type is vXi8.1813 unsigned NumElts = VecTy->getNumElements();1814 Value *Zero = llvm::Constant::getNullValue(VecTy);1815 1816 // If pslldq is shifting the vector more than 15 bytes, emit zero.1817 if (ShiftVal >= 16)1818 return Zero;1819 1820 int Indices[64];1821 // 256/512-bit pslldq operates on 128-bit lanes so we need to handle that1822 for (unsigned l = 0; l != NumElts; l += 16) {1823 for (unsigned i = 0; i != 16; ++i) {1824 unsigned Idx = NumElts + i - ShiftVal;1825 if (Idx < NumElts)1826 Idx -= NumElts - 16; // end of lane, switch operand.1827 Indices[l + i] = Idx + l;1828 }1829 }1830 return Builder.CreateShuffleVector(Zero, Ops[0], ArrayRef(Indices, NumElts),1831 "pslldq");1832 }1833 case X86::BI__builtin_ia32_psrldqi128_byteshift:1834 case X86::BI__builtin_ia32_psrldqi256_byteshift:1835 case X86::BI__builtin_ia32_psrldqi512_byteshift: {1836 unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[1])->getZExtValue() & 0xff;1837 auto *VecTy = cast<llvm::FixedVectorType>(Ops[0]->getType());1838 // Builtin type is vXi8.1839 unsigned NumElts = VecTy->getNumElements();1840 Value *Zero = llvm::Constant::getNullValue(VecTy);1841 1842 // If psrldq is shifting the vector more than 15 bytes, emit zero.1843 if (ShiftVal >= 16)1844 return Zero;1845 1846 int Indices[64];1847 // 256/512-bit psrldq operates on 128-bit lanes so we need to handle that1848 for (unsigned l = 0; l != NumElts; l += 16) {1849 for (unsigned i = 0; i != 16; ++i) {1850 unsigned Idx = i + ShiftVal;1851 if (Idx >= 16)1852 Idx += NumElts - 16; // end of lane, switch operand.1853 Indices[l + i] = Idx + l;1854 }1855 }1856 return Builder.CreateShuffleVector(Ops[0], Zero, ArrayRef(Indices, NumElts),1857 "psrldq");1858 }1859 case X86::BI__builtin_ia32_kshiftliqi:1860 case X86::BI__builtin_ia32_kshiftlihi:1861 case X86::BI__builtin_ia32_kshiftlisi:1862 case X86::BI__builtin_ia32_kshiftlidi: {1863 unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[1])->getZExtValue() & 0xff;1864 unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth();1865 1866 if (ShiftVal >= NumElts)1867 return llvm::Constant::getNullValue(Ops[0]->getType());1868 1869 Value *In = getMaskVecValue(*this, Ops[0], NumElts);1870 1871 int Indices[64];1872 for (unsigned i = 0; i != NumElts; ++i)1873 Indices[i] = NumElts + i - ShiftVal;1874 1875 Value *Zero = llvm::Constant::getNullValue(In->getType());1876 Value *SV = Builder.CreateShuffleVector(1877 Zero, In, ArrayRef(Indices, NumElts), "kshiftl");1878 return Builder.CreateBitCast(SV, Ops[0]->getType());1879 }1880 case X86::BI__builtin_ia32_kshiftriqi:1881 case X86::BI__builtin_ia32_kshiftrihi:1882 case X86::BI__builtin_ia32_kshiftrisi:1883 case X86::BI__builtin_ia32_kshiftridi: {1884 unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[1])->getZExtValue() & 0xff;1885 unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth();1886 1887 if (ShiftVal >= NumElts)1888 return llvm::Constant::getNullValue(Ops[0]->getType());1889 1890 Value *In = getMaskVecValue(*this, Ops[0], NumElts);1891 1892 int Indices[64];1893 for (unsigned i = 0; i != NumElts; ++i)1894 Indices[i] = i + ShiftVal;1895 1896 Value *Zero = llvm::Constant::getNullValue(In->getType());1897 Value *SV = Builder.CreateShuffleVector(1898 In, Zero, ArrayRef(Indices, NumElts), "kshiftr");1899 return Builder.CreateBitCast(SV, Ops[0]->getType());1900 }1901 case X86::BI__builtin_ia32_movnti:1902 case X86::BI__builtin_ia32_movnti64:1903 case X86::BI__builtin_ia32_movntsd:1904 case X86::BI__builtin_ia32_movntss: {1905 llvm::MDNode *Node = llvm::MDNode::get(1906 getLLVMContext(), llvm::ConstantAsMetadata::get(Builder.getInt32(1)));1907 1908 Value *Ptr = Ops[0];1909 Value *Src = Ops[1];1910 1911 // Extract the 0'th element of the source vector.1912 if (BuiltinID == X86::BI__builtin_ia32_movntsd ||1913 BuiltinID == X86::BI__builtin_ia32_movntss)1914 Src = Builder.CreateExtractElement(Src, (uint64_t)0, "extract");1915 1916 // Unaligned nontemporal store of the scalar value.1917 StoreInst *SI = Builder.CreateDefaultAlignedStore(Src, Ptr);1918 SI->setMetadata(llvm::LLVMContext::MD_nontemporal, Node);1919 SI->setAlignment(llvm::Align(1));1920 return SI;1921 }1922 // Rotate is a special case of funnel shift - 1st 2 args are the same.1923 case X86::BI__builtin_ia32_vprotbi:1924 case X86::BI__builtin_ia32_vprotwi:1925 case X86::BI__builtin_ia32_vprotdi:1926 case X86::BI__builtin_ia32_vprotqi:1927 case X86::BI__builtin_ia32_prold128:1928 case X86::BI__builtin_ia32_prold256:1929 case X86::BI__builtin_ia32_prold512:1930 case X86::BI__builtin_ia32_prolq128:1931 case X86::BI__builtin_ia32_prolq256:1932 case X86::BI__builtin_ia32_prolq512:1933 return EmitX86FunnelShift(*this, Ops[0], Ops[0], Ops[1], false);1934 case X86::BI__builtin_ia32_prord128:1935 case X86::BI__builtin_ia32_prord256:1936 case X86::BI__builtin_ia32_prord512:1937 case X86::BI__builtin_ia32_prorq128:1938 case X86::BI__builtin_ia32_prorq256:1939 case X86::BI__builtin_ia32_prorq512:1940 return EmitX86FunnelShift(*this, Ops[0], Ops[0], Ops[1], true);1941 case X86::BI__builtin_ia32_selectb_128:1942 case X86::BI__builtin_ia32_selectb_256:1943 case X86::BI__builtin_ia32_selectb_512:1944 case X86::BI__builtin_ia32_selectw_128:1945 case X86::BI__builtin_ia32_selectw_256:1946 case X86::BI__builtin_ia32_selectw_512:1947 case X86::BI__builtin_ia32_selectd_128:1948 case X86::BI__builtin_ia32_selectd_256:1949 case X86::BI__builtin_ia32_selectd_512:1950 case X86::BI__builtin_ia32_selectq_128:1951 case X86::BI__builtin_ia32_selectq_256:1952 case X86::BI__builtin_ia32_selectq_512:1953 case X86::BI__builtin_ia32_selectph_128:1954 case X86::BI__builtin_ia32_selectph_256:1955 case X86::BI__builtin_ia32_selectph_512:1956 case X86::BI__builtin_ia32_selectpbf_128:1957 case X86::BI__builtin_ia32_selectpbf_256:1958 case X86::BI__builtin_ia32_selectpbf_512:1959 case X86::BI__builtin_ia32_selectps_128:1960 case X86::BI__builtin_ia32_selectps_256:1961 case X86::BI__builtin_ia32_selectps_512:1962 case X86::BI__builtin_ia32_selectpd_128:1963 case X86::BI__builtin_ia32_selectpd_256:1964 case X86::BI__builtin_ia32_selectpd_512:1965 return EmitX86Select(*this, Ops[0], Ops[1], Ops[2]);1966 case X86::BI__builtin_ia32_selectsh_128:1967 case X86::BI__builtin_ia32_selectsbf_128:1968 case X86::BI__builtin_ia32_selectss_128:1969 case X86::BI__builtin_ia32_selectsd_128: {1970 Value *A = Builder.CreateExtractElement(Ops[1], (uint64_t)0);1971 Value *B = Builder.CreateExtractElement(Ops[2], (uint64_t)0);1972 A = EmitX86ScalarSelect(*this, Ops[0], A, B);1973 return Builder.CreateInsertElement(Ops[1], A, (uint64_t)0);1974 }1975 case X86::BI__builtin_ia32_cmpb128_mask:1976 case X86::BI__builtin_ia32_cmpb256_mask:1977 case X86::BI__builtin_ia32_cmpb512_mask:1978 case X86::BI__builtin_ia32_cmpw128_mask:1979 case X86::BI__builtin_ia32_cmpw256_mask:1980 case X86::BI__builtin_ia32_cmpw512_mask:1981 case X86::BI__builtin_ia32_cmpd128_mask:1982 case X86::BI__builtin_ia32_cmpd256_mask:1983 case X86::BI__builtin_ia32_cmpd512_mask:1984 case X86::BI__builtin_ia32_cmpq128_mask:1985 case X86::BI__builtin_ia32_cmpq256_mask:1986 case X86::BI__builtin_ia32_cmpq512_mask: {1987 unsigned CC = cast<llvm::ConstantInt>(Ops[2])->getZExtValue() & 0x7;1988 return EmitX86MaskedCompare(*this, CC, true, Ops);1989 }1990 case X86::BI__builtin_ia32_ucmpb128_mask:1991 case X86::BI__builtin_ia32_ucmpb256_mask:1992 case X86::BI__builtin_ia32_ucmpb512_mask:1993 case X86::BI__builtin_ia32_ucmpw128_mask:1994 case X86::BI__builtin_ia32_ucmpw256_mask:1995 case X86::BI__builtin_ia32_ucmpw512_mask:1996 case X86::BI__builtin_ia32_ucmpd128_mask:1997 case X86::BI__builtin_ia32_ucmpd256_mask:1998 case X86::BI__builtin_ia32_ucmpd512_mask:1999 case X86::BI__builtin_ia32_ucmpq128_mask:2000 case X86::BI__builtin_ia32_ucmpq256_mask:2001 case X86::BI__builtin_ia32_ucmpq512_mask: {2002 unsigned CC = cast<llvm::ConstantInt>(Ops[2])->getZExtValue() & 0x7;2003 return EmitX86MaskedCompare(*this, CC, false, Ops);2004 }2005 case X86::BI__builtin_ia32_vpcomb:2006 case X86::BI__builtin_ia32_vpcomw:2007 case X86::BI__builtin_ia32_vpcomd:2008 case X86::BI__builtin_ia32_vpcomq:2009 return EmitX86vpcom(*this, Ops, true);2010 case X86::BI__builtin_ia32_vpcomub:2011 case X86::BI__builtin_ia32_vpcomuw:2012 case X86::BI__builtin_ia32_vpcomud:2013 case X86::BI__builtin_ia32_vpcomuq:2014 return EmitX86vpcom(*this, Ops, false);2015 2016 case X86::BI__builtin_ia32_kortestcqi:2017 case X86::BI__builtin_ia32_kortestchi:2018 case X86::BI__builtin_ia32_kortestcsi:2019 case X86::BI__builtin_ia32_kortestcdi: {2020 Value *Or = EmitX86MaskLogic(*this, Instruction::Or, Ops);2021 Value *C = llvm::Constant::getAllOnesValue(Ops[0]->getType());2022 Value *Cmp = Builder.CreateICmpEQ(Or, C);2023 return Builder.CreateZExt(Cmp, ConvertType(E->getType()));2024 }2025 case X86::BI__builtin_ia32_kortestzqi:2026 case X86::BI__builtin_ia32_kortestzhi:2027 case X86::BI__builtin_ia32_kortestzsi:2028 case X86::BI__builtin_ia32_kortestzdi: {2029 Value *Or = EmitX86MaskLogic(*this, Instruction::Or, Ops);2030 Value *C = llvm::Constant::getNullValue(Ops[0]->getType());2031 Value *Cmp = Builder.CreateICmpEQ(Or, C);2032 return Builder.CreateZExt(Cmp, ConvertType(E->getType()));2033 }2034 2035 case X86::BI__builtin_ia32_ktestcqi:2036 case X86::BI__builtin_ia32_ktestzqi:2037 case X86::BI__builtin_ia32_ktestchi:2038 case X86::BI__builtin_ia32_ktestzhi:2039 case X86::BI__builtin_ia32_ktestcsi:2040 case X86::BI__builtin_ia32_ktestzsi:2041 case X86::BI__builtin_ia32_ktestcdi:2042 case X86::BI__builtin_ia32_ktestzdi: {2043 Intrinsic::ID IID;2044 switch (BuiltinID) {2045 default: llvm_unreachable("Unsupported intrinsic!");2046 case X86::BI__builtin_ia32_ktestcqi:2047 IID = Intrinsic::x86_avx512_ktestc_b;2048 break;2049 case X86::BI__builtin_ia32_ktestzqi:2050 IID = Intrinsic::x86_avx512_ktestz_b;2051 break;2052 case X86::BI__builtin_ia32_ktestchi:2053 IID = Intrinsic::x86_avx512_ktestc_w;2054 break;2055 case X86::BI__builtin_ia32_ktestzhi:2056 IID = Intrinsic::x86_avx512_ktestz_w;2057 break;2058 case X86::BI__builtin_ia32_ktestcsi:2059 IID = Intrinsic::x86_avx512_ktestc_d;2060 break;2061 case X86::BI__builtin_ia32_ktestzsi:2062 IID = Intrinsic::x86_avx512_ktestz_d;2063 break;2064 case X86::BI__builtin_ia32_ktestcdi:2065 IID = Intrinsic::x86_avx512_ktestc_q;2066 break;2067 case X86::BI__builtin_ia32_ktestzdi:2068 IID = Intrinsic::x86_avx512_ktestz_q;2069 break;2070 }2071 2072 unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth();2073 Value *LHS = getMaskVecValue(*this, Ops[0], NumElts);2074 Value *RHS = getMaskVecValue(*this, Ops[1], NumElts);2075 Function *Intr = CGM.getIntrinsic(IID);2076 return Builder.CreateCall(Intr, {LHS, RHS});2077 }2078 2079 case X86::BI__builtin_ia32_kaddqi:2080 case X86::BI__builtin_ia32_kaddhi:2081 case X86::BI__builtin_ia32_kaddsi:2082 case X86::BI__builtin_ia32_kadddi: {2083 Intrinsic::ID IID;2084 switch (BuiltinID) {2085 default: llvm_unreachable("Unsupported intrinsic!");2086 case X86::BI__builtin_ia32_kaddqi:2087 IID = Intrinsic::x86_avx512_kadd_b;2088 break;2089 case X86::BI__builtin_ia32_kaddhi:2090 IID = Intrinsic::x86_avx512_kadd_w;2091 break;2092 case X86::BI__builtin_ia32_kaddsi:2093 IID = Intrinsic::x86_avx512_kadd_d;2094 break;2095 case X86::BI__builtin_ia32_kadddi:2096 IID = Intrinsic::x86_avx512_kadd_q;2097 break;2098 }2099 2100 unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth();2101 Value *LHS = getMaskVecValue(*this, Ops[0], NumElts);2102 Value *RHS = getMaskVecValue(*this, Ops[1], NumElts);2103 Function *Intr = CGM.getIntrinsic(IID);2104 Value *Res = Builder.CreateCall(Intr, {LHS, RHS});2105 return Builder.CreateBitCast(Res, Ops[0]->getType());2106 }2107 case X86::BI__builtin_ia32_kandqi:2108 case X86::BI__builtin_ia32_kandhi:2109 case X86::BI__builtin_ia32_kandsi:2110 case X86::BI__builtin_ia32_kanddi:2111 return EmitX86MaskLogic(*this, Instruction::And, Ops);2112 case X86::BI__builtin_ia32_kandnqi:2113 case X86::BI__builtin_ia32_kandnhi:2114 case X86::BI__builtin_ia32_kandnsi:2115 case X86::BI__builtin_ia32_kandndi:2116 return EmitX86MaskLogic(*this, Instruction::And, Ops, true);2117 case X86::BI__builtin_ia32_korqi:2118 case X86::BI__builtin_ia32_korhi:2119 case X86::BI__builtin_ia32_korsi:2120 case X86::BI__builtin_ia32_kordi:2121 return EmitX86MaskLogic(*this, Instruction::Or, Ops);2122 case X86::BI__builtin_ia32_kxnorqi:2123 case X86::BI__builtin_ia32_kxnorhi:2124 case X86::BI__builtin_ia32_kxnorsi:2125 case X86::BI__builtin_ia32_kxnordi:2126 return EmitX86MaskLogic(*this, Instruction::Xor, Ops, true);2127 case X86::BI__builtin_ia32_kxorqi:2128 case X86::BI__builtin_ia32_kxorhi:2129 case X86::BI__builtin_ia32_kxorsi:2130 case X86::BI__builtin_ia32_kxordi:2131 return EmitX86MaskLogic(*this, Instruction::Xor, Ops);2132 case X86::BI__builtin_ia32_knotqi:2133 case X86::BI__builtin_ia32_knothi:2134 case X86::BI__builtin_ia32_knotsi:2135 case X86::BI__builtin_ia32_knotdi: {2136 unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth();2137 Value *Res = getMaskVecValue(*this, Ops[0], NumElts);2138 return Builder.CreateBitCast(Builder.CreateNot(Res),2139 Ops[0]->getType());2140 }2141 case X86::BI__builtin_ia32_kmovb:2142 case X86::BI__builtin_ia32_kmovw:2143 case X86::BI__builtin_ia32_kmovd:2144 case X86::BI__builtin_ia32_kmovq: {2145 // Bitcast to vXi1 type and then back to integer. This gets the mask2146 // register type into the IR, but might be optimized out depending on2147 // what's around it.2148 unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth();2149 Value *Res = getMaskVecValue(*this, Ops[0], NumElts);2150 return Builder.CreateBitCast(Res, Ops[0]->getType());2151 }2152 2153 case X86::BI__builtin_ia32_kunpckdi:2154 case X86::BI__builtin_ia32_kunpcksi:2155 case X86::BI__builtin_ia32_kunpckhi: {2156 unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth();2157 Value *LHS = getMaskVecValue(*this, Ops[0], NumElts);2158 Value *RHS = getMaskVecValue(*this, Ops[1], NumElts);2159 int Indices[64];2160 for (unsigned i = 0; i != NumElts; ++i)2161 Indices[i] = i;2162 2163 // First extract half of each vector. This gives better codegen than2164 // doing it in a single shuffle.2165 LHS = Builder.CreateShuffleVector(LHS, LHS, ArrayRef(Indices, NumElts / 2));2166 RHS = Builder.CreateShuffleVector(RHS, RHS, ArrayRef(Indices, NumElts / 2));2167 // Concat the vectors.2168 // NOTE: Operands are swapped to match the intrinsic definition.2169 Value *Res =2170 Builder.CreateShuffleVector(RHS, LHS, ArrayRef(Indices, NumElts));2171 return Builder.CreateBitCast(Res, Ops[0]->getType());2172 }2173 2174 case X86::BI__builtin_ia32_sqrtsh_round_mask:2175 case X86::BI__builtin_ia32_sqrtsd_round_mask:2176 case X86::BI__builtin_ia32_sqrtss_round_mask: {2177 unsigned CC = cast<llvm::ConstantInt>(Ops[4])->getZExtValue();2178 // Support only if the rounding mode is 4 (AKA CUR_DIRECTION),2179 // otherwise keep the intrinsic.2180 if (CC != 4) {2181 Intrinsic::ID IID;2182 2183 switch (BuiltinID) {2184 default:2185 llvm_unreachable("Unsupported intrinsic!");2186 case X86::BI__builtin_ia32_sqrtsh_round_mask:2187 IID = Intrinsic::x86_avx512fp16_mask_sqrt_sh;2188 break;2189 case X86::BI__builtin_ia32_sqrtsd_round_mask:2190 IID = Intrinsic::x86_avx512_mask_sqrt_sd;2191 break;2192 case X86::BI__builtin_ia32_sqrtss_round_mask:2193 IID = Intrinsic::x86_avx512_mask_sqrt_ss;2194 break;2195 }2196 return Builder.CreateCall(CGM.getIntrinsic(IID), Ops);2197 }2198 Value *A = Builder.CreateExtractElement(Ops[1], (uint64_t)0);2199 Function *F;2200 if (Builder.getIsFPConstrained()) {2201 CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);2202 F = CGM.getIntrinsic(Intrinsic::experimental_constrained_sqrt,2203 A->getType());2204 A = Builder.CreateConstrainedFPCall(F, A);2205 } else {2206 F = CGM.getIntrinsic(Intrinsic::sqrt, A->getType());2207 A = Builder.CreateCall(F, A);2208 }2209 Value *Src = Builder.CreateExtractElement(Ops[2], (uint64_t)0);2210 A = EmitX86ScalarSelect(*this, Ops[3], A, Src);2211 return Builder.CreateInsertElement(Ops[0], A, (uint64_t)0);2212 }2213 case X86::BI__builtin_ia32_sqrtph512:2214 case X86::BI__builtin_ia32_sqrtps512:2215 case X86::BI__builtin_ia32_sqrtpd512: {2216 unsigned CC = cast<llvm::ConstantInt>(Ops[1])->getZExtValue();2217 // Support only if the rounding mode is 4 (AKA CUR_DIRECTION),2218 // otherwise keep the intrinsic.2219 if (CC != 4) {2220 Intrinsic::ID IID;2221 2222 switch (BuiltinID) {2223 default:2224 llvm_unreachable("Unsupported intrinsic!");2225 case X86::BI__builtin_ia32_sqrtph512:2226 IID = Intrinsic::x86_avx512fp16_sqrt_ph_512;2227 break;2228 case X86::BI__builtin_ia32_sqrtps512:2229 IID = Intrinsic::x86_avx512_sqrt_ps_512;2230 break;2231 case X86::BI__builtin_ia32_sqrtpd512:2232 IID = Intrinsic::x86_avx512_sqrt_pd_512;2233 break;2234 }2235 return Builder.CreateCall(CGM.getIntrinsic(IID), Ops);2236 }2237 if (Builder.getIsFPConstrained()) {2238 CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);2239 Function *F = CGM.getIntrinsic(Intrinsic::experimental_constrained_sqrt,2240 Ops[0]->getType());2241 return Builder.CreateConstrainedFPCall(F, Ops[0]);2242 } else {2243 Function *F = CGM.getIntrinsic(Intrinsic::sqrt, Ops[0]->getType());2244 return Builder.CreateCall(F, Ops[0]);2245 }2246 }2247 2248 case X86::BI__builtin_ia32_pmuludq128:2249 case X86::BI__builtin_ia32_pmuludq256:2250 case X86::BI__builtin_ia32_pmuludq512:2251 return EmitX86Muldq(*this, /*IsSigned*/false, Ops);2252 2253 case X86::BI__builtin_ia32_pmuldq128:2254 case X86::BI__builtin_ia32_pmuldq256:2255 case X86::BI__builtin_ia32_pmuldq512:2256 return EmitX86Muldq(*this, /*IsSigned*/true, Ops);2257 2258 case X86::BI__builtin_ia32_pternlogd512_mask:2259 case X86::BI__builtin_ia32_pternlogq512_mask:2260 case X86::BI__builtin_ia32_pternlogd128_mask:2261 case X86::BI__builtin_ia32_pternlogd256_mask:2262 case X86::BI__builtin_ia32_pternlogq128_mask:2263 case X86::BI__builtin_ia32_pternlogq256_mask:2264 return EmitX86Ternlog(*this, /*ZeroMask*/false, Ops);2265 2266 case X86::BI__builtin_ia32_pternlogd512_maskz:2267 case X86::BI__builtin_ia32_pternlogq512_maskz:2268 case X86::BI__builtin_ia32_pternlogd128_maskz:2269 case X86::BI__builtin_ia32_pternlogd256_maskz:2270 case X86::BI__builtin_ia32_pternlogq128_maskz:2271 case X86::BI__builtin_ia32_pternlogq256_maskz:2272 return EmitX86Ternlog(*this, /*ZeroMask*/true, Ops);2273 2274 case X86::BI__builtin_ia32_vpshldd128:2275 case X86::BI__builtin_ia32_vpshldd256:2276 case X86::BI__builtin_ia32_vpshldd512:2277 case X86::BI__builtin_ia32_vpshldq128:2278 case X86::BI__builtin_ia32_vpshldq256:2279 case X86::BI__builtin_ia32_vpshldq512:2280 case X86::BI__builtin_ia32_vpshldw128:2281 case X86::BI__builtin_ia32_vpshldw256:2282 case X86::BI__builtin_ia32_vpshldw512:2283 return EmitX86FunnelShift(*this, Ops[0], Ops[1], Ops[2], false);2284 2285 case X86::BI__builtin_ia32_vpshrdd128:2286 case X86::BI__builtin_ia32_vpshrdd256:2287 case X86::BI__builtin_ia32_vpshrdd512:2288 case X86::BI__builtin_ia32_vpshrdq128:2289 case X86::BI__builtin_ia32_vpshrdq256:2290 case X86::BI__builtin_ia32_vpshrdq512:2291 case X86::BI__builtin_ia32_vpshrdw128:2292 case X86::BI__builtin_ia32_vpshrdw256:2293 case X86::BI__builtin_ia32_vpshrdw512:2294 // Ops 0 and 1 are swapped.2295 return EmitX86FunnelShift(*this, Ops[1], Ops[0], Ops[2], true);2296 2297 // Reductions2298 case X86::BI__builtin_ia32_reduce_fadd_pd512:2299 case X86::BI__builtin_ia32_reduce_fadd_ps512:2300 case X86::BI__builtin_ia32_reduce_fadd_ph512:2301 case X86::BI__builtin_ia32_reduce_fadd_ph256:2302 case X86::BI__builtin_ia32_reduce_fadd_ph128: {2303 Function *F =2304 CGM.getIntrinsic(Intrinsic::vector_reduce_fadd, Ops[1]->getType());2305 IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);2306 Builder.getFastMathFlags().setAllowReassoc();2307 return Builder.CreateCall(F, {Ops[0], Ops[1]});2308 }2309 case X86::BI__builtin_ia32_reduce_fmul_pd512:2310 case X86::BI__builtin_ia32_reduce_fmul_ps512:2311 case X86::BI__builtin_ia32_reduce_fmul_ph512:2312 case X86::BI__builtin_ia32_reduce_fmul_ph256:2313 case X86::BI__builtin_ia32_reduce_fmul_ph128: {2314 Function *F =2315 CGM.getIntrinsic(Intrinsic::vector_reduce_fmul, Ops[1]->getType());2316 IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);2317 Builder.getFastMathFlags().setAllowReassoc();2318 return Builder.CreateCall(F, {Ops[0], Ops[1]});2319 }2320 case X86::BI__builtin_ia32_reduce_fmax_pd512:2321 case X86::BI__builtin_ia32_reduce_fmax_ps512:2322 case X86::BI__builtin_ia32_reduce_fmax_ph512:2323 case X86::BI__builtin_ia32_reduce_fmax_ph256:2324 case X86::BI__builtin_ia32_reduce_fmax_ph128: {2325 Function *F =2326 CGM.getIntrinsic(Intrinsic::vector_reduce_fmax, Ops[0]->getType());2327 IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);2328 Builder.getFastMathFlags().setNoNaNs();2329 return Builder.CreateCall(F, {Ops[0]});2330 }2331 case X86::BI__builtin_ia32_reduce_fmin_pd512:2332 case X86::BI__builtin_ia32_reduce_fmin_ps512:2333 case X86::BI__builtin_ia32_reduce_fmin_ph512:2334 case X86::BI__builtin_ia32_reduce_fmin_ph256:2335 case X86::BI__builtin_ia32_reduce_fmin_ph128: {2336 Function *F =2337 CGM.getIntrinsic(Intrinsic::vector_reduce_fmin, Ops[0]->getType());2338 IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);2339 Builder.getFastMathFlags().setNoNaNs();2340 return Builder.CreateCall(F, {Ops[0]});2341 }2342 2343 case X86::BI__builtin_ia32_rdrand16_step:2344 case X86::BI__builtin_ia32_rdrand32_step:2345 case X86::BI__builtin_ia32_rdrand64_step:2346 case X86::BI__builtin_ia32_rdseed16_step:2347 case X86::BI__builtin_ia32_rdseed32_step:2348 case X86::BI__builtin_ia32_rdseed64_step: {2349 Intrinsic::ID ID;2350 switch (BuiltinID) {2351 default: llvm_unreachable("Unsupported intrinsic!");2352 case X86::BI__builtin_ia32_rdrand16_step:2353 ID = Intrinsic::x86_rdrand_16;2354 break;2355 case X86::BI__builtin_ia32_rdrand32_step:2356 ID = Intrinsic::x86_rdrand_32;2357 break;2358 case X86::BI__builtin_ia32_rdrand64_step:2359 ID = Intrinsic::x86_rdrand_64;2360 break;2361 case X86::BI__builtin_ia32_rdseed16_step:2362 ID = Intrinsic::x86_rdseed_16;2363 break;2364 case X86::BI__builtin_ia32_rdseed32_step:2365 ID = Intrinsic::x86_rdseed_32;2366 break;2367 case X86::BI__builtin_ia32_rdseed64_step:2368 ID = Intrinsic::x86_rdseed_64;2369 break;2370 }2371 2372 Value *Call = Builder.CreateCall(CGM.getIntrinsic(ID));2373 Builder.CreateDefaultAlignedStore(Builder.CreateExtractValue(Call, 0),2374 Ops[0]);2375 return Builder.CreateExtractValue(Call, 1);2376 }2377 case X86::BI__builtin_ia32_addcarryx_u32:2378 case X86::BI__builtin_ia32_addcarryx_u64:2379 case X86::BI__builtin_ia32_subborrow_u32:2380 case X86::BI__builtin_ia32_subborrow_u64: {2381 Intrinsic::ID IID;2382 switch (BuiltinID) {2383 default: llvm_unreachable("Unsupported intrinsic!");2384 case X86::BI__builtin_ia32_addcarryx_u32:2385 IID = Intrinsic::x86_addcarry_32;2386 break;2387 case X86::BI__builtin_ia32_addcarryx_u64:2388 IID = Intrinsic::x86_addcarry_64;2389 break;2390 case X86::BI__builtin_ia32_subborrow_u32:2391 IID = Intrinsic::x86_subborrow_32;2392 break;2393 case X86::BI__builtin_ia32_subborrow_u64:2394 IID = Intrinsic::x86_subborrow_64;2395 break;2396 }2397 2398 Value *Call = Builder.CreateCall(CGM.getIntrinsic(IID),2399 { Ops[0], Ops[1], Ops[2] });2400 Builder.CreateDefaultAlignedStore(Builder.CreateExtractValue(Call, 1),2401 Ops[3]);2402 return Builder.CreateExtractValue(Call, 0);2403 }2404 2405 case X86::BI__builtin_ia32_fpclassps128_mask:2406 case X86::BI__builtin_ia32_fpclassps256_mask:2407 case X86::BI__builtin_ia32_fpclassps512_mask:2408 case X86::BI__builtin_ia32_vfpclassbf16128_mask:2409 case X86::BI__builtin_ia32_vfpclassbf16256_mask:2410 case X86::BI__builtin_ia32_vfpclassbf16512_mask:2411 case X86::BI__builtin_ia32_fpclassph128_mask:2412 case X86::BI__builtin_ia32_fpclassph256_mask:2413 case X86::BI__builtin_ia32_fpclassph512_mask:2414 case X86::BI__builtin_ia32_fpclasspd128_mask:2415 case X86::BI__builtin_ia32_fpclasspd256_mask:2416 case X86::BI__builtin_ia32_fpclasspd512_mask: {2417 unsigned NumElts =2418 cast<llvm::FixedVectorType>(Ops[0]->getType())->getNumElements();2419 Value *MaskIn = Ops[2];2420 Ops.erase(&Ops[2]);2421 2422 Intrinsic::ID ID;2423 switch (BuiltinID) {2424 default: llvm_unreachable("Unsupported intrinsic!");2425 case X86::BI__builtin_ia32_vfpclassbf16128_mask:2426 ID = Intrinsic::x86_avx10_fpclass_bf16_128;2427 break;2428 case X86::BI__builtin_ia32_vfpclassbf16256_mask:2429 ID = Intrinsic::x86_avx10_fpclass_bf16_256;2430 break;2431 case X86::BI__builtin_ia32_vfpclassbf16512_mask:2432 ID = Intrinsic::x86_avx10_fpclass_bf16_512;2433 break;2434 case X86::BI__builtin_ia32_fpclassph128_mask:2435 ID = Intrinsic::x86_avx512fp16_fpclass_ph_128;2436 break;2437 case X86::BI__builtin_ia32_fpclassph256_mask:2438 ID = Intrinsic::x86_avx512fp16_fpclass_ph_256;2439 break;2440 case X86::BI__builtin_ia32_fpclassph512_mask:2441 ID = Intrinsic::x86_avx512fp16_fpclass_ph_512;2442 break;2443 case X86::BI__builtin_ia32_fpclassps128_mask:2444 ID = Intrinsic::x86_avx512_fpclass_ps_128;2445 break;2446 case X86::BI__builtin_ia32_fpclassps256_mask:2447 ID = Intrinsic::x86_avx512_fpclass_ps_256;2448 break;2449 case X86::BI__builtin_ia32_fpclassps512_mask:2450 ID = Intrinsic::x86_avx512_fpclass_ps_512;2451 break;2452 case X86::BI__builtin_ia32_fpclasspd128_mask:2453 ID = Intrinsic::x86_avx512_fpclass_pd_128;2454 break;2455 case X86::BI__builtin_ia32_fpclasspd256_mask:2456 ID = Intrinsic::x86_avx512_fpclass_pd_256;2457 break;2458 case X86::BI__builtin_ia32_fpclasspd512_mask:2459 ID = Intrinsic::x86_avx512_fpclass_pd_512;2460 break;2461 }2462 2463 Value *Fpclass = Builder.CreateCall(CGM.getIntrinsic(ID), Ops);2464 return EmitX86MaskedCompareResult(*this, Fpclass, NumElts, MaskIn);2465 }2466 2467 case X86::BI__builtin_ia32_vp2intersect_q_512:2468 case X86::BI__builtin_ia32_vp2intersect_q_256:2469 case X86::BI__builtin_ia32_vp2intersect_q_128:2470 case X86::BI__builtin_ia32_vp2intersect_d_512:2471 case X86::BI__builtin_ia32_vp2intersect_d_256:2472 case X86::BI__builtin_ia32_vp2intersect_d_128: {2473 unsigned NumElts =2474 cast<llvm::FixedVectorType>(Ops[0]->getType())->getNumElements();2475 Intrinsic::ID ID;2476 2477 switch (BuiltinID) {2478 default: llvm_unreachable("Unsupported intrinsic!");2479 case X86::BI__builtin_ia32_vp2intersect_q_512:2480 ID = Intrinsic::x86_avx512_vp2intersect_q_512;2481 break;2482 case X86::BI__builtin_ia32_vp2intersect_q_256:2483 ID = Intrinsic::x86_avx512_vp2intersect_q_256;2484 break;2485 case X86::BI__builtin_ia32_vp2intersect_q_128:2486 ID = Intrinsic::x86_avx512_vp2intersect_q_128;2487 break;2488 case X86::BI__builtin_ia32_vp2intersect_d_512:2489 ID = Intrinsic::x86_avx512_vp2intersect_d_512;2490 break;2491 case X86::BI__builtin_ia32_vp2intersect_d_256:2492 ID = Intrinsic::x86_avx512_vp2intersect_d_256;2493 break;2494 case X86::BI__builtin_ia32_vp2intersect_d_128:2495 ID = Intrinsic::x86_avx512_vp2intersect_d_128;2496 break;2497 }2498 2499 Value *Call = Builder.CreateCall(CGM.getIntrinsic(ID), {Ops[0], Ops[1]});2500 Value *Result = Builder.CreateExtractValue(Call, 0);2501 Result = EmitX86MaskedCompareResult(*this, Result, NumElts, nullptr);2502 Builder.CreateDefaultAlignedStore(Result, Ops[2]);2503 2504 Result = Builder.CreateExtractValue(Call, 1);2505 Result = EmitX86MaskedCompareResult(*this, Result, NumElts, nullptr);2506 return Builder.CreateDefaultAlignedStore(Result, Ops[3]);2507 }2508 2509 case X86::BI__builtin_ia32_vpmultishiftqb128:2510 case X86::BI__builtin_ia32_vpmultishiftqb256:2511 case X86::BI__builtin_ia32_vpmultishiftqb512: {2512 Intrinsic::ID ID;2513 switch (BuiltinID) {2514 default: llvm_unreachable("Unsupported intrinsic!");2515 case X86::BI__builtin_ia32_vpmultishiftqb128:2516 ID = Intrinsic::x86_avx512_pmultishift_qb_128;2517 break;2518 case X86::BI__builtin_ia32_vpmultishiftqb256:2519 ID = Intrinsic::x86_avx512_pmultishift_qb_256;2520 break;2521 case X86::BI__builtin_ia32_vpmultishiftqb512:2522 ID = Intrinsic::x86_avx512_pmultishift_qb_512;2523 break;2524 }2525 2526 return Builder.CreateCall(CGM.getIntrinsic(ID), Ops);2527 }2528 2529 case X86::BI__builtin_ia32_vpshufbitqmb128_mask:2530 case X86::BI__builtin_ia32_vpshufbitqmb256_mask:2531 case X86::BI__builtin_ia32_vpshufbitqmb512_mask: {2532 unsigned NumElts =2533 cast<llvm::FixedVectorType>(Ops[0]->getType())->getNumElements();2534 Value *MaskIn = Ops[2];2535 Ops.erase(&Ops[2]);2536 2537 Intrinsic::ID ID;2538 switch (BuiltinID) {2539 default: llvm_unreachable("Unsupported intrinsic!");2540 case X86::BI__builtin_ia32_vpshufbitqmb128_mask:2541 ID = Intrinsic::x86_avx512_vpshufbitqmb_128;2542 break;2543 case X86::BI__builtin_ia32_vpshufbitqmb256_mask:2544 ID = Intrinsic::x86_avx512_vpshufbitqmb_256;2545 break;2546 case X86::BI__builtin_ia32_vpshufbitqmb512_mask:2547 ID = Intrinsic::x86_avx512_vpshufbitqmb_512;2548 break;2549 }2550 2551 Value *Shufbit = Builder.CreateCall(CGM.getIntrinsic(ID), Ops);2552 return EmitX86MaskedCompareResult(*this, Shufbit, NumElts, MaskIn);2553 }2554 2555 // packed comparison intrinsics2556 case X86::BI__builtin_ia32_cmpeqps:2557 case X86::BI__builtin_ia32_cmpeqpd:2558 return getVectorFCmpIR(CmpInst::FCMP_OEQ, /*IsSignaling*/false);2559 case X86::BI__builtin_ia32_cmpltps:2560 case X86::BI__builtin_ia32_cmpltpd:2561 return getVectorFCmpIR(CmpInst::FCMP_OLT, /*IsSignaling*/true);2562 case X86::BI__builtin_ia32_cmpleps:2563 case X86::BI__builtin_ia32_cmplepd:2564 return getVectorFCmpIR(CmpInst::FCMP_OLE, /*IsSignaling*/true);2565 case X86::BI__builtin_ia32_cmpunordps:2566 case X86::BI__builtin_ia32_cmpunordpd:2567 return getVectorFCmpIR(CmpInst::FCMP_UNO, /*IsSignaling*/false);2568 case X86::BI__builtin_ia32_cmpneqps:2569 case X86::BI__builtin_ia32_cmpneqpd:2570 return getVectorFCmpIR(CmpInst::FCMP_UNE, /*IsSignaling*/false);2571 case X86::BI__builtin_ia32_cmpnltps:2572 case X86::BI__builtin_ia32_cmpnltpd:2573 return getVectorFCmpIR(CmpInst::FCMP_UGE, /*IsSignaling*/true);2574 case X86::BI__builtin_ia32_cmpnleps:2575 case X86::BI__builtin_ia32_cmpnlepd:2576 return getVectorFCmpIR(CmpInst::FCMP_UGT, /*IsSignaling*/true);2577 case X86::BI__builtin_ia32_cmpordps:2578 case X86::BI__builtin_ia32_cmpordpd:2579 return getVectorFCmpIR(CmpInst::FCMP_ORD, /*IsSignaling*/false);2580 case X86::BI__builtin_ia32_cmpph128_mask:2581 case X86::BI__builtin_ia32_cmpph256_mask:2582 case X86::BI__builtin_ia32_cmpph512_mask:2583 case X86::BI__builtin_ia32_cmpps128_mask:2584 case X86::BI__builtin_ia32_cmpps256_mask:2585 case X86::BI__builtin_ia32_cmpps512_mask:2586 case X86::BI__builtin_ia32_cmppd128_mask:2587 case X86::BI__builtin_ia32_cmppd256_mask:2588 case X86::BI__builtin_ia32_cmppd512_mask:2589 case X86::BI__builtin_ia32_vcmpbf16512_mask:2590 case X86::BI__builtin_ia32_vcmpbf16256_mask:2591 case X86::BI__builtin_ia32_vcmpbf16128_mask:2592 IsMaskFCmp = true;2593 [[fallthrough]];2594 case X86::BI__builtin_ia32_cmpps:2595 case X86::BI__builtin_ia32_cmpps256:2596 case X86::BI__builtin_ia32_cmppd:2597 case X86::BI__builtin_ia32_cmppd256: {2598 // Lowering vector comparisons to fcmp instructions, while2599 // ignoring signalling behaviour requested2600 // ignoring rounding mode requested2601 // This is only possible if fp-model is not strict and FENV_ACCESS is off.2602 2603 // The third argument is the comparison condition, and integer in the2604 // range [0, 31]2605 unsigned CC = cast<llvm::ConstantInt>(Ops[2])->getZExtValue() & 0x1f;2606 2607 // Lowering to IR fcmp instruction.2608 // Ignoring requested signaling behaviour,2609 // e.g. both _CMP_GT_OS & _CMP_GT_OQ are translated to FCMP_OGT.2610 FCmpInst::Predicate Pred;2611 bool IsSignaling;2612 // Predicates for 16-31 repeat the 0-15 predicates. Only the signalling2613 // behavior is inverted. We'll handle that after the switch.2614 switch (CC & 0xf) {2615 case 0x00: Pred = FCmpInst::FCMP_OEQ; IsSignaling = false; break;2616 case 0x01: Pred = FCmpInst::FCMP_OLT; IsSignaling = true; break;2617 case 0x02: Pred = FCmpInst::FCMP_OLE; IsSignaling = true; break;2618 case 0x03: Pred = FCmpInst::FCMP_UNO; IsSignaling = false; break;2619 case 0x04: Pred = FCmpInst::FCMP_UNE; IsSignaling = false; break;2620 case 0x05: Pred = FCmpInst::FCMP_UGE; IsSignaling = true; break;2621 case 0x06: Pred = FCmpInst::FCMP_UGT; IsSignaling = true; break;2622 case 0x07: Pred = FCmpInst::FCMP_ORD; IsSignaling = false; break;2623 case 0x08: Pred = FCmpInst::FCMP_UEQ; IsSignaling = false; break;2624 case 0x09: Pred = FCmpInst::FCMP_ULT; IsSignaling = true; break;2625 case 0x0a: Pred = FCmpInst::FCMP_ULE; IsSignaling = true; break;2626 case 0x0b: Pred = FCmpInst::FCMP_FALSE; IsSignaling = false; break;2627 case 0x0c: Pred = FCmpInst::FCMP_ONE; IsSignaling = false; break;2628 case 0x0d: Pred = FCmpInst::FCMP_OGE; IsSignaling = true; break;2629 case 0x0e: Pred = FCmpInst::FCMP_OGT; IsSignaling = true; break;2630 case 0x0f: Pred = FCmpInst::FCMP_TRUE; IsSignaling = false; break;2631 default: llvm_unreachable("Unhandled CC");2632 }2633 2634 // Invert the signalling behavior for 16-31.2635 if (CC & 0x10)2636 IsSignaling = !IsSignaling;2637 2638 // If the predicate is true or false and we're using constrained intrinsics,2639 // we don't have a compare intrinsic we can use. Just use the legacy X862640 // specific intrinsic.2641 // If the intrinsic is mask enabled and we're using constrained intrinsics,2642 // use the legacy X86 specific intrinsic.2643 if (Builder.getIsFPConstrained() &&2644 (Pred == FCmpInst::FCMP_TRUE || Pred == FCmpInst::FCMP_FALSE ||2645 IsMaskFCmp)) {2646 2647 Intrinsic::ID IID;2648 switch (BuiltinID) {2649 default: llvm_unreachable("Unexpected builtin");2650 case X86::BI__builtin_ia32_cmpps:2651 IID = Intrinsic::x86_sse_cmp_ps;2652 break;2653 case X86::BI__builtin_ia32_cmpps256:2654 IID = Intrinsic::x86_avx_cmp_ps_256;2655 break;2656 case X86::BI__builtin_ia32_cmppd:2657 IID = Intrinsic::x86_sse2_cmp_pd;2658 break;2659 case X86::BI__builtin_ia32_cmppd256:2660 IID = Intrinsic::x86_avx_cmp_pd_256;2661 break;2662 case X86::BI__builtin_ia32_cmpph128_mask:2663 IID = Intrinsic::x86_avx512fp16_mask_cmp_ph_128;2664 break;2665 case X86::BI__builtin_ia32_cmpph256_mask:2666 IID = Intrinsic::x86_avx512fp16_mask_cmp_ph_256;2667 break;2668 case X86::BI__builtin_ia32_cmpph512_mask:2669 IID = Intrinsic::x86_avx512fp16_mask_cmp_ph_512;2670 break;2671 case X86::BI__builtin_ia32_cmpps512_mask:2672 IID = Intrinsic::x86_avx512_mask_cmp_ps_512;2673 break;2674 case X86::BI__builtin_ia32_cmppd512_mask:2675 IID = Intrinsic::x86_avx512_mask_cmp_pd_512;2676 break;2677 case X86::BI__builtin_ia32_cmpps128_mask:2678 IID = Intrinsic::x86_avx512_mask_cmp_ps_128;2679 break;2680 case X86::BI__builtin_ia32_cmpps256_mask:2681 IID = Intrinsic::x86_avx512_mask_cmp_ps_256;2682 break;2683 case X86::BI__builtin_ia32_cmppd128_mask:2684 IID = Intrinsic::x86_avx512_mask_cmp_pd_128;2685 break;2686 case X86::BI__builtin_ia32_cmppd256_mask:2687 IID = Intrinsic::x86_avx512_mask_cmp_pd_256;2688 break;2689 }2690 2691 Function *Intr = CGM.getIntrinsic(IID);2692 if (IsMaskFCmp) {2693 unsigned NumElts =2694 cast<llvm::FixedVectorType>(Ops[0]->getType())->getNumElements();2695 Ops[3] = getMaskVecValue(*this, Ops[3], NumElts);2696 Value *Cmp = Builder.CreateCall(Intr, Ops);2697 return EmitX86MaskedCompareResult(*this, Cmp, NumElts, nullptr);2698 }2699 2700 return Builder.CreateCall(Intr, Ops);2701 }2702 2703 // Builtins without the _mask suffix return a vector of integers2704 // of the same width as the input vectors2705 if (IsMaskFCmp) {2706 // We ignore SAE if strict FP is disabled. We only keep precise2707 // exception behavior under strict FP.2708 // NOTE: If strict FP does ever go through here a CGFPOptionsRAII2709 // object will be required.2710 unsigned NumElts =2711 cast<llvm::FixedVectorType>(Ops[0]->getType())->getNumElements();2712 Value *Cmp;2713 if (IsSignaling)2714 Cmp = Builder.CreateFCmpS(Pred, Ops[0], Ops[1]);2715 else2716 Cmp = Builder.CreateFCmp(Pred, Ops[0], Ops[1]);2717 return EmitX86MaskedCompareResult(*this, Cmp, NumElts, Ops[3]);2718 }2719 2720 return getVectorFCmpIR(Pred, IsSignaling);2721 }2722 2723 // SSE scalar comparison intrinsics2724 case X86::BI__builtin_ia32_cmpeqss:2725 return getCmpIntrinsicCall(Intrinsic::x86_sse_cmp_ss, 0);2726 case X86::BI__builtin_ia32_cmpltss:2727 return getCmpIntrinsicCall(Intrinsic::x86_sse_cmp_ss, 1);2728 case X86::BI__builtin_ia32_cmpless:2729 return getCmpIntrinsicCall(Intrinsic::x86_sse_cmp_ss, 2);2730 case X86::BI__builtin_ia32_cmpunordss:2731 return getCmpIntrinsicCall(Intrinsic::x86_sse_cmp_ss, 3);2732 case X86::BI__builtin_ia32_cmpneqss:2733 return getCmpIntrinsicCall(Intrinsic::x86_sse_cmp_ss, 4);2734 case X86::BI__builtin_ia32_cmpnltss:2735 return getCmpIntrinsicCall(Intrinsic::x86_sse_cmp_ss, 5);2736 case X86::BI__builtin_ia32_cmpnless:2737 return getCmpIntrinsicCall(Intrinsic::x86_sse_cmp_ss, 6);2738 case X86::BI__builtin_ia32_cmpordss:2739 return getCmpIntrinsicCall(Intrinsic::x86_sse_cmp_ss, 7);2740 case X86::BI__builtin_ia32_cmpeqsd:2741 return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 0);2742 case X86::BI__builtin_ia32_cmpltsd:2743 return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 1);2744 case X86::BI__builtin_ia32_cmplesd:2745 return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 2);2746 case X86::BI__builtin_ia32_cmpunordsd:2747 return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 3);2748 case X86::BI__builtin_ia32_cmpneqsd:2749 return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 4);2750 case X86::BI__builtin_ia32_cmpnltsd:2751 return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 5);2752 case X86::BI__builtin_ia32_cmpnlesd:2753 return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 6);2754 case X86::BI__builtin_ia32_cmpordsd:2755 return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 7);2756 2757 // f16c half2float intrinsics2758 case X86::BI__builtin_ia32_vcvtph2ps_mask:2759 case X86::BI__builtin_ia32_vcvtph2ps256_mask:2760 case X86::BI__builtin_ia32_vcvtph2ps512_mask: {2761 CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);2762 return EmitX86CvtF16ToFloatExpr(*this, Ops, ConvertType(E->getType()));2763 }2764 2765 // AVX512 bf16 intrinsics2766 case X86::BI__builtin_ia32_cvtneps2bf16_128_mask: {2767 Ops[2] = getMaskVecValue(2768 *this, Ops[2],2769 cast<llvm::FixedVectorType>(Ops[0]->getType())->getNumElements());2770 Intrinsic::ID IID = Intrinsic::x86_avx512bf16_mask_cvtneps2bf16_128;2771 return Builder.CreateCall(CGM.getIntrinsic(IID), Ops);2772 }2773 2774 case X86::BI__builtin_ia32_cvtneps2bf16_256_mask:2775 case X86::BI__builtin_ia32_cvtneps2bf16_512_mask: {2776 Intrinsic::ID IID;2777 switch (BuiltinID) {2778 default: llvm_unreachable("Unsupported intrinsic!");2779 case X86::BI__builtin_ia32_cvtneps2bf16_256_mask:2780 IID = Intrinsic::x86_avx512bf16_cvtneps2bf16_256;2781 break;2782 case X86::BI__builtin_ia32_cvtneps2bf16_512_mask:2783 IID = Intrinsic::x86_avx512bf16_cvtneps2bf16_512;2784 break;2785 }2786 Value *Res = Builder.CreateCall(CGM.getIntrinsic(IID), Ops[0]);2787 return EmitX86Select(*this, Ops[2], Res, Ops[1]);2788 }2789 2790 case X86::BI__cpuid:2791 case X86::BI__cpuidex: {2792 Value *FuncId = EmitScalarExpr(E->getArg(1));2793 Value *SubFuncId = BuiltinID == X86::BI__cpuidex2794 ? EmitScalarExpr(E->getArg(2))2795 : llvm::ConstantInt::get(Int32Ty, 0);2796 2797 llvm::StructType *CpuidRetTy =2798 llvm::StructType::get(Int32Ty, Int32Ty, Int32Ty, Int32Ty);2799 llvm::FunctionType *FTy =2800 llvm::FunctionType::get(CpuidRetTy, {Int32Ty, Int32Ty}, false);2801 2802 StringRef Asm, Constraints;2803 if (getTarget().getTriple().getArch() == llvm::Triple::x86) {2804 Asm = "cpuid";2805 Constraints = "={ax},={bx},={cx},={dx},{ax},{cx}";2806 } else {2807 // x86-64 uses %rbx as the base register, so preserve it.2808 Asm = "xchgq %rbx, ${1:q}\n"2809 "cpuid\n"2810 "xchgq %rbx, ${1:q}";2811 Constraints = "={ax},=r,={cx},={dx},0,2";2812 }2813 2814 llvm::InlineAsm *IA = llvm::InlineAsm::get(FTy, Asm, Constraints,2815 /*hasSideEffects=*/false);2816 Value *IACall = Builder.CreateCall(IA, {FuncId, SubFuncId});2817 Value *BasePtr = EmitScalarExpr(E->getArg(0));2818 Value *Store = nullptr;2819 for (unsigned i = 0; i < 4; i++) {2820 Value *Extracted = Builder.CreateExtractValue(IACall, i);2821 Value *StorePtr = Builder.CreateConstInBoundsGEP1_32(Int32Ty, BasePtr, i);2822 Store = Builder.CreateAlignedStore(Extracted, StorePtr, getIntAlign());2823 }2824 2825 // Return the last store instruction to signal that we have emitted the2826 // the intrinsic.2827 return Store;2828 }2829 2830 case X86::BI__emul:2831 case X86::BI__emulu: {2832 llvm::Type *Int64Ty = llvm::IntegerType::get(getLLVMContext(), 64);2833 bool isSigned = (BuiltinID == X86::BI__emul);2834 Value *LHS = Builder.CreateIntCast(Ops[0], Int64Ty, isSigned);2835 Value *RHS = Builder.CreateIntCast(Ops[1], Int64Ty, isSigned);2836 return Builder.CreateMul(LHS, RHS, "", !isSigned, isSigned);2837 }2838 case X86::BI__mulh:2839 case X86::BI__umulh:2840 case X86::BI_mul128:2841 case X86::BI_umul128: {2842 llvm::Type *ResType = ConvertType(E->getType());2843 llvm::Type *Int128Ty = llvm::IntegerType::get(getLLVMContext(), 128);2844 2845 bool IsSigned = (BuiltinID == X86::BI__mulh || BuiltinID == X86::BI_mul128);2846 Value *LHS = Builder.CreateIntCast(Ops[0], Int128Ty, IsSigned);2847 Value *RHS = Builder.CreateIntCast(Ops[1], Int128Ty, IsSigned);2848 2849 Value *MulResult, *HigherBits;2850 if (IsSigned) {2851 MulResult = Builder.CreateNSWMul(LHS, RHS);2852 HigherBits = Builder.CreateAShr(MulResult, 64);2853 } else {2854 MulResult = Builder.CreateNUWMul(LHS, RHS);2855 HigherBits = Builder.CreateLShr(MulResult, 64);2856 }2857 HigherBits = Builder.CreateIntCast(HigherBits, ResType, IsSigned);2858 2859 if (BuiltinID == X86::BI__mulh || BuiltinID == X86::BI__umulh)2860 return HigherBits;2861 2862 Address HighBitsAddress = EmitPointerWithAlignment(E->getArg(2));2863 Builder.CreateStore(HigherBits, HighBitsAddress);2864 return Builder.CreateIntCast(MulResult, ResType, IsSigned);2865 }2866 2867 case X86::BI__faststorefence: {2868 return Builder.CreateFence(llvm::AtomicOrdering::SequentiallyConsistent,2869 llvm::SyncScope::System);2870 }2871 case X86::BI__shiftleft128:2872 case X86::BI__shiftright128: {2873 llvm::Function *F = CGM.getIntrinsic(2874 BuiltinID == X86::BI__shiftleft128 ? Intrinsic::fshl : Intrinsic::fshr,2875 Int64Ty);2876 // Flip low/high ops and zero-extend amount to matching type.2877 // shiftleft128(Low, High, Amt) -> fshl(High, Low, Amt)2878 // shiftright128(Low, High, Amt) -> fshr(High, Low, Amt)2879 std::swap(Ops[0], Ops[1]);2880 Ops[2] = Builder.CreateZExt(Ops[2], Int64Ty);2881 return Builder.CreateCall(F, Ops);2882 }2883 case X86::BI_ReadWriteBarrier:2884 case X86::BI_ReadBarrier:2885 case X86::BI_WriteBarrier: {2886 return Builder.CreateFence(llvm::AtomicOrdering::SequentiallyConsistent,2887 llvm::SyncScope::SingleThread);2888 }2889 2890 case X86::BI_AddressOfReturnAddress: {2891 Function *F =2892 CGM.getIntrinsic(Intrinsic::addressofreturnaddress, AllocaInt8PtrTy);2893 return Builder.CreateCall(F);2894 }2895 case X86::BI__stosb: {2896 // We treat __stosb as a volatile memset - it may not generate "rep stosb"2897 // instruction, but it will create a memset that won't be optimized away.2898 return Builder.CreateMemSet(Ops[0], Ops[1], Ops[2], Align(1), true);2899 }2900 case X86::BI__ud2:2901 // llvm.trap makes a ud2a instruction on x86.2902 return EmitTrapCall(Intrinsic::trap);2903 case X86::BI__int2c: {2904 // This syscall signals a driver assertion failure in x86 NT kernels.2905 llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);2906 llvm::InlineAsm *IA =2907 llvm::InlineAsm::get(FTy, "int $$0x2c", "", /*hasSideEffects=*/true);2908 llvm::AttributeList NoReturnAttr = llvm::AttributeList::get(2909 getLLVMContext(), llvm::AttributeList::FunctionIndex,2910 llvm::Attribute::NoReturn);2911 llvm::CallInst *CI = Builder.CreateCall(IA);2912 CI->setAttributes(NoReturnAttr);2913 return CI;2914 }2915 case X86::BI__readfsbyte:2916 case X86::BI__readfsword:2917 case X86::BI__readfsdword:2918 case X86::BI__readfsqword: {2919 llvm::Type *IntTy = ConvertType(E->getType());2920 Value *Ptr = Builder.CreateIntToPtr(2921 Ops[0], llvm::PointerType::get(getLLVMContext(), 257));2922 LoadInst *Load = Builder.CreateAlignedLoad(2923 IntTy, Ptr, getContext().getTypeAlignInChars(E->getType()));2924 Load->setVolatile(true);2925 return Load;2926 }2927 case X86::BI__readgsbyte:2928 case X86::BI__readgsword:2929 case X86::BI__readgsdword:2930 case X86::BI__readgsqword: {2931 llvm::Type *IntTy = ConvertType(E->getType());2932 Value *Ptr = Builder.CreateIntToPtr(2933 Ops[0], llvm::PointerType::get(getLLVMContext(), 256));2934 LoadInst *Load = Builder.CreateAlignedLoad(2935 IntTy, Ptr, getContext().getTypeAlignInChars(E->getType()));2936 Load->setVolatile(true);2937 return Load;2938 }2939 case X86::BI__builtin_ia32_encodekey128_u32: {2940 Intrinsic::ID IID = Intrinsic::x86_encodekey128;2941 2942 Value *Call = Builder.CreateCall(CGM.getIntrinsic(IID), {Ops[0], Ops[1]});2943 2944 for (int i = 0; i < 3; ++i) {2945 Value *Extract = Builder.CreateExtractValue(Call, i + 1);2946 Value *Ptr = Builder.CreateConstGEP1_32(Int8Ty, Ops[2], i * 16);2947 Builder.CreateAlignedStore(Extract, Ptr, Align(1));2948 }2949 2950 return Builder.CreateExtractValue(Call, 0);2951 }2952 case X86::BI__builtin_ia32_encodekey256_u32: {2953 Intrinsic::ID IID = Intrinsic::x86_encodekey256;2954 2955 Value *Call =2956 Builder.CreateCall(CGM.getIntrinsic(IID), {Ops[0], Ops[1], Ops[2]});2957 2958 for (int i = 0; i < 4; ++i) {2959 Value *Extract = Builder.CreateExtractValue(Call, i + 1);2960 Value *Ptr = Builder.CreateConstGEP1_32(Int8Ty, Ops[3], i * 16);2961 Builder.CreateAlignedStore(Extract, Ptr, Align(1));2962 }2963 2964 return Builder.CreateExtractValue(Call, 0);2965 }2966 case X86::BI__builtin_ia32_aesenc128kl_u8:2967 case X86::BI__builtin_ia32_aesdec128kl_u8:2968 case X86::BI__builtin_ia32_aesenc256kl_u8:2969 case X86::BI__builtin_ia32_aesdec256kl_u8: {2970 Intrinsic::ID IID;2971 StringRef BlockName;2972 switch (BuiltinID) {2973 default:2974 llvm_unreachable("Unexpected builtin");2975 case X86::BI__builtin_ia32_aesenc128kl_u8:2976 IID = Intrinsic::x86_aesenc128kl;2977 BlockName = "aesenc128kl";2978 break;2979 case X86::BI__builtin_ia32_aesdec128kl_u8:2980 IID = Intrinsic::x86_aesdec128kl;2981 BlockName = "aesdec128kl";2982 break;2983 case X86::BI__builtin_ia32_aesenc256kl_u8:2984 IID = Intrinsic::x86_aesenc256kl;2985 BlockName = "aesenc256kl";2986 break;2987 case X86::BI__builtin_ia32_aesdec256kl_u8:2988 IID = Intrinsic::x86_aesdec256kl;2989 BlockName = "aesdec256kl";2990 break;2991 }2992 2993 Value *Call = Builder.CreateCall(CGM.getIntrinsic(IID), {Ops[1], Ops[2]});2994 2995 BasicBlock *NoError =2996 createBasicBlock(BlockName + "_no_error", this->CurFn);2997 BasicBlock *Error = createBasicBlock(BlockName + "_error", this->CurFn);2998 BasicBlock *End = createBasicBlock(BlockName + "_end", this->CurFn);2999 3000 Value *Ret = Builder.CreateExtractValue(Call, 0);3001 Value *Succ = Builder.CreateTrunc(Ret, Builder.getInt1Ty());3002 Value *Out = Builder.CreateExtractValue(Call, 1);3003 Builder.CreateCondBr(Succ, NoError, Error);3004 3005 Builder.SetInsertPoint(NoError);3006 Builder.CreateDefaultAlignedStore(Out, Ops[0]);3007 Builder.CreateBr(End);3008 3009 Builder.SetInsertPoint(Error);3010 Constant *Zero = llvm::Constant::getNullValue(Out->getType());3011 Builder.CreateDefaultAlignedStore(Zero, Ops[0]);3012 Builder.CreateBr(End);3013 3014 Builder.SetInsertPoint(End);3015 return Builder.CreateExtractValue(Call, 0);3016 }3017 case X86::BI__builtin_ia32_aesencwide128kl_u8:3018 case X86::BI__builtin_ia32_aesdecwide128kl_u8:3019 case X86::BI__builtin_ia32_aesencwide256kl_u8:3020 case X86::BI__builtin_ia32_aesdecwide256kl_u8: {3021 Intrinsic::ID IID;3022 StringRef BlockName;3023 switch (BuiltinID) {3024 case X86::BI__builtin_ia32_aesencwide128kl_u8:3025 IID = Intrinsic::x86_aesencwide128kl;3026 BlockName = "aesencwide128kl";3027 break;3028 case X86::BI__builtin_ia32_aesdecwide128kl_u8:3029 IID = Intrinsic::x86_aesdecwide128kl;3030 BlockName = "aesdecwide128kl";3031 break;3032 case X86::BI__builtin_ia32_aesencwide256kl_u8:3033 IID = Intrinsic::x86_aesencwide256kl;3034 BlockName = "aesencwide256kl";3035 break;3036 case X86::BI__builtin_ia32_aesdecwide256kl_u8:3037 IID = Intrinsic::x86_aesdecwide256kl;3038 BlockName = "aesdecwide256kl";3039 break;3040 }3041 3042 llvm::Type *Ty = FixedVectorType::get(Builder.getInt64Ty(), 2);3043 Value *InOps[9];3044 InOps[0] = Ops[2];3045 for (int i = 0; i != 8; ++i) {3046 Value *Ptr = Builder.CreateConstGEP1_32(Ty, Ops[1], i);3047 InOps[i + 1] = Builder.CreateAlignedLoad(Ty, Ptr, Align(16));3048 }3049 3050 Value *Call = Builder.CreateCall(CGM.getIntrinsic(IID), InOps);3051 3052 BasicBlock *NoError =3053 createBasicBlock(BlockName + "_no_error", this->CurFn);3054 BasicBlock *Error = createBasicBlock(BlockName + "_error", this->CurFn);3055 BasicBlock *End = createBasicBlock(BlockName + "_end", this->CurFn);3056 3057 Value *Ret = Builder.CreateExtractValue(Call, 0);3058 Value *Succ = Builder.CreateTrunc(Ret, Builder.getInt1Ty());3059 Builder.CreateCondBr(Succ, NoError, Error);3060 3061 Builder.SetInsertPoint(NoError);3062 for (int i = 0; i != 8; ++i) {3063 Value *Extract = Builder.CreateExtractValue(Call, i + 1);3064 Value *Ptr = Builder.CreateConstGEP1_32(Extract->getType(), Ops[0], i);3065 Builder.CreateAlignedStore(Extract, Ptr, Align(16));3066 }3067 Builder.CreateBr(End);3068 3069 Builder.SetInsertPoint(Error);3070 for (int i = 0; i != 8; ++i) {3071 Value *Out = Builder.CreateExtractValue(Call, i + 1);3072 Constant *Zero = llvm::Constant::getNullValue(Out->getType());3073 Value *Ptr = Builder.CreateConstGEP1_32(Out->getType(), Ops[0], i);3074 Builder.CreateAlignedStore(Zero, Ptr, Align(16));3075 }3076 Builder.CreateBr(End);3077 3078 Builder.SetInsertPoint(End);3079 return Builder.CreateExtractValue(Call, 0);3080 }3081 case X86::BI__builtin_ia32_vfcmaddcph512_mask:3082 IsConjFMA = true;3083 [[fallthrough]];3084 case X86::BI__builtin_ia32_vfmaddcph512_mask: {3085 Intrinsic::ID IID = IsConjFMA3086 ? Intrinsic::x86_avx512fp16_mask_vfcmadd_cph_5123087 : Intrinsic::x86_avx512fp16_mask_vfmadd_cph_512;3088 Value *Call = Builder.CreateCall(CGM.getIntrinsic(IID), Ops);3089 return EmitX86Select(*this, Ops[3], Call, Ops[0]);3090 }3091 case X86::BI__builtin_ia32_vfcmaddcsh_round_mask:3092 IsConjFMA = true;3093 [[fallthrough]];3094 case X86::BI__builtin_ia32_vfmaddcsh_round_mask: {3095 Intrinsic::ID IID = IsConjFMA ? Intrinsic::x86_avx512fp16_mask_vfcmadd_csh3096 : Intrinsic::x86_avx512fp16_mask_vfmadd_csh;3097 Value *Call = Builder.CreateCall(CGM.getIntrinsic(IID), Ops);3098 Value *And = Builder.CreateAnd(Ops[3], llvm::ConstantInt::get(Int8Ty, 1));3099 return EmitX86Select(*this, And, Call, Ops[0]);3100 }3101 case X86::BI__builtin_ia32_vfcmaddcsh_round_mask3:3102 IsConjFMA = true;3103 [[fallthrough]];3104 case X86::BI__builtin_ia32_vfmaddcsh_round_mask3: {3105 Intrinsic::ID IID = IsConjFMA ? Intrinsic::x86_avx512fp16_mask_vfcmadd_csh3106 : Intrinsic::x86_avx512fp16_mask_vfmadd_csh;3107 Value *Call = Builder.CreateCall(CGM.getIntrinsic(IID), Ops);3108 static constexpr int Mask[] = {0, 5, 6, 7};3109 return Builder.CreateShuffleVector(Call, Ops[2], Mask);3110 }3111 case X86::BI__builtin_ia32_prefetchi:3112 return Builder.CreateCall(3113 CGM.getIntrinsic(Intrinsic::prefetch, Ops[0]->getType()),3114 {Ops[0], llvm::ConstantInt::get(Int32Ty, 0), Ops[1],3115 llvm::ConstantInt::get(Int32Ty, 0)});3116 }3117}3118