diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -182,6 +182,56 @@ int MatchType = 7; } +// Encode placeholder. +// [15:8] is the ID used how to resolve ArgCode. + +// (ACIdx << 3) | ArgCode +class EncAnyType { + int ID = 0x100; + int ret = !or(ID, ArgCode); +} + +// (Mapping[Num] << 3) | AK.MatchType +class EncMatchType { + int ID = 0x200; + int ret = !or(ID, Num); +} + +// (Mapping[Num] << 3) | ArgCodes[Mapping[Num]] +class EncSameWidth { + int ID = 0x300; + int ret = !or(ID, Num); +} + +// ACIdx +class EncNextArgA { + int ID = 0x400; + int ret = !or(ID, dummy); +} + +// Mapping[Num] +class EncNextArgN { + int ID = 0x500; + int ret = !or(ID, Num); +} + +class ResolveArgCode< + list Mapping, + list ArgCodes, + int ACIdx, + int ax> { + int ah = !and(ax, 0xFF00); + int al = !and(ax, 0x00FF); + int num = Mapping[al]; + int ret = !cond( + !eq(ah, EncAnyType<>.ID) : !or(!shl(ACIdx, 3), al), + !eq(ah, EncMatchType<>.ID) : !or(!shl(num, 3), ArgKind.MatchType), + !eq(ah, EncSameWidth<>.ID) : !or(!shl(num, 3), ArgCodes[num]), + !eq(ah, EncNextArgA<>.ID) : ACIdx, + !eq(ah, EncNextArgN<>.ID) : num, + true : al); +} + //===----------------------------------------------------------------------===// // IIT_Info //===----------------------------------------------------------------------===// @@ -268,6 +318,25 @@ def IIT_I4 : IIT_Int<4, 58>; } +defvar IIT_all_FixedTypes = !filter(iit, IIT_all, + !or(!isa(iit), !isa(iit))); + +defvar IIT_all_VectorTypes = !filter(iit, IIT_all, + !isa(iit)); + +defvar IIT_RetNumbers = [ + [IIT_Done.Number], + [], + [IIT_STRUCT2.Number], + [IIT_STRUCT3.Number], + [IIT_STRUCT4.Number], + [IIT_STRUCT5.Number], + [IIT_STRUCT6.Number], + [IIT_STRUCT7.Number], + [IIT_STRUCT8.Number], + [IIT_STRUCT9.Number], +]; + //===----------------------------------------------------------------------===// // Types used by intrinsics. //===----------------------------------------------------------------------===// @@ -275,19 +344,70 @@ class LLVMType { ValueType VT = vt; int isAny = vt.isOverloaded; + + int ArgCode = ?; + int Number = ?; + + list IITs = !filter(iit, IIT_all_FixedTypes, + !not(!empty(!filter(iit_vt, iit.VTs, + !eq(iit_vt, !if(vt.isVector, vt.ElementType, vt)))))); + assert !le(!size(IITs), 1), "Duplicate type"; + + list IIT_Vecs = !if(vt.isVector, + !filter(iit, IIT_all_VectorTypes, + !not(!empty(!filter(iit_vt, iit.VTs, !and( + !eq(iit_vt.ElementType, vt.ElementType), + !eq(iit_vt.nElem, vt.nElem)))))), + []); + assert !le(!size(IIT_Vecs), 1), "Duplicate type"; + + list Sig = !listconcat( + !if(vt.isScalable, [IIT_SCALABLE_VEC.Number], []), + !foreach(iit, IIT_Vecs, iit.Number), + !foreach(iit, IITs, iit.Number)); +} + +class LLVMAnyType : LLVMType { + let ArgCode = !cond( + !eq(vt, Any) : ArgKind.Any, + !eq(vt, iAny) : ArgKind.AnyInteger, + !eq(vt, fAny) : ArgKind.AnyFloat, + !eq(vt, vAny) : ArgKind.AnyVector, + !eq(vt, iPTRAny) : ArgKind.AnyPointer, + ); + let Sig = [ + IIT_ARG.Number, + EncAnyType.ret, + ]; + + assert isAny, "LLVMAnyType.VT should have isOverloaded"; } class LLVMQualPointerType : LLVMType{ LLVMType ElTy = elty; int AddrSpace = addrspace; + assert !and(!le(0, addrspace), !le(addrspace, 255)), + "Address space exceeds 255"; + + // D63507: LLVMPointerType + let isAny = elty.isAny; + + let Sig = !listconcat( + !if(addrspace, [ + IIT_ANYPTR.Number, + addrspace, + ], [ + IIT_PTR.Number, + ]), + ElTy.Sig); } class LLVMPointerType : LLVMQualPointerType; class LLVMAnyPointerType - : LLVMType{ + : LLVMAnyType { LLVMType ElTy = elty; assert isAny, "iPTRAny should have isOverloaded"; @@ -299,52 +419,75 @@ // Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_anyfloat_ty, LLVMMatchType<0>]> // has two overloaded types, the 2nd and 3rd arguments. LLVMMatchType<0> // refers to the first overloaded type, which is the 2nd argument. -class LLVMMatchType +class LLVMMatchType : LLVMType{ - int Number = num; + let Number = num; + let Sig = [ + IIT_Info.Number, + EncMatchType.ret, + ]; +} + +class LLVMMatchTypeNextArg + : LLVMMatchType { + let Sig = [ + IIT_Info.Number, + EncNextArgA<>.ret, + EncNextArgN.ret, + ]; } // Match the type of another intrinsic parameter that is expected to be based on // an integral type (i.e. either iN or ), but change the scalar size to // be twice as wide or half as wide as the other type. This is only useful when // the intrinsic is overloaded, so the matched type should be declared as iAny. -class LLVMExtendedType : LLVMMatchType; -class LLVMTruncatedType : LLVMMatchType; +class LLVMExtendedType : LLVMMatchType; +class LLVMTruncatedType : LLVMMatchType; // Match the scalar/vector of another intrinsic parameter but with a different // element type. Either both are scalars or both are vectors with the same // number of elements. class LLVMScalarOrSameVectorWidth - : LLVMMatchType { + : LLVMMatchType { ValueType ElTy = elty.VT; + let Sig = !listconcat([ + IIT_SAME_VEC_WIDTH_ARG.Number, + EncSameWidth.ret, + ], elty.Sig); } -class LLVMPointerTo : LLVMMatchType; -class LLVMPointerToElt : LLVMMatchType; -class LLVMAnyPointerToElt : LLVMMatchType; -class LLVMVectorOfAnyPointersToElt : LLVMMatchType; -class LLVMVectorElementType : LLVMMatchType; +class LLVMPointerTo : LLVMMatchType; +class LLVMPointerToElt : LLVMMatchType; +class LLVMAnyPointerToElt + : LLVMMatchTypeNextArg; +class LLVMVectorOfAnyPointersToElt + : LLVMMatchTypeNextArg; +class LLVMVectorElementType : LLVMMatchType; // Match the type of another intrinsic parameter that is expected to be a // vector type, but change the element count to be half as many. -class LLVMHalfElementsVectorType : LLVMMatchType; +class LLVMHalfElementsVectorType + : LLVMMatchType; // Match the type of another intrinsic parameter that is expected to be a // vector type (i.e. ) but with each element subdivided to // form a vector with more elements that are smaller than the original. -class LLVMSubdivide2VectorType : LLVMMatchType; -class LLVMSubdivide4VectorType : LLVMMatchType; +class LLVMSubdivide2VectorType + : LLVMMatchType; +class LLVMSubdivide4VectorType + : LLVMMatchType; // Match the element count and bit width of another intrinsic parameter, but // change the element type to an integer. -class LLVMVectorOfBitcastsToInt : LLVMMatchType; +class LLVMVectorOfBitcastsToInt + : LLVMMatchType; def llvm_void_ty : LLVMType; -def llvm_any_ty : LLVMType; -def llvm_anyint_ty : LLVMType; -def llvm_anyfloat_ty : LLVMType; -def llvm_anyvector_ty : LLVMType; +def llvm_any_ty : LLVMAnyType; +def llvm_anyint_ty : LLVMAnyType; +def llvm_anyfloat_ty : LLVMAnyType; +def llvm_anyvector_ty : LLVMAnyType; def llvm_i1_ty : LLVMType; def llvm_i8_ty : LLVMType; @@ -449,6 +592,60 @@ def llvm_externref_ty : LLVMType; def llvm_funcref_ty : LLVMType; +//===----------------------------------------------------------------------===// + +class MakeIdx Set> { + list IdxsR = !foreach(i, !range(Set), + !if(Set[i], + !foldl(0, !range(0, i), m, j, !add(m, Set[j])), + -1)); + + list RIdxsR = !foreach(i, !range(Set), + !foldl(-1, !range(Set), m, j, + !if(!and(Set[j], !eq(IdxsR[j], i)), j, m))); + + list Idxs = !foreach(a, IdxsR, !if(!ge(a, 0), a, ?)); + list RIdxs = !foreach(a, RIdxsR, !if(!ge(a, 0), a, ?)); +} + +class TypeInfoGen< + list RetTypes, + list ParamTypes> { + list AllTypes = !listconcat(RetTypes, ParamTypes); + + // ArgCodes for NextArg -- isAny or MatchTypeNextArg + list ACIdxs = MakeIdx< + !foreach(ty, AllTypes, + !or(ty.isAny, !isa(ty)))>.Idxs; + + // ArgCodes (only for isAny or MatchTypeNextArg) + list ACTys = !filter(ty, AllTypes, + !or(ty.isAny, !isa(ty))); + + list ArgCodes = !foreach(ty, ACTys, ty.ArgCode); + + // Mappings MatchTypeIdx to ACTys + list MappingRIdxs = MakeIdx< + !foreach(ty, ACTys, ty.isAny)>.RIdxs; + + // D63507: Exclude LLVMPointerType + bit isOverloaded = !not(!empty(!filter(ty, AllTypes, + !isa(ty)))); + + list Types = !foreach(ty, AllTypes, + !if(!isa(ty), ACTys[MappingRIdxs[ty.Number]], ty)); + + list> TypeSig = !listconcat( + [IIT_RetNumbers[!size(RetTypes)]], + !foreach(i, !range(AllTypes), + !foreach(a, AllTypes[i].Sig, + ResolveArgCode< + MappingRIdxs, + ArgCodes, + ACIdxs[i], + a>.ret))); +} + //===----------------------------------------------------------------------===// // Intrinsic Definitions. //===----------------------------------------------------------------------===// @@ -482,6 +679,11 @@ bit DisableDefaultAttributes = disable_default_attributes; bit isTarget = false; + + TypeInfoGen TypeInfo = TypeInfoGen; + bit isOverloaded = TypeInfo.isOverloaded; + list Types = TypeInfo.Types; + list> TypeSig = TypeInfo.TypeSig; } // Intrinsic with default attributes (disable_default_attributes = false). diff --git a/llvm/utils/TableGen/CodeGenIntrinsics.cpp b/llvm/utils/TableGen/CodeGenIntrinsics.cpp --- a/llvm/utils/TableGen/CodeGenIntrinsics.cpp +++ b/llvm/utils/TableGen/CodeGenIntrinsics.cpp @@ -120,6 +120,9 @@ TargetPrefix + ".'!"); } +#define OLD 1 + +#if OLD ListInit *RetTypes = R->getValueAsListInit("RetTypes"); ListInit *ParamTypes = R->getValueAsListInit("ParamTypes"); @@ -206,6 +209,35 @@ IS.ParamVTs.push_back(VT); IS.ParamTypeDefs.push_back(TyEl); } +#endif // OLD + + if (auto *Types = R->getValue("Types")) { +#if OLD + auto OrigRetVTs = std::move(IS.RetVTs); + auto OrigParamVTs = std::move(IS.ParamVTs); + auto OrigOverloaded = isOverloaded; + IS.RetVTs.clear(); + IS.ParamVTs.clear(); +#endif // OLD + + auto *TypeList = cast(Types->getValue()); + isOverloaded = R->getValueAsBit("isOverloaded"); + + unsigned I = 0; + for (unsigned E = R->getValueAsListInit("RetTypes")->size(); I < E; ++I) + IS.RetVTs.push_back( + getValueType(TypeList->getElementAsRecord(I)->getValueAsDef("VT"))); + + for (unsigned E = TypeList->size(); I < E; ++I) + IS.ParamVTs.push_back( + getValueType(TypeList->getElementAsRecord(I)->getValueAsDef("VT"))); + +#if OLD + assert(IS.RetVTs == OrigRetVTs); + assert(IS.ParamVTs == OrigParamVTs); + assert(OrigOverloaded == isOverloaded); +#endif + } // Parse the intrinsic properties. ListInit *PropList = R->getValueAsListInit("IntrProperties"); diff --git a/llvm/utils/TableGen/IntrinsicEmitter.cpp b/llvm/utils/TableGen/IntrinsicEmitter.cpp --- a/llvm/utils/TableGen/IntrinsicEmitter.cpp +++ b/llvm/utils/TableGen/IntrinsicEmitter.cpp @@ -252,6 +252,9 @@ OS << "#endif\n\n"; } +#define OLD 1 +#if OLD + // 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. @@ -528,10 +531,13 @@ #pragma optimize("", on) #endif +#endif // OLD + /// 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 &TypeSig) { +#if OLD std::vector ArgCodes; // Add codes for any overloaded result VTs. @@ -571,6 +577,22 @@ for (unsigned i = 0, e = Int.IS.ParamTypeDefs.size(); i != e; ++i) EncodeFixedType(Int.IS.ParamTypeDefs[i], ArgCodes, NextArgCode, TypeSig, ArgMapping); +#endif // OLD + + if (auto *R = Int.TheDef->getValue("TypeSig")) { +#if OLD + auto OrigTS = std::move(TypeSig); + TypeSig.clear(); +#endif // OLD + for (auto &a : cast(R->getValue())->getValues()) { + for (auto &b : cast(a)->getValues()) + TypeSig.push_back(cast(b)->getValue()); + } + +#if OLD + assert(TypeSig == OrigTS); +#endif + } } static void printIITEntry(raw_ostream &OS, unsigned char X) {