[llvm] [LLVM][Intrinsics] Change overly defensive code in `DecodeIITType` (PR #190260)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Apr 11 16:03:28 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-ir
Author: Rahul Joshi (jurahul)
<details>
<summary>Changes</summary>
`DecodeIITType` does a range check each time the next entry from the IIT encoding table is read. This is required to handle IIT encodings that are in-lined into the table `IIT_Table` entries, since the `IITEntries` array in `getIntrinsicInfoTableEntries` is terminated after the last non-zero nibble is seen in the inlined encoding (but that may not be the actual end). Change this code to instead have the `IITEntries` array for the inlined case point to the full payload + a IIT_Done terminator, so that such entries look exactly like they would if they were encoded in the long encoding table and then remove the range check in `DecodeIITType` to streamline that code a bit.
Additionally, change some use if 0s (in loop conditions and default constructed terminator in the IIT long encoding table) to explicitly use IIT_Done to clarify the code better.
Also use `consume_front()` in a few places instead of `front()` followed by `slice(1)`.
---
Full diff: https://github.com/llvm/llvm-project/pull/190260.diff
2 Files Affected:
- (modified) llvm/lib/IR/Intrinsics.cpp (+27-26)
- (modified) llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp (+7-1)
``````````diff
diff --git a/llvm/lib/IR/Intrinsics.cpp b/llvm/lib/IR/Intrinsics.cpp
index 0e01529bda711..0220d74ca9f12 100644
--- a/llvm/lib/IR/Intrinsics.cpp
+++ b/llvm/lib/IR/Intrinsics.cpp
@@ -202,6 +202,8 @@ enum IIT_Info {
#include "llvm/IR/IntrinsicImpl.inc"
};
+static_assert(IIT_Done == 0, "IIT_Done expected to be 0");
+
static void
DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
IIT_Info LastInfo,
@@ -354,42 +356,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 +408,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 +430,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;
@@ -457,8 +456,13 @@ void Intrinsic::getIntrinsicInfoTableEntries(
// Array to hold the inlined fixed encoding values expanded from nibbles to
// bytes. Its size can be be atmost FixedEncodingBits / 4 i.e., number
- // of nibbles that can fit in `FixedEncodingTy`.
- unsigned char IITValues[FixedEncodingBits / 4];
+ // of nibbles that can fit in `FixedEncodingTy` + 1 (the IIT_Done terminator
+ // that is not explicitly encoded). Note that if there are trailing 0 bytes
+ // in the encoding (for example, payload following one of the IIT tokens),
+ // the inlined encoding does not encode the actual size of the encoding, so
+ // we always assume its size of this maximum length possible, followed by the
+ // IIT_Done terminator token (whose value is 0).
+ unsigned char IITValues[FixedEncodingBits / 4 + 1] = {0};
ArrayRef<unsigned char> IITEntries;
unsigned NextElt = 0;
@@ -478,13 +482,13 @@ void Intrinsic::getIntrinsicInfoTableEntries(
TableVal >>= 4;
} while (TableVal);
- IITEntries = ArrayRef(IITValues).take_front(NextElt);
+ IITEntries = IITValues;
NextElt = 0;
}
// Okay, decode the table into the output vector of IITDescriptors.
DecodeIITType(NextElt, IITEntries, IIT_Done, T);
- while (NextElt != IITEntries.size() && IITEntries[NextElt] != 0)
+ while (IITEntries[NextElt] != IIT_Done)
DecodeIITType(NextElt, IITEntries, IIT_Done, T);
}
@@ -493,8 +497,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 +865,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 +999,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);
+ Infos.consume_front();
return IsDeferredCheck || DeferCheck(Ty);
}
auto *ReferenceType =
@@ -1114,8 +1116,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());
``````````
</details>
https://github.com/llvm/llvm-project/pull/190260
More information about the llvm-commits
mailing list