[llvm] decfe59 - [IR][TableGen] Add RangeSet TableGen intrinsic property (#203623)

via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 28 03:17:15 PDT 2026


Author: Kirill Vedernikov
Date: 2026-08-28T12:17:10+02:00
New Revision: decfe59a36e1e87f9b860b4726edb15cdb1e2c6e

URL: https://github.com/llvm/llvm-project/commit/decfe59a36e1e87f9b860b4726edb15cdb1e2c6e
DIFF: https://github.com/llvm/llvm-project/commit/decfe59a36e1e87f9b860b4726edb15cdb1e2c6e.diff

LOG: [IR][TableGen] Add RangeSet TableGen intrinsic property (#203623)

This change introduces a `RangeSet` TableGen intrinsic property.
Existing `Range<idx, lo, hi>` keeps its current half-open semantics and
continues to emit the existing range attribute.

TableGen syntax: `RangeSet<idx, [[lo0, hi0], [lo1, hi1], ...]>` where
`[lo, hi]` are closed ordered and non-overlapped intervals.

Added: 
    llvm/test/TableGen/intrinsic-rangeset-errors.td
    llvm/test/TableGen/intrinsic-rangeset.td

Modified: 
    llvm/include/llvm/IR/Intrinsics.h
    llvm/include/llvm/IR/Intrinsics.td
    llvm/lib/IR/Intrinsics.cpp
    llvm/lib/IR/Verifier.cpp
    llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
    llvm/utils/TableGen/Basic/CodeGenIntrinsics.h
    llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/Intrinsics.h b/llvm/include/llvm/IR/Intrinsics.h
index a4799751832bf..86b6f9caa9078 100644
--- a/llvm/include/llvm/IR/Intrinsics.h
+++ b/llvm/include/llvm/IR/Intrinsics.h
@@ -25,15 +25,16 @@
 
 namespace llvm {
 
-class Type;
-class FunctionType;
+class APInt;
+class AttributeList;
+class AttributeSet;
+class Constant;
 class Function;
+class FunctionType;
 class LLVMContext;
 class Module;
-class AttributeList;
-class AttributeSet;
 class raw_ostream;
-class Constant;
+class Type;
 
 /// This namespace contains an enum with a value for every intrinsic/builtin
 /// function known by LLVM. The enum values are returned by
@@ -327,6 +328,11 @@ LLVM_ABI void printImmArg(ID IID, unsigned ArgIdx, raw_ostream &OS,
 
 LLVM_ABI void printFPClassMask(raw_ostream &OS, const Constant *ImmArgVal);
 
+/// Returns true if \p Value satisfies the range constraints specified for
+/// argument \p ArgIdx of intrinsic \p IID.
+LLVM_ABI bool isImmArgValueInRangeSet(ID IID, unsigned ArgIdx,
+                                      const APInt &Value);
+
 } // namespace Intrinsic
 
 } // namespace llvm

diff  --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index c20ea64c7eef4..1d960dc011a5a 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -173,6 +173,25 @@ class ReadNone<ArgIndex idx> : IntrinsicProperty {
   int ArgNo = idx.Value;
 }
 
+// A RangeSet specifies a union of ordered and disjoint closed ranges that an
+// immediate argument must be in.
+class RangeSet<ArgIndex idx, list<list<int>> ranges> : IntrinsicProperty {
+  list<list<int>> ValidRanges = !filter(r, ranges, !eq(!size(r), 2));
+
+  assert !not(!empty(ranges)), "RangeSet requires at least one range";
+  assert !eq(!size(ValidRanges), !size(ranges)),
+         "RangeSet requires each range to have exactly two bounds";
+  assert !empty(!filter(r, ValidRanges, !lt(r[1], r[0]))),
+         "RangeSet requires lower <= upper for each range";
+  assert !empty(!filter(i, !range(1, !size(ValidRanges)),
+                        !le(ValidRanges[i][0],
+                            ValidRanges[!sub(i, 1)][1]))),
+         "RangeSet requires ordered and non-overlapping ranges";
+
+  int ArgNo = idx.Value;
+  list<list<int>> Ranges = ranges;
+}
+
 // The return value or argument is in the range [lower, upper),
 // where lower and upper are interpreted as signed integers.
 class Range<AttrIndex idx, int lower, int upper> : IntrinsicProperty {

diff  --git a/llvm/lib/IR/Intrinsics.cpp b/llvm/lib/IR/Intrinsics.cpp
index 266af8e06a230..fefd407a5556b 100644
--- a/llvm/lib/IR/Intrinsics.cpp
+++ b/llvm/lib/IR/Intrinsics.cpp
@@ -1478,6 +1478,9 @@ LLVM_ABI void Intrinsic::printFPClassMask(raw_ostream &OS,
   OS << static_cast<FPClassTest>(Val);
 }
 
+#define GET_INTRINSIC_IMMARG_RANGE_SET_CHECKS
+#include "llvm/IR/IntrinsicImpl.inc"
+
 #define GET_INTRINSIC_PRETTY_PRINT_ARGUMENTS
 #include "llvm/IR/IntrinsicImpl.inc"
 

diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index f47cbccf171f4..8a85a34bcd290 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -4003,6 +4003,12 @@ void Verifier::visitCallBase(CallBase &Call) {
                 Call);
         }
       }
+      if (auto *CI = dyn_cast<ConstantInt>(ArgVal))
+        Check(Intrinsic::isImmArgValueInRangeSet(Call.getIntrinsicID(), i,
+                                                 CI->getValue()),
+              formatv("immarg value {} for arg {} out of range set",
+                      CI->getValue(), i),
+              Call);
     }
 
     if (Call.paramHasAttr(i, Attribute::Preallocated)) {

diff  --git a/llvm/test/TableGen/intrinsic-rangeset-errors.td b/llvm/test/TableGen/intrinsic-rangeset-errors.td
new file mode 100644
index 0000000000000..591b83d2780ef
--- /dev/null
+++ b/llvm/test/TableGen/intrinsic-rangeset-errors.td
@@ -0,0 +1,45 @@
+// RUN: not llvm-tblgen -gen-intrinsic-impl -I %p/../../include -DEMPTY %s 2>&1 | FileCheck --check-prefix=EMPTY %s -DFILE=%s
+// RUN: not llvm-tblgen -gen-intrinsic-impl -I %p/../../include -DBAD_BOUNDS %s 2>&1 | FileCheck --check-prefix=BAD-BOUNDS %s -DFILE=%s
+// RUN: not llvm-tblgen -gen-intrinsic-impl -I %p/../../include -DOVERLAP %s 2>&1 | FileCheck --check-prefix=OVERLAP %s -DFILE=%s
+// RUN: not llvm-tblgen -gen-intrinsic-impl -I %p/../../include -DMISSING_IMMARG %s 2>&1 | FileCheck --check-prefix=MISSING-IMMARG %s -DFILE=%s
+// RUN: not llvm-tblgen -gen-intrinsic-impl -I %p/../../include -DDUPLICATE %s 2>&1 | FileCheck --check-prefix=DUPLICATE %s -DFILE=%s
+
+#define TEST_INTRINSICS_SUPPRESS_DEFS
+include "llvm/IR/Intrinsics.td"
+
+#ifdef EMPTY
+// EMPTY: error: assertion failed: RangeSet requires at least one range
+def int_rangeset_empty : Intrinsic<
+    [llvm_i32_ty], [llvm_i16_ty],
+    [ImmArg<ArgIndex<0>>, RangeSet<ArgIndex<0>, []>]>;
+#endif
+
+#ifdef BAD_BOUNDS
+// BAD-BOUNDS: error: assertion failed: RangeSet requires lower <= upper for each range
+def int_rangeset_bad_bounds : Intrinsic<
+    [llvm_i32_ty], [llvm_i16_ty],
+    [ImmArg<ArgIndex<0>>, RangeSet<ArgIndex<0>, [[4, 3]]>]>;
+#endif
+
+#ifdef OVERLAP
+// OVERLAP: error: assertion failed: RangeSet requires ordered and non-overlapping ranges
+def int_rangeset_overlap : Intrinsic<
+    [llvm_i32_ty], [llvm_i16_ty],
+    [ImmArg<ArgIndex<0>>, RangeSet<ArgIndex<0>, [[0, 2], [2, 4]]>]>;
+#endif
+
+#ifdef MISSING_IMMARG
+// MISSING-IMMARG: error: RangeSet requires ImmArg for argument 0
+def int_rangeset_missing_immarg : Intrinsic<
+    [llvm_i32_ty], [llvm_i16_ty],
+    [RangeSet<ArgIndex<0>, [[0, 2]]>]>;
+#endif
+
+#ifdef DUPLICATE
+// DUPLICATE: error: RangeSet for argument 0 already specified
+def int_rangeset_duplicate : Intrinsic<
+    [llvm_i32_ty], [llvm_i16_ty],
+    [ImmArg<ArgIndex<0>>,
+     RangeSet<ArgIndex<0>, [[0, 2]]>,
+     RangeSet<ArgIndex<0>, [[3, 4]]>]>;
+#endif

diff  --git a/llvm/test/TableGen/intrinsic-rangeset.td b/llvm/test/TableGen/intrinsic-rangeset.td
new file mode 100644
index 0000000000000..e630e7538f47f
--- /dev/null
+++ b/llvm/test/TableGen/intrinsic-rangeset.td
@@ -0,0 +1,47 @@
+// RUN: llvm-tblgen -gen-intrinsic-impl -I %p/../../include %s | FileCheck %s
+
+#define TEST_INTRINSICS_SUPPRESS_DEFS
+include "llvm/IR/Intrinsics.td"
+
+def int_rangeset_tst : Intrinsic<
+    [llvm_i32_ty], [llvm_i16_ty],
+    [ImmArg<ArgIndex<0>>, RangeSet<ArgIndex<0>, [[0, 2], [5, 8]]>]>;
+
+def int_rangeset_coalesce_tst : Intrinsic<
+    [llvm_i32_ty], [llvm_i16_ty],
+    [ImmArg<ArgIndex<0>>, RangeSet<ArgIndex<0>, [[0, 2], [3, 4], [6, 8]]>]>;
+
+def int_rangeset_multi_tst : Intrinsic<
+    [llvm_i32_ty], [llvm_i16_ty, llvm_i16_ty],
+    [ImmArg<ArgIndex<0>>, ImmArg<ArgIndex<1>>,
+     RangeSet<ArgIndex<0>, [[1, 1]]>,
+     RangeSet<ArgIndex<1>, [[2, 3]]>]>;
+
+// CHECK-NOT: Attribute::RangeSet
+
+// CHECK: static constexpr ImmArgRange ImmArgRangeTable[] = {
+// CHECK-DAG: {0, 3}
+// CHECK-DAG: {5, 9}
+// CHECK-DAG: {0, 5}
+// CHECK-DAG: {6, 9}
+// CHECK-DAG: {1, 2}
+// CHECK-DAG: {2, 4}
+
+// CHECK: static constexpr ImmArgRangeSet ImmArgRangeSetTable[] = {
+// CHECK-DAG: {0, {{[0-9]+}}, 2}
+// CHECK-DAG: {0, {{[0-9]+}}, 2}
+// CHECK-DAG: {0, {{[0-9]+}}, 1}
+// CHECK-DAG: {1, {{[0-9]+}}, 1}
+
+// CHECK: static constexpr ImmArgRangeSetList ImmArgRangeSetListTable[] = {
+// CHECK-DAG: // llvm.rangeset.tst
+// CHECK-DAG: // llvm.rangeset.coalesce.tst
+// CHECK-DAG: {1, 2}, // llvm.rangeset.multi.tst
+
+// CHECK: bool Intrinsic::isImmArgValueInRangeSet
+// CHECK-NOT: switch
+// CHECK: const ImmArgRangeSetList &List = ImmArgRangeSetListTable[IID];
+// CHECK: ArrayRef<ImmArgRangeSet> RangeSets(
+// CHECK: for (const ImmArgRangeSet &RangeSet : RangeSets) {
+// CHECK: ArrayRef<ImmArgRange> Ranges(ImmArgRangeTable + RangeSet.RangesStart,
+// CHECK: for (const ImmArgRange &Range : Ranges) {

diff  --git a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
index cfbb6604ee2b9..8373e23d5a82c 100644
--- a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
+++ b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
@@ -22,6 +22,7 @@
 #include "llvm/TableGen/Record.h"
 #include <algorithm>
 #include <cassert>
+#include <limits>
 using namespace llvm;
 
 // As the type of more than one return values is represented as an anonymous
@@ -31,6 +32,38 @@ using namespace llvm;
 // return is 257.
 static constexpr unsigned MaxNumReturn = 257;
 
+using ImmArgRange = CodeGenIntrinsic::ImmArgRangeSet::Range;
+using ImmArgRangeList = CodeGenIntrinsic::ImmArgRangeSet::RangeList;
+
+static ImmArgRange getHalfOpenRange(const Record *R, const ListInit *Range,
+                                    StringRef AttrName) {
+  auto GetBound = [&](const Init *Bound) -> int64_t {
+    if (const auto *II = dyn_cast<IntInit>(Bound))
+      return II->getValue();
+    PrintFatalError(R->getLoc(),
+                    Twine(AttrName) +
+                        " bound is not an integer: " + Bound->getAsString());
+  };
+
+  int64_t Lower = GetBound(Range->getElement(0));
+  int64_t Upper = GetBound(Range->getElement(1));
+  if (Upper == std::numeric_limits<int64_t>::max())
+    PrintFatalError(R->getLoc(),
+                    Twine(AttrName) + " closed upper bound is too large");
+  return ImmArgRange(Lower, Upper + 1);
+}
+
+static void appendHalfOpenRange(SmallVectorImpl<ImmArgRange> &Ranges,
+                                ImmArgRange Range) {
+  if (!Ranges.empty()) {
+    if (Range.first == Ranges.back().second) {
+      Ranges.back().second = Range.second;
+      return;
+    }
+  }
+  Ranges.push_back(Range);
+}
+
 //===----------------------------------------------------------------------===//
 // CodeGenIntrinsic Implementation
 //===----------------------------------------------------------------------===//
@@ -388,6 +421,12 @@ CodeGenIntrinsic::CodeGenIntrinsic(const Record *R,
   for (auto &Attrs : ArgumentAttributes)
     llvm::sort(Attrs);
 
+  for (const ImmArgRangeSet &RangeSet : ImmArgRangeSets)
+    if (!isParamImmArg(RangeSet.ArgNo))
+      PrintFatalError(
+          TheDef->getLoc(),
+          formatv("RangeSet requires ImmArg for argument {}", RangeSet.ArgNo));
+
   // Default values are not yet supported for overloaded intrinsics
   // (overloaded support will come in a follow-up).
   if (isOverloaded &&
@@ -566,6 +605,25 @@ void CodeGenIntrinsic::setProperty(const Record *R) {
     int64_t Lower = R->getValueAsInt("Lower");
     int64_t Upper = R->getValueAsInt("Upper");
     addArgAttribute(ArgNo, Range, Lower, Upper);
+  } else if (R->isSubClassOf("RangeSet")) {
+    unsigned ArgNo = R->getValueAsInt("ArgNo");
+    const ListInit *RangeList = R->getValueAsListInit("Ranges");
+    ImmArgRangeList Ranges;
+
+    if (ArgNo < 1)
+      PrintFatalError(R->getLoc(), "RangeSet should only apply to arguments");
+    unsigned ParamNo = ArgNo - 1;
+
+    for (const ImmArgRangeSet &RangeSet : ImmArgRangeSets)
+      if (RangeSet.ArgNo == ParamNo)
+        PrintFatalError(
+            R->getLoc(),
+            formatv("RangeSet for argument {} already specified", ParamNo));
+
+    for (const Init *Range : RangeList->getElements())
+      appendHalfOpenRange(
+          Ranges, getHalfOpenRange(R, cast<ListInit>(Range), "RangeSet"));
+    addImmArgRangeSet(ParamNo, std::move(Ranges));
   } else if (R->isSubClassOf("NoFreeObj")) {
     unsigned ArgNo = R->getValueAsInt("ArgNo");
     addArgAttribute(ArgNo, NoFreeObj);
@@ -637,6 +695,11 @@ void CodeGenIntrinsic::addArgAttribute(unsigned Idx, ArgAttrKind AK, uint64_t V,
   ArgumentAttributes[Idx].emplace_back(AK, V, V2);
 }
 
+void CodeGenIntrinsic::addImmArgRangeSet(unsigned ArgNo,
+                                         ImmArgRangeSet::RangeList Ranges) {
+  ImmArgRangeSets.push_back({ArgNo, std::move(Ranges)});
+}
+
 void CodeGenIntrinsic::addPrettyPrintFunction(unsigned ArgIdx,
                                               StringRef ArgName,
                                               StringRef FuncName) {

diff  --git a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h
index 296e8e11f3be0..bd8a35dfc4de8 100644
--- a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h
+++ b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h
@@ -151,11 +151,23 @@ struct CodeGenIntrinsic {
     }
   };
 
+  struct ImmArgRangeSet {
+    using Range = std::pair<int64_t, int64_t>;
+    using RangeList = SmallVector<Range, 4>;
+
+    unsigned ArgNo;
+    RangeList Ranges;
+  };
+
   /// Vector of attributes for each argument.
   SmallVector<SmallVector<ArgAttribute, 0>> ArgumentAttributes;
 
+  /// Range-set constraints for immediate arguments, indexed by argument number.
+  SmallVector<ImmArgRangeSet> ImmArgRangeSets;
+
   void addArgAttribute(unsigned Idx, ArgAttrKind AK, uint64_t V = 0,
                        uint64_t V2 = 0);
+  void addImmArgRangeSet(unsigned ArgNo, ImmArgRangeSet::RangeList Ranges);
 
   /// Structure to store pretty print and argument information.
   struct PrettyPrintArgInfo {

diff  --git a/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp b/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp
index e7b47fcd83002..6b3a3026a7d64 100644
--- a/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp
@@ -73,6 +73,8 @@ class IntrinsicEmitter {
       function_ref<bool(const CodeGenIntrinsic &Int)> GetProperty);
   void EmitGenerator(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
   void EmitAttributes(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
+  void EmitImmArgRangeSetChecks(const CodeGenIntrinsicTable &Ints,
+                                raw_ostream &OS);
   void EmitPrettyPrintArguments(const CodeGenIntrinsicTable &Ints,
                                 raw_ostream &OS);
   void EmitDefaultArgValuesTable(const CodeGenIntrinsicTable &Ints,
@@ -130,6 +132,9 @@ void IntrinsicEmitter::run(raw_ostream &OS, bool Enums) {
     // Emit the intrinsic parameter attributes.
     EmitAttributes(Ints, OS);
 
+    // Emit immediate argument range-set checks.
+    EmitImmArgRangeSetChecks(Ints, OS);
+
     // Emit the intrinsic ID -> pretty print table.
     EmitIntrinsicToPrettyPrintTable(Ints, OS);
 
@@ -888,6 +893,133 @@ AttributeSet Intrinsic::getFnAttributes(LLVMContext &C, ID id) {{
                 NoFunctionAttrsID);
 }
 
+void IntrinsicEmitter::EmitImmArgRangeSetChecks(
+    const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
+  using ImmArgRangeSet = CodeGenIntrinsic::ImmArgRangeSet;
+  struct RangeSetInfo {
+    uint32_t ArgNo;
+    uint32_t RangesStart;
+    uint32_t NumRanges;
+  };
+  struct RangeSetListInfo {
+    uint32_t RangeSetsStart;
+    uint32_t NumRangeSets;
+  };
+
+  SequenceToOffsetTable<ImmArgRangeSet::RangeList> RangeTable(
+      /*Terminator=*/std::nullopt);
+
+  for (const CodeGenIntrinsic &Int : Ints) {
+    for (const ImmArgRangeSet &RangeSet : Int.ImmArgRangeSets)
+      RangeTable.add(RangeSet.Ranges);
+  }
+
+  IfDefEmitter IfDef(OS, "GET_INTRINSIC_IMMARG_RANGE_SET_CHECKS");
+  if (RangeTable.empty()) {
+    OS << R"(
+bool Intrinsic::isImmArgValueInRangeSet(ID IID, unsigned ArgIdx,
+                                        const APInt &Value) {
+  return true;
+}
+)";
+    return;
+  }
+
+  RangeTable.layout();
+
+  std::vector<RangeSetInfo> RangeSetInfos;
+  std::vector<RangeSetListInfo> PerIntrinsicRangeSetInfos;
+  PerIntrinsicRangeSetInfos.reserve(Ints.size() + 1);
+  PerIntrinsicRangeSetInfos.push_back({0, 0}); // not_intrinsic
+
+  for (const CodeGenIntrinsic &Int : Ints) {
+    uint32_t Start = static_cast<uint32_t>(RangeSetInfos.size());
+    for (const ImmArgRangeSet &RangeSet : Int.ImmArgRangeSets)
+      RangeSetInfos.push_back({RangeSet.ArgNo, RangeTable.get(RangeSet.Ranges),
+                               static_cast<uint32_t>(RangeSet.Ranges.size())});
+    PerIntrinsicRangeSetInfos.push_back(
+        {Start, static_cast<uint32_t>(Int.ImmArgRangeSets.size())});
+  }
+
+  OS << R"(
+namespace {
+struct ImmArgRange {
+  int64_t Lower, Upper;
+};
+
+struct ImmArgRangeSet {
+  uint32_t ArgIdx;
+  uint32_t RangesStart;
+  uint32_t NumRanges;
+};
+
+struct ImmArgRangeSetList {
+  uint32_t RangeSetsStart;
+  uint32_t NumRangeSets;
+};
+} // namespace
+
+static constexpr ImmArgRange ImmArgRangeTable[] = {
+)";
+  RangeTable.emit(OS, [](raw_ostream &OS, ImmArgRangeSet::Range Elem) {
+    OS << "{" << Elem.first << ", " << Elem.second << "}";
+  });
+  OS << R"(}; // ImmArgRangeTable
+
+static constexpr ImmArgRangeSet ImmArgRangeSetTable[] = {
+)";
+  for (const RangeSetInfo &Info : RangeSetInfos)
+    OS << "  {" << Info.ArgNo << ", " << Info.RangesStart << ", "
+       << Info.NumRanges << "},\n";
+  OS << R"(}; // ImmArgRangeSetTable
+
+static constexpr ImmArgRangeSetList ImmArgRangeSetListTable[] = {
+)";
+  for (const auto &[Idx, Infos] : enumerate(PerIntrinsicRangeSetInfos)) {
+    OS << "  {" << Infos.RangeSetsStart << ", " << Infos.NumRangeSets << "},";
+    if (Idx == 0)
+      OS << " // not_intrinsic\n";
+    else
+      OS << " // " << Ints[Idx - 1].Name << "\n";
+  }
+  OS << R"(}; // ImmArgRangeSetListTable
+
+static bool isValueInImmArgRange(const ImmArgRange &Range,
+                                 const APInt &Value) {
+  unsigned BitWidth = Value.getBitWidth();
+  return ConstantRange(
+             APInt(BitWidth, Range.Lower, /*isSigned=*/true,
+                   /*implicitTrunc=*/true),
+             APInt(BitWidth, Range.Upper, /*isSigned=*/true,
+                   /*implicitTrunc=*/true))
+      .contains(Value);
+}
+
+bool Intrinsic::isImmArgValueInRangeSet(ID IID, unsigned ArgIdx,
+                                        const APInt &Value) {
+  if (IID >= Intrinsic::num_intrinsics)
+    return true;
+
+  const ImmArgRangeSetList &List = ImmArgRangeSetListTable[IID];
+  ArrayRef<ImmArgRangeSet> RangeSets(
+      ImmArgRangeSetTable + List.RangeSetsStart, List.NumRangeSets);
+  for (const ImmArgRangeSet &RangeSet : RangeSets) {
+    if (RangeSet.ArgIdx != ArgIdx)
+      continue;
+
+    ArrayRef<ImmArgRange> Ranges(ImmArgRangeTable + RangeSet.RangesStart,
+                                 RangeSet.NumRanges);
+    for (const ImmArgRange &Range : Ranges) {
+      if (isValueInImmArgRange(Range, Value))
+        return true;
+    }
+    return false;
+  }
+  return true;
+}
+)";
+}
+
 void IntrinsicEmitter::EmitIntrinsicToPrettyPrintTable(
     const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
   EmitIntrinsicBitTable(Ints, OS, "GET_INTRINSIC_PRETTY_PRINT_TABLE", "PPTable",


        


More information about the llvm-commits mailing list