xref: /llvm-project/llvm/lib/IR/Intrinsics.cpp (revision f4de28a63c81c909df28b6b065fad19e2189c54e)
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