[llvm] [LLVM][Intrinsics] Change overly defensive code in `DecodeIITType` (PR #190260)

Rahul Joshi via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 2 13:49:46 PDT 2026


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

>From 7b122db3e2c6d47033112068c36dd0a686518895 Mon Sep 17 00:00:00 2001
From: Rahul Joshi <rjoshi at nvidia.com>
Date: Thu, 2 Apr 2026 13:35:16 -0700
Subject: [PATCH] [LLVM][Intrinsics] Change overly defensive code in
 `DecodeIITType`

`DecodeIITType` seems to do a range check each time the next entry
from the IIT encoding table is read. This is overly defensive and
can negatively impact compile time. Assuming a well formed IIT
encoding table, we don't need these checks and in debug builds
if we do run off the end, the ArrayRef indexing (in `Infos`) will
trigger an assert failure.

Additionaly, change some use if 0s (in loop conditions and defaut
constructed terminator in the IIT long encoding table) to explicitly
use IIT_Done to clarify the code better.
---
 llvm/lib/IR/Intrinsics.cpp                    | 40 ++++++++-----------
 .../utils/TableGen/Basic/IntrinsicEmitter.cpp |  8 +++-
 2 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/llvm/lib/IR/Intrinsics.cpp b/llvm/lib/IR/Intrinsics.cpp
index 0e01529bda711..920543b71b6bf 100644
--- a/llvm/lib/IR/Intrinsics.cpp
+++ b/llvm/lib/IR/Intrinsics.cpp
@@ -354,42 +354,39 @@ DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
         IITDescriptor::get(IITDescriptor::Pointer, Infos[NextElt++]));
     return;
   case IIT_ANY: {
-    unsigned OverloadInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
+    unsigned OverloadInfo = Infos[NextElt++];
     OutputTable.push_back(
         IITDescriptor::get(IITDescriptor::Overloaded, OverloadInfo));
     return;
   }
   case IIT_EXTEND_ARG: {
-    unsigned OverloadIndex = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
+    unsigned OverloadIndex = Infos[NextElt++];
     OutputTable.push_back(
         IITDescriptor::get(IITDescriptor::Extend, OverloadIndex));
     return;
   }
   case IIT_TRUNC_ARG: {
-    unsigned OverloadIndex = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
+    unsigned OverloadIndex = Infos[NextElt++];
     OutputTable.push_back(
         IITDescriptor::get(IITDescriptor::Trunc, OverloadIndex));
     return;
   }
   case IIT_ONE_NTH_ELTS_VEC_ARG: {
-    unsigned short OverloadIndex =
-        (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
-    unsigned short N = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
+    unsigned short OverloadIndex = Infos[NextElt++];
+    unsigned short N = Infos[NextElt++];
     OutputTable.push_back(IITDescriptor::get(IITDescriptor::OneNthEltsVec,
                                              /*Hi=*/N, /*Lo=*/OverloadIndex));
     return;
   }
   case IIT_SAME_VEC_WIDTH_ARG: {
-    unsigned OverloadIndex = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
+    unsigned OverloadIndex = Infos[NextElt++];
     OutputTable.push_back(
         IITDescriptor::get(IITDescriptor::SameVecWidth, OverloadIndex));
     return;
   }
   case IIT_VEC_OF_ANYPTRS_TO_ELT: {
-    unsigned short OverloadIndex =
-        (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
-    unsigned short RefOverloadIndex =
-        (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
+    unsigned short OverloadIndex = Infos[NextElt++];
+    unsigned short RefOverloadIndex = Infos[NextElt++];
     OutputTable.push_back(IITDescriptor::get(IITDescriptor::VecOfAnyPtrsToElt,
                                              /*Hi=*/RefOverloadIndex,
                                              /*Lo=*/OverloadIndex));
@@ -409,19 +406,19 @@ DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
     return;
   }
   case IIT_SUBDIVIDE2_ARG: {
-    unsigned OverloadIndex = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
+    unsigned OverloadIndex = Infos[NextElt++];
     OutputTable.push_back(
         IITDescriptor::get(IITDescriptor::Subdivide2, OverloadIndex));
     return;
   }
   case IIT_SUBDIVIDE4_ARG: {
-    unsigned OverloadIndex = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
+    unsigned OverloadIndex = Infos[NextElt++];
     OutputTable.push_back(
         IITDescriptor::get(IITDescriptor::Subdivide4, OverloadIndex));
     return;
   }
   case IIT_VEC_ELEMENT: {
-    unsigned OverloadIndex = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
+    unsigned OverloadIndex = Infos[NextElt++];
     OutputTable.push_back(
         IITDescriptor::get(IITDescriptor::VecElement, OverloadIndex));
     return;
@@ -431,7 +428,7 @@ DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
     return;
   }
   case IIT_VEC_OF_BITCASTS_TO_INT: {
-    unsigned OverloadIndex = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
+    unsigned OverloadIndex = Infos[NextElt++];
     OutputTable.push_back(
         IITDescriptor::get(IITDescriptor::VecOfBitcastsToInt, OverloadIndex));
     return;
@@ -484,7 +481,7 @@ void Intrinsic::getIntrinsicInfoTableEntries(
 
   // Okay, decode the table into the output vector of IITDescriptors.
   DecodeIITType(NextElt, IITEntries, IIT_Done, T);
-  while (NextElt != IITEntries.size() && IITEntries[NextElt] != 0)
+  while (NextElt != IITEntries.size() && IITEntries[NextElt] != IIT_Done)
     DecodeIITType(NextElt, IITEntries, IIT_Done, T);
 }
 
@@ -493,8 +490,7 @@ static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos,
                              LLVMContext &Context) {
   using namespace Intrinsic;
 
-  IITDescriptor D = Infos.front();
-  Infos = Infos.slice(1);
+  IITDescriptor D = Infos.consume_front();
 
   switch (D.Kind) {
   case IITDescriptor::Void:
@@ -862,8 +858,7 @@ matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor> &Infos,
     return false;
   };
 
-  IITDescriptor D = Infos.front();
-  Infos = Infos.slice(1);
+  IITDescriptor D = Infos.consume_front();
 
   switch (D.Kind) {
   case IITDescriptor::Void:
@@ -997,7 +992,7 @@ matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor> &Infos,
   case IITDescriptor::SameVecWidth: {
     if (D.getOverloadIndex() >= OverloadTys.size()) {
       // Defer check and subsequent check for the vector element type.
-      Infos = Infos.slice(1);
+      (void)Infos.drop_front();
       return IsDeferredCheck || DeferCheck(Ty);
     }
     auto *ReferenceType =
@@ -1114,8 +1109,7 @@ bool Intrinsic::matchIntrinsicVarArg(
     return true;
 
   // Check and verify the descriptor.
-  IITDescriptor D = Infos.front();
-  Infos = Infos.slice(1);
+  IITDescriptor D = Infos.consume_front();
   if (D.Kind == IITDescriptor::VarArg)
     return !isVarArg;
 
diff --git a/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp b/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp
index bda911b50d813..85524981a2a57 100644
--- a/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp
@@ -224,6 +224,8 @@ void IntrinsicEmitter::EmitIITInfo(raw_ostream &OS) {
     RecsByNumber[Number] = Rec->getName();
   }
   if (IIT_Base.size() > 0) {
+    if (RecsByNumber[0] != "IIT_Done")
+      PrintFatalError("IIT_Done expected to have value 0");
     for (unsigned I = 0, E = RecsByNumber.size(); I < E; ++I)
       if (!RecsByNumber[I].empty())
         OS << "  " << RecsByNumber[I] << " = " << I << ",\n";
@@ -351,7 +353,11 @@ void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable &Ints,
   // If we can compute a 16/32-bit fixed encoding for this intrinsic, do so and
   // capture it in this vector, otherwise store a ~0U.
   std::vector<FixedEncodingTy> FixedEncodings;
-  SequenceToOffsetTable<TypeSigTy> LongEncodingTable;
+
+  // Each IIT encoding sequence in the long encoding table is terminated by
+  // IIT_Done(=0) token.
+  constexpr unsigned char IIT_Done = 0;
+  SequenceToOffsetTable<TypeSigTy> LongEncodingTable(IIT_Done);
 
   FixedEncodings.reserve(Ints.size());
 



More information about the llvm-commits mailing list