12469d7e3SRahul Joshi //===-- Intrinsics.cpp - Intrinsic Function Handling ------------*- C++ -*-===// 22469d7e3SRahul Joshi // 32469d7e3SRahul Joshi // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42469d7e3SRahul Joshi // See https://llvm.org/LICENSE.txt for license information. 52469d7e3SRahul Joshi // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 62469d7e3SRahul Joshi // 72469d7e3SRahul Joshi //===----------------------------------------------------------------------===// 82469d7e3SRahul Joshi // 92469d7e3SRahul Joshi // This file implements functions required for supporting intrinsic functions. 102469d7e3SRahul Joshi // 112469d7e3SRahul Joshi //===----------------------------------------------------------------------===// 122469d7e3SRahul Joshi 132469d7e3SRahul Joshi #include "llvm/IR/Intrinsics.h" 142469d7e3SRahul Joshi #include "llvm/ADT/StringExtras.h" 15*f4de28a6SChandler Carruth #include "llvm/ADT/StringTable.h" 162469d7e3SRahul Joshi #include "llvm/IR/Function.h" 172469d7e3SRahul Joshi #include "llvm/IR/IntrinsicsAArch64.h" 182469d7e3SRahul Joshi #include "llvm/IR/IntrinsicsAMDGPU.h" 192469d7e3SRahul Joshi #include "llvm/IR/IntrinsicsARM.h" 202469d7e3SRahul Joshi #include "llvm/IR/IntrinsicsBPF.h" 212469d7e3SRahul Joshi #include "llvm/IR/IntrinsicsHexagon.h" 222469d7e3SRahul Joshi #include "llvm/IR/IntrinsicsLoongArch.h" 232469d7e3SRahul Joshi #include "llvm/IR/IntrinsicsMips.h" 242469d7e3SRahul Joshi #include "llvm/IR/IntrinsicsNVPTX.h" 252469d7e3SRahul Joshi #include "llvm/IR/IntrinsicsPowerPC.h" 262469d7e3SRahul Joshi #include "llvm/IR/IntrinsicsR600.h" 272469d7e3SRahul Joshi #include "llvm/IR/IntrinsicsRISCV.h" 282469d7e3SRahul Joshi #include "llvm/IR/IntrinsicsS390.h" 292469d7e3SRahul Joshi #include "llvm/IR/IntrinsicsVE.h" 302469d7e3SRahul Joshi #include "llvm/IR/IntrinsicsX86.h" 312469d7e3SRahul Joshi #include "llvm/IR/IntrinsicsXCore.h" 322469d7e3SRahul Joshi #include "llvm/IR/Module.h" 332469d7e3SRahul Joshi #include "llvm/IR/Type.h" 342469d7e3SRahul Joshi 352469d7e3SRahul Joshi using namespace llvm; 362469d7e3SRahul Joshi 372469d7e3SRahul Joshi /// Table of string intrinsic names indexed by enum value. 382469d7e3SRahul Joshi #define GET_INTRINSIC_NAME_TABLE 392469d7e3SRahul Joshi #include "llvm/IR/IntrinsicImpl.inc" 402469d7e3SRahul Joshi #undef GET_INTRINSIC_NAME_TABLE 412469d7e3SRahul Joshi 422469d7e3SRahul Joshi StringRef Intrinsic::getBaseName(ID id) { 432469d7e3SRahul Joshi assert(id < num_intrinsics && "Invalid intrinsic ID!"); 44*f4de28a6SChandler Carruth return IntrinsicNameTable[IntrinsicNameOffsetTable[id]]; 452469d7e3SRahul Joshi } 462469d7e3SRahul Joshi 472469d7e3SRahul Joshi StringRef Intrinsic::getName(ID id) { 482469d7e3SRahul Joshi assert(id < num_intrinsics && "Invalid intrinsic ID!"); 493c3f19caSAdrian Kuegel assert(!Intrinsic::isOverloaded(id) && 502469d7e3SRahul Joshi "This version of getName does not support overloading"); 512469d7e3SRahul Joshi return getBaseName(id); 522469d7e3SRahul Joshi } 532469d7e3SRahul Joshi 542469d7e3SRahul Joshi /// Returns a stable mangling for the type specified for use in the name 552469d7e3SRahul Joshi /// mangling scheme used by 'any' types in intrinsic signatures. The mangling 562469d7e3SRahul Joshi /// of named types is simply their name. Manglings for unnamed types consist 572469d7e3SRahul Joshi /// of a prefix ('p' for pointers, 'a' for arrays, 'f_' for functions) 582469d7e3SRahul Joshi /// combined with the mangling of their component types. A vararg function 592469d7e3SRahul Joshi /// type will have a suffix of 'vararg'. Since function types can contain 602469d7e3SRahul Joshi /// other function types, we close a function type mangling with suffix 'f' 612469d7e3SRahul Joshi /// which can't be confused with it's prefix. This ensures we don't have 622469d7e3SRahul Joshi /// collisions between two unrelated function types. Otherwise, you might 632469d7e3SRahul Joshi /// parse ffXX as f(fXX) or f(fX)X. (X is a placeholder for any other type.) 642469d7e3SRahul Joshi /// The HasUnnamedType boolean is set if an unnamed type was encountered, 652469d7e3SRahul Joshi /// indicating that extra care must be taken to ensure a unique name. 662469d7e3SRahul Joshi static std::string getMangledTypeStr(Type *Ty, bool &HasUnnamedType) { 672469d7e3SRahul Joshi std::string Result; 682469d7e3SRahul Joshi if (PointerType *PTyp = dyn_cast<PointerType>(Ty)) { 692469d7e3SRahul Joshi Result += "p" + utostr(PTyp->getAddressSpace()); 702469d7e3SRahul Joshi } else if (ArrayType *ATyp = dyn_cast<ArrayType>(Ty)) { 712469d7e3SRahul Joshi Result += "a" + utostr(ATyp->getNumElements()) + 722469d7e3SRahul Joshi getMangledTypeStr(ATyp->getElementType(), HasUnnamedType); 732469d7e3SRahul Joshi } else if (StructType *STyp = dyn_cast<StructType>(Ty)) { 742469d7e3SRahul Joshi if (!STyp->isLiteral()) { 752469d7e3SRahul Joshi Result += "s_"; 762469d7e3SRahul Joshi if (STyp->hasName()) 772469d7e3SRahul Joshi Result += STyp->getName(); 782469d7e3SRahul Joshi else 792469d7e3SRahul Joshi HasUnnamedType = true; 802469d7e3SRahul Joshi } else { 812469d7e3SRahul Joshi Result += "sl_"; 822469d7e3SRahul Joshi for (auto *Elem : STyp->elements()) 832469d7e3SRahul Joshi Result += getMangledTypeStr(Elem, HasUnnamedType); 842469d7e3SRahul Joshi } 852469d7e3SRahul Joshi // Ensure nested structs are distinguishable. 862469d7e3SRahul Joshi Result += "s"; 872469d7e3SRahul Joshi } else if (FunctionType *FT = dyn_cast<FunctionType>(Ty)) { 882469d7e3SRahul Joshi Result += "f_" + getMangledTypeStr(FT->getReturnType(), HasUnnamedType); 892469d7e3SRahul Joshi for (size_t i = 0; i < FT->getNumParams(); i++) 902469d7e3SRahul Joshi Result += getMangledTypeStr(FT->getParamType(i), HasUnnamedType); 912469d7e3SRahul Joshi if (FT->isVarArg()) 922469d7e3SRahul Joshi Result += "vararg"; 932469d7e3SRahul Joshi // Ensure nested function types are distinguishable. 942469d7e3SRahul Joshi Result += "f"; 952469d7e3SRahul Joshi } else if (VectorType *VTy = dyn_cast<VectorType>(Ty)) { 962469d7e3SRahul Joshi ElementCount EC = VTy->getElementCount(); 972469d7e3SRahul Joshi if (EC.isScalable()) 982469d7e3SRahul Joshi Result += "nx"; 992469d7e3SRahul Joshi Result += "v" + utostr(EC.getKnownMinValue()) + 1002469d7e3SRahul Joshi getMangledTypeStr(VTy->getElementType(), HasUnnamedType); 1012469d7e3SRahul Joshi } else if (TargetExtType *TETy = dyn_cast<TargetExtType>(Ty)) { 1022469d7e3SRahul Joshi Result += "t"; 1032469d7e3SRahul Joshi Result += TETy->getName(); 1042469d7e3SRahul Joshi for (Type *ParamTy : TETy->type_params()) 1052469d7e3SRahul Joshi Result += "_" + getMangledTypeStr(ParamTy, HasUnnamedType); 1062469d7e3SRahul Joshi for (unsigned IntParam : TETy->int_params()) 1072469d7e3SRahul Joshi Result += "_" + utostr(IntParam); 1082469d7e3SRahul Joshi // Ensure nested target extension types are distinguishable. 1092469d7e3SRahul Joshi Result += "t"; 1102469d7e3SRahul Joshi } else if (Ty) { 1112469d7e3SRahul Joshi switch (Ty->getTypeID()) { 1122469d7e3SRahul Joshi default: 1132469d7e3SRahul Joshi llvm_unreachable("Unhandled type"); 1142469d7e3SRahul Joshi case Type::VoidTyID: 1152469d7e3SRahul Joshi Result += "isVoid"; 1162469d7e3SRahul Joshi break; 1172469d7e3SRahul Joshi case Type::MetadataTyID: 1182469d7e3SRahul Joshi Result += "Metadata"; 1192469d7e3SRahul Joshi break; 1202469d7e3SRahul Joshi case Type::HalfTyID: 1212469d7e3SRahul Joshi Result += "f16"; 1222469d7e3SRahul Joshi break; 1232469d7e3SRahul Joshi case Type::BFloatTyID: 1242469d7e3SRahul Joshi Result += "bf16"; 1252469d7e3SRahul Joshi break; 1262469d7e3SRahul Joshi case Type::FloatTyID: 1272469d7e3SRahul Joshi Result += "f32"; 1282469d7e3SRahul Joshi break; 1292469d7e3SRahul Joshi case Type::DoubleTyID: 1302469d7e3SRahul Joshi Result += "f64"; 1312469d7e3SRahul Joshi break; 1322469d7e3SRahul Joshi case Type::X86_FP80TyID: 1332469d7e3SRahul Joshi Result += "f80"; 1342469d7e3SRahul Joshi break; 1352469d7e3SRahul Joshi case Type::FP128TyID: 1362469d7e3SRahul Joshi Result += "f128"; 1372469d7e3SRahul Joshi break; 1382469d7e3SRahul Joshi case Type::PPC_FP128TyID: 1392469d7e3SRahul Joshi Result += "ppcf128"; 1402469d7e3SRahul Joshi break; 1412469d7e3SRahul Joshi case Type::X86_AMXTyID: 1422469d7e3SRahul Joshi Result += "x86amx"; 1432469d7e3SRahul Joshi break; 1442469d7e3SRahul Joshi case Type::IntegerTyID: 1452469d7e3SRahul Joshi Result += "i" + utostr(cast<IntegerType>(Ty)->getBitWidth()); 1462469d7e3SRahul Joshi break; 1472469d7e3SRahul Joshi } 1482469d7e3SRahul Joshi } 1492469d7e3SRahul Joshi return Result; 1502469d7e3SRahul Joshi } 1512469d7e3SRahul Joshi 1523c3f19caSAdrian Kuegel static std::string getIntrinsicNameImpl(Intrinsic::ID Id, ArrayRef<Type *> Tys, 1533c3f19caSAdrian Kuegel Module *M, FunctionType *FT, 1542469d7e3SRahul Joshi bool EarlyModuleCheck) { 1552469d7e3SRahul Joshi 1563c3f19caSAdrian Kuegel assert(Id < Intrinsic::num_intrinsics && "Invalid intrinsic ID!"); 1573c3f19caSAdrian Kuegel assert((Tys.empty() || Intrinsic::isOverloaded(Id)) && 1582469d7e3SRahul Joshi "This version of getName is for overloaded intrinsics only"); 1592469d7e3SRahul Joshi (void)EarlyModuleCheck; 1602469d7e3SRahul Joshi assert((!EarlyModuleCheck || M || 1612469d7e3SRahul Joshi !any_of(Tys, [](Type *T) { return isa<PointerType>(T); })) && 1622469d7e3SRahul Joshi "Intrinsic overloading on pointer types need to provide a Module"); 1632469d7e3SRahul Joshi bool HasUnnamedType = false; 1643c3f19caSAdrian Kuegel std::string Result(Intrinsic::getBaseName(Id)); 1652469d7e3SRahul Joshi for (Type *Ty : Tys) 1662469d7e3SRahul Joshi Result += "." + getMangledTypeStr(Ty, HasUnnamedType); 1672469d7e3SRahul Joshi if (HasUnnamedType) { 1682469d7e3SRahul Joshi assert(M && "unnamed types need a module"); 1692469d7e3SRahul Joshi if (!FT) 1703c3f19caSAdrian Kuegel FT = Intrinsic::getType(M->getContext(), Id, Tys); 1712469d7e3SRahul Joshi else 1723c3f19caSAdrian Kuegel assert((FT == Intrinsic::getType(M->getContext(), Id, Tys)) && 1732469d7e3SRahul Joshi "Provided FunctionType must match arguments"); 1742469d7e3SRahul Joshi return M->getUniqueIntrinsicName(Result, Id, FT); 1752469d7e3SRahul Joshi } 1762469d7e3SRahul Joshi return Result; 1772469d7e3SRahul Joshi } 1782469d7e3SRahul Joshi 1792469d7e3SRahul Joshi std::string Intrinsic::getName(ID Id, ArrayRef<Type *> Tys, Module *M, 1802469d7e3SRahul Joshi FunctionType *FT) { 1812469d7e3SRahul Joshi assert(M && "We need to have a Module"); 1822469d7e3SRahul Joshi return getIntrinsicNameImpl(Id, Tys, M, FT, true); 1832469d7e3SRahul Joshi } 1842469d7e3SRahul Joshi 1852469d7e3SRahul Joshi std::string Intrinsic::getNameNoUnnamedTypes(ID Id, ArrayRef<Type *> Tys) { 1862469d7e3SRahul Joshi return getIntrinsicNameImpl(Id, Tys, nullptr, nullptr, false); 1872469d7e3SRahul Joshi } 1882469d7e3SRahul Joshi 1892469d7e3SRahul Joshi /// IIT_Info - These are enumerators that describe the entries returned by the 1902469d7e3SRahul Joshi /// getIntrinsicInfoTableEntries function. 1912469d7e3SRahul Joshi /// 1922469d7e3SRahul Joshi /// Defined in Intrinsics.td. 1932469d7e3SRahul Joshi enum IIT_Info { 1942469d7e3SRahul Joshi #define GET_INTRINSIC_IITINFO 1952469d7e3SRahul Joshi #include "llvm/IR/IntrinsicImpl.inc" 1962469d7e3SRahul Joshi #undef GET_INTRINSIC_IITINFO 1972469d7e3SRahul Joshi }; 1982469d7e3SRahul Joshi 1993c3f19caSAdrian Kuegel static void 2003c3f19caSAdrian Kuegel DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos, 2012469d7e3SRahul Joshi IIT_Info LastInfo, 2023c3f19caSAdrian Kuegel SmallVectorImpl<Intrinsic::IITDescriptor> &OutputTable) { 2033c3f19caSAdrian Kuegel using namespace Intrinsic; 2043c3f19caSAdrian Kuegel 2053c3f19caSAdrian Kuegel bool IsScalableVector = (LastInfo == IIT_SCALABLE_VEC); 2062469d7e3SRahul Joshi 2072469d7e3SRahul Joshi IIT_Info Info = IIT_Info(Infos[NextElt++]); 2082469d7e3SRahul Joshi unsigned StructElts = 2; 2092469d7e3SRahul Joshi 2102469d7e3SRahul Joshi switch (Info) { 2112469d7e3SRahul Joshi case IIT_Done: 2122469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::Void, 0)); 2132469d7e3SRahul Joshi return; 2142469d7e3SRahul Joshi case IIT_VARARG: 2152469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::VarArg, 0)); 2162469d7e3SRahul Joshi return; 2172469d7e3SRahul Joshi case IIT_MMX: 2182469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::MMX, 0)); 2192469d7e3SRahul Joshi return; 2202469d7e3SRahul Joshi case IIT_AMX: 2212469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::AMX, 0)); 2222469d7e3SRahul Joshi return; 2232469d7e3SRahul Joshi case IIT_TOKEN: 2242469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::Token, 0)); 2252469d7e3SRahul Joshi return; 2262469d7e3SRahul Joshi case IIT_METADATA: 2272469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::Metadata, 0)); 2282469d7e3SRahul Joshi return; 2292469d7e3SRahul Joshi case IIT_F16: 2302469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::Half, 0)); 2312469d7e3SRahul Joshi return; 2322469d7e3SRahul Joshi case IIT_BF16: 2332469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::BFloat, 0)); 2342469d7e3SRahul Joshi return; 2352469d7e3SRahul Joshi case IIT_F32: 2362469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::Float, 0)); 2372469d7e3SRahul Joshi return; 2382469d7e3SRahul Joshi case IIT_F64: 2392469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::Double, 0)); 2402469d7e3SRahul Joshi return; 2412469d7e3SRahul Joshi case IIT_F128: 2422469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::Quad, 0)); 2432469d7e3SRahul Joshi return; 2442469d7e3SRahul Joshi case IIT_PPCF128: 2452469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::PPCQuad, 0)); 2462469d7e3SRahul Joshi return; 2472469d7e3SRahul Joshi case IIT_I1: 2482469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 1)); 2492469d7e3SRahul Joshi return; 2502469d7e3SRahul Joshi case IIT_I2: 2512469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 2)); 2522469d7e3SRahul Joshi return; 2532469d7e3SRahul Joshi case IIT_I4: 2542469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 4)); 2552469d7e3SRahul Joshi return; 2562469d7e3SRahul Joshi case IIT_AARCH64_SVCOUNT: 2572469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::AArch64Svcount, 0)); 2582469d7e3SRahul Joshi return; 2592469d7e3SRahul Joshi case IIT_I8: 2602469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 8)); 2612469d7e3SRahul Joshi return; 2622469d7e3SRahul Joshi case IIT_I16: 2632469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 16)); 2642469d7e3SRahul Joshi return; 2652469d7e3SRahul Joshi case IIT_I32: 2662469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 32)); 2672469d7e3SRahul Joshi return; 2682469d7e3SRahul Joshi case IIT_I64: 2692469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 64)); 2702469d7e3SRahul Joshi return; 2712469d7e3SRahul Joshi case IIT_I128: 2722469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 128)); 2732469d7e3SRahul Joshi return; 2742469d7e3SRahul Joshi case IIT_V1: 2752469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::getVector(1, IsScalableVector)); 2762469d7e3SRahul Joshi DecodeIITType(NextElt, Infos, Info, OutputTable); 2772469d7e3SRahul Joshi return; 2782469d7e3SRahul Joshi case IIT_V2: 2792469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::getVector(2, IsScalableVector)); 2802469d7e3SRahul Joshi DecodeIITType(NextElt, Infos, Info, OutputTable); 2812469d7e3SRahul Joshi return; 2822469d7e3SRahul Joshi case IIT_V3: 2832469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::getVector(3, IsScalableVector)); 2842469d7e3SRahul Joshi DecodeIITType(NextElt, Infos, Info, OutputTable); 2852469d7e3SRahul Joshi return; 2862469d7e3SRahul Joshi case IIT_V4: 2872469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::getVector(4, IsScalableVector)); 2882469d7e3SRahul Joshi DecodeIITType(NextElt, Infos, Info, OutputTable); 2892469d7e3SRahul Joshi return; 2902469d7e3SRahul Joshi case IIT_V6: 2912469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::getVector(6, IsScalableVector)); 2922469d7e3SRahul Joshi DecodeIITType(NextElt, Infos, Info, OutputTable); 2932469d7e3SRahul Joshi return; 2942469d7e3SRahul Joshi case IIT_V8: 2952469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::getVector(8, IsScalableVector)); 2962469d7e3SRahul Joshi DecodeIITType(NextElt, Infos, Info, OutputTable); 2972469d7e3SRahul Joshi return; 2982469d7e3SRahul Joshi case IIT_V10: 2992469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::getVector(10, IsScalableVector)); 3002469d7e3SRahul Joshi DecodeIITType(NextElt, Infos, Info, OutputTable); 3012469d7e3SRahul Joshi return; 3022469d7e3SRahul Joshi case IIT_V16: 3032469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::getVector(16, IsScalableVector)); 3042469d7e3SRahul Joshi DecodeIITType(NextElt, Infos, Info, OutputTable); 3052469d7e3SRahul Joshi return; 3062469d7e3SRahul Joshi case IIT_V32: 3072469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::getVector(32, IsScalableVector)); 3082469d7e3SRahul Joshi DecodeIITType(NextElt, Infos, Info, OutputTable); 3092469d7e3SRahul Joshi return; 3102469d7e3SRahul Joshi case IIT_V64: 3112469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::getVector(64, IsScalableVector)); 3122469d7e3SRahul Joshi DecodeIITType(NextElt, Infos, Info, OutputTable); 3132469d7e3SRahul Joshi return; 3142469d7e3SRahul Joshi case IIT_V128: 3152469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::getVector(128, IsScalableVector)); 3162469d7e3SRahul Joshi DecodeIITType(NextElt, Infos, Info, OutputTable); 3172469d7e3SRahul Joshi return; 3182469d7e3SRahul Joshi case IIT_V256: 3192469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::getVector(256, IsScalableVector)); 3202469d7e3SRahul Joshi DecodeIITType(NextElt, Infos, Info, OutputTable); 3212469d7e3SRahul Joshi return; 3222469d7e3SRahul Joshi case IIT_V512: 3232469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::getVector(512, IsScalableVector)); 3242469d7e3SRahul Joshi DecodeIITType(NextElt, Infos, Info, OutputTable); 3252469d7e3SRahul Joshi return; 3262469d7e3SRahul Joshi case IIT_V1024: 3272469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::getVector(1024, IsScalableVector)); 3282469d7e3SRahul Joshi DecodeIITType(NextElt, Infos, Info, OutputTable); 3292469d7e3SRahul Joshi return; 3302469d7e3SRahul Joshi case IIT_EXTERNREF: 3312469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, 10)); 3322469d7e3SRahul Joshi return; 3332469d7e3SRahul Joshi case IIT_FUNCREF: 3342469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, 20)); 3352469d7e3SRahul Joshi return; 3362469d7e3SRahul Joshi case IIT_PTR: 3372469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, 0)); 3382469d7e3SRahul Joshi return; 3392469d7e3SRahul Joshi case IIT_ANYPTR: // [ANYPTR addrspace] 3402469d7e3SRahul Joshi OutputTable.push_back( 3412469d7e3SRahul Joshi IITDescriptor::get(IITDescriptor::Pointer, Infos[NextElt++])); 3422469d7e3SRahul Joshi return; 3432469d7e3SRahul Joshi case IIT_ARG: { 3442469d7e3SRahul Joshi unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); 3452469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::Argument, ArgInfo)); 3462469d7e3SRahul Joshi return; 3472469d7e3SRahul Joshi } 3482469d7e3SRahul Joshi case IIT_EXTEND_ARG: { 3492469d7e3SRahul Joshi unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); 3502469d7e3SRahul Joshi OutputTable.push_back( 3512469d7e3SRahul Joshi IITDescriptor::get(IITDescriptor::ExtendArgument, ArgInfo)); 3522469d7e3SRahul Joshi return; 3532469d7e3SRahul Joshi } 3542469d7e3SRahul Joshi case IIT_TRUNC_ARG: { 3552469d7e3SRahul Joshi unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); 3562469d7e3SRahul Joshi OutputTable.push_back( 3572469d7e3SRahul Joshi IITDescriptor::get(IITDescriptor::TruncArgument, ArgInfo)); 3582469d7e3SRahul Joshi return; 3592469d7e3SRahul Joshi } 3602469d7e3SRahul Joshi case IIT_HALF_VEC_ARG: { 3612469d7e3SRahul Joshi unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); 3622469d7e3SRahul Joshi OutputTable.push_back( 3632469d7e3SRahul Joshi IITDescriptor::get(IITDescriptor::HalfVecArgument, ArgInfo)); 3642469d7e3SRahul Joshi return; 3652469d7e3SRahul Joshi } 3662469d7e3SRahul Joshi case IIT_SAME_VEC_WIDTH_ARG: { 3672469d7e3SRahul Joshi unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); 3682469d7e3SRahul Joshi OutputTable.push_back( 3692469d7e3SRahul Joshi IITDescriptor::get(IITDescriptor::SameVecWidthArgument, ArgInfo)); 3702469d7e3SRahul Joshi return; 3712469d7e3SRahul Joshi } 3722469d7e3SRahul Joshi case IIT_VEC_OF_ANYPTRS_TO_ELT: { 3732469d7e3SRahul Joshi unsigned short ArgNo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); 3742469d7e3SRahul Joshi unsigned short RefNo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); 3752469d7e3SRahul Joshi OutputTable.push_back( 3762469d7e3SRahul Joshi IITDescriptor::get(IITDescriptor::VecOfAnyPtrsToElt, ArgNo, RefNo)); 3772469d7e3SRahul Joshi return; 3782469d7e3SRahul Joshi } 3792469d7e3SRahul Joshi case IIT_EMPTYSTRUCT: 3802469d7e3SRahul Joshi OutputTable.push_back(IITDescriptor::get(IITDescriptor::Struct, 0)); 3812469d7e3SRahul Joshi return; 3822469d7e3SRahul Joshi case IIT_STRUCT9: 3832469d7e3SRahul Joshi ++StructElts; 3842469d7e3SRahul Joshi [[fallthrough]]; 3852469d7e3SRahul Joshi case IIT_STRUCT8: 3862469d7e3SRahul Joshi ++StructElts; 3872469d7e3SRahul Joshi [[fallthrough]]; 3882469d7e3SRahul Joshi case IIT_STRUCT7: 3892469d7e3SRahul Joshi ++StructElts; 3902469d7e3SRahul Joshi [[fallthrough]]; 3912469d7e3SRahul Joshi case IIT_STRUCT6: 3922469d7e3SRahul Joshi ++StructElts; 3932469d7e3SRahul Joshi [[fallthrough]]; 3942469d7e3SRahul Joshi case IIT_STRUCT5: 3952469d7e3SRahul Joshi ++StructElts; 3962469d7e3SRahul Joshi [[fallthrough]]; 3972469d7e3SRahul Joshi case IIT_STRUCT4: 3982469d7e3SRahul Joshi ++StructElts; 3992469d7e3SRahul Joshi [[fallthrough]]; 4002469d7e3SRahul Joshi case IIT_STRUCT3: 4012469d7e3SRahul Joshi ++StructElts; 4022469d7e3SRahul Joshi [[fallthrough]]; 4032469d7e3SRahul Joshi case IIT_STRUCT2: { 4042469d7e3SRahul Joshi OutputTable.push_back( 4052469d7e3SRahul Joshi IITDescriptor::get(IITDescriptor::Struct, StructElts)); 4062469d7e3SRahul Joshi 4072469d7e3SRahul Joshi for (unsigned i = 0; i != StructElts; ++i) 4082469d7e3SRahul Joshi DecodeIITType(NextElt, Infos, Info, OutputTable); 4092469d7e3SRahul Joshi return; 4102469d7e3SRahul Joshi } 4112469d7e3SRahul Joshi case IIT_SUBDIVIDE2_ARG: { 4122469d7e3SRahul Joshi unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); 4132469d7e3SRahul Joshi OutputTable.push_back( 4142469d7e3SRahul Joshi IITDescriptor::get(IITDescriptor::Subdivide2Argument, ArgInfo)); 4152469d7e3SRahul Joshi return; 4162469d7e3SRahul Joshi } 4172469d7e3SRahul Joshi case IIT_SUBDIVIDE4_ARG: { 4182469d7e3SRahul Joshi unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); 4192469d7e3SRahul Joshi OutputTable.push_back( 4202469d7e3SRahul Joshi IITDescriptor::get(IITDescriptor::Subdivide4Argument, ArgInfo)); 4212469d7e3SRahul Joshi return; 4222469d7e3SRahul Joshi } 4232469d7e3SRahul Joshi case IIT_VEC_ELEMENT: { 4242469d7e3SRahul Joshi unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); 4252469d7e3SRahul Joshi OutputTable.push_back( 4262469d7e3SRahul Joshi IITDescriptor::get(IITDescriptor::VecElementArgument, ArgInfo)); 4272469d7e3SRahul Joshi return; 4282469d7e3SRahul Joshi } 4292469d7e3SRahul Joshi case IIT_SCALABLE_VEC: { 4302469d7e3SRahul Joshi DecodeIITType(NextElt, Infos, Info, OutputTable); 4312469d7e3SRahul Joshi return; 4322469d7e3SRahul Joshi } 4332469d7e3SRahul Joshi case IIT_VEC_OF_BITCASTS_TO_INT: { 4342469d7e3SRahul Joshi unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); 4352469d7e3SRahul Joshi OutputTable.push_back( 4362469d7e3SRahul Joshi IITDescriptor::get(IITDescriptor::VecOfBitcastsToInt, ArgInfo)); 4372469d7e3SRahul Joshi return; 4382469d7e3SRahul Joshi } 4392469d7e3SRahul Joshi } 4402469d7e3SRahul Joshi llvm_unreachable("unhandled"); 4412469d7e3SRahul Joshi } 4422469d7e3SRahul Joshi 4432469d7e3SRahul Joshi #define GET_INTRINSIC_GENERATOR_GLOBAL 4442469d7e3SRahul Joshi #include "llvm/IR/IntrinsicImpl.inc" 4452469d7e3SRahul Joshi #undef GET_INTRINSIC_GENERATOR_GLOBAL 4462469d7e3SRahul Joshi 4472469d7e3SRahul Joshi void Intrinsic::getIntrinsicInfoTableEntries( 4482469d7e3SRahul Joshi ID id, SmallVectorImpl<IITDescriptor> &T) { 4492469d7e3SRahul Joshi static_assert(sizeof(IIT_Table[0]) == 2, 4502469d7e3SRahul Joshi "Expect 16-bit entries in IIT_Table"); 4512469d7e3SRahul Joshi // Check to see if the intrinsic's type was expressible by the table. 4522469d7e3SRahul Joshi uint16_t TableVal = IIT_Table[id - 1]; 4532469d7e3SRahul Joshi 4542469d7e3SRahul Joshi // Decode the TableVal into an array of IITValues. 4552469d7e3SRahul Joshi SmallVector<unsigned char> IITValues; 4562469d7e3SRahul Joshi ArrayRef<unsigned char> IITEntries; 4572469d7e3SRahul Joshi unsigned NextElt = 0; 4582469d7e3SRahul Joshi if (TableVal >> 15) { 4592469d7e3SRahul Joshi // This is an offset into the IIT_LongEncodingTable. 4602469d7e3SRahul Joshi IITEntries = IIT_LongEncodingTable; 4612469d7e3SRahul Joshi 4622469d7e3SRahul Joshi // Strip sentinel bit. 4632469d7e3SRahul Joshi NextElt = TableVal & 0x7fff; 4642469d7e3SRahul Joshi } else { 4652469d7e3SRahul Joshi // If the entry was encoded into a single word in the table itself, decode 4662469d7e3SRahul Joshi // it from an array of nibbles to an array of bytes. 4672469d7e3SRahul Joshi do { 4682469d7e3SRahul Joshi IITValues.push_back(TableVal & 0xF); 4692469d7e3SRahul Joshi TableVal >>= 4; 4702469d7e3SRahul Joshi } while (TableVal); 4712469d7e3SRahul Joshi 4722469d7e3SRahul Joshi IITEntries = IITValues; 4732469d7e3SRahul Joshi NextElt = 0; 4742469d7e3SRahul Joshi } 4752469d7e3SRahul Joshi 4762469d7e3SRahul Joshi // Okay, decode the table into the output vector of IITDescriptors. 4772469d7e3SRahul Joshi DecodeIITType(NextElt, IITEntries, IIT_Done, T); 4782469d7e3SRahul Joshi while (NextElt != IITEntries.size() && IITEntries[NextElt] != 0) 4792469d7e3SRahul Joshi DecodeIITType(NextElt, IITEntries, IIT_Done, T); 4802469d7e3SRahul Joshi } 4812469d7e3SRahul Joshi 4823c3f19caSAdrian Kuegel static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos, 4832469d7e3SRahul Joshi ArrayRef<Type *> Tys, LLVMContext &Context) { 4843c3f19caSAdrian Kuegel using namespace Intrinsic; 4853c3f19caSAdrian Kuegel 4862469d7e3SRahul Joshi IITDescriptor D = Infos.front(); 4872469d7e3SRahul Joshi Infos = Infos.slice(1); 4882469d7e3SRahul Joshi 4892469d7e3SRahul Joshi switch (D.Kind) { 4902469d7e3SRahul Joshi case IITDescriptor::Void: 4912469d7e3SRahul Joshi return Type::getVoidTy(Context); 4922469d7e3SRahul Joshi case IITDescriptor::VarArg: 4932469d7e3SRahul Joshi return Type::getVoidTy(Context); 4942469d7e3SRahul Joshi case IITDescriptor::MMX: 4952469d7e3SRahul Joshi return llvm::FixedVectorType::get(llvm::IntegerType::get(Context, 64), 1); 4962469d7e3SRahul Joshi case IITDescriptor::AMX: 4972469d7e3SRahul Joshi return Type::getX86_AMXTy(Context); 4982469d7e3SRahul Joshi case IITDescriptor::Token: 4992469d7e3SRahul Joshi return Type::getTokenTy(Context); 5002469d7e3SRahul Joshi case IITDescriptor::Metadata: 5012469d7e3SRahul Joshi return Type::getMetadataTy(Context); 5022469d7e3SRahul Joshi case IITDescriptor::Half: 5032469d7e3SRahul Joshi return Type::getHalfTy(Context); 5042469d7e3SRahul Joshi case IITDescriptor::BFloat: 5052469d7e3SRahul Joshi return Type::getBFloatTy(Context); 5062469d7e3SRahul Joshi case IITDescriptor::Float: 5072469d7e3SRahul Joshi return Type::getFloatTy(Context); 5082469d7e3SRahul Joshi case IITDescriptor::Double: 5092469d7e3SRahul Joshi return Type::getDoubleTy(Context); 5102469d7e3SRahul Joshi case IITDescriptor::Quad: 5112469d7e3SRahul Joshi return Type::getFP128Ty(Context); 5122469d7e3SRahul Joshi case IITDescriptor::PPCQuad: 5132469d7e3SRahul Joshi return Type::getPPC_FP128Ty(Context); 5142469d7e3SRahul Joshi case IITDescriptor::AArch64Svcount: 5152469d7e3SRahul Joshi return TargetExtType::get(Context, "aarch64.svcount"); 5162469d7e3SRahul Joshi 5172469d7e3SRahul Joshi case IITDescriptor::Integer: 5182469d7e3SRahul Joshi return IntegerType::get(Context, D.Integer_Width); 5192469d7e3SRahul Joshi case IITDescriptor::Vector: 5202469d7e3SRahul Joshi return VectorType::get(DecodeFixedType(Infos, Tys, Context), 5212469d7e3SRahul Joshi D.Vector_Width); 5222469d7e3SRahul Joshi case IITDescriptor::Pointer: 5232469d7e3SRahul Joshi return PointerType::get(Context, D.Pointer_AddressSpace); 5242469d7e3SRahul Joshi case IITDescriptor::Struct: { 5252469d7e3SRahul Joshi SmallVector<Type *, 8> Elts; 5262469d7e3SRahul Joshi for (unsigned i = 0, e = D.Struct_NumElements; i != e; ++i) 5272469d7e3SRahul Joshi Elts.push_back(DecodeFixedType(Infos, Tys, Context)); 5282469d7e3SRahul Joshi return StructType::get(Context, Elts); 5292469d7e3SRahul Joshi } 5302469d7e3SRahul Joshi case IITDescriptor::Argument: 5312469d7e3SRahul Joshi return Tys[D.getArgumentNumber()]; 5322469d7e3SRahul Joshi case IITDescriptor::ExtendArgument: { 5332469d7e3SRahul Joshi Type *Ty = Tys[D.getArgumentNumber()]; 5342469d7e3SRahul Joshi if (VectorType *VTy = dyn_cast<VectorType>(Ty)) 5352469d7e3SRahul Joshi return VectorType::getExtendedElementVectorType(VTy); 5362469d7e3SRahul Joshi 5372469d7e3SRahul Joshi return IntegerType::get(Context, 2 * cast<IntegerType>(Ty)->getBitWidth()); 5382469d7e3SRahul Joshi } 5392469d7e3SRahul Joshi case IITDescriptor::TruncArgument: { 5402469d7e3SRahul Joshi Type *Ty = Tys[D.getArgumentNumber()]; 5412469d7e3SRahul Joshi if (VectorType *VTy = dyn_cast<VectorType>(Ty)) 5422469d7e3SRahul Joshi return VectorType::getTruncatedElementVectorType(VTy); 5432469d7e3SRahul Joshi 5442469d7e3SRahul Joshi IntegerType *ITy = cast<IntegerType>(Ty); 5452469d7e3SRahul Joshi assert(ITy->getBitWidth() % 2 == 0); 5462469d7e3SRahul Joshi return IntegerType::get(Context, ITy->getBitWidth() / 2); 5472469d7e3SRahul Joshi } 5482469d7e3SRahul Joshi case IITDescriptor::Subdivide2Argument: 5492469d7e3SRahul Joshi case IITDescriptor::Subdivide4Argument: { 5502469d7e3SRahul Joshi Type *Ty = Tys[D.getArgumentNumber()]; 5512469d7e3SRahul Joshi VectorType *VTy = dyn_cast<VectorType>(Ty); 5522469d7e3SRahul Joshi assert(VTy && "Expected an argument of Vector Type"); 5532469d7e3SRahul Joshi int SubDivs = D.Kind == IITDescriptor::Subdivide2Argument ? 1 : 2; 5542469d7e3SRahul Joshi return VectorType::getSubdividedVectorType(VTy, SubDivs); 5552469d7e3SRahul Joshi } 5562469d7e3SRahul Joshi case IITDescriptor::HalfVecArgument: 5572469d7e3SRahul Joshi return VectorType::getHalfElementsVectorType( 5582469d7e3SRahul Joshi cast<VectorType>(Tys[D.getArgumentNumber()])); 5592469d7e3SRahul Joshi case IITDescriptor::SameVecWidthArgument: { 5602469d7e3SRahul Joshi Type *EltTy = DecodeFixedType(Infos, Tys, Context); 5612469d7e3SRahul Joshi Type *Ty = Tys[D.getArgumentNumber()]; 5622469d7e3SRahul Joshi if (auto *VTy = dyn_cast<VectorType>(Ty)) 5632469d7e3SRahul Joshi return VectorType::get(EltTy, VTy->getElementCount()); 5642469d7e3SRahul Joshi return EltTy; 5652469d7e3SRahul Joshi } 5662469d7e3SRahul Joshi case IITDescriptor::VecElementArgument: { 5672469d7e3SRahul Joshi Type *Ty = Tys[D.getArgumentNumber()]; 5682469d7e3SRahul Joshi if (VectorType *VTy = dyn_cast<VectorType>(Ty)) 5692469d7e3SRahul Joshi return VTy->getElementType(); 5702469d7e3SRahul Joshi llvm_unreachable("Expected an argument of Vector Type"); 5712469d7e3SRahul Joshi } 5722469d7e3SRahul Joshi case IITDescriptor::VecOfBitcastsToInt: { 5732469d7e3SRahul Joshi Type *Ty = Tys[D.getArgumentNumber()]; 5742469d7e3SRahul Joshi VectorType *VTy = dyn_cast<VectorType>(Ty); 5752469d7e3SRahul Joshi assert(VTy && "Expected an argument of Vector Type"); 5762469d7e3SRahul Joshi return VectorType::getInteger(VTy); 5772469d7e3SRahul Joshi } 5782469d7e3SRahul Joshi case IITDescriptor::VecOfAnyPtrsToElt: 5792469d7e3SRahul Joshi // Return the overloaded type (which determines the pointers address space) 5802469d7e3SRahul Joshi return Tys[D.getOverloadArgNumber()]; 5812469d7e3SRahul Joshi } 5822469d7e3SRahul Joshi llvm_unreachable("unhandled"); 5832469d7e3SRahul Joshi } 5842469d7e3SRahul Joshi 5852469d7e3SRahul Joshi FunctionType *Intrinsic::getType(LLVMContext &Context, ID id, 5862469d7e3SRahul Joshi ArrayRef<Type *> Tys) { 5872469d7e3SRahul Joshi SmallVector<IITDescriptor, 8> Table; 5882469d7e3SRahul Joshi getIntrinsicInfoTableEntries(id, Table); 5892469d7e3SRahul Joshi 5902469d7e3SRahul Joshi ArrayRef<IITDescriptor> TableRef = Table; 5912469d7e3SRahul Joshi Type *ResultTy = DecodeFixedType(TableRef, Tys, Context); 5922469d7e3SRahul Joshi 5932469d7e3SRahul Joshi SmallVector<Type *, 8> ArgTys; 5942469d7e3SRahul Joshi while (!TableRef.empty()) 5952469d7e3SRahul Joshi ArgTys.push_back(DecodeFixedType(TableRef, Tys, Context)); 5962469d7e3SRahul Joshi 5972469d7e3SRahul Joshi // DecodeFixedType returns Void for IITDescriptor::Void and 5982469d7e3SRahul Joshi // IITDescriptor::VarArg If we see void type as the type of the last argument, 5992469d7e3SRahul Joshi // it is vararg intrinsic 6002469d7e3SRahul Joshi if (!ArgTys.empty() && ArgTys.back()->isVoidTy()) { 6012469d7e3SRahul Joshi ArgTys.pop_back(); 6022469d7e3SRahul Joshi return FunctionType::get(ResultTy, ArgTys, true); 6032469d7e3SRahul Joshi } 6042469d7e3SRahul Joshi return FunctionType::get(ResultTy, ArgTys, false); 6052469d7e3SRahul Joshi } 6062469d7e3SRahul Joshi 6072469d7e3SRahul Joshi bool Intrinsic::isOverloaded(ID id) { 6082469d7e3SRahul Joshi #define GET_INTRINSIC_OVERLOAD_TABLE 6092469d7e3SRahul Joshi #include "llvm/IR/IntrinsicImpl.inc" 6102469d7e3SRahul Joshi #undef GET_INTRINSIC_OVERLOAD_TABLE 6112469d7e3SRahul Joshi } 6122469d7e3SRahul Joshi 6132469d7e3SRahul Joshi /// Table of per-target intrinsic name tables. 6142469d7e3SRahul Joshi #define GET_INTRINSIC_TARGET_DATA 6152469d7e3SRahul Joshi #include "llvm/IR/IntrinsicImpl.inc" 6162469d7e3SRahul Joshi #undef GET_INTRINSIC_TARGET_DATA 6172469d7e3SRahul Joshi 6183c3f19caSAdrian Kuegel bool Intrinsic::isTargetIntrinsic(Intrinsic::ID IID) { 6193c3f19caSAdrian Kuegel return IID > TargetInfos[0].Count; 6203c3f19caSAdrian Kuegel } 6212469d7e3SRahul Joshi 622f0297ae5SChandler Carruth /// Looks up Name in NameTable via binary search. NameTable must be sorted 623f0297ae5SChandler Carruth /// and all entries must start with "llvm.". If NameTable contains an exact 624f0297ae5SChandler Carruth /// match for Name or a prefix of Name followed by a dot, its index in 625f0297ae5SChandler Carruth /// NameTable is returned. Otherwise, -1 is returned. 626f0297ae5SChandler Carruth static int lookupLLVMIntrinsicByName(ArrayRef<unsigned> NameOffsetTable, 627f0297ae5SChandler Carruth StringRef Name, StringRef Target = "") { 6282469d7e3SRahul Joshi assert(Name.starts_with("llvm.") && "Unexpected intrinsic prefix"); 6292469d7e3SRahul Joshi assert(Name.drop_front(5).starts_with(Target) && "Unexpected target"); 6302469d7e3SRahul Joshi 6312469d7e3SRahul Joshi // Do successive binary searches of the dotted name components. For 6322469d7e3SRahul Joshi // "llvm.gc.experimental.statepoint.p1i8.p1i32", we will find the range of 6332469d7e3SRahul Joshi // intrinsics starting with "llvm.gc", then "llvm.gc.experimental", then 6342469d7e3SRahul Joshi // "llvm.gc.experimental.statepoint", and then we will stop as the range is 6352469d7e3SRahul Joshi // size 1. During the search, we can skip the prefix that we already know is 6362469d7e3SRahul Joshi // identical. By using strncmp we consider names with differing suffixes to 6372469d7e3SRahul Joshi // be part of the equal range. 6382469d7e3SRahul Joshi size_t CmpEnd = 4; // Skip the "llvm" component. 6392469d7e3SRahul Joshi if (!Target.empty()) 6402469d7e3SRahul Joshi CmpEnd += 1 + Target.size(); // skip the .target component. 6412469d7e3SRahul Joshi 642f0297ae5SChandler Carruth const unsigned *Low = NameOffsetTable.begin(); 643f0297ae5SChandler Carruth const unsigned *High = NameOffsetTable.end(); 644f0297ae5SChandler Carruth const unsigned *LastLow = Low; 6452469d7e3SRahul Joshi while (CmpEnd < Name.size() && High - Low > 0) { 6462469d7e3SRahul Joshi size_t CmpStart = CmpEnd; 6472469d7e3SRahul Joshi CmpEnd = Name.find('.', CmpStart + 1); 6482469d7e3SRahul Joshi CmpEnd = CmpEnd == StringRef::npos ? Name.size() : CmpEnd; 649f0297ae5SChandler Carruth auto Cmp = [CmpStart, CmpEnd](auto LHS, auto RHS) { 650f0297ae5SChandler Carruth // `equal_range` requires the comparison to work with either side being an 651f0297ae5SChandler Carruth // offset or the value. Detect which kind each side is to set up the 652f0297ae5SChandler Carruth // compared strings. 653*f4de28a6SChandler Carruth StringRef LHSStr; 654f0297ae5SChandler Carruth if constexpr (std::is_integral_v<decltype(LHS)>) { 655*f4de28a6SChandler Carruth LHSStr = IntrinsicNameTable[LHS]; 656f0297ae5SChandler Carruth } else { 657f0297ae5SChandler Carruth LHSStr = LHS; 658f0297ae5SChandler Carruth } 659*f4de28a6SChandler Carruth StringRef RHSStr; 660f0297ae5SChandler Carruth if constexpr (std::is_integral_v<decltype(RHS)>) { 661*f4de28a6SChandler Carruth RHSStr = IntrinsicNameTable[RHS]; 662f0297ae5SChandler Carruth } else { 663f0297ae5SChandler Carruth RHSStr = RHS; 664f0297ae5SChandler Carruth } 665*f4de28a6SChandler Carruth return strncmp(LHSStr.data() + CmpStart, RHSStr.data() + CmpStart, 666*f4de28a6SChandler Carruth CmpEnd - CmpStart) < 0; 6672469d7e3SRahul Joshi }; 6682469d7e3SRahul Joshi LastLow = Low; 6692469d7e3SRahul Joshi std::tie(Low, High) = std::equal_range(Low, High, Name.data(), Cmp); 6702469d7e3SRahul Joshi } 6712469d7e3SRahul Joshi if (High - Low > 0) 6722469d7e3SRahul Joshi LastLow = Low; 6732469d7e3SRahul Joshi 674f0297ae5SChandler Carruth if (LastLow == NameOffsetTable.end()) 6752469d7e3SRahul Joshi return -1; 676*f4de28a6SChandler Carruth StringRef NameFound = IntrinsicNameTable[*LastLow]; 6772469d7e3SRahul Joshi if (Name == NameFound || 6782469d7e3SRahul Joshi (Name.starts_with(NameFound) && Name[NameFound.size()] == '.')) 679f0297ae5SChandler Carruth return LastLow - NameOffsetTable.begin(); 6802469d7e3SRahul Joshi return -1; 6812469d7e3SRahul Joshi } 6822469d7e3SRahul Joshi 683f0297ae5SChandler Carruth /// Find the segment of \c IntrinsicNameOffsetTable for intrinsics with the same 6842469d7e3SRahul Joshi /// target as \c Name, or the generic table if \c Name is not target specific. 6852469d7e3SRahul Joshi /// 686f0297ae5SChandler Carruth /// Returns the relevant slice of \c IntrinsicNameOffsetTable and the target 687f0297ae5SChandler Carruth /// name. 688f0297ae5SChandler Carruth static std::pair<ArrayRef<unsigned>, StringRef> 6892469d7e3SRahul Joshi findTargetSubtable(StringRef Name) { 6902469d7e3SRahul Joshi assert(Name.starts_with("llvm.")); 6912469d7e3SRahul Joshi 6922469d7e3SRahul Joshi ArrayRef<IntrinsicTargetInfo> Targets(TargetInfos); 6932469d7e3SRahul Joshi // Drop "llvm." and take the first dotted component. That will be the target 6942469d7e3SRahul Joshi // if this is target specific. 6952469d7e3SRahul Joshi StringRef Target = Name.drop_front(5).split('.').first; 6962469d7e3SRahul Joshi auto It = partition_point( 6972469d7e3SRahul Joshi Targets, [=](const IntrinsicTargetInfo &TI) { return TI.Name < Target; }); 6982469d7e3SRahul Joshi // We've either found the target or just fall back to the generic set, which 6992469d7e3SRahul Joshi // is always first. 7002469d7e3SRahul Joshi const auto &TI = It != Targets.end() && It->Name == Target ? *It : Targets[0]; 701f0297ae5SChandler Carruth return {ArrayRef(&IntrinsicNameOffsetTable[1] + TI.Offset, TI.Count), 702f0297ae5SChandler Carruth TI.Name}; 7032469d7e3SRahul Joshi } 7042469d7e3SRahul Joshi 7052469d7e3SRahul Joshi /// This does the actual lookup of an intrinsic ID which matches the given 7062469d7e3SRahul Joshi /// function name. 7073c3f19caSAdrian Kuegel Intrinsic::ID Intrinsic::lookupIntrinsicID(StringRef Name) { 708f0297ae5SChandler Carruth auto [NameOffsetTable, Target] = findTargetSubtable(Name); 709f0297ae5SChandler Carruth int Idx = lookupLLVMIntrinsicByName(NameOffsetTable, Name, Target); 7102469d7e3SRahul Joshi if (Idx == -1) 7113c3f19caSAdrian Kuegel return Intrinsic::not_intrinsic; 7122469d7e3SRahul Joshi 7132469d7e3SRahul Joshi // Intrinsic IDs correspond to the location in IntrinsicNameTable, but we have 7142469d7e3SRahul Joshi // an index into a sub-table. 715f0297ae5SChandler Carruth int Adjust = NameOffsetTable.data() - IntrinsicNameOffsetTable; 7163c3f19caSAdrian Kuegel Intrinsic::ID ID = static_cast<Intrinsic::ID>(Idx + Adjust); 7172469d7e3SRahul Joshi 7182469d7e3SRahul Joshi // If the intrinsic is not overloaded, require an exact match. If it is 7192469d7e3SRahul Joshi // overloaded, require either exact or prefix match. 720*f4de28a6SChandler Carruth const auto MatchSize = IntrinsicNameTable[NameOffsetTable[Idx]].size(); 7212469d7e3SRahul Joshi assert(Name.size() >= MatchSize && "Expected either exact or prefix match"); 7222469d7e3SRahul Joshi bool IsExactMatch = Name.size() == MatchSize; 7233c3f19caSAdrian Kuegel return IsExactMatch || Intrinsic::isOverloaded(ID) ? ID 7243c3f19caSAdrian Kuegel : Intrinsic::not_intrinsic; 7252469d7e3SRahul Joshi } 7262469d7e3SRahul Joshi 7272469d7e3SRahul Joshi /// This defines the "Intrinsic::getAttributes(ID id)" method. 7282469d7e3SRahul Joshi #define GET_INTRINSIC_ATTRIBUTES 7292469d7e3SRahul Joshi #include "llvm/IR/IntrinsicImpl.inc" 7302469d7e3SRahul Joshi #undef GET_INTRINSIC_ATTRIBUTES 7312469d7e3SRahul Joshi 732fa789dffSRahul Joshi Function *Intrinsic::getOrInsertDeclaration(Module *M, ID id, 733fa789dffSRahul Joshi ArrayRef<Type *> Tys) { 7342469d7e3SRahul Joshi // There can never be multiple globals with the same name of different types, 7352469d7e3SRahul Joshi // because intrinsics must be a specific type. 7362469d7e3SRahul Joshi auto *FT = getType(M->getContext(), id, Tys); 7372469d7e3SRahul Joshi return cast<Function>( 7382469d7e3SRahul Joshi M->getOrInsertFunction( 7392469d7e3SRahul Joshi Tys.empty() ? getName(id) : getName(id, Tys, M, FT), FT) 7402469d7e3SRahul Joshi .getCallee()); 7412469d7e3SRahul Joshi } 7422469d7e3SRahul Joshi 7436924fc03SRahul Joshi Function *Intrinsic::getDeclarationIfExists(const Module *M, ID id) { 7446924fc03SRahul Joshi return M->getFunction(getName(id)); 7456924fc03SRahul Joshi } 7466924fc03SRahul Joshi 7476924fc03SRahul Joshi Function *Intrinsic::getDeclarationIfExists(Module *M, ID id, 7486924fc03SRahul Joshi ArrayRef<Type *> Tys, 7496924fc03SRahul Joshi FunctionType *FT) { 7506924fc03SRahul Joshi return M->getFunction(getName(id, Tys, M, FT)); 7516924fc03SRahul Joshi } 7526924fc03SRahul Joshi 7532469d7e3SRahul Joshi // This defines the "Intrinsic::getIntrinsicForClangBuiltin()" method. 7542469d7e3SRahul Joshi #define GET_LLVM_INTRINSIC_FOR_CLANG_BUILTIN 7552469d7e3SRahul Joshi #include "llvm/IR/IntrinsicImpl.inc" 7562469d7e3SRahul Joshi #undef GET_LLVM_INTRINSIC_FOR_CLANG_BUILTIN 7572469d7e3SRahul Joshi 7582469d7e3SRahul Joshi // This defines the "Intrinsic::getIntrinsicForMSBuiltin()" method. 7592469d7e3SRahul Joshi #define GET_LLVM_INTRINSIC_FOR_MS_BUILTIN 7602469d7e3SRahul Joshi #include "llvm/IR/IntrinsicImpl.inc" 7612469d7e3SRahul Joshi #undef GET_LLVM_INTRINSIC_FOR_MS_BUILTIN 7622469d7e3SRahul Joshi 7632469d7e3SRahul Joshi bool Intrinsic::isConstrainedFPIntrinsic(ID QID) { 7642469d7e3SRahul Joshi switch (QID) { 7653c3f19caSAdrian Kuegel #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ 7663c3f19caSAdrian Kuegel case Intrinsic::INTRINSIC: 7672469d7e3SRahul Joshi #include "llvm/IR/ConstrainedOps.def" 7682469d7e3SRahul Joshi #undef INSTRUCTION 7692469d7e3SRahul Joshi return true; 7702469d7e3SRahul Joshi default: 7712469d7e3SRahul Joshi return false; 7722469d7e3SRahul Joshi } 7732469d7e3SRahul Joshi } 7742469d7e3SRahul Joshi 7753c3f19caSAdrian Kuegel bool Intrinsic::hasConstrainedFPRoundingModeOperand(Intrinsic::ID QID) { 7762469d7e3SRahul Joshi switch (QID) { 7772469d7e3SRahul Joshi #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ 7783c3f19caSAdrian Kuegel case Intrinsic::INTRINSIC: \ 7792469d7e3SRahul Joshi return ROUND_MODE == 1; 7802469d7e3SRahul Joshi #include "llvm/IR/ConstrainedOps.def" 7812469d7e3SRahul Joshi #undef INSTRUCTION 7822469d7e3SRahul Joshi default: 7832469d7e3SRahul Joshi return false; 7842469d7e3SRahul Joshi } 7852469d7e3SRahul Joshi } 7862469d7e3SRahul Joshi 7873c3f19caSAdrian Kuegel using DeferredIntrinsicMatchPair = 7883c3f19caSAdrian Kuegel std::pair<Type *, ArrayRef<Intrinsic::IITDescriptor>>; 7892469d7e3SRahul Joshi 7902469d7e3SRahul Joshi static bool 7913c3f19caSAdrian Kuegel matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor> &Infos, 7922469d7e3SRahul Joshi SmallVectorImpl<Type *> &ArgTys, 7932469d7e3SRahul Joshi SmallVectorImpl<DeferredIntrinsicMatchPair> &DeferredChecks, 7942469d7e3SRahul Joshi bool IsDeferredCheck) { 7953c3f19caSAdrian Kuegel using namespace Intrinsic; 7963c3f19caSAdrian Kuegel 7972469d7e3SRahul Joshi // If we ran out of descriptors, there are too many arguments. 7982469d7e3SRahul Joshi if (Infos.empty()) 7992469d7e3SRahul Joshi return true; 8002469d7e3SRahul Joshi 8012469d7e3SRahul Joshi // Do this before slicing off the 'front' part 8022469d7e3SRahul Joshi auto InfosRef = Infos; 8032469d7e3SRahul Joshi auto DeferCheck = [&DeferredChecks, &InfosRef](Type *T) { 8042469d7e3SRahul Joshi DeferredChecks.emplace_back(T, InfosRef); 8052469d7e3SRahul Joshi return false; 8062469d7e3SRahul Joshi }; 8072469d7e3SRahul Joshi 8082469d7e3SRahul Joshi IITDescriptor D = Infos.front(); 8092469d7e3SRahul Joshi Infos = Infos.slice(1); 8102469d7e3SRahul Joshi 8112469d7e3SRahul Joshi switch (D.Kind) { 8122469d7e3SRahul Joshi case IITDescriptor::Void: 8132469d7e3SRahul Joshi return !Ty->isVoidTy(); 8142469d7e3SRahul Joshi case IITDescriptor::VarArg: 8152469d7e3SRahul Joshi return true; 8162469d7e3SRahul Joshi case IITDescriptor::MMX: { 8172469d7e3SRahul Joshi FixedVectorType *VT = dyn_cast<FixedVectorType>(Ty); 8182469d7e3SRahul Joshi return !VT || VT->getNumElements() != 1 || 8192469d7e3SRahul Joshi !VT->getElementType()->isIntegerTy(64); 8202469d7e3SRahul Joshi } 8212469d7e3SRahul Joshi case IITDescriptor::AMX: 8222469d7e3SRahul Joshi return !Ty->isX86_AMXTy(); 8232469d7e3SRahul Joshi case IITDescriptor::Token: 8242469d7e3SRahul Joshi return !Ty->isTokenTy(); 8252469d7e3SRahul Joshi case IITDescriptor::Metadata: 8262469d7e3SRahul Joshi return !Ty->isMetadataTy(); 8272469d7e3SRahul Joshi case IITDescriptor::Half: 8282469d7e3SRahul Joshi return !Ty->isHalfTy(); 8292469d7e3SRahul Joshi case IITDescriptor::BFloat: 8302469d7e3SRahul Joshi return !Ty->isBFloatTy(); 8312469d7e3SRahul Joshi case IITDescriptor::Float: 8322469d7e3SRahul Joshi return !Ty->isFloatTy(); 8332469d7e3SRahul Joshi case IITDescriptor::Double: 8342469d7e3SRahul Joshi return !Ty->isDoubleTy(); 8352469d7e3SRahul Joshi case IITDescriptor::Quad: 8362469d7e3SRahul Joshi return !Ty->isFP128Ty(); 8372469d7e3SRahul Joshi case IITDescriptor::PPCQuad: 8382469d7e3SRahul Joshi return !Ty->isPPC_FP128Ty(); 8392469d7e3SRahul Joshi case IITDescriptor::Integer: 8402469d7e3SRahul Joshi return !Ty->isIntegerTy(D.Integer_Width); 8412469d7e3SRahul Joshi case IITDescriptor::AArch64Svcount: 8422469d7e3SRahul Joshi return !isa<TargetExtType>(Ty) || 8432469d7e3SRahul Joshi cast<TargetExtType>(Ty)->getName() != "aarch64.svcount"; 8442469d7e3SRahul Joshi case IITDescriptor::Vector: { 8452469d7e3SRahul Joshi VectorType *VT = dyn_cast<VectorType>(Ty); 8462469d7e3SRahul Joshi return !VT || VT->getElementCount() != D.Vector_Width || 8472469d7e3SRahul Joshi matchIntrinsicType(VT->getElementType(), Infos, ArgTys, 8482469d7e3SRahul Joshi DeferredChecks, IsDeferredCheck); 8492469d7e3SRahul Joshi } 8502469d7e3SRahul Joshi case IITDescriptor::Pointer: { 8512469d7e3SRahul Joshi PointerType *PT = dyn_cast<PointerType>(Ty); 8522469d7e3SRahul Joshi return !PT || PT->getAddressSpace() != D.Pointer_AddressSpace; 8532469d7e3SRahul Joshi } 8542469d7e3SRahul Joshi 8552469d7e3SRahul Joshi case IITDescriptor::Struct: { 8562469d7e3SRahul Joshi StructType *ST = dyn_cast<StructType>(Ty); 8572469d7e3SRahul Joshi if (!ST || !ST->isLiteral() || ST->isPacked() || 8582469d7e3SRahul Joshi ST->getNumElements() != D.Struct_NumElements) 8592469d7e3SRahul Joshi return true; 8602469d7e3SRahul Joshi 8612469d7e3SRahul Joshi for (unsigned i = 0, e = D.Struct_NumElements; i != e; ++i) 8622469d7e3SRahul Joshi if (matchIntrinsicType(ST->getElementType(i), Infos, ArgTys, 8632469d7e3SRahul Joshi DeferredChecks, IsDeferredCheck)) 8642469d7e3SRahul Joshi return true; 8652469d7e3SRahul Joshi return false; 8662469d7e3SRahul Joshi } 8672469d7e3SRahul Joshi 8682469d7e3SRahul Joshi case IITDescriptor::Argument: 8692469d7e3SRahul Joshi // If this is the second occurrence of an argument, 8702469d7e3SRahul Joshi // verify that the later instance matches the previous instance. 8712469d7e3SRahul Joshi if (D.getArgumentNumber() < ArgTys.size()) 8722469d7e3SRahul Joshi return Ty != ArgTys[D.getArgumentNumber()]; 8732469d7e3SRahul Joshi 8742469d7e3SRahul Joshi if (D.getArgumentNumber() > ArgTys.size() || 8752469d7e3SRahul Joshi D.getArgumentKind() == IITDescriptor::AK_MatchType) 8762469d7e3SRahul Joshi return IsDeferredCheck || DeferCheck(Ty); 8772469d7e3SRahul Joshi 8782469d7e3SRahul Joshi assert(D.getArgumentNumber() == ArgTys.size() && !IsDeferredCheck && 8792469d7e3SRahul Joshi "Table consistency error"); 8802469d7e3SRahul Joshi ArgTys.push_back(Ty); 8812469d7e3SRahul Joshi 8822469d7e3SRahul Joshi switch (D.getArgumentKind()) { 8832469d7e3SRahul Joshi case IITDescriptor::AK_Any: 8842469d7e3SRahul Joshi return false; // Success 8852469d7e3SRahul Joshi case IITDescriptor::AK_AnyInteger: 8862469d7e3SRahul Joshi return !Ty->isIntOrIntVectorTy(); 8872469d7e3SRahul Joshi case IITDescriptor::AK_AnyFloat: 8882469d7e3SRahul Joshi return !Ty->isFPOrFPVectorTy(); 8892469d7e3SRahul Joshi case IITDescriptor::AK_AnyVector: 8902469d7e3SRahul Joshi return !isa<VectorType>(Ty); 8912469d7e3SRahul Joshi case IITDescriptor::AK_AnyPointer: 8922469d7e3SRahul Joshi return !isa<PointerType>(Ty); 8932469d7e3SRahul Joshi default: 8942469d7e3SRahul Joshi break; 8952469d7e3SRahul Joshi } 8962469d7e3SRahul Joshi llvm_unreachable("all argument kinds not covered"); 8972469d7e3SRahul Joshi 8982469d7e3SRahul Joshi case IITDescriptor::ExtendArgument: { 8992469d7e3SRahul Joshi // If this is a forward reference, defer the check for later. 9002469d7e3SRahul Joshi if (D.getArgumentNumber() >= ArgTys.size()) 9012469d7e3SRahul Joshi return IsDeferredCheck || DeferCheck(Ty); 9022469d7e3SRahul Joshi 9032469d7e3SRahul Joshi Type *NewTy = ArgTys[D.getArgumentNumber()]; 9042469d7e3SRahul Joshi if (VectorType *VTy = dyn_cast<VectorType>(NewTy)) 9052469d7e3SRahul Joshi NewTy = VectorType::getExtendedElementVectorType(VTy); 9062469d7e3SRahul Joshi else if (IntegerType *ITy = dyn_cast<IntegerType>(NewTy)) 9072469d7e3SRahul Joshi NewTy = IntegerType::get(ITy->getContext(), 2 * ITy->getBitWidth()); 9082469d7e3SRahul Joshi else 9092469d7e3SRahul Joshi return true; 9102469d7e3SRahul Joshi 9112469d7e3SRahul Joshi return Ty != NewTy; 9122469d7e3SRahul Joshi } 9132469d7e3SRahul Joshi case IITDescriptor::TruncArgument: { 9142469d7e3SRahul Joshi // If this is a forward reference, defer the check for later. 9152469d7e3SRahul Joshi if (D.getArgumentNumber() >= ArgTys.size()) 9162469d7e3SRahul Joshi return IsDeferredCheck || DeferCheck(Ty); 9172469d7e3SRahul Joshi 9182469d7e3SRahul Joshi Type *NewTy = ArgTys[D.getArgumentNumber()]; 9192469d7e3SRahul Joshi if (VectorType *VTy = dyn_cast<VectorType>(NewTy)) 9202469d7e3SRahul Joshi NewTy = VectorType::getTruncatedElementVectorType(VTy); 9212469d7e3SRahul Joshi else if (IntegerType *ITy = dyn_cast<IntegerType>(NewTy)) 9222469d7e3SRahul Joshi NewTy = IntegerType::get(ITy->getContext(), ITy->getBitWidth() / 2); 9232469d7e3SRahul Joshi else 9242469d7e3SRahul Joshi return true; 9252469d7e3SRahul Joshi 9262469d7e3SRahul Joshi return Ty != NewTy; 9272469d7e3SRahul Joshi } 9282469d7e3SRahul Joshi case IITDescriptor::HalfVecArgument: 9292469d7e3SRahul Joshi // If this is a forward reference, defer the check for later. 9302469d7e3SRahul Joshi if (D.getArgumentNumber() >= ArgTys.size()) 9312469d7e3SRahul Joshi return IsDeferredCheck || DeferCheck(Ty); 9322469d7e3SRahul Joshi return !isa<VectorType>(ArgTys[D.getArgumentNumber()]) || 9332469d7e3SRahul Joshi VectorType::getHalfElementsVectorType( 9342469d7e3SRahul Joshi cast<VectorType>(ArgTys[D.getArgumentNumber()])) != Ty; 9352469d7e3SRahul Joshi case IITDescriptor::SameVecWidthArgument: { 9362469d7e3SRahul Joshi if (D.getArgumentNumber() >= ArgTys.size()) { 9372469d7e3SRahul Joshi // Defer check and subsequent check for the vector element type. 9382469d7e3SRahul Joshi Infos = Infos.slice(1); 9392469d7e3SRahul Joshi return IsDeferredCheck || DeferCheck(Ty); 9402469d7e3SRahul Joshi } 9412469d7e3SRahul Joshi auto *ReferenceType = dyn_cast<VectorType>(ArgTys[D.getArgumentNumber()]); 9422469d7e3SRahul Joshi auto *ThisArgType = dyn_cast<VectorType>(Ty); 9432469d7e3SRahul Joshi // Both must be vectors of the same number of elements or neither. 9442469d7e3SRahul Joshi if ((ReferenceType != nullptr) != (ThisArgType != nullptr)) 9452469d7e3SRahul Joshi return true; 9462469d7e3SRahul Joshi Type *EltTy = Ty; 9472469d7e3SRahul Joshi if (ThisArgType) { 9482469d7e3SRahul Joshi if (ReferenceType->getElementCount() != ThisArgType->getElementCount()) 9492469d7e3SRahul Joshi return true; 9502469d7e3SRahul Joshi EltTy = ThisArgType->getElementType(); 9512469d7e3SRahul Joshi } 9522469d7e3SRahul Joshi return matchIntrinsicType(EltTy, Infos, ArgTys, DeferredChecks, 9532469d7e3SRahul Joshi IsDeferredCheck); 9542469d7e3SRahul Joshi } 9552469d7e3SRahul Joshi case IITDescriptor::VecOfAnyPtrsToElt: { 9562469d7e3SRahul Joshi unsigned RefArgNumber = D.getRefArgNumber(); 9572469d7e3SRahul Joshi if (RefArgNumber >= ArgTys.size()) { 9582469d7e3SRahul Joshi if (IsDeferredCheck) 9592469d7e3SRahul Joshi return true; 9602469d7e3SRahul Joshi // If forward referencing, already add the pointer-vector type and 9612469d7e3SRahul Joshi // defer the checks for later. 9622469d7e3SRahul Joshi ArgTys.push_back(Ty); 9632469d7e3SRahul Joshi return DeferCheck(Ty); 9642469d7e3SRahul Joshi } 9652469d7e3SRahul Joshi 9662469d7e3SRahul Joshi if (!IsDeferredCheck) { 9672469d7e3SRahul Joshi assert(D.getOverloadArgNumber() == ArgTys.size() && 9682469d7e3SRahul Joshi "Table consistency error"); 9692469d7e3SRahul Joshi ArgTys.push_back(Ty); 9702469d7e3SRahul Joshi } 9712469d7e3SRahul Joshi 9722469d7e3SRahul Joshi // Verify the overloaded type "matches" the Ref type. 9732469d7e3SRahul Joshi // i.e. Ty is a vector with the same width as Ref. 9742469d7e3SRahul Joshi // Composed of pointers to the same element type as Ref. 9752469d7e3SRahul Joshi auto *ReferenceType = dyn_cast<VectorType>(ArgTys[RefArgNumber]); 9762469d7e3SRahul Joshi auto *ThisArgVecTy = dyn_cast<VectorType>(Ty); 9772469d7e3SRahul Joshi if (!ThisArgVecTy || !ReferenceType || 9782469d7e3SRahul Joshi (ReferenceType->getElementCount() != ThisArgVecTy->getElementCount())) 9792469d7e3SRahul Joshi return true; 9802469d7e3SRahul Joshi return !ThisArgVecTy->getElementType()->isPointerTy(); 9812469d7e3SRahul Joshi } 9822469d7e3SRahul Joshi case IITDescriptor::VecElementArgument: { 9832469d7e3SRahul Joshi if (D.getArgumentNumber() >= ArgTys.size()) 9842469d7e3SRahul Joshi return IsDeferredCheck ? true : DeferCheck(Ty); 9852469d7e3SRahul Joshi auto *ReferenceType = dyn_cast<VectorType>(ArgTys[D.getArgumentNumber()]); 9862469d7e3SRahul Joshi return !ReferenceType || Ty != ReferenceType->getElementType(); 9872469d7e3SRahul Joshi } 9882469d7e3SRahul Joshi case IITDescriptor::Subdivide2Argument: 9892469d7e3SRahul Joshi case IITDescriptor::Subdivide4Argument: { 9902469d7e3SRahul Joshi // If this is a forward reference, defer the check for later. 9912469d7e3SRahul Joshi if (D.getArgumentNumber() >= ArgTys.size()) 9922469d7e3SRahul Joshi return IsDeferredCheck || DeferCheck(Ty); 9932469d7e3SRahul Joshi 9942469d7e3SRahul Joshi Type *NewTy = ArgTys[D.getArgumentNumber()]; 9952469d7e3SRahul Joshi if (auto *VTy = dyn_cast<VectorType>(NewTy)) { 9962469d7e3SRahul Joshi int SubDivs = D.Kind == IITDescriptor::Subdivide2Argument ? 1 : 2; 9972469d7e3SRahul Joshi NewTy = VectorType::getSubdividedVectorType(VTy, SubDivs); 9982469d7e3SRahul Joshi return Ty != NewTy; 9992469d7e3SRahul Joshi } 10002469d7e3SRahul Joshi return true; 10012469d7e3SRahul Joshi } 10022469d7e3SRahul Joshi case IITDescriptor::VecOfBitcastsToInt: { 10032469d7e3SRahul Joshi if (D.getArgumentNumber() >= ArgTys.size()) 10042469d7e3SRahul Joshi return IsDeferredCheck || DeferCheck(Ty); 10052469d7e3SRahul Joshi auto *ReferenceType = dyn_cast<VectorType>(ArgTys[D.getArgumentNumber()]); 10062469d7e3SRahul Joshi auto *ThisArgVecTy = dyn_cast<VectorType>(Ty); 10072469d7e3SRahul Joshi if (!ThisArgVecTy || !ReferenceType) 10082469d7e3SRahul Joshi return true; 10092469d7e3SRahul Joshi return ThisArgVecTy != VectorType::getInteger(ReferenceType); 10102469d7e3SRahul Joshi } 10112469d7e3SRahul Joshi } 10122469d7e3SRahul Joshi llvm_unreachable("unhandled"); 10132469d7e3SRahul Joshi } 10142469d7e3SRahul Joshi 10153c3f19caSAdrian Kuegel Intrinsic::MatchIntrinsicTypesResult 10162469d7e3SRahul Joshi Intrinsic::matchIntrinsicSignature(FunctionType *FTy, 10173c3f19caSAdrian Kuegel ArrayRef<Intrinsic::IITDescriptor> &Infos, 10182469d7e3SRahul Joshi SmallVectorImpl<Type *> &ArgTys) { 10192469d7e3SRahul Joshi SmallVector<DeferredIntrinsicMatchPair, 2> DeferredChecks; 10202469d7e3SRahul Joshi if (matchIntrinsicType(FTy->getReturnType(), Infos, ArgTys, DeferredChecks, 10212469d7e3SRahul Joshi false)) 10222469d7e3SRahul Joshi return MatchIntrinsicTypes_NoMatchRet; 10232469d7e3SRahul Joshi 10242469d7e3SRahul Joshi unsigned NumDeferredReturnChecks = DeferredChecks.size(); 10252469d7e3SRahul Joshi 10262469d7e3SRahul Joshi for (auto *Ty : FTy->params()) 10272469d7e3SRahul Joshi if (matchIntrinsicType(Ty, Infos, ArgTys, DeferredChecks, false)) 10282469d7e3SRahul Joshi return MatchIntrinsicTypes_NoMatchArg; 10292469d7e3SRahul Joshi 10302469d7e3SRahul Joshi for (unsigned I = 0, E = DeferredChecks.size(); I != E; ++I) { 10312469d7e3SRahul Joshi DeferredIntrinsicMatchPair &Check = DeferredChecks[I]; 10322469d7e3SRahul Joshi if (matchIntrinsicType(Check.first, Check.second, ArgTys, DeferredChecks, 10332469d7e3SRahul Joshi true)) 10342469d7e3SRahul Joshi return I < NumDeferredReturnChecks ? MatchIntrinsicTypes_NoMatchRet 10352469d7e3SRahul Joshi : MatchIntrinsicTypes_NoMatchArg; 10362469d7e3SRahul Joshi } 10372469d7e3SRahul Joshi 10382469d7e3SRahul Joshi return MatchIntrinsicTypes_Match; 10392469d7e3SRahul Joshi } 10402469d7e3SRahul Joshi 10413c3f19caSAdrian Kuegel bool Intrinsic::matchIntrinsicVarArg( 10423c3f19caSAdrian Kuegel bool isVarArg, ArrayRef<Intrinsic::IITDescriptor> &Infos) { 10432469d7e3SRahul Joshi // If there are no descriptors left, then it can't be a vararg. 10442469d7e3SRahul Joshi if (Infos.empty()) 10452469d7e3SRahul Joshi return isVarArg; 10462469d7e3SRahul Joshi 10472469d7e3SRahul Joshi // There should be only one descriptor remaining at this point. 10482469d7e3SRahul Joshi if (Infos.size() != 1) 10492469d7e3SRahul Joshi return true; 10502469d7e3SRahul Joshi 10512469d7e3SRahul Joshi // Check and verify the descriptor. 10522469d7e3SRahul Joshi IITDescriptor D = Infos.front(); 10532469d7e3SRahul Joshi Infos = Infos.slice(1); 10542469d7e3SRahul Joshi if (D.Kind == IITDescriptor::VarArg) 10552469d7e3SRahul Joshi return !isVarArg; 10562469d7e3SRahul Joshi 10572469d7e3SRahul Joshi return true; 10582469d7e3SRahul Joshi } 10592469d7e3SRahul Joshi 10603c3f19caSAdrian Kuegel bool Intrinsic::getIntrinsicSignature(Intrinsic::ID ID, FunctionType *FT, 10612469d7e3SRahul Joshi SmallVectorImpl<Type *> &ArgTys) { 10622469d7e3SRahul Joshi if (!ID) 10632469d7e3SRahul Joshi return false; 10642469d7e3SRahul Joshi 10653c3f19caSAdrian Kuegel SmallVector<Intrinsic::IITDescriptor, 8> Table; 10662469d7e3SRahul Joshi getIntrinsicInfoTableEntries(ID, Table); 10673c3f19caSAdrian Kuegel ArrayRef<Intrinsic::IITDescriptor> TableRef = Table; 10682469d7e3SRahul Joshi 10693c3f19caSAdrian Kuegel if (Intrinsic::matchIntrinsicSignature(FT, TableRef, ArgTys) != 10703c3f19caSAdrian Kuegel Intrinsic::MatchIntrinsicTypesResult::MatchIntrinsicTypes_Match) { 10712469d7e3SRahul Joshi return false; 10722469d7e3SRahul Joshi } 10733c3f19caSAdrian Kuegel if (Intrinsic::matchIntrinsicVarArg(FT->isVarArg(), TableRef)) 10742469d7e3SRahul Joshi return false; 10752469d7e3SRahul Joshi return true; 10762469d7e3SRahul Joshi } 10772469d7e3SRahul Joshi 10782469d7e3SRahul Joshi bool Intrinsic::getIntrinsicSignature(Function *F, 10792469d7e3SRahul Joshi SmallVectorImpl<Type *> &ArgTys) { 10802469d7e3SRahul Joshi return getIntrinsicSignature(F->getIntrinsicID(), F->getFunctionType(), 10812469d7e3SRahul Joshi ArgTys); 10822469d7e3SRahul Joshi } 10832469d7e3SRahul Joshi 10842469d7e3SRahul Joshi std::optional<Function *> Intrinsic::remangleIntrinsicFunction(Function *F) { 10852469d7e3SRahul Joshi SmallVector<Type *, 4> ArgTys; 10862469d7e3SRahul Joshi if (!getIntrinsicSignature(F, ArgTys)) 10872469d7e3SRahul Joshi return std::nullopt; 10882469d7e3SRahul Joshi 10893c3f19caSAdrian Kuegel Intrinsic::ID ID = F->getIntrinsicID(); 10902469d7e3SRahul Joshi StringRef Name = F->getName(); 10912469d7e3SRahul Joshi std::string WantedName = 10923c3f19caSAdrian Kuegel Intrinsic::getName(ID, ArgTys, F->getParent(), F->getFunctionType()); 10932469d7e3SRahul Joshi if (Name == WantedName) 10942469d7e3SRahul Joshi return std::nullopt; 10952469d7e3SRahul Joshi 10962469d7e3SRahul Joshi Function *NewDecl = [&] { 10972469d7e3SRahul Joshi if (auto *ExistingGV = F->getParent()->getNamedValue(WantedName)) { 10982469d7e3SRahul Joshi if (auto *ExistingF = dyn_cast<Function>(ExistingGV)) 10992469d7e3SRahul Joshi if (ExistingF->getFunctionType() == F->getFunctionType()) 11002469d7e3SRahul Joshi return ExistingF; 11012469d7e3SRahul Joshi 11022469d7e3SRahul Joshi // The name already exists, but is not a function or has the wrong 11032469d7e3SRahul Joshi // prototype. Make place for the new one by renaming the old version. 11042469d7e3SRahul Joshi // Either this old version will be removed later on or the module is 11052469d7e3SRahul Joshi // invalid and we'll get an error. 11062469d7e3SRahul Joshi ExistingGV->setName(WantedName + ".renamed"); 11072469d7e3SRahul Joshi } 11083c3f19caSAdrian Kuegel return Intrinsic::getOrInsertDeclaration(F->getParent(), ID, ArgTys); 11092469d7e3SRahul Joshi }(); 11102469d7e3SRahul Joshi 11112469d7e3SRahul Joshi NewDecl->setCallingConv(F->getCallingConv()); 11122469d7e3SRahul Joshi assert(NewDecl->getFunctionType() == F->getFunctionType() && 11132469d7e3SRahul Joshi "Shouldn't change the signature"); 11142469d7e3SRahul Joshi return NewDecl; 11152469d7e3SRahul Joshi } 1116