[llvm] [LLVM][Intrinsics] Refactor IIT encoding generation (PR #189790)

Rahul Joshi via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 1 05:44:11 PDT 2026


https://github.com/jurahul updated https://github.com/llvm/llvm-project/pull/189790

>From 18d86f23bcea8ae7ca560dc4ec35b8c013c21ea3 Mon Sep 17 00:00:00 2001
From: Rahul Joshi <rjoshi at nvidia.com>
Date: Tue, 31 Mar 2026 15:56:39 -0700
Subject: [PATCH 1/2] [LLVM][Intrinsics] Simplify IIT encoding generation

---
 llvm/include/llvm/IR/Intrinsics.h          |  13 +-
 llvm/include/llvm/IR/Intrinsics.td         | 250 +++++++++++----------
 llvm/include/llvm/IR/IntrinsicsAMDGPU.td   |  10 +-
 llvm/lib/Target/AMDGPU/MIMGInstructions.td |   4 +-
 llvm/test/TableGen/intrinsic-struct.td     |  29 +--
 5 files changed, 164 insertions(+), 142 deletions(-)

diff --git a/llvm/include/llvm/IR/Intrinsics.h b/llvm/include/llvm/IR/Intrinsics.h
index dd59520cafa47..73311c96b1326 100644
--- a/llvm/include/llvm/IR/Intrinsics.h
+++ b/llvm/include/llvm/IR/Intrinsics.h
@@ -201,14 +201,13 @@ namespace Intrinsic {
              Kind == TruncArgument || Kind == SameVecWidthArgument ||
              Kind == VecElementArgument || Kind == Subdivide2Argument ||
              Kind == Subdivide4Argument || Kind == VecOfBitcastsToInt);
-      return ArgumentInfo >> 3;
+      // Overload index is packed into lower 5 bits.
+      return ArgumentInfo & 0x1f;
     }
     ArgKind getArgumentKind() const {
-      assert(Kind == Argument || Kind == ExtendArgument ||
-             Kind == TruncArgument || Kind == SameVecWidthArgument ||
-             Kind == VecElementArgument || Kind == Subdivide2Argument ||
-             Kind == Subdivide4Argument || Kind == VecOfBitcastsToInt);
-      return (ArgKind)(ArgumentInfo & 7);
+      // Argument kind is packed into upper 3 bits.
+      assert(Kind == Argument);
+      return (ArgKind)((ArgumentInfo >> 5) & 0x7);
     }
 
     // VecOfAnyPtrsToElt uses both an overloaded argument (for address space)
@@ -217,12 +216,14 @@ namespace Intrinsic {
       assert(Kind == VecOfAnyPtrsToElt);
       return ArgumentInfo >> 16;
     }
+
     // OneNthEltsVecArguments uses both a divisor N and a reference argument for
     // the full-width vector to match
     unsigned getVectorDivisor() const {
       assert(Kind == OneNthEltsVecArgument);
       return ArgumentInfo >> 16;
     }
