From cbfa8a1dc599c42c1a871ce526fbbb7858a79897 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Tue, 23 Sep 2025 11:11:42 -0400 Subject: [PATCH] [Intrinsic] Unify IIT_STRUCT{2-9} into ITT_STRUCT to support upto 257 return values - Currently, Intrinsic can only have up to 9 return values. In case new intrinsics require more than 9 return values, additional ITT_STRUCTxxx values need to be added to support > 9 return values. Instead, this patch unifies them into a single IIT_STRUCT followed by a BYTE specifying the minimal 2 (encoded as 0) and maximal 257 (encoded as 255) return values. --- llvm/include/llvm/IR/Intrinsics.td | 91 ++++++++----------- llvm/lib/IR/Intrinsics.cpp | 26 +----- llvm/test/TableGen/intrinsic-struct.td | 58 +++++++++--- llvm/test/TableGen/intrinsic-varargs.td | 2 +- .../TableGen/Basic/CodeGenIntrinsics.cpp | 23 ++--- llvm/utils/TableGen/Basic/CodeGenIntrinsics.h | 3 - 6 files changed, 98 insertions(+), 105 deletions(-) diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index dba44e7c3c506..3c4ed946b98d0 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -297,46 +297,39 @@ def IIT_MMX : IIT_VT; def IIT_TOKEN : IIT_VT; def IIT_METADATA : IIT_VT; def IIT_EMPTYSTRUCT : IIT_VT; -def IIT_STRUCT2 : IIT_Base<21>; -def IIT_STRUCT3 : IIT_Base<22>; -def IIT_STRUCT4 : IIT_Base<23>; -def IIT_STRUCT5 : IIT_Base<24>; -def IIT_EXTEND_ARG : IIT_Base<25>; -def IIT_TRUNC_ARG : IIT_Base<26>; -def IIT_ANYPTR : IIT_Base<27>; -def IIT_V1 : IIT_Vec<1, 28>; -def IIT_VARARG : IIT_VT; -def IIT_ONE_NTH_ELTS_VEC_ARG : IIT_Base<30>; -def IIT_SAME_VEC_WIDTH_ARG : IIT_Base<31>; -def IIT_VEC_OF_ANYPTRS_TO_ELT : IIT_Base<34>; -def IIT_I128 : IIT_Int<128, 35>; -def IIT_V512 : IIT_Vec<512, 36>; -def IIT_V1024 : IIT_Vec<1024, 37>; -def IIT_STRUCT6 : IIT_Base<38>; -def IIT_STRUCT7 : IIT_Base<39>; -def IIT_STRUCT8 : IIT_Base<40>; -def IIT_F128 : IIT_VT; -def IIT_VEC_ELEMENT : IIT_Base<42>; -def IIT_SCALABLE_VEC : IIT_Base<43>; -def IIT_SUBDIVIDE2_ARG : IIT_Base<44>; -def IIT_SUBDIVIDE4_ARG : IIT_Base<45>; -def IIT_VEC_OF_BITCASTS_TO_INT : IIT_Base<46>; -def IIT_V128 : IIT_Vec<128, 47>; -def IIT_BF16 : IIT_VT; -def IIT_STRUCT9 : IIT_Base<49>; -def IIT_V256 : IIT_Vec<256, 50>; -def IIT_AMX : IIT_VT; -def IIT_PPCF128 : IIT_VT; -def IIT_V3 : IIT_Vec<3, 53>; -def IIT_EXTERNREF : IIT_VT; -def IIT_FUNCREF : IIT_VT; -def IIT_I2 : IIT_Int<2, 57>; -def IIT_I4 : IIT_Int<4, 58>; -def IIT_AARCH64_SVCOUNT : IIT_VT; -def IIT_V6 : IIT_Vec<6, 60>; -def IIT_V10 : IIT_Vec<10, 61>; -def IIT_V2048 : IIT_Vec<2048, 62>; -def IIT_V4096 : IIT_Vec<4096, 63>; +def IIT_STRUCT : IIT_Base<21>; +def IIT_EXTEND_ARG : IIT_Base<22>; +def IIT_TRUNC_ARG : IIT_Base<23>; +def IIT_ANYPTR : IIT_Base<24>; +def IIT_V1 : IIT_Vec<1, 25>; +def IIT_VARARG : IIT_VT; +def IIT_ONE_NTH_ELTS_VEC_ARG : IIT_Base<27>; +def IIT_SAME_VEC_WIDTH_ARG : IIT_Base<28>; +def IIT_VEC_OF_ANYPTRS_TO_ELT : IIT_Base<29>; +def IIT_I128 : IIT_Int<128, 30>; +def IIT_V512 : IIT_Vec<512, 31>; +def IIT_V1024 : IIT_Vec<1024, 32>; +def IIT_F128 : IIT_VT; +def IIT_VEC_ELEMENT : IIT_Base<34>; +def IIT_SCALABLE_VEC : IIT_Base<35>; +def IIT_SUBDIVIDE2_ARG : IIT_Base<36>; +def IIT_SUBDIVIDE4_ARG : IIT_Base<37>; +def IIT_VEC_OF_BITCASTS_TO_INT : IIT_Base<38>; +def IIT_V128 : IIT_Vec<128, 39>; +def IIT_BF16 : IIT_VT; +def IIT_V256 : IIT_Vec<256, 41>; +def IIT_AMX : IIT_VT; +def IIT_PPCF128 : IIT_VT; +def IIT_V3 : IIT_Vec<3, 44>; +def IIT_EXTERNREF : IIT_VT; +def IIT_FUNCREF : IIT_VT; +def IIT_I2 : IIT_Int<2, 47>; +def IIT_I4 : IIT_Int<4, 48>; +def IIT_AARCH64_SVCOUNT : IIT_VT; +def IIT_V6 : IIT_Vec<6, 50>; +def IIT_V10 : IIT_Vec<10, 51>; +def IIT_V2048 : IIT_Vec<2048, 52>; +def IIT_V4096 : IIT_Vec<4096, 53>; } defvar IIT_all_FixedTypes = !filter(iit, IIT_all, @@ -345,19 +338,6 @@ defvar IIT_all_FixedTypes = !filter(iit, IIT_all, 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. //===----------------------------------------------------------------------===// @@ -663,7 +643,10 @@ class TypeInfoGen< !if(!isa(ty), ACTys[MappingRIdxs[ty.Number]], ty)); list TypeSig = !listflatten(!listconcat( - [IIT_RetNumbers[!size(RetTypes)]], + [!cond( + !eq(!size(RetTypes), 0): [IIT_Done.Number], + !eq(!size(RetTypes), 1): [], + true: [IIT_STRUCT.Number, !sub(!size(RetTypes), 2)])], !foreach(i, !range(AllTypes), !foreach(a, AllTypes[i].Sig, ResolveArgCode< diff --git a/llvm/lib/IR/Intrinsics.cpp b/llvm/lib/IR/Intrinsics.cpp index 4d2e8fadff4f7..6797a100ff732 100644 --- a/llvm/lib/IR/Intrinsics.cpp +++ b/llvm/lib/IR/Intrinsics.cpp @@ -207,7 +207,6 @@ DecodeIITType(unsigned &NextElt, ArrayRef Infos, bool IsScalableVector = (LastInfo == IIT_SCALABLE_VEC); IIT_Info Info = IIT_Info(Infos[NextElt++]); - unsigned StructElts = 2; switch (Info) { case IIT_Done: @@ -390,28 +389,9 @@ DecodeIITType(unsigned &NextElt, ArrayRef Infos, case IIT_EMPTYSTRUCT: OutputTable.push_back(IITDescriptor::get(IITDescriptor::Struct, 0)); return; - case IIT_STRUCT9: - ++StructElts; - [[fallthrough]]; - case IIT_STRUCT8: - ++StructElts; - [[fallthrough]]; - case IIT_STRUCT7: - ++StructElts; - [[fallthrough]]; - case IIT_STRUCT6: - ++StructElts; - [[fallthrough]]; - case IIT_STRUCT5: - ++StructElts; - [[fallthrough]]; - case IIT_STRUCT4: - ++StructElts; - [[fallthrough]]; - case IIT_STRUCT3: - ++StructElts; - [[fallthrough]]; - case IIT_STRUCT2: { + case IIT_STRUCT: { + unsigned StructElts = Infos[NextElt++] + 2; + OutputTable.push_back( IITDescriptor::get(IITDescriptor::Struct, StructElts)); diff --git a/llvm/test/TableGen/intrinsic-struct.td b/llvm/test/TableGen/intrinsic-struct.td index 467fd9057c183..032cdc10e74ed 100644 --- a/llvm/test/TableGen/intrinsic-struct.td +++ b/llvm/test/TableGen/intrinsic-struct.td @@ -1,22 +1,58 @@ // RUN: llvm-tblgen -gen-intrinsic-enums -I %p/../../include %s -DTEST_INTRINSICS_SUPPRESS_DEFS | FileCheck %s --check-prefix=CHECK-ENUM -// RUN: llvm-tblgen -gen-intrinsic-impl -I %p/../../include %s -DTEST_INTRINSICS_SUPPRESS_DEFS > /dev/null 2>&1 +// RUN: llvm-tblgen -gen-intrinsic-impl -I %p/../../include %s -DTEST_INTRINSICS_SUPPRESS_DEFS | FileCheck %s --check-prefix=CHECK-IMPL // RUN: not llvm-tblgen -gen-intrinsic-impl -I %p/../../include %s -DTEST_INTRINSICS_SUPPRESS_DEFS -DENABLE_ERROR 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR // XFAIL: vg_leak include "llvm/IR/Intrinsics.td" -// Make sure we can return up to 9 values. -// CHECK-ENUM: returns_9_results = {{[0-9]+}}, // llvm.returns.9.results -def int_returns_9_results : Intrinsic< - !listsplat(llvm_anyint_ty, 9), - [], [], "llvm.returns.9.results">; +// Make sure we can return up to 257 values. Intrinsics are in alphabetical order. +// CHECK-ENUM: returns_a0_results = {{[0-9]+}}, // llvm.returns.a0.results +// CHECK-ENUM: returns_b1_results, // llvm.returns.b1.results +// CHECK-ENUM: returns_c2_results, // llvm.returns.c2.results +// CHECK-ENUM: returns_d9_results, // llvm.returns.d9.results +// CHECK-ENUM: returns_e10_results, // llvm.returns.e10.results +// CHECK-ENUM: returns_f257_results, // llvm.returns.f257.results -#ifdef ENABLE_ERROR -// CHECK-ERROR: error: intrinsics can only return upto 9 values, 'int_returns_10_results' returns 10 values -// CHECK-ERROR-NEXT: def int_returns_10_results : Intrinsic< -def int_returns_10_results : Intrinsic< +// Make sure the encoding table is correctly generated. +// CHECK-IMPL: IIT_LongEncodingTable +// CHECK-IMPL-NEXT: 21, 255 +// CHECK-IMPL-SAME: 15, 1, 15, 9, 15, 17, 15, 25, 15, 33, 15, 41, 15, 49, 15, 57, 15, 65, 15, 73, 15, 81, +// CHECK-IMPL-NEXT: 21, 0 +// CHECK-IMPL-SAME: 15, 1, 15, 9, 0 +// CHECK-IMPL-NEXT: 21, 7 +// CHECK-IMPL-SAME: 15, 1, 15, 9, 15, 17, 15, 25, 15, 33, 15, 41, 15, 49, 15, 57, 15, 65, 0 +// CHECK-IMPL-NEXT: 21, 8 +// CHECK-IMPL-SAME: 15, 1, 15, 9, 15, 17, 15, 25, 15, 33, 15, 41, 15, 49, 15, 57, 15, 65, 15, 73, 0 +def int_returns_a0_results : Intrinsic< + [], + [], [], "llvm.returns.a0.results">; + +def int_returns_b1_results : Intrinsic< + [llvm_anyint_ty], + [], [], "llvm.returns.b1.results">; + +def int_returns_c2_results : Intrinsic< + !listsplat(llvm_anyint_ty, 2), + [], [], "llvm.returns.c2.results">; + +def int_returns_d9_results : Intrinsic< + !listsplat(llvm_anyint_ty, 9), + [], [], "llvm.returns.d9.results">; + +def int_returns_e10_results : Intrinsic< !listsplat(llvm_anyint_ty, 10), - [], [], "llvm.returns.10.results">; + [], [], "llvm.returns.e10.results">; + +def int_returns_f257_results : Intrinsic< + !listsplat(llvm_anyint_ty, 257), + [], [], "llvm.returns.f257.results">; + +#ifdef ENABLE_ERROR +// CHECK-ERROR: error: intrinsics can only return upto 257 values, 'int_returns_g258_results' returns 258 values +// CHECK-ERROR-NEXT: def int_returns_g258_results : Intrinsic< +def int_returns_g258_results : Intrinsic< + !listsplat(llvm_anyint_ty, 258), + [], [], "llvm.returns.g258.results">; #endif diff --git a/llvm/test/TableGen/intrinsic-varargs.td b/llvm/test/TableGen/intrinsic-varargs.td index 3634e16e20565..f94e1d0d6750e 100644 --- a/llvm/test/TableGen/intrinsic-varargs.td +++ b/llvm/test/TableGen/intrinsic-varargs.td @@ -3,5 +3,5 @@ include "llvm/IR/Intrinsics.td" -// CHECK: /* 0 */ 0, 29, 0, +// CHECK: /* 0 */ 0, 26, 0, def int_foo : Intrinsic<[], [llvm_vararg_ty]>; diff --git a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp index bc42efa3b2e9c..be7537c83da3a 100644 --- a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp +++ b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp @@ -21,6 +21,13 @@ #include using namespace llvm; +// As the type of more than one return values is represented as an anonymous +// struct, which is encoded with `IIT_STRUCT` followed by a byte specifying +// the number of return values, starting from 2 (encoded as 0) to 257 +// (encoded as 255). So, the maximum number of values that an intrinsic can +// return is 257. +static constexpr unsigned MaxNumReturn = 257; + //===----------------------------------------------------------------------===// // CodeGenIntrinsic Implementation //===----------------------------------------------------------------------===// @@ -29,15 +36,6 @@ CodeGenIntrinsicContext::CodeGenIntrinsicContext(const RecordKeeper &RC) { for (const Record *Rec : RC.getAllDerivedDefinitions("IntrinsicProperty")) if (Rec->getValueAsBit("IsDefault")) DefaultProperties.push_back(Rec); - - // The maximum number of values that an intrinsic can return is the size of - // of `IIT_RetNumbers` list - 1 (since we index into this list using the - // number of return values as the index). - const auto *IIT_RetNumbers = - dyn_cast_or_null(RC.getGlobal("IIT_RetNumbers")); - if (!IIT_RetNumbers) - PrintFatalError("unable to find 'IIT_RetNumbers' list"); - MaxNumReturn = IIT_RetNumbers->size() - 1; } CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC) { @@ -302,11 +300,10 @@ CodeGenIntrinsic::CodeGenIntrinsic(const Record *R, } unsigned NumRet = R->getValueAsListInit("RetTypes")->size(); - if (NumRet > Ctx.MaxNumReturn) + if (NumRet > MaxNumReturn) PrintFatalError(DefLoc, "intrinsics can only return upto " + - Twine(Ctx.MaxNumReturn) + " values, '" + - DefName + "' returns " + Twine(NumRet) + - " values"); + Twine(MaxNumReturn) + " values, '" + DefName + + "' returns " + Twine(NumRet) + " values"); const Record *TypeInfo = R->getValueAsDef("TypeInfo"); if (!TypeInfo->isSubClassOf("TypeInfoGen")) diff --git a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h index 676f575b2749d..2e86149514f46 100644 --- a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h +++ b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h @@ -30,9 +30,6 @@ class RecordKeeper; struct CodeGenIntrinsicContext { explicit CodeGenIntrinsicContext(const RecordKeeper &RC); std::vector DefaultProperties; - - // Maximum number of values an intrinsic can return. - unsigned MaxNumReturn; }; struct CodeGenIntrinsic {