Path: blob/main/contrib/llvm-project/llvm/lib/IR/IRBuilder.cpp
35233 views
//===- IRBuilder.cpp - Builder for LLVM Instrs ----------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the IRBuilder class, which is used as a convenient way9// to create LLVM instructions with a consistent and simplified interface.10//11//===----------------------------------------------------------------------===//1213#include "llvm/IR/IRBuilder.h"14#include "llvm/ADT/ArrayRef.h"15#include "llvm/IR/Constant.h"16#include "llvm/IR/Constants.h"17#include "llvm/IR/DebugInfoMetadata.h"18#include "llvm/IR/DerivedTypes.h"19#include "llvm/IR/Function.h"20#include "llvm/IR/GlobalValue.h"21#include "llvm/IR/GlobalVariable.h"22#include "llvm/IR/IntrinsicInst.h"23#include "llvm/IR/Intrinsics.h"24#include "llvm/IR/LLVMContext.h"25#include "llvm/IR/Module.h"26#include "llvm/IR/NoFolder.h"27#include "llvm/IR/Operator.h"28#include "llvm/IR/Statepoint.h"29#include "llvm/IR/Type.h"30#include "llvm/IR/Value.h"31#include "llvm/Support/Casting.h"32#include <cassert>33#include <cstdint>34#include <optional>35#include <vector>3637using namespace llvm;3839/// CreateGlobalString - Make a new global variable with an initializer that40/// has array of i8 type filled in with the nul terminated string value41/// specified. If Name is specified, it is the name of the global variable42/// created.43GlobalVariable *IRBuilderBase::CreateGlobalString(StringRef Str,44const Twine &Name,45unsigned AddressSpace,46Module *M, bool AddNull) {47Constant *StrConstant = ConstantDataArray::getString(Context, Str, AddNull);48if (!M)49M = BB->getParent()->getParent();50auto *GV = new GlobalVariable(51*M, StrConstant->getType(), true, GlobalValue::PrivateLinkage,52StrConstant, Name, nullptr, GlobalVariable::NotThreadLocal, AddressSpace);53GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);54GV->setAlignment(Align(1));55return GV;56}5758Type *IRBuilderBase::getCurrentFunctionReturnType() const {59assert(BB && BB->getParent() && "No current function!");60return BB->getParent()->getReturnType();61}6263DebugLoc IRBuilderBase::getCurrentDebugLocation() const {64for (auto &KV : MetadataToCopy)65if (KV.first == LLVMContext::MD_dbg)66return {cast<DILocation>(KV.second)};6768return {};69}70void IRBuilderBase::SetInstDebugLocation(Instruction *I) const {71for (const auto &KV : MetadataToCopy)72if (KV.first == LLVMContext::MD_dbg) {73I->setDebugLoc(DebugLoc(KV.second));74return;75}76}7778CallInst *79IRBuilderBase::createCallHelper(Function *Callee, ArrayRef<Value *> Ops,80const Twine &Name, Instruction *FMFSource,81ArrayRef<OperandBundleDef> OpBundles) {82CallInst *CI = CreateCall(Callee, Ops, OpBundles, Name);83if (FMFSource)84CI->copyFastMathFlags(FMFSource);85return CI;86}8788Value *IRBuilderBase::CreateVScale(Constant *Scaling, const Twine &Name) {89assert(isa<ConstantInt>(Scaling) && "Expected constant integer");90if (cast<ConstantInt>(Scaling)->isZero())91return Scaling;92Module *M = GetInsertBlock()->getParent()->getParent();93Function *TheFn =94Intrinsic::getDeclaration(M, Intrinsic::vscale, {Scaling->getType()});95CallInst *CI = CreateCall(TheFn, {}, {}, Name);96return cast<ConstantInt>(Scaling)->isOne() ? CI : CreateMul(CI, Scaling);97}9899Value *IRBuilderBase::CreateElementCount(Type *DstType, ElementCount EC) {100Constant *MinEC = ConstantInt::get(DstType, EC.getKnownMinValue());101return EC.isScalable() ? CreateVScale(MinEC) : MinEC;102}103104Value *IRBuilderBase::CreateTypeSize(Type *DstType, TypeSize Size) {105Constant *MinSize = ConstantInt::get(DstType, Size.getKnownMinValue());106return Size.isScalable() ? CreateVScale(MinSize) : MinSize;107}108109Value *IRBuilderBase::CreateStepVector(Type *DstType, const Twine &Name) {110Type *STy = DstType->getScalarType();111if (isa<ScalableVectorType>(DstType)) {112Type *StepVecType = DstType;113// TODO: We expect this special case (element type < 8 bits) to be114// temporary - once the intrinsic properly supports < 8 bits this code115// can be removed.116if (STy->getScalarSizeInBits() < 8)117StepVecType =118VectorType::get(getInt8Ty(), cast<ScalableVectorType>(DstType));119Value *Res = CreateIntrinsic(Intrinsic::experimental_stepvector,120{StepVecType}, {}, nullptr, Name);121if (StepVecType != DstType)122Res = CreateTrunc(Res, DstType);123return Res;124}125126unsigned NumEls = cast<FixedVectorType>(DstType)->getNumElements();127128// Create a vector of consecutive numbers from zero to VF.129SmallVector<Constant *, 8> Indices;130for (unsigned i = 0; i < NumEls; ++i)131Indices.push_back(ConstantInt::get(STy, i));132133// Add the consecutive indices to the vector value.134return ConstantVector::get(Indices);135}136137CallInst *IRBuilderBase::CreateMemSet(Value *Ptr, Value *Val, Value *Size,138MaybeAlign Align, bool isVolatile,139MDNode *TBAATag, MDNode *ScopeTag,140MDNode *NoAliasTag) {141Value *Ops[] = {Ptr, Val, Size, getInt1(isVolatile)};142Type *Tys[] = { Ptr->getType(), Size->getType() };143Module *M = BB->getParent()->getParent();144Function *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memset, Tys);145146CallInst *CI = CreateCall(TheFn, Ops);147148if (Align)149cast<MemSetInst>(CI)->setDestAlignment(*Align);150151// Set the TBAA info if present.152if (TBAATag)153CI->setMetadata(LLVMContext::MD_tbaa, TBAATag);154155if (ScopeTag)156CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag);157158if (NoAliasTag)159CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag);160161return CI;162}163164CallInst *IRBuilderBase::CreateMemSetInline(Value *Dst, MaybeAlign DstAlign,165Value *Val, Value *Size,166bool IsVolatile, MDNode *TBAATag,167MDNode *ScopeTag,168MDNode *NoAliasTag) {169Value *Ops[] = {Dst, Val, Size, getInt1(IsVolatile)};170Type *Tys[] = {Dst->getType(), Size->getType()};171Module *M = BB->getParent()->getParent();172Function *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memset_inline, Tys);173174CallInst *CI = CreateCall(TheFn, Ops);175176if (DstAlign)177cast<MemSetInlineInst>(CI)->setDestAlignment(*DstAlign);178179// Set the TBAA info if present.180if (TBAATag)181CI->setMetadata(LLVMContext::MD_tbaa, TBAATag);182183if (ScopeTag)184CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag);185186if (NoAliasTag)187CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag);188189return CI;190}191192CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemSet(193Value *Ptr, Value *Val, Value *Size, Align Alignment, uint32_t ElementSize,194MDNode *TBAATag, MDNode *ScopeTag, MDNode *NoAliasTag) {195196Value *Ops[] = {Ptr, Val, Size, getInt32(ElementSize)};197Type *Tys[] = {Ptr->getType(), Size->getType()};198Module *M = BB->getParent()->getParent();199Function *TheFn = Intrinsic::getDeclaration(200M, Intrinsic::memset_element_unordered_atomic, Tys);201202CallInst *CI = CreateCall(TheFn, Ops);203204cast<AtomicMemSetInst>(CI)->setDestAlignment(Alignment);205206// Set the TBAA info if present.207if (TBAATag)208CI->setMetadata(LLVMContext::MD_tbaa, TBAATag);209210if (ScopeTag)211CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag);212213if (NoAliasTag)214CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag);215216return CI;217}218219CallInst *IRBuilderBase::CreateMemTransferInst(220Intrinsic::ID IntrID, Value *Dst, MaybeAlign DstAlign, Value *Src,221MaybeAlign SrcAlign, Value *Size, bool isVolatile, MDNode *TBAATag,222MDNode *TBAAStructTag, MDNode *ScopeTag, MDNode *NoAliasTag) {223assert((IntrID == Intrinsic::memcpy || IntrID == Intrinsic::memcpy_inline ||224IntrID == Intrinsic::memmove) &&225"Unexpected intrinsic ID");226Value *Ops[] = {Dst, Src, Size, getInt1(isVolatile)};227Type *Tys[] = { Dst->getType(), Src->getType(), Size->getType() };228Module *M = BB->getParent()->getParent();229Function *TheFn = Intrinsic::getDeclaration(M, IntrID, Tys);230231CallInst *CI = CreateCall(TheFn, Ops);232233auto* MCI = cast<MemTransferInst>(CI);234if (DstAlign)235MCI->setDestAlignment(*DstAlign);236if (SrcAlign)237MCI->setSourceAlignment(*SrcAlign);238239// Set the TBAA info if present.240if (TBAATag)241CI->setMetadata(LLVMContext::MD_tbaa, TBAATag);242243// Set the TBAA Struct info if present.244if (TBAAStructTag)245CI->setMetadata(LLVMContext::MD_tbaa_struct, TBAAStructTag);246247if (ScopeTag)248CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag);249250if (NoAliasTag)251CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag);252253return CI;254}255256CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemCpy(257Value *Dst, Align DstAlign, Value *Src, Align SrcAlign, Value *Size,258uint32_t ElementSize, MDNode *TBAATag, MDNode *TBAAStructTag,259MDNode *ScopeTag, MDNode *NoAliasTag) {260assert(DstAlign >= ElementSize &&261"Pointer alignment must be at least element size");262assert(SrcAlign >= ElementSize &&263"Pointer alignment must be at least element size");264Value *Ops[] = {Dst, Src, Size, getInt32(ElementSize)};265Type *Tys[] = {Dst->getType(), Src->getType(), Size->getType()};266Module *M = BB->getParent()->getParent();267Function *TheFn = Intrinsic::getDeclaration(268M, Intrinsic::memcpy_element_unordered_atomic, Tys);269270CallInst *CI = CreateCall(TheFn, Ops);271272// Set the alignment of the pointer args.273auto *AMCI = cast<AtomicMemCpyInst>(CI);274AMCI->setDestAlignment(DstAlign);275AMCI->setSourceAlignment(SrcAlign);276277// Set the TBAA info if present.278if (TBAATag)279CI->setMetadata(LLVMContext::MD_tbaa, TBAATag);280281// Set the TBAA Struct info if present.282if (TBAAStructTag)283CI->setMetadata(LLVMContext::MD_tbaa_struct, TBAAStructTag);284285if (ScopeTag)286CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag);287288if (NoAliasTag)289CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag);290291return CI;292}293294/// isConstantOne - Return true only if val is constant int 1295static bool isConstantOne(const Value *Val) {296assert(Val && "isConstantOne does not work with nullptr Val");297const ConstantInt *CVal = dyn_cast<ConstantInt>(Val);298return CVal && CVal->isOne();299}300301CallInst *IRBuilderBase::CreateMalloc(Type *IntPtrTy, Type *AllocTy,302Value *AllocSize, Value *ArraySize,303ArrayRef<OperandBundleDef> OpB,304Function *MallocF, const Twine &Name) {305// malloc(type) becomes:306// i8* malloc(typeSize)307// malloc(type, arraySize) becomes:308// i8* malloc(typeSize*arraySize)309if (!ArraySize)310ArraySize = ConstantInt::get(IntPtrTy, 1);311else if (ArraySize->getType() != IntPtrTy)312ArraySize = CreateIntCast(ArraySize, IntPtrTy, false);313314if (!isConstantOne(ArraySize)) {315if (isConstantOne(AllocSize)) {316AllocSize = ArraySize; // Operand * 1 = Operand317} else {318// Multiply type size by the array size...319AllocSize = CreateMul(ArraySize, AllocSize, "mallocsize");320}321}322323assert(AllocSize->getType() == IntPtrTy && "malloc arg is wrong size");324// Create the call to Malloc.325Module *M = BB->getParent()->getParent();326Type *BPTy = PointerType::getUnqual(Context);327FunctionCallee MallocFunc = MallocF;328if (!MallocFunc)329// prototype malloc as "void *malloc(size_t)"330MallocFunc = M->getOrInsertFunction("malloc", BPTy, IntPtrTy);331CallInst *MCall = CreateCall(MallocFunc, AllocSize, OpB, Name);332333MCall->setTailCall();334if (Function *F = dyn_cast<Function>(MallocFunc.getCallee())) {335MCall->setCallingConv(F->getCallingConv());336F->setReturnDoesNotAlias();337}338339assert(!MCall->getType()->isVoidTy() && "Malloc has void return type");340341return MCall;342}343344CallInst *IRBuilderBase::CreateMalloc(Type *IntPtrTy, Type *AllocTy,345Value *AllocSize, Value *ArraySize,346Function *MallocF, const Twine &Name) {347348return CreateMalloc(IntPtrTy, AllocTy, AllocSize, ArraySize, std::nullopt,349MallocF, Name);350}351352/// CreateFree - Generate the IR for a call to the builtin free function.353CallInst *IRBuilderBase::CreateFree(Value *Source,354ArrayRef<OperandBundleDef> Bundles) {355assert(Source->getType()->isPointerTy() &&356"Can not free something of nonpointer type!");357358Module *M = BB->getParent()->getParent();359360Type *VoidTy = Type::getVoidTy(M->getContext());361Type *VoidPtrTy = PointerType::getUnqual(M->getContext());362// prototype free as "void free(void*)"363FunctionCallee FreeFunc = M->getOrInsertFunction("free", VoidTy, VoidPtrTy);364CallInst *Result = CreateCall(FreeFunc, Source, Bundles, "");365Result->setTailCall();366if (Function *F = dyn_cast<Function>(FreeFunc.getCallee()))367Result->setCallingConv(F->getCallingConv());368369return Result;370}371372CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemMove(373Value *Dst, Align DstAlign, Value *Src, Align SrcAlign, Value *Size,374uint32_t ElementSize, MDNode *TBAATag, MDNode *TBAAStructTag,375MDNode *ScopeTag, MDNode *NoAliasTag) {376assert(DstAlign >= ElementSize &&377"Pointer alignment must be at least element size");378assert(SrcAlign >= ElementSize &&379"Pointer alignment must be at least element size");380Value *Ops[] = {Dst, Src, Size, getInt32(ElementSize)};381Type *Tys[] = {Dst->getType(), Src->getType(), Size->getType()};382Module *M = BB->getParent()->getParent();383Function *TheFn = Intrinsic::getDeclaration(384M, Intrinsic::memmove_element_unordered_atomic, Tys);385386CallInst *CI = CreateCall(TheFn, Ops);387388// Set the alignment of the pointer args.389CI->addParamAttr(0, Attribute::getWithAlignment(CI->getContext(), DstAlign));390CI->addParamAttr(1, Attribute::getWithAlignment(CI->getContext(), SrcAlign));391392// Set the TBAA info if present.393if (TBAATag)394CI->setMetadata(LLVMContext::MD_tbaa, TBAATag);395396// Set the TBAA Struct info if present.397if (TBAAStructTag)398CI->setMetadata(LLVMContext::MD_tbaa_struct, TBAAStructTag);399400if (ScopeTag)401CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag);402403if (NoAliasTag)404CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag);405406return CI;407}408409CallInst *IRBuilderBase::getReductionIntrinsic(Intrinsic::ID ID, Value *Src) {410Module *M = GetInsertBlock()->getParent()->getParent();411Value *Ops[] = {Src};412Type *Tys[] = { Src->getType() };413auto Decl = Intrinsic::getDeclaration(M, ID, Tys);414return CreateCall(Decl, Ops);415}416417CallInst *IRBuilderBase::CreateFAddReduce(Value *Acc, Value *Src) {418Module *M = GetInsertBlock()->getParent()->getParent();419Value *Ops[] = {Acc, Src};420auto Decl = Intrinsic::getDeclaration(M, Intrinsic::vector_reduce_fadd,421{Src->getType()});422return CreateCall(Decl, Ops);423}424425CallInst *IRBuilderBase::CreateFMulReduce(Value *Acc, Value *Src) {426Module *M = GetInsertBlock()->getParent()->getParent();427Value *Ops[] = {Acc, Src};428auto Decl = Intrinsic::getDeclaration(M, Intrinsic::vector_reduce_fmul,429{Src->getType()});430return CreateCall(Decl, Ops);431}432433CallInst *IRBuilderBase::CreateAddReduce(Value *Src) {434return getReductionIntrinsic(Intrinsic::vector_reduce_add, Src);435}436437CallInst *IRBuilderBase::CreateMulReduce(Value *Src) {438return getReductionIntrinsic(Intrinsic::vector_reduce_mul, Src);439}440441CallInst *IRBuilderBase::CreateAndReduce(Value *Src) {442return getReductionIntrinsic(Intrinsic::vector_reduce_and, Src);443}444445CallInst *IRBuilderBase::CreateOrReduce(Value *Src) {446return getReductionIntrinsic(Intrinsic::vector_reduce_or, Src);447}448449CallInst *IRBuilderBase::CreateXorReduce(Value *Src) {450return getReductionIntrinsic(Intrinsic::vector_reduce_xor, Src);451}452453CallInst *IRBuilderBase::CreateIntMaxReduce(Value *Src, bool IsSigned) {454auto ID =455IsSigned ? Intrinsic::vector_reduce_smax : Intrinsic::vector_reduce_umax;456return getReductionIntrinsic(ID, Src);457}458459CallInst *IRBuilderBase::CreateIntMinReduce(Value *Src, bool IsSigned) {460auto ID =461IsSigned ? Intrinsic::vector_reduce_smin : Intrinsic::vector_reduce_umin;462return getReductionIntrinsic(ID, Src);463}464465CallInst *IRBuilderBase::CreateFPMaxReduce(Value *Src) {466return getReductionIntrinsic(Intrinsic::vector_reduce_fmax, Src);467}468469CallInst *IRBuilderBase::CreateFPMinReduce(Value *Src) {470return getReductionIntrinsic(Intrinsic::vector_reduce_fmin, Src);471}472473CallInst *IRBuilderBase::CreateFPMaximumReduce(Value *Src) {474return getReductionIntrinsic(Intrinsic::vector_reduce_fmaximum, Src);475}476477CallInst *IRBuilderBase::CreateFPMinimumReduce(Value *Src) {478return getReductionIntrinsic(Intrinsic::vector_reduce_fminimum, Src);479}480481CallInst *IRBuilderBase::CreateLifetimeStart(Value *Ptr, ConstantInt *Size) {482assert(isa<PointerType>(Ptr->getType()) &&483"lifetime.start only applies to pointers.");484if (!Size)485Size = getInt64(-1);486else487assert(Size->getType() == getInt64Ty() &&488"lifetime.start requires the size to be an i64");489Value *Ops[] = { Size, Ptr };490Module *M = BB->getParent()->getParent();491Function *TheFn =492Intrinsic::getDeclaration(M, Intrinsic::lifetime_start, {Ptr->getType()});493return CreateCall(TheFn, Ops);494}495496CallInst *IRBuilderBase::CreateLifetimeEnd(Value *Ptr, ConstantInt *Size) {497assert(isa<PointerType>(Ptr->getType()) &&498"lifetime.end only applies to pointers.");499if (!Size)500Size = getInt64(-1);501else502assert(Size->getType() == getInt64Ty() &&503"lifetime.end requires the size to be an i64");504Value *Ops[] = { Size, Ptr };505Module *M = BB->getParent()->getParent();506Function *TheFn =507Intrinsic::getDeclaration(M, Intrinsic::lifetime_end, {Ptr->getType()});508return CreateCall(TheFn, Ops);509}510511CallInst *IRBuilderBase::CreateInvariantStart(Value *Ptr, ConstantInt *Size) {512513assert(isa<PointerType>(Ptr->getType()) &&514"invariant.start only applies to pointers.");515if (!Size)516Size = getInt64(-1);517else518assert(Size->getType() == getInt64Ty() &&519"invariant.start requires the size to be an i64");520521Value *Ops[] = {Size, Ptr};522// Fill in the single overloaded type: memory object type.523Type *ObjectPtr[1] = {Ptr->getType()};524Module *M = BB->getParent()->getParent();525Function *TheFn =526Intrinsic::getDeclaration(M, Intrinsic::invariant_start, ObjectPtr);527return CreateCall(TheFn, Ops);528}529530static MaybeAlign getAlign(Value *Ptr) {531if (auto *O = dyn_cast<GlobalObject>(Ptr))532return O->getAlign();533if (auto *A = dyn_cast<GlobalAlias>(Ptr))534return A->getAliaseeObject()->getAlign();535return {};536}537538CallInst *IRBuilderBase::CreateThreadLocalAddress(Value *Ptr) {539assert(isa<GlobalValue>(Ptr) && cast<GlobalValue>(Ptr)->isThreadLocal() &&540"threadlocal_address only applies to thread local variables.");541CallInst *CI = CreateIntrinsic(llvm::Intrinsic::threadlocal_address,542{Ptr->getType()}, {Ptr});543if (MaybeAlign A = getAlign(Ptr)) {544CI->addParamAttr(0, Attribute::getWithAlignment(CI->getContext(), *A));545CI->addRetAttr(Attribute::getWithAlignment(CI->getContext(), *A));546}547return CI;548}549550CallInst *551IRBuilderBase::CreateAssumption(Value *Cond,552ArrayRef<OperandBundleDef> OpBundles) {553assert(Cond->getType() == getInt1Ty() &&554"an assumption condition must be of type i1");555556Value *Ops[] = { Cond };557Module *M = BB->getParent()->getParent();558Function *FnAssume = Intrinsic::getDeclaration(M, Intrinsic::assume);559return CreateCall(FnAssume, Ops, OpBundles);560}561562Instruction *IRBuilderBase::CreateNoAliasScopeDeclaration(Value *Scope) {563Module *M = BB->getModule();564auto *FnIntrinsic = Intrinsic::getDeclaration(565M, Intrinsic::experimental_noalias_scope_decl, {});566return CreateCall(FnIntrinsic, {Scope});567}568569/// Create a call to a Masked Load intrinsic.570/// \p Ty - vector type to load571/// \p Ptr - base pointer for the load572/// \p Alignment - alignment of the source location573/// \p Mask - vector of booleans which indicates what vector lanes should574/// be accessed in memory575/// \p PassThru - pass-through value that is used to fill the masked-off lanes576/// of the result577/// \p Name - name of the result variable578CallInst *IRBuilderBase::CreateMaskedLoad(Type *Ty, Value *Ptr, Align Alignment,579Value *Mask, Value *PassThru,580const Twine &Name) {581auto *PtrTy = cast<PointerType>(Ptr->getType());582assert(Ty->isVectorTy() && "Type should be vector");583assert(Mask && "Mask should not be all-ones (null)");584if (!PassThru)585PassThru = PoisonValue::get(Ty);586Type *OverloadedTypes[] = { Ty, PtrTy };587Value *Ops[] = {Ptr, getInt32(Alignment.value()), Mask, PassThru};588return CreateMaskedIntrinsic(Intrinsic::masked_load, Ops,589OverloadedTypes, Name);590}591592/// Create a call to a Masked Store intrinsic.593/// \p Val - data to be stored,594/// \p Ptr - base pointer for the store595/// \p Alignment - alignment of the destination location596/// \p Mask - vector of booleans which indicates what vector lanes should597/// be accessed in memory598CallInst *IRBuilderBase::CreateMaskedStore(Value *Val, Value *Ptr,599Align Alignment, Value *Mask) {600auto *PtrTy = cast<PointerType>(Ptr->getType());601Type *DataTy = Val->getType();602assert(DataTy->isVectorTy() && "Val should be a vector");603assert(Mask && "Mask should not be all-ones (null)");604Type *OverloadedTypes[] = { DataTy, PtrTy };605Value *Ops[] = {Val, Ptr, getInt32(Alignment.value()), Mask};606return CreateMaskedIntrinsic(Intrinsic::masked_store, Ops, OverloadedTypes);607}608609/// Create a call to a Masked intrinsic, with given intrinsic Id,610/// an array of operands - Ops, and an array of overloaded types -611/// OverloadedTypes.612CallInst *IRBuilderBase::CreateMaskedIntrinsic(Intrinsic::ID Id,613ArrayRef<Value *> Ops,614ArrayRef<Type *> OverloadedTypes,615const Twine &Name) {616Module *M = BB->getParent()->getParent();617Function *TheFn = Intrinsic::getDeclaration(M, Id, OverloadedTypes);618return CreateCall(TheFn, Ops, {}, Name);619}620621/// Create a call to a Masked Gather intrinsic.622/// \p Ty - vector type to gather623/// \p Ptrs - vector of pointers for loading624/// \p Align - alignment for one element625/// \p Mask - vector of booleans which indicates what vector lanes should626/// be accessed in memory627/// \p PassThru - pass-through value that is used to fill the masked-off lanes628/// of the result629/// \p Name - name of the result variable630CallInst *IRBuilderBase::CreateMaskedGather(Type *Ty, Value *Ptrs,631Align Alignment, Value *Mask,632Value *PassThru,633const Twine &Name) {634auto *VecTy = cast<VectorType>(Ty);635ElementCount NumElts = VecTy->getElementCount();636auto *PtrsTy = cast<VectorType>(Ptrs->getType());637assert(NumElts == PtrsTy->getElementCount() && "Element count mismatch");638639if (!Mask)640Mask = getAllOnesMask(NumElts);641642if (!PassThru)643PassThru = PoisonValue::get(Ty);644645Type *OverloadedTypes[] = {Ty, PtrsTy};646Value *Ops[] = {Ptrs, getInt32(Alignment.value()), Mask, PassThru};647648// We specify only one type when we create this intrinsic. Types of other649// arguments are derived from this type.650return CreateMaskedIntrinsic(Intrinsic::masked_gather, Ops, OverloadedTypes,651Name);652}653654/// Create a call to a Masked Scatter intrinsic.655/// \p Data - data to be stored,656/// \p Ptrs - the vector of pointers, where the \p Data elements should be657/// stored658/// \p Align - alignment for one element659/// \p Mask - vector of booleans which indicates what vector lanes should660/// be accessed in memory661CallInst *IRBuilderBase::CreateMaskedScatter(Value *Data, Value *Ptrs,662Align Alignment, Value *Mask) {663auto *PtrsTy = cast<VectorType>(Ptrs->getType());664auto *DataTy = cast<VectorType>(Data->getType());665ElementCount NumElts = PtrsTy->getElementCount();666667if (!Mask)668Mask = getAllOnesMask(NumElts);669670Type *OverloadedTypes[] = {DataTy, PtrsTy};671Value *Ops[] = {Data, Ptrs, getInt32(Alignment.value()), Mask};672673// We specify only one type when we create this intrinsic. Types of other674// arguments are derived from this type.675return CreateMaskedIntrinsic(Intrinsic::masked_scatter, Ops, OverloadedTypes);676}677678/// Create a call to Masked Expand Load intrinsic679/// \p Ty - vector type to load680/// \p Ptr - base pointer for the load681/// \p Mask - vector of booleans which indicates what vector lanes should682/// be accessed in memory683/// \p PassThru - pass-through value that is used to fill the masked-off lanes684/// of the result685/// \p Name - name of the result variable686CallInst *IRBuilderBase::CreateMaskedExpandLoad(Type *Ty, Value *Ptr,687Value *Mask, Value *PassThru,688const Twine &Name) {689assert(Ty->isVectorTy() && "Type should be vector");690assert(Mask && "Mask should not be all-ones (null)");691if (!PassThru)692PassThru = PoisonValue::get(Ty);693Type *OverloadedTypes[] = {Ty};694Value *Ops[] = {Ptr, Mask, PassThru};695return CreateMaskedIntrinsic(Intrinsic::masked_expandload, Ops,696OverloadedTypes, Name);697}698699/// Create a call to Masked Compress Store intrinsic700/// \p Val - data to be stored,701/// \p Ptr - base pointer for the store702/// \p Mask - vector of booleans which indicates what vector lanes should703/// be accessed in memory704CallInst *IRBuilderBase::CreateMaskedCompressStore(Value *Val, Value *Ptr,705Value *Mask) {706Type *DataTy = Val->getType();707assert(DataTy->isVectorTy() && "Val should be a vector");708assert(Mask && "Mask should not be all-ones (null)");709Type *OverloadedTypes[] = {DataTy};710Value *Ops[] = {Val, Ptr, Mask};711return CreateMaskedIntrinsic(Intrinsic::masked_compressstore, Ops,712OverloadedTypes);713}714715template <typename T0>716static std::vector<Value *>717getStatepointArgs(IRBuilderBase &B, uint64_t ID, uint32_t NumPatchBytes,718Value *ActualCallee, uint32_t Flags, ArrayRef<T0> CallArgs) {719std::vector<Value *> Args;720Args.push_back(B.getInt64(ID));721Args.push_back(B.getInt32(NumPatchBytes));722Args.push_back(ActualCallee);723Args.push_back(B.getInt32(CallArgs.size()));724Args.push_back(B.getInt32(Flags));725llvm::append_range(Args, CallArgs);726// GC Transition and Deopt args are now always handled via operand bundle.727// They will be removed from the signature of gc.statepoint shortly.728Args.push_back(B.getInt32(0));729Args.push_back(B.getInt32(0));730// GC args are now encoded in the gc-live operand bundle731return Args;732}733734template<typename T1, typename T2, typename T3>735static std::vector<OperandBundleDef>736getStatepointBundles(std::optional<ArrayRef<T1>> TransitionArgs,737std::optional<ArrayRef<T2>> DeoptArgs,738ArrayRef<T3> GCArgs) {739std::vector<OperandBundleDef> Rval;740if (DeoptArgs) {741SmallVector<Value*, 16> DeoptValues;742llvm::append_range(DeoptValues, *DeoptArgs);743Rval.emplace_back("deopt", DeoptValues);744}745if (TransitionArgs) {746SmallVector<Value*, 16> TransitionValues;747llvm::append_range(TransitionValues, *TransitionArgs);748Rval.emplace_back("gc-transition", TransitionValues);749}750if (GCArgs.size()) {751SmallVector<Value*, 16> LiveValues;752llvm::append_range(LiveValues, GCArgs);753Rval.emplace_back("gc-live", LiveValues);754}755return Rval;756}757758template <typename T0, typename T1, typename T2, typename T3>759static CallInst *CreateGCStatepointCallCommon(760IRBuilderBase *Builder, uint64_t ID, uint32_t NumPatchBytes,761FunctionCallee ActualCallee, uint32_t Flags, ArrayRef<T0> CallArgs,762std::optional<ArrayRef<T1>> TransitionArgs,763std::optional<ArrayRef<T2>> DeoptArgs, ArrayRef<T3> GCArgs,764const Twine &Name) {765Module *M = Builder->GetInsertBlock()->getParent()->getParent();766// Fill in the one generic type'd argument (the function is also vararg)767Function *FnStatepoint =768Intrinsic::getDeclaration(M, Intrinsic::experimental_gc_statepoint,769{ActualCallee.getCallee()->getType()});770771std::vector<Value *> Args = getStatepointArgs(772*Builder, ID, NumPatchBytes, ActualCallee.getCallee(), Flags, CallArgs);773774CallInst *CI = Builder->CreateCall(775FnStatepoint, Args,776getStatepointBundles(TransitionArgs, DeoptArgs, GCArgs), Name);777CI->addParamAttr(2,778Attribute::get(Builder->getContext(), Attribute::ElementType,779ActualCallee.getFunctionType()));780return CI;781}782783CallInst *IRBuilderBase::CreateGCStatepointCall(784uint64_t ID, uint32_t NumPatchBytes, FunctionCallee ActualCallee,785ArrayRef<Value *> CallArgs, std::optional<ArrayRef<Value *>> DeoptArgs,786ArrayRef<Value *> GCArgs, const Twine &Name) {787return CreateGCStatepointCallCommon<Value *, Value *, Value *, Value *>(788this, ID, NumPatchBytes, ActualCallee, uint32_t(StatepointFlags::None),789CallArgs, std::nullopt /* No Transition Args */, DeoptArgs, GCArgs, Name);790}791792CallInst *IRBuilderBase::CreateGCStatepointCall(793uint64_t ID, uint32_t NumPatchBytes, FunctionCallee ActualCallee,794uint32_t Flags, ArrayRef<Value *> CallArgs,795std::optional<ArrayRef<Use>> TransitionArgs,796std::optional<ArrayRef<Use>> DeoptArgs, ArrayRef<Value *> GCArgs,797const Twine &Name) {798return CreateGCStatepointCallCommon<Value *, Use, Use, Value *>(799this, ID, NumPatchBytes, ActualCallee, Flags, CallArgs, TransitionArgs,800DeoptArgs, GCArgs, Name);801}802803CallInst *IRBuilderBase::CreateGCStatepointCall(804uint64_t ID, uint32_t NumPatchBytes, FunctionCallee ActualCallee,805ArrayRef<Use> CallArgs, std::optional<ArrayRef<Value *>> DeoptArgs,806ArrayRef<Value *> GCArgs, const Twine &Name) {807return CreateGCStatepointCallCommon<Use, Value *, Value *, Value *>(808this, ID, NumPatchBytes, ActualCallee, uint32_t(StatepointFlags::None),809CallArgs, std::nullopt, DeoptArgs, GCArgs, Name);810}811812template <typename T0, typename T1, typename T2, typename T3>813static InvokeInst *CreateGCStatepointInvokeCommon(814IRBuilderBase *Builder, uint64_t ID, uint32_t NumPatchBytes,815FunctionCallee ActualInvokee, BasicBlock *NormalDest,816BasicBlock *UnwindDest, uint32_t Flags, ArrayRef<T0> InvokeArgs,817std::optional<ArrayRef<T1>> TransitionArgs,818std::optional<ArrayRef<T2>> DeoptArgs, ArrayRef<T3> GCArgs,819const Twine &Name) {820Module *M = Builder->GetInsertBlock()->getParent()->getParent();821// Fill in the one generic type'd argument (the function is also vararg)822Function *FnStatepoint =823Intrinsic::getDeclaration(M, Intrinsic::experimental_gc_statepoint,824{ActualInvokee.getCallee()->getType()});825826std::vector<Value *> Args =827getStatepointArgs(*Builder, ID, NumPatchBytes, ActualInvokee.getCallee(),828Flags, InvokeArgs);829830InvokeInst *II = Builder->CreateInvoke(831FnStatepoint, NormalDest, UnwindDest, Args,832getStatepointBundles(TransitionArgs, DeoptArgs, GCArgs), Name);833II->addParamAttr(2,834Attribute::get(Builder->getContext(), Attribute::ElementType,835ActualInvokee.getFunctionType()));836return II;837}838839InvokeInst *IRBuilderBase::CreateGCStatepointInvoke(840uint64_t ID, uint32_t NumPatchBytes, FunctionCallee ActualInvokee,841BasicBlock *NormalDest, BasicBlock *UnwindDest,842ArrayRef<Value *> InvokeArgs, std::optional<ArrayRef<Value *>> DeoptArgs,843ArrayRef<Value *> GCArgs, const Twine &Name) {844return CreateGCStatepointInvokeCommon<Value *, Value *, Value *, Value *>(845this, ID, NumPatchBytes, ActualInvokee, NormalDest, UnwindDest,846uint32_t(StatepointFlags::None), InvokeArgs,847std::nullopt /* No Transition Args*/, DeoptArgs, GCArgs, Name);848}849850InvokeInst *IRBuilderBase::CreateGCStatepointInvoke(851uint64_t ID, uint32_t NumPatchBytes, FunctionCallee ActualInvokee,852BasicBlock *NormalDest, BasicBlock *UnwindDest, uint32_t Flags,853ArrayRef<Value *> InvokeArgs, std::optional<ArrayRef<Use>> TransitionArgs,854std::optional<ArrayRef<Use>> DeoptArgs, ArrayRef<Value *> GCArgs,855const Twine &Name) {856return CreateGCStatepointInvokeCommon<Value *, Use, Use, Value *>(857this, ID, NumPatchBytes, ActualInvokee, NormalDest, UnwindDest, Flags,858InvokeArgs, TransitionArgs, DeoptArgs, GCArgs, Name);859}860861InvokeInst *IRBuilderBase::CreateGCStatepointInvoke(862uint64_t ID, uint32_t NumPatchBytes, FunctionCallee ActualInvokee,863BasicBlock *NormalDest, BasicBlock *UnwindDest, ArrayRef<Use> InvokeArgs,864std::optional<ArrayRef<Value *>> DeoptArgs, ArrayRef<Value *> GCArgs,865const Twine &Name) {866return CreateGCStatepointInvokeCommon<Use, Value *, Value *, Value *>(867this, ID, NumPatchBytes, ActualInvokee, NormalDest, UnwindDest,868uint32_t(StatepointFlags::None), InvokeArgs, std::nullopt, DeoptArgs,869GCArgs, Name);870}871872CallInst *IRBuilderBase::CreateGCResult(Instruction *Statepoint,873Type *ResultType, const Twine &Name) {874Intrinsic::ID ID = Intrinsic::experimental_gc_result;875Module *M = BB->getParent()->getParent();876Type *Types[] = {ResultType};877Function *FnGCResult = Intrinsic::getDeclaration(M, ID, Types);878879Value *Args[] = {Statepoint};880return CreateCall(FnGCResult, Args, {}, Name);881}882883CallInst *IRBuilderBase::CreateGCRelocate(Instruction *Statepoint,884int BaseOffset, int DerivedOffset,885Type *ResultType, const Twine &Name) {886Module *M = BB->getParent()->getParent();887Type *Types[] = {ResultType};888Function *FnGCRelocate =889Intrinsic::getDeclaration(M, Intrinsic::experimental_gc_relocate, Types);890891Value *Args[] = {Statepoint, getInt32(BaseOffset), getInt32(DerivedOffset)};892return CreateCall(FnGCRelocate, Args, {}, Name);893}894895CallInst *IRBuilderBase::CreateGCGetPointerBase(Value *DerivedPtr,896const Twine &Name) {897Module *M = BB->getParent()->getParent();898Type *PtrTy = DerivedPtr->getType();899Function *FnGCFindBase = Intrinsic::getDeclaration(900M, Intrinsic::experimental_gc_get_pointer_base, {PtrTy, PtrTy});901return CreateCall(FnGCFindBase, {DerivedPtr}, {}, Name);902}903904CallInst *IRBuilderBase::CreateGCGetPointerOffset(Value *DerivedPtr,905const Twine &Name) {906Module *M = BB->getParent()->getParent();907Type *PtrTy = DerivedPtr->getType();908Function *FnGCGetOffset = Intrinsic::getDeclaration(909M, Intrinsic::experimental_gc_get_pointer_offset, {PtrTy});910return CreateCall(FnGCGetOffset, {DerivedPtr}, {}, Name);911}912913CallInst *IRBuilderBase::CreateUnaryIntrinsic(Intrinsic::ID ID, Value *V,914Instruction *FMFSource,915const Twine &Name) {916Module *M = BB->getModule();917Function *Fn = Intrinsic::getDeclaration(M, ID, {V->getType()});918return createCallHelper(Fn, {V}, Name, FMFSource);919}920921Value *IRBuilderBase::CreateBinaryIntrinsic(Intrinsic::ID ID, Value *LHS,922Value *RHS, Instruction *FMFSource,923const Twine &Name) {924Module *M = BB->getModule();925Function *Fn = Intrinsic::getDeclaration(M, ID, { LHS->getType() });926if (Value *V = Folder.FoldBinaryIntrinsic(ID, LHS, RHS, Fn->getReturnType(),927FMFSource))928return V;929return createCallHelper(Fn, {LHS, RHS}, Name, FMFSource);930}931932CallInst *IRBuilderBase::CreateIntrinsic(Intrinsic::ID ID,933ArrayRef<Type *> Types,934ArrayRef<Value *> Args,935Instruction *FMFSource,936const Twine &Name) {937Module *M = BB->getModule();938Function *Fn = Intrinsic::getDeclaration(M, ID, Types);939return createCallHelper(Fn, Args, Name, FMFSource);940}941942CallInst *IRBuilderBase::CreateIntrinsic(Type *RetTy, Intrinsic::ID ID,943ArrayRef<Value *> Args,944Instruction *FMFSource,945const Twine &Name) {946Module *M = BB->getModule();947948SmallVector<Intrinsic::IITDescriptor> Table;949Intrinsic::getIntrinsicInfoTableEntries(ID, Table);950ArrayRef<Intrinsic::IITDescriptor> TableRef(Table);951952SmallVector<Type *> ArgTys;953ArgTys.reserve(Args.size());954for (auto &I : Args)955ArgTys.push_back(I->getType());956FunctionType *FTy = FunctionType::get(RetTy, ArgTys, false);957SmallVector<Type *> OverloadTys;958Intrinsic::MatchIntrinsicTypesResult Res =959matchIntrinsicSignature(FTy, TableRef, OverloadTys);960(void)Res;961assert(Res == Intrinsic::MatchIntrinsicTypes_Match && TableRef.empty() &&962"Wrong types for intrinsic!");963// TODO: Handle varargs intrinsics.964965Function *Fn = Intrinsic::getDeclaration(M, ID, OverloadTys);966return createCallHelper(Fn, Args, Name, FMFSource);967}968969CallInst *IRBuilderBase::CreateConstrainedFPBinOp(970Intrinsic::ID ID, Value *L, Value *R, Instruction *FMFSource,971const Twine &Name, MDNode *FPMathTag,972std::optional<RoundingMode> Rounding,973std::optional<fp::ExceptionBehavior> Except) {974Value *RoundingV = getConstrainedFPRounding(Rounding);975Value *ExceptV = getConstrainedFPExcept(Except);976977FastMathFlags UseFMF = FMF;978if (FMFSource)979UseFMF = FMFSource->getFastMathFlags();980981CallInst *C = CreateIntrinsic(ID, {L->getType()},982{L, R, RoundingV, ExceptV}, nullptr, Name);983setConstrainedFPCallAttr(C);984setFPAttrs(C, FPMathTag, UseFMF);985return C;986}987988CallInst *IRBuilderBase::CreateConstrainedFPUnroundedBinOp(989Intrinsic::ID ID, Value *L, Value *R, Instruction *FMFSource,990const Twine &Name, MDNode *FPMathTag,991std::optional<fp::ExceptionBehavior> Except) {992Value *ExceptV = getConstrainedFPExcept(Except);993994FastMathFlags UseFMF = FMF;995if (FMFSource)996UseFMF = FMFSource->getFastMathFlags();997998CallInst *C =999CreateIntrinsic(ID, {L->getType()}, {L, R, ExceptV}, nullptr, Name);1000setConstrainedFPCallAttr(C);1001setFPAttrs(C, FPMathTag, UseFMF);1002return C;1003}10041005Value *IRBuilderBase::CreateNAryOp(unsigned Opc, ArrayRef<Value *> Ops,1006const Twine &Name, MDNode *FPMathTag) {1007if (Instruction::isBinaryOp(Opc)) {1008assert(Ops.size() == 2 && "Invalid number of operands!");1009return CreateBinOp(static_cast<Instruction::BinaryOps>(Opc),1010Ops[0], Ops[1], Name, FPMathTag);1011}1012if (Instruction::isUnaryOp(Opc)) {1013assert(Ops.size() == 1 && "Invalid number of operands!");1014return CreateUnOp(static_cast<Instruction::UnaryOps>(Opc),1015Ops[0], Name, FPMathTag);1016}1017llvm_unreachable("Unexpected opcode!");1018}10191020CallInst *IRBuilderBase::CreateConstrainedFPCast(1021Intrinsic::ID ID, Value *V, Type *DestTy,1022Instruction *FMFSource, const Twine &Name, MDNode *FPMathTag,1023std::optional<RoundingMode> Rounding,1024std::optional<fp::ExceptionBehavior> Except) {1025Value *ExceptV = getConstrainedFPExcept(Except);10261027FastMathFlags UseFMF = FMF;1028if (FMFSource)1029UseFMF = FMFSource->getFastMathFlags();10301031CallInst *C;1032if (Intrinsic::hasConstrainedFPRoundingModeOperand(ID)) {1033Value *RoundingV = getConstrainedFPRounding(Rounding);1034C = CreateIntrinsic(ID, {DestTy, V->getType()}, {V, RoundingV, ExceptV},1035nullptr, Name);1036} else1037C = CreateIntrinsic(ID, {DestTy, V->getType()}, {V, ExceptV}, nullptr,1038Name);10391040setConstrainedFPCallAttr(C);10411042if (isa<FPMathOperator>(C))1043setFPAttrs(C, FPMathTag, UseFMF);1044return C;1045}10461047Value *IRBuilderBase::CreateFCmpHelper(1048CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name,1049MDNode *FPMathTag, bool IsSignaling) {1050if (IsFPConstrained) {1051auto ID = IsSignaling ? Intrinsic::experimental_constrained_fcmps1052: Intrinsic::experimental_constrained_fcmp;1053return CreateConstrainedFPCmp(ID, P, LHS, RHS, Name);1054}10551056if (auto *V = Folder.FoldCmp(P, LHS, RHS))1057return V;1058return Insert(setFPAttrs(new FCmpInst(P, LHS, RHS), FPMathTag, FMF), Name);1059}10601061CallInst *IRBuilderBase::CreateConstrainedFPCmp(1062Intrinsic::ID ID, CmpInst::Predicate P, Value *L, Value *R,1063const Twine &Name, std::optional<fp::ExceptionBehavior> Except) {1064Value *PredicateV = getConstrainedFPPredicate(P);1065Value *ExceptV = getConstrainedFPExcept(Except);10661067CallInst *C = CreateIntrinsic(ID, {L->getType()},1068{L, R, PredicateV, ExceptV}, nullptr, Name);1069setConstrainedFPCallAttr(C);1070return C;1071}10721073CallInst *IRBuilderBase::CreateConstrainedFPCall(1074Function *Callee, ArrayRef<Value *> Args, const Twine &Name,1075std::optional<RoundingMode> Rounding,1076std::optional<fp::ExceptionBehavior> Except) {1077llvm::SmallVector<Value *, 6> UseArgs;10781079append_range(UseArgs, Args);10801081if (Intrinsic::hasConstrainedFPRoundingModeOperand(Callee->getIntrinsicID()))1082UseArgs.push_back(getConstrainedFPRounding(Rounding));1083UseArgs.push_back(getConstrainedFPExcept(Except));10841085CallInst *C = CreateCall(Callee, UseArgs, Name);1086setConstrainedFPCallAttr(C);1087return C;1088}10891090Value *IRBuilderBase::CreateSelect(Value *C, Value *True, Value *False,1091const Twine &Name, Instruction *MDFrom) {1092if (auto *V = Folder.FoldSelect(C, True, False))1093return V;10941095SelectInst *Sel = SelectInst::Create(C, True, False);1096if (MDFrom) {1097MDNode *Prof = MDFrom->getMetadata(LLVMContext::MD_prof);1098MDNode *Unpred = MDFrom->getMetadata(LLVMContext::MD_unpredictable);1099Sel = addBranchMetadata(Sel, Prof, Unpred);1100}1101if (isa<FPMathOperator>(Sel))1102setFPAttrs(Sel, nullptr /* MDNode* */, FMF);1103return Insert(Sel, Name);1104}11051106Value *IRBuilderBase::CreatePtrDiff(Type *ElemTy, Value *LHS, Value *RHS,1107const Twine &Name) {1108assert(LHS->getType() == RHS->getType() &&1109"Pointer subtraction operand types must match!");1110Value *LHS_int = CreatePtrToInt(LHS, Type::getInt64Ty(Context));1111Value *RHS_int = CreatePtrToInt(RHS, Type::getInt64Ty(Context));1112Value *Difference = CreateSub(LHS_int, RHS_int);1113return CreateExactSDiv(Difference, ConstantExpr::getSizeOf(ElemTy),1114Name);1115}11161117Value *IRBuilderBase::CreateLaunderInvariantGroup(Value *Ptr) {1118assert(isa<PointerType>(Ptr->getType()) &&1119"launder.invariant.group only applies to pointers.");1120auto *PtrType = Ptr->getType();1121Module *M = BB->getParent()->getParent();1122Function *FnLaunderInvariantGroup = Intrinsic::getDeclaration(1123M, Intrinsic::launder_invariant_group, {PtrType});11241125assert(FnLaunderInvariantGroup->getReturnType() == PtrType &&1126FnLaunderInvariantGroup->getFunctionType()->getParamType(0) ==1127PtrType &&1128"LaunderInvariantGroup should take and return the same type");11291130return CreateCall(FnLaunderInvariantGroup, {Ptr});1131}11321133Value *IRBuilderBase::CreateStripInvariantGroup(Value *Ptr) {1134assert(isa<PointerType>(Ptr->getType()) &&1135"strip.invariant.group only applies to pointers.");11361137auto *PtrType = Ptr->getType();1138Module *M = BB->getParent()->getParent();1139Function *FnStripInvariantGroup = Intrinsic::getDeclaration(1140M, Intrinsic::strip_invariant_group, {PtrType});11411142assert(FnStripInvariantGroup->getReturnType() == PtrType &&1143FnStripInvariantGroup->getFunctionType()->getParamType(0) ==1144PtrType &&1145"StripInvariantGroup should take and return the same type");11461147return CreateCall(FnStripInvariantGroup, {Ptr});1148}11491150Value *IRBuilderBase::CreateVectorReverse(Value *V, const Twine &Name) {1151auto *Ty = cast<VectorType>(V->getType());1152if (isa<ScalableVectorType>(Ty)) {1153Module *M = BB->getParent()->getParent();1154Function *F = Intrinsic::getDeclaration(M, Intrinsic::vector_reverse, Ty);1155return Insert(CallInst::Create(F, V), Name);1156}1157// Keep the original behaviour for fixed vector1158SmallVector<int, 8> ShuffleMask;1159int NumElts = Ty->getElementCount().getKnownMinValue();1160for (int i = 0; i < NumElts; ++i)1161ShuffleMask.push_back(NumElts - i - 1);1162return CreateShuffleVector(V, ShuffleMask, Name);1163}11641165Value *IRBuilderBase::CreateVectorSplice(Value *V1, Value *V2, int64_t Imm,1166const Twine &Name) {1167assert(isa<VectorType>(V1->getType()) && "Unexpected type");1168assert(V1->getType() == V2->getType() &&1169"Splice expects matching operand types!");11701171if (auto *VTy = dyn_cast<ScalableVectorType>(V1->getType())) {1172Module *M = BB->getParent()->getParent();1173Function *F = Intrinsic::getDeclaration(M, Intrinsic::vector_splice, VTy);11741175Value *Ops[] = {V1, V2, getInt32(Imm)};1176return Insert(CallInst::Create(F, Ops), Name);1177}11781179unsigned NumElts = cast<FixedVectorType>(V1->getType())->getNumElements();1180assert(((-Imm <= NumElts) || (Imm < NumElts)) &&1181"Invalid immediate for vector splice!");11821183// Keep the original behaviour for fixed vector1184unsigned Idx = (NumElts + Imm) % NumElts;1185SmallVector<int, 8> Mask;1186for (unsigned I = 0; I < NumElts; ++I)1187Mask.push_back(Idx + I);11881189return CreateShuffleVector(V1, V2, Mask);1190}11911192Value *IRBuilderBase::CreateVectorSplat(unsigned NumElts, Value *V,1193const Twine &Name) {1194auto EC = ElementCount::getFixed(NumElts);1195return CreateVectorSplat(EC, V, Name);1196}11971198Value *IRBuilderBase::CreateVectorSplat(ElementCount EC, Value *V,1199const Twine &Name) {1200assert(EC.isNonZero() && "Cannot splat to an empty vector!");12011202// First insert it into a poison vector so we can shuffle it.1203Value *Poison = PoisonValue::get(VectorType::get(V->getType(), EC));1204V = CreateInsertElement(Poison, V, getInt64(0), Name + ".splatinsert");12051206// Shuffle the value across the desired number of elements.1207SmallVector<int, 16> Zeros;1208Zeros.resize(EC.getKnownMinValue());1209return CreateShuffleVector(V, Zeros, Name + ".splat");1210}12111212Value *IRBuilderBase::CreatePreserveArrayAccessIndex(1213Type *ElTy, Value *Base, unsigned Dimension, unsigned LastIndex,1214MDNode *DbgInfo) {1215auto *BaseType = Base->getType();1216assert(isa<PointerType>(BaseType) &&1217"Invalid Base ptr type for preserve.array.access.index.");12181219Value *LastIndexV = getInt32(LastIndex);1220Constant *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0);1221SmallVector<Value *, 4> IdxList(Dimension, Zero);1222IdxList.push_back(LastIndexV);12231224Type *ResultType = GetElementPtrInst::getGEPReturnType(Base, IdxList);12251226Module *M = BB->getParent()->getParent();1227Function *FnPreserveArrayAccessIndex = Intrinsic::getDeclaration(1228M, Intrinsic::preserve_array_access_index, {ResultType, BaseType});12291230Value *DimV = getInt32(Dimension);1231CallInst *Fn =1232CreateCall(FnPreserveArrayAccessIndex, {Base, DimV, LastIndexV});1233Fn->addParamAttr(12340, Attribute::get(Fn->getContext(), Attribute::ElementType, ElTy));1235if (DbgInfo)1236Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);12371238return Fn;1239}12401241Value *IRBuilderBase::CreatePreserveUnionAccessIndex(1242Value *Base, unsigned FieldIndex, MDNode *DbgInfo) {1243assert(isa<PointerType>(Base->getType()) &&1244"Invalid Base ptr type for preserve.union.access.index.");1245auto *BaseType = Base->getType();12461247Module *M = BB->getParent()->getParent();1248Function *FnPreserveUnionAccessIndex = Intrinsic::getDeclaration(1249M, Intrinsic::preserve_union_access_index, {BaseType, BaseType});12501251Value *DIIndex = getInt32(FieldIndex);1252CallInst *Fn =1253CreateCall(FnPreserveUnionAccessIndex, {Base, DIIndex});1254if (DbgInfo)1255Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);12561257return Fn;1258}12591260Value *IRBuilderBase::CreatePreserveStructAccessIndex(1261Type *ElTy, Value *Base, unsigned Index, unsigned FieldIndex,1262MDNode *DbgInfo) {1263auto *BaseType = Base->getType();1264assert(isa<PointerType>(BaseType) &&1265"Invalid Base ptr type for preserve.struct.access.index.");12661267Value *GEPIndex = getInt32(Index);1268Constant *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0);1269Type *ResultType =1270GetElementPtrInst::getGEPReturnType(Base, {Zero, GEPIndex});12711272Module *M = BB->getParent()->getParent();1273Function *FnPreserveStructAccessIndex = Intrinsic::getDeclaration(1274M, Intrinsic::preserve_struct_access_index, {ResultType, BaseType});12751276Value *DIIndex = getInt32(FieldIndex);1277CallInst *Fn = CreateCall(FnPreserveStructAccessIndex,1278{Base, GEPIndex, DIIndex});1279Fn->addParamAttr(12800, Attribute::get(Fn->getContext(), Attribute::ElementType, ElTy));1281if (DbgInfo)1282Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);12831284return Fn;1285}12861287Value *IRBuilderBase::createIsFPClass(Value *FPNum, unsigned Test) {1288ConstantInt *TestV = getInt32(Test);1289Module *M = BB->getParent()->getParent();1290Function *FnIsFPClass =1291Intrinsic::getDeclaration(M, Intrinsic::is_fpclass, {FPNum->getType()});1292return CreateCall(FnIsFPClass, {FPNum, TestV});1293}12941295CallInst *IRBuilderBase::CreateAlignmentAssumptionHelper(const DataLayout &DL,1296Value *PtrValue,1297Value *AlignValue,1298Value *OffsetValue) {1299SmallVector<Value *, 4> Vals({PtrValue, AlignValue});1300if (OffsetValue)1301Vals.push_back(OffsetValue);1302OperandBundleDefT<Value *> AlignOpB("align", Vals);1303return CreateAssumption(ConstantInt::getTrue(getContext()), {AlignOpB});1304}13051306CallInst *IRBuilderBase::CreateAlignmentAssumption(const DataLayout &DL,1307Value *PtrValue,1308unsigned Alignment,1309Value *OffsetValue) {1310assert(isa<PointerType>(PtrValue->getType()) &&1311"trying to create an alignment assumption on a non-pointer?");1312assert(Alignment != 0 && "Invalid Alignment");1313auto *PtrTy = cast<PointerType>(PtrValue->getType());1314Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace());1315Value *AlignValue = ConstantInt::get(IntPtrTy, Alignment);1316return CreateAlignmentAssumptionHelper(DL, PtrValue, AlignValue, OffsetValue);1317}13181319CallInst *IRBuilderBase::CreateAlignmentAssumption(const DataLayout &DL,1320Value *PtrValue,1321Value *Alignment,1322Value *OffsetValue) {1323assert(isa<PointerType>(PtrValue->getType()) &&1324"trying to create an alignment assumption on a non-pointer?");1325return CreateAlignmentAssumptionHelper(DL, PtrValue, Alignment, OffsetValue);1326}13271328IRBuilderDefaultInserter::~IRBuilderDefaultInserter() = default;1329IRBuilderCallbackInserter::~IRBuilderCallbackInserter() = default;1330IRBuilderFolder::~IRBuilderFolder() = default;1331void ConstantFolder::anchor() {}1332void NoFolder::anchor() {}133313341335