+
     unsigned getRefArgNumber() const {
       assert(Kind == VecOfAnyPtrsToElt || Kind == OneNthEltsVecArgument);
       return ArgumentInfo & 0xFFFF;
diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index e48c82ce89b51..3b833615418fa 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -243,52 +243,40 @@ 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> {
+// Placeholder to encode the overload index of the current type. We encode bit
+// 8 = 1 to indicate that this entry needs to be patched up with the overload
+// index (to prevent conflict with any valid not-to-be-patched IIT enccoding
+// byte, whose value will be <= 255). The ArgKind itself is in the lower bits.
+// Note that this is just a transient representation till its gets processed
+// by `DoPatchOverloadIndex` below, so this is *not* the encoding of the
+// final type signature.
+class PatchOverloadIndex<int ArgKindVal> {
   int ID = 0x100;
-  int ret = !or(ID, ArgCode);
-}
-
-// (Num << 3) | AK.MatchType
-class EncMatchType<int Num=0> {
-  int ID = 0x200;
-  int ret = !or(ID, Num);
-}
-
-// (Num << 3) | ArgCodes[Num]
-class EncSameWidth<int Num=0> {
-  int ID = 0x300;
-  int ret = !or(ID, Num);
+  int ret = !or(ID, ArgKindVal);
 }
 
-// ACIdx
-class EncNextArgA<int dummy=0> {
-  int ID = 0x400;
-  int ret = !or(ID, dummy);
+// This class defines how the overload index and the arg kind are actually
+// packed into a single byte for the final IIT table encoding. Overload index is
+// packed in low 5 bits, argument kind is packed in upper 3 bits. This enables
+// us to use the same packing for llvm_any* types, which use a argument kind
+// and for partially dependent types like `LLVMVectorOfAnyPointersToElt` which
+// do not use the argument kind and expect the overload index in the lower bits.
+class PackOverloadIndex<int OverloadIndex, int ArgKindVal> {
+  assert !lt(OverloadIndex, 32), "Cannot support more than 32 overload types";
+  assert !lt(ArgKindVal, 8), "Cannot support more than 8 argument kinds";
+  int ret = !or(!shl(ArgKindVal, 5), OverloadIndex);
 }
 
-// Num
-class EncNextArgN<int Num=0> {
-  int ID = 0x500;
-  int ret = !or(ID, Num);
-}
-
-class ResolveArgCode<
-    list<int> ArgCodes,
-    int ACIdx,
-    int ax> {
-  int ah = !and(ax, 0xFF00);
-  int al = !and(ax, 0x00FF);
+// This class handles the actual patching of the overload index into a component
+// value in the type signature. If its > 255, its a value generated by
+// `PatchOverloadIndex` and patching is needed, else the value is passed through
+// as is.
+class DoPatchOverloadIndex<int Sig, int OverloadIndex> {
+  int ArgKindVal = !and(Sig, 0x7);
   int ret = !cond(
-    !eq(ah, EncAnyType<>.ID)   : !or(!shl(ACIdx, 3), al),
-    !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)  : al,
-    true : al);
+    // If the value is > 255, it indicates that patching is needed.
+    !gt(Sig, 255) : PackOverloadIndex<OverloadIndex, ArgKindVal>.ret,
+    true: Sig);
 }
 
 //===----------------------------------------------------------------------===//
@@ -384,10 +372,6 @@ defvar IIT_all_VectorTypes = !filter(iit, IIT_all,
 
 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,
@@ -413,7 +397,7 @@ class LLVMType<ValueType vt> {
 }
 
 class LLVMAnyType<ValueType vt> : LLVMType<vt> {
-  let ArgCode = !cond(
+  int ArgCode = !cond(
     !eq(vt, Any)     : ArgKind.Any,
     !eq(vt, iAny)    : ArgKind.AnyInteger,
     !eq(vt, fAny)    : ArgKind.AnyFloat,
@@ -422,10 +406,10 @@ class LLVMAnyType<ValueType vt> : LLVMType<vt> {
   );
   let Sig = [
     IIT_ARG.Number,
-    EncAnyType<ArgCode>.ret,
+    PatchOverloadIndex<ArgCode>.ret,
   ];
 
-  assert isAny, "LLVMAnyType.VT should have isOverloaded";
+  assert VT.isOverloaded, "LLVMAnyType.VT should have isOverloaded";
 }
 
 class LLVMQualPointerType<int addrspace>
@@ -442,15 +426,54 @@ class LLVMQualPointerType<int addrspace>
     ]);
 }
 
-class LLVMAnyPointerType : LLVMAnyType<pAny> {
-  assert isAny, "pAny should have isOverloaded";
+// Note: CodeGenIntrinsics.cpp seems to check this class to check pointers.
+class LLVMAnyPointerType : LLVMAnyType<pAny>;
+
+// Dependent types: These are types that depend on another LLVMAnyType overload
+// type. There are 2 subclasses of dependent types:
+// 1. Fully dependent types: dependent type can be completely derived from
+//    another overload type.
+// 2. Partially dependent types: dependent type is constrained by another
+//    overload type, but cannot be fully derived from it. Such types get
+//    assigned an overload index and are a part of the overloaded types for an
+//    intrinsics.
+class LLVMDependentType<int oidx> : LLVMType<OtherVT> {
+  // Overload index of the overload type that this dependent type is dependent
+  // on.
+  int OverloadIndex = oidx;
+}
+
+class LLVMFullyDependentType<int oidx, IIT_Base IIT_Info>
+  : LLVMDependentType<oidx> {
+  // For fully dependent overload types, the type signature is just the IIT code
+  // followed by the overload index of the overload type it depends on.
+  let Sig = [
+    IIT_Info.Number,
+    PackOverloadIndex<OverloadIndex, ArgKind.MatchType>.ret
+  ];
+}
+
+class LLVMPartiallyDependentType<int oidx, IIT_Base IIT_Info>
+  : LLVMDependentType<oidx> {
+  // For partially dependent type, the type signature is the IIT code, followed
+  // by this type's oveerload index, followed by the overload index of the
+  // overload type its depends on.
+  let Sig = [
+    IIT_Info.Number,
+    // This types overload index, arg kind ignored.
+    PatchOverloadIndex<0>.ret,
+    // Overload index of the reference overload type, arg kind ignored.
+    PackOverloadIndex<OverloadIndex, 0>.ret,
+  ];
 }
 
-// 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:
+// ----------------------------------------------------------------------------
+// Various sub-classes of fully dependent types.
+
+// Match the type of another intrinsic parameter. `oidx` is an index of the
+// overloaded types that this type is dependent on. Overload types either
+// LLVMAnyType or LLVMPartiallyDependentType. The `oidx` value must refer to a
+// previously listed type. For example:
 //
 //   Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_anyfloat_ty, LLVMMatchType<0>]>
 //
@@ -467,54 +490,37 @@ class LLVMAnyPointerType : LLVMAnyType<pAny> {
 //
 // 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;
-  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,
-  ];
-}
+class LLVMMatchType<int oidx> : LLVMFullyDependentType<oidx, IIT_ARG>;
 
 // 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, IIT_EXTEND_ARG>;
-class LLVMTruncatedType<int num> : LLVMMatchType<num, IIT_TRUNC_ARG>;
+class LLVMExtendedType<int oidx> : LLVMFullyDependentType<oidx, IIT_EXTEND_ARG>;
+class LLVMTruncatedType<int oidx> : LLVMFullyDependentType<oidx, IIT_TRUNC_ARG>;
 
 // 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<int idx, LLVMType elty>
-  : LLVMMatchType<idx, IIT_SAME_VEC_WIDTH_ARG> {
+class LLVMScalarOrSameVectorWidth<int oidx, LLVMType elty>
+  : LLVMFullyDependentType<oidx, IIT_SAME_VEC_WIDTH_ARG> {
   let Sig = !listconcat([
     IIT_SAME_VEC_WIDTH_ARG.Number,
-    EncSameWidth<idx>.ret,
+    // Overload index of the reference overload type, arg kind ignored.
+    PackOverloadIndex<OverloadIndex, 0>.ret,
   ], elty.Sig);
 }
 
-class LLVMVectorOfAnyPointersToElt<int num>
-  : LLVMMatchTypeNextArg<num, IIT_VEC_OF_ANYPTRS_TO_ELT>;
-class LLVMVectorElementType<int num> : LLVMMatchType<num, IIT_VEC_ELEMENT>;
+class LLVMVectorElementType<int oidx>
+  : LLVMFullyDependentType<oidx, 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 1/n of it.
-class LLVMOneNthElementsVectorType<int idx, int n>
-  : LLVMMatchType<idx, IIT_ONE_NTH_ELTS_VEC_ARG> {
+class LLVMOneNthElementsVectorType<int oidx, int n>
+  : LLVMFullyDependentType<oidx, IIT_ONE_NTH_ELTS_VEC_ARG> {
   let Sig = [
     IIT_ONE_NTH_ELTS_VEC_ARG.Number,
-    EncNextArgN<idx>.ret,
+    PackOverloadIndex<OverloadIndex, 0>.ret,
     n,
   ];
 }
@@ -522,15 +528,22 @@ class LLVMOneNthElementsVectorType<int idx, int n>
 // 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, IIT_SUBDIVIDE2_ARG>;
-class LLVMSubdivide4VectorType<int num>
-  : LLVMMatchType<num, IIT_SUBDIVIDE4_ARG>;
+class LLVMSubdivide2VectorType<int oidx>
+  : LLVMFullyDependentType<oidx, IIT_SUBDIVIDE2_ARG>;
+class LLVMSubdivide4VectorType<int oidx>
+  : LLVMFullyDependentType<oidx, 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, IIT_VEC_OF_BITCASTS_TO_INT>;
+class LLVMVectorOfBitcastsToInt<int oidx>
+  : LLVMFullyDependentType<oidx, IIT_VEC_OF_BITCASTS_TO_INT>;
+
+// ----------------------------------------------------------------------------
+// Various sub-classes of partially dependent types.
+
+class LLVMVectorOfAnyPointersToElt<int oidx>
+  : LLVMPartiallyDependentType<oidx, IIT_VEC_OF_ANYPTRS_TO_ELT>;
+
 
 def llvm_void_ty       : LLVMType<isVoid>;
 
@@ -538,6 +551,7 @@ 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_anyptr_ty     : LLVMAnyPointerType;      // ptr addrspace(N)
 
 def llvm_i1_ty         : LLVMType<i1>;
 def llvm_i8_ty         : LLVMType<i8>;
@@ -553,7 +567,6 @@ def llvm_f80_ty        : LLVMType<f80>;
 def llvm_f128_ty       : LLVMType<f128>;
 def llvm_ppcf128_ty    : LLVMType<ppcf128>;
 def llvm_ptr_ty        : LLVMQualPointerType<0>; // ptr
-def llvm_anyptr_ty     : LLVMAnyPointerType;     // ptr addrspace(N)
 def llvm_empty_ty      : LLVMType<OtherVT>;      // { }
 def llvm_metadata_ty   : LLVMType<MetadataVT>;   // !{...}
 def llvm_token_ty      : LLVMType<token>;        // token
@@ -657,43 +670,49 @@ def llvm_exnref_ty     : LLVMType<exnref>;
 
 //===----------------------------------------------------------------------===//
 
-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])),
+// Computes the overload index for overloaded types used by an intrinsic.
+// Input `IsOverloadedType` is a list of booleans, one for each type in the
+// intrinsic's type signature. A 0 value indicate that that type is not an
+// overloaded type, and 1 indicates that its an overloaded type.
+//
+// Assigns overload index by essentially computing a prefix sum on this list.
+// The output list `ret` has value ? for non-overload types and the overload
+// index for overloaded types.
+class AssignOverloadIndex<list<bit> IsOverloadedType> {
+  list<int> PrefixSum = !foreach(i, !range(IsOverloadedType),
+    !if(IsOverloadedType[i],
+      !foldl(0, !range(0, i), m, j, !add(m, IsOverloadedType[j])),
       -1));
 
-  list<int> Idxs  = !foreach(a, IdxsR,  !if(!ge(a, 0), a, ?));
+  // Assign ? if the entry was -1, else its the expected prefix sum.
+  list<int> ret  = !foreach(a, PrefixSum, !if(!ge(a, 0), a, ?));
 }
 
-class TypeInfoGen<
-    list<LLVMType> RetTypes,
-    list<LLVMType> ParamTypes> {
+class TypeInfoGen<list<LLVMType> RetTypes, list<LLVMType> ParamTypes> {
   list<LLVMType> AllTypes = !listconcat(RetTypes, ParamTypes);
 
-  // ArgCodes for NextArg -- isAny or MatchTypeNextArg
-  list<int> ACIdxs = MakeIdx<
+  // Assign overload index for all overloaded types
+  // (LLVMAnyType or LLVMPartiallyDependentType).
+  list<int> OverloadIdxs = AssignOverloadIndex<
     !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)));
