[llvm] 91b80ce - TableGen: Implement TypeSig generator in `Intrinsics.td`

NAKAMURA Takumi via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 26 07:50:36 PDT 2023


Author: NAKAMURA Takumi
Date: 2023-04-26T23:48:39+09:00
New Revision: 91b80ce417c9d90e008aa9eaefff231fde97afa6

URL: https://github.com/llvm/llvm-project/commit/91b80ce417c9d90e008aa9eaefff231fde97afa6
DIFF: https://github.com/llvm/llvm-project/commit/91b80ce417c9d90e008aa9eaefff231fde97afa6.diff

LOG: TableGen: Implement TypeSig generator in `Intrinsics.td`

This commit doesn't replace `IntrinsicEmitter::ComputeFixedEncoding()`,
but compares outputs to it, to make sure implementation correct.

Depends on D145871, D145872, D145874, and D146914

Differential Revision: https://reviews.llvm.org/D146915

Added: 
    

Modified: 
    llvm/include/llvm/IR/Intrinsics.td
    llvm/utils/TableGen/CodeGenIntrinsics.cpp
    llvm/utils/TableGen/IntrinsicEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index c831c9d21c40a..35f03ed0fd085 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -182,6 +182,56 @@ def ArgKind {
   int MatchType  = 7;
 }
 
+// Encode placeholder.
+// [15:8] is the ID used how to resolve ArgCode.
+
+// (ACIdx << 3) | ArgCode
+class EncAnyType<int ArgCode=0> {
+  int ID = 0x100;
+  int ret = !or(ID, ArgCode);
+}
+
+// (Mapping[Num] << 3) | AK.MatchType
+class EncMatchType<int Num=0> {
+  int ID = 0x200;
+  int ret = !or(ID, Num);
+}
+
+// (Mapping[Num] << 3) | ArgCodes[Mapping[Num]]
+class EncSameWidth<int Num=0> {
+  int ID = 0x300;
+  int ret = !or(ID, Num);
+}
+
+// ACIdx
+class EncNextArgA<int dummy=0> {
+  int ID = 0x400;
+  int ret = !or(ID, dummy);
+}
+
+// Mapping[Num]
+class EncNextArgN<int Num=0> {
+  int ID = 0x500;
+  int ret = !or(ID, Num);
+}
+
+class ResolveArgCode<
+    list<int> Mapping,
+    list<int> 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_I2 : IIT_Int<2, 57>;
 def IIT_I4 : IIT_Int<4, 58>;
 }
 
