Expand Up
@@ -20,7 +20,6 @@
#include " llvm/ADT/Twine.h"
#include " llvm/Support/CommandLine.h"
#include " llvm/Support/ErrorHandling.h"
#include " llvm/Support/MachineValueType.h"
#include " llvm/Support/ModRef.h"
#include " llvm/Support/raw_ostream.h"
#include " llvm/TableGen/Error.h"
Expand All
@@ -36,7 +35,6 @@
#include < utility>
#include < vector>
using namespace llvm ;
using namespace llvm ::tmp;
cl::OptionCategory GenIntrinsicCat (" Options for -gen-intrinsic-enums" );
cl::opt<std::string>
Expand Down
Expand Up
@@ -252,327 +250,16 @@ void IntrinsicEmitter::EmitIntrinsicToOverloadTable(
OS << " #endif\n\n " ;
}
// NOTE: This must be kept in synch with the copy in lib/IR/Function.cpp!
enum IIT_Info {
// Common values should be encoded with 0-15.
IIT_Done = 0 ,
IIT_I1 = 1 ,
IIT_I8 = 2 ,
IIT_I16 = 3 ,
IIT_I32 = 4 ,
IIT_I64 = 5 ,
IIT_F16 = 6 ,
IIT_F32 = 7 ,
IIT_F64 = 8 ,
IIT_V2 = 9 ,
IIT_V4 = 10 ,
IIT_V8 = 11 ,
IIT_V16 = 12 ,
IIT_V32 = 13 ,
IIT_PTR = 14 ,
IIT_ARG = 15 ,
// Values from 16+ are only encodable with the inefficient encoding.
IIT_V64 = 16 ,
IIT_MMX = 17 ,
IIT_TOKEN = 18 ,
IIT_METADATA = 19 ,
IIT_EMPTYSTRUCT = 20 ,
IIT_STRUCT2 = 21 ,
IIT_STRUCT3 = 22 ,
IIT_STRUCT4 = 23 ,
IIT_STRUCT5 = 24 ,
IIT_EXTEND_ARG = 25 ,
IIT_TRUNC_ARG = 26 ,
IIT_ANYPTR = 27 ,
IIT_V1 = 28 ,
IIT_VARARG = 29 ,
IIT_HALF_VEC_ARG = 30 ,
IIT_SAME_VEC_WIDTH_ARG = 31 ,
IIT_PTR_TO_ARG = 32 ,
IIT_PTR_TO_ELT = 33 ,
IIT_VEC_OF_ANYPTRS_TO_ELT = 34 ,
IIT_I128 = 35 ,
IIT_V512 = 36 ,
IIT_V1024 = 37 ,
IIT_STRUCT6 = 38 ,
IIT_STRUCT7 = 39 ,
IIT_STRUCT8 = 40 ,
IIT_F128 = 41 ,
IIT_VEC_ELEMENT = 42 ,
IIT_SCALABLE_VEC = 43 ,
IIT_SUBDIVIDE2_ARG = 44 ,
IIT_SUBDIVIDE4_ARG = 45 ,
IIT_VEC_OF_BITCASTS_TO_INT = 46 ,
IIT_V128 = 47 ,
IIT_BF16 = 48 ,
IIT_STRUCT9 = 49 ,
IIT_V256 = 50 ,
IIT_AMX = 51 ,
IIT_PPCF128 = 52 ,
IIT_V3 = 53 ,
IIT_EXTERNREF = 54 ,
IIT_FUNCREF = 55 ,
IIT_ANYPTR_TO_ELT = 56 ,
IIT_I2 = 57 ,
IIT_I4 = 58 ,
};
static void EncodeFixedValueType (MVT::SimpleValueType VT,
std::vector<unsigned char > &Sig) {
// clang-format off
if (MVT (VT).isInteger ()) {
unsigned BitWidth = MVT (VT).getFixedSizeInBits ();
switch (BitWidth) {
default : PrintFatalError (" unhandled integer type width in intrinsic!" );
case 1 : return Sig.push_back (IIT_I1);
case 2 : return Sig.push_back (IIT_I2);
case 4 : return Sig.push_back (IIT_I4);
case 8 : return Sig.push_back (IIT_I8);
case 16 : return Sig.push_back (IIT_I16);
case 32 : return Sig.push_back (IIT_I32);
case 64 : return Sig.push_back (IIT_I64);
case 128 : return Sig.push_back (IIT_I128);
}
}
switch (VT) {
default : PrintFatalError (" unhandled MVT in intrinsic!" );
case MVT::f16: return Sig.push_back (IIT_F16);
case MVT::bf16: return Sig.push_back (IIT_BF16);
case MVT::f32: return Sig.push_back (IIT_F32);
case MVT::f64: return Sig.push_back (IIT_F64);
case MVT::f128: return Sig.push_back (IIT_F128);
case MVT::ppcf128: return Sig.push_back (IIT_PPCF128);
case MVT::token: return Sig.push_back (IIT_TOKEN);
case MVT::Metadata: return Sig.push_back (IIT_METADATA);
case MVT::x86mmx: return Sig.push_back (IIT_MMX);
case MVT::x86amx: return Sig.push_back (IIT_AMX);
// MVT::OtherVT is used to mean the empty struct type here.
case MVT::Other: return Sig.push_back (IIT_EMPTYSTRUCT);
// MVT::isVoid is used to represent varargs here.
case MVT::isVoid: return Sig.push_back (IIT_VARARG);
case MVT::externref:
return Sig.push_back (IIT_EXTERNREF);
case MVT::funcref:
return Sig.push_back (IIT_FUNCREF);
}
// clang-format on
}
#if defined(_MSC_VER) && !defined(__clang__)
#pragma optimize("",off) // MSVC 2015 optimizer can't deal with this function.
#endif
static void EncodeFixedType (Record *R, std::vector<unsigned char > &ArgCodes,
unsigned &NextArgCode,
std::vector<unsigned char > &Sig,
ArrayRef<unsigned char > Mapping) {
if (R->isSubClassOf (" LLVMMatchType" )) {
unsigned Number = Mapping[R->getValueAsInt (" Number" )];
assert (Number < ArgCodes.size () && " Invalid matching number!" );
if (R->isSubClassOf (" LLVMExtendedType" ))
Sig.push_back (IIT_EXTEND_ARG);
else if (R->isSubClassOf (" LLVMTruncatedType" ))
Sig.push_back (IIT_TRUNC_ARG);
else if (R->isSubClassOf (" LLVMHalfElementsVectorType" ))
Sig.push_back (IIT_HALF_VEC_ARG);
else if (R->isSubClassOf (" LLVMScalarOrSameVectorWidth" )) {
Sig.push_back (IIT_SAME_VEC_WIDTH_ARG);
Sig.push_back ((Number << 3 ) | ArgCodes[Number]);
MVT::SimpleValueType VT = getValueType (R->getValueAsDef (" ElTy" ));
EncodeFixedValueType (VT, Sig);
return ;
}
else if (R->isSubClassOf (" LLVMPointerTo" ))
Sig.push_back (IIT_PTR_TO_ARG);
else if (R->isSubClassOf (" LLVMVectorOfAnyPointersToElt" )) {
Sig.push_back (IIT_VEC_OF_ANYPTRS_TO_ELT);
// Encode overloaded ArgNo
Sig.push_back (NextArgCode++);
// Encode LLVMMatchType<Number> ArgNo
Sig.push_back (Number);
return ;
} else if (R->isSubClassOf (" LLVMAnyPointerToElt" )) {
Sig.push_back (IIT_ANYPTR_TO_ELT);
// Encode overloaded ArgNo
Sig.push_back (NextArgCode++);
// Encode LLVMMatchType<Number> ArgNo
Sig.push_back (Number);
return ;
} else if (R->isSubClassOf (" LLVMPointerToElt" ))
Sig.push_back (IIT_PTR_TO_ELT);
else if (R->isSubClassOf (" LLVMVectorElementType" ))
Sig.push_back (IIT_VEC_ELEMENT);
else if (R->isSubClassOf (" LLVMSubdivide2VectorType" ))
Sig.push_back (IIT_SUBDIVIDE2_ARG);
else if (R->isSubClassOf (" LLVMSubdivide4VectorType" ))
Sig.push_back (IIT_SUBDIVIDE4_ARG);
else if (R->isSubClassOf (" LLVMVectorOfBitcastsToInt" ))
Sig.push_back (IIT_VEC_OF_BITCASTS_TO_INT);
else
Sig.push_back (IIT_ARG);
return Sig.push_back ((Number << 3 ) | 7 /* IITDescriptor::AK_MatchType*/ );
}
MVT::SimpleValueType VT = getValueType (R->getValueAsDef (" VT" ));
unsigned Tmp = 0 ;
switch (VT) {
default : break ;
case MVT::iPTRAny: ++Tmp; [[fallthrough]];
case MVT::vAny: ++Tmp; [[fallthrough]];
case MVT::fAny : ++Tmp; [[fallthrough]];
case MVT::iAny: ++Tmp; [[fallthrough]];
case MVT::Any: {
// If this is an "any" valuetype, then the type is the type of the next
// type in the list specified to getIntrinsic().
Sig.push_back (IIT_ARG);
// Figure out what arg # this is consuming, and remember what kind it was.
assert (NextArgCode < ArgCodes.size () && ArgCodes[NextArgCode] == Tmp &&
" Invalid or no ArgCode associated with overloaded VT!" );
unsigned ArgNo = NextArgCode++;
// Encode what sort of argument it must be in the low 3 bits of the ArgNo.
return Sig.push_back ((ArgNo << 3 ) | Tmp);
}
case MVT::iPTR: {
unsigned AddrSpace = 0 ;
if (R->isSubClassOf (" LLVMQualPointerType" )) {
AddrSpace = R->getValueAsInt (" AddrSpace" );
assert (AddrSpace < 256 && " Address space exceeds 255" );
}
if (AddrSpace) {
Sig.push_back (IIT_ANYPTR);
Sig.push_back (AddrSpace);
} else {
Sig.push_back (IIT_PTR);
}
return EncodeFixedType (R->getValueAsDef (" ElTy" ), ArgCodes, NextArgCode, Sig,
Mapping);
}
}
if (MVT (VT).isVector ()) {
MVT VVT = VT;
if (VVT.isScalableVector ())
Sig.push_back (IIT_SCALABLE_VEC);
switch (VVT.getVectorMinNumElements ()) {
default : PrintFatalError (" unhandled vector type width in intrinsic!" );
case 1 : Sig.push_back (IIT_V1); break ;
case 2 : Sig.push_back (IIT_V2); break ;
case 3 : Sig.push_back (IIT_V3); break ;
case 4 : Sig.push_back (IIT_V4); break ;
case 8 : Sig.push_back (IIT_V8); break ;
case 16 : Sig.push_back (IIT_V16); break ;
case 32 : Sig.push_back (IIT_V32); break ;
case 64 : Sig.push_back (IIT_V64); break ;
case 128 : Sig.push_back (IIT_V128); break ;
case 256 : Sig.push_back (IIT_V256); break ;
case 512 : Sig.push_back (IIT_V512); break ;
case 1024 : Sig.push_back (IIT_V1024); break ;
}
return EncodeFixedValueType (VVT.getVectorElementType ().SimpleTy , Sig);
}
EncodeFixedValueType (VT, Sig);
}
static void UpdateArgCodes (Record *R, std::vector<unsigned char > &ArgCodes,
unsigned int &NumInserted,
SmallVectorImpl<unsigned char > &Mapping) {
if (R->isSubClassOf (" LLVMMatchType" )) {
if (R->isSubClassOf (" LLVMVectorOfAnyPointersToElt" )) {
ArgCodes.push_back (3 /* vAny*/ );
++NumInserted;
} else if (R->isSubClassOf (" LLVMAnyPointerToElt" )) {
ArgCodes.push_back (4 /* iPTRAny*/ );
++NumInserted;
}
return ;
}
unsigned Tmp = 0 ;
switch (getValueType (R->getValueAsDef (" VT" ))) {
default : break ;
case MVT::iPTR:
UpdateArgCodes (R->getValueAsDef (" ElTy" ), ArgCodes, NumInserted, Mapping);
break ;
case MVT::iPTRAny:
++Tmp;
[[fallthrough]];
case MVT::vAny:
++Tmp;
[[fallthrough]];
case MVT::fAny :
++Tmp;
[[fallthrough]];
case MVT::iAny:
++Tmp;
[[fallthrough]];
case MVT::Any:
unsigned OriginalIdx = ArgCodes.size () - NumInserted;
assert (OriginalIdx >= Mapping.size ());
Mapping.resize (OriginalIdx+1 );
Mapping[OriginalIdx] = ArgCodes.size ();
ArgCodes.push_back (Tmp);
break ;
}
}
#if defined(_MSC_VER) && !defined(__clang__)
#pragma optimize("",on)
#endif
// / ComputeFixedEncoding - If we can encode the type signature for this
// / intrinsic into 32 bits, return it. If not, return ~0U.
static void ComputeFixedEncoding (const CodeGenIntrinsic &Int,
std::vector<unsigned char > &TypeSig) {
std::vector<unsigned char > ArgCodes;
// Add codes for any overloaded result VTs.
unsigned int NumInserted = 0 ;
SmallVector<unsigned char , 8 > ArgMapping;
for (unsigned i = 0 , e = Int.IS .RetVTs .size (); i != e; ++i)
UpdateArgCodes (Int.IS .RetTypeDefs [i], ArgCodes, NumInserted, ArgMapping);
// Add codes for any overloaded operand VTs.
for (unsigned i = 0 , e = Int.IS .ParamTypeDefs .size (); i != e; ++i)
UpdateArgCodes (Int.IS .ParamTypeDefs [i], ArgCodes, NumInserted, ArgMapping);
unsigned NextArgCode = 0 ;
if (Int.IS .RetVTs .empty ())
TypeSig.push_back (IIT_Done);
else if (Int.IS .RetVTs .size () == 1 &&
Int.IS .RetVTs [0 ] == MVT::isVoid)
TypeSig.push_back (IIT_Done);
else {
switch (Int.IS .RetVTs .size ()) {
case 1 : break ;
case 2 : TypeSig.push_back (IIT_STRUCT2); break ;
case 3 : TypeSig.push_back (IIT_STRUCT3); break ;
case 4 : TypeSig.push_back (IIT_STRUCT4); break ;
case 5 : TypeSig.push_back (IIT_STRUCT5); break ;
case 6 : TypeSig.push_back (IIT_STRUCT6); break ;
case 7 : TypeSig.push_back (IIT_STRUCT7); break ;
case 8 : TypeSig.push_back (IIT_STRUCT8); break ;
case 9 : TypeSig.push_back (IIT_STRUCT9); break ;
default : llvm_unreachable (" Unhandled case in struct" );
if (auto *R = Int.TheDef ->getValue (" TypeSig" )) {
for (auto &a : cast<ListInit>(R->getValue ())->getValues ()) {
for (auto &b : cast<ListInit>(a)->getValues ())
TypeSig.push_back (cast<IntInit>(b)->getValue ());
}
for (unsigned i = 0 , e = Int.IS .RetVTs .size (); i != e; ++i)
EncodeFixedType (Int.IS .RetTypeDefs [i], ArgCodes, NextArgCode, TypeSig,
ArgMapping);
}
for (unsigned i = 0 , e = Int.IS .ParamTypeDefs .size (); i != e; ++i)
EncodeFixedType (Int.IS .ParamTypeDefs [i], ArgCodes, NextArgCode, TypeSig,
ArgMapping);
}
static void printIITEntry (raw_ostream &OS, unsigned char X) {
Expand Down