+      !or(!isa<LLVMAnyType>(ty), !isa<LLVMPartiallyDependentType>(ty)))>.ret;
 
-  list<int> ArgCodes = !foreach(ty, ACTys, ty.ArgCode);
+  // List of all overloaded types, in their overload-index order.
+  list<LLVMType> OverloadTypes = !filter(ty, AllTypes,
+    !or(!isa<LLVMAnyType>(ty), !isa<LLVMPartiallyDependentType>(ty)));
 
-  bit isOverloaded = !not(!empty(ACTys));
+  bit isOverloaded = !not(!empty(OverloadTypes));
 
   // Validate that the overload index referenced by dependent types always
-  // references an "isAny" type.
+  // references an LLVMAnyType 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)),
+      !isa<LLVMDependentType>(ty),
+      !if(!ge(!cast<LLVMDependentType>(ty).OverloadIndex, !size(OverloadTypes)),
         1,
-        !not(ACTys[ty.Number].isAny)
+        !not(!isa<LLVMAnyType>(OverloadTypes[!cast<LLVMDependentType>(ty).OverloadIndex]))
       )
     )
   );
@@ -701,7 +720,9 @@ class TypeInfoGen<
      "dependent types must reference an overload index of an \'llvm_any\' type";
 
   list<LLVMType> Types = !foreach(ty, AllTypes,
-    !if(!isa<LLVMMatchType>(ty), ACTys[ty.Number], ty));
+    !if(!isa<LLVMDependentType>(ty),
+        OverloadTypes[!cast<LLVMDependentType>(ty).OverloadIndex],
+        ty));
 
   list<int> TypeSig = !listflatten(!listconcat(
     [!cond(
@@ -710,10 +731,7 @@ class TypeInfoGen<
       true: [IIT_STRUCT.Number, !sub(!size(RetTypes), 2)])],
     !foreach(i, !range(AllTypes),
       !foreach(a, AllTypes[i].Sig,
-        ResolveArgCode<
-          ArgCodes,
-          ACIdxs[i],
-          a>.ret))));
+        DoPatchOverloadIndex<a, OverloadIdxs[i]>.ret))));
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td
index 7b4b51a112e19..f576972183eca 100644
--- a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td
+++ b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td
@@ -928,7 +928,7 @@ class arglistmatchshift<list<AMDGPUArg> arglist, int shift> {
   list<AMDGPUArg> ret =
     !foreach(arg, arglist,
              !if(!isa<LLVMMatchType>(arg.Type),
-                 AMDGPUArg<LLVMMatchType<!add(!cast<LLVMMatchType>(arg.Type).Number, shift)>,
+                 AMDGPUArg<LLVMMatchType<!add(!cast<LLVMMatchType>(arg.Type).OverloadIndex, shift)>,
                            arg.Name>,
                  arg));
 }
