[NFC][LLVM] Simplify TypeInfoGen in Intrinsics.td (#189278)

Eliminate `MappingRIdx` by making it an identity function. Currently,
`MappingRIdx` is used to map the index of an `llvm_any*` type in an
intrinsic type signature to its overload index. Eliminating this mapping
means that dependent types in LLVM intrinsic definitions (like
`LLVMMatchType` and its subclasses) should use the overload index to
reference the overload type that it depends on (and not the index within
the llvm_any* subset of overloaded types).

See
https://discourse.llvm.org/t/rfc-simplifying-intrinsics-type-signature-iit-info-generation-encoding-in-intrinsicemitter-cpp/90383
This commit is contained in:
Rahul Joshi 2026-03-31 15:51:19 -07:00 committed by GitHub
parent cdce9cd4a1
commit c19e28d854
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 121 additions and 30 deletions

View File

@ -252,13 +252,13 @@ class EncAnyType<int ArgCode=0> {
int ret = !or(ID, ArgCode);
}
// (Mapping[Num] << 3) | AK.MatchType
// (Num << 3) | AK.MatchType
class EncMatchType<int Num=0> {
int ID = 0x200;
int ret = !or(ID, Num);
}
// (Mapping[Num] << 3) | ArgCodes[Mapping[Num]]
// (Num << 3) | ArgCodes[Num]
class EncSameWidth<int Num=0> {
int ID = 0x300;
int ret = !or(ID, Num);
@ -270,26 +270,24 @@ class EncNextArgA<int dummy=0> {
int ret = !or(ID, dummy);
}
// Mapping[Num]
// 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, EncMatchType<>.ID) : !or(!shl(al, 3), ArgKind.MatchType),
!eq(ah, EncSameWidth<>.ID) : !or(!shl(al, 3), ArgCodes[al]),
!eq(ah, EncNextArgA<>.ID) : ACIdx,
!eq(ah, EncNextArgN<>.ID) : num,
!eq(ah, EncNextArgN<>.ID) : al,
true : al);
}
@ -448,12 +446,28 @@ class LLVMAnyPointerType : LLVMAnyType<pAny> {
assert isAny, "pAny should have isOverloaded";
}
// Match the type of another intrinsic parameter. Number is an index into the
// list of overloaded types for the intrinsic, excluding all the fixed types.
// The Number value must refer to a previously listed type. For example:
// Match the type of another intrinsic parameter. Number is an index into the
// list of overloaded types for the intrinsic (i.e, the overload index),
// excluding all the fixed types and all fully dependent types (i.e., all
// sub-classes of LLVMMatchType, except LLVMMatchTypeNextArg). The Number
// value must refer to a previously listed type. For example:
//
// 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.
//
// has one overloaded type, the 2nd argument. LLVMMatchType<0> refers to this
// first overloaded type, which is the 2nd argument. As another example,
//
// Intrinsic<[llvm_anyint_ty],
// [llvm_anyfloat_ty, LLVMMatchType<0>, llvm_anyfloat_ty, LLVMMatchType<2>]>
//
// has 3 overloaded types:
// overload index 0 = return type
// overload index 1 = first argument
// overload index 2 = third argument
//
// LLVMMatchType<0> therefore will match the return type, and
// LLVMMatchType<2> will match the 3rd argument.
class LLVMMatchType<int num, IIT_Base IIT_Info = IIT_ARG>
: LLVMType<OtherVT>{
let Number = num;
@ -649,12 +663,7 @@ class MakeIdx<list<int> Set> {
!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<
@ -673,16 +682,26 @@ class TypeInfoGen<
list<int> ArgCodes = !foreach(ty, ACTys, ty.ArgCode);
// Mappings MatchTypeIdx to ACTys
list<int> MappingRIdxs = MakeIdx<
!foreach(ty, ACTys, ty.isAny)>.RIdxs;
bit isOverloaded = !not(!empty(ACTys));
// D63507: Exclude LLVMPointerType<llvm_any_ty>
bit isOverloaded = !not(!empty(!filter(ty, AllTypes,
!isa<LLVMAnyType>(ty))));
// Validate that the overload index referenced by dependent types always
// references an "isAny" type.
list<int> InvalidOverload = !foreach(ty, AllTypes,
// an entry in the list will be 1 if its a dependent type and it
// references another overload type that is not `Any`.
!and(
!or(!isa<LLVMMatchType>(ty), !isa<LLVMMatchTypeNextArg>(ty)),
!if(!ge(ty.Number, !size(ACTys)),
1,
!not(ACTys[ty.Number].isAny)
)
)
);
assert !eq(!foldl(0, InvalidOverload, a, x, !add(a, x)), 0),
"dependent types must reference an overload index of an \'llvm_any\' type";
list<LLVMType> Types = !foreach(ty, AllTypes,
!if(!isa<LLVMMatchType>(ty), ACTys[MappingRIdxs[ty.Number]], ty));
!if(!isa<LLVMMatchType>(ty), ACTys[ty.Number], ty));
list<int> TypeSig = !listflatten(!listconcat(
[!cond(
@ -692,7 +711,6 @@ class TypeInfoGen<
!foreach(i, !range(AllTypes),
!foreach(a, AllTypes[i].Sig,
ResolveArgCode<
MappingRIdxs,
ArgCodes,
ACIdxs[i],
a>.ret))));

View File

@ -66,6 +66,7 @@ set(LLVM_TEST_DEPENDS_COMMON
count
llvm-config
not
split-file
)
set(LLVM_TEST_DEPENDS
@ -154,7 +155,6 @@ set(LLVM_TEST_DEPENDS
opt
sancov
sanstats
split-file
verify-uselistorder
yaml-bench
yaml2obj

View File

@ -2,9 +2,8 @@
include "llvm/IR/Intrinsics.td"
// CHECK: error: expected record type for the element with index 2 in list {{.*}}
// CHECK: error: assertion failed: dependent types must reference an overload index of an 'llvm_any' type
def int_test : DefaultAttrsIntrinsic<
[llvm_anyint_ty],
[llvm_anyint_ty,
LLVMMatchType<2>],
[llvm_anyint_ty, LLVMMatchType<2>],
[IntrNoMem]>;

View File

@ -0,0 +1,74 @@
// RUN: not llvm-tblgen -gen-intrinsic-impl -I %p/../../include %s -DTEST0 2>&1 | FileCheck %s --check-prefix=CHECK-TEST0
// RUN: not llvm-tblgen -gen-intrinsic-impl -I %p/../../include %s -DTEST1 2>&1 | FileCheck %s --check-prefix=CHECK-TEST1
// RUN: not llvm-tblgen -gen-intrinsic-impl -I %p/../../include %s -DTEST2 2>&1 | FileCheck %s --check-prefix=CHECK-TEST2
// RUN: not llvm-tblgen -gen-intrinsic-impl -I %p/../../include %s -DTEST3 2>&1 | FileCheck %s --check-prefix=CHECK-TEST3
// This unit test tests various overloaded intrinsics that use dependent
// types to validate that if they reference an overload type is not one of the
// llvm_any*, it results in an error.
#define TEST_INTRINSICS_SUPPRESS_DEFS
include "llvm/IR/Intrinsics.td"
#ifdef TEST0
// CHECK-TEST0: error: assertion failed: dependent types must reference an overload index of an 'llvm_any' type
def int_test: DefaultAttrsIntrinsic<
[ llvm_anyvector_ty], // overload index 0.
[ LLVMVectorOfAnyPointersToElt<0>, // overload index 1.
llvm_anyvector_ty, // overload index 2.
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>,
// Error: Fully dependent type references overload index 1,
// which is not one of the llvm_any-types.
LLVMMatchType<1>,
LLVMScalarOrSameVectorWidth<1, llvm_i1_ty>,
LLVMVectorOfAnyPointersToElt<1>, // overload index 3.
llvm_i32_ty]>;
#endif // TEST0
#ifdef TEST1
// CHECK-TEST1: error: assertion failed: dependent types must reference an overload index of an 'llvm_any' type
def int_test: DefaultAttrsIntrinsic<
[ llvm_anyvector_ty], // overload index 0.
[ LLVMVectorOfAnyPointersToElt<0>, // overload index 1.
llvm_anyvector_ty, // overload index 2.
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>,
LLVMMatchType<0>,
// Error: Fully dependent type references overload index 1,
// which is not one of the llvm_any-types.
LLVMScalarOrSameVectorWidth<1, llvm_i1_ty>,
LLVMVectorOfAnyPointersToElt<1>, // overload index 3.
llvm_i32_ty]>;
#endif // TEST1
#ifdef TEST2
// CHECK-TEST2: error: assertion failed: dependent types must reference an overload index of an 'llvm_any' type
def int_test: DefaultAttrsIntrinsic<
[ llvm_anyvector_ty], // overload index 0.
[ LLVMVectorOfAnyPointersToElt<0>, // overload index 1.
llvm_anyvector_ty, // overload index 2.
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>,
LLVMMatchType<0>,
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>,
// Error: Partially dependent type references overload index 1,
// which is not one of the llvm_any-types.
LLVMVectorOfAnyPointersToElt<1>, // overload index 3.
llvm_i32_ty]>;
#endif // TEST2
#ifdef TEST3
// CHECK-TEST3: error: assertion failed: dependent types must reference an overload index of an 'llvm_any' type
def int_test: DefaultAttrsIntrinsic<
[ llvm_anyvector_ty], // overload index 0.
[ LLVMVectorOfAnyPointersToElt<0>, // overload index 1.
llvm_anyvector_ty, // overload index 2.
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>,
LLVMMatchType<0>,
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>,
// Error: Partially dependent type references overload index 3 (itself).
LLVMVectorOfAnyPointersToElt<3>, // overload index 3.
llvm_i32_ty]>;
#endif // TEST3