+defvar IIT_all_FixedTypes = !filter(iit, IIT_all,
+  !or(!isa<IIT_VT>(iit), !isa<IIT_Int>(iit)));
+
+defvar IIT_all_VectorTypes = !filter(iit, IIT_all,
+  !isa<IIT_Vec>(iit));
+
+defvar IIT_RetNumbers = [
+  [IIT_Done.Number],
+  []<int>,
+  [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 @@ def IIT_I4 : IIT_Int<4, 58>;
 class LLVMType<ValueType vt> {
   ValueType VT = vt;
   int isAny = vt.isOverloaded;
+
+  int ArgCode = ?;
+  int Number = ?;
+
+  list<IIT_Base> 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_Base> 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<int> Sig = !listconcat(
+    !if(vt.isScalable, [IIT_SCALABLE_VEC.Number], []),
+    !foreach(iit, IIT_Vecs, iit.Number),
+    !foreach(iit, IITs,     iit.Number));
+}
+
+class LLVMAnyType<ValueType vt> : LLVMType<vt> {
+  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<ArgCode>.ret,
+  ];
+
+  assert isAny, "LLVMAnyType.VT should have isOverloaded";
 }
 
 class LLVMQualPointerType<LLVMType elty, int addrspace>
   : LLVMType<iPTR>{
   LLVMType ElTy = elty;
   int AddrSpace = addrspace;
+  assert !and(!le(0, addrspace), !le(addrspace, 255)),
+    "Address space exceeds 255";
+
+  // D63507: LLVMPointerType<llvm_any_ty>
+  let isAny = elty.isAny;
+
+  let Sig = !listconcat(
+    !if(addrspace, [
+      IIT_ANYPTR.Number,
+      addrspace,
+    ], [
+      IIT_PTR.Number,
+    ]),
+    ElTy.Sig);
 }
 
 class LLVMPointerType<LLVMType elty>
   : LLVMQualPointerType<elty, 0>;
 
 class LLVMAnyPointerType<LLVMType elty>
-  : LLVMType<iPTRAny>{
+  : LLVMAnyType<iPTRAny> {
   LLVMType ElTy = elty;
 
   assert isAny, "iPTRAny should have isOverloaded";
@@ -299,52 +419,75 @@ class LLVMAnyPointerType<LLVMType elty>
 //   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<int num>
+class LLVMMatchType<int num, IIT_Base IIT_Info = IIT_ARG>
   : LLVMType<OtherVT>{
-  int Number = num;
+  let Number = num;
+  let Sig = [
+    IIT_Info.Number,
+    EncMatchType<num>.ret,
+  ];
+}
+
+class LLVMMatchTypeNextArg<int num, IIT_Base IIT_Info>
+  : LLVMMatchType<num, IIT_Info> {
+  let Sig = [
+    IIT_Info.Number,
+    EncNextArgA<>.ret,
+    EncNextArgN<num>.ret,
+  ];
 }
 
 // Match the type of another intrinsic parameter that is expected to be based on
 // an integral type (i.e. either iN or <N x iM>), 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<int num> : LLVMMatchType<num>;
-class LLVMTruncatedType<int num> : LLVMMatchType<num>;
+class LLVMExtendedType<int num> : LLVMMatchType<num, IIT_EXTEND_ARG>;
+class LLVMTruncatedType<int num> : LLVMMatchType<num, IIT_TRUNC_ARG>;
 
 // Match the scalar/vector of another intrinsic parameter but with a 
diff erent
 // element type. Either both are scalars or both are vectors with the same
 // number of elements.
 class LLVMScalarOrSameVectorWidth<int idx, LLVMType elty>
-  : LLVMMatchType<idx> {
+  : LLVMMatchType<idx, IIT_SAME_VEC_WIDTH_ARG> {
   ValueType ElTy = elty.VT;
+  let Sig = !listconcat([
+    IIT_SAME_VEC_WIDTH_ARG.Number,
+    EncSameWidth<idx>.ret,
+  ], elty.Sig);
 }
 
-class LLVMPointerTo<int num> : LLVMMatchType<num>;
-class LLVMPointerToElt<int num> : LLVMMatchType<num>;
-class LLVMAnyPointerToElt<int num> : LLVMMatchType<num>;
-class LLVMVectorOfAnyPointersToElt<int num> : LLVMMatchType<num>;
-class LLVMVectorElementType<int num> : LLVMMatchType<num>;
+class LLVMPointerTo<int num> : LLVMMatchType<num, IIT_PTR_TO_ARG>;
+class LLVMPointerToElt<int num> : LLVMMatchType<num, IIT_PTR_TO_ELT>;
+class LLVMAnyPointerToElt<int num>
+  : LLVMMatchTypeNextArg<num, IIT_ANYPTR_TO_ELT>;
+class LLVMVectorOfAnyPointersToElt<int num>
+  : LLVMMatchTypeNextArg<num, IIT_VEC_OF_ANYPTRS_TO_ELT>;
+class LLVMVectorElementType<int num> : LLVMMatchType<num, IIT_VEC_ELEMENT>;
 
 // 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<int num> : LLVMMatchType<num>;
+class LLVMHalfElementsVectorType<int num>
+  : LLVMMatchType<num, IIT_HALF_VEC_ARG>;
 
 // Match the type of another intrinsic parameter that is expected to be a
 // vector type (i.e. <N x iM>) but with each element subdivided to
 // form a vector with more elements that are smaller than the original.
-class LLVMSubdivide2VectorType<int num> : LLVMMatchType<num>;
-class LLVMSubdivide4VectorType<int num> : LLVMMatchType<num>;
+class LLVMSubdivide2VectorType<int num>
+  : LLVMMatchType<num, IIT_SUBDIVIDE2_ARG>;
+class LLVMSubdivide4VectorType<int num>
+  : LLVMMatchType<num, IIT_SUBDIVIDE4_ARG>;
 
 // Match the element count and bit width of another intrinsic parameter, but
 // change the element type to an integer.
-class LLVMVectorOfBitcastsToInt<int num> : LLVMMatchType<num>;
+class LLVMVectorOfBitcastsToInt<int num>
+  : LLVMMatchType<num, IIT_VEC_OF_BITCASTS_TO_INT>;
 
 def llvm_void_ty       : LLVMType<isVoid>;
 
-def llvm_any_ty        : LLVMType<Any>;
-def llvm_anyint_ty     : LLVMType<iAny>;
-def llvm_anyfloat_ty   : LLVMType<fAny>;
-def llvm_anyvector_ty  : LLVMType<vAny>;
+def llvm_any_ty        : LLVMAnyType<Any>;
+def llvm_anyint_ty     : LLVMAnyType<iAny>;
+def llvm_anyfloat_ty   : LLVMAnyType<fAny>;
+def llvm_anyvector_ty  : LLVMAnyType<vAny>;
 
 def llvm_i1_ty         : LLVMType<i1>;
 def llvm_i8_ty         : LLVMType<i8>;
@@ -449,6 +592,60 @@ def llvm_vararg_ty     : LLVMType<isVoid>;   // this means vararg here
 def llvm_externref_ty  : LLVMType<externref>;
 def llvm_funcref_ty    : LLVMType<funcref>;
 
+//===----------------------------------------------------------------------===//
+
+class MakeIdx<list<int> Set> {
+  list<int> IdxsR = !foreach(i, !range(Set),
+    !if(Set[i],
+      !foldl(0, !range(0, i), m, j, !add(m, Set[j])),
+      -1));
+
+  list<int> RIdxsR = !foreach(i, !range(Set),
+    !foldl(-1, !range(Set), m, j,
+      !if(!and(Set[j], !eq(IdxsR[j], i)), j, m)));
+
+  list<int> Idxs  = !foreach(a, IdxsR,  !if(!ge(a, 0), a, ?));
+  list<int> RIdxs = !foreach(a, RIdxsR, !if(!ge(a, 0), a, ?));
+}
+
+class TypeInfoGen<
+    list<LLVMType> RetTypes,
+    list<LLVMType> ParamTypes> {
+  list<LLVMType> AllTypes = !listconcat(RetTypes, ParamTypes);
+
+  // ArgCodes for NextArg -- isAny or MatchTypeNextArg
+  list<int> ACIdxs = MakeIdx<
+    !foreach(ty, AllTypes,
+      !or(ty.isAny, !isa<LLVMMatchTypeNextArg>(ty)))>.Idxs;
+
+  // ArgCodes (only for isAny or MatchTypeNextArg)
+  list<LLVMType> ACTys = !filter(ty, AllTypes,
+    !or(ty.isAny, !isa<LLVMMatchTypeNextArg>(ty)));
+
+  list<int> ArgCodes = !foreach(ty, ACTys, ty.ArgCode);
+
+  // Mappings MatchTypeIdx to ACTys
+  list<int> MappingRIdxs = MakeIdx<
+    !foreach(ty, ACTys, ty.isAny)>.RIdxs;
+
+  // D63507: Exclude LLVMPointerType<llvm_any_ty>
+  bit isOverloaded = !not(!empty(!filter(ty, AllTypes,
+    !isa<LLVMAnyType>(ty))));
+
+  list<LLVMType> Types = !foreach(ty, AllTypes,
+    !if(!isa<LLVMMatchType>(ty), ACTys[MappingRIdxs[ty.Number]], ty));
+
+  list<list<int>> 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 @@ class Intrinsic<list<LLVMType> ret_types,
   bit DisableDefaultAttributes = disable_default_attributes;
 
   bit isTarget = false;
+
+  TypeInfoGen TypeInfo = TypeInfoGen<RetTypes, ParamTypes>;
+  bit isOverloaded = TypeInfo.isOverloaded;
+  list<LLVMType> Types = TypeInfo.Types;
+  list<list<int>> 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
index 73e40c7dd6b80..a0c7257992d97 100644
--- a/llvm/utils/TableGen/CodeGenIntrinsics.cpp
+++ b/llvm/utils/TableGen/CodeGenIntrinsics.cpp
@@ -120,6 +120,9 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R,
                                   TargetPrefix + ".'!");
   }
 
+#define OLD 1
+
+#if OLD
   ListInit *RetTypes = R->getValueAsListInit("RetTypes");
   ListInit *ParamTypes = R->getValueAsListInit("ParamTypes");
 
@@ -206,6 +209,35 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R,
     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<ListInit>(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
index 39c361665fb5d..947b3af652a81 100644
--- a/llvm/utils/TableGen/IntrinsicEmitter.cpp
+++ b/llvm/utils/TableGen/IntrinsicEmitter.cpp
@@ -252,6 +252,9 @@ void IntrinsicEmitter::EmitIntrinsicToOverloadTable(
   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 @@ static void UpdateArgCodes(Record *R, std::vector<unsigned char> &ArgCodes,
 #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<unsigned char> &TypeSig) {
+#if OLD
   std::vector<unsigned char> ArgCodes;
 
   // Add codes for any overloaded result VTs.
@@ -571,6 +577,22 @@ static void ComputeFixedEncoding(const CodeGenIntrinsic &Int,
   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<ListInit>(R->getValue())->getValues()) {
+      for (auto &b : cast<ListInit>(a)->getValues())
+        TypeSig.push_back(cast<IntInit>(b)->getValue());
+    }
+
+#if OLD
+    assert(TypeSig == OrigTS);
+#endif
+  }
 }
 
 static void printIITEntry(raw_ostream &OS, unsigned char X) {


        


More information about the llvm-commits mailing list