@@ -942,7 +942,7 @@ class arglistconcat<list<list<AMDGPUArg>> arglists, int shift = 0> {
              lhs,
              arglistmatchshift<rhs,
                                !add(shift, !foldl(0, lhs, a, b,
-                                                  !add(a, b.Type.isAny)))>.ret));
+                                                  !add(a, !isa<LLVMAnyType>(b.Type))))>.ret));
 }
 
 // Represent texture/image types / dimensionality.
@@ -1074,7 +1074,7 @@ class AMDGPUDimProfile<string opmod,
 
   int NumRetAndDataAnyTypes =
     !foldl(0, !listconcat(RetTypes, !foreach(arg, DataArgs, arg.Type)), a, b,
-           !add(a, b.isAny));
+           !add(a, !isa<LLVMAnyType>(b)));
 
   list<AMDGPUArg> AddrArgs =
     arglistconcat<[ExtraAddrArgs,
@@ -1087,12 +1087,12 @@ class AMDGPUDimProfile<string opmod,
   list<LLVMType> AddrTypes = !foreach(arg, AddrArgs, arg.Type);
   list<AMDGPUArg> AddrDefaultArgs =
     !foreach(arg, AddrArgs,
-             AMDGPUArg<!if(!or(arg.Type.isAny, !isa<LLVMMatchType>(arg.Type)),
+             AMDGPUArg<!if(!or(!isa<LLVMAnyType>(arg.Type), !isa<LLVMMatchType>(arg.Type)),
                            !if(IsSample, llvm_float_ty, llvm_i32_ty), arg.Type),
                        arg.Name>);
   list<AMDGPUArg> AddrA16Args =
     !foreach(arg, AddrArgs,
-             AMDGPUArg<!if(!or(arg.Type.isAny, !isa<LLVMMatchType>(arg.Type)),
+             AMDGPUArg<!if(!or(!isa<LLVMAnyType>(arg.Type), !isa<LLVMMatchType>(arg.Type)),
                            !if(IsSample, llvm_half_ty, llvm_i16_ty), arg.Type),
                        arg.Name>);
 }
diff --git a/llvm/lib/Target/AMDGPU/MIMGInstructions.td b/llvm/lib/Target/AMDGPU/MIMGInstructions.td
index 03159cf9398ca..c8e698882ed28 100644
--- a/llvm/lib/Target/AMDGPU/MIMGInstructions.td
+++ b/llvm/lib/Target/AMDGPU/MIMGInstructions.td
@@ -1858,9 +1858,9 @@ class ImageDimIntrinsicInfo<AMDGPUImageDimIntrinsic I> {
   bits<8> CachePolicyIndex = DimEval.CachePolicyArgIndex;
 
   bits<8> BiasTyArg = !add(I.P.NumRetAndDataAnyTypes,
-    !if(!eq(NumOffsetArgs, 0), 0, I.P.ExtraAddrArgs[0].Type.isAny));
+    !if(!eq(NumOffsetArgs, 0), 0, !isa<LLVMAnyType>(I.P.ExtraAddrArgs[0].Type)));
   bits<8> GradientTyArg = !add(I.P.NumRetAndDataAnyTypes,
-    !foldl(0, I.P.ExtraAddrArgs, cnt, arg, !add(cnt, arg.Type.isAny)));
+    !foldl(0, I.P.ExtraAddrArgs, cnt, arg, !add(cnt, !isa<LLVMAnyType>(arg.Type))));
   bits<8> CoordTyArg = !add(GradientTyArg, !if(I.P.Gradients, 1, 0));
 }
 
diff --git a/llvm/test/TableGen/intrinsic-struct.td b/llvm/test/TableGen/intrinsic-struct.td
index 032cdc10e74ed..8ecdcc854adc3 100644
--- a/llvm/test/TableGen/intrinsic-struct.td
+++ b/llvm/test/TableGen/intrinsic-struct.td
@@ -17,42 +17,45 @@ include "llvm/IR/Intrinsics.td"
 // 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,
+// There should be list of 257 '4's (IIT code for i32) followed by 0. We just
+// match the suffix that ends with 0 (IIT_Done).
+// CHECK-IMPL-SAME: 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0
+// CHECK-IMPL-NEXT: 15, 32, 0
 // CHECK-IMPL-NEXT: 21, 0
-// CHECK-IMPL-SAME: 15, 1, 15, 9, 0
+// CHECK-IMPL-SAME: 15, 32, 15, 33, 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-SAME: 15, 32, 15, 33, 15, 34, 15, 35, 15, 36, 15, 37, 15, 38, 15, 39, 15, 40, 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
+// CHECK-IMPL-SAME: 15, 32, 15, 33, 15, 34, 15, 35, 15, 36, 15, 37, 15, 38, 15, 39, 15, 40, 15, 41, 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.e10.results">;
+                              [], []>;
 
 def int_returns_f257_results : Intrinsic<
-                               !listsplat(llvm_anyint_ty, 257),
-                               [], [], "llvm.returns.f257.results">;
+                               !listsplat(llvm_i32_ty, 257),
+                               [], []>;
 
 #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">;
+                               !listsplat(llvm_i32_ty, 258),
+                               [], []>;
 
 #endif

>From f59e5fe0e7a0bad3c98acc3bd915ba4930fc9a5e Mon Sep 17 00:00:00 2001
From: Rahul Joshi <rjoshi at nvidia.com>
Date: Wed, 1 Apr 2026 05:43:45 -0700
Subject: [PATCH 2/2] Review feedback

---
 llvm/include/llvm/IR/Intrinsics.td | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index 3b833615418fa..abab8c3b53574 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -250,7 +250,7 @@ def ArgKind {
 // Note that this is just a transient representation till its gets processed
 // by `DoPatchOverloadIndex` below, so this is *not* the encoding of the
 // final type signature.
-class PatchOverloadIndex<int ArgKindVal> {
+class OverloadIndexPlaceholder <int ArgKindVal> {
   int ID = 0x100;
   int ret = !or(ID, ArgKindVal);
 }
@@ -268,10 +268,10 @@ class PackOverloadIndex<int OverloadIndex, int ArgKindVal> {
 }
 
 // This class handles the actual patching of the overload index into a component
-// value in the type signature. If its > 255, its a value generated by
-// `PatchOverloadIndex` and patching is needed, else the value is passed through
-// as is.
-class DoPatchOverloadIndex<int Sig, int OverloadIndex> {
+// value `Sig` in the type signature. If the value is > 255, it's a placeholder
+// value generated by OverloadIndexPlaceholder and patching is needed, else the
+// value is left unchanged.
+class PatchOverloadIndex<int Sig, int OverloadIndex> {
   int ArgKindVal = !and(Sig, 0x7);
   int ret = !cond(
     // If the value is > 255, it indicates that patching is needed.
@@ -406,7 +406,7 @@ class LLVMAnyType<ValueType vt> : LLVMType<vt> {
   );
   let Sig = [
     IIT_ARG.Number,
-    PatchOverloadIndex<ArgCode>.ret,
+    OverloadIndexPlaceholder <ArgCode>.ret,
   ];
 
   assert VT.isOverloaded, "LLVMAnyType.VT should have isOverloaded";
@@ -461,7 +461,7 @@ class LLVMPartiallyDependentType<int oidx, IIT_Base IIT_Info>
   let Sig = [
     IIT_Info.Number,
     // This types overload index, arg kind ignored.
-    PatchOverloadIndex<0>.ret,
+    OverloadIndexPlaceholder <0>.ret,
     // Overload index of the reference overload type, arg kind ignored.
     PackOverloadIndex<OverloadIndex, 0>.ret,
   ];
@@ -470,10 +470,10 @@ class LLVMPartiallyDependentType<int oidx, IIT_Base IIT_Info>
 // ----------------------------------------------------------------------------
 // Various sub-classes of fully dependent types.
 
-// Match the type of another intrinsic parameter. `oidx` is an index of the
-// overloaded types that this type is dependent on. Overload types either
-// LLVMAnyType or LLVMPartiallyDependentType. The `oidx` value must refer to a
-// previously listed type. For example:
+// Match the type of another intrinsic parameter. `oidx` is the overload index
+// of the overloaded type that this type is dependent on. Overload types are
+// either LLVMAnyType or LLVMPartiallyDependentType. The `oidx` value must refer
+// to a previously listed type. For example:
 //
 //   Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_anyfloat_ty, LLVMMatchType<0>]>
 //
@@ -731,7 +731,7 @@ class TypeInfoGen<list<LLVMType> RetTypes, list<LLVMType> ParamTypes> {
       true: [IIT_STRUCT.Number, !sub(!size(RetTypes), 2)])],
     !foreach(i, !range(AllTypes),
       !foreach(a, AllTypes[i].Sig,
-        DoPatchOverloadIndex<a, OverloadIdxs[i]>.ret))));
+        PatchOverloadIndex<a, OverloadIdxs[i]>.ret))));
 }
 
 //===----------------------------------------------------------------------===//



More information about the llvm-commits